From 3060dd0b7c5d5874b4d4d37d0eb424ce18880920 Mon Sep 17 00:00:00 2001 From: Steph Milovic Date: Fri, 11 Aug 2023 10:22:26 -0600 Subject: [PATCH 1/6] initial --- .../cloud_experiments/common/constants.ts | 1 + .../guided_onboarding/siem_guide_config.ts | 136 +++++++++--------- .../common/guided_onboarding/translations.ts | 92 ++++++++++++ .../security_solution/server/plugin.ts | 42 +++++- 4 files changed, 199 insertions(+), 72 deletions(-) create mode 100644 x-pack/plugins/security_solution/common/guided_onboarding/translations.ts diff --git a/x-pack/plugins/cloud_integrations/cloud_experiments/common/constants.ts b/x-pack/plugins/cloud_integrations/cloud_experiments/common/constants.ts index 0cbfeb509e8b3..f15796d3d6f74 100644 --- a/x-pack/plugins/cloud_integrations/cloud_experiments/common/constants.ts +++ b/x-pack/plugins/cloud_integrations/cloud_experiments/common/constants.ts @@ -21,6 +21,7 @@ export enum FEATURE_FLAG_NAMES { * It resolves the URL that the button "Add Integrations" will point to. */ 'security-solutions.add-integrations-url' = 'security-solutions.add-integrations-url', + 'security-solutions.guided-onboarding-content' = 'security-solutions.guided-onboarding-content', } /** diff --git a/x-pack/plugins/security_solution/common/guided_onboarding/siem_guide_config.ts b/x-pack/plugins/security_solution/common/guided_onboarding/siem_guide_config.ts index 707595d0bd8f8..d20ad74fe98b4 100644 --- a/x-pack/plugins/security_solution/common/guided_onboarding/siem_guide_config.ts +++ b/x-pack/plugins/security_solution/common/guided_onboarding/siem_guide_config.ts @@ -6,50 +6,67 @@ */ import type { GuideConfig } from '@kbn/guided-onboarding'; -import { i18n } from '@kbn/i18n'; +import * as i18t from './translations'; export const siemGuideId = 'siem'; -export const siemGuideConfig: GuideConfig = { - title: i18n.translate('xpack.securitySolution.guideConfig.title', { - defaultMessage: 'Detect threats in my data with SIEM', - }), + +export const defaultGuideTranslations = { + title: i18t.TITLE, + description: i18t.DESCRIPTION, + docs: i18t.DOCS, + steps: { + add_data: { + title: i18t.ADD_DATA_TITLE, + description: i18t.ADD_DATA_DESCRIPTION, + }, + rules: { + title: i18t.RULES_TITLE, + description: i18t.RULES_DESCRIPTION, + manualCompletion: { + title: i18t.RULES_MANUAL_TITLE, + description: i18t.RULES_MANUAL_DESCRIPTION, + }, + }, + alertsCases: { + title: i18t.CASES_TITLE, + description: i18t.CASES_DESCRIPTION, + manualCompletion: { + title: i18t.CASES_MANUAL_TITLE, + description: i18t.CASES_MANUAL_DESCRIPTION, + }, + }, + }, +}; + +export const getSiemGuideConfig = (launchDarkly = defaultGuideTranslations): GuideConfig => ({ + // check each launchDarkly property in case data is misformatted + title: launchDarkly.title ? launchDarkly.title : defaultGuideTranslations.title, guideName: 'Security', - telemetryId: 'siem', + telemetryId: siemGuideId, completedGuideRedirectLocation: { appID: 'securitySolutionUI', path: '/dashboards', }, - description: i18n.translate('xpack.securitySolution.guideConfig.description', { - defaultMessage: `There are many ways to get your SIEM data into Elastic. In this guide, we'll help you get set up quickly using the Elastic Defend integration.`, - }), + description: launchDarkly.description + ? launchDarkly.description + : defaultGuideTranslations.description, docs: { - text: i18n.translate('xpack.securitySolution.guideConfig.documentationLink', { - defaultMessage: 'Learn more', - }), + text: launchDarkly.docs ? launchDarkly.docs : defaultGuideTranslations.docs, url: 'https://www.elastic.co/guide/en/security/current/ingest-data.html', }, steps: [ { id: 'add_data', - title: i18n.translate('xpack.securitySolution.guideConfig.addDataStep.title', { - defaultMessage: 'Add data with Elastic Defend', - }), + title: launchDarkly.steps?.add_data?.title + ? launchDarkly.steps.add_data.title + : defaultGuideTranslations.steps.add_data.title, description: { - descriptionText: i18n.translate( - 'xpack.securitySolution.guideConfig.addDataStep.description', - { - defaultMessage: - 'Install Elastic Agent and its Elastic Defend integration on one of your computers to get SIEM data flowing.', - } - ), + descriptionText: launchDarkly.steps?.add_data?.description + ? launchDarkly.steps.add_data.description + : defaultGuideTranslations.steps.add_data.description, linkUrl: 'https://docs.elastic.co/en/integrations/endpoint', isLinkExternal: true, - linkText: i18n.translate( - 'xpack.securitySolution.guideConfig.addDataStep.description.linkText', - { - defaultMessage: 'Learn more', - } - ), + linkText: i18t.LINK_TEXT, }, integration: 'endpoint', location: { @@ -59,26 +76,19 @@ export const siemGuideConfig: GuideConfig = { }, { id: 'rules', - title: i18n.translate('xpack.securitySolution.guideConfig.rulesStep.title', { - defaultMessage: 'Turn on rules', - }), - description: i18n.translate('xpack.securitySolution.guideConfig.rulesStep.description', { - defaultMessage: - 'Load the Elastic prebuilt rules, select the rules you want, and enable them to generate alerts.', - }), + title: launchDarkly.steps?.rules?.title + ? launchDarkly.steps.rules.title + : defaultGuideTranslations.steps.rules.title, + description: launchDarkly.steps?.rules?.description + ? launchDarkly.steps.rules.description + : defaultGuideTranslations.steps.rules.description, manualCompletion: { - title: i18n.translate( - 'xpack.securitySolution.guideConfig.rulesStep.manualCompletion.title', - { - defaultMessage: 'Continue with the guide', - } - ), - description: i18n.translate( - 'xpack.securitySolution.guideConfig.rulesStep.manualCompletion.description', - { - defaultMessage: `After you've enabled the rules you need, continue.`, - } - ), + title: launchDarkly.steps?.rules?.manualCompletion?.title + ? launchDarkly.steps.rules.manualCompletion.title + : defaultGuideTranslations.steps.rules.manualCompletion.title, + description: launchDarkly.steps?.rules?.manualCompletion?.description + ? launchDarkly.steps.rules.manualCompletion.description + : defaultGuideTranslations.steps.rules.manualCompletion.description, }, location: { appID: 'securitySolutionUI', @@ -87,30 +97,24 @@ export const siemGuideConfig: GuideConfig = { }, { id: 'alertsCases', - title: i18n.translate('xpack.securitySolution.guideConfig.alertsStep.title', { - defaultMessage: 'Manage alerts and cases', - }), - description: i18n.translate('xpack.securitySolution.guideConfig.alertsStep.description', { - defaultMessage: 'Learn how to view and triage alerts with cases.', - }), + title: launchDarkly.steps?.alertsCases?.title + ? launchDarkly.steps.alertsCases.title + : defaultGuideTranslations.steps.alertsCases.title, + description: launchDarkly.steps?.alertsCases?.description + ? launchDarkly.steps.alertsCases.description + : defaultGuideTranslations.steps.alertsCases.description, location: { appID: 'securitySolutionUI', path: '/alerts', }, manualCompletion: { - title: i18n.translate( - 'xpack.securitySolution.guideConfig.alertsStep.manualCompletion.title', - { - defaultMessage: 'Continue the guide', - } - ), - description: i18n.translate( - 'xpack.securitySolution.guideConfig.alertsStep.manualCompletion.description', - { - defaultMessage: `After you've explored the case, continue.`, - } - ), + title: launchDarkly.steps?.alertsCases?.manualCompletion?.title + ? launchDarkly.steps.alertsCases.manualCompletion.title + : defaultGuideTranslations.steps.alertsCases.manualCompletion.title, + description: launchDarkly.steps?.alertsCases?.manualCompletion?.description + ? launchDarkly.steps.alertsCases.manualCompletion.description + : defaultGuideTranslations.steps.alertsCases.manualCompletion.description, }, }, ], -}; +}); diff --git a/x-pack/plugins/security_solution/common/guided_onboarding/translations.ts b/x-pack/plugins/security_solution/common/guided_onboarding/translations.ts new file mode 100644 index 0000000000000..9d96333796a34 --- /dev/null +++ b/x-pack/plugins/security_solution/common/guided_onboarding/translations.ts @@ -0,0 +1,92 @@ +/* + * 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 { i18n } from '@kbn/i18n'; + +export const TITLE = i18n.translate('xpack.securitySolution.guideConfig.title', { + defaultMessage: 'Detect threats in my data with SIEM', +}); + +export const DESCRIPTION = i18n.translate('xpack.securitySolution.guideConfig.description', { + defaultMessage: `There are many ways to get your SIEM data into Elastic. In this guide, we'll help you get set up quickly using the Elastic Defend integration.`, +}); + +export const DOCS = i18n.translate('xpack.securitySolution.guideConfig.documentationLink', { + defaultMessage: 'Learn more', +}); + +export const LINK_TEXT = i18n.translate( + 'xpack.securitySolution.guideConfig.addDataStep.description.linkText', + { + defaultMessage: 'Learn more', + } +); + +export const ADD_DATA_TITLE = i18n.translate( + 'xpack.securitySolution.guideConfig.addDataStep.title', + { + defaultMessage: 'Add data with Elastic Defend', + } +); + +export const ADD_DATA_DESCRIPTION = i18n.translate( + 'xpack.securitySolution.guideConfig.addDataStep.description', + { + defaultMessage: + 'Install Elastic Agent and its Elastic Defend integration on one of your computers to get SIEM data flowing.', + } +); + +export const RULES_TITLE = i18n.translate('xpack.securitySolution.guideConfig.rulesStep.title', { + defaultMessage: 'Turn on rules', +}); + +export const RULES_DESCRIPTION = i18n.translate( + 'xpack.securitySolution.guideConfig.rulesStep.description', + { + defaultMessage: + 'Load the Elastic prebuilt rules, select the rules you want, and enable them to generate alerts.', + } +); + +export const RULES_MANUAL_TITLE = i18n.translate( + 'xpack.securitySolution.guideConfig.rulesStep.manualCompletion.title', + { + defaultMessage: 'Continue with the guide', + } +); + +export const RULES_MANUAL_DESCRIPTION = i18n.translate( + 'xpack.securitySolution.guideConfig.rulesStep.manualCompletion.description', + { + defaultMessage: `After you've enabled the rules you need, continue.`, + } +); + +export const CASES_TITLE = i18n.translate('xpack.securitySolution.guideConfig.alertsStep.title', { + defaultMessage: 'Manage alerts and cases', +}); +export const CASES_DESCRIPTION = i18n.translate( + 'xpack.securitySolution.guideConfig.alertsStep.description', + { + defaultMessage: 'Learn how to view and triage alerts with cases.', + } +); + +export const CASES_MANUAL_TITLE = i18n.translate( + 'xpack.securitySolution.guideConfig.alertsStep.manualCompletion.title', + { + defaultMessage: 'Continue the guide', + } +); + +export const CASES_MANUAL_DESCRIPTION = i18n.translate( + 'xpack.securitySolution.guideConfig.alertsStep.manualCompletion.description', + { + defaultMessage: `After you've explored the case, continue.`, + } +); diff --git a/x-pack/plugins/security_solution/server/plugin.ts b/x-pack/plugins/security_solution/server/plugin.ts index 4e7beb558d4de..b0f672696441c 100644 --- a/x-pack/plugins/security_solution/server/plugin.ts +++ b/x-pack/plugins/security_solution/server/plugin.ts @@ -20,7 +20,11 @@ import type { ILicense } from '@kbn/licensing-plugin/server'; import { turnOffPolicyProtectionsIfNotSupported } from './endpoint/migrations/turn_off_policy_protections'; import { endpointSearchStrategyProvider } from './search_strategy/endpoint'; import { getScheduleNotificationResponseActionsService } from './lib/detection_engine/rule_response_actions/schedule_notification_response_actions'; -import { siemGuideId, siemGuideConfig } from '../common/guided_onboarding/siem_guide_config'; +import { + siemGuideId, + getSiemGuideConfig, + defaultGuideTranslations, +} from '../common/guided_onboarding/siem_guide_config'; import { createEqlAlertType, createIndicatorMatchAlertType, @@ -377,6 +381,36 @@ export class Plugin implements ISecuritySolutionPlugin { ); plugins.data.search.registerSearchStrategy(ENDPOINT_SEARCH_STRATEGY, endpointSearchStrategy); + + /** + * Register a config for the security guide + */ + console.log('depsStart', depsStart); + if (depsStart.cloudExperiments) { + console.log('in cloud experiments'); + try { + depsStart.cloudExperiments + .getVariation('security-solutions.guided-onboarding-content', defaultGuideTranslations) + .then((variation) => { + console.log('variation', variation); + plugins.guidedOnboarding.registerGuideConfig( + siemGuideId, + getSiemGuideConfig(variation) + ); + }); + } catch { + plugins.guidedOnboarding.registerGuideConfig( + siemGuideId, + getSiemGuideConfig(defaultGuideTranslations) + ); + } + } else { + console.log('NOT in cloud experiments'); + plugins.guidedOnboarding.registerGuideConfig( + siemGuideId, + getSiemGuideConfig(defaultGuideTranslations) + ); + } }); setIsElasticCloudDeployment(plugins.cloud.isCloudEnabled ?? false); @@ -397,11 +431,6 @@ export class Plugin implements ISecuritySolutionPlugin { featureUsageService.setup(plugins.licensing); - /** - * Register a config for the security guide - */ - plugins.guidedOnboarding.registerGuideConfig(siemGuideId, siemGuideConfig); - return { setAppFeatures: this.appFeatures.set.bind(this.appFeatures), }; @@ -411,6 +440,7 @@ export class Plugin implements ISecuritySolutionPlugin { core: SecuritySolutionPluginCoreStartDependencies, plugins: SecuritySolutionPluginStartDependencies ): SecuritySolutionPluginStart { + console.log('PLUGS HERE', Object.keys(plugins)); const { config, logger } = this; this.ruleMonitoringService.start(core, plugins); From b8c3f4f94ba4a0134fae0458f18ab96114d7eaa8 Mon Sep 17 00:00:00 2001 From: Steph Milovic Date: Tue, 15 Aug 2023 10:24:10 -0600 Subject: [PATCH 2/6] rm logs, it works! --- x-pack/plugins/security_solution/server/plugin.ts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/x-pack/plugins/security_solution/server/plugin.ts b/x-pack/plugins/security_solution/server/plugin.ts index b0f672696441c..9da9c093efb7b 100644 --- a/x-pack/plugins/security_solution/server/plugin.ts +++ b/x-pack/plugins/security_solution/server/plugin.ts @@ -385,14 +385,11 @@ export class Plugin implements ISecuritySolutionPlugin { /** * Register a config for the security guide */ - console.log('depsStart', depsStart); if (depsStart.cloudExperiments) { - console.log('in cloud experiments'); try { depsStart.cloudExperiments .getVariation('security-solutions.guided-onboarding-content', defaultGuideTranslations) .then((variation) => { - console.log('variation', variation); plugins.guidedOnboarding.registerGuideConfig( siemGuideId, getSiemGuideConfig(variation) @@ -405,7 +402,6 @@ export class Plugin implements ISecuritySolutionPlugin { ); } } else { - console.log('NOT in cloud experiments'); plugins.guidedOnboarding.registerGuideConfig( siemGuideId, getSiemGuideConfig(defaultGuideTranslations) @@ -440,7 +436,6 @@ export class Plugin implements ISecuritySolutionPlugin { core: SecuritySolutionPluginCoreStartDependencies, plugins: SecuritySolutionPluginStartDependencies ): SecuritySolutionPluginStart { - console.log('PLUGS HERE', Object.keys(plugins)); const { config, logger } = this; this.ruleMonitoringService.start(core, plugins); From 817af1e29d848a963f70e5ff6076f743aaf1bf29 Mon Sep 17 00:00:00 2001 From: Steph Milovic Date: Tue, 15 Aug 2023 10:35:42 -0600 Subject: [PATCH 3/6] add tests --- .../siem_guide_config.test.ts | 227 ++++++++++++++++++ .../guided_onboarding/siem_guide_config.ts | 92 ++++--- 2 files changed, 269 insertions(+), 50 deletions(-) create mode 100644 x-pack/plugins/security_solution/common/guided_onboarding/siem_guide_config.test.ts diff --git a/x-pack/plugins/security_solution/common/guided_onboarding/siem_guide_config.test.ts b/x-pack/plugins/security_solution/common/guided_onboarding/siem_guide_config.test.ts new file mode 100644 index 0000000000000..21b4e6b3ff627 --- /dev/null +++ b/x-pack/plugins/security_solution/common/guided_onboarding/siem_guide_config.test.ts @@ -0,0 +1,227 @@ +/* + * 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 { defaultGuideTranslations, getSiemGuideConfig, siemGuideId } from './siem_guide_config'; +import * as i18n from './translations'; + +describe('getSiemGuideConfig', () => { + it('returns a GuideConfig object with default values when no arguments are passed', () => { + const result = getSiemGuideConfig(); + expect(result).toEqual({ + title: defaultGuideTranslations.title, + guideName: 'Security', + telemetryId: siemGuideId, + completedGuideRedirectLocation: { + appID: 'securitySolutionUI', + path: '/dashboards', + }, + description: defaultGuideTranslations.description, + docs: { + text: defaultGuideTranslations.docs, + url: 'https://www.elastic.co/guide/en/security/current/ingest-data.html', + }, + steps: [ + { + id: 'add_data', + title: defaultGuideTranslations.steps.add_data.title, + description: { + descriptionText: defaultGuideTranslations.steps.add_data.description, + linkUrl: 'https://docs.elastic.co/en/integrations/endpoint', + isLinkExternal: true, + linkText: i18n.LINK_TEXT, + }, + integration: 'endpoint', + location: { + appID: 'integrations', + path: '/browse/security', + }, + }, + { + id: 'rules', + title: defaultGuideTranslations.steps.rules.title, + description: defaultGuideTranslations.steps.rules.description, + location: { + appID: 'securitySolutionUI', + path: '/rules', + }, + }, + { + id: 'alertsCases', + title: defaultGuideTranslations.steps.alertsCases.title, + description: defaultGuideTranslations.steps.alertsCases.description, + location: { + appID: 'securitySolutionUI', + path: '/alerts', + }, + }, + ], + }); + }); + + it('returns a GuideConfig object with values from the launchDarkly argument when it is passed', () => { + const launchDarkly = { + title: 'Custom Title', + description: 'Custom Description', + docs: 'Custom Docs', + steps: { + add_data: { + title: 'Custom Add Data Title', + description: 'Custom Add Data Description', + }, + rules: { + title: 'Custom Rules Title', + description: 'Custom Rules Description', + manualCompletion: { + title: 'Custom Rules Manual Title', + description: 'Custom Rules Manual Description', + }, + }, + alertsCases: { + title: 'Custom Alerts Cases Title', + description: 'Custom Alerts Cases Description', + manualCompletion: { + title: 'Custom Alerts Cases Manual Title', + description: 'Custom Alerts Cases Manual Description', + }, + }, + }, + }; + const result = getSiemGuideConfig(launchDarkly); + expect(result).toEqual({ + title: launchDarkly.title, + guideName: 'Security', + telemetryId: siemGuideId, + completedGuideRedirectLocation: { + appID: 'securitySolutionUI', + path: '/dashboards', + }, + description: launchDarkly.description, + docs: { + text: launchDarkly.docs, + url: 'https://www.elastic.co/guide/en/security/current/ingest-data.html', + }, + steps: [ + { + id: 'add_data', + title: launchDarkly.steps.add_data.title, + description: { + descriptionText: launchDarkly.steps.add_data.description, + linkUrl: 'https://docs.elastic.co/en/integrations/endpoint', + isLinkExternal: true, + linkText: i18n.LINK_TEXT, + }, + integration: 'endpoint', + location: { + appID: 'integrations', + path: '/browse/security', + }, + }, + { + id: 'rules', + title: launchDarkly.steps.rules.title, + description: launchDarkly.steps.rules.description, + manualCompletion: { + title: launchDarkly.steps.rules.manualCompletion.title, + description: launchDarkly.steps.rules.manualCompletion.description, + }, + location: { + appID: 'securitySolutionUI', + path: '/rules', + }, + }, + { + id: 'alertsCases', + title: launchDarkly.steps.alertsCases.title, + description: launchDarkly.steps.alertsCases.description, + manualCompletion: { + title: launchDarkly.steps.alertsCases.manualCompletion.title, + description: launchDarkly.steps.alertsCases.manualCompletion.description, + }, + location: { + appID: 'securitySolutionUI', + path: '/alerts', + }, + }, + ], + }); + }); + + it('returns a GuideConfig object with values from the launchDarkly argument and default values when some properties are missing', () => { + const launchDarkly = { + steps: { + add_data: { + title: 'Custom Add Data Title', + }, + rules: { + description: 'Custom Rules Description', + }, + alertsCases: { + manualCompletion: { + title: 'Custom Alerts Cases Manual Title', + }, + }, + }, + }; + // Ignore because intentionally passing an incomplete object to test that we handle missing properties + // since there is no validation on the object from LaunchDarkly + // @ts-ignore + const result = getSiemGuideConfig(launchDarkly); + expect(result).toEqual({ + title: defaultGuideTranslations.title, + guideName: 'Security', + telemetryId: siemGuideId, + completedGuideRedirectLocation: { + appID: 'securitySolutionUI', + path: '/dashboards', + }, + description: defaultGuideTranslations.description, + docs: { + text: defaultGuideTranslations.docs, + url: 'https://www.elastic.co/guide/en/security/current/ingest-data.html', + }, + steps: [ + { + id: 'add_data', + title: launchDarkly.steps.add_data.title, + description: { + descriptionText: defaultGuideTranslations.steps.add_data.description, + linkUrl: 'https://docs.elastic.co/en/integrations/endpoint', + isLinkExternal: true, + linkText: i18n.LINK_TEXT, + }, + integration: 'endpoint', + location: { + appID: 'integrations', + path: '/browse/security', + }, + }, + { + id: 'rules', + title: defaultGuideTranslations.steps.rules.title, + description: launchDarkly.steps.rules.description, + location: { + appID: 'securitySolutionUI', + path: '/rules', + }, + }, + { + id: 'alertsCases', + title: defaultGuideTranslations.steps.alertsCases.title, + description: defaultGuideTranslations.steps.alertsCases.description, + manualCompletion: { + title: launchDarkly.steps.alertsCases.manualCompletion.title, + description: defaultGuideTranslations.steps.alertsCases.manualCompletion.description, + }, + location: { + appID: 'securitySolutionUI', + path: '/alerts', + }, + }, + ], + }); + }); +}); diff --git a/x-pack/plugins/security_solution/common/guided_onboarding/siem_guide_config.ts b/x-pack/plugins/security_solution/common/guided_onboarding/siem_guide_config.ts index d20ad74fe98b4..f260c94262513 100644 --- a/x-pack/plugins/security_solution/common/guided_onboarding/siem_guide_config.ts +++ b/x-pack/plugins/security_solution/common/guided_onboarding/siem_guide_config.ts @@ -6,33 +6,33 @@ */ import type { GuideConfig } from '@kbn/guided-onboarding'; -import * as i18t from './translations'; +import * as i18n from './translations'; export const siemGuideId = 'siem'; export const defaultGuideTranslations = { - title: i18t.TITLE, - description: i18t.DESCRIPTION, - docs: i18t.DOCS, + title: i18n.TITLE, + description: i18n.DESCRIPTION, + docs: i18n.DOCS, steps: { add_data: { - title: i18t.ADD_DATA_TITLE, - description: i18t.ADD_DATA_DESCRIPTION, + title: i18n.ADD_DATA_TITLE, + description: i18n.ADD_DATA_DESCRIPTION, }, rules: { - title: i18t.RULES_TITLE, - description: i18t.RULES_DESCRIPTION, + title: i18n.RULES_TITLE, + description: i18n.RULES_DESCRIPTION, manualCompletion: { - title: i18t.RULES_MANUAL_TITLE, - description: i18t.RULES_MANUAL_DESCRIPTION, + title: i18n.RULES_MANUAL_TITLE, + description: i18n.RULES_MANUAL_DESCRIPTION, }, }, alertsCases: { - title: i18t.CASES_TITLE, - description: i18t.CASES_DESCRIPTION, + title: i18n.CASES_TITLE, + description: i18n.CASES_DESCRIPTION, manualCompletion: { - title: i18t.CASES_MANUAL_TITLE, - description: i18t.CASES_MANUAL_DESCRIPTION, + title: i18n.CASES_MANUAL_TITLE, + description: i18n.CASES_MANUAL_DESCRIPTION, }, }, }, @@ -40,33 +40,29 @@ export const defaultGuideTranslations = { export const getSiemGuideConfig = (launchDarkly = defaultGuideTranslations): GuideConfig => ({ // check each launchDarkly property in case data is misformatted - title: launchDarkly.title ? launchDarkly.title : defaultGuideTranslations.title, + title: launchDarkly.title ?? defaultGuideTranslations.title, guideName: 'Security', telemetryId: siemGuideId, completedGuideRedirectLocation: { appID: 'securitySolutionUI', path: '/dashboards', }, - description: launchDarkly.description - ? launchDarkly.description - : defaultGuideTranslations.description, + description: launchDarkly.description ?? defaultGuideTranslations.description, docs: { - text: launchDarkly.docs ? launchDarkly.docs : defaultGuideTranslations.docs, + text: launchDarkly.docs ?? defaultGuideTranslations.docs, url: 'https://www.elastic.co/guide/en/security/current/ingest-data.html', }, steps: [ { id: 'add_data', - title: launchDarkly.steps?.add_data?.title - ? launchDarkly.steps.add_data.title - : defaultGuideTranslations.steps.add_data.title, + title: launchDarkly.steps?.add_data?.title ?? defaultGuideTranslations.steps.add_data.title, description: { - descriptionText: launchDarkly.steps?.add_data?.description - ? launchDarkly.steps.add_data.description - : defaultGuideTranslations.steps.add_data.description, + descriptionText: + launchDarkly.steps?.add_data?.description ?? + defaultGuideTranslations.steps.add_data.description, linkUrl: 'https://docs.elastic.co/en/integrations/endpoint', isLinkExternal: true, - linkText: i18t.LINK_TEXT, + linkText: i18n.LINK_TEXT, }, integration: 'endpoint', location: { @@ -76,19 +72,16 @@ export const getSiemGuideConfig = (launchDarkly = defaultGuideTranslations): Gui }, { id: 'rules', - title: launchDarkly.steps?.rules?.title - ? launchDarkly.steps.rules.title - : defaultGuideTranslations.steps.rules.title, - description: launchDarkly.steps?.rules?.description - ? launchDarkly.steps.rules.description - : defaultGuideTranslations.steps.rules.description, + title: launchDarkly.steps?.rules?.title ?? defaultGuideTranslations.steps.rules.title, + description: + launchDarkly.steps?.rules?.description ?? defaultGuideTranslations.steps.rules.description, manualCompletion: { - title: launchDarkly.steps?.rules?.manualCompletion?.title - ? launchDarkly.steps.rules.manualCompletion.title - : defaultGuideTranslations.steps.rules.manualCompletion.title, - description: launchDarkly.steps?.rules?.manualCompletion?.description - ? launchDarkly.steps.rules.manualCompletion.description - : defaultGuideTranslations.steps.rules.manualCompletion.description, + title: + launchDarkly.steps?.rules?.manualCompletion?.title ?? + defaultGuideTranslations.steps.rules.manualCompletion.title, + description: + launchDarkly.steps?.rules?.manualCompletion?.description ?? + defaultGuideTranslations.steps.rules.manualCompletion.description, }, location: { appID: 'securitySolutionUI', @@ -97,23 +90,22 @@ export const getSiemGuideConfig = (launchDarkly = defaultGuideTranslations): Gui }, { id: 'alertsCases', - title: launchDarkly.steps?.alertsCases?.title - ? launchDarkly.steps.alertsCases.title - : defaultGuideTranslations.steps.alertsCases.title, - description: launchDarkly.steps?.alertsCases?.description - ? launchDarkly.steps.alertsCases.description - : defaultGuideTranslations.steps.alertsCases.description, + title: + launchDarkly.steps?.alertsCases?.title ?? defaultGuideTranslations.steps.alertsCases.title, + description: + launchDarkly.steps?.alertsCases?.description ?? + defaultGuideTranslations.steps.alertsCases.description, location: { appID: 'securitySolutionUI', path: '/alerts', }, manualCompletion: { - title: launchDarkly.steps?.alertsCases?.manualCompletion?.title - ? launchDarkly.steps.alertsCases.manualCompletion.title - : defaultGuideTranslations.steps.alertsCases.manualCompletion.title, - description: launchDarkly.steps?.alertsCases?.manualCompletion?.description - ? launchDarkly.steps.alertsCases.manualCompletion.description - : defaultGuideTranslations.steps.alertsCases.manualCompletion.description, + title: + launchDarkly.steps?.alertsCases?.manualCompletion?.title ?? + defaultGuideTranslations.steps.alertsCases.manualCompletion.title, + description: + launchDarkly.steps?.alertsCases?.manualCompletion?.description ?? + defaultGuideTranslations.steps.alertsCases.manualCompletion.description, }, }, ], From 5b05a9a6c31bdd2a312a4afdb6fdf80a61a0c4d5 Mon Sep 17 00:00:00 2001 From: Steph Milovic Date: Wed, 16 Aug 2023 11:28:12 -0600 Subject: [PATCH 4/6] only run experiment when language is english --- .../common/guided_onboarding/siem_guide_config.test.ts | 3 +++ x-pack/plugins/security_solution/server/plugin.ts | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/security_solution/common/guided_onboarding/siem_guide_config.test.ts b/x-pack/plugins/security_solution/common/guided_onboarding/siem_guide_config.test.ts index 21b4e6b3ff627..5000244c994a5 100644 --- a/x-pack/plugins/security_solution/common/guided_onboarding/siem_guide_config.test.ts +++ b/x-pack/plugins/security_solution/common/guided_onboarding/siem_guide_config.test.ts @@ -48,6 +48,7 @@ describe('getSiemGuideConfig', () => { appID: 'securitySolutionUI', path: '/rules', }, + manualCompletion: defaultGuideTranslations.steps.rules.manualCompletion, }, { id: 'alertsCases', @@ -57,6 +58,7 @@ describe('getSiemGuideConfig', () => { appID: 'securitySolutionUI', path: '/alerts', }, + manualCompletion: defaultGuideTranslations.steps.alertsCases.manualCompletion, }, ], }); @@ -207,6 +209,7 @@ describe('getSiemGuideConfig', () => { appID: 'securitySolutionUI', path: '/rules', }, + manualCompletion: defaultGuideTranslations.steps.rules.manualCompletion, }, { id: 'alertsCases', diff --git a/x-pack/plugins/security_solution/server/plugin.ts b/x-pack/plugins/security_solution/server/plugin.ts index 8a1b77d332965..5992fe12514df 100644 --- a/x-pack/plugins/security_solution/server/plugin.ts +++ b/x-pack/plugins/security_solution/server/plugin.ts @@ -17,6 +17,7 @@ import { Dataset } from '@kbn/rule-registry-plugin/server'; import type { ListPluginSetup } from '@kbn/lists-plugin/server'; import type { ILicense } from '@kbn/licensing-plugin/server'; +import { i18n } from '@kbn/i18n'; import { turnOffPolicyProtectionsIfNotSupported } from './endpoint/migrations/turn_off_policy_protections'; import { endpointSearchStrategyProvider } from './search_strategy/endpoint'; import { getScheduleNotificationResponseActionsService } from './lib/detection_engine/rule_response_actions/schedule_notification_response_actions'; @@ -375,7 +376,7 @@ export class Plugin implements ISecuritySolutionPlugin { /** * Register a config for the security guide */ - if (depsStart.cloudExperiments) { + if (depsStart.cloudExperiments && i18n.getLocale() === 'en') { try { depsStart.cloudExperiments .getVariation('security-solutions.guided-onboarding-content', defaultGuideTranslations) From eac2caa28c7b6cd16bb75c3d4241e8a9158af2ee Mon Sep 17 00:00:00 2001 From: Steph Milovic Date: Mon, 21 Aug 2023 08:37:30 -0600 Subject: [PATCH 5/6] add definition comment --- .../cloud_integrations/cloud_experiments/common/constants.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/x-pack/plugins/cloud_integrations/cloud_experiments/common/constants.ts b/x-pack/plugins/cloud_integrations/cloud_experiments/common/constants.ts index f15796d3d6f74..6eb9e01f333b0 100644 --- a/x-pack/plugins/cloud_integrations/cloud_experiments/common/constants.ts +++ b/x-pack/plugins/cloud_integrations/cloud_experiments/common/constants.ts @@ -21,6 +21,11 @@ export enum FEATURE_FLAG_NAMES { * It resolves the URL that the button "Add Integrations" will point to. */ 'security-solutions.add-integrations-url' = 'security-solutions.add-integrations-url', + /** + * Used in the Security Solutions guided onboarding tour. + * Returns JSON corresponding to the tour guide config as + * defined by type { GuideConfig } from '@kbn/guided-onboarding'; + */ 'security-solutions.guided-onboarding-content' = 'security-solutions.guided-onboarding-content', } From 5bfb7f116dc0b12417bf3246238c6dd7a3d7e66a Mon Sep 17 00:00:00 2001 From: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Date: Tue, 12 Sep 2023 14:34:36 +0000 Subject: [PATCH 6/6] [CI] Auto-commit changed files from 'node scripts/eslint --no-cache --fix' --- x-pack/plugins/security_solution/server/plugin.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/security_solution/server/plugin.ts b/x-pack/plugins/security_solution/server/plugin.ts index 1512126b5b24e..2998854f484e4 100644 --- a/x-pack/plugins/security_solution/server/plugin.ts +++ b/x-pack/plugins/security_solution/server/plugin.ts @@ -17,8 +17,8 @@ import { Dataset } from '@kbn/rule-registry-plugin/server'; import type { ListPluginSetup } from '@kbn/lists-plugin/server'; import type { ILicense } from '@kbn/licensing-plugin/server'; -import { endpointPackagePoliciesStatsSearchStrategyProvider } from './search_strategy/endpoint_package_policies_stats'; import { i18n } from '@kbn/i18n'; +import { endpointPackagePoliciesStatsSearchStrategyProvider } from './search_strategy/endpoint_package_policies_stats'; import { turnOffPolicyProtectionsIfNotSupported } from './endpoint/migrations/turn_off_policy_protections'; import { endpointSearchStrategyProvider } from './search_strategy/endpoint'; import { getScheduleNotificationResponseActionsService } from './lib/detection_engine/rule_response_actions/schedule_notification_response_actions';