diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/__snapshots__/migrations_state_action_machine.test.ts.snap b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/__snapshots__/migrations_state_action_machine.test.ts.snap index b0c7fd0f37289..28d12601d23f3 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/__snapshots__/migrations_state_action_machine.test.ts.snap +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/__snapshots__/migrations_state_action_machine.test.ts.snap @@ -96,6 +96,11 @@ Object { "type": "server", }, }, + Object { + "term": Object { + "type": "siem-detection-engine-rule-execution-info", + }, + }, Object { "term": Object { "type": "siem-detection-engine-rule-status", @@ -282,6 +287,11 @@ Object { "type": "server", }, }, + Object { + "term": Object { + "type": "siem-detection-engine-rule-execution-info", + }, + }, Object { "term": Object { "type": "siem-detection-engine-rule-status", @@ -472,6 +482,11 @@ Object { "type": "server", }, }, + Object { + "term": Object { + "type": "siem-detection-engine-rule-execution-info", + }, + }, Object { "term": Object { "type": "siem-detection-engine-rule-status", @@ -666,6 +681,11 @@ Object { "type": "server", }, }, + Object { + "term": Object { + "type": "siem-detection-engine-rule-execution-info", + }, + }, Object { "term": Object { "type": "siem-detection-engine-rule-status", @@ -902,6 +922,11 @@ Object { "type": "server", }, }, + Object { + "term": Object { + "type": "siem-detection-engine-rule-execution-info", + }, + }, Object { "term": Object { "type": "siem-detection-engine-rule-status", @@ -1099,6 +1124,11 @@ Object { "type": "server", }, }, + Object { + "term": Object { + "type": "siem-detection-engine-rule-execution-info", + }, + }, Object { "term": Object { "type": "siem-detection-engine-rule-status", diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/core/unused_types.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/core/unused_types.ts index 60ace4e28de0e..3f46404066383 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/core/unused_types.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/core/unused_types.ts @@ -33,6 +33,8 @@ export const REMOVED_TYPES: string[] = [ 'osquery-usage-metric', // Was removed in 8.1 https://github.com/elastic/kibana/issues/91265 'siem-detection-engine-rule-status', + // Was removed in 8.7 https://github.com/elastic/kibana/issues/130966 + 'siem-detection-engine-rule-execution-info', // Was removed in 7.16 'timelion-sheet', // Removed in 8.3 https://github.com/elastic/kibana/issues/127745 diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/initial_state.test.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/initial_state.test.ts index ee99e599a998a..8a66bac6ce9fe 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/initial_state.test.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/initial_state.test.ts @@ -133,6 +133,11 @@ describe('createInitialState', () => { "type": "server", }, }, + Object { + "term": Object { + "type": "siem-detection-engine-rule-execution-info", + }, + }, Object { "term": Object { "type": "siem-detection-engine-rule-status", diff --git a/src/core/server/integration_tests/saved_objects/migrations/check_registered_types.test.ts b/src/core/server/integration_tests/saved_objects/migrations/check_registered_types.test.ts index 54a61456ac769..347401e9b30f9 100644 --- a/src/core/server/integration_tests/saved_objects/migrations/check_registered_types.test.ts +++ b/src/core/server/integration_tests/saved_objects/migrations/check_registered_types.test.ts @@ -131,7 +131,6 @@ describe('checking migration metadata changes on all registered SO types', () => "security-rule": "e0dfdba5d66139d0300723b2e6672993cd4a11f3", "security-solution-signals-migration": "e65933e32926e0ca385415bd44fc6da0b6d3d419", "siem-detection-engine-rule-actions": "d4b5934c0c0e4ccdf509a41000eb0bee07be0c28", - "siem-detection-engine-rule-execution-info": "b92d51db7b7d591758d3e85892a91064aff01ff8", "siem-ui-timeline": "95474f10662802e2f9ea068b45bf69212a2f5842", "siem-ui-timeline-note": "08c71dc0b8b8018a67e80beb4659a078404c223d", "siem-ui-timeline-pinned-event": "e2697b38751506c7fce6e8b7207a830483dc4283", diff --git a/x-pack/plugins/security_solution/common/detection_engine/rule_monitoring/model/execution_status.ts b/x-pack/plugins/security_solution/common/detection_engine/rule_monitoring/model/execution_status.ts index 22e599b18c541..af5049c8f9bf0 100644 --- a/x-pack/plugins/security_solution/common/detection_engine/rule_monitoring/model/execution_status.ts +++ b/x-pack/plugins/security_solution/common/detection_engine/rule_monitoring/model/execution_status.ts @@ -7,6 +7,7 @@ import type * as t from 'io-ts'; import { enumeration, PositiveInteger } from '@kbn/securitysolution-io-ts-types'; +import type { RuleLastRunOutcomes } from '@kbn/alerting-plugin/common'; import { assertUnreachable } from '../../../utility_types'; /** @@ -78,3 +79,19 @@ export const ruleExecutionStatusToNumber = ( return 0; } }; + +export const ruleLastRunOutcomeToExecutionStatus = ( + outcome: RuleLastRunOutcomes +): RuleExecutionStatus => { + switch (outcome) { + case 'succeeded': + return RuleExecutionStatus.succeeded; + case 'warning': + return RuleExecutionStatus['partial failure']; + case 'failed': + return RuleExecutionStatus.failed; + default: + assertUnreachable(outcome); + return RuleExecutionStatus.failed; + } +}; diff --git a/x-pack/plugins/security_solution/public/detections/components/rules/rule_execution_status/rule_status_badge.tsx b/x-pack/plugins/security_solution/public/detections/components/rules/rule_execution_status/rule_status_badge.tsx index b80445403959f..fff3fe48074ce 100644 --- a/x-pack/plugins/security_solution/public/detections/components/rules/rule_execution_status/rule_status_badge.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/rules/rule_execution_status/rule_status_badge.tsx @@ -30,7 +30,9 @@ const RuleStatusBadgeComponent = ({ status, message }: RuleStatusBadgeProps) => const statusColor = getStatusColor(status); return ( ( +

{line}

+ ))} healthColor={statusColor} dataTestSubj="ruleExecutionStatus" > diff --git a/x-pack/plugins/security_solution/public/detections/components/rules/rule_execution_status/rule_status_failed_callout.tsx b/x-pack/plugins/security_solution/public/detections/components/rules/rule_execution_status/rule_status_failed_callout.tsx index 042484634a925..ff5b559eb4b32 100644 --- a/x-pack/plugins/security_solution/public/detections/components/rules/rule_execution_status/rule_status_failed_callout.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/rules/rule_execution_status/rule_status_failed_callout.tsx @@ -40,7 +40,9 @@ const RuleStatusFailedCallOutComponent: React.FC = iconType="alert" data-test-subj="ruleStatusFailedCallOut" > -

{message}

+ {message.split('\n').map((line) => ( +

{line}

+ ))} ); }; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/update_prebuilt_rules.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/update_prebuilt_rules.ts index 341038097f448..4956b9377c947 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/update_prebuilt_rules.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/update_prebuilt_rules.ts @@ -87,7 +87,6 @@ const createPromises = ( await deleteRules({ ruleId: migratedRule.id, rulesClient, - ruleExecutionLog, }); return createRules({ diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_actions/route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_actions/route.ts index 82660cba2a870..2234f09cb1888 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_actions/route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_actions/route.ts @@ -329,7 +329,6 @@ export const performBulkActionRoute = ( ]); const rulesClient = ctx.alerting.getRulesClient(); - const ruleExecutionLog = ctx.securitySolution.getRuleExecutionLog(); const exceptionsClient = ctx.lists?.getExceptionListClient(); const savedObjectsClient = ctx.core.savedObjects.client; @@ -481,7 +480,6 @@ export const performBulkActionRoute = ( await deleteRules({ ruleId: migratedRule.id, rulesClient, - ruleExecutionLog, }); return null; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_create_rules/route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_create_rules/route.ts index f4497830fd85b..958a1e01ce2f5 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_create_rules/route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_create_rules/route.ts @@ -121,7 +121,7 @@ export const bulkCreateRulesRoute = ( params: payloadRule, }); - return transformValidateBulkError(createdRule.params.ruleId, createdRule, null); + return transformValidateBulkError(createdRule.params.ruleId, createdRule); } catch (err) { return transformBulkError( payloadRule.rule_id, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_delete_rules/route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_delete_rules/route.ts index 399b12ded105e..7864fb0bbb3d3 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_delete_rules/route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_delete_rules/route.ts @@ -64,7 +64,6 @@ export const bulkDeleteRulesRoute = (router: SecuritySolutionPluginRouter, logge const ctx = await context.resolve(['core', 'securitySolution', 'alerting']); const rulesClient = ctx.alerting.getRulesClient(); - const ruleExecutionLog = ctx.securitySolution.getRuleExecutionLog(); const savedObjectsClient = ctx.core.savedObjects.client; const rules = await Promise.all( @@ -91,19 +90,12 @@ export const bulkDeleteRulesRoute = (router: SecuritySolutionPluginRouter, logge return getIdBulkError({ id, ruleId }); } - const ruleExecutionSummary = await ruleExecutionLog.getExecutionSummary(migratedRule.id); - await deleteRules({ ruleId: migratedRule.id, rulesClient, - ruleExecutionLog, }); - return transformValidateBulkError( - idOrRuleIdOrUnknown, - migratedRule, - ruleExecutionSummary - ); + return transformValidateBulkError(idOrRuleIdOrUnknown, migratedRule); } catch (err) { return transformBulkError(idOrRuleIdOrUnknown, err); } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_patch_rules/route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_patch_rules/route.ts index b2b56fb3b0d8f..2aa1f46c9b9d6 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_patch_rules/route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_patch_rules/route.ts @@ -56,7 +56,6 @@ export const bulkPatchRulesRoute = ( const ctx = await context.resolve(['core', 'securitySolution', 'alerting', 'licensing']); const rulesClient = ctx.alerting.getRulesClient(); - const ruleExecutionLog = ctx.securitySolution.getRuleExecutionLog(); const savedObjectsClient = ctx.core.savedObjects.client; const mlAuthz = buildMlAuthz({ @@ -111,8 +110,7 @@ export const bulkPatchRulesRoute = ( nextParams: payloadRule, }); if (rule != null && rule.enabled != null && rule.name != null) { - const ruleExecutionSummary = await ruleExecutionLog.getExecutionSummary(rule.id); - return transformValidateBulkError(rule.id, rule, ruleExecutionSummary); + return transformValidateBulkError(rule.id, rule); } else { return getIdBulkError({ id: payloadRule.id, ruleId: payloadRule.rule_id }); } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_update_rules/route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_update_rules/route.ts index 86738289fd79e..d186abecf7b38 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_update_rules/route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_update_rules/route.ts @@ -61,7 +61,6 @@ export const bulkUpdateRulesRoute = ( const ctx = await context.resolve(['core', 'securitySolution', 'alerting', 'licensing']); const rulesClient = ctx.alerting.getRulesClient(); - const ruleExecutionLog = ctx.securitySolution.getRuleExecutionLog(); const savedObjectsClient = ctx.core.savedObjects.client; const mlAuthz = buildMlAuthz({ @@ -116,8 +115,7 @@ export const bulkUpdateRulesRoute = ( ruleUpdate: payloadRule, }); if (rule != null) { - const ruleExecutionSummary = await ruleExecutionLog.getExecutionSummary(rule.id); - return transformValidateBulkError(rule.id, rule, ruleExecutionSummary); + return transformValidateBulkError(rule.id, rule); } else { return getIdBulkError({ id: payloadRule.id, ruleId: payloadRule.rule_id }); } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/create_rule/route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/create_rule/route.ts index 8b081b6f7e20b..912d4227554d6 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/create_rule/route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/create_rule/route.ts @@ -55,7 +55,6 @@ export const createRuleRoute = ( ]); const rulesClient = ctx.alerting.getRulesClient(); - const ruleExecutionLog = ctx.securitySolution.getRuleExecutionLog(); const savedObjectsClient = ctx.core.savedObjects.client; const exceptionsClient = ctx.lists?.getExceptionListClient(); @@ -99,9 +98,7 @@ export const createRuleRoute = ( params: request.body, }); - const ruleExecutionSummary = await ruleExecutionLog.getExecutionSummary(createdRule.id); - - const [validated, errors] = transformValidate(createdRule, ruleExecutionSummary); + const [validated, errors] = transformValidate(createdRule); if (errors != null) { return siemResponse.error({ statusCode: 500, body: errors }); } else { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/delete_rule/route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/delete_rule/route.ts index f5dfb61cd32ef..b4044e3dd9914 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/delete_rule/route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/delete_rule/route.ts @@ -46,7 +46,6 @@ export const deleteRuleRoute = (router: SecuritySolutionPluginRouter) => { const ctx = await context.resolve(['core', 'securitySolution', 'alerting']); const rulesClient = ctx.alerting.getRulesClient(); - const ruleExecutionLog = ctx.securitySolution.getRuleExecutionLog(); const savedObjectsClient = ctx.core.savedObjects.client; const rule = await readRules({ rulesClient, id, ruleId }); @@ -64,15 +63,12 @@ export const deleteRuleRoute = (router: SecuritySolutionPluginRouter) => { }); } - const ruleExecutionSummary = await ruleExecutionLog.getExecutionSummary(migratedRule.id); - await deleteRules({ ruleId: migratedRule.id, rulesClient, - ruleExecutionLog, }); - const transformed = transform(migratedRule, ruleExecutionSummary); + const transformed = transform(migratedRule); if (transformed == null) { return siemResponse.error({ statusCode: 500, body: 'failed to transform alert' }); } else { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/find_rules/route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/find_rules/route.ts index 34117ca07f817..8654a9dafd245 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/find_rules/route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/find_rules/route.ts @@ -49,7 +49,6 @@ export const findRulesRoute = (router: SecuritySolutionPluginRouter, logger: Log const { query } = request; const ctx = await context.resolve(['core', 'securitySolution', 'alerting']); const rulesClient = ctx.alerting.getRulesClient(); - const ruleExecutionLog = ctx.securitySolution.getRuleExecutionLog(); const savedObjectsClient = ctx.core.savedObjects.client; const rules = await findRules({ @@ -64,12 +63,13 @@ export const findRulesRoute = (router: SecuritySolutionPluginRouter, logger: Log const ruleIds = rules.data.map((rule) => rule.id); - const [ruleExecutionSummaries, ruleActions] = await Promise.all([ - ruleExecutionLog.getExecutionSummariesBulk(ruleIds), - legacyGetBulkRuleActionsSavedObject({ alertIds: ruleIds, savedObjectsClient, logger }), - ]); + const ruleActions = await legacyGetBulkRuleActionsSavedObject({ + alertIds: ruleIds, + savedObjectsClient, + logger, + }); - const transformed = transformFindAlerts(rules, ruleExecutionSummaries, ruleActions); + const transformed = transformFindAlerts(rules, ruleActions); if (transformed == null) { return siemResponse.error({ statusCode: 500, body: 'Internal error transforming' }); } else { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/patch_rule/route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/patch_rule/route.ts index 298891be82d33..a06c36a1502ea 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/patch_rule/route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/patch_rule/route.ts @@ -52,7 +52,6 @@ export const patchRuleRoute = (router: SecuritySolutionPluginRouter, ml: SetupPl try { const params = request.body; const rulesClient = (await context.alerting).getRulesClient(); - const ruleExecutionLog = (await context.securitySolution).getRuleExecutionLog(); const savedObjectsClient = (await context.core).savedObjects.client; const mlAuthz = buildMlAuthz({ @@ -96,9 +95,7 @@ export const patchRuleRoute = (router: SecuritySolutionPluginRouter, ml: SetupPl nextParams: params, }); if (rule != null && rule.enabled != null && rule.name != null) { - const ruleExecutionSummary = await ruleExecutionLog.getExecutionSummary(rule.id); - - const [validated, errors] = transformValidate(rule, ruleExecutionSummary); + const [validated, errors] = transformValidate(rule); if (errors != null) { return siemResponse.error({ statusCode: 500, body: errors }); } else { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/read_rule/route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/read_rule/route.ts index eaa58bf00a1be..eca9636842074 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/read_rule/route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/read_rule/route.ts @@ -45,7 +45,6 @@ export const readRuleRoute = (router: SecuritySolutionPluginRouter, logger: Logg try { const rulesClient = (await context.alerting).getRulesClient(); - const ruleExecutionLog = (await context.securitySolution).getRuleExecutionLog(); const savedObjectsClient = (await context.core).savedObjects.client; const rule = await readRules({ @@ -60,9 +59,7 @@ export const readRuleRoute = (router: SecuritySolutionPluginRouter, logger: Logg logger, }); - const ruleExecutionSummary = await ruleExecutionLog.getExecutionSummary(rule.id); - - const transformed = transform(rule, ruleExecutionSummary, legacyRuleActions); + const transformed = transform(rule, legacyRuleActions); if (transformed == null) { return siemResponse.error({ statusCode: 500, body: 'Internal error transforming' }); } else { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/update_rule/route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/update_rule/route.ts index 6e37b325dfd95..1f171b15df6e7 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/update_rule/route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/update_rule/route.ts @@ -84,9 +84,7 @@ export const updateRuleRoute = (router: SecuritySolutionPluginRouter, ml: SetupP }); if (rule != null) { - const ruleExecutionLog = ctx.securitySolution.getRuleExecutionLog(); - const ruleExecutionSummary = await ruleExecutionLog.getExecutionSummary(rule.id); - const [validated, errors] = transformValidate(rule, ruleExecutionSummary); + const [validated, errors] = transformValidate(rule); if (errors != null) { return siemResponse.error({ statusCode: 500, body: errors }); } else { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/crud/delete_rules.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/crud/delete_rules.test.ts index e7176b8d51af0..c34adec573f15 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/crud/delete_rules.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/crud/delete_rules.test.ts @@ -6,29 +6,24 @@ */ import { rulesClientMock } from '@kbn/alerting-plugin/server/mocks'; -import { ruleExecutionLogMock } from '../../../rule_monitoring/mocks'; import type { DeleteRuleOptions } from './delete_rules'; import { deleteRules } from './delete_rules'; describe('deleteRules', () => { let rulesClient: ReturnType; - let ruleExecutionLog: ReturnType; beforeEach(() => { rulesClient = rulesClientMock.create(); - ruleExecutionLog = ruleExecutionLogMock.forRoutes.create(); }); it('should delete the rule along with its actions, and statuses', async () => { const options: DeleteRuleOptions = { ruleId: 'ruleId', rulesClient, - ruleExecutionLog, }; await deleteRules(options); expect(rulesClient.delete).toHaveBeenCalledWith({ id: options.ruleId }); - expect(ruleExecutionLog.clearExecutionSummary).toHaveBeenCalledWith(options.ruleId); }); }); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/crud/delete_rules.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/crud/delete_rules.ts index a1190d8827c0d..e650c89fd96eb 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/crud/delete_rules.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/crud/delete_rules.ts @@ -7,15 +7,12 @@ import type { RulesClient } from '@kbn/alerting-plugin/server'; import type { RuleObjectId } from '../../../../../../common/detection_engine/rule_schema'; -import type { IRuleExecutionLogForRoutes } from '../../../rule_monitoring'; export interface DeleteRuleOptions { ruleId: RuleObjectId; rulesClient: RulesClient; - ruleExecutionLog: IRuleExecutionLogForRoutes; } -export const deleteRules = async ({ ruleId, rulesClient, ruleExecutionLog }: DeleteRuleOptions) => { +export const deleteRules = async ({ ruleId, rulesClient }: DeleteRuleOptions) => { await rulesClient.delete({ id: ruleId }); - await ruleExecutionLog.clearExecutionSummary(ruleId); }; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/export/get_export_by_object_ids.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/export/get_export_by_object_ids.ts index 67da643d503e4..60a7ec4c8185c 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/export/get_export_by_object_ids.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/export/get_export_by_object_ids.ts @@ -120,7 +120,7 @@ export const getRulesFromObjects = async ( ) { return { statusCode: 200, - rule: internalRuleToAPIResponse(matchingRule, null, legacyActions[matchingRule.id]), + rule: internalRuleToAPIResponse(matchingRule, legacyActions[matchingRule.id]), }; } else { return { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/normalization/rule_converters.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/normalization/rule_converters.ts index 4e2d17ec91803..9e06b584a06e9 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/normalization/rule_converters.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/normalization/rule_converters.ts @@ -19,7 +19,6 @@ import { } from '../../../../../common/constants'; import type { PatchRuleRequestBody } from '../../../../../common/detection_engine/rule_management'; -import type { RuleExecutionSummary } from '../../../../../common/detection_engine/rule_monitoring'; import type { RelatedIntegrationArray, RequiredFieldArray, @@ -54,7 +53,6 @@ import { assertUnreachable } from '../../../../../common/utility_types'; // eslint-disable-next-line no-restricted-imports import type { LegacyRuleActions } from '../../rule_actions_legacy'; -import { mergeRuleExecutionSummary } from '../../rule_monitoring'; import type { InternalRuleCreate, RuleParams, @@ -83,6 +81,7 @@ import { transformToNotifyWhen, } from './rule_actions'; import { convertAlertSuppressionToCamel, convertAlertSuppressionToSnake } from '../utils/utils'; +import { createRuleExecutionSummary } from '../../rule_monitoring'; // These functions provide conversions from the request API schema to the internal rule schema and from the internal rule schema // to the response API schema. This provides static type-check assurances that the internal schema is in sync with the API schema for @@ -669,13 +668,9 @@ export const commonParamsCamelToSnake = (params: BaseRuleParams) => { export const internalRuleToAPIResponse = ( rule: SanitizedRule | ResolvedSanitizedRule, - ruleExecutionSummary?: RuleExecutionSummary | null, legacyRuleActions?: LegacyRuleActions | null ): RuleResponse => { - const mergedExecutionSummary = mergeRuleExecutionSummary( - rule.executionStatus, - ruleExecutionSummary ?? null - ); + const executionSummary = createRuleExecutionSummary(rule); const isResolvedRule = (obj: unknown): obj is ResolvedSanitizedRule => (obj as ResolvedSanitizedRule).outcome != null; @@ -703,6 +698,6 @@ export const internalRuleToAPIResponse = ( throttle: transformFromAlertThrottle(rule, legacyRuleActions), actions: transformActions(rule.actions, legacyRuleActions), // Execution summary - execution_summary: mergedExecutionSummary ?? undefined, + execution_summary: executionSummary ?? undefined, }; }; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/utils/utils.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/utils/utils.test.ts index 4737fad57a7e9..91cdfc0e8a37b 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/utils/utils.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/utils/utils.test.ts @@ -277,7 +277,7 @@ describe('utils', () => { describe('transformFindAlerts', () => { test('outputs empty data set when data set is empty correct', () => { - const output = transformFindAlerts({ data: [], page: 1, perPage: 0, total: 0 }, {}, {}); + const output = transformFindAlerts({ data: [], page: 1, perPage: 0, total: 0 }, {}); expect(output).toEqual({ data: [], page: 1, perPage: 0, total: 0 }); }); @@ -289,7 +289,6 @@ describe('utils', () => { total: 0, data: [getRuleMock(getQueryRuleParams())], }, - {}, {} ); const expected = getOutputRuleAlertForRest(); @@ -309,7 +308,6 @@ describe('utils', () => { total: 0, data: [getRuleMock(getQueryRuleParams())], }, - {}, { '123': undefined, } @@ -348,7 +346,6 @@ describe('utils', () => { total: 0, data: [getRuleMock(getQueryRuleParams())], }, - {}, legacyRuleActions ); const expected = { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/utils/utils.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/utils/utils.ts index 3e3275321d7ab..5b09fe1b3a8cd 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/utils/utils.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/utils/utils.ts @@ -15,7 +15,6 @@ import type { PartialRule, FindResult } from '@kbn/alerting-plugin/server'; import type { ActionsClient, FindActionResult } from '@kbn/actions-plugin/server'; import type { RuleToImport } from '../../../../../common/detection_engine/rule_management'; -import type { RuleExecutionSummary } from '../../../../../common/detection_engine/rule_monitoring'; import type { AlertSuppression, RuleResponse, @@ -23,7 +22,6 @@ import type { // eslint-disable-next-line no-restricted-imports import type { LegacyRulesActionsSavedObject } from '../../rule_actions_legacy'; -import type { RuleExecutionSummariesByRuleId } from '../../rule_monitoring'; import type { AlertSuppressionCamel, RuleAlertType, RuleParams } from '../../rule_schema'; import { isAlertType } from '../../rule_schema'; import type { BulkError, OutputError } from '../../routes/utils'; @@ -96,12 +94,11 @@ export const transformAlertsToRules = ( rules: RuleAlertType[], legacyRuleActions: Record ): RuleResponse[] => { - return rules.map((rule) => internalRuleToAPIResponse(rule, null, legacyRuleActions[rule.id])); + return rules.map((rule) => internalRuleToAPIResponse(rule, legacyRuleActions[rule.id])); }; export const transformFindAlerts = ( ruleFindResults: FindResult, - ruleExecutionSummariesByRuleId: RuleExecutionSummariesByRuleId, legacyRuleActions: Record ): { page: number; @@ -114,19 +111,17 @@ export const transformFindAlerts = ( perPage: ruleFindResults.perPage, total: ruleFindResults.total, data: ruleFindResults.data.map((rule) => { - const executionSummary = ruleExecutionSummariesByRuleId[rule.id]; - return internalRuleToAPIResponse(rule, executionSummary, legacyRuleActions[rule.id]); + return internalRuleToAPIResponse(rule, legacyRuleActions[rule.id]); }), }; }; export const transform = ( rule: PartialRule, - ruleExecutionSummary?: RuleExecutionSummary | null, legacyRuleActions?: LegacyRulesActionsSavedObject | null ): RuleResponse | null => { if (isAlertType(rule)) { - return internalRuleToAPIResponse(rule, ruleExecutionSummary, legacyRuleActions); + return internalRuleToAPIResponse(rule, legacyRuleActions); } return null; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/utils/validate.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/utils/validate.test.ts index f90ce4a33b573..40ced9baaf28f 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/utils/validate.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/utils/validate.test.ts @@ -8,7 +8,6 @@ import { transformValidate, transformValidateBulkError } from './validate'; import type { BulkError } from '../../routes/utils'; import { getRuleMock } from '../../routes/__mocks__/request_responses'; -import { ruleExecutionSummaryMock } from '../../../../../common/detection_engine/rule_monitoring/mocks'; import { getListArrayMock } from '../../../../../common/detection_engine/schemas/types/lists.mock'; import { getThreatMock } from '../../../../../common/detection_engine/schemas/types/threat.mock'; import { getQueryRuleParams } from '../../rule_schema/mocks'; @@ -102,7 +101,7 @@ describe('validate', () => { describe('transformValidateBulkError', () => { test('it should do a validation correctly of a rule id', () => { const ruleAlert = getRuleMock(getQueryRuleParams()); - const validatedOrError = transformValidateBulkError('rule-1', ruleAlert, null); + const validatedOrError = transformValidateBulkError('rule-1', ruleAlert); expect(validatedOrError).toEqual(ruleOutput()); }); @@ -110,7 +109,7 @@ describe('validate', () => { const ruleAlert = getRuleMock(getQueryRuleParams()); // @ts-expect-error delete ruleAlert.name; - const validatedOrError = transformValidateBulkError('rule-1', ruleAlert, null); + const validatedOrError = transformValidateBulkError('rule-1', ruleAlert); const expected: BulkError = { error: { message: 'Invalid value "undefined" supplied to "name"', @@ -121,22 +120,11 @@ describe('validate', () => { expect(validatedOrError).toEqual(expected); }); - test('it should do a validation correctly of a rule id with rule execution summary passed in', () => { - const rule = getRuleMock(getQueryRuleParams()); - const ruleExecutionSumary = ruleExecutionSummaryMock.getSummarySucceeded(); - const validatedOrError = transformValidateBulkError('rule-1', rule, ruleExecutionSumary); - const expected: RuleResponse = { - ...ruleOutput(), - execution_summary: ruleExecutionSumary, - }; - expect(validatedOrError).toEqual(expected); - }); - test('it should return error object if "alert" is not expected alert type', () => { const ruleAlert = getRuleMock(getQueryRuleParams()); // @ts-expect-error delete ruleAlert.alertTypeId; - const validatedOrError = transformValidateBulkError('rule-1', ruleAlert, null); + const validatedOrError = transformValidateBulkError('rule-1', ruleAlert); const expected: BulkError = { error: { message: 'Internal error transforming', diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/utils/validate.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/utils/validate.ts index e784068e0248e..5ae9efb4501d5 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/utils/validate.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/utils/validate.ts @@ -8,7 +8,6 @@ import { validateNonExact } from '@kbn/securitysolution-io-ts-utils'; import type { PartialRule } from '@kbn/alerting-plugin/server'; -import type { RuleExecutionSummary } from '../../../../../common/detection_engine/rule_monitoring'; import { RuleResponse } from '../../../../../common/detection_engine/rule_schema'; import type { RuleParams } from '../../rule_schema'; import { isAlertType } from '../../rule_schema'; @@ -21,10 +20,9 @@ import { internalRuleToAPIResponse } from '../normalization/rule_converters'; export const transformValidate = ( rule: PartialRule, - ruleExecutionSummary: RuleExecutionSummary | null, legacyRuleActions?: LegacyRulesActionsSavedObject | null ): [RuleResponse | null, string | null] => { - const transformed = transform(rule, ruleExecutionSummary, legacyRuleActions); + const transformed = transform(rule, legacyRuleActions); if (transformed == null) { return [null, 'Internal error transforming']; } else { @@ -34,11 +32,10 @@ export const transformValidate = ( export const transformValidateBulkError = ( ruleId: string, - rule: PartialRule, - ruleExecutionSummary: RuleExecutionSummary | null + rule: PartialRule ): RuleResponse | BulkError => { if (isAlertType(rule)) { - const transformed = internalRuleToAPIResponse(rule, ruleExecutionSummary); + const transformed = internalRuleToAPIResponse(rule); const [validated, errors] = validateNonExact(transformed, RuleResponse); if (errors != null || validated == null) { return createBulkErrorObject({ diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/rule_execution_log/__mocks__/index.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/rule_execution_log/__mocks__/index.ts index e43a03c46a906..c0cb0cefa234e 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/rule_execution_log/__mocks__/index.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/rule_execution_log/__mocks__/index.ts @@ -8,7 +8,6 @@ import { getRuleExecutionEventsResponseMock, getRuleExecutionResultsResponseMock, - ruleExecutionSummaryMock, } from '../../../../../../../common/detection_engine/rule_monitoring/mocks'; import type { IRuleExecutionLogForRoutes } from '../client_for_routes/client_interface'; @@ -17,29 +16,11 @@ import type { RuleExecutionContext, } from '../client_for_executors/client_interface'; -type GetExecutionSummariesBulk = IRuleExecutionLogForRoutes['getExecutionSummariesBulk']; -type GetExecutionSummary = IRuleExecutionLogForRoutes['getExecutionSummary']; -type ClearExecutionSummary = IRuleExecutionLogForRoutes['clearExecutionSummary']; type GetExecutionEvents = IRuleExecutionLogForRoutes['getExecutionEvents']; type GetExecutionResults = IRuleExecutionLogForRoutes['getExecutionResults']; const ruleExecutionLogForRoutesMock = { create: (): jest.Mocked => ({ - getExecutionSummariesBulk: jest - .fn, Parameters>() - .mockResolvedValue({ - '04128c15-0d1b-4716-a4c5-46997ac7f3bd': ruleExecutionSummaryMock.getSummarySucceeded(), - '1ea5a820-4da1-4e82-92a1-2b43a7bece08': ruleExecutionSummaryMock.getSummaryFailed(), - }), - - getExecutionSummary: jest - .fn, Parameters>() - .mockResolvedValue(ruleExecutionSummaryMock.getSummarySucceeded()), - - clearExecutionSummary: jest - .fn, Parameters>() - .mockResolvedValue(), - getExecutionEvents: jest .fn, Parameters>() .mockResolvedValue(getRuleExecutionEventsResponseMock.getSomeResponse()), diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/rule_execution_log/client_for_executors/client.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/rule_execution_log/client_for_executors/client.ts index 3c712847851fd..a0cbe754d6b3c 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/rule_execution_log/client_for_executors/client.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/rule_execution_log/client_for_executors/client.ts @@ -9,17 +9,20 @@ import { sum } from 'lodash'; import type { Duration } from 'moment'; import type { Logger } from '@kbn/core/server'; +import type { + PublicRuleResultService, + PublicRuleMonitoringService, +} from '@kbn/alerting-plugin/server/types'; import type { RuleExecutionMetrics, RuleExecutionSettings, - RuleExecutionStatus, } from '../../../../../../../common/detection_engine/rule_monitoring'; import { LogLevel, logLevelFromExecutionStatus, LogLevelSetting, logLevelToNumber, - ruleExecutionStatusToNumber, + RuleExecutionStatus, } from '../../../../../../../common/detection_engine/rule_monitoring'; import { assertUnreachable } from '../../../../../../../common/utility_types'; @@ -29,7 +32,6 @@ import type { ExtMeta } from '../utils/console_logging'; import { getCorrelationIds } from './correlation_ids'; import type { IEventLogWriter } from '../event_log/event_log_writer'; -import type { IRuleExecutionSavedObjectsClient } from '../execution_saved_object/saved_objects_client'; import type { IRuleExecutionLogForExecutors, RuleExecutionContext, @@ -38,10 +40,11 @@ import type { export const createClientForExecutors = ( settings: RuleExecutionSettings, - soClient: IRuleExecutionSavedObjectsClient, eventLog: IEventLogWriter, logger: Logger, - context: RuleExecutionContext + context: RuleExecutionContext, + ruleMonitoringService: PublicRuleMonitoringService, + ruleResultService: PublicRuleResultService ): IRuleExecutionLogForExecutors => { const baseCorrelationIds = getCorrelationIds(context); const baseLogSuffix = baseCorrelationIds.getLogSuffix(); @@ -84,7 +87,7 @@ export const createClientForExecutors = ( await Promise.all([ writeStatusChangeToConsole(normalizedArgs, logMeta), - writeStatusChangeToSavedObjects(normalizedArgs), + writeStatusChangeToRuleObject(normalizedArgs), writeStatusChangeToEventLog(normalizedArgs), ]); } catch (e) { @@ -157,21 +160,38 @@ export const createClientForExecutors = ( writeMessageToConsole(logMessage, logLevel, logMeta); }; - // TODO: Add executionId to new status SO? - const writeStatusChangeToSavedObjects = async ( - args: NormalizedStatusChangeArgs - ): Promise => { + const writeStatusChangeToRuleObject = async (args: NormalizedStatusChangeArgs): Promise => { const { newStatus, message, metrics } = args; - await soClient.createOrUpdate(ruleId, { - last_execution: { - date: nowISO(), - status: newStatus, - status_order: ruleExecutionStatusToNumber(newStatus), - message, - metrics: metrics ?? {}, - }, - }); + if (newStatus === RuleExecutionStatus.running) { + return; + } + + const { + total_search_duration_ms: totalSearchDurationMs, + total_indexing_duration_ms: totalIndexingDurationMs, + execution_gap_duration_s: executionGapDurationS, + } = metrics ?? {}; + + if (totalSearchDurationMs) { + ruleMonitoringService.setLastRunMetricsTotalSearchDurationMs(totalSearchDurationMs); + } + + if (totalIndexingDurationMs) { + ruleMonitoringService.setLastRunMetricsTotalIndexingDurationMs(totalIndexingDurationMs); + } + + if (executionGapDurationS) { + ruleMonitoringService.setLastRunMetricsGapDurationS(executionGapDurationS); + } + + if (newStatus === RuleExecutionStatus.failed) { + ruleResultService.addLastRunError(message); + } else if (newStatus === RuleExecutionStatus['partial failure']) { + ruleResultService.addLastRunWarning(message); + } + + ruleResultService.setLastRunOutcomeMessage(message); }; const writeStatusChangeToEventLog = (args: NormalizedStatusChangeArgs): void => { @@ -204,8 +224,6 @@ export const createClientForExecutors = ( return client; }; -const nowISO = () => new Date().toISOString(); - interface NormalizedStatusChangeArgs { newStatus: RuleExecutionStatus; message: string; @@ -213,6 +231,12 @@ interface NormalizedStatusChangeArgs { } const normalizeStatusChangeArgs = (args: StatusChangeArgs): NormalizedStatusChangeArgs => { + if (args.newStatus === RuleExecutionStatus.running) { + return { + newStatus: args.newStatus, + message: '', + }; + } const { newStatus, message, metrics } = args; return { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/rule_execution_log/client_for_executors/client_interface.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/rule_execution_log/client_for_executors/client_interface.ts index 5e48a43e949c3..cb65b42d50b69 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/rule_execution_log/client_for_executors/client_interface.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/rule_execution_log/client_for_executors/client_interface.ts @@ -103,6 +103,10 @@ export interface RuleExecutionContext { spaceId: string; } +export interface RunningStatusChangeArgs { + newStatus: RuleExecutionStatus.running; +} + /** * Information about the status change event. */ diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/rule_execution_log/client_for_routes/client.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/rule_execution_log/client_for_routes/client.ts index 095c77d86a4ce..f760eb9cd2455 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/rule_execution_log/client_for_routes/client.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/rule_execution_log/client_for_routes/client.ts @@ -5,122 +5,27 @@ * 2.0. */ -import { chunk, mapValues } from 'lodash'; import type { Logger } from '@kbn/core/server'; -import { initPromisePool } from '../../../../../../utils/promise_pool'; import { withSecuritySpan } from '../../../../../../utils/with_security_span'; import type { ExtMeta } from '../utils/console_logging'; -import { truncateList } from '../utils/normalization'; import type { GetRuleExecutionEventsResponse, GetRuleExecutionResultsResponse, - RuleExecutionSummary, } from '../../../../../../../common/detection_engine/rule_monitoring'; import type { IEventLogReader } from '../event_log/event_log_reader'; -import type { IRuleExecutionSavedObjectsClient } from '../execution_saved_object/saved_objects_client'; import type { GetExecutionEventsArgs, GetExecutionResultsArgs, IRuleExecutionLogForRoutes, - RuleExecutionSummariesByRuleId, } from './client_interface'; -const RULES_PER_CHUNK = 1000; - export const createClientForRoutes = ( - soClient: IRuleExecutionSavedObjectsClient, eventLog: IEventLogReader, logger: Logger ): IRuleExecutionLogForRoutes => { return { - getExecutionSummariesBulk: (ruleIds: string[]): Promise => { - return withSecuritySpan('IRuleExecutionLogForRoutes.getExecutionSummariesBulk', async () => { - try { - // This method splits work into chunks so not to overwhelm Elasticsearch - // when fetching statuses for a big number of rules. - const ruleIdsChunks = chunk(ruleIds, RULES_PER_CHUNK); - - const { results, errors } = await initPromisePool({ - concurrency: 1, - items: ruleIdsChunks, - executor: async (ruleIdsChunk) => { - try { - const savedObjectsByRuleId = await soClient.getManyByRuleIds(ruleIdsChunk); - return mapValues(savedObjectsByRuleId, (so) => so?.attributes ?? null); - } catch (e) { - const ruleIdsString = `[${truncateList(ruleIdsChunk).join(', ')}]`; - - const logMessage = 'Error fetching a chunk of rule execution saved objects'; - const logReason = e instanceof Error ? e.stack ?? e.message : String(e); - const logSuffix = `[${ruleIdsChunk.length} rules][rule ids: ${ruleIdsString}]`; - - logger.error(`${logMessage}: ${logReason} ${logSuffix}`); - throw e; - } - }, - }); - - if (errors.length) { - const numAllChunks = ruleIdsChunks.length; - const numFailedChunks = errors.length; - const message = `Error fetching rule execution saved objects in chunks: ${numFailedChunks}/${numAllChunks} chunks failed`; - throw new AggregateError(errors, message); - } - - // Merge all rule statuses into a single dict - return Object.assign({}, ...results.map(({ result }) => result)); - } catch (e) { - const ruleIdsString = `[${truncateList(ruleIds).join(', ')}]`; - - const logMessage = 'Error bulk getting rule execution summaries'; - const logReason = e instanceof Error ? e.message : String(e); - const logSuffix = `[${ruleIds.length} rules][rule ids: ${ruleIdsString}]`; - - logger.error(`${logMessage}: ${logReason} ${logSuffix}`); - throw e; - } - }); - }, - - getExecutionSummary: (ruleId: string): Promise => { - return withSecuritySpan('IRuleExecutionLogForRoutes.getExecutionSummary', async () => { - try { - const savedObject = await soClient.getOneByRuleId(ruleId); - return savedObject ? savedObject.attributes : null; - } catch (e) { - const logMessage = 'Error getting rule execution summary'; - const logReason = e instanceof Error ? e.message : String(e); - const logSuffix = `[rule id ${ruleId}]`; - const logMeta: ExtMeta = { - rule: { id: ruleId }, - }; - - logger.error(`${logMessage}: ${logReason} ${logSuffix}`, logMeta); - throw e; - } - }); - }, - - clearExecutionSummary: (ruleId: string): Promise => { - return withSecuritySpan('IRuleExecutionLogForRoutes.clearExecutionSummary', async () => { - try { - await soClient.delete(ruleId); - } catch (e) { - const logMessage = 'Error clearing rule execution summary'; - const logReason = e instanceof Error ? e.message : String(e); - const logSuffix = `[rule id ${ruleId}]`; - const logMeta: ExtMeta = { - rule: { id: ruleId }, - }; - - logger.error(`${logMessage}: ${logReason} ${logSuffix}`, logMeta); - throw e; - } - }); - }, - getExecutionEvents: (args: GetExecutionEventsArgs): Promise => { return withSecuritySpan('IRuleExecutionLogForRoutes.getExecutionEvents', async () => { const { ruleId } = args; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/rule_execution_log/client_for_routes/client_interface.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/rule_execution_log/client_for_routes/client_interface.ts index dec3990654b80..a3fb5365181eb 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/rule_execution_log/client_for_routes/client_interface.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/rule_execution_log/client_for_routes/client_interface.ts @@ -12,7 +12,6 @@ import type { LogLevel, RuleExecutionEventType, RuleExecutionStatus, - RuleExecutionSummary, SortFieldOfRuleExecutionResult, } from '../../../../../../../common/detection_engine/rule_monitoring'; @@ -22,26 +21,6 @@ import type { * - execution events such as recent failures and status changes */ export interface IRuleExecutionLogForRoutes { - /** - * Fetches a list of current execution summaries of multiple rules. - * @param ruleIds A list of saved object ids of multiple rules (`rule.id`). - * @returns A dict with rule IDs as keys and execution summaries as values. - * @throws AggregateError if any of the rule status requests fail. - */ - getExecutionSummariesBulk(ruleIds: string[]): Promise; - - /** - * Fetches current execution summary of a given rule. - * @param ruleId Saved object id of the rule (`rule.id`). - */ - getExecutionSummary(ruleId: string): Promise; - - /** - * Deletes the current execution summary if it exists. - * @param ruleId Saved object id of the rule (`rule.id`). - */ - clearExecutionSummary(ruleId: string): Promise; - /** * Fetches plain execution events of a given rule from Event Log. This includes debug, info, and * error messages that executor functions write during a rule execution to the log. @@ -103,5 +82,3 @@ export interface GetExecutionResultsArgs { /** Number of results to fetch per page. */ perPage: number; } - -export type RuleExecutionSummariesByRuleId = Record; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/rule_execution_log/create_rule_execution_summary.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/rule_execution_log/create_rule_execution_summary.ts new file mode 100644 index 0000000000000..c12dbf9c36d9c --- /dev/null +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/rule_execution_log/create_rule_execution_summary.ts @@ -0,0 +1,54 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { ResolvedSanitizedRule, SanitizedRule } from '@kbn/alerting-plugin/common'; + +import type { RuleExecutionSummary } from '../../../../../../common/detection_engine/rule_monitoring'; +import { + ruleLastRunOutcomeToExecutionStatus, + ruleExecutionStatusToNumber, + RuleExecutionStatus, +} from '../../../../../../common/detection_engine/rule_monitoring'; +import type { RuleParams } from '../../../rule_schema'; + +export const createRuleExecutionSummary = ( + rule: SanitizedRule | ResolvedSanitizedRule +): RuleExecutionSummary | null => { + if (rule.running) { + return { + last_execution: { + date: new Date().toISOString(), + message: '', + metrics: {}, + status: RuleExecutionStatus.running, + status_order: ruleExecutionStatusToNumber(RuleExecutionStatus.running), + }, + }; + } + + if (!rule.lastRun) { + return null; + } + + const ruleExecutionStatus = ruleLastRunOutcomeToExecutionStatus(rule.lastRun.outcome); + + return { + last_execution: { + date: rule.monitoring?.run.last_run?.timestamp ?? new Date().toISOString(), + status: ruleExecutionStatus, + status_order: ruleExecutionStatusToNumber(ruleExecutionStatus), + message: rule.lastRun?.outcomeMsg?.join(' \n') ?? '', + metrics: { + total_indexing_duration_ms: + rule.monitoring?.run.last_run.metrics.total_indexing_duration_ms ?? undefined, + total_search_duration_ms: + rule.monitoring?.run.last_run.metrics.total_search_duration_ms ?? undefined, + execution_gap_duration_s: rule.monitoring?.run.last_run.metrics.gap_duration_s ?? undefined, + }, + }, + }; +}; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/rule_execution_log/execution_saved_object/saved_objects_client.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/rule_execution_log/execution_saved_object/saved_objects_client.ts deleted file mode 100644 index 08a7c49f739c0..0000000000000 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/rule_execution_log/execution_saved_object/saved_objects_client.ts +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { Logger, SavedObjectsClientContract } from '@kbn/core/server'; -import { SavedObjectsErrorHelpers } from '@kbn/core/server'; - -import { withSecuritySpan } from '../../../../../../utils/with_security_span'; - -import type { RuleExecutionSavedObject, RuleExecutionAttributes } from './saved_objects_type'; -import { RULE_EXECUTION_SO_TYPE } from './saved_objects_type'; -import { - getRuleExecutionSoId, - getRuleExecutionSoReferences, - extractRuleIdFromReferences, -} from './saved_objects_utils'; - -export interface IRuleExecutionSavedObjectsClient { - createOrUpdate( - ruleId: string, - attributes: RuleExecutionAttributes - ): Promise; - - delete(ruleId: string): Promise; - - getOneByRuleId(ruleId: string): Promise; - - getManyByRuleIds(ruleIds: string[]): Promise; -} - -export type RuleExecutionSavedObjectsByRuleId = Record; - -export const createRuleExecutionSavedObjectsClient = ( - soClient: SavedObjectsClientContract, - logger: Logger -): IRuleExecutionSavedObjectsClient => { - return { - async createOrUpdate(ruleId, attributes) { - const id = getRuleExecutionSoId(ruleId); - const references = getRuleExecutionSoReferences(ruleId); - - const result = await withSecuritySpan('createOrUpdateRuleExecutionSO', () => { - return soClient.create(RULE_EXECUTION_SO_TYPE, attributes, { - id, - references, - overwrite: true, - }); - }); - - return result; - }, - - async delete(ruleId) { - try { - const id = getRuleExecutionSoId(ruleId); - await withSecuritySpan('deleteRuleExecutionSO', () => { - return soClient.delete(RULE_EXECUTION_SO_TYPE, id); - }); - } catch (e) { - if (SavedObjectsErrorHelpers.isNotFoundError(e)) { - return; - } - throw e; - } - }, - - async getOneByRuleId(ruleId) { - try { - const id = getRuleExecutionSoId(ruleId); - return await withSecuritySpan('getRuleExecutionSO', () => { - return soClient.get(RULE_EXECUTION_SO_TYPE, id); - }); - } catch (e) { - if (SavedObjectsErrorHelpers.isNotFoundError(e)) { - return null; - } - throw e; - } - }, - - async getManyByRuleIds(ruleIds) { - const ids = ruleIds - .map((id) => getRuleExecutionSoId(id)) - .map((id) => ({ id, type: RULE_EXECUTION_SO_TYPE })); - - const response = await withSecuritySpan('bulkGetRuleExecutionSOs', () => { - return soClient.bulkGet(ids); - }); - - const result = prepopulateRuleExecutionSavedObjectsByRuleId(ruleIds); - - response.saved_objects.forEach((so) => { - // NOTE: We need to explicitly check that this saved object is not an error result and has references in it. - // "Saved object" may not actually contain most of its properties (despite the fact that they are required - // in its TypeScript interface), for example if it wasn't found. In this case it will look like that: - // { - // id: '64b51590-a87e-5afc-9ede-906c3f3483b7', - // type: 'siem-detection-engine-rule-execution-info', - // error: { - // statusCode: 404, - // error: 'Not Found', - // message: 'Saved object [siem-detection-engine-rule-execution-info/64b51590-a87e-5afc-9ede-906c3f3483b7] not found' - // }, - // namespaces: undefined - // } - const hasReferences = !so.error && so.references && Array.isArray(so.references); - const references = hasReferences ? so.references : []; - - const ruleId = extractRuleIdFromReferences(references); - if (ruleId) { - result[ruleId] = so; - } - - if (so.error && so.error.statusCode !== 404) { - logger.error(so.error.message); - } - }); - - return result; - }, - }; -}; - -const prepopulateRuleExecutionSavedObjectsByRuleId = (ruleIds: string[]) => { - const result: RuleExecutionSavedObjectsByRuleId = {}; - ruleIds.forEach((ruleId) => { - result[ruleId] = null; - }); - return result; -}; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/rule_execution_log/execution_saved_object/saved_objects_type.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/rule_execution_log/execution_saved_object/saved_objects_type.ts deleted file mode 100644 index 1e0a2e74cadcd..0000000000000 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/rule_execution_log/execution_saved_object/saved_objects_type.ts +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { SavedObject, SavedObjectsType } from '@kbn/core/server'; -import type { - RuleExecutionMetrics, - RuleExecutionStatus, - RuleExecutionStatusOrder, -} from '../../../../../../../common/detection_engine/rule_monitoring'; - -export const RULE_EXECUTION_SO_TYPE = 'siem-detection-engine-rule-execution-info'; - -/** - * This side-car SO stores information about rule executions (like last status and metrics). - * Eventually we're going to replace it with data stored in the rule itself: - * https://github.com/elastic/kibana/issues/112193 - */ -export type RuleExecutionSavedObject = SavedObject; - -export interface RuleExecutionAttributes { - last_execution: { - date: string; - status: RuleExecutionStatus; - status_order: RuleExecutionStatusOrder; - message: string; - metrics: RuleExecutionMetrics; - }; -} - -const ruleExecutionMappings: SavedObjectsType['mappings'] = { - properties: { - last_execution: { - type: 'object', - properties: { - date: { - type: 'date', - }, - status: { - type: 'keyword', - ignore_above: 1024, - }, - status_order: { - type: 'long', - }, - message: { - type: 'text', - }, - metrics: { - type: 'object', - properties: { - total_search_duration_ms: { - type: 'long', - }, - total_indexing_duration_ms: { - type: 'long', - }, - total_enrichment_duration_ms: { - type: 'long', - }, - execution_gap_duration_s: { - type: 'long', - }, - }, - }, - }, - }, - }, -}; - -export const ruleExecutionType: SavedObjectsType = { - name: RULE_EXECUTION_SO_TYPE, - mappings: ruleExecutionMappings, - hidden: false, - namespaceType: 'multiple-isolated', - convertToMultiNamespaceTypeVersion: '8.0.0', -}; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/rule_execution_log/execution_saved_object/saved_objects_utils.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/rule_execution_log/execution_saved_object/saved_objects_utils.ts deleted file mode 100644 index 9d84a1731b088..0000000000000 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/rule_execution_log/execution_saved_object/saved_objects_utils.ts +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { v5 as uuidv5 } from 'uuid'; -import type { SavedObjectReference } from '@kbn/core/server'; -import { RULE_EXECUTION_SO_TYPE } from './saved_objects_type'; - -export const getRuleExecutionSoId = (ruleId: string): string => { - // The uuidv5 namespace constant (uuidv5.DNS) is arbitrary. - return uuidv5(`${RULE_EXECUTION_SO_TYPE}:${ruleId}`, uuidv5.DNS); -}; - -const RULE_REFERENCE_TYPE = 'alert'; -const RULE_REFERENCE_NAME = 'alert_0'; - -export const getRuleExecutionSoReferences = (ruleId: string): SavedObjectReference[] => { - return [ - { - id: ruleId, - type: RULE_REFERENCE_TYPE, - name: RULE_REFERENCE_NAME, - }, - ]; -}; - -export const extractRuleIdFromReferences = (references: SavedObjectReference[]): string | null => { - const foundReference = references.find( - (r) => r.type === RULE_REFERENCE_TYPE && r.name === RULE_REFERENCE_NAME - ); - - return foundReference?.id || null; -}; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/rule_execution_log/index.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/rule_execution_log/index.ts index 1cc6be1e0c6c4..40f9babb53af5 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/rule_execution_log/index.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/rule_execution_log/index.ts @@ -10,8 +10,6 @@ export * from './client_for_routes/client_interface'; export * from './service_interface'; export * from './service'; -export { ruleExecutionType } from './execution_saved_object/saved_objects_type'; - export { RULE_EXECUTION_LOG_PROVIDER } from './event_log/constants'; -export { mergeRuleExecutionSummary } from './merge_rule_execution_summary'; +export { createRuleExecutionSummary } from './create_rule_execution_summary'; export * from './utils/normalization'; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/rule_execution_log/merge_rule_execution_summary.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/rule_execution_log/merge_rule_execution_summary.ts deleted file mode 100644 index cf403f3d6b66c..0000000000000 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/rule_execution_log/merge_rule_execution_summary.ts +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { RuleExecutionStatus as RuleExecutionStatusByFramework } from '@kbn/alerting-plugin/common'; - -import type { RuleExecutionSummary } from '../../../../../../common/detection_engine/rule_monitoring'; -import { - RuleExecutionStatus, - ruleExecutionStatusToNumber, -} from '../../../../../../common/detection_engine/rule_monitoring'; - -export const mergeRuleExecutionSummary = ( - ruleExecutionStatus: RuleExecutionStatusByFramework, - ruleExecutionSummary: RuleExecutionSummary | null -): RuleExecutionSummary | null => { - if (ruleExecutionSummary == null) { - return null; - } - - const frameworkStatus = ruleExecutionStatus; - const customStatus = ruleExecutionSummary.last_execution; - - if ( - frameworkStatus.status === 'error' && - new Date(frameworkStatus.lastExecutionDate) > new Date(customStatus.date) - ) { - return { - ...ruleExecutionSummary, - last_execution: { - date: frameworkStatus.lastExecutionDate.toISOString(), - status: RuleExecutionStatus.failed, - status_order: ruleExecutionStatusToNumber(RuleExecutionStatus.failed), - message: `Reason: ${frameworkStatus.error?.reason} Message: ${frameworkStatus.error?.message}`, - metrics: customStatus.metrics, - }, - }; - } - - return ruleExecutionSummary; -}; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/rule_execution_log/service.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/rule_execution_log/service.ts index db5aefdaf7370..cea7f5d23a14f 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/rule_execution_log/service.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/rule_execution_log/service.ts @@ -6,6 +6,7 @@ */ import type { Logger } from '@kbn/core/server'; +import { invariant } from '../../../../../../common/utils/invariant'; import type { ConfigType } from '../../../../../config'; import { withSecuritySpan } from '../../../../../utils/with_security_span'; import type { @@ -21,7 +22,6 @@ import { createClientForExecutors } from './client_for_executors/client'; import { registerEventLogProvider } from './event_log/register_event_log_provider'; import { createEventLogReader } from './event_log/event_log_reader'; import { createEventLogWriter } from './event_log/event_log_writer'; -import { createRuleExecutionSavedObjectsClient } from './execution_saved_object/saved_objects_client'; import { fetchRuleExecutionSettings } from './execution_settings/fetch_rule_execution_settings'; import type { ClientForExecutorsParams, @@ -41,19 +41,21 @@ export const createRuleExecutionLogService = ( }, createClientForRoutes: (params: ClientForRoutesParams): IRuleExecutionLogForRoutes => { - const { savedObjectsClient, eventLogClient } = params; + const { eventLogClient } = params; - const soClient = createRuleExecutionSavedObjectsClient(savedObjectsClient, logger); const eventLogReader = createEventLogReader(eventLogClient); - return createClientForRoutes(soClient, eventLogReader, logger); + return createClientForRoutes(eventLogReader, logger); }, createClientForExecutors: ( params: ClientForExecutorsParams ): Promise => { return withSecuritySpan('IRuleExecutionLogService.createClientForExecutors', async () => { - const { savedObjectsClient, context } = params; + const { savedObjectsClient, context, ruleMonitoringService, ruleResultService } = params; + + invariant(ruleMonitoringService, 'ruleMonitoringService required for detection rules'); + invariant(ruleResultService, 'ruleResultService required for detection rules'); const childLogger = logger.get('ruleExecution'); @@ -64,15 +66,15 @@ export const createRuleExecutionLogService = ( savedObjectsClient ); - const soClient = createRuleExecutionSavedObjectsClient(savedObjectsClient, childLogger); const eventLogWriter = createEventLogWriter(plugins.eventLog); return createClientForExecutors( ruleExecutionSettings, - soClient, eventLogWriter, childLogger, - context + context, + ruleMonitoringService, + ruleResultService ); }); }, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/rule_execution_log/service_interface.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/rule_execution_log/service_interface.ts index 27207ea2afde0..aa8d5e0bfee36 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/rule_execution_log/service_interface.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/rule_execution_log/service_interface.ts @@ -8,6 +8,10 @@ import type { SavedObjectsClientContract } from '@kbn/core/server'; import type { IEventLogClient } from '@kbn/event-log-plugin/server'; +import type { + PublicRuleResultService, + PublicRuleMonitoringService, +} from '@kbn/alerting-plugin/server/types'; import type { IRuleExecutionLogForRoutes } from './client_for_routes/client_interface'; import type { IRuleExecutionLogForExecutors, @@ -31,5 +35,7 @@ export interface ClientForRoutesParams { export interface ClientForExecutorsParams { savedObjectsClient: SavedObjectsClientContract; + ruleMonitoringService?: PublicRuleMonitoringService; + ruleResultService?: PublicRuleResultService; context: RuleExecutionContext; } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_preview/api/preview_rules/route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_preview/api/preview_rules/route.ts index 24aaf9ac4cd0c..457412dd01501 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_preview/api/preview_rules/route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_preview/api/preview_rules/route.ts @@ -267,7 +267,7 @@ export const previewRulesRoute = async ( const errors = loggedStatusChanges .filter((item) => item.newStatus === RuleExecutionStatus.failed) - .map((item) => item.message ?? 'Unkown Error'); + .map((item) => item.message ?? 'Unknown Error'); const warnings = loggedStatusChanges .filter((item) => item.newStatus === RuleExecutionStatus['partial failure']) 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 9c6b80f80fd79..270a521c78e13 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 @@ -88,6 +88,8 @@ export const createSecurityRuleTypeWrapper: CreateSecurityRuleTypeWrapper = savedObjectsClient, scopedClusterClient, uiSettingsClient, + ruleMonitoringService, + ruleResultService, } = services; const searchAfterSize = Math.min(maxSignals, DEFAULT_SEARCH_AFTER_PAGE_SIZE); @@ -95,6 +97,8 @@ export const createSecurityRuleTypeWrapper: CreateSecurityRuleTypeWrapper = const ruleExecutionLogger = await ruleExecutionLoggerFactory({ savedObjectsClient, + ruleMonitoringService, + ruleResultService, context: { executionId, ruleId: rule.id, diff --git a/x-pack/plugins/security_solution/server/saved_objects.ts b/x-pack/plugins/security_solution/server/saved_objects.ts index bc1d86add3767..7ce17ff0c0b51 100644 --- a/x-pack/plugins/security_solution/server/saved_objects.ts +++ b/x-pack/plugins/security_solution/server/saved_objects.ts @@ -10,7 +10,6 @@ import type { CoreSetup } from '@kbn/core/server'; import { noteType, pinnedEventType, timelineType } from './lib/timeline/saved_object_mappings'; // eslint-disable-next-line no-restricted-imports import { legacyType as legacyRuleActionsType } from './lib/detection_engine/rule_actions_legacy'; -import { ruleExecutionType } from './lib/detection_engine/rule_monitoring'; import { ruleAssetType } from './lib/detection_engine/prebuilt_rules/logic/rule_asset/rule_asset_saved_object_mappings'; import { type as signalsMigrationType } from './lib/detection_engine/migrations/saved_objects'; import { @@ -22,7 +21,6 @@ const types = [ noteType, pinnedEventType, legacyRuleActionsType, - ruleExecutionType, ruleAssetType, timelineType, exceptionsArtifactType, diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/check_privileges.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/check_privileges.ts index 0b7de71969a7b..b4ae68bb8d61c 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/check_privileges.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/check_privileges.ts @@ -84,7 +84,13 @@ export default ({ getService }: FtrProviderContext) => { await deleteUserAndRole(getService, ROLES.detections_admin); }); + }); + const thresholdIndexTestCases = [ + ['host_alias', 'auditbeat-8.0.0'], + ['host_alias*', 'auditbeat-*'], + ]; + thresholdIndexTestCases.forEach((index) => { it(`for threshold rule with index param: ${index}`, async () => { const rule: ThresholdRuleCreateProps = { ...getThresholdRuleForSignalTesting(index),