[Security Solution] Remove the automatic rule mute/unmute logic from all our BE endpoints (#154804)

**Addresses:** https://github.com/elastic/kibana/issues/147736

## Summary

This PR removes automatic rule muting and unmuting at Security solution's APIs.


### Checklist

- [ ] [Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html) was added for features that require explanation or tutorials
- [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios
This commit is contained in:
Maxim Palenov 2023-04-19 23:13:56 +02:00 committed by GitHub
parent 03a2cd7aea
commit 6994c9f901
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 6 additions and 124 deletions

View file

@ -5,23 +5,13 @@
* 2.0.
*/
import type { BulkOperationError, RulesClient } from '@kbn/alerting-plugin/server';
import pMap from 'p-map';
import {
MAX_RULES_TO_UPDATE_IN_PARALLEL,
NOTIFICATION_THROTTLE_NO_ACTIONS,
} from '../../../../../../common/constants';
import type { RulesClient } from '@kbn/alerting-plugin/server';
import type {
BulkActionEditPayload,
BulkActionEditPayloadRuleActions,
} from '../../../../../../common/detection_engine/rule_management/api/rules/bulk_actions/request_schema';
import { BulkActionEditType } from '../../../../../../common/detection_engine/rule_management/api/rules/bulk_actions/request_schema';
import type { BulkActionEditPayload } from '../../../../../../common/detection_engine/rule_management/api/rules/bulk_actions/request_schema';
import type { MlAuthz } from '../../../../machine_learning/authz';
import { enrichFilterWithRuleTypeMapping } from '../search/enrich_filter_with_rule_type_mappings';
import { readRules } from '../crud/read_rules';
import type { RuleAlertType } from '../../../rule_schema';
import { ruleParamsModifier } from './rule_params_modifier';
@ -67,52 +57,5 @@ export const bulkEditRules = async ({
},
});
// rulesClient bulkEdit currently doesn't support bulk mute/unmute.
// this is a workaround to mitigate this,
// until https://github.com/elastic/kibana/issues/139084 is resolved
// if rule actions has been applied, we go through each rule, unmute it if necessary and refetch it
// calling unmute needed only if rule was muted and throttle value is not NOTIFICATION_THROTTLE_NO_ACTIONS
const ruleActions = attributesActions.filter((rule): rule is BulkActionEditPayloadRuleActions =>
[BulkActionEditType.set_rule_actions, BulkActionEditType.add_rule_actions].includes(rule.type)
);
// bulk edit actions are applied in historical order.
// So, we need to find a rule action that will be applied the last, to be able to check if rule should be muted/unmuted
const rulesAction = ruleActions.pop();
if (rulesAction) {
const unmuteErrors: BulkOperationError[] = [];
const rulesToUnmute = await pMap(
result.rules,
async (rule) => {
try {
if (rule.muteAll && rulesAction.value.throttle !== NOTIFICATION_THROTTLE_NO_ACTIONS) {
await rulesClient.unmuteAll({ id: rule.id });
return (await readRules({ rulesClient, id: rule.id, ruleId: undefined })) ?? rule;
}
return rule;
} catch (err) {
unmuteErrors.push({
message: err.message,
rule: {
id: rule.id,
name: rule.name,
},
});
return null;
}
},
{ concurrency: MAX_RULES_TO_UPDATE_IN_PARALLEL }
);
return {
...result,
rules: rulesToUnmute.filter((rule): rule is RuleAlertType => rule != null),
errors: [...result.errors, ...unmuteErrors],
};
}
return result;
};

View file

@ -9,7 +9,6 @@ import type { SanitizedRule } from '@kbn/alerting-plugin/common';
import type { RulesClient } from '@kbn/alerting-plugin/server';
import type { RuleCreateProps } from '../../../../../../common/detection_engine/rule_schema';
import { NOTIFICATION_THROTTLE_NO_ACTIONS } from '../../../../../../common/constants';
import { convertCreateAPIToInternalSchema } from '../../normalization/rule_converters';
import type { RuleParams } from '../../../rule_schema';
@ -39,10 +38,5 @@ export const createRules = async ({
allowMissingConnectorSecrets,
});
// Mute the rule if it is first created with the explicit no actions
if (params.throttle === NOTIFICATION_THROTTLE_NO_ACTIONS) {
await rulesClient.muteAll({ id: rule.id });
}
return rule;
};

View file

