From 1dd669cb09f33620422e148206c0276b20f00b94 Mon Sep 17 00:00:00 2001 From: Ashokaditya <1849116+ashokaditya@users.noreply.github.com> Date: Thu, 16 Dec 2021 18:58:09 +0100 Subject: [PATCH] [Security Solution][Endpoint] Improve endpoint performance with TA wildcard paths (#120349) * Show full executable names in placeholder for wildcard paths fixes elastic/security-team/issues/2293 * Show soft warning when wildcard also in executable names fixes elastic/security-team/issues/2293 * add wildcard path entries to fake TA list refs elastic/security-team/issues/2293 * Append a process.name entry when executable name in wildcard path fixes elastic/security-team/issues/2293 * commit using ashokaditya@elastic.co * linux should always use `_cased` types review changes * use better TS * use matcher functions to compute operator value for linux review suggestions * use path to extract filenames on server side review suggestions * improve regex for windows and unix filepaths review suggestions * update test mocks review changes * update regex to match multi spaces and single chars with spaces in filenames * add comment to explain review suggestions * update copy Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../exceptions_list_item_generator.ts | 5 +- .../data_generators/trusted_app_generator.ts | 25 ++- .../service/trusted_apps/validations.test.ts | 57 ++++++- .../service/trusted_apps/validations.ts | 29 ++++ .../common/utils/path_placeholder.ts | 4 +- .../artifact_entry_card.test.tsx | 4 +- .../artifact_entry_card_minified.test.tsx | 2 +- .../artifact_entry_card/test_utils.ts | 2 +- .../pages/mocks/trusted_apps_http_mocks.ts | 8 +- .../policy_trusted_apps_layout.test.tsx | 4 +- .../components/create_trusted_app_form.tsx | 28 +++- .../view/trusted_apps_page.test.tsx | 2 +- .../server/endpoint/lib/artifacts/lists.ts | 149 +++++++++++++++--- .../endpoint/schemas/artifacts/lists.ts | 24 +++ 14 files changed, 296 insertions(+), 47 deletions(-) diff --git a/x-pack/plugins/security_solution/common/endpoint/data_generators/exceptions_list_item_generator.ts b/x-pack/plugins/security_solution/common/endpoint/data_generators/exceptions_list_item_generator.ts index fe14e51490471..d66f1e950c34f 100644 --- a/x-pack/plugins/security_solution/common/endpoint/data_generators/exceptions_list_item_generator.ts +++ b/x-pack/plugins/security_solution/common/endpoint/data_generators/exceptions_list_item_generator.ts @@ -29,7 +29,10 @@ export class ExceptionsListItemGenerator extends BaseDataGenerator { ...(scopeType === 'policy' ? { policies: this.randomArray(5, () => this.randomUUID()) } : {}), }) as EffectScope; + const os = overrides.os ?? 'windows'; + const pathEntry = this.randomChoice([ + { + field: ConditionEntryField.PATH, + operator: 'included', + type: 'match', + value: os !== 'windows' ? '/one/two/three' : 'c:\\fol\\bin.exe', + }, + { + field: ConditionEntryField.PATH, + operator: 'included', + type: 'wildcard', + value: os !== 'windows' ? '/one/t*/*re/three.app' : 'c:\\fol*\\*ub*\\bin.exe', + }, + ]); + // TS types are conditional when it comes to the combination of OS and ENTRIES // @ts-expect-error TS2322 return merge( { description: `Generator says we trust ${name}`, name, - os: this.randomOSFamily(), + os, effectScope, entries: [ { @@ -82,12 +98,7 @@ export class TrustedAppGenerator extends BaseDataGenerator { type: 'match', value: '1234234659af249ddf3e40864e9fb241', }, - { - field: ConditionEntryField.PATH, - operator: 'included', - type: 'match', - value: '/one/two/three', - }, + pathEntry, ], }, overrides diff --git a/x-pack/plugins/security_solution/common/endpoint/service/trusted_apps/validations.test.ts b/x-pack/plugins/security_solution/common/endpoint/service/trusted_apps/validations.test.ts index ae95c21630bd8..952a2fa234ace 100644 --- a/x-pack/plugins/security_solution/common/endpoint/service/trusted_apps/validations.test.ts +++ b/x-pack/plugins/security_solution/common/endpoint/service/trusted_apps/validations.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { isPathValid } from './validations'; +import { isPathValid, hasSimpleExecutableName } from './validations'; import { OperatingSystem, ConditionEntryField } from '../../types'; describe('Unacceptable Windows wildcard paths', () => { @@ -504,3 +504,58 @@ describe('Unacceptable Mac/Linux exact paths', () => { ).toEqual(false); }); }); + +describe('Executable filenames with wildcard PATHS', () => { + it('should return TRUE when MAC/LINUX wildcard paths have an executable name', () => { + expect( + hasSimpleExecutableName({ + os: OperatingSystem.LINUX, + type: 'wildcard', + value: '/opt/*/app', + }) + ).toEqual(true); + expect( + hasSimpleExecutableName({ + os: OperatingSystem.MAC, + type: 'wildcard', + value: '/op*/**/app.dmg', + }) + ).toEqual(true); + }); + + it('should return TRUE when WINDOWS wildcards paths have a executable name', () => { + expect( + hasSimpleExecutableName({ + os: OperatingSystem.WINDOWS, + type: 'wildcard', + value: 'c:\\**\\path.exe', + }) + ).toEqual(true); + }); + + it('should return FALSE when MAC/LINUX wildcard paths have a wildcard in executable name', () => { + expect( + hasSimpleExecutableName({ + os: OperatingSystem.LINUX, + type: 'wildcard', + value: '/op/*/*pp', + }) + ).toEqual(false); + expect( + hasSimpleExecutableName({ + os: OperatingSystem.MAC, + type: 'wildcard', + value: '/op*/b**/ap.m**', + }) + ).toEqual(false); + }); + it('should return FALSE when WINDOWS wildcards paths have a wildcard in executable name', () => { + expect( + hasSimpleExecutableName({ + os: OperatingSystem.WINDOWS, + type: 'wildcard', + value: 'c:\\**\\pa*h.exe', + }) + ).toEqual(false); + }); +}); diff --git a/x-pack/plugins/security_solution/common/endpoint/service/trusted_apps/validations.ts b/x-pack/plugins/security_solution/common/endpoint/service/trusted_apps/validations.ts index 0fe3c0269bd15..3fee05e2f0061 100644 --- a/x-pack/plugins/security_solution/common/endpoint/service/trusted_apps/validations.ts +++ b/x-pack/plugins/security_solution/common/endpoint/service/trusted_apps/validations.ts @@ -34,6 +34,35 @@ export const getDuplicateFields = (entries: ConditionEntry[]) => { .map((entry) => entry[0]); }; +/* + * regex to match executable names + * starts matching from the eol of the path + * file names with a single or multiple spaces (for spaced names) + * and hyphens and combinations of these that produce complex names + * such as: + * c:\home\lib\dmp.dmp + * c:\home\lib\my-binary-app-+/ some/ x/ dmp.dmp + * /home/lib/dmp.dmp + * /home/lib/my-binary-app+-\ some\ x\ dmp.dmp + */ +const WIN_EXEC_PATH = /\\(\w+|\w*[\w+|-]+\/ +)+\w+[\w+|-]+\.*\w+$/i; +const UNIX_EXEC_PATH = /(\/|\w*[\w+|-]+\\ +)+\w+[\w+|-]+\.*\w*$/i; + +export const hasSimpleExecutableName = ({ + os, + type, + value, +}: { + os: OperatingSystem; + type: TrustedAppEntryTypes; + value: string; +}): boolean => { + if (type === 'wildcard') { + return os === OperatingSystem.WINDOWS ? WIN_EXEC_PATH.test(value) : UNIX_EXEC_PATH.test(value); + } + return true; +}; + export const isPathValid = ({ os, field, diff --git a/x-pack/plugins/security_solution/common/utils/path_placeholder.ts b/x-pack/plugins/security_solution/common/utils/path_placeholder.ts index bba01b6d05b65..b7dd541c6cc03 100644 --- a/x-pack/plugins/security_solution/common/utils/path_placeholder.ts +++ b/x-pack/plugins/security_solution/common/utils/path_placeholder.ts @@ -9,11 +9,11 @@ import { ConditionEntryField, OperatingSystem, TrustedAppEntryTypes } from '../e export const getPlaceholderText = () => ({ windows: { - wildcard: 'C:\\sample\\**\\*', + wildcard: 'C:\\sample\\**\\path.exe', exact: 'C:\\sample\\path.exe', }, others: { - wildcard: '/opt/**/*', + wildcard: '/opt/**/app', exact: '/opt/bin', }, }); diff --git a/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/artifact_entry_card.test.tsx b/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/artifact_entry_card.test.tsx index 289a8e407000f..fb2d9ba1ef00a 100644 --- a/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/artifact_entry_card.test.tsx +++ b/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/artifact_entry_card.test.tsx @@ -108,7 +108,7 @@ describe.each([ render(); expect(renderResult.getByTestId('testCard-criteriaConditions').textContent).toEqual( - ' OSIS WindowsAND process.hash.*IS 1234234659af249ddf3e40864e9fb241AND process.executable.caselessIS /one/two/three' + ' OSIS WindowsAND process.hash.*IS 1234234659af249ddf3e40864e9fb241AND process.executable.caselessIS c:\\fol\\bin.exe' ); }); @@ -124,7 +124,7 @@ describe.each([ render(); expect(renderResult.getByTestId('testCard-criteriaConditions').textContent).toEqual( - ` OSIS ${OS_LINUX}, ${OS_MAC}, ${OS_WINDOWS}AND process.hash.*IS 1234234659af249ddf3e40864e9fb241AND process.executable.caselessIS /one/two/three` + ` OSIS ${OS_LINUX}, ${OS_MAC}, ${OS_WINDOWS}AND process.hash.*IS 1234234659af249ddf3e40864e9fb241AND process.executable.caselessIS c:\\fol\\bin.exe` ); }); diff --git a/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/artifact_entry_card_minified.test.tsx b/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/artifact_entry_card_minified.test.tsx index 508dc3103ca12..17e9f83465274 100644 --- a/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/artifact_entry_card_minified.test.tsx +++ b/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/artifact_entry_card_minified.test.tsx @@ -69,7 +69,7 @@ describe.each([ await fireEvent.click(renderResult.getByTestId('testCard-collapse')); }); expect(renderResult.getByTestId('testCard-criteriaConditions').textContent).toEqual( - ' OSIS WindowsAND process.hash.*IS 1234234659af249ddf3e40864e9fb241AND process.executable.caselessIS /one/two/three' + ' OSIS WindowsAND process.hash.*IS 1234234659af249ddf3e40864e9fb241AND process.executable.caselessIS c:\\fol\\bin.exe' ); expect(renderResult.getByTestId('testCard-collapse').textContent).toEqual('Hide details'); }); diff --git a/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/test_utils.ts b/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/test_utils.ts index d7d8899b005ed..6482fc3d3331e 100644 --- a/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/test_utils.ts +++ b/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/test_utils.ts @@ -51,7 +51,7 @@ export const getExceptionProviderMock = (): ExceptionListItemSchema => { field: 'process.executable.caseless', operator: 'included', type: 'match', - value: '/one/two/three', + value: 'c:\\fol\\bin.exe', }, ], tags: ['policy:all'], diff --git a/x-pack/plugins/security_solution/public/management/pages/mocks/trusted_apps_http_mocks.ts b/x-pack/plugins/security_solution/public/management/pages/mocks/trusted_apps_http_mocks.ts index a175d516e9e9a..45bb3841c0098 100644 --- a/x-pack/plugins/security_solution/public/management/pages/mocks/trusted_apps_http_mocks.ts +++ b/x-pack/plugins/security_solution/public/management/pages/mocks/trusted_apps_http_mocks.ts @@ -58,7 +58,7 @@ export const trustedAppsGetListHttpMocks = const generator = new ExceptionsListItemGenerator('seed'); const perPage = apiQueryParams.per_page ?? 10; const data = Array.from({ length: Math.min(perPage, 50) }, () => - generator.generate({ list_id: ENDPOINT_TRUSTED_APPS_LIST_ID }) + generator.generate({ list_id: ENDPOINT_TRUSTED_APPS_LIST_ID, os_types: ['windows'] }) ); // FIXME: remove hard-coded IDs below adn get them from the new FleetPackagePolicyGenerator (#2262) @@ -128,7 +128,9 @@ export const trustedAppsGetOneHttpMocks = method: 'get', handler: ({ query }): ExceptionListItemSchema => { const apiQueryParams = query as ReadExceptionListItemSchema; - const exceptionItem = new ExceptionsListItemGenerator('seed').generate(); + const exceptionItem = new ExceptionsListItemGenerator('seed').generate({ + os_types: ['windows'], + }); exceptionItem.item_id = apiQueryParams.item_id ?? exceptionItem.item_id; exceptionItem.namespace_type = @@ -155,7 +157,7 @@ export const trustedAppPostHttpMocks = httpHandlerMockFactory { if (options.query?.filter === hasAnyQuery) { const exceptionsGenerator = new ExceptionsListItemGenerator('seed'); return { - data: Array.from({ length: 10 }, () => exceptionsGenerator.generate()), + data: Array.from({ length: 10 }, () => + exceptionsGenerator.generate({ os_types: ['windows'] }) + ), total: 10, page: 0, per_page: 10, 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 147529b164ae1..12bdea5736bfa 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 @@ -30,6 +30,7 @@ import { import { isValidHash, isPathValid, + hasSimpleExecutableName, } from '../../../../../../common/endpoint/service/trusted_apps/validations'; import { useIsExperimentalFeatureEnabled } from '../../../../../common/hooks/use_experimental_features'; @@ -136,6 +137,13 @@ const validateFormValues = (values: MaybeImmutable): ValidationRe ); } else { values.entries.forEach((entry, index) => { + const isValidPathEntry = isPathValid({ + os: values.os, + field: entry.field, + type: entry.type, + value: entry.value, + }); + if (!entry.field || !entry.value.trim()) { isValid = false; addResultToValidation( @@ -161,9 +169,7 @@ const validateFormValues = (values: MaybeImmutable): ValidationRe values: { row: index + 1 }, }) ); - } else if ( - !isPathValid({ os: values.os, field: entry.field, type: entry.type, value: entry.value }) - ) { + } else if (!isValidPathEntry) { addResultToValidation( validation, 'entries', @@ -173,6 +179,22 @@ const validateFormValues = (values: MaybeImmutable): ValidationRe values: { row: index + 1 }, }) ); + } else if ( + isValidPathEntry && + !hasSimpleExecutableName({ os: values.os, value: entry.value, type: entry.type }) + ) { + addResultToValidation( + validation, + 'entries', + 'warnings', + i18n.translate( + 'xpack.securitySolution.trustedapps.create.conditionFieldDegradedPerformanceMsg', + { + defaultMessage: `[{row}] A wildcard in the filename will affect the endpoint's performance`, + values: { row: index + 1 }, + } + ) + ); } }); } 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 6144679787554..01330eb0e246c 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 @@ -297,7 +297,7 @@ describe('When on the Trusted Apps Page', () => { field: 'process.executable.caseless', operator: 'included', type: 'match', - value: '/one/two/three', + value: 'c:\\fol\\bin.exe', }, ], os_types: ['windows'], diff --git a/x-pack/plugins/security_solution/server/endpoint/lib/artifacts/lists.ts b/x-pack/plugins/security_solution/server/endpoint/lib/artifacts/lists.ts index e26a2c7f4b4bc..d4a486539855b 100644 --- a/x-pack/plugins/security_solution/server/endpoint/lib/artifacts/lists.ts +++ b/x-pack/plugins/security_solution/server/endpoint/lib/artifacts/lists.ts @@ -5,6 +5,7 @@ * 2.0. */ +import path from 'path'; import { createHash } from 'crypto'; import type { Entry, @@ -19,14 +20,18 @@ import { ENDPOINT_LIST_ID, ENDPOINT_TRUSTED_APPS_LIST_ID, } from '@kbn/securitysolution-list-constants'; +import { OperatingSystem } from '../../../../common/endpoint/types'; import { ExceptionListClient } from '../../../../../lists/server'; import { InternalArtifactCompleteSchema, TranslatedEntry, + TranslatedPerformantEntries, + translatedPerformantEntries as translatedPerformantEntriesType, translatedEntry as translatedEntryType, translatedEntryMatchAnyMatcher, TranslatedEntryMatcher, translatedEntryMatchMatcher, + TranslatedEntryMatchWildcard, TranslatedEntryMatchWildcardMatcher, translatedEntryMatchWildcardMatcher, TranslatedEntryNestedEntry, @@ -35,6 +40,7 @@ import { WrappedTranslatedExceptionList, wrappedTranslatedExceptionList, } from '../../schemas'; +import { hasSimpleExecutableName } from '../../../../common/endpoint/service/trusted_apps/validations'; export async function buildArtifact( exceptions: WrappedTranslatedExceptionList, @@ -194,18 +200,38 @@ export function translateToEndpointExceptions( } } -function getMatcherFunction(field: string, matchAny?: boolean): TranslatedEntryMatcher { +function getMatcherFunction({ + field, + matchAny, + os, +}: { + field: string; + matchAny?: boolean; + os: ExceptionListItemSchema['os_types'][number]; +}): TranslatedEntryMatcher { return matchAny ? field.endsWith('.caseless') ? 'exact_caseless_any' : 'exact_cased_any' : field.endsWith('.caseless') - ? 'exact_caseless' + ? os === 'linux' + ? 'exact_cased' + : 'exact_caseless' : 'exact_cased'; } -function getMatcherWildcardFunction(field: string): TranslatedEntryMatchWildcardMatcher { - return field.endsWith('.caseless') ? 'wildcard_caseless' : 'wildcard_cased'; +function getMatcherWildcardFunction({ + field, + os, +}: { + field: string; + os: ExceptionListItemSchema['os_types'][number]; +}): TranslatedEntryMatchWildcardMatcher { + return field.endsWith('.caseless') + ? os === 'linux' + ? 'wildcard_cased' + : 'wildcard_caseless' + : 'wildcard_cased'; } function normalizeFieldName(field: string): string { @@ -217,31 +243,84 @@ function translateItem( item: ExceptionListItemSchema ): TranslatedExceptionListItem { const itemSet = new Set(); - return { - type: item.type, - entries: item.entries.reduce((translatedEntries, entry) => { - const translatedEntry = translateEntry(schemaVersion, entry); - if (translatedEntry !== undefined && translatedEntryType.is(translatedEntry)) { - const itemHash = createHash('sha256').update(JSON.stringify(translatedEntry)).digest('hex'); - if (!itemSet.has(itemHash)) { - translatedEntries.push(translatedEntry); - itemSet.add(itemHash); + const getEntries = (): TranslatedExceptionListItem['entries'] => { + return item.entries.reduce((translatedEntries, entry) => { + const translatedEntry = translateEntry(schemaVersion, entry, item.os_types[0]); + + if (translatedEntry !== undefined) { + if (translatedEntryType.is(translatedEntry)) { + const itemHash = createHash('sha256') + .update(JSON.stringify(translatedEntry)) + .digest('hex'); + if (!itemSet.has(itemHash)) { + translatedEntries.push(translatedEntry); + itemSet.add(itemHash); + } + } + if (translatedPerformantEntriesType.is(translatedEntry)) { + translatedEntry.forEach((tpe) => { + const itemHash = createHash('sha256').update(JSON.stringify(tpe)).digest('hex'); + if (!itemSet.has(itemHash)) { + translatedEntries.push(tpe); + itemSet.add(itemHash); + } + }); } } + return translatedEntries; - }, []), + }, []); + }; + + return { + type: item.type, + entries: getEntries(), }; } +function appendProcessNameEntry({ + wildcardProcessEntry, + entry, + os, +}: { + wildcardProcessEntry: TranslatedEntryMatchWildcard; + entry: { + field: string; + operator: 'excluded' | 'included'; + type: 'wildcard'; + value: string; + }; + os: ExceptionListItemSchema['os_types'][number]; +}): TranslatedPerformantEntries { + const entries: TranslatedPerformantEntries = [ + wildcardProcessEntry, + { + field: normalizeFieldName('process.name'), + operator: entry.operator, + type: (os === 'linux' ? 'exact_cased' : 'exact_caseless') as Extract< + TranslatedEntryMatcher, + 'exact_caseless' | 'exact_cased' + >, + value: os === 'windows' ? path.win32.basename(entry.value) : path.posix.basename(entry.value), + }, + ].reduce((p, c) => { + p.push(c); + return p; + }, []); + + return entries; +} + function translateEntry( schemaVersion: string, - entry: Entry | EntryNested -): TranslatedEntry | undefined { + entry: Entry | EntryNested, + os: ExceptionListItemSchema['os_types'][number] +): TranslatedEntry | TranslatedPerformantEntries | undefined { switch (entry.type) { case 'nested': { const nestedEntries = entry.entries.reduce( (entries, nestedEntry) => { - const translatedEntry = translateEntry(schemaVersion, nestedEntry); + const translatedEntry = translateEntry(schemaVersion, nestedEntry, os); if (nestedEntry !== undefined && translatedEntryNestedEntry.is(translatedEntry)) { entries.push(translatedEntry); } @@ -256,7 +335,7 @@ function translateEntry( }; } case 'match': { - const matcher = getMatcherFunction(entry.field); + const matcher = getMatcherFunction({ field: entry.field, os }); return translatedEntryMatchMatcher.is(matcher) ? { field: normalizeFieldName(entry.field), @@ -267,7 +346,7 @@ function translateEntry( : undefined; } case 'match_any': { - const matcher = getMatcherFunction(entry.field, true); + const matcher = getMatcherFunction({ field: entry.field, matchAny: true, os }); return translatedEntryMatchAnyMatcher.is(matcher) ? { field: normalizeFieldName(entry.field), @@ -278,15 +357,37 @@ function translateEntry( : undefined; } case 'wildcard': { - const matcher = getMatcherWildcardFunction(entry.field); - return translatedEntryMatchWildcardMatcher.is(matcher) - ? { + const wildcardMatcher = getMatcherWildcardFunction({ field: entry.field, os }); + const translatedEntryWildcardMatcher = + translatedEntryMatchWildcardMatcher.is(wildcardMatcher); + + const buildEntries = () => { + if (translatedEntryWildcardMatcher) { + // default process.executable entry + const wildcardProcessEntry: TranslatedEntryMatchWildcard = { field: normalizeFieldName(entry.field), operator: entry.operator, - type: matcher, + type: wildcardMatcher, value: entry.value, + }; + + const hasExecutableName = hasSimpleExecutableName({ + os: os as OperatingSystem, + type: entry.type, + value: entry.value, + }); + if (hasExecutableName) { + // when path has a full executable name + // append a process.name entry based on os + // `exact_cased` for linux and `exact_caseless` for others + return appendProcessNameEntry({ entry, os, wildcardProcessEntry }); + } else { + return wildcardProcessEntry; } - : undefined; + } + }; + + return buildEntries(); } } } diff --git a/x-pack/plugins/security_solution/server/endpoint/schemas/artifacts/lists.ts b/x-pack/plugins/security_solution/server/endpoint/schemas/artifacts/lists.ts index 3a37bfbe9320c..7703304e3ae5c 100644 --- a/x-pack/plugins/security_solution/server/endpoint/schemas/artifacts/lists.ts +++ b/x-pack/plugins/security_solution/server/endpoint/schemas/artifacts/lists.ts @@ -48,6 +48,24 @@ export const translatedEntryMatchWildcard = t.exact( ); export type TranslatedEntryMatchWildcard = t.TypeOf; +export const translatedEntryMatchWildcardNameMatcher = t.keyof({ + exact_cased: null, + exact_caseless: null, +}); +export type TranslatedEntryMatchWildcardNameMatcher = t.TypeOf< + typeof translatedEntryMatchWildcardNameMatcher +>; + +export const translatedEntryMatchWildcardName = t.exact( + t.type({ + field: t.string, + operator, + type: translatedEntryMatchWildcardNameMatcher, + value: t.string, + }) +); +export type TranslatedEntryMatchWildcardName = t.TypeOf; + export const translatedEntryMatch = t.exact( t.type({ field: t.string, @@ -84,6 +102,12 @@ export const translatedEntry = t.union([ ]); export type TranslatedEntry = t.TypeOf; +export const translatedPerformantEntries = t.array( + t.union([translatedEntryMatchWildcard, translatedEntryMatchWildcardName]) +); + +export type TranslatedPerformantEntries = t.TypeOf; + export const translatedExceptionListItem = t.exact( t.type({ type: t.string,