Skip to content

Commit

Permalink
[Security Solution] Bulk editing rule custom highlighted fields (#179312
Browse files Browse the repository at this point in the history
)

**Resolves: #164301
**Resolves: elastic/security-team#8958

## Summary

With these changes we introduce a new feature - Bulk custom highlighted
fields update. It works similarly to bulk tags and indices update.

Here is the overview of the work that has been done:


https://github.com/elastic/kibana/assets/2700761/b1ba6670-9984-43c9-9f1e-e18a2b7f071f

### Checklist

Delete any items that are not applicable to this PR.

- [x] Any text added follows [EUI's writing
guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses
sentence case text and includes [i18n
support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md)
- [x]
[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)
was added for features that require explanation or tutorials
  - [ ] elastic/security-docs#5090
- [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
- [x] [Flaky Test
Runner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was
used on any tests changed
- [ ] [ESS 100
times](https://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/5834)
- [ ] [Serverless 100
times](https://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/5835)

---------

Co-authored-by: Kibana Machine <[email protected]>
Co-authored-by: Devin W. Hurley <[email protected]>
  • Loading branch information
3 people authored May 2, 2024
1 parent 887bb7d commit b4b316a
Show file tree
Hide file tree
Showing 31 changed files with 1,457 additions and 94 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import {
RuleActionAlertsFilter,
IndexPatternArray,
RuleTagArray,
InvestigationFields,
TimelineTemplateId,
TimelineTemplateTitle,
} from '../../model/rule_schema/common_attributes.gen';
Expand All @@ -52,6 +53,7 @@ export const BulkActionsDryRunErrCode = z.enum([
'MACHINE_LEARNING_AUTH',
'MACHINE_LEARNING_INDEX_PATTERN',
'ESQL_INDEX_PATTERN',
'INVESTIGATION_FIELDS_FEATURE',
]);
export type BulkActionsDryRunErrCodeEnum = typeof BulkActionsDryRunErrCode.enum;
export const BulkActionsDryRunErrCodeEnum = BulkActionsDryRunErrCode.enum;
Expand Down Expand Up @@ -187,6 +189,9 @@ export const BulkActionEditType = z.enum([
'add_rule_actions',
'set_rule_actions',
'set_schedule',
'add_investigation_fields',
'delete_investigation_fields',
'set_investigation_fields',
]);
export type BulkActionEditTypeEnum = typeof BulkActionEditType.enum;
export const BulkActionEditTypeEnum = BulkActionEditType.enum;
Expand Down Expand Up @@ -239,6 +244,18 @@ export const BulkActionEditPayloadTags = z.object({
value: RuleTagArray,
});

export type BulkActionEditPayloadInvestigationFields = z.infer<
typeof BulkActionEditPayloadInvestigationFields
>;
export const BulkActionEditPayloadInvestigationFields = z.object({
type: z.enum([
'add_investigation_fields',
'delete_investigation_fields',
'set_investigation_fields',
]),
value: InvestigationFields,
});

export type BulkActionEditPayloadTimeline = z.infer<typeof BulkActionEditPayloadTimeline>;
export const BulkActionEditPayloadTimeline = z.object({
type: z.literal('set_timeline'),
Expand All @@ -252,6 +269,7 @@ export type BulkActionEditPayload = z.infer<typeof BulkActionEditPayload>;
export const BulkActionEditPayload = z.union([
BulkActionEditPayloadTags,
BulkActionEditPayloadIndexPatterns,
BulkActionEditPayloadInvestigationFields,
BulkActionEditPayloadTimeline,
BulkActionEditPayloadRuleActions,
BulkActionEditPayloadSchedule,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ components:
- MACHINE_LEARNING_AUTH
- MACHINE_LEARNING_INDEX_PATTERN
- ESQL_INDEX_PATTERN
- INVESTIGATION_FIELDS_FEATURE

NormalizedRuleError:
type: object
Expand Down Expand Up @@ -281,6 +282,9 @@ components:
- add_rule_actions
- set_rule_actions
- set_schedule
- add_investigation_fields
- delete_investigation_fields
- set_investigation_fields

# Per rulesClient.bulkEdit rules actions operation contract (x-pack/plugins/alerting/server/rules_client/rules_client.ts) normalized rule action object is expected (NormalizedAlertAction) as value for the edit operation
NormalizedRuleAction:
Expand Down Expand Up @@ -381,6 +385,21 @@ components:
- type
- value

BulkActionEditPayloadInvestigationFields:
type: object
properties:
type:
type: string
enum:
- add_investigation_fields
- delete_investigation_fields
- set_investigation_fields
value:
$ref: '../../model/rule_schema/common_attributes.schema.yaml#/components/schemas/InvestigationFields'
required:
- type
- value

BulkActionEditPayloadTimeline:
type: object
properties:
Expand All @@ -406,6 +425,7 @@ components:
anyOf:
- $ref: '#/components/schemas/BulkActionEditPayloadTags'
- $ref: '#/components/schemas/BulkActionEditPayloadIndexPatterns'
- $ref: '#/components/schemas/BulkActionEditPayloadInvestigationFields'
- $ref: '#/components/schemas/BulkActionEditPayloadTimeline'
- $ref: '#/components/schemas/BulkActionEditPayloadRuleActions'
- $ref: '#/components/schemas/BulkActionEditPayloadSchedule'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ describe('Perform bulk action request schema', () => {
expectParseError(result);

expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
`"action: Invalid literal value, expected \\"delete\\", action: Invalid literal value, expected \\"disable\\", action: Invalid literal value, expected \\"enable\\", action: Invalid literal value, expected \\"export\\", action: Invalid literal value, expected \\"duplicate\\", and 9 more"`
`"action: Invalid literal value, expected \\"delete\\", action: Invalid literal value, expected \\"disable\\", action: Invalid literal value, expected \\"enable\\", action: Invalid literal value, expected \\"export\\", action: Invalid literal value, expected \\"duplicate\\", and 11 more"`
);
});

Expand Down Expand Up @@ -249,7 +249,7 @@ describe('Perform bulk action request schema', () => {
expectParseError(result);

expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
`"action: Invalid literal value, expected \\"delete\\", action: Invalid literal value, expected \\"disable\\", action: Invalid literal value, expected \\"enable\\", action: Invalid literal value, expected \\"export\\", action: Invalid literal value, expected \\"duplicate\\", and 9 more"`
`"action: Invalid literal value, expected \\"delete\\", action: Invalid literal value, expected \\"disable\\", action: Invalid literal value, expected \\"enable\\", action: Invalid literal value, expected \\"export\\", action: Invalid literal value, expected \\"duplicate\\", and 11 more"`
);
});

Expand Down Expand Up @@ -299,6 +299,62 @@ describe('Perform bulk action request schema', () => {
});
});

describe('investigation_fields', () => {
test('valid request: set_investigation_fields edit action', () => {
const payload: PerformBulkActionRequestBody = {
query: 'name: test',
action: BulkActionTypeEnum.edit,
[BulkActionTypeEnum.edit]: [
{
type: BulkActionEditTypeEnum.set_investigation_fields,
value: { field_names: ['field-1'] },
},
],
};

const result = PerformBulkActionRequestBody.safeParse(payload);

expectParseSuccess(result);
expect(result.data).toEqual(payload);
});

test('valid request: add_investigation_fields edit action', () => {
const payload: PerformBulkActionRequestBody = {
query: 'name: test',
action: BulkActionTypeEnum.edit,
[BulkActionTypeEnum.edit]: [
{
type: BulkActionEditTypeEnum.add_investigation_fields,
value: { field_names: ['field-2'] },
},
],
};

const result = PerformBulkActionRequestBody.safeParse(payload);

expectParseSuccess(result);
expect(result.data).toEqual(payload);
});

test('valid request: delete_investigation_fields edit action', () => {
const payload: PerformBulkActionRequestBody = {
query: 'name: test',
action: BulkActionTypeEnum.edit,
[BulkActionTypeEnum.edit]: [
{
type: BulkActionEditTypeEnum.delete_investigation_fields,
value: { field_names: ['field-3'] },
},
],
};

const result = PerformBulkActionRequestBody.safeParse(payload);

expectParseSuccess(result);
expect(result.data).toEqual(payload);
});
});

describe('timeline', () => {
test('invalid request: wrong timeline payload type', () => {
const payload = {
Expand All @@ -311,7 +367,7 @@ describe('Perform bulk action request schema', () => {

expectParseError(result);
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
`"action: Invalid literal value, expected \\"delete\\", action: Invalid literal value, expected \\"disable\\", action: Invalid literal value, expected \\"enable\\", action: Invalid literal value, expected \\"export\\", action: Invalid literal value, expected \\"duplicate\\", and 7 more"`
`"action: Invalid literal value, expected \\"delete\\", action: Invalid literal value, expected \\"disable\\", action: Invalid literal value, expected \\"enable\\", action: Invalid literal value, expected \\"export\\", action: Invalid literal value, expected \\"duplicate\\", and 9 more"`
);
});

Expand All @@ -333,7 +389,7 @@ describe('Perform bulk action request schema', () => {

expectParseError(result);
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
`"action: Invalid literal value, expected \\"delete\\", action: Invalid literal value, expected \\"disable\\", action: Invalid literal value, expected \\"enable\\", action: Invalid literal value, expected \\"export\\", action: Invalid literal value, expected \\"duplicate\\", and 10 more"`
`"action: Invalid literal value, expected \\"delete\\", action: Invalid literal value, expected \\"disable\\", action: Invalid literal value, expected \\"enable\\", action: Invalid literal value, expected \\"export\\", action: Invalid literal value, expected \\"duplicate\\", and 12 more"`
);
});

Expand Down Expand Up @@ -371,7 +427,7 @@ describe('Perform bulk action request schema', () => {

expectParseError(result);
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
`"action: Invalid literal value, expected \\"delete\\", action: Invalid literal value, expected \\"disable\\", action: Invalid literal value, expected \\"enable\\", action: Invalid literal value, expected \\"export\\", action: Invalid literal value, expected \\"duplicate\\", and 7 more"`
`"action: Invalid literal value, expected \\"delete\\", action: Invalid literal value, expected \\"disable\\", action: Invalid literal value, expected \\"enable\\", action: Invalid literal value, expected \\"export\\", action: Invalid literal value, expected \\"duplicate\\", and 9 more"`
);
});

Expand Down Expand Up @@ -416,7 +472,7 @@ describe('Perform bulk action request schema', () => {

expectParseError(result);
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
`"action: Invalid literal value, expected \\"delete\\", action: Invalid literal value, expected \\"disable\\", action: Invalid literal value, expected \\"enable\\", action: Invalid literal value, expected \\"export\\", action: Invalid literal value, expected \\"duplicate\\", and 10 more"`
`"action: Invalid literal value, expected \\"delete\\", action: Invalid literal value, expected \\"disable\\", action: Invalid literal value, expected \\"enable\\", action: Invalid literal value, expected \\"export\\", action: Invalid literal value, expected \\"duplicate\\", and 12 more"`
);
});

Expand All @@ -438,7 +494,7 @@ describe('Perform bulk action request schema', () => {

expectParseError(result);
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
`"action: Invalid literal value, expected \\"delete\\", action: Invalid literal value, expected \\"disable\\", action: Invalid literal value, expected \\"enable\\", action: Invalid literal value, expected \\"export\\", action: Invalid literal value, expected \\"duplicate\\", and 10 more"`
`"action: Invalid literal value, expected \\"delete\\", action: Invalid literal value, expected \\"disable\\", action: Invalid literal value, expected \\"enable\\", action: Invalid literal value, expected \\"export\\", action: Invalid literal value, expected \\"duplicate\\", and 12 more"`
);
});

Expand Down Expand Up @@ -476,7 +532,7 @@ describe('Perform bulk action request schema', () => {

expectParseError(result);
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
`"action: Invalid literal value, expected \\"delete\\", action: Invalid literal value, expected \\"disable\\", action: Invalid literal value, expected \\"enable\\", action: Invalid literal value, expected \\"export\\", action: Invalid literal value, expected \\"duplicate\\", and 7 more"`
`"action: Invalid literal value, expected \\"delete\\", action: Invalid literal value, expected \\"disable\\", action: Invalid literal value, expected \\"enable\\", action: Invalid literal value, expected \\"export\\", action: Invalid literal value, expected \\"duplicate\\", and 9 more"`
);
});

Expand All @@ -498,7 +554,7 @@ describe('Perform bulk action request schema', () => {

expectParseError(result);
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
`"action: Invalid literal value, expected \\"delete\\", action: Invalid literal value, expected \\"disable\\", action: Invalid literal value, expected \\"enable\\", action: Invalid literal value, expected \\"export\\", action: Invalid literal value, expected \\"duplicate\\", and 11 more"`
`"action: Invalid literal value, expected \\"delete\\", action: Invalid literal value, expected \\"disable\\", action: Invalid literal value, expected \\"enable\\", action: Invalid literal value, expected \\"export\\", action: Invalid literal value, expected \\"duplicate\\", and 13 more"`
);
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import type {
BulkActionEditPayloadIndexPatterns,
BulkActionEditPayloadInvestigationFields,
BulkActionEditPayloadRuleActions,
BulkActionEditPayloadSchedule,
BulkActionEditPayloadTags,
Expand All @@ -26,5 +27,6 @@ export type BulkActionEditForRuleAttributes =
*/
export type BulkActionEditForRuleParams =
| BulkActionEditPayloadIndexPatterns
| BulkActionEditPayloadInvestigationFields
| BulkActionEditPayloadTimeline
| BulkActionEditPayloadSchedule;
1 change: 1 addition & 0 deletions x-pack/plugins/security_solution/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,7 @@ export enum BulkActionsDryRunErrCode {
MACHINE_LEARNING_AUTH = 'MACHINE_LEARNING_AUTH',
MACHINE_LEARNING_INDEX_PATTERN = 'MACHINE_LEARNING_INDEX_PATTERN',
ESQL_INDEX_PATTERN = 'ESQL_INDEX_PATTERN',
INVESTIGATION_FIELDS_FEATURE = 'INVESTIGATION_FIELDS_FEATURE',
}

export const MAX_NUMBER_OF_NEW_TERMS_FIELDS = 3;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,11 @@ export const allowedExperimentalValues = Object.freeze({
* Enables the new modal for the value list items
*/
valueListItemsModalEnabled: true,

/**
* Enables the new rule's bulk action to manage custom highlighted fields
*/
bulkCustomHighlightedFieldsEnabled: false,
});

type ExperimentalConfigKeys = Array<keyof ExperimentalFeatures>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ export enum TELEMETRY_EVENT {
DELETE_VALUE_LIST_ITEM = 'delete_value_list_item',
EDIT_VALUE_LIST_ITEM = 'edit_value_list_item',
ADDITIONAL_UPLOAD_VALUE_LIST_ITEM = 'additinonal_upload_value_list_item',

// Bulk custom highlighted fields action
ADD_INVESTIGATION_FIELDS = 'add_investigation_fields',
SET_INVESTIGATION_FIELDS = 'set_investigation_fields',
DELETE_INVESTIGATION_FIELDS = 'delete_investigation_fields',
}

export enum TelemetryEventTypes {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { TagsForm } from './forms/tags_form';
import { TimelineTemplateForm } from './forms/timeline_template_form';
import { RuleActionsForm } from './forms/rule_actions_form';
import { ScheduleForm } from './forms/schedule_form';
import { InvestigationFieldsForm } from './forms/investigation_fields_form';

interface BulkEditFlyoutProps {
onClose: () => void;
Expand All @@ -38,6 +39,11 @@ const BulkEditFlyoutComponent = ({ editAction, ...props }: BulkEditFlyoutProps)
case BulkActionEditTypeEnum.set_tags:
return <TagsForm {...props} editAction={editAction} />;

case BulkActionEditTypeEnum.add_investigation_fields:
case BulkActionEditTypeEnum.delete_investigation_fields:
case BulkActionEditTypeEnum.set_investigation_fields:
return <InvestigationFieldsForm {...props} editAction={editAction} />;

case BulkActionEditTypeEnum.set_timeline:
return <TimelineTemplateForm {...props} />;

Expand Down
Loading

0 comments on commit b4b316a

Please sign in to comment.