mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[ResponseOps][Cases] Disable md5 algo in cases files when fips mode enabled (#189074)
## Summary Disables the `md5` hashing algorithm in cases files when Kibana is running in FIPS mode. ## References Closes #185600 ### Checklist - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios
This commit is contained in:
parent
1e6e23a45d
commit
b5f617c891
5 changed files with 99 additions and 49 deletions
|
@ -76,6 +76,36 @@ describe('FileActionsPopoverButton', () => {
|
|||
expect(await screen.queryByTestId('cases-files-copy-hash-button')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('only renders menu items for the enabled hashes', async () => {
|
||||
appMockRender.render(
|
||||
<FileActionsPopoverButton
|
||||
caseId={basicCaseId}
|
||||
theFile={{ ...basicFileMock, hash: { sha1: 'sha1' } }}
|
||||
/>
|
||||
);
|
||||
|
||||
const popoverButton = await screen.findByTestId(
|
||||
`cases-files-actions-popover-button-${basicFileMock.id}`
|
||||
);
|
||||
|
||||
expect(popoverButton).toBeInTheDocument();
|
||||
userEvent.click(popoverButton);
|
||||
|
||||
expect(
|
||||
await screen.findByTestId(`cases-files-popover-${basicFileMock.id}`)
|
||||
).toBeInTheDocument();
|
||||
|
||||
const copyFileHashButton = await screen.findByTestId('cases-files-copy-hash-button');
|
||||
|
||||
expect(copyFileHashButton).toBeInTheDocument();
|
||||
|
||||
userEvent.click(copyFileHashButton);
|
||||
|
||||
expect(await screen.findByTestId(`cases-files-copy-sha1-hash-button`)).toBeInTheDocument();
|
||||
expect(screen.queryByTestId('cases-files-copy-md5-hash-button')).not.toBeInTheDocument();
|
||||
expect(screen.queryByTestId('cases-files-copy-sha256-hash-button')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('clicking the copy file hash button rerenders the popover correctly', async () => {
|
||||
appMockRender.render(<FileActionsPopoverButton caseId={basicCaseId} theFile={basicFileMock} />);
|
||||
|
||||
|
|
|
@ -65,49 +65,52 @@ export const FileActionsPopoverButton: React.FC<{ caseId: string; theFile: FileJ
|
|||
id: 1,
|
||||
title: i18n.COPY_FILE_HASH,
|
||||
items: [
|
||||
{
|
||||
name: 'MD5',
|
||||
icon: 'copyClipboard',
|
||||
disabled: !theFile.hash?.md5,
|
||||
onClick: () => {
|
||||
if (theFile.hash?.md5) {
|
||||
navigator.clipboard.writeText(theFile.hash.md5).then(() => {
|
||||
closePopover();
|
||||
showSuccessToast(i18n.COPY_FILE_HASH_SUCCESS('md5'));
|
||||
});
|
||||
theFile.hash?.md5
|
||||
? {
|
||||
name: 'MD5',
|
||||
icon: 'copyClipboard',
|
||||
onClick: () => {
|
||||
if (theFile.hash?.md5) {
|
||||
navigator.clipboard.writeText(theFile.hash.md5).then(() => {
|
||||
closePopover();
|
||||
showSuccessToast(i18n.COPY_FILE_HASH_SUCCESS('md5'));
|
||||
});
|
||||
}
|
||||
},
|
||||
'data-test-subj': 'cases-files-copy-md5-hash-button',
|
||||
}
|
||||
},
|
||||
'data-test-subj': 'cases-files-copy-md5-hash-button',
|
||||
},
|
||||
{
|
||||
name: 'SHA1',
|
||||
icon: 'copyClipboard',
|
||||
disabled: !theFile.hash?.sha1,
|
||||
onClick: () => {
|
||||
if (theFile.hash?.sha1) {
|
||||
navigator.clipboard.writeText(theFile.hash.sha1).then(() => {
|
||||
closePopover();
|
||||
showSuccessToast(i18n.COPY_FILE_HASH_SUCCESS('sha1'));
|
||||
});
|
||||
: null,
|
||||
theFile.hash?.sha1
|
||||
? {
|
||||
name: 'SHA1',
|
||||
icon: 'copyClipboard',
|
||||
onClick: () => {
|
||||
if (theFile.hash?.sha1) {
|
||||
navigator.clipboard.writeText(theFile.hash.sha1).then(() => {
|
||||
closePopover();
|
||||
showSuccessToast(i18n.COPY_FILE_HASH_SUCCESS('sha1'));
|
||||
});
|
||||
}
|
||||
},
|
||||
'data-test-subj': 'cases-files-copy-sha1-hash-button',
|
||||
}
|
||||
},
|
||||
'data-test-subj': 'cases-files-copy-sha1-hash-button',
|
||||
},
|
||||
{
|
||||
name: 'SHA256',
|
||||
icon: 'copyClipboard',
|
||||
disabled: !theFile.hash?.sha256,
|
||||
onClick: () => {
|
||||
if (theFile.hash?.sha256) {
|
||||
navigator.clipboard.writeText(theFile.hash.sha256).then(() => {
|
||||
closePopover();
|
||||
showSuccessToast(i18n.COPY_FILE_HASH_SUCCESS('sha256'));
|
||||
});
|
||||
: null,
|
||||
theFile.hash?.sha256
|
||||
? {
|
||||
name: 'SHA256',
|
||||
icon: 'copyClipboard',
|
||||
onClick: () => {
|
||||
if (theFile.hash?.sha256) {
|
||||
navigator.clipboard.writeText(theFile.hash.sha256).then(() => {
|
||||
closePopover();
|
||||
showSuccessToast(i18n.COPY_FILE_HASH_SUCCESS('sha256'));
|
||||
});
|
||||
}
|
||||
},
|
||||
'data-test-subj': 'cases-files-copy-sha256-hash-button',
|
||||
}
|
||||
},
|
||||
'data-test-subj': 'cases-files-copy-sha256-hash-button',
|
||||
},
|
||||
],
|
||||
: null,
|
||||
].filter(Boolean) as EuiContextMenuPanelDescriptor['items'],
|
||||
},
|
||||
];
|
||||
|
||||
|
|
|
@ -109,6 +109,15 @@ describe('server files', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('hashing algorithms', () => {
|
||||
it('excludes md5 when fips is enabled', () => {
|
||||
const schema = ConfigSchema.validate({});
|
||||
registerCaseFileKinds(schema.files, mockFilesSetup, true);
|
||||
|
||||
expect(mockFilesSetup.registerFileKind.mock.calls[0][0].hashes).not.toContain('md5');
|
||||
});
|
||||
});
|
||||
|
||||
describe('allowed mime types', () => {
|
||||
describe('image png', () => {
|
||||
const schema = ConfigSchema.validate({ files: { allowedMimeTypes: ['image/png'] } });
|
||||
|
|
|
@ -20,13 +20,17 @@ import { IMAGE_MIME_TYPES } from '../../common/constants/mime_types';
|
|||
import type { FilesConfig } from './types';
|
||||
import { constructFileKindIdByOwner, constructFilesHttpOperationTag } from '../../common/files';
|
||||
|
||||
const buildFileKind = (config: FilesConfig, owner: Owner): FileKind => {
|
||||
const buildFileKind = (config: FilesConfig, owner: Owner, isFipsMode = false): FileKind => {
|
||||
const hashes: FileKind['hashes'] = ['sha1', 'sha256'];
|
||||
if (!isFipsMode) {
|
||||
hashes.unshift('md5');
|
||||
}
|
||||
return {
|
||||
id: constructFileKindIdByOwner(owner),
|
||||
http: fileKindHttpTags(owner),
|
||||
maxSizeBytes: createMaxCallback(config),
|
||||
allowedMimeTypes: config.allowedMimeTypes,
|
||||
hashes: ['md5', 'sha1', 'sha256'],
|
||||
hashes,
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -73,16 +77,20 @@ export const createMaxCallback =
|
|||
/**
|
||||
* The file kind definition for interacting with the file service for the backend
|
||||
*/
|
||||
const createFileKinds = (config: FilesConfig): Record<Owner, FileKind> => {
|
||||
const createFileKinds = (config: FilesConfig, isFipsMode = false): Record<Owner, FileKind> => {
|
||||
return {
|
||||
[APP_ID]: buildFileKind(config, APP_ID),
|
||||
[OBSERVABILITY_OWNER]: buildFileKind(config, OBSERVABILITY_OWNER),
|
||||
[SECURITY_SOLUTION_OWNER]: buildFileKind(config, SECURITY_SOLUTION_OWNER),
|
||||
[APP_ID]: buildFileKind(config, APP_ID, isFipsMode),
|
||||
[OBSERVABILITY_OWNER]: buildFileKind(config, OBSERVABILITY_OWNER, isFipsMode),
|
||||
[SECURITY_SOLUTION_OWNER]: buildFileKind(config, SECURITY_SOLUTION_OWNER, isFipsMode),
|
||||
};
|
||||
};
|
||||
|
||||
export const registerCaseFileKinds = (config: FilesConfig, filesSetupPlugin: FilesSetup) => {
|
||||
const fileKinds = createFileKinds(config);
|
||||
export const registerCaseFileKinds = (
|
||||
config: FilesConfig,
|
||||
filesSetupPlugin: FilesSetup,
|
||||
isFipsMode = false
|
||||
) => {
|
||||
const fileKinds = createFileKinds(config, isFipsMode);
|
||||
|
||||
for (const fileKind of Object.values(fileKinds)) {
|
||||
filesSetupPlugin.registerFileKind(fileKind);
|
||||
|
|
|
@ -86,7 +86,7 @@ export class CasePlugin
|
|||
this.persistableStateAttachmentTypeRegistry
|
||||
);
|
||||
|
||||
registerCaseFileKinds(this.caseConfig.files, plugins.files);
|
||||
registerCaseFileKinds(this.caseConfig.files, plugins.files, core.security.fips.isEnabled());
|
||||
|
||||
this.securityPluginSetup = plugins.security;
|
||||
this.lensEmbeddableFactory = plugins.lens.lensEmbeddableFactory;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue