mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
# Backport This will backport the following commits from `main` to `8.8`: - [[Security Solution][Alerts] resolves alerts suppression review feedback (#155839)](https://github.com/elastic/kibana/pull/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/elastic/kibana/pull/155055\r\n- addresses UI changes from\r\nhttps://github.com/elastic/kibana/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/elastic/kibana/pull/155055\r\n- addresses UI changes from\r\nhttps://github.com/elastic/kibana/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/elastic/kibana/pull/155055\r\n- addresses UI changes from\r\nhttps://github.com/elastic/kibana/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>
This commit is contained in:
parent
e8e87a7629
commit
951802a7a9
10 changed files with 135 additions and 73 deletions
|
@ -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`,
|
||||
|
|
|
@ -283,6 +283,7 @@ export interface DocLinks {
|
|||
readonly networkMap: string;
|
||||
readonly troubleshootGaps: string;
|
||||
readonly ruleApiOverview: string;
|
||||
readonly configureAlertSuppression: string;
|
||||
};
|
||||
readonly securitySolution: {
|
||||
readonly trustedApps: string;
|
||||
|
|
|
@ -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',
|
||||
}
|
||||
);
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
|
||||
import type { EuiButtonGroupOptionProps } from '@elastic/eui';
|
||||
import {
|
||||
EuiAccordion,
|
||||
EuiButtonEmpty,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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" />
|
||||
<UseField
|
||||
path="groupByFields"
|
||||
component={GroupByFields}
|
||||
componentProps={{
|
||||
browserFields: termsAggregationFields,
|
||||
isDisabled:
|
||||
!license.isAtLeast(minimumLicenseForSuppression) &&
|
||||
initialState.groupByFields.length === 0,
|
||||
}}
|
||||
/>
|
||||
</RuleTypeEuiFormRow>
|
||||
|
||||
<RuleTypeEuiFormRow
|
||||
$isVisible={isQueryRule(ruleType)}
|
||||
data-test-subj="alertSuppressionInput"
|
||||
<IntendedRuleTypeEuiFormRow
|
||||
$isVisible={isQueryRule(ruleType)}
|
||||
data-test-subj="alertSuppressionDuration"
|
||||
>
|
||||
<UseMultiFields
|
||||
fields={{
|
||||
groupByRadioSelection: {
|
||||
path: 'groupByRadioSelection',
|
||||
},
|
||||
groupByDurationValue: {
|
||||
path: 'groupByDuration.value',
|
||||
},
|
||||
groupByDurationUnit: {
|
||||
path: 'groupByDuration.unit',
|
||||
},
|
||||
}}
|
||||
>
|
||||
<UseField
|
||||
path="groupByFields"
|
||||
component={GroupByFields}
|
||||
componentProps={{
|
||||
browserFields: termsAggregationFields,
|
||||
isDisabled:
|
||||
!license.isAtLeast(minimumLicenseForSuppression) &&
|
||||
initialState.groupByFields.length === 0,
|
||||
}}
|
||||
/>
|
||||
</RuleTypeEuiFormRow>
|
||||
{GroupByChildren}
|
||||
</UseMultiFields>
|
||||
</IntendedRuleTypeEuiFormRow>
|
||||
|
||||
<RuleTypeEuiFormRow
|
||||
$isVisible={isQueryRule(ruleType)}
|
||||
data-test-subj="alertSuppressionDuration"
|
||||
<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={{
|
||||
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}
|
||||
>
|
||||
<UseMultiFields
|
||||
fields={{
|
||||
suppressionMissingFields: {
|
||||
path: 'suppressionMissingFields',
|
||||
},
|
||||
}}
|
||||
>
|
||||
{AlertsSuppressionMissingFields}
|
||||
</UseMultiFields>
|
||||
</RuleTypeEuiFormRow>
|
||||
</EuiAccordion>
|
||||
<EuiSpacer size="l" />
|
||||
{AlertsSuppressionMissingFields}
|
||||
</UseMultiFields>
|
||||
</IntendedRuleTypeEuiFormRow>
|
||||
|
||||
<RuleTypeEuiFormRow $isVisible={isMlRule(ruleType)} fullWidth>
|
||||
<>
|
||||
|
|
|
@ -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',
|
||||
}
|
||||
),
|
||||
},
|
||||
|
|
|
@ -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',
|
||||
}
|
||||
);
|
||||
|
|
|
@ -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';
|
|
@ -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,
|
||||
|
@ -154,6 +155,7 @@ export const stepDefineDefaultValue: DefineStepRule = {
|
|||
value: 5,
|
||||
unit: 'm',
|
||||
},
|
||||
suppressionMissingFields: DEFAULT_SUPPRESSION_MISSING_FIELDS_STRATEGY,
|
||||
};
|
||||
|
||||
export const stepAboutDefaultValue: AboutStepRule = {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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([
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue