Skip to content

Commit a3d0075

Browse files
committed
Reworks form state, adds fields to signals mapping, and fixes rehydration in edit mode
1 parent be0b05f commit a3d0075

17 files changed

Lines changed: 281 additions & 79 deletions

File tree

x-pack/plugins/security_solution/public/alerts/components/rules/description_step/index.tsx

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,11 @@ import {
1818
} from '../../../../../../../../src/plugins/data/public';
1919
import { DEFAULT_TIMELINE_TITLE } from '../../../../timelines/components/timeline/translations';
2020
import { useKibana } from '../../../../common/lib/kibana';
21-
import { IMitreEnterpriseAttack } from '../../../pages/detection_engine/rules/types';
21+
import {
22+
AboutStepRiskScore,
23+
AboutStepSeverity,
24+
IMitreEnterpriseAttack,
25+
} from '../../../pages/detection_engine/rules/types';
2226
import { FieldValueTimeline } from '../pick_timeline';
2327
import { FormSchema } from '../../../../shared_imports';
2428
import { ListItems } from './types';
@@ -184,9 +188,18 @@ export const getDescriptionItem = (
184188
} else if (Array.isArray(get(field, data))) {
185189
const values: string[] = get(field, data);
186190
return buildStringArrayDescription(label, field, values);
191+
// TODO: Add custom UI for Risk/Severity Mappings (and fix missing label)
192+
} else if (field === 'riskScore') {
193+
const val: AboutStepRiskScore = get(field, data);
194+
return [
195+
{
196+
title: label,
197+
description: val.value,
198+
},
199+
];
187200
} else if (field === 'severity') {
188-
const val: string = get(field, data);
189-
return buildSeverityDescription(label, val);
201+
const val: AboutStepSeverity = get(field, data);
202+
return buildSeverityDescription(label, val.value);
190203
} else if (field === 'timeline') {
191204
const timeline = get(field, data) as FieldValueTimeline;
192205
return [

x-pack/plugins/security_solution/public/alerts/components/rules/risk_score_mapping/index.tsx

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import {
1515
EuiIcon,
1616
EuiSpacer,
1717
} from '@elastic/eui';
18-
import React, { useMemo, useState } from 'react';
18+
import React, { useCallback, useMemo, useState } from 'react';
1919
import styled from 'styled-components';
2020
import * as i18n from './translations';
2121
import { FieldHook } from '../../../../../../../../src/plugins/es_ui_shared/static/forms/hook_form_lib';
@@ -41,10 +41,23 @@ interface RiskScoreFieldProps {
4141
}
4242

4343
export const RiskScoreField = ({ dataTestSubj, field, idAria, indices }: RiskScoreFieldProps) => {
44-
// const isInvalid = field.errors.length > 0 && form.isSubmitted;
45-
// const errorMessage = field.errors.length ? (field.errors[0].message as string) : null;
4644
const [isRiskScoreMappingSelected, setIsRiskScoreMappingSelected] = useState(false);
47-
// const [riskScoreField, setRiskScoreField] = useState<string | undefined>();
45+
46+
const updateRiskScoreMapping = useCallback(
47+
(event) => {
48+
field.setValue({
49+
value: field.value.value,
50+
mapping: [
51+
{
52+
field: event.target.value,
53+
operator: 'equals',
54+
value: '',
55+
},
56+
],
57+
});
58+
},
59+
[field]
60+
);
4861

4962
const severityLabel = useMemo(() => {
5063
return (
@@ -97,7 +110,7 @@ export const RiskScoreField = ({ dataTestSubj, field, idAria, indices }: RiskSco
97110
describedByIds={idAria ? [idAria] : undefined}
98111
>
99112
<CommonUseField
100-
path="riskScore"
113+
path="riskScore.value"
101114
componentProps={{
102115
idAria: 'detectionEngineStepAboutRuleRiskScore',
103116
'data-test-subj': 'detectionEngineStepAboutRuleRiskScore',
@@ -150,8 +163,11 @@ export const RiskScoreField = ({ dataTestSubj, field, idAria, indices }: RiskSco
150163
<EuiFlexGroup alignItems="center" gutterSize="s">
151164
<EuiFlexItem>
152165
<EuiFieldText
153-
onChange={(e) => {}}
154-
aria-label="Use aria labels when no actual label is in use"
166+
data-test-subj={`detectionEngineStepAboutRuleRiskScoreMappingValue`}
167+
idAria={`detectionEngineStepAboutRuleRiskScoreMappingValue`}
168+
isDisabled={false}
169+
onChange={updateRiskScoreMapping.bind(null)}
170+
value={field.value.mapping?.[0]?.field ?? ''}
155171
/>
156172
</EuiFlexItem>
157173
<EuiFlexItemIconColumn grow={false}>

x-pack/plugins/security_solution/public/alerts/components/rules/severity_mapping/index.tsx

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import {
1515
EuiIcon,
1616
EuiSpacer,
1717
} from '@elastic/eui';
18-
import React, { useMemo, useState } from 'react';
18+
import React, { useCallback, useMemo, useState } from 'react';
1919
import styled from 'styled-components';
2020
import * as i18n from './translations';
2121
import { FieldHook } from '../../../../../../../../src/plugins/es_ui_shared/static/forms/hook_form_lib';
@@ -46,13 +46,29 @@ export const SeverityField = ({
4646
dataTestSubj,
4747
field,
4848
idAria,
49-
indices,
49+
indices, // TODO: To be used with autocomplete fields once https://github.com/elastic/kibana/pull/67013 is merged
5050
options,
5151
}: SeverityFieldProps) => {
52-
// const isInvalid = field.errors.length > 0 && form.isSubmitted;
53-
// const errorMessage = field.errors.length ? (field.errors[0].message as string) : null;
5452
const [isSeverityMappingChecked, setIsSeverityMappingChecked] = useState(false);
55-
// const [severityField, setSeverityField] = useState<string | undefined>();
53+
54+
const updateSeverityMapping = useCallback(
55+
(index: number, severity: string, mappingField: string, event) => {
56+
field.setValue({
57+
value: field.value.value,
58+
mapping: [
59+
...field.value.mapping.slice(0, index),
60+
{
61+
...field.value.mapping[index],
62+
[mappingField]: event.target.value,
63+
operator: 'equals',
64+
severity,
65+
},
66+
...field.value.mapping.slice(index + 1),
67+
],
68+
});
69+
},
70+
[field]
71+
);
5672

5773
const severityLabel = useMemo(() => {
5874
return (
@@ -159,18 +175,23 @@ export const SeverityField = ({
159175
<EuiFlexItem key={option.value}>
160176
<EuiFlexGroup alignItems="center" gutterSize="s">
161177
<EuiFlexItem>
162-
<CommonUseField
163-
path={`severity[${index}].mapping`}
164-
componentProps={{
165-
'data-test-subj': 'detectionEngineStepAboutRuleRiskScore111',
166-
idAria: 'detectionEngineStepAboutRuleRiskScore111',
167-
isDisabled: false,
168-
}}
178+
<EuiFieldText
179+
data-test-subj={`detectionEngineStepAboutRuleSeverityMappingField${option.value}`}
180+
idAria={`detectionEngineStepAboutRuleSeverityMappingField${option.value}`}
181+
isDisabled={false}
182+
onChange={updateSeverityMapping.bind(null, index, option.value, 'field')}
183+
value={field.value.mapping?.[index]?.field ?? ''}
169184
/>
170185
</EuiFlexItem>
171186

172187
<EuiFlexItem>
173-
<EuiFieldText onChange={() => {}} />
188+
<EuiFieldText
189+
data-test-subj={`detectionEngineStepAboutRuleSeverityMappingValue${option.value}`}
190+
idAria={`detectionEngineStepAboutRuleSeverityMappingValue${option.value}`}
191+
isDisabled={false}
192+
onChange={updateSeverityMapping.bind(null, index, option.value, 'value')}
193+
value={field.value.mapping?.[index]?.value ?? ''}
194+
/>
174195
</EuiFlexItem>
175196
<EuiFlexItemIconColumn grow={false}>
176197
<EuiIcon type={'sortRight'} />

x-pack/plugins/security_solution/public/alerts/components/rules/step_about_rule/default_value.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ export const stepAboutDefaultValue: AboutStepRule = {
2020
description: '',
2121
isBuildingBlock: false,
2222
isNew: true,
23-
severity: { value: 'low' },
24-
riskScore: 50,
23+
severity: { value: 'low', mapping: [] },
24+
riskScore: { value: 50, mapping: [] },
2525
references: [''],
2626
falsePositives: [''],
2727
license: '',

x-pack/plugins/security_solution/public/alerts/components/rules/step_about_rule/index.test.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -174,8 +174,8 @@ describe('StepAboutRuleComponent', () => {
174174
name: 'Test name text',
175175
note: '',
176176
references: [''],
177-
riskScore: 50,
178-
severity: { value: 'low' },
177+
riskScore: { value: 50, mapping: [] },
178+
severity: { value: 'low', mapping: [] },
179179
tags: [],
180180
threat: [
181181
{
@@ -232,8 +232,8 @@ describe('StepAboutRuleComponent', () => {
232232
name: 'Test name text',
233233
note: '',
234234
references: [''],
235-
riskScore: 80,
236-
severity: { value: 'low' },
235+
riskScore: { value: 80, mapping: [] },
236+
severity: { value: 'low', mapping: [] },
237237
tags: [],
238238
threat: [
239239
{

x-pack/plugins/security_solution/public/alerts/components/rules/step_about_rule/schema.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,13 @@ export const schema: FormSchema = {
112112
},
113113
},
114114
riskScore: {
115-
type: FIELD_TYPES.RANGE,
116-
serializer: (input: string) => Number(input),
115+
value: {
116+
type: FIELD_TYPES.RANGE,
117+
serializer: (input: string) => Number(input),
118+
},
119+
mapping: {
120+
type: FIELD_TYPES.TEXT,
121+
},
117122
},
118123
references: {
119124
label: i18n.translate(

x-pack/plugins/security_solution/public/alerts/pages/detection_engine/rules/all/__mocks__/mock.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ export const mockRule = (id: string): Rule => ({
7878

7979
export const mockRuleWithEverything = (id: string): Rule => ({
8080
actions: [],
81+
author: [],
8182
created_at: '2020-01-10T21:11:45.839Z',
8283
updated_at: '2020-01-10T21:11:45.839Z',
8384
created_by: 'elastic',
@@ -113,9 +114,12 @@ export const mockRuleWithEverything = (id: string): Rule => ({
113114
interval: '5m',
114115
rule_id: 'b5ba41ab-aaf3-4f43-971b-bdf9434ce0ea',
115116
language: 'kuery',
117+
license: 'Elastic License',
116118
output_index: '.siem-signals-default',
117119
max_signals: 100,
118120
risk_score: 21,
121+
risk_score_mapping: [],
122+
rule_name_override: 'message',
119123
name: 'Query with rule-id',
120124
query: 'user.name: root or user.name: admin',
121125
references: ['www.test.co'],
@@ -124,6 +128,7 @@ export const mockRuleWithEverything = (id: string): Rule => ({
124128
timeline_title: 'Titled timeline',
125129
meta: { from: '0m' },
126130
severity: 'low',
131+
severity_mapping: [],
127132
updated_by: 'elastic',
128133
tags: ['tag1', 'tag2'],
129134
to: 'now',
@@ -146,6 +151,7 @@ export const mockRuleWithEverything = (id: string): Rule => ({
146151
},
147152
],
148153
throttle: 'no_actions',
154+
timestamp_override: 'event.ingested',
149155
note: '# this is some markdown documentation',
150156
version: 1,
151157
});
@@ -160,8 +166,8 @@ export const mockAboutStepRule = (isNew = false): AboutStepRule => ({
160166
license: 'Elastic License',
161167
name: 'Query with rule-id',
162168
description: '24/7',
163-
severity: { value: 'low' },
164-
riskScore: 21,
169+
severity: { value: 'low', mapping: [] },
170+
riskScore: { value: 21, mapping: [] },
165171
references: ['www.test.co'],
166172
falsePositives: ['test'],
167173
tags: ['tag1', 'tag2'],

x-pack/plugins/security_solution/public/alerts/pages/detection_engine/rules/create/helpers.test.ts

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -342,14 +342,15 @@ describe('helpers', () => {
342342
author: ['Elastic'],
343343
description: '24/7',
344344
false_positives: ['test'],
345-
isBuildingBlock: false,
346345
license: 'Elastic License',
347346
name: 'Query with rule-id',
348347
note: '# this is some markdown documentation',
349348
references: ['www.test.co'],
350349
risk_score: 21,
351-
ruleNameOverride: '',
352-
severity: { value: 'low' },
350+
risk_score_mapping: [],
351+
rule_name_override: '',
352+
severity: 'low',
353+
severity_mapping: [],
353354
tags: ['tag1', 'tag2'],
354355
threat: [
355356
{
@@ -368,7 +369,7 @@ describe('helpers', () => {
368369
],
369370
},
370371
],
371-
timestampOverride: '',
372+
timestamp_override: '',
372373
};
373374

374375
expect(result).toEqual(expected);
@@ -385,14 +386,15 @@ describe('helpers', () => {
385386
author: ['Elastic'],
386387
description: '24/7',
387388
false_positives: ['test'],
388-
isBuildingBlock: false,
389389
license: 'Elastic License',
390390
name: 'Query with rule-id',
391391
note: '# this is some markdown documentation',
392392
references: ['www.test.co'],
393393
risk_score: 21,
394-
ruleNameOverride: '',
395-
severity: { value: 'low' },
394+
risk_score_mapping: [],
395+
rule_name_override: '',
396+
severity: 'low',
397+
severity_mapping: [],
396398
tags: ['tag1', 'tag2'],
397399
threat: [
398400
{
@@ -411,7 +413,7 @@ describe('helpers', () => {
411413
],
412414
},
413415
],
414-
timestampOverride: '',
416+
timestamp_override: '',
415417
};
416418

417419
expect(result).toEqual(expected);
@@ -427,13 +429,14 @@ describe('helpers', () => {
427429
author: ['Elastic'],
428430
description: '24/7',
429431
false_positives: ['test'],
430-
isBuildingBlock: false,
431432
license: 'Elastic License',
432433
name: 'Query with rule-id',
433434
references: ['www.test.co'],
434435
risk_score: 21,
435-
ruleNameOverride: '',
436-
severity: { value: 'low' },
436+
risk_score_mapping: [],
437+
rule_name_override: '',
438+
severity: 'low',
439+
severity_mapping: [],
437440
tags: ['tag1', 'tag2'],
438441
threat: [
439442
{
@@ -452,7 +455,7 @@ describe('helpers', () => {
452455
],
453456
},
454457
],
455-
timestampOverride: '',
458+
timestamp_override: '',
456459
};
457460

458461
expect(result).toEqual(expected);
@@ -497,16 +500,17 @@ describe('helpers', () => {
497500
const result: AboutStepRuleJson = formatAboutStepData(mockStepData);
498501
const expected = {
499502
author: ['Elastic'],
500-
isBuildingBlock: false,
501503
license: 'Elastic License',
502504
description: '24/7',
503505
false_positives: ['test'],
504506
name: 'Query with rule-id',
505507
note: '# this is some markdown documentation',
506508
references: ['www.test.co'],
507509
risk_score: 21,
508-
ruleNameOverride: '',
509-
severity: { value: 'low' },
510+
risk_score_mapping: [],
511+
rule_name_override: '',
512+
severity: 'low',
513+
severity_mapping: [],
510514
tags: ['tag1', 'tag2'],
511515
threat: [
512516
{
@@ -515,7 +519,7 @@ describe('helpers', () => {
515519
technique: [{ id: '456', name: 'technique1', reference: 'technique reference' }],
516520
},
517521
],
518-
timestampOverride: '',
522+
timestamp_override: '',
519523
};
520524

521525
expect(result).toEqual(expected);

0 commit comments

Comments
 (0)