@ -10,7 +10,6 @@ import type { PartialRule, RulesClient } from '@kbn/alerting-plugin/server';
import type { PatchRuleRequestBody } from '../../../../../../common/detection_engine/rule_management';
import type { RuleAlertType, RuleParams } from '../../../rule_schema';
import { convertPatchAPIToInternalSchema } from '../../normalization/rule_converters';
import { maybeMute } from '../rule_actions/muting';
export interface PatchRulesOptions {
rulesClient: RulesClient;
@ -41,15 +40,6 @@ export const patchRules = async ({
shouldIncrementRevision: () => shouldIncrementRevision,
});
if (nextParams.throttle !== undefined) {
await maybeMute({
rulesClient,
muteAll: existingRule.muteAll,
throttle: nextParams.throttle,
id: update.id,
});
}
if (existingRule.enabled && nextParams.enabled === false) {
await rulesClient.disable({ id: existingRule.id });
} else if (!existingRule.enabled && nextParams.enabled === true) {

View file

@ -14,7 +14,6 @@ import { transformRuleToAlertAction } from '../../../../../../common/detection_e
import type { InternalRuleUpdate, RuleParams, RuleAlertType } from '../../../rule_schema';
import { transformToAlertThrottle, transformToNotifyWhen } from '../../normalization/rule_actions';
import { typeSpecificSnakeToCamel } from '../../normalization/rule_converters';
import { maybeMute } from '../rule_actions/muting';
export interface UpdateRulesOptions {
rulesClient: RulesClient;
@ -81,13 +80,6 @@ export const updateRules = async ({
data: newInternalRule,
});
await maybeMute({
rulesClient,
muteAll: existingRule.muteAll,
throttle: ruleUpdate.throttle,
id: update.id,
});
if (existingRule.enabled && enabled === false) {
await rulesClient.disable({ id: existingRule.id });
} else if (!existingRule.enabled && enabled === true) {

View file

@ -1,37 +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 { RulesClient } from '@kbn/alerting-plugin/server';
import { NOTIFICATION_THROTTLE_NO_ACTIONS } from '../../../../../../common/constants';
import type { RuleAlertType } from '../../../rule_schema';
/**
* Mutes, unmutes, or does nothing to the alert if no changed is detected
* @param id The id of the alert to (un)mute
* @param rulesClient the rules client
* @param muteAll If the existing alert has all actions muted
* @param throttle If the existing alert has a throttle set
*/
export const maybeMute = async ({
id,
rulesClient,
muteAll,
throttle,
}: {
id: RuleAlertType['id'];
rulesClient: RulesClient;
muteAll: RuleAlertType['muteAll'];
throttle: string | null | undefined;
}): Promise<void> => {
if (muteAll && throttle !== NOTIFICATION_THROTTLE_NO_ACTIONS) {
await rulesClient.unmuteAll({ id });
} else if (!muteAll && throttle === NOTIFICATION_THROTTLE_NO_ACTIONS) {
await rulesClient.muteAll({ id });
} else {
// Do nothing, no-operation
}
};

View file

@ -72,7 +72,7 @@ export default ({ getService }: FtrProviderContext) => {
expect(notifyWhen).to.eql('onActiveAlert');
});
it('When creating throttle with "NOTIFICATION_THROTTLE_NO_ACTIONS" set and no actions, the rule should have its kibana alerting "mute_all" set to "true" and notify_when set to null', async () => {
it('When creating throttle with "NOTIFICATION_THROTTLE_NO_ACTIONS" set and no actions, the rule should have its kibana alerting "mute_all" set to "false" and notify_when set to null', async () => {
const ruleWithThrottle: RuleCreateProps = {
...getSimpleRule(),
throttle: NOTIFICATION_THROTTLE_NO_ACTIONS,
@ -81,11 +81,11 @@ export default ({ getService }: FtrProviderContext) => {
const {
body: { mute_all: muteAll, notify_when: notifyWhen },
} = await supertest.get(`/api/alerting/rule/${rule.id}`);
expect(muteAll).to.eql(true);
expect(muteAll).to.eql(false);
expect(notifyWhen).to.eql(null);
});
it('When creating throttle with "NOTIFICATION_THROTTLE_NO_ACTIONS" set and with actions set, the rule should have its kibana alerting "mute_all" set to "true" and notify_when set to null', async () => {
it('When creating throttle with "NOTIFICATION_THROTTLE_NO_ACTIONS" set and with actions set, the rule should have its kibana alerting "mute_all" set to "false" and notify_when set to null', async () => {
// create a new action
const { body: hookAction } = await supertest
.post('/api/actions/action')
@ -101,7 +101,7 @@ export default ({ getService }: FtrProviderContext) => {
const {
body: { mute_all: muteAll, notify_when: notifyWhen },
} = await supertest.get(`/api/alerting/rule/${rule.id}`);
expect(muteAll).to.eql(true);
expect(muteAll).to.eql(false);
expect(notifyWhen).to.eql(null);
});