Show old risk scores (#167235)

## Use legacy risk score indices if the new risks engine wasn't
installed

Legacy risk scores indices:
- `ml_user_risk_score_latest_default`
- `ml_host_risk_score_latest_default`

New risk score indices:
- `risk-score.risk-score-latest-default`

Which parts use risk score indices?
- Entity Analytics dashboard
- All host/user risk tab
- Single host/user risk tab
- Alert enrichment UI
- Alert enrichment Backend

All these components can use only one risk score data source at a time,
a new or legacy one.
Previously we started to use the new risk score indices if FF -
`['riskScoringPersistence', 'riskScoringRoutesEnabled'] ` was present
and there was no possibility for the client to see old risk score data
in UI, or use it for alert enrichments

This PR, changes the way, that clients will use legacy risk score
indices until they specifically choose to upgrade the risk engine.


In this video legacy risk transforms are installed, but user risk
transforms are not installed.


16acf38a-5694-4706-9426-cdea58b70a9b

### Cypress tests

I modify those tests in a way that we test that it works still with
legacy risk scores, but also with new risk scores.
Also, add some tests for upgrade workflow.

Also, some risk scores a different in legacy and new indices for the
same entities. So we can show in the tests, that they use different
indices.

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Khristinin Nikita 2023-09-29 18:54:31 +02:00 committed by GitHub
parent 772739ab40
commit e1a280f602
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
64 changed files with 2052 additions and 1027 deletions

View file

@ -16,7 +16,7 @@ export const allHostsSchema = requestBasicOptionsSchema.extend({
sort, sort,
pagination, pagination,
timerange, timerange,
isNewRiskScoreModuleAvailable: z.boolean().default(false), isNewRiskScoreModuleInstalled: z.boolean().default(false),
factoryQueryType: z.literal(HostsQueries.hosts), factoryQueryType: z.literal(HostsQueries.hosts),
}); });

View file

@ -15,7 +15,7 @@ export const relatedHostsRequestOptionsSchema = requestBasicOptionsSchema.extend
skip: z.boolean().optional(), skip: z.boolean().optional(),
from: z.string(), from: z.string(),
inspect, inspect,
isNewRiskScoreModuleAvailable: z.boolean().default(false), isNewRiskScoreModuleInstalled: z.boolean().default(false),
factoryQueryType: z.literal(RelatedEntitiesQueries.relatedHosts), factoryQueryType: z.literal(RelatedEntitiesQueries.relatedHosts),
}); });

View file

@ -15,7 +15,7 @@ export const relatedUsersRequestOptionsSchema = requestBasicOptionsSchema.extend
skip: z.boolean().optional(), skip: z.boolean().optional(),
from: z.string(), from: z.string(),
inspect, inspect,
isNewRiskScoreModuleAvailable: z.boolean().default(false), isNewRiskScoreModuleInstalled: z.boolean().default(false),
factoryQueryType: z.literal(RelatedEntitiesQueries.relatedUsers), factoryQueryType: z.literal(RelatedEntitiesQueries.relatedUsers),
}); });

View file

@ -22,7 +22,7 @@ export const usersSchema = requestOptionsPaginatedSchema.extend({
field: z.enum([UsersFields.name, UsersFields.lastSeen]), field: z.enum([UsersFields.name, UsersFields.lastSeen]),
}), }),
timerange, timerange,
isNewRiskScoreModuleAvailable: z.boolean().default(false), isNewRiskScoreModuleInstalled: z.boolean().default(false),
factoryQueryType: z.literal(UsersQueries.users), factoryQueryType: z.literal(UsersQueries.users),
}); });

View file

