Skip to content

Commit

Permalink
[Security Solutions] Update new user details flyout to be consistent …
Browse files Browse the repository at this point in the history
…with Expandable Alerts Flyout (#169514)

## Summary
Update new user details flyout to be consistent with Expandable Alerts
Flyout. The previous user details flyout implementation was hidden
behind a flag and never went live.


![Screenshot 2023-11-09 at 15 42
59](https://github.com/elastic/kibana/assets/1490444/0e4dee8a-0319-4531-8dcf-81cd88526aeb)


### What is included
* Update new user details flyout to use the expandable flyout component
* Update UI components according to the new design
* Keep the feature hidden behind newUserDetailsFlyout flag
* Supporting alert risk inputs

### What is NOT included
* Supporting multiple categories of risk inputs
* Host details flyout
* User and host pages
* Asset integrations (okta and azure)
* Update the flyout on the timeline (It is currently a technical
restriction of the expandable flyout, but the team is working to fix it)

### How to test it?
* Enable experimental flag `newUserDetailsFlyout`
`xpack.securitySolution.enableExperimental: ['newUserDetailsFlyout']`
* Create alerts and open alerts page
* Click on a username

- [x] Test edge cases
  - [x] No cases permissions (it hides cases actions)
  - [x] Basic license (it hides the risk score summary)  
- [x] No risk score data for a user (It hides the risk score summary)
<img width="434" alt="Screenshot 2023-11-13 at 15 56 33"
src="https://github.com/elastic/kibana/assets/1490444/4fc13042-cd3d-487b-9982-bfbf02f003b4">


### 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/packages/kbn-i18n/README.md)
- [x] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios
- [x] This renders correctly on smaller devices using a responsive
layout. (You can test this [in your
browser](https://www.browserstack.com/guide/responsive-testing-on-local-server))
  • Loading branch information
machadoum authored Nov 21, 2023
1 parent e859b14 commit 3a58207
Show file tree
Hide file tree
Showing 86 changed files with 2,540 additions and 560 deletions.
1 change: 1 addition & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -1466,6 +1466,7 @@ x-pack/plugins/security_solution/public/overview/components/entity_analytics
x-pack/plugins/security_solution/server/lib/entity_analytics @elastic/security-entity-analytics
x-pack/plugins/security_solution/server/lib/risk_score @elastic/security-entity-analytics
x-pack/test/security_solution_api_integration/test_suites/entity_analytics @elastic/security-entity-analytics
x-pack/plugins/security_solution/public/flyout/entity_details @elastic/security-entity-analytics

# Security Defend Workflows - OSQuery Ownership
/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_response_actions @elastic/security-defend-workflows
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ export enum TableId {
kubernetesPageSessions = 'kubernetes-page-sessions',
alertsOnCasePage = 'alerts-case-page',
alertsRiskInputs = 'alerts-risk-inputs',
// New version of `alertsRiskInputs` designed to support multiple kinds of risk inputs
riskInputs = 'risk-inputs',
}

export enum TableEntityType {
Expand All @@ -52,6 +54,7 @@ export const tableEntity: Record<TableId, TableEntityType> = {
[TableId.hostsPageSessions]: TableEntityType.session,
[TableId.kubernetesPageSessions]: TableEntityType.session,
[TableId.alertsRiskInputs]: TableEntityType.alert,
[TableId.riskInputs]: TableEntityType.alert,
} as const;

const TableIdLiteralRt = runtimeTypes.union([
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,6 @@ export const latestRiskScoreIndexPattern = 'risk-score.risk-score-latest-*';

export const getRiskScoreLatestIndex = (spaceId = 'default') =>
`${riskScoreBaseIndexName}.risk-score-latest-${spaceId}`;

export const getRiskScoreTimeSeriesIndex = (spaceId = 'default') =>
`${riskScoreBaseIndexName}.risk-score-${spaceId}`;
Original file line number Diff line number Diff line change
Expand Up @@ -103,11 +103,3 @@ export const EMPTY_SEVERITY_COUNT = {
[RiskSeverity.moderate]: 0,
[RiskSeverity.unknown]: 0,
};

export const SEVERITY_UI_SORT_ORDER = [
RiskSeverity.unknown,
RiskSeverity.low,
RiskSeverity.moderate,
RiskSeverity.high,
RiskSeverity.critical,
];
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@

import type { ESQuery } from '../../../../typed_json';
import { RISKY_HOSTS_INDEX_PREFIX, RISKY_USERS_INDEX_PREFIX } from '../../../../constants';
import { RiskScoreEntity, getRiskScoreLatestIndex } from '../../../../risk_engine';
import {
RiskScoreEntity,
getRiskScoreLatestIndex,
getRiskScoreTimeSeriesIndex,
} from '../../../../risk_engine';
export { RiskQueries } from '../../../../api/search_strategy';

/**
Expand All @@ -30,7 +34,9 @@ export const getUserRiskIndex = (
isNewRiskScoreModuleInstalled: boolean
): string => {
return isNewRiskScoreModuleInstalled
? getRiskScoreLatestIndex(spaceId)
? onlyLatest
? getRiskScoreLatestIndex(spaceId)
: getRiskScoreTimeSeriesIndex(spaceId)
: `${RISKY_USERS_INDEX_PREFIX}${onlyLatest ? 'latest_' : ''}${spaceId}`;
};

Expand Down
4 changes: 2 additions & 2 deletions x-pack/plugins/security_solution/public/cases/pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import type { CaseViewRefreshPropInterface } from '@kbn/cases-plugin/common';
import { CaseMetricsFeature } from '@kbn/cases-plugin/common';
import { useUiSetting$ } from '@kbn/kibana-react-plugin/public';
import { useExpandableFlyoutContext } from '@kbn/expandable-flyout';
import { RightPanelKey } from '../../flyout/document_details/right';
import { DocumentDetailsRightPanelKey } from '../../flyout/document_details/right';
import { useTourContext } from '../../common/components/guided_onboarding_tour';
import {
AlertsCasesTourSteps,
Expand Down Expand Up @@ -74,7 +74,7 @@ const CaseContainerComponent: React.FC = () => {
if (isSecurityFlyoutEnabled) {
openFlyout({
right: {
id: RightPanelKey,
id: DocumentDetailsRightPanelKey,
params: {
id: alertId,
indexName: index,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { dataTableActions, TableId } from '@kbn/securitysolution-data-table';
import { useUiSetting$ } from '@kbn/kibana-react-plugin/public';
import { timelineActions } from '../../../../timelines/store/timeline';
import { ENABLE_EXPANDABLE_FLYOUT_SETTING } from '../../../../../common/constants';
import { RightPanelKey } from '../../../../flyout/document_details/right';
import { DocumentDetailsRightPanelKey } from '../../../../flyout/document_details/right';
import type {
SetEventsDeleted,
SetEventsLoading,
Expand Down Expand Up @@ -103,7 +103,7 @@ const RowActionComponent = ({
if (isSecurityFlyoutEnabled && tableId !== TableId.rulePreview) {
openFlyout({
right: {
id: RightPanelKey,
id: DocumentDetailsRightPanelKey,
params: {
id: eventId,
indexName,
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*
* 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 { RiskScoreEntity } from '../../../../../../../common/risk_engine';
import { renderHook } from '@testing-library/react-hooks';
import { wrapper } from '../../../mocks';
import { useLensAttributes } from '../../../use_lens_attributes';
import { getRiskScoreSummaryAttributes } from './risk_score_summary';
import { RiskSeverity } from '../../../../../../../common/search_strategy';
import type { MetricVisualizationState } from '@kbn/lens-plugin/public';

jest.mock('../../../../../containers/sourcerer', () => ({
useSourcererDataView: jest.fn().mockReturnValue({
selectedPatterns: ['auditbeat-mytest-*'],
dataViewId: 'security-solution-my-test',
indicesExist: true,
}),
}));

jest.mock('uuid', () => ({
v4: jest.fn().mockReturnValue('2cc5663b-f062-43f8-8688-fc8166c2ca8e'),
}));

describe('getRiskScoreSummaryAttributes', () => {
it('should render', () => {
const { result } = renderHook(
() =>
useLensAttributes({
lensAttributes: getRiskScoreSummaryAttributes({
severity: RiskSeverity.low,
query: `user.name: test.user`,
spaceId: 'default',
riskEntity: RiskScoreEntity.user,
}),
}),
{ wrapper }
);

expect(result?.current).toMatchSnapshot();
});

it('renders the subtitle', () => {
const { result } = renderHook(
() =>
useLensAttributes({
lensAttributes: getRiskScoreSummaryAttributes({
severity: RiskSeverity.low,
query: `user.name: test.user`,
spaceId: 'default',
riskEntity: RiskScoreEntity.user,
}),
}),
{ wrapper }
);

expect((result?.current?.state.visualization as MetricVisualizationState).subtitle).toBe('Low');
});

it('renders the query when applyGlobalQueriesAndFilters is false', () => {
const query = `test.field: test.user`;

const { result } = renderHook(
() =>
useLensAttributes({
lensAttributes: getRiskScoreSummaryAttributes({
severity: RiskSeverity.low,
query,
spaceId: 'default',
riskEntity: RiskScoreEntity.user,
}),
applyGlobalQueriesAndFilters: false,
}),
{ wrapper }
);

expect(result?.current?.state.query.query).toBe(query);
});
});
Loading

0 comments on commit 3a58207

Please sign in to comment.