[Entity Analytics] Rename asset criticality levels + tweak designs (#176802)

## Summary

Primarily rename asset criticality levels, the old vs new levels are:

- `very_important` -> `extreme_impact` 
- `important` -> `high_impact`
- `normal` -> `medium_impact`
- `not_important` -> `low_impact`

Also some remaining asset criticality design tweaks:

- Removed criticality level description from picker options (pic 1
below)
- Changed picker text to "Change asset criticality" (pic 1 below)
- Replaced contexts table with asset criticality badge, with new
descriptive subheading in the risk inputs left flyout (pic 2 below)
- Replaced contexts with asset criticality in risk summaries table, and
never populate count (pic 3 below)

### 1. Criticality picker
<img width="1077" alt="Screenshot 2024-02-13 at 11 09 39"
src="f6890835-b81a-4df1-816e-dc04952dbb1e">

### 2. Risk inputs assigned criticality
<img width="1075" alt="Screenshot 2024-02-13 at 13 05 04"
src="729e635a-2dcd-4cf0-bcf2-a114aeae7d05">

### 3. Risk summary table asset criticality tweaks

<img width="703" alt="Screenshot 2024-02-13 at 13 37 18"
src="b1b15ffe-3342-4e43-919c-cae4f77fc6be">

---------

Co-authored-by: jaredburgettelastic <jared.burgett@elastic.co>
This commit is contained in:
Mark Hopkin 2024-02-13 20:36:51 +00:00 committed by GitHub
parent d809be71f0
commit 442bd13b52
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
32 changed files with 194 additions and 347 deletions

View file

@ -39,7 +39,7 @@ export const CreateAssetCriticalityRecord = AssetCriticalityRecordIdParts.merge(
/**
* The criticality level of the asset.
*/
criticality_level: z.enum(['very_important', 'important', 'normal', 'not_important']),
criticality_level: z.enum(['low_impact', 'medium_impact', 'high_impact', 'extreme_impact']),
})
);

View file

@ -48,7 +48,7 @@ components:
properties:
criticality_level:
type: string
enum: [very_important, important, normal, not_important]
enum: [low_impact, medium_impact, high_impact, extreme_impact]
description: The criticality level of the asset.
required:
- criticality_level

View file

@ -124,8 +124,8 @@ components:
description: The number of risk input documents that contributed to the Category 2 score (`category_2_score`).
criticality_level:
type: string
example: very_important
description: The designated criticality level of the entity. Possible values are `not_important`, `normal`, `important`, and `very_important`.
example: extreme_impact
description: The designated criticality level of the entity. Possible values are `low_impact`, `medium_impact`, `high_impact`, and `extreme_impact`.
criticality_modifier:
type: number
format: double

View file

