From 526f376ff1e3833fd4185f75eeef0172dc55b7f9 Mon Sep 17 00:00:00 2001 From: Ying Date: Wed, 14 Dec 2022 12:48:19 -0500 Subject: [PATCH] Adding autoRecoverAlerts flag to rule type to determine whether recovery alerts should be calculated and alerts stored in task state. Hacking 1h throttle to 5m for testing --- .../alerting/server/lib/process_alerts.ts | 13 +++++++++-- x-pack/plugins/alerting/server/plugin.ts | 2 ++ .../server/task_runner/task_runner.ts | 23 ++++++++++++++----- x-pack/plugins/alerting/server/types.ts | 6 +++++ .../create_persistence_rule_type_wrapper.ts | 1 + .../logic/crud/update_rules.ts | 2 +- .../normalization/rule_converters.ts | 4 ++-- .../create_security_rule_type_wrapper.ts | 1 + 8 files changed, 41 insertions(+), 11 deletions(-) diff --git a/x-pack/plugins/alerting/server/lib/process_alerts.ts b/x-pack/plugins/alerting/server/lib/process_alerts.ts index 40c86dc461ab0..6ce363742a3d8 100644 --- a/x-pack/plugins/alerting/server/lib/process_alerts.ts +++ b/x-pack/plugins/alerting/server/lib/process_alerts.ts @@ -20,6 +20,7 @@ interface ProcessAlertsOpts< previouslyRecoveredAlerts: Record>; hasReachedAlertLimit: boolean; alertLimit: number; + autoRecoverAlerts: boolean; // flag used to determine whether or not we want to push the flapping state on to the flappingHistory array setFlapping: boolean; } @@ -47,6 +48,7 @@ export function processAlerts< previouslyRecoveredAlerts, hasReachedAlertLimit, alertLimit, + autoRecoverAlerts, setFlapping, }: ProcessAlertsOpts): ProcessAlertsResult< State, @@ -62,7 +64,13 @@ export function processAlerts< alertLimit, setFlapping ) - : processAlertsHelper(alerts, existingAlerts, previouslyRecoveredAlerts, setFlapping); + : processAlertsHelper( + alerts, + existingAlerts, + previouslyRecoveredAlerts, + autoRecoverAlerts, + setFlapping + ); } function processAlertsHelper< @@ -74,6 +82,7 @@ function processAlertsHelper< alerts: Record>, existingAlerts: Record>, previouslyRecoveredAlerts: Record>, + autoRecoverAlerts: boolean, setFlapping: boolean ): ProcessAlertsResult { const existingAlertIds = new Set(Object.keys(existingAlerts)); @@ -123,7 +132,7 @@ function processAlertsHelper< updateAlertFlappingHistory(activeAlerts[id], false); } } - } else if (existingAlertIds.has(id)) { + } else if (existingAlertIds.has(id) && autoRecoverAlerts) { recoveredAlerts[id] = alerts[id]; currentRecoveredAlerts[id] = alerts[id]; diff --git a/x-pack/plugins/alerting/server/plugin.ts b/x-pack/plugins/alerting/server/plugin.ts index 48d1bfee78e40..3ec7f81eb0da0 100644 --- a/x-pack/plugins/alerting/server/plugin.ts +++ b/x-pack/plugins/alerting/server/plugin.ts @@ -335,6 +335,8 @@ export class AlertingPlugin { ruleType.cancelAlertsOnRuleTimeout = ruleType.cancelAlertsOnRuleTimeout ?? this.config.cancelAlertsOnRuleTimeout; ruleType.doesSetRecoveryContext = ruleType.doesSetRecoveryContext ?? false; + ruleType.autoRecoverAlerts = + ruleType.autoRecoverAlerts === undefined ? true : ruleType.autoRecoverAlerts; ruleTypeRegistry.register(ruleType); }, getSecurityHealth: async () => { diff --git a/x-pack/plugins/alerting/server/task_runner/task_runner.ts b/x-pack/plugins/alerting/server/task_runner/task_runner.ts index 4bde4489dc00b..1b55981240ccf 100644 --- a/x-pack/plugins/alerting/server/task_runner/task_runner.ts +++ b/x-pack/plugins/alerting/server/task_runner/task_runner.ts @@ -49,6 +49,7 @@ import { RuleTypeState, parseDuration, WithoutReservedActionGroups, + RawAlertInstance, } from '../../common'; import { NormalizedRuleType, UntypedNormalizedRuleType } from '../rule_type_registry'; import { getEsErrorMessage } from '../lib/errors'; @@ -415,6 +416,8 @@ export class TaskRunner< previouslyRecoveredAlerts: originalRecoveredAlerts, hasReachedAlertLimit, alertLimit: this.maxAlerts, + autoRecoverAlerts: + this.ruleType.autoRecoverAlerts !== undefined ? this.ruleType.autoRecoverAlerts : true, setFlapping: true, }); @@ -479,12 +482,20 @@ export class TaskRunner< } }); - const { alertsToReturn, recoveredAlertsToReturn } = determineAlertsToReturn< - State, - Context, - ActionGroupIds, - RecoveryActionGroupId - >(activeAlerts, recoveredAlerts); + let alertsToReturn: Record = {}; + let recoveredAlertsToReturn: Record = {}; + + // Only serialize alerts into task state if we're auto-recovering, otherwise + // we don't need to keep this information around. + if (this.ruleType.autoRecoverAlerts) { + const { alertsToReturn: alerts, recoveredAlertsToReturn: recovered } = + determineAlertsToReturn( + activeAlerts, + recoveredAlerts + ); + alertsToReturn = alerts; + recoveredAlertsToReturn = recovered; + } return { metrics: ruleRunMetricsStore.getMetrics(), diff --git a/x-pack/plugins/alerting/server/types.ts b/x-pack/plugins/alerting/server/types.ts index c2af1555cfa36..cf4625d38ab54 100644 --- a/x-pack/plugins/alerting/server/types.ts +++ b/x-pack/plugins/alerting/server/types.ts @@ -196,6 +196,12 @@ export interface RuleType< cancelAlertsOnRuleTimeout?: boolean; doesSetRecoveryContext?: boolean; getSummarizedAlerts?: GetSummarizedAlertsFn; + + /** + * Determines whether framework should + * automatically make recovery determination. Defaults to true. + */ + autoRecoverAlerts?: boolean; } export type UntypedRuleType = RuleType< RuleTypeParams, diff --git a/x-pack/plugins/rule_registry/server/utils/create_persistence_rule_type_wrapper.ts b/x-pack/plugins/rule_registry/server/utils/create_persistence_rule_type_wrapper.ts index bc898ae65c90f..3c4bc838506c1 100644 --- a/x-pack/plugins/rule_registry/server/utils/create_persistence_rule_type_wrapper.ts +++ b/x-pack/plugins/rule_registry/server/utils/create_persistence_rule_type_wrapper.ts @@ -137,6 +137,7 @@ export const createPersistenceRuleTypeWrapper: CreatePersistenceRuleTypeWrapper }; }) .filter((_, idx) => response.body.items[idx].create?.status === 201); + console.log(`persistence alerts ${createdAlerts.length}`); createdAlerts.forEach((alert) => options.services.alertFactory.create(alert._id).scheduleActions('default', {}) diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/crud/update_rules.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/crud/update_rules.ts index 518f18a67947e..910a984b029e1 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/crud/update_rules.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/crud/update_rules.ts @@ -87,7 +87,7 @@ export const updateRules = async ({ frequency: { summary: throttle !== null, notifyWhen, - throttle, + throttle: throttle === '1h' ? '5m' : throttle, }, }; }) 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 fbf9604d36caf..3364bb0c81daa 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 @@ -476,7 +476,7 @@ export const convertPatchAPIToInternalSchema = ( frequency: { summary: throttle !== null, notifyWhen, - throttle, + throttle: throttle === '1h' ? '5m' : throttle, }, }; }) @@ -546,7 +546,7 @@ export const convertCreateAPIToInternalSchema = ( frequency: { summary: throttle !== null, notifyWhen, - throttle, + throttle: throttle === '1h' ? '5m' : throttle, }, }; }) ?? [], 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 9cb01b62da161..898e67ab52f71 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 @@ -54,6 +54,7 @@ export const createSecurityRuleTypeWrapper: CreateSecurityRuleTypeWrapper = injectReferences: (params, savedObjectReferences) => injectReferences({ logger, params, savedObjectReferences }), }, + autoRecoverAlerts: false, async executor(options) { agent.setTransactionName(`${options.rule.ruleTypeId} execution`); return withSecuritySpan('securityRuleTypeExecutor', async () => {