diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/build_exceptions_query.test.ts b/x-pack/plugins/security_solution/common/detection_engine/build_exceptions_query.test.ts similarity index 99% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/build_exceptions_query.test.ts rename to x-pack/plugins/security_solution/common/detection_engine/build_exceptions_query.test.ts index ce7cc50e81d671..ed0344207d18fd 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/build_exceptions_query.test.ts +++ b/x-pack/plugins/security_solution/common/detection_engine/build_exceptions_query.test.ts @@ -17,13 +17,13 @@ import { buildNested, } from './build_exceptions_query'; import { - EntriesArray, + EntryNested, EntryExists, EntryMatch, EntryMatchAny, - EntryNested, -} from '../../../../../lists/common/schemas'; -import { getExceptionListItemSchemaMock } from '../../../../../lists/common/schemas/response/exception_list_item_schema.mock'; + EntriesArray, +} from '../../../lists/common/schemas'; +import { getExceptionListItemSchemaMock } from '../../../lists/common/schemas/response/exception_list_item_schema.mock'; describe('build_exceptions_query', () => { describe('getLanguageBooleanOperator', () => { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/build_exceptions_query.ts b/x-pack/plugins/security_solution/common/detection_engine/build_exceptions_query.ts similarity index 95% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/build_exceptions_query.ts rename to x-pack/plugins/security_solution/common/detection_engine/build_exceptions_query.ts index ba0d9dec7d1b02..36353d42d26b75 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/build_exceptions_query.ts +++ b/x-pack/plugins/security_solution/common/detection_engine/build_exceptions_query.ts @@ -3,11 +3,9 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { Language, Query } from '../../../../common/detection_engine/schemas/common/schemas'; -import { Query as DataQuery } from '../../../../../../../src/plugins/data/server'; +import { Query as DataQuery } from '../../../../../src/plugins/data/common'; import { Entry, - ExceptionListItemSchema, EntryMatch, EntryMatchAny, EntryNested, @@ -19,7 +17,9 @@ import { entriesMatch, entriesNested, entriesList, -} from '../../../../../lists/common/schemas'; + ExceptionListItemSchema, +} from '../../../lists/common/schemas'; +import { Language, Query } from './schemas/common/schemas'; type Operators = 'and' | 'or' | 'not'; type LuceneOperators = 'AND' | 'OR' | 'NOT'; diff --git a/x-pack/plugins/security_solution/common/detection_engine/get_query_filter.test.ts b/x-pack/plugins/security_solution/common/detection_engine/get_query_filter.test.ts new file mode 100644 index 00000000000000..6edd2489e90c95 --- /dev/null +++ b/x-pack/plugins/security_solution/common/detection_engine/get_query_filter.test.ts @@ -0,0 +1,650 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { getQueryFilter } from './get_query_filter'; +import { Filter } from 'src/plugins/data/public'; +import { getExceptionListItemSchemaMock } from '../../../lists/common/schemas/response/exception_list_item_schema.mock'; + +describe('get_filter', () => { + describe('getQueryFilter', () => { + test('it should work with an empty filter as kuery', () => { + const esQuery = getQueryFilter('host.name: linux', 'kuery', [], ['auditbeat-*'], []); + expect(esQuery).toEqual({ + bool: { + must: [], + filter: [ + { + bool: { + should: [ + { + match: { + 'host.name': 'linux', + }, + }, + ], + minimum_should_match: 1, + }, + }, + ], + should: [], + must_not: [], + }, + }); + }); + + test('it should work with an empty filter as lucene', () => { + const esQuery = getQueryFilter('host.name: linux', 'lucene', [], ['auditbeat-*'], []); + expect(esQuery).toEqual({ + bool: { + must: [ + { + query_string: { + query: 'host.name: linux', + analyze_wildcard: true, + time_zone: 'Zulu', + }, + }, + ], + filter: [], + should: [], + must_not: [], + }, + }); + }); + + test('it should work with a simple filter as a kuery', () => { + const esQuery = getQueryFilter( + 'host.name: windows', + 'kuery', + [ + { + meta: { + alias: 'custom label here', + disabled: false, + key: 'host.name', + negate: false, + params: { + query: 'siem-windows', + }, + type: 'phrase', + }, + query: { + match_phrase: { + 'host.name': 'siem-windows', + }, + }, + }, + ], + ['auditbeat-*'], + [] + ); + expect(esQuery).toEqual({ + bool: { + must: [], + filter: [ + { + bool: { + should: [ + { + match: { + 'host.name': 'windows', + }, + }, + ], + minimum_should_match: 1, + }, + }, + { + match_phrase: { + 'host.name': 'siem-windows', + }, + }, + ], + should: [], + must_not: [], + }, + }); + }); + + test('it should work with a simple filter as a kuery without meta information', () => { + const esQuery = getQueryFilter( + 'host.name: windows', + 'kuery', + [ + { + query: { + match_phrase: { + 'host.name': 'siem-windows', + }, + }, + }, + ], + ['auditbeat-*'], + [] + ); + expect(esQuery).toEqual({ + bool: { + must: [], + filter: [ + { + bool: { + should: [ + { + match: { + 'host.name': 'windows', + }, + }, + ], + minimum_should_match: 1, + }, + }, + { + match_phrase: { + 'host.name': 'siem-windows', + }, + }, + ], + should: [], + must_not: [], + }, + }); + }); + + test('it should work with a simple filter as a kuery without meta information with an exists', () => { + const query: Partial = { + query: { + match_phrase: { + 'host.name': 'siem-windows', + }, + }, + }; + + const exists: Partial = { + exists: { + field: 'host.hostname', + }, + } as Partial; + + const esQuery = getQueryFilter( + 'host.name: windows', + 'kuery', + [query, exists], + ['auditbeat-*'], + [] + ); + expect(esQuery).toEqual({ + bool: { + must: [], + filter: [ + { + bool: { + should: [ + { + match: { + 'host.name': 'windows', + }, + }, + ], + minimum_should_match: 1, + }, + }, + { + match_phrase: { + 'host.name': 'siem-windows', + }, + }, + { + exists: { + field: 'host.hostname', + }, + }, + ], + should: [], + must_not: [], + }, + }); + }); + + test('it should work with a simple filter that is disabled as a kuery', () => { + const esQuery = getQueryFilter( + 'host.name: windows', + 'kuery', + [ + { + meta: { + alias: 'custom label here', + disabled: true, + key: 'host.name', + negate: false, + params: { + query: 'siem-windows', + }, + type: 'phrase', + }, + query: { + match_phrase: { + 'host.name': 'siem-windows', + }, + }, + }, + ], + ['auditbeat-*'], + [] + ); + expect(esQuery).toEqual({ + bool: { + must: [], + filter: [ + { + bool: { + should: [ + { + match: { + 'host.name': 'windows', + }, + }, + ], + minimum_should_match: 1, + }, + }, + ], + should: [], + must_not: [], + }, + }); + }); + + test('it should work with a simple filter as a lucene', () => { + const esQuery = getQueryFilter( + 'host.name: windows', + 'lucene', + [ + { + meta: { + alias: 'custom label here', + disabled: false, + key: 'host.name', + negate: false, + params: { + query: 'siem-windows', + }, + type: 'phrase', + }, + query: { + match_phrase: { + 'host.name': 'siem-windows', + }, + }, + }, + ], + ['auditbeat-*'], + [] + ); + expect(esQuery).toEqual({ + bool: { + must: [ + { + query_string: { + query: 'host.name: windows', + analyze_wildcard: true, + time_zone: 'Zulu', + }, + }, + ], + filter: [ + { + match_phrase: { + 'host.name': 'siem-windows', + }, + }, + ], + should: [], + must_not: [], + }, + }); + }); + + test('it should work with a simple filter that is disabled as a lucene', () => { + const esQuery = getQueryFilter( + 'host.name: windows', + 'lucene', + [ + { + meta: { + alias: 'custom label here', + disabled: true, + key: 'host.name', + negate: false, + params: { + query: 'siem-windows', + }, + type: 'phrase', + }, + query: { + match_phrase: { + 'host.name': 'siem-windows', + }, + }, + }, + ], + ['auditbeat-*'], + [] + ); + expect(esQuery).toEqual({ + bool: { + must: [ + { + query_string: { + query: 'host.name: windows', + analyze_wildcard: true, + time_zone: 'Zulu', + }, + }, + ], + filter: [], + should: [], + must_not: [], + }, + }); + }); + + test('it should work with a list', () => { + const esQuery = getQueryFilter( + 'host.name: linux', + 'kuery', + [], + ['auditbeat-*'], + [getExceptionListItemSchemaMock()] + ); + expect(esQuery).toEqual({ + bool: { + filter: [ + { + bool: { + filter: [ + { + bool: { + minimum_should_match: 1, + should: [ + { + match: { + 'host.name': 'linux', + }, + }, + ], + }, + }, + { + bool: { + filter: [ + { + nested: { + path: 'some.parentField', + query: { + bool: { + minimum_should_match: 1, + should: [ + { + match: { + 'some.parentField.nested.field': 'some value', + }, + }, + ], + }, + }, + score_mode: 'none', + }, + }, + { + bool: { + must_not: { + bool: { + minimum_should_match: 1, + should: [ + { + match: { + 'some.not.nested.field': 'some value', + }, + }, + ], + }, + }, + }, + }, + ], + }, + }, + ], + }, + }, + ], + must: [], + must_not: [], + should: [], + }, + }); + }); + + test('it should work with an empty list', () => { + const esQuery = getQueryFilter('host.name: linux', 'kuery', [], ['auditbeat-*'], []); + expect(esQuery).toEqual({ + bool: { + filter: [ + { bool: { minimum_should_match: 1, should: [{ match: { 'host.name': 'linux' } }] } }, + ], + must: [], + must_not: [], + should: [], + }, + }); + }); + + test('it should work when lists has value undefined', () => { + const esQuery = getQueryFilter('host.name: linux', 'kuery', [], ['auditbeat-*'], []); + expect(esQuery).toEqual({ + bool: { + filter: [ + { bool: { minimum_should_match: 1, should: [{ match: { 'host.name': 'linux' } }] } }, + ], + must: [], + must_not: [], + should: [], + }, + }); + }); + + test('it should work with a nested object queries', () => { + const esQuery = getQueryFilter( + 'category:{ name:Frank and trusted:true }', + 'kuery', + [], + ['auditbeat-*'], + [] + ); + expect(esQuery).toEqual({ + bool: { + must: [], + filter: [ + { + nested: { + path: 'category', + query: { + bool: { + filter: [ + { + bool: { + should: [ + { + match: { + 'category.name': 'Frank', + }, + }, + ], + minimum_should_match: 1, + }, + }, + { + bool: { + should: [ + { + match: { + 'category.trusted': true, + }, + }, + ], + minimum_should_match: 1, + }, + }, + ], + }, + }, + score_mode: 'none', + }, + }, + ], + should: [], + must_not: [], + }, + }); + }); + + test('it works with references and does not add indexes', () => { + const esQuery = getQueryFilter( + '(event.module:suricata and event.kind:alert) and suricata.eve.alert.signature_id: (2610182 or 2610183 or 2610184 or 2610185 or 2610186 or 2610187)', + 'kuery', + [], + ['my custom index'], + [] + ); + expect(esQuery).toEqual({ + bool: { + must: [], + filter: [ + { + bool: { + filter: [ + { + bool: { + filter: [ + { + bool: { + should: [{ match: { 'event.module': 'suricata' } }], + minimum_should_match: 1, + }, + }, + { + bool: { + should: [{ match: { 'event.kind': 'alert' } }], + minimum_should_match: 1, + }, + }, + ], + }, + }, + { + bool: { + should: [ + { + bool: { + should: [{ match: { 'suricata.eve.alert.signature_id': 2610182 } }], + minimum_should_match: 1, + }, + }, + { + bool: { + should: [ + { + bool: { + should: [ + { match: { 'suricata.eve.alert.signature_id': 2610183 } }, + ], + minimum_should_match: 1, + }, + }, + { + bool: { + should: [ + { + bool: { + should: [ + { match: { 'suricata.eve.alert.signature_id': 2610184 } }, + ], + minimum_should_match: 1, + }, + }, + { + bool: { + should: [ + { + bool: { + should: [ + { + match: { + 'suricata.eve.alert.signature_id': 2610185, + }, + }, + ], + minimum_should_match: 1, + }, + }, + { + bool: { + should: [ + { + bool: { + should: [ + { + match: { + 'suricata.eve.alert.signature_id': 2610186, + }, + }, + ], + minimum_should_match: 1, + }, + }, + { + bool: { + should: [ + { + match: { + 'suricata.eve.alert.signature_id': 2610187, + }, + }, + ], + minimum_should_match: 1, + }, + }, + ], + minimum_should_match: 1, + }, + }, + ], + minimum_should_match: 1, + }, + }, + ], + minimum_should_match: 1, + }, + }, + ], + minimum_should_match: 1, + }, + }, + ], + minimum_should_match: 1, + }, + }, + ], + }, + }, + ], + should: [], + must_not: [], + }, + }); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/common/detection_engine/get_query_filter.ts b/x-pack/plugins/security_solution/common/detection_engine/get_query_filter.ts new file mode 100644 index 00000000000000..ef390c3b449395 --- /dev/null +++ b/x-pack/plugins/security_solution/common/detection_engine/get_query_filter.ts @@ -0,0 +1,41 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { + Filter, + IIndexPattern, + isFilterDisabled, + buildEsQuery, + Query as DataQuery, +} from '../../../../../src/plugins/data/common'; +import { ExceptionListItemSchema } from '../../../lists/common/schemas'; +import { buildQueryExceptions } from './build_exceptions_query'; +import { Query, Language, Index } from './schemas/common/schemas'; + +export const getQueryFilter = ( + query: Query, + language: Language, + filters: Array>, + index: Index, + lists: ExceptionListItemSchema[] +) => { + const indexPattern: IIndexPattern = { + fields: [], + title: index.join(), + }; + + const queries: DataQuery[] = buildQueryExceptions({ query, language, lists }); + + const config = { + allowLeadingWildcards: true, + queryStringOptions: { analyze_wildcard: true }, + ignoreFilterIfFieldNotInIndex: false, + dateFormatTZ: 'Zulu', + }; + + const enabledFilters = ((filters as unknown) as Filter[]).filter((f) => !isFilterDisabled(f)); + return buildEsQuery(indexPattern, queries, enabledFilters, config); +}; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/get_filter.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/get_filter.test.ts index 9b3a446bc666dc..f34879781e0b02 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/get_filter.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/get_filter.test.ts @@ -4,8 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { getQueryFilter, getFilter } from './get_filter'; -import { PartialFilter } from '../types'; +import { getFilter } from './get_filter'; import { alertsMock, AlertServicesMock } from '../../../../../alerts/server/mocks'; import { getExceptionListItemSchemaMock } from '../../../../../lists/common/schemas/response/exception_list_item_schema.mock'; @@ -34,509 +33,6 @@ describe('get_filter', () => { jest.resetAllMocks(); }); - describe('getQueryFilter', () => { - test('it should work with an empty filter as kuery', () => { - const esQuery = getQueryFilter('host.name: linux', 'kuery', [], ['auditbeat-*'], []); - expect(esQuery).toEqual({ - bool: { - must: [], - filter: [ - { - bool: { - should: [ - { - match: { - 'host.name': 'linux', - }, - }, - ], - minimum_should_match: 1, - }, - }, - ], - should: [], - must_not: [], - }, - }); - }); - - test('it should work with an empty filter as lucene', () => { - const esQuery = getQueryFilter('host.name: linux', 'lucene', [], ['auditbeat-*'], []); - expect(esQuery).toEqual({ - bool: { - must: [ - { - query_string: { - query: 'host.name: linux', - analyze_wildcard: true, - time_zone: 'Zulu', - }, - }, - ], - filter: [], - should: [], - must_not: [], - }, - }); - }); - - test('it should work with a simple filter as a kuery', () => { - const esQuery = getQueryFilter( - 'host.name: windows', - 'kuery', - [ - { - meta: { - alias: 'custom label here', - disabled: false, - key: 'host.name', - negate: false, - params: { - query: 'siem-windows', - }, - type: 'phrase', - }, - query: { - match_phrase: { - 'host.name': 'siem-windows', - }, - }, - }, - ], - ['auditbeat-*'], - [] - ); - expect(esQuery).toEqual({ - bool: { - must: [], - filter: [ - { - bool: { - should: [ - { - match: { - 'host.name': 'windows', - }, - }, - ], - minimum_should_match: 1, - }, - }, - { - match_phrase: { - 'host.name': 'siem-windows', - }, - }, - ], - should: [], - must_not: [], - }, - }); - }); - - test('it should work with a simple filter as a kuery without meta information', () => { - const esQuery = getQueryFilter( - 'host.name: windows', - 'kuery', - [ - { - query: { - match_phrase: { - 'host.name': 'siem-windows', - }, - }, - }, - ], - ['auditbeat-*'], - [] - ); - expect(esQuery).toEqual({ - bool: { - must: [], - filter: [ - { - bool: { - should: [ - { - match: { - 'host.name': 'windows', - }, - }, - ], - minimum_should_match: 1, - }, - }, - { - match_phrase: { - 'host.name': 'siem-windows', - }, - }, - ], - should: [], - must_not: [], - }, - }); - }); - - test('it should work with a simple filter as a kuery without meta information with an exists', () => { - const query: PartialFilter = { - query: { - match_phrase: { - 'host.name': 'siem-windows', - }, - }, - } as PartialFilter; - - const exists: PartialFilter = { - exists: { - field: 'host.hostname', - }, - } as PartialFilter; - - const esQuery = getQueryFilter( - 'host.name: windows', - 'kuery', - [query, exists], - ['auditbeat-*'], - [] - ); - expect(esQuery).toEqual({ - bool: { - must: [], - filter: [ - { - bool: { - should: [ - { - match: { - 'host.name': 'windows', - }, - }, - ], - minimum_should_match: 1, - }, - }, - { - match_phrase: { - 'host.name': 'siem-windows', - }, - }, - { - exists: { - field: 'host.hostname', - }, - }, - ], - should: [], - must_not: [], - }, - }); - }); - - test('it should work with a simple filter that is disabled as a kuery', () => { - const esQuery = getQueryFilter( - 'host.name: windows', - 'kuery', - [ - { - meta: { - alias: 'custom label here', - disabled: true, - key: 'host.name', - negate: false, - params: { - query: 'siem-windows', - }, - type: 'phrase', - }, - query: { - match_phrase: { - 'host.name': 'siem-windows', - }, - }, - }, - ], - ['auditbeat-*'], - [] - ); - expect(esQuery).toEqual({ - bool: { - must: [], - filter: [ - { - bool: { - should: [ - { - match: { - 'host.name': 'windows', - }, - }, - ], - minimum_should_match: 1, - }, - }, - ], - should: [], - must_not: [], - }, - }); - }); - - test('it should work with a simple filter as a lucene', () => { - const esQuery = getQueryFilter( - 'host.name: windows', - 'lucene', - [ - { - meta: { - alias: 'custom label here', - disabled: false, - key: 'host.name', - negate: false, - params: { - query: 'siem-windows', - }, - type: 'phrase', - }, - query: { - match_phrase: { - 'host.name': 'siem-windows', - }, - }, - }, - ], - ['auditbeat-*'], - [] - ); - expect(esQuery).toEqual({ - bool: { - must: [ - { - query_string: { - query: 'host.name: windows', - analyze_wildcard: true, - time_zone: 'Zulu', - }, - }, - ], - filter: [ - { - match_phrase: { - 'host.name': 'siem-windows', - }, - }, - ], - should: [], - must_not: [], - }, - }); - }); - - test('it should work with a simple filter that is disabled as a lucene', () => { - const esQuery = getQueryFilter( - 'host.name: windows', - 'lucene', - [ - { - meta: { - alias: 'custom label here', - disabled: true, - key: 'host.name', - negate: false, - params: { - query: 'siem-windows', - }, - type: 'phrase', - }, - query: { - match_phrase: { - 'host.name': 'siem-windows', - }, - }, - }, - ], - ['auditbeat-*'], - [] - ); - expect(esQuery).toEqual({ - bool: { - must: [ - { - query_string: { - query: 'host.name: windows', - analyze_wildcard: true, - time_zone: 'Zulu', - }, - }, - ], - filter: [], - should: [], - must_not: [], - }, - }); - }); - - test('it should work with a list', () => { - const esQuery = getQueryFilter( - 'host.name: linux', - 'kuery', - [], - ['auditbeat-*'], - [getExceptionListItemSchemaMock()] - ); - expect(esQuery).toEqual({ - bool: { - filter: [ - { - bool: { - filter: [ - { - bool: { - minimum_should_match: 1, - should: [ - { - match: { - 'host.name': 'linux', - }, - }, - ], - }, - }, - { - bool: { - filter: [ - { - nested: { - path: 'some.parentField', - query: { - bool: { - minimum_should_match: 1, - should: [ - { - match: { - 'some.parentField.nested.field': 'some value', - }, - }, - ], - }, - }, - score_mode: 'none', - }, - }, - { - bool: { - must_not: { - bool: { - minimum_should_match: 1, - should: [ - { - match: { - 'some.not.nested.field': 'some value', - }, - }, - ], - }, - }, - }, - }, - ], - }, - }, - ], - }, - }, - ], - must: [], - must_not: [], - should: [], - }, - }); - }); - - test('it should work with an empty list', () => { - const esQuery = getQueryFilter('host.name: linux', 'kuery', [], ['auditbeat-*'], []); - expect(esQuery).toEqual({ - bool: { - filter: [ - { bool: { minimum_should_match: 1, should: [{ match: { 'host.name': 'linux' } }] } }, - ], - must: [], - must_not: [], - should: [], - }, - }); - }); - - test('it should work when lists has value undefined', () => { - const esQuery = getQueryFilter('host.name: linux', 'kuery', [], ['auditbeat-*'], []); - expect(esQuery).toEqual({ - bool: { - filter: [ - { bool: { minimum_should_match: 1, should: [{ match: { 'host.name': 'linux' } }] } }, - ], - must: [], - must_not: [], - should: [], - }, - }); - }); - - test('it should work with a nested object queries', () => { - const esQuery = getQueryFilter( - 'category:{ name:Frank and trusted:true }', - 'kuery', - [], - ['auditbeat-*'], - [] - ); - expect(esQuery).toEqual({ - bool: { - must: [], - filter: [ - { - nested: { - path: 'category', - query: { - bool: { - filter: [ - { - bool: { - should: [ - { - match: { - 'category.name': 'Frank', - }, - }, - ], - minimum_should_match: 1, - }, - }, - { - bool: { - should: [ - { - match: { - 'category.trusted': true, - }, - }, - ], - minimum_should_match: 1, - }, - }, - ], - }, - }, - score_mode: 'none', - }, - }, - ], - should: [], - must_not: [], - }, - }); - }); - }); - describe('getFilter', () => { test('returns a query if given a type of query', async () => { const filter = await getFilter({ @@ -685,142 +181,6 @@ describe('get_filter', () => { ).rejects.toThrow('Unsupported Rule of type "machine_learning" supplied to getFilter'); }); - test('it works with references and does not add indexes', () => { - const esQuery = getQueryFilter( - '(event.module:suricata and event.kind:alert) and suricata.eve.alert.signature_id: (2610182 or 2610183 or 2610184 or 2610185 or 2610186 or 2610187)', - 'kuery', - [], - ['my custom index'], - [] - ); - expect(esQuery).toEqual({ - bool: { - must: [], - filter: [ - { - bool: { - filter: [ - { - bool: { - filter: [ - { - bool: { - should: [{ match: { 'event.module': 'suricata' } }], - minimum_should_match: 1, - }, - }, - { - bool: { - should: [{ match: { 'event.kind': 'alert' } }], - minimum_should_match: 1, - }, - }, - ], - }, - }, - { - bool: { - should: [ - { - bool: { - should: [{ match: { 'suricata.eve.alert.signature_id': 2610182 } }], - minimum_should_match: 1, - }, - }, - { - bool: { - should: [ - { - bool: { - should: [ - { match: { 'suricata.eve.alert.signature_id': 2610183 } }, - ], - minimum_should_match: 1, - }, - }, - { - bool: { - should: [ - { - bool: { - should: [ - { match: { 'suricata.eve.alert.signature_id': 2610184 } }, - ], - minimum_should_match: 1, - }, - }, - { - bool: { - should: [ - { - bool: { - should: [ - { - match: { - 'suricata.eve.alert.signature_id': 2610185, - }, - }, - ], - minimum_should_match: 1, - }, - }, - { - bool: { - should: [ - { - bool: { - should: [ - { - match: { - 'suricata.eve.alert.signature_id': 2610186, - }, - }, - ], - minimum_should_match: 1, - }, - }, - { - bool: { - should: [ - { - match: { - 'suricata.eve.alert.signature_id': 2610187, - }, - }, - ], - minimum_should_match: 1, - }, - }, - ], - minimum_should_match: 1, - }, - }, - ], - minimum_should_match: 1, - }, - }, - ], - minimum_should_match: 1, - }, - }, - ], - minimum_should_match: 1, - }, - }, - ], - minimum_should_match: 1, - }, - }, - ], - }, - }, - ], - should: [], - must_not: [], - }, - }); - }); - test('returns a query when given a list', async () => { const filter = await getFilter({ type: 'query', diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/get_filter.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/get_filter.ts index 50ce01aaa6f74f..4bd9de734f4480 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/get_filter.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/get_filter.ts @@ -4,6 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ +import { getQueryFilter } from '../../../../common/detection_engine/get_query_filter'; import { LanguageOrUndefined, QueryOrUndefined, @@ -11,50 +12,12 @@ import { SavedIdOrUndefined, IndexOrUndefined, Language, - Index, - Query, } from '../../../../common/detection_engine/schemas/common/schemas'; import { ExceptionListItemSchema } from '../../../../../lists/common/schemas'; import { AlertServices } from '../../../../../alerts/server'; import { assertUnreachable } from '../../../utils/build_query'; -import { - Filter, - Query as DataQuery, - esQuery, - esFilters, - IIndexPattern, -} from '../../../../../../../src/plugins/data/server'; import { PartialFilter } from '../types'; import { BadRequestError } from '../errors/bad_request_error'; -import { buildQueryExceptions } from './build_exceptions_query'; - -export const getQueryFilter = ( - query: Query, - language: Language, - filters: PartialFilter[], - index: Index, - lists: ExceptionListItemSchema[] -) => { - const indexPattern = { - fields: [], - title: index.join(), - } as IIndexPattern; - - const queries: DataQuery[] = buildQueryExceptions({ query, language, lists }); - - const config = { - allowLeadingWildcards: true, - queryStringOptions: { analyze_wildcard: true }, - ignoreFilterIfFieldNotInIndex: false, - dateFormatTZ: 'Zulu', - }; - - const enabledFilters = ((filters as unknown) as Filter[]).filter( - (f) => f && !esFilters.isFilterDisabled(f) - ); - - return esQuery.buildEsQuery(indexPattern, queries, enabledFilters, config); -}; interface GetFilterArgs { type: Type;