[Security Solution] Add "Customized Elastic rule" badge to Rule Details page (#186914)

**Resolves: https://github.com/elastic/kibana/issues/180170**

## Summary
This PR adds a "Customized Elastic rule" badge to the Rule Details page.
This badge is only displayed if a rule has `rule_source.is_customized`
set to `true` and the feature flag is turned on.

Tests for this feature will be added later under a separate ticket
(https://github.com/elastic/kibana/issues/186916).

### Screenshots
**Customized Elastic rule – has badge**
<img width="827" alt="Scherm­afbeelding 2024-06-25 om 19 29 47"
src="be64271f-5f91-46a9-aa71-35594c788586">

**Custom rule – no badge**
<img width="827" alt="Scherm­afbeelding 2024-06-25 om 19 29 02"
src="c576bf52-efde-46dd-88af-9fdf5f0b44ea">
This commit is contained in:
Nikita Indik 2024-06-26 16:29:32 +02:00 committed by GitHub
parent 0ffd02c1d2
commit 199e2ad44e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 60 additions and 3 deletions

View file

@ -7,6 +7,7 @@
export * from './common_attributes.gen';
export * from './rule_schemas.gen';
export * from './utils';
export * from './specific_attributes/eql_attributes.gen';
export * from './specific_attributes/ml_attributes.gen';

View file

@ -0,0 +1,12 @@
/*
* 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 type { RuleResponse } from './rule_schemas.gen';
export function isCustomizedPrebuiltRule(rule: RuleResponse): boolean {
return rule.rule_source?.type === 'external' && rule.rule_source.is_customized;
}

View file

@ -139,6 +139,7 @@ import { RuleSnoozeBadge } from '../../../rule_management/components/rule_snooze
import { useBoolState } from '../../../../common/hooks/use_bool_state';
import { RuleDefinitionSection } from '../../../rule_management/components/rule_details/rule_definition_section';
import { RuleScheduleSection } from '../../../rule_management/components/rule_details/rule_schedule_section';
import { CustomizedPrebuiltRuleBadge } from '../../../rule_management/components/rule_details/customized_prebuilt_rule_badge';
import { ManualRuleRunModal } from '../../../rule_gaps/components/manual_rule_run';
import { useManualRuleRunConfirmation } from '../../../rule_gaps/components/manual_rule_run/use_manual_rule_run_confirmation';
// eslint-disable-next-line no-restricted-imports
@ -592,15 +593,16 @@ const RuleDetailsPageComponent: React.FC<DetectionEngineComponentProps> = ({
border
subtitle={subTitle}
subtitle2={
<>
<EuiFlexGroup gutterSize="xs" alignItems="center" justifyContent="flexStart">
<EuiFlexGroup gutterSize="m" alignItems="center" justifyContent="flexStart">
<CustomizedPrebuiltRuleBadge rule={rule} />
<EuiFlexGroup alignItems="center" gutterSize="xs">
<EuiFlexItem grow={false}>
{ruleStatusI18n.STATUS}
{':'}
</EuiFlexItem>
{ruleStatusInfo}
</EuiFlexGroup>
</>
</EuiFlexGroup>
}
title={title}
badgeOptions={badgeOptions}

View file

@ -0,0 +1,35 @@
/*
* 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 from 'react';
import { EuiBadge } from '@elastic/eui';
import * as i18n from './translations';
import { isCustomizedPrebuiltRule } from '../../../../../common/api/detection_engine';
import type { RuleResponse } from '../../../../../common/api/detection_engine';
import { useIsExperimentalFeatureEnabled } from '../../../../common/hooks/use_experimental_features';
interface CustomizedPrebuiltRuleBadgeProps {
rule: RuleResponse | null;
}
export const CustomizedPrebuiltRuleBadge: React.FC<CustomizedPrebuiltRuleBadgeProps> = ({
rule,
}) => {
const isPrebuiltRulesCustomizationEnabled = useIsExperimentalFeatureEnabled(
'prebuiltRulesCustomizationEnabled'
);
if (!isPrebuiltRulesCustomizationEnabled) {
return null;
}
if (rule === null || !isCustomizedPrebuiltRule(rule)) {
return null;
}
return <EuiBadge color="hollow">{i18n.CUSTOMIZED_PREBUILT_RULE_LABEL}</EuiBadge>;
};

View file

@ -349,3 +349,10 @@ export const MAX_SIGNALS_FIELD_LABEL = i18n.translate(
defaultMessage: 'Max alerts per run',
}
);
export const CUSTOMIZED_PREBUILT_RULE_LABEL = i18n.translate(
'xpack.securitySolution.detectionEngine.ruleDetails.customizedPrebuiltRuleLabel',
{
defaultMessage: 'Customized Elastic rule',
}
);