@ -17,9 +17,9 @@ export { RiskQueries } from '../../../../api/search_strategy';
export const getHostRiskIndex = ( export const getHostRiskIndex = (
spaceId: string, spaceId: string,
onlyLatest: boolean = true, onlyLatest: boolean = true,
isNewRiskScoreModuleAvailable: boolean isNewRiskScoreModuleInstalled: boolean
): string => { ): string => {
return isNewRiskScoreModuleAvailable return isNewRiskScoreModuleInstalled
? getRiskScoreLatestIndex(spaceId) ? getRiskScoreLatestIndex(spaceId)
: `${RISKY_HOSTS_INDEX_PREFIX}${onlyLatest ? 'latest_' : ''}${spaceId}`; : `${RISKY_HOSTS_INDEX_PREFIX}${onlyLatest ? 'latest_' : ''}${spaceId}`;
}; };
@ -27,9 +27,9 @@ export const getHostRiskIndex = (
export const getUserRiskIndex = ( export const getUserRiskIndex = (
spaceId: string, spaceId: string,
onlyLatest: boolean = true, onlyLatest: boolean = true,
isNewRiskScoreModuleAvailable: boolean isNewRiskScoreModuleInstalled: boolean
): string => { ): string => {
return isNewRiskScoreModuleAvailable return isNewRiskScoreModuleInstalled
? getRiskScoreLatestIndex(spaceId) ? getRiskScoreLatestIndex(spaceId)
: `${RISKY_USERS_INDEX_PREFIX}${onlyLatest ? 'latest_' : ''}${spaceId}`; : `${RISKY_USERS_INDEX_PREFIX}${onlyLatest ? 'latest_' : ''}${spaceId}`;
}; };

View file

@ -12,7 +12,7 @@ import { RelatedEntitiesQueries } from '../../../../../common/search_strategy/se
import type { RelatedHost } from '../../../../../common/search_strategy/security_solution/related_entities/related_hosts'; import type { RelatedHost } from '../../../../../common/search_strategy/security_solution/related_entities/related_hosts';
import { useSearchStrategy } from '../../use_search_strategy'; import { useSearchStrategy } from '../../use_search_strategy';
import { FAIL_RELATED_HOSTS } from './translations'; import { FAIL_RELATED_HOSTS } from './translations';
import { useIsExperimentalFeatureEnabled } from '../../../hooks/use_experimental_features'; import { useIsNewRiskScoreModuleInstalled } from '../../../../entity_analytics/api/hooks/use_risk_engine_status';
export interface UseUserRelatedHostsResult { export interface UseUserRelatedHostsResult {
inspect: InspectResponse; inspect: InspectResponse;
@ -50,7 +50,8 @@ export const useUserRelatedHosts = ({
errorMessage: FAIL_RELATED_HOSTS, errorMessage: FAIL_RELATED_HOSTS,
abort: skip, abort: skip,
}); });
const isNewRiskScoreModuleAvailable = useIsExperimentalFeatureEnabled('riskScoringRoutesEnabled');
const isNewRiskScoreModuleInstalled = useIsNewRiskScoreModuleInstalled();
const userRelatedHostsResponse = useMemo( const userRelatedHostsResponse = useMemo(
() => ({ () => ({
@ -69,9 +70,9 @@ export const useUserRelatedHosts = ({
factoryQueryType: RelatedEntitiesQueries.relatedHosts, factoryQueryType: RelatedEntitiesQueries.relatedHosts,
userName, userName,
from, from,
isNewRiskScoreModuleAvailable, isNewRiskScoreModuleInstalled,
}), }),
[indexNames, from, userName, isNewRiskScoreModuleAvailable] [indexNames, from, userName, isNewRiskScoreModuleInstalled]
); );
useEffect(() => { useEffect(() => {

View file

@ -12,7 +12,7 @@ import { RelatedEntitiesQueries } from '../../../../../common/search_strategy/se
import type { RelatedUser } from '../../../../../common/search_strategy/security_solution/related_entities/related_users'; import type { RelatedUser } from '../../../../../common/search_strategy/security_solution/related_entities/related_users';
import { useSearchStrategy } from '../../use_search_strategy'; import { useSearchStrategy } from '../../use_search_strategy';
import { FAIL_RELATED_USERS } from './translations'; import { FAIL_RELATED_USERS } from './translations';
import { useIsExperimentalFeatureEnabled } from '../../../hooks/use_experimental_features'; import { useIsNewRiskScoreModuleInstalled } from '../../../../entity_analytics/api/hooks/use_risk_engine_status';
export interface UseHostRelatedUsersResult { export interface UseHostRelatedUsersResult {
inspect: InspectResponse; inspect: InspectResponse;
@ -35,7 +35,7 @@ export const useHostRelatedUsers = ({
from, from,
skip = false, skip = false,
}: UseHostRelatedUsersParam): UseHostRelatedUsersResult => { }: UseHostRelatedUsersParam): UseHostRelatedUsersResult => {
const isNewRiskScoreModuleAvailable = useIsExperimentalFeatureEnabled('riskScoringRoutesEnabled'); const isNewRiskScoreModuleInstalled = useIsNewRiskScoreModuleInstalled();
const { const {
loading, loading,
result: response, result: response,
@ -69,9 +69,9 @@ export const useHostRelatedUsers = ({
factoryQueryType: RelatedEntitiesQueries.relatedUsers, factoryQueryType: RelatedEntitiesQueries.relatedUsers,
hostName, hostName,
from, from,
isNewRiskScoreModuleAvailable, isNewRiskScoreModuleInstalled,
}), }),
[indexNames, from, hostName, isNewRiskScoreModuleAvailable] [indexNames, from, hostName, isNewRiskScoreModuleInstalled]
); );
useEffect(() => { useEffect(() => {

View file

@ -21,19 +21,36 @@ export const useInvalidateRiskEngineStatusQuery = () => {
}, [queryClient]); }, [queryClient]);
}; };
export const useIsNewRiskScoreModuleInstalled = () => {
const { data: riskEngineStatus } = useRiskEngineStatus();
return riskEngineStatus?.isNewRiskScoreModuleInstalled ?? false;
};
export const useRiskEngineStatus = () => { export const useRiskEngineStatus = () => {
const isRiskEngineEnabled = useIsExperimentalFeatureEnabled('riskScoringRoutesEnabled'); const isNewRiskScoreModuleAvailable = useIsExperimentalFeatureEnabled('riskScoringRoutesEnabled');
return useQuery(FETCH_RISK_ENGINE_STATUS, async ({ signal }) => { return useQuery(FETCH_RISK_ENGINE_STATUS, async ({ signal }) => {
if (!isRiskEngineEnabled) { if (!isNewRiskScoreModuleAvailable) {
return null; return {
isUpdateAvailable: false,
isNewRiskScoreModuleInstalled: false,
isNewRiskScoreModuleAvailable,
risk_engine_status: null,
legacy_risk_engine_status: null,
is_max_amount_of_risk_engines_reached: false,
};
} }
const response = await fetchRiskEngineStatus({ signal }); const response = await fetchRiskEngineStatus({ signal });
const isUpdateAvailable = const isUpdateAvailable =
response?.legacy_risk_engine_status === RiskEngineStatus.ENABLED && response?.legacy_risk_engine_status === RiskEngineStatus.ENABLED &&
response.risk_engine_status === RiskEngineStatus.NOT_INSTALLED; response.risk_engine_status === RiskEngineStatus.NOT_INSTALLED;
const isNewRiskScoreModuleInstalled =
response.risk_engine_status !== RiskEngineStatus.NOT_INSTALLED;
return { return {
isUpdateAvailable, isUpdateAvailable,
isNewRiskScoreModuleInstalled,
isNewRiskScoreModuleAvailable,
...response, ...response,
}; };
}); });

View file

@ -13,6 +13,7 @@ import { SecurityPageName } from '../../../common/constants';
export const RiskScoreUpdatePanel = () => { export const RiskScoreUpdatePanel = () => {
return ( return (
<>
<EuiCallOut title={i18n.UPDATE_PANEL_TITLE} color="primary" iconType="starEmpty"> <EuiCallOut title={i18n.UPDATE_PANEL_TITLE} color="primary" iconType="starEmpty">
<EuiText>{i18n.UPDATE_PANEL_MESSAGE}</EuiText> <EuiText>{i18n.UPDATE_PANEL_MESSAGE}</EuiText>
<EuiSpacer size="m" /> <EuiSpacer size="m" />
@ -21,10 +22,13 @@ export const RiskScoreUpdatePanel = () => {
color="primary" color="primary"
fill fill
deepLinkId={SecurityPageName.entityAnalyticsManagement} deepLinkId={SecurityPageName.entityAnalyticsManagement}
data-test-subj="update-risk-score-button"
> >
{i18n.UPDATE_PANEL_GO_TO_MANAGE} {i18n.UPDATE_PANEL_GO_TO_MANAGE}
</SecuritySolutionLinkButton> </SecuritySolutionLinkButton>
</EuiFlexGroup> </EuiFlexGroup>
</EuiCallOut> </EuiCallOut>
<EuiSpacer size="m" />
</>
); );
}; };

View file

@ -170,14 +170,15 @@ export const UPDATE_RISK_ENGINE_MODAL_EXISTING_USER_HOST_2 = i18n.translate(
export const UPDATE_RISK_ENGINE_MODAL_EXISTING_DATA_1 = i18n.translate( export const UPDATE_RISK_ENGINE_MODAL_EXISTING_DATA_1 = i18n.translate(
'xpack.securitySolution.riskScore.updateRiskEngineModal.existingData_1', 'xpack.securitySolution.riskScore.updateRiskEngineModal.existingData_1',
{ {
defaultMessage: 'None of your risk score data will be deleted', defaultMessage: 'Legacy risk score data will not be deleted',
} }
); );
export const UPDATE_RISK_ENGINE_MODAL_EXISTING_DATA_2 = i18n.translate( export const UPDATE_RISK_ENGINE_MODAL_EXISTING_DATA_2 = i18n.translate(
'xpack.securitySolution.riskScore.updateRiskEngineModal.existingData_2', 'xpack.securitySolution.riskScore.updateRiskEngineModal.existingData_2',
{ {
defaultMessage: ', you will need to remove any old risk score data manually.', defaultMessage:
', it will still exist in the index but will no longer be available in the user interface. You will need to remove legacy risk score data manually.',
} }
); );

View file

@ -6,7 +6,6 @@
*/ */
import { EuiEmptyPrompt, EuiPanel, EuiToolTip } from '@elastic/eui'; import { EuiEmptyPrompt, EuiPanel, EuiToolTip } from '@elastic/eui';
import React from 'react'; import React from 'react';
import { RiskScoreUpgradeButton } from '../risk_score_onboarding/risk_score_upgrade_button';
import type { RiskScoreEntity } from '../../../../../common/search_strategy'; import type { RiskScoreEntity } from '../../../../../common/search_strategy';
import { useCheckSignalIndex } from '../../../../detections/containers/detection_engine/alerts/use_check_signal_index'; import { useCheckSignalIndex } from '../../../../detections/containers/detection_engine/alerts/use_check_signal_index';
import type { inputsModel } from '../../../../common/store'; import type { inputsModel } from '../../../../common/store';
@ -64,23 +63,12 @@ const EnableRiskScoreComponent = ({
} }
actions={ actions={
<EuiToolTip content={!signalIndexExists ? i18n.ENABLE_RISK_SCORE_POPOVER : null}> <EuiToolTip content={!signalIndexExists ? i18n.ENABLE_RISK_SCORE_POPOVER : null}>
{isDeprecated ? (
<RiskScoreUpgradeButton
refetch={refetch}
riskScoreEntity={entityType}
disabled={!signalIndexExists}
timerange={timerange}
data-test-subj={`upgrade_${entityType}_risk_score`}
title={text.cta}
/>
) : (
<RiskScoreEnableButton <RiskScoreEnableButton
disabled={!signalIndexExists} disabled={!signalIndexExists}
refetch={refetch} refetch={refetch}
riskScoreEntity={entityType} riskScoreEntity={entityType}
timerange={timerange} timerange={timerange}
/> />
)}
</EuiToolTip> </EuiToolTip>
} }
/> />

View file

@ -36,7 +36,7 @@ import { useDashboardHref } from '../../../../common/hooks/use_dashboard_href';
import { RiskScoresNoDataDetected } from '../risk_score_onboarding/risk_score_no_data_detected'; import { RiskScoresNoDataDetected } from '../risk_score_onboarding/risk_score_no_data_detected';
import { useRiskEngineStatus } from '../../../../entity_analytics/api/hooks/use_risk_engine_status'; import { useRiskEngineStatus } from '../../../../entity_analytics/api/hooks/use_risk_engine_status';
import { RiskScoreUpdatePanel } from '../../../../entity_analytics/components/risk_score_update_panel'; import { RiskScoreUpdatePanel } from '../../../../entity_analytics/components/risk_score_update_panel';
import { useIsExperimentalFeatureEnabled } from '../../../../common/hooks/use_experimental_features';
const StyledEuiFlexGroup = styled(EuiFlexGroup)` const StyledEuiFlexGroup = styled(EuiFlexGroup)`
margin-top: ${({ theme }) => theme.eui.euiSizeL}; margin-top: ${({ theme }) => theme.eui.euiSizeL};
`; `;
@ -59,7 +59,6 @@ const RiskDetailsTabBodyComponent: React.FC<
: UserRiskScoreQueryId.USER_DETAILS_RISK_SCORE, : UserRiskScoreQueryId.USER_DETAILS_RISK_SCORE,
[riskEntity] [riskEntity]
); );
const isNewRiskScoreModuleAvailable = useIsExperimentalFeatureEnabled('riskScoringRoutesEnabled');
const severitySelectionRedux = useDeepEqualSelector((state: State) => const severitySelectionRedux = useDeepEqualSelector((state: State) =>
riskEntity === RiskScoreEntity.host riskEntity === RiskScoreEntity.host
@ -135,10 +134,6 @@ const RiskDetailsTabBodyComponent: React.FC<
isDeprecated: isDeprecated && !loading, isDeprecated: isDeprecated && !loading,
}; };
if (riskScoreEngineStatus?.isUpdateAvailable) {
return <RiskScoreUpdatePanel />;
}
if (status.isDisabled || status.isDeprecated) { if (status.isDisabled || status.isDeprecated) {
return ( return (
<EnableRiskScore <EnableRiskScore
@ -156,7 +151,8 @@ const RiskDetailsTabBodyComponent: React.FC<
return ( return (
<> <>
{isNewRiskScoreModuleAvailable ? ( {riskScoreEngineStatus?.isUpdateAvailable && <RiskScoreUpdatePanel />}
{riskScoreEngineStatus?.isNewRiskScoreModuleInstalled ? (
<StyledEuiFlexGroup gutterSize="s"> <StyledEuiFlexGroup gutterSize="s">
<EuiFlexItem> <EuiFlexItem>
{data?.[0] && ( {data?.[0] && (

View file

@ -74,6 +74,7 @@ const RiskScoreEnableButtonComponent = ({
color="primary" color="primary"
fill fill
deepLinkId={SecurityPageName.entityAnalyticsManagement} deepLinkId={SecurityPageName.entityAnalyticsManagement}
data-test-subj={`enable_${riskScoreEntity}_risk_score`}
> >
<FormattedMessage <FormattedMessage
id="xpack.securitySolution.riskScore.enableButtonTitle" id="xpack.securitySolution.riskScore.enableButtonTitle"

View file

@ -15,7 +15,7 @@ import { RiskScoreHeaderTitle } from './risk_score_header_title';
import { RiskScoreRestartButton } from './risk_score_restart_button'; import { RiskScoreRestartButton } from './risk_score_restart_button';
import type { inputsModel } from '../../../../common/store'; import type { inputsModel } from '../../../../common/store';
import * as overviewI18n from '../../../../overview/components/entity_analytics/common/translations'; import * as overviewI18n from '../../../../overview/components/entity_analytics/common/translations';
import { useIsExperimentalFeatureEnabled } from '../../../../common/hooks/use_experimental_features'; import { useIsNewRiskScoreModuleInstalled } from '../../../../entity_analytics/api/hooks/use_risk_engine_status';
const RiskScoresNoDataDetectedComponent = ({ const RiskScoresNoDataDetectedComponent = ({
entityType, entityType,
@ -24,7 +24,7 @@ const RiskScoresNoDataDetectedComponent = ({
entityType: RiskScoreEntity; entityType: RiskScoreEntity;
refetch: inputsModel.Refetch; refetch: inputsModel.Refetch;
}) => { }) => {
const isNewRiskScoreModuleAvailable = useIsExperimentalFeatureEnabled('riskScoringRoutesEnabled'); const isNewRiskScoreModuleInstalled = useIsNewRiskScoreModuleInstalled();
const translations = useMemo( const translations = useMemo(
() => ({ () => ({
@ -51,7 +51,7 @@ const RiskScoresNoDataDetectedComponent = ({
body={translations.body} body={translations.body}
actions={ actions={
<> <>
{!isNewRiskScoreModuleAvailable && ( {!isNewRiskScoreModuleInstalled && (
<EuiToolTip content={i18n.RESTART_TOOLTIP}> <EuiToolTip content={i18n.RESTART_TOOLTIP}>
<RiskScoreRestartButton refetch={refetch} riskScoreEntity={entityType} /> <RiskScoreRestartButton refetch={refetch} riskScoreEntity={entityType} />
</EuiToolTip> </EuiToolTip>

View file

@ -1,122 +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 { act, render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import React from 'react';
import { RiskScoreEntity } from '../../../../../common/search_strategy';
import { TestProviders } from '../../../../common/mock';
import { RiskScoreUpgradeButton } from './risk_score_upgrade_button';
import { upgradeHostRiskScoreModule, upgradeUserRiskScoreModule } from './utils';
jest.mock('./utils');
describe('RiskScoreUpgradeButton', () => {
const mockRefetch = jest.fn();
const timerange = {
from: 'mockStartDate',
to: 'mockEndDate',
};
const hostTestProps = {
refetch: mockRefetch,
riskScoreEntity: RiskScoreEntity.host,
timerange,
title: 'upgrade',
};
const userTestProps = {
refetch: mockRefetch,
riskScoreEntity: RiskScoreEntity.user,
timerange,
title: 'upgrade',
};
beforeEach(() => {
jest.clearAllMocks();
});
describe.each([
[RiskScoreEntity.host, hostTestProps],
[RiskScoreEntity.user, userTestProps],
])('%s', (riskScoreEntity, testProps) => {
it('Renders expected children', () => {
render(
<TestProviders>
<RiskScoreUpgradeButton {...testProps} />
</TestProviders>
);
expect(screen.getByTestId(`${riskScoreEntity}-risk-score-upgrade`)).toBeInTheDocument();
expect(screen.getByTestId(`${riskScoreEntity}-risk-score-upgrade`)).toHaveTextContent(
testProps.title
);
});
it('Triggers the confirmation modal before upgrading', async () => {
render(
<TestProviders>
<RiskScoreUpgradeButton {...testProps} />
</TestProviders>
);
await act(async () => {
await userEvent.click(screen.getByTestId(`${riskScoreEntity}-risk-score-upgrade`));
});
expect(
screen.getByTestId(`${riskScoreEntity}-risk-score-upgrade-confirmation-modal`)
).toBeInTheDocument();
await act(async () => {
await userEvent.click(screen.getByText('Erase data and Upgrade'));
});
expect(
screen.queryByTestId(`${riskScoreEntity}-risk-score-upgrade-confirmation-modal`)
).not.toBeInTheDocument();
if (riskScoreEntity === RiskScoreEntity.user) {
expect(upgradeUserRiskScoreModule).toHaveBeenCalled();
expect(upgradeHostRiskScoreModule).not.toHaveBeenCalled();
} else {
expect(upgradeUserRiskScoreModule).not.toHaveBeenCalled();
expect(upgradeHostRiskScoreModule).toHaveBeenCalled();
}
});
it('Shows doc link in the confirmation modal', async () => {
render(
<TestProviders>
<RiskScoreUpgradeButton {...testProps} />
</TestProviders>
);
await act(async () => {
await userEvent.click(screen.getByTestId(`${riskScoreEntity}-risk-score-upgrade`));
});
expect(screen.getByText('Preserve data')).toHaveProperty(
'href',
`https://www.elastic.co/guide/en/security/current/${riskScoreEntity}-risk-score.html`
);
});
it('Update button state while upgrading', async () => {
render(
<TestProviders>
<RiskScoreUpgradeButton {...testProps} />
</TestProviders>
);
userEvent.click(screen.getByTestId(`${riskScoreEntity}-risk-score-upgrade`));
userEvent.click(screen.getByText('Erase data and Upgrade'));
await waitFor(() => {
expect(screen.getByTestId(`${riskScoreEntity}-risk-score-upgrade`)).toHaveProperty(
'disabled',
true
);
});
});
});
});

View file

@ -1,127 +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 { EuiButton, EuiConfirmModal } from '@elastic/eui';
import React, { useCallback, useState } from 'react';
import { FormattedMessage } from '@kbn/i18n-react';
import { useSpaceId } from '../../../../common/hooks/use_space_id';
import { useKibana } from '../../../../common/lib/kibana';
import type { inputsModel } from '../../../../common/store';
import { upgradeHostRiskScoreModule, upgradeUserRiskScoreModule } from './utils';
import { RiskScoreEntity } from '../../../../../common/search_strategy';
import { useRiskScoreToastContent } from './use_risk_score_toast_content';
import { REQUEST_NAMES, useFetch } from '../../../../common/hooks/use_fetch';
import { RiskScoreDocLink } from './risk_score_doc_link';
const RiskScoreUpgradeButtonComponent = ({
disabled,
refetch,
riskScoreEntity,
timerange,
title,
}: {
disabled?: boolean;
refetch: inputsModel.Refetch;
riskScoreEntity: RiskScoreEntity;
timerange: {
from: string;
to: string;
};
title: string;
}) => {
const spaceId = useSpaceId();
const { http, notifications, theme, dashboard } = useKibana().services;
const { renderDocLink, renderDashboardLink } = useRiskScoreToastContent(riskScoreEntity);
const { fetch, isLoading } = useFetch(
REQUEST_NAMES.UPGRADE_RISK_SCORE,
riskScoreEntity === RiskScoreEntity.user
? upgradeUserRiskScoreModule
: upgradeHostRiskScoreModule
);
const [isModalVisible, setIsModalVisible] = useState(false);
const closeModal = useCallback(() => setIsModalVisible(false), []);
const showModal = useCallback(() => setIsModalVisible(true), []);
const upgradeRiskScore = useCallback(async () => {
closeModal();
fetch({
http,
notifications,
spaceId,
timerange,
refetch,
renderDashboardLink,
renderDocLink,
riskScoreEntity,
theme,
dashboard,
});
}, [
closeModal,
fetch,
http,
notifications,
spaceId,
timerange,
refetch,
renderDashboardLink,
renderDocLink,
riskScoreEntity,
theme,
dashboard,
]);
return (
<>
<EuiButton
color="primary"
data-test-subj={`${riskScoreEntity}-risk-score-upgrade`}
disabled={disabled}
fill
isLoading={isLoading}
onClick={showModal}
>
{title}
</EuiButton>
{isModalVisible && (
<EuiConfirmModal
data-test-subj={`${riskScoreEntity}-risk-score-upgrade-confirmation-modal`}
title={title}
onCancel={closeModal}
onConfirm={upgradeRiskScore}
cancelButtonText={
<RiskScoreDocLink
riskScoreEntity={riskScoreEntity}
title={
<FormattedMessage
id="xpack.securitySolution.riskScore.upgradeConfirmation.cancel"
defaultMessage="Preserve data"
/>
}
/>
}
confirmButtonText={
<FormattedMessage
data-test-subj={`${riskScoreEntity}-risk-score-upgrade-confirmation-button`}
id="xpack.securitySolution.riskScore.upgradeConfirmation.confirm"
defaultMessage="Erase data and Upgrade"
/>
}
buttonColor="danger"
defaultFocusedButton="confirm"
>
<FormattedMessage
id="xpack.securitySolution.riskScore.upgradeConfirmation.content"
defaultMessage="The upgrade will delete existing risk scores from your environment. You may preserve existing risk data before upgrading the Risk Score package. Do you wish to upgrade?"
/>
</EuiConfirmModal>
)}
</>
);
};
export const RiskScoreUpgradeButton = React.memo(RiskScoreUpgradeButtonComponent);
RiskScoreUpgradeButton.displayName = 'RiskScoreUpgradeButton';

View file

@ -28,7 +28,7 @@ import { isIndexNotFoundError } from '../../../../common/utils/exceptions';
import type { inputsModel } from '../../../../common/store'; import type { inputsModel } from '../../../../common/store';
import { useSpaceId } from '../../../../common/hooks/use_space_id'; import { useSpaceId } from '../../../../common/hooks/use_space_id';
import { useSearchStrategy } from '../../../../common/containers/use_search_strategy'; import { useSearchStrategy } from '../../../../common/containers/use_search_strategy';
import { useIsExperimentalFeatureEnabled } from '../../../../common/hooks/use_experimental_features'; import { useIsNewRiskScoreModuleInstalled } from '../../../../entity_analytics/api/hooks/use_risk_engine_status';
export interface RiskScoreState<T extends RiskScoreEntity.host | RiskScoreEntity.user> { export interface RiskScoreState<T extends RiskScoreEntity.host | RiskScoreEntity.user> {
data: data:
@ -84,11 +84,11 @@ export const useRiskScore = <T extends RiskScoreEntity.host | RiskScoreEntity.us
includeAlertsCount = false, includeAlertsCount = false,
}: UseRiskScore<T>): RiskScoreState<T> => { }: UseRiskScore<T>): RiskScoreState<T> => {
const spaceId = useSpaceId(); const spaceId = useSpaceId();
const isNewRiskScoreModuleAvailable = useIsExperimentalFeatureEnabled('riskScoringRoutesEnabled'); const isNewRiskScoreModuleInstalled = useIsNewRiskScoreModuleInstalled();
const defaultIndex = spaceId const defaultIndex = spaceId
? riskEntity === RiskScoreEntity.host ? riskEntity === RiskScoreEntity.host
? getHostRiskIndex(spaceId, onlyLatest, isNewRiskScoreModuleAvailable) ? getHostRiskIndex(spaceId, onlyLatest, isNewRiskScoreModuleInstalled)
: getUserRiskIndex(spaceId, onlyLatest, isNewRiskScoreModuleAvailable) : getUserRiskIndex(spaceId, onlyLatest, isNewRiskScoreModuleInstalled)
: undefined; : undefined;
const factoryQueryType = const factoryQueryType =
riskEntity === RiskScoreEntity.host ? RiskQueries.hostsRiskScore : RiskQueries.usersRiskScore; riskEntity === RiskScoreEntity.host ? RiskQueries.hostsRiskScore : RiskQueries.usersRiskScore;
@ -207,5 +207,7 @@ export const useRiskScore = <T extends RiskScoreEntity.host | RiskScoreEntity.us
} }
}, [isEnabled, isDeprecated, isAuthorized, isDeprecatedLoading, riskScoreRequest, search, skip]); }, [isEnabled, isDeprecated, isAuthorized, isDeprecatedLoading, riskScoreRequest, search, skip]);
return { ...riskScoreResponse, loading: loading || isDeprecatedLoading }; const result = { ...riskScoreResponse, loading: loading || isDeprecatedLoading };
return result;
}; };

View file

@ -25,7 +25,7 @@ import { useSearchStrategy } from '../../../../common/containers/use_search_stra
import type { InspectResponse } from '../../../../types'; import type { InspectResponse } from '../../../../types';
import type { inputsModel } from '../../../../common/store'; import type { inputsModel } from '../../../../common/store';
import { useAppToasts } from '../../../../common/hooks/use_app_toasts'; import { useAppToasts } from '../../../../common/hooks/use_app_toasts';
import { useIsExperimentalFeatureEnabled } from '../../../../common/hooks/use_experimental_features'; import { useIsNewRiskScoreModuleInstalled } from '../../../../entity_analytics/api/hooks/use_risk_engine_status';
interface RiskScoreKpi { interface RiskScoreKpi {
error: unknown; error: unknown;
@ -53,11 +53,11 @@ export const useRiskScoreKpi = ({
const { addError } = useAppToasts(); const { addError } = useAppToasts();
const spaceId = useSpaceId(); const spaceId = useSpaceId();
const featureEnabled = useMlCapabilities().isPlatinumOrTrialLicense; const featureEnabled = useMlCapabilities().isPlatinumOrTrialLicense;
const isNewRiskScoreModuleAvailable = useIsExperimentalFeatureEnabled('riskScoringRoutesEnabled'); const isNewRiskScoreModuleInstalled = useIsNewRiskScoreModuleInstalled();
const defaultIndex = spaceId const defaultIndex = spaceId
? riskEntity === RiskScoreEntity.host ? riskEntity === RiskScoreEntity.host
? getHostRiskIndex(spaceId, true, isNewRiskScoreModuleAvailable) ? getHostRiskIndex(spaceId, true, isNewRiskScoreModuleInstalled)
: getUserRiskIndex(spaceId, true, isNewRiskScoreModuleAvailable) : getUserRiskIndex(spaceId, true, isNewRiskScoreModuleInstalled)
: undefined; : undefined;
const { loading, result, search, refetch, inspect, error } = const { loading, result, search, refetch, inspect, error } =

View file

@ -22,7 +22,7 @@ import type { ESTermQuery } from '../../../../../common/typed_json';
import * as i18n from './translations'; import * as i18n from './translations';
import type { InspectResponse } from '../../../../types'; import type { InspectResponse } from '../../../../types';
import { useSearchStrategy } from '../../../../common/containers/use_search_strategy'; import { useSearchStrategy } from '../../../../common/containers/use_search_strategy';
import { useIsExperimentalFeatureEnabled } from '../../../../common/hooks/use_experimental_features'; import { useIsNewRiskScoreModuleInstalled } from '../../../../entity_analytics/api/hooks/use_risk_engine_status';
export const ID = 'hostsAllQuery'; export const ID = 'hostsAllQuery';
@ -62,7 +62,7 @@ export const useAllHost = ({
getHostsSelector(state, type) getHostsSelector(state, type)
); );
const isNewRiskScoreModuleAvailable = useIsExperimentalFeatureEnabled('riskScoringRoutesEnabled'); const isNewRiskScoreModuleInstalled = useIsNewRiskScoreModuleInstalled();
const [hostsRequest, setHostRequest] = useState<HostsRequestOptionsInput | null>(null); const [hostsRequest, setHostRequest] = useState<HostsRequestOptionsInput | null>(null);
@ -145,7 +145,7 @@ export const useAllHost = ({
direction, direction,
field: sortField, field: sortField,
}, },
isNewRiskScoreModuleAvailable, isNewRiskScoreModuleInstalled,
}; };
if (!deepEqual(prevRequest, myRequest)) { if (!deepEqual(prevRequest, myRequest)) {
return myRequest; return myRequest;
@ -161,7 +161,7 @@ export const useAllHost = ({
limit, limit,
startDate, startDate,
sortField, sortField,
isNewRiskScoreModuleAvailable, isNewRiskScoreModuleInstalled,
]); ]);
useEffect(() => { useEffect(() => {

View file

@ -95,10 +95,6 @@ export const HostRiskScoreQueryTabBody = ({
isDeprecated: isDeprecated && !loading, isDeprecated: isDeprecated && !loading,
}; };
if (riskScoreEngineStatus?.isUpdateAvailable) {
return <RiskScoreUpdatePanel />;
}
if (status.isDisabled || status.isDeprecated) { if (status.isDisabled || status.isDeprecated) {
return ( return (
<EuiPanel hasBorder> <EuiPanel hasBorder>
@ -123,6 +119,8 @@ export const HostRiskScoreQueryTabBody = ({
} }
return ( return (
<>
{riskScoreEngineStatus?.isUpdateAvailable && <RiskScoreUpdatePanel />}
<HostRiskScoreTableManage <HostRiskScoreTableManage
deleteQuery={deleteQuery} deleteQuery={deleteQuery}
data={data ?? []} data={data ?? []}
@ -138,6 +136,7 @@ export const HostRiskScoreQueryTabBody = ({
totalCount={totalCount} totalCount={totalCount}
type={type} type={type}
/> />
</>
); );
}; };

View file

@ -19,7 +19,7 @@ import { generateTablePaginationOptions } from '../../../components/paginated_ta
import { useDeepEqualSelector } from '../../../../common/hooks/use_selector'; import { useDeepEqualSelector } from '../../../../common/hooks/use_selector';
import { usersSelectors } from '../../store'; import { usersSelectors } from '../../store';
import { useQueryToggle } from '../../../../common/containers/query_toggle'; import { useQueryToggle } from '../../../../common/containers/query_toggle';
import { useIsExperimentalFeatureEnabled } from '../../../../common/hooks/use_experimental_features'; import { useIsNewRiskScoreModuleInstalled } from '../../../../entity_analytics/api/hooks/use_risk_engine_status';
const UsersTableManage = manageQuery(UsersTable); const UsersTableManage = manageQuery(UsersTable);
@ -43,7 +43,7 @@ export const AllUsersQueryTabBody = ({
const getUsersSelector = useMemo(() => usersSelectors.allUsersSelector(), []); const getUsersSelector = useMemo(() => usersSelectors.allUsersSelector(), []);
const { activePage, limit, sort } = useDeepEqualSelector((state) => getUsersSelector(state)); const { activePage, limit, sort } = useDeepEqualSelector((state) => getUsersSelector(state));
const isNewRiskScoreModuleAvailable = useIsExperimentalFeatureEnabled('riskScoringRoutesEnabled'); const isNewRiskScoreModuleInstalled = useIsNewRiskScoreModuleInstalled();
const { const {
loading, loading,
@ -78,7 +78,7 @@ export const AllUsersQueryTabBody = ({
}, },
pagination: generateTablePaginationOptions(activePage, limit), pagination: generateTablePaginationOptions(activePage, limit),
sort, sort,
isNewRiskScoreModuleAvailable, isNewRiskScoreModuleInstalled,
}); });
} }
}, [ }, [
@ -91,7 +91,7 @@ export const AllUsersQueryTabBody = ({
activePage, activePage,
limit, limit,
sort, sort,
isNewRiskScoreModuleAvailable, isNewRiskScoreModuleInstalled,
]); ]);
return ( return (

View file

@ -95,10 +95,6 @@ export const UserRiskScoreQueryTabBody = ({
isDeprecated: isDeprecated && !loading, isDeprecated: isDeprecated && !loading,
}; };
if (riskScoreEngineStatus?.isUpdateAvailable) {
return <RiskScoreUpdatePanel />;
}
if (status.isDisabled || status.isDeprecated) { if (status.isDisabled || status.isDeprecated) {
return ( return (
<EnableRiskScore <EnableRiskScore
@ -115,6 +111,8 @@ export const UserRiskScoreQueryTabBody = ({
} }
return ( return (
<>
{riskScoreEngineStatus?.isUpdateAvailable && <RiskScoreUpdatePanel />}
<UserRiskScoreTableManage <UserRiskScoreTableManage
deleteQuery={deleteQuery} deleteQuery={deleteQuery}
data={data ?? []} data={data ?? []}
@ -130,6 +128,7 @@ export const UserRiskScoreQueryTabBody = ({
totalCount={totalCount} totalCount={totalCount}
type={type} type={type}
/> />
</>
); );
}; };

View file

@ -35,7 +35,6 @@ import { useNavigateToAlertsPageWithFilters } from '../../../../common/hooks/use
import { getRiskEntityTranslation } from './translations'; import { getRiskEntityTranslation } from './translations';
import { useKibana } from '../../../../common/lib/kibana'; import { useKibana } from '../../../../common/lib/kibana';
import { useGlobalFilterQuery } from '../../../../common/hooks/use_global_filter_query'; import { useGlobalFilterQuery } from '../../../../common/hooks/use_global_filter_query';
import { useRiskEngineStatus } from '../../../../entity_analytics/api/hooks/use_risk_engine_status';
const EntityAnalyticsRiskScoresComponent = ({ riskEntity }: { riskEntity: RiskScoreEntity }) => { const EntityAnalyticsRiskScoresComponent = ({ riskEntity }: { riskEntity: RiskScoreEntity }) => {
const { deleteQuery, setQuery, from, to } = useGlobalTime(); const { deleteQuery, setQuery, from, to } = useGlobalTime();
@ -126,8 +125,6 @@ const EntityAnalyticsRiskScoresComponent = ({ riskEntity }: { riskEntity: RiskSc
includeAlertsCount: true, includeAlertsCount: true,
}); });
const { data: riskScoreEngineStatus } = useRiskEngineStatus();
useQueryInspector({ useQueryInspector({
queryId: entity.tableQueryId, queryId: entity.tableQueryId,
loading: isTableLoading, loading: isTableLoading,
@ -152,10 +149,6 @@ const EntityAnalyticsRiskScoresComponent = ({ riskEntity }: { riskEntity: RiskSc
isDeprecated: isDeprecated && !isTableLoading, isDeprecated: isDeprecated && !isTableLoading,
}; };
if (riskScoreEngineStatus?.isUpdateAvailable) {
return null;
}
if (status.isDisabled || status.isDeprecated) { if (status.isDisabled || status.isDeprecated) {
return ( return (
<EnableRiskScore <EnableRiskScore

View file

@ -16,11 +16,11 @@ import { getFieldValue } from '../utils/events';
export const getIsHostRiskScoreAvailable: GetIsRiskScoreAvailable = async ({ export const getIsHostRiskScoreAvailable: GetIsRiskScoreAvailable = async ({
spaceId, spaceId,
services, services,
isNewRiskScoreModuleAvailable, isNewRiskScoreModuleInstalled,
}) => { }) => {
const isHostRiskScoreIndexExist = await services.scopedClusterClient.asCurrentUser.indices.exists( const isHostRiskScoreIndexExist = await services.scopedClusterClient.asCurrentUser.indices.exists(
{ {
index: getHostRiskIndex(spaceId, true, isNewRiskScoreModuleAvailable), index: getHostRiskIndex(spaceId, true, isNewRiskScoreModuleInstalled),
} }
); );
@ -32,11 +32,11 @@ export const createHostRiskEnrichments: CreateRiskEnrichment = async ({
logger, logger,
events, events,
spaceId, spaceId,
isNewRiskScoreModuleAvailable, isNewRiskScoreModuleInstalled,
}) => { }) => {
return createSingleFieldMatchEnrichment({ return createSingleFieldMatchEnrichment({
name: 'Host Risk', name: 'Host Risk',
index: [getHostRiskIndex(spaceId, true, isNewRiskScoreModuleAvailable)], index: [getHostRiskIndex(spaceId, true, isNewRiskScoreModuleInstalled)],
services, services,
logger, logger,
events, events,

View file

@ -15,11 +15,11 @@ import { getFieldValue } from '../utils/events';
export const getIsUserRiskScoreAvailable: GetIsRiskScoreAvailable = async ({ export const getIsUserRiskScoreAvailable: GetIsRiskScoreAvailable = async ({
services, services,
spaceId, spaceId,
isNewRiskScoreModuleAvailable, isNewRiskScoreModuleInstalled,
}) => { }) => {
const isUserRiskScoreIndexExist = await services.scopedClusterClient.asCurrentUser.indices.exists( const isUserRiskScoreIndexExist = await services.scopedClusterClient.asCurrentUser.indices.exists(
{ {
index: getUserRiskIndex(spaceId, true, isNewRiskScoreModuleAvailable), index: getUserRiskIndex(spaceId, true, isNewRiskScoreModuleInstalled),
} }
); );
@ -31,11 +31,11 @@ export const createUserRiskEnrichments: CreateRiskEnrichment = async ({
logger, logger,
events, events,
spaceId, spaceId,
isNewRiskScoreModuleAvailable, isNewRiskScoreModuleInstalled,
}) => { }) => {
return createSingleFieldMatchEnrichment({ return createSingleFieldMatchEnrichment({
name: 'User Risk', name: 'User Risk',
index: [getUserRiskIndex(spaceId, true, isNewRiskScoreModuleAvailable)], index: [getUserRiskIndex(spaceId, true, isNewRiskScoreModuleInstalled)],
services, services,
logger, logger,
events, events,

View file

@ -34,9 +34,18 @@ export const enrichEvents: EnrichEventsFunction = async ({
logger.debug('Alert enrichments started'); logger.debug('Alert enrichments started');
const isNewRiskScoreModuleAvailable = experimentalFeatures?.riskScoringRoutesEnabled ?? false; const isNewRiskScoreModuleAvailable = experimentalFeatures?.riskScoringRoutesEnabled ?? false;
let isNewRiskScoreModuleInstalled = false;
if (isNewRiskScoreModuleAvailable) {
isNewRiskScoreModuleInstalled = await getIsHostRiskScoreAvailable({
spaceId,
services,
isNewRiskScoreModuleInstalled: true,
});
}
const [isHostRiskScoreIndexExist, isUserRiskScoreIndexExist] = await Promise.all([ const [isHostRiskScoreIndexExist, isUserRiskScoreIndexExist] = await Promise.all([
getIsHostRiskScoreAvailable({ spaceId, services, isNewRiskScoreModuleAvailable }), getIsHostRiskScoreAvailable({ spaceId, services, isNewRiskScoreModuleInstalled }),
getIsUserRiskScoreAvailable({ spaceId, services, isNewRiskScoreModuleAvailable }), getIsUserRiskScoreAvailable({ spaceId, services, isNewRiskScoreModuleInstalled }),
]); ]);
if (isHostRiskScoreIndexExist) { if (isHostRiskScoreIndexExist) {
@ -46,7 +55,7 @@ export const enrichEvents: EnrichEventsFunction = async ({
logger, logger,
events, events,
spaceId, spaceId,
isNewRiskScoreModuleAvailable, isNewRiskScoreModuleInstalled,
}) })
); );
} }
@ -58,7 +67,7 @@ export const enrichEvents: EnrichEventsFunction = async ({
logger, logger,
events, events,
spaceId, spaceId,
isNewRiskScoreModuleAvailable, isNewRiskScoreModuleInstalled,
}) })
); );
} }

View file

@ -76,13 +76,13 @@ export type SearchEnrichments = (params: {
export type GetIsRiskScoreAvailable = (params: { export type GetIsRiskScoreAvailable = (params: {
spaceId: string; spaceId: string;
services: RuleServices; services: RuleServices;
isNewRiskScoreModuleAvailable: boolean; isNewRiskScoreModuleInstalled: boolean;
}) => Promise<boolean>; }) => Promise<boolean>;
export type CreateRiskEnrichment = <T extends BaseFieldsLatest>( export type CreateRiskEnrichment = <T extends BaseFieldsLatest>(
params: BasedEnrichParamters<T> & { params: BasedEnrichParamters<T> & {
spaceId: string; spaceId: string;
isNewRiskScoreModuleAvailable: boolean; isNewRiskScoreModuleInstalled: boolean;
} }
) => Promise<EventsMapByEnrichments>; ) => Promise<EventsMapByEnrichments>;

View file

@ -31,7 +31,7 @@ export const mockOptions: HostsRequestOptions = {
pagination: { activePage: 0, cursorStart: 0, fakePossibleCount: 50, querySize: 10 }, pagination: { activePage: 0, cursorStart: 0, fakePossibleCount: 50, querySize: 10 },
timerange: { interval: '12h', from: '2020-09-03T09:15:21.415Z', to: '2020-09-04T09:15:21.415Z' }, timerange: { interval: '12h', from: '2020-09-03T09:15:21.415Z', to: '2020-09-04T09:15:21.415Z' },
sort: { direction: Direction.desc, field: HostsFields.lastSeen }, sort: { direction: Direction.desc, field: HostsFields.lastSeen },
isNewRiskScoreModuleAvailable: false, isNewRiskScoreModuleInstalled: false,
}; };
export const mockSearchStrategyResponse: IEsSearchResponse<unknown> = { export const mockSearchStrategyResponse: IEsSearchResponse<unknown> = {

View file

@ -72,7 +72,7 @@ export const allHosts: SecuritySolutionFactory<HostsQueries.hosts> = {
hostNames, hostNames,
deps.spaceId, deps.spaceId,
deps.esClient, deps.esClient,
options.isNewRiskScoreModuleAvailable options.isNewRiskScoreModuleInstalled
) )
: edges; : edges;
@ -95,13 +95,13 @@ async function enhanceEdges(
hostNames: string[], hostNames: string[],
spaceId: string, spaceId: string,
esClient: IScopedClusterClient, esClient: IScopedClusterClient,
isNewRiskScoreModuleAvailable: boolean isNewRiskScoreModuleInstalled: boolean
): Promise<HostsEdges[]> { ): Promise<HostsEdges[]> {
const hostRiskData = await getHostRiskData( const hostRiskData = await getHostRiskData(
esClient, esClient,
spaceId, spaceId,
hostNames, hostNames,
isNewRiskScoreModuleAvailable isNewRiskScoreModuleInstalled
); );
const hostsRiskByHostName: Record<string, string> | undefined = hostRiskData?.hits.hits.reduce( const hostsRiskByHostName: Record<string, string> | undefined = hostRiskData?.hits.hits.reduce(
(acc, hit) => ({ (acc, hit) => ({
@ -126,12 +126,12 @@ export async function getHostRiskData(
esClient: IScopedClusterClient, esClient: IScopedClusterClient,
spaceId: string, spaceId: string,
hostNames: string[], hostNames: string[],
isNewRiskScoreModuleAvailable: boolean isNewRiskScoreModuleInstalled: boolean
) { ) {
try { try {
const hostRiskResponse = await esClient.asCurrentUser.search<HostRiskScore>( const hostRiskResponse = await esClient.asCurrentUser.search<HostRiskScore>(
buildRiskScoreQuery({ buildRiskScoreQuery({
defaultIndex: [getHostRiskIndex(spaceId, true, isNewRiskScoreModuleAvailable)], defaultIndex: [getHostRiskIndex(spaceId, true, isNewRiskScoreModuleInstalled)],
filterQuery: buildHostNamesFilter(hostNames), filterQuery: buildHostNamesFilter(hostNames),
riskScoreEntity: RiskScoreEntity.host, riskScoreEntity: RiskScoreEntity.host,
factoryQueryType: RiskQueries.hostsRiskScore, factoryQueryType: RiskQueries.hostsRiskScore,

View file

@ -21,7 +21,7 @@ export const mockOptions: RelatedHostsRequestOptions = {
factoryQueryType: RelatedEntitiesQueries.relatedHosts, factoryQueryType: RelatedEntitiesQueries.relatedHosts,
userName: 'user1', userName: 'user1',
from: '2020-09-02T15:17:13.678Z', from: '2020-09-02T15:17:13.678Z',
isNewRiskScoreModuleAvailable: false, isNewRiskScoreModuleInstalled: false,
}; };
export const mockSearchStrategyResponse: IEsSearchResponse<unknown> = { export const mockSearchStrategyResponse: IEsSearchResponse<unknown> = {

View file

@ -61,7 +61,7 @@ export const usersRelatedHosts: SecuritySolutionFactory<RelatedEntitiesQueries.r
relatedHosts, relatedHosts,
deps.spaceId, deps.spaceId,
deps.esClient, deps.esClient,
options.isNewRiskScoreModuleAvailable options.isNewRiskScoreModuleInstalled
) )
: relatedHosts; : relatedHosts;
@ -78,14 +78,14 @@ async function addHostRiskData(
relatedHosts: RelatedHost[], relatedHosts: RelatedHost[],
spaceId: string, spaceId: string,
esClient: IScopedClusterClient, esClient: IScopedClusterClient,
isNewRiskScoreModuleAvailable: boolean isNewRiskScoreModuleInstalled: boolean
): Promise<RelatedHost[]> { ): Promise<RelatedHost[]> {
const hostNames = relatedHosts.map((item) => item.host); const hostNames = relatedHosts.map((item) => item.host);
const hostRiskData = await getHostRiskData( const hostRiskData = await getHostRiskData(
esClient, esClient,
spaceId, spaceId,
hostNames, hostNames,
isNewRiskScoreModuleAvailable isNewRiskScoreModuleInstalled
); );
const hostsRiskByHostName: Record<string, RiskSeverity> | undefined = const hostsRiskByHostName: Record<string, RiskSeverity> | undefined =
hostRiskData?.hits.hits.reduce( hostRiskData?.hits.hits.reduce(

View file

@ -21,7 +21,7 @@ export const mockOptions: RelatedUsersRequestOptions = {
factoryQueryType: RelatedEntitiesQueries.relatedUsers, factoryQueryType: RelatedEntitiesQueries.relatedUsers,
hostName: 'host1', hostName: 'host1',
from: '2020-09-02T15:17:13.678Z', from: '2020-09-02T15:17:13.678Z',
isNewRiskScoreModuleAvailable: false, isNewRiskScoreModuleInstalled: false,
}; };
export const mockSearchStrategyResponse: IEsSearchResponse<unknown> = { export const mockSearchStrategyResponse: IEsSearchResponse<unknown> = {

View file

@ -60,7 +60,7 @@ export const hostsRelatedUsers: SecuritySolutionFactory<RelatedEntitiesQueries.r
relatedUsers, relatedUsers,
deps.spaceId, deps.spaceId,
deps.esClient, deps.esClient,
options.isNewRiskScoreModuleAvailable options.isNewRiskScoreModuleInstalled
) )
: relatedUsers; : relatedUsers;
@ -77,14 +77,14 @@ async function addUserRiskData(
relatedUsers: RelatedUser[], relatedUsers: RelatedUser[],
spaceId: string, spaceId: string,
esClient: IScopedClusterClient, esClient: IScopedClusterClient,
isNewRiskScoreModuleAvailable: boolean isNewRiskScoreModuleInstalled: boolean
): Promise<RelatedUser[]> { ): Promise<RelatedUser[]> {
const userNames = relatedUsers.map((item) => item.user); const userNames = relatedUsers.map((item) => item.user);
const userRiskData = await getUserRiskData( const userRiskData = await getUserRiskData(
esClient, esClient,
spaceId, spaceId,
userNames, userNames,
isNewRiskScoreModuleAvailable isNewRiskScoreModuleInstalled
); );
const usersRiskByUserName: Record<string, RiskSeverity> | undefined = const usersRiskByUserName: Record<string, RiskSeverity> | undefined =
userRiskData?.hits.hits.reduce( userRiskData?.hits.hits.reduce(

View file

@ -33,7 +33,7 @@ export const mockOptions: UsersRequestOptions = {
querySize: 10, querySize: 10,
}, },
sort: { field: UsersFields.name, direction: Direction.asc }, sort: { field: UsersFields.name, direction: Direction.asc },
isNewRiskScoreModuleAvailable: false, isNewRiskScoreModuleInstalled: false,
}; };
export const mockSearchStrategyResponse: IEsSearchResponse<unknown> = { export const mockSearchStrategyResponse: IEsSearchResponse<unknown> = {

View file

@ -78,7 +78,7 @@ export const allUsers: SecuritySolutionFactory<UsersQueries.users> = {
userNames, userNames,
deps.spaceId, deps.spaceId,
deps.esClient, deps.esClient,
options.isNewRiskScoreModuleAvailable options.isNewRiskScoreModuleInstalled
) )
: edges; : edges;
@ -101,13 +101,13 @@ async function enhanceEdges(
userNames: string[], userNames: string[],
spaceId: string, spaceId: string,
esClient: IScopedClusterClient, esClient: IScopedClusterClient,
isNewRiskScoreModuleAvailable: boolean isNewRiskScoreModuleInstalled: boolean
): Promise<User[]> { ): Promise<User[]> {
const userRiskData = await getUserRiskData( const userRiskData = await getUserRiskData(
esClient, esClient,
spaceId, spaceId,
userNames, userNames,
isNewRiskScoreModuleAvailable isNewRiskScoreModuleInstalled
); );
const usersRiskByUserName: Record<string, RiskSeverity> | undefined = const usersRiskByUserName: Record<string, RiskSeverity> | undefined =
userRiskData?.hits.hits.reduce( userRiskData?.hits.hits.reduce(
@ -132,12 +132,12 @@ export async function getUserRiskData(
esClient: IScopedClusterClient, esClient: IScopedClusterClient,
spaceId: string, spaceId: string,
userNames: string[], userNames: string[],
isNewRiskScoreModuleAvailable: boolean isNewRiskScoreModuleInstalled: boolean
) { ) {
try { try {
const userRiskResponse = await esClient.asCurrentUser.search<UserRiskScore>( const userRiskResponse = await esClient.asCurrentUser.search<UserRiskScore>(
buildRiskScoreQuery({ buildRiskScoreQuery({
defaultIndex: [getUserRiskIndex(spaceId, true, isNewRiskScoreModuleAvailable)], defaultIndex: [getUserRiskIndex(spaceId, true, isNewRiskScoreModuleInstalled)],
filterQuery: buildUserNamesFilter(userNames), filterQuery: buildUserNamesFilter(userNames),
riskScoreEntity: RiskScoreEntity.user, riskScoreEntity: RiskScoreEntity.user,
factoryQueryType: RiskQueries.usersRiskScore, factoryQueryType: RiskQueries.usersRiskScore,

View file

@ -33622,9 +33622,6 @@
"xpack.securitySolution.riskScore.savedObjects.bulkDeleteFailureTitle": "Impossible de supprimer les objets enregistrés", "xpack.securitySolution.riskScore.savedObjects.bulkDeleteFailureTitle": "Impossible de supprimer les objets enregistrés",
"xpack.securitySolution.riskScore.technicalPreviewLabel": "Version d'évaluation technique", "xpack.securitySolution.riskScore.technicalPreviewLabel": "Version d'évaluation technique",
"xpack.securitySolution.riskScore.uninstall.errorMessageTitle": "Erreur de désinstallation", "xpack.securitySolution.riskScore.uninstall.errorMessageTitle": "Erreur de désinstallation",
"xpack.securitySolution.riskScore.upgradeConfirmation.cancel": "Conserver les données",
"xpack.securitySolution.riskScore.upgradeConfirmation.confirm": "Effacer et mettre à niveau",
"xpack.securitySolution.riskScore.upgradeConfirmation.content": "La mise à niveau supprimera les scores de risque existants de votre environnement. Vous pouvez conserver les données de risque existantes avant de mettre à niveau le package Score de risque. Voulez-vous effectuer la mise à niveau ?",
"xpack.securitySolution.riskScore.userRiskScoresEnabledTitle": "Scores de risque de l'utilisateur activés", "xpack.securitySolution.riskScore.userRiskScoresEnabledTitle": "Scores de risque de l'utilisateur activés",
"xpack.securitySolution.riskScore.usersDashboardRestartTooltip": "Le calcul du score de risque pourra prendre un certain temps à se lancer. Cependant, en appuyant sur Redémarrer, vous pouvez le forcer à s'exécuter immédiatement.", "xpack.securitySolution.riskScore.usersDashboardRestartTooltip": "Le calcul du score de risque pourra prendre un certain temps à se lancer. Cependant, en appuyant sur Redémarrer, vous pouvez le forcer à s'exécuter immédiatement.",
"xpack.securitySolution.riskScore.usersDashboardWarningPanelBody": "Nous navons pas trouvé de données de score de risque de lutilisateur. Vérifiez si vous avez des filtres globaux dans la barre de recherche KQL globale. Si vous venez dactiver le module de risque de lutilisateur, le moteur de risque peut mettre une heure à générer les données de score de risque de lutilisateur et à les afficher dans ce panneau.", "xpack.securitySolution.riskScore.usersDashboardWarningPanelBody": "Nous navons pas trouvé de données de score de risque de lutilisateur. Vérifiez si vous avez des filtres globaux dans la barre de recherche KQL globale. Si vous venez dactiver le module de risque de lutilisateur, le moteur de risque peut mettre une heure à générer les données de score de risque de lutilisateur et à les afficher dans ce panneau.",

View file

@ -33621,9 +33621,6 @@
"xpack.securitySolution.riskScore.savedObjects.bulkDeleteFailureTitle": "保存されたオブジェクトを削除できませんでした", "xpack.securitySolution.riskScore.savedObjects.bulkDeleteFailureTitle": "保存されたオブジェクトを削除できませんでした",
"xpack.securitySolution.riskScore.technicalPreviewLabel": "テクニカルプレビュー", "xpack.securitySolution.riskScore.technicalPreviewLabel": "テクニカルプレビュー",
"xpack.securitySolution.riskScore.uninstall.errorMessageTitle": "アンインストールエラー", "xpack.securitySolution.riskScore.uninstall.errorMessageTitle": "アンインストールエラー",
"xpack.securitySolution.riskScore.upgradeConfirmation.cancel": "データの保持",
"xpack.securitySolution.riskScore.upgradeConfirmation.confirm": "データを消去してアップグレード",
"xpack.securitySolution.riskScore.upgradeConfirmation.content": "アップグレードを実行すると、既存のリスクスコアが環境から削除されます。既存のリスクデータを保持するには、リスクスコアパッケージをアップグレードしてください。アップグレードしますか?",
"xpack.securitySolution.riskScore.userRiskScoresEnabledTitle": "ユーザーリスクスコア有効", "xpack.securitySolution.riskScore.userRiskScoresEnabledTitle": "ユーザーリスクスコア有効",
"xpack.securitySolution.riskScore.usersDashboardRestartTooltip": "リスクスコア計算の実行には少し時間がかかる場合があります。ただし、再起動を押すと、すぐに強制的に実行できます。", "xpack.securitySolution.riskScore.usersDashboardRestartTooltip": "リスクスコア計算の実行には少し時間がかかる場合があります。ただし、再起動を押すと、すぐに強制的に実行できます。",
"xpack.securitySolution.riskScore.usersDashboardWarningPanelBody": "ユーザーリスクスコアデータが見つかりません。グローバルKQL検索バーにグローバルフィルターがあるかどうかを確認してください。ユーザーリスクモジュールを有効にしたばかりの場合は、リスクエンジンがユーザーリスクスコアデータを生成し、このパネルに表示するまでに1時間かかることがあります。", "xpack.securitySolution.riskScore.usersDashboardWarningPanelBody": "ユーザーリスクスコアデータが見つかりません。グローバルKQL検索バーにグローバルフィルターがあるかどうかを確認してください。ユーザーリスクモジュールを有効にしたばかりの場合は、リスクエンジンがユーザーリスクスコアデータを生成し、このパネルに表示するまでに1時間かかることがあります。",

View file

@ -33617,9 +33617,6 @@
"xpack.securitySolution.riskScore.savedObjects.bulkDeleteFailureTitle": "无法删除已保存对象", "xpack.securitySolution.riskScore.savedObjects.bulkDeleteFailureTitle": "无法删除已保存对象",
"xpack.securitySolution.riskScore.technicalPreviewLabel": "技术预览", "xpack.securitySolution.riskScore.technicalPreviewLabel": "技术预览",
"xpack.securitySolution.riskScore.uninstall.errorMessageTitle": "卸载错误", "xpack.securitySolution.riskScore.uninstall.errorMessageTitle": "卸载错误",
"xpack.securitySolution.riskScore.upgradeConfirmation.cancel": "保留数据",
"xpack.securitySolution.riskScore.upgradeConfirmation.confirm": "擦除数据并升级",
"xpack.securitySolution.riskScore.upgradeConfirmation.content": "升级会从您的环境中删除现有风险分数。您可以先保留现有风险数据,然后再升级风险分数软件包。是否升级?",
"xpack.securitySolution.riskScore.userRiskScoresEnabledTitle": "已启用用户风险分数", "xpack.securitySolution.riskScore.userRiskScoresEnabledTitle": "已启用用户风险分数",
"xpack.securitySolution.riskScore.usersDashboardRestartTooltip": "风险分数计算可能需要一段时间运行。但是,通过按“重新启动”,您可以立即强制运行该计算。", "xpack.securitySolution.riskScore.usersDashboardRestartTooltip": "风险分数计算可能需要一段时间运行。但是,通过按“重新启动”,您可以立即强制运行该计算。",
"xpack.securitySolution.riskScore.usersDashboardWarningPanelBody": "找不到任何用户风险分数数据。检查全局 KQL 搜索栏中是否具有任何全局筛选。如果刚刚启用了用户风险模块,风险引擎可能需要一小时才能生成并在此面板中显示用户风险分数数据。", "xpack.securitySolution.riskScore.usersDashboardWarningPanelBody": "找不到任何用户风险分数数据。检查全局 KQL 搜索栏中是否具有任何全局筛选。如果刚刚启用了用户风险模块,风险引擎可能需要一小时才能生成并在此面板中显示用户风险分数数据。",

View file

@ -48,6 +48,8 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) {
'alertDetailsPageEnabled', 'alertDetailsPageEnabled',
'chartEmbeddablesEnabled', 'chartEmbeddablesEnabled',
'discoverInTimeline', 'discoverInTimeline',
'riskScoringRoutesEnabled',
'riskScoringPersistence',
])}`, ])}`,
// mock cloud to enable the guided onboarding tour in e2e tests // mock cloud to enable the guided onboarding tour in e2e tests
'--xpack.cloud.id=test', '--xpack.cloud.id=test',

View file

@ -30,11 +30,18 @@ import { login } from '../../tasks/login';
import { visitWithTimeRange } from '../../tasks/navigation'; import { visitWithTimeRange } from '../../tasks/navigation';
import { ALERTS_URL } from '../../urls/navigation'; import { ALERTS_URL } from '../../urls/navigation';
import { deleteRiskEngineConfiguration } from '../../tasks/api_calls/risk_engine';
import { enableRiskEngine } from '../../tasks/entity_analytics';
const CURRENT_HOST_RISK_CLASIFICATION = 'Current host risk classification';
const ORIGINAL_HOST_RISK_CLASIFICATION = 'Original host risk classification';
// TODO: https://github.com/elastic/kibana/issues/161539 // TODO: https://github.com/elastic/kibana/issues/161539
describe('Enrichment', { tags: ['@ess', '@serverless', '@brokenInServerless'] }, () => { describe('Enrichment', { tags: ['@ess', '@serverless', '@brokenInServerless'] }, () => {
before(() => { before(() => {
cleanKibana(); cleanKibana();
cy.task('esArchiverUnload', 'risk_scores_new');
cy.task('esArchiverUnload', 'risk_scores_new_updated');
cy.task('esArchiverLoad', { archiveName: 'risk_users' }); cy.task('esArchiverLoad', { archiveName: 'risk_users' });
}); });
@ -43,12 +50,14 @@ describe('Enrichment', { tags: ['@ess', '@serverless', '@brokenInServerless'] },
}); });
describe('Custom query rule', () => { describe('Custom query rule', () => {
describe('from legacy risk scores', () => {
beforeEach(() => { beforeEach(() => {
disableExpandableFlyout(); disableExpandableFlyout();
cy.task('esArchiverLoad', { archiveName: 'risk_hosts' }); cy.task('esArchiverLoad', { archiveName: 'risk_hosts' });
deleteAlertsAndRules(); deleteAlertsAndRules();
createRule(getNewRule({ rule_id: 'rule1' })); createRule(getNewRule({ rule_id: 'rule1' }));
login(); login();
deleteRiskEngineConfiguration();
visitWithTimeRange(ALERTS_URL); visitWithTimeRange(ALERTS_URL);
waitForAlertsToPopulate(); waitForAlertsToPopulate();
}); });
@ -58,7 +67,7 @@ describe('Enrichment', { tags: ['@ess', '@serverless', '@brokenInServerless'] },
cy.task('esArchiverUnload', 'risk_hosts_updated'); cy.task('esArchiverUnload', 'risk_hosts_updated');
}); });
it('Should has enrichment fields', function () { it('Should has enrichment fields from legacy risk', function () {
cy.get(ALERTS_COUNT) cy.get(ALERTS_COUNT)
.invoke('text') .invoke('text')
.should('match', /^[1-9].+$/); // Any number of alerts .should('match', /^[1-9].+$/); // Any number of alerts
@ -71,16 +80,61 @@ describe('Enrichment', { tags: ['@ess', '@serverless', '@brokenInServerless'] },
scrollAlertTableColumnIntoView(ACTION_COLUMN); scrollAlertTableColumnIntoView(ACTION_COLUMN);
expandFirstAlert(); expandFirstAlert();
cy.get(ENRICHED_DATA_ROW).contains('Low'); cy.get(ENRICHED_DATA_ROW).contains('Low');
cy.get(ENRICHED_DATA_ROW).contains('Current host risk classification'); cy.get(ENRICHED_DATA_ROW).contains(CURRENT_HOST_RISK_CLASIFICATION);
cy.get(ENRICHED_DATA_ROW).contains('Critical').should('not.exist'); cy.get(ENRICHED_DATA_ROW).contains('Critical').should('not.exist');
cy.get(ENRICHED_DATA_ROW).contains('Original host risk classification').should('not.exist'); cy.get(ENRICHED_DATA_ROW).contains(ORIGINAL_HOST_RISK_CLASIFICATION).should('not.exist');
closeAlertFlyout(); closeAlertFlyout();
cy.task('esArchiverUnload', 'risk_hosts'); cy.task('esArchiverUnload', 'risk_hosts');
cy.task('esArchiverLoad', { archiveName: 'risk_hosts_updated' }); cy.task('esArchiverLoad', { archiveName: 'risk_hosts_updated' });
expandFirstAlert(); expandFirstAlert();
cy.get(ENRICHED_DATA_ROW).contains('Critical'); cy.get(ENRICHED_DATA_ROW).contains('Critical');
cy.get(ENRICHED_DATA_ROW).contains('Original host risk classification'); cy.get(ENRICHED_DATA_ROW).contains(ORIGINAL_HOST_RISK_CLASIFICATION);
});
});
describe('from new risk scores', () => {
beforeEach(() => {
disableExpandableFlyout();
cy.task('esArchiverLoad', { archiveName: 'risk_scores_new' });
deleteAlertsAndRules();
createRule(getNewRule({ rule_id: 'rule1' }));
login();
enableRiskEngine();
visitWithTimeRange(ALERTS_URL);
waitForAlertsToPopulate();
});
afterEach(() => {
cy.task('esArchiverUnload', 'risk_scores_new');
cy.task('esArchiverUnload', 'risk_scores_new_updated');
deleteRiskEngineConfiguration();
});
it('Should has enrichment fields from legacy risk', function () {
cy.get(ALERTS_COUNT)
.invoke('text')
.should('match', /^[1-9].+$/); // Any number of alerts
cy.get(HOST_RISK_HEADER_COLIMN).contains('host.risk.calculated_level');
cy.get(USER_RISK_HEADER_COLIMN).contains('user.risk.calculated_level');
scrollAlertTableColumnIntoView(HOST_RISK_COLUMN);
cy.get(HOST_RISK_COLUMN).contains('Critical');
scrollAlertTableColumnIntoView(USER_RISK_COLUMN);
cy.get(USER_RISK_COLUMN).contains('High');
scrollAlertTableColumnIntoView(ACTION_COLUMN);
expandFirstAlert();
cy.get(ENRICHED_DATA_ROW).contains('Critical');
cy.get(ENRICHED_DATA_ROW).contains(CURRENT_HOST_RISK_CLASIFICATION);
cy.get(ENRICHED_DATA_ROW).contains('Low').should('not.exist');
cy.get(ENRICHED_DATA_ROW).contains(ORIGINAL_HOST_RISK_CLASIFICATION).should('not.exist');
closeAlertFlyout();
cy.task('esArchiverUnload', 'risk_scores_new');
cy.task('esArchiverLoad', { archiveName: 'risk_scores_new_updated' });
expandFirstAlert();
cy.get(ENRICHED_DATA_ROW).contains('Low');
cy.get(ENRICHED_DATA_ROW).contains(ORIGINAL_HOST_RISK_CLASIFICATION);
});
}); });
}); });
}); });

View file

@ -26,7 +26,7 @@ import { ENTITY_ANALYTICS_MANAGEMENT_URL } from '../../urls/navigation';
import { getNewRule } from '../../objects/rule'; import { getNewRule } from '../../objects/rule';
import { createRule } from '../../tasks/api_calls/rules'; import { createRule } from '../../tasks/api_calls/rules';
import { import {
deleteConfiguration, deleteRiskEngineConfiguration,
interceptRiskPreviewError, interceptRiskPreviewError,
interceptRiskPreviewSuccess, interceptRiskPreviewSuccess,
interceptRiskInitError, interceptRiskInitError,
@ -35,8 +35,7 @@ import { updateDateRangeInLocalDatePickers } from '../../tasks/date_picker';
import { fillLocalSearchBar, submitLocalSearch } from '../../tasks/search_bar'; import { fillLocalSearchBar, submitLocalSearch } from '../../tasks/search_bar';
import { import {
riskEngineStatusChange, riskEngineStatusChange,
updateRiskEngine, upgradeRiskEngine,
updateRiskEngineConfirm,
previewErrorButtonClick, previewErrorButtonClick,
} from '../../tasks/entity_analytics'; } from '../../tasks/entity_analytics';
@ -44,9 +43,6 @@ import {
describe( describe(
'Entity analytics management page', 'Entity analytics management page',
{ {
env: {
ftrConfig: { enableExperimental: ['riskScoringRoutesEnabled', 'riskScoringPersistence'] },
},
tags: ['@ess', '@serverless', '@brokenInServerless'], tags: ['@ess', '@serverless', '@brokenInServerless'],
}, },
() => { () => {
@ -58,7 +54,7 @@ describe(
beforeEach(() => { beforeEach(() => {
login(); login();
createRule(getNewRule({ query: 'user.name:* or host.name:*', risk_score: 70 })); createRule(getNewRule({ query: 'user.name:* or host.name:*', risk_score: 70 }));
deleteConfiguration(); deleteRiskEngineConfiguration();
visit(ENTITY_ANALYTICS_MANAGEMENT_URL); visit(ENTITY_ANALYTICS_MANAGEMENT_URL);
}); });
@ -147,10 +143,7 @@ describe(
cy.get(RISK_SCORE_STATUS).should('not.exist'); cy.get(RISK_SCORE_STATUS).should('not.exist');
updateRiskEngine(); upgradeRiskEngine();
updateRiskEngineConfirm();
cy.get(RISK_SCORE_STATUS).should('have.text', 'On');
deleteRiskScore({ riskScoreEntity: RiskScoreEntity.host, spaceId: 'default' }); deleteRiskScore({ riskScoreEntity: RiskScoreEntity.host, spaceId: 'default' });
}); });

View file

@ -1,125 +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 { getNewRule } from '../../../objects/rule';
import {
ENABLE_HOST_RISK_SCORE_BUTTON,
ENABLE_USER_RISK_SCORE_BUTTON,
RISK_SCORE_DASHBOARDS_INSTALLATION_SUCCESS_TOAST,
RISK_SCORE_INSTALLATION_SUCCESS_TOAST,
} from '../../../screens/entity_analytics';
import {
deleteRiskScore,
interceptInstallRiskScoreModule,
waitForInstallRiskScoreModule,
} from '../../../tasks/api_calls/risk_scores';
import { findSavedObjects } from '../../../tasks/api_calls/risk_scores/saved_objects';
import { createRule } from '../../../tasks/api_calls/rules';
import { cleanKibana } from '../../../tasks/common';
import { login } from '../../../tasks/login';
import { visitWithTimeRange } from '../../../tasks/navigation';
import { clickEnableRiskScore } from '../../../tasks/risk_scores';
import { RiskScoreEntity } from '../../../tasks/risk_scores/common';
import {
getRiskScoreLatestTransformId,
getRiskScorePivotTransformId,
getTransformState,
} from '../../../tasks/risk_scores/transforms';
import { ENTITY_ANALYTICS_URL } from '../../../urls/navigation';
const spaceId = 'default';
// FLAKY: https://github.com/elastic/kibana/issues/165644
describe('Enable risk scores', { tags: ['@ess', '@serverless', '@brokenInServerless'] }, () => {
before(() => {
cleanKibana();
login();
createRule(getNewRule({ rule_id: 'rule1' }));
});
beforeEach(() => {
login();
deleteRiskScore({ riskScoreEntity: RiskScoreEntity.host, spaceId });
deleteRiskScore({ riskScoreEntity: RiskScoreEntity.user, spaceId });
visitWithTimeRange(ENTITY_ANALYTICS_URL);
});
afterEach(() => {
deleteRiskScore({ riskScoreEntity: RiskScoreEntity.host, spaceId });
deleteRiskScore({ riskScoreEntity: RiskScoreEntity.user, spaceId });
});
it('shows enable host risk button', () => {
cy.get(ENABLE_HOST_RISK_SCORE_BUTTON).should('exist');
});
it('should install host risk score successfully', { tags: ['@brokenInServerless'] }, () => {
interceptInstallRiskScoreModule();
clickEnableRiskScore(RiskScoreEntity.host);
waitForInstallRiskScoreModule();
cy.get(ENABLE_HOST_RISK_SCORE_BUTTON).should('be.disabled');
cy.get(RISK_SCORE_INSTALLATION_SUCCESS_TOAST(RiskScoreEntity.host)).should('exist');
cy.get(RISK_SCORE_DASHBOARDS_INSTALLATION_SUCCESS_TOAST(RiskScoreEntity.host)).should('exist');
cy.get(ENABLE_HOST_RISK_SCORE_BUTTON).should('not.exist');
getTransformState(getRiskScorePivotTransformId(RiskScoreEntity.host, spaceId)).then((res) => {
expect(res.status).to.eq(200);
expect(res.body.transforms[0].id).to.eq(
getRiskScorePivotTransformId(RiskScoreEntity.host, spaceId)
);
expect(res.body.transforms[0].state).to.eq('started');
});
getTransformState(getRiskScoreLatestTransformId(RiskScoreEntity.host, spaceId)).then((res) => {
expect(res.status).to.eq(200);
expect(res.body.transforms[0].id).to.eq(
getRiskScoreLatestTransformId(RiskScoreEntity.host, spaceId)
);
expect(res.body.transforms[0].state).to.eq('started');
});
findSavedObjects(RiskScoreEntity.host, spaceId).then((res) => {
expect(res.status).to.eq(200);
expect(res.body.saved_objects.length).to.eq(11);
});
});
it('shows enable user risk button', () => {
cy.get(ENABLE_USER_RISK_SCORE_BUTTON).should('exist');
});
it('should install user risk score successfully', { tags: ['@brokenInServerless'] }, () => {
interceptInstallRiskScoreModule();
clickEnableRiskScore(RiskScoreEntity.user);
waitForInstallRiskScoreModule();
cy.get(ENABLE_USER_RISK_SCORE_BUTTON).should('be.disabled');
cy.get(RISK_SCORE_INSTALLATION_SUCCESS_TOAST(RiskScoreEntity.user)).should('exist');
cy.get(RISK_SCORE_DASHBOARDS_INSTALLATION_SUCCESS_TOAST(RiskScoreEntity.user)).should('exist');
cy.get(ENABLE_USER_RISK_SCORE_BUTTON).should('not.exist');
getTransformState(getRiskScorePivotTransformId(RiskScoreEntity.user, spaceId)).then((res) => {
expect(res.status).to.eq(200);
expect(res.body.transforms[0].id).to.eq(
getRiskScorePivotTransformId(RiskScoreEntity.user, spaceId)
);
expect(res.body.transforms[0].state).to.eq('started');
});
getTransformState(getRiskScoreLatestTransformId(RiskScoreEntity.user, spaceId)).then((res) => {
expect(res.status).to.eq(200);
expect(res.body.transforms[0].id).to.eq(
getRiskScoreLatestTransformId(RiskScoreEntity.user, spaceId)
);
expect(res.body.transforms[0].state).to.eq('started');
});
findSavedObjects(RiskScoreEntity.user, spaceId).then((res) => {
expect(res.status).to.eq(200);
expect(res.body.saved_objects.length).to.eq(11);
});
});
});

View file

@ -0,0 +1,53 @@
/*
* 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 {
ENABLE_HOST_RISK_SCORE_BUTTON,
ENABLE_USER_RISK_SCORE_BUTTON,
} from '../../../screens/entity_analytics';
import { cleanKibana } from '../../../tasks/common';
import { login } from '../../../tasks/login';
import { visit } from '../../../tasks/navigation';
import { clickEnableRiskScore } from '../../../tasks/risk_scores';
import { RiskScoreEntity } from '../../../tasks/risk_scores/common';
import { ENTITY_ANALYTICS_URL } from '../../../urls/navigation';
import { PAGE_TITLE } from '../../../screens/entity_analytics_management';
// FLAKY: https://github.com/elastic/kibana/issues/165644
describe(
'Enable risk scores from dashboard',
{ tags: ['@ess', '@serverless', '@brokenInServerless'] },
() => {
before(() => {
cleanKibana();
login();
});
beforeEach(() => {
login();
visit(ENTITY_ANALYTICS_URL);
});
it('host risk enable button should redirect to entity management page', () => {
cy.get(ENABLE_HOST_RISK_SCORE_BUTTON).should('exist');
clickEnableRiskScore(RiskScoreEntity.host);
cy.get(PAGE_TITLE).should('have.text', 'Entity Risk Score');
});
it('user risk enable button should redirect to entity management page', () => {
cy.get(ENABLE_USER_RISK_SCORE_BUTTON).should('exist');
clickEnableRiskScore(RiskScoreEntity.user);
cy.get(PAGE_TITLE).should('have.text', 'Entity Risk Score');
});
}
);

View file

@ -20,8 +20,6 @@ import {
HOSTS_DONUT_CHART, HOSTS_DONUT_CHART,
HOSTS_TABLE_ROWS, HOSTS_TABLE_ROWS,
HOST_RISK_SCORE_NO_DATA_DETECTED, HOST_RISK_SCORE_NO_DATA_DETECTED,
UPGRADE_HOST_RISK_SCORE_BUTTON,
UPGRADE_USER_RISK_SCORE_BUTTON,
USERS_DONUT_CHART, USERS_DONUT_CHART,
USERS_TABLE, USERS_TABLE,
USERS_TABLE_ROWS, USERS_TABLE_ROWS,
@ -35,7 +33,13 @@ import {
import { import {
openRiskTableFilterAndSelectTheLowOption, openRiskTableFilterAndSelectTheLowOption,
removeLowFilterAndCloseRiskTableFilter, removeLowFilterAndCloseRiskTableFilter,
openRiskTableFilterAndSelectTheCriticalOption,
removeCriticalFilterAndCloseRiskTableFilter,
} from '../../../tasks/host_risk'; } from '../../../tasks/host_risk';
import {
removeLowFilterAndCloseUserRiskTableFilter,
openUserRiskTableFilterAndSelectTheLowOption,
} from '../../../tasks/user_risk';
import { createRule } from '../../../tasks/api_calls/rules'; import { createRule } from '../../../tasks/api_calls/rules';
import { waitForAlertsToPopulate } from '../../../tasks/create_new_rule'; import { waitForAlertsToPopulate } from '../../../tasks/create_new_rule';
import { getNewRule } from '../../../objects/rule'; import { getNewRule } from '../../../objects/rule';
@ -49,6 +53,8 @@ import {
navigateToNextPage, navigateToNextPage,
waitForAnomaliesToBeLoaded, waitForAnomaliesToBeLoaded,
} from '../../../tasks/entity_analytics'; } from '../../../tasks/entity_analytics';
import { deleteRiskEngineConfiguration } from '../../../tasks/api_calls/risk_engine';
import { enableRiskEngine } from '../../../tasks/entity_analytics';
const TEST_USER_ALERTS = 2; const TEST_USER_ALERTS = 2;
const TEST_USER_NAME = 'test'; const TEST_USER_NAME = 'test';
@ -59,8 +65,11 @@ const END_DATE = 'Jan 19, 2019 @ 20:33:29.186';
describe('Entity Analytics Dashboard', { tags: ['@ess', '@brokenInServerless'] }, () => { describe('Entity Analytics Dashboard', { tags: ['@ess', '@brokenInServerless'] }, () => {
before(() => { before(() => {
cleanKibana(); cleanKibana();
login();
deleteRiskEngineConfiguration();
}); });
describe('legcay risk score', () => {
describe('Without data', () => { describe('Without data', () => {
beforeEach(() => { beforeEach(() => {
login(); login();
@ -117,12 +126,12 @@ describe('Entity Analytics Dashboard', { tags: ['@ess', '@brokenInServerless'] }
cy.task('esArchiverUnload', 'risk_users_legacy_data'); cy.task('esArchiverUnload', 'risk_users_legacy_data');
}); });
it('shows upgrade host risk button', () => { it('shows enable host risk button', () => {
cy.get(UPGRADE_HOST_RISK_SCORE_BUTTON).should('be.visible'); cy.get(ENABLE_HOST_RISK_SCORE_BUTTON).should('be.visible');
}); });
it('shows upgrade user risk button', () => { it('shows enable user risk button', () => {
cy.get(UPGRADE_USER_RISK_SCORE_BUTTON).should('be.visible'); cy.get(ENABLE_USER_RISK_SCORE_BUTTON).should('be.visible');
}); });
}); });
@ -302,6 +311,233 @@ describe('Entity Analytics Dashboard', { tags: ['@ess', '@brokenInServerless'] }
}); });
}); });
}); });
});
describe('new risk score', () => {
describe('Without data', () => {
beforeEach(() => {
login();
visitWithTimeRange(ENTITY_ANALYTICS_URL);
});
it('shows enable host and user risk button', () => {
cy.get(ENABLE_HOST_RISK_SCORE_BUTTON).should('be.visible');
cy.get(ENABLE_USER_RISK_SCORE_BUTTON).should('be.visible');
});
});
describe('Risk Score enabled but still no data', () => {
before(() => {
cy.task('esArchiverLoad', { archiveName: 'risk_scores_new_no_data' });
});
beforeEach(() => {
login();
enableRiskEngine();
visitWithTimeRange(ENTITY_ANALYTICS_URL);
});
afterEach(() => {
deleteRiskEngineConfiguration();
});
after(() => {
cy.task('esArchiverUnload', 'risk_scores_new_no_data');
});
it('shows no data detected prompt for host and user risk scores', () => {
cy.get(HOST_RISK_SCORE_NO_DATA_DETECTED).should('be.visible');
cy.get(USER_RISK_SCORE_NO_DATA_DETECTED).should('be.visible');
});
});
describe('With host risk data', () => {
before(() => {
cy.task('esArchiverLoad', { archiveName: 'risk_scores_new' });
login();
enableRiskEngine();
});
beforeEach(() => {
login();
visitWithTimeRange(ENTITY_ANALYTICS_URL);
});
after(() => {
cy.task('esArchiverUnload', 'risk_scores_new');
deleteRiskEngineConfiguration();
});
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(HOSTS_TABLE_ROWS).should('have.length', 5);
});
it('renders alerts column', () => {
cy.get(HOSTS_TABLE_ALERT_CELL).should('have.length', 5);
});
it('filters by risk classification', () => {
cy.get(HOSTS_DONUT_CHART).should('include.text', '6Total');
openRiskTableFilterAndSelectTheCriticalOption();
cy.get(HOSTS_DONUT_CHART).should('include.text', '1Total');
cy.get(HOSTS_TABLE_ROWS).should('have.length', 1);
removeCriticalFilterAndCloseRiskTableFilter();
});
it('filters the host risk table with KQL search bar query', () => {
kqlSearch(`host.name : ${SIEM_KIBANA_HOST_NAME}{enter}`);
cy.get(HOSTS_DONUT_CHART).should('include.text', '1Total');
cy.get(HOSTS_TABLE_ROWS).should('have.length', 1);
clearSearchBar();
});
describe('With alerts data', () => {
before(() => {
createRule(getNewRule());
});
beforeEach(() => {
login();
visitWithTimeRange(ALERTS_URL);
waitForAlertsToPopulate();
visitWithTimeRange(ENTITY_ANALYTICS_URL);
});
after(() => {
deleteAlertsAndRules();
});
it('populates alerts column', () => {
cy.get(HOSTS_TABLE_ALERT_CELL).first().should('include.text', SIEM_KIBANA_HOST_ALERTS);
});
it('filters the alerts count with time range', () => {
setEndDate(END_DATE);
updateDates();
cy.get(HOSTS_TABLE_ALERT_CELL).first().should('include.text', 0);
// CLEAR DATES
setEndDateNow();
updateDates();
});
it('opens alerts page when alerts count is clicked', () => {
clickOnFirstHostsAlerts();
cy.url().should('include', ALERTS_URL);
cy.get(OPTION_LIST_LABELS).eq(0).should('include.text', 'Status');
cy.get(OPTION_LIST_VALUES(0)).should('include.text', 'open');
cy.get(OPTION_LIST_LABELS).eq(1).should('include.text', 'Host');
cy.get(OPTION_LIST_VALUES(1)).should('include.text', SIEM_KIBANA_HOST_NAME);
});
});
});
describe('With user risk data', () => {
before(() => {
cy.task('esArchiverLoad', { archiveName: 'risk_scores_new' });
login();
enableRiskEngine();
});
beforeEach(() => {
login();
visitWithTimeRange(ENTITY_ANALYTICS_URL);
});
after(() => {
cy.task('esArchiverUnload', 'risk_scores_new');
deleteRiskEngineConfiguration();
});
it('renders donut chart', () => {
cy.get(USERS_DONUT_CHART).should('include.text', '7Total');
});
it('renders table', () => {
cy.get(USERS_TABLE).should('be.visible');
cy.get(USERS_TABLE_ROWS).should('have.length', 5);
});
it('renders alerts column', () => {
cy.get(USERS_TABLE_ALERT_CELL).should('have.length', 5);
});
it('filters by risk classification', () => {
cy.get(USERS_DONUT_CHART).should('include.text', '7Total');
openUserRiskTableFilterAndSelectTheLowOption(1);
cy.get(USERS_DONUT_CHART).should('include.text', '1Total');
cy.get(USERS_TABLE_ROWS).should('have.length', 1);
removeLowFilterAndCloseUserRiskTableFilter();
});
it('filters the host risk table with KQL search bar query', () => {
kqlSearch(`user.name : ${TEST_USER_NAME}{enter}`);
cy.get(USERS_DONUT_CHART).should('include.text', '1Total');
cy.get(USERS_TABLE_ROWS).should('have.length', 1);
clearSearchBar();
});
describe('With alerts data', () => {
before(() => {
createRule(getNewRule());
});
beforeEach(() => {
login();
visitWithTimeRange(ALERTS_URL);
waitForAlertsToPopulate();
visitWithTimeRange(ENTITY_ANALYTICS_URL);
});
after(() => {
deleteAlertsAndRules();
});
it('populates alerts column', () => {
cy.get(USERS_TABLE_ALERT_CELL).first().should('include.text', TEST_USER_ALERTS);
});
it('filters the alerts count with time range', () => {
setEndDate(END_DATE);
updateDates();
cy.get(USERS_TABLE_ALERT_CELL).first().should('include.text', 0);
// CLEAR DATES
setEndDateNow();
updateDates();
});
it('opens alerts page when alerts count is clicked', () => {
clickOnFirstUsersAlerts();
cy.url().should('include', ALERTS_URL);
cy.get(OPTION_LIST_LABELS).eq(0).should('include.text', 'Status');
cy.get(OPTION_LIST_VALUES(0)).should('include.text', 'open');
cy.get(OPTION_LIST_LABELS).eq(1).should('include.text', 'User');
cy.get(OPTION_LIST_VALUES(1)).should('include.text', TEST_USER_NAME);
});
});
});
});
describe('With anomalies data', () => { describe('With anomalies data', () => {
before(() => { before(() => {

View file

@ -7,35 +7,32 @@
import { getNewRule } from '../../../objects/rule'; import { getNewRule } from '../../../objects/rule';
import { import {
RISK_SCORE_INSTALLATION_SUCCESS_TOAST, UPGRADE_RISK_SCORE_BUTTON,
UPGRADE_HOST_RISK_SCORE_BUTTON, USERS_TABLE,
UPGRADE_USER_RISK_SCORE_BUTTON, HOSTS_TABLE_ROWS,
UPGRADE_CANCELLATION_BUTTON, HOSTS_TABLE,
UPGRADE_CONFIRMATION_MODAL, USERS_TABLE_ROWS,
RISK_SCORE_DASHBOARDS_INSTALLATION_SUCCESS_TOAST, HOST_RISK_SCORE_NO_DATA_DETECTED,
USER_RISK_SCORE_NO_DATA_DETECTED,
} from '../../../screens/entity_analytics'; } from '../../../screens/entity_analytics';
import { PAGE_TITLE } from '../../../screens/entity_analytics_management';
import { import {
deleteRiskScore, deleteRiskScore,
installLegacyRiskScoreModule, installLegacyRiskScoreModule,
installRiskScoreModule,
} from '../../../tasks/api_calls/risk_scores'; } from '../../../tasks/api_calls/risk_scores';
import { findSavedObjects } from '../../../tasks/api_calls/risk_scores/saved_objects'; import { clickUpgradeRiskScore } from '../../../tasks/risk_scores';
import { createRule } from '../../../tasks/api_calls/rules'; import { createRule } from '../../../tasks/api_calls/rules';
import { cleanKibana } from '../../../tasks/common'; import { cleanKibana } from '../../../tasks/common';
import { login } from '../../../tasks/login'; import { login } from '../../../tasks/login';
import { visitWithTimeRange } from '../../../tasks/navigation'; import { visitWithTimeRange } from '../../../tasks/navigation';
import {
clickUpgradeRiskScore,
clickUpgradeRiskScoreConfirmed,
interceptUpgradeRiskScoreModule,
waitForUpgradeRiskScoreModule,
} from '../../../tasks/risk_scores';
import { RiskScoreEntity } from '../../../tasks/risk_scores/common'; import { RiskScoreEntity } from '../../../tasks/risk_scores/common';
import {
getRiskScoreLatestTransformId,
getRiskScorePivotTransformId,
getTransformState,
} from '../../../tasks/risk_scores/transforms';
import { ENTITY_ANALYTICS_URL } from '../../../urls/navigation'; import { ENTITY_ANALYTICS_URL } from '../../../urls/navigation';
import { upgradeRiskEngine } from '../../../tasks/entity_analytics';
import { deleteRiskEngineConfiguration } from '../../../tasks/api_calls/risk_engine';
const spaceId = 'default'; const spaceId = 'default';
@ -44,9 +41,11 @@ describe('Upgrade risk scores', { tags: ['@ess', '@serverless', '@brokenInServer
before(() => { before(() => {
cleanKibana(); cleanKibana();
login(); login();
deleteRiskEngineConfiguration();
createRule(getNewRule({ rule_id: 'rule1' })); createRule(getNewRule({ rule_id: 'rule1' }));
}); });
describe('show upgrade risk button', () => {
beforeEach(() => { beforeEach(() => {
login(); login();
deleteRiskScore({ riskScoreEntity: RiskScoreEntity.host, spaceId }); deleteRiskScore({ riskScoreEntity: RiskScoreEntity.host, spaceId });
@ -56,140 +55,55 @@ describe('Upgrade risk scores', { tags: ['@ess', '@serverless', '@brokenInServer
visitWithTimeRange(ENTITY_ANALYTICS_URL); visitWithTimeRange(ENTITY_ANALYTICS_URL);
}); });
it('shows upgrade risk button for host and user', () => { afterEach(() => {
cy.get(UPGRADE_HOST_RISK_SCORE_BUTTON).should('be.visible'); deleteRiskScore({ riskScoreEntity: RiskScoreEntity.host, spaceId });
cy.get(UPGRADE_USER_RISK_SCORE_BUTTON).should('be.visible'); deleteRiskScore({ riskScoreEntity: RiskScoreEntity.user, spaceId });
cy.task('esArchiverUnload', 'risk_hosts');
cy.task('esArchiverUnload', 'risk_users');
}); });
it( it('shows upgrade panel', () => {
'should show a confirmation modal for upgrading host risk score and display a link to host risk score Elastic doc', cy.get(UPGRADE_RISK_SCORE_BUTTON).should('be.visible');
{ tags: ['@brokenInServerless'] },
() => {
clickUpgradeRiskScore(RiskScoreEntity.host);
cy.get(UPGRADE_CONFIRMATION_MODAL(RiskScoreEntity.host)).should('exist');
cy.get(UPGRADE_CANCELLATION_BUTTON) clickUpgradeRiskScore();
.get(`${UPGRADE_CONFIRMATION_MODAL(RiskScoreEntity.host)} a`)
.then((link) => { cy.get(PAGE_TITLE).should('have.text', 'Entity Risk Score');
expect(link.prop('href')).to.eql(
`https://www.elastic.co/guide/en/security/current/${RiskScoreEntity.host}-risk-score.html`
);
}); });
}
);
it(
'should show a confirmation modal for upgrading user risk score and display a link to user risk score Elastic doc',
{ tags: ['@brokenInServerless'] },
() => {
clickUpgradeRiskScore(RiskScoreEntity.user);
cy.get(UPGRADE_CONFIRMATION_MODAL(RiskScoreEntity.user)).should('exist');
cy.get(UPGRADE_CANCELLATION_BUTTON)
.get(`${UPGRADE_CONFIRMATION_MODAL(RiskScoreEntity.user)} a`)
.then((link) => {
expect(link.prop('href')).to.eql(
`https://www.elastic.co/guide/en/security/current/${RiskScoreEntity.user}-risk-score.html`
);
});
}
);
}); });
const versions: Array<'8.3' | '8.4'> = ['8.3', '8.4']; describe('upgrade risk engine', () => {
versions.forEach((version) =>
describe(`handles version ${version} upgrades`, () => {
before(() => { before(() => {
cleanKibana(); cy.task('esArchiverLoad', { archiveName: 'risk_hosts' });
cy.task('esArchiverLoad', { archiveName: 'risk_users' });
}); });
beforeEach(() => { beforeEach(() => {
login(); login();
createRule(getNewRule({ rule_id: 'rule1' })); installRiskScoreModule();
deleteRiskScore({ riskScoreEntity: RiskScoreEntity.host, spaceId });
deleteRiskScore({ riskScoreEntity: RiskScoreEntity.user, spaceId });
installLegacyRiskScoreModule(RiskScoreEntity.host, spaceId, version);
installLegacyRiskScoreModule(RiskScoreEntity.user, spaceId, version);
visitWithTimeRange(ENTITY_ANALYTICS_URL); visitWithTimeRange(ENTITY_ANALYTICS_URL);
}); });
afterEach(() => { after(() => {
cy.task('esArchiverUnload', 'risk_hosts');
cy.task('esArchiverUnload', 'risk_users');
deleteRiskScore({ riskScoreEntity: RiskScoreEntity.host, spaceId }); deleteRiskScore({ riskScoreEntity: RiskScoreEntity.host, spaceId });
deleteRiskScore({ riskScoreEntity: RiskScoreEntity.user, spaceId }); deleteRiskScore({ riskScoreEntity: RiskScoreEntity.user, spaceId });
deleteRiskEngineConfiguration();
}); });
it('should upgrade host risk score successfully', () => { it('show old risk score data before upgrade, and hide after', () => {
clickUpgradeRiskScore(RiskScoreEntity.host); cy.get(HOSTS_TABLE).should('be.visible');
cy.get(HOSTS_TABLE_ROWS).should('have.length', 5);
interceptUpgradeRiskScoreModule(RiskScoreEntity.host, version); cy.get(USERS_TABLE).should('be.visible');
cy.get(USERS_TABLE_ROWS).should('have.length', 5);
clickUpgradeRiskScoreConfirmed(); upgradeRiskEngine();
waitForUpgradeRiskScoreModule();
cy.get(UPGRADE_HOST_RISK_SCORE_BUTTON).should('be.disabled'); visitWithTimeRange(ENTITY_ANALYTICS_URL);
cy.get(RISK_SCORE_INSTALLATION_SUCCESS_TOAST(RiskScoreEntity.host)).should('exist'); cy.get(HOST_RISK_SCORE_NO_DATA_DETECTED).should('be.visible');
cy.get(RISK_SCORE_DASHBOARDS_INSTALLATION_SUCCESS_TOAST(RiskScoreEntity.host)).should( cy.get(USER_RISK_SCORE_NO_DATA_DETECTED).should('be.visible');
'exist'
);
cy.get(UPGRADE_HOST_RISK_SCORE_BUTTON).should('not.exist');
getTransformState(getRiskScorePivotTransformId(RiskScoreEntity.host, spaceId)).then((res) => {
expect(res.status).to.eq(200);
expect(res.body.transforms[0].id).to.eq(
getRiskScorePivotTransformId(RiskScoreEntity.host, spaceId)
);
expect(res.body.transforms[0].state).to.eq('started');
});
getTransformState(getRiskScoreLatestTransformId(RiskScoreEntity.host, spaceId)).then(
(res) => {
expect(res.status).to.eq(200);
expect(res.body.transforms[0].id).to.eq(
getRiskScoreLatestTransformId(RiskScoreEntity.host, spaceId)
);
expect(res.body.transforms[0].state).to.eq('started');
}
);
findSavedObjects(RiskScoreEntity.host, spaceId).then((res) => {
expect(res.status).to.eq(200);
expect(res.body.saved_objects.length).to.eq(11);
}); });
}); });
it('should upgrade user risk score successfully', () => {
clickUpgradeRiskScore(RiskScoreEntity.user);
interceptUpgradeRiskScoreModule(RiskScoreEntity.user);
clickUpgradeRiskScoreConfirmed();
waitForUpgradeRiskScoreModule();
cy.get(UPGRADE_USER_RISK_SCORE_BUTTON).should('be.disabled');
cy.get(RISK_SCORE_INSTALLATION_SUCCESS_TOAST(RiskScoreEntity.user)).should('exist');
cy.get(RISK_SCORE_DASHBOARDS_INSTALLATION_SUCCESS_TOAST(RiskScoreEntity.user)).should(
'exist'
);
cy.get(UPGRADE_USER_RISK_SCORE_BUTTON).should('not.exist');
getTransformState(getRiskScorePivotTransformId(RiskScoreEntity.user, spaceId)).then((res) => {
expect(res.status).to.eq(200);
expect(res.body.transforms[0].id).to.eq(
getRiskScorePivotTransformId(RiskScoreEntity.user, spaceId)
);
expect(res.body.transforms[0].state).to.eq('started');
}); });
getTransformState(getRiskScoreLatestTransformId(RiskScoreEntity.user, spaceId)).then(
(res) => {
expect(res.status).to.eq(200);
expect(res.body.transforms[0].id).to.eq(
getRiskScoreLatestTransformId(RiskScoreEntity.user, spaceId)
);
expect(res.body.transforms[0].state).to.eq('started');
}
);
findSavedObjects(RiskScoreEntity.user, spaceId).then((res) => {
expect(res.status).to.eq(200);
expect(res.body.saved_objects.length).to.eq(11);
});
});
})
);

View file

@ -10,8 +10,14 @@ import { visitHostDetailsPage } from '../../../tasks/navigation';
import { cleanKibana, waitForTableToLoad } from '../../../tasks/common'; import { cleanKibana, waitForTableToLoad } from '../../../tasks/common';
import { TABLE_CELL, TABLE_ROWS } from '../../../screens/alerts_details'; import { TABLE_CELL, TABLE_ROWS } from '../../../screens/alerts_details';
import { deleteRiskEngineConfiguration } from '../../../tasks/api_calls/risk_engine';
import { openRiskInformationFlyout, enableRiskEngine } from '../../../tasks/entity_analytics';
import { ALERTS_COUNT, ALERT_GRID_CELL } from '../../../screens/alerts';
import { RISK_INFORMATION_FLYOUT_HEADER } from '../../../screens/entity_analytics';
import { navigateToHostRiskDetailTab } from '../../../tasks/host_risk';
describe('risk tab', { tags: ['@ess', '@serverless', '@brokenInServerless'] }, () => { describe('risk tab', { tags: ['@ess', '@serverless', '@brokenInServerless'] }, () => {
describe('with legacy risk score', () => {
before(() => { before(() => {
cleanKibana(); cleanKibana();
// illegal_argument_exception: unknown setting [index.lifecycle.rollover_alias] // illegal_argument_exception: unknown setting [index.lifecycle.rollover_alias]
@ -20,6 +26,7 @@ describe('risk tab', { tags: ['@ess', '@serverless', '@brokenInServerless'] }, (
beforeEach(() => { beforeEach(() => {
login(); login();
deleteRiskEngineConfiguration();
}); });
after(() => { after(() => {
@ -28,7 +35,7 @@ describe('risk tab', { tags: ['@ess', '@serverless', '@brokenInServerless'] }, (
it('renders risk tab', () => { it('renders risk tab', () => {
visitHostDetailsPage('siem-kibana'); visitHostDetailsPage('siem-kibana');
cy.get('[data-test-subj="navigation-hostRisk"]').click(); navigateToHostRiskDetailTab();
waitForTableToLoad(); waitForTableToLoad();
cy.get('[data-test-subj="topRiskScoreContributors"]') cy.get('[data-test-subj="topRiskScoreContributors"]')
@ -40,13 +47,51 @@ describe('risk tab', { tags: ['@ess', '@serverless', '@brokenInServerless'] }, (
it('shows risk information overlay when button is clicked', () => { it('shows risk information overlay when button is clicked', () => {
visitHostDetailsPage('siem-kibana'); visitHostDetailsPage('siem-kibana');
cy.get('[data-test-subj="navigation-hostRisk"]').click(); navigateToHostRiskDetailTab();
waitForTableToLoad(); waitForTableToLoad();
cy.get('[data-test-subj="open-risk-information-flyout-trigger"]').click(); openRiskInformationFlyout();
cy.get('[data-test-subj="open-risk-information-flyout"] .euiFlyoutHeader').contains( cy.get(RISK_INFORMATION_FLYOUT_HEADER).contains('How is host risk calculated?');
'How is host risk calculated?' });
); });
describe('with new risk score', () => {
before(() => {
cleanKibana();
cy.task('esArchiverLoad', { archiveName: 'risk_scores_new' });
cy.task('esArchiverLoad', { archiveName: 'query_alert' });
login();
enableRiskEngine();
});
beforeEach(() => {
login();
});
after(() => {
cy.task('esArchiverUnload', 'risk_scores_new');
cy.task('esArchiverUnload', 'query_alert');
deleteRiskEngineConfiguration();
});
it('renders risk tab', () => {
visitHostDetailsPage('Host-fwarau82er');
navigateToHostRiskDetailTab();
waitForTableToLoad();
cy.get(ALERTS_COUNT).should('have.text', '1 alert');
cy.get(ALERT_GRID_CELL).contains('Endpoint Security');
});
it('shows risk information overlay when button is clicked', () => {
visitHostDetailsPage('siem-kibana');
navigateToHostRiskDetailTab();
waitForTableToLoad();
openRiskInformationFlyout();
cy.get(RISK_INFORMATION_FLYOUT_HEADER).contains('How is host risk calculated?');
});
}); });
}); });

View file

@ -18,20 +18,28 @@ import {
HOST_BY_RISK_TABLE_NEXT_PAGE_BUTTON, HOST_BY_RISK_TABLE_NEXT_PAGE_BUTTON,
} from '../../../screens/hosts/host_risk'; } from '../../../screens/hosts/host_risk';
import { login } from '../../../tasks/login'; import { login } from '../../../tasks/login';
import { visit } from '../../../tasks/navigation'; import { visitWithTimeRange } from '../../../tasks/navigation';
import { hostsUrl } from '../../../urls/navigation'; import { hostsUrl } from '../../../urls/navigation';
import { clearSearchBar, kqlSearch } from '../../../tasks/security_header'; import { clearSearchBar, kqlSearch } from '../../../tasks/security_header';
import { deleteRiskEngineConfiguration } from '../../../tasks/api_calls/risk_engine';
import { enableRiskEngine } from '../../../tasks/entity_analytics';
// Tracked by https://github.com/elastic/security-team/issues/7696 // Tracked by https://github.com/elastic/security-team/issues/7696
describe.skip('risk tab', { tags: ['@ess', '@brokenInServerless'] }, () => { describe('risk tab', { tags: ['@ess', '@brokenInServerless'] }, () => {
describe('with legacy risk score', () => {
before(() => { before(() => {
cleanKibana(); cleanKibana();
login();
deleteRiskEngineConfiguration();
cy.task('esArchiverLoad', { archiveName: 'risk_hosts' }); cy.task('esArchiverLoad', { archiveName: 'risk_hosts' });
}); });
beforeEach(() => { beforeEach(() => {
login(); login();
visit(hostsUrl('allHosts')); visitWithTimeRange(hostsUrl('allHosts'));
// by some reason after navigate to host risk, page is sometimes is reload or go to all host tab
// this fix wait until we fave host in all host table, and then we go to risk tab
cy.contains('siem-kibana');
navigateToHostRiskDetailTab(); navigateToHostRiskDetailTab();
}); });
@ -68,3 +76,56 @@ describe.skip('risk tab', { tags: ['@ess', '@brokenInServerless'] }, () => {
clearSearchBar(); clearSearchBar();
}); });
}); });
describe('with new risk score', () => {
before(() => {
cleanKibana();
cy.task('esArchiverLoad', { archiveName: 'risk_scores_new' });
login();
enableRiskEngine();
});
beforeEach(() => {
login();
visitWithTimeRange(hostsUrl('allHosts'));
// by some reason after navigate to host risk, page is sometimes is reload or go to all host tab
// this fix wait until we fave host in all host table, and then we go to risk tab
cy.contains('siem-kibana');
navigateToHostRiskDetailTab();
});
after(() => {
cy.task('esArchiverUnload', 'risk_scores_new');
deleteRiskEngineConfiguration();
});
it('renders the table', () => {
kqlSearch('host.name: "siem-kibana" {enter}');
cy.get(HOST_BY_RISK_TABLE_CELL).eq(3).should('have.text', 'siem-kibana');
cy.get(HOST_BY_RISK_TABLE_CELL).eq(4).should('have.text', '90');
cy.get(HOST_BY_RISK_TABLE_CELL).eq(5).should('have.text', 'Critical');
clearSearchBar();
});
it.skip('filters the table', () => {
openRiskTableFilterAndSelectTheCriticalOption();
cy.get(HOST_BY_RISK_TABLE_CELL).eq(3).should('not.have.text', 'siem-kibana');
removeCriticalFilterAndCloseRiskTableFilter();
});
// Flaky
it.skip('should be able to change items count per page', () => {
selectFiveItemsPerPageOption();
cy.get(HOST_BY_RISK_TABLE_HOSTNAME_CELL).should('have.length', 5);
});
it('should not allow page change when page is empty', () => {
kqlSearch('host.name: "nonexistent_host" {enter}');
cy.get(HOST_BY_RISK_TABLE_NEXT_PAGE_BUTTON).should(`not.exist`);
clearSearchBar();
});
});
});

View file

@ -12,8 +12,11 @@ import { hostsUrl } from '../../../urls/navigation';
import { cleanKibana } from '../../../tasks/common'; import { cleanKibana } from '../../../tasks/common';
import { TABLE_CELL } from '../../../screens/alerts_details'; import { TABLE_CELL } from '../../../screens/alerts_details';
import { kqlSearch } from '../../../tasks/security_header'; import { kqlSearch } from '../../../tasks/security_header';
import { deleteRiskEngineConfiguration } from '../../../tasks/api_calls/risk_engine';
import { enableRiskEngine } from '../../../tasks/entity_analytics';
describe('All hosts table', { tags: ['@ess', '@serverless', '@brokenInServerless'] }, () => { describe('All hosts table', { tags: ['@ess', '@serverless', '@brokenInServerless'] }, () => {
describe('with legacy risk score', () => {
before(() => { before(() => {
cleanKibana(); cleanKibana();
// illegal_argument_exception: unknown setting [index.lifecycle.name] // illegal_argument_exception: unknown setting [index.lifecycle.name]
@ -22,6 +25,7 @@ describe('All hosts table', { tags: ['@ess', '@serverless', '@brokenInServerless
beforeEach(() => { beforeEach(() => {
login(); login();
deleteRiskEngineConfiguration();
}); });
after(() => { after(() => {
@ -36,3 +40,30 @@ describe('All hosts table', { tags: ['@ess', '@serverless', '@brokenInServerless
cy.get(`${TABLE_CELL} .euiTableCellContent`).eq(4).should('have.text', 'Low'); cy.get(`${TABLE_CELL} .euiTableCellContent`).eq(4).should('have.text', 'Low');
}); });
}); });
describe('with new risk score', () => {
before(() => {
cleanKibana();
// illegal_argument_exception: unknown setting [index.lifecycle.name]
cy.task('esArchiverLoad', { archiveName: 'risk_scores_new' });
});
beforeEach(() => {
login();
enableRiskEngine();
});
after(() => {
cy.task('esArchiverUnload', 'risk_scores_new');
deleteRiskEngineConfiguration();
});
it('it renders risk column', () => {
visitWithTimeRange(hostsUrl('allHosts'));
kqlSearch('host.name: "siem-kibana" {enter}');
cy.get('[data-test-subj="tableHeaderCell_node.risk_4"]').should('exist');
cy.get(`${TABLE_CELL} .euiTableCellContent`).eq(4).should('have.text', 'Critical');
});
});
});

View file

@ -13,6 +13,8 @@ export const UPGRADE_HOST_RISK_SCORE_BUTTON = '[data-test-subj="host-risk-score-
export const UPGRADE_USER_RISK_SCORE_BUTTON = '[data-test-subj="user-risk-score-upgrade"]'; export const UPGRADE_USER_RISK_SCORE_BUTTON = '[data-test-subj="user-risk-score-upgrade"]';
export const UPGRADE_RISK_SCORE_BUTTON = '[data-test-subj="update-risk-score-button"]';
export const HOST_RISK_SCORE_NO_DATA_DETECTED = export const HOST_RISK_SCORE_NO_DATA_DETECTED =
'[data-test-subj="host-risk-score-no-data-detected"]'; '[data-test-subj="host-risk-score-no-data-detected"]';
@ -68,3 +70,9 @@ export const USERS_TABLE_ALERT_CELL =
export const HOSTS_TABLE_ALERT_CELL = export const HOSTS_TABLE_ALERT_CELL =
'[data-test-subj="entity_analytics_hosts"] [data-test-subj="risk-score-alerts"]'; '[data-test-subj="entity_analytics_hosts"] [data-test-subj="risk-score-alerts"]';
export const OPEN_RISK_INFORMATION_FLYOUT_BUTTON =
'[data-test-subj="open-risk-information-flyout-trigger"]';
export const RISK_INFORMATION_FLYOUT_HEADER =
'[data-test-subj="open-risk-information-flyout"] .euiFlyoutHeader';

View file

@ -29,7 +29,7 @@ export const RISK_SCORE_UPDATE_CANCEL = '[data-test-subj="risk-score-update-canc
export const RISK_SCORE_UPDATE_CONFIRM = '[data-test-subj="risk-score-update-confirm"]'; export const RISK_SCORE_UPDATE_CONFIRM = '[data-test-subj="risk-score-update-confirm"]';
export const RISK_SCORE_UDATE_BUTTON = '[data-test-subj="risk-score-update-button"]'; export const RISK_SCORE_UPDATE_BUTTON = '[data-test-subj="risk-score-update-button"]';
export const RISK_SCORE_STATUS = '[data-test-subj="risk-score-status"]'; export const RISK_SCORE_STATUS = '[data-test-subj="risk-score-status"]';

View file

@ -7,3 +7,6 @@
export const RISK_SCORE_TAB = '[data-test-subj="navigation-userRisk"]'; export const RISK_SCORE_TAB = '[data-test-subj="navigation-userRisk"]';
export const RISK_SCORE_TAB_CONTENT = '[data-test-subj="table-userRisk-loading-false"]'; export const RISK_SCORE_TAB_CONTENT = '[data-test-subj="table-userRisk-loading-false"]';
export const USER_BY_RISK_TABLE_FILTER = '[data-test-subj="risk-filter-button"]';
export const USER_BY_RISK_TABLE_FILTER_LOW = '[data-test-subj="risk-filter-item-Low"]';

View file

@ -5,7 +5,7 @@
* 2.0. * 2.0.
*/ */
export const deleteConfiguration = () => { export const deleteRiskEngineConfiguration = () => {
cy.request({ cy.request({
method: 'GET', method: 'GET',
url: `/api/saved_objects/_find?type=risk-engine-configuration`, url: `/api/saved_objects/_find?type=risk-engine-configuration`,

View file

@ -10,11 +10,13 @@ import {
ANOMALIES_TABLE_ROWS, ANOMALIES_TABLE_ROWS,
ANOMALIES_TABLE_ENABLE_JOB_BUTTON, ANOMALIES_TABLE_ENABLE_JOB_BUTTON,
ANOMALIES_TABLE_NEXT_PAGE_BUTTON, ANOMALIES_TABLE_NEXT_PAGE_BUTTON,
OPEN_RISK_INFORMATION_FLYOUT_BUTTON,
} from '../screens/entity_analytics'; } from '../screens/entity_analytics';
import { ENTITY_ANALYTICS_URL } from '../urls/navigation'; import { RISK_SCORE_STATUS } from '../screens/entity_analytics_management';
import { ENTITY_ANALYTICS_URL, ENTITY_ANALYTICS_MANAGEMENT_URL } from '../urls/navigation';
import { import {
RISK_SCORE_UPDATE_CONFIRM, RISK_SCORE_UPDATE_CONFIRM,
RISK_SCORE_UDATE_BUTTON, RISK_SCORE_UPDATE_BUTTON,
RISK_SCORE_SWITCH, RISK_SCORE_SWITCH,
RISK_PREVIEW_ERROR_BUTTON, RISK_PREVIEW_ERROR_BUTTON,
} from '../screens/entity_analytics_management'; } from '../screens/entity_analytics_management';
@ -42,8 +44,14 @@ export const riskEngineStatusChange = () => {
cy.get(RISK_SCORE_SWITCH).click(); cy.get(RISK_SCORE_SWITCH).click();
}; };
export const enableRiskEngine = () => {
cy.visit(ENTITY_ANALYTICS_MANAGEMENT_URL);
cy.get(RISK_SCORE_STATUS).should('have.text', 'Off');
riskEngineStatusChange();
};
export const updateRiskEngine = () => { export const updateRiskEngine = () => {
cy.get(RISK_SCORE_UDATE_BUTTON).click(); cy.get(RISK_SCORE_UPDATE_BUTTON).click();
}; };
export const updateRiskEngineConfirm = () => { export const updateRiskEngineConfirm = () => {
@ -53,3 +61,12 @@ export const updateRiskEngineConfirm = () => {
export const previewErrorButtonClick = () => { export const previewErrorButtonClick = () => {
cy.get(RISK_PREVIEW_ERROR_BUTTON).click(); cy.get(RISK_PREVIEW_ERROR_BUTTON).click();
}; };
export const openRiskInformationFlyout = () => cy.get(OPEN_RISK_INFORMATION_FLYOUT_BUTTON).click();
export const upgradeRiskEngine = () => {
visitWithTimeRange(ENTITY_ANALYTICS_MANAGEMENT_URL);
updateRiskEngine();
updateRiskEngineConfirm();
cy.get(RISK_SCORE_STATUS).should('have.text', 'On');
};

View file

@ -21,7 +21,7 @@ export const navigateToHostRiskDetailTab = () => {
}; };
export const openRiskTableFilterAndSelectTheCriticalOption = () => { export const openRiskTableFilterAndSelectTheCriticalOption = () => {
cy.get(HOST_BY_RISK_TABLE_FILTER).click(); cy.get(HOST_BY_RISK_TABLE_FILTER).first().click();
cy.get(HOST_BY_RISK_TABLE_FILTER_CRITICAL).click(); cy.get(HOST_BY_RISK_TABLE_FILTER_CRITICAL).click();
}; };

View file

@ -10,8 +10,7 @@ import {
ENABLE_USER_RISK_SCORE_BUTTON, ENABLE_USER_RISK_SCORE_BUTTON,
HOSTS_TABLE_ALERT_CELL, HOSTS_TABLE_ALERT_CELL,
UPGRADE_CONFIRMATION_BUTTON, UPGRADE_CONFIRMATION_BUTTON,
UPGRADE_HOST_RISK_SCORE_BUTTON, UPGRADE_RISK_SCORE_BUTTON,
UPGRADE_USER_RISK_SCORE_BUTTON,
USERS_TABLE_ALERT_CELL, USERS_TABLE_ALERT_CELL,
} from '../../screens/entity_analytics'; } from '../../screens/entity_analytics';
import { import {
@ -68,13 +67,8 @@ export const clickEnableRiskScore = (riskScoreEntity: RiskScoreEntity) => {
cy.get(button).click(); cy.get(button).click();
}; };
export const clickUpgradeRiskScore = (riskScoreEntity: RiskScoreEntity) => { export const clickUpgradeRiskScore = () => {
const button = cy.get(UPGRADE_RISK_SCORE_BUTTON).click();
riskScoreEntity === RiskScoreEntity.user
? UPGRADE_USER_RISK_SCORE_BUTTON
: UPGRADE_HOST_RISK_SCORE_BUTTON;
cy.get(button).click();
}; };
export const clickUpgradeRiskScoreConfirmed = () => { export const clickUpgradeRiskScoreConfirmed = () => {

View file

@ -0,0 +1,21 @@
/*
* 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 {
USER_BY_RISK_TABLE_FILTER,
USER_BY_RISK_TABLE_FILTER_LOW,
} from '../screens/users/user_risk_score';
export const openUserRiskTableFilterAndSelectTheLowOption = (eq = 0) => {
cy.get(USER_BY_RISK_TABLE_FILTER).eq(eq).click();
cy.get(USER_BY_RISK_TABLE_FILTER_LOW).click();
};
export const removeLowFilterAndCloseUserRiskTableFilter = () => {
cy.get(USER_BY_RISK_TABLE_FILTER_LOW).click();
cy.get(USER_BY_RISK_TABLE_FILTER).first().click();
};

View file

@ -119,6 +119,9 @@
"path": "C:/fake_malware.exe", "path": "C:/fake_malware.exe",
"size": 3456 "size": 3456
}, },
"user": {
"name": "user1"
},
"host": { "host": {
"architecture": "wtnozeqvub", "architecture": "wtnozeqvub",
"hostname": "Host-fwarau82er", "hostname": "Host-fwarau82er",

View file

@ -0,0 +1,485 @@
{
"type": "doc",
"value": {
"id": "a4cf452c1e0375c3d4412cb550ad1783358468a3b3b777da4829d72c7d6fb74f",
"index": "risk-score.risk-score-latest-default",
"source": {
"@timestamp": "2021-03-10T14:51:05.766Z",
"host": {
"name": "siem-kibana",
"risk": {
"calculated_level": "Critical",
"calculated_score_norm": 90,
"id_field": "host.name",
"id_value": "siem-kibana",
"calculated_score": 150,
"category_1_score": 150,
"category_1_count": 1,
"notes": [],
"inputs": [
{
"id": "62895f54816047b9bf82929a61a6c571f41de9c2361670f6ef0136360e006f58",
"index": ".internal.alerts-security.alerts-default-000001",
"description": "New Rule Test",
"category": "category_1",
"risk_score": 70,
"timestamp": "2023-08-14T09:08:18.664Z"
},
{
"id": "e5bf3da3c855486ac7b40fa1aa33e19cf1380e413b79ed76bddf728f8fec4462",
"index": ".internal.alerts-security.alerts-default-000001",
"description": "New Rule Test",
"category": "category_1",
"risk_score": 70,
"timestamp": "2023-08-14T09:08:18.664Z"
}
]
}
}
}
}
}
{
"type": "doc",
"value": {
"id": "a2cf452c1e0375c3d4412cb550bd1783358468a3b3b777da4829d72c7d6fb71f",
"index": "risk-score.risk-score-latest-default",
"source": {
"@timestamp": "2021-03-10T14:51:05.766Z",
"host": {
"name": "fake-1",
"risk": {
"calculated_level": "Moderate",
"calculated_score_norm": 50,
"id_field": "host.name",
"id_value": "fake-1",
"calculated_score": 200,
"category_1_score": 200,
"category_1_count": 1,
"notes": [],
"inputs": [
{
"id": "2e17f189-d77d-4537-8d84-592e29334493",
"index": ".internal.alerts-security.alerts-default-000001",
"description": "Alert from Rule: Rule 2",
"category": "category_1",
"risk_score": 70,
"timestamp": "2023-08-14T09:08:18.664Z"
}
]
}
}
}
}
}
{
"type": "doc",
"value": {
"id": "a2cf452c1e0375c3d4412cb550bd1283358468a3b3b777da4829d72c7d6fb72f",
"index": "risk-score.risk-score-latest-default",
"source": {
"@timestamp": "2021-03-10T14:51:05.766Z",
"host": {
"name": "fake-2",
"risk": {
"calculated_level": "Moderate",
"calculated_score_norm": 50,
"id_field": "host.name",
"id_value": "fake-2",
"calculated_score": 220,
"category_1_score": 200,
"category_1_count": 1,
"notes": [],
"inputs": [
{
"id": "2e17f189-d77d-4537-8d84-592e29334493",
"index": ".internal.alerts-security.alerts-default-000001",
"description": "Alert from Rule: Rule 2",
"category": "category_1",
"risk_score": 70,
"timestamp": "2023-08-14T09:08:18.664Z"
}
]
}
}
}
}
}
{
"type": "doc",
"value": {
"id": "a2cf452c1e0375c3d4412cb550bd1782358468a3b3b777da4829d72c7d6fb73f",
"index": "risk-score.risk-score-latest-default",
"source": {
"@timestamp": "2021-03-10T14:51:05.766Z",
"host": {
"name": "fake-3",
"risk": {
"calculated_level": "Moderate",
"calculated_score_norm": 50,
"id_field": "host.name",
"id_value": "fake-3",
"calculated_score": 220,
"category_1_score": 220,
"category_1_count": 1,
"notes": [],
"inputs": [
{
"id": "2e17f189-d77d-4537-8d84-592e29334493",
"index": ".internal.alerts-security.alerts-default-000001",
"description": "Alert from Rule: Rule 2",
"category": "category_1",
"risk_score": 70,
"timestamp": "2023-08-14T09:08:18.664Z"
}
]
}
}
}
}
}
{
"type": "doc",
"value": {
"id": "a2cf452c1e0375c3d4412cb550bd1783358468a3b3b777da4829d72c7d6fb745",
"index": "risk-score.risk-score-latest-default",
"source": {
"@timestamp": "2021-03-10T14:51:05.766Z",
"host": {
"name": "fake-4",
"risk": {
"calculated_level": "Moderate",
"calculated_score_norm": 50,
"id_field": "host.name",
"id_value": "fake-4",
"calculated_score": 220,
"category_1_score": 200,
"category_1_count": 1,
"notes": [],
"inputs": [
{
"id": "2e17f189-d77d-4537-8d84-592e29334493",
"index": ".internal.alerts-security.alerts-default-000001",
"description": "Alert from Rule: Rule 2",
"category": "category_1",
"risk_score": 70,
"timestamp": "2023-08-14T09:08:18.664Z"
}
]
}
}
}
}
}
{
"type": "doc",
"value": {
"id": "a2cf452c1e0375c3d4412cb550bd1783358468a3b3b777da4829d72c7d6fb752",
"index": "risk-score.risk-score-latest-default",
"source": {
"@timestamp": "2021-03-10T14:51:05.766Z",
"host": {
"name": "fake-5",
"risk": {
"calculated_level": "Moderate",
"calculated_score_norm": 50,
"id_field": "host.name",
"id_value": "fake-5",
"calculated_score": 220,
"category_1_score": 220,
"category_1_count": 1,
"notes": [],
"inputs": [
{
"id": "2e17f189-d77d-4537-8d84-592e29334493",
"index": ".internal.alerts-security.alerts-default-000001",
"description": "Alert from Rule: Rule 2",
"category": "category_1",
"risk_score": 70,
"timestamp": "2023-08-14T09:08:18.664Z"
}
]
}
}
}
}
}
{
"type": "doc",
"value": {
"id": "a2cf452c1e0375c3d4412cb550bd1783358468a3b3b777da4829d72c7d6fb752",
"index": "risk-score.risk-score-latest-default",
"source": {
"@timestamp": "2021-03-10T14:51:05.766Z",
"host": {
"name": "Host-fwarau82er",
"risk": {
"calculated_level": "Moderate",
"calculated_score_norm": 50,
"id_field": "host.name",
"id_value": "Host-fwarau82er",
"calculated_score": 220,
"category_1_score": 220,
"category_1_count": 1,
"notes": [],
"inputs": [
{
"id": "eabbdefc23da981f2b74ab58b82622a97bb9878caa11bc914e2adfacc94780f1",
"index": ".internal.alerts-security.alerts-default-000001",
"description": "Endpoint Security",
"category": "category_1",
"risk_score": 70,
"timestamp": "2023-08-14T09:08:18.664Z"
}
]
}
}
}
}
}
{
"type": "doc",
"value": {
"id": "a2cf452c1e0375c3d4412cb550bd1783358468a3b3b777da4829d72c7d2fb74f",
"index": "risk-score.risk-score-latest-default",
"source": {
"@timestamp": "2021-03-10T14:51:05.766Z",
"user": {
"name": "user2",
"risk": {
"calculated_score_norm": 50,
"calculated_level": "Moderate",
"id_field": "user.name",
"id_value": "user2",
"calculated_score": 150,
"category_1_score": 150,
"category_1_count": 1,
"notes": [],
"inputs": [
{
"id": "2e17f189-d77d-4537-8d84-592e29334493",
"index": ".internal.alerts-security.alerts-default-000001",
"description": "Alert from Rule: Rule 2",
"category": "category_1",
"risk_score": 70,
"timestamp": "2023-08-14T09:08:18.664Z"
}
]
}
}
}
}
}
{
"type": "doc",
"value": {
"id": "a2cf452c1e0375c3d4412cb550bd1783358468a3b3b777da4829d72c7d6fb72f",
"index": "risk-score.risk-score-latest-default",
"source": {
"@timestamp": "2021-03-10T14:51:05.766Z",
"user": {
"name": "user3",
"risk": {
"calculated_score_norm": 50,
"calculated_level": "Moderate",
"id_field": "user.name",
"id_value": "user3",
"calculated_score": 150,
"category_1_score": 150,
"category_1_count": 1,
"notes": [],
"inputs": [
{
"id": "2e17f189-d77d-4537-8d84-592e29334493",
"index": ".internal.alerts-security.alerts-default-000001",
"description": "Alert from Rule: Rule 2",
"category": "category_1",
"risk_score": 70,
"timestamp": "2023-08-14T09:08:18.664Z"
}
]
}
}
}
}
}
{
"type": "doc",
"value": {
"id": "a2cf452c1e0375c3d4412cb550bd1783358468a3b3b777da4829d72c7d6fb73f",
"index": "risk-score.risk-score-latest-default",
"source": {
"@timestamp": "2021-03-10T14:51:05.766Z",
"user": {
"name": "user4",
"risk": {
"calculated_score_norm": 50,
"calculated_level": "Moderate",
"id_field": "user.name",
"id_value": "user4",
"calculated_score": 150,
"category_1_score": 150,
"category_1_count": 1,
"notes": [],
"inputs": [
{
"id": "2e17f189-d77d-4537-8d84-592e29334493",
"index": ".internal.alerts-security.alerts-default-000001",
"description": "Alert from Rule: Rule 2",
"category": "category_1",
"risk_score": 70,
"timestamp": "2023-08-14T09:08:18.664Z"
}
]
}
}
}
}
}
{
"type": "doc",
"value": {
"id": "a2cf452c1e0375c3d4412cb550bd1783358468a3b3b777da4829d72c7d6fb74f",
"index": "risk-score.risk-score-latest-default",
"source": {
"@timestamp": "2021-03-10T14:51:05.766Z",
"user": {
"name": "user5",
"risk": {
"calculated_score_norm": 50,
"calculated_level": "Moderate",
"id_field": "user.name",
"id_value": "user6",
"calculated_score": 150,
"category_1_score": 150,
"category_1_count": 1,
"notes": [],
"inputs": [
{
"id": "2e17f189-d77d-4537-8d84-592e29334493",
"index": ".internal.alerts-security.alerts-default-000001",
"description": "Alert from Rule: Rule 2",
"category": "category_1",
"risk_score": 70,
"timestamp": "2023-08-14T09:08:18.664Z"
}
]
}
}
}
}
}
{
"type": "doc",
"value": {
"id": "a2cf452c1e0375c3d4412cb550bd1783358468a3b3b777da4829d72c7d6fb75f",
"index": "risk-score.risk-score-latest-default",
"source": {
"@timestamp": "2021-03-10T14:51:05.766Z",
"user": {
"name": "user6",
"risk": {
"calculated_score_norm": 50,
"calculated_level": "Moderate",
"id_field": "user.name",
"id_value": "user6",
"calculated_score": 220,
"category_1_score": 220,
"category_1_count": 1,
"notes": [],
"inputs": [
{
"id": "2e17f189-d77d-4537-8d84-592e29334493",
"index": ".internal.alerts-security.alerts-default-000001",
"description": "Alert from Rule: Rule 2",
"category": "category_1",
"risk_score": 70,
"timestamp": "2023-08-14T09:08:18.664Z"
}
]
}
}
}
}
}
{
"type": "doc",
"value": {
"id": "a4cf452c1e0375c3d4412cb550bd1783358468b3b3b777da4829d72c7d6fb74f",
"index": "risk-score.risk-score-latest-default",
"source": {
"@timestamp": "2021-03-10T14:51:05.766Z",
"user": {
"name": "user1",
"risk": {
"calculated_score_norm": 21,
"calculated_level": "Low",
"id_field": "user.name",
"id_value": "user1",
"calculated_score": 150,
"category_1_score": 150,
"category_1_count": 1,
"notes": [],
"inputs": [
{
"id": "eabbdefc23da981f2b74ab58b82622a97bb9878caa11bc914e2adfacc94780f1",
"index": ".internal.alerts-security.alerts-default-000001",
"description": "Endpoint Security",
"category": "category_1",
"risk_score": 70,
"timestamp": "2023-08-14T09:08:18.664Z"
}
]
}
}
}
}
}
{
"type": "doc",
"value": {
"id": "a4cf452c1e0375c3d4412cb550bd1783358468b3123314829d72c7df6fb74",
"index": "risk-score.risk-score-latest-default",
"source": {
"@timestamp": "2021-03-10T14:52:05.766Z",
"user": {
"name": "test",
"risk": {
"calculated_score_norm": 60,
"calculated_level": "High",
"id_field": "user.name",
"id_value": "test",
"calculated_score": 150,
"category_1_score": 150,
"category_1_count": 1,
"notes": [],
"inputs": [
{
"id": "eabbdefc23da981f2b74ab58b82622a97bb9878caa11bc914e2adfacc94780f1-d77d-4537-8d84-592e29334493",
"index": ".internal.alerts-security.alerts-default-000001",
"description": "Alert from Rule: Rule 2",
"category": "category_1",
"risk_score": 70,
"timestamp": "2023-08-14T09:08:18.664Z"
}
]
}
}
}
}
}

View file

@ -0,0 +1,135 @@
{
"type": "index",
"value": {
"index": "risk-score.risk-score-latest-default",
"mappings": {
"dynamic": "strict",
"properties": {
"@timestamp": {
"type": "date"
},
"host": {
"properties": {
"name": {
"type": "keyword"
},
"risk": {
"properties": {
"calculated_level": {
"type": "keyword"
},
"calculated_score": {
"type": "float"
},
"calculated_score_norm": {
"type": "float"
},
"category_1_count": {
"type": "long"
},
"category_1_score": {
"type": "float"
},
"id_field": {
"type": "keyword"
},
"id_value": {
"type": "keyword"
},
"inputs": {
"properties": {
"category": {
"type": "keyword"
},
"description": {
"type": "keyword"
},
"id": {
"type": "keyword"
},
"index": {
"type": "keyword"
},
"risk_score": {
"type": "float"
},
"timestamp": {
"type": "date"
}
}
},
"notes": {
"type": "keyword"
}
}
}
}
},
"user": {
"properties": {
"name": {
"type": "keyword"
},
"risk": {
"properties": {
"calculated_level": {
"type": "keyword"
},
"calculated_score": {
"type": "float"
},
"calculated_score_norm": {
"type": "float"
},
"category_1_count": {
"type": "long"
},
"category_1_score": {
"type": "float"
},
"id_field": {
"type": "keyword"
},
"id_value": {
"type": "keyword"
},
"inputs": {
"properties": {
"category": {
"type": "keyword"
},
"description": {
"type": "keyword"
},
"id": {
"type": "keyword"
},
"index": {
"type": "keyword"
},
"risk_score": {
"type": "float"
},
"timestamp": {
"type": "date"
}
}
},
"notes": {
"type": "keyword"
}
}
}
}
}
}
},
"settings": {
"index": {
"auto_expand_replicas": "0-1",
"number_of_replicas": "0",
"number_of_shards": "1"
}
}
}
}

View file

@ -0,0 +1,136 @@
{
"type": "index",
"value": {
"index": "risk-score.risk-score-latest-default",
"mappings": {
"dynamic": "strict",
"properties": {
"@timestamp": {
"type": "date"
},
"host": {
"properties": {
"name": {
"type": "keyword"
},
"risk": {
"properties": {
"calculated_level": {
"type": "keyword"
},
"calculated_score": {
"type": "float"
},
"calculated_score_norm": {
"type": "float"
},
"category_1_count": {
"type": "long"
},
"category_1_score": {
"type": "float"
},
"id_field": {
"type": "keyword"
},
"id_value": {
"type": "keyword"
},
"inputs": {
"properties": {
"category": {
"type": "keyword"
},
"description": {
"type": "keyword"
},
"id": {
"type": "keyword"
},
"index": {
"type": "keyword"
},
"risk_score": {
"type": "float"
},
"timestamp": {
"type": "date"
}
}
},
"notes": {
"type": "keyword"
}
}
}
}
},
"user": {
"properties": {
"name": {
"type": "keyword"
},
"risk": {
"properties": {
"calculated_level": {
"type": "keyword"
},
"calculated_score": {
"type": "float"
},
"calculated_score_norm": {
"type": "float"
},
"category_1_count": {
"type": "long"
},
"category_1_score": {
"type": "float"
},
"id_field": {
"type": "keyword"
},
"id_value": {
"type": "keyword"
},
"inputs": {
"properties": {
"category": {
"type": "keyword"
},
"description": {
"type": "keyword"
},
"id": {
"type": "keyword"
},
"index": {
"type": "keyword"
},
"risk_score": {
"type": "float"
},
"timestamp": {
"type": "date"
}
}
},
"notes": {
"type": "keyword"
}
}
}
}
}
}
},
"settings": {
"index": {
"auto_expand_replicas": "0-1",
"number_of_replicas": "0",
"number_of_shards": "1"
}
}
}
}

View file

@ -0,0 +1,67 @@
{
"type": "doc",
"value": {
"id": "a4cf452c1e0375c3d4412cb550bd1783358468a3b3b777da4829d72c7d6fb74f",
"index": "risk-score.risk-score-latest-default",
"source": {
"@timestamp": "2021-03-10T14:51:05.766Z",
"host": {
"name": "siem-kibana",
"risk": {
"calculated_level": "Low",
"calculated_score_norm": 20,
"id_field": "host.name",
"id_value": "siem-kibana",
"calculated_score": 150,
"category_1_score": 150,
"category_1_count": 1,
"notes": [],
"inputs": [
{
"id": "2e17f189-d77d-4537-8d84-592e29334493",
"index": ".internal.alerts-security.alerts-default-000001",
"description": "Alert from Rule: Rule 2",
"category": "category_1",
"risk_score": 70,
"timestamp": "2023-08-14T09:08:18.664Z"
}
]
}
}
}
}
}
{
"type": "doc",
"value": {
"id": "a4cf452c1e0375c3d4412cb550bd1783358468b3123314829d72c7df6fb74",
"index": "risk-score.risk-score-latest-default",
"source": {
"@timestamp": "2021-03-10T14:52:05.766Z",
"user": {
"name": "test",
"risk": {
"calculated_score_norm": 60,
"calculated_level": "High",
"id_field": "user.name",
"id_value": "test",
"calculated_score": 150,
"category_1_score": 150,
"category_1_count": 1,
"notes": [],
"inputs": [
{
"id": "eabbdefc23da981f2b74ab58b82622a97bb9878caa11bc914e2adfacc94780f1-d77d-4537-8d84-592e29334493",
"index": ".internal.alerts-security.alerts-default-000001",
"description": "Alert from Rule: Rule 2",
"category": "category_1",
"risk_score": 70,
"timestamp": "2023-08-14T09:08:18.664Z"
}
]
}
}
}
}
}

View file

@ -0,0 +1,136 @@
{
"type": "index",
"value": {
"index": "risk-score.risk-score-latest-default",
"mappings": {
"dynamic": "strict",
"properties": {
"@timestamp": {
"type": "date"
},
"host": {
"properties": {
"name": {
"type": "keyword"
},
"risk": {
"properties": {
"calculated_level": {
"type": "keyword"
},
"calculated_score": {
"type": "float"
},
"calculated_score_norm": {
"type": "float"
},
"category_1_count": {
"type": "long"
},
"category_1_score": {
"type": "float"
},
"id_field": {
"type": "keyword"
},
"id_value": {
"type": "keyword"
},
"inputs": {
"properties": {
"category": {
"type": "keyword"
},
"description": {
"type": "keyword"
},
"id": {
"type": "keyword"
},
"index": {
"type": "keyword"
},
"risk_score": {
"type": "float"
},
"timestamp": {
"type": "date"
}
}
},
"notes": {
"type": "keyword"
}
}
}
}
},
"user": {
"properties": {
"name": {
"type": "keyword"
},
"risk": {
"properties": {
"calculated_level": {
"type": "keyword"
},
"calculated_score": {
"type": "float"
},
"calculated_score_norm": {
"type": "float"
},
"category_1_count": {
"type": "long"
},
"category_1_score": {
"type": "float"
},
"id_field": {
"type": "keyword"
},
"id_value": {
"type": "keyword"
},
"inputs": {
"properties": {
"category": {
"type": "keyword"
},
"description": {
"type": "keyword"
},
"id": {
"type": "keyword"
},
"index": {
"type": "keyword"
},
"risk_score": {
"type": "float"
},
"timestamp": {
"type": "date"
}
}
},
"notes": {
"type": "keyword"
}
}
}
}
}
}
},
"settings": {
"index": {
"auto_expand_replicas": "0-1",
"number_of_replicas": "0",
"number_of_shards": "1"
}
}
}
}

View file

@ -29,6 +29,10 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) {
...svlSharedConfig.get('kbnTestServer.serverArgs'), ...svlSharedConfig.get('kbnTestServer.serverArgs'),
'--serverless=security', '--serverless=security',
'--xpack.encryptedSavedObjects.encryptionKey="abcdefghijklmnopqrstuvwxyz123456"', '--xpack.encryptedSavedObjects.encryptionKey="abcdefghijklmnopqrstuvwxyz123456"',
`--xpack.securitySolution.enableExperimental=${JSON.stringify([
'riskScoringRoutesEnabled',
'riskScoringPersistence',
])}`,
`--xpack.securitySolutionServerless.productTypes=${JSON.stringify([ `--xpack.securitySolutionServerless.productTypes=${JSON.stringify([
{ product_line: 'security', product_tier: 'complete' }, { product_line: 'security', product_tier: 'complete' },
{ product_line: 'endpoint', product_tier: 'complete' }, { product_line: 'endpoint', product_tier: 'complete' },