Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Security Solution][Detections] adds bulk edit rule actions #138900

Merged
merged 54 commits into from
Sep 6, 2022
Merged
Show file tree
Hide file tree
Changes from 29 commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
2d2cf84
init bulk actions
vitaliidm Aug 15, 2022
e23d690
bulk edit rules
vitaliidm Aug 16, 2022
cc11341
[RAM] revisit later
vitaliidm Aug 16, 2022
e5cddaf
remove .only
vitaliidm Aug 16, 2022
eebaa87
fix eslint
vitaliidm Aug 16, 2022
d0f6b61
it's alive!
vitaliidm Aug 17, 2022
afab282
additonal tests
vitaliidm Aug 17, 2022
fdc0e9f
Merge branch 'main' into detections/bulk-actions
vitaliidm Aug 17, 2022
4e53111
rename actims
vitaliidm Aug 17, 2022
7cb4a07
fix tests
vitaliidm Aug 17, 2022
32a73a3
services.application.capabilities.actions.show;
vitaliidm Aug 17, 2022
85ead17
trying to fix bundle
vitaliidm Aug 17, 2022
3a8f591
immutability fix
vitaliidm Aug 17, 2022
f9e805a
types
vitaliidm Aug 18, 2022
f7517a8
increase bundle limit
vitaliidm Aug 18, 2022
5f893b6
Merge branch 'main' into detections/bulk-actions
vitaliidm Aug 18, 2022
1cce11f
remove services.application.capabilities.actions.show;
vitaliidm Aug 18, 2022
7f4f966
refactoring
vitaliidm Aug 18, 2022
075369a
fixes
vitaliidm Aug 18, 2022
2679a64
refactor
vitaliidm Aug 18, 2022
d6ccf0b
wording
vitaliidm Aug 22, 2022
13a7c94
Merge branch 'main' into detections/bulk-actions
vitaliidm Aug 22, 2022
070319e
update tests
vitaliidm Aug 22, 2022
f11fa66
[CI] Auto-commit changed files from 'node scripts/precommit_hook.js -…
kibanamachine Aug 22, 2022
d8aa8db
Merge branch 'main' into detections/bulk-actions
vitaliidm Aug 24, 2022
3b37cb9
update message
vitaliidm Aug 25, 2022
4eb402a
fix i18n
vitaliidm Aug 25, 2022
0470b0c
updates
vitaliidm Aug 25, 2022
841a562
Merge branch 'main' into detections/bulk-actions
vitaliidm Aug 26, 2022
2cbc926
attempt to reduce bundle size
vitaliidm Aug 26, 2022
3ddf3a7
Merge branch 'detections/bulk-actions' of https://github.com/vitaliid…
vitaliidm Aug 26, 2022
34510ca
fix versino increment issue for prebuilt rules
vitaliidm Aug 26, 2022
1add5c0
Merge branch 'main' into detections/bulk-actions
vitaliidm Aug 30, 2022
7f73996
Merge branch 'main' into detections/bulk-actions
vitaliidm Aug 30, 2022
1c67a1c
Merge branch 'main' into detections/bulk-actions
vitaliidm Aug 31, 2022
0cd3934
fix issue with duplicated rule variables
vitaliidm Aug 31, 2022
a145e01
Merge branch 'main' into detections/bulk-actions
kibanamachine Aug 31, 2022
f11ae45
Merge branch 'main' into detections/bulk-actions
vitaliidm Aug 31, 2022
aa36d99
Update bulk_edit_rules.ts
vitaliidm Aug 31, 2022
905f358
move bulk actions enums to request schema
vitaliidm Sep 5, 2022
76aa2d6
CR: spelling
vitaliidm Sep 5, 2022
c1bfbac
CR: typings
vitaliidm Sep 5, 2022
6f82e91
CR: workaround feedback
vitaliidm Sep 5, 2022
ea9ca29
fix types for tests
vitaliidm Sep 5, 2022
c459748
Merge branch 'main' into detections/bulk-actions
vitaliidm Sep 5, 2022
5d48c02
Update x-pack/plugins/security_solution/public/detections/pages/detec…
vitaliidm Sep 6, 2022
d50a8b3
Update x-pack/plugins/security_solution/public/detections/pages/detec…
vitaliidm Sep 6, 2022
f5f216d
Update x-pack/plugins/security_solution/public/detections/pages/detec…
vitaliidm Sep 6, 2022
fc5d288
Update x-pack/plugins/security_solution/public/detections/pages/detec…
vitaliidm Sep 6, 2022
cc32c07
Update x-pack/plugins/security_solution/public/detections/pages/detec…
vitaliidm Sep 6, 2022
291b8bc
woridng
vitaliidm Sep 6, 2022
6f530b2
text updates
vitaliidm Sep 6, 2022
9c6dc77
back to ul
vitaliidm Sep 6, 2022
1a0df5a
Merge branch 'main' into detections/bulk-actions
vitaliidm Sep 6, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/kbn-optimizer/limits.yml
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ pageLoadAssetSize:
expressionShape: 34008
interactiveSetup: 80000
expressionTagcloud: 27505
securitySolution: 273763
securitySolution: 301655
customIntegrations: 28810
expressionMetricVis: 23121
expressionLegacyMetricVis: 23121
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,13 @@ import {
UUID,
LimitedSizeArray,
} from '@kbn/securitysolution-io-ts-types';
import {
throttle,
action_group as actionGroup,
action_params as actionParams,
action_id as actionId,
} from '@kbn/securitysolution-io-ts-alerting-types';

