Skip to content

Commit 122c7e1

Browse files
authored
[Security Solution]: Add banner to promote prebuilt rule customization in ESS (#213750)
**Resolves: #205594 ## Summary **Changes:** - Adds a banner to promote prebuilt rule customization in ESS. Link currently leads to a 404 page since the blog post is not yet published. (Serverless banner to be added later, after April 1, when the blog post is published). Banner is dismissible. It's state is stored in localStorage. <img width="1006" alt="Scherm­afbeelding 2025-03-11 om 12 25 45" src="https://github.com/user-attachments/assets/41d83db9-4bc4-433e-a7e2-c5ef1049a20c" /> - A couple unrelated small changes: - Fixes spelling of singular/plural for "require" in the upgrade flyout - Fixes horizontal line misalignment in upgrade flyout. It was caused by an incorrect `css` function import: `import { css } from '@emotion/css';` instead of `import { css } from '@emotion/react';` <img width="653" alt="Scherm­afbeelding 2025-03-10 om 12 12 33" src="https://github.com/user-attachments/assets/ab5f3b9e-73b2-4938-bda2-401eece5407d" /> <img width="676" alt="Scherm­afbeelding 2025-03-10 om 12 13 17" src="https://github.com/user-attachments/assets/37bbff65-326f-415c-aab8-c9c661ef14ce" /> <img width="1966" alt="Scherm­afbeelding 2025-03-10 om 12 26 05" src="https://github.com/user-attachments/assets/16ac2b9e-13ba-45d8-adcd-c9fb74f8db6e" /> <img width="1966" alt="Scherm­afbeelding 2025-03-10 om 12 24 54" src="https://github.com/user-attachments/assets/c53e7642-26f5-490f-b1bc-6f3961aef71a" />
1 parent aa850d4 commit 122c7e1

File tree

8 files changed

+139
-2
lines changed

8 files changed

+139
-2
lines changed

src/platform/packages/shared/kbn-doc-links/src/get_doc_links.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -449,6 +449,9 @@ export const getDocLinks = ({ kibanaBranch, buildFlavor }: GetDocLinkOptions): D
449449
updatePrebuiltDetectionRules: isServerless
450450
? `${SERVERLESS_DOCS}security-prebuilt-rules-management.html#update-prebuilt-rules`
451451
: `${SECURITY_SOLUTION_DOCS}prebuilt-rules-management.html#update-prebuilt-rules`,
452+
prebuiltRuleCustomizationPromoBlog: isServerless
453+
? '' // URL for Serverless to be added later, once the blog post is published. Issue: https://github.com/elastic/kibana/issues/209000
454+
: `${ELASTIC_WEBSITE_URL}blog/security-prebuilt-rules-editing`,
452455
createEsqlRuleType: `${SECURITY_SOLUTION_DOCS}rules-ui-create.html#create-esql-rule`,
453456
ruleUiAdvancedParams: `${SECURITY_SOLUTION_DOCS}rules-ui-create.html#rule-ui-advanced-params`,
454457
entityAnalytics: {

src/platform/packages/shared/kbn-doc-links/src/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,7 @@ export interface DocLinks {
313313
readonly manageDetectionRules: string;
314314
readonly createDetectionRules: string;
315315
readonly updatePrebuiltDetectionRules: string;
316+
readonly prebuiltRuleCustomizationPromoBlog: string;
316317
readonly createEsqlRuleType: string;
317318
readonly ruleUiAdvancedParams: string;
318319
readonly entityAnalytics: {

x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/field_upgrade_side_header.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import type { PropsWithChildren } from 'react';
99
import React from 'react';
1010
import { EuiFlexGroup, EuiFlexItem, EuiHorizontalRule, useEuiTheme } from '@elastic/eui';
11-
import { css } from '@emotion/css';
11+
import { css } from '@emotion/react';
1212

1313
export function FieldUpgradeSideHeader({ children }: PropsWithChildren<{}>) {
1414
const { euiTheme } = useEuiTheme();

x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/rule_upgrade/translations.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import { useKibana } from '../../../../../../common/lib/kibana/kibana_react';
1414
export const TOTAL_NUM_OF_FIELDS = (count: number) => (
1515
<FormattedMessage
1616
id="xpack.securitySolution.detectionEngine.rules.upgradeRules.diffTab.totalNumOfFieldsWithUpdates"
17-
defaultMessage="{countValue} {count, plural, one {field} other {fields}} require review"
17+
defaultMessage="{countValue} {count, plural, one {field} other {fields}} {count, plural, one {requires} other {require}} review"
1818
values={{ countValue: <strong>{count}</strong>, count }}
1919
/>
2020
);

x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management_ui/pages/rule_management/index.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import { RulesTableContextProvider } from '../../components/rules_table/rules_ta
3636
import { useInvalidateFetchCoverageOverviewQuery } from '../../../rule_management/api/hooks/use_fetch_coverage_overview_query';
3737
import { HeaderPage } from '../../../../common/components/header_page';
3838
import { RuleUpdateCallouts } from '../../components/rule_update_callouts/rule_update_callouts';
39+
import { BlogPostPrebuiltRuleCustomizationCallout } from '../../../../detections/components/callouts/blog_post_prebuilt_rule_customization_callout';
3940

4041
const RulesPageComponent: React.FC = () => {
4142
const [isImportModalVisible, showImportModal, hideImportModal] = useBoolState();
@@ -175,6 +176,7 @@ const RulesPageComponent: React.FC = () => {
175176
kibanaServices={kibanaServices}
176177
categories={[DEFAULT_APP_CATEGORIES.security.id]}
177178
/>
179+
<BlogPostPrebuiltRuleCustomizationCallout />
178180
<AllRules data-test-subj="all-rules" />
179181
</SecuritySolutionPageWrapper>
180182
</RulesTableContextProvider>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0; you may not use this file except in compliance with the Elastic License
5+
* 2.0.
6+
*/
7+
8+
import React from 'react';
9+
import { EuiCallOut, useEuiTheme, type EuiCallOutProps } from '@elastic/eui';
10+
import { css } from '@emotion/react';
11+
12+
interface BackgroundImageCalloutProps extends EuiCallOutProps {
13+
backgroundImage: string;
14+
description: JSX.Element;
15+
}
16+
17+
export function BackgroundImageCallout({
18+
description,
19+
backgroundImage,
20+
...euiCalloutProps
21+
}: BackgroundImageCalloutProps) {
22+
const { euiTheme } = useEuiTheme();
23+
24+
return (
25+
<EuiCallOut
26+
css={css`
27+
padding-left: ${euiTheme.size.xl};
28+
background-image: url(${backgroundImage});
29+
background-repeat: no-repeat;
30+
background-position-x: right;
31+
background-position-y: bottom;
32+
`}
33+
{...euiCalloutProps}
34+
>
35+
{description}
36+
</EuiCallOut>
37+
);
38+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0; you may not use this file except in compliance with the Elastic License
5+
* 2.0.
6+
*/
7+
8+
import React, { useCallback, useMemo } from 'react';
9+
import avcBannerBackground from '@kbn/avc-banner/src/avc_banner_background.svg';
10+
import { EuiSpacer, EuiButton } from '@elastic/eui';
11+
import { type CallOutMessage } from '../../../../common/components/callouts';
12+
import { useCallOutStorage } from '../../../../common/components/callouts/use_callout_storage';
13+
import * as i18n from './translations';
14+
import { useKibana } from '../../../../common/lib/kibana';
15+
import { BackgroundImageCallout } from '../background_image_callout';
16+
17+
export function BlogPostPrebuiltRuleCustomizationCallout() {
18+
// URL is currently only available in ESS. So we are only showing this callout in ESS for now.
19+
const blogPostUrl =
20+
useKibana().services.docLinks.links.securitySolution.prebuiltRuleCustomizationPromoBlog;
21+
22+
const calloutMessage: CallOutMessage = useMemo(
23+
() => ({
24+
type: 'success',
25+
id: 'blog-post-elastic-security-prebuilt-rule-customization',
26+
title: i18n.CALLOUT_TITLE,
27+
description: (
28+
<>
29+
{i18n.CALLOUT_DESCRIPTION}
30+
<EuiSpacer size="s" />
31+
<EuiButton size="s" color="success" href={blogPostUrl} target="_blank">
32+
{i18n.CALLOUT_ACTION_BUTTON_LABEL}
33+
</EuiButton>
34+
</>
35+
),
36+
}),
37+
[blogPostUrl]
38+
);
39+
40+
const { isVisible, dismiss } = useCallOutStorage([calloutMessage], 'detections');
41+
42+
const handleDismiss = useCallback(() => {
43+
dismiss(calloutMessage);
44+
}, [dismiss, calloutMessage]);
45+
46+
if (blogPostUrl && isVisible(calloutMessage)) {
47+
return (
48+
<>
49+
<BackgroundImageCallout
50+
backgroundImage={avcBannerBackground}
51+
title={calloutMessage.title}
52+
description={calloutMessage.description}
53+
color={calloutMessage.type}
54+
iconType="cheer"
55+
onDismiss={handleDismiss}
56+
/>
57+
<EuiSpacer size="l" />
58+
</>
59+
);
60+
}
61+
62+
return null;
63+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0; you may not use this file except in compliance with the Elastic License
5+
* 2.0.
6+
*/
7+
8+
import { i18n } from '@kbn/i18n';
9+
10+
export const CALLOUT_TITLE = i18n.translate(
11+
'xpack.securitySolution.detectionEngine.blogPostPrebuiltRuleCustomizationCallout.calloutTitle',
12+
{
13+
defaultMessage: 'Get more value out of Elastic prebuilt rules!',
14+
}
15+
);
16+
17+
export const CALLOUT_DESCRIPTION = i18n.translate(
18+
'xpack.securitySolution.detectionEngine.blogPostPrebuiltRuleCustomizationCallout.calloutDescription',
19+
{
20+
defaultMessage:
21+
'Learn how to customize prebuilt rules and update them with the latest improvements.',
22+
}
23+
);
24+
25+
export const CALLOUT_ACTION_BUTTON_LABEL = i18n.translate(
26+
'xpack.securitySolution.detectionEngine.blogPostPrebuiltRuleCustomizationCallout.calloutButtonLabel',
27+
{
28+
defaultMessage: 'Read the blog',
29+
}
30+
);

0 commit comments

Comments
 (0)