diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/get_signals_template.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/get_signals_template.ts index 5ccde6d3eab9..b676ab5705bf 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/get_signals_template.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/get_signals_template.ts @@ -8,6 +8,7 @@ import signalsMapping from './signals_mapping.json'; import ecsMapping from './ecs_mapping.json'; export const getSignalsTemplate = (index: string) => { + const version = 2; const template = { settings: { index: { @@ -29,8 +30,11 @@ export const getSignalsTemplate = (index: string) => { ...ecsMapping.mappings.properties, signal: signalsMapping.mappings.properties.signal, }, + _meta: { + version, + }, }, - version: 1, + version, }; return template; }; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/signal_rule_alert_type.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/signal_rule_alert_type.ts index 9436dc9cf8a8..68fdbbeae1d8 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/signal_rule_alert_type.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/signal_rule_alert_type.ts @@ -8,6 +8,7 @@ import { Logger, KibanaRequest } from 'src/core/server'; +import { get } from 'lodash'; import { SIGNALS_ID, DEFAULT_SEARCH_AFTER_PAGE_SIZE, @@ -116,6 +117,18 @@ export const signalRulesAlertType = ({ type, exceptionsList, } = params; + const outputIndexTemplateMapping: unknown = await services.callCluster( + 'indices.getTemplate', + { name: outputIndex } + ); + const signalMappingVersion: number | undefined = get(outputIndexTemplateMapping, [ + outputIndex, + 'version', + ]); + if (signalMappingVersion !== undefined && typeof signalMappingVersion !== 'number') { + throw new Error('Found non-numeric value for "version" in output index template'); + } + const searchAfterSize = Math.min(maxSignals, DEFAULT_SEARCH_AFTER_PAGE_SIZE); let hasError: boolean = false; let result = createSearchAfterReturnType(); @@ -436,7 +449,16 @@ export const signalRulesAlertType = ({ }); } else if (isEqlRule(type)) { if (query === undefined) { - throw new Error('eql query rule must have a query defined'); + throw new Error('EQL query rule must have a query defined'); + } + const MIN_EQL_RULE_TEMPLATE_VERSION = 2; + if ( + signalMappingVersion === undefined || + signalMappingVersion < MIN_EQL_RULE_TEMPLATE_VERSION + ) { + throw new Error( + `EQL based rules require an update to version ${MIN_EQL_RULE_TEMPLATE_VERSION} of the detection alerts index mapping` + ); } const inputIndex = await getInputIndex(services, version, index); const request = buildEqlSearchRequest(