diff --git a/packages/kbn-securitysolution-io-ts-alerting-types/src/actions/index.ts b/packages/kbn-securitysolution-io-ts-alerting-types/src/actions/index.ts index 2e0d814bf93c5..baa36d97682ba 100644 --- a/packages/kbn-securitysolution-io-ts-alerting-types/src/actions/index.ts +++ b/packages/kbn-securitysolution-io-ts-alerting-types/src/actions/index.ts @@ -5,6 +5,7 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ +import { NonEmptyString } from '@kbn/securitysolution-io-ts-types'; import * as t from 'io-ts'; import { saved_object_attributes } from '../saved_object_attributes'; @@ -18,6 +19,9 @@ export const RuleActionId = t.string; export type RuleActionTypeId = t.TypeOf; export const RuleActionTypeId = t.string; +export type RuleActionUuid = t.TypeOf; +export const RuleActionUuid = NonEmptyString; + /** * Params is an "object", since it is a type of RuleActionParams which is action templates. * @see x-pack/plugins/alerting/common/rule.ts @@ -27,12 +31,15 @@ export const RuleActionParams = saved_object_attributes; export type RuleAction = t.TypeOf; export const RuleAction = t.exact( - t.type({ - group: RuleActionGroup, - id: RuleActionId, - action_type_id: RuleActionTypeId, - params: RuleActionParams, - }) + t.intersection([ + t.type({ + group: RuleActionGroup, + id: RuleActionId, + action_type_id: RuleActionTypeId, + params: RuleActionParams, + }), + t.partial({ uuid: RuleActionUuid }), + ]) ); export type RuleActionArray = t.TypeOf; @@ -40,12 +47,15 @@ export const RuleActionArray = t.array(RuleAction); export type RuleActionCamel = t.TypeOf; export const RuleActionCamel = t.exact( - t.type({ - group: RuleActionGroup, - id: RuleActionId, - actionTypeId: RuleActionTypeId, - params: RuleActionParams, - }) + t.intersection([ + t.type({ + group: RuleActionGroup, + id: RuleActionId, + actionTypeId: RuleActionTypeId, + params: RuleActionParams, + }), + t.partial({ uuid: RuleActionUuid }), + ]) ); export type RuleActionArrayCamel = t.TypeOf; diff --git a/src/core/server/integration_tests/saved_objects/migrations/group2/check_registered_types.test.ts b/src/core/server/integration_tests/saved_objects/migrations/group2/check_registered_types.test.ts index 571c2fe18fd6a..7d9e4bae782e2 100644 --- a/src/core/server/integration_tests/saved_objects/migrations/group2/check_registered_types.test.ts +++ b/src/core/server/integration_tests/saved_objects/migrations/group2/check_registered_types.test.ts @@ -57,7 +57,7 @@ describe('checking migration metadata changes on all registered SO types', () => Object { "action": "6cfc277ed3211639e37546ac625f4a68f2494215", "action_task_params": "db2afea7d78e00e725486b791554d0d4e81956ef", - "alert": "f81ad957a7936522482e4539c7a96a963ebdbc3e", + "alert": "2568bf6d8ba0876441c61c9e58e08016c1dc1617", "api_key_pending_invalidation": "16e7bcf8e78764102d7f525542d5b616809a21ee", "apm-indices": "d19dd7fb51f2d2cbc1f8769481721e0953f9a6d2", "apm-server-schema": "1d42f17eff9ec6c16d3a9324d9539e2d123d0a9a", diff --git a/x-pack/plugins/alerting/common/rule.ts b/x-pack/plugins/alerting/common/rule.ts index 833d514df1f86..cc5d7fda4a8b6 100644 --- a/x-pack/plugins/alerting/common/rule.ts +++ b/x-pack/plugins/alerting/common/rule.ts @@ -77,6 +77,7 @@ export type RuleActionParams = SavedObjectAttributes; export type RuleActionParam = SavedObjectAttribute; export interface RuleAction { + uuid?: string; group: string; id: string; actionTypeId: string; diff --git a/x-pack/plugins/alerting/public/alert_api.test.ts b/x-pack/plugins/alerting/public/alert_api.test.ts index 2f09643e499e3..abbaa6a5049eb 100644 --- a/x-pack/plugins/alerting/public/alert_api.test.ts +++ b/x-pack/plugins/alerting/public/alert_api.test.ts @@ -109,6 +109,7 @@ describe('loadRule', () => { "params": Object { "message": "alert 37: {{context.message}}", }, + "uuid": "123-456", }, ], "alertTypeId": ".index-threshold", @@ -278,6 +279,7 @@ function getApiRule() { }, group: 'threshold met', id: '3619a0d0-582b-11ec-8995-2b1578a3bc5d', + uuid: '123-456', }, ], params: { x: 42 }, @@ -319,6 +321,7 @@ function getRule(): Rule<{ x: number }> { }, group: 'threshold met', id: '3619a0d0-582b-11ec-8995-2b1578a3bc5d', + uuid: '123-456', }, ], params: { x: 42 }, diff --git a/x-pack/plugins/alerting/public/lib/common_transformations.test.ts b/x-pack/plugins/alerting/public/lib/common_transformations.test.ts index cef3cf8804f40..ac57340f109b2 100644 --- a/x-pack/plugins/alerting/public/lib/common_transformations.test.ts +++ b/x-pack/plugins/alerting/public/lib/common_transformations.test.ts @@ -31,6 +31,7 @@ describe('common_transformations', () => { group: 'some group', id: 'some-connector-id', params: { foo: 'car', bar: [1, 2, 3] }, + uuid: '123-456', }, ], params: { bar: 'foo', numbers: { 1: [2, 3] } } as never, @@ -108,6 +109,7 @@ describe('common_transformations', () => { ], "foo": "car", }, + "uuid": "123-456", }, ], "alertTypeId": "some-rule-type", @@ -213,6 +215,7 @@ describe('common_transformations', () => { group: 'some group', id: 'some-connector-id', params: {}, + uuid: '123-456', }, ], params: {} as never, @@ -277,6 +280,7 @@ describe('common_transformations', () => { "group": "some group", "id": "some-connector-id", "params": Object {}, + "uuid": "123-456", }, ], "alertTypeId": "some-rule-type", diff --git a/x-pack/plugins/alerting/server/routes/bulk_edit_rules.test.ts b/x-pack/plugins/alerting/server/routes/bulk_edit_rules.test.ts index 0ff709c252f56..944b2db172c91 100644 --- a/x-pack/plugins/alerting/server/routes/bulk_edit_rules.test.ts +++ b/x-pack/plugins/alerting/server/routes/bulk_edit_rules.test.ts @@ -41,6 +41,7 @@ describe('bulkEditInternalRulesRoute', () => { params: { foo: true, }, + uuid: '123-456', }, ], consumer: 'bar', @@ -111,6 +112,7 @@ describe('bulkEditInternalRulesRoute', () => { params: { foo: true, }, + uuid: '123-456', }, ], }), diff --git a/x-pack/plugins/alerting/server/routes/bulk_edit_rules.ts b/x-pack/plugins/alerting/server/routes/bulk_edit_rules.ts index 6c3aba9f5ef43..fa30b0ff8d2ed 100644 --- a/x-pack/plugins/alerting/server/routes/bulk_edit_rules.ts +++ b/x-pack/plugins/alerting/server/routes/bulk_edit_rules.ts @@ -18,6 +18,7 @@ const ruleActionSchema = schema.object({ group: schema.string(), id: schema.string(), params: schema.recordOf(schema.string(), schema.any(), { defaultValue: {} }), + uuid: schema.maybe(schema.string()), }); const operationsSchema = schema.arrayOf( diff --git a/x-pack/plugins/alerting/server/routes/clone_rule.test.ts b/x-pack/plugins/alerting/server/routes/clone_rule.test.ts index 7b89f217f9c8f..6c79ca7680940 100644 --- a/x-pack/plugins/alerting/server/routes/clone_rule.test.ts +++ b/x-pack/plugins/alerting/server/routes/clone_rule.test.ts @@ -48,6 +48,7 @@ describe('cloneRuleRoute', () => { params: { foo: true, }, + uuid: '123-456', }, ], enabled: true, @@ -97,6 +98,7 @@ describe('cloneRuleRoute', () => { { ...ruleToClone.actions[0], connector_type_id: 'test', + uuid: '123-456', }, ], }; diff --git a/x-pack/plugins/alerting/server/routes/create_rule.test.ts b/x-pack/plugins/alerting/server/routes/create_rule.test.ts index cbb7965cab081..0d8caff92202a 100644 --- a/x-pack/plugins/alerting/server/routes/create_rule.test.ts +++ b/x-pack/plugins/alerting/server/routes/create_rule.test.ts @@ -51,6 +51,7 @@ describe('createRuleRoute', () => { params: { foo: true, }, + uuid: '123-456', }, ], enabled: true, @@ -100,6 +101,7 @@ describe('createRuleRoute', () => { { ...ruleToCreate.actions[0], connector_type_id: 'test', + uuid: '123-456', }, ], }; diff --git a/x-pack/plugins/alerting/server/routes/get_rule.test.ts b/x-pack/plugins/alerting/server/routes/get_rule.test.ts index 065cd567f1f69..81b0ed5a6032a 100644 --- a/x-pack/plugins/alerting/server/routes/get_rule.test.ts +++ b/x-pack/plugins/alerting/server/routes/get_rule.test.ts @@ -44,6 +44,7 @@ describe('getRuleRoute', () => { params: { foo: true, }, + uuid: '123-456', }, ], consumer: 'bar', @@ -85,6 +86,7 @@ describe('getRuleRoute', () => { id: mockedAlert.actions[0].id, params: mockedAlert.actions[0].params, connector_type_id: mockedAlert.actions[0].actionTypeId, + uuid: mockedAlert.actions[0].uuid, }, ], }; diff --git a/x-pack/plugins/alerting/server/routes/get_rule.ts b/x-pack/plugins/alerting/server/routes/get_rule.ts index 6e7faac3131ab..06bb7716f7f66 100644 --- a/x-pack/plugins/alerting/server/routes/get_rule.ts +++ b/x-pack/plugins/alerting/server/routes/get_rule.ts @@ -60,7 +60,7 @@ const rewriteBodyRes: RewriteResponseCase> = ({ last_execution_date: executionStatus.lastExecutionDate, last_duration: executionStatus.lastDuration, }, - actions: actions.map(({ group, id, actionTypeId, params, frequency }) => ({ + actions: actions.map(({ group, id, actionTypeId, params, frequency, uuid }) => ({ group, id, params, @@ -72,6 +72,7 @@ const rewriteBodyRes: RewriteResponseCase> = ({ throttle: frequency.throttle, } : undefined, + ...(uuid && { uuid }), })), ...(lastRun ? { last_run: rewriteRuleLastRun(lastRun) } : {}), ...(nextRun ? { next_run: nextRun } : {}), diff --git a/x-pack/plugins/alerting/server/routes/lib/actions_schema.ts b/x-pack/plugins/alerting/server/routes/lib/actions_schema.ts index d89873a48c2ea..76c09e093543f 100644 --- a/x-pack/plugins/alerting/server/routes/lib/actions_schema.ts +++ b/x-pack/plugins/alerting/server/routes/lib/actions_schema.ts @@ -24,6 +24,7 @@ export const actionsSchema = schema.arrayOf( throttle: schema.nullable(schema.string({ validate: validateDurationSchema })), }) ), + uuid: schema.maybe(schema.string()), }), { defaultValue: [] } ); diff --git a/x-pack/plugins/alerting/server/routes/lib/rewrite_rule.ts b/x-pack/plugins/alerting/server/routes/lib/rewrite_rule.ts index bbcb489a9597e..eef33bb793d4a 100644 --- a/x-pack/plugins/alerting/server/routes/lib/rewrite_rule.ts +++ b/x-pack/plugins/alerting/server/routes/lib/rewrite_rule.ts @@ -57,7 +57,7 @@ export const rewriteRule = ({ last_execution_date: executionStatus.lastExecutionDate, last_duration: executionStatus.lastDuration, }, - actions: actions.map(({ group, id, actionTypeId, params, frequency }) => ({ + actions: actions.map(({ group, id, actionTypeId, params, frequency, uuid }) => ({ group, id, params, @@ -71,6 +71,7 @@ export const rewriteRule = ({ }, } : {}), + ...(uuid && { uuid }), })), ...(lastRun ? { last_run: rewriteRuleLastRun(lastRun) } : {}), ...(nextRun ? { next_run: nextRun } : {}), diff --git a/x-pack/plugins/alerting/server/routes/resolve_rule.test.ts b/x-pack/plugins/alerting/server/routes/resolve_rule.test.ts index 656874b5cf332..dfac49fc04a67 100644 --- a/x-pack/plugins/alerting/server/routes/resolve_rule.test.ts +++ b/x-pack/plugins/alerting/server/routes/resolve_rule.test.ts @@ -44,6 +44,7 @@ describe('resolveRuleRoute', () => { params: { foo: true, }, + uuid: '123-456', }, ], consumer: 'bar', @@ -97,6 +98,7 @@ describe('resolveRuleRoute', () => { id: mockedRule.actions[0].id, params: mockedRule.actions[0].params, connector_type_id: mockedRule.actions[0].actionTypeId, + uuid: mockedRule.actions[0].uuid, }, ], outcome: 'aliasMatch', diff --git a/x-pack/plugins/alerting/server/routes/update_rule.test.ts b/x-pack/plugins/alerting/server/routes/update_rule.test.ts index 8c335a9bf9864..617ea3d8fe6e0 100644 --- a/x-pack/plugins/alerting/server/routes/update_rule.test.ts +++ b/x-pack/plugins/alerting/server/routes/update_rule.test.ts @@ -42,6 +42,7 @@ describe('updateRuleRoute', () => { updatedAt: new Date(), actions: [ { + uuid: '1234-5678', group: 'default', id: '2', actionTypeId: 'test', @@ -58,6 +59,7 @@ describe('updateRuleRoute', () => { notify_when: mockedAlert.notifyWhen, actions: [ { + uuid: '1234-5678', group: mockedAlert.actions[0].group, id: mockedAlert.actions[0].id, params: mockedAlert.actions[0].params, @@ -114,6 +116,7 @@ describe('updateRuleRoute', () => { "params": Object { "baz": true, }, + "uuid": "1234-5678", }, ], "name": "abc", diff --git a/x-pack/plugins/alerting/server/rules_client/lib/add_uuid.ts b/x-pack/plugins/alerting/server/rules_client/lib/add_uuid.ts new file mode 100644 index 0000000000000..be377467acbec --- /dev/null +++ b/x-pack/plugins/alerting/server/rules_client/lib/add_uuid.ts @@ -0,0 +1,16 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { v4 } from 'uuid'; +import { NormalizedAlertAction, NormalizedAlertActionWithUuid } from '..'; + +export function addUuid(actions: NormalizedAlertAction[] = []): NormalizedAlertActionWithUuid[] { + return actions.map((action) => ({ + ...action, + uuid: action.uuid || v4(), + })); +} diff --git a/x-pack/plugins/alerting/server/rules_client/lib/denormalize_actions.ts b/x-pack/plugins/alerting/server/rules_client/lib/denormalize_actions.ts index 0f7a164d2a741..045053b5d7524 100644 --- a/x-pack/plugins/alerting/server/rules_client/lib/denormalize_actions.ts +++ b/x-pack/plugins/alerting/server/rules_client/lib/denormalize_actions.ts @@ -8,12 +8,11 @@ import { SavedObjectReference } from '@kbn/core/server'; import { RawRule } from '../../types'; import { preconfiguredConnectorActionRefPrefix } from '../common/constants'; -import { RulesClientContext } from '../types'; -import { NormalizedAlertAction } from '../types'; +import { NormalizedAlertActionWithUuid, RulesClientContext } from '../types'; export async function denormalizeActions( context: RulesClientContext, - alertActions: NormalizedAlertAction[] + alertActions: NormalizedAlertActionWithUuid[] ): Promise<{ actions: RawRule['actions']; references: SavedObjectReference[] }> { const references: SavedObjectReference[] = []; const actions: RawRule['actions'] = []; diff --git a/x-pack/plugins/alerting/server/rules_client/lib/extract_references.ts b/x-pack/plugins/alerting/server/rules_client/lib/extract_references.ts index 58f6f6ab20dbc..a374d7957e392 100644 --- a/x-pack/plugins/alerting/server/rules_client/lib/extract_references.ts +++ b/x-pack/plugins/alerting/server/rules_client/lib/extract_references.ts @@ -8,7 +8,7 @@ import { SavedObjectReference } from '@kbn/core/server'; import { RawRule, RuleTypeParams } from '../../types'; import { UntypedNormalizedRuleType } from '../../rule_type_registry'; -import { NormalizedAlertAction } from '../types'; +import { NormalizedAlertActionWithUuid } from '../types'; import { extractedSavedObjectParamReferenceNamePrefix } from '../common/constants'; import { RulesClientContext } from '../types'; import { denormalizeActions } from './denormalize_actions'; @@ -19,7 +19,7 @@ export async function extractReferences< >( context: RulesClientContext, ruleType: UntypedNormalizedRuleType, - ruleActions: NormalizedAlertAction[], + ruleActions: NormalizedAlertActionWithUuid[], ruleParams: Params ): Promise<{ actions: RawRule['actions']; diff --git a/x-pack/plugins/alerting/server/rules_client/lib/index.ts b/x-pack/plugins/alerting/server/rules_client/lib/index.ts index 1f9534a5c6da2..26cf359d14f15 100644 --- a/x-pack/plugins/alerting/server/rules_client/lib/index.ts +++ b/x-pack/plugins/alerting/server/rules_client/lib/index.ts @@ -15,3 +15,4 @@ export { checkAuthorizationAndGetTotal } from './check_authorization_and_get_tot export { scheduleTask } from './schedule_task'; export { createNewAPIKeySet } from './create_new_api_key_set'; export { recoverRuleAlerts } from './recover_rule_alerts'; +export { addUuid } from './add_uuid'; diff --git a/x-pack/plugins/alerting/server/rules_client/lib/validate_actions.ts b/x-pack/plugins/alerting/server/rules_client/lib/validate_actions.ts index ea6145b8f6e99..0f039d0d95f9b 100644 --- a/x-pack/plugins/alerting/server/rules_client/lib/validate_actions.ts +++ b/x-pack/plugins/alerting/server/rules_client/lib/validate_actions.ts @@ -31,6 +31,15 @@ export async function validateActions( const errors = []; + const uniqueActions = new Set(actions.map((action) => action.uuid)); + if (uniqueActions.size < actions.length) { + errors.push( + i18n.translate('xpack.alerting.rulesClient.validateActions.hasDuplicatedUuid', { + defaultMessage: 'Actions have duplicated UUIDs', + }) + ); + } + // check for actions using connectors with missing secrets const actionsClient = await context.getActionsClient(); const actionIds = [...new Set(actions.map((action) => action.id))]; diff --git a/x-pack/plugins/alerting/server/rules_client/methods/bulk_edit.ts b/x-pack/plugins/alerting/server/rules_client/methods/bulk_edit.ts index 6f3c28437a48e..9bf0280e4314b 100644 --- a/x-pack/plugins/alerting/server/rules_client/methods/bulk_edit.ts +++ b/x-pack/plugins/alerting/server/rules_client/methods/bulk_edit.ts @@ -54,13 +54,14 @@ import { API_KEY_GENERATE_CONCURRENCY, } from '../common/constants'; import { getMappedParams } from '../common/mapped_params_utils'; -import { getAlertFromRaw, extractReferences, validateActions, updateMeta } from '../lib'; +import { getAlertFromRaw, extractReferences, validateActions, updateMeta, addUuid } from '../lib'; import { NormalizedAlertAction, BulkOperationError, RuleBulkOperationAggregation, RulesClientContext, CreateAPIKeyResult, + NormalizedAlertActionWithUuid, } from '../types'; export type BulkEditFields = keyof Pick< @@ -452,7 +453,7 @@ async function updateRuleAttributesAndParamsInMemory omit(action, 'frequency')); if (!attributes.notifyWhen) { diff --git a/x-pack/plugins/alerting/server/rules_client/methods/create.ts b/x-pack/plugins/alerting/server/rules_client/methods/create.ts index 09dc8f62494b8..48735c0327d04 100644 --- a/x-pack/plugins/alerting/server/rules_client/methods/create.ts +++ b/x-pack/plugins/alerting/server/rules_client/methods/create.ts @@ -11,16 +11,15 @@ import { AlertConsumers } from '@kbn/rule-data-utils'; import { SavedObjectsUtils } from '@kbn/core/server'; import { withSpan } from '@kbn/apm-utils'; import { parseDuration } from '../../../common/parse_duration'; -import { RawRule, SanitizedRule, RuleTypeParams, RuleAction, Rule } from '../../types'; +import { RawRule, SanitizedRule, RuleTypeParams, Rule } from '../../types'; import { WriteOperations, AlertingAuthorizationEntity } from '../../authorization'; import { validateRuleTypeParams, getRuleNotifyWhenType, getDefaultMonitoring } from '../../lib'; import { getRuleExecutionStatusPending } from '../../lib/rule_execution_status'; -import { createRuleSavedObject, extractReferences, validateActions } from '../lib'; +import { createRuleSavedObject, extractReferences, validateActions, addUuid } from '../lib'; import { generateAPIKeyName, getMappedParams, apiKeyAsAlertAttributes } from '../common'; import { ruleAuditEvent, RuleAuditAction } from '../common/audit_events'; -import { RulesClientContext } from '../types'; +import { NormalizedAlertAction, RulesClientContext } from '../types'; -type NormalizedAlertAction = Omit; interface SavedObjectOptions { id?: string; migrationVersion?: Record; @@ -51,8 +50,10 @@ export interface CreateOptions { export async function create( context: RulesClientContext, - { data, options, allowMissingConnectorSecrets }: CreateOptions + { data: initialData, options, allowMissingConnectorSecrets }: CreateOptions ): Promise> { + const data = { ...initialData, actions: addUuid(initialData.actions) }; + const id = options?.id || SavedObjectsUtils.generateId(); try { @@ -105,7 +106,6 @@ export async function create( } } - await validateActions(context, ruleType, data, allowMissingConnectorSecrets); await withSpan({ name: 'validateActions', type: 'rules' }, () => validateActions(context, ruleType, data, allowMissingConnectorSecrets) ); diff --git a/x-pack/plugins/alerting/server/rules_client/methods/update.ts b/x-pack/plugins/alerting/server/rules_client/methods/update.ts index 5e116f9f21b28..673f300a722c6 100644 --- a/x-pack/plugins/alerting/server/rules_client/methods/update.ts +++ b/x-pack/plugins/alerting/server/rules_client/methods/update.ts @@ -24,7 +24,13 @@ import { bulkMarkApiKeysForInvalidation } from '../../invalidate_pending_api_key import { ruleAuditEvent, RuleAuditAction } from '../common/audit_events'; import { getMappedParams } from '../common/mapped_params_utils'; import { NormalizedAlertAction, RulesClientContext } from '../types'; -import { validateActions, extractReferences, updateMeta, getPartialRuleFromRaw } from '../lib'; +import { + validateActions, + extractReferences, + updateMeta, + getPartialRuleFromRaw, + addUuid, +} from '../lib'; import { generateAPIKeyName, apiKeyAsAlertAttributes } from '../common'; export interface UpdateOptions { @@ -143,9 +149,11 @@ async function updateWithOCC( async function updateAlert( context: RulesClientContext, - { id, data, allowMissingConnectorSecrets }: UpdateOptions, + { id, data: initialData, allowMissingConnectorSecrets }: UpdateOptions, { attributes, version }: SavedObject ): Promise> { + const data = { ...initialData, actions: addUuid(initialData.actions) }; + const ruleType = context.ruleTypeRegistry.get(attributes.alertTypeId); // TODO https://github.com/elastic/kibana/issues/148414 diff --git a/x-pack/plugins/alerting/server/rules_client/tests/bulk_edit.test.ts b/x-pack/plugins/alerting/server/rules_client/tests/bulk_edit.test.ts index 9f302d178b394..9bcf957a467a6 100644 --- a/x-pack/plugins/alerting/server/rules_client/tests/bulk_edit.test.ts +++ b/x-pack/plugins/alerting/server/rules_client/tests/bulk_edit.test.ts @@ -20,6 +20,7 @@ import { ActionsAuthorization, ActionsClient } from '@kbn/actions-plugin/server' import { auditLoggerMock } from '@kbn/security-plugin/server/audit/mocks'; import { getBeforeSetup, setGlobalDate } from './lib'; import { bulkMarkApiKeysForInvalidation } from '../../invalidate_pending_api_keys/bulk_mark_api_keys_for_invalidation'; +import { NormalizedAlertAction } from '../types'; jest.mock('../../invalidate_pending_api_keys/bulk_mark_api_keys_for_invalidation', () => ({ bulkMarkApiKeysForInvalidation: jest.fn(), @@ -29,6 +30,11 @@ jest.mock('../../lib/snooze/is_snooze_active', () => ({ isSnoozeActive: jest.fn(), })); +jest.mock('uuid', () => { + let uuid = 100; + return { v4: () => `${uuid++}` }; +}); + const { isSnoozeActive } = jest.requireMock('../../lib/snooze/is_snooze_active'); const taskManager = taskManagerMock.createStart(); @@ -115,7 +121,29 @@ describe('bulkEdit()', () => { beforeEach(async () => { rulesClient = new RulesClient(rulesClientParams); + + actionsClient = (await rulesClientParams.getActionsClient()) as jest.Mocked; + actionsClient.getBulk.mockReset(); + actionsClient.getBulk.mockResolvedValue([ + { + id: '1', + actionTypeId: 'test', + config: { + from: 'me@me.com', + hasAuth: false, + host: 'hello', + port: 22, + secure: null, + service: null, + }, + isMissingSecrets: false, + name: 'email connector', + isPreconfigured: false, + isDeprecated: false, + }, + ]); rulesClientParams.getActionsClient.mockResolvedValue(actionsClient); + authorization.getFindAuthorizationFilter.mockResolvedValue({ ensureRuleTypeIsAuthorized() {}, }); @@ -426,6 +454,146 @@ describe('bulkEdit()', () => { }); }); + describe('actions operations', () => { + beforeEach(() => { + mockCreatePointInTimeFinderAsInternalUser({ + saved_objects: [existingDecryptedRule], + }); + }); + + test('should add uuid to new actions', async () => { + const existingAction = { + frequency: { + notifyWhen: 'onActiveAlert', + summary: false, + throttle: null, + }, + group: 'default', + id: '1', + params: {}, + uuid: '111', + }; + const newAction = { + frequency: { + notifyWhen: 'onActiveAlert', + summary: false, + throttle: null, + }, + group: 'default', + id: '2', + params: {}, + }; + const newAction2 = { + frequency: { + notifyWhen: 'onActiveAlert', + summary: false, + throttle: null, + }, + group: 'default', + id: '3', + params: {}, + }; + + unsecuredSavedObjectsClient.bulkCreate.mockResolvedValue({ + saved_objects: [ + { + ...existingRule, + attributes: { + ...existingRule.attributes, + actions: [ + { + ...existingAction, + actionRef: 'action_0', + }, + { + ...newAction, + actionRef: 'action_1', + uuid: '222', + }, + ], + }, + references: [ + { + name: 'action_0', + type: 'action', + id: '1', + }, + { + name: 'action_1', + type: 'action', + id: '2', + }, + ], + }, + ], + }); + + const result = await rulesClient.bulkEdit({ + filter: '', + operations: [ + { + field: 'actions', + operation: 'add', + value: [existingAction, newAction, newAction2] as NormalizedAlertAction[], + }, + ], + }); + + expect(unsecuredSavedObjectsClient.bulkCreate).toHaveBeenCalledWith( + [ + { + ...existingRule, + attributes: { + ...existingRule.attributes, + actions: [ + { + actionRef: 'action_0', + actionTypeId: 'test', + frequency: { notifyWhen: 'onActiveAlert', summary: false, throttle: null }, + group: 'default', + params: {}, + uuid: '111', + }, + { + actionRef: '', + actionTypeId: '', + frequency: { notifyWhen: 'onActiveAlert', summary: false, throttle: null }, + group: 'default', + params: {}, + uuid: '100', + }, + { + actionRef: '', + actionTypeId: '', + frequency: { notifyWhen: 'onActiveAlert', summary: false, throttle: null }, + group: 'default', + params: {}, + uuid: '101', + }, + ], + apiKey: null, + apiKeyOwner: null, + meta: { versionApiKeyLastmodified: 'v8.2.0' }, + name: 'my rule name', + enabled: false, + updatedAt: '2019-02-12T21:01:22.479Z', + updatedBy: 'elastic', + tags: ['foo'], + }, + references: [{ id: '1', name: 'action_0', type: 'action' }], + }, + ], + { overwrite: true } + ); + expect(result.rules[0]).toEqual({ + ...existingRule.attributes, + actions: [existingAction, { ...newAction, uuid: '222' }], + id: existingRule.id, + snoozeSchedule: [], + }); + }); + }); + describe('index pattern operations', () => { beforeEach(() => { mockCreatePointInTimeFinderAsInternalUser({ diff --git a/x-pack/plugins/alerting/server/rules_client/tests/create.test.ts b/x-pack/plugins/alerting/server/rules_client/tests/create.test.ts index dddfbe85f9ee3..84226a318f9c3 100644 --- a/x-pack/plugins/alerting/server/rules_client/tests/create.test.ts +++ b/x-pack/plugins/alerting/server/rules_client/tests/create.test.ts @@ -38,6 +38,11 @@ jest.mock('@kbn/core-saved-objects-utils-server', () => { }; }); +jest.mock('uuid', () => { + let uuid = 100; + return { v4: () => `${uuid++}` }; +}); + const taskManager = taskManagerMock.createStart(); const ruleTypeRegistry = ruleTypeRegistryMock.create(); const unsecuredSavedObjectsClient = savedObjectsClientMock.create(); @@ -406,6 +411,7 @@ describe('create()', () => { "params": Object { "foo": true, }, + "uuid": "102", }, ], "alertTypeId": "123", @@ -624,6 +630,7 @@ describe('create()', () => { "params": Object { "foo": true, }, + "uuid": "104", }, ], "alertTypeId": "123", @@ -1053,6 +1060,7 @@ describe('create()', () => { params: { foo: true, }, + uuid: '108', }, { group: 'default', @@ -1061,6 +1069,7 @@ describe('create()', () => { params: { foo: true, }, + uuid: '109', }, { group: 'default', @@ -1069,6 +1078,7 @@ describe('create()', () => { params: { foo: true, }, + uuid: '110', }, ], alertTypeId: '123', @@ -1272,7 +1282,13 @@ describe('create()', () => { 'alert', { actions: [ - { actionRef: 'action_0', actionTypeId: 'test', group: 'default', params: { foo: true } }, + { + actionRef: 'action_0', + actionTypeId: 'test', + group: 'default', + params: { foo: true }, + uuid: '112', + }, ], alertTypeId: '123', apiKey: null, @@ -1445,7 +1461,13 @@ describe('create()', () => { 'alert', { actions: [ - { actionRef: 'action_0', actionTypeId: 'test', group: 'default', params: { foo: true } }, + { + actionRef: 'action_0', + actionTypeId: 'test', + group: 'default', + params: { foo: true }, + uuid: '113', + }, ], alertTypeId: '123', apiKey: null, @@ -1612,6 +1634,7 @@ describe('create()', () => { group: 'default', actionTypeId: 'test', params: { foo: true }, + uuid: '115', }, ], alertTypeId: '123', @@ -1747,6 +1770,7 @@ describe('create()', () => { group: 'default', actionTypeId: 'test', params: { foo: true }, + uuid: '116', }, ], legacyId: null, @@ -1882,6 +1906,7 @@ describe('create()', () => { group: 'default', actionTypeId: 'test', params: { foo: true }, + uuid: '117', }, ], legacyId: null, @@ -2044,6 +2069,7 @@ describe('create()', () => { }, actionRef: 'action_0', actionTypeId: 'test', + uuid: '118', }, ], apiKeyOwner: null, @@ -2409,6 +2435,7 @@ describe('create()', () => { group: 'default', actionTypeId: 'test', params: { foo: true }, + uuid: '126', }, ], alertTypeId: '123', @@ -2513,6 +2540,7 @@ describe('create()', () => { group: 'default', actionTypeId: 'test', params: { foo: true }, + uuid: '127', }, ], legacyId: null, diff --git a/x-pack/plugins/alerting/server/rules_client/tests/update.test.ts b/x-pack/plugins/alerting/server/rules_client/tests/update.test.ts index 4d16f3e5d66a0..2e1be7076004a 100644 --- a/x-pack/plugins/alerting/server/rules_client/tests/update.test.ts +++ b/x-pack/plugins/alerting/server/rules_client/tests/update.test.ts @@ -37,6 +37,11 @@ jest.mock('../../invalidate_pending_api_keys/bulk_mark_api_keys_for_invalidation bulkMarkApiKeysForInvalidation: jest.fn(), })); +jest.mock('uuid', () => { + let uuid = 100; + return { v4: () => `${uuid++}` }; +}); + const bulkMarkApiKeysForInvalidationMock = bulkMarkApiKeysForInvalidation as jest.Mock; const taskManager = taskManagerMock.createStart(); const ruleTypeRegistry = ruleTypeRegistryMock.create(); @@ -350,6 +355,7 @@ describe('update()', () => { "params": Object { "foo": true, }, + "uuid": "100", }, Object { "actionRef": "action_1", @@ -358,6 +364,7 @@ describe('update()', () => { "params": Object { "foo": true, }, + "uuid": "101", }, Object { "actionRef": "action_2", @@ -366,6 +373,7 @@ describe('update()', () => { "params": Object { "foo": true, }, + "uuid": "102", }, ], "alertTypeId": "myType", @@ -585,6 +593,7 @@ describe('update()', () => { params: { foo: true, }, + uuid: '103', }, { group: 'default', @@ -593,6 +602,7 @@ describe('update()', () => { params: { foo: true, }, + uuid: '104', }, { group: 'custom', @@ -601,6 +611,7 @@ describe('update()', () => { params: { foo: true, }, + uuid: '105', }, ], alertTypeId: 'myType', @@ -779,7 +790,13 @@ describe('update()', () => { 'alert', { actions: [ - { actionRef: 'action_0', actionTypeId: 'test', group: 'default', params: { foo: true } }, + { + actionRef: 'action_0', + actionTypeId: 'test', + group: 'default', + params: { foo: true }, + uuid: '106', + }, ], alertTypeId: 'myType', apiKey: null, @@ -953,6 +970,7 @@ describe('update()', () => { "params": Object { "foo": true, }, + "uuid": "107", }, ], "alertTypeId": "myType", @@ -1101,6 +1119,7 @@ describe('update()', () => { "params": Object { "foo": true, }, + "uuid": "108", }, ], "alertTypeId": "myType", @@ -2113,6 +2132,7 @@ describe('update()', () => { params: { foo: true, }, + uuid: '144', }, ], alertTypeId: 'myType', @@ -2522,4 +2542,166 @@ describe('update()', () => { ); }); }); + + test('updates an action with uuid and adds uuid to an action without it', async () => { + actionsClient.getBulk.mockReset(); + actionsClient.getBulk.mockResolvedValue([ + { + id: '1', + actionTypeId: 'test', + config: { + from: 'me@me.com', + hasAuth: false, + host: 'hello', + port: 22, + secure: null, + service: null, + }, + isMissingSecrets: false, + name: 'email connector', + isPreconfigured: false, + isDeprecated: false, + }, + ]); + unsecuredSavedObjectsClient.create.mockResolvedValueOnce({ + id: '1', + type: 'alert', + attributes: { + enabled: true, + schedule: { interval: '1m' }, + params: { + bar: true, + }, + actions: [ + { + group: 'default', + actionRef: 'action_0', + actionTypeId: 'test', + params: { + foo: true, + }, + frequency: { + notifyWhen: 'onActiveAlert', + throttle: null, + summary: false, + }, + uuid: '123-456', + }, + { + group: 'default', + actionRef: 'action_1', + actionTypeId: 'test', + params: { + foo: true, + }, + frequency: { + notifyWhen: 'onActiveAlert', + throttle: null, + summary: false, + }, + uuid: '111-111', + }, + ], + scheduledTaskId: 'task-123', + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + }, + references: [ + { + name: 'action_0', + type: 'action', + id: '1', + }, + { + name: 'action_1', + type: 'action', + id: '2', + }, + ], + }); + await rulesClient.update({ + id: '1', + data: { + schedule: { interval: '1m' }, + name: 'abc', + tags: ['foo'], + params: { + bar: true, + risk_score: 40, + severity: 'low', + }, + actions: [ + { + group: 'default', + id: '1', + params: { + foo: true, + }, + frequency: { + notifyWhen: 'onActiveAlert', + throttle: null, + summary: false, + }, + uuid: '123-456', + }, + { + group: 'default', + id: '2', + params: { + foo: true, + }, + frequency: { + notifyWhen: 'onActiveAlert', + throttle: null, + summary: false, + }, + }, + ], + }, + }); + expect(unsecuredSavedObjectsClient.create).toHaveBeenCalledWith( + 'alert', + { + actions: [ + { + actionRef: 'action_0', + actionTypeId: 'test', + frequency: { notifyWhen: 'onActiveAlert', summary: false, throttle: null }, + group: 'default', + params: { foo: true }, + uuid: '123-456', + }, + { + actionRef: '', + actionTypeId: '', + frequency: { notifyWhen: 'onActiveAlert', summary: false, throttle: null }, + group: 'default', + params: { foo: true }, + uuid: '151', + }, + ], + alertTypeId: 'myType', + apiKey: null, + apiKeyOwner: null, + consumer: 'myApp', + enabled: true, + mapped_params: { risk_score: 40, severity: '20-low' }, + meta: { versionApiKeyLastmodified: 'v7.10.0' }, + name: 'abc', + notifyWhen: null, + params: { bar: true, risk_score: 40, severity: 'low' }, + schedule: { interval: '1m' }, + scheduledTaskId: 'task-123', + tags: ['foo'], + updatedAt: '2019-02-12T21:01:22.479Z', + updatedBy: 'elastic', + }, + { + id: '1', + overwrite: true, + references: [{ id: '1', name: 'action_0', type: 'action' }], + version: '123', + } + ); + }); }); diff --git a/x-pack/plugins/alerting/server/rules_client/types.ts b/x-pack/plugins/alerting/server/rules_client/types.ts index ff59b5527f902..c6243d6fad5e2 100644 --- a/x-pack/plugins/alerting/server/rules_client/types.ts +++ b/x-pack/plugins/alerting/server/rules_client/types.ts @@ -73,6 +73,10 @@ export interface RulesClientContext { export type NormalizedAlertAction = Omit; +export type NormalizedAlertActionWithUuid = Omit & { + uuid: string; +}; + export interface RegistryAlertTypeWithAuth extends RegistryRuleType { authorizedConsumers: string[]; } diff --git a/x-pack/plugins/alerting/server/saved_objects/mappings.ts b/x-pack/plugins/alerting/server/saved_objects/mappings.ts index be70255f18840..f065c5e069ce1 100644 --- a/x-pack/plugins/alerting/server/saved_objects/mappings.ts +++ b/x-pack/plugins/alerting/server/saved_objects/mappings.ts @@ -41,6 +41,7 @@ export const alertMappings: SavedObjectsTypeMappingDefinition = { type: 'keyword', }, actions: { + dynamic: false, type: 'nested', properties: { group: { diff --git a/x-pack/plugins/alerting/server/saved_objects/migrations/8.7/index.ts b/x-pack/plugins/alerting/server/saved_objects/migrations/8.7/index.ts index 1b49f606cb6b5..831e4eff10d43 100644 --- a/x-pack/plugins/alerting/server/saved_objects/migrations/8.7/index.ts +++ b/x-pack/plugins/alerting/server/saved_objects/migrations/8.7/index.ts @@ -7,6 +7,7 @@ import { SavedObjectUnsanitizedDoc } from '@kbn/core-saved-objects-server'; import { EncryptedSavedObjectsPluginSetup } from '@kbn/encrypted-saved-objects-plugin/server'; +import { v4 as uuidv4 } from 'uuid'; import { extractedSavedObjectParamReferenceNamePrefix } from '../../../rules_client/common/constants'; import { createEsoMigration, @@ -37,6 +38,27 @@ function addGroupByToEsQueryRule( return doc; } +function addActionUuid( + doc: SavedObjectUnsanitizedDoc +): SavedObjectUnsanitizedDoc { + const { + attributes: { actions }, + } = doc; + + return { + ...doc, + attributes: { + ...doc.attributes, + actions: actions + ? actions.map((action) => ({ + ...action, + uuid: uuidv4(), + })) + : [], + }, + }; +} + function addLogViewRefToLogThresholdRule( doc: SavedObjectUnsanitizedDoc ): SavedObjectUnsanitizedDoc { @@ -94,5 +116,10 @@ export const getMigrations870 = (encryptedSavedObjects: EncryptedSavedObjectsPlu createEsoMigration( encryptedSavedObjects, (doc: SavedObjectUnsanitizedDoc): doc is SavedObjectUnsanitizedDoc => true, - pipeMigrations(addGroupByToEsQueryRule, addLogViewRefToLogThresholdRule, addOutcomeOrder) + pipeMigrations( + addGroupByToEsQueryRule, + addLogViewRefToLogThresholdRule, + addOutcomeOrder, + addActionUuid + ) ); diff --git a/x-pack/plugins/alerting/server/saved_objects/migrations/index.test.ts b/x-pack/plugins/alerting/server/saved_objects/migrations/index.test.ts index 7ecf7596259fa..940b926f5e326 100644 --- a/x-pack/plugins/alerting/server/saved_objects/migrations/index.test.ts +++ b/x-pack/plugins/alerting/server/saved_objects/migrations/index.test.ts @@ -8,7 +8,7 @@ import sinon from 'sinon'; import { v4 as uuidv4 } from 'uuid'; import { getMigrations } from '.'; -import { RawRule } from '../../types'; +import { RawRule, RawRuleAction } from '../../types'; import { SavedObjectMigrationContext, SavedObjectUnsanitizedDoc } from '@kbn/core/server'; import { encryptedSavedObjectsMock } from '@kbn/encrypted-saved-objects-plugin/server/mocks'; import { migrationMocks } from '@kbn/core/server/mocks'; @@ -2628,6 +2628,28 @@ describe('successful migrations', () => { outcomeOrder: 0, }); }); + + test('adds uuid to rule actions', () => { + const migration870 = getMigrations(encryptedSavedObjectsSetup, {}, isPreconfigured)['8.7.0']; + const rule = getMockData( + { + params: { foo: true }, + alertTypeId: '.not-es-query', + }, + true + ); + const migratedAlert870 = migration870(rule, migrationContext); + + expect(migratedAlert870.attributes.actions).toEqual([ + { + group: 'default', + actionRef: '1', + actionTypeId: '1', + params: { foo: true }, + uuid: expect.stringMatching(/.*\S.*/), // non-empty string + }, + ]); + }); }); describe('Metrics Inventory Threshold rule', () => { @@ -2974,7 +2996,7 @@ function getMockData( params: { foo: true, }, - }, + } as unknown as RawRuleAction, ], ...overwrites, }, diff --git a/x-pack/plugins/alerting/server/task_runner/fixtures.ts b/x-pack/plugins/alerting/server/task_runner/fixtures.ts index 7acb36c34bd9c..920afcfbe3035 100644 --- a/x-pack/plugins/alerting/server/task_runner/fixtures.ts +++ b/x-pack/plugins/alerting/server/task_runner/fixtures.ts @@ -50,6 +50,7 @@ export const RULE_ACTIONS = [ params: { foo: true, }, + uuid: '111-111', }, { actionTypeId: 'action', @@ -58,6 +59,7 @@ export const RULE_ACTIONS = [ params: { isResolved: true, }, + uuid: '222-222', }, ]; @@ -190,6 +192,7 @@ export const mockedRuleTypeSavedObject: Rule = { params: { foo: true, }, + uuid: '111-111', }, { group: RecoveredActionGroup.id, @@ -198,6 +201,7 @@ export const mockedRuleTypeSavedObject: Rule = { params: { isResolved: true, }, + uuid: '222-222', }, ], executionStatus: { diff --git a/x-pack/plugins/alerting/server/task_runner/rule_action_helper.test.ts b/x-pack/plugins/alerting/server/task_runner/rule_action_helper.test.ts index a2488b6a6cd01..c69d394d258ec 100644 --- a/x-pack/plugins/alerting/server/task_runner/rule_action_helper.test.ts +++ b/x-pack/plugins/alerting/server/task_runner/rule_action_helper.test.ts @@ -20,6 +20,7 @@ const mockOldAction: RuleAction = { group: 'default', actionTypeId: 'slack', params: {}, + uuid: '123-456', }; const mockAction: RuleAction = { @@ -32,6 +33,7 @@ const mockAction: RuleAction = { notifyWhen: 'onActiveAlert', throttle: null, }, + uuid: '123-456', }; const mockSummaryAction: RuleAction = { 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 8b7284bb8ffd4..779b467160b2d 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 @@ -1284,6 +1284,7 @@ describe('Task Runner', () => { params: { foo: true, }, + uuid: '111-111', }, { group: recoveryActionGroup.id, @@ -1292,6 +1293,7 @@ describe('Task Runner', () => { params: { isResolved: true, }, + uuid: '222-222', }, ], }); @@ -1388,6 +1390,7 @@ describe('Task Runner', () => { params: { foo: true, }, + uuid: '111-111', }, ], }); @@ -1464,6 +1467,7 @@ describe('Task Runner', () => { params: { foo: true, }, + uuid: '111-111', }, ], }); diff --git a/x-pack/plugins/alerting/server/types.ts b/x-pack/plugins/alerting/server/types.ts index 1ecff391be4af..e319f315440af 100644 --- a/x-pack/plugins/alerting/server/types.ts +++ b/x-pack/plugins/alerting/server/types.ts @@ -235,6 +235,7 @@ export type UntypedRuleType = RuleType< >; export interface RawRuleAction extends SavedObjectAttributes { + uuid: string; group: string; actionRef: string; actionTypeId: string; diff --git a/x-pack/plugins/security_solution/common/detection_engine/transform_actions.test.ts b/x-pack/plugins/security_solution/common/detection_engine/transform_actions.test.ts index 6e7807247e57c..a8901fee7a3de 100644 --- a/x-pack/plugins/security_solution/common/detection_engine/transform_actions.test.ts +++ b/x-pack/plugins/security_solution/common/detection_engine/transform_actions.test.ts @@ -36,6 +36,7 @@ describe('transform_actions', () => { group: 'group', actionTypeId: 'actionTypeId', params: {}, + uuid: '111', }; const ruleAction = transformAlertToRuleAction(alertAction); expect(ruleAction).toEqual({ @@ -43,6 +44,7 @@ describe('transform_actions', () => { group: alertAction.group, action_type_id: alertAction.actionTypeId, params: alertAction.params, + uuid: '111', }); }); test('it should transform ResponseAction[] to RuleResponseAction[]', () => { diff --git a/x-pack/plugins/security_solution/common/detection_engine/transform_actions.ts b/x-pack/plugins/security_solution/common/detection_engine/transform_actions.ts index da720b578bc65..354713e30d7c8 100644 --- a/x-pack/plugins/security_solution/common/detection_engine/transform_actions.ts +++ b/x-pack/plugins/security_solution/common/detection_engine/transform_actions.ts @@ -12,13 +12,15 @@ import type { RuleAlertAction } from './types'; export const transformRuleToAlertAction = ({ group, id, - action_type_id, // eslint-disable-line @typescript-eslint/naming-convention + action_type_id: actionTypeId, params, + uuid, }: RuleAlertAction): RuleAction => ({ group, id, params, - actionTypeId: action_type_id, + actionTypeId, + ...(uuid && { uuid }), }); export const transformAlertToRuleAction = ({ @@ -26,11 +28,13 @@ export const transformAlertToRuleAction = ({ id, actionTypeId, params, + uuid, }: RuleAction): RuleAlertAction => ({ group, id, params, action_type_id: actionTypeId, + ...(uuid && { uuid }), }); export const transformRuleToAlertResponseAction = ({ diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/clone.test.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/clone.test.ts index 9efd9b12f4b14..54e987d18c917 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/clone.test.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/clone.test.ts @@ -43,6 +43,7 @@ describe('cloneRule', () => { summary: false, }, connector_type_id: '.server-log', + uuid: '123456', }, ], scheduled_task_id: '1', @@ -74,6 +75,7 @@ describe('cloneRule', () => { "level": "info", "message": "alert ", }, + "uuid": "123456", }, ], "activeSnoozes": undefined, diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/common_transformations.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/common_transformations.ts index f8a9639bb30bd..97b17f460f3d4 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/common_transformations.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/common_transformations.ts @@ -9,6 +9,7 @@ import { AsApiContract, RewriteRequestCase } from '@kbn/actions-plugin/common'; import { Rule, RuleAction, ResolvedRule, RuleLastRun } from '../../../types'; const transformAction: RewriteRequestCase = ({ + uuid, group, id, connector_type_id: actionTypeId, @@ -28,6 +29,7 @@ const transformAction: RewriteRequestCase = ({ }, } : {}), + ...(uuid && { uuid }), }); const transformExecutionStatus: RewriteRequestCase = ({ diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/update.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/update.ts index aefaf9019a967..51c6febf6c557 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/update.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/update.ts @@ -17,7 +17,7 @@ type RuleUpdatesBody = Pick< >; const rewriteBodyRequest: RewriteResponseCase = ({ actions, ...res }): any => ({ ...res, - actions: actions.map(({ group, id, params, frequency }) => ({ + actions: actions.map(({ group, id, params, frequency, uuid }) => ({ group, id, params, @@ -26,6 +26,7 @@ const rewriteBodyRequest: RewriteResponseCase = ({ actions, ... throttle: frequency!.throttle, summary: frequency!.summary, }, + ...(uuid && { uuid }), })), }); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/value_validators.test.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/value_validators.test.ts index ecd377f6976f9..a0069bcdc328d 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/value_validators.test.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/value_validators.test.ts @@ -345,6 +345,7 @@ describe('getRuleWithInvalidatedFields', () => { field: {}, }, }, + uuid: '123-456', }, ], tags: [], @@ -390,6 +391,7 @@ describe('getRuleWithInvalidatedFields', () => { field: {}, }, }, + uuid: '111-111', }, { actionTypeId: 'test', @@ -402,6 +404,7 @@ describe('getRuleWithInvalidatedFields', () => { }, }, }, + uuid: '222-222', }, ], tags: [], diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/connectors_selection.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/connectors_selection.test.tsx index ff31b977612f0..97742e22a9ae4 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/connectors_selection.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/connectors_selection.test.tsx @@ -45,6 +45,7 @@ describe('connectors_selection', () => { group: 'group', class: 'test class', }, + uuid: '123-456', }; const actionTypeIndex: Record = { diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_form/rule_reducer.test.ts b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_form/rule_reducer.test.ts index 9b066bb1060a0..996676b73d59e 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_form/rule_reducer.test.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_form/rule_reducer.test.ts @@ -111,6 +111,7 @@ describe('rule reducer', () => { actionTypeId: 'testId', group: 'Rule', params: {}, + uuid: '123-456', }); const updatedRule = ruleReducer( { rule: initialRule }, @@ -151,6 +152,7 @@ describe('rule reducer', () => { params: { testActionParam: 'some value', }, + uuid: '123-456', }); const updatedRule = ruleReducer( { rule: initialRule }, @@ -172,6 +174,7 @@ describe('rule reducer', () => { actionTypeId: 'testId', group: 'Rule', params: {}, + uuid: '123-456', }); const updatedRule = ruleReducer( { rule: initialRule }, @@ -193,6 +196,7 @@ describe('rule reducer', () => { actionTypeId: 'testId', group: 'Rule', params: {}, + uuid: '123-456', }); const updatedRule = ruleReducer( { rule: initialRule }, diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/create.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/create.ts index 066ae0303d2b5..6fa2b71176788 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/create.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/create.ts @@ -106,6 +106,7 @@ export default function createAlertTests({ getService }: FtrProviderContext) { connector_type_id: createdAction.connector_type_id, group: 'default', params: {}, + uuid: response.body.actions[0].uuid, }, ], enabled: true, diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/find.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/find.ts index d35314176d657..a75751d6df66f 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/find.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/find.ts @@ -321,6 +321,7 @@ const findTestUtils = ( group: 'default', connector_type_id: 'test.noop', params: {}, + uuid: createdAlert.actions[0].uuid, }, ], params: {}, diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/alerts.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/alerts.ts index 60e6daee3d51d..e97c0df7bf1df 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/alerts.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/alerts.ts @@ -74,12 +74,13 @@ export default function alertTests({ getService }: FtrProviderContext) { updatedBy: user.fullName, actions: actions.map((action: any) => { /* eslint-disable @typescript-eslint/naming-convention */ - const { connector_type_id, group, id, params } = action; + const { connector_type_id, group, id, params, uuid } = action; return { actionTypeId: connector_type_id, group, id, params, + uuid, }; }), producer: 'alertsFixture', @@ -421,12 +422,13 @@ instanceStateValue: true updatedBy: Superuser.fullName, actions: response2.body.actions.map((action: any) => { /* eslint-disable @typescript-eslint/naming-convention */ - const { connector_type_id, group, id, params } = action; + const { connector_type_id, group, id, params, uuid } = action; return { actionTypeId: connector_type_id, group, id, params, + uuid, }; }), producer: 'alertsFixture', diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/update.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/update.ts index 25cc8384f14e4..a5254c6032109 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/update.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/update.ts @@ -127,6 +127,7 @@ export default function createUpdateTests({ getService }: FtrProviderContext) { connector_type_id: 'test.noop', group: 'default', params: {}, + uuid: response.body.actions[0].uuid, }, ], scheduled_task_id: createdAlert.scheduled_task_id, diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/alerting/bulk_edit.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/alerting/bulk_edit.ts index df53acd6acdbd..515b5662246b7 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/alerting/bulk_edit.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/alerting/bulk_edit.ts @@ -116,6 +116,7 @@ export default function createUpdateTests({ getService }: FtrProviderContext) { group: 'default', params: {}, connector_type_id: 'test.noop', + uuid: response.body.rules[0].actions[0].uuid, }, ]); expect(response.statusCode).to.eql(200); diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/alerting/clone.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/alerting/clone.ts index e473394f26b8e..8bb9d14572725 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/alerting/clone.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/alerting/clone.ts @@ -145,6 +145,7 @@ export default function createAlertTests({ getService }: FtrProviderContext) { connector_type_id: response.body.actions[0].connector_type_id, group: 'default', params: {}, + uuid: response.body.actions[0].uuid, }, ], enabled: true, diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/alerts_base.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/alerts_base.ts index 8e0d7b27cfa4d..f50e0be3c03c5 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/alerts_base.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/alerts_base.ts @@ -113,12 +113,13 @@ export function alertTests({ getService }: FtrProviderContext, space: Space) { updatedBy: null, actions: response.body.actions.map((action: any) => { /* eslint-disable @typescript-eslint/naming-convention */ - const { connector_type_id, group, id, params } = action; + const { connector_type_id, group, id, params, uuid } = action; return { actionTypeId: connector_type_id, group, id, params, + uuid, }; }), producer: 'alertsFixture', diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/create.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/create.ts index 534df486281be..ccf6d89cc602e 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/create.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/create.ts @@ -76,6 +76,7 @@ export default function createAlertTests({ getService }: FtrProviderContext) { connector_type_id: createdAction.connector_type_id, group: 'default', params: {}, + uuid: response.body.actions[0].uuid, }, ], enabled: true, @@ -169,6 +170,7 @@ export default function createAlertTests({ getService }: FtrProviderContext) { connector_type_id: createdAction.connector_type_id, group: 'default', params: {}, + uuid: response.body.actions[0].uuid, }, { id: 'my-slack1', @@ -177,6 +179,7 @@ export default function createAlertTests({ getService }: FtrProviderContext) { params: { message: 'something important happened!', }, + uuid: response.body.actions[1].uuid, }, ], enabled: true, @@ -219,6 +222,7 @@ export default function createAlertTests({ getService }: FtrProviderContext) { actionTypeId: 'test.noop', group: 'default', params: {}, + uuid: rawActions[0].uuid, }, { actionRef: 'preconfigured:my-slack1', @@ -227,6 +231,7 @@ export default function createAlertTests({ getService }: FtrProviderContext) { params: { message: 'something important happened!', }, + uuid: rawActions[1].uuid, }, ]); @@ -479,6 +484,7 @@ export default function createAlertTests({ getService }: FtrProviderContext) { actionTypeId: createdAction.connector_type_id, group: 'default', params: {}, + uuid: response.body.actions[0].uuid, }, ], enabled: true, diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/find.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/find.ts index 975ed2a3913c6..d730c2819596c 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/find.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/find.ts @@ -102,6 +102,7 @@ const findTestUtils = ( notify_when: 'onThrottleInterval', throttle: '1m', }, + uuid: match.actions[0].uuid, }, ], params: {}, diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group4/migrations.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group4/migrations.ts index 20980f390c79b..50667e7742374 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group4/migrations.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group4/migrations.ts @@ -5,7 +5,7 @@ * 2.0. */ -import expect from '@kbn/expect'; +import expect from 'expect'; import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { RawRule, RawRuleAction } from '@kbn/alerting-plugin/server/types'; import { FILEBEAT_7X_INDICATOR_PATH } from '@kbn/alerting-plugin/server/saved_objects/migrations'; @@ -33,8 +33,8 @@ export default function createGetTests({ getService }: FtrProviderContext) { `${getUrlPrefix(``)}/api/alerting/rule/74f3e6d7-b7bb-477d-ac28-92ee22728e6e` ); - expect(response.status).to.eql(200); - expect(response.body.consumer).to.equal('alerts'); + expect(response.status).toBe(200); + expect(response.body.consumer).toEqual('alerts'); }); it('7.10.0 migrates the `metrics` consumer to be the `infrastructure`', async () => { @@ -42,8 +42,8 @@ export default function createGetTests({ getService }: FtrProviderContext) { `${getUrlPrefix(``)}/api/alerting/rule/74f3e6d7-b7bb-477d-ac28-fdf248d5f2a4` ); - expect(response.status).to.eql(200); - expect(response.body.consumer).to.equal('infrastructure'); + expect(response.status).toEqual(200); + expect(response.body.consumer).toEqual('infrastructure'); }); it('7.10.0 migrates PagerDuty actions to have a default dedupKey', async () => { @@ -51,10 +51,10 @@ export default function createGetTests({ getService }: FtrProviderContext) { `${getUrlPrefix(``)}/api/alerting/rule/b6087f72-994f-46fb-8120-c6e5c50d0f8f` ); - expect(response.status).to.eql(200); + expect(response.status).toEqual(200); - expect(response.body.actions).to.eql([ - { + expect(response.body.actions).toEqual([ + expect.objectContaining({ connector_type_id: '.pagerduty', id: 'a6a8ab7a-35cf-445e-ade3-215a029c2ee3', group: 'default', @@ -63,8 +63,8 @@ export default function createGetTests({ getService }: FtrProviderContext) { eventAction: 'trigger', summary: 'fired {{alertInstanceId}}', }, - }, - { + }), + expect.objectContaining({ connector_type_id: '.pagerduty', id: 'a6a8ab7a-35cf-445e-ade3-215a029c2ee3', group: 'default', @@ -74,8 +74,8 @@ export default function createGetTests({ getService }: FtrProviderContext) { eventAction: 'resolve', summary: 'fired {{alertInstanceId}}', }, - }, - { + }), + expect.objectContaining({ connector_type_id: '.pagerduty', id: 'a6a8ab7a-35cf-445e-ade3-215a029c2ee3', group: 'default', @@ -85,7 +85,7 @@ export default function createGetTests({ getService }: FtrProviderContext) { eventAction: 'resolve', summary: 'fired {{alertInstanceId}}', }, - }, + }), ]); }); @@ -94,8 +94,8 @@ export default function createGetTests({ getService }: FtrProviderContext) { `${getUrlPrefix(``)}/api/alerting/rule/74f3e6d7-b7bb-477d-ac28-92ee22728e6e` ); - expect(response.status).to.eql(200); - expect(response.body.updated_at).to.eql('2020-06-17T15:35:39.839Z'); + expect(response.status).toEqual(200); + expect(response.body.updated_at).toEqual('2020-06-17T15:35:39.839Z'); }); it('7.11.0 migrates alerts to contain `notifyWhen` field', async () => { @@ -103,8 +103,8 @@ export default function createGetTests({ getService }: FtrProviderContext) { `${getUrlPrefix(``)}/api/alerting/rule/74f3e6d7-b7bb-477d-ac28-92ee22728e6e` ); - expect(response.status).to.eql(200); - expect(response.body.notify_when).to.eql('onActiveAlert'); + expect(response.status).toEqual(200); + expect(response.body.notify_when).toEqual('onActiveAlert'); }); it('7.11.2 migrates alerts with case actions, case fields are nested in an incident object', async () => { @@ -112,9 +112,9 @@ export default function createGetTests({ getService }: FtrProviderContext) { `${getUrlPrefix(``)}/api/alerting/rule/99f3e6d7-b7bb-477d-ac28-92ee22726969` ); - expect(response.status).to.eql(200); - expect(response.body.actions).to.eql([ - { + expect(response.status).toEqual(200); + expect(response.body.actions).toEqual([ + expect.objectContaining({ id: '66a8ab7a-35cf-445e-ade3-215a029c6969', connector_type_id: '.servicenow', group: 'threshold met', @@ -131,8 +131,8 @@ export default function createGetTests({ getService }: FtrProviderContext) { comments: [{ commentId: '1', comment: 'sn comment' }], }, }, - }, - { + }), + expect.objectContaining({ id: '66a8ab7a-35cf-445e-ade3-215a029c6969', connector_type_id: '.jira', group: 'threshold met', @@ -155,8 +155,8 @@ export default function createGetTests({ getService }: FtrProviderContext) { ], }, }, - }, - { + }), + expect.objectContaining({ id: '66a8ab7a-35cf-445e-ade3-215a029c6969', connector_type_id: '.resilient', group: 'threshold met', @@ -177,7 +177,7 @@ export default function createGetTests({ getService }: FtrProviderContext) { ], }, }, - }, + }), ]); }); @@ -190,8 +190,8 @@ export default function createGetTests({ getService }: FtrProviderContext) { }, { meta: true } ); - expect(response.statusCode).to.eql(200); - expect(response.body._source?.references).to.eql([ + expect(response.statusCode).toEqual(200); + expect(response.body._source?.references).toEqual([ { name: 'param:exceptionsList_0', id: 'endpoint_list', @@ -219,10 +219,10 @@ export default function createGetTests({ getService }: FtrProviderContext) { }, { meta: true } ); - expect(searchResult.statusCode).to.equal(200); - expect((searchResult.body.hits.total as estypes.SearchTotalHits).value).to.equal(1); + expect(searchResult.statusCode).toEqual(200); + expect((searchResult.body.hits.total as estypes.SearchTotalHits).value).toEqual(1); const hit = searchResult.body.hits.hits[0]; - expect((hit!._source!.alert! as RawRule).legacyId).to.equal( + expect((hit!._source!.alert! as RawRule).legacyId).toEqual( '74f3e6d7-b7bb-477d-ac28-92ee22728e6e' ); }); @@ -241,31 +241,31 @@ export default function createGetTests({ getService }: FtrProviderContext) { }, { meta: true } ); - expect(searchResult.statusCode).to.equal(200); - expect((searchResult.body.hits.total as estypes.SearchTotalHits).value).to.equal(1); + expect(searchResult.statusCode).toEqual(200); + expect((searchResult.body.hits.total as estypes.SearchTotalHits).value).toEqual(1); const hit = searchResult.body.hits.hits[0]; - expect((hit!._source!.alert! as RawRule).actions! as RawRuleAction[]).to.eql([ - { + expect((hit!._source!.alert! as RawRule).actions! as RawRuleAction[]).toEqual([ + expect.objectContaining({ actionRef: 'action_0', actionTypeId: 'test.noop', group: 'default', params: {}, - }, - { + }), + expect.objectContaining({ actionRef: 'preconfigured:my-slack1', actionTypeId: '.slack', group: 'default', params: { message: 'something happened!', }, - }, + }), ]); - expect(hit!._source!.references!).to.eql([ - { + expect(hit!._source!.references!).toEqual([ + expect.objectContaining({ id: '66a8ab7a-35cf-445e-ade3-215a029c6969', name: 'action_0', type: 'action', - }, + }), ]); }); @@ -278,8 +278,8 @@ export default function createGetTests({ getService }: FtrProviderContext) { }, { meta: true } ); - expect(response.statusCode).to.eql(200); - expect(response.body._source?.references).to.eql([ + expect(response.statusCode).toEqual(200); + expect(response.body._source?.references).toEqual([ { name: 'param:alert_0', id: '1a4ed6ae-3c89-44b2-999d-db554144504c', @@ -302,8 +302,8 @@ export default function createGetTests({ getService }: FtrProviderContext) { }, { meta: true } ); - expect(response.statusCode).to.eql(200); - expect(response.body._source?.alert?.params?.threatIndicatorPath).to.eql( + expect(response.statusCode).toEqual(200); + expect(response.body._source?.alert?.params?.threatIndicatorPath).toEqual( FILEBEAT_7X_INDICATOR_PATH ); }); @@ -322,8 +322,8 @@ export default function createGetTests({ getService }: FtrProviderContext) { }, { meta: true } ); - expect(response.statusCode).to.eql(200); - expect(response.body._source?.alert?.params?.threatIndicatorPath).to.eql( + expect(response.statusCode).toEqual(200); + expect(response.body._source?.alert?.params?.threatIndicatorPath).toEqual( 'custom.indicator.path' ); }); @@ -342,8 +342,8 @@ export default function createGetTests({ getService }: FtrProviderContext) { }, { meta: true } ); - expect(response.statusCode).to.eql(200); - expect(response.body._source?.alert?.params?.threatIndicatorPath).not.to.eql( + expect(response.statusCode).toEqual(200); + expect(response.body._source?.alert?.params?.threatIndicatorPath).not.toEqual( FILEBEAT_7X_INDICATOR_PATH ); }); @@ -356,8 +356,8 @@ export default function createGetTests({ getService }: FtrProviderContext) { }, { meta: true } ); - expect(response.statusCode).to.eql(200); - expect(response.body._source?.alert?.actions?.[0].group).to.be( + expect(response.statusCode).toEqual(200); + expect(response.body._source?.alert?.actions?.[0].group).toBe( 'metrics.inventory_threshold.fired' ); }); @@ -370,9 +370,9 @@ export default function createGetTests({ getService }: FtrProviderContext) { }, { meta: true } ); - expect(response.statusCode).to.eql(200); - expect(response.body._source?.alert?.alertTypeId).to.be('siem.queryRule'); - expect(response.body._source?.alert?.enabled).to.be(false); + expect(response.statusCode).toEqual(200); + expect(response.body._source?.alert?.alertTypeId).toBe('siem.queryRule'); + expect(response.body._source?.alert?.enabled).toBe(false); }); it('8.0.1 migrates and adds tags to disabled rules in 8.0', async () => { @@ -383,7 +383,7 @@ export default function createGetTests({ getService }: FtrProviderContext) { }, { meta: true } ); - expect(responseEnabledBeforeMigration.statusCode).to.eql(200); + expect(responseEnabledBeforeMigration.statusCode).toEqual(200); const responseDisabledBeforeMigration = await es.get<{ alert: RawRule }>( { index: '.kibana', @@ -391,17 +391,17 @@ export default function createGetTests({ getService }: FtrProviderContext) { }, { meta: true } ); - expect(responseDisabledBeforeMigration.statusCode).to.eql(200); + expect(responseDisabledBeforeMigration.statusCode).toEqual(200); // Both should be disabled - expect(responseEnabledBeforeMigration.body._source?.alert?.enabled).to.be(false); - expect(responseDisabledBeforeMigration.body._source?.alert?.enabled).to.be(false); + expect(responseEnabledBeforeMigration.body._source?.alert?.enabled).toBe(false); + expect(responseDisabledBeforeMigration.body._source?.alert?.enabled).toBe(false); // Only the rule that was enabled should be tagged - expect(responseEnabledBeforeMigration.body._source?.alert?.tags).to.eql([ + expect(responseEnabledBeforeMigration.body._source?.alert?.tags).toEqual([ 'auto_disabled_8.0', ]); - expect(responseDisabledBeforeMigration.body._source?.alert?.tags).to.eql([]); + expect(responseDisabledBeforeMigration.body._source?.alert?.tags).toEqual([]); }); it('8.2.0 migrates params to mapped_params for specific params properties', async () => { @@ -413,8 +413,8 @@ export default function createGetTests({ getService }: FtrProviderContext) { { meta: true } ); - expect(response.statusCode).to.equal(200); - expect(response.body._source?.alert?.mapped_params).to.eql({ + expect(response.statusCode).toEqual(200); + expect(response.body._source?.alert?.mapped_params).toEqual({ risk_score: 90, severity: '80-critical', }); @@ -428,8 +428,8 @@ export default function createGetTests({ getService }: FtrProviderContext) { }, { meta: true } ); - expect(response.statusCode).to.equal(200); - expect(response.body._source?.alert?.params.searchType).to.eql('esQuery'); + expect(response.statusCode).toEqual(200); + expect(response.body._source?.alert?.params.searchType).toEqual('esQuery'); }); it('8.3.0 removes internal tags in Security Solution rule', async () => { @@ -441,8 +441,8 @@ export default function createGetTests({ getService }: FtrProviderContext) { { meta: true } ); - expect(response.statusCode).to.equal(200); - expect(response.body._source?.alert?.tags).to.eql(['test-tag-1', 'foo-tag']); + expect(response.statusCode).toEqual(200); + expect(response.body._source?.alert?.tags).toEqual(['test-tag-1', 'foo-tag']); }); it('8.4.1 removes IsSnoozedUntil', async () => { @@ -460,9 +460,9 @@ export default function createGetTests({ getService }: FtrProviderContext) { { meta: true } ); - expect(searchResult.statusCode).to.equal(200); + expect(searchResult.statusCode).toEqual(200); const hit = searchResult.body.hits.hits[0]; - expect((hit!._source!.alert! as RawRule).isSnoozedUntil).to.be(undefined); + expect((hit!._source!.alert! as RawRule).isSnoozedUntil).toBe(undefined); }); it('8.5.0 removes runtime and field params from older ES Query rules', async () => { @@ -479,8 +479,8 @@ export default function createGetTests({ getService }: FtrProviderContext) { }, { meta: true } ); - expect(response.statusCode).to.eql(200); - expect(response.body._source?.alert?.params?.esQuery).to.eql( + expect(response.statusCode).toEqual(200); + expect(response.body._source?.alert?.params?.esQuery).toEqual( JSON.stringify({ query: { match_all: {} } }, null, 4) ); }); @@ -499,8 +499,8 @@ export default function createGetTests({ getService }: FtrProviderContext) { }, { meta: true } ); - expect(response.statusCode).to.eql(200); - expect(response.body._source?.alert?.params?.esQuery).to.eql( + expect(response.statusCode).toEqual(200); + expect(response.body._source?.alert?.params?.esQuery).toEqual( '{\n\t"query":\n{\n\t"match_all":\n\t{}\n}\n}' ); }); @@ -519,8 +519,8 @@ export default function createGetTests({ getService }: FtrProviderContext) { }, { meta: true } ); - expect(response.statusCode).to.eql(200); - expect(response.body._source?.alert?.params?.esQuery).to.eql('{"query":}'); + expect(response.statusCode).toEqual(200); + expect(response.body._source?.alert?.params?.esQuery).toEqual('{"query":}'); }); it('8.6.0 migrates executionStatus and monitoring', async () => { @@ -533,7 +533,7 @@ export default function createGetTests({ getService }: FtrProviderContext) { ); const alert = response.body._source?.alert; - expect(alert?.monitoring).to.eql({ + expect(alert?.monitoring).toEqual({ run: { history: [ { @@ -557,7 +557,7 @@ export default function createGetTests({ getService }: FtrProviderContext) { }, }); - expect(alert?.lastRun).to.eql({ + expect(alert?.lastRun).toEqual({ outcome: 'succeeded', outcomeMsg: null, outcomeOrder: 0, @@ -565,7 +565,7 @@ export default function createGetTests({ getService }: FtrProviderContext) { alertsCount: {}, }); - expect(alert?.nextRun).to.eql(undefined); + expect(alert?.nextRun).toEqual(undefined); }); it('8.6 migrates executionStatus warnings and errors', async () => { @@ -579,9 +579,9 @@ export default function createGetTests({ getService }: FtrProviderContext) { const alert = response.body._source?.alert; - expect(alert?.lastRun?.outcome).to.eql('warning'); - expect(alert?.lastRun?.warning).to.eql('warning reason'); - expect(alert?.lastRun?.outcomeMsg).to.eql('warning message'); + expect(alert?.lastRun?.outcome).toEqual('warning'); + expect(alert?.lastRun?.warning).toEqual('warning reason'); + expect(alert?.lastRun?.outcomeMsg).toEqual('warning message'); }); it('8.7.0 adds aggType and groupBy to ES query rules', async () => { @@ -604,10 +604,10 @@ export default function createGetTests({ getService }: FtrProviderContext) { }, { meta: true } ); - expect(response.statusCode).to.eql(200); + expect(response.statusCode).toEqual(200); response.body.hits.hits.forEach((hit) => { - expect((hit?._source?.alert as RawRule)?.params?.aggType).to.eql('count'); - expect((hit?._source?.alert as RawRule)?.params?.groupBy).to.eql('all'); + expect((hit?._source?.alert as RawRule)?.params?.aggType).toEqual('count'); + expect((hit?._source?.alert as RawRule)?.params?.groupBy).toEqual('all'); }); }); @@ -635,8 +635,39 @@ export default function createGetTests({ getService }: FtrProviderContext) { { meta: true } ); - expect(response.body._source?.alert?.params.logView).to.eql(logView); - expect(response.body._source?.references).to.eql(references); + expect(response.body._source?.alert?.params.logView).toEqual(logView); + expect(response.body._source?.references).toEqual(references); + }); + + it('8.7 adds uuid to the actions', async () => { + const response = await es.get<{ alert: RawRule }>( + { + index: '.kibana', + id: 'alert:9c003b00-00ee-11ec-b067-2524946ba327', + }, + { meta: true } + ); + + const alert = response.body._source?.alert; + + expect(alert?.actions).toEqual([ + { + actionRef: 'action_0', + actionTypeId: 'test.noop', + group: 'default', + params: {}, + uuid: expect.any(String), + }, + { + actionRef: 'preconfigured:my-slack1', + actionTypeId: '.slack', + group: 'default', + params: { + message: 'something happened!', + }, + uuid: expect.any(String), + }, + ]); }); }); } diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/add_actions.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/add_actions.ts index 94a8b58ff70a0..ef414b37a3f9b 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/add_actions.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/add_actions.ts @@ -57,7 +57,10 @@ export default ({ getService }: FtrProviderContext) => { const rule = await createRule(supertest, log, getRuleWithWebHookAction(hookAction.id)); const bodyToCompare = removeServerGeneratedProperties(rule); expect(bodyToCompare).to.eql( - getSimpleRuleOutputWithWebHookAction(`${bodyToCompare?.actions?.[0].id}`) + getSimpleRuleOutputWithWebHookAction( + `${bodyToCompare?.actions?.[0].id}`, + `${bodyToCompare?.actions?.[0].uuid}` + ) ); }); diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/export_rules.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/export_rules.ts index 60af78ec6cff9..c4c109f25952c 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/export_rules.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/export_rules.ts @@ -165,7 +165,10 @@ export default ({ getService }: FtrProviderContext): void => { const outputRule1: ReturnType = { ...getSimpleRuleOutput('rule-1'), - actions: [action1, action2], + actions: [ + { ...action1, uuid: firstRule.actions[0].uuid }, + { ...action2, uuid: firstRule.actions[1].uuid }, + ], throttle: 'rule', }; expect(firstRule).to.eql(outputRule1); @@ -213,12 +216,12 @@ export default ({ getService }: FtrProviderContext): void => { const outputRule1: ReturnType = { ...getSimpleRuleOutput('rule-2'), - actions: [action], + actions: [{ ...action, uuid: firstRule.actions[0].uuid }], throttle: 'rule', }; const outputRule2: ReturnType = { ...getSimpleRuleOutput('rule-1'), - actions: [action], + actions: [{ ...action, uuid: secondRule.actions[0].uuid }], throttle: 'rule', }; expect(firstRule).to.eql(outputRule1); diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/find_rules.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/find_rules.ts index f2e5e19ed182f..1ddf36277ec6b 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/find_rules.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/find_rules.ts @@ -126,7 +126,7 @@ export default ({ getService }: FtrProviderContext): void => { const ruleWithActions: ReturnType = { ...getSimpleRuleOutput(), - actions: [action], + actions: [{ ...action, uuid: body.data[0].actions[0].uuid }], throttle: 'rule', }; @@ -171,7 +171,7 @@ export default ({ getService }: FtrProviderContext): void => { const ruleWithActions: ReturnType = { ...getSimpleRuleOutput(), - actions: [action], + actions: [{ ...action, uuid: body.data[0].actions[0].uuid }], throttle: '1h', // <-- throttle makes this a scheduled action }; diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/update_actions.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/update_actions.ts index 4897805e09eb2..cf1c198933447 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/update_actions.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/update_actions.ts @@ -71,7 +71,10 @@ export default ({ getService }: FtrProviderContext) => { const bodyToCompare = removeServerGeneratedProperties(updatedRule); const expected = { - ...getSimpleRuleOutputWithWebHookAction(`${bodyToCompare.actions?.[0].id}`), + ...getSimpleRuleOutputWithWebHookAction( + `${bodyToCompare.actions?.[0].id}`, + `${bodyToCompare.actions?.[0].uuid}` + ), version: 2, // version bump is required since this is an updated rule and this is part of the testing that we do bump the version number on update }; expect(bodyToCompare).to.eql(expected); @@ -147,7 +150,10 @@ export default ({ getService }: FtrProviderContext) => { const updatedRule = await updateRule(supertest, log, ruleToUpdate); const bodyToCompare = removeServerGeneratedProperties(updatedRule); - const expected = getSimpleRuleOutputWithWebHookAction(`${bodyToCompare.actions?.[0].id}`); + const expected = getSimpleRuleOutputWithWebHookAction( + `${bodyToCompare.actions?.[0].id}`, + `${bodyToCompare.actions?.[0].uuid}` + ); expect(bodyToCompare.actions).to.eql(expected.actions); expect(bodyToCompare.throttle).to.eql(expected.throttle); @@ -180,7 +186,10 @@ export default ({ getService }: FtrProviderContext) => { expect(body.data.length).to.eql(1); // should have only one length to the data set, otherwise we have duplicates or the tags were removed and that is incredibly bad. const bodyToCompare = removeServerGeneratedProperties(body.data[0]); - const expected = getSimpleRuleOutputWithWebHookAction(`${bodyToCompare.actions?.[0].id}`); + const expected = getSimpleRuleOutputWithWebHookAction( + `${bodyToCompare.actions?.[0].id}`, + `${bodyToCompare.actions?.[0].uuid}` + ); expect(bodyToCompare.actions).to.eql(expected.actions); expect(bodyToCompare.immutable).to.be(true); diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/legacy_actions_migrations.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/legacy_actions_migrations.ts index ad6e45954e06a..ac187485c4509 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/legacy_actions_migrations.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/legacy_actions_migrations.ts @@ -121,6 +121,7 @@ export default ({ getService }: FtrProviderContext) => { subject: 'Test Actions', to: ['test@test.com'], }, + uuid: ruleSO?.alert.actions[0].uuid, }, ]); expect(ruleSO?.alert.throttle).to.eql(null); @@ -179,6 +180,7 @@ export default ({ getService }: FtrProviderContext) => { }, actionRef: 'action_0', group: 'default', + uuid: ruleSO?.alert.actions[0].uuid, }, { actionTypeId: '.slack', @@ -187,6 +189,7 @@ export default ({ getService }: FtrProviderContext) => { }, actionRef: 'action_1', group: 'default', + uuid: ruleSO?.alert.actions[1].uuid, }, ]); expect(ruleSO?.alert.throttle).to.eql('1h'); @@ -249,6 +252,7 @@ export default ({ getService }: FtrProviderContext) => { subject: 'Test Actions', to: ['test@test.com'], }, + uuid: ruleSO?.alert.actions[0].uuid, }, ]); expect(ruleSO?.alert.throttle).to.eql('1d'); @@ -306,6 +310,7 @@ export default ({ getService }: FtrProviderContext) => { subject: 'Test Actions', to: ['test@test.com'], }, + uuid: ruleSO?.alert.actions[0].uuid, }, ]); expect(ruleSO?.alert.throttle).to.eql('7d'); diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/patch_rules.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/patch_rules.ts index 2ec13365eb1d1..7137c0ab342f5 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/patch_rules.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/patch_rules.ts @@ -359,6 +359,7 @@ export default ({ getService }: FtrProviderContext) => { .send({ id: rule.id, enabled: false }) .expect(200); + const bodyToCompare = removeServerGeneratedProperties(patchResponse.body); const outputRule = getSimpleRuleOutput(); outputRule.actions = [ { @@ -369,10 +370,11 @@ export default ({ getService }: FtrProviderContext) => { message: 'Hourly\nRule {{context.rule.name}} generated {{state.signals_count}} alerts', }, + uuid: bodyToCompare.actions[0].uuid, }, ]; outputRule.throttle = '1h'; - const bodyToCompare = removeServerGeneratedProperties(patchResponse.body); + expect(bodyToCompare).to.eql(outputRule); }); diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/patch_rules_bulk.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/patch_rules_bulk.ts index b844e9500e126..0f9129ae8316f 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/patch_rules_bulk.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/patch_rules_bulk.ts @@ -181,6 +181,7 @@ export default ({ getService }: FtrProviderContext) => { // @ts-expect-error body.forEach((response) => { + const bodyToCompare = removeServerGeneratedProperties(response); const outputRule = getSimpleRuleOutput(response.rule_id, false); outputRule.actions = [ { @@ -191,10 +192,10 @@ export default ({ getService }: FtrProviderContext) => { message: 'Hourly\nRule {{context.rule.name}} generated {{state.signals_count}} alerts', }, + uuid: bodyToCompare.actions[0].uuid, }, ]; outputRule.throttle = '1h'; - const bodyToCompare = removeServerGeneratedProperties(response); expect(bodyToCompare).to.eql(outputRule); }); }); diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/perform_bulk_action.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/perform_bulk_action.ts index 13f1f99fc3b23..cc2b17015a5a4 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/perform_bulk_action.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/perform_bulk_action.ts @@ -173,6 +173,7 @@ export default ({ getService }: FtrProviderContext): void => { params: { body: '{"test":"a default action"}', }, + uuid: rule.actions[0].uuid, }, ], }); @@ -325,6 +326,7 @@ export default ({ getService }: FtrProviderContext): void => { params: { message: 'Hourly\nRule {{context.rule.name}} generated {{state.signals_count}} alerts', }, + uuid: ruleBody.actions[0].uuid, }, ]); }); @@ -394,6 +396,7 @@ export default ({ getService }: FtrProviderContext): void => { params: { message: 'Hourly\nRule {{context.rule.name}} generated {{state.signals_count}} alerts', }, + uuid: ruleBody.actions[0].uuid, }, ]); }); @@ -484,6 +487,7 @@ export default ({ getService }: FtrProviderContext): void => { message: 'Hourly\nRule {{context.rule.name}} generated {{state.signals_count}} alerts', }, + uuid: rule.actions[0].uuid, }, ]); }); @@ -1113,6 +1117,7 @@ export default ({ getService }: FtrProviderContext): void => { message: 'Hourly\nRule {{context.rule.name}} generated {{state.signals_count}} alerts', }, + uuid: setTagsRule.actions[0].uuid, }, ]); }); @@ -1396,6 +1401,7 @@ export default ({ getService }: FtrProviderContext): void => { ...webHookActionMock, id: webHookConnector.id, action_type_id: '.webhook', + uuid: body.attributes.results.updated[0].actions[0].uuid, }, ]; @@ -1452,6 +1458,7 @@ export default ({ getService }: FtrProviderContext): void => { ...webHookActionMock, id: webHookConnector.id, action_type_id: '.webhook', + uuid: body.attributes.results.updated[0].actions[0].uuid, }, ]; @@ -1544,6 +1551,7 @@ export default ({ getService }: FtrProviderContext): void => { ...webHookActionMock, id: webHookConnector.id, action_type_id: '.webhook', + uuid: body.attributes.results.updated[0].actions[0].uuid, }, ]; @@ -1598,11 +1606,12 @@ export default ({ getService }: FtrProviderContext): void => { .expect(200); const expectedRuleActions = [ - defaultRuleAction, + { ...defaultRuleAction, uuid: body.attributes.results.updated[0].actions[0].uuid }, { ...webHookActionMock, id: webHookConnector.id, action_type_id: '.webhook', + uuid: body.attributes.results.updated[0].actions[1].uuid, }, ]; @@ -1665,11 +1674,12 @@ export default ({ getService }: FtrProviderContext): void => { .expect(200); const expectedRuleActions = [ - defaultRuleAction, + { ...defaultRuleAction, uuid: body.attributes.results.updated[0].actions[0].uuid }, { ...slackConnectorMockProps, id: slackConnector.id, action_type_id: '.slack', + uuid: body.attributes.results.updated[0].actions[1].uuid, }, ]; @@ -1719,12 +1729,16 @@ export default ({ getService }: FtrProviderContext): void => { .expect(200); // Check that the updated rule is returned with the response - expect(body.attributes.results.updated[0].actions).to.eql([defaultRuleAction]); + expect(body.attributes.results.updated[0].actions).to.eql([ + { ...defaultRuleAction, uuid: createdRule.actions[0].uuid }, + ]); // Check that the updates have been persisted const { body: readRule } = await fetchRule(ruleId).expect(200); - expect(readRule.actions).to.eql([defaultRuleAction]); + expect(readRule.actions).to.eql([ + { ...defaultRuleAction, uuid: createdRule.actions[0].uuid }, + ]); }); it('should change throttle if actions list in payload is empty', async () => { @@ -1816,6 +1830,7 @@ export default ({ getService }: FtrProviderContext): void => { ...webHookActionMock, id: webHookConnector.id, action_type_id: '.webhook', + uuid: editedRule.actions[0].uuid, }, ]); // version of prebuilt rule should not change @@ -1829,6 +1844,7 @@ export default ({ getService }: FtrProviderContext): void => { ...webHookActionMock, id: webHookConnector.id, action_type_id: '.webhook', + uuid: readRule.actions[0].uuid, }, ]); expect(prebuiltRule.version).to.be(readRule.version); diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/read_rules.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/read_rules.ts index 5f03ce094e95e..0bdf609276f09 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/read_rules.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/read_rules.ts @@ -135,7 +135,7 @@ export default ({ getService }: FtrProviderContext) => { const bodyToCompare = removeServerGeneratedProperties(body); const ruleWithActions: ReturnType = { ...getSimpleRuleOutput(), - actions: [action], + actions: [{ ...action, uuid: bodyToCompare.actions[0].uuid }], throttle: 'rule', }; expect(bodyToCompare).to.eql(ruleWithActions); @@ -174,7 +174,7 @@ export default ({ getService }: FtrProviderContext) => { const bodyToCompare = removeServerGeneratedProperties(body); const ruleWithActions: ReturnType = { ...getSimpleRuleOutput(), - actions: [action], + actions: [{ ...action, uuid: bodyToCompare.actions[0].uuid }], throttle: '1h', // <-- throttle makes this a scheduled action }; expect(bodyToCompare).to.eql(ruleWithActions); diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/update_rules.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/update_rules.ts index a33aacd26bb8a..d92261c5bb344 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/update_rules.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/update_rules.ts @@ -229,6 +229,8 @@ export default ({ getService }: FtrProviderContext) => { .send(updatedRule) .expect(200); + const bodyToCompare = removeServerGeneratedPropertiesIncludingRuleId(body); + const outputRule = getSimpleRuleOutputWithoutRuleId(); outputRule.name = 'some other name'; outputRule.version = 2; @@ -241,10 +243,11 @@ export default ({ getService }: FtrProviderContext) => { message: 'Hourly\nRule {{context.rule.name}} generated {{state.signals_count}} alerts', }, + uuid: bodyToCompare.actions![0].uuid, }, ]; outputRule.throttle = '1d'; - const bodyToCompare = removeServerGeneratedPropertiesIncludingRuleId(body); + expect(bodyToCompare).to.eql(outputRule); }); diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/update_rules_bulk.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/update_rules_bulk.ts index 04f3eb2536a41..3aafa81aa9716 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/update_rules_bulk.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/update_rules_bulk.ts @@ -166,6 +166,7 @@ export default ({ getService }: FtrProviderContext) => { .expect(200); body.forEach((response) => { + const bodyToCompare = removeServerGeneratedProperties(response); const outputRule = getSimpleRuleOutput(response.rule_id); outputRule.name = 'some other name'; outputRule.version = 2; @@ -178,10 +179,11 @@ export default ({ getService }: FtrProviderContext) => { message: 'Hourly\nRule {{context.rule.name}} generated {{state.signals_count}} alerts', }, + uuid: bodyToCompare.actions[0].uuid, }, ]; outputRule.throttle = '1d'; - const bodyToCompare = removeServerGeneratedProperties(response); + expect(bodyToCompare).to.eql(outputRule); }); }); diff --git a/x-pack/test/detection_engine_api_integration/utils/get_simple_rule_output_with_web_hook_action.ts b/x-pack/test/detection_engine_api_integration/utils/get_simple_rule_output_with_web_hook_action.ts index c96537bfd0813..25776fefd5687 100644 --- a/x-pack/test/detection_engine_api_integration/utils/get_simple_rule_output_with_web_hook_action.ts +++ b/x-pack/test/detection_engine_api_integration/utils/get_simple_rule_output_with_web_hook_action.ts @@ -9,7 +9,8 @@ import { getSimpleRuleOutput } from './get_simple_rule_output'; import { RuleWithoutServerGeneratedProperties } from './remove_server_generated_properties'; export const getSimpleRuleOutputWithWebHookAction = ( - actionId: string + actionId: string, + uuid: string ): RuleWithoutServerGeneratedProperties => ({ ...getSimpleRuleOutput(), throttle: 'rule', @@ -21,6 +22,7 @@ export const getSimpleRuleOutputWithWebHookAction = ( params: { body: '{}', }, + uuid, }, ], }); diff --git a/x-pack/test/functional_with_es_ssl/apps/discover_ml_uptime/uptime/simple_down_alert.ts b/x-pack/test/functional_with_es_ssl/apps/discover_ml_uptime/uptime/simple_down_alert.ts index a0e041996f4bc..4064a8a6b7ae2 100644 --- a/x-pack/test/functional_with_es_ssl/apps/discover_ml_uptime/uptime/simple_down_alert.ts +++ b/x-pack/test/functional_with_es_ssl/apps/discover_ml_uptime/uptime/simple_down_alert.ts @@ -100,6 +100,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { message: MonitorStatusTranslations.defaultRecoveryMessage, }, id: 'my-slack1', + uuid: actions[0].uuid, }, { actionTypeId: '.slack', @@ -108,6 +109,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { message: MonitorStatusTranslations.defaultActionMessage, }, id: 'my-slack1', + uuid: actions[1].uuid, }, ]); expect(alertTypeId).to.eql('xpack.uptime.alerts.monitorStatus');