[Security Solution][Detection Engine] use Upselling Service for alert suppression licensing messages (#172555)

## Summary

Small refactoring PR

Use common [Upselling Service
](https://github.com/elastic/kibana/tree/main/x-pack/packages/security-solution/upselling/service)
for alert suppression licensing messages, instead of manual hardcoding,
in:

- rule details section
- rule form

No changes in UI
This commit is contained in:
Vitalii Dmyterko 2023-12-06 09:35:08 +00:00 committed by GitHub
parent 165a1bdd01
commit b45c1890e2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 60 additions and 74 deletions

View file

@ -22,3 +22,19 @@ export const UPGRADE_ALERT_ASSIGNMENTS = (requiredLicense: string) =>
requiredLicense,
},
});
export const ALERT_SUPPRESSION_RULE_FORM = (requiredLicense: 'Platinum') =>
i18n.translate('securitySolutionPackages.alertSuppressionRuleForm.upsell', {
defaultMessage: 'Alert suppression is enabled with {requiredLicense} license or above',
values: {
requiredLicense,
},
});
export const ALERT_SUPPRESSION_RULE_DETAILS = i18n.translate(
'securitySolutionPackages.alertSuppressionRuleDetails.upsell',
{
defaultMessage:
'Alert suppression is configured but will not be applied due to insufficient licensing',
}
);

View file

@ -17,4 +17,8 @@ export type UpsellingSectionId =
| 'osquery_automated_response_actions'
| 'ruleDetailsEndpointExceptions';
export type UpsellingMessageId = 'investigation_guide' | 'alert_assignments';
export type UpsellingMessageId =
| 'investigation_guide'
| 'alert_assignments'
| 'alert_suppression_rule_form'
| 'alert_suppression_rule_details';

View file

