diff --git a/src/platform/packages/shared/deeplinks/security/deep_links.ts b/src/platform/packages/shared/deeplinks/security/deep_links.ts
index 464003abd369c..cb47043cc4a18 100644
--- a/src/platform/packages/shared/deeplinks/security/deep_links.ts
+++ b/src/platform/packages/shared/deeplinks/security/deep_links.ts
@@ -11,6 +11,7 @@ export enum SecurityPageName {
administration = 'administration',
alerts = 'alerts',
assets = 'assets',
+ assetInventory = 'asset_inventory',
attackDiscovery = 'attack_discovery',
blocklist = 'blocklist',
/*
diff --git a/x-pack/solutions/security/plugins/asset_inventory/public/application.tsx b/x-pack/solutions/security/plugins/asset_inventory/public/application.tsx
deleted file mode 100644
index f442f01d17f7c..0000000000000
--- a/x-pack/solutions/security/plugins/asset_inventory/public/application.tsx
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-import React from 'react';
-import ReactDOM from 'react-dom';
-import type { AppMountParameters, CoreStart } from '@kbn/core/public';
-import type { AppPluginStartDependencies } from './types';
-import { AssetInventoryApp } from './components/app';
-
-export const renderApp = (
- { notifications, http }: CoreStart,
- {}: AppPluginStartDependencies,
- { appBasePath, element }: AppMountParameters
-) => {
- ReactDOM.render(
- ,
- element
- );
-
- return () => ReactDOM.unmountComponentAtNode(element);
-};
diff --git a/x-pack/solutions/security/plugins/asset_inventory/public/components/app.tsx b/x-pack/solutions/security/plugins/asset_inventory/public/components/app.tsx
index 924091034353b..50040ab9d22d3 100644
--- a/x-pack/solutions/security/plugins/asset_inventory/public/components/app.tsx
+++ b/x-pack/solutions/security/plugins/asset_inventory/public/components/app.tsx
@@ -6,33 +6,26 @@
*/
import React from 'react';
import { FormattedMessage, I18nProvider } from '@kbn/i18n-react';
-import { BrowserRouter as Router } from '@kbn/shared-ux-router';
import { EuiPageTemplate, EuiTitle } from '@elastic/eui';
-import type { CoreStart } from '@kbn/core/public';
-interface AssetInventoryAppDeps {
- basename: string;
- notifications: CoreStart['notifications'];
- http: CoreStart['http'];
-}
-
-export const AssetInventoryApp = ({ basename }: AssetInventoryAppDeps) => {
+const AssetInventoryApp = () => {
return (
-
-
- <>
-
-
-
-
-
-
-
-
-
-
- >
-
-
+
+ <>
+
+
+
+
+
+
+
+
+
+
+ >
+
);
};
+
+// we need to use default exports to import it via React.lazy
+export default AssetInventoryApp; // eslint-disable-line import/no-default-export
diff --git a/x-pack/solutions/security/plugins/asset_inventory/public/methods/index.tsx b/x-pack/solutions/security/plugins/asset_inventory/public/methods/index.tsx
new file mode 100644
index 0000000000000..bc44445b9b14a
--- /dev/null
+++ b/x-pack/solutions/security/plugins/asset_inventory/public/methods/index.tsx
@@ -0,0 +1,34 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React, { lazy, Suspense } from 'react';
+import { EuiLoadingSpinner } from '@elastic/eui';
+import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
+import { AppPluginStartDependencies } from '../types';
+
+// Initializing react-query
+const queryClient = new QueryClient({
+ defaultOptions: {
+ queries: {
+ refetchOnWindowFocus: false,
+ refetchOnMount: false,
+ refetchOnReconnect: false,
+ },
+ },
+});
+
+const AssetInventoryLazy = lazy(() => import('../components/app'));
+
+export const getAssetInventoryLazy = (props: AppPluginStartDependencies) => {
+ return (
+
+ }>
+
+
+
+ );
+};
diff --git a/x-pack/solutions/security/plugins/asset_inventory/public/plugin.ts b/x-pack/solutions/security/plugins/asset_inventory/public/plugin.ts
index fd2841f5b2335..f6663399e7a2b 100644
--- a/x-pack/solutions/security/plugins/asset_inventory/public/plugin.ts
+++ b/x-pack/solutions/security/plugins/asset_inventory/public/plugin.ts
@@ -4,12 +4,13 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
-import type { AppMountParameters, CoreSetup, CoreStart, Plugin } from '@kbn/core/public';
+import type { CoreSetup, CoreStart, Plugin } from '@kbn/core/public';
import type {
AssetInventoryPluginSetup,
AssetInventoryPluginStart,
AppPluginStartDependencies,
} from './types';
+import { getAssetInventoryLazy } from './methods';
export class AssetInventoryPlugin
implements Plugin
@@ -17,16 +18,10 @@ export class AssetInventoryPlugin
public setup(core: CoreSetup): AssetInventoryPluginSetup {
return {};
}
- public start(
- coreStart: CoreStart,
- depsStart: AppPluginStartDependencies
- ): AssetInventoryPluginStart {
+ public start(coreStart: CoreStart): AssetInventoryPluginStart {
return {
- getAssetInventoryPage: async (params: AppMountParameters) => {
- // Load application bundle
- const { renderApp } = await import('./application');
- // Render the application
- return renderApp(coreStart, depsStart as AppPluginStartDependencies, params);
+ getAssetInventoryPage: (assetInventoryDeps: AppPluginStartDependencies) => {
+ return getAssetInventoryLazy(assetInventoryDeps);
},
};
}
diff --git a/x-pack/solutions/security/plugins/asset_inventory/public/types.ts b/x-pack/solutions/security/plugins/asset_inventory/public/types.ts
index a551b4d231c3d..2d1f51329e5c9 100644
--- a/x-pack/solutions/security/plugins/asset_inventory/public/types.ts
+++ b/x-pack/solutions/security/plugins/asset_inventory/public/types.ts
@@ -8,8 +8,9 @@
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface AssetInventoryPluginSetup {}
-// eslint-disable-next-line @typescript-eslint/no-empty-interface
-export interface AssetInventoryPluginStart {}
+export interface AssetInventoryPluginStart {
+ getAssetInventoryPage: (assetInventoryStartDeps: AppPluginStartDependencies) => JSX.Element;
+}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface AppPluginStartDependencies {}
diff --git a/x-pack/solutions/security/plugins/asset_inventory/tsconfig.json b/x-pack/solutions/security/plugins/asset_inventory/tsconfig.json
index b733fc545be25..b4dd4bdb16a02 100644
--- a/x-pack/solutions/security/plugins/asset_inventory/tsconfig.json
+++ b/x-pack/solutions/security/plugins/asset_inventory/tsconfig.json
@@ -14,10 +14,5 @@
"../../../../../typings/**/*"
],
"exclude": ["target/**/*"],
- "kbn_references": [
- "@kbn/core",
- "@kbn/i18n-react",
- "@kbn/shared-ux-router",
- "@kbn/securitysolution-es-utils"
- ]
+ "kbn_references": ["@kbn/core", "@kbn/i18n-react", "@kbn/securitysolution-es-utils"]
}
diff --git a/x-pack/solutions/security/plugins/security_solution/common/constants.ts b/x-pack/solutions/security/plugins/security_solution/common/constants.ts
index 3818813d94a72..3339c97a61a6a 100644
--- a/x-pack/solutions/security/plugins/security_solution/common/constants.ts
+++ b/x-pack/solutions/security/plugins/security_solution/common/constants.ts
@@ -19,6 +19,7 @@ export { SecurityPageName } from '@kbn/security-solution-navigation';
*/
export const APP_ID = 'securitySolution' as const;
export const APP_UI_ID = 'securitySolutionUI' as const;
+export const ASSET_INVENTORY_FEATURE_ID = 'securitySolutionAssetInventory' as const;
export const ASSISTANT_FEATURE_ID = 'securitySolutionAssistant' as const;
export const ATTACK_DISCOVERY_FEATURE_ID = 'securitySolutionAttackDiscovery' as const;
export const CASES_FEATURE_ID = 'securitySolutionCasesV2' as const;
@@ -102,6 +103,7 @@ export const EXCEPTIONS_PATH = '/exceptions' as const;
export const EXCEPTION_LIST_DETAIL_PATH = `${EXCEPTIONS_PATH}/details/:detailName` as const;
export const HOSTS_PATH = '/hosts' as const;
export const ATTACK_DISCOVERY_PATH = '/attack_discovery' as const;
+export const ASSET_INVENTORY_PATH = '/asset_inventory' as const;
export const USERS_PATH = '/users' as const;
export const KUBERNETES_PATH = '/kubernetes' as const;
export const NETWORK_PATH = '/network' as const;
diff --git a/x-pack/solutions/security/plugins/security_solution/kibana.jsonc b/x-pack/solutions/security/plugins/security_solution/kibana.jsonc
index f672378c88df8..0ffd1922fd2ab 100644
--- a/x-pack/solutions/security/plugins/security_solution/kibana.jsonc
+++ b/x-pack/solutions/security/plugins/security_solution/kibana.jsonc
@@ -16,6 +16,7 @@
],
"requiredPlugins": [
"actions",
+ "assetInventory",
"alerting",
"cases",
"cloud",
diff --git a/x-pack/solutions/security/plugins/security_solution/public/app/solution_navigation/categories.ts b/x-pack/solutions/security/plugins/security_solution/public/app/solution_navigation/categories.ts
index 8d815ded5a3c4..5cfabe266eda8 100644
--- a/x-pack/solutions/security/plugins/security_solution/public/app/solution_navigation/categories.ts
+++ b/x-pack/solutions/security/plugins/security_solution/public/app/solution_navigation/categories.ts
@@ -37,6 +37,10 @@ export const CATEGORIES: Array> = [
SecurityPageName.exploreLanding,
],
},
+ {
+ type: LinkCategoryType.separator,
+ linkIds: [SecurityPageName.assetInventory],
+ },
{
type: LinkCategoryType.separator,
linkIds: [SecurityPageName.assets],
diff --git a/x-pack/solutions/security/plugins/security_solution/public/app/translations.ts b/x-pack/solutions/security/plugins/security_solution/public/app/translations.ts
index 1769a805f488f..79de4e62f0473 100644
--- a/x-pack/solutions/security/plugins/security_solution/public/app/translations.ts
+++ b/x-pack/solutions/security/plugins/security_solution/public/app/translations.ts
@@ -119,6 +119,10 @@ export const ATTACK_DISCOVERY = i18n.translate(
}
);
+export const INVENTORY = i18n.translate('xpack.securitySolution.navigation.inventory', {
+ defaultMessage: 'Inventory',
+});
+
export const TIMELINES = i18n.translate('xpack.securitySolution.navigation.timelines', {
defaultMessage: 'Timelines',
});
diff --git a/x-pack/solutions/security/plugins/security_solution/public/app_links.ts b/x-pack/solutions/security/plugins/security_solution/public/app_links.ts
index dca76b1c37f70..d70b96bbd8250 100644
--- a/x-pack/solutions/security/plugins/security_solution/public/app_links.ts
+++ b/x-pack/solutions/security/plugins/security_solution/public/app_links.ts
@@ -7,6 +7,7 @@
import type { CoreStart } from '@kbn/core/public';
import { links as attackDiscoveryLinks } from './attack_discovery/links';
+import { links as assetInventoryLinks } from './asset_inventory/links';
import type { AppLinkItems } from './common/links/types';
import { indicatorsLinks } from './threat_intelligence/links';
import { links as alertsLinks } from './detections/links';
@@ -32,6 +33,7 @@ export const appLinks: AppLinkItems = Object.freeze([
timelinesLinks,
indicatorsLinks,
exploreLinks,
+ assetInventoryLinks,
rulesLinks,
onboardingLinks,
managementLinks,
@@ -52,6 +54,7 @@ export const getFilteredLinks = async (
timelinesLinks,
indicatorsLinks,
exploreLinks,
+ assetInventoryLinks,
rulesLinks,
onboardingLinks,
managementFilteredLinks,
diff --git a/x-pack/solutions/security/plugins/security_solution/public/asset_inventory/index.ts b/x-pack/solutions/security/plugins/security_solution/public/asset_inventory/index.ts
new file mode 100644
index 0000000000000..78f27a3e42328
--- /dev/null
+++ b/x-pack/solutions/security/plugins/security_solution/public/asset_inventory/index.ts
@@ -0,0 +1,19 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import type { SecuritySubPlugin } from '../app/types';
+import { routes } from './routes';
+
+export class AssetInventory {
+ public setup() {}
+
+ public start(): SecuritySubPlugin {
+ return {
+ routes,
+ };
+ }
+}
diff --git a/x-pack/solutions/security/plugins/security_solution/public/asset_inventory/links.ts b/x-pack/solutions/security/plugins/security_solution/public/asset_inventory/links.ts
new file mode 100644
index 0000000000000..2eb5902006744
--- /dev/null
+++ b/x-pack/solutions/security/plugins/security_solution/public/asset_inventory/links.ts
@@ -0,0 +1,26 @@
+/*
+ * 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';
+
+import { INVENTORY } from '../app/translations';
+import { ASSET_INVENTORY_PATH, SecurityPageName, SERVER_APP_ID } from '../../common/constants';
+import type { LinkItem } from '../common/links/types';
+
+export const links: LinkItem = {
+ capabilities: [`${SERVER_APP_ID}.show`],
+ globalNavPosition: 10,
+ globalSearchKeywords: [
+ i18n.translate('xpack.securitySolution.appLinks.inventory', {
+ defaultMessage: 'Inventory',
+ }),
+ ],
+ experimentalKey: 'assetInventoryStoreEnabled',
+ id: SecurityPageName.assetInventory,
+ path: ASSET_INVENTORY_PATH,
+ title: INVENTORY,
+};
diff --git a/x-pack/solutions/security/plugins/security_solution/public/asset_inventory/pages/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/asset_inventory/pages/index.tsx
new file mode 100644
index 0000000000000..4f7a0f5947c88
--- /dev/null
+++ b/x-pack/solutions/security/plugins/security_solution/public/asset_inventory/pages/index.tsx
@@ -0,0 +1,25 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React from 'react';
+import { SecuritySolutionPageWrapper } from '../../common/components/page_wrapper';
+import { useKibana } from '../../common/lib/kibana';
+import { SecurityPageName } from '../../../common/constants';
+import { SpyRoute } from '../../common/utils/route/spy_routes';
+
+export const AssetInventoryContainer = React.memo(() => {
+ const { assetInventory } = useKibana().services;
+
+ return (
+
+ {assetInventory.getAssetInventoryPage({})}
+
+
+ );
+});
+
+AssetInventoryContainer.displayName = 'AssetInventoryContainer';
diff --git a/x-pack/solutions/security/plugins/security_solution/public/asset_inventory/routes.tsx b/x-pack/solutions/security/plugins/security_solution/public/asset_inventory/routes.tsx
new file mode 100644
index 0000000000000..5707d859d844e
--- /dev/null
+++ b/x-pack/solutions/security/plugins/security_solution/public/asset_inventory/routes.tsx
@@ -0,0 +1,30 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React from 'react';
+import type { SecuritySubPluginRoutes } from '../app/types';
+import { SecurityPageName } from '../app/types';
+import { ASSET_INVENTORY_PATH } from '../../common/constants';
+import { PluginTemplateWrapper } from '../common/components/plugin_template_wrapper';
+import { SecurityRoutePageWrapper } from '../common/components/security_route_page_wrapper';
+import { ExperimentalFeaturesService } from '../common/experimental_features_service';
+import { AssetInventoryContainer } from './pages';
+
+export const AssetInventoryRoutes = () => (
+
+
+
+
+
+);
+
+export const routes: SecuritySubPluginRoutes = [
+ {
+ path: ExperimentalFeaturesService.get().assetInventoryStoreEnabled ? ASSET_INVENTORY_PATH : [],
+ component: AssetInventoryRoutes,
+ },
+];
diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/navigation/security_side_nav/categories.ts b/x-pack/solutions/security/plugins/security_solution/public/common/components/navigation/security_side_nav/categories.ts
index cc695d72a8ffc..49f0601dc11c6 100644
--- a/x-pack/solutions/security/plugins/security_solution/public/common/components/navigation/security_side_nav/categories.ts
+++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/navigation/security_side_nav/categories.ts
@@ -31,4 +31,8 @@ export const CATEGORIES: SeparatorLinkCategory[] = [
SecurityPageName.exploreLanding,
],
},
+ {
+ type: LinkCategoryType.separator,
+ linkIds: [SecurityPageName.assetInventory],
+ },
];
diff --git a/x-pack/solutions/security/plugins/security_solution/public/lazy_sub_plugins.tsx b/x-pack/solutions/security/plugins/security_solution/public/lazy_sub_plugins.tsx
index 1be423c988397..a399f25fb8bda 100644
--- a/x-pack/solutions/security/plugins/security_solution/public/lazy_sub_plugins.tsx
+++ b/x-pack/solutions/security/plugins/security_solution/public/lazy_sub_plugins.tsx
@@ -10,6 +10,7 @@
* By loading these later we can reduce the initial bundle size and allow users to delay loading these dependencies until they are needed.
*/
+import { AssetInventory } from './asset_inventory';
import { AttackDiscovery } from './attack_discovery';
import { Cases } from './cases';
import { Detections } from './detections';
@@ -35,6 +36,7 @@ import { SiemMigrations } from './siem_migrations';
* The classes used to instantiate the sub plugins. These are grouped into a single object for the sake of bundling them in a single dynamic import.
*/
const subPluginClasses = {
+ AssetInventory,
AttackDiscovery,
Detections,
Cases,
diff --git a/x-pack/solutions/security/plugins/security_solution/public/management/links.ts b/x-pack/solutions/security/plugins/security_solution/public/management/links.ts
index 49049218d4dc1..909395df8df4f 100644
--- a/x-pack/solutions/security/plugins/security_solution/public/management/links.ts
+++ b/x-pack/solutions/security/plugins/security_solution/public/management/links.ts
@@ -99,7 +99,7 @@ export const links: LinkItem = {
path: MANAGE_PATH,
skipUrlState: true,
hideTimeline: true,
- globalNavPosition: 10,
+ globalNavPosition: 11,
capabilities: [`${SERVER_APP_ID}.show`],
globalSearchKeywords: [
i18n.translate('xpack.securitySolution.appLinks.manage', {
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 497b92637dad5..64146d5b587e4 100644
--- a/x-pack/solutions/security/plugins/security_solution/public/plugin.tsx
+++ b/x-pack/solutions/security/plugins/security_solution/public/plugin.tsx
@@ -288,6 +288,7 @@ export class Plugin implements IPlugin;
alerts: Awaited>;
+ assetInventory: Awaited>;
attackDiscovery: ReturnType;
cloudDefend: ReturnType;
cloudSecurityPosture: ReturnType;
diff --git a/x-pack/solutions/security/plugins/security_solution/tsconfig.json b/x-pack/solutions/security/plugins/security_solution/tsconfig.json
index c6f5b8ac09166..655fe3a489694 100644
--- a/x-pack/solutions/security/plugins/security_solution/tsconfig.json
+++ b/x-pack/solutions/security/plugins/security_solution/tsconfig.json
@@ -215,6 +215,7 @@
"@kbn/cbor",
"@kbn/zod",
"@kbn/cloud-security-posture",
+ "@kbn/asset-inventory-plugin",
"@kbn/security-solution-distribution-bar",
"@kbn/cloud-security-posture-common",
"@kbn/cloud-security-posture-graph",