Skip to content

Commit

Permalink
Create Entity Analytics dashboard (#137688)
Browse files Browse the repository at this point in the history
* Create Entity analytics page

* Add Hosts risk dashboard to Entity analytics page

* Add entity analytics to the old menu

* Add entity analytics dashboard header

* Add User risk dashboard to Entity analytics

* Add entityAnalyticsDashoardEnabled feature flag

* Move useEnableHostRiskFromUrl to a shared folder

* Upgrade Entity analytics license to platinum

* Add ml permission check for entity analytics dashboard old menu

Co-authored-by: Kibana Machine <[email protected]>
  • Loading branch information
machadoum and kibanamachine authored Aug 25, 2022
1 parent acf675c commit bbcadf1
Show file tree
Hide file tree
Showing 51 changed files with 2,061 additions and 41 deletions.
4 changes: 3 additions & 1 deletion x-pack/plugins/security_solution/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ export enum SecurityPageName {
usersAuthentications = 'users-authentications',
usersEvents = 'users-events',
usersRisk = 'users-risk',
entityAnalytics = 'entity-analytics',
}

export const EXPLORE_PATH = '/explore' as const;
Expand Down Expand Up @@ -159,7 +160,7 @@ export const HOST_ISOLATION_EXCEPTIONS_PATH =
`${MANAGEMENT_PATH}/host_isolation_exceptions` as const;
export const BLOCKLIST_PATH = `${MANAGEMENT_PATH}/blocklist` as const;
export const RESPONSE_ACTIONS_PATH = `${MANAGEMENT_PATH}/response_actions` as const;

export const ENTITY_ANALYTICS_PATH = '/entity_analytics' as const;
export const APP_OVERVIEW_PATH = `${APP_PATH}${OVERVIEW_PATH}` as const;
export const APP_LANDING_PATH = `${APP_PATH}${LANDING_PATH}` as const;
export const APP_DETECTION_RESPONSE_PATH = `${APP_PATH}${DETECTION_RESPONSE_PATH}` as const;
Expand All @@ -183,6 +184,7 @@ export const APP_HOST_ISOLATION_EXCEPTIONS_PATH =
`${APP_PATH}${HOST_ISOLATION_EXCEPTIONS_PATH}` as const;
export const APP_BLOCKLIST_PATH = `${APP_PATH}${BLOCKLIST_PATH}` as const;
export const APP_RESPONSE_ACTIONS_PATH = `${APP_PATH}${RESPONSE_ACTIONS_PATH}` as const;
export const APP_ENTITY_ANALYTICS_PATH = `${APP_PATH}${ENTITY_ANALYTICS_PATH}` as const;

// cloud logs to exclude from default index pattern
export const EXCLUDE_ELASTIC_CLOUD_INDICES = ['-*elastic-cloud-logs-*'];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export const allowedExperimentalValues = Object.freeze({
policyListEnabled: true,
policyResponseInFleetEnabled: true,
threatIntelligenceEnabled: false,
entityAnalyticsDashboardEnabled: false,

/**
* This is used for enabling the end-to-end tests for the security_solution telemetry.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
/*
* 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 { login, visit } from '../../tasks/login';

import { ENTITY_ANALYTICS_URL } from '../../urls/navigation';

import { esArchiverLoad, esArchiverUnload } from '../../tasks/es_archiver';
import { cleanKibana } from '../../tasks/common';
import {
ENABLE_HOST_RISK_SCORE_BUTTON,
ENABLE_USER_RISK_SCORE_BUTTON,
HOSTS_DONUT_CHART,
HOSTS_TABLE,
TABLE_ROWS,
USERS_DONUT_CHART,
USERS_TABLE,
} from '../../screens/entity_analytics';
import { openRiskTableFilterAndSelectTheLowOption } from '../../tasks/host_risk';

describe('Entity Analytics Dashboard', () => {
before(() => {
cleanKibana();
login();
});

describe('Without data', () => {
before(() => {
visit(ENTITY_ANALYTICS_URL);
});

it('shows enable host risk button', () => {
cy.get(ENABLE_HOST_RISK_SCORE_BUTTON).should('be.visible');
});

it('shows enable user risk button', () => {
cy.get(ENABLE_USER_RISK_SCORE_BUTTON).should('be.visible');
});
});

describe('With host risk data', () => {
before(() => {
esArchiverLoad('risky_hosts');
visit(ENTITY_ANALYTICS_URL);
});

after(() => {
esArchiverUnload('risky_hosts');
});

it('renders donut chart', () => {
cy.get(HOSTS_DONUT_CHART).should('include.text', '6Total');
});

it('renders table', () => {
cy.get(HOSTS_TABLE).should('be.visible');
cy.get(TABLE_ROWS).should('have.length', 5);
});

it('filters by risk classification', () => {
openRiskTableFilterAndSelectTheLowOption();

cy.get(HOSTS_DONUT_CHART).should('include.text', '1Total');
cy.get(TABLE_ROWS).should('have.length', 1);
});
});

describe('With user risk data', () => {
before(() => {
esArchiverLoad('risky_users');
visit(ENTITY_ANALYTICS_URL);
});

after(() => {
esArchiverUnload('risky_users');
});

it('renders donut chart', () => {
cy.get(USERS_DONUT_CHART).should('include.text', '6Total');
});

it('renders table', () => {
cy.get(USERS_TABLE).should('be.visible');
cy.get(TABLE_ROWS).should('have.length', 5);
});

it('filters by risk classification', () => {
openRiskTableFilterAndSelectTheLowOption();

cy.get(USERS_DONUT_CHART).should('include.text', '1Total');
cy.get(TABLE_ROWS).should('have.length', 1);
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import {
POLICIES,
EXPLORE,
MANAGE,
ENTITY_ANALYTICS,
} from '../../screens/security_header';

import { login, visit } from '../../tasks/login';
Expand Down Expand Up @@ -58,6 +59,7 @@ import {
CSP_BENCHMARKS_URL,
CSP_FINDINGS_URL,
POLICIES_URL,
ENTITY_ANALYTICS_URL,
INDICATORS_URL,
} from '../../urls/navigation';
import {
Expand Down Expand Up @@ -99,6 +101,11 @@ describe('top-level navigation common to all pages in the Security app', () => {
cy.url().should('include', DETECTION_RESPONSE_URL);
});

it('navigates to the Entity Analytics page', () => {
navigateFromHeaderTo(ENTITY_ANALYTICS);
cy.url().should('include', ENTITY_ANALYTICS_URL);
});

it('navigates to the Kubernetes page', () => {
navigateFromHeaderTo(KUBERNETES);
cy.url().should('include', KUBERNETES_URL);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* 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.
*/

export const ENABLE_HOST_RISK_SCORE_BUTTON = '[data-test-subj="enable_host_risk_score"]';

export const HOSTS_DONUT_CHART =
'[data-test-subj="entity_analytics_hosts"] [data-test-subj="donut-chart"]';

export const HOSTS_TABLE = '[data-test-subj="entity_analytics_hosts"] #hostRiskDashboardTable';

export const TABLE_ROWS = '.euiTableRow';

export const USERS_DONUT_CHART =
'[data-test-subj="entity_analytics_users"] [data-test-subj="donut-chart"]';

export const USERS_TABLE = '[data-test-subj="entity_analytics_users"] #userRiskDashboardTable';

export const ENABLE_USER_RISK_SCORE_BUTTON = '[data-test-subj="enable_user_risk_score"]';
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ export const HOST_BY_RISK_TABLE_FILTER = '[data-test-subj="risk-filter-button"]'

export const HOST_BY_RISK_TABLE_FILTER_CRITICAL = '[data-test-subj="risk-filter-item-Critical"]';

export const HOST_BY_RISK_TABLE_FILTER_LOW = '[data-test-subj="risk-filter-item-Low"]';

export const HOST_BY_RISK_TABLE_PERPAGE_BUTTON =
'[data-test-subj="loadingMoreSizeRowPopover"] button';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ export const OVERVIEW = '[data-test-subj="groupedNavPanelLink-overview"]';

export const DETECTION_RESPONSE = '[data-test-subj="groupedNavPanelLink-detection_response"]';

export const ENTITY_ANALYTICS = '[data-test-subj="groupedNavPanelLink-entity-analytics"]';

export const KUBERNETES = '[data-test-subj="groupedNavPanelLink-kubernetes"]';

export const CSP_DASHBOARD =
Expand Down Expand Up @@ -71,6 +73,7 @@ export const openNavigationPanelFor = (page: string) => {
case OVERVIEW:
case DETECTION_RESPONSE:
case KUBERNETES:
case ENTITY_ANALYTICS:
case CSP_DASHBOARD: {
panel = DASHBOARDS;
break;
Expand Down
8 changes: 8 additions & 0 deletions x-pack/plugins/security_solution/cypress/tasks/host_risk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import {
HOST_BY_RISK_TABLE_FILTER,
HOST_BY_RISK_TABLE_FILTER_CRITICAL,
HOST_BY_RISK_TABLE_FILTER_LOW,
HOST_BY_RISK_TABLE_PERPAGE_BUTTON,
HOST_BY_RISK_TABLE_PERPAGE_OPTIONS,
LOADING_SPINNER,
Expand All @@ -23,9 +24,16 @@ export const openRiskTableFilterAndSelectTheCriticalOption = () => {
cy.get(HOST_BY_RISK_TABLE_FILTER).click();
cy.get(HOST_BY_RISK_TABLE_FILTER_CRITICAL).click();
};

export const openRiskTableFilterAndSelectTheLowOption = () => {
cy.get(HOST_BY_RISK_TABLE_FILTER).click();
cy.get(HOST_BY_RISK_TABLE_FILTER_LOW).click();
};

export const removeCritialFilter = () => {
cy.get(HOST_BY_RISK_TABLE_FILTER_CRITICAL).click();
};

export const selectFiveItemsPerPageOption = () => {
cy.get(HOST_BY_RISK_TABLE_PERPAGE_BUTTON).click();
cy.get(HOST_BY_RISK_TABLE_PERPAGE_OPTIONS).first().click();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export const NETWORK_URL = '/app/security/network';
export const OVERVIEW_URL = '/app/security/overview';
export const DASHBOARDS_URL = '/app/security/dashboards';
export const DETECTION_RESPONSE_URL = '/app/security/detection_response';
export const ENTITY_ANALYTICS_URL = '/app/security/entity_analytics';
export const KUBERNETES_URL = '/app/security/kubernetes';
export const CSP_DASHBOARD_URL = '/app/security/cloud_security_posture/dashboard';
export const INDICATORS_URL = '/app/security/threat_intelligence/indicators';
Expand Down
15 changes: 15 additions & 0 deletions x-pack/plugins/security_solution/public/app/deep_links/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import {
OVERVIEW,
POLICIES,
RESPONSE_ACTIONS,
ENTITY_ANALYTICS,
RULES,
TIMELINES,
TRUSTED_APPLICATIONS,
Expand All @@ -65,6 +66,7 @@ import {
OVERVIEW_PATH,
POLICIES_PATH,
RESPONSE_ACTIONS_PATH,
ENTITY_ANALYTICS_PATH,
RULES_CREATE_PATH,
RULES_PATH,
SERVER_APP_ID,
Expand Down Expand Up @@ -166,6 +168,19 @@ export const securitySolutionsDeepLinks: SecuritySolutionDeepLink[] = [
...getSecuritySolutionLink<SecurityPageName>('dashboard'),
features: [FEATURE.general],
},
{
id: SecurityPageName.entityAnalytics,
title: ENTITY_ANALYTICS,
path: ENTITY_ANALYTICS_PATH,
features: [FEATURE.general],
experimentalKey: 'entityAnalyticsDashboardEnabled',
isPremium: true,
keywords: [
i18n.translate('xpack.securitySolution.search.entityAnalytics', {
defaultMessage: 'Entity Analytics',
}),
],
},
],
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import {
APP_KUBERNETES_PATH,
APP_LANDING_PATH,
APP_RESPONSE_ACTIONS_PATH,
APP_ENTITY_ANALYTICS_PATH,
APP_PATH,
} from '../../../common/constants';

Expand Down Expand Up @@ -188,6 +189,13 @@ export const navTabs: SecurityNav = {
...getSecuritySolutionCSPNavTab<SecurityPageName>('rules', APP_PATH),
urlKey: 'administration',
},
[SecurityPageName.entityAnalytics]: {
id: SecurityPageName.entityAnalytics,
name: i18n.ENTITY_ANALYTICS,
href: APP_ENTITY_ANALYTICS_PATH,
disabled: false,
urlKey: 'entity_analytics',
},
};

export const securityNavGroup: SecurityNavGroup = {
Expand Down
7 changes: 7 additions & 0 deletions x-pack/plugins/security_solution/public/app/translations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,13 @@ export const DETECTION_RESPONSE = i18n.translate(
}
);

export const ENTITY_ANALYTICS = i18n.translate(
'xpack.securitySolution.navigation.entityAnalytics',
{
defaultMessage: 'Entity Analytics',
}
);

export const HOSTS = i18n.translate('xpack.securitySolution.navigation.hosts', {
defaultMessage: 'Hosts',
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,6 @@ describe('DonutChart', () => {
const props: DonutChartProps = {
data: parsedMockAlertsData?.open?.severities,
label: 'Open',
link: null,
title: <ChartLabel count={parsedMockAlertsData?.open?.total} />,
fillColor: jest.fn(() => '#ccc'),
totalCount: parsedMockAlertsData?.open?.total,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,8 @@ export interface DonutChartProps {
data: DonutChartData[] | null | undefined;
fillColor: FillColor;
height?: number;
label: string;
label: React.ReactElement | string;
legendItems?: LegendItem[] | null | undefined;
link?: string | null;
title: React.ReactElement | string | number | null;
totalCount: number | null | undefined;
}
Expand All @@ -71,7 +70,6 @@ export const DonutChart = ({
height = 90,
label,
legendItems,
link,
title,
totalCount,
}: DonutChartProps) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ const LegendItemComponent: React.FC<{

return (
<EuiText size="xs">
<EuiFlexGroup alignItems="center" gutterSize="none">
<EuiFlexGroup alignItems="center" gutterSize="none" responsive={false}>
{color != null && (
<EuiFlexItem grow={false}>
<EuiHealth data-test-subj="legend-color" color={color} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,6 @@ export const getTabsOnUsersDetailsUrl = (
tabName: UsersTableType,
search?: string
) => `/name/${detailName}/${tabName}${appendSearch(search)}`;

export const getTabsOnUsersUrl = (tabName: UsersTableType, search?: string) =>
`/${tabName}${appendSearch(search)}`;
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ export type UrlStateType =
| 'dashboards'
| 'indicators'
| 'cloud_posture'
| 'findings';
| 'findings'
| 'entity_analytics';

export type SecurityNavGroup = Record<SecurityNavGroupKey, NavGroupTab>;
export interface NavTab {
Expand Down Expand Up @@ -87,6 +88,7 @@ export const securityNavKeys = [
SecurityPageName.cloudSecurityPostureFindings,
SecurityPageName.cloudSecurityPostureBenchmarks,
SecurityPageName.cloudSecurityPostureRules,
SecurityPageName.entityAnalytics,
] as const;
export type SecurityNavKey = typeof securityNavKeys[number];

Expand Down
Loading

0 comments on commit bbcadf1

Please sign in to comment.