From 24fe2c2f845aab4e67a02348765c3e0c55fe7960 Mon Sep 17 00:00:00 2001 From: Garrett Spong Date: Thu, 23 Sep 2021 17:30:30 -0600 Subject: [PATCH 01/20] Adds Rule Execution UUID --- .../src/technical_field_names.ts | 3 +++ .../src/get_index_exists/index.ts | 1 + .../server/alert_instance/alert_instance.ts | 2 ++ .../alerting/server/task_runner/task_runner.ts | 12 +++++++++++- x-pack/plugins/alerting/server/types.ts | 1 + .../plugins/event_log/generated/mappings.json | 17 ++++++++++++++++- x-pack/plugins/event_log/generated/schemas.ts | 13 +++++++++++++ x-pack/plugins/event_log/scripts/mappings.js | 14 ++++++++++++++ .../metric_threshold_executor.test.ts | 1 + .../field_maps/technical_rule_field_map.ts | 5 +++++ .../utils/create_lifecycle_rule_type.test.ts | 1 + .../create_persistence_rule_type_factory.ts | 3 ++- .../server/utils/rule_executor_test_utils.ts | 1 + .../alert_types/es_query/alert_type.test.ts | 6 ++++++ .../index_threshold/alert_type.test.ts | 3 +++ 15 files changed, 80 insertions(+), 3 deletions(-) diff --git a/packages/kbn-rule-data-utils/src/technical_field_names.ts b/packages/kbn-rule-data-utils/src/technical_field_names.ts index 86a036bbb9fe2..d14cf99727ced 100644 --- a/packages/kbn-rule-data-utils/src/technical_field_names.ts +++ b/packages/kbn-rule-data-utils/src/technical_field_names.ts @@ -46,6 +46,7 @@ const ALERT_RULE_CREATED_AT = `${ALERT_RULE_NAMESPACE}.created_at` as const; const ALERT_RULE_CREATED_BY = `${ALERT_RULE_NAMESPACE}.created_by` as const; const ALERT_RULE_DESCRIPTION = `${ALERT_RULE_NAMESPACE}.description` as const; const ALERT_RULE_ENABLED = `${ALERT_RULE_NAMESPACE}.enabled` as const; +const ALERT_RULE_EXECUTION_UUID = `${ALERT_RULE_NAMESPACE}.execution.uuid` as const; const ALERT_RULE_FROM = `${ALERT_RULE_NAMESPACE}.from` as const; const ALERT_RULE_INTERVAL = `${ALERT_RULE_NAMESPACE}.interval` as const; const ALERT_RULE_LICENSE = `${ALERT_RULE_NAMESPACE}.license` as const; @@ -104,6 +105,7 @@ const fields = { ALERT_RULE_CREATED_BY, ALERT_RULE_DESCRIPTION, ALERT_RULE_ENABLED, + ALERT_RULE_EXECUTION_UUID, ALERT_RULE_FROM, ALERT_RULE_INTERVAL, ALERT_RULE_LICENSE, @@ -159,6 +161,7 @@ export { ALERT_RULE_CREATED_BY, ALERT_RULE_DESCRIPTION, ALERT_RULE_ENABLED, + ALERT_RULE_EXECUTION_UUID, ALERT_RULE_FROM, ALERT_RULE_INTERVAL, ALERT_RULE_LICENSE, diff --git a/packages/kbn-securitysolution-es-utils/src/get_index_exists/index.ts b/packages/kbn-securitysolution-es-utils/src/get_index_exists/index.ts index b7d12cab3f48c..8a5f01f8eb3a8 100644 --- a/packages/kbn-securitysolution-es-utils/src/get_index_exists/index.ts +++ b/packages/kbn-securitysolution-es-utils/src/get_index_exists/index.ts @@ -8,6 +8,7 @@ import { ElasticsearchClient } from '../elasticsearch_client'; +// TODO: Being fooled by alias, so can return true if concrete index doesn't exist export const getIndexExists = async ( esClient: ElasticsearchClient, index: string diff --git a/x-pack/plugins/alerting/server/alert_instance/alert_instance.ts b/x-pack/plugins/alerting/server/alert_instance/alert_instance.ts index b41a4e551040c..ec5af7506f5cc 100644 --- a/x-pack/plugins/alerting/server/alert_instance/alert_instance.ts +++ b/x-pack/plugins/alerting/server/alert_instance/alert_instance.ts @@ -46,6 +46,7 @@ export class AlertInstance< private state: State; constructor({ state, meta = {} }: RawAlertInstance = {}) { + // TODO: Add 'kibana.alert.rule.execution.uuid' to framework along with other execution status/metrics? this.state = (state || {}) as State; this.meta = meta; } @@ -182,6 +183,7 @@ export class AlertInstance< } toRaw(): RawAlertInstance { + // TODO: To add 'kibana.alert.rule.execution.uuid' to framework return { state: this.state, meta: this.meta, diff --git a/x-pack/plugins/alerting/server/task_runner/task_runner.ts b/x-pack/plugins/alerting/server/task_runner/task_runner.ts index 28cc0f2dba4d0..e64d8070ecdbd 100644 --- a/x-pack/plugins/alerting/server/task_runner/task_runner.ts +++ b/x-pack/plugins/alerting/server/task_runner/task_runner.ts @@ -8,6 +8,7 @@ import type { PublicMethodsOf } from '@kbn/utility-types'; import { Dictionary, pickBy, mapValues, without, cloneDeep } from 'lodash'; import type { Request } from '@hapi/hapi'; +import uuid from 'uuid'; import { addSpaceIdToPath } from '../../../spaces/server'; import { Logger, KibanaRequest } from '../../../../../src/core/server'; import { TaskRunnerContext } from './task_runner_factory'; @@ -246,6 +247,7 @@ export class TaskRunner< } = this.taskInstance; const namespace = this.context.spaceIdToNamespace(spaceId); const alertType = this.ruleTypeRegistry.get(alertTypeId); + const executionId = uuid.v4(); const alertInstances = mapValues< Record, @@ -274,6 +276,7 @@ export class TaskRunner< updatedAlertTypeState = await this.context.executionContext.withContext(ctx, () => this.alertType.executor({ alertId, + executionId, services: { ...services, alertInstanceFactory: createAlertInstanceFactory< @@ -504,7 +507,7 @@ export class TaskRunner< async run(): Promise { const { - params: { alertId, spaceId }, + params: { alertId, executionId, spaceId }, startedAt, state: originalState, schedule: taskSchedule, @@ -527,6 +530,13 @@ export class TaskRunner< category: [this.alertType.producer], }, kibana: { + alert: { + rule: { + execution: { + uuid: executionId, + }, + }, + }, saved_objects: [ { rel: SAVED_OBJECT_REL_PRIMARY, diff --git a/x-pack/plugins/alerting/server/types.ts b/x-pack/plugins/alerting/server/types.ts index ba35890efd781..6895d0b1caa72 100644 --- a/x-pack/plugins/alerting/server/types.ts +++ b/x-pack/plugins/alerting/server/types.ts @@ -85,6 +85,7 @@ export interface AlertExecutorOptions< ActionGroupIds extends string = never > { alertId: string; + executionId: string; startedAt: Date; previousStartedAt: Date | null; services: AlertServices; diff --git a/x-pack/plugins/event_log/generated/mappings.json b/x-pack/plugins/event_log/generated/mappings.json index cbb59cc3204c0..a0adec1ab1118 100644 --- a/x-pack/plugins/event_log/generated/mappings.json +++ b/x-pack/plugins/event_log/generated/mappings.json @@ -267,6 +267,21 @@ } } }, + "alert": { + "properties": { + "rule": { + "properties": { + "execution": { + "properties": { + "uuid": { + "type": "keyword" + } + } + } + } + } + } + }, "saved_objects": { "type": "nested", "properties": { @@ -298,4 +313,4 @@ } } } -} \ No newline at end of file +} diff --git a/x-pack/plugins/event_log/generated/schemas.ts b/x-pack/plugins/event_log/generated/schemas.ts index 15dc182dbe653..8d8e1d610139d 100644 --- a/x-pack/plugins/event_log/generated/schemas.ts +++ b/x-pack/plugins/event_log/generated/schemas.ts @@ -116,6 +116,19 @@ export const EventSchema = schema.maybe( status: ecsString(), }) ), + alert: schema.maybe( + schema.object({ + rule: schema.maybe( + schema.object({ + execution: schema.maybe( + schema.object({ + uuid: ecsString(), + }) + ), + }) + ), + }) + ), saved_objects: schema.maybe( schema.arrayOf( schema.object({ diff --git a/x-pack/plugins/event_log/scripts/mappings.js b/x-pack/plugins/event_log/scripts/mappings.js index d114603052491..a4cc8d59f34ad 100644 --- a/x-pack/plugins/event_log/scripts/mappings.js +++ b/x-pack/plugins/event_log/scripts/mappings.js @@ -49,6 +49,20 @@ exports.EcsCustomPropertyMappings = { }, }, }, + alert: { + properties: { + rule: { + properties: { + execution: { + properties: { + uuid: { + type: 'keyword', + }, + }, + }, + }, + }, + }, // array of saved object references, for "linking" via search saved_objects: { type: 'nested', diff --git a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/metric_threshold_executor.test.ts b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/metric_threshold_executor.test.ts index 869d0afd52367..19cd5c6306ad6 100644 --- a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/metric_threshold_executor.test.ts +++ b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/metric_threshold_executor.test.ts @@ -48,6 +48,7 @@ const initialRuleState: TestRuleState = { const mockOptions = { alertId: '', + executionId: '', startedAt: new Date(), previousStartedAt: null, state: { diff --git a/x-pack/plugins/rule_registry/common/assets/field_maps/technical_rule_field_map.ts b/x-pack/plugins/rule_registry/common/assets/field_maps/technical_rule_field_map.ts index 54a4b80a35bb4..0a2c9ce028eb7 100644 --- a/x-pack/plugins/rule_registry/common/assets/field_maps/technical_rule_field_map.ts +++ b/x-pack/plugins/rule_registry/common/assets/field_maps/technical_rule_field_map.ts @@ -114,6 +114,11 @@ export const technicalRuleFieldMap = { array: false, required: false, }, + [Fields.ALERT_RULE_EXECUTION_UUID]: { + type: 'keyword', + array: false, + required: false, + }, [Fields.ALERT_RULE_FROM]: { type: 'keyword', array: false, diff --git a/x-pack/plugins/rule_registry/server/utils/create_lifecycle_rule_type.test.ts b/x-pack/plugins/rule_registry/server/utils/create_lifecycle_rule_type.test.ts index 3fa567b8aca96..4efaa28302082 100644 --- a/x-pack/plugins/rule_registry/server/utils/create_lifecycle_rule_type.test.ts +++ b/x-pack/plugins/rule_registry/server/utils/create_lifecycle_rule_type.test.ts @@ -116,6 +116,7 @@ function createRule() { tags: ['tags'], updatedBy: 'updatedBy', namespace: 'namespace', + executionId: 'executionId', })) ?? {}) as Record; previousStartedAt = startedAt; diff --git a/x-pack/plugins/rule_registry/server/utils/create_persistence_rule_type_factory.ts b/x-pack/plugins/rule_registry/server/utils/create_persistence_rule_type_factory.ts index 837d0378703f7..d9e118ac23744 100644 --- a/x-pack/plugins/rule_registry/server/utils/create_persistence_rule_type_factory.ts +++ b/x-pack/plugins/rule_registry/server/utils/create_persistence_rule_type_factory.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { ALERT_INSTANCE_ID, VERSION } from '@kbn/rule-data-utils'; +import { ALERT_INSTANCE_ID, ALERT_RULE_EXECUTION_UUID, VERSION } from '@kbn/rule-data-utils'; import { getCommonAlertFields } from './get_common_alert_fields'; import { CreatePersistenceRuleTypeFactory } from './persistence_types'; @@ -31,6 +31,7 @@ export const createPersistenceRuleTypeFactory: CreatePersistenceRuleTypeFactory { index: {} }, { [ALERT_INSTANCE_ID]: alert.id, + [ALERT_RULE_EXECUTION_UUID]: options.executionId, [VERSION]: ruleDataClient.kibanaVersion, ...commonRuleFields, ...alert.fields, diff --git a/x-pack/plugins/rule_registry/server/utils/rule_executor_test_utils.ts b/x-pack/plugins/rule_registry/server/utils/rule_executor_test_utils.ts index 95a6761152371..567d28c998f5f 100644 --- a/x-pack/plugins/rule_registry/server/utils/rule_executor_test_utils.ts +++ b/x-pack/plugins/rule_registry/server/utils/rule_executor_test_utils.ts @@ -74,4 +74,5 @@ export const createDefaultAlertExecutorOptions = < updatedBy: null, previousStartedAt: null, namespace: undefined, + executionId: 'executionId', }); diff --git a/x-pack/plugins/stack_alerts/server/alert_types/es_query/alert_type.test.ts b/x-pack/plugins/stack_alerts/server/alert_types/es_query/alert_type.test.ts index 85ecd67117ab6..2a909e4f30d06 100644 --- a/x-pack/plugins/stack_alerts/server/alert_types/es_query/alert_type.test.ts +++ b/x-pack/plugins/stack_alerts/server/alert_types/es_query/alert_type.test.ts @@ -141,6 +141,7 @@ describe('alertType', () => { const result = await alertType.executor({ alertId: uuid.v4(), + executionId: uuid.v4(), startedAt: new Date(), previousStartedAt: new Date(), services: alertServices as unknown as AlertServices< @@ -220,6 +221,7 @@ describe('alertType', () => { const result = await alertType.executor({ alertId: uuid.v4(), + executionId: uuid.v4(), startedAt: new Date(), previousStartedAt: new Date(), services: alertServices as unknown as AlertServices< @@ -373,6 +375,7 @@ describe('alertType', () => { const result = await alertType.executor({ alertId: uuid.v4(), + executionId: uuid.v4(), startedAt: new Date(), previousStartedAt: new Date(), services: alertServices as unknown as AlertServices< @@ -451,6 +454,7 @@ describe('alertType', () => { const executorOptions = { alertId: uuid.v4(), + executionId: uuid.v4(), startedAt: new Date(), previousStartedAt: new Date(), services: alertServices as unknown as AlertServices< @@ -566,6 +570,7 @@ describe('alertType', () => { const result = await alertType.executor({ alertId: uuid.v4(), + executionId: uuid.v4(), startedAt: new Date(), previousStartedAt: new Date(), services: alertServices as unknown as AlertServices< @@ -650,6 +655,7 @@ describe('alertType', () => { const result = await alertType.executor({ alertId: uuid.v4(), + executionId: uuid.v4(), startedAt: new Date(), previousStartedAt: new Date(), services: alertServices as unknown as AlertServices< diff --git a/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/alert_type.test.ts b/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/alert_type.test.ts index 7ab382ec77172..f6b1c4a3a3b0a 100644 --- a/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/alert_type.test.ts +++ b/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/alert_type.test.ts @@ -169,6 +169,7 @@ describe('alertType', () => { await alertType.executor({ alertId: uuid.v4(), + executionId: uuid.v4(), startedAt: new Date(), previousStartedAt: new Date(), services: alertServices as unknown as AlertServices<{}, ActionContext, typeof ActionGroupId>, @@ -230,6 +231,7 @@ describe('alertType', () => { await alertType.executor({ alertId: uuid.v4(), + executionId: uuid.v4(), startedAt: new Date(), previousStartedAt: new Date(), services: customAlertServices as unknown as AlertServices< @@ -295,6 +297,7 @@ describe('alertType', () => { await alertType.executor({ alertId: uuid.v4(), + executionId: uuid.v4(), startedAt: new Date(), previousStartedAt: new Date(), services: customAlertServices as unknown as AlertServices< From f2b2ae9109ed658752e2625172fa948502909429 Mon Sep 17 00:00:00 2001 From: Garrett Spong Date: Thu, 23 Sep 2021 18:25:11 -0600 Subject: [PATCH 02/20] Fixes event-log mapping --- .../plugins/event_log/generated/mappings.json | 21 ++++++++++--------- x-pack/plugins/event_log/scripts/mappings.js | 2 ++ 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/x-pack/plugins/event_log/generated/mappings.json b/x-pack/plugins/event_log/generated/mappings.json index a0adec1ab1118..ae1fc16db1440 100644 --- a/x-pack/plugins/event_log/generated/mappings.json +++ b/x-pack/plugins/event_log/generated/mappings.json @@ -267,21 +267,22 @@ } } }, - "alert": { - "properties": { - "rule": { - "properties": { - "execution": { - "properties": { - "uuid": { - "type": "keyword" + "alert": { + "properties": { + "rule": { + "properties": { + "execution": { + "properties": { + "uuid": { + "ignore_above": 1024, + "type": "keyword" + } } } } } } - } - }, + }, "saved_objects": { "type": "nested", "properties": { diff --git a/x-pack/plugins/event_log/scripts/mappings.js b/x-pack/plugins/event_log/scripts/mappings.js index a4cc8d59f34ad..ee8a7795a660c 100644 --- a/x-pack/plugins/event_log/scripts/mappings.js +++ b/x-pack/plugins/event_log/scripts/mappings.js @@ -57,7 +57,9 @@ exports.EcsCustomPropertyMappings = { properties: { uuid: { type: 'keyword', + ignore_above: 1024, }, + }, }, }, }, From 70de4caba7e5f0ea12e413be62241afe792e2014 Mon Sep 17 00:00:00 2001 From: Garrett Spong Date: Fri, 24 Sep 2021 16:26:51 -0600 Subject: [PATCH 03/20] Updated JSDoc --- .../detection_engine/rule_types/factories/utils/build_alert.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/build_alert.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/build_alert.ts index 6bb14df48eac0..cc3eea2d07cee 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/build_alert.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/build_alert.ts @@ -105,6 +105,8 @@ export const removeClashes = (doc: SimpleHit) => { * Builds the `kibana.alert.*` fields that are common across all alerts. * @param docs The parent alerts/events of the new alert to be built. * @param rule The rule that is generating the new alert. + * @param spaceId The space ID in which the rule was executed. + * @param reason Human readable string summarizing alert. */ export const buildAlert = ( docs: SimpleHit[], From fd3bdc31e546becb3ec79d348f6ac66a4002a664 Mon Sep 17 00:00:00 2001 From: Garrett Spong Date: Fri, 1 Oct 2021 17:35:00 -0600 Subject: [PATCH 04/20] Increases happiness of test input parameters --- .../server/task_runner/task_runner.test.ts | 239 ++++++++++++++++++ ...gacy_rules_notification_alert_type.test.ts | 1 + .../signals/signal_rule_alert_type.test.ts | 1 + 3 files changed, 241 insertions(+) diff --git a/x-pack/plugins/alerting/server/task_runner/task_runner.test.ts b/x-pack/plugins/alerting/server/task_runner/task_runner.test.ts index bc477136ec111..2425cfaa0da6e 100644 --- a/x-pack/plugins/alerting/server/task_runner/task_runner.test.ts +++ b/x-pack/plugins/alerting/server/task_runner/task_runner.test.ts @@ -306,6 +306,13 @@ describe('Task Runner', () => { "kind": "alert", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": undefined, + }, + }, + }, "saved_objects": Array [ Object { "id": "1", @@ -453,6 +460,13 @@ describe('Task Runner', () => { kind: 'alert', }, kibana: { + alert: { + rule: { + execution: { + uuid: undefined, + }, + }, + }, task: { schedule_delay: 0, scheduled: '1970-01-01T00:00:00.000Z', @@ -581,6 +595,13 @@ describe('Task Runner', () => { '@timestamp': '1970-01-01T00:00:00.000Z', event: { action: 'execute', category: ['alerts'], kind: 'alert', outcome: 'success' }, kibana: { + alert: { + rule: { + execution: { + uuid: undefined, + }, + }, + }, alerting: { status: 'active', }, @@ -677,6 +698,13 @@ describe('Task Runner', () => { schedule_delay: 0, scheduled: '1970-01-01T00:00:00.000Z', }, + alert: { + rule: { + execution: { + uuid: undefined, + }, + }, + }, saved_objects: [ { id: '1', @@ -770,6 +798,13 @@ describe('Task Runner', () => { outcome: 'success', }, kibana: { + alert: { + rule: { + execution: { + uuid: undefined, + }, + }, + }, alerting: { status: 'active', }, @@ -920,6 +955,7 @@ describe('Task Runner', () => { const eventLogger = taskRunnerFactoryInitializerParams.eventLogger; expect(eventLogger.logEvent).toHaveBeenCalledTimes(3); expect(eventLogger.startTiming).toHaveBeenCalledTimes(1); + // TODO: Necessary for "action": "active-instance" alert as well too? expect(eventLogger.logEvent.mock.calls).toMatchInlineSnapshot(` Array [ Array [ @@ -933,6 +969,13 @@ describe('Task Runner', () => { "kind": "alert", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": undefined, + }, + }, + }, "saved_objects": Array [ Object { "id": "1", @@ -1004,6 +1047,13 @@ describe('Task Runner', () => { "outcome": "success", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": undefined, + }, + }, + }, "alerting": Object { "status": "active", }, @@ -1271,6 +1321,13 @@ describe('Task Runner', () => { "kind": "alert", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": undefined, + }, + }, + }, "saved_objects": Array [ Object { "id": "1", @@ -1419,6 +1476,13 @@ describe('Task Runner', () => { "outcome": "success", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": undefined, + }, + }, + }, "alerting": Object { "status": "active", }, @@ -1568,6 +1632,13 @@ describe('Task Runner', () => { "kind": "alert", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": undefined, + }, + }, + }, "saved_objects": Array [ Object { "id": "1", @@ -1757,6 +1828,13 @@ describe('Task Runner', () => { "outcome": "success", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": undefined, + }, + }, + }, "alerting": Object { "status": "active", }, @@ -2137,6 +2215,13 @@ describe('Task Runner', () => { "kind": "alert", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": undefined, + }, + }, + }, "saved_objects": Array [ Object { "id": "1", @@ -2245,6 +2330,13 @@ describe('Task Runner', () => { "outcome": "success", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": undefined, + }, + }, + }, "alerting": Object { "status": "active", }, @@ -2473,6 +2565,13 @@ describe('Task Runner', () => { "kind": "alert", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": undefined, + }, + }, + }, "saved_objects": Array [ Object { "id": "1", @@ -2512,6 +2611,13 @@ describe('Task Runner', () => { "reason": "execute", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": undefined, + }, + }, + }, "alerting": Object { "status": "error", }, @@ -2582,6 +2688,13 @@ describe('Task Runner', () => { "kind": "alert", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": undefined, + }, + }, + }, "saved_objects": Array [ Object { "id": "1", @@ -2621,6 +2734,13 @@ describe('Task Runner', () => { "reason": "decrypt", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": undefined, + }, + }, + }, "alerting": Object { "status": "error", }, @@ -2699,6 +2819,13 @@ describe('Task Runner', () => { "kind": "alert", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": undefined, + }, + }, + }, "saved_objects": Array [ Object { "id": "1", @@ -2738,6 +2865,13 @@ describe('Task Runner', () => { "reason": "license", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": undefined, + }, + }, + }, "alerting": Object { "status": "error", }, @@ -2816,6 +2950,13 @@ describe('Task Runner', () => { "kind": "alert", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": undefined, + }, + }, + }, "saved_objects": Array [ Object { "id": "1", @@ -2855,6 +2996,13 @@ describe('Task Runner', () => { "reason": "unknown", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": undefined, + }, + }, + }, "alerting": Object { "status": "error", }, @@ -2932,6 +3080,13 @@ describe('Task Runner', () => { "kind": "alert", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": undefined, + }, + }, + }, "saved_objects": Array [ Object { "id": "1", @@ -2971,6 +3126,13 @@ describe('Task Runner', () => { "reason": "read", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": undefined, + }, + }, + }, "alerting": Object { "status": "error", }, @@ -3222,6 +3384,13 @@ describe('Task Runner', () => { "kind": "alert", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": undefined, + }, + }, + }, "saved_objects": Array [ Object { "id": "1", @@ -3401,6 +3570,13 @@ describe('Task Runner', () => { "outcome": "success", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": undefined, + }, + }, + }, "alerting": Object { "status": "active", }, @@ -3508,6 +3684,13 @@ describe('Task Runner', () => { "kind": "alert", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": undefined, + }, + }, + }, "saved_objects": Array [ Object { "id": "1", @@ -3615,6 +3798,13 @@ describe('Task Runner', () => { "outcome": "success", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": undefined, + }, + }, + }, "alerting": Object { "status": "active", }, @@ -3714,6 +3904,13 @@ describe('Task Runner', () => { "kind": "alert", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": undefined, + }, + }, + }, "saved_objects": Array [ Object { "id": "1", @@ -3817,6 +4014,13 @@ describe('Task Runner', () => { "outcome": "success", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": undefined, + }, + }, + }, "alerting": Object { "status": "active", }, @@ -3911,6 +4115,13 @@ describe('Task Runner', () => { "kind": "alert", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": undefined, + }, + }, + }, "saved_objects": Array [ Object { "id": "1", @@ -4018,6 +4229,13 @@ describe('Task Runner', () => { "outcome": "success", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": undefined, + }, + }, + }, "alerting": Object { "status": "ok", }, @@ -4114,6 +4332,13 @@ describe('Task Runner', () => { "kind": "alert", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": undefined, + }, + }, + }, "saved_objects": Array [ Object { "id": "1", @@ -4215,6 +4440,13 @@ describe('Task Runner', () => { "outcome": "success", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": undefined, + }, + }, + }, "alerting": Object { "status": "ok", }, @@ -4362,6 +4594,13 @@ describe('Task Runner', () => { "kind": "alert", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": undefined, + }, + }, + }, "saved_objects": Array [ Object { "id": "1", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/legacy_rules_notification_alert_type.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/legacy_rules_notification_alert_type.test.ts index 6c0ffa65a9afa..5f3ea892d1c73 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/legacy_rules_notification_alert_type.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/legacy_rules_notification_alert_type.test.ts @@ -39,6 +39,7 @@ describe('legacyRules_notification_alert_type', () => { payload = { alertId: '1111', + executionId: '', services: alertServices, params: { ruleAlertId: '2222' }, state: {}, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/signal_rule_alert_type.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/signal_rule_alert_type.test.ts index 2696d6981083e..31c4c0056ea5d 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/signal_rule_alert_type.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/signal_rule_alert_type.test.ts @@ -69,6 +69,7 @@ const getPayload = ( services: AlertServicesMock ): RuleExecutorOptions => ({ alertId: ruleAlert.id, + executionId: '', services, name: ruleAlert.name, tags: ruleAlert.tags, From 54976a56630c2dea3b0671ce512b58009f60c010 Mon Sep 17 00:00:00 2001 From: Garrett Spong Date: Mon, 11 Oct 2021 11:58:51 -0600 Subject: [PATCH 05/20] Merged with rule execution event-log updates, and adds support to signals index --- .../routes/index/get_signals_template.ts | 12 +++++----- .../routes/index/signal_aad_mapping.json | 1 + .../routes/index/signals_mapping.json | 7 ++++++ .../event_log_adapter/event_log_adapter.ts | 15 +++++++++++-- .../event_log_adapter/event_log_client.ts | 5 +++++ .../rule_execution_log/types.ts | 3 +++ .../create_security_rule_type_factory.ts | 2 ++ .../signals/build_bulk_body.test.ts | 7 ++++++ .../signals/build_bulk_body.ts | 22 +++++++++++++++++-- .../signals/search_after_bulk_create.test.ts | 1 + .../signals/signal_rule_alert_type.ts | 3 +++ .../lib/detection_engine/signals/types.ts | 10 +++++++++ .../detection_engine/signals/utils.test.ts | 4 ++++ .../lib/detection_engine/signals/utils.ts | 8 +++++++ .../signals/wrap_hits_factory.ts | 11 +++++++++- 15 files changed, 100 insertions(+), 11 deletions(-) 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 b7a0521e5c3ce..2c99b025628a1 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 @@ -24,8 +24,8 @@ import signalExtraFields from './signal_extra_fields.json'; @description This value represents the template version assumed by app code. If this number is greater than the user's signals index version, the detections UI will attempt to update the signals template and roll over to - a new signals index. - + a new signals index. + Since we create a new index for new versions, this version on an existing index should never change. If making mappings changes in a patch release, this number should be incremented by 1. @@ -33,7 +33,7 @@ import signalExtraFields from './signal_extra_fields.json'; incremented by 10 in order to add "room" for the aforementioned patch release */ -export const SIGNALS_TEMPLATE_VERSION = 57; +export const SIGNALS_TEMPLATE_VERSION = 67; /** @constant @type {number} @@ -43,8 +43,8 @@ export const SIGNALS_TEMPLATE_VERSION = 57; This version number can change over time on existing indices as we add backwards compatibility fields. - If any .siem-signals- indices have an aliases_version less than this value, the detections - UI will call create_index_route and and go through the index update process. Increment this number if + If any .siem-signals- indices have an aliases_version less than this value, the detections + UI will call create_index_route and and go through the index update process. Increment this number if making changes to the field aliases we use to make signals forwards-compatible. */ export const SIGNALS_FIELD_ALIASES_VERSION = 1; @@ -52,7 +52,7 @@ export const SIGNALS_FIELD_ALIASES_VERSION = 1; /** @constant @type {number} - @description This value represents the minimum required index version (SIGNALS_TEMPLATE_VERSION) for EQL + @description This value represents the minimum required index version (SIGNALS_TEMPLATE_VERSION) for EQL rules to write signals correctly. If the write index has a `version` less than this value, the EQL rule will throw an error on execution. */ diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/signal_aad_mapping.json b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/signal_aad_mapping.json index 8391d490162df..80dff917c33f7 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/signal_aad_mapping.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/signal_aad_mapping.json @@ -33,6 +33,7 @@ "signal.rule.created_by": "kibana.alert.rule.created_by", "signal.rule.description": "kibana.alert.rule.description", "signal.rule.enabled": "kibana.alert.rule.enabled", + "signal.rule.execution.uuid": "kibana.alert.rule.execution.uuid", "signal.rule.false_positives": "kibana.alert.rule.false_positives", "signal.rule.from": "kibana.alert.rule.from", "signal.rule.id": "kibana.alert.rule.uuid", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/signals_mapping.json b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/signals_mapping.json index 4f754ecd2d33a..6df246d06760d 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/signals_mapping.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/signals_mapping.json @@ -286,6 +286,13 @@ "enabled": { "type": "keyword" }, + "execution": { + "properties": { + "uuid": { + "type": "keyword" + } + } + }, "filters": { "type": "object" }, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/event_log_adapter/event_log_adapter.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/event_log_adapter/event_log_adapter.ts index 6b1a0cd5b18d0..b2246cb1847b2 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/event_log_adapter/event_log_adapter.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/event_log_adapter/event_log_adapter.ts @@ -31,10 +31,17 @@ export class EventLogAdapter implements IRuleExecutionLogClient { return {}; // TODO Implement } - public async update({ attributes, spaceId, ruleName, ruleType }: UpdateExecutionLogArgs) { - // execution events are immutable, so we just log a status change istead of updating previous + public async update({ + attributes, + executionId, + spaceId, + ruleName, + ruleType, + }: UpdateExecutionLogArgs) { + // execution events are immutable, so we just log a status change instead of updating previous if (attributes.status) { this.eventLogClient.logStatusChange({ + executionId, ruleName, ruleType, ruleId: attributes.alertId, @@ -49,6 +56,7 @@ export class EventLogAdapter implements IRuleExecutionLogClient { } public async logExecutionMetrics({ + executionId, ruleId, spaceId, ruleType, @@ -56,6 +64,7 @@ export class EventLogAdapter implements IRuleExecutionLogClient { metrics, }: LogExecutionMetricsArgs) { this.eventLogClient.logExecutionMetrics({ + executionId, ruleId, ruleName, ruleType, @@ -73,7 +82,9 @@ export class EventLogAdapter implements IRuleExecutionLogClient { public async logStatusChange(args: LogStatusChangeArgs) { if (args.metrics) { + // TODO: Await here? this.logExecutionMetrics({ + executionId: args.executionId, ruleId: args.ruleId, ruleName: args.ruleName, ruleType: args.ruleType, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/event_log_adapter/event_log_client.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/event_log_adapter/event_log_client.ts index d85c67e422035..0ea7099ed0b69 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/event_log_adapter/event_log_client.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/event_log_adapter/event_log_client.ts @@ -37,6 +37,7 @@ interface FindExecutionLogArgs { } interface LogExecutionMetricsArgs { + executionId?: string; ruleId: string; ruleName: string; ruleType: string; @@ -71,6 +72,7 @@ export class EventLogClient implements IExecLogEventLogClient { } public logExecutionMetrics({ + executionId, ruleId, ruleName, ruleType, @@ -97,6 +99,7 @@ export class EventLogClient implements IExecLogEventLogClient { total_search_duration_ms: metrics.totalSearchDuration, total_indexing_duration_ms: metrics.totalIndexingDuration, }, + uuid: executionId, }, }, }, @@ -114,6 +117,7 @@ export class EventLogClient implements IExecLogEventLogClient { } public logStatusChange({ + executionId, ruleId, ruleName, ruleType, @@ -139,6 +143,7 @@ export class EventLogClient implements IExecLogEventLogClient { execution: { status: newStatus, status_order: statusSeverityDict[newStatus], + uuid: executionId, }, }, }, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/types.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/types.ts index e38f974ddee2e..fff1460deee1e 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/types.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/types.ts @@ -38,6 +38,7 @@ export interface ExecutionMetrics { } export interface LogStatusChangeArgs { + executionId?: string; ruleId: string; ruleName: string; ruleType: string; @@ -51,6 +52,7 @@ export interface LogStatusChangeArgs { } export interface UpdateExecutionLogArgs { + executionId?: string; id: string; attributes: IRuleStatusSOAttributes; ruleName: string; @@ -64,6 +66,7 @@ export interface CreateExecutionLogArgs { } export interface LogExecutionMetricsArgs { + executionId?: string; ruleId: string; ruleName: string; ruleType: string; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/create_security_rule_type_factory.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/create_security_rule_type_factory.ts index 9ea36abe997c3..441f9f2b9168f 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/create_security_rule_type_factory.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/create_security_rule_type_factory.ts @@ -49,6 +49,7 @@ export const createSecurityRuleTypeFactory: CreateSecurityRuleTypeFactory = async executor(options) { const { alertId, + executionId, params, previousStartedAt, startedAt, @@ -92,6 +93,7 @@ export const createSecurityRuleTypeFactory: CreateSecurityRuleTypeFactory = let wroteWarningStatus = false; const basicLogArguments = { spaceId, + executionId, ruleId: alertId, ruleName: name, ruleType: alertTypeId, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/build_bulk_body.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/build_bulk_body.test.ts index 00286e9f0d3c9..6ac2b8ae68502 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/build_bulk_body.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/build_bulk_body.test.ts @@ -42,6 +42,7 @@ describe('buildBulkBody', () => { const fakeSignalSourceHit: SignalHitOptionalTimestamp = buildBulkBody( ruleSO, doc, + 'executionId', 'missingFields', [], buildReasonMessage @@ -114,6 +115,7 @@ describe('buildBulkBody', () => { const fakeSignalSourceHit: SignalHitOptionalTimestamp = buildBulkBody( ruleSO, doc, + 'executionId', 'missingFields', [], buildReasonMessage @@ -200,6 +202,7 @@ describe('buildBulkBody', () => { const fakeSignalSourceHit: SignalHitOptionalTimestamp = buildBulkBody( ruleSO, doc, + 'executionId', 'missingFields', [], buildReasonMessage @@ -272,6 +275,7 @@ describe('buildBulkBody', () => { const fakeSignalSourceHit: SignalHitOptionalTimestamp = buildBulkBody( ruleSO, doc, + 'executionId', 'missingFields', [], buildReasonMessage @@ -341,6 +345,7 @@ describe('buildBulkBody', () => { const fakeSignalSourceHit: SignalHitOptionalTimestamp = buildBulkBody( ruleSO, doc, + 'executionId', 'missingFields', [], buildReasonMessage @@ -409,6 +414,7 @@ describe('buildBulkBody', () => { const { '@timestamp': timestamp, ...fakeSignalSourceHit } = buildBulkBody( ruleSO, doc, + 'executionId', 'missingFields', [], buildReasonMessage @@ -473,6 +479,7 @@ describe('buildBulkBody', () => { const { '@timestamp': timestamp, ...fakeSignalSourceHit } = buildBulkBody( ruleSO, doc, + 'executionId', 'missingFields', [], buildReasonMessage diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/build_bulk_body.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/build_bulk_body.ts index f62e6cebf719b..1882f67bbc9b7 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/build_bulk_body.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/build_bulk_body.ts @@ -16,6 +16,7 @@ import { BaseSignalHit, SignalSource, WrappedSignalHit, + SignalHitExecutionId, } from './types'; import { buildRuleWithoutOverrides, buildRuleWithOverrides } from './build_rule'; import { additionalSignalFields, buildSignal } from './build_signal'; @@ -31,12 +32,17 @@ import { BuildReasonMessage } from './reason_formatters'; * then the event object, and finally we strip away any additional temporary data that was added * such as the "threshold_result". * @param ruleSO The rule saved object to build overrides + * @param executionId Unique id representing a specific rule execution * @param doc The SignalSourceHit with "_source", "fields", and additional data such as "threshold_result" + * @param mergeStrategy Specific merge strategy for building alert from source/fields + * @param ignoreFields Array of fields that should be ignored and never merged + * @param buildReasonMessage Function for building reason message string * @returns The body that can be added to a bulk call for inserting the signal. */ export const buildBulkBody = ( ruleSO: SavedObject, doc: SignalSourceHit, + executionId: string, mergeStrategy: ConfigType['alertMergeStrategy'], ignoreFields: ConfigType['alertIgnoreFields'], buildReasonMessage: BuildReasonMessage @@ -60,11 +66,20 @@ export const buildBulkBody = ( } = mergedDoc._source || { threshold_result: null, }; - const signalHit: SignalHit = { + // TODO: Modify upstream types? + const signalHit: SignalHit & SignalHitExecutionId = { ...filteredSource, [TIMESTAMP]: timestamp, event, - signal, + signal: { + ...signal, + rule: { + ...signal.rule, + execution: { + uuid: executionId, + }, + }, + }, }; return signalHit; }; @@ -76,6 +91,9 @@ export const buildBulkBody = ( * @param sequence The raw ES documents that make up the sequence * @param ruleSO SavedObject representing the rule that found the sequence * @param outputIndex Index to write the resulting signals to + * @param mergeStrategy Specific merge strategy for building alert from source/fields + * @param ignoreFields Array of fields that should be ignored and never merged + * @param buildReasonMessage Function for building reason message string */ export const buildSignalGroupFromSequence = ( sequence: EqlSequence, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/search_after_bulk_create.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/search_after_bulk_create.test.ts index 1f46654e855b2..4475a740a1e89 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/search_after_bulk_create.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/search_after_bulk_create.test.ts @@ -73,6 +73,7 @@ describe('searchAfterAndBulkCreate', () => { wrapHits = wrapHitsFactory({ ruleSO, signalsIndex: DEFAULT_SIGNALS_INDEX, + executionId: 'executionId', mergeStrategy: 'missingFields', ignoreFields: [], }); 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 1e3a8a513c4a1..1df3ae691096e 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 @@ -122,6 +122,7 @@ export const signalRulesAlertType = ({ minimumLicenseRequired: 'basic', isExportable: false, async executor({ + executionId, previousStartedAt, startedAt, state, @@ -162,6 +163,7 @@ export const signalRulesAlertType = ({ let wroteWarningStatus = false; const basicLogArguments = { spaceId, + executionId, ruleId: alertId, ruleName: name, ruleType: alertTypeId, @@ -279,6 +281,7 @@ export const signalRulesAlertType = ({ const wrapHits = wrapHitsFactory({ ruleSO: savedObject, + executionId, signalsIndex: params.outputIndex, mergeStrategy, ignoreFields, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/types.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/types.ts index 82b4a46f482b6..738c09f99300b 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/types.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/types.ts @@ -253,6 +253,16 @@ export interface SignalHit { [key: string]: SearchTypes; } +export interface SignalHitExecutionId { + signal: { + rule: { + execution: { + uuid: string; + }; + }; + }; +} + export interface AlertAttributes { actions: RuleAlertAction[]; alertTypeId: string; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.test.ts index 7d2eafa46d382..c2402c2d5c5c4 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.test.ts @@ -783,6 +783,7 @@ describe('utils', () => { const res = await hasTimestampFields({ wroteStatus: false, timestampField, + executionId: 'executionId', ruleName: 'myfakerulename', // eslint-disable-next-line @typescript-eslint/no-explicit-any timestampFieldCapsResponse: timestampFieldCapsResponse as ApiResponse>, @@ -827,6 +828,7 @@ describe('utils', () => { const res = await hasTimestampFields({ wroteStatus: false, timestampField, + executionId: 'executionId', ruleName: 'myfakerulename', // eslint-disable-next-line @typescript-eslint/no-explicit-any timestampFieldCapsResponse: timestampFieldCapsResponse as ApiResponse>, @@ -857,6 +859,7 @@ describe('utils', () => { const res = await hasTimestampFields({ wroteStatus: false, timestampField, + executionId: 'executionId', ruleName: 'Endpoint Security', // eslint-disable-next-line @typescript-eslint/no-explicit-any timestampFieldCapsResponse: timestampFieldCapsResponse as ApiResponse>, @@ -887,6 +890,7 @@ describe('utils', () => { const res = await hasTimestampFields({ wroteStatus: false, timestampField, + executionId: 'executionId', ruleName: 'NOT Endpoint Security', // eslint-disable-next-line @typescript-eslint/no-explicit-any timestampFieldCapsResponse: timestampFieldCapsResponse as ApiResponse>, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.ts index 2aefc7ea0bd64..9f1eebe782a31 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.ts @@ -97,6 +97,7 @@ export const hasReadIndexPrivileges = async (args: { privileges: Privilege; logger: Logger; buildRuleMessage: BuildRuleMessage; + executionId: string; ruleStatusClient: IRuleExecutionLogClient; ruleId: string; ruleName: string; @@ -107,6 +108,7 @@ export const hasReadIndexPrivileges = async (args: { privileges, logger, buildRuleMessage, + executionId, ruleStatusClient, ruleId, ruleName, @@ -128,6 +130,7 @@ export const hasReadIndexPrivileges = async (args: { )}`; logger.error(buildRuleMessage(errorString)); await ruleStatusClient.logStatusChange({ + executionId, message: errorString, ruleId, ruleName, @@ -147,6 +150,7 @@ export const hasReadIndexPrivileges = async (args: { )}`; logger.error(buildRuleMessage(errorString)); await ruleStatusClient.logStatusChange({ + executionId, message: errorString, ruleId, ruleName, @@ -162,6 +166,7 @@ export const hasReadIndexPrivileges = async (args: { export const hasTimestampFields = async (args: { wroteStatus: boolean; timestampField: string; + executionId: string; ruleName: string; // any is derived from here // node_modules/@elastic/elasticsearch/api/kibana.d.ts @@ -178,6 +183,7 @@ export const hasTimestampFields = async (args: { const { wroteStatus, timestampField, + executionId, ruleName, timestampFieldCapsResponse, inputIndices, @@ -199,6 +205,7 @@ export const hasTimestampFields = async (args: { }`; logger.error(buildRuleMessage(errorString.trimEnd())); await ruleStatusClient.logStatusChange({ + executionId, message: errorString.trimEnd(), ruleId, ruleName, @@ -227,6 +234,7 @@ export const hasTimestampFields = async (args: { )}`; logger.error(buildRuleMessage(errorString)); await ruleStatusClient.logStatusChange({ + executionId, message: errorString, ruleId, ruleName, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/wrap_hits_factory.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/wrap_hits_factory.ts index 6f040465389fc..b4eeaa852d38d 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/wrap_hits_factory.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/wrap_hits_factory.ts @@ -14,11 +14,13 @@ import type { ConfigType } from '../../../config'; export const wrapHitsFactory = ({ ruleSO, + executionId, signalsIndex, mergeStrategy, ignoreFields, }: { ruleSO: SearchAfterAndBulkCreateParams['ruleSO']; + executionId: string; signalsIndex: string; mergeStrategy: ConfigType['alertMergeStrategy']; ignoreFields: ConfigType['alertIgnoreFields']; @@ -33,7 +35,14 @@ export const wrapHitsFactory = String(doc._version), ruleSO.attributes.params.ruleId ?? '' ), - _source: buildBulkBody(ruleSO, doc, mergeStrategy, ignoreFields, buildReasonMessage), + _source: buildBulkBody( + ruleSO, + doc, + executionId, + mergeStrategy, + ignoreFields, + buildReasonMessage + ), }, ]); From 95da7a0c2f80d771452d9b829ca6817a0327ab59 Mon Sep 17 00:00:00 2001 From: Garrett Spong Date: Thu, 18 Nov 2021 13:02:32 -0700 Subject: [PATCH 06/20] Adding default executionId to rule preview functionality --- .../lib/detection_engine/routes/rules/preview_rules_route.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/preview_rules_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/preview_rules_route.ts index 882732544dcbb..d16ede5f3c4f5 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/preview_rules_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/preview_rules_route.ts @@ -152,6 +152,7 @@ export const previewRulesRoute = async ( statePreview = (await executor({ alertId: previewId, createdBy: rule.createdBy, + executionId: uuid.v4(), name: rule.name, params, previousStartedAt, From a64dd30c67b9f81e2de651ad866aff2c1ab3324b Mon Sep 17 00:00:00 2001 From: Garrett Spong Date: Thu, 18 Nov 2021 19:15:10 -0700 Subject: [PATCH 07/20] Increases integrity of test outputs --- ...eate_alert_event_log_record_object.test.ts | 21 ++++++++ .../server/rules_client/tests/disable.test.ts | 7 +++ .../create_execution_handler.test.ts | 7 +++ .../server/task_runner/task_runner.test.ts | 28 +++++++++++ .../task_runner/task_runner_cancel.test.ts | 49 +++++++++++++++++++ 5 files changed, 112 insertions(+) diff --git a/x-pack/plugins/alerting/server/lib/create_alert_event_log_record_object.test.ts b/x-pack/plugins/alerting/server/lib/create_alert_event_log_record_object.test.ts index 0731886bcaeb0..729959166da78 100644 --- a/x-pack/plugins/alerting/server/lib/create_alert_event_log_record_object.test.ts +++ b/x-pack/plugins/alerting/server/lib/create_alert_event_log_record_object.test.ts @@ -50,6 +50,13 @@ describe('createAlertEventLogRecordObject', () => { kind: 'alert', }, kibana: { + alert: { + rule: { + execution: { + uuid: undefined, + }, + }, + }, saved_objects: [ { id: '1', @@ -109,6 +116,13 @@ describe('createAlertEventLogRecordObject', () => { start: '1970-01-01T00:00:00.000Z', }, kibana: { + alert: { + rule: { + execution: { + uuid: undefined, + }, + }, + }, alerting: { action_group_id: 'group 1', action_subgroup: 'subgroup value', @@ -176,6 +190,13 @@ describe('createAlertEventLogRecordObject', () => { start: '1970-01-01T00:00:00.000Z', }, kibana: { + alert: { + rule: { + execution: { + uuid: undefined, + }, + }, + }, alerting: { action_group_id: 'group 1', action_subgroup: 'subgroup value', diff --git a/x-pack/plugins/alerting/server/rules_client/tests/disable.test.ts b/x-pack/plugins/alerting/server/rules_client/tests/disable.test.ts index c518d385dd747..8217e9d7ebcbc 100644 --- a/x-pack/plugins/alerting/server/rules_client/tests/disable.test.ts +++ b/x-pack/plugins/alerting/server/rules_client/tests/disable.test.ts @@ -325,6 +325,13 @@ describe('disable()', () => { kind: 'alert', }, kibana: { + alert: { + rule: { + execution: { + uuid: undefined, + }, + }, + }, alerting: { action_group_id: 'default', action_subgroup: 'newSubgroup', diff --git a/x-pack/plugins/alerting/server/task_runner/create_execution_handler.test.ts b/x-pack/plugins/alerting/server/task_runner/create_execution_handler.test.ts index fc5c5cf8897f0..27d744f99335f 100644 --- a/x-pack/plugins/alerting/server/task_runner/create_execution_handler.test.ts +++ b/x-pack/plugins/alerting/server/task_runner/create_execution_handler.test.ts @@ -173,6 +173,13 @@ test('enqueues execution per selected action', async () => { "kind": "alert", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": undefined, + }, + }, + }, "alerting": Object { "action_group_id": "default", "instance_id": "2", diff --git a/x-pack/plugins/alerting/server/task_runner/task_runner.test.ts b/x-pack/plugins/alerting/server/task_runner/task_runner.test.ts index b2dcfead7530a..6aef1291471da 100644 --- a/x-pack/plugins/alerting/server/task_runner/task_runner.test.ts +++ b/x-pack/plugins/alerting/server/task_runner/task_runner.test.ts @@ -561,6 +561,13 @@ describe('Task Runner', () => { kind: 'alert', }, kibana: { + alert: { + rule: { + execution: { + uuid: undefined, + }, + }, + }, alerting: { instance_id: '1', action_group_id: 'default', @@ -1435,6 +1442,13 @@ describe('Task Runner', () => { "kind": "alert", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": undefined, + }, + }, + }, "alerting": Object { "action_group_id": "default", "instance_id": "1", @@ -1745,6 +1759,13 @@ describe('Task Runner', () => { "kind": "alert", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": undefined, + }, + }, + }, "alerting": Object { "action_group_id": "recovered", "instance_id": "2", @@ -1785,6 +1806,13 @@ describe('Task Runner', () => { "kind": "alert", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": undefined, + }, + }, + }, "alerting": Object { "action_group_id": "default", "instance_id": "1", diff --git a/x-pack/plugins/alerting/server/task_runner/task_runner_cancel.test.ts b/x-pack/plugins/alerting/server/task_runner/task_runner_cancel.test.ts index 95cb356af3c1a..d69a25798de0c 100644 --- a/x-pack/plugins/alerting/server/task_runner/task_runner_cancel.test.ts +++ b/x-pack/plugins/alerting/server/task_runner/task_runner_cancel.test.ts @@ -202,6 +202,13 @@ describe('Task Runner Cancel', () => { kind: 'alert', }, kibana: { + alert: { + rule: { + execution: { + uuid: undefined, + }, + }, + }, saved_objects: [ { id: '1', @@ -257,6 +264,13 @@ describe('Task Runner Cancel', () => { outcome: 'success', }, kibana: { + alert: { + rule: { + execution: { + uuid: undefined, + }, + }, + }, alerting: { status: 'ok', }, @@ -430,6 +444,13 @@ describe('Task Runner Cancel', () => { kind: 'alert', }, kibana: { + alert: { + rule: { + execution: { + uuid: undefined, + }, + }, + }, task: { schedule_delay: 0, scheduled: '1970-01-01T00:00:00.000Z', @@ -486,6 +507,13 @@ describe('Task Runner Cancel', () => { outcome: 'success', }, kibana: { + alert: { + rule: { + execution: { + uuid: undefined, + }, + }, + }, alerting: { status: 'active', }, @@ -545,6 +573,13 @@ describe('Task Runner Cancel', () => { kind: 'alert', }, kibana: { + alert: { + rule: { + execution: { + uuid: undefined, + }, + }, + }, task: { schedule_delay: 0, scheduled: '1970-01-01T00:00:00.000Z', @@ -659,6 +694,13 @@ describe('Task Runner Cancel', () => { kind: 'alert', }, kibana: { + alert: { + rule: { + execution: { + uuid: undefined, + }, + }, + }, alerting: { instance_id: '1', action_group_id: 'default', @@ -691,6 +733,13 @@ describe('Task Runner Cancel', () => { '@timestamp': '1970-01-01T00:00:00.000Z', event: { action: 'execute', category: ['alerts'], kind: 'alert', outcome: 'success' }, kibana: { + alert: { + rule: { + execution: { + uuid: undefined, + }, + }, + }, alerting: { status: 'active', }, From 9878e77d41735ff6deb0f0fa5f54e9d82f8641ec Mon Sep 17 00:00:00 2001 From: Garrett Spong Date: Mon, 22 Nov 2021 17:37:32 -0700 Subject: [PATCH 08/20] Updating snapshot tests --- .../get_signals_template.test.ts.snap | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/__snapshots__/get_signals_template.test.ts.snap b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/__snapshots__/get_signals_template.test.ts.snap index af9040ea8e6cd..414f24bc756ab 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/__snapshots__/get_signals_template.test.ts.snap +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/__snapshots__/get_signals_template.test.ts.snap @@ -147,6 +147,10 @@ Object { "path": "signal.rule.enabled", "type": "alias", }, + "kibana.alert.rule.execution.uuid": Object { + "path": "signal.rule.execution.uuid", + "type": "alias", + }, "kibana.alert.rule.false_positives": Object { "path": "signal.rule.false_positives", "type": "alias", @@ -613,7 +617,7 @@ Object { "mappings": Object { "_meta": Object { "aliases_version": 1, - "version": 57, + "version": 67, }, "dynamic": false, "properties": Object { @@ -2430,6 +2434,10 @@ Object { "path": "signal.rule.enabled", "type": "alias", }, + "kibana.alert.rule.execution.uuid": Object { + "path": "signal.rule.execution.uuid", + "type": "alias", + }, "kibana.alert.rule.false_positives": Object { "path": "signal.rule.false_positives", "type": "alias", @@ -4292,6 +4300,13 @@ Object { "enabled": Object { "type": "keyword", }, + "execution": Object { + "properties": Object { + "uuid": Object { + "type": "keyword", + }, + }, + }, "false_positives": Object { "type": "keyword", }, @@ -6348,6 +6363,6 @@ Object { }, }, }, - "version": 57, + "version": 67, } `; From b60791d7909c3b4d12e1c23cbfd5d0a1f78fdce1 Mon Sep 17 00:00:00 2001 From: Garrett Spong Date: Tue, 23 Nov 2021 11:43:44 -0700 Subject: [PATCH 09/20] Removes signals mappings for executionId as not shipping in 7.16 --- .../lib/detection_engine/routes/index/get_signals_template.ts | 2 +- .../lib/detection_engine/routes/index/signal_aad_mapping.json | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) 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 2d56d90e2421f..b76d74bfada99 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 @@ -33,7 +33,7 @@ import signalExtraFields from './signal_extra_fields.json'; incremented by 10 in order to add "room" for the aforementioned patch release */ -export const SIGNALS_TEMPLATE_VERSION = 67; +export const SIGNALS_TEMPLATE_VERSION = 57; /** @constant @type {number} diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/signal_aad_mapping.json b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/signal_aad_mapping.json index fb8f7d4356318..94e9419c9f55c 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/signal_aad_mapping.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/signal_aad_mapping.json @@ -33,7 +33,6 @@ "signal.rule.created_by": "kibana.alert.rule.created_by", "signal.rule.description": "kibana.alert.rule.description", "signal.rule.enabled": "kibana.alert.rule.enabled", - "signal.rule.execution.uuid": "kibana.alert.rule.execution.uuid", "signal.rule.false_positives": "kibana.alert.rule.false_positives", "signal.rule.from": "kibana.alert.rule.from", "signal.rule.id": "kibana.alert.rule.uuid", From 0c697916d0abf9572edc995f4cd4c93ce9eea49f Mon Sep 17 00:00:00 2001 From: Garrett Spong Date: Tue, 23 Nov 2021 13:47:11 -0700 Subject: [PATCH 10/20] Fixing snapshot test for signal index revert --- .../get_signals_template.test.ts.snap | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/__snapshots__/get_signals_template.test.ts.snap b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/__snapshots__/get_signals_template.test.ts.snap index 414f24bc756ab..af9040ea8e6cd 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/__snapshots__/get_signals_template.test.ts.snap +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/__snapshots__/get_signals_template.test.ts.snap @@ -147,10 +147,6 @@ Object { "path": "signal.rule.enabled", "type": "alias", }, - "kibana.alert.rule.execution.uuid": Object { - "path": "signal.rule.execution.uuid", - "type": "alias", - }, "kibana.alert.rule.false_positives": Object { "path": "signal.rule.false_positives", "type": "alias", @@ -617,7 +613,7 @@ Object { "mappings": Object { "_meta": Object { "aliases_version": 1, - "version": 67, + "version": 57, }, "dynamic": false, "properties": Object { @@ -2434,10 +2430,6 @@ Object { "path": "signal.rule.enabled", "type": "alias", }, - "kibana.alert.rule.execution.uuid": Object { - "path": "signal.rule.execution.uuid", - "type": "alias", - }, "kibana.alert.rule.false_positives": Object { "path": "signal.rule.false_positives", "type": "alias", @@ -4300,13 +4292,6 @@ Object { "enabled": Object { "type": "keyword", }, - "execution": Object { - "properties": Object { - "uuid": Object { - "type": "keyword", - }, - }, - }, "false_positives": Object { "type": "keyword", }, @@ -6363,6 +6348,6 @@ Object { }, }, }, - "version": 67, + "version": 57, } `; From 8ade837b1336ad0aab702c6be0832ab3398489ba Mon Sep 17 00:00:00 2001 From: Garrett Spong Date: Tue, 23 Nov 2021 14:47:13 -0700 Subject: [PATCH 11/20] Snapshot for .alerts index --- .../index/__snapshots__/get_signals_template.test.ts.snap | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/__snapshots__/get_signals_template.test.ts.snap b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/__snapshots__/get_signals_template.test.ts.snap index af9040ea8e6cd..5e0d3ae791351 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/__snapshots__/get_signals_template.test.ts.snap +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/__snapshots__/get_signals_template.test.ts.snap @@ -4292,6 +4292,13 @@ Object { "enabled": Object { "type": "keyword", }, + "execution": Object { + "properties": Object { + "uuid": Object { + "type": "keyword", + }, + }, + }, "false_positives": Object { "type": "keyword", }, From 1db77df44f493dc37f614888c5961008a553f382 Mon Sep 17 00:00:00 2001 From: Garrett Spong Date: Mon, 29 Nov 2021 16:09:54 -0700 Subject: [PATCH 12/20] Fixes cypress test and ml functional test --- .../cypress/integration/detection_alerts/alerts_details.spec.ts | 2 +- .../security_and_spaces/tests/create_ml.ts | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_details.spec.ts b/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_details.spec.ts index 116ee4d3820f9..cccb636db4b5a 100644 --- a/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_details.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_details.spec.ts @@ -57,7 +57,7 @@ describe('Alert details with unmapped fields', () => { // This test needs to be updated to not look for the field in a specific row, as it prevents us from adding/removing fields it('Displays the unmapped field on the table', () => { const expectedUnmmappedField = { - row: 82, + row: 83, field: 'unmapped', text: 'This is the unmapped field', }; diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/create_ml.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/create_ml.ts index 57f4875b6c864..3837169288562 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/create_ml.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/create_ml.ts @@ -8,6 +8,7 @@ import expect from '@kbn/expect'; import { ALERT_REASON, + ALERT_RULE_EXECUTION_UUID, ALERT_RULE_NAMESPACE, ALERT_RULE_UPDATED_AT, ALERT_STATUS, @@ -118,6 +119,7 @@ export default ({ getService }: FtrProviderContext) => { expect(signal._source).eql({ '@timestamp': signal._source['@timestamp'], + [ALERT_RULE_EXECUTION_UUID]: signal._source[ALERT_RULE_EXECUTION_UUID], [ALERT_UUID]: signal._source[ALERT_UUID], [VERSION]: signal._source[VERSION], actual: [1], From 86ebaa15f403a5e07589442efa965a99927572cd Mon Sep 17 00:00:00 2001 From: Garrett Spong Date: Wed, 8 Dec 2021 17:37:04 -0700 Subject: [PATCH 13/20] Fixing task_runner test --- .../server/task_runner/task_runner.test.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/x-pack/plugins/alerting/server/task_runner/task_runner.test.ts b/x-pack/plugins/alerting/server/task_runner/task_runner.test.ts index 0a3c40475c1af..6adb99a9a3008 100644 --- a/x-pack/plugins/alerting/server/task_runner/task_runner.test.ts +++ b/x-pack/plugins/alerting/server/task_runner/task_runner.test.ts @@ -4702,6 +4702,13 @@ describe('Task Runner', () => { category: ['alerts'], }, kibana: { + alert: { + rule: { + execution: { + uuid: undefined, + }, + }, + }, saved_objects: [ { rel: 'primary', type: 'alert', id: '1', namespace: undefined, type_id: 'test' }, ], @@ -4724,6 +4731,13 @@ describe('Task Runner', () => { outcome: 'failure', }, kibana: { + alert: { + rule: { + execution: { + uuid: undefined, + }, + }, + }, saved_objects: [ { rel: 'primary', type: 'alert', id: '1', namespace: undefined, type_id: 'test' }, ], From a993668663dd4fc25d3336e2d474101ed8d1b74d Mon Sep 17 00:00:00 2001 From: Garrett Spong Date: Fri, 17 Dec 2021 13:48:06 -0700 Subject: [PATCH 14/20] Plumbs through remaining EVENT_LOG_ACTIONS types --- .../src/get_index_exists/index.ts | 1 - .../server/rules_client/rules_client.ts | 1 + .../server/rules_client/tests/disable.test.ts | 6 +- .../create_execution_handler.test.ts | 3 +- .../task_runner/create_execution_handler.ts | 3 + .../server/task_runner/task_runner.test.ts | 245 +++++++++++++++--- .../server/task_runner/task_runner.ts | 27 +- .../task_runner/task_runner_cancel.test.ts | 53 +++- 8 files changed, 285 insertions(+), 54 deletions(-) diff --git a/packages/kbn-securitysolution-es-utils/src/get_index_exists/index.ts b/packages/kbn-securitysolution-es-utils/src/get_index_exists/index.ts index b4182312ad8ac..50ba298d10259 100644 --- a/packages/kbn-securitysolution-es-utils/src/get_index_exists/index.ts +++ b/packages/kbn-securitysolution-es-utils/src/get_index_exists/index.ts @@ -8,7 +8,6 @@ import type { ElasticsearchClient } from '../elasticsearch_client'; -// TODO: Being fooled by alias, so can return true if concrete index doesn't exist export const getIndexExists = async ( esClient: ElasticsearchClient, index: string diff --git a/x-pack/plugins/alerting/server/rules_client/rules_client.ts b/x-pack/plugins/alerting/server/rules_client/rules_client.ts index e182a5c2b0058..a1fadecb64c24 100644 --- a/x-pack/plugins/alerting/server/rules_client/rules_client.ts +++ b/x-pack/plugins/alerting/server/rules_client/rules_client.ts @@ -1303,6 +1303,7 @@ export class RulesClient { ruleId: id, ruleName: attributes.name, ruleType: this.ruleTypeRegistry.get(attributes.alertTypeId), + executionId: 'rules-client', // TODO: Is it possible to get executionId from relevant `TaskRunner` instance, or does it need to saved to `params` of AlertTaskInstance? instanceId, action: EVENT_LOG_ACTIONS.recoveredInstance, message, diff --git a/x-pack/plugins/alerting/server/rules_client/tests/disable.test.ts b/x-pack/plugins/alerting/server/rules_client/tests/disable.test.ts index b6abed9545885..a2ba66a2fe58f 100644 --- a/x-pack/plugins/alerting/server/rules_client/tests/disable.test.ts +++ b/x-pack/plugins/alerting/server/rules_client/tests/disable.test.ts @@ -21,6 +21,10 @@ import { getBeforeSetup, setGlobalDate } from './lib'; import { eventLoggerMock } from '../../../../event_log/server/event_logger.mock'; import { TaskStatus } from '../../../../task_manager/server'; +jest.mock('uuid', () => ({ + v4: () => '5f6aa57d-3e22-484e-bae8-cbed868f4d28', +})); + const taskManager = taskManagerMock.createStart(); const ruleTypeRegistry = ruleTypeRegistryMock.create(); const unsecuredSavedObjectsClient = savedObjectsClientMock.create(); @@ -328,7 +332,7 @@ describe('disable()', () => { alert: { rule: { execution: { - uuid: undefined, + uuid: 'rules-client', // TODO: See TODO in `rules_client.ts` }, }, }, diff --git a/x-pack/plugins/alerting/server/task_runner/create_execution_handler.test.ts b/x-pack/plugins/alerting/server/task_runner/create_execution_handler.test.ts index 2df51241cb30a..71ec12e29a9dd 100644 --- a/x-pack/plugins/alerting/server/task_runner/create_execution_handler.test.ts +++ b/x-pack/plugins/alerting/server/task_runner/create_execution_handler.test.ts @@ -73,6 +73,7 @@ const createExecutionHandlerParams: jest.Mocked< spaceId: 'test1', ruleId: '1', ruleName: 'name-of-alert', + executionId: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', tags: ['tag-A', 'tag-B'], apiKey: 'MTIzOmFiYw==', kibanaBaseUrl: 'http://localhost:5601', @@ -176,7 +177,7 @@ test('enqueues execution per selected action', async () => { "alert": Object { "rule": Object { "execution": Object { - "uuid": undefined, + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", }, }, }, diff --git a/x-pack/plugins/alerting/server/task_runner/create_execution_handler.ts b/x-pack/plugins/alerting/server/task_runner/create_execution_handler.ts index 112cb949e3ad7..58f8089890c87 100644 --- a/x-pack/plugins/alerting/server/task_runner/create_execution_handler.ts +++ b/x-pack/plugins/alerting/server/task_runner/create_execution_handler.ts @@ -36,6 +36,7 @@ export interface CreateExecutionHandlerOptions< > { ruleId: string; ruleName: string; + executionId: string; tags?: string[]; actionsPlugin: ActionsPluginStartContract; actions: AlertAction[]; @@ -83,6 +84,7 @@ export function createExecutionHandler< logger, ruleId, ruleName, + executionId, tags, actionsPlugin, actions: ruleActions, @@ -206,6 +208,7 @@ export function createExecutionHandler< ruleId, ruleType: ruleType as UntypedNormalizedRuleType, action: EVENT_LOG_ACTIONS.executeAction, + executionId, instanceId: alertId, group: actionGroup, subgroup: actionSubgroup, diff --git a/x-pack/plugins/alerting/server/task_runner/task_runner.test.ts b/x-pack/plugins/alerting/server/task_runner/task_runner.test.ts index 43081384de151..488412b1ef8c9 100644 --- a/x-pack/plugins/alerting/server/task_runner/task_runner.test.ts +++ b/x-pack/plugins/alerting/server/task_runner/task_runner.test.ts @@ -41,6 +41,10 @@ import { UntypedNormalizedRuleType } from '../rule_type_registry'; import { ruleTypeRegistryMock } from '../rule_type_registry.mock'; import { ExecuteOptions } from '../../../actions/server/create_execute_function'; +jest.mock('uuid', () => ({ + v4: () => '5f6aa57d-3e22-484e-bae8-cbed868f4d28', +})); + const ruleType: jest.Mocked = { id: 'test', name: 'My test rule', @@ -310,7 +314,7 @@ describe('Task Runner', () => { "alert": Object { "rule": Object { "execution": Object { - "uuid": undefined, + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", }, }, }, @@ -465,7 +469,7 @@ describe('Task Runner', () => { alert: { rule: { execution: { - uuid: undefined, + uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', }, }, }, @@ -500,6 +504,13 @@ describe('Task Runner', () => { start: '1970-01-01T00:00:00.000Z', }, kibana: { + alert: { + rule: { + execution: { + uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', + }, + }, + }, alerting: { action_group_id: 'default', action_subgroup: 'subDefault', @@ -534,6 +545,13 @@ describe('Task Runner', () => { start: '1970-01-01T00:00:00.000Z', }, kibana: { + alert: { + rule: { + execution: { + uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', + }, + }, + }, alerting: { action_group_id: 'default', action_subgroup: 'subDefault', @@ -564,7 +582,7 @@ describe('Task Runner', () => { alert: { rule: { execution: { - uuid: undefined, + uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', }, }, }, @@ -606,7 +624,7 @@ describe('Task Runner', () => { alert: { rule: { execution: { - uuid: undefined, + uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', }, }, }, @@ -709,7 +727,7 @@ describe('Task Runner', () => { alert: { rule: { execution: { - uuid: undefined, + uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', }, }, }, @@ -740,6 +758,13 @@ describe('Task Runner', () => { start: '1970-01-01T00:00:00.000Z', }, kibana: { + alert: { + rule: { + execution: { + uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', + }, + }, + }, alerting: { action_group_id: 'default', instance_id: '1', @@ -773,6 +798,13 @@ describe('Task Runner', () => { start: '1970-01-01T00:00:00.000Z', }, kibana: { + alert: { + rule: { + execution: { + uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', + }, + }, + }, alerting: { instance_id: '1', action_group_id: 'default', @@ -808,7 +840,7 @@ describe('Task Runner', () => { alert: { rule: { execution: { - uuid: undefined, + uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', }, }, }, @@ -980,7 +1012,7 @@ describe('Task Runner', () => { "alert": Object { "rule": Object { "execution": Object { - "uuid": undefined, + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", }, }, }, @@ -1019,6 +1051,13 @@ describe('Task Runner', () => { "start": "1969-12-31T00:00:00.000Z", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", + }, + }, + }, "alerting": Object { "action_group_id": "default", "instance_id": "1", @@ -1057,7 +1096,7 @@ describe('Task Runner', () => { "alert": Object { "rule": Object { "execution": Object { - "uuid": undefined, + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", }, }, }, @@ -1333,7 +1372,7 @@ describe('Task Runner', () => { "alert": Object { "rule": Object { "execution": Object { - "uuid": undefined, + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", }, }, }, @@ -1372,6 +1411,13 @@ describe('Task Runner', () => { "start": "1970-01-01T00:00:00.000Z", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", + }, + }, + }, "alerting": Object { "action_group_id": "default", "instance_id": "1", @@ -1408,6 +1454,13 @@ describe('Task Runner', () => { "start": "1970-01-01T00:00:00.000Z", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", + }, + }, + }, "alerting": Object { "action_group_id": "default", "instance_id": "1", @@ -1445,7 +1498,7 @@ describe('Task Runner', () => { "alert": Object { "rule": Object { "execution": Object { - "uuid": undefined, + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", }, }, }, @@ -1493,7 +1546,7 @@ describe('Task Runner', () => { "alert": Object { "rule": Object { "execution": Object { - "uuid": undefined, + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", }, }, }, @@ -1649,7 +1702,7 @@ describe('Task Runner', () => { "alert": Object { "rule": Object { "execution": Object { - "uuid": undefined, + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", }, }, }, @@ -1689,6 +1742,13 @@ describe('Task Runner', () => { "start": "1969-12-31T06:00:00.000Z", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", + }, + }, + }, "alerting": Object { "instance_id": "2", }, @@ -1724,6 +1784,13 @@ describe('Task Runner', () => { "start": "1969-12-31T00:00:00.000Z", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", + }, + }, + }, "alerting": Object { "action_group_id": "default", "instance_id": "1", @@ -1761,7 +1828,7 @@ describe('Task Runner', () => { "alert": Object { "rule": Object { "execution": Object { - "uuid": undefined, + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", }, }, }, @@ -1808,7 +1875,7 @@ describe('Task Runner', () => { "alert": Object { "rule": Object { "execution": Object { - "uuid": undefined, + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", }, }, }, @@ -1856,7 +1923,7 @@ describe('Task Runner', () => { "alert": Object { "rule": Object { "execution": Object { - "uuid": undefined, + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", }, }, }, @@ -2245,7 +2312,7 @@ describe('Task Runner', () => { "alert": Object { "rule": Object { "execution": Object { - "uuid": undefined, + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", }, }, }, @@ -2285,6 +2352,13 @@ describe('Task Runner', () => { "start": "1969-12-31T06:00:00.000Z", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", + }, + }, + }, "alerting": Object { "action_group_id": "default", "instance_id": "2", @@ -2321,6 +2395,13 @@ describe('Task Runner', () => { "start": "1969-12-31T00:00:00.000Z", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", + }, + }, + }, "alerting": Object { "action_group_id": "default", "instance_id": "1", @@ -2359,7 +2440,7 @@ describe('Task Runner', () => { "alert": Object { "rule": Object { "execution": Object { - "uuid": undefined, + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", }, }, }, @@ -2599,7 +2680,7 @@ describe('Task Runner', () => { "alert": Object { "rule": Object { "execution": Object { - "uuid": undefined, + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", }, }, }, @@ -2644,7 +2725,7 @@ describe('Task Runner', () => { "alert": Object { "rule": Object { "execution": Object { - "uuid": undefined, + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", }, }, }, @@ -2720,7 +2801,7 @@ describe('Task Runner', () => { "alert": Object { "rule": Object { "execution": Object { - "uuid": undefined, + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", }, }, }, @@ -2765,7 +2846,7 @@ describe('Task Runner', () => { "alert": Object { "rule": Object { "execution": Object { - "uuid": undefined, + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", }, }, }, @@ -2850,7 +2931,7 @@ describe('Task Runner', () => { "alert": Object { "rule": Object { "execution": Object { - "uuid": undefined, + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", }, }, }, @@ -2895,7 +2976,7 @@ describe('Task Runner', () => { "alert": Object { "rule": Object { "execution": Object { - "uuid": undefined, + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", }, }, }, @@ -2980,7 +3061,7 @@ describe('Task Runner', () => { "alert": Object { "rule": Object { "execution": Object { - "uuid": undefined, + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", }, }, }, @@ -3025,7 +3106,7 @@ describe('Task Runner', () => { "alert": Object { "rule": Object { "execution": Object { - "uuid": undefined, + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", }, }, }, @@ -3109,7 +3190,7 @@ describe('Task Runner', () => { "alert": Object { "rule": Object { "execution": Object { - "uuid": undefined, + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", }, }, }, @@ -3154,7 +3235,7 @@ describe('Task Runner', () => { "alert": Object { "rule": Object { "execution": Object { - "uuid": undefined, + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", }, }, }, @@ -3416,7 +3497,7 @@ describe('Task Runner', () => { "alert": Object { "rule": Object { "execution": Object { - "uuid": undefined, + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", }, }, }, @@ -3455,6 +3536,13 @@ describe('Task Runner', () => { "start": "1970-01-01T00:00:00.000Z", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", + }, + }, + }, "alerting": Object { "action_group_id": "default", "instance_id": "1", @@ -3491,6 +3579,13 @@ describe('Task Runner', () => { "start": "1970-01-01T00:00:00.000Z", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", + }, + }, + }, "alerting": Object { "action_group_id": "default", "instance_id": "2", @@ -3527,6 +3622,13 @@ describe('Task Runner', () => { "start": "1970-01-01T00:00:00.000Z", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", + }, + }, + }, "alerting": Object { "action_group_id": "default", "instance_id": "1", @@ -3563,6 +3665,13 @@ describe('Task Runner', () => { "start": "1970-01-01T00:00:00.000Z", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", + }, + }, + }, "alerting": Object { "action_group_id": "default", "instance_id": "2", @@ -3601,7 +3710,7 @@ describe('Task Runner', () => { "alert": Object { "rule": Object { "execution": Object { - "uuid": undefined, + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", }, }, }, @@ -3715,7 +3824,7 @@ describe('Task Runner', () => { "alert": Object { "rule": Object { "execution": Object { - "uuid": undefined, + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", }, }, }, @@ -3754,6 +3863,13 @@ describe('Task Runner', () => { "start": "1969-12-31T00:00:00.000Z", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", + }, + }, + }, "alerting": Object { "action_group_id": "default", "instance_id": "1", @@ -3790,6 +3906,13 @@ describe('Task Runner', () => { "start": "1969-12-31T06:00:00.000Z", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", + }, + }, + }, "alerting": Object { "action_group_id": "default", "instance_id": "2", @@ -3828,7 +3951,7 @@ describe('Task Runner', () => { "alert": Object { "rule": Object { "execution": Object { - "uuid": undefined, + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", }, }, }, @@ -3934,7 +4057,7 @@ describe('Task Runner', () => { "alert": Object { "rule": Object { "execution": Object { - "uuid": undefined, + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", }, }, }, @@ -3971,6 +4094,13 @@ describe('Task Runner', () => { "kind": "alert", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", + }, + }, + }, "alerting": Object { "action_group_id": "default", "instance_id": "1", @@ -4005,6 +4135,13 @@ describe('Task Runner', () => { "kind": "alert", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", + }, + }, + }, "alerting": Object { "action_group_id": "default", "instance_id": "2", @@ -4043,7 +4180,7 @@ describe('Task Runner', () => { "alert": Object { "rule": Object { "execution": Object { - "uuid": undefined, + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", }, }, }, @@ -4144,7 +4281,7 @@ describe('Task Runner', () => { "alert": Object { "rule": Object { "execution": Object { - "uuid": undefined, + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", }, }, }, @@ -4184,6 +4321,13 @@ describe('Task Runner', () => { "start": "1969-12-31T00:00:00.000Z", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", + }, + }, + }, "alerting": Object { "instance_id": "1", }, @@ -4220,6 +4364,13 @@ describe('Task Runner', () => { "start": "1969-12-31T06:00:00.000Z", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", + }, + }, + }, "alerting": Object { "instance_id": "2", }, @@ -4257,7 +4408,7 @@ describe('Task Runner', () => { "alert": Object { "rule": Object { "execution": Object { - "uuid": undefined, + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", }, }, }, @@ -4360,7 +4511,7 @@ describe('Task Runner', () => { "alert": Object { "rule": Object { "execution": Object { - "uuid": undefined, + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", }, }, }, @@ -4397,6 +4548,13 @@ describe('Task Runner', () => { "kind": "alert", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", + }, + }, + }, "alerting": Object { "instance_id": "1", }, @@ -4430,6 +4588,13 @@ describe('Task Runner', () => { "kind": "alert", }, "kibana": Object { + "alert": Object { + "rule": Object { + "execution": Object { + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", + }, + }, + }, "alerting": Object { "instance_id": "2", }, @@ -4467,7 +4632,7 @@ describe('Task Runner', () => { "alert": Object { "rule": Object { "execution": Object { - "uuid": undefined, + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", }, }, }, @@ -4621,7 +4786,7 @@ describe('Task Runner', () => { "alert": Object { "rule": Object { "execution": Object { - "uuid": undefined, + "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", }, }, }, @@ -4705,7 +4870,7 @@ describe('Task Runner', () => { alert: { rule: { execution: { - uuid: undefined, + uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', }, }, }, @@ -4734,7 +4899,7 @@ describe('Task Runner', () => { alert: { rule: { execution: { - uuid: undefined, + uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', }, }, }, diff --git a/x-pack/plugins/alerting/server/task_runner/task_runner.ts b/x-pack/plugins/alerting/server/task_runner/task_runner.ts index ceedcff91dc79..738ae18c6dc94 100644 --- a/x-pack/plugins/alerting/server/task_runner/task_runner.ts +++ b/x-pack/plugins/alerting/server/task_runner/task_runner.ts @@ -94,6 +94,7 @@ export class TaskRunner< ActionGroupIds, RecoveryActionGroupId >; + private readonly executionId: string; private readonly ruleTypeRegistry: RuleTypeRegistry; private searchAbortController: AbortController; private cancelled: boolean; @@ -119,6 +120,7 @@ export class TaskRunner< this.ruleTypeRegistry = context.ruleTypeRegistry; this.searchAbortController = new AbortController(); this.cancelled = false; + this.executionId = uuid.v4(); } async getDecryptedAttributes( @@ -197,6 +199,7 @@ export class TaskRunner< ruleId, ruleName, tags, + executionId: this.executionId, logger: this.logger, actionsPlugin: this.context.actionsPlugin, apiKey, @@ -292,7 +295,6 @@ export class TaskRunner< } = this.taskInstance; const namespace = this.context.spaceIdToNamespace(spaceId); const ruleType = this.ruleTypeRegistry.get(alertTypeId); - const executionId = uuid.v4(); const alerts = mapValues< Record, @@ -318,7 +320,7 @@ export class TaskRunner< updatedRuleTypeState = await this.context.executionContext.withContext(ctx, () => this.ruleType.executor({ alertId: ruleId, - executionId, + executionId: this.executionId, services: { ...services, alertInstanceFactory: createAlertInstanceFactory< @@ -406,6 +408,7 @@ export class TaskRunner< if (this.shouldLogAndScheduleActionsForAlerts()) { generateNewAndRecoveredAlertEvents({ eventLogger, + executionId: this.executionId, originalAlerts, currentAlerts: alertsWithScheduledActions, recoveredAlerts, @@ -573,7 +576,7 @@ export class TaskRunner< async run(): Promise { const { - params: { alertId: ruleId, executionId, spaceId }, + params: { alertId: ruleId, spaceId }, startedAt, state: originalState, schedule: taskSchedule, @@ -599,7 +602,7 @@ export class TaskRunner< ruleType: this.ruleType as UntypedNormalizedRuleType, action: EVENT_LOG_ACTIONS.execute, namespace, - executionId, + executionId: this.executionId, task: { scheduled: this.taskInstance.runAt.toISOString(), scheduleDelay: Millis2Nanos * scheduleDelay, @@ -756,6 +759,13 @@ export class TaskRunner< this.ruleType.ruleTaskTimeout }`, kibana: { + alert: { + rule: { + execution: { + uuid: this.executionId, + }, + }, + }, saved_objects: [ { rel: SAVED_OBJECT_REL_PRIMARY, @@ -852,6 +862,7 @@ interface GenerateNewAndRecoveredAlertEventsParams< InstanceContext extends AlertInstanceContext > { eventLogger: IEventLogger; + executionId: string; originalAlerts: Dictionary>; currentAlerts: Dictionary>; recoveredAlerts: Dictionary>; @@ -880,6 +891,7 @@ function generateNewAndRecoveredAlertEvents< >(params: GenerateNewAndRecoveredAlertEventsParams) { const { eventLogger, + executionId, ruleId, namespace, currentAlerts, @@ -959,6 +971,13 @@ function generateNewAndRecoveredAlertEvents< ...(state?.duration !== undefined ? { duration: state.duration as number } : {}), }, kibana: { + alert: { + rule: { + execution: { + uuid: executionId, + }, + }, + }, alerting: { instance_id: alertId, ...(group ? { action_group_id: group } : {}), diff --git a/x-pack/plugins/alerting/server/task_runner/task_runner_cancel.test.ts b/x-pack/plugins/alerting/server/task_runner/task_runner_cancel.test.ts index 7e3765d6f65ff..e24be639c7fcc 100644 --- a/x-pack/plugins/alerting/server/task_runner/task_runner_cancel.test.ts +++ b/x-pack/plugins/alerting/server/task_runner/task_runner_cancel.test.ts @@ -32,6 +32,10 @@ import { Alert, RecoveredActionGroup } from '../../common'; import { UntypedNormalizedRuleType } from '../rule_type_registry'; import { ruleTypeRegistryMock } from '../rule_type_registry.mock'; +jest.mock('uuid', () => ({ + v4: () => '5f6aa57d-3e22-484e-bae8-cbed868f4d28', +})); + const ruleType: jest.Mocked = { id: 'test', name: 'My test rule', @@ -211,7 +215,7 @@ describe('Task Runner Cancel', () => { alert: { rule: { execution: { - uuid: undefined, + uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', }, }, }, @@ -243,6 +247,13 @@ describe('Task Runner Cancel', () => { kind: 'alert', }, kibana: { + alert: { + rule: { + execution: { + uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', + }, + }, + }, saved_objects: [ { id: '1', @@ -271,7 +282,7 @@ describe('Task Runner Cancel', () => { alert: { rule: { execution: { - uuid: undefined, + uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', }, }, }, @@ -454,7 +465,7 @@ describe('Task Runner Cancel', () => { alert: { rule: { execution: { - uuid: undefined, + uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', }, }, }, @@ -486,6 +497,13 @@ describe('Task Runner Cancel', () => { kind: 'alert', }, kibana: { + alert: { + rule: { + execution: { + uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', + }, + }, + }, saved_objects: [ { id: '1', @@ -515,7 +533,7 @@ describe('Task Runner Cancel', () => { alert: { rule: { execution: { - uuid: undefined, + uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', }, }, }, @@ -584,7 +602,7 @@ describe('Task Runner Cancel', () => { alert: { rule: { execution: { - uuid: undefined, + uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', }, }, }, @@ -617,6 +635,13 @@ describe('Task Runner Cancel', () => { kind: 'alert', }, kibana: { + alert: { + rule: { + execution: { + uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', + }, + }, + }, saved_objects: [ { id: '1', @@ -644,6 +669,13 @@ describe('Task Runner Cancel', () => { start: '1970-01-01T00:00:00.000Z', }, kibana: { + alert: { + rule: { + execution: { + uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', + }, + }, + }, alerting: { action_group_id: 'default', instance_id: '1', @@ -677,6 +709,13 @@ describe('Task Runner Cancel', () => { start: '1970-01-01T00:00:00.000Z', }, kibana: { + alert: { + rule: { + execution: { + uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', + }, + }, + }, alerting: { action_group_id: 'default', instance_id: '1', @@ -704,7 +743,7 @@ describe('Task Runner Cancel', () => { alert: { rule: { execution: { - uuid: undefined, + uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', }, }, }, @@ -742,7 +781,7 @@ describe('Task Runner Cancel', () => { alert: { rule: { execution: { - uuid: undefined, + uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', }, }, }, From c81341c325edcb0eaca1dab2521b2a86fea18389 Mon Sep 17 00:00:00 2001 From: Garrett Spong Date: Wed, 12 Jan 2022 15:57:58 -0700 Subject: [PATCH 15/20] Removed legacy signals impl, now writing to all alert types, and test cleanup --- .../server/alert_instance/alert_instance.ts | 2 -- ...eate_alert_event_log_record_object.test.ts | 9 +++++--- .../create_alert_event_log_record_object.ts | 18 +++++++++------ .../server/rules_client/rules_client.ts | 1 - .../server/rules_client/tests/disable.test.ts | 7 ------ .../server/task_runner/task_runner.test.ts | 1 - .../utils/create_lifecycle_rule_type.test.ts | 2 +- .../create_persistence_rule_type_wrapper.ts | 3 +-- .../server/utils/get_common_alert_fields.ts | 3 +++ .../server/utils/rule_executor_test_utils.ts | 2 +- ...gacy_rules_notification_alert_type.test.ts | 2 +- .../event_log_adapter/event_log_client.ts | 2 +- .../rule_execution_log_client.ts | 5 +++-- .../rule_execution_log/types.ts | 4 ++-- .../rule_types/factories/wrap_hits_factory.ts | 1 - .../signals/build_bulk_body.ts | 22 ++----------------- .../signals/search_after_bulk_create.test.ts | 1 - .../lib/detection_engine/signals/types.ts | 10 --------- .../detection_engine/signals/utils.test.ts | 8 +++---- .../signals/wrap_hits_factory.ts | 11 +--------- 20 files changed, 37 insertions(+), 77 deletions(-) diff --git a/x-pack/plugins/alerting/server/alert_instance/alert_instance.ts b/x-pack/plugins/alerting/server/alert_instance/alert_instance.ts index ec5af7506f5cc..b41a4e551040c 100644 --- a/x-pack/plugins/alerting/server/alert_instance/alert_instance.ts +++ b/x-pack/plugins/alerting/server/alert_instance/alert_instance.ts @@ -46,7 +46,6 @@ export class AlertInstance< private state: State; constructor({ state, meta = {} }: RawAlertInstance = {}) { - // TODO: Add 'kibana.alert.rule.execution.uuid' to framework along with other execution status/metrics? this.state = (state || {}) as State; this.meta = meta; } @@ -183,7 +182,6 @@ export class AlertInstance< } toRaw(): RawAlertInstance { - // TODO: To add 'kibana.alert.rule.execution.uuid' to framework return { state: this.state, meta: this.meta, diff --git a/x-pack/plugins/alerting/server/lib/create_alert_event_log_record_object.test.ts b/x-pack/plugins/alerting/server/lib/create_alert_event_log_record_object.test.ts index adeb863f7c21f..3895c90d4a6c2 100644 --- a/x-pack/plugins/alerting/server/lib/create_alert_event_log_record_object.test.ts +++ b/x-pack/plugins/alerting/server/lib/create_alert_event_log_record_object.test.ts @@ -25,6 +25,7 @@ describe('createAlertEventLogRecordObject', () => { test('created alert event "execute-start"', async () => { expect( createAlertEventLogRecordObject({ + executionId: '7a7065d7-6e8b-4aae-8d20-c93613dec9fb', ruleId: '1', ruleType, action: 'execute-start', @@ -53,7 +54,7 @@ describe('createAlertEventLogRecordObject', () => { alert: { rule: { execution: { - uuid: undefined, + uuid: '7a7065d7-6e8b-4aae-8d20-c93613dec9fb', }, }, }, @@ -83,6 +84,7 @@ describe('createAlertEventLogRecordObject', () => { test('created alert event "recovered-instance"', async () => { expect( createAlertEventLogRecordObject({ + executionId: '7a7065d7-6e8b-4aae-8d20-c93613dec9fb', ruleId: '1', ruleName: 'test name', ruleType, @@ -119,7 +121,7 @@ describe('createAlertEventLogRecordObject', () => { alert: { rule: { execution: { - uuid: undefined, + uuid: '7a7065d7-6e8b-4aae-8d20-c93613dec9fb', }, }, }, @@ -152,6 +154,7 @@ describe('createAlertEventLogRecordObject', () => { test('created alert event "execute-action"', async () => { expect( createAlertEventLogRecordObject({ + executionId: '7a7065d7-6e8b-4aae-8d20-c93613dec9fb', ruleId: '1', ruleName: 'test name', ruleType, @@ -193,7 +196,7 @@ describe('createAlertEventLogRecordObject', () => { alert: { rule: { execution: { - uuid: undefined, + uuid: '7a7065d7-6e8b-4aae-8d20-c93613dec9fb', }, }, }, diff --git a/x-pack/plugins/alerting/server/lib/create_alert_event_log_record_object.ts b/x-pack/plugins/alerting/server/lib/create_alert_event_log_record_object.ts index f6815b3f855bc..95e33d394fbd2 100644 --- a/x-pack/plugins/alerting/server/lib/create_alert_event_log_record_object.ts +++ b/x-pack/plugins/alerting/server/lib/create_alert_event_log_record_object.ts @@ -71,13 +71,17 @@ export function createAlertEventLogRecordObject(params: CreateAlertEventLogRecor }, kibana: { ...(alerting ? alerting : {}), - alert: { - rule: { - execution: { - uuid: executionId, - }, - }, - }, + ...(executionId + ? { + alert: { + rule: { + execution: { + uuid: executionId, + }, + }, + }, + } + : {}), saved_objects: params.savedObjects.map((so) => ({ ...(so.relation ? { rel: so.relation } : {}), type: so.type, diff --git a/x-pack/plugins/alerting/server/rules_client/rules_client.ts b/x-pack/plugins/alerting/server/rules_client/rules_client.ts index 91abc58dd3708..50a93a5630d42 100644 --- a/x-pack/plugins/alerting/server/rules_client/rules_client.ts +++ b/x-pack/plugins/alerting/server/rules_client/rules_client.ts @@ -1303,7 +1303,6 @@ export class RulesClient { ruleId: id, ruleName: attributes.name, ruleType: this.ruleTypeRegistry.get(attributes.alertTypeId), - executionId: 'rules-client', // TODO: Is it possible to get executionId from relevant `TaskRunner` instance, or does it need to saved to `params` of AlertTaskInstance? instanceId, action: EVENT_LOG_ACTIONS.recoveredInstance, message, diff --git a/x-pack/plugins/alerting/server/rules_client/tests/disable.test.ts b/x-pack/plugins/alerting/server/rules_client/tests/disable.test.ts index a2ba66a2fe58f..9c3e5872c76e1 100644 --- a/x-pack/plugins/alerting/server/rules_client/tests/disable.test.ts +++ b/x-pack/plugins/alerting/server/rules_client/tests/disable.test.ts @@ -329,13 +329,6 @@ describe('disable()', () => { kind: 'alert', }, kibana: { - alert: { - rule: { - execution: { - uuid: 'rules-client', // TODO: See TODO in `rules_client.ts` - }, - }, - }, alerting: { action_group_id: 'default', action_subgroup: 'newSubgroup', diff --git a/x-pack/plugins/alerting/server/task_runner/task_runner.test.ts b/x-pack/plugins/alerting/server/task_runner/task_runner.test.ts index 488412b1ef8c9..2c108ebdf8d22 100644 --- a/x-pack/plugins/alerting/server/task_runner/task_runner.test.ts +++ b/x-pack/plugins/alerting/server/task_runner/task_runner.test.ts @@ -996,7 +996,6 @@ describe('Task Runner', () => { const eventLogger = taskRunnerFactoryInitializerParams.eventLogger; expect(eventLogger.logEvent).toHaveBeenCalledTimes(3); expect(eventLogger.startTiming).toHaveBeenCalledTimes(1); - // TODO: Necessary for "action": "active-instance" alert as well too? expect(eventLogger.logEvent.mock.calls).toMatchInlineSnapshot(` Array [ Array [ diff --git a/x-pack/plugins/rule_registry/server/utils/create_lifecycle_rule_type.test.ts b/x-pack/plugins/rule_registry/server/utils/create_lifecycle_rule_type.test.ts index 23c8e3efa0a52..9ad1502b11877 100644 --- a/x-pack/plugins/rule_registry/server/utils/create_lifecycle_rule_type.test.ts +++ b/x-pack/plugins/rule_registry/server/utils/create_lifecycle_rule_type.test.ts @@ -119,7 +119,7 @@ function createRule(shouldWriteAlerts: boolean = true) { tags: ['tags'], updatedBy: 'updatedBy', namespace: 'namespace', - executionId: 'executionId', + executionId: 'b33f65d7-6e8b-4aae-8d20-c93613dec9f9', })) ?? {}) as Record; previousStartedAt = startedAt; diff --git a/x-pack/plugins/rule_registry/server/utils/create_persistence_rule_type_wrapper.ts b/x-pack/plugins/rule_registry/server/utils/create_persistence_rule_type_wrapper.ts index 4f4fbe9425df6..2d914e5e0945e 100644 --- a/x-pack/plugins/rule_registry/server/utils/create_persistence_rule_type_wrapper.ts +++ b/x-pack/plugins/rule_registry/server/utils/create_persistence_rule_type_wrapper.ts @@ -7,7 +7,7 @@ import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { chunk } from 'lodash'; -import { ALERT_RULE_EXECUTION_UUID, ALERT_UUID, VERSION } from '@kbn/rule-data-utils'; +import { ALERT_UUID, VERSION } from '@kbn/rule-data-utils'; import { getCommonAlertFields } from './get_common_alert_fields'; import { CreatePersistenceRuleTypeWrapper } from './persistence_types'; @@ -84,7 +84,6 @@ export const createPersistenceRuleTypeWrapper: CreatePersistenceRuleTypeWrapper return { ...alert, _source: { - [ALERT_RULE_EXECUTION_UUID]: options.executionId, [VERSION]: ruleDataClient.kibanaVersion, ...commonRuleFields, ...alert._source, diff --git a/x-pack/plugins/rule_registry/server/utils/get_common_alert_fields.ts b/x-pack/plugins/rule_registry/server/utils/get_common_alert_fields.ts index 8b4daf30763f6..db8c56f84b2c4 100644 --- a/x-pack/plugins/rule_registry/server/utils/get_common_alert_fields.ts +++ b/x-pack/plugins/rule_registry/server/utils/get_common_alert_fields.ts @@ -11,6 +11,7 @@ import { ALERT_UUID, ALERT_RULE_CATEGORY, ALERT_RULE_CONSUMER, + ALERT_RULE_EXECUTION_UUID, ALERT_RULE_NAME, ALERT_RULE_PRODUCER, ALERT_RULE_TYPE_ID, @@ -26,6 +27,7 @@ import { ParsedTechnicalFields } from '../../common/parse_technical_fields'; const commonAlertFieldNames = [ ALERT_RULE_CATEGORY, ALERT_RULE_CONSUMER, + ALERT_RULE_EXECUTION_UUID, ALERT_RULE_NAME, ALERT_RULE_PRODUCER, ALERT_RULE_TYPE_ID, @@ -47,6 +49,7 @@ export const getCommonAlertFields = ( return { [ALERT_RULE_CATEGORY]: options.rule.ruleTypeName, [ALERT_RULE_CONSUMER]: options.rule.consumer, + [ALERT_RULE_EXECUTION_UUID]: options.executionId, [ALERT_RULE_NAME]: options.rule.name, [ALERT_RULE_PRODUCER]: options.rule.producer, [ALERT_RULE_TYPE_ID]: options.rule.ruleTypeId, diff --git a/x-pack/plugins/rule_registry/server/utils/rule_executor_test_utils.ts b/x-pack/plugins/rule_registry/server/utils/rule_executor_test_utils.ts index 97ead4f30963d..08b1b0a8ecbf2 100644 --- a/x-pack/plugins/rule_registry/server/utils/rule_executor_test_utils.ts +++ b/x-pack/plugins/rule_registry/server/utils/rule_executor_test_utils.ts @@ -79,5 +79,5 @@ export const createDefaultAlertExecutorOptions = < updatedBy: null, previousStartedAt: null, namespace: undefined, - executionId: 'executionId', + executionId: 'b33f65d7-6e8b-4aae-8d20-c93613deb33f', }); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/legacy_rules_notification_alert_type.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/legacy_rules_notification_alert_type.test.ts index 5f3ea892d1c73..11b88fdc375bd 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/legacy_rules_notification_alert_type.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/legacy_rules_notification_alert_type.test.ts @@ -39,7 +39,7 @@ describe('legacyRules_notification_alert_type', () => { payload = { alertId: '1111', - executionId: '', + executionId: 'b33f65d7-b33f-4aae-8d20-c93613dec9f9', services: alertServices, params: { ruleAlertId: '2222' }, state: {}, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/event_log_adapter/event_log_client.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/event_log_adapter/event_log_client.ts index aad725d6eec37..424443bbaa530 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/event_log_adapter/event_log_client.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/event_log_adapter/event_log_client.ts @@ -35,7 +35,7 @@ const statusSeverityDict: Record = { }; interface LogExecutionMetricsArgs { - executionId?: string; + executionId: string; ruleId: string; ruleName: string; ruleType: string; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/rule_execution_log_client.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/rule_execution_log_client.ts index 3efddf4d7afb0..c56b5c3991502 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/rule_execution_log_client.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/rule_execution_log_client.ts @@ -92,7 +92,7 @@ export class RuleExecutionLogClient implements IRuleExecutionLogClient { } public async logStatusChange(args: LogStatusChangeArgs): Promise { - const { newStatus, message, ruleId, ruleName, ruleType, spaceId } = args; + const { executionId, newStatus, message, ruleId, ruleName, ruleType, spaceId } = args; try { const truncatedMessage = message ? truncateMessage(message) : message; @@ -109,7 +109,7 @@ export class RuleExecutionLogClient implements IRuleExecutionLogClient { ); } catch (e) { const logMessage = 'Error logging rule execution status change'; - const logAttributes = `status: "${newStatus}", rule id: "${ruleId}", rule name: "${ruleName}"`; + const logAttributes = `status: "${newStatus}", rule id: "${ruleId}", rule name: "${ruleName}", execution uuid: "${executionId}"`; const logReason = e instanceof Error ? `${e.stack}` : `${e}`; const logMeta: ExtMeta = { rule: { @@ -118,6 +118,7 @@ export class RuleExecutionLogClient implements IRuleExecutionLogClient { type: ruleType, execution: { status: newStatus, + uuid: executionId, }, }, kibana: { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/types.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/types.ts index 259db5ac1662c..111539300a750 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/types.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/types.ts @@ -74,7 +74,7 @@ export interface CreateExecutionLogArgs { } export interface LogStatusChangeArgs { - executionId?: string; + executionId: string; ruleId: string; ruleName: string; ruleType: string; @@ -88,7 +88,7 @@ export interface LogStatusChangeArgs { } export interface LogExecutionMetricsArgs { - executionId?: string; + executionId: string; ruleId: string; ruleName: string; ruleType: string; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/wrap_hits_factory.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/wrap_hits_factory.ts index 01a6457f86716..81a4af31881fb 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/wrap_hits_factory.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/wrap_hits_factory.ts @@ -38,7 +38,6 @@ export const wrapHitsFactory = _id: id, _index: '', _source: { - // TODO: executionId here as well? ...buildBulkBody( spaceId, completeRule, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/build_bulk_body.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/build_bulk_body.ts index c7eb329d7867e..21bfced47df42 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/build_bulk_body.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/build_bulk_body.ts @@ -14,7 +14,6 @@ import { BaseSignalHit, SignalSource, WrappedSignalHit, - SignalHitExecutionId, } from './types'; import { buildRuleWithoutOverrides, buildRuleWithOverrides } from './build_rule'; import { additionalSignalFields, buildSignal } from './build_signal'; @@ -32,16 +31,11 @@ import { CompleteRule, RuleParams } from '../schemas/rule_schemas'; * such as the "threshold_result". * @param completeRule The rule object to build overrides * @param doc The SignalSourceHit with "_source", "fields", and additional data such as "threshold_result" - * @param executionId Unique id representing a specific rule execution - * @param mergeStrategy Specific merge strategy for building alert from source/fields - * @param ignoreFields Array of fields that should be ignored and never merged - * @param buildReasonMessage Function for building reason message string * @returns The body that can be added to a bulk call for inserting the signal. */ export const buildBulkBody = ( completeRule: CompleteRule, doc: SignalSourceHit, - executionId: string, mergeStrategy: ConfigType['alertMergeStrategy'], ignoreFields: ConfigType['alertIgnoreFields'], buildReasonMessage: BuildReasonMessage @@ -69,20 +63,11 @@ export const buildBulkBody = ( } = mergedDoc._source || { threshold_result: null, }; - // TODO: Modify upstream types? - const signalHit: SignalHit & SignalHitExecutionId = { + const signalHit: SignalHit = { ...filteredSource, [TIMESTAMP]: timestamp, event, - signal: { - ...signal, - rule: { - ...signal.rule, - execution: { - uuid: executionId, - }, - }, - }, + signal, }; return signalHit; }; @@ -94,9 +79,6 @@ export const buildBulkBody = ( * @param sequence The raw ES documents that make up the sequence * @param completeRule rule object representing the rule that found the sequence * @param outputIndex Index to write the resulting signals to - * @param mergeStrategy Specific merge strategy for building alert from source/fields - * @param ignoreFields Array of fields that should be ignored and never merged - * @param buildReasonMessage Function for building reason message string */ export const buildSignalGroupFromSequence = ( sequence: EqlSequence, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/search_after_bulk_create.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/search_after_bulk_create.test.ts index b5a9068b85585..01f8816bb9ce5 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/search_after_bulk_create.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/search_after_bulk_create.test.ts @@ -74,7 +74,6 @@ describe('searchAfterAndBulkCreate', () => { wrapHits = wrapHitsFactory({ completeRule: queryCompleteRule, signalsIndex: DEFAULT_SIGNALS_INDEX, - executionId: 'executionId', mergeStrategy: 'missingFields', ignoreFields: [], }); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/types.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/types.ts index bfdd14def06c9..da0c2e7819c18 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/types.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/types.ts @@ -255,16 +255,6 @@ export interface SignalHit { [key: string]: SearchTypes; } -export interface SignalHitExecutionId { - signal: { - rule: { - execution: { - uuid: string; - }; - }; - }; -} - export interface AlertAttributes { actions: RuleAlertAction[]; alertTypeId: string; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.test.ts index 263aad91f135a..7e11194348058 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.test.ts @@ -664,7 +664,7 @@ describe('utils', () => { mockLogger.error.mockClear(); const res = await hasTimestampFields({ timestampField, - executionId: 'executionId', + executionId: '7a7065d7-b33f-4aae-8d20-c93613dec9fb', ruleName: 'myfakerulename', timestampFieldCapsResponse: timestampFieldCapsResponse as TransportResult< // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -710,7 +710,7 @@ describe('utils', () => { mockLogger.error.mockClear(); const res = await hasTimestampFields({ timestampField, - executionId: 'executionId', + executionId: '7a7065d7-b33f-4aae-8d20-c93613dec9fb', ruleName: 'myfakerulename', timestampFieldCapsResponse: timestampFieldCapsResponse as TransportResult< // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -742,7 +742,7 @@ describe('utils', () => { mockLogger.error.mockClear(); const res = await hasTimestampFields({ timestampField, - executionId: 'executionId', + executionId: '7a7065d7-b33f-4aae-8d20-c93613dec9fb', ruleName: 'Endpoint Security', timestampFieldCapsResponse: timestampFieldCapsResponse as TransportResult< // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -774,7 +774,7 @@ describe('utils', () => { mockLogger.error.mockClear(); const res = await hasTimestampFields({ timestampField, - executionId: 'executionId', + executionId: '7a7065d7-b33f-4aae-8d20-c93613dec9fb', ruleName: 'NOT Endpoint Security', timestampFieldCapsResponse: timestampFieldCapsResponse as TransportResult< // eslint-disable-next-line @typescript-eslint/no-explicit-any diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/wrap_hits_factory.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/wrap_hits_factory.ts index 3260b3c1e6940..22af4dcdb9f4a 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/wrap_hits_factory.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/wrap_hits_factory.ts @@ -15,13 +15,11 @@ import { CompleteRule, RuleParams } from '../schemas/rule_schemas'; export const wrapHitsFactory = ({ completeRule, - executionId, signalsIndex, mergeStrategy, ignoreFields, }: { completeRule: CompleteRule; - executionId: string; signalsIndex: string; mergeStrategy: ConfigType['alertMergeStrategy']; ignoreFields: ConfigType['alertIgnoreFields']; @@ -31,14 +29,7 @@ export const wrapHitsFactory = { _index: signalsIndex, _id: generateId(doc._index, doc._id, String(doc._version), completeRule.alertId ?? ''), - _source: buildBulkBody( - completeRule, - doc, - executionId, - mergeStrategy, - ignoreFields, - buildReasonMessage - ), + _source: buildBulkBody(completeRule, doc, mergeStrategy, ignoreFields, buildReasonMessage), }, ]); From 4fea3d6a4f86a073af5ed9175958976c0b03eb1d Mon Sep 17 00:00:00 2001 From: Garrett Spong Date: Wed, 12 Jan 2022 17:46:26 -0700 Subject: [PATCH 16/20] Fixes snapshot and ftr tests --- .../server/utils/create_lifecycle_rule_type.test.ts | 2 ++ .../spaces_only/tests/trial/create_rule.ts | 10 +++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/rule_registry/server/utils/create_lifecycle_rule_type.test.ts b/x-pack/plugins/rule_registry/server/utils/create_lifecycle_rule_type.test.ts index 9ad1502b11877..05a71677c7535 100644 --- a/x-pack/plugins/rule_registry/server/utils/create_lifecycle_rule_type.test.ts +++ b/x-pack/plugins/rule_registry/server/utils/create_lifecycle_rule_type.test.ts @@ -225,6 +225,7 @@ describe('createLifecycleRuleTypeFactory', () => { "kibana.alert.instance.id": "opbeans-java", "kibana.alert.rule.category": "ruleTypeName", "kibana.alert.rule.consumer": "consumer", + "kibana.alert.rule.execution.uuid": "b33f65d7-6e8b-4aae-8d20-c93613dec9f9", "kibana.alert.rule.name": "name", "kibana.alert.rule.producer": "producer", "kibana.alert.rule.rule_type_id": "ruleTypeId", @@ -252,6 +253,7 @@ describe('createLifecycleRuleTypeFactory', () => { "kibana.alert.instance.id": "opbeans-node", "kibana.alert.rule.category": "ruleTypeName", "kibana.alert.rule.consumer": "consumer", + "kibana.alert.rule.execution.uuid": "b33f65d7-6e8b-4aae-8d20-c93613dec9f9", "kibana.alert.rule.name": "name", "kibana.alert.rule.producer": "producer", "kibana.alert.rule.rule_type_id": "ruleTypeId", diff --git a/x-pack/test/rule_registry/spaces_only/tests/trial/create_rule.ts b/x-pack/test/rule_registry/spaces_only/tests/trial/create_rule.ts index ac36bad1f595b..be3146f34c30e 100644 --- a/x-pack/test/rule_registry/spaces_only/tests/trial/create_rule.ts +++ b/x-pack/test/rule_registry/spaces_only/tests/trial/create_rule.ts @@ -9,6 +9,7 @@ import expect from '@kbn/expect'; import { ALERT_DURATION, ALERT_END, + ALERT_RULE_EXECUTION_UUID, ALERT_RULE_UUID, ALERT_START, ALERT_STATUS, @@ -187,7 +188,14 @@ export default function registryRulesApiTest({ getService }: FtrProviderContext) const alertEvent = afterViolatingDataResponse.hits.hits[0].fields as Record; - const exclude = ['@timestamp', ALERT_START, ALERT_UUID, ALERT_RULE_UUID, VERSION]; + const exclude = [ + '@timestamp', + ALERT_START, + ALERT_UUID, + ALERT_RULE_EXECUTION_UUID, + ALERT_RULE_UUID, + VERSION, + ]; const toCompare = omit(alertEvent, exclude); From 0f1df1d222f547e8a68f2522c6681a26862df1a9 Mon Sep 17 00:00:00 2001 From: Garrett Spong Date: Fri, 14 Jan 2022 17:20:15 -0700 Subject: [PATCH 17/20] Adds functional test coverage for identifying unqiue execution ids --- .../common/lib/get_event_log.ts | 6 +++--- .../spaces_only/tests/alerting/event_log_alerts.ts | 12 ++++++++++++ 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/x-pack/test/alerting_api_integration/common/lib/get_event_log.ts b/x-pack/test/alerting_api_integration/common/lib/get_event_log.ts index a4cc9d5139148..3ee7929170338 100644 --- a/x-pack/test/alerting_api_integration/common/lib/get_event_log.ts +++ b/x-pack/test/alerting_api_integration/common/lib/get_event_log.ts @@ -16,7 +16,7 @@ interface EqualCondition { equal: number; } -function isEqualConsition( +function isEqualCondition( condition: GreaterThanEqualCondition | EqualCondition ): condition is EqualCondition { return Number.isInteger((condition as EqualCondition).equal); @@ -67,7 +67,7 @@ export async function getEventLog(params: GetEventLogParams): Promise= condition.gte) ) @@ -76,7 +76,7 @@ export async function getEventLog(params: GetEventLogParams): Promise event?.event?.action !== 'execute' ); + // Verify unique executionId generated per `action:execute` grouping + const eventExecutionIdSet = new Set(); + events.forEach((event) => { + if (event?.event?.action === 'execute') { + eventExecutionIdSet.add(event?.kibana?.alert?.rule?.execution?.uuid); + expect(eventExecutionIdSet.size).to.equal(1); + eventExecutionIdSet.clear(); + } else { + eventExecutionIdSet.add(event?.kibana?.alert?.rule?.execution?.uuid); + } + }); + const currentAlertSpan: { alertId?: string; start?: string; From d3e01daef093eb6475223d789ccb3ba4dfe48fdb Mon Sep 17 00:00:00 2001 From: Garrett Spong Date: Wed, 19 Jan 2022 19:51:33 -0700 Subject: [PATCH 18/20] Adds executionId to buildRuleMessageFactory --- .../rule_types/create_security_rule_type_wrapper.ts | 1 + .../rule_types/factories/build_rule_message_factory.ts | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) 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 9feae450f8273..e62bd3880a47a 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 @@ -103,6 +103,7 @@ export const createSecurityRuleTypeWrapper: CreateSecurityRuleTypeWrapper = const buildRuleMessage = buildRuleMessageFactory({ id: alertId, + executionId, ruleId, name, index: spaceId, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/build_rule_message_factory.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/build_rule_message_factory.ts index 6ebc902db6992..bac112bb3cab1 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/build_rule_message_factory.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/build_rule_message_factory.ts @@ -7,6 +7,7 @@ export type BuildRuleMessage = (...messages: string[]) => string; export interface BuildRuleMessageFactoryParams { + executionId: string; name: string; id: string; ruleId: string | null | undefined; @@ -15,12 +16,13 @@ export interface BuildRuleMessageFactoryParams { // TODO: change `index` param to `spaceId` export const buildRuleMessageFactory = - ({ id, ruleId, index, name }: BuildRuleMessageFactoryParams): BuildRuleMessage => + ({ executionId, id, ruleId, index, name }: BuildRuleMessageFactoryParams): BuildRuleMessage => (...messages) => [ ...messages, `name: "${name}"`, `id: "${id}"`, `rule id: "${ruleId ?? '(unknown rule id)'}"`, + `execution id: "${executionId}"`, `space ID: "${index}"`, ].join(' '); From 677d232d9190beb233e94e7713e928daad618c3c Mon Sep 17 00:00:00 2001 From: Garrett Spong Date: Thu, 20 Jan 2022 16:40:00 -0700 Subject: [PATCH 19/20] Reworks executionId through new rule execution logger changes from main --- .../__mocks__/rule_execution_log_client.ts | 1 + .../rule_execution_events/events_writer.ts | 7 +++++-- .../rule_execution_logger/logger.ts | 8 ++++++-- .../rule_execution_logger/logger_interface.ts | 1 + .../rule_types/create_security_rule_type_wrapper.ts | 11 +---------- .../server/lib/detection_engine/signals/utils.test.ts | 4 ---- .../server/lib/detection_engine/signals/utils.ts | 5 ----- 7 files changed, 14 insertions(+), 23 deletions(-) diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/__mocks__/rule_execution_log_client.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/__mocks__/rule_execution_log_client.ts index 22a41f356c226..7cf82722c47ff 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/__mocks__/rule_execution_log_client.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/__mocks__/rule_execution_log_client.ts @@ -23,6 +23,7 @@ const ruleExecutionLogClientMock = { const ruleExecutionLoggerMock = { create: (context: Partial = {}): jest.Mocked => ({ context: { + executionId: context.executionId ?? 'some execution id', ruleId: context.ruleId ?? 'some rule id', ruleName: context.ruleName ?? 'Some rule', ruleType: context.ruleType ?? 'some rule type', diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/rule_execution_events/events_writer.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/rule_execution_events/events_writer.ts index dad30e9cb5d88..2869f1c2c82e8 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/rule_execution_events/events_writer.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/rule_execution_events/events_writer.ts @@ -24,6 +24,7 @@ export interface IRuleExecutionEventsWriter { } export interface BaseArgs { + executionId: string; ruleId: string; ruleName: string; ruleType: string; @@ -49,7 +50,7 @@ export const createRuleExecutionEventsWriter = ( let sequence = 0; return { - logStatusChange({ ruleId, ruleName, ruleType, spaceId, newStatus, message }) { + logStatusChange({ executionId, ruleId, ruleName, ruleType, spaceId, newStatus, message }) { eventLogger.logEvent({ '@timestamp': nowISO(), message, @@ -69,6 +70,7 @@ export const createRuleExecutionEventsWriter = ( execution: { status: newStatus, status_order: ruleExecutionStatusOrderByStatus[newStatus], + uuid: executionId, }, }, }, @@ -85,7 +87,7 @@ export const createRuleExecutionEventsWriter = ( }); }, - logExecutionMetrics({ ruleId, ruleName, ruleType, spaceId, metrics }) { + logExecutionMetrics({ executionId, ruleId, ruleName, ruleType, spaceId, metrics }) { eventLogger.logEvent({ '@timestamp': nowISO(), rule: { @@ -103,6 +105,7 @@ export const createRuleExecutionEventsWriter = ( rule: { execution: { metrics, + uuid: executionId, }, }, }, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/rule_execution_logger/logger.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/rule_execution_logger/logger.ts index f67aae472ef60..a3e14f9569e25 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/rule_execution_logger/logger.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/rule_execution_logger/logger.ts @@ -28,7 +28,7 @@ export const createRuleExecutionLogger = ( logger: Logger, context: RuleExecutionContext ): IRuleExecutionLogger => { - const { ruleId, ruleName, ruleType, spaceId } = context; + const { executionId, ruleId, ruleName, ruleType, spaceId } = context; const ruleExecutionLogger: IRuleExecutionLogger = { get context() { @@ -44,7 +44,7 @@ export const createRuleExecutionLogger = ( ]); } catch (e) { const logMessage = 'Error logging rule execution status change'; - const logAttributes = `status: "${args.newStatus}", rule id: "${ruleId}", rule name: "${ruleName}"`; + const logAttributes = `status: "${args.newStatus}", rule id: "${ruleId}", rule name: "${ruleName}", execution uuid: "${executionId}"`; const logReason = e instanceof Error ? e.stack ?? e.message : String(e); const logMeta: ExtMeta = { rule: { @@ -53,6 +53,7 @@ export const createRuleExecutionLogger = ( type: ruleType, execution: { status: args.newStatus, + uuid: executionId, }, }, kibana: { @@ -65,6 +66,7 @@ export const createRuleExecutionLogger = ( }, }; + // TODO: Add executionId to new status SO? const writeStatusChangeToSavedObjects = async ( args: NormalizedStatusChangeArgs ): Promise => { @@ -86,6 +88,7 @@ export const createRuleExecutionLogger = ( if (metrics) { eventsWriter.logExecutionMetrics({ + executionId, ruleId, ruleName, ruleType, @@ -95,6 +98,7 @@ export const createRuleExecutionLogger = ( } eventsWriter.logStatusChange({ + executionId, ruleId, ruleName, ruleType, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/rule_execution_logger/logger_interface.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/rule_execution_logger/logger_interface.ts index e31c10bd9747f..874d60cf4a401 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/rule_execution_logger/logger_interface.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/rule_execution_logger/logger_interface.ts @@ -29,6 +29,7 @@ export interface IRuleExecutionLogger { } export interface RuleExecutionContext { + executionId: string; ruleId: string; ruleName: string; ruleType: string; 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 296b913cc6f40..ba30b0335fb39 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 @@ -77,12 +77,12 @@ export const createSecurityRuleTypeWrapper: CreateSecurityRuleTypeWrapper = const esClient = scopedClusterClient.asCurrentUser; - // TODO: Add executionId in place of `basicLogArguments` const ruleExecutionLogger = ruleExecutionLoggerFactory( savedObjectsClient, eventLogService, logger, { + executionId, ruleId: alertId, ruleName: rule.name, ruleType: rule.ruleTypeId, @@ -117,7 +117,6 @@ export const createSecurityRuleTypeWrapper: CreateSecurityRuleTypeWrapper = let wroteWarningStatus = false; - // TODO: Add executionId in place of `basicLogArguments` await ruleExecutionLogger.logStatusChange({ newStatus: RuleExecutionStatus['going to run'], }); @@ -151,7 +150,6 @@ export const createSecurityRuleTypeWrapper: CreateSecurityRuleTypeWrapper = const privileges = await checkPrivilegesFromEsClient(esClient, inputIndices); - // TODO: Add executionId in place of `basicLogArguments` wroteWarningStatus = await hasReadIndexPrivileges({ privileges, logger, @@ -169,7 +167,6 @@ export const createSecurityRuleTypeWrapper: CreateSecurityRuleTypeWrapper = include_unmapped: true, }) ); - // TODO: Add executionId in place of `basicLogArguments` wroteWarningStatus = await hasTimestampFields({ timestampField: hasTimestampOverride ? (timestampOverride as string) @@ -185,7 +182,6 @@ export const createSecurityRuleTypeWrapper: CreateSecurityRuleTypeWrapper = } catch (exc) { const errorMessage = buildRuleMessage(`Check privileges failed to execute ${exc}`); logger.warn(errorMessage); - // TODO: Add executionId in place of `basicLogArguments` await ruleExecutionLogger.logStatusChange({ newStatus: RuleExecutionStatus['partial failure'], message: errorMessage, @@ -212,7 +208,6 @@ export const createSecurityRuleTypeWrapper: CreateSecurityRuleTypeWrapper = ); logger.warn(gapMessage); hasError = true; - // TODO: Add executionId in place of `basicLogArguments` await ruleExecutionLogger.logStatusChange({ newStatus: RuleExecutionStatus.failed, message: gapMessage, @@ -294,7 +289,6 @@ export const createSecurityRuleTypeWrapper: CreateSecurityRuleTypeWrapper = if (result.warningMessages.length) { const warningMessage = buildRuleMessage(truncateList(result.warningMessages).join()); - // TODO: Add executionId in place of `basicLogArguments` await ruleExecutionLogger.logStatusChange({ newStatus: RuleExecutionStatus['partial failure'], message: warningMessage, @@ -354,7 +348,6 @@ export const createSecurityRuleTypeWrapper: CreateSecurityRuleTypeWrapper = ); if (!hasError && !wroteWarningStatus && !result.warning) { - // TODO: Add executionId in place of `basicLogArguments` await ruleExecutionLogger.logStatusChange({ newStatus: RuleExecutionStatus.succeeded, message: 'succeeded', @@ -397,7 +390,6 @@ export const createSecurityRuleTypeWrapper: CreateSecurityRuleTypeWrapper = truncateList(result.errors).join() ); logger.error(errorMessage); - // TODO: Add executionId in place of `basicLogArguments` await ruleExecutionLogger.logStatusChange({ newStatus: RuleExecutionStatus.failed, message: errorMessage, @@ -433,7 +425,6 @@ export const createSecurityRuleTypeWrapper: CreateSecurityRuleTypeWrapper = ); logger.error(message); - // TODO: Add executionId in place of `basicLogArguments` await ruleExecutionLogger.logStatusChange({ newStatus: RuleExecutionStatus.failed, message, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.test.ts index 1ef4fbc167642..cae1019ae3f80 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.test.ts @@ -663,7 +663,6 @@ describe('utils', () => { }, }, }; - // TODO: Add executionId to mock const ruleExecutionLogger = ruleExecutionLogMock.logger.create(); mockLogger.warn.mockClear(); @@ -715,7 +714,6 @@ describe('utils', () => { }, }; - // TODO: Add executionId to mock '7a7065d7-b33f-4aae-8d20-c93613dec9fb' const ruleExecutionLogger = ruleExecutionLogMock.logger.create(); mockLogger.warn.mockClear(); @@ -752,7 +750,6 @@ describe('utils', () => { }, }; - // TODO: Add executionId to mock '7a7065d7-b33f-4aae-8d20-c93613dec9fb' const ruleExecutionLogger = ruleExecutionLogMock.logger.create({ ruleName: 'Endpoint Security', }); @@ -792,7 +789,6 @@ describe('utils', () => { }; // SUT uses rule execution logger's context to check the rule name - // TODO: Add executionId to mock '7a7065d7-b33f-4aae-8d20-c93613dec9fb' const ruleExecutionLogger = ruleExecutionLogMock.logger.create({ ruleName: 'NOT Endpoint Security', }); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.ts index a502cc8f0b7d2..21f7f90a95de9 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.ts @@ -85,7 +85,6 @@ export const shorthandMap = { }, }; -// TODO: Add executionId to IRuleExecutionLogger export const hasReadIndexPrivileges = async (args: { privileges: Privilege; logger: Logger; @@ -107,7 +106,6 @@ export const hasReadIndexPrivileges = async (args: { indexesWithNoReadPrivileges )}`; logger.warn(buildRuleMessage(errorString)); - // TODO: Add executionId await ruleExecutionLogger.logStatusChange({ newStatus: RuleExecutionStatus['partial failure'], message: errorString, @@ -117,7 +115,6 @@ export const hasReadIndexPrivileges = async (args: { return false; }; -// TODO: Add executionId to IRuleExecutionLogger export const hasTimestampFields = async (args: { timestampField: string; // any is derived from here @@ -149,7 +146,6 @@ export const hasTimestampFields = async (args: { : '' }`; logger.warn(buildRuleMessage(errorString.trimEnd())); - // TODO: Add executionId await ruleExecutionLogger.logStatusChange({ newStatus: RuleExecutionStatus['partial failure'], message: errorString.trimEnd(), @@ -174,7 +170,6 @@ export const hasTimestampFields = async (args: { )}`; logger.warn(buildRuleMessage(errorString)); - // TODO: Add executionId await ruleExecutionLogger.logStatusChange({ newStatus: RuleExecutionStatus['partial failure'], message: errorString, From a15d328f3a3da7e2a0d9cfef8408b725a243616b Mon Sep 17 00:00:00 2001 From: Garrett Spong Date: Thu, 20 Jan 2022 16:52:45 -0700 Subject: [PATCH 20/20] Adds test coverage to ensure each execution has a different id genereated --- .../spaces_only/tests/alerting/event_log_alerts.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/event_log_alerts.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/event_log_alerts.ts index 71cdf78bbde2e..6fa3eb1a43b62 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/event_log_alerts.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/event_log_alerts.ts @@ -71,8 +71,12 @@ export default function eventLogAlertTests({ getService }: FtrProviderContext) { // Verify unique executionId generated per `action:execute` grouping const eventExecutionIdSet = new Set(); + const totalUniqueExecutionIds = new Set(); + let totalExecutionEventCount = 0; events.forEach((event) => { + totalUniqueExecutionIds.add(event?.kibana?.alert?.rule?.execution?.uuid); if (event?.event?.action === 'execute') { + totalExecutionEventCount += 1; eventExecutionIdSet.add(event?.kibana?.alert?.rule?.execution?.uuid); expect(eventExecutionIdSet.size).to.equal(1); eventExecutionIdSet.clear(); @@ -81,6 +85,9 @@ export default function eventLogAlertTests({ getService }: FtrProviderContext) { } }); + // Ensure every execution actually had a unique id from the others + expect(totalUniqueExecutionIds.size).to.equal(totalExecutionEventCount); + const currentAlertSpan: { alertId?: string; start?: string;