mirror of
https://github.com/elastic/kibana.git
synced 2025-04-19 15:35:00 -04:00
[SecuritySolution] Bootstrap Initial Privileges User Monitoring Onboarding Workflow (#217180)
## Summary Bootstrap the initial page structure for Privileges User Monitoring Onboarding Workflow ### What's included * Create Entity Analytics Page * Create Privileged User Monitoring Page * Add the pages to the SecuritySolution and the global menu * Hide the page when the experimental flag is disabled `privilegeMonitoringEnabled` ### What's not included * The content of the Entity Analytics and Privileged User Monitoring pages ### Answered Questions * The path `entity_analytics` has already been taken. I chose `entity_analytics_landing` * Should the link show up on the global EA page? Yes * Navigation Menu for ESS? Good for now * Which permission/capabilities are required? Same as risk engine ### How to test it? * You only need to run Kibana and check if the navigation item is in the menu * The page should show up on the global nav * The page should show up on the global search bar * Visibility constraints * It should be hidden when `privilegeMonitoringEnabled` is not enabled * It should be visible when the user has access to the entity analytics feature * It should be visible for platinum users ### Checklist - [x] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/main/src/platform/packages/shared/kbn-i18n/README.md) - [x] The PR description includes the appropriate Release Notes section, and the correct `release_note:*` label is applied per the [guidelines](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)
This commit is contained in:
parent
f3042efa8f
commit
47090f198e
18 changed files with 267 additions and 3 deletions
|
@ -80,9 +80,11 @@ export enum SecurityPageName {
|
|||
usersAuthentications = 'users-authentications',
|
||||
usersEvents = 'users-events',
|
||||
usersRisk = 'users-risk',
|
||||
entityAnalytics = 'entity_analytics',
|
||||
entityAnalytics = 'entity_analytics', // This is the first Entity Analytics page, that is why the name is too generic.
|
||||
entityAnalyticsManagement = 'entity_analytics-management',
|
||||
entityAnalyticsAssetClassification = 'entity_analytics-asset-classification',
|
||||
entityAnalyticsLanding = 'entity_analytics-landing',
|
||||
privilegedUserMonitoring = 'entity_analytics-privileged_user_monitoring',
|
||||
entityAnalyticsEntityStoreManagement = 'entity_analytics-entity_store_management',
|
||||
coverageOverview = 'coverage-overview',
|
||||
notes = 'notes',
|
||||
|
|
|
@ -153,6 +153,11 @@ export const i18nStrings = {
|
|||
entityStore: i18n.translate('securitySolutionPackages.navLinks.entityStore', {
|
||||
defaultMessage: 'Entity Store',
|
||||
}),
|
||||
entityAnalytics: {
|
||||
landing: i18n.translate('securitySolutionPackages.navLinks.entityAnalytics', {
|
||||
defaultMessage: 'Entity Analytics',
|
||||
}),
|
||||
},
|
||||
devTools: i18n.translate('securitySolutionPackages.navLinks.devTools', {
|
||||
defaultMessage: 'Developer tools',
|
||||
}),
|
||||
|
|
|
@ -129,6 +129,9 @@ export const ENTITY_ANALYTICS_ASSET_CRITICALITY_PATH =
|
|||
`/entity_analytics_asset_criticality` as const;
|
||||
export const ENTITY_ANALYTICS_ENTITY_STORE_MANAGEMENT_PATH =
|
||||
`/entity_analytics_entity_store` as const;
|
||||
export const ENTITY_ANALYTICS_LANDING_PATH = '/entity_analytics_landing' as const;
|
||||
export const ENTITY_ANALYTICS_PRIVILEGED_USER_MONITORING_PATH =
|
||||
'/entity_analytics_privileged_user_monitoring' as const;
|
||||
export const APP_ALERTS_PATH = `${APP_PATH}${ALERTS_PATH}` as const;
|
||||
export const APP_CASES_PATH = `${APP_PATH}${CASES_PATH}` as const;
|
||||
export const APP_ENDPOINTS_PATH = `${APP_PATH}${ENDPOINTS_PATH}` as const;
|
||||
|
|
|
@ -37,6 +37,10 @@ export const CATEGORIES: Array<SeparatorLinkCategory<SolutionPageName>> = [
|
|||
SecurityPageName.exploreLanding,
|
||||
],
|
||||
},
|
||||
{
|
||||
type: LinkCategoryType.separator,
|
||||
linkIds: [SecurityPageName.entityAnalyticsLanding],
|
||||
},
|
||||
{
|
||||
type: LinkCategoryType.separator,
|
||||
linkIds: [SecurityPageName.assetInventory],
|
||||
|
|
|
@ -54,6 +54,13 @@ export const ENTITY_ANALYTICS = i18n.translate(
|
|||
}
|
||||
);
|
||||
|
||||
export const ENTITY_ANALYTICS_PRIVILEGED_USER_MONITORING = i18n.translate(
|
||||
'xpack.securitySolution.navigation.privilegedUserMonitoring',
|
||||
{
|
||||
defaultMessage: 'Privileged User Monitoring',
|
||||
}
|
||||
);
|
||||
|
||||
export const HOSTS = i18n.translate('xpack.securitySolution.navigation.hosts', {
|
||||
defaultMessage: 'Hosts',
|
||||
});
|
||||
|
|
|
@ -21,6 +21,7 @@ import { onboardingLinks } from './onboarding/links';
|
|||
import { findingsLinks } from './cloud_security_posture/links';
|
||||
import type { StartPlugins } from './types';
|
||||
import { dashboardsLinks } from './dashboards/links';
|
||||
import { entityAnalyticsLinks } from './entity_analytics/links';
|
||||
|
||||
// TODO: remove after rollout https://github.com/elastic/kibana/issues/179572
|
||||
export { solutionAppLinksSwitcher } from './app/solution_navigation/links/app_links';
|
||||
|
@ -36,6 +37,7 @@ export const appLinks: AppLinkItems = Object.freeze([
|
|||
timelinesLinks,
|
||||
indicatorsLinks,
|
||||
exploreLinks,
|
||||
entityAnalyticsLinks,
|
||||
assetInventoryLinks,
|
||||
rulesLinks,
|
||||
onboardingLinks,
|
||||
|
@ -59,6 +61,7 @@ export const getFilteredLinks = async (
|
|||
timelinesLinks,
|
||||
indicatorsLinks,
|
||||
exploreLinks,
|
||||
entityAnalyticsLinks,
|
||||
assetInventoryLinks,
|
||||
rulesLinks,
|
||||
onboardingLinks,
|
||||
|
|
|
@ -18,7 +18,7 @@ import type { LinkItem } from '../common/links/types';
|
|||
|
||||
export const links: LinkItem = {
|
||||
capabilities: [`${SECURITY_FEATURE_ID}.show`],
|
||||
globalNavPosition: 10,
|
||||
globalNavPosition: 11,
|
||||
globalSearchKeywords: [
|
||||
i18n.translate('xpack.securitySolution.appLinks.inventory', {
|
||||
defaultMessage: 'Inventory',
|
||||
|
|
|
@ -31,6 +31,10 @@ export const CATEGORIES: SeparatorLinkCategory[] = [
|
|||
SecurityPageName.exploreLanding,
|
||||
],
|
||||
},
|
||||
{
|
||||
type: LinkCategoryType.separator,
|
||||
linkIds: [SecurityPageName.entityAnalyticsLanding],
|
||||
},
|
||||
{
|
||||
type: LinkCategoryType.separator,
|
||||
linkIds: [SecurityPageName.assetInventory],
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 6.8 KiB |
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* 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 {
|
||||
SecurityPageName,
|
||||
SECURITY_FEATURE_ID,
|
||||
ENTITY_ANALYTICS_LANDING_PATH,
|
||||
ENTITY_ANALYTICS_PRIVILEGED_USER_MONITORING_PATH,
|
||||
} from '../../common/constants';
|
||||
import type { LinkItem } from '../common/links/types';
|
||||
import { ENTITY_ANALYTICS, ENTITY_ANALYTICS_PRIVILEGED_USER_MONITORING } from '../app/translations';
|
||||
import privilegedUserMonitoringPageImg from '../common/images/privileged_user_monitoring_page.png';
|
||||
|
||||
const privMonLinks: LinkItem = {
|
||||
id: SecurityPageName.privilegedUserMonitoring,
|
||||
title: ENTITY_ANALYTICS_PRIVILEGED_USER_MONITORING,
|
||||
landingImage: privilegedUserMonitoringPageImg,
|
||||
description: i18n.translate(
|
||||
'xpack.securitySolution.appLinks.privilegedUserMonitoring.Description',
|
||||
{
|
||||
defaultMessage: '???????????????????', // TODO
|
||||
}
|
||||
),
|
||||
path: ENTITY_ANALYTICS_PRIVILEGED_USER_MONITORING_PATH,
|
||||
globalSearchKeywords: [
|
||||
i18n.translate('xpack.securitySolution.appLinks.privilegedUserMonitoring', {
|
||||
defaultMessage: 'Privileged User Monitoring',
|
||||
}),
|
||||
],
|
||||
experimentalKey: 'privilegeMonitoringEnabled',
|
||||
hideTimeline: true,
|
||||
skipUrlState: true,
|
||||
capabilities: [`${SECURITY_FEATURE_ID}.entity-analytics`],
|
||||
licenseType: 'platinum',
|
||||
};
|
||||
|
||||
export const entityAnalyticsLinks: LinkItem = {
|
||||
id: SecurityPageName.entityAnalyticsLanding,
|
||||
title: ENTITY_ANALYTICS,
|
||||
path: ENTITY_ANALYTICS_LANDING_PATH,
|
||||
globalNavPosition: 10,
|
||||
globalSearchKeywords: [
|
||||
i18n.translate('xpack.securitySolution.appLinks.entityAnalytics.landing', {
|
||||
defaultMessage: 'Entity Analytics',
|
||||
}),
|
||||
],
|
||||
links: [privMonLinks],
|
||||
hideTimeline: true,
|
||||
skipUrlState: true,
|
||||
experimentalKey: 'privilegeMonitoringEnabled',
|
||||
capabilities: [`${SECURITY_FEATURE_ID}.entity-analytics`],
|
||||
licenseType: 'platinum',
|
||||
};
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* 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 { i18n } from '@kbn/i18n';
|
||||
import { LandingLinksImages } from '@kbn/security-solution-navigation/landing_links';
|
||||
import { SecurityPageName } from '../../app/types';
|
||||
import { HeaderPage } from '../../common/components/header_page';
|
||||
import { useRootNavLink } from '../../common/links/nav_links';
|
||||
import { SecuritySolutionPageWrapper } from '../../common/components/page_wrapper';
|
||||
import { SpyRoute } from '../../common/utils/route/spy_routes';
|
||||
import { trackLandingLinkClick } from '../../common/lib/telemetry/trackers';
|
||||
import { useGlobalQueryString } from '../../common/utils/global_query_string';
|
||||
|
||||
const PAGE_TITLE = i18n.translate('xpack.securitySolution.entityAnalytics.landing.pageTitle', {
|
||||
defaultMessage: 'Entity Analytics',
|
||||
});
|
||||
|
||||
export const EntityAnalyticsLandingPage = () => {
|
||||
const { links = [] } = useRootNavLink(SecurityPageName.entityAnalyticsLanding) ?? {};
|
||||
const urlState = useGlobalQueryString();
|
||||
|
||||
return (
|
||||
<SecuritySolutionPageWrapper>
|
||||
<HeaderPage title={PAGE_TITLE} />
|
||||
<LandingLinksImages items={links} urlState={urlState} onLinkClick={trackLandingLinkClick} />
|
||||
<SpyRoute pageName={SecurityPageName.entityAnalyticsLanding} />
|
||||
</SecuritySolutionPageWrapper>
|
||||
);
|
||||
};
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* 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 { i18n } from '@kbn/i18n';
|
||||
import { SecurityPageName } from '../../app/types';
|
||||
import { HeaderPage } from '../../common/components/header_page';
|
||||
import { SecuritySolutionPageWrapper } from '../../common/components/page_wrapper';
|
||||
import { SpyRoute } from '../../common/utils/route/spy_routes';
|
||||
|
||||
const PAGE_TITLE = i18n.translate(
|
||||
'xpack.securitySolution.entityAnalytics.privilegedUserMonitoring.pageTitle',
|
||||
{
|
||||
defaultMessage: 'Privileged User Monitoring',
|
||||
}
|
||||
);
|
||||
|
||||
export const EntityAnalyticsPrivilegedUserMonitoringPage = () => {
|
||||
return (
|
||||
<SecuritySolutionPageWrapper>
|
||||
<HeaderPage title={PAGE_TITLE} />
|
||||
<SpyRoute pageName={SecurityPageName.privilegedUserMonitoring} />
|
||||
</SecuritySolutionPageWrapper>
|
||||
);
|
||||
};
|
|
@ -15,12 +15,16 @@ import { NotFoundPage } from '../app/404';
|
|||
import {
|
||||
ENTITY_ANALYTICS_ASSET_CRITICALITY_PATH,
|
||||
ENTITY_ANALYTICS_ENTITY_STORE_MANAGEMENT_PATH,
|
||||
ENTITY_ANALYTICS_LANDING_PATH,
|
||||
ENTITY_ANALYTICS_MANAGEMENT_PATH,
|
||||
ENTITY_ANALYTICS_PRIVILEGED_USER_MONITORING_PATH,
|
||||
SecurityPageName,
|
||||
} from '../../common/constants';
|
||||
import { EntityAnalyticsManagementPage } from './pages/entity_analytics_management_page';
|
||||
import { PluginTemplateWrapper } from '../common/components/plugin_template_wrapper';
|
||||
import { EntityStoreManagementPage } from './pages/entity_store_management_page';
|
||||
import { EntityAnalyticsLandingPage } from './pages/entity_analytics_landing';
|
||||
import { EntityAnalyticsPrivilegedUserMonitoringPage } from './pages/entity_analytics_privileged_user_monitoring_page';
|
||||
|
||||
const EntityAnalyticsManagementTelemetry = () => (
|
||||
<PluginTemplateWrapper>
|
||||
|
@ -94,6 +98,55 @@ const EntityAnalyticsEntityStoreContainer: React.FC = React.memo(() => {
|
|||
|
||||
EntityAnalyticsEntityStoreContainer.displayName = 'EntityAnalyticsEntityStoreContainer';
|
||||
|
||||
const EntityAnalyticsLandingTelemetry = () => (
|
||||
<PluginTemplateWrapper>
|
||||
<TrackApplicationView viewId={SecurityPageName.entityAnalyticsLanding}>
|
||||
<EntityAnalyticsLandingPage />
|
||||
<SpyRoute pageName={SecurityPageName.entityAnalyticsLanding} />
|
||||
</TrackApplicationView>
|
||||
</PluginTemplateWrapper>
|
||||
);
|
||||
|
||||
const EntityAnalyticsLandingContainer: React.FC = React.memo(() => {
|
||||
return (
|
||||
<Routes>
|
||||
<Route
|
||||
path={ENTITY_ANALYTICS_LANDING_PATH}
|
||||
exact
|
||||
component={EntityAnalyticsLandingTelemetry}
|
||||
/>
|
||||
<Route component={NotFoundPage} />
|
||||
</Routes>
|
||||
);
|
||||
});
|
||||
|
||||
EntityAnalyticsLandingContainer.displayName = 'EntityAnalyticsLandingContainer';
|
||||
|
||||
const EntityAnalyticsPrivilegedUserMonitoringTelemetry = () => (
|
||||
<PluginTemplateWrapper>
|
||||
<TrackApplicationView viewId={SecurityPageName.privilegedUserMonitoring}>
|
||||
<EntityAnalyticsPrivilegedUserMonitoringPage />
|
||||
<SpyRoute pageName={SecurityPageName.privilegedUserMonitoring} />
|
||||
</TrackApplicationView>
|
||||
</PluginTemplateWrapper>
|
||||
);
|
||||
|
||||
const EntityAnalyticsPrivilegedUserMonitoringContainer: React.FC = React.memo(() => {
|
||||
return (
|
||||
<Routes>
|
||||
<Route
|
||||
path={ENTITY_ANALYTICS_PRIVILEGED_USER_MONITORING_PATH}
|
||||
exact
|
||||
component={EntityAnalyticsPrivilegedUserMonitoringTelemetry}
|
||||
/>
|
||||
<Route component={NotFoundPage} />
|
||||
</Routes>
|
||||
);
|
||||
});
|
||||
|
||||
EntityAnalyticsPrivilegedUserMonitoringContainer.displayName =
|
||||
'EntityAnalyticsPrivilegedUserMonitoringContainer';
|
||||
|
||||
export const routes = [
|
||||
{
|
||||
path: ENTITY_ANALYTICS_MANAGEMENT_PATH,
|
||||
|
@ -107,4 +160,12 @@ export const routes = [
|
|||
path: ENTITY_ANALYTICS_ENTITY_STORE_MANAGEMENT_PATH,
|
||||
component: EntityAnalyticsEntityStoreContainer,
|
||||
},
|
||||
{
|
||||
path: ENTITY_ANALYTICS_LANDING_PATH,
|
||||
component: EntityAnalyticsLandingContainer,
|
||||
},
|
||||
{
|
||||
path: ENTITY_ANALYTICS_PRIVILEGED_USER_MONITORING_PATH,
|
||||
component: EntityAnalyticsPrivilegedUserMonitoringContainer,
|
||||
},
|
||||
];
|
||||
|
|
|
@ -92,7 +92,7 @@ export const links: LinkItem = {
|
|||
path: MANAGE_PATH,
|
||||
skipUrlState: true,
|
||||
hideTimeline: true,
|
||||
globalNavPosition: 11,
|
||||
globalNavPosition: 12,
|
||||
capabilities: [`${SECURITY_FEATURE_ID}.show`],
|
||||
globalSearchKeywords: [
|
||||
i18n.translate('xpack.securitySolution.appLinks.manage', {
|
||||
|
|
|
@ -374,6 +374,20 @@ Object {
|
|||
},
|
||||
],
|
||||
},
|
||||
Object {
|
||||
"children": Array [
|
||||
Object {
|
||||
"id": "entity_analytics-privileged_user_monitoring",
|
||||
"link": "securitySolutionUI:entity_analytics-privileged_user_monitoring",
|
||||
"renderAs": "item",
|
||||
},
|
||||
],
|
||||
"id": "entity_analytics-landing",
|
||||
"link": "securitySolutionUI:entity_analytics-landing",
|
||||
"renderAs": "panelOpener",
|
||||
"spaceBefore": null,
|
||||
"title": "Entity Analytics",
|
||||
},
|
||||
Object {
|
||||
"breadcrumbStatus": "hidden",
|
||||
"children": Array [
|
||||
|
|
|
@ -438,6 +438,20 @@ const createNavigationTree$ = (services: Services): Rx.Observable<NavigationTree
|
|||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'entity_analytics-landing',
|
||||
link: securityLink(SecurityPageName.entityAnalyticsLanding),
|
||||
title: i18nStrings.entityAnalytics.landing,
|
||||
spaceBefore: null,
|
||||
children: [
|
||||
{
|
||||
id: 'entity_analytics-privileged_user_monitoring',
|
||||
link: securityLink(SecurityPageName.privilegedUserMonitoring),
|
||||
renderAs: 'item',
|
||||
},
|
||||
],
|
||||
renderAs: 'panelOpener',
|
||||
},
|
||||
{
|
||||
breadcrumbStatus: 'hidden',
|
||||
children: [
|
||||
|
|
|
@ -360,6 +360,20 @@ Object {
|
|||
"renderAs": "panelOpener",
|
||||
"title": "Assets",
|
||||
},
|
||||
Object {
|
||||
"children": Array [
|
||||
Object {
|
||||
"id": "entity_analytics-privileged_user_monitoring",
|
||||
"link": "securitySolutionUI:entity_analytics-privileged_user_monitoring",
|
||||
"renderAs": "item",
|
||||
},
|
||||
],
|
||||
"id": "entity_analytics-landing",
|
||||
"link": "securitySolutionUI:entity_analytics-landing",
|
||||
"renderAs": "panelOpener",
|
||||
"spaceBefore": null,
|
||||
"title": "Entity Analytics",
|
||||
},
|
||||
Object {
|
||||
"children": Array [
|
||||
Object {
|
||||
|
|
|
@ -416,6 +416,20 @@ export const createSecurityNavigationTree$ = (
|
|||
],
|
||||
renderAs: 'panelOpener',
|
||||
},
|
||||
{
|
||||
id: 'entity_analytics-landing',
|
||||
link: securityLink(SecurityPageName.entityAnalyticsLanding),
|
||||
title: i18nStrings.entityAnalytics.landing,
|
||||
spaceBefore: null,
|
||||
children: [
|
||||
{
|
||||
id: 'entity_analytics-privileged_user_monitoring',
|
||||
link: securityLink(SecurityPageName.privilegedUserMonitoring),
|
||||
renderAs: 'item',
|
||||
},
|
||||
],
|
||||
renderAs: 'panelOpener',
|
||||
},
|
||||
createMachineLearningNavigationTree(),
|
||||
{
|
||||
id: 'entity_analytics-management',
|
||||
|
|
Loading…
Add table
Reference in a new issue