diff --git a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/create_trusted_app_form.test.tsx b/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/create_trusted_app_form.test.tsx index 7d056ae6999e7..24797bb483bdb 100644 --- a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/create_trusted_app_form.test.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/create_trusted_app_form.test.tsx @@ -267,6 +267,11 @@ describe('When showing the Trusted App Create Form', () => { expect(renderResult.getByText('Name is required')); }); + it('should validate invalid Hash value', () => { + setTextFieldValue(getConditionValue(getCondition(renderResult)), 'someHASH'); + expect(renderResult.getByText('[1] Invalid hash value')); + }); + it('should validate that a condition value has a non empty space value', () => { setTextFieldValue(getConditionValue(getCondition(renderResult)), ' '); expect(renderResult.getByText('[1] Field entry must have a value')); @@ -281,13 +286,27 @@ describe('When showing the Trusted App Create Form', () => { setTextFieldValue(getConditionValue(getCondition(renderResult)), 'someHASH'); expect(renderResult.getByText('[2] Field entry must have a value')); }); + + it('should validate multiple errors in form', () => { + const andButton = getConditionBuilderAndButton(renderResult); + reactTestingLibrary.act(() => { + fireEvent.click(andButton, { button: 1 }); + }); + + setTextFieldValue(getConditionValue(getCondition(renderResult)), 'someHASH'); + expect(renderResult.getByText('[1] Invalid hash value')); + expect(renderResult.getByText('[2] Field entry must have a value')); + }); }); describe('and all required data passes validation', () => { it('should call change callback with isValid set to true and contain the new item', () => { const renderResult = render(); setTextFieldValue(getNameField(renderResult), 'Some Process'); - setTextFieldValue(getConditionValue(getCondition(renderResult)), 'someHASH'); + setTextFieldValue( + getConditionValue(getCondition(renderResult)), + 'e50fb1a0e5fff590ece385082edc6c41' + ); setTextFieldValue(getDescriptionField(renderResult), 'some description'); expect(getAllValidationErrors(renderResult)).toHaveLength(0); @@ -300,7 +319,7 @@ describe('When showing the Trusted App Create Form', () => { field: ConditionEntryField.HASH, operator: 'included', type: 'match', - value: 'someHASH', + value: 'e50fb1a0e5fff590ece385082edc6c41', }, ], name: 'Some Process', diff --git a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/create_trusted_app_form.tsx b/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/create_trusted_app_form.tsx index f4344796fc562..f99c3567e7912 100644 --- a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/create_trusted_app_form.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/create_trusted_app_form.tsx @@ -17,10 +17,13 @@ import { import { i18n } from '@kbn/i18n'; import { EuiFormProps } from '@elastic/eui/src/components/form/form'; import { + ConditionEntryField, MacosLinuxConditionEntry, NewTrustedApp, OperatingSystem, } from '../../../../../../common/endpoint/types'; +import { isValidHash } from '../../../../../../common/endpoint/validation/trusted_apps'; + import { isMacosLinuxTrustedAppCondition, isWindowsTrustedAppCondition, @@ -113,7 +116,7 @@ const validateFormValues = (values: NewTrustedApp): ValidationResult => { }) ); } else { - values.entries.some((entry, index) => { + values.entries.forEach((entry, index) => { if (!entry.field || !entry.value.trim()) { isValid = false; addResultToValidation( @@ -128,9 +131,18 @@ const validateFormValues = (values: NewTrustedApp): ValidationResult => { } ) ); - return true; + } else if (entry.field === ConditionEntryField.HASH && !isValidHash(entry.value)) { + isValid = false; + addResultToValidation( + validation, + 'entries', + 'errors', + i18n.translate('xpack.securitySolution.trustedapps.create.conditionFieldInvalidHashMsg', { + defaultMessage: '[{row}] Invalid hash value', + values: { row: index + 1 }, + }) + ); } - return false; }); } diff --git a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/trusted_apps_page.test.tsx b/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/trusted_apps_page.test.tsx index 69c7616b502c8..d891731f6d768 100644 --- a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/trusted_apps_page.test.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/trusted_apps_page.test.tsx @@ -201,7 +201,7 @@ describe('When on the Trusted Apps Page', () => { fireEvent.change( getByTestId('addTrustedAppFlyout-createForm-conditionsBuilder-group1-entry0-value'), - { target: { value: 'SOME$HASH#HERE' } } + { target: { value: '44ed10b389dbcd1cf16cec79d16d7378' } } ); fireEvent.change(getByTestId('addTrustedAppFlyout-createForm-descriptionField'), { @@ -363,6 +363,29 @@ describe('When on the Trusted Apps Page', () => { }); }); }); + + describe('and when the form data is not valid', () => { + it('should not enable the Flyout Add button with an invalid hash', async () => { + const renderResult = await renderAndClickAddButton(); + const { getByTestId } = renderResult; + + reactTestingLibrary.act(() => { + fireEvent.change(getByTestId('addTrustedAppFlyout-createForm-nameTextField'), { + target: { value: 'trusted app A' }, + }); + + fireEvent.change( + getByTestId('addTrustedAppFlyout-createForm-conditionsBuilder-group1-entry0-value'), + { target: { value: 'invalid hash' } } + ); + }); + + const flyoutAddButton = getByTestId( + 'addTrustedAppFlyout-createButton' + ) as HTMLButtonElement; + expect(flyoutAddButton.disabled).toBe(true); + }); + }); }); describe('and there are no trusted apps', () => {