From 6ae9b0b424a49d34735edf6a1e306ee5688d8e63 Mon Sep 17 00:00:00 2001 From: Angela Chuang Date: Tue, 4 Mar 2025 14:23:20 +0000 Subject: [PATCH 01/10] set product feature keys --- .../routes/results/get_index_results.ts | 2 +- .../security_solution/public/plugin.tsx | 46 ++++++++++++------- .../public/plugin_contract.ts | 8 +++- .../plugins/security_solution/public/types.ts | 2 + .../security_solution_ess/public/plugin.ts | 4 ++ .../public/plugin.ts | 4 ++ 6 files changed, 47 insertions(+), 19 deletions(-) diff --git a/x-pack/solutions/security/plugins/ecs_data_quality_dashboard/server/routes/results/get_index_results.ts b/x-pack/solutions/security/plugins/ecs_data_quality_dashboard/server/routes/results/get_index_results.ts index 71f2422146f9c..10f7759f06c5c 100644 --- a/x-pack/solutions/security/plugins/ecs_data_quality_dashboard/server/routes/results/get_index_results.ts +++ b/x-pack/solutions/security/plugins/ecs_data_quality_dashboard/server/routes/results/get_index_results.ts @@ -141,7 +141,7 @@ export const getIndexResultsRoute = ( outcome, }), }; - const { hits } = await client.asInternalUser.search(query); + const { hits } = await client.asCurrentUser.search(query); const resultsWithUndefined = hits.hits.map((doc) => doc._source) ?? []; diff --git a/x-pack/solutions/security/plugins/security_solution/public/plugin.tsx b/x-pack/solutions/security/plugins/security_solution/public/plugin.tsx index 2dfef2a01e978..5e251617079c3 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/plugin.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/plugin.tsx @@ -7,7 +7,7 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; -import { Subject, combineLatestWith } from 'rxjs'; +import { Subject, combineLatestWith, take } from 'rxjs'; import type * as H from 'history'; import type { AppMountParameters, @@ -61,6 +61,7 @@ import { PluginContract } from './plugin_contract'; import { PluginServices } from './plugin_services'; import { getExternalReferenceAttachmentEndpointRegular } from './cases/attachments/external_reference'; import { hasAccessToSecuritySolution } from './helpers_access'; +import { ProductFeatureAssistantKey } from '../../../packages/features/src/product_features_keys'; export class Plugin implements IPlugin { private config: SecuritySolutionUiConfigType; @@ -99,6 +100,7 @@ export class Plugin implements IPlugin { @@ -183,23 +185,33 @@ export class Plugin implements IPlugin { - const { renderApp, services, store } = await mountDependencies(); - const { ManagementSettings } = await this.lazyAssistantSettingsManagement(); - - return renderApp({ - ...params, - services, - store, - usageCollection, - children: , + productFeatureKeys$.subscribe((productFeatureKeys) => { + // initial value is null, then it is set as an array in serverless/ess plugin + console.log('productFeatureKeys---',productFeatureKeys); + // This seemed to work with serverless but not sure how to deal with ess productFeatureKeys + + const isInProductFeatureKeys = productFeatureKeys && productFeatureKeys.length > 0 && productFeatureKeys.includes(ProductFeatureAssistantKey.assistant); + if (isInProductFeatureKeys) { + console.log('======registering assistant management======'); + management?.sections.section.kibana.registerApp({ + id: 'securityAiAssistantManagement', + title: ASSISTANT_MANAGEMENT_TITLE, + hideFromSidebar: true, + order: 1, + mount: async (params) => { + const { renderApp, services, store } = await mountDependencies(); + const { ManagementSettings } = await this.lazyAssistantSettingsManagement(); + + return renderApp({ + ...params, + services, + store, + usageCollection, + children: , + }); + }, }); - }, + } }); cases?.attachmentFramework.registerExternalReference( diff --git a/x-pack/solutions/security/plugins/security_solution/public/plugin_contract.ts b/x-pack/solutions/security/plugins/security_solution/public/plugin_contract.ts index d9b79a06c1e8a..2e4d3b1a5a562 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/plugin_contract.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/plugin_contract.ts @@ -4,7 +4,6 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - import { BehaviorSubject } from 'rxjs'; import { UpsellingService } from '@kbn/security-solution-upselling/service'; import type { CoreStart } from '@kbn/core/public'; @@ -14,24 +13,31 @@ import { navLinks$, updateNavLinks } from './common/links/nav_links'; import { breadcrumbsNav$ } from './common/breadcrumbs'; import { ContractComponentsService } from './contract_components'; import { OnboardingService } from './onboarding/service'; +import { ProductFeatureKeys } from '../../../packages/features/src/types'; export class PluginContract { public componentsService: ContractComponentsService; public upsellingService: UpsellingService; public onboardingService: OnboardingService; public isSolutionNavigationEnabled$: BehaviorSubject; + public productFeatureKeys$: BehaviorSubject; constructor(private readonly experimentalFeatures: ExperimentalFeatures) { this.onboardingService = new OnboardingService(); this.componentsService = new ContractComponentsService(); this.upsellingService = new UpsellingService(); this.isSolutionNavigationEnabled$ = new BehaviorSubject(false); // defaults to classic navigation + this.productFeatureKeys$ = new BehaviorSubject(null); } public getSetupContract(): PluginSetup { + return { resolver: lazyResolver, experimentalFeatures: { ...this.experimentalFeatures }, + setProductFeatureKeys: (productFeatureKeys: ProductFeatureKeys) => { + this.productFeatureKeys$.next(productFeatureKeys); + }, }; } diff --git a/x-pack/solutions/security/plugins/security_solution/public/types.ts b/x-pack/solutions/security/plugins/security_solution/public/types.ts index 57dd3b34edcbf..a74cefd2bf375 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/types.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/types.ts @@ -49,6 +49,7 @@ import type { GuidedOnboardingPluginStart } from '@kbn/guided-onboarding-plugin/ import type { DataViewsServicePublic } from '@kbn/data-views-plugin/public'; import type { ContentManagementPublicStart } from '@kbn/content-management-plugin/public'; import type { ExpressionsStart } from '@kbn/expressions-plugin/public'; +import type { ProductFeatureKeyType } from '@kbn/security-solution-features/keys'; import type { DiscoverStart } from '@kbn/discover-plugin/public'; import type { ManagementSetup } from '@kbn/management-plugin/public'; @@ -213,6 +214,7 @@ export type StartRenderServices = Pick< export interface PluginSetup { resolver: () => Promise; experimentalFeatures: ExperimentalFeatures; + setProductFeatureKeys: (productFeatureKeys: ProductFeatureKeyType[]) => void; } export interface PluginStart { diff --git a/x-pack/solutions/security/plugins/security_solution_ess/public/plugin.ts b/x-pack/solutions/security/plugins/security_solution_ess/public/plugin.ts index 9cd5e77e5a4e4..3248b738a6790 100644 --- a/x-pack/solutions/security/plugins/security_solution_ess/public/plugin.ts +++ b/x-pack/solutions/security/plugins/security_solution_ess/public/plugin.ts @@ -30,6 +30,10 @@ export class SecuritySolutionEssPlugin _core: CoreSetup, _setupDeps: SecuritySolutionEssPluginSetupDeps ): SecuritySolutionEssPluginSetup { + const { securitySolution } = _setupDeps; + + securitySolution.setProductFeatureKeys([]); + return {}; } diff --git a/x-pack/solutions/security/plugins/security_solution_serverless/public/plugin.ts b/x-pack/solutions/security/plugins/security_solution_serverless/public/plugin.ts index a9743ef4fa51f..46f046f4dfbd8 100644 --- a/x-pack/solutions/security/plugins/security_solution_serverless/public/plugin.ts +++ b/x-pack/solutions/security/plugins/security_solution_serverless/public/plugin.ts @@ -24,6 +24,7 @@ import { } from '../common/experimental_features'; import { setOnboardingSettings } from './onboarding'; import { getAdditionalChargesMessage } from './components/additional_charges_message'; +import { getProductProductFeatures } from '../common/pli/pli_features'; export class SecuritySolutionServerlessPlugin implements @@ -47,12 +48,15 @@ export class SecuritySolutionServerlessPlugin setupDeps: SecuritySolutionServerlessPluginSetupDeps ): SecuritySolutionServerlessPluginSetup { const { securitySolution } = setupDeps; + const { productTypes } = this.config; this.experimentalFeatures = parseExperimentalConfigValue( this.config.enableExperimental, securitySolution.experimentalFeatures ).features; + console.log('serverless setup: setProductFeatureKeys====== ') + securitySolution.setProductFeatureKeys(getProductProductFeatures(productTypes)); return {}; } From e5fdb464fc7ffb81650f3f46af3a243c89b030d1 Mon Sep 17 00:00:00 2001 From: Angela Chuang Date: Tue, 4 Mar 2025 14:38:52 +0000 Subject: [PATCH 02/10] set product feature keys --- .../server/routes/results/get_index_results.ts | 2 +- .../security/plugins/security_solution/public/plugin.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/solutions/security/plugins/ecs_data_quality_dashboard/server/routes/results/get_index_results.ts b/x-pack/solutions/security/plugins/ecs_data_quality_dashboard/server/routes/results/get_index_results.ts index 10f7759f06c5c..71f2422146f9c 100644 --- a/x-pack/solutions/security/plugins/ecs_data_quality_dashboard/server/routes/results/get_index_results.ts +++ b/x-pack/solutions/security/plugins/ecs_data_quality_dashboard/server/routes/results/get_index_results.ts @@ -141,7 +141,7 @@ export const getIndexResultsRoute = ( outcome, }), }; - const { hits } = await client.asCurrentUser.search(query); + const { hits } = await client.asInternalUser.search(query); const resultsWithUndefined = hits.hits.map((doc) => doc._source) ?? []; diff --git a/x-pack/solutions/security/plugins/security_solution/public/plugin.tsx b/x-pack/solutions/security/plugins/security_solution/public/plugin.tsx index 5e251617079c3..9e163d5876139 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/plugin.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/plugin.tsx @@ -7,7 +7,7 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; -import { Subject, combineLatestWith, take } from 'rxjs'; +import { Subject, combineLatestWith } from 'rxjs'; import type * as H from 'history'; import type { AppMountParameters, From 82c62105a84629960736add4efb4c5e97be7b259 Mon Sep 17 00:00:00 2001 From: Angela Chuang Date: Tue, 4 Mar 2025 17:30:10 +0000 Subject: [PATCH 03/10] set product feature keys --- .../plugins/security_solution/public/plugin.tsx | 15 +++++++-------- .../security_solution/public/plugin_contract.ts | 8 ++++---- .../plugins/security_solution/public/types.ts | 2 +- .../security_solution_ess/public/plugin.ts | 3 ++- .../security_solution_serverless/public/plugin.ts | 3 +-- 5 files changed, 15 insertions(+), 16 deletions(-) diff --git a/x-pack/solutions/security/plugins/security_solution/public/plugin.tsx b/x-pack/solutions/security/plugins/security_solution/public/plugin.tsx index 9e163d5876139..8631273065cff 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/plugin.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/plugin.tsx @@ -7,7 +7,7 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; -import { Subject, combineLatestWith } from 'rxjs'; +import { Subject, withLatestFrom, combineLatestWith } from 'rxjs'; import type * as H from 'history'; import type { AppMountParameters, @@ -185,14 +185,13 @@ export class Plugin implements IPlugin { - // initial value is null, then it is set as an array in serverless/ess plugin - console.log('productFeatureKeys---',productFeatureKeys); - // This seemed to work with serverless but not sure how to deal with ess productFeatureKeys - const isInProductFeatureKeys = productFeatureKeys && productFeatureKeys.length > 0 && productFeatureKeys.includes(ProductFeatureAssistantKey.assistant); - if (isInProductFeatureKeys) { - console.log('======registering assistant management======'); + productFeatureKeys$.pipe(withLatestFrom(plugins.licensing.license$)).subscribe(([productFeatureKeys, license]) => { + + const isInProductFeatureKeys = productFeatureKeys?.has(ProductFeatureAssistantKey.assistant); + const hasRegistered = management?.sections.section.kibana.getApp('securityAiAssistantManagement') + + if (isInProductFeatureKeys && license?.hasAtLeast('enterprise') && !hasRegistered) { management?.sections.section.kibana.registerApp({ id: 'securityAiAssistantManagement', title: ASSISTANT_MANAGEMENT_TITLE, diff --git a/x-pack/solutions/security/plugins/security_solution/public/plugin_contract.ts b/x-pack/solutions/security/plugins/security_solution/public/plugin_contract.ts index 2e4d3b1a5a562..8c1620e1b4efa 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/plugin_contract.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/plugin_contract.ts @@ -13,21 +13,21 @@ import { navLinks$, updateNavLinks } from './common/links/nav_links'; import { breadcrumbsNav$ } from './common/breadcrumbs'; import { ContractComponentsService } from './contract_components'; import { OnboardingService } from './onboarding/service'; -import { ProductFeatureKeys } from '../../../packages/features/src/types'; +import { ProductFeatureKeyType } from '../../../packages/features/src/types'; export class PluginContract { public componentsService: ContractComponentsService; public upsellingService: UpsellingService; public onboardingService: OnboardingService; public isSolutionNavigationEnabled$: BehaviorSubject; - public productFeatureKeys$: BehaviorSubject; + public productFeatureKeys$: BehaviorSubject | null>; constructor(private readonly experimentalFeatures: ExperimentalFeatures) { this.onboardingService = new OnboardingService(); this.componentsService = new ContractComponentsService(); this.upsellingService = new UpsellingService(); this.isSolutionNavigationEnabled$ = new BehaviorSubject(false); // defaults to classic navigation - this.productFeatureKeys$ = new BehaviorSubject(null); + this.productFeatureKeys$ = new BehaviorSubject | null>(null); } public getSetupContract(): PluginSetup { @@ -35,7 +35,7 @@ export class PluginContract { return { resolver: lazyResolver, experimentalFeatures: { ...this.experimentalFeatures }, - setProductFeatureKeys: (productFeatureKeys: ProductFeatureKeys) => { + setProductFeatureKeys: (productFeatureKeys: Set) => { this.productFeatureKeys$.next(productFeatureKeys); }, }; diff --git a/x-pack/solutions/security/plugins/security_solution/public/types.ts b/x-pack/solutions/security/plugins/security_solution/public/types.ts index a74cefd2bf375..637d214b7ddf9 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/types.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/types.ts @@ -214,7 +214,7 @@ export type StartRenderServices = Pick< export interface PluginSetup { resolver: () => Promise; experimentalFeatures: ExperimentalFeatures; - setProductFeatureKeys: (productFeatureKeys: ProductFeatureKeyType[]) => void; + setProductFeatureKeys: (productFeatureKeys: Set) => void; } export interface PluginStart { diff --git a/x-pack/solutions/security/plugins/security_solution_ess/public/plugin.ts b/x-pack/solutions/security/plugins/security_solution_ess/public/plugin.ts index 3248b738a6790..36dbcf2b5493f 100644 --- a/x-pack/solutions/security/plugins/security_solution_ess/public/plugin.ts +++ b/x-pack/solutions/security/plugins/security_solution_ess/public/plugin.ts @@ -16,6 +16,7 @@ import type { SecuritySolutionEssPluginStartDeps, } from './types'; import { setOnboardingSettings } from './onboarding'; +import { DEFAULT_PRODUCT_FEATURES } from '../server/constants'; export class SecuritySolutionEssPlugin implements @@ -32,7 +33,7 @@ export class SecuritySolutionEssPlugin ): SecuritySolutionEssPluginSetup { const { securitySolution } = _setupDeps; - securitySolution.setProductFeatureKeys([]); + securitySolution.setProductFeatureKeys(new Set(DEFAULT_PRODUCT_FEATURES)); return {}; } diff --git a/x-pack/solutions/security/plugins/security_solution_serverless/public/plugin.ts b/x-pack/solutions/security/plugins/security_solution_serverless/public/plugin.ts index 46f046f4dfbd8..76bf8907f6b47 100644 --- a/x-pack/solutions/security/plugins/security_solution_serverless/public/plugin.ts +++ b/x-pack/solutions/security/plugins/security_solution_serverless/public/plugin.ts @@ -55,8 +55,7 @@ export class SecuritySolutionServerlessPlugin securitySolution.experimentalFeatures ).features; - console.log('serverless setup: setProductFeatureKeys====== ') - securitySolution.setProductFeatureKeys(getProductProductFeatures(productTypes)); + securitySolution.setProductFeatureKeys(new Set(getProductProductFeatures(productTypes))); return {}; } From 5b268f8d43933289885721d8e8dd26dbf7fdbc25 Mon Sep 17 00:00:00 2001 From: Angela Chuang <6295984+angorayc@users.noreply.github.com> Date: Wed, 5 Mar 2025 10:33:49 +0000 Subject: [PATCH 04/10] Update x-pack/solutions/security/plugins/security_solution/public/plugin_contract.ts Co-authored-by: Sergi Massaneda --- .../plugins/security_solution/public/plugin_contract.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/solutions/security/plugins/security_solution/public/plugin_contract.ts b/x-pack/solutions/security/plugins/security_solution/public/plugin_contract.ts index 8c1620e1b4efa..1f8bc30afb733 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/plugin_contract.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/plugin_contract.ts @@ -35,8 +35,8 @@ export class PluginContract { return { resolver: lazyResolver, experimentalFeatures: { ...this.experimentalFeatures }, - setProductFeatureKeys: (productFeatureKeys: Set) => { - this.productFeatureKeys$.next(productFeatureKeys); + setProductFeatureKeys: (productFeatureKeys: ProductFeatureKeys) => { + this.productFeatureKeys$.next(new Set(productFeatureKeys)); }, }; } From 82a297d2044706cebdf914e786391d1946f0e2d9 Mon Sep 17 00:00:00 2001 From: Angela Chuang <6295984+angorayc@users.noreply.github.com> Date: Wed, 5 Mar 2025 10:34:37 +0000 Subject: [PATCH 05/10] Update x-pack/solutions/security/plugins/security_solution/public/plugin.tsx Co-authored-by: Sergi Massaneda --- .../security/plugins/security_solution/public/plugin.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/x-pack/solutions/security/plugins/security_solution/public/plugin.tsx b/x-pack/solutions/security/plugins/security_solution/public/plugin.tsx index 8631273065cff..3d18df4205406 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/plugin.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/plugin.tsx @@ -188,10 +188,10 @@ export class Plugin implements IPlugin { - const isInProductFeatureKeys = productFeatureKeys?.has(ProductFeatureAssistantKey.assistant); - const hasRegistered = management?.sections.section.kibana.getApp('securityAiAssistantManagement') + const isAssistantAvailable = productFeatureKeys?.has(ProductFeatureAssistantKey.assistant) && license?.hasAtLeast('enterprise'); + const assistantManagementApp = management?.sections.section.kibana.getApp('securityAiAssistantManagement') - if (isInProductFeatureKeys && license?.hasAtLeast('enterprise') && !hasRegistered) { + if (isAssistantAvailable && !assistantManagementApp) { management?.sections.section.kibana.registerApp({ id: 'securityAiAssistantManagement', title: ASSISTANT_MANAGEMENT_TITLE, From 7efa0f38c40a26945a943839c89ceb4e9a8b58ab Mon Sep 17 00:00:00 2001 From: Angela Chuang Date: Wed, 5 Mar 2025 11:17:21 +0000 Subject: [PATCH 06/10] code review --- .../security_solution/public/plugin.tsx | 39 ++++++++++--------- .../public/plugin_contract.ts | 2 +- .../plugins/security_solution/public/types.ts | 4 +- .../security_solution_ess/public/plugin.ts | 2 +- .../public/plugin.ts | 2 +- 5 files changed, 25 insertions(+), 24 deletions(-) diff --git a/x-pack/solutions/security/plugins/security_solution/public/plugin.tsx b/x-pack/solutions/security/plugins/security_solution/public/plugin.tsx index 3d18df4205406..209d765495f94 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/plugin.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/plugin.tsx @@ -185,31 +185,32 @@ export class Plugin implements IPlugin { + const { renderApp, services, store } = await mountDependencies(); + const { ManagementSettings } = await this.lazyAssistantSettingsManagement(); + + return renderApp({ + ...params, + services, + store, + usageCollection, + children: , + }); + }, + }); productFeatureKeys$.pipe(withLatestFrom(plugins.licensing.license$)).subscribe(([productFeatureKeys, license]) => { const isAssistantAvailable = productFeatureKeys?.has(ProductFeatureAssistantKey.assistant) && license?.hasAtLeast('enterprise'); const assistantManagementApp = management?.sections.section.kibana.getApp('securityAiAssistantManagement') - if (isAssistantAvailable && !assistantManagementApp) { - management?.sections.section.kibana.registerApp({ - id: 'securityAiAssistantManagement', - title: ASSISTANT_MANAGEMENT_TITLE, - hideFromSidebar: true, - order: 1, - mount: async (params) => { - const { renderApp, services, store } = await mountDependencies(); - const { ManagementSettings } = await this.lazyAssistantSettingsManagement(); - - return renderApp({ - ...params, - services, - store, - usageCollection, - children: , - }); - }, - }); + if (!isAssistantAvailable) { + assistantManagementApp?.disable(); } }); diff --git a/x-pack/solutions/security/plugins/security_solution/public/plugin_contract.ts b/x-pack/solutions/security/plugins/security_solution/public/plugin_contract.ts index 1f8bc30afb733..154773fdab1cc 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/plugin_contract.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/plugin_contract.ts @@ -13,7 +13,7 @@ import { navLinks$, updateNavLinks } from './common/links/nav_links'; import { breadcrumbsNav$ } from './common/breadcrumbs'; import { ContractComponentsService } from './contract_components'; import { OnboardingService } from './onboarding/service'; -import { ProductFeatureKeyType } from '../../../packages/features/src/types'; +import { ProductFeatureKeyType, ProductFeatureKeys } from '../../../packages/features/src/types'; export class PluginContract { public componentsService: ContractComponentsService; diff --git a/x-pack/solutions/security/plugins/security_solution/public/types.ts b/x-pack/solutions/security/plugins/security_solution/public/types.ts index 637d214b7ddf9..7b8140b2c9c15 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/types.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/types.ts @@ -49,7 +49,6 @@ import type { GuidedOnboardingPluginStart } from '@kbn/guided-onboarding-plugin/ import type { DataViewsServicePublic } from '@kbn/data-views-plugin/public'; import type { ContentManagementPublicStart } from '@kbn/content-management-plugin/public'; import type { ExpressionsStart } from '@kbn/expressions-plugin/public'; -import type { ProductFeatureKeyType } from '@kbn/security-solution-features/keys'; import type { DiscoverStart } from '@kbn/discover-plugin/public'; import type { ManagementSetup } from '@kbn/management-plugin/public'; @@ -97,6 +96,7 @@ import type { OnboardingService } from './onboarding/service'; import type { SolutionNavigation } from './app/solution_navigation/solution_navigation'; import type { TelemetryServiceStart } from './common/lib/telemetry'; import type { SiemMigrationsService } from './siem_migrations/service'; +import { ProductFeatureKeys } from '../../../packages/features'; export interface SetupPlugins { cloud?: CloudSetup; @@ -214,7 +214,7 @@ export type StartRenderServices = Pick< export interface PluginSetup { resolver: () => Promise; experimentalFeatures: ExperimentalFeatures; - setProductFeatureKeys: (productFeatureKeys: Set) => void; + setProductFeatureKeys: (productFeatureKeys: ProductFeatureKeys) => void; } export interface PluginStart { diff --git a/x-pack/solutions/security/plugins/security_solution_ess/public/plugin.ts b/x-pack/solutions/security/plugins/security_solution_ess/public/plugin.ts index 36dbcf2b5493f..5cd39823164ca 100644 --- a/x-pack/solutions/security/plugins/security_solution_ess/public/plugin.ts +++ b/x-pack/solutions/security/plugins/security_solution_ess/public/plugin.ts @@ -33,7 +33,7 @@ export class SecuritySolutionEssPlugin ): SecuritySolutionEssPluginSetup { const { securitySolution } = _setupDeps; - securitySolution.setProductFeatureKeys(new Set(DEFAULT_PRODUCT_FEATURES)); + securitySolution.setProductFeatureKeys(DEFAULT_PRODUCT_FEATURES); return {}; } diff --git a/x-pack/solutions/security/plugins/security_solution_serverless/public/plugin.ts b/x-pack/solutions/security/plugins/security_solution_serverless/public/plugin.ts index 76bf8907f6b47..c65949a19efe2 100644 --- a/x-pack/solutions/security/plugins/security_solution_serverless/public/plugin.ts +++ b/x-pack/solutions/security/plugins/security_solution_serverless/public/plugin.ts @@ -55,7 +55,7 @@ export class SecuritySolutionServerlessPlugin securitySolution.experimentalFeatures ).features; - securitySolution.setProductFeatureKeys(new Set(getProductProductFeatures(productTypes))); + securitySolution.setProductFeatureKeys(getProductProductFeatures(productTypes)); return {}; } From 666ef4f863b9fa6b9158ae5d5b056abfabce225a Mon Sep 17 00:00:00 2001 From: Angela Chuang Date: Wed, 5 Mar 2025 11:19:44 +0000 Subject: [PATCH 07/10] code review --- .../security/plugins/security_solution_ess/public/plugin.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/solutions/security/plugins/security_solution_ess/public/plugin.ts b/x-pack/solutions/security/plugins/security_solution_ess/public/plugin.ts index 5cd39823164ca..7e2a680e7a3af 100644 --- a/x-pack/solutions/security/plugins/security_solution_ess/public/plugin.ts +++ b/x-pack/solutions/security/plugins/security_solution_ess/public/plugin.ts @@ -29,9 +29,9 @@ export class SecuritySolutionEssPlugin { public setup( _core: CoreSetup, - _setupDeps: SecuritySolutionEssPluginSetupDeps + setupDeps: SecuritySolutionEssPluginSetupDeps ): SecuritySolutionEssPluginSetup { - const { securitySolution } = _setupDeps; + const { securitySolution } = setupDeps; securitySolution.setProductFeatureKeys(DEFAULT_PRODUCT_FEATURES); From 93a2c5c8ce8bb9c8546c535e4577c807935db347 Mon Sep 17 00:00:00 2001 From: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Date: Wed, 5 Mar 2025 12:00:02 +0000 Subject: [PATCH 08/10] [CI] Auto-commit changed files from 'node scripts/eslint --no-cache --fix' --- .../security_solution/public/plugin.tsx | 23 +++++++++++-------- .../public/plugin_contract.ts | 6 +++-- .../plugins/security_solution/public/types.ts | 2 +- 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/x-pack/solutions/security/plugins/security_solution/public/plugin.tsx b/x-pack/solutions/security/plugins/security_solution/public/plugin.tsx index 209d765495f94..1bfdb420aa404 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/plugin.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/plugin.tsx @@ -24,6 +24,7 @@ import type { SecuritySolutionAppWrapperFeature, SecuritySolutionCellRendererFeature, } from '@kbn/discover-shared-plugin/public/services/discover_features'; +import { ProductFeatureAssistantKey } from '@kbn/security-solution-features/src/product_features_keys'; import { getLazyCloudSecurityPosturePliAuthBlockExtension } from './cloud_security_posture/lazy_cloud_security_posture_pli_auth_block_extension'; import { getLazyEndpointAgentTamperProtectionExtension } from './management/pages/policy/view/ingest_manager_integration/lazy_endpoint_agent_tamper_protection_extension'; import type { @@ -61,7 +62,6 @@ import { PluginContract } from './plugin_contract'; import { PluginServices } from './plugin_services'; import { getExternalReferenceAttachmentEndpointRegular } from './cases/attachments/external_reference'; import { hasAccessToSecuritySolution } from './helpers_access'; -import { ProductFeatureAssistantKey } from '../../../packages/features/src/product_features_keys'; export class Plugin implements IPlugin { private config: SecuritySolutionUiConfigType; @@ -204,15 +204,20 @@ export class Plugin implements IPlugin { - - const isAssistantAvailable = productFeatureKeys?.has(ProductFeatureAssistantKey.assistant) && license?.hasAtLeast('enterprise'); - const assistantManagementApp = management?.sections.section.kibana.getApp('securityAiAssistantManagement') + productFeatureKeys$ + .pipe(withLatestFrom(plugins.licensing.license$)) + .subscribe(([productFeatureKeys, license]) => { + const isAssistantAvailable = + productFeatureKeys?.has(ProductFeatureAssistantKey.assistant) && + license?.hasAtLeast('enterprise'); + const assistantManagementApp = management?.sections.section.kibana.getApp( + 'securityAiAssistantManagement' + ); - if (!isAssistantAvailable) { - assistantManagementApp?.disable(); - } - }); + if (!isAssistantAvailable) { + assistantManagementApp?.disable(); + } + }); cases?.attachmentFramework.registerExternalReference( getExternalReferenceAttachmentEndpointRegular() diff --git a/x-pack/solutions/security/plugins/security_solution/public/plugin_contract.ts b/x-pack/solutions/security/plugins/security_solution/public/plugin_contract.ts index 154773fdab1cc..0f526070f26f7 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/plugin_contract.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/plugin_contract.ts @@ -7,13 +7,16 @@ import { BehaviorSubject } from 'rxjs'; import { UpsellingService } from '@kbn/security-solution-upselling/service'; import type { CoreStart } from '@kbn/core/public'; +import type { + ProductFeatureKeyType, + ProductFeatureKeys, +} from '@kbn/security-solution-features/src/types'; import type { ContractStartServices, PluginSetup, PluginStart } from './types'; import type { ExperimentalFeatures } from '../common/experimental_features'; import { navLinks$, updateNavLinks } from './common/links/nav_links'; import { breadcrumbsNav$ } from './common/breadcrumbs'; import { ContractComponentsService } from './contract_components'; import { OnboardingService } from './onboarding/service'; -import { ProductFeatureKeyType, ProductFeatureKeys } from '../../../packages/features/src/types'; export class PluginContract { public componentsService: ContractComponentsService; @@ -31,7 +34,6 @@ export class PluginContract { } public getSetupContract(): PluginSetup { - return { resolver: lazyResolver, experimentalFeatures: { ...this.experimentalFeatures }, diff --git a/x-pack/solutions/security/plugins/security_solution/public/types.ts b/x-pack/solutions/security/plugins/security_solution/public/types.ts index 7b8140b2c9c15..47fb76cec1796 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/types.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/types.ts @@ -62,6 +62,7 @@ import type { MapsStartApi } from '@kbn/maps-plugin/public'; import type { ServerlessPluginStart } from '@kbn/serverless/public'; import type { DiscoverSharedPublicStart } from '@kbn/discover-shared-plugin/public'; import type { AutomaticImportPluginStart } from '@kbn/automatic-import-plugin/public'; +import type { ProductFeatureKeys } from '@kbn/security-solution-features'; import type { ResolverPluginSetup } from './resolver/types'; import type { Inspect } from '../common/search_strategy'; import type { Detections } from './detections'; @@ -96,7 +97,6 @@ import type { OnboardingService } from './onboarding/service'; import type { SolutionNavigation } from './app/solution_navigation/solution_navigation'; import type { TelemetryServiceStart } from './common/lib/telemetry'; import type { SiemMigrationsService } from './siem_migrations/service'; -import { ProductFeatureKeys } from '../../../packages/features'; export interface SetupPlugins { cloud?: CloudSetup; From 5612a56c77d79d8513be0837ada29aaae327c4b2 Mon Sep 17 00:00:00 2001 From: Angela Chuang Date: Wed, 5 Mar 2025 13:51:11 +0000 Subject: [PATCH 09/10] code review --- .../security/plugins/security_solution/public/mocks.ts | 3 ++- .../security/plugins/security_solution/public/plugin.tsx | 3 +-- .../plugins/security_solution/public/plugin_contract.ts | 6 +++--- .../security_solution_ess/{server => common}/constants.ts | 0 .../security/plugins/security_solution_ess/public/plugin.ts | 2 +- .../security/plugins/security_solution_ess/server/plugin.ts | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) rename x-pack/solutions/security/plugins/security_solution_ess/{server => common}/constants.ts (100%) diff --git a/x-pack/solutions/security/plugins/security_solution/public/mocks.ts b/x-pack/solutions/security/plugins/security_solution/public/mocks.ts index 8e16b883f474b..b45d0eb1316b8 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/mocks.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/mocks.ts @@ -24,7 +24,8 @@ export const contractStartServicesMock: ContractStartServices = { const setupMock = (): PluginSetup => ({ resolver: jest.fn(), - experimentalFeatures: allowedExperimentalValues, // default values + experimentalFeatures: allowedExperimentalValues, // default values, + setProductFeatureKeys: jest.fn(), }); const startMock = (): PluginStart => ({ diff --git a/x-pack/solutions/security/plugins/security_solution/public/plugin.tsx b/x-pack/solutions/security/plugins/security_solution/public/plugin.tsx index 209d765495f94..723665838393d 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/plugin.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/plugin.tsx @@ -204,8 +204,7 @@ export class Plugin implements IPlugin { - + productFeatureKeys$.pipe(combineLatestWith(plugins.licensing.license$)).subscribe(([productFeatureKeys, license]) => { const isAssistantAvailable = productFeatureKeys?.has(ProductFeatureAssistantKey.assistant) && license?.hasAtLeast('enterprise'); const assistantManagementApp = management?.sections.section.kibana.getApp('securityAiAssistantManagement') diff --git a/x-pack/solutions/security/plugins/security_solution/public/plugin_contract.ts b/x-pack/solutions/security/plugins/security_solution/public/plugin_contract.ts index 154773fdab1cc..8a7d7840107bc 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/plugin_contract.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/plugin_contract.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { BehaviorSubject } from 'rxjs'; +import { BehaviorSubject, Subject } from 'rxjs'; import { UpsellingService } from '@kbn/security-solution-upselling/service'; import type { CoreStart } from '@kbn/core/public'; import type { ContractStartServices, PluginSetup, PluginStart } from './types'; @@ -20,14 +20,14 @@ export class PluginContract { public upsellingService: UpsellingService; public onboardingService: OnboardingService; public isSolutionNavigationEnabled$: BehaviorSubject; - public productFeatureKeys$: BehaviorSubject | null>; + public productFeatureKeys$: Subject | null>; constructor(private readonly experimentalFeatures: ExperimentalFeatures) { this.onboardingService = new OnboardingService(); this.componentsService = new ContractComponentsService(); this.upsellingService = new UpsellingService(); this.isSolutionNavigationEnabled$ = new BehaviorSubject(false); // defaults to classic navigation - this.productFeatureKeys$ = new BehaviorSubject | null>(null); + this.productFeatureKeys$ = new Subject | null>(); } public getSetupContract(): PluginSetup { diff --git a/x-pack/solutions/security/plugins/security_solution_ess/server/constants.ts b/x-pack/solutions/security/plugins/security_solution_ess/common/constants.ts similarity index 100% rename from x-pack/solutions/security/plugins/security_solution_ess/server/constants.ts rename to x-pack/solutions/security/plugins/security_solution_ess/common/constants.ts diff --git a/x-pack/solutions/security/plugins/security_solution_ess/public/plugin.ts b/x-pack/solutions/security/plugins/security_solution_ess/public/plugin.ts index 7e2a680e7a3af..faa6d40121605 100644 --- a/x-pack/solutions/security/plugins/security_solution_ess/public/plugin.ts +++ b/x-pack/solutions/security/plugins/security_solution_ess/public/plugin.ts @@ -16,7 +16,7 @@ import type { SecuritySolutionEssPluginStartDeps, } from './types'; import { setOnboardingSettings } from './onboarding'; -import { DEFAULT_PRODUCT_FEATURES } from '../server/constants'; +import { DEFAULT_PRODUCT_FEATURES } from '../common/constants'; export class SecuritySolutionEssPlugin implements diff --git a/x-pack/solutions/security/plugins/security_solution_ess/server/plugin.ts b/x-pack/solutions/security/plugins/security_solution_ess/server/plugin.ts index de4081f60ac49..6c0edcf40dbaf 100644 --- a/x-pack/solutions/security/plugins/security_solution_ess/server/plugin.ts +++ b/x-pack/solutions/security/plugins/security_solution_ess/server/plugin.ts @@ -7,7 +7,7 @@ import type { Plugin, CoreSetup } from '@kbn/core/server'; import { getProductProductFeaturesConfigurator } from './product_features'; -import { DEFAULT_PRODUCT_FEATURES } from './constants'; +import { DEFAULT_PRODUCT_FEATURES } from '../common/constants'; import type { SecuritySolutionEssPluginSetup, From 68d2c9eda2a5fcd751f8249b78735b5a24f67b7f Mon Sep 17 00:00:00 2001 From: Angela Chuang Date: Wed, 5 Mar 2025 15:47:18 +0000 Subject: [PATCH 10/10] code review --- .../security/plugins/security_solution/public/plugin.tsx | 4 ++++ .../plugins/security_solution/public/plugin_contract.ts | 6 +++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/x-pack/solutions/security/plugins/security_solution/public/plugin.tsx b/x-pack/solutions/security/plugins/security_solution/public/plugin.tsx index 2474e5f1463dd..2da2fa8a8c347 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/plugin.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/plugin.tsx @@ -207,6 +207,10 @@ export class Plugin implements IPlugin { + if (!productFeatureKeys || !license) { + return; + } + const isAssistantAvailable = productFeatureKeys?.has(ProductFeatureAssistantKey.assistant) && license?.hasAtLeast('enterprise'); diff --git a/x-pack/solutions/security/plugins/security_solution/public/plugin_contract.ts b/x-pack/solutions/security/plugins/security_solution/public/plugin_contract.ts index 67acf15cfadee..0f526070f26f7 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/plugin_contract.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/plugin_contract.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { BehaviorSubject, Subject } from 'rxjs'; +import { BehaviorSubject } from 'rxjs'; import { UpsellingService } from '@kbn/security-solution-upselling/service'; import type { CoreStart } from '@kbn/core/public'; import type { @@ -23,14 +23,14 @@ export class PluginContract { public upsellingService: UpsellingService; public onboardingService: OnboardingService; public isSolutionNavigationEnabled$: BehaviorSubject; - public productFeatureKeys$: Subject | null>; + public productFeatureKeys$: BehaviorSubject | null>; constructor(private readonly experimentalFeatures: ExperimentalFeatures) { this.onboardingService = new OnboardingService(); this.componentsService = new ContractComponentsService(); this.upsellingService = new UpsellingService(); this.isSolutionNavigationEnabled$ = new BehaviorSubject(false); // defaults to classic navigation - this.productFeatureKeys$ = new Subject | null>(); + this.productFeatureKeys$ = new BehaviorSubject | null>(null); } public getSetupContract(): PluginSetup {