@ -40,7 +40,6 @@ import * as descriptionStepI18n from '../../../../detections/components/rules/de
import { RelatedIntegrationsDescription } from '../../../../detections/components/rules/related_integrations/integrations_description';
import { AlertSuppressionTechnicalPreviewBadge } from '../../../../detections/components/rules/description_step/alert_suppression_technical_preview_badge';
import { useGetSavedQuery } from '../../../../detections/pages/detection_engine/rules/use_get_saved_query';
import { useLicense } from '../../../../common/hooks/use_license';
import * as threatMatchI18n from '../../../../common/components/threat_match/translations';
import * as timelinesI18n from '../../../../timelines/components/timeline/translations';
import { useRuleIndexPattern } from '../../../rule_creation_ui/pages/form';
@ -357,9 +356,7 @@ interface AlertSuppressionTitleProps {
}
const AlertSuppressionTitle = ({ title }: AlertSuppressionTitleProps) => {
const license = useLicense();
return <AlertSuppressionTechnicalPreviewBadge label={title} license={license} />;
return <AlertSuppressionTechnicalPreviewBadge label={title} />;
};
interface SuppressAlertsByFieldProps {

View file

@ -8,26 +8,24 @@
import React from 'react';
import { EuiIcon, EuiToolTip } from '@elastic/eui';
import type { LicenseService } from '../../../../../common/license';
import { TechnicalPreviewBadge } from '../technical_preview_badge';
import * as i18n from './translations';
import { MINIMUM_LICENSE_FOR_SUPPRESSION } from '../../../../../common/detection_engine/constants';
import { useUpsellingMessage } from '../../../../common/hooks/use_upselling';
interface TechnicalPreviewBadgeProps {
label: string;
license: LicenseService;
}
export const AlertSuppressionTechnicalPreviewBadge = ({
label,
license,
}: TechnicalPreviewBadgeProps) => (
<>
<TechnicalPreviewBadge label={label} />
{!license.isAtLeast(MINIMUM_LICENSE_FOR_SUPPRESSION) && (
<EuiToolTip position="top" content={i18n.ALERT_SUPPRESSION_INSUFFICIENT_LICENSE}>
<EuiIcon type={'warning'} size="l" color="#BD271E" style={{ marginLeft: '8px' }} />
</EuiToolTip>
)}
</>
);
export const AlertSuppressionTechnicalPreviewBadge = ({ label }: TechnicalPreviewBadgeProps) => {
const alertSuppressionUpsellingMessage = useUpsellingMessage('alert_suppression_rule_details');
return (
<>
<TechnicalPreviewBadge label={label} />
{alertSuppressionUpsellingMessage && (
<EuiToolTip position="top" content={alertSuppressionUpsellingMessage}>
<EuiIcon type={'warning'} size="l" color="#BD271E" style={{ marginLeft: '8px' }} />
</EuiToolTip>
)}
</>
);
};

View file

@ -52,7 +52,6 @@ import { defaultToEmptyTag } from '../../../../common/components/empty_value';
import { ThreatEuiFlexGroup } from './threat_description';
import { AlertSuppressionTechnicalPreviewBadge } from './alert_suppression_technical_preview_badge';
import { TechnicalPreviewBadge } from '../technical_preview_badge';
import type { LicenseService } from '../../../../../common/license';
const NoteDescriptionContainer = styled(EuiFlexItem)`
height: 105px;
overflow-y: hidden;
@ -569,11 +568,7 @@ export const buildRequiredFieldsDescription = (
];
};
export const buildAlertSuppressionDescription = (
label: string,
values: string[],
license: LicenseService
): ListItems[] => {
export const buildAlertSuppressionDescription = (label: string, values: string[]): ListItems[] => {
if (isEmpty(values)) {
return [];
}
@ -591,7 +586,7 @@ export const buildAlertSuppressionDescription = (
</EuiFlexGroup>
);
const title = <AlertSuppressionTechnicalPreviewBadge label={label} license={license} />;
const title = <AlertSuppressionTechnicalPreviewBadge label={label} />;
return [
{
title,
@ -603,7 +598,6 @@ export const buildAlertSuppressionDescription = (
export const buildAlertSuppressionWindowDescription = (
label: string,
value: Duration,
license: LicenseService,
groupByRadioSelection: GroupByOptions
): ListItems[] => {
const description =
@ -611,7 +605,7 @@ export const buildAlertSuppressionWindowDescription = (
? `${value.value}${value.unit}`
: i18n.ALERT_SUPPRESSION_PER_RULE_EXECUTION;
const title = <AlertSuppressionTechnicalPreviewBadge label={label} license={license} />;
const title = <AlertSuppressionTechnicalPreviewBadge label={label} />;
return [
{
title,
@ -622,8 +616,7 @@ export const buildAlertSuppressionWindowDescription = (
export const buildAlertSuppressionMissingFieldsDescription = (
label: string,
value: AlertSuppressionMissingFieldsStrategy,
license: LicenseService
value: AlertSuppressionMissingFieldsStrategy
): ListItems[] => {
if (isEmpty(value)) {
return [];
@ -634,7 +627,7 @@ export const buildAlertSuppressionMissingFieldsDescription = (
? i18n.ALERT_SUPPRESSION_SUPPRESS_ON_MISSING_FIELDS
: i18n.ALERT_SUPPRESSION_DO_NOT_SUPPRESS_ON_MISSING_FIELDS;
const title = <AlertSuppressionTechnicalPreviewBadge label={label} license={license} />;
const title = <AlertSuppressionTechnicalPreviewBadge label={label} />;
return [
{
title,

View file

@ -205,7 +205,7 @@ export const getDescriptionItem = (
return [];
} else if (field === 'groupByFields') {
const values: string[] = get(field, data);
return buildAlertSuppressionDescription(label, values, license);
return buildAlertSuppressionDescription(label, values);
} else if (field === 'groupByRadioSelection') {
return [];
} else if (field === 'groupByDuration') {
@ -214,7 +214,6 @@ export const getDescriptionItem = (
return buildAlertSuppressionWindowDescription(
label,
value,
license,
get('groupByRadioSelection', data)
);
} else {
@ -223,7 +222,7 @@ export const getDescriptionItem = (
} else if (field === 'suppressionMissingFields') {
if (get('groupByFields', data).length > 0) {
const value = get(field, data);
return buildAlertSuppressionMissingFieldsDescription(label, value, license);
return buildAlertSuppressionMissingFieldsDescription(label, value);
} else {
return [];
}

View file

@ -147,14 +147,6 @@ export const EQL_TIMESTAMP_FIELD_LABEL = i18n.translate(
}
);
export const ALERT_SUPPRESSION_INSUFFICIENT_LICENSE = i18n.translate(
'xpack.securitySolution.detectionEngine.ruleDescription.alertSuppressionInsufficientLicense',
{
defaultMessage:
'Alert suppression is configured but will not be applied due to insufficient licensing',
}
);
export const ALERT_SUPPRESSION_PER_RULE_EXECUTION = i18n.translate(
'xpack.securitySolution.detectionEngine.ruleDescription.alertSuppressionPerRuleExecution',
{

View file

@ -84,6 +84,7 @@ import { AlertSuppressionMissingFieldsStrategyEnum } from '../../../../../common
import { DurationInput } from '../duration_input';
import { MINIMUM_LICENSE_FOR_SUPPRESSION } from '../../../../../common/detection_engine/constants';
import { useIsExperimentalFeatureEnabled } from '../../../../common/hooks/use_experimental_features';
import { useUpsellingMessage } from '../../../../common/hooks/use_upselling';
const CommonUseField = getUseField({ component: Field });
@ -187,6 +188,7 @@ const StepDefineRuleComponent: FC<StepDefineRuleProps> = ({
const isAlertSuppressionLicenseValid = license.isAtLeast(MINIMUM_LICENSE_FOR_SUPPRESSION);
const isThresholdRule = getIsThresholdRule(ruleType);
const alertSuppressionUpsellingMessage = useUpsellingMessage('alert_suppression_rule_form');
const { getFields, reset, setFieldValue } = form;
@ -981,14 +983,7 @@ const StepDefineRuleComponent: FC<StepDefineRuleProps> = ({
<EuiSpacer size="m" />
<RuleTypeEuiFormRow $isVisible={isAlertSuppressionEnabled && isThresholdRule} fullWidth>
<EuiToolTip
content={
!isAlertSuppressionLicenseValid
? i18n.ENABLE_THRESHOLD_SUPPRESSION_LICENSE_WARNING
: null
}
position="right"
>
<EuiToolTip content={alertSuppressionUpsellingMessage} position="right">
<CommonUseField
path="enableThresholdSuppression"
componentProps={{
@ -1012,7 +1007,7 @@ const StepDefineRuleComponent: FC<StepDefineRuleProps> = ({
component={MultiSelectFieldsAutocomplete}
componentProps={{
browserFields: termsAggregationFields,
disabledText: i18n.GROUP_BY_FIELD_LICENSE_WARNING,
disabledText: alertSuppressionUpsellingMessage,
isDisabled: !isAlertSuppressionLicenseValid,
}}
/>

View file

@ -188,20 +188,6 @@ export const ESQL_QUERY = i18n.translate(
}
);
export const GROUP_BY_FIELD_LICENSE_WARNING = i18n.translate(
'xpack.securitySolution.detectionEngine.createRule.stepDefineRule.groupBy.licenseWarning',
{
defaultMessage: 'Alert suppression is enabled with Platinum license or above',
}
);
export const ENABLE_THRESHOLD_SUPPRESSION_LICENSE_WARNING = i18n.translate(
'xpack.securitySolution.detectionEngine.createRule.stepDefineRule.enableThresholdSuppression.licenseWarning',
{
defaultMessage: 'Alert suppression is enabled with Platinum license or above',
}
);
export const ALERT_SUPPRESSION_PER_RULE_EXECUTION = i18n.translate(
'xpack.securitySolution.detectionEngine.createRule.stepDefineRule.alertSuppressionOptions.perRuleExecutionLabel',
{

View file

@ -19,6 +19,8 @@ import React, { lazy } from 'react';
import {
UPGRADE_ALERT_ASSIGNMENTS,
UPGRADE_INVESTIGATION_GUIDE,
ALERT_SUPPRESSION_RULE_FORM,
ALERT_SUPPRESSION_RULE_DETAILS,
} from '@kbn/security-solution-upselling/messages';
import type { Services } from '../common/services';
import { withServicesProvider } from '../common/services';
@ -115,4 +117,14 @@ export const upsellingMessages: UpsellingMessages = [
minimumLicenseRequired: 'platinum',
message: UPGRADE_ALERT_ASSIGNMENTS('Platinum'),
},
{
id: 'alert_suppression_rule_form',
minimumLicenseRequired: 'platinum',
message: ALERT_SUPPRESSION_RULE_FORM('Platinum'),
},
{
id: 'alert_suppression_rule_details',
minimumLicenseRequired: 'platinum',
message: ALERT_SUPPRESSION_RULE_DETAILS,
},
];

View file

@ -33169,7 +33169,6 @@
"xpack.securitySolution.detectionEngine.createRule.stepDefineRule.fieldThresholdCardinalityValueFieldLabel": "Valeurs uniques",
"xpack.securitySolution.detectionEngine.createRule.stepDefineRule.fieldThresholdFieldCardinalityFieldHelpText": "Sélectionner un champ pour vérifier la cardinalité",
"xpack.securitySolution.detectionEngine.createRule.stepDefineRule.fieldThresholdLabel": "Seuil",
"xpack.securitySolution.detectionEngine.createRule.stepDefineRule.groupBy.licenseWarning": "La suppression d'alertes est activée avec la licence Platinum ou supérieure",
"xpack.securitySolution.detectionEngine.createRule.stepDefineRule.groupByDurationValueLabel": "Supprimer les alertes pour",
"xpack.securitySolution.detectionEngine.createRule.stepDefineRule.groupByFieldsLabel": "Supprimer les alertes par",
"xpack.securitySolution.detectionEngine.createRule.stepDefineRule.groupByFieldsLabelAppend": "Facultatif (version d'évaluation technique)",
@ -33944,7 +33943,6 @@
"xpack.securitySolution.detectionEngine.relatedIntegrations.uninstalledTooltip": "Lintégration nest pas installée. Suivez le lien d'intégration pour installer et configurer l'intégration.",
"xpack.securitySolution.detectionEngine.rule.editRule.actionSectionsTitle": "Actions",
"xpack.securitySolution.detectionEngine.ruleDescription.alertSuppressionDoNotSuppressOnMissingFieldsDescription": "Ne pas supprimer dalertes pour les événements avec des champs manquants",
"xpack.securitySolution.detectionEngine.ruleDescription.alertSuppressionInsufficientLicense": "La suppression d'alertes est configurée mais elle ne sera pas appliquée en raison d'une licence insuffisante",
"xpack.securitySolution.detectionEngine.ruleDescription.alertSuppressionPerRuleExecution": "Exécution d'une règle",
"xpack.securitySolution.detectionEngine.ruleDescription.alertSuppressionSuppressOnMissingFieldsDescription": "Supprimer et regrouper les alertes pour les événements avec des champs manquants",
"xpack.securitySolution.detectionEngine.ruleDescription.buildingBlockDescription": "Toutes les alertes générées sont marquées comme \"fondamentales\"",

View file

@ -33168,7 +33168,6 @@
"xpack.securitySolution.detectionEngine.createRule.stepDefineRule.fieldThresholdCardinalityValueFieldLabel": "一意の値",
"xpack.securitySolution.detectionEngine.createRule.stepDefineRule.fieldThresholdFieldCardinalityFieldHelpText": "カーディナリティを確認するフィールドを選択します",
"xpack.securitySolution.detectionEngine.createRule.stepDefineRule.fieldThresholdLabel": "しきい値",
"xpack.securitySolution.detectionEngine.createRule.stepDefineRule.groupBy.licenseWarning": "アラートの非表示は、プラチナライセンス以上で有効です",
"xpack.securitySolution.detectionEngine.createRule.stepDefineRule.groupByDurationValueLabel": "アラートを非表示",
"xpack.securitySolution.detectionEngine.createRule.stepDefineRule.groupByFieldsLabel": "アラートを非表示",
"xpack.securitySolution.detectionEngine.createRule.stepDefineRule.groupByFieldsLabelAppend": "任意(テクニカルプレビュー)",
@ -33943,7 +33942,6 @@
"xpack.securitySolution.detectionEngine.relatedIntegrations.uninstalledTooltip": "統合はインストールされていません。統合リンクに従って、インストールし、統合を構成してください。",
"xpack.securitySolution.detectionEngine.rule.editRule.actionSectionsTitle": "アクション",
"xpack.securitySolution.detectionEngine.ruleDescription.alertSuppressionDoNotSuppressOnMissingFieldsDescription": "フィールドが欠落しているイベントのアラートを抑制しない",
"xpack.securitySolution.detectionEngine.ruleDescription.alertSuppressionInsufficientLicense": "アラート非表示が構成されていますが、ライセンス不足のため適用されません",
"xpack.securitySolution.detectionEngine.ruleDescription.alertSuppressionPerRuleExecution": "1つのルール実行",
"xpack.securitySolution.detectionEngine.ruleDescription.alertSuppressionSuppressOnMissingFieldsDescription": "フィールドが欠落しているイベントのアラートを抑制してグループ化",
"xpack.securitySolution.detectionEngine.ruleDescription.buildingBlockDescription": "すべての生成されたアラートが「基本」アラートに設定されます",

View file

@ -33163,7 +33163,6 @@
"xpack.securitySolution.detectionEngine.createRule.stepDefineRule.fieldThresholdCardinalityValueFieldLabel": "唯一值",
"xpack.securitySolution.detectionEngine.createRule.stepDefineRule.fieldThresholdFieldCardinalityFieldHelpText": "选择字段以检查基数",
"xpack.securitySolution.detectionEngine.createRule.stepDefineRule.fieldThresholdLabel": "阈值",
"xpack.securitySolution.detectionEngine.createRule.stepDefineRule.groupBy.licenseWarning": "告警阻止通过白金级或更高级许可证启用",
"xpack.securitySolution.detectionEngine.createRule.stepDefineRule.groupByDurationValueLabel": "阻止以下项的告警",
"xpack.securitySolution.detectionEngine.createRule.stepDefineRule.groupByFieldsLabel": "阻止告警的依据",
"xpack.securitySolution.detectionEngine.createRule.stepDefineRule.groupByFieldsLabelAppend": "可选(技术预览)",
@ -33938,7 +33937,6 @@
"xpack.securitySolution.detectionEngine.relatedIntegrations.uninstalledTooltip": "未安装集成。访问集成链接以安装和配置集成。",
"xpack.securitySolution.detectionEngine.rule.editRule.actionSectionsTitle": "操作",
"xpack.securitySolution.detectionEngine.ruleDescription.alertSuppressionDoNotSuppressOnMissingFieldsDescription": "不对缺失字段的事件阻止告警",
"xpack.securitySolution.detectionEngine.ruleDescription.alertSuppressionInsufficientLicense": "已配置告警阻止,但由于许可不足而无法应用",
"xpack.securitySolution.detectionEngine.ruleDescription.alertSuppressionPerRuleExecution": "一次规则执行",
"xpack.securitySolution.detectionEngine.ruleDescription.alertSuppressionSuppressOnMissingFieldsDescription": "对缺失字段的事件阻止告警并进行分组",
"xpack.securitySolution.detectionEngine.ruleDescription.buildingBlockDescription": "所有生成的告警将标记为“构建块”告警",