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

[7.6] [SIEM][Detection Engine] Critical blocker rule changes and ECS changes (#55883) #55948

Merged
merged 1 commit into from
Jan 25, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export const NewRuleSchema = t.intersection([
rule_id: t.string,
saved_id: t.string,
tags: t.array(t.string),
threats: t.array(t.unknown),
threat: t.array(t.unknown),
to: t.string,
updated_by: t.string,
}),
Expand Down Expand Up @@ -73,7 +73,7 @@ export const RuleSchema = t.intersection([
tags: t.array(t.string),
type: t.string,
to: t.string,
threats: t.array(t.unknown),
threat: t.array(t.unknown),
updated_at: t.string,
updated_by: t.string,
}),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4940,7 +4940,7 @@
"deprecationReason": null
},
{
"name": "threats",
"name": "threat",
"description": "",
"args": [],
"type": { "kind": "SCALAR", "name": "ToAny", "ofType": null },
Expand Down
2 changes: 1 addition & 1 deletion x-pack/legacy/plugins/siem/public/graphql/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1015,7 +1015,7 @@ export interface RuleField {

tags?: Maybe<string[]>;

threats?: Maybe<ToAny>;
threat?: Maybe<ToAny>;

type?: Maybe<string[]>;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { SignalsHistogramOption } from './types';
export const signalsHistogramOptions: SignalsHistogramOption[] = [
{ text: 'signal.rule.risk_score', value: 'signal.rule.risk_score' },
{ text: 'signal.rule.severity', value: 'signal.rule.severity' },
{ text: 'signal.rule.threat.tactic.name', value: 'signal.rule.threat.tactic.name' },
{ text: 'destination.ip', value: 'destination.ip' },
{ text: 'event.action', value: 'event.action' },
{ text: 'event.category', value: 'event.category' },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ export const tacticsOptions: MitreTacticsOptions[] = [
},
];

export const techniques = [
export const technique = [
{
name: '.bash_profile and .bashrc',
id: 'T1156',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export const mockRule = (id: string): Rule => ({
tags: [],
to: 'now',
type: 'saved_query',
threats: [],
threat: [],
version: 1,
});

Expand Down Expand Up @@ -87,7 +87,7 @@ export const mockTableData: TableData[] = [
saved_id: "Garrett's IP",
severity: 'low',
tags: [],
threats: [],
threat: [],
timeline_id: '86aa74d0-2136-11ea-9864-ebc8cc1cb8c2',
timeline_title: 'Untitled timeline',
to: 'now',
Expand Down Expand Up @@ -136,7 +136,7 @@ export const mockTableData: TableData[] = [
saved_id: "Garrett's IP",
severity: 'low',
tags: [],
threats: [],
threat: [],
timeline_id: '86aa74d0-2136-11ea-9864-ebc8cc1cb8c2',
timeline_title: 'Untitled timeline',
to: 'now',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import { tacticsOptions, techniquesOptions } from '../../../mitre/mitre_tactics_

import { FilterLabel } from './filter_label';
import * as i18n from './translations';
import { BuildQueryBarDescription, BuildThreatsDescription, ListItems } from './types';
import { BuildQueryBarDescription, BuildThreatDescription, ListItems } from './types';
import { SeverityBadge } from '../severity_badge';
import ListTreeIcon from './assets/list_tree_icon.svg';

Expand Down Expand Up @@ -94,7 +94,7 @@ export const buildQueryBarDescription = ({
return items;
};

const ThreatsEuiFlexGroup = styled(EuiFlexGroup)`
const ThreatEuiFlexGroup = styled(EuiFlexGroup)`
.euiFlexItem {
margin-bottom: 0px;
}
Expand All @@ -114,25 +114,22 @@ const ReferenceLinkItem = styled(EuiButtonEmpty)`
}
`;

export const buildThreatsDescription = ({
label,
threats,
}: BuildThreatsDescription): ListItems[] => {
if (threats.length > 0) {
export const buildThreatDescription = ({ label, threat }: BuildThreatDescription): ListItems[] => {
if (threat.length > 0) {
return [
{
title: label,
description: (
<ThreatsEuiFlexGroup direction="column">
{threats.map((threat, index) => {
const tactic = tacticsOptions.find(t => t.id === threat.tactic.id);
<ThreatEuiFlexGroup direction="column">
{threat.map((singleThreat, index) => {
const tactic = tacticsOptions.find(t => t.id === singleThreat.tactic.id);
return (
<EuiFlexItem key={`${threat.tactic.name}-${index}`}>
<EuiLink href={threat.tactic.reference} target="_blank">
<EuiFlexItem key={`${singleThreat.tactic.name}-${index}`}>
<EuiLink href={singleThreat.tactic.reference} target="_blank">
{tactic != null ? tactic.text : ''}
</EuiLink>
<EuiFlexGroup gutterSize="none" alignItems="flexStart" direction="column">
{threat.techniques.map(technique => {
{singleThreat.technique.map(technique => {
const myTechnique = techniquesOptions.find(t => t.id === technique.id);
return (
<EuiFlexItem>
Expand All @@ -153,7 +150,7 @@ export const buildThreatsDescription = ({
);
})}
<EuiSpacer />
</ThreatsEuiFlexGroup>
</ThreatEuiFlexGroup>
),
},
];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import {
buildQueryBarDescription,
buildSeverityDescription,
buildStringArrayDescription,
buildThreatsDescription,
buildThreatDescription,
buildUnorderedListArrayDescription,
buildUrlsDescription,
} from './helpers';
Expand Down Expand Up @@ -116,11 +116,11 @@ const getDescriptionItem = (
savedId,
indexPatterns,
});
} else if (field === 'threats') {
const threats: IMitreEnterpriseAttack[] = get(field, value).filter(
(threat: IMitreEnterpriseAttack) => threat.tactic.name !== 'none'
} else if (field === 'threat') {
const threat: IMitreEnterpriseAttack[] = get(field, value).filter(
(singleThreat: IMitreEnterpriseAttack) => singleThreat.tactic.name !== 'none'
);
return buildThreatsDescription({ label, threats });
return buildThreatDescription({ label, threat });
} else if (field === 'description') {
return [
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export interface BuildQueryBarDescription {
indexPatterns?: IIndexPattern;
}

export interface BuildThreatsDescription {
export interface BuildThreatDescription {
label: string;
threats: IMitreEnterpriseAttack[];
threat: IMitreEnterpriseAttack[];
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import { IMitreAttack } from '../../types';

export const isMitreAttackInvalid = (
tacticName: string | null | undefined,
techniques: IMitreAttack[] | null | undefined
technique: IMitreAttack[] | null | undefined
) => {
if (isEmpty(tacticName) || (tacticName !== 'none' && isEmpty(techniques))) {
if (isEmpty(tacticName) || (tacticName !== 'none' && isEmpty(technique))) {
return true;
}
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import styled from 'styled-components';
import { tacticsOptions, techniquesOptions } from '../../../mitre/mitre_tactics_techniques';
import * as Rulei18n from '../../translations';
import { FieldHook, getFieldValidityAndErrorMessage } from '../shared_imports';
import { threatsDefault } from '../step_about_rule/default_value';
import { threatDefault } from '../step_about_rule/default_value';
import { IMitreEnterpriseAttack } from '../../types';
import { MyAddItemButton } from '../add_item_form';
import { isMitreAttackInvalid } from './helpers';
Expand Down Expand Up @@ -49,7 +49,7 @@ export const AddMitreThreat = ({ dataTestSubj, field, idAria, isDisabled }: AddI
const values = field.value as string[];
const newValues = [...values.slice(0, index), ...values.slice(index + 1)];
if (isEmpty(newValues)) {
field.setValue(threatsDefault);
field.setValue(threatDefault);
} else {
field.setValue(newValues);
}
Expand All @@ -62,10 +62,10 @@ export const AddMitreThreat = ({ dataTestSubj, field, idAria, isDisabled }: AddI
if (!isEmpty(values[values.length - 1])) {
field.setValue([
...values,
{ tactic: { id: 'none', name: 'none', reference: 'none' }, techniques: [] },
{ tactic: { id: 'none', name: 'none', reference: 'none' }, technique: [] },
]);
} else {
field.setValue([{ tactic: { id: 'none', name: 'none', reference: 'none' }, techniques: [] }]);
field.setValue([{ tactic: { id: 'none', name: 'none', reference: 'none' }, technique: [] }]);
}
}, [field]);

Expand All @@ -82,7 +82,7 @@ export const AddMitreThreat = ({ dataTestSubj, field, idAria, isDisabled }: AddI
{
...values[index],
tactic: { id, reference, name },
techniques: [],
technique: [],
},
...values.slice(index + 1),
]);
Expand All @@ -96,7 +96,7 @@ export const AddMitreThreat = ({ dataTestSubj, field, idAria, isDisabled }: AddI
...values.slice(0, index),
{
...values[index],
techniques: selectedOptions,
technique: selectedOptions,
},
...values.slice(index + 1),
]);
Expand Down Expand Up @@ -133,9 +133,9 @@ export const AddMitreThreat = ({ dataTestSubj, field, idAria, isDisabled }: AddI
);

const getSelectTechniques = (item: IMitreEnterpriseAttack, index: number, disabled: boolean) => {
const invalid = isMitreAttackInvalid(item.tactic.name, item.techniques);
const invalid = isMitreAttackInvalid(item.tactic.name, item.technique);
const options = techniquesOptions.filter(t => t.tactics.includes(kebabCase(item.tactic.name)));
const selectedOptions = item.techniques.map(technic => ({
const selectedOptions = item.technique.map(technic => ({
...technic,
label: `${technic.name} (${technic.id})`, // API doesn't allow for label field
}));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export const TACTIC = i18n.translate('xpack.siem.detectionEngine.mitreAttack.tac
export const TECHNIQUE = i18n.translate(
'xpack.siem.detectionEngine.mitreAttack.techniquesDescription',
{
defaultMessage: 'technique',
defaultMessage: 'techniques',
}
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@
import { AboutStepRule } from '../../types';
import { DEFAULT_TIMELINE_TITLE } from '../../../../../components/timeline/search_super_select/translations';

export const threatsDefault = [
export const threatDefault = [
{
framework: 'MITRE ATT&CK',
tactic: { id: 'none', name: 'none', reference: 'none' },
techniques: [],
technique: [],
},
];

Expand All @@ -28,5 +28,5 @@ export const stepAboutDefaultValue: AboutStepRule = {
id: null,
title: DEFAULT_TIMELINE_TITLE,
},
threats: threatsDefault,
threat: threatDefault,
};
Original file line number Diff line number Diff line change
Expand Up @@ -227,12 +227,12 @@ const StepAboutRuleComponent: FC<StepAboutRuleProps> = ({
}}
/>
<UseField
path="threats"
path="threat"
component={AddMitreThreat}
componentProps={{
idAria: 'detectionEngineStepAboutRuleMitreThreats',
idAria: 'detectionEngineStepAboutRuleMitreThreat',
isDisabled: isLoading,
dataTestSubj: 'detectionEngineStepAboutRuleMitreThreats',
dataTestSubj: 'detectionEngineStepAboutRuleMitreThreat',
}}
/>
</AdvancedSettingsAccordion>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ export const schema: FormSchema = {
),
labelAppend: OptionalFieldLabel,
},
threats: {
threat: {
label: i18n.translate(
'xpack.siem.detectionEngine.createRule.stepAboutRule.fieldMitreThreatLabel',
{
Expand All @@ -155,7 +155,7 @@ export const schema: FormSchema = {
const [{ value, path }] = args;
let hasError = false;
(value as IMitreEnterpriseAttack[]).forEach(v => {
if (isMitreAttackInvalid(v.tactic.name, v.techniques)) {
if (isMitreAttackInvalid(v.tactic.name, v.technique)) {
hasError = true;
}
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,15 +72,7 @@ const formatScheduleStepData = (scheduleData: ScheduleStepRule): ScheduleStepRul
};

const formatAboutStepData = (aboutStepData: AboutStepRule): AboutStepRuleJson => {
const {
falsePositives,
references,
riskScore,
threats,
timeline,
isNew,
...rest
} = aboutStepData;
const { falsePositives, references, riskScore, threat, timeline, isNew, ...rest } = aboutStepData;
return {
false_positives: falsePositives.filter(item => !isEmpty(item)),
references: references.filter(item => !isEmpty(item)),
Expand All @@ -91,12 +83,12 @@ const formatAboutStepData = (aboutStepData: AboutStepRule): AboutStepRuleJson =>
timeline_title: timeline.title,
}
: {}),
threats: threats
.filter(threat => threat.tactic.name !== 'none')
.map(threat => ({
...threat,
threat: threat
.filter(singleThreat => singleThreat.tactic.name !== 'none')
.map(singleThreat => ({
...singleThreat,
framework: 'MITRE ATT&CK',
techniques: threat.techniques.map(technique => {
technique: singleThreat.technique.map(technique => {
const { id, name, reference } = technique;
return { id, name, reference };
}),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,9 @@ export const getStepsData = ({
rule != null
? {
isNew: false,
...pick(['description', 'name', 'references', 'severity', 'tags', 'threats'], rule),
...pick(['description', 'name', 'references', 'severity', 'tags', 'threat'], rule),
...(detailsView ? { name: '' } : {}),
threats: rule.threats as IMitreEnterpriseAttack[],
threat: rule.threat as IMitreEnterpriseAttack[],
falsePositives: rule.false_positives,
riskScore: rule.risk_score,
timeline: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ export interface AboutStepRule extends StepRuleData {
falsePositives: string[];
tags: string[];
timeline: FieldValueTimeline;
threats: IMitreEnterpriseAttack[];
threat: IMitreEnterpriseAttack[];
}

export interface DefineStepRule extends StepRuleData {
Expand Down Expand Up @@ -109,7 +109,7 @@ export interface AboutStepRuleJson {
tags: string[];
timeline_id?: string;
timeline_title?: string;
threats: IMitreEnterpriseAttack[];
threat: IMitreEnterpriseAttack[];
}

export interface ScheduleStepRuleJson {
Expand All @@ -134,5 +134,5 @@ export interface IMitreAttack {
export interface IMitreEnterpriseAttack {
framework: string;
tactic: IMitreAttack;
techniques: IMitreAttack[];
technique: IMitreAttack[];
}
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ export const SignalsByCategory = React.memo<Props>(
showLinkToSignals={true}
defaultStackByOption={{
text: `${i18n.SIGNALS_BY_CATEGORY}`,
value: 'signal.rule.threats',
value: 'signal.rule.threat',
}}
legendPosition={'right'}
to={to}
Expand Down
Loading