import * as t from 'io-ts';

export const author = t.array(t.string);
Expand Down Expand Up @@ -379,6 +386,8 @@ export enum BulkActionEditType {
'delete_index_patterns' = 'delete_index_patterns',
'set_index_patterns' = 'set_index_patterns',
'set_timeline' = 'set_timeline',
'add_rule_actions' = 'add_rule_actions',
'set_rule_actions' = 'set_rule_actions',
}

const bulkActionEditPayloadTags = t.type({
Expand Down Expand Up @@ -418,16 +427,46 @@ const bulkActionEditPayloadTimeline = t.type({

export type BulkActionEditPayloadTimeline = t.TypeOf<typeof bulkActionEditPayloadTimeline>;

const bulkActionEditPayloadRuleActions = t.type({
type: t.union([
t.literal(BulkActionEditType.add_rule_actions),
t.literal(BulkActionEditType.set_rule_actions),
]),
value: t.type({
throttle,
actions: t.array(
t.exact(
t.type({
group: actionGroup,
id: actionId,
params: actionParams,
})
)
),
}),
});

export type bulkActionEditPayloadRuleActions = t.TypeOf<typeof bulkActionEditPayloadRuleActions>;

export const bulkActionEditPayload = t.union([
bulkActionEditPayloadTags,
bulkActionEditPayloadIndexPatterns,
bulkActionEditPayloadTimeline,
bulkActionEditPayloadRuleActions,
]);

export type BulkActionEditPayload = t.TypeOf<typeof bulkActionEditPayload>;

export type BulkActionEditForRuleAttributes = BulkActionEditPayloadTags;
/**
* actions that modifies rules attributes
*/
export type BulkActionEditForRuleAttributes =
| BulkActionEditPayloadTags
| bulkActionEditPayloadRuleActions;

/**
* actions that modifies rules params
*/
export type BulkActionEditForRuleParams =
| BulkActionEditPayloadIndexPatterns
| BulkActionEditPayloadTimeline;
Original file line number Diff line number Diff line change
Expand Up @@ -343,12 +343,12 @@ describe('perform_bulk_action_schema', () => {

const message = retrieveValidationMessage(payload);

expect(getPaths(left(message.errors))).toEqual([
'Invalid value "edit" supplied to "action"',
'Invalid value "set_timeline" supplied to "edit,type"',
'Invalid value "{"timeline_title":"Test timeline title"}" supplied to "edit,value"',
'Invalid value "undefined" supplied to "edit,value,timeline_id"',
]);
expect(getPaths(left(message.errors))).toEqual(
expect.arrayContaining([
'Invalid value "{"timeline_title":"Test timeline title"}" supplied to "edit,value"',
'Invalid value "undefined" supplied to "edit,value,timeline_id"',
])
);
expect(message.schema).toEqual({});
});

Expand All @@ -373,5 +373,163 @@ describe('perform_bulk_action_schema', () => {
expect(message.schema).toEqual(payload);
});
});

describe('rule actions', () => {
test('invalid request: invalid rule actions payload', () => {
const payload = {
query: 'name: test',
action: BulkAction.edit,
[BulkAction.edit]: [{ type: BulkActionEditType.add_rule_actions, value: [] }],
};

const message = retrieveValidationMessage(payload);

expect(getPaths(left(message.errors))).toEqual(
expect.arrayContaining(['Invalid value "[]" supplied to "edit,value"'])
);
expect(message.schema).toEqual({});
});

test('invalid request: missing throttle in payload', () => {
const payload = {
query: 'name: test',
action: BulkAction.edit,
[BulkAction.edit]: [
{
type: BulkActionEditType.add_rule_actions,
value: {
actions: [],
},
},
],
};

const message = retrieveValidationMessage(payload);

expect(getPaths(left(message.errors))).toEqual(
expect.arrayContaining(['Invalid value "undefined" supplied to "edit,value,throttle"'])
);
expect(message.schema).toEqual({});
});

test('invalid request: missing actions in payload', () => {
const payload = {
query: 'name: test',
action: BulkAction.edit,
[BulkAction.edit]: [
{
type: BulkActionEditType.add_rule_actions,
value: {
throttle: '1h',
},
},
],
};

const message = retrieveValidationMessage(payload);

expect(getPaths(left(message.errors))).toEqual(
expect.arrayContaining(['Invalid value "undefined" supplied to "edit,value,actions"'])
);
expect(message.schema).toEqual({});
});

test('invalid request: invalid action_type_id property in actions array', () => {
const payload = {
query: 'name: test',
action: BulkAction.edit,
[BulkAction.edit]: [
{
type: BulkActionEditType.add_rule_actions,
value: {
throttle: '1h',
actions: [
{
action_type_id: '.webhook',
group: 'default',
id: '458a50e0-1a28-11ed-9098-47fd8e1f3345',
params: {
body: {
rule_id: '{{rule.id}}',
},
},
},
],
},
},
],
};

const message = retrieveValidationMessage(payload);
expect(getPaths(left(message.errors))).toEqual(
expect.arrayContaining(['invalid keys "action_type_id"'])
);
expect(message.schema).toEqual({});
});

test('valid request: add_rule_actions edit action', () => {
const payload: PerformBulkActionSchema = {
query: 'name: test',
action: BulkAction.edit,
[BulkAction.edit]: [
{
type: BulkActionEditType.add_rule_actions,
value: {
throttle: '1h',
actions: [
{
group: 'default',
id: '458a50e0-1a28-11ed-9098-47fd8e1f3345',
params: {
body: {
rule_id: '{{rule.id}}',
},
},
},
],
},
},
],
};

const message = retrieveValidationMessage(payload);

expect(getPaths(left(message.errors))).toEqual([]);
expect(message.schema).toEqual(payload);
});

test('valid request: set_rule_actions edit action', () => {
const payload: PerformBulkActionSchema = {
query: 'name: test',
action: BulkAction.edit,
[BulkAction.edit]: [
{
type: BulkActionEditType.set_rule_actions,
value: {
throttle: '1h',
actions: [
{
group: 'default',
id: '458a50e0-1a28-11ed-9098-47fd8e1f3345',
params: {
documents: [
{
rule_id: '{{rule.id}}',
},
],
},
},
],
},
},
],
};

const message = retrieveValidationMessage(payload);

expect(getPaths(left(message.errors))).toEqual([]);
expect(message.schema).toEqual(payload);
});
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* 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 { i18n } from '@kbn/i18n';

import type { ActionTypeRegistryContract } from '@kbn/triggers-actions-ui-plugin/public';
import { validateRuleActionsField } from '../../../containers/detection_engine/rules/validate_rule_actions_field';

import type { FormSchema } from '../../../../shared_imports';
import type { ActionsStepRule } from '../../../pages/detection_engine/rules/types';

export const getSchema = ({
actionTypeRegistry,
}: {
actionTypeRegistry: ActionTypeRegistryContract;
}): FormSchema<ActionsStepRule> => ({
actions: {
validations: [
{
validator: validateRuleActionsField(actionTypeRegistry),
},
],
},
enabled: {},
kibanaSiemAppUrl: {},
throttle: {
label: i18n.translate(
'xpack.securitySolution.detectionEngine.createRule.stepRuleActions.fieldThrottleLabel',
{
defaultMessage: 'Actions frequency',
}
),
helpText: i18n.translate(
'xpack.securitySolution.detectionEngine.createRule.stepRuleActions.fieldThrottleHelpText',
{
defaultMessage:
'Select when automated actions should be performed if a rule evaluates as true.',
}
),
},
});
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import {
} from '../throttle_select_field';
import { RuleActionsField } from '../rule_actions_field';
import { useKibana } from '../../../../common/lib/kibana';
import { getSchema } from './schema';
import { getSchema } from './get_schema';
import * as I18n from './translations';
import { APP_UI_ID } from '../../../../../common/constants';
import { useManageCaseAction } from './use_manage_case_action';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
*/

import { i18n } from '@kbn/i18n';
import { startCase } from 'lodash/fp';

export const COMPLETE_WITHOUT_ENABLING = i18n.translate(
'xpack.securitySolution.detectionEngine.createRule.stepScheduleRule.completeWithoutEnablingTitle',
Expand All @@ -29,14 +28,3 @@ export const NO_ACTIONS_READ_PERMISSIONS = i18n.translate(
'Cannot create rule actions. You do not have "Read" permissions for the "Actions" plugin.',
}
);

export const INVALID_MUSTACHE_TEMPLATE = (paramKey: string) =>
i18n.translate(
'xpack.securitySolution.detectionEngine.createRule.stepRuleActions.invalidMustacheTemplateErrorMessage',
{
defaultMessage: '{key} is not valid mustache template',
values: {
key: startCase(paramKey),
},
}
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/*
* 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.
*/

export { validateRuleActionsField } from './validate_rule_actions_field';
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* 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 { i18n } from '@kbn/i18n';
import { startCase } from 'lodash/fp';

export const INVALID_MUSTACHE_TEMPLATE = (paramKey: string) =>
i18n.translate(
'xpack.securitySolution.detectionEngine.createRule.stepRuleActions.invalidMustacheTemplateErrorMessage',
{
defaultMessage: '{key} is not valid mustache template',
values: {
key: startCase(paramKey),
},
}
);
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@
* 2.0.
*/

import { validateSingleAction, validateRuleActionsField } from './schema';
import { validateSingleAction, validateRuleActionsField } from './validate_rule_actions_field';
import { getActionTypeName, validateMustache, validateActionParams } from './utils';
import { actionTypeRegistryMock } from '@kbn/triggers-actions-ui-plugin/public/application/action_type_registry.mock';
import type { FormHook } from '../../../../shared_imports';
import type { FormHook } from '../../../../../shared_imports';
jest.mock('./utils');

describe('stepRuleActions schema', () => {
describe('validate_rule_actions_field', () => {
const actionTypeRegistry = actionTypeRegistryMock.create();

describe('validateSingleAction', () => {
Expand Down
Loading