Skip to content

Commit

Permalink
[8.8] [Security Solution][Alerts] resolves alerts suppression review …
Browse files Browse the repository at this point in the history
…feedback (#155839) (#157192)

# Backport

This will backport the following commits from `main` to `8.8`:
- [[Security Solution][Alerts] resolves alerts suppression review
feedback (#155839)](#155839)

<!--- Backport version: 8.9.7 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sqren/backport)

<!--BACKPORT [{"author":{"name":"Vitalii
Dmyterko","email":"92328789+vitaliidm@users.noreply.github.com"},"sourceCommit":{"committedDate":"2023-05-09T16:12:20Z","message":"[Security
Solution][Alerts] resolves alerts suppression review feedback
(#155839)\n\n## Summary\r\n\r\n- addresses review feedback
on\r\nhttps://github.com//pull/155055\r\n- addresses UI
changes from\r\nhttps://github.com//issues/150101\r\n -
removes accordion in favour of intended suppression components\r\n -
adds popover with a link to documentation\r\n - changes wording\r\n-
addresses https://github.com/elastic/kibana/issues/156247\r\n\r\n###
Before\r\n<img width=\"1017\" alt=\"Screenshot 2023-04-24 at 19 44
33\"\r\nsrc=\"https://user-images.githubusercontent.com/92328789/234824612-b0ed2870-8aa0-44af-a37d-c061358c54a3.png\">\r\n\r\n###
After\r\n\r\n#### Intended Fields\r\n<img width=\"1016\"
alt=\"Screenshot 2023-05-05 at 10 42
46\"\r\nsrc=\"https://user-images.githubusercontent.com/92328789/236426053-279d2f5b-46ea-434b-9cfa-696c71321661.png\">\r\n\r\n####
Tooltip\r\n<img width=\"1016\" alt=\"Screenshot 2023-05-05 at 10 43
41\"\r\nsrc=\"https://user-images.githubusercontent.com/92328789/236426061-1c39a5c2-63ca-4a36-b15e-2a1c1943481d.png\">\r\n\r\n---------\r\n\r\nCo-authored-by:
Kibana Machine
<42973632+kibanamachine@users.noreply.github.com>\r\nCo-authored-by:
Garrett Spong
<spong@users.noreply.github.com>","sha":"31b6062148b55f712015fc9061172eca54c0acd4","branchLabelMapping":{"^v8.9.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","Team:
SecuritySolution","Team:Detection
Alerts","backport:prev-minor","v8.8.0","v8.9.0"],"number":155839,"url":"https://github.com/elastic/kibana/pull/155839","mergeCommit":{"message":"[Security
Solution][Alerts] resolves alerts suppression review feedback
(#155839)\n\n## Summary\r\n\r\n- addresses review feedback
on\r\nhttps://github.com//pull/155055\r\n- addresses UI
changes from\r\nhttps://github.com//issues/150101\r\n -
removes accordion in favour of intended suppression components\r\n -
adds popover with a link to documentation\r\n - changes wording\r\n-
addresses https://github.com/elastic/kibana/issues/156247\r\n\r\n###
Before\r\n<img width=\"1017\" alt=\"Screenshot 2023-04-24 at 19 44
33\"\r\nsrc=\"https://user-images.githubusercontent.com/92328789/234824612-b0ed2870-8aa0-44af-a37d-c061358c54a3.png\">\r\n\r\n###
After\r\n\r\n#### Intended Fields\r\n<img width=\"1016\"
alt=\"Screenshot 2023-05-05 at 10 42
46\"\r\nsrc=\"https://user-images.githubusercontent.com/92328789/236426053-279d2f5b-46ea-434b-9cfa-696c71321661.png\">\r\n\r\n####
Tooltip\r\n<img width=\"1016\" alt=\"Screenshot 2023-05-05 at 10 43
41\"\r\nsrc=\"https://user-images.githubusercontent.com/92328789/236426061-1c39a5c2-63ca-4a36-b15e-2a1c1943481d.png\">\r\n\r\n---------\r\n\r\nCo-authored-by:
Kibana Machine
<42973632+kibanamachine@users.noreply.github.com>\r\nCo-authored-by:
Garrett Spong
<spong@users.noreply.github.com>","sha":"31b6062148b55f712015fc9061172eca54c0acd4"}},"sourceBranch":"main","suggestedTargetBranches":["8.8"],"targetPullRequestStates":[{"branch":"8.8","label":"v8.8.0","labelRegex":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"main","label":"v8.9.0","labelRegex":"^v8.9.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/155839","number":155839,"mergeCommit":{"message":"[Security
Solution][Alerts] resolves alerts suppression review feedback
(#155839)\n\n## Summary\r\n\r\n- addresses review feedback
on\r\nhttps://github.com//pull/155055\r\n- addresses UI
changes from\r\nhttps://github.com//issues/150101\r\n -
removes accordion in favour of intended suppression components\r\n -
adds popover with a link to documentation\r\n - changes wording\r\n-
addresses https://github.com/elastic/kibana/issues/156247\r\n\r\n###
Before\r\n<img width=\"1017\" alt=\"Screenshot 2023-04-24 at 19 44
33\"\r\nsrc=\"https://user-images.githubusercontent.com/92328789/234824612-b0ed2870-8aa0-44af-a37d-c061358c54a3.png\">\r\n\r\n###
After\r\n\r\n#### Intended Fields\r\n<img width=\"1016\"
alt=\"Screenshot 2023-05-05 at 10 42
46\"\r\nsrc=\"https://user-images.githubusercontent.com/92328789/236426053-279d2f5b-46ea-434b-9cfa-696c71321661.png\">\r\n\r\n####
Tooltip\r\n<img width=\"1016\" alt=\"Screenshot 2023-05-05 at 10 43
41\"\r\nsrc=\"https://user-images.githubusercontent.com/92328789/236426061-1c39a5c2-63ca-4a36-b15e-2a1c1943481d.png\">\r\n\r\n---------\r\n\r\nCo-authored-by:
Kibana Machine
<42973632+kibanamachine@users.noreply.github.com>\r\nCo-authored-by:
Garrett Spong
<spong@users.noreply.github.com>","sha":"31b6062148b55f712015fc9061172eca54c0acd4"}}]}]
BACKPORT-->

Co-authored-by: Vitalii Dmyterko <92328789+vitaliidm@users.noreply.github.com>
Co-authored-by: Pedro Jaramillo <pedro.jaramillo@elastic.co>
  • Loading branch information
3 people authored May 10, 2023
1 parent e8e87a7 commit 951802a
Show file tree
Hide file tree
Showing 10 changed files with 136 additions and 74 deletions.
1 change: 1 addition & 0 deletions packages/kbn-doc-links/src/get_doc_links.ts
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,7 @@ export const getDocLinks = ({ kibanaBranch }: GetDocLinkOptions): DocLinks => {
networkMap: `${SECURITY_SOLUTION_DOCS}conf-map-ui.html`,
troubleshootGaps: `${SECURITY_SOLUTION_DOCS}alerts-ui-monitor.html#troubleshoot-gaps`,
ruleApiOverview: `${SECURITY_SOLUTION_DOCS}rule-api-overview.html`,
configureAlertSuppression: `${SECURITY_SOLUTION_DOCS}alert-suppression.html#_configure_alert_suppression`,
},
securitySolution: {
trustedApps: `${SECURITY_SOLUTION_DOCS}trusted-apps-ov.html`,
Expand Down
1 change: 1 addition & 0 deletions packages/kbn-doc-links/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,7 @@ export interface DocLinks {
readonly networkMap: string;
readonly troubleshootGaps: string;
readonly ruleApiOverview: string;
readonly configureAlertSuppression: string;
};
readonly securitySolution: {
readonly trustedApps: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,13 +151,13 @@ export const ALERT_SUPPRESSION_PER_RULE_EXECUTION = i18n.translate(
export const ALERT_SUPPRESSION_SUPPRESS_ON_MISSING_FIELDS = i18n.translate(
'xpack.securitySolution.detectionEngine.ruleDescription.alertSuppressionSuppressOnMissingFieldsDescription',
{
defaultMessage: 'Suppress on missing field value',
defaultMessage: 'Suppress and group alerts for events with missing fields',
}
);

export const ALERT_SUPPRESSION_DO_NOT_SUPPRESS_ON_MISSING_FIELDS = i18n.translate(
'xpack.securitySolution.detectionEngine.ruleDescription.alertSuppressionDoNotSuppressOnMissingFieldsDescription',
{
defaultMessage: 'Do not suppress',
defaultMessage: 'Do not suppress alerts for events with missing fields',
}
);
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

import type { EuiButtonGroupOptionProps } from '@elastic/eui';
import {
EuiAccordion,
EuiButtonEmpty,
EuiFlexGroup,
EuiFlexItem,
Expand Down Expand Up @@ -58,6 +57,7 @@ import { PickTimeline } from '../pick_timeline';
import { StepContentWrapper } from '../step_content_wrapper';
import { NextStep } from '../next_step';
import { ThresholdInput } from '../threshold_input';
import { SuppressionInfoIcon } from '../suppression_info_icon';
import {
Field,
Form,
Expand Down Expand Up @@ -129,6 +129,10 @@ const RuleTypeEuiFormRow = styled(EuiFormRow).attrs<{ $isVisible: boolean }>(({
},
}))<{ $isVisible: boolean }>``;

const IntendedRuleTypeEuiFormRow = styled(RuleTypeEuiFormRow)`
${({ theme }) => `padding-left: ${theme.eui.euiSizeXL};`}
`;

const StepDefineRuleComponent: FC<StepDefineRuleProps> = ({
addPadding = false,
defaultValues: initialState,
Expand Down Expand Up @@ -899,68 +903,63 @@ const StepDefineRuleComponent: FC<StepDefineRuleProps> = ({
</>
)}

<EuiSpacer size="l" />
<EuiAccordion
data-test-subj="alertSuppressionAccordion"
id="alertSuppressionAccordion"
buttonContent={i18n.ALERT_SUPPRESSION_ACCORDION_BUTTON}
<RuleTypeEuiFormRow
$isVisible={isQueryRule(ruleType)}
data-test-subj="alertSuppressionInput"
>
<EuiSpacer size="l" />

<RuleTypeEuiFormRow
$isVisible={isQueryRule(ruleType)}
data-test-subj="alertSuppressionInput"
>
<UseField
path="groupByFields"
component={GroupByFields}
componentProps={{
browserFields: termsAggregationFields,
isDisabled:
!license.isAtLeast(minimumLicenseForSuppression) &&
initialState.groupByFields.length === 0,
}}
/>
</RuleTypeEuiFormRow>
<UseField
path="groupByFields"
component={GroupByFields}
componentProps={{
browserFields: termsAggregationFields,
isDisabled:
!license.isAtLeast(minimumLicenseForSuppression) &&
initialState.groupByFields.length === 0,
}}
/>
</RuleTypeEuiFormRow>

<RuleTypeEuiFormRow
$isVisible={isQueryRule(ruleType)}
data-test-subj="alertSuppressionDuration"
<IntendedRuleTypeEuiFormRow
$isVisible={isQueryRule(ruleType)}
data-test-subj="alertSuppressionDuration"
>
<UseMultiFields
fields={{
groupByRadioSelection: {
path: 'groupByRadioSelection',
},
groupByDurationValue: {
path: 'groupByDuration.value',
},
groupByDurationUnit: {
path: 'groupByDuration.unit',
},
}}
>
<UseMultiFields
fields={{
groupByRadioSelection: {
path: 'groupByRadioSelection',
},
groupByDurationValue: {
path: 'groupByDuration.value',
},
groupByDurationUnit: {
path: 'groupByDuration.unit',
},
}}
>
{GroupByChildren}
</UseMultiFields>
</RuleTypeEuiFormRow>

<RuleTypeEuiFormRow
$isVisible={isQueryRule(ruleType)}
data-test-subj="alertSuppressionMissingFields"
label={i18n.ALERT_SUPPRESSION_MISSING_FIELDS_FORM_ROW_LABEL}
{GroupByChildren}
</UseMultiFields>
</IntendedRuleTypeEuiFormRow>

<IntendedRuleTypeEuiFormRow
$isVisible={isQueryRule(ruleType)}
data-test-subj="alertSuppressionMissingFields"
label={
<span>
{i18n.ALERT_SUPPRESSION_MISSING_FIELDS_FORM_ROW_LABEL} <SuppressionInfoIcon />
</span>
}
fullWidth
>
<UseMultiFields
fields={{
suppressionMissingFields: {
path: 'suppressionMissingFields',
},
}}
>
<UseMultiFields
fields={{
suppressionMissingFields: {
path: 'suppressionMissingFields',
},
}}
>
{AlertsSuppressionMissingFields}
</UseMultiFields>
</RuleTypeEuiFormRow>
</EuiAccordion>
<EuiSpacer size="l" />
{AlertsSuppressionMissingFields}
</UseMultiFields>
</IntendedRuleTypeEuiFormRow>

<RuleTypeEuiFormRow $isVisible={isMlRule(ruleType)} fullWidth>
<>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -626,7 +626,7 @@ export const schema: FormSchema<DefineStepRule> = {
label: i18n.translate(
'xpack.securitySolution.detectionEngine.createRule.stepDefineRule.suppressionMissingFieldsLabel',
{
defaultMessage: 'If “Suppress by” field does not exist',
defaultMessage: 'If a suppression field is missing',
}
),
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,30 +150,23 @@ export const RULE_PREVIEW_TITLE = i18n.translate(
}
);

export const ALERT_SUPPRESSION_ACCORDION_BUTTON = i18n.translate(
'xpack.securitySolution.detectionEngine.createRule.stepDefineRule.alertSuppressionAccordionButtonLabel',
{
defaultMessage: 'Suppression Configuration',
}
);

export const ALERT_SUPPRESSION_MISSING_FIELDS_FORM_ROW_LABEL = i18n.translate(
'xpack.securitySolution.detectionEngine.createRule.stepDefineRule.alertSuppressionMissingFieldsLabel',
{
defaultMessage: 'If “Suppress by” field does not exist',
defaultMessage: 'If a suppression field is missing',
}
);

export const ALERT_SUPPRESSION_MISSING_FIELDS_SUPPRESS_OPTION = i18n.translate(
'xpack.securitySolution.detectionEngine.createRule.stepDefineRule.alertSuppressionMissingFieldsSuppressLabel',
{
defaultMessage: 'Suppress on missing field value',
defaultMessage: 'Suppress and group alerts for events with missing fields',
}
);

export const ALERT_SUPPRESSION_MISSING_FIELDS_DO_NOT_SUPPRESS_OPTION = i18n.translate(
'xpack.securitySolution.detectionEngine.createRule.stepDefineRule.alertSuppressionMissingFieldsDoNotSuppressLabel',
{
defaultMessage: 'Do not suppress',
defaultMessage: 'Do not suppress alerts for events with missing fields',
}
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
* 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 React, { useState } from 'react';
import { EuiLink, EuiPopover, EuiText, EuiButtonIcon } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n-react';

import { useKibana } from '../../../../common/lib/kibana';

const POPOVER_WIDTH = 320;

/**
* Icon and popover that gives hint to users how suppression for missing fields work
*/
const SuppressionInfoIconComponent = () => {
const [isPopoverOpen, setIsPopoverOpen] = useState(false);
const { docLinks } = useKibana().services;

const onButtonClick = () => setIsPopoverOpen(!isPopoverOpen);
const closePopover = () => setIsPopoverOpen(false);

const button = (
<EuiButtonIcon
iconType="questionInCircle"
onClick={onButtonClick}
aria-label="Open help popover"
/>
);

return (
<EuiPopover button={button} isOpen={isPopoverOpen} closePopover={closePopover}>
<EuiText style={{ width: POPOVER_WIDTH }} size="s">
<FormattedMessage
id="xpack.securitySolution.detectionEngine.createRule.stepDefineRule.alertSuppressionMissingFieldsTooltipContent"
defaultMessage="Choose how to handle events with missing {suppressBy} fields. Either group events with missing fields together, or create a separate alert for each event. {learnMoreLink}"
values={{
suppressBy: (
<strong>
<FormattedMessage
id="xpack.securitySolution.detectionEngine.createRule.stepDefineRule.alertSuppressionMissingFieldsTooltipSuppressByDescription"
defaultMessage="Suppress alerts by"
/>
</strong>
),
learnMoreLink: (
<EuiLink href={docLinks.links.siem.configureAlertSuppression} target="_blank">
<FormattedMessage
id="xpack.securitySolution.detectionEngine.createRule.stepDefineRule.alertSuppressionMissingFieldsTooltipLink"
defaultMessage="Learn more"
/>
</EuiLink>
),
}}
/>
</EuiText>
</EuiPopover>
);
};

export const SuppressionInfoIcon = React.memo(SuppressionInfoIconComponent);

SuppressionInfoIcon.displayName = 'SuppressionInfoIcon';
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { DEFAULT_THREAT_MATCH_QUERY, RULES_PATH } from '../../../../../common/co
import type { AboutStepRule, DefineStepRule, RuleStepsOrder, ScheduleStepRule } from './types';
import { DataSourceType, GroupByOptions, RuleStep } from './types';
import type { GetSecuritySolutionUrl } from '../../../../common/components/link_to';
import { DEFAULT_SUPPRESSION_MISSING_FIELDS_STRATEGY } from '../../../../../common/detection_engine/rule_schema';
import {
RuleDetailTabs,
RULE_DETAILS_TAB_NAME,
Expand Down Expand Up @@ -154,6 +155,7 @@ export const stepDefineDefaultValue: DefineStepRule = {
value: 5,
unit: 'm',
},
suppressionMissingFields: DEFAULT_SUPPRESSION_MISSING_FIELDS_STRATEGY,
};

export const stepAboutDefaultValue: AboutStepRule = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export const bulkCreateUnsuppressedAlerts: BulkCreateUnsuppressedAlerts = async
}) => {
const bulkCreatedResult = await searchAfterAndBulkCreate({
tuple: { ...runOpts.tuple, maxSignals: size },
exceptionsList: runOpts.unprocessedExceptions,
exceptionsList: [],
services,
listClient: runOpts.listClient,
ruleExecutionLogger: runOpts.ruleExecutionLogger,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1911,7 +1911,7 @@ export default ({ getService }: FtrProviderContext) => {
const firstDoc = { id, '@timestamp': timestamp, agent: { name: 'agent-1' } };
const secondDoc = { id, '@timestamp': laterTimestamp, agent: { name: 'agent-1' } };
const thirdDoc = { id, '@timestamp': laterTimestamp, agent: { name: 'agent-2' } };
const missingFieldDoc1 = { id, '@timestamp': laterTimestamp };
const missingFieldDoc1 = { id, '@timestamp': timestamp };
const missingFieldDoc2 = { id, '@timestamp': laterTimestamp };

await indexListOfDocuments([
Expand Down

0 comments on commit 951802a

Please sign in to comment.