diff --git a/packages/kbn-securitysolution-autocomplete/src/field_value_match/index.tsx b/packages/kbn-securitysolution-autocomplete/src/field_value_match/index.tsx index 03604343f5d2d..07b258deaae49 100644 --- a/packages/kbn-securitysolution-autocomplete/src/field_value_match/index.tsx +++ b/packages/kbn-securitysolution-autocomplete/src/field_value_match/index.tsx @@ -39,6 +39,7 @@ const BOOLEAN_OPTIONS = [ ]; const SINGLE_SELECTION = { asPlainText: true }; + type Warning = string | React.ReactNode; interface AutocompleteFieldMatchProps { @@ -152,9 +153,10 @@ export const AutocompleteFieldMatchComponent: React.FC {

diff --git a/packages/kbn-securitysolution-list-utils/src/helpers/index.test.ts b/packages/kbn-securitysolution-list-utils/src/helpers/index.test.ts index 6e06731798cc5..0da36d21f405b 100644 --- a/packages/kbn-securitysolution-list-utils/src/helpers/index.test.ts +++ b/packages/kbn-securitysolution-list-utils/src/helpers/index.test.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { getMappingConflictsInfo, fieldSupportsMatches } from '.'; +import { getMappingConflictsInfo, fieldSupportsMatches, hasWrongOperatorWithWildcard } from '.'; describe('Helpers', () => { describe('getMappingConflictsInfo', () => { @@ -181,4 +181,43 @@ describe('Helpers', () => { ).toBeFalsy(); }); }); + describe('hasWrongOperatorWithWildcard', () => { + test('it returns true if there is at least one exception entry with a wildcard and the wrong operator', () => { + expect( + hasWrongOperatorWithWildcard([ + { + description: '', + name: '', + type: 'simple', + entries: [{ type: 'match', value: 'withwildcard*', field: '', operator: 'included' }], + }, + ]) + ).toBeTruthy(); + expect( + hasWrongOperatorWithWildcard([ + { + description: '', + name: '', + type: 'simple', + entries: [{ type: 'match', value: 'withwildcard?', field: '', operator: 'included' }], + }, + ]) + ).toBeTruthy(); + }); + test('it returns false if there are no exception entries with a wildcard and the wrong operator', () => { + expect( + hasWrongOperatorWithWildcard([ + { + description: '', + name: '', + type: 'simple', + entries: [ + { type: 'match', value: 'nowildcard', field: '', operator: 'excluded' }, + { type: 'wildcard', value: 'withwildcard*?', field: '', operator: 'included' }, + ], + }, + ]) + ).toBeFalsy(); + }); + }); }); diff --git a/packages/kbn-securitysolution-list-utils/src/helpers/index.ts b/packages/kbn-securitysolution-list-utils/src/helpers/index.ts index bb08dd49887e7..433aa62487b1d 100644 --- a/packages/kbn-securitysolution-list-utils/src/helpers/index.ts +++ b/packages/kbn-securitysolution-list-utils/src/helpers/index.ts @@ -7,7 +7,11 @@ */ import { v4 as uuidv4 } from 'uuid'; -import { addIdToItem, removeIdFromItem } from '@kbn/securitysolution-utils'; +import { + addIdToItem, + removeIdFromItem, + validateHasWildcardWithWrongOperator, +} from '@kbn/securitysolution-utils'; import { validate } from '@kbn/securitysolution-io-ts-utils'; import { CreateExceptionListItemSchema, @@ -1021,3 +1025,19 @@ export const getMappingConflictsInfo = (field: DataViewField): FieldConflictsInf } return conflicts; }; + +/** + * Given an exceptions list, determine if any entries have an "IS" operator with a wildcard value + */ +export const hasWrongOperatorWithWildcard = ( + items: ExceptionsBuilderReturnExceptionItem[] +): boolean => { + return items[0]?.entries.some((e) => { + if (e.type !== 'list' && 'value' in e) { + return validateHasWildcardWithWrongOperator({ + operator: e.type, + value: e.value, + }); + } + }); +}; diff --git a/packages/kbn-securitysolution-utils/src/path_validations/index.test.ts b/packages/kbn-securitysolution-utils/src/path_validations/index.test.ts index b0ca96642c823..f768b78b932f4 100644 --- a/packages/kbn-securitysolution-utils/src/path_validations/index.test.ts +++ b/packages/kbn-securitysolution-utils/src/path_validations/index.test.ts @@ -11,10 +11,10 @@ import { hasSimpleExecutableName, OperatingSystem, ConditionEntryField, + validateWildcardInput, validateHasWildcardWithWrongOperator, validatePotentialWildcardInput, validateFilePathInput, - validateWildcardInput, WILDCARD_WARNING, FILEPATH_WARNING, } from '.'; diff --git a/packages/kbn-securitysolution-utils/src/path_validations/index.ts b/packages/kbn-securitysolution-utils/src/path_validations/index.ts index 6c0798c7ffe24..2c5505f90d74a 100644 --- a/packages/kbn-securitysolution-utils/src/path_validations/index.ts +++ b/packages/kbn-securitysolution-utils/src/path_validations/index.ts @@ -101,9 +101,17 @@ export const validateFilePathInput = ({ } }; -export const validateWildcardInput = (value?: string): string | undefined => { - if (/[*?]/.test(value ?? '')) { - return WILDCARD_WARNING; +export const validateWildcardInput = (value: string | string[]): string | undefined => { + const wildcardRegex = /[*?]/; + if (Array.isArray(value)) { + const doesAnyValueContainWildcardInput = value.some((v) => wildcardRegex.test(v)); + if (doesAnyValueContainWildcardInput) { + return WILDCARD_WARNING; + } + } else { + if (wildcardRegex.test(value)) { + return WILDCARD_WARNING; + } } }; @@ -112,7 +120,7 @@ export const validateHasWildcardWithWrongOperator = ({ value, }: { operator: TrustedAppEntryTypes | EventFiltersTypes; - value: string; + value: string | string[]; }): boolean => { if (operator !== 'wildcard' && validateWildcardInput(value)) { return true; diff --git a/x-pack/plugins/lists/public/exceptions/components/builder/entry_renderer.tsx b/x-pack/plugins/lists/public/exceptions/components/builder/entry_renderer.tsx index 52075f49cb241..7ac354ed12ce3 100644 --- a/x-pack/plugins/lists/public/exceptions/components/builder/entry_renderer.tsx +++ b/x-pack/plugins/lists/public/exceptions/components/builder/entry_renderer.tsx @@ -137,9 +137,10 @@ export const BuilderEntryItem: React.FC = ({ ([newOperator]: OperatorOption[]): void => { const { updatedEntry, index } = getEntryOnOperatorChange(entry, newOperator); handleError(false); + handleWarning(false); onChange(updatedEntry, index); }, - [onChange, entry, handleError] + [onChange, entry, handleError, handleWarning] ); const handleFieldMatchValueChange = useCallback( @@ -420,7 +421,7 @@ export const BuilderEntryItem: React.FC = ({ const value = typeof entry.value === 'string' ? entry.value : undefined; const fieldMatchWarning = /[*?]/.test(value ?? '') ? getWildcardWithIsOperatorWarning() - : ''; + : undefined; return ( { it('should NOT display the eql sequence callout', () => { expect(wrapper.find('[data-test-subj="eqlSequenceCallout"]').exists()).not.toBeTruthy(); }); + + it('should show a warning callout if wildcard is used', async () => { + const callProps = mockGetExceptionBuilderComponentLazy.mock.calls[0][0]; + await waitFor(() => + callProps.onChange({ + exceptionItems: [ + { + ...getExceptionListItemSchemaMock(), + entries: [ + { + field: 'event.category', + operator: 'included', + type: 'match', + value: 'wildcardvalue*?', + }, + ], + }, + ], + }) + ); + + wrapper.update(); + expect( + wrapper.find('[data-test-subj="wildcardWithWrongOperatorCallout"]').exists() + ).toBeTruthy(); + }); }); describe('alert data is passed in', () => { diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/add_exception_flyout/index.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/add_exception_flyout/index.tsx index 2a6b5c9523cfe..a16fa6677b57b 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/add_exception_flyout/index.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/add_exception_flyout/index.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import React, { memo, useEffect, useCallback, useMemo, useReducer } from 'react'; +import React, { memo, useEffect, useCallback, useMemo, useReducer, useState } from 'react'; import styled, { css } from 'styled-components'; import { isEmpty } from 'lodash/fp'; @@ -30,11 +30,13 @@ import { import { ENDPOINT_LIST_ID } from '@kbn/securitysolution-list-constants'; import { ExceptionListTypeEnum } from '@kbn/securitysolution-io-ts-list-types'; import type { OsTypeArray, ExceptionListSchema } from '@kbn/securitysolution-io-ts-list-types'; +import { hasWrongOperatorWithWildcard } from '@kbn/securitysolution-list-utils'; import type { ExceptionsBuilderExceptionItem, ExceptionsBuilderReturnExceptionItem, } from '@kbn/securitysolution-list-utils'; +import { WildCardWithWrongOperatorCallout } from '@kbn/securitysolution-exception-list-components'; import type { Moment } from 'moment'; import type { Status } from '../../../../../common/api/detection_engine'; import * as i18n from './translations'; @@ -44,6 +46,7 @@ import { retrieveAlertOsTypes, getPrepopulatedRuleExceptionWithHighlightFields, } from '../../utils/helpers'; +import { RULE_EXCEPTION, ENDPOINT_EXCEPTION } from '../../utils/translations'; import type { AlertData } from '../../utils/types'; import { initialState, createExceptionItemsReducer } from './reducer'; import { ExceptionsFlyoutMeta } from '../flyout_components/item_meta_form'; @@ -58,6 +61,8 @@ import { useCloseAlertsFromExceptions } from '../../logic/use_close_alerts'; import { ruleTypesThatAllowLargeValueLists } from '../../utils/constants'; import { useInvalidateFetchRuleByIdQuery } from '../../../rule_management/api/hooks/use_fetch_rule_by_id_query'; import { ExceptionsExpireTime } from '../flyout_components/expire_time'; +import { CONFIRM_WARNING_MODAL_LABELS } from '../../../../management/common/translations'; +import { ArtifactConfirmModal } from '../../../../management/components/artifact_list_page/components/artifact_confirm_modal'; const SectionHeader = styled(EuiTitle)` ${() => css` @@ -117,6 +122,7 @@ export const AddExceptionFlyout = memo(function AddExceptionFlyout({ onConfirm, }: AddExceptionFlyoutProps) { const { euiTheme } = useEuiTheme(); + const [showConfirmModal, setShowConfirmModal] = useState(false); const { isLoading, indexPatterns, getExtendedFields } = useFetchIndexPatterns(rules); const [isSubmitting, submitNewExceptionItems] = useAddNewExceptionItems(); const [isClosingAlerts, closeAlerts] = useCloseAlertsFromExceptions(); @@ -165,6 +171,7 @@ export const AddExceptionFlyout = memo(function AddExceptionFlyout({ errorSubmitting, expireTime, expireErrorExists, + wildcardWarningExists, }, dispatch, ] = useReducer(createExceptionItemsReducer(), { @@ -193,6 +200,10 @@ export const AddExceptionFlyout = memo(function AddExceptionFlyout({ const setExceptionItemsToAdd = useCallback( (items: ExceptionsBuilderReturnExceptionItem[]): void => { + dispatch({ + type: 'setWildcardWithWrongOperator', + warningExists: hasWrongOperatorWithWildcard(items), + }); dispatch({ type: 'setExceptionItems', items, @@ -380,7 +391,7 @@ export const AddExceptionFlyout = memo(function AddExceptionFlyout({ return hasAlertData ? retrieveAlertOsTypes(alertData) : selectedOs ? [...selectedOs] : []; }, [hasAlertData, alertData, selectedOs]); - const handleOnSubmit = useCallback(async (): Promise => { + const submitException = useCallback(async (): Promise => { if (submitNewExceptionItems == null) return; try { @@ -451,6 +462,14 @@ export const AddExceptionFlyout = memo(function AddExceptionFlyout({ expireTime, ]); + const handleOnSubmit = useCallback(() => { + if (wildcardWarningExists) { + setShowConfirmModal(true); + } else { + return submitException(); + } + }, [wildcardWarningExists, submitException]); + const isSubmitButtonDisabled = useMemo( (): boolean => isSubmitting || @@ -499,6 +518,24 @@ export const AddExceptionFlyout = memo(function AddExceptionFlyout({ prefix: 'exceptionFlyoutTitle', }); + const confirmModal = useMemo(() => { + const { title, body, confirmButton, cancelButton } = CONFIRM_WARNING_MODAL_LABELS( + listType === ExceptionListTypeEnum.ENDPOINT ? ENDPOINT_EXCEPTION : RULE_EXCEPTION + ); + + return ( + setShowConfirmModal(false)} + data-test-subj="artifactConfirmModal" + /> + ); + }, [listType, submitException]); + return ( - + {wildcardWarningExists && } {listType !== ExceptionListTypeEnum.ENDPOINT && !sharedListToAddTo?.length && ( <> @@ -639,6 +676,7 @@ export const AddExceptionFlyout = memo(function AddExceptionFlyout({ + {showConfirmModal && confirmModal} ); }); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/add_exception_flyout/reducer.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/add_exception_flyout/reducer.ts index ec8040d1fe7cc..01b0ce85b45d1 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/add_exception_flyout/reducer.ts +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/add_exception_flyout/reducer.ts @@ -34,6 +34,7 @@ export interface State { errorSubmitting: Error | null; expireTime: Moment | undefined; expireErrorExists: boolean; + wildcardWarningExists: boolean; } export const initialState: State = { @@ -55,6 +56,7 @@ export const initialState: State = { errorSubmitting: null, expireTime: undefined, expireErrorExists: false, + wildcardWarningExists: false, }; export type Action = @@ -129,11 +131,15 @@ export type Action = | { type: 'setExpireError'; errorExists: boolean; + } + | { + type: 'setWildcardWithWrongOperator'; + warningExists: boolean; }; export const createExceptionItemsReducer = () => - /* eslint complexity: ["error", 21]*/ + /* eslint complexity: ["error", 22]*/ (state: State, action: Action): State => { switch (action.type) { case 'setExceptionItemMeta': { @@ -171,6 +177,13 @@ export const createExceptionItemsReducer = itemConditionValidationErrorExists: errorExists, }; } + case 'setWildcardWithWrongOperator': { + const { warningExists } = action; + return { + ...state, + wildcardWarningExists: warningExists, + }; + } case 'setComment': { const { comment } = action; @@ -250,7 +263,6 @@ export const createExceptionItemsReducer = } case 'setListType': { const { listType } = action; - return { ...state, listType, diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/edit_exception_flyout/index.test.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/edit_exception_flyout/index.test.tsx index 077befdad52ba..8fc6ddaa7d9b7 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/edit_exception_flyout/index.test.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/edit_exception_flyout/index.test.tsx @@ -297,6 +297,32 @@ describe('When the edit exception modal is opened', () => { it('should NOT display the eql sequence callout', () => { expect(wrapper.find('[data-test-subj="eqlSequenceCallout"]').exists()).not.toBeTruthy(); }); + + it('should show a warning callout if wildcard is used', async () => { + const callProps = mockGetExceptionBuilderComponentLazy.mock.calls[0][0]; + await waitFor(() => + callProps.onChange({ + exceptionItems: [ + { + ...getExceptionListItemSchemaMock(), + entries: [ + { + field: 'event.category', + operator: 'included', + type: 'match', + value: 'wildcardvalue?', + }, + ], + }, + ], + }) + ); + + wrapper.update(); + expect( + wrapper.find('[data-test-subj="wildcardWithWrongOperatorCallout"]').exists() + ).toBeTruthy(); + }); }); describe('when exception entry fields and index allow user to bulk close', () => { diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/edit_exception_flyout/index.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/edit_exception_flyout/index.tsx index 6470db5c9b4a0..b620814ee3fe6 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/edit_exception_flyout/index.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/edit_exception_flyout/index.tsx @@ -6,7 +6,7 @@ */ import { isEmpty } from 'lodash/fp'; -import React, { useCallback, useEffect, useMemo, useReducer } from 'react'; +import React, { useCallback, useEffect, useMemo, useReducer, useState } from 'react'; import styled, { css } from 'styled-components'; import { EuiButton, @@ -32,8 +32,11 @@ import { ExceptionListTypeEnum, } from '@kbn/securitysolution-io-ts-list-types'; +import { hasWrongOperatorWithWildcard } from '@kbn/securitysolution-list-utils'; import type { ExceptionsBuilderReturnExceptionItem } from '@kbn/securitysolution-list-utils'; +import { WildCardWithWrongOperatorCallout } from '@kbn/securitysolution-exception-list-components'; + import type { Moment } from 'moment'; import moment from 'moment'; import { @@ -58,7 +61,10 @@ import { createExceptionItemsReducer } from './reducer'; import { useEditExceptionItems } from './use_edit_exception'; import * as i18n from './translations'; +import { RULE_EXCEPTION, ENDPOINT_EXCEPTION } from '../../utils/translations'; import { ExceptionsExpireTime } from '../flyout_components/expire_time'; +import { CONFIRM_WARNING_MODAL_LABELS } from '../../../../management/common/translations'; +import { ArtifactConfirmModal } from '../../../../management/components/artifact_list_page/components/artifact_confirm_modal'; interface EditExceptionFlyoutProps { list: ExceptionListSchema; @@ -125,6 +131,7 @@ const EditExceptionFlyoutComponent: React.FC = ({ entryErrorExists, expireTime, expireErrorExists, + wildcardWarningExists, }, dispatch, ] = useReducer(createExceptionItemsReducer(), { @@ -138,6 +145,7 @@ const EditExceptionFlyoutComponent: React.FC = ({ entryErrorExists: false, expireTime: itemToEdit.expire_time !== undefined ? moment(itemToEdit.expire_time) : undefined, expireErrorExists: false, + wildcardWarningExists: false, }); const allowLargeValueLists = useMemo((): boolean => { @@ -152,6 +160,8 @@ const EditExceptionFlyoutComponent: React.FC = ({ } }, [rule]); + const [showConfirmModal, setShowConfirmModal] = useState(wildcardWarningExists); + const [isLoadingReferences, referenceFetchError, ruleReferences, fetchReferences] = useFindExceptionListReferences(); @@ -172,6 +182,10 @@ const EditExceptionFlyoutComponent: React.FC = ({ * */ const setExceptionItemsToAdd = useCallback( (items: ExceptionsBuilderReturnExceptionItem[]): void => { + dispatch({ + type: 'setWildcardWithWrongOperator', + warningExists: hasWrongOperatorWithWildcard(items), + }); dispatch({ type: 'setExceptionItems', items, @@ -281,7 +295,7 @@ const EditExceptionFlyoutComponent: React.FC = ({ [] ); - const handleSubmit = useCallback(async (): Promise => { + const handleSubmitException = useCallback(async (): Promise => { if (submitEditExceptionItems == null) return; try { @@ -335,6 +349,14 @@ const EditExceptionFlyoutComponent: React.FC = ({ expireTime, ]); + const handleOnSubmit = useCallback(() => { + if (wildcardWarningExists) { + setShowConfirmModal(true); + } else { + return handleSubmitException(); + } + }, [wildcardWarningExists, handleSubmitException]); + const editExceptionMessage = useMemo( () => listType === ExceptionListTypeEnum.ENDPOINT @@ -367,6 +389,24 @@ const EditExceptionFlyoutComponent: React.FC = ({ prefix: 'exceptionFlyoutTitle', }); + const confirmModal = useMemo(() => { + const { title, body, confirmButton, cancelButton } = CONFIRM_WARNING_MODAL_LABELS( + listType === ExceptionListTypeEnum.ENDPOINT ? ENDPOINT_EXCEPTION : RULE_EXCEPTION + ); + + return ( + setShowConfirmModal(false)} + data-test-subj="artifactConfirmModal" + /> + ); + }, [listType, handleSubmitException]); + return ( = ({ onSetErrorExists={setConditionsValidationError} getExtendedFields={getExtendedFields} /> + {wildcardWarningExists && } {!openedFromListDetailPage && listType === ExceptionListTypeEnum.DETECTION && ( <> @@ -466,7 +507,7 @@ const EditExceptionFlyoutComponent: React.FC = ({ @@ -474,6 +515,7 @@ const EditExceptionFlyoutComponent: React.FC = ({ + {showConfirmModal && confirmModal} ); }; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/edit_exception_flyout/reducer.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/edit_exception_flyout/reducer.ts index e6dee3af16572..351af20900291 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/edit_exception_flyout/reducer.ts +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/edit_exception_flyout/reducer.ts @@ -19,6 +19,7 @@ export interface State { entryErrorExists: boolean; expireTime: Moment | undefined; expireErrorExists: boolean; + wildcardWarningExists: boolean; } export type Action = @@ -61,6 +62,10 @@ export type Action = | { type: 'setExpireError'; errorExists: boolean; + } + | { + type: 'setWildcardWithWrongOperator'; + warningExists: boolean; }; export const createExceptionItemsReducer = @@ -150,6 +155,13 @@ export const createExceptionItemsReducer = expireErrorExists: errorExists, }; } + case 'setWildcardWithWrongOperator': { + const { warningExists } = action; + return { + ...state, + wildcardWarningExists: warningExists, + }; + } default: return state; } diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/utils/translations.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/utils/translations.ts index 012f4e677a5b2..cfa7f54fcb5ea 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/utils/translations.ts +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/utils/translations.ts @@ -141,3 +141,17 @@ export const ERROR_FETCHING_REFERENCES_TITLE = i18n.translate( defaultMessage: 'Error fetching exception references', } ); + +export const RULE_EXCEPTION = i18n.translate( + 'xpack.securitySolution.ruleExceptions.addException.ruleException', + { + defaultMessage: 'rule exception', + } +); + +export const ENDPOINT_EXCEPTION = i18n.translate( + 'xpack.securitySolution.ruleExceptions.addException.endpointException', + { + defaultMessage: 'endpoint exception', + } +); diff --git a/x-pack/plugins/security_solution/public/management/common/translations.ts b/x-pack/plugins/security_solution/public/management/common/translations.ts index c1d05301afd6c..bc3bb8128a428 100644 --- a/x-pack/plugins/security_solution/public/management/common/translations.ts +++ b/x-pack/plugins/security_solution/public/management/common/translations.ts @@ -202,7 +202,7 @@ export const CONFIRM_WARNING_MODAL_LABELS = (entryType: string) => { }), body: i18n.translate('xpack.securitySolution.artifacts.confirmWarningModal.body', { defaultMessage: - 'Using a "*" or a "?" in the value with the "IS" operator can make the entry ineffective. Change the operator to ‘matches’ to ensure wildcards run properly. Select “cancel” to revise your entry, or "add" to continue with the entry in its current state.', + 'Using a "*" or a "?" in the value with the "is" operator can make the entry ineffective. Change the operator to "matches" to ensure wildcards run properly. Select “Cancel” to revise your entry, or "Add" to continue with the entry in its current state.', }), confirmButton: i18n.translate( 'xpack.securitySolution.artifacts.confirmWarningModal.confirmButtonText', diff --git a/x-pack/plugins/security_solution/public/management/pages/event_filters/view/components/form.tsx b/x-pack/plugins/security_solution/public/management/pages/event_filters/view/components/form.tsx index e6d42f65e7a08..ee2ae2d5c6b6e 100644 --- a/x-pack/plugins/security_solution/public/management/pages/event_filters/view/components/form.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/event_filters/view/components/form.tsx @@ -23,9 +23,12 @@ import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; import type { ExceptionListItemSchema } from '@kbn/securitysolution-io-ts-list-types'; -import { EVENT_FILTERS_OPERATORS } from '@kbn/securitysolution-list-utils'; +import { + EVENT_FILTERS_OPERATORS, + hasWrongOperatorWithWildcard, +} from '@kbn/securitysolution-list-utils'; import { WildCardWithWrongOperatorCallout } from '@kbn/securitysolution-exception-list-components'; -import { OperatingSystem, validateHasWildcardWithWrongOperator } from '@kbn/securitysolution-utils'; +import { OperatingSystem } from '@kbn/securitysolution-utils'; import { getExceptionBuilderComponentLazy } from '@kbn/lists-plugin/public'; import type { OnChangeProps } from '@kbn/lists-plugin/public'; @@ -146,8 +149,10 @@ export const EventFiltersForm: React.FC(false); - const [hasWildcardWithWrongOperator, setHasWildcardWithWrongOperator] = - useState(false); + const [hasWildcardWithWrongOperator, setHasWildcardWithWrongOperator] = useState( + hasWrongOperatorWithWildcard([exception]) + ); + // This value has to be memoized to avoid infinite useEffect loop on useFetchIndex const indexNames = useMemo(() => [eventsIndexPattern], []); const [isIndexPatternLoading, { indexPatterns }] = useFetchIndex( @@ -425,17 +430,7 @@ export const EventFiltersForm: React.FC { - if ( - validateHasWildcardWithWrongOperator({ - operator: (e as EventFilterItemEntries[number]).type, - value: (e as EventFilterItemEntries[number]).value, - }) - ) { - setHasWildcardWithWrongOperator(true); - } - }); + setHasWildcardWithWrongOperator(hasWrongOperatorWithWildcard(arg.exceptionItems)); const updatedItem: Partial = arg.exceptionItems[0] !== undefined diff --git a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/translations.ts b/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/translations.ts index 115e4a9f3add1..c1e544be537ef 100644 --- a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/translations.ts +++ b/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/translations.ts @@ -156,7 +156,7 @@ export const INPUT_ERRORS = { ), wildcardWithWrongOperatorWarning: (index: number) => i18n.translate('xpack.securitySolution.trustedapps.create.conditionWrongOperatorMsg', { - defaultMessage: `[{row}] Using a '*' or a '?' in the value with the 'IS' operator can make the entry ineffective. Change the operator to 'matches' to ensure wildcards run properly.`, + defaultMessage: `[{row}] Using a "*" or a "?" in the value with the "is" operator can make the entry ineffective. Change the operator to "matches" to ensure wildcards run properly.`, values: { row: index + 1 }, }), wildcardWithWrongField: (index: number) =>