@ -5,44 +5,25 @@
* 2.0.
*/
import React from 'react';
import { EuiHealth, EuiText } from '@elastic/eui';
import { EuiHealth } from '@elastic/eui';
import { euiLightVars } from '@kbn/ui-theme';
import { FormattedMessage } from '@kbn/i18n-react';
import { CRITICALITY_LEVEL_TITLE, CRITICALITY_LEVEL_DESCRIPTION } from './translations';
import { CRITICALITY_LEVEL_TITLE } from './translations';
import type { CriticalityLevel } from '../../../../common/entity_analytics/asset_criticality/types';
export const CRITICALITY_LEVEL_COLOR: Record<CriticalityLevel, string> = {
very_important: '#E7664C',
important: '#D6BF57',
normal: '#54B399',
not_important: euiLightVars.euiColorMediumShade,
extreme_impact: '#E7664C',
high_impact: '#D6BF57',
medium_impact: '#54B399',
low_impact: euiLightVars.euiColorMediumShade,
};
export const AssetCriticalityBadge: React.FC<{
criticalityLevel: CriticalityLevel;
withDescription?: boolean;
style?: React.CSSProperties;
className?: string;
dataTestSubj?: string;
}> = ({
criticalityLevel,
style,
dataTestSubj = 'asset-criticality-badge',
withDescription = false,
className,
}) => {
const showDescription = withDescription ?? false;
const badgeContent = showDescription ? (
<>
<strong>{CRITICALITY_LEVEL_TITLE[criticalityLevel]}</strong>
<EuiText size="s" color="subdued">
<p>{CRITICALITY_LEVEL_DESCRIPTION[criticalityLevel]}</p>
</EuiText>
</>
) : (
CRITICALITY_LEVEL_TITLE[criticalityLevel]
);
}> = ({ criticalityLevel, style, dataTestSubj = 'asset-criticality-badge', className }) => {
return (
<EuiHealth
data-test-subj={dataTestSubj}
@ -50,24 +31,22 @@ export const AssetCriticalityBadge: React.FC<{
style={style}
className={className}
>
{badgeContent}
{CRITICALITY_LEVEL_TITLE[criticalityLevel]}
</EuiHealth>
);
};
export const AssetCriticalityBadgeAllowMissing: React.FC<{
criticalityLevel?: CriticalityLevel;
withDescription?: boolean;
style?: React.CSSProperties;
dataTestSubj?: string;
className?: string;
}> = ({ criticalityLevel, style, dataTestSubj, withDescription, className }) => {
}> = ({ criticalityLevel, style, dataTestSubj, className }) => {
if (criticalityLevel) {
return (
<AssetCriticalityBadge
criticalityLevel={criticalityLevel}
dataTestSubj={dataTestSubj}
withDescription={withDescription}
style={style}
className={className}
/>

View file

@ -181,7 +181,7 @@ interface ModalProps {
const AssetCriticalityModal: React.FC<ModalProps> = ({ criticality, entity, toggle }) => {
const basicSelectId = useGeneratedHtmlId({ prefix: 'basicSelect' });
const [value, setNewValue] = useState<CriticalityLevel>(
criticality.query.data?.criticality_level ?? 'normal'
criticality.query.data?.criticality_level ?? 'medium_impact'
);
return (
@ -238,7 +238,6 @@ const option = (level: CriticalityLevel): EuiSuperSelectOption<CriticalityLevel>
criticalityLevel={level}
style={{ lineHeight: 'inherit' }}
dataTestSubj="asset-criticality-modal-select-option"
withDescription
/>
),
inputDisplay: (
@ -246,10 +245,10 @@ const option = (level: CriticalityLevel): EuiSuperSelectOption<CriticalityLevel>
),
});
const options: Array<EuiSuperSelectOption<CriticalityLevel>> = [
option('normal'),
option('not_important'),
option('important'),
option('very_important'),
option('low_impact'),
option('medium_impact'),
option('high_impact'),
option('extreme_impact'),
];
export const AssetCriticalityAccordion = React.memo(AssetCriticalityAccordionComponent);

View file

@ -11,59 +11,33 @@ import type { CriticalityLevel } from '../../../../common/entity_analytics/asset
export const PICK_ASSET_CRITICALITY = i18n.translate(
'xpack.securitySolution.entityAnalytics.assetCriticality.pickerText',
{
defaultMessage: 'Pick asset criticality level',
defaultMessage: 'Change asset criticality',
}
);
export const CRITICALITY_LEVEL_TITLE: Record<CriticalityLevel, string> = {
normal: i18n.translate(
'xpack.securitySolution.entityAnalytics.assetCriticality.levelTitle.normal',
medium_impact: i18n.translate(
'xpack.securitySolution.entityAnalytics.assetCriticality.levelTitle.mediumImpact',
{
defaultMessage: 'Normal',
defaultMessage: 'Medium Impact',
}
),
not_important: i18n.translate(
'xpack.securitySolution.entityAnalytics.assetCriticality.levelTitle.notImportant',
low_impact: i18n.translate(
'xpack.securitySolution.entityAnalytics.assetCriticality.levelTitle.lowImpact',
{
defaultMessage: 'Not important',
defaultMessage: 'Low Impact',
}
),
important: i18n.translate(
'xpack.securitySolution.entityAnalytics.assetCriticality.levelTitle.important',
high_impact: i18n.translate(
'xpack.securitySolution.entityAnalytics.assetCriticality.levelTitle.highImpact',
{
defaultMessage: 'Important',
defaultMessage: 'High Impact',
}
),
very_important: i18n.translate(
'xpack.securitySolution.entityAnalytics.assetCriticality.levelTitle.veryImportant',
extreme_impact: i18n.translate(
'xpack.securitySolution.entityAnalytics.assetCriticality.levelTitle.extremeImpact',
{
defaultMessage: 'Very important',
}
),
};
export const CRITICALITY_LEVEL_DESCRIPTION: Record<CriticalityLevel, string> = {
normal: i18n.translate(
'xpack.securitySolution.entityAnalytics.assetCriticality.levelDescription.normal',
{
defaultMessage: 'Entity risk score rises at normal speed',
}
),
not_important: i18n.translate(
'xpack.securitySolution.entityAnalytics.assetCriticality.levelDescription.notImportant',
{
defaultMessage: 'Entity risk score rises slower',
}
),
important: i18n.translate(
'xpack.securitySolution.entityAnalytics.assetCriticality.levelDescription.important',
{
defaultMessage: 'Entity risk score rises faster',
}
),
very_important: i18n.translate(
'xpack.securitySolution.entityAnalytics.assetCriticality.levelDescription.veryImportant',
{
defaultMessage: 'Entity risk score rises much faster',
defaultMessage: 'Extreme Impact',
}
),
};

View file

@ -1,79 +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 { render, screen } from '@testing-library/react';
import { ContextsTable } from './contexts_table';
import type { UserRiskScore } from '../../../../../../common/search_strategy';
import { RiskLevels } from '../../../../../../common/entity_analytics/risk_engine';
describe('ContextsTable', () => {
it('renders the correct criticality when the risk has a criticality_level', () => {
const riskScore: UserRiskScore = {
'@timestamp': '2021-08-05T15:00:00.000Z',
user: {
name: 'elastic',
risk: {
'@timestamp': '2023-02-15T00:15:19.231Z',
id_field: 'host.name',
id_value: 'hostname',
calculated_level: RiskLevels.high,
calculated_score: 149,
calculated_score_norm: 85.332,
category_1_score: 85,
category_1_count: 12,
category_2_count: 0,
category_2_score: 0,
criticality_level: 'very_important',
criticality_modifier: 2,
notes: [],
inputs: [],
rule_risks: [],
multipliers: [],
},
},
};
render(<ContextsTable riskScore={riskScore} loading={false} />);
expect(screen.getByText('Asset Criticality Level')).toBeInTheDocument();
expect(screen.getByTestId('risk-inputs-asset-criticality-badge')).toBeInTheDocument();
expect(screen.getByText('Very important')).toBeInTheDocument();
});
it('renders the correct criticality when the risk does not have a criticality_level', () => {
const riskScore: UserRiskScore = {
'@timestamp': '2021-08-05T15:00:00.000Z',
user: {
name: 'elastic',
risk: {
'@timestamp': '2023-02-15T00:15:19.231Z',
id_field: 'host.name',
id_value: 'hostname',
calculated_level: RiskLevels.high,
calculated_score: 149,
calculated_score_norm: 85.332,
category_1_score: 85,
category_1_count: 12,
category_2_count: 0,
category_2_score: 0,
criticality_modifier: 2,
notes: [],
inputs: [],
rule_risks: [],
multipliers: [],
},
},
};
render(<ContextsTable riskScore={riskScore} loading={false} />);
expect(screen.getByText('Asset Criticality Level')).toBeInTheDocument();
expect(screen.getByTestId('risk-inputs-asset-criticality-badge')).toBeInTheDocument();
expect(screen.getByText('Criticality Unassigned')).toBeInTheDocument();
});
});

View file

@ -1,86 +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 { euiLightVars } from '@kbn/ui-theme';
import React, { useMemo } from 'react';
import { FormattedMessage } from '@kbn/i18n-react';
import styled from '@emotion/styled';
import { BasicTable } from '../../../../../common/components/ml/tables/basic_table';
import { AssetCriticalityBadgeAllowMissing } from '../../../asset_criticality';
import { isUserRiskScore } from '../../../../../../common/search_strategy';
import type { UserRiskScore, HostRiskScore } from '../../../../../../common/search_strategy';
const FieldLabel = styled.span`
font-weight: ${euiLightVars.euiFontWeightMedium};
color: ${euiLightVars.euiTitleColor};
`;
const columns = [
{
name: (
<FormattedMessage
id="xpack.securitySolution.flyout.entityDetails.fieldColumnTitle"
defaultMessage="Field"
/>
),
field: 'label',
render: (label: string) => <FieldLabel>{label}</FieldLabel>,
},
{
name: (
<FormattedMessage
id="xpack.securitySolution.flyout.entityDetails.valuesColumnTitle"
defaultMessage="Values"
/>
),
field: 'field',
render: (field: string | undefined, { render }: { render: () => JSX.Element }) => render(),
},
];
export const ContextsTable: React.FC<{
riskScore?: UserRiskScore | HostRiskScore;
loading: boolean;
}> = ({ riskScore, loading }) => {
const criticalityLevel = useMemo(() => {
if (!riskScore) {
return undefined;
}
if (isUserRiskScore(riskScore)) {
return riskScore.user.risk.criticality_level;
}
return riskScore.host.risk.criticality_level;
}, [riskScore]);
const items = useMemo(
() => [
{
label: 'Asset Criticality Level',
render: () => (
<AssetCriticalityBadgeAllowMissing
criticalityLevel={criticalityLevel}
dataTestSubj="risk-inputs-asset-criticality-badge"
/>
),
},
],
[criticalityLevel]
);
return (
<BasicTable
data-test-subj="contexts-table"
columns={columns}
items={items}
compressed={true}
loading={loading}
/>
);
};

View file

@ -46,6 +46,10 @@ const riskScore = {
};
describe('RiskInputsTab', () => {
beforeEach(() => {
jest.clearAllMocks();
});
it('renders', () => {
mockUseRiskContributingAlerts.mockReturnValue({
loading: false,
@ -64,13 +68,13 @@ describe('RiskInputsTab', () => {
</TestProviders>
);
expect(queryByTestId('risk-input-contexts-title')).not.toBeInTheDocument();
expect(queryByTestId('risk-input-asset-criticality-title')).not.toBeInTheDocument();
expect(getByTestId('risk-input-table-description-cell')).toHaveTextContent(
'Risk inputRule Name'
);
});
it('renders the context section if enabled', () => {
it('Does not render the context section if enabled but no asset criticality', () => {
mockUseIsExperimentalFeatureEnabled.mockReturnValue(true);
const { queryByTestId } = render(
@ -79,7 +83,36 @@ describe('RiskInputsTab', () => {
</TestProviders>
);
expect(queryByTestId('risk-input-contexts-title')).toBeInTheDocument();
expect(queryByTestId('risk-input-asset-criticality-title')).not.toBeInTheDocument();
});
it('Renders the context section if enabled and risks contains asset criticality', () => {
mockUseIsExperimentalFeatureEnabled.mockReturnValue(true);
const riskScorewWithAssetCriticality = {
'@timestamp': '2021-08-19T16:00:00.000Z',
user: {
name: 'elastic',
risk: {
...riskScore.user.risk,
criticality_level: 'extreme_impact',
},
},
};
mockUseRiskScore.mockReturnValue({
loading: false,
error: false,
data: [riskScorewWithAssetCriticality],
});
const { queryByTestId } = render(
<TestProviders>
<RiskInputsTab entityType={RiskScoreEntity.user} entityName="elastic" />
</TestProviders>
);
expect(queryByTestId('risk-input-asset-criticality-title')).toBeInTheDocument();
});
it('paginates', () => {

View file

@ -6,7 +6,7 @@
*/
import type { EuiBasicTableColumn, Pagination } from '@elastic/eui';
import { EuiSpacer, EuiInMemoryTable, EuiTitle, EuiCallOut } from '@elastic/eui';
import { EuiSpacer, EuiInMemoryTable, EuiTitle, EuiCallOut, EuiText } from '@elastic/eui';
import React, { useCallback, useMemo, useState } from 'react';
import { FormattedMessage } from '@kbn/i18n-react';
import { get } from 'lodash/fp';
@ -16,13 +16,15 @@ import { ActionColumn } from '../../components/action_column';
import { RiskInputsUtilityBar } from '../../components/utility_bar';
import { useRiskContributingAlerts } from '../../../../hooks/use_risk_contributing_alerts';
import { useRiskScore } from '../../../../api/hooks/use_risk_score';
import type { HostRiskScore, UserRiskScore } from '../../../../../../common/search_strategy';
import {
buildHostNamesFilter,
buildUserNamesFilter,
isUserRiskScore,
} from '../../../../../../common/search_strategy';
import { RiskScoreEntity } from '../../../../../../common/entity_analytics/risk_engine';
import { ContextsTable } from './contexts_table';
import { useIsExperimentalFeatureEnabled } from '../../../../../common/hooks/use_experimental_features';
import { AssetCriticalityBadgeAllowMissing } from '../../../asset_criticality';
export interface RiskInputsTabProps extends Record<string, unknown> {
entityType: RiskScoreEntity;
entityName: string;
@ -170,22 +172,6 @@ export const RiskInputsTab = ({ entityType, entityName }: RiskInputsTabProps) =>
);
}
const riskInputsContextSection = (
<>
<EuiTitle size="xs" data-test-subj="risk-input-contexts-title">
<h3>
<FormattedMessage
id="xpack.securitySolution.flyout.entityDetails.riskInputs.contextsTitle"
defaultMessage="Contexts"
/>
</h3>
</EuiTitle>
<EuiSpacer size="xs" />
<ContextsTable riskScore={riskScore} loading={loadingRiskScore} />
<EuiSpacer size="m" />
</>
);
const riskInputsAlertSection = (
<>
<EuiTitle size="xs" data-test-subj="risk-input-alert-title">
@ -216,10 +202,60 @@ export const RiskInputsTab = ({ entityType, entityName }: RiskInputsTabProps) =>
return (
<>
{isAssetCriticalityEnabled && riskInputsContextSection}
{isAssetCriticalityEnabled && (
<RiskInputsAssetCriticalitySection loading={loadingRiskScore} riskScore={riskScore} />
)}
{riskInputsAlertSection}
</>
);
};
const RiskInputsAssetCriticalitySection: React.FC<{
riskScore?: UserRiskScore | HostRiskScore;
loading: boolean;
}> = ({ riskScore, loading }) => {
const criticalityLevel = useMemo(() => {
if (!riskScore) {
return undefined;
}
if (isUserRiskScore(riskScore)) {
return riskScore.user.risk.criticality_level;
}
return riskScore.host.risk.criticality_level;
}, [riskScore]);
if (loading || criticalityLevel === undefined) {
return null;
}
return (
<>
<EuiTitle size="xs" data-test-subj="risk-input-asset-criticality-title">
<h3>
<FormattedMessage
id="xpack.securitySolution.flyout.entityDetails.riskInputs.assetCriticalityTitle"
defaultMessage="Asset Criticality"
/>
</h3>
</EuiTitle>
<EuiSpacer size="xs" />
<EuiText size="xs" color="subdued">
<FormattedMessage
id="xpack.securitySolution.flyout.entityDetails.riskInputs.assetCriticalityDescription"
defaultMessage="The criticality assigned at the time of the risk score calculation."
/>
</EuiText>
<EuiSpacer size="s" />
<AssetCriticalityBadgeAllowMissing
criticalityLevel={criticalityLevel}
dataTestSubj="risk-inputs-asset-criticality-badge"
/>
<EuiSpacer size="m" />
</>
);
};
RiskInputsTab.displayName = 'RiskInputsTab';

View file

@ -14,7 +14,7 @@ import type { HostRiskScore, RiskStats, UserRiskScore } from '../../../../common
interface TableItem {
category: string;
count: number;
count: number | undefined;
score: number;
}
@ -80,7 +80,9 @@ export const buildColumns: (showFooter: boolean) => Array<EuiBasicTableColumn<Ta
align: 'right',
footer: (props) =>
showFooter ? (
<span data-test-subj="risk-summary-result-count">{sumBy((i) => i.count, props.items)}</span>
<span data-test-subj="risk-summary-result-count">
{sumBy((i) => i.count ?? 0, props.items)}
</span>
) : undefined,
},
];
@ -101,13 +103,13 @@ export const getItems: (
? [
{
category: i18n.translate(
'xpack.securitySolution.flyout.entityDetails.contextGroupLabel',
'xpack.securitySolution.flyout.entityDetails.assetCriticalityGroupLabel',
{
defaultMessage: 'Contexts',
defaultMessage: 'Asset Criticality',
}
),
score: entityData?.risk.category_2_score ?? 0,
count: entityData?.risk.category_2_count ?? 0,
count: undefined,
},
]
: []),

View file

@ -95,20 +95,9 @@ describe('RiskSummary', () => {
`AlertsScore${mockHostRiskScoreState.data?.[0].host.risk.category_1_score ?? 0}`
);
// Context
expect(getByTestId('risk-summary-table')).toHaveTextContent(
`Inputs${mockHostRiskScoreState.data?.[0].host.risk.category_2_count ?? 0}`
);
expect(getByTestId('risk-summary-table')).toHaveTextContent(
`ContextsScore${mockHostRiskScoreState.data?.[0].host.risk.category_2_score ?? 0}`
);
// Result
expect(getByTestId('risk-summary-result-count')).toHaveTextContent(
`${
(mockHostRiskScoreState.data?.[0].host.risk.category_1_count ?? 0) +
(mockHostRiskScoreState.data?.[0].host.risk.category_2_count ?? 0)
}`
`${mockHostRiskScoreState.data?.[0].host.risk.category_1_count ?? 0}`
);
expect(getByTestId('risk-summary-result-score')).toHaveTextContent(

View file

@ -73,7 +73,7 @@ const assetCriticalityHostResponse = [
{
fields: {
id_value: ['host name 2'],
criticality_level: ['very_important'],
criticality_level: ['extremely_critical'],
},
},
{

View file

@ -25,7 +25,7 @@ const buildMockCriticalityHit = (
'@timestamp': '2021-09-16T15:00:00.000Z',
id_field: 'host.name',
id_value: 'hostname',
criticality_level: 'normal',
criticality_level: 'medium_impact',
...overrides,
},
});
@ -140,7 +140,7 @@ describe('AssetCriticalityService', () => {
buildMockCriticalityHit({
id_field: 'user.name',
id_value: 'username',
criticality_level: 'very_important',
criticality_level: 'extreme_impact',
}),
];

View file

@ -39,8 +39,8 @@ export const assetCriticalityFieldMap: FieldMap = {
* CriticalityModifiers are used to adjust the risk score based on the criticality of the asset.
*/
export const CriticalityModifiers: Record<AssetCriticalityRecord['criticality_level'], number> = {
very_important: 2,
important: 1.5,
normal: 1,
not_important: 0.5,
extreme_impact: 2,
high_impact: 1.5,
medium_impact: 1,
low_impact: 0.5,
};

View file

@ -88,7 +88,7 @@ const buildResponseMock = (
'@timestamp': '2021-08-19T20:55:59.000Z',
id_field: 'host.name',
id_value: 'hostname',
criticality_level: 'important',
criticality_level: 'high_impact',
criticality_modifier: 1.5,
calculated_level: RiskLevels.unknown,
calculated_score: 20,

View file

@ -53,7 +53,7 @@ describe('RiskEngineDataWriter', () => {
"category_1_score": 85,
"category_2_count": 0,
"category_2_score": 0,
"criticality_level": "very_important",
"criticality_level": "high_impact",
"criticality_modifier": 2,
"id_field": "host.name",
"id_value": "hostname",
@ -79,7 +79,7 @@ describe('RiskEngineDataWriter', () => {
"category_1_score": 85,
"category_2_count": 0,
"category_2_score": 0,
"criticality_level": "very_important",
"criticality_level": "high_impact",
"criticality_modifier": 2,
"id_field": "host.name",
"id_value": "hostname",
@ -127,7 +127,7 @@ describe('RiskEngineDataWriter', () => {
"category_1_score": 85,
"category_2_count": 0,
"category_2_score": 0,
"criticality_level": "very_important",
"criticality_level": "high_impact",
"criticality_modifier": 2,
"id_field": "user.name",
"id_value": "username_1",
@ -153,7 +153,7 @@ describe('RiskEngineDataWriter', () => {
"category_1_score": 85,
"category_2_count": 0,
"category_2_score": 0,
"criticality_level": "very_important",
"criticality_level": "high_impact",
"criticality_modifier": 2,
"id_field": "user.name",
"id_value": "username_2",
@ -207,7 +207,7 @@ describe('RiskEngineDataWriter', () => {
"category_1_score": 85,
"category_2_count": 0,
"category_2_score": 0,
"criticality_level": "very_important",
"criticality_level": "high_impact",
"criticality_modifier": 2,
"id_field": "host.name",
"id_value": "hostname_1",
@ -233,7 +233,7 @@ describe('RiskEngineDataWriter', () => {
"category_1_score": 85,
"category_2_count": 0,
"category_2_score": 0,
"criticality_level": "very_important",
"criticality_level": "high_impact",
"criticality_modifier": 2,
"id_field": "user.name",
"id_value": "username_1",
@ -259,7 +259,7 @@ describe('RiskEngineDataWriter', () => {
"category_1_score": 85,
"category_2_count": 0,
"category_2_score": 0,
"criticality_level": "very_important",
"criticality_level": "high_impact",
"criticality_modifier": 2,
"id_field": "user.name",
"id_value": "username_2",

View file

@ -20,7 +20,7 @@ const createRiskScoreMock = (overrides: Partial<RiskScore> = {}): RiskScore => (
category_1_count: 12,
category_2_count: 0,
category_2_score: 0,
criticality_level: 'very_important',
criticality_level: 'high_impact',
criticality_modifier: 2,
notes: [],
inputs: [],

View file

@ -6,7 +6,7 @@
"source": {
"id_field": "host.name",
"id_value": "suricata-zeek-sensor-toronto",
"criticality_level": "important",
"criticality_level": "high_impact",
"@timestamp": "2022-08-12T14:45:36.171Z",
"updated_at": "2022-08-12T14:45:36.171Z"
},
@ -22,7 +22,7 @@
"source": {
"id_field": "host.name",
"id_value": "host-0",
"criticality_level": "very_important",
"criticality_level": "extreme_impact",
"@timestamp": "2022-08-12T14:45:36.171Z",
"updated_at": "2022-08-12T14:45:36.171Z"
},
@ -38,7 +38,7 @@
"source": {
"id_field": "host.name",
"id_value": "zeek-newyork-sha-aa8df15",
"criticality_level": "normal",
"criticality_level": "medium_impact",
"@timestamp": "2022-08-12T14:45:36.171Z",
"updated_at": "2022-08-12T14:45:36.171Z"
},
@ -54,7 +54,7 @@
"source": {
"id_field": "host.name",
"id_value": "zeek-sensor-amsterdam",
"criticality_level": "low",
"criticality_level": "low_impact",
"@timestamp": "2022-08-12T14:45:36.171Z",
"updated_at": "2022-08-12T14:45:36.171Z"
},
@ -70,7 +70,7 @@
"source": {
"id_field": "host.name",
"id_value": "suricata-sensor-london",
"criticality_level": "important",
"criticality_level": "high_impact",
"@timestamp": "2022-08-12T14:45:36.171Z",
"updated_at": "2022-08-12T14:45:36.171Z"
},
@ -86,7 +86,7 @@
"source": {
"id_field": "user.name",
"id_value": "root",
"criticality_level": "very_important",
"criticality_level": "extreme_impact",
"@timestamp": "2022-08-12T14:45:36.171Z",
"updated_at": "2022-08-12T14:45:36.171Z"
},
@ -102,7 +102,7 @@
"source": {
"id_field": "user.name",
"id_value": "User 2",
"criticality_level": "important",
"criticality_level": "high_impact",
"@timestamp": "2022-08-12T14:45:36.171Z",
"updated_at": "2022-08-12T14:45:36.171Z"
},
@ -118,7 +118,7 @@
"source": {
"id_field": "host.name",
"id_value": "abc",
"criticality_level": "normal",
"criticality_level": "medium_impact",
"@timestamp": "2022-08-12T14:45:36.171Z",
"updated_at": "2022-08-12T14:45:36.171Z"
},
@ -134,7 +134,7 @@
"source": {
"id_field": "user.name",
"id_value": "abc",
"criticality_level": "not_important",
"criticality_level": "low_impact",
"@timestamp": "2022-08-12T14:45:36.171Z",
"updated_at": "2022-08-12T14:45:36.171Z"
},

View file

@ -648,7 +648,7 @@ export default ({ getService }: FtrProviderContext) => {
const { previewId } = await previewRule({ supertest, rule });
const previewAlerts = await getPreviewAlerts({ es, previewId });
const fullAlert = previewAlerts[0]._source;
expect(fullAlert?.['host.asset.criticality']).to.eql('important');
expect(fullAlert?.['host.asset.criticality']).to.eql('high_impact');
});
});
});

View file

@ -894,7 +894,7 @@ export default ({ getService }: FtrProviderContext) => {
expect(previewAlerts.length).toBe(1);
expect(previewAlerts[0]?._source?.['host.asset.criticality']).toBe('very_important');
expect(previewAlerts[0]?._source?.['host.asset.criticality']).toBe('extreme_impact');
});
});

View file

@ -291,8 +291,8 @@ export default ({ getService }: FtrProviderContext) => {
expect(previewAlerts.length).toBe(1);
const fullAlert = previewAlerts[0]._source;
expect(fullAlert?.['host.asset.criticality']).toBe('normal');
expect(fullAlert?.['user.asset.criticality']).toBe('very_important');
expect(fullAlert?.['host.asset.criticality']).toBe('medium_impact');
expect(fullAlert?.['user.asset.criticality']).toBe('extreme_impact');
});
});
});

View file

@ -1064,8 +1064,8 @@ export default ({ getService }: FtrProviderContext) => {
const previewAlerts = await getPreviewAlerts({ es, previewId });
const fullAlert = previewAlerts[0]._source;
expect(fullAlert?.['host.asset.criticality']).to.eql('normal');
expect(fullAlert?.['user.asset.criticality']).to.eql('very_important');
expect(fullAlert?.['host.asset.criticality']).to.eql('medium_impact');
expect(fullAlert?.['user.asset.criticality']).to.eql('extreme_impact');
});
});
});

View file

@ -298,8 +298,8 @@ export default ({ getService }: FtrProviderContext) => {
};
const { previewId } = await previewRule({ supertest, rule });
const previewAlerts = await getPreviewAlerts({ es, previewId });
expect(previewAlerts[0]?._source?.['host.asset.criticality']).to.eql('important');
expect(previewAlerts[0]?._source?.['user.asset.criticality']).to.eql('very_important');
expect(previewAlerts[0]?._source?.['host.asset.criticality']).to.eql('high_impact');
expect(previewAlerts[0]?._source?.['user.asset.criticality']).to.eql('extreme_impact');
});
});

View file

@ -1661,8 +1661,8 @@ export default ({ getService }: FtrProviderContext) => {
return expect(fullAlert).to.be.ok();
}
expect(fullAlert?.['host.asset.criticality']).to.eql('low');
expect(fullAlert?.['user.asset.criticality']).to.eql('very_important');
expect(fullAlert?.['host.asset.criticality']).to.eql('low_impact');
expect(fullAlert?.['user.asset.criticality']).to.eql('extreme_impact');
});
});
});

View file

@ -452,7 +452,7 @@ export default ({ getService }: FtrProviderContext) => {
const previewAlerts = await getPreviewAlerts({ es, previewId, sort: ['host.name'] });
const fullAlert = previewAlerts[0]?._source;
expect(fullAlert?.['host.asset.criticality']).toEqual('important');
expect(fullAlert?.['host.asset.criticality']).toEqual('high_impact');
});
});
});

View file

@ -87,14 +87,14 @@ export default ({ getService }: FtrProviderContext) => {
const assetCriticality = {
id_field: 'host.name',
id_value: 'host-01',
criticality_level: 'important',
criticality_level: 'high_impact',
};
const { body: result } = await assetCriticalityRoutes.upsert(assetCriticality);
expect(result.id_field).to.eql('host.name');
expect(result.id_value).to.eql('host-01');
expect(result.criticality_level).to.eql('important');
expect(result.criticality_level).to.eql('high_impact');
expect(result['@timestamp']).to.be.a('string');
const doc = await getAssetCriticalityDoc({ idField: 'host.name', idValue: 'host-01', es });
@ -118,7 +118,7 @@ export default ({ getService }: FtrProviderContext) => {
const assetCriticality = {
id_field: 'invalid',
id_value: 'host-01',
criticality_level: 'important',
criticality_level: 'high_impact',
};
await assetCriticalityRoutes.upsert(assetCriticality, {
@ -132,7 +132,7 @@ export default ({ getService }: FtrProviderContext) => {
const assetCriticality = {
id_field: 'host.name',
id_value: 'host-02',
criticality_level: 'important',
criticality_level: 'high_impact',
};
await assetCriticalityRoutes.upsert(assetCriticality);
@ -141,7 +141,7 @@ export default ({ getService }: FtrProviderContext) => {
expect(result.id_field).to.eql('host.name');
expect(result.id_value).to.eql('host-02');
expect(result.criticality_level).to.eql('important');
expect(result.criticality_level).to.eql('high_impact');
expect(result['@timestamp']).to.be.a('string');
});
@ -157,21 +157,21 @@ export default ({ getService }: FtrProviderContext) => {
const assetCriticality = {
id_field: 'host.name',
id_value: 'host-01',
criticality_level: 'important',
criticality_level: 'high_impact',
};
const { body: createdDoc } = await assetCriticalityRoutes.upsert(assetCriticality);
const updatedAssetCriticality = {
id_field: 'host.name',
id_value: 'host-01',
criticality_level: 'very_important',
criticality_level: 'extreme_impact',
};
const { body: updatedDoc } = await assetCriticalityRoutes.upsert(updatedAssetCriticality);
expect(updatedDoc.id_field).to.eql('host.name');
expect(updatedDoc.id_value).to.eql('host-01');
expect(updatedDoc.criticality_level).to.eql('very_important');
expect(updatedDoc.criticality_level).to.eql('extreme_impact');
expect(updatedDoc['@timestamp']).to.be.a('string');
expect(updatedDoc['@timestamp']).to.not.eql(createdDoc['@timestamp']);
@ -186,7 +186,7 @@ export default ({ getService }: FtrProviderContext) => {
const assetCriticality = {
id_field: 'host.name',
id_value: 'delete-me',
criticality_level: 'important',
criticality_level: 'high_impact',
};
await assetCriticalityRoutes.upsert(assetCriticality);

View file

@ -318,7 +318,7 @@ export default ({ getService }: FtrProviderContext): void => {
await assetCriticalityRoutes.upsert({
id_field: 'host.name',
id_value: 'host-1',
criticality_level: 'important',
criticality_level: 'high_impact',
});
});
@ -344,7 +344,7 @@ export default ({ getService }: FtrProviderContext): void => {
const [score] = normalizeScores(scores);
expect(score).to.eql({
criticality_level: 'important',
criticality_level: 'high_impact',
criticality_modifier: 1.5,
calculated_level: 'Unknown',
calculated_score: 21,

View file

@ -563,7 +563,7 @@ export default ({ getService }: FtrProviderContext): void => {
await assetCriticalityRoutes.upsert({
id_field: 'host.name',
id_value: 'host-1',
criticality_level: 'very_important',
criticality_level: 'extreme_impact',
});
});
@ -585,7 +585,7 @@ export default ({ getService }: FtrProviderContext): void => {
expect(sanitizeScores(body.scores.host!)).to.eql([
{
criticality_level: 'very_important',
criticality_level: 'extreme_impact',
criticality_modifier: 2.0,
calculated_level: 'Unknown',
calculated_score: 21,

View file

@ -233,7 +233,7 @@ export default ({ getService }: FtrProviderContext): void => {
await assetCriticalityRoutes.upsert({
id_field: 'host.name',
id_value: 'host-1',
criticality_level: 'very_important',
criticality_level: 'extreme_impact',
});
});
@ -255,7 +255,7 @@ export default ({ getService }: FtrProviderContext): void => {
(riskScore) => riskScore.host?.risk.criticality_modifier
);
expect(assetCriticalityLevels).to.contain('very_important');
expect(assetCriticalityLevels).to.contain('extreme_impact');
expect(assetCriticalityModifiers).to.contain(2);
const scoreWithCriticality = riskScores.find((score) => score.host?.name === 'host-1');
@ -263,7 +263,7 @@ export default ({ getService }: FtrProviderContext): void => {
{
id_field: 'host.name',
id_value: 'host-1',
criticality_level: 'very_important',
criticality_level: 'extreme_impact',
criticality_modifier: 2,
calculated_level: 'Moderate',
calculated_score: 79.81345973382406,

View file

@ -99,7 +99,7 @@ describe(
it('should show asset criticality in the risk input panel', () => {
expandFirstAlertUserFlyout();
expandRiskInputsFlyoutPanel();
cy.get(ASSET_CRITICALITY_BADGE).should('contain.text', 'Very important');
cy.get(ASSET_CRITICALITY_BADGE).should('contain.text', 'Extreme Impact');
});
it('should display asset criticality accordion', () => {
@ -119,16 +119,16 @@ describe(
toggleAssetCriticalityModal();
cy.get(ENTITY_DETAILS_FLYOUT_ASSET_CRITICALITY_MODAL_TITLE).should(
'have.text',
'Pick asset criticality level'
'Change asset criticality'
);
});
it('should update asset criticality state', () => {
cy.log('asset criticality update');
expandFirstAlertUserFlyout();
selectAssetCriticalityLevel('Important');
selectAssetCriticalityLevel('High Impact');
cy.get(ENTITY_DETAILS_FLYOUT_ASSET_CRITICALITY_LEVEL)
.contains('Important')
.contains('High Impact')
.should('be.visible');
});
});
@ -180,7 +180,7 @@ describe(
it('should show asset criticality in the risk input panel', () => {
expandFirstAlertHostFlyout();
expandRiskInputsFlyoutPanel();
cy.get(ASSET_CRITICALITY_BADGE).should('contain.text', 'Very important');
cy.get(ASSET_CRITICALITY_BADGE).should('contain.text', 'Extreme Impact');
});
it('should display asset criticality accordion', () => {
@ -200,16 +200,16 @@ describe(
toggleAssetCriticalityModal();
cy.get(ENTITY_DETAILS_FLYOUT_ASSET_CRITICALITY_MODAL_TITLE).should(
'have.text',
'Pick asset criticality level'
'Change asset criticality'
);
});
it('should update asset criticality state', () => {
cy.log('asset criticality update');
expandFirstAlertHostFlyout();
selectAssetCriticalityLevel('Important');
selectAssetCriticalityLevel('High Impact');
cy.get(ENTITY_DETAILS_FLYOUT_ASSET_CRITICALITY_LEVEL)
.contains('Important')
.contains('High Impact')
.should('be.visible');
});
});

View file

@ -230,7 +230,7 @@
"category_1_count": 1,
"category_2_score": 220,
"category_2_count": 1,
"criticality_level": "very_important",
"criticality_level": "extreme_impact",
"notes": [],
"inputs": [
{
@ -438,7 +438,7 @@
"category_1_count": 1,
"category_2_score": 220,
"category_2_count": 1,
"criticality_level": "very_important",
"criticality_level": "extreme_impact",
"notes": [],
"inputs": [
{
@ -730,7 +730,7 @@
"category_1_count": 1,
"category_2_score": 220,
"category_2_count": 1,
"criticality_level": "very_important",
"criticality_level": "extreme_impact",
"notes": [],
"inputs": [
{
@ -944,7 +944,7 @@
"category_1_count": 1,
"category_2_score": 220,
"category_2_count": 1,
"criticality_level": "very_important",
"criticality_level": "extreme_impact",
"notes": [],
"inputs": [
{