[Security Solution][Detections] refactors update rule actions tests (#142464)

## Summary

- addresses https://github.com/elastic/kibana/issues/138757

according to proposal in above task:
- removes step of updating immutable rule with mock data
- makes assertions whether rule properties were not modified against fetched earlier immutable rule


### Checklist

- [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:
Vitalii Dmyterko 2022-10-04 10:39:50 +01:00 committed by GitHub
parent f1c12a097a
commit 10884e6a5f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 87 additions and 40 deletions

View file

@ -6,6 +6,7 @@
*/
import expect from '@kbn/expect';
import { omit } from 'lodash';
import { CreateRulesSchema } from '@kbn/security-solution-plugin/common/detection_engine/schemas/request';
import { FtrProviderContext } from '../../common/ftr_provider_context';
@ -26,14 +27,24 @@ import {
findImmutableRuleById,
getPrePackagedRulesStatus,
getSimpleRuleOutput,
ruleToUpdateSchema,
} from '../../utils';
// Rule id of "9a1a2dae-0b5f-4c3d-8305-a268d404c306" is from the file:
// x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security.json
const RULE_ID = '9a1a2dae-0b5f-4c3d-8305-a268d404c306';
// eslint-disable-next-line import/no-default-export
export default ({ getService }: FtrProviderContext) => {
const supertest = getService('supertest');
const esArchiver = getService('esArchiver');
const log = getService('log');
const getImmutableRule = async () => {
await installPrePackagedRules(supertest, log);
return getRule(supertest, log, RULE_ID);
};
describe('update_actions', () => {
describe('updating actions', () => {
before(async () => {
@ -105,50 +116,53 @@ export default ({ getService }: FtrProviderContext) => {
});
it('should not change properties of immutable rule when applying actions to it', async () => {
await installPrePackagedRules(supertest, log);
// Rule id of "9a1a2dae-0b5f-4c3d-8305-a268d404c306" is from the file:
// x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint.json
const immutableRule = await getRule(supertest, log, '9a1a2dae-0b5f-4c3d-8305-a268d404c306');
const hookAction = await createNewAction(supertest, log);
const newRuleToUpdate = getSimpleRule(immutableRule.rule_id);
const ruleToUpdate = getRuleWithWebHookAction(hookAction.id, false, newRuleToUpdate);
const updatedRule = await updateRule(supertest, log, ruleToUpdate);
const bodyToCompare = removeServerGeneratedProperties(updatedRule);
// actions and throttle to be removed from assertion (it asserted in a separate test case)
const actionsProps = ['actions', 'throttle'];
const expected = {
...getSimpleRuleOutputWithWebHookAction(`${bodyToCompare.actions?.[0].id}`),
rule_id: immutableRule.rule_id, // Rule id should match the same as the immutable rule
version: immutableRule.version, // This version number should not change when an immutable rule is updated
immutable: true, // It should stay immutable true when returning
required_fields: immutableRule.required_fields, // required_fields cannot be modified, so newRuleToUpdate will have required_fields from immutable rule
};
expect(bodyToCompare).to.eql(expected);
const immutableRule = await getImmutableRule();
const hookAction = await createNewAction(supertest, log);
const ruleToUpdate = getRuleWithWebHookAction(
hookAction.id,
immutableRule.enabled,
ruleToUpdateSchema(immutableRule)
);
const updatedRule = await updateRule(supertest, log, ruleToUpdate);
const expected = omit(removeServerGeneratedProperties(updatedRule), actionsProps);
const immutableRuleToAssert = omit(
removeServerGeneratedProperties(immutableRule),
actionsProps
);
expect(immutableRuleToAssert).to.eql(expected);
expect(expected.immutable).to.be(true); // It should stay immutable true when returning
});
it('should be able to create a new webhook action and attach it to an immutable rule', async () => {
await installPrePackagedRules(supertest, log);
// Rule id of "9a1a2dae-0b5f-4c3d-8305-a268d404c306" is from the file:
// x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint.json
const immutableRule = await getRule(supertest, log, '9a1a2dae-0b5f-4c3d-8305-a268d404c306');
const immutableRule = await getImmutableRule();
const hookAction = await createNewAction(supertest, log);
const newRuleToUpdate = getSimpleRule(immutableRule.rule_id);
const ruleToUpdate = getRuleWithWebHookAction(hookAction.id, false, newRuleToUpdate);
const ruleToUpdate = getRuleWithWebHookAction(
hookAction.id,
immutableRule.enabled,
ruleToUpdateSchema(immutableRule)
);
const updatedRule = await updateRule(supertest, log, ruleToUpdate);
const bodyToCompare = removeServerGeneratedProperties(updatedRule);
const expected = getSimpleRuleOutputWithWebHookAction(`${bodyToCompare.actions?.[0].id}`);
expect(bodyToCompare.actions).to.eql(expected.actions);
expect(bodyToCompare.throttle).to.eql(expected.throttle);
});
it('should be able to create a new webhook action, attach it to an immutable rule and the count of prepackaged rules should not increase. If this fails, suspect the immutable tags are not staying on the rule correctly.', async () => {
await installPrePackagedRules(supertest, log);
// Rule id of "9a1a2dae-0b5f-4c3d-8305-a268d404c306" is from the file:
// x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint.json
const immutableRule = await getRule(supertest, log, '9a1a2dae-0b5f-4c3d-8305-a268d404c306');
const immutableRule = await getImmutableRule();
const hookAction = await createNewAction(supertest, log);
const newRuleToUpdate = getSimpleRule(immutableRule.rule_id);
const ruleToUpdate = getRuleWithWebHookAction(hookAction.id, false, newRuleToUpdate);
const ruleToUpdate = getRuleWithWebHookAction(
hookAction.id,
immutableRule.enabled,
ruleToUpdateSchema(immutableRule)
);
await updateRule(supertest, log, ruleToUpdate);
const status = await getPrePackagedRulesStatus(supertest, log);
@ -156,19 +170,15 @@ export default ({ getService }: FtrProviderContext) => {
});
it('should be able to create a new webhook action, attach it to an immutable rule and the rule should stay immutable when searching against immutable tags', async () => {
await installPrePackagedRules(supertest, log);
// Rule id of "9a1a2dae-0b5f-4c3d-8305-a268d404c306" is from the file:
// x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint.json
const immutableRule = await getRule(supertest, log, '9a1a2dae-0b5f-4c3d-8305-a268d404c306');
const immutableRule = await getImmutableRule();
const hookAction = await createNewAction(supertest, log);
const newRuleToUpdate = getSimpleRule(immutableRule.rule_id);
const ruleToUpdate = getRuleWithWebHookAction(hookAction.id, false, newRuleToUpdate);
await updateRule(supertest, log, ruleToUpdate);
const body = await findImmutableRuleById(
supertest,
log,
'9a1a2dae-0b5f-4c3d-8305-a268d404c306'
const ruleToUpdate = getRuleWithWebHookAction(
hookAction.id,
immutableRule.enabled,
ruleToUpdateSchema(immutableRule)
);
await updateRule(supertest, log, ruleToUpdate);
const body = await findImmutableRuleById(supertest, log, RULE_ID);
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]);

View file

@ -85,6 +85,7 @@ export * from './remove_server_generated_properties';
export * from './remove_server_generated_properties_including_rule_id';
export * from './resolve_simple_rule_output';
export * from './rule_to_ndjson';
export * from './rule_to_update_schema';
export * from './set_signal_status';
export * from './start_signals_migration';
export * from './update_rule';

View file

@ -0,0 +1,36 @@
/*
* 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 {
FullResponseSchema,
UpdateRulesSchema,
} from '@kbn/security-solution-plugin/common/detection_engine/schemas/request';
import { omit, pickBy } from 'lodash';
const propertiesToRemove = [
'id',
'immutable',
'updated_at',
'updated_by',
'created_at',
'created_by',
'related_integrations',
'required_fields',
'setup',
'execution_summary',
];
/**
* transforms FullResponseSchema rule to UpdateRulesSchema
* returned result can be used in rule update API calls
*/
export const ruleToUpdateSchema = (rule: FullResponseSchema): UpdateRulesSchema => {
const removedProperties = omit(rule, propertiesToRemove);
// We're only removing undefined values, so this cast correctly narrows the type
return pickBy(removedProperties, (value) => value !== undefined) as UpdateRulesSchema;
};