From b005ea907b7173b2aa7ab0974f9a2fcfef08de0d Mon Sep 17 00:00:00 2001 From: Vitalii Dmyterko <92328789+vitaliidm@users.noreply.github.com> Date: Mon, 30 Sep 2024 14:15:24 +0100 Subject: [PATCH] [Security Solution][Detection Engine] removes field_caps call for all fields in index during rule execution (#193869) ## Summary - addresses https://github.com/elastic/kibana/issues/187059 ### Checklist Delete any items that are not applicable to this PR. - [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 --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .../create_security_rule_type_wrapper.ts | 21 ----- .../create_indicator_match_alert_type.ts | 2 - .../indicator_match/indicator_match.ts | 5 +- .../threat_mapping/create_event_signal.ts | 1 + .../threat_mapping/create_threat_signal.ts | 1 + .../threat_mapping/create_threat_signals.ts | 20 ++-- .../indicator_match/threat_mapping/types.ts | 1 - .../new_terms/create_new_terms_alert_type.ts | 3 +- .../rule_types/query/query.ts | 1 - .../threshold/create_threshold_alert_type.ts | 2 - .../rule_types/threshold/threshold.test.ts | 4 +- .../rule_types/threshold/threshold.ts | 6 +- .../lib/detection_engine/rule_types/types.ts | 3 +- .../utils/get_fields_for_wildcard.test.ts | 94 ------------------- .../utils/get_fields_for_wildcard.ts | 39 -------- .../rule_types/utils/get_query_fields.ts | 28 ++++++ 16 files changed, 50 insertions(+), 181 deletions(-) delete mode 100644 x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/get_fields_for_wildcard.test.ts delete mode 100644 x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/get_fields_for_wildcard.ts create mode 100644 x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/get_query_fields.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/create_security_rule_type_wrapper.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/create_security_rule_type_wrapper.ts index f25a8429089b..ac56d2c41a8f 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/create_security_rule_type_wrapper.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/create_security_rule_type_wrapper.ts @@ -11,7 +11,6 @@ import agent from 'elastic-apm-node'; import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { TIMESTAMP } from '@kbn/rule-data-utils'; import { createPersistenceRuleTypeWrapper } from '@kbn/rule-registry-plugin/server'; -import type { DataViewFieldBase } from '@kbn/es-query'; import { buildExceptionFilter } from '@kbn/lists-plugin/server/services/exception_lists'; import { technicalRuleFieldMap } from '@kbn/rule-registry-plugin/common/assets/field_maps/technical_rule_field_map'; import type { FieldMap } from '@kbn/alerts-as-data-utils'; @@ -26,8 +25,6 @@ import { hasTimestampFields, isMachineLearningParams, isEsqlParams, - isQueryParams, - isEqlParams, getDisabledActionsWarningText, } from './utils/utils'; import { DEFAULT_MAX_SIGNALS, DEFAULT_SEARCH_AFTER_PAGE_SIZE } from '../../../../common/constants'; @@ -47,7 +44,6 @@ import { withSecuritySpan } from '../../../utils/with_security_span'; import { getInputIndex, DataViewError } from './utils/get_input_output_index'; import { TIMESTAMP_RUNTIME_FIELD } from './constants'; import { buildTimestampRuntimeMapping } from './utils/build_timestamp_runtime_mapping'; -import { getFieldsForWildcard } from './utils/get_fields_for_wildcard'; import { alertsFieldMap, rulesFieldMap } from '../../../../common/field_maps'; import { sendAlertSuppressionTelemetryEvent } from './utils/telemetry/send_alert_suppression_telemetry_event'; @@ -139,7 +135,6 @@ export const createSecurityRuleTypeWrapper: CreateSecurityRuleTypeWrapper = } = options; let runState = state; let inputIndex: string[] = []; - let inputIndexFields: DataViewFieldBase[] = []; let runtimeMappings: estypes.MappingRuntimeFields | undefined; const { from, maxSignals, timestampOverride, timestampOverrideFallbackDisabled, to } = params; @@ -337,21 +332,6 @@ export const createSecurityRuleTypeWrapper: CreateSecurityRuleTypeWrapper = }); } - if ( - !isMachineLearningParams(params) && - !isEsqlParams(params) && - !isQueryParams(params) && - !isEqlParams(params) - ) { - const dataViews = await services.getDataViews(); - inputIndexFields = await getFieldsForWildcard({ - index: inputIndex, - dataViews, - language: params.language, - ruleExecutionLogger, - }); - } - try { const { listClient, exceptionsClient } = getListClient({ esClient: services.scopedClusterClient.asCurrentUser, @@ -426,7 +406,6 @@ export const createSecurityRuleTypeWrapper: CreateSecurityRuleTypeWrapper = inputIndex, exceptionFilter, unprocessedExceptions, - inputIndexFields, runtimeMappings: { ...runtimeMappings, ...timestampRuntimeMappings, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/create_indicator_match_alert_type.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/create_indicator_match_alert_type.ts index 3ad9925f7f05..d7f3e96d9a43 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/create_indicator_match_alert_type.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/create_indicator_match_alert_type.ts @@ -76,7 +76,6 @@ export const createIndicatorMatchAlertType = ( secondaryTimestamp, exceptionFilter, unprocessedExceptions, - inputIndexFields, }, services, spaceId, @@ -119,7 +118,6 @@ export const createIndicatorMatchAlertType = ( secondaryTimestamp, exceptionFilter, unprocessedExceptions, - inputIndexFields, wrapSuppressedHits, runOpts, licensing, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/indicator_match.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/indicator_match.ts index 4f004f0bdc62..b8392a82bb6c 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/indicator_match.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/indicator_match.ts @@ -15,7 +15,7 @@ import type { RuleExecutorServices, } from '@kbn/alerting-plugin/server'; import type { ListClient } from '@kbn/lists-plugin/server'; -import type { Filter, DataViewFieldBase } from '@kbn/es-query'; +import type { Filter } from '@kbn/es-query'; import type { RuleRangeTuple, BulkCreate, WrapHits, WrapSuppressedHits, RunOpts } from '../types'; import type { ITelemetryEventsSender } from '../../../telemetry/sender'; import { createThreatSignals } from './threat_mapping/create_threat_signals'; @@ -43,7 +43,6 @@ export const indicatorMatchExecutor = async ({ secondaryTimestamp, exceptionFilter, unprocessedExceptions, - inputIndexFields, wrapSuppressedHits, runOpts, licensing, @@ -65,7 +64,6 @@ export const indicatorMatchExecutor = async ({ secondaryTimestamp?: string; exceptionFilter: Filter | undefined; unprocessedExceptions: ExceptionListItemSchema[]; - inputIndexFields: DataViewFieldBase[]; wrapSuppressedHits: WrapSuppressedHits; runOpts: RunOpts; licensing: LicensingPluginSetup; @@ -106,7 +104,6 @@ export const indicatorMatchExecutor = async ({ secondaryTimestamp, exceptionFilter, unprocessedExceptions, - inputIndexFields, runOpts, licensing, experimentalFeatures, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/create_event_signal.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/create_event_signal.ts index e6bd194504fd..59d20b9dcf0a 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/create_event_signal.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/create_event_signal.ts @@ -144,6 +144,7 @@ export const createEventSignal = async ({ index: inputIndex, exceptionFilter, fields: inputIndexFields, + loadFields: true, }); ruleExecutionLogger.debug(`${ids?.length} matched signals found`); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/create_threat_signal.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/create_threat_signal.ts index 318f8ddfbb75..8d726fb17e90 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/create_threat_signal.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/create_threat_signal.ts @@ -81,6 +81,7 @@ export const createThreatSignal = async ({ index: inputIndex, exceptionFilter, fields: inputIndexFields, + loadFields: true, }); ruleExecutionLogger.debug( diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/create_threat_signals.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/create_threat_signals.ts index 46e5ce84e808..4d477d53604a 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/create_threat_signals.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/create_threat_signals.ts @@ -36,8 +36,8 @@ import { getEventCount, getEventList } from './get_event_count'; import { getMappingFilters } from './get_mapping_filters'; import { THREAT_PIT_KEEP_ALIVE } from '../../../../../../common/cti/constants'; import { getMaxSignalsWarning, getSafeSortIds } from '../../utils/utils'; -import { getFieldsForWildcard } from '../../utils/get_fields_for_wildcard'; import { getDataTierFilter } from '../../utils/get_data_tier_filter'; +import { getQueryFields } from '../../utils/get_query_fields'; export const createThreatSignals = async ({ alertId, @@ -72,7 +72,6 @@ export const createThreatSignals = async ({ secondaryTimestamp, exceptionFilter, unprocessedExceptions, - inputIndexFields, licensing, experimentalFeatures, }: CreateThreatSignalsOptions): Promise => { @@ -115,6 +114,14 @@ export const createThreatSignals = async ({ const allEventFilters = [...filters, eventMappingFilter, ...dataTiersFilters]; const allThreatFilters = [...threatFilters, indicatorMappingFilter, ...dataTiersFilters]; + const dataViews = await services.getDataViews(); + const inputIndexFields = await getQueryFields({ + dataViews, + index: inputIndex, + query, + language, + }); + const eventCount = await getEventCount({ esClient: services.scopedClusterClient.asCurrentUser, index: inputIndex, @@ -140,12 +147,11 @@ export const createThreatSignals = async ({ if (newPitId) threatPitId = newPitId; }; - const dataViews = await services.getDataViews(); - const threatIndexFields = await getFieldsForWildcard({ - index: threatIndex, - language: threatLanguage ?? 'kuery', + const threatIndexFields = await getQueryFields({ dataViews, - ruleExecutionLogger, + index: threatIndex, + query: threatQuery, + language: threatLanguage, }); const threatListCount = await getThreatListCount({ diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/types.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/types.ts index e1072f873917..37bc9d181013 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/types.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/types.ts @@ -77,7 +77,6 @@ export interface CreateThreatSignalsOptions { secondaryTimestamp?: string; exceptionFilter: Filter | undefined; unprocessedExceptions: ExceptionListItemSchema[]; - inputIndexFields: DataViewFieldBase[]; runOpts: RunOpts; licensing: LicensingPluginSetup; experimentalFeatures: ExperimentalFeatures; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/new_terms/create_new_terms_alert_type.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/new_terms/create_new_terms_alert_type.ts index e33f580388f9..fc0c4b31426d 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/new_terms/create_new_terms_alert_type.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/new_terms/create_new_terms_alert_type.ts @@ -110,7 +110,6 @@ export const createNewTermsAlertType = ( unprocessedExceptions, alertTimestampOverride, publicBaseUrl, - inputIndexFields, alertWithSuppression, }, services, @@ -135,7 +134,7 @@ export const createNewTermsAlertType = ( type: params.type, query: params.query, exceptionFilter, - fields: inputIndexFields, + loadFields: true, }; const esFilter = await getFilter(filterArgs); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/query/query.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/query/query.ts index 5915447e5a54..edf7ece7cc84 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/query/query.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/query/query.ts @@ -58,7 +58,6 @@ export const queryExecutor = async ({ services, index: runOpts.inputIndex, exceptionFilter: runOpts.exceptionFilter, - fields: runOpts.inputIndexFields, loadFields: true, }); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/threshold/create_threshold_alert_type.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/threshold/create_threshold_alert_type.ts index 84f3a52af95e..f48cea676b95 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/threshold/create_threshold_alert_type.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/threshold/create_threshold_alert_type.ts @@ -74,7 +74,6 @@ export const createThresholdAlertType = ( aggregatableTimestampField, exceptionFilter, unprocessedExceptions, - inputIndexFields, }, services, startedAt, @@ -99,7 +98,6 @@ export const createThresholdAlertType = ( aggregatableTimestampField, exceptionFilter, unprocessedExceptions, - inputIndexFields, spaceId, runOpts: execOptions.runOpts, licensing, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/threshold/threshold.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/threshold/threshold.test.ts index 50a315a58ef4..8c790596b99b 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/threshold/threshold.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/threshold/threshold.test.ts @@ -22,6 +22,8 @@ import { ruleExecutionLogMock } from '../../rule_monitoring/mocks'; import type { RunOpts } from '../types'; import type { ExperimentalFeatures } from '../../../../../common'; +jest.mock('../utils/get_filter', () => ({ getFilter: jest.fn() })); + describe('threshold_executor', () => { let alertServices: RuleExecutorServicesMock; let ruleExecutionLogger: ReturnType; @@ -107,7 +109,6 @@ describe('threshold_executor', () => { aggregatableTimestampField: TIMESTAMP, exceptionFilter: undefined, unprocessedExceptions: [], - inputIndexFields: [], spaceId: 'default', runOpts: {} as RunOpts, licensing, @@ -173,7 +174,6 @@ describe('threshold_executor', () => { aggregatableTimestampField: TIMESTAMP, exceptionFilter: undefined, unprocessedExceptions: [getExceptionListItemSchemaMock()], - inputIndexFields: [], spaceId: 'default', runOpts: {} as RunOpts, licensing, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/threshold/threshold.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/threshold/threshold.ts index ee0e80f03df1..06a0ff89ccc4 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/threshold/threshold.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/threshold/threshold.ts @@ -18,7 +18,7 @@ import type { RuleExecutorServices, } from '@kbn/alerting-plugin/server'; import type { IRuleDataClient } from '@kbn/rule-registry-plugin/server'; -import type { Filter, DataViewFieldBase } from '@kbn/es-query'; +import type { Filter } from '@kbn/es-query'; import type { CompleteRule, ThresholdRuleParams } from '../../rule_schema'; import { getFilter } from '../utils/get_filter'; import { bulkCreateThresholdSignals } from './bulk_create_threshold_signals'; @@ -64,7 +64,6 @@ export const thresholdExecutor = async ({ aggregatableTimestampField, exceptionFilter, unprocessedExceptions, - inputIndexFields, spaceId, runOpts, licensing, @@ -87,7 +86,6 @@ export const thresholdExecutor = async ({ aggregatableTimestampField: string; exceptionFilter: Filter | undefined; unprocessedExceptions: ExceptionListItemSchema[]; - inputIndexFields: DataViewFieldBase[]; spaceId: string; runOpts: RunOpts; licensing: LicensingPluginSetup; @@ -135,7 +133,7 @@ export const thresholdExecutor = async ({ services, index: inputIndex, exceptionFilter, - fields: inputIndexFields, + loadFields: true, }); // Look for new events over threshold diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/types.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/types.ts index 78c0a729be10..6e2999ae5e3b 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/types.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/types.ts @@ -32,7 +32,7 @@ import type { } from '@kbn/rule-registry-plugin/server'; import type { EcsFieldMap } from '@kbn/rule-registry-plugin/common/assets/field_maps/ecs_field_map'; import type { TypeOfFieldMap } from '@kbn/rule-registry-plugin/common/field_map'; -import type { Filter, DataViewFieldBase } from '@kbn/es-query'; +import type { Filter } from '@kbn/es-query'; import type { LicensingPluginSetup } from '@kbn/licensing-plugin/server'; import type { RulePreviewLoggedRequest } from '../../../../common/api/detection_engine/rule_preview/rule_preview.gen'; @@ -104,7 +104,6 @@ export interface RunOpts { alertWithSuppression: SuppressedAlertService; refreshOnIndexingAlerts: RefreshTypes; publicBaseUrl: string | undefined; - inputIndexFields: DataViewFieldBase[]; experimentalFeatures?: ExperimentalFeatures; } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/get_fields_for_wildcard.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/get_fields_for_wildcard.test.ts deleted file mode 100644 index 709adb63ad9a..000000000000 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/get_fields_for_wildcard.test.ts +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { DataViewsContract } from '@kbn/data-views-plugin/common'; - -import { getFieldsForWildcard } from './get_fields_for_wildcard'; -import { ruleExecutionLogMock } from '../../rule_monitoring/mocks'; - -const mockFields = [ - { - name: 'agent.id', - type: 'string', - esTypes: ['keyword'], - }, - { - name: 'agent.name', - type: 'string', - esTypes: ['keyword'], - }, -]; - -const dataViewsMock = { - getFieldsForWildcard: jest.fn().mockResolvedValue(mockFields), -} as unknown as DataViewsContract; - -const ruleExecutionLogger = ruleExecutionLogMock.forExecutors.create(); - -describe('getFieldsForWildcard', () => { - it('should return empty array and not call dataViews API for eql language', async () => { - const fields = await getFieldsForWildcard({ - index: ['auditbeat-*'], - language: 'eql', - dataViews: dataViewsMock, - ruleExecutionLogger, - }); - - expect(fields).toEqual([]); - expect(dataViewsMock.getFieldsForWildcard).not.toHaveBeenCalled(); - }); - it('should return empty array and not call dataViews API for lucene language', async () => { - const fields = await getFieldsForWildcard({ - index: ['auditbeat-*'], - language: 'lucene', - dataViews: dataViewsMock, - ruleExecutionLogger, - }); - - expect(fields).toEqual([]); - expect(dataViewsMock.getFieldsForWildcard).not.toHaveBeenCalled(); - }); - it('should return empty array and not call dataViews API for non existing index', async () => { - const fields = await getFieldsForWildcard({ - index: undefined, - language: 'kuery', - dataViews: dataViewsMock, - ruleExecutionLogger, - }); - - expect(fields).toEqual([]); - expect(dataViewsMock.getFieldsForWildcard).not.toHaveBeenCalled(); - }); - it('should return fields and call dataViews API for kuery language', async () => { - const fields = await getFieldsForWildcard({ - index: ['auditbeat-*', 'filebeat-*'], - language: 'kuery', - dataViews: dataViewsMock, - ruleExecutionLogger, - }); - - expect(fields).toEqual(mockFields); - expect(dataViewsMock.getFieldsForWildcard).toHaveBeenCalledWith({ - pattern: 'auditbeat-*,filebeat-*', - allowNoIndex: true, - }); - }); - it('should return empty array on dataViews API error', async () => { - (dataViewsMock.getFieldsForWildcard as jest.Mock).mockRejectedValue(Error('some test error')); - const fields = await getFieldsForWildcard({ - index: ['auditbeat-*', 'filebeat-*'], - language: 'kuery', - dataViews: dataViewsMock, - ruleExecutionLogger, - }); - - expect(fields).toEqual([]); - expect(ruleExecutionLogger.error).toHaveBeenCalledWith( - expect.stringMatching('some test error') - ); - }); -}); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/get_fields_for_wildcard.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/get_fields_for_wildcard.ts deleted file mode 100644 index e1111c37604b..000000000000 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/get_fields_for_wildcard.ts +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { DataViewsContract, FieldSpec } from '@kbn/data-views-plugin/common'; -import type { LanguageOrUndefined } from '@kbn/securitysolution-io-ts-alerting-types'; - -import type { IRuleExecutionLogForExecutors } from '../../rule_monitoring'; - -export const getFieldsForWildcard = async ({ - index, - dataViews, - language, - ruleExecutionLogger, -}: { - index: string[] | undefined; - language: LanguageOrUndefined; - dataViews: DataViewsContract; - ruleExecutionLogger: IRuleExecutionLogForExecutors; -}): Promise => { - if (!index || language !== 'kuery') { - return []; - } - - try { - const fields = await dataViews.getFieldsForWildcard({ - pattern: index.join(), - allowNoIndex: true, - }); - - return fields; - } catch (e) { - ruleExecutionLogger.error(`Failed to fetch index fields: ${e?.message}`); - return []; - } -}; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/get_query_fields.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/get_query_fields.ts new file mode 100644 index 000000000000..3cef5dc280c8 --- /dev/null +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/get_query_fields.ts @@ -0,0 +1,28 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import type { DataViewsContract } from '@kbn/data-views-plugin/common'; +import { queryToFields } from '@kbn/data-plugin/common'; +import type { LanguageOrUndefined } from '@kbn/securitysolution-io-ts-alerting-types'; + +interface GetQueryFieldsArgs { + dataViews: DataViewsContract; + index: string[]; + query: string; + language: LanguageOrUndefined; +} + +export const getQueryFields = async ({ dataViews, index, query, language }: GetQueryFieldsArgs) => { + const dataViewLazy = await dataViews.createDataViewLazy({ + title: index.join(), + }); + return Object.values( + await queryToFields({ + dataView: dataViewLazy, + request: { query: [{ query, language: language || 'kuery' }] }, + }) + ); +};