From e9cf1ec496137bd2e27a79052668dc5bf2176f92 Mon Sep 17 00:00:00 2001 From: Nikita Indik Date: Thu, 20 Feb 2025 11:17:57 +0100 Subject: [PATCH] [Security Solution] Update prebuilt rule customization UI copy (#210817) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit **Resolves: https://github.com/elastic/security-docs/issues/6238** **Deployed here: [link](https://nikitaindik-pr-210817-prebuilt-rule-customization-update-ui.kbndev.co/app/security/rules/updates?rulesTable=(field:name,order:asc,searchTerm:'Shared%20Object%20Created%20or%20Changed%20by%20Previously%20Unknown%20Process')&sourcerer=(default:(id:security-solution-default,selectedPatterns:!()))&timerange=(global:(linkTo:!(timeline),timerange:(from:'2025-02-11T23:00:00.000Z',fromStr:now/d,kind:absolute,to:'2025-02-12T22:59:59.999Z',toStr:now/d)),timeline:(linkTo:!(global),timerange:(from:'2025-02-11T23:00:00.000Z',fromStr:now/d,kind:absolute,to:'2025-02-12T22:59:59.999Z',toStr:now/d)))&timeline=(activeTab:query,graphEventId:'',isOpen:!f))** > ⚠️ CI fails are caused by an issue unrelated to this PR ## Summary Changes in this PR: - UI copy is updated in accordance with [recommendations](https://docs.google.com/document/d/1Yl6DyN9pertqgB-iIKIEN3xdvlDM50oscJ00G-WwtyA/edit?tab=t.0) (internal link) from Security Documentation team - Text color for "No update" fields in upgrade flyout changed from green to default. - Fixed a minor bug with placeholder not displaying for "Setup guide" and "Investigation guide" fields on Rule Creation/Editing page
A few screenshots taken in Serverless (click to expand) serverless_rep_tooltip serverless_bulk_action_error serverless_upgrade_callout no_update_white
## Testing You can use [this deployment](https://nikitaindik-pr-210817-prebuilt-rule-customization-update-ui.kbndev.co) (default credentials) test to changes on ESS Enterprise license. Here's a couple rules that has field updates of different kinds: - Unusual User Privilege Enumeration via id - Shared Object Created or Changed by Previously Unknown Process To test on Serverless or with other licenses, you'll need to run it locally. Reach out to me if you need help with this. Work started: 11-Feb-2025 (cherry picked from commit 994201ce875cc40cb685b821b51b3752e00a6e45) --- .../translations/translations/fr-FR.json | 2 - .../translations/translations/ja-JP.json | 2 - .../translations/translations/zh-CN.json | 2 - .../packages/upselling/messages/index.tsx | 21 +++++++- .../packages/upselling/service/types.ts | 3 +- .../components/markdown_editor/editor.tsx | 3 ++ .../components/markdown_editor/eui_form.tsx | 3 +- .../description_step/translations.ts | 2 +- .../components/step_about_rule/index.tsx | 4 +- .../components/step_about_rule/schema.tsx | 14 +---- .../step_about_rule/translations.ts | 27 +++++++--- .../pages/rule_editing/index.tsx | 4 +- .../comparison_side_help_info.tsx | 35 +++++-------- .../comparison_side/field_comparison_side.tsx | 3 +- .../comparison_side/translations.ts | 42 +++++++++------ .../three_way_diff/comparison_side/utils.ts | 18 ++----- .../versions_picker.stories.tsx | 1 - .../versions_picker/versions_picker.tsx | 13 +---- .../components/field_final_side_help_info.tsx | 6 +-- .../field_upgrade_state_info.tsx | 2 +- .../field_upgrade_state_info/translations.tsx | 14 ++--- .../rule_upgrade/rule_upgrade_callout.tsx | 13 ++++- .../rule_upgrade/translations.tsx | 52 ++++++++++++++++--- .../components/rule_details/translations.tsx | 6 +-- ...lt_rule_customization_upselling_message.ts | 5 +- ...use_prebuilt_rules_customization_status.ts | 4 +- .../bulk_action_rule_errors_list.tsx | 4 +- .../customization_disabled_callout.tsx | 14 +++-- .../translations.tsx | 25 +++++---- .../detection_engine/rules/translations.ts | 4 +- .../public/upselling/register_upsellings.tsx | 10 +++- .../public/upselling/upsellings.tsx | 16 ++++-- .../prebuilt_rules_preview.cy.ts | 2 +- .../cypress/tasks/prebuilt_rules_preview.ts | 2 +- 34 files changed, 225 insertions(+), 153 deletions(-) diff --git a/x-pack/platform/plugins/private/translations/translations/fr-FR.json b/x-pack/platform/plugins/private/translations/translations/fr-FR.json index 444a8726d1df0..81a00b99d8717 100644 --- a/x-pack/platform/plugins/private/translations/translations/fr-FR.json +++ b/x-pack/platform/plugins/private/translations/translations/fr-FR.json @@ -37663,8 +37663,6 @@ "xpack.securitySolution.detectionEngine.createRule.stepAboutRule.guideLabel": "Guide d'investigation", "xpack.securitySolution.detectionEngine.createRule.stepAboutRule.maxAlertsFieldLessThanWarning": "Kibana ne permet qu'un maximum de {maxNumber} {maxNumber, plural, =1 {alerte} other {alertes}} par exécution de règle.", "xpack.securitySolution.detectionEngine.createRule.stepAboutRule.nameFieldRequiredError": "Nom obligatoire.", - "xpack.securitySolution.detectionEngine.createRule.stepAboutrule.noteHelpText": "Ajouter un guide d'investigation sur les règles...", - "xpack.securitySolution.detectionEngine.createRule.stepAboutrule.setupHelpText": "Ajouter le guide de configuration de règle...", "xpack.securitySolution.detectionEngine.createRule.stepAboutRule.setupHelpText": "Fournissez des instructions sur les conditions préalables à la règle, telles que les intégrations requises, les étapes de configuration et tout ce qui est nécessaire au bon fonctionnement de la règle.", "xpack.securitySolution.detectionEngine.createRule.stepAboutRule.setupLabel": "Guide de configuration", "xpack.securitySolution.detectionEngine.createRule.stepAboutRule.tagFieldEmptyError": "Une balise ne doit pas être vide", diff --git a/x-pack/platform/plugins/private/translations/translations/ja-JP.json b/x-pack/platform/plugins/private/translations/translations/ja-JP.json index 3c38c02d0d04f..2f04ca06012d3 100644 --- a/x-pack/platform/plugins/private/translations/translations/ja-JP.json +++ b/x-pack/platform/plugins/private/translations/translations/ja-JP.json @@ -37520,8 +37520,6 @@ "xpack.securitySolution.detectionEngine.createRule.stepAboutRule.guideLabel": "調査ガイド", "xpack.securitySolution.detectionEngine.createRule.stepAboutRule.maxAlertsFieldLessThanWarning": "Kibanaで許可される最大数は、1回の実行につき、{maxNumber} {maxNumber, plural, other {アラート}}です。", "xpack.securitySolution.detectionEngine.createRule.stepAboutRule.nameFieldRequiredError": "名前が必要です。", - "xpack.securitySolution.detectionEngine.createRule.stepAboutrule.noteHelpText": "ルール調査ガイドを追加...", - "xpack.securitySolution.detectionEngine.createRule.stepAboutrule.setupHelpText": "ルールセットアップガイドを追加...", "xpack.securitySolution.detectionEngine.createRule.stepAboutRule.setupHelpText": "必要な統合、構成ステップ、ルールが正常に動作するために必要な他のすべての項目といった、ルール前提条件に関する指示を入力します。", "xpack.securitySolution.detectionEngine.createRule.stepAboutRule.setupLabel": "セットアップガイド", "xpack.securitySolution.detectionEngine.createRule.stepAboutRule.tagFieldEmptyError": "タグを空にすることはできません", diff --git a/x-pack/platform/plugins/private/translations/translations/zh-CN.json b/x-pack/platform/plugins/private/translations/translations/zh-CN.json index 8d3cfabc5463b..1bc259be3bff9 100644 --- a/x-pack/platform/plugins/private/translations/translations/zh-CN.json +++ b/x-pack/platform/plugins/private/translations/translations/zh-CN.json @@ -37615,8 +37615,6 @@ "xpack.securitySolution.detectionEngine.createRule.stepAboutRule.guideLabel": "调查指南", "xpack.securitySolution.detectionEngine.createRule.stepAboutRule.maxAlertsFieldLessThanWarning": "每次规则运行时,Kibana 最多只允许 {maxNumber} 个{maxNumber, plural, other {告警}}。", "xpack.securitySolution.detectionEngine.createRule.stepAboutRule.nameFieldRequiredError": "名称必填。", - "xpack.securitySolution.detectionEngine.createRule.stepAboutrule.noteHelpText": "添加规则调查指南......", - "xpack.securitySolution.detectionEngine.createRule.stepAboutrule.setupHelpText": "添加规则设置指南......", "xpack.securitySolution.detectionEngine.createRule.stepAboutRule.setupHelpText": "提供有关规则先决条件的说明,如所需集成、配置步骤,以及规则正常运行所需的任何其他内容。", "xpack.securitySolution.detectionEngine.createRule.stepAboutRule.setupLabel": "设置指南", "xpack.securitySolution.detectionEngine.createRule.stepAboutRule.tagFieldEmptyError": "标签不得为空", diff --git a/x-pack/solutions/security/packages/upselling/messages/index.tsx b/x-pack/solutions/security/packages/upselling/messages/index.tsx index 1c969e7074d63..d61114e472a23 100644 --- a/x-pack/solutions/security/packages/upselling/messages/index.tsx +++ b/x-pack/solutions/security/packages/upselling/messages/index.tsx @@ -55,10 +55,27 @@ export const UPGRADE_NOTES_MANAGEMENT_USER_FILTER = (requiredLicense: string) => }, }); -export const UPGRADE_PREBUILT_RULE_CUSTOMIZATION = (requiredLicense: string) => +export const PREBUILT_RULE_CUSTOMIZATION = (requiredLicense: string, licenseKind: string) => i18n.translate('securitySolutionPackages.ruleManagement.prebuiltRuleCustomization.upsell', { - defaultMessage: 'Upgrade to {requiredLicense} to enable prebuilt rule customization', + defaultMessage: '{requiredLicense} {licenseKind} is required to customize prebuilt rules', values: { requiredLicense, + licenseKind, }, }); + +export const PREBUILT_RULE_CUSTOMIZATION_DESCRIPTION = ( + requiredLicense: string, + licenseKind: string +) => + i18n.translate( + 'securitySolutionPackages.ruleManagement.prebuiltRuleCustomization.descriptionUpsell', + { + defaultMessage: + "Without the {requiredLicense} {licenseKind}, prebuilt rules can't be customized. To access this feature, upgrade your {licenseKind} or contact your admin for assistance.", + values: { + requiredLicense, + licenseKind, + }, + } + ); diff --git a/x-pack/solutions/security/packages/upselling/service/types.ts b/x-pack/solutions/security/packages/upselling/service/types.ts index 2e41e920f68e0..b681b7ba762cc 100644 --- a/x-pack/solutions/security/packages/upselling/service/types.ts +++ b/x-pack/solutions/security/packages/upselling/service/types.ts @@ -29,4 +29,5 @@ export type UpsellingMessageId = | 'alert_suppression_rule_form' | 'alert_suppression_rule_details' | 'note_management_user_filter' - | 'prebuilt_rule_customization'; + | 'prebuilt_rule_customization' + | 'prebuilt_rule_customization_description'; diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/markdown_editor/editor.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/markdown_editor/editor.tsx index c1dcb839f9c0d..42e69235f6309 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/markdown_editor/editor.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/markdown_editor/editor.tsx @@ -34,6 +34,7 @@ interface MarkdownEditorProps { autoFocusDisabled?: boolean; setIsMarkdownInvalid: (value: boolean) => void; includePlugins?: boolean; + placeholder?: string; } type EuiMarkdownEditorRef = ElementRef; @@ -56,6 +57,7 @@ const MarkdownEditorComponent = forwardRef { @@ -118,6 +120,7 @@ const MarkdownEditorComponent = forwardRef ); } diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/markdown_editor/eui_form.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/markdown_editor/eui_form.tsx index 5600d263bcf7f..b637c1b617562 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/markdown_editor/eui_form.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/markdown_editor/eui_form.tsx @@ -25,7 +25,7 @@ type MarkdownEditorFormProps = EuiMarkdownEditorProps & { export const MarkdownEditorForm = React.memo( forwardRef( - ({ field, dataTestSubj, idAria, includePlugins }, ref) => { + ({ field, dataTestSubj, idAria, includePlugins, placeholder }, ref) => { const { isInvalid, errorMessage } = getFieldValidityAndErrorMessage(field); const [isMarkdownInvalid, setIsMarkdownInvalid] = useState(false); @@ -48,6 +48,7 @@ export const MarkdownEditorForm = React.memo( data-test-subj={`${dataTestSubj}-markdown-editor`} setIsMarkdownInvalid={setIsMarkdownInvalid} includePlugins={includePlugins} + placeholder={placeholder} /> ); diff --git a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation_ui/components/description_step/translations.ts b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation_ui/components/description_step/translations.ts index 74a9faa4efd4c..70e6228bb7b63 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation_ui/components/description_step/translations.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation_ui/components/description_step/translations.ts @@ -196,7 +196,7 @@ export const BUILDING_BLOCK_LABEL = i18n.translate( export const BUILDING_BLOCK_DESCRIPTION = i18n.translate( 'xpack.securitySolution.detectionEngine.ruleDescription.buildingBlockDescription', { - defaultMessage: 'All generated alerts will be marked as "building block" alerts', + defaultMessage: 'All generated alerts will be marked as building block alerts', } ); diff --git a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation_ui/components/step_about_rule/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation_ui/components/step_about_rule/index.tsx index 64b666781ce3c..3accb1dce4396 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation_ui/components/step_about_rule/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation_ui/components/step_about_rule/index.tsx @@ -284,7 +284,7 @@ const StepAboutRuleComponent: FC = ({ = ({ = { author: { type: FIELD_TYPES.COMBO_BOX, - label: i18n.translate( - 'xpack.securitySolution.detectionEngine.createRule.stepAboutRule.fieldAuthorLabel', - { - defaultMessage: 'Author', - } - ), + label: I18n.AUTHOR_FIELD_LABEL, helpText: i18n.translate( 'xpack.securitySolution.detectionEngine.createRule.stepAboutRule.fieldAuthorHelpText', { @@ -209,12 +204,7 @@ export const schema: FormSchema = { }, license: { type: FIELD_TYPES.TEXT, - label: i18n.translate( - 'xpack.securitySolution.detectionEngine.createRule.stepAboutRule.fieldLicenseLabel', - { - defaultMessage: 'License', - } - ), + label: I18n.LICENSE_FIELD_LABEL, helpText: i18n.translate( 'xpack.securitySolution.detectionEngine.createRule.stepAboutRule.fieldLicenseHelpText', { diff --git a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation_ui/components/step_about_rule/translations.ts b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation_ui/components/step_about_rule/translations.ts index c295cf4b9296e..5820a4b295bbc 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation_ui/components/step_about_rule/translations.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation_ui/components/step_about_rule/translations.ts @@ -85,29 +85,40 @@ export const URL_FORMAT_INVALID = i18n.translate( ); export const ADD_RULE_NOTE_HELP_TEXT = i18n.translate( - 'xpack.securitySolution.detectionEngine.createRule.stepAboutrule.noteHelpText', + 'xpack.securitySolution.detectionEngine.createRule.stepAboutRule.noteHelpText', { defaultMessage: 'Add rule investigation guide...', } ); export const ADD_RULE_SETUP_HELP_TEXT = i18n.translate( - 'xpack.securitySolution.detectionEngine.createRule.stepAboutrule.setupHelpText', + 'xpack.securitySolution.detectionEngine.createRule.stepAboutRule.addRuleSetupHelpText', { defaultMessage: 'Add rule setup guide...', } ); -export const AUTHOR_IMMUTABLE_FIELD_TOOLTIP_TEXT = i18n.translate( - 'xpack.securitySolution.detectionEngine.createRule.stepAboutrule.authorImmutableFieldTooltipText', +export const AUTHOR_FIELD_LABEL = i18n.translate( + 'xpack.securitySolution.detectionEngine.createRule.stepAboutRule.fieldAuthorLabel', { - defaultMessage: 'Author is not editable for Elastic rules', + defaultMessage: 'Author', } ); -export const LICENSE_IMMUTABLE_FIELD_TOOLTIP_TEXT = i18n.translate( - 'xpack.securitySolution.detectionEngine.createRule.stepAboutrule.licenseImmutableFieldTooltipText', +export const LICENSE_FIELD_LABEL = i18n.translate( + 'xpack.securitySolution.detectionEngine.createRule.stepAboutRule.fieldLicenseLabel', { - defaultMessage: 'License is not editable for Elastic rules', + defaultMessage: 'License', } ); + +export const FIELD_NOT_EDITABLE_TOOLTIP_TEXT = (fieldName: string) => + i18n.translate( + 'xpack.securitySolution.detectionEngine.createRule.stepAboutRule.fieldNotEditableTooltipText', + { + defaultMessage: "{fieldName} can't be edited for Elastic rules.", + values: { + fieldName, + }, + } + ); diff --git a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation_ui/pages/rule_editing/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation_ui/pages/rule_editing/index.tsx index 4df46abd4db24..b0b134a0bed1e 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation_ui/pages/rule_editing/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation_ui/pages/rule_editing/index.tsx @@ -95,7 +95,9 @@ const EditRulePageComponent: FC<{ rule: RuleResponse }> = ({ rule }) => { usePrebuiltRulesCustomizationStatus(); const canEditRule = isRulesCustomizationEnabled || !rule.immutable; - const prebuiltCustomizationUpsellingMessage = usePrebuiltRuleCustomizationUpsellingMessage(); + const prebuiltCustomizationUpsellingMessage = usePrebuiltRuleCustomizationUpsellingMessage( + 'prebuilt_rule_customization_description' + ); const { detailName: ruleId } = useParams<{ detailName: string }>(); diff --git a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/comparison_side/comparison_side_help_info.tsx b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/comparison_side/comparison_side_help_info.tsx index 1f4e6a255fb86..7cf8c1a7cecef 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/comparison_side/comparison_side_help_info.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/comparison_side/comparison_side_help_info.tsx @@ -9,9 +9,8 @@ import React from 'react'; import useToggle from 'react-use/lib/useToggle'; import { EuiPopover, EuiText, EuiButtonIcon } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; -import { TITLE } from './translations'; +import * as i18n from './translations'; import type { VersionsPickerOptionEnum } from './versions_picker/versions_picker'; -import { useFieldUpgradeContext } from '../rule_upgrade/field_upgrade_context'; import { getOptionDetails } from './utils'; /** @@ -30,10 +29,7 @@ interface ComparisonSideHelpInfoProps { export function ComparisonSideHelpInfo({ options }: ComparisonSideHelpInfoProps): JSX.Element { const [isPopoverOpen, togglePopover] = useToggle(false); - const { hasResolvedValueDifferentFromSuggested } = useFieldUpgradeContext(); - const optionsWithDescriptions = options.map((option) => - getOptionDetails(option, hasResolvedValueDifferentFromSuggested) - ); + const optionsWithDescriptions = options.map((option) => getOptionDetails(option)); const button = ( {TITLE}, - versions: ( - <> -
-
    - {optionsWithDescriptions.map( - ({ title: displayName, description: explanation }) => ( -
  • - {displayName} {'-'} {explanation} -
  • - ) - )} -
- - ), + title: {i18n.TITLE}, }} /> +
    + {optionsWithDescriptions.map(({ title: displayName, description: explanation }) => ( +
  • + {displayName} + {':'} {explanation} +
  • + ))} +
+

{i18n.DIFF_FORMAT_AND_COLORS_EXPLANATION}

); diff --git a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/comparison_side/field_comparison_side.tsx b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/comparison_side/field_comparison_side.tsx index e519844b5c580..83431f893bb62 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/comparison_side/field_comparison_side.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/comparison_side/field_comparison_side.tsx @@ -54,7 +54,7 @@ export function FieldComparisonSide(): JSX.Element { ) { setSelectedOption(VersionsPickerOptionEnum.MyChanges); } - }, [hasResolvedValueDifferentFromSuggested, selectedOption, prevResolvedValue, resolvedValue]); + }, [selectedOption, prevResolvedValue, resolvedValue]); return ( <> @@ -73,7 +73,6 @@ export function FieldComparisonSide(): JSX.Element { options={options} selectedOption={selectedOption} onChange={setSelectedOption} - hasResolvedValueDifferentFromSuggested={hasResolvedValueDifferentFromSuggested} /> diff --git a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/comparison_side/translations.ts b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/comparison_side/translations.ts index 808ce32e7b88a..533d0fbb5a493 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/comparison_side/translations.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/comparison_side/translations.ts @@ -25,28 +25,30 @@ export const NO_CHANGES = i18n.translate( export const UPDATE_FROM_ELASTIC_TITLE = i18n.translate( 'xpack.securitySolution.detectionEngine.rules.upgradeRules.versions.updateFromElasticTitle', { - defaultMessage: 'Update from Elastic', + defaultMessage: 'Changes from Elastic', } ); export const UPDATE_FROM_ELASTIC_EXPLANATION = i18n.translate( 'xpack.securitySolution.detectionEngine.rules.upgradeRules.versions.updateFromElasticExplanation', { - defaultMessage: 'view the changes in Elastic’s latest update', + defaultMessage: + "Compare the field's original value with changes from the Elastic update. Your changes aren't displayed.", } ); -export const MY_CHANGES_TITLE = i18n.translate( - 'xpack.securitySolution.detectionEngine.rules.upgradeRules.versions.myChangesTitle', +export const MY_CHANGES_AND_FINAL_UPDATES_TITLE = i18n.translate( + 'xpack.securitySolution.detectionEngine.rules.upgradeRules.versions.myChangesAndFinalUpdatesTitle', { - defaultMessage: 'My changes', + defaultMessage: 'My changes and final updates', } ); -export const MY_CHANGES_EXPLANATION = i18n.translate( - 'xpack.securitySolution.detectionEngine.rules.upgradeRules.versions.myChangesExplanation', +export const MY_CHANGES_AND_FINAL_UPDATES_EXPLANATION = i18n.translate( + 'xpack.securitySolution.detectionEngine.rules.upgradeRules.versions.myChangesAndFinalUpdatesExplanation', { - defaultMessage: `view what you have changed in your installed rule and in the {finalUpdateSectionLabel} section`, + defaultMessage: + "Compare the field's original value with your changes or changes made in the {finalUpdateSectionLabel} section.", values: { finalUpdateSectionLabel: FINAL_UPDATE, }, @@ -54,9 +56,9 @@ export const MY_CHANGES_EXPLANATION = i18n.translate( ); export const MY_CHANGES_IN_RULE_UPGRADE_WORKFLOW_EXPLANATION = i18n.translate( - 'xpack.securitySolution.detectionEngine.rules.upgradeRules.versions.myChangesFinalUpdateOnlyExplanation', + 'xpack.securitySolution.detectionEngine.rules.upgradeRules.versions.myChangesInRuleUpdateWorkflowOnlyExplanation', { - defaultMessage: `view the changes you made in the {finalUpdateSectionLabel} section`, + defaultMessage: 'View the changes you made in the {finalUpdateSectionLabel} section.', values: { finalUpdateSectionLabel: FINAL_UPDATE, }, @@ -66,30 +68,40 @@ export const MY_CHANGES_IN_RULE_UPGRADE_WORKFLOW_EXPLANATION = i18n.translate( export const MERGED_CHANGES_TITLE = i18n.translate( 'xpack.securitySolution.detectionEngine.rules.upgradeRules.versions.mergedChangesTitle', { - defaultMessage: 'My changes merged with Elastic’s', + defaultMessage: "My changes merged with Elastic's", } ); export const MERGED_CHANGES_EXPLANATION = i18n.translate( 'xpack.securitySolution.detectionEngine.rules.upgradeRules.versions.mergedChangesExplanation', { - defaultMessage: 'view an update suggestion that combines your changes with Elastic’s', + defaultMessage: + "Compare the field's original value with a version that combines your changes with those in the Elastic update. This version is only a suggestion.", } ); export const MY_ORIGINAL_CHANGES_TITLE = i18n.translate( 'xpack.securitySolution.detectionEngine.rules.upgradeRules.versions.myOriginalChangesTitle', { - defaultMessage: 'My original changes', + defaultMessage: 'My changes only', } ); export const MY_ORIGINAL_CHANGES_EXPLANATION = i18n.translate( - 'xpack.securitySolution.detectionEngine.rules.upgradeRules.versions.myCustomizationExplanation', + 'xpack.securitySolution.detectionEngine.rules.upgradeRules.versions.myOriginalChangesExplanation', { - defaultMessage: `view what you have changed in your installed rule. Doesn’t include changes made in the {finalUpdateSectionLabel} section.`, + defaultMessage: + "Compare the field's original value with your changes. Modifications in the {finalUpdateSectionLabel} section aren't displayed.", values: { finalUpdateSectionLabel: FINAL_UPDATE, }, } ); + +export const DIFF_FORMAT_AND_COLORS_EXPLANATION = i18n.translate( + 'xpack.securitySolution.detectionEngine.rules.upgradeRules.versions.diffFormatAndColorsExplanation', + { + defaultMessage: + "Differences are shown in JSON and color-coded or bolded. Lines that are highlighted in green were added. Lines that are highlighted in red were removed. Text that's bolded was changed.", + } +); diff --git a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/comparison_side/utils.ts b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/comparison_side/utils.ts index 23bd893ba1e97..dd63caf040e53 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/comparison_side/utils.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/comparison_side/utils.ts @@ -60,21 +60,13 @@ interface OptionDetails { /** * Returns the title and description for a given versions picker option. */ -export function getOptionDetails( - option: VersionsPickerOptionEnum, - hasResolvedValueDifferentFromSuggested: boolean -): OptionDetails { +export function getOptionDetails(option: VersionsPickerOptionEnum): OptionDetails { switch (option) { case VersionsPickerOptionEnum.MyChanges: - return hasResolvedValueDifferentFromSuggested - ? { - title: i18n.MY_CHANGES_TITLE, - description: i18n.MY_CHANGES_IN_RULE_UPGRADE_WORKFLOW_EXPLANATION, - } - : { - title: i18n.MY_CHANGES_TITLE, - description: i18n.MY_CHANGES_EXPLANATION, - }; + return { + title: i18n.MY_CHANGES_AND_FINAL_UPDATES_TITLE, + description: i18n.MY_CHANGES_AND_FINAL_UPDATES_EXPLANATION, + }; case VersionsPickerOptionEnum.MyOriginalChanges: return { title: i18n.MY_ORIGINAL_CHANGES_TITLE, diff --git a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/comparison_side/versions_picker/versions_picker.stories.tsx b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/comparison_side/versions_picker/versions_picker.stories.tsx index 75486d4176c82..e30e32c41f8dc 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/comparison_side/versions_picker/versions_picker.stories.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/comparison_side/versions_picker/versions_picker.stories.tsx @@ -22,7 +22,6 @@ export const Default = () => { options={options} selectedOption={selectedOption} onChange={setSelectedOption} - hasResolvedValueDifferentFromSuggested={false} /> ); }; diff --git a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/comparison_side/versions_picker/versions_picker.tsx b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/comparison_side/versions_picker/versions_picker.tsx index 6fb33113bc36d..8754c959d71d9 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/comparison_side/versions_picker/versions_picker.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/comparison_side/versions_picker/versions_picker.tsx @@ -22,20 +22,11 @@ interface VersionsPickerProps { options: VersionsPickerOptionEnum[]; selectedOption: VersionsPickerOptionEnum; onChange: (selectedOption: VersionsPickerOptionEnum) => void; - hasResolvedValueDifferentFromSuggested: boolean; } -export function VersionsPicker({ - options, - selectedOption, - onChange, - hasResolvedValueDifferentFromSuggested, -}: VersionsPickerProps) { +export function VersionsPicker({ options, selectedOption, onChange }: VersionsPickerProps) { const euiSelectOptions = options.map((option) => { - const { title: displayName, description: explanation } = getOptionDetails( - option, - hasResolvedValueDifferentFromSuggested - ); + const { title: displayName, description: explanation } = getOptionDetails(option); return { value: option, diff --git a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/field_final_side/components/field_final_side_help_info.tsx b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/field_final_side/components/field_final_side_help_info.tsx index ef8cfc820535d..867cac5690a3b 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/field_final_side/components/field_final_side_help_info.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/field_final_side/components/field_final_side_help_info.tsx @@ -9,7 +9,7 @@ import React from 'react'; import useToggle from 'react-use/lib/useToggle'; import { EuiPopover, EuiText, EuiButtonIcon } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; -import * as i18n from '../../../../../../rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/translations'; +import * as i18n from './translations'; /** * Theme doesn't expose width variables. Using provided size variables will require @@ -36,9 +36,9 @@ export function FieldFinalSideHelpInfo(): JSX.Element { {i18n.UPDATE_BUTTON_LABEL}, + finalUpdateSectionLabel: {i18n.FINAL_UPDATE}, }} /> diff --git a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/rule_upgrade/field_upgrade_state_info/field_upgrade_state_info.tsx b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/rule_upgrade/field_upgrade_state_info/field_upgrade_state_info.tsx index ed2f7050a2c90..83e8b57905b12 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/rule_upgrade/field_upgrade_state_info/field_upgrade_state_info.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/rule_upgrade/field_upgrade_state_info/field_upgrade_state_info.tsx @@ -23,7 +23,7 @@ export function FieldUpgradeStateInfo({ state }: FieldUpgradeStateInfoProps): JS switch (state) { case FieldUpgradeStateEnum.NoUpdate: return { - color: 'success', + color: 'default', title: i18n.NO_UPDATE, description: i18n.NO_UPDATE_DESCRIPTION, }; diff --git a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/rule_upgrade/field_upgrade_state_info/translations.tsx b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/rule_upgrade/field_upgrade_state_info/translations.tsx index 0b67f590d3f64..0826d4c3a1573 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/rule_upgrade/field_upgrade_state_info/translations.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/rule_upgrade/field_upgrade_state_info/translations.tsx @@ -17,8 +17,7 @@ export const NO_UPDATE = i18n.translate( export const NO_UPDATE_DESCRIPTION = i18n.translate( 'xpack.securitySolution.detectionEngine.rules.upgradeRules.fieldUpgradeState.noUpdateDescription', { - defaultMessage: - 'The field was modified after rule installation but does not have Elastic update.', + defaultMessage: 'This field has no Elastic update but can still be edited if needed.', } ); @@ -47,7 +46,8 @@ export const NO_CONFLICT = i18n.translate( export const NO_CONFLICT_DESCRIPTION = i18n.translate( 'xpack.securitySolution.detectionEngine.rules.upgradeRules.fieldUpgradeState.noConflictDescription', { - defaultMessage: 'The update has no conflicts and has been applied to the final update.', + defaultMessage: + "There are no conflicts with the field's current value and incoming Elastic update.", } ); @@ -61,7 +61,7 @@ export const REVIEWED_AND_ACCEPTED = i18n.translate( export const SOLVABLE_CONFLICT = i18n.translate( 'xpack.securitySolution.detectionEngine.rules.upgradeRules.fieldUpgradeState.solvableConflict', { - defaultMessage: 'Solved conflict', + defaultMessage: 'Auto-resolved conflict', } ); @@ -69,14 +69,14 @@ export const SOLVABLE_CONFLICT_DESCRIPTION = i18n.translate( 'xpack.securitySolution.detectionEngine.rules.upgradeRules.fieldUpgradeState.solvableConflictDescription', { defaultMessage: - 'We have suggested an update for this modified field, please review before accepting.', + "We combined your changes with changes from the Elastic update. Review the suggested changes to ensure they're correct.", } ); export const NON_SOLVABLE_CONFLICT = i18n.translate( 'xpack.securitySolution.detectionEngine.rules.upgradeRules.fieldUpgradeState.nonSolvableConflict', { - defaultMessage: 'Unsolved conflict', + defaultMessage: 'Unresolved conflict', } ); @@ -84,7 +84,7 @@ export const NON_SOLVABLE_CONFLICT_DESCRIPTION = i18n.translate( 'xpack.securitySolution.detectionEngine.rules.upgradeRules.fieldUpgradeState.nonSolvableConflictDescription', { defaultMessage: - 'Unable to suggest a merged version for the update. Current version is provided for you to edit.', + "We couldn't resolve this conflict. Edit the provided current version before saving and accepting the final update.", } ); diff --git a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/rule_upgrade/rule_upgrade_callout.tsx b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/rule_upgrade/rule_upgrade_callout.tsx index 3b3c0c7e49e51..10f432e236828 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/rule_upgrade/rule_upgrade_callout.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/rule_upgrade/rule_upgrade_callout.tsx @@ -36,7 +36,12 @@ export function RuleUpgradeCallout({ color="danger" size="s" > -

{i18n.RULE_HAS_HARD_CONFLICTS_DESCRIPTION}

+ {i18n.RULE_HAS_HARD_CONFLICTS_DESCRIPTION} +
    +
  • {i18n.RULE_HAS_HARD_CONFLICTS_KEEP_YOUR_CHANGES}
  • +
  • {i18n.RULE_HAS_HARD_CONFLICTS_ACCEPT_ELASTIC_UPDATE}
  • +
  • {i18n.RULE_HAS_HARD_CONFLICTS_EDIT_FINAL_VERSION}
  • +
); } @@ -56,7 +61,11 @@ export function RuleUpgradeCallout({ color="warning" size="s" > -

{i18n.RULE_HAS_SOFT_CONFLICTS_DESCRIPTION}

+ {i18n.RULE_HAS_SOFT_CONFLICTS_DESCRIPTION} +
    +
  • {i18n.RULE_HAS_SOFT_CONFLICTS_ACCEPT_SUGGESTED_UPDATE}
  • +
  • {i18n.RULE_HAS_SOFT_CONFLICTS_EDIT_FINAL_VERSION}
  • +
); } diff --git a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/rule_upgrade/translations.tsx b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/rule_upgrade/translations.tsx index 04b398bf408e9..819e746739f39 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/rule_upgrade/translations.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/rule_upgrade/translations.tsx @@ -14,7 +14,7 @@ import { useKibana } from '../../../../../../common/lib/kibana/kibana_react'; export const TOTAL_NUM_OF_FIELDS = (count: number) => ( {count}, count }} /> ); @@ -26,7 +26,7 @@ export const VERSION_UPDATE_INFO = ( ) => ( {numOfFieldsWithUpdates}, numOfFieldsWithUpdates, @@ -79,7 +79,7 @@ export function RuleUpgradeHelper(): JSX.Element { export const UPGRADE_STATUS = i18n.translate( 'xpack.securitySolution.detectionEngine.rules.upgradeRules.fieldUpgradeState.upgradeStatusTitle', { - defaultMessage: 'Update status:', + defaultMessage: 'Status:', } ); @@ -89,7 +89,7 @@ export const RULE_HAS_CONFLICTS = (count: number) => { values: { count }, defaultMessage: - '{count} {count, plural, one {field has a conflict} other {fields have conflicts}}. Please review and provide a final update.', + '{count} {count, plural, one {field has a conflict} other {fields have conflicts}}. Review and provide a final update.', } ); @@ -97,7 +97,21 @@ export const RULE_HAS_SOFT_CONFLICTS_DESCRIPTION = i18n.translate( 'xpack.securitySolution.detectionEngine.rules.upgradeRules.fieldUpgradeState.ruleHasSoftConflictsDescription', { defaultMessage: - 'Please review and accept conflicts. You can also keep the current version without the updates, or accept the Elastic update but lose your modifications.', + 'We auto-resolved the conflicts between your changes and the Elastic update. Review them and do one of the following:', + } +); + +export const RULE_HAS_SOFT_CONFLICTS_ACCEPT_SUGGESTED_UPDATE = i18n.translate( + 'xpack.securitySolution.detectionEngine.rules.upgradeRules.fieldUpgradeState.ruleHasSoftConflictsAcceptSuggestedUpdate', + { + defaultMessage: 'Accept the suggested update.', + } +); + +export const RULE_HAS_SOFT_CONFLICTS_EDIT_FINAL_VERSION = i18n.translate( + 'xpack.securitySolution.detectionEngine.rules.upgradeRules.fieldUpgradeState.ruleHasSoftConflictsEditFinalVersion', + { + defaultMessage: 'Edit the final version and choose a more appropriate field value.', } ); @@ -105,14 +119,36 @@ export const RULE_HAS_HARD_CONFLICTS_DESCRIPTION = i18n.translate( 'xpack.securitySolution.detectionEngine.rules.upgradeRules.fieldUpgradeState.ruleHasHardConflictsDescription', { defaultMessage: - 'Please provide an input for the conflicts. You can also keep the current version without the updates, or accept the Elastic update but lose your modifications.', + "We couldn't auto-resolve the conflicts between your changes and the Elastic update. To resolve them, do one of the following:", + } +); + +export const RULE_HAS_HARD_CONFLICTS_KEEP_YOUR_CHANGES = i18n.translate( + 'xpack.securitySolution.detectionEngine.rules.upgradeRules.fieldUpgradeState.ruleHasHardConflictsKeepYourChanges', + { + defaultMessage: 'Keep your changes and reject the Elastic update.', + } +); + +export const RULE_HAS_HARD_CONFLICTS_ACCEPT_ELASTIC_UPDATE = i18n.translate( + 'xpack.securitySolution.detectionEngine.rules.upgradeRules.fieldUpgradeState.ruleHasHardConflictsAcceptElasticUpdate', + { + defaultMessage: 'Accept the Elastic update and overwrite your changes.', + } +); + +export const RULE_HAS_HARD_CONFLICTS_EDIT_FINAL_VERSION = i18n.translate( + 'xpack.securitySolution.detectionEngine.rules.upgradeRules.fieldUpgradeState.ruleHasHardConflictsEditFinalVersion', + { + defaultMessage: + 'Edit the final version by combining your changes with the Elastic update or choosing a more appropriate field value.', } ); export const RULE_IS_READY_FOR_UPGRADE_DESCRIPTION = i18n.translate( 'xpack.securitySolution.detectionEngine.rules.upgradeRules.fieldUpgradeState.ruleIsReadyForUpgradeDescription', { - defaultMessage: 'There are no conflicts and the update is ready to be applied.', + defaultMessage: 'There are no conflicts. The rule is ready to be updated.', } ); @@ -120,6 +156,6 @@ export const FIELD_MODIFIED_BADGE_DESCRIPTION = i18n.translate( 'xpack.securitySolution.detectionEngine.upgradeFlyout.fieldModifiedBadgeDescription', { defaultMessage: - "The field value was edited after rule's installation and differs from the value upon installation", + 'This field value differs from the one provided in the original version of the rule.', } ); diff --git a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/translations.tsx b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/translations.tsx index 69e113b5e112c..b72ec31ac63b3 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/translations.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/translations.tsx @@ -33,7 +33,7 @@ export const INVESTIGATION_GUIDE_TAB_LABEL = i18n.translate( export const UPDATES_TAB_LABEL = i18n.translate( 'xpack.securitySolution.detectionEngine.ruleDetails.updatesTabLabel', { - defaultMessage: 'Updates', + defaultMessage: 'Elastic update overview', } ); @@ -117,14 +117,14 @@ export const BUILDING_BLOCK_FIELD_LABEL = i18n.translate( export const BUILDING_BLOCK_ENABLED_FIELD_DESCRIPTION = i18n.translate( 'xpack.securitySolution.detectionEngine.ruleDetails.buildingBlockFieldDescription', { - defaultMessage: 'All generated alerts will be marked as "building block" alerts', + defaultMessage: 'All generated alerts will be marked as building block alerts', } ); export const BUILDING_BLOCK_DISABLED_FIELD_DESCRIPTION = i18n.translate( 'xpack.securitySolution.detectionEngine.ruleDetails.buildingBlockDisabledFieldDescription', { - defaultMessage: 'Will not mark alerts as "building block" alerts', + defaultMessage: 'Will not mark alerts as building block alerts', } ); diff --git a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/logic/prebuilt_rules/use_prebuilt_rule_customization_upselling_message.ts b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/logic/prebuilt_rules/use_prebuilt_rule_customization_upselling_message.ts index 3bcc465698964..ac6bfdb0e0ac4 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/logic/prebuilt_rules/use_prebuilt_rule_customization_upselling_message.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/logic/prebuilt_rules/use_prebuilt_rule_customization_upselling_message.ts @@ -5,6 +5,7 @@ * 2.0. */ +import type { UpsellingMessageId } from '@kbn/security-solution-upselling/service'; import { useIsExperimentalFeatureEnabled } from '../../../../common/hooks/use_experimental_features'; import { useUpsellingMessage } from '../../../../common/hooks/use_upselling'; @@ -13,10 +14,10 @@ import { useUpsellingMessage } from '../../../../common/hooks/use_upselling'; * for prebuilt rule customization. If the license level is sufficient, it * returns `undefined`. */ -export const usePrebuiltRuleCustomizationUpsellingMessage = () => { +export const usePrebuiltRuleCustomizationUpsellingMessage = (messageId: UpsellingMessageId) => { // Upselling message is returned when the license level is insufficient, // otherwise it's undefined - const upsellingMessage = useUpsellingMessage('prebuilt_rule_customization'); + const upsellingMessage = useUpsellingMessage(messageId); // We show the upselling message only if the feature flag is enabled const isFeatureFlagEnabled = useIsExperimentalFeatureEnabled('prebuiltRulesCustomizationEnabled'); diff --git a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/logic/prebuilt_rules/use_prebuilt_rules_customization_status.ts b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/logic/prebuilt_rules/use_prebuilt_rules_customization_status.ts index d8ea83ef3ae94..5647feb083cad 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/logic/prebuilt_rules/use_prebuilt_rules_customization_status.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/logic/prebuilt_rules/use_prebuilt_rules_customization_status.ts @@ -20,7 +20,9 @@ export const usePrebuiltRulesCustomizationStatus = (): PrebuiltRulesCustomizatio const isFeatureFlagEnabled = useIsExperimentalFeatureEnabled('prebuiltRulesCustomizationEnabled'); // Upselling message is returned when the license level is insufficient, // otherwise it's undefined - const upsellingMessage = usePrebuiltRuleCustomizationUpsellingMessage(); + const upsellingMessage = usePrebuiltRuleCustomizationUpsellingMessage( + 'prebuilt_rule_customization' + ); const isRulesCustomizationEnabled = isFeatureFlagEnabled && !upsellingMessage; let customizationDisabledReason; diff --git a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/bulk_actions/bulk_action_rule_errors_list.tsx b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/bulk_actions/bulk_action_rule_errors_list.tsx index af937d7e5e70f..f8ee7a177287c 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/bulk_actions/bulk_action_rule_errors_list.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/bulk_actions/bulk_action_rule_errors_list.tsx @@ -29,7 +29,9 @@ const BulkEditRuleErrorItem = ({ message, rulesCount, }: BulkActionRuleErrorItemProps) => { - const upsellingMessage = usePrebuiltRuleCustomizationUpsellingMessage(); + const upsellingMessage = usePrebuiltRuleCustomizationUpsellingMessage( + 'prebuilt_rule_customization' + ); switch (errorCode) { case BulkActionsDryRunErrCodeEnum.IMMUTABLE: diff --git a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/customization_disabled_callout.tsx b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/customization_disabled_callout.tsx index 01bde0ea95b2b..be08c2cf5fd37 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/customization_disabled_callout.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/customization_disabled_callout.tsx @@ -7,20 +7,24 @@ import React from 'react'; import { EuiCallOut } from '@elastic/eui'; -import { CUSTOMIZATION_DISABLED_CALLOUT_DESCRIPTION } from './translations'; import { usePrebuiltRuleCustomizationUpsellingMessage } from '../../../../rule_management/logic/prebuilt_rules/use_prebuilt_rule_customization_upselling_message'; +import * as i18n from './translations'; export function CustomizationDisabledCallout() { - const upsellingMessage = usePrebuiltRuleCustomizationUpsellingMessage(); + const title = usePrebuiltRuleCustomizationUpsellingMessage('prebuilt_rule_customization'); + const description = usePrebuiltRuleCustomizationUpsellingMessage( + 'prebuilt_rule_customization_description' + ); // Upselling message is returned only when the license level is insufficient - if (!upsellingMessage) { + if (!title) { return null; } return ( - -

{CUSTOMIZATION_DISABLED_CALLOUT_DESCRIPTION}

+ +

{i18n.MODIFIED_RULE_UPGRADE_LICENSE_INSUFFICIENT_CALLOUT_DESCRIPTION}

+

{description}

); } diff --git a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/translations.tsx b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/translations.tsx index b3564dd2fd704..73fb4e9381d73 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/translations.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/translations.tsx @@ -44,7 +44,7 @@ export const BULK_UPDATE_ALL_RULES_BUTTON_TOOLTIP_CONFLICTS = i18n.translate( export const BULK_UPDATE_SELECTED_RULES_BUTTON_TOOLTIP_CONFLICTS = i18n.translate( 'xpack.securitySolution.detectionEngine.rules.upgradeRules.bulkButtons.selectedRules.conflicts', { - defaultMessage: 'All selected rules have conflicts. Update them individually.', + defaultMessage: 'The selected rules have conflicts that must be manually resolved.', } ); @@ -58,7 +58,7 @@ export const SEARCH_PLACEHOLDER = i18n.translate( export const UPDATE_BUTTON_LABEL = i18n.translate( 'xpack.securitySolution.detectionEngine.ruleDetails.updateButtonLabel', { - defaultMessage: 'Update', + defaultMessage: 'Update rule', } ); @@ -86,7 +86,14 @@ export const RULE_TYPE_CHANGE_CALLOUT_TITLE = i18n.translate( export const RULE_TYPE_CHANGE_CALLOUT_DESCRIPTION = i18n.translate( 'xpack.securitySolution.detectionEngine.upgradeRules.ruleTypeChangeCalloutDescription', { - defaultMessage: 'Elastic update has rule type changed.', + defaultMessage: 'The rule type will change if you update this rule.', + } +); + +export const MODIFIED_RULE_UPGRADE_LICENSE_INSUFFICIENT_CALLOUT_DESCRIPTION = i18n.translate( + 'xpack.securitySolution.detectionEngine.upgradeRules.ruleUpgradeLicenseInsufficientCalloutDescription', + { + defaultMessage: 'Updating the rule will erase your changes.', } ); @@ -94,14 +101,14 @@ export const RULE_TYPE_CHANGE_WITH_CUSTOMIZATIONS_CALLOUT_DESCRIPTION = i18n.tra 'xpack.securitySolution.detectionEngine.upgradeRules.ruleTypeChangeWithCustomizationCalloutDescription', { defaultMessage: - 'Your customization will be lost at update. Please take note of your customization or clone this rule before updating.', + 'Updating the rule will erase your changes. To save them, first duplicate the rule, then update it.', } ); export const LAST_UPDATE = i18n.translate( 'xpack.securitySolution.detectionEngine.upgradeFlyout.header.lastUpdate', { - defaultMessage: 'Last update', + defaultMessage: 'Last updated', } ); @@ -168,11 +175,3 @@ export const RULE_NEW_VERSION_DETECTED_WARNING_DESCRIPTION = (ruleName: string) values: { ruleName }, } ); - -export const CUSTOMIZATION_DISABLED_CALLOUT_DESCRIPTION = i18n.translate( - 'xpack.securitySolution.detectionEngine.upgradeRules.customizationDisabledCalloutDescription', - { - defaultMessage: - 'Prebuilt rule customization is disabled. Only updates to Elastic version are available.', - } -); diff --git a/x-pack/solutions/security/plugins/security_solution/public/detections/pages/detection_engine/rules/translations.ts b/x-pack/solutions/security/plugins/security_solution/public/detections/pages/detection_engine/rules/translations.ts index a7bc737b81dc2..6337d7bf8c730 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detections/pages/detection_engine/rules/translations.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/detections/pages/detection_engine/rules/translations.ts @@ -831,7 +831,7 @@ export const NO_TAGS_AVAILABLE = i18n.translate( export const RULE_SOURCE = i18n.translate( 'xpack.securitySolution.detectionEngine.rules.allRules.filters.ruleSourceLabel', { - defaultMessage: 'Modifications', + defaultMessage: 'Modified/Unmodified', } ); @@ -1436,7 +1436,7 @@ export const UPDATE_RULE_BUTTON = i18n.translate( export const UPDATE_RULE_BUTTON_TOOLTIP_CONFLICTS = i18n.translate( 'xpack.securitySolution.detectionEngine.rules.upgradeRules.button.conflicts', { - defaultMessage: 'Rule has conflicts. Resolve them manually.', + defaultMessage: 'This rule has conflicts that must be manually resolved.', } ); diff --git a/x-pack/solutions/security/plugins/security_solution_ess/public/upselling/register_upsellings.tsx b/x-pack/solutions/security/plugins/security_solution_ess/public/upselling/register_upsellings.tsx index 756cbccd8e960..36a3fc13e240e 100644 --- a/x-pack/solutions/security/plugins/security_solution_ess/public/upselling/register_upsellings.tsx +++ b/x-pack/solutions/security/plugins/security_solution_ess/public/upselling/register_upsellings.tsx @@ -10,10 +10,11 @@ import { SecurityPageName } from '@kbn/security-solution-plugin/common'; import { ALERT_SUPPRESSION_RULE_DETAILS, ALERT_SUPPRESSION_RULE_FORM, + PREBUILT_RULE_CUSTOMIZATION_DESCRIPTION, UPGRADE_ALERT_ASSIGNMENTS, UPGRADE_INVESTIGATION_GUIDE, UPGRADE_NOTES_MANAGEMENT_USER_FILTER, - UPGRADE_PREBUILT_RULE_CUSTOMIZATION, + PREBUILT_RULE_CUSTOMIZATION, } from '@kbn/security-solution-upselling/messages'; import type { MessageUpsellings, @@ -142,6 +143,11 @@ export const upsellingMessages: UpsellingMessages = [ { id: 'prebuilt_rule_customization', minimumLicenseRequired: 'enterprise', - message: UPGRADE_PREBUILT_RULE_CUSTOMIZATION('Enterprise'), + message: PREBUILT_RULE_CUSTOMIZATION('Enterprise', 'subscription'), + }, + { + id: 'prebuilt_rule_customization_description', + minimumLicenseRequired: 'enterprise', + message: PREBUILT_RULE_CUSTOMIZATION_DESCRIPTION('Enterprise', 'subscription'), }, ]; diff --git a/x-pack/solutions/security/plugins/security_solution_serverless/public/upselling/upsellings.tsx b/x-pack/solutions/security/plugins/security_solution_serverless/public/upselling/upsellings.tsx index b1d2f4ee9df4c..fbaa27ad45864 100644 --- a/x-pack/solutions/security/plugins/security_solution_serverless/public/upselling/upsellings.tsx +++ b/x-pack/solutions/security/plugins/security_solution_serverless/public/upselling/upsellings.tsx @@ -10,7 +10,8 @@ import { SecurityPageName } from '@kbn/security-solution-plugin/common'; import { UPGRADE_INVESTIGATION_GUIDE, UPGRADE_INVESTIGATION_GUIDE_INTERACTIONS, - UPGRADE_PREBUILT_RULE_CUSTOMIZATION, + PREBUILT_RULE_CUSTOMIZATION, + PREBUILT_RULE_CUSTOMIZATION_DESCRIPTION, } from '@kbn/security-solution-upselling/messages'; import type { UpsellingMessageId, @@ -168,8 +169,17 @@ export const upsellingMessages: UpsellingMessages = [ { id: 'prebuilt_rule_customization', pli: ProductFeatureKey.prebuiltRuleCustomization, - message: UPGRADE_PREBUILT_RULE_CUSTOMIZATION( - getProductTypeByPLI(ProductFeatureKey.prebuiltRuleCustomization) ?? '' + message: PREBUILT_RULE_CUSTOMIZATION( + getProductTypeByPLI(ProductFeatureKey.prebuiltRuleCustomization) ?? '', + 'feature tier' + ), + }, + { + id: 'prebuilt_rule_customization_description', + pli: ProductFeatureKey.prebuiltRuleCustomization, + message: PREBUILT_RULE_CUSTOMIZATION_DESCRIPTION( + getProductTypeByPLI(ProductFeatureKey.prebuiltRuleCustomization) ?? '', + 'feature tier' ), }, ]; diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/prebuilt_rules/prebuilt_rules_preview.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/prebuilt_rules/prebuilt_rules_preview.cy.ts index fe27c4d76f22f..3ff737c2999c9 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/prebuilt_rules/prebuilt_rules_preview.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/prebuilt_rules/prebuilt_rules_preview.cy.ts @@ -73,7 +73,7 @@ import { enableRules, waitForRulesToFinishExecution } from '../../../../tasks/ap const PREVIEW_TABS = { OVERVIEW: 'Overview', JSON_VIEW: 'JSON view', - UPDATES: 'Updates', // Currently open by default on upgrade + UPDATES: 'Elastic update overview', // Currently open by default on upgrade }; describe( diff --git a/x-pack/test/security_solution_cypress/cypress/tasks/prebuilt_rules_preview.ts b/x-pack/test/security_solution_cypress/cypress/tasks/prebuilt_rules_preview.ts index 9ae6c623a388f..38bf7141cdd5c 100644 --- a/x-pack/test/security_solution_cypress/cypress/tasks/prebuilt_rules_preview.ts +++ b/x-pack/test/security_solution_cypress/cypress/tasks/prebuilt_rules_preview.ts @@ -142,7 +142,7 @@ export const assertCommonPropertiesShown = (properties: Partial