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,
pagination,
timerange,
isNewRiskScoreModuleAvailable: z.boolean().default(false),
isNewRiskScoreModuleInstalled: z.boolean().default(false),
factoryQueryType: z.literal(HostsQueries.hosts),
});

View file

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

View file

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

View file

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

View file

@ -17,9 +17,9 @@ export { RiskQueries } from '../../../../api/search_strategy';
export const getHostRiskIndex = (
spaceId: string,
onlyLatest: boolean = true,
isNewRiskScoreModuleAvailable: boolean
isNewRiskScoreModuleInstalled: boolean
): string => {
return isNewRiskScoreModuleAvailable
return isNewRiskScoreModuleInstalled
? getRiskScoreLatestIndex(spaceId)
: `${RISKY_HOSTS_INDEX_PREFIX}${onlyLatest ? 'latest_' : ''}${spaceId}`;
};
@ -27,9 +27,9 @@ export const getHostRiskIndex = (
export const getUserRiskIndex = (
spaceId: string,
onlyLatest: boolean = true,
isNewRiskScoreModuleAvailable: boolean
isNewRiskScoreModuleInstalled: boolean
): string => {
return isNewRiskScoreModuleAvailable
return isNewRiskScoreModuleInstalled
? getRiskScoreLatestIndex(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 { useSearchStrategy } from '../../use_search_strategy';
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 {
inspect: InspectResponse;
@ -50,7 +50,8 @@ export const useUserRelatedHosts = ({
errorMessage: FAIL_RELATED_HOSTS,
abort: skip,
});
const isNewRiskScoreModuleAvailable = useIsExperimentalFeatureEnabled('riskScoringRoutesEnabled');
const isNewRiskScoreModuleInstalled = useIsNewRiskScoreModuleInstalled();
const userRelatedHostsResponse = useMemo(
() => ({
@ -69,9 +70,9 @@ export const useUserRelatedHosts = ({
factoryQueryType: RelatedEntitiesQueries.relatedHosts,
userName,
from,
isNewRiskScoreModuleAvailable,
isNewRiskScoreModuleInstalled,
}),
[indexNames, from, userName, isNewRiskScoreModuleAvailable]
[indexNames, from, userName, isNewRiskScoreModuleInstalled]
);
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 { useSearchStrategy } from '../../use_search_strategy';
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 {
inspect: InspectResponse;
@ -35,7 +35,7 @@ export const useHostRelatedUsers = ({
from,
skip = false,
}: UseHostRelatedUsersParam): UseHostRelatedUsersResult => {
const isNewRiskScoreModuleAvailable = useIsExperimentalFeatureEnabled('riskScoringRoutesEnabled');
const isNewRiskScoreModuleInstalled = useIsNewRiskScoreModuleInstalled();
const {
loading,
result: response,
@ -69,9 +69,9 @@ export const useHostRelatedUsers = ({
factoryQueryType: RelatedEntitiesQueries.relatedUsers,
hostName,
from,
isNewRiskScoreModuleAvailable,
isNewRiskScoreModuleInstalled,
}),
[indexNames, from, hostName, isNewRiskScoreModuleAvailable]
[indexNames, from, hostName, isNewRiskScoreModuleInstalled]
);
useEffect(() => {

View file

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

View file

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

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(
'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(
'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 React from 'react';
import { RiskScoreUpgradeButton } from '../risk_score_onboarding/risk_score_upgrade_button';
import type { RiskScoreEntity } from '../../../../../common/search_strategy';
import { useCheckSignalIndex } from '../../../../detections/containers/detection_engine/alerts/use_check_signal_index';
import type { inputsModel } from '../../../../common/store';
@ -64,23 +63,12 @@ const EnableRiskScoreComponent = ({
}
actions={
<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
disabled={!signalIndexExists}
refetch={refetch}
riskScoreEntity={entityType}
timerange={timerange}
/>
)}
<RiskScoreEnableButton
disabled={!signalIndexExists}
refetch={refetch}
riskScoreEntity={entityType}
timerange={timerange}
/>
</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 { useRiskEngineStatus } from '../../../../entity_analytics/api/hooks/use_risk_engine_status';
import { RiskScoreUpdatePanel } from '../../../../entity_analytics/components/risk_score_update_panel';
import { useIsExperimentalFeatureEnabled } from '../../../../common/hooks/use_experimental_features';
const StyledEuiFlexGroup = styled(EuiFlexGroup)`
margin-top: ${({ theme }) => theme.eui.euiSizeL};
`;
@ -59,7 +59,6 @@ const RiskDetailsTabBodyComponent: React.FC<
: UserRiskScoreQueryId.USER_DETAILS_RISK_SCORE,
[riskEntity]
);
const isNewRiskScoreModuleAvailable = useIsExperimentalFeatureEnabled('riskScoringRoutesEnabled');
const severitySelectionRedux = useDeepEqualSelector((state: State) =>
riskEntity === RiskScoreEntity.host
@ -135,10 +134,6 @@ const RiskDetailsTabBodyComponent: React.FC<
isDeprecated: isDeprecated && !loading,
};
if (riskScoreEngineStatus?.isUpdateAvailable) {
return <RiskScoreUpdatePanel />;
}
if (status.isDisabled || status.isDeprecated) {
return (
<EnableRiskScore
@ -156,7 +151,8 @@ const RiskDetailsTabBodyComponent: React.FC<
return (
<>
{isNewRiskScoreModuleAvailable ? (
{riskScoreEngineStatus?.isUpdateAvailable && <RiskScoreUpdatePanel />}
{riskScoreEngineStatus?.isNewRiskScoreModuleInstalled ? (
<StyledEuiFlexGroup gutterSize="s">
<EuiFlexItem>
{data?.[0] && (

View file

@ -74,6 +74,7 @@ const RiskScoreEnableButtonComponent = ({
color="primary"
fill
deepLinkId={SecurityPageName.entityAnalyticsManagement}
data-test-subj={`enable_${riskScoreEntity}_risk_score`}
>
<FormattedMessage
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 type { inputsModel } from '../../../../common/store';
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 = ({
entityType,
@ -24,7 +24,7 @@ const RiskScoresNoDataDetectedComponent = ({
entityType: RiskScoreEntity;
refetch: inputsModel.Refetch;
}) => {
const isNewRiskScoreModuleAvailable = useIsExperimentalFeatureEnabled('riskScoringRoutesEnabled');
const isNewRiskScoreModuleInstalled = useIsNewRiskScoreModuleInstalled();
const translations = useMemo(
() => ({
@ -51,7 +51,7 @@ const RiskScoresNoDataDetectedComponent = ({
body={translations.body}
actions={
<>
{!isNewRiskScoreModuleAvailable && (
{!isNewRiskScoreModuleInstalled && (
<EuiToolTip content={i18n.RESTART_TOOLTIP}>
<RiskScoreRestartButton refetch={refetch} riskScoreEntity={entityType} />
</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 { useSpaceId } from '../../../../common/hooks/use_space_id';
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> {
data:
@ -84,11 +84,11 @@ export const useRiskScore = <T extends RiskScoreEntity.host | RiskScoreEntity.us
includeAlertsCount = false,
}: UseRiskScore<T>): RiskScoreState<T> => {
const spaceId = useSpaceId();
const isNewRiskScoreModuleAvailable = useIsExperimentalFeatureEnabled('riskScoringRoutesEnabled');
const isNewRiskScoreModuleInstalled = useIsNewRiskScoreModuleInstalled();
const defaultIndex = spaceId
? riskEntity === RiskScoreEntity.host
? getHostRiskIndex(spaceId, onlyLatest, isNewRiskScoreModuleAvailable)
: getUserRiskIndex(spaceId, onlyLatest, isNewRiskScoreModuleAvailable)
? getHostRiskIndex(spaceId, onlyLatest, isNewRiskScoreModuleInstalled)
: getUserRiskIndex(spaceId, onlyLatest, isNewRiskScoreModuleInstalled)
: undefined;
const factoryQueryType =
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]);
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 { inputsModel } from '../../../../common/store';
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 {
error: unknown;
@ -53,11 +53,11 @@ export const useRiskScoreKpi = ({
const { addError } = useAppToasts();
const spaceId = useSpaceId();
const featureEnabled = useMlCapabilities().isPlatinumOrTrialLicense;
const isNewRiskScoreModuleAvailable = useIsExperimentalFeatureEnabled('riskScoringRoutesEnabled');
const isNewRiskScoreModuleInstalled = useIsNewRiskScoreModuleInstalled();
const defaultIndex = spaceId
? riskEntity === RiskScoreEntity.host
? getHostRiskIndex(spaceId, true, isNewRiskScoreModuleAvailable)
: getUserRiskIndex(spaceId, true, isNewRiskScoreModuleAvailable)
? getHostRiskIndex(spaceId, true, isNewRiskScoreModuleInstalled)
: getUserRiskIndex(spaceId, true, isNewRiskScoreModuleInstalled)
: undefined;
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 type { InspectResponse } from '../../../../types';
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';
@ -62,7 +62,7 @@ export const useAllHost = ({
getHostsSelector(state, type)
);
const isNewRiskScoreModuleAvailable = useIsExperimentalFeatureEnabled('riskScoringRoutesEnabled');
const isNewRiskScoreModuleInstalled = useIsNewRiskScoreModuleInstalled();
const [hostsRequest, setHostRequest] = useState<HostsRequestOptionsInput | null>(null);
@ -145,7 +145,7 @@ export const useAllHost = ({
direction,
field: sortField,
},
isNewRiskScoreModuleAvailable,
isNewRiskScoreModuleInstalled,
};
if (!deepEqual(prevRequest, myRequest)) {
return myRequest;
@ -161,7 +161,7 @@ export const useAllHost = ({
limit,
startDate,
sortField,
isNewRiskScoreModuleAvailable,
isNewRiskScoreModuleInstalled,
]);
useEffect(() => {

View file

@ -95,10 +95,6 @@ export const HostRiskScoreQueryTabBody = ({
isDeprecated: isDeprecated && !loading,
};
if (riskScoreEngineStatus?.isUpdateAvailable) {
return <RiskScoreUpdatePanel />;
}
if (status.isDisabled || status.isDeprecated) {
return (
<EuiPanel hasBorder>
@ -123,21 +119,24 @@ export const HostRiskScoreQueryTabBody = ({
}
return (
<HostRiskScoreTableManage
deleteQuery={deleteQuery}
data={data ?? []}
id={HostRiskScoreQueryId.HOSTS_BY_RISK}
inspect={inspect}
isInspect={isInspected}
loading={loading || isKpiLoading}
loadPage={noop} // It isn't necessary because PaginatedTable updates redux store and we load the page when activePage updates on the store
refetch={refetch}
setQuery={setQuery}
setQuerySkip={setQuerySkip}
severityCount={severityCount ?? EMPTY_SEVERITY_COUNT}
totalCount={totalCount}
type={type}
/>
<>
{riskScoreEngineStatus?.isUpdateAvailable && <RiskScoreUpdatePanel />}
<HostRiskScoreTableManage
deleteQuery={deleteQuery}
data={data ?? []}
id={HostRiskScoreQueryId.HOSTS_BY_RISK}
inspect={inspect}
isInspect={isInspected}
loading={loading || isKpiLoading}
loadPage={noop} // It isn't necessary because PaginatedTable updates redux store and we load the page when activePage updates on the store
refetch={refetch}
setQuery={setQuery}
setQuerySkip={setQuerySkip}
severityCount={severityCount ?? EMPTY_SEVERITY_COUNT}
totalCount={totalCount}
type={type}
/>
</>
);
};

View file

@ -19,7 +19,7 @@ import { generateTablePaginationOptions } from '../../../components/paginated_ta
import { useDeepEqualSelector } from '../../../../common/hooks/use_selector';
import { usersSelectors } from '../../store';
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);
@ -43,7 +43,7 @@ export const AllUsersQueryTabBody = ({
const getUsersSelector = useMemo(() => usersSelectors.allUsersSelector(), []);
const { activePage, limit, sort } = useDeepEqualSelector((state) => getUsersSelector(state));
const isNewRiskScoreModuleAvailable = useIsExperimentalFeatureEnabled('riskScoringRoutesEnabled');
const isNewRiskScoreModuleInstalled = useIsNewRiskScoreModuleInstalled();
const {
loading,
@ -78,7 +78,7 @@ export const AllUsersQueryTabBody = ({
},
pagination: generateTablePaginationOptions(activePage, limit),
sort,
isNewRiskScoreModuleAvailable,
isNewRiskScoreModuleInstalled,
});
}
}, [
@ -91,7 +91,7 @@ export const AllUsersQueryTabBody = ({
activePage,
limit,
sort,
isNewRiskScoreModuleAvailable,
isNewRiskScoreModuleInstalled,
]);
return (

View file

@ -95,10 +95,6 @@ export const UserRiskScoreQueryTabBody = ({
isDeprecated: isDeprecated && !loading,
};
if (riskScoreEngineStatus?.isUpdateAvailable) {
return <RiskScoreUpdatePanel />;
}
if (status.isDisabled || status.isDeprecated) {
return (
<EnableRiskScore
@ -115,21 +111,24 @@ export const UserRiskScoreQueryTabBody = ({
}
return (
<UserRiskScoreTableManage
deleteQuery={deleteQuery}
data={data ?? []}
id={UserRiskScoreQueryId.USERS_BY_RISK}
inspect={inspect}
isInspect={isInspected}
loading={loading || isKpiLoading}
loadPage={noop} // It isn't necessary because PaginatedTable updates redux store and we load the page when activePage updates on the store
refetch={refetch}
setQuery={setQuery}
setQuerySkip={setQuerySkip}
severityCount={severityCount ?? EMPTY_SEVERITY_COUNT}
totalCount={totalCount}
type={type}
/>
<>
{riskScoreEngineStatus?.isUpdateAvailable && <RiskScoreUpdatePanel />}
<UserRiskScoreTableManage
deleteQuery={deleteQuery}
data={data ?? []}
id={UserRiskScoreQueryId.USERS_BY_RISK}
inspect={inspect}
isInspect={isInspected}
loading={loading || isKpiLoading}
loadPage={noop} // It isn't necessary because PaginatedTable updates redux store and we load the page when activePage updates on the store
refetch={refetch}
setQuery={setQuery}
setQuerySkip={setQuerySkip}
severityCount={severityCount ?? EMPTY_SEVERITY_COUNT}
totalCount={totalCount}
type={type}
/>
</>
);
};

View file

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

View file

@ -16,11 +16,11 @@ import { getFieldValue } from '../utils/events';
export const getIsHostRiskScoreAvailable: GetIsRiskScoreAvailable = async ({
spaceId,
services,
isNewRiskScoreModuleAvailable,
isNewRiskScoreModuleInstalled,
}) => {
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,
events,
spaceId,
isNewRiskScoreModuleAvailable,
isNewRiskScoreModuleInstalled,
}) => {
return createSingleFieldMatchEnrichment({
name: 'Host Risk',
index: [getHostRiskIndex(spaceId, true, isNewRiskScoreModuleAvailable)],
index: [getHostRiskIndex(spaceId, true, isNewRiskScoreModuleInstalled)],
services,
logger,
events,

View file

@ -15,11 +15,11 @@ import { getFieldValue } from '../utils/events';
export const getIsUserRiskScoreAvailable: GetIsRiskScoreAvailable = async ({
services,
spaceId,
isNewRiskScoreModuleAvailable,
isNewRiskScoreModuleInstalled,
}) => {
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,
events,
spaceId,
isNewRiskScoreModuleAvailable,
isNewRiskScoreModuleInstalled,
}) => {
return createSingleFieldMatchEnrichment({
name: 'User Risk',
index: [getUserRiskIndex(spaceId, true, isNewRiskScoreModuleAvailable)],
index: [getUserRiskIndex(spaceId, true, isNewRiskScoreModuleInstalled)],
services,
logger,
events,

View file

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

View file

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

View file

@ -31,7 +31,7 @@ export const mockOptions: HostsRequestOptions = {
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' },
sort: { direction: Direction.desc, field: HostsFields.lastSeen },
isNewRiskScoreModuleAvailable: false,
isNewRiskScoreModuleInstalled: false,
};
export const mockSearchStrategyResponse: IEsSearchResponse<unknown> = {

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -33622,9 +33622,6 @@
"xpack.securitySolution.riskScore.savedObjects.bulkDeleteFailureTitle": "Impossible de supprimer les objets enregistrés",
"xpack.securitySolution.riskScore.technicalPreviewLabel": "Version d'évaluation technique",
"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.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.",

View file

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

View file

@ -33617,9 +33617,6 @@
"xpack.securitySolution.riskScore.savedObjects.bulkDeleteFailureTitle": "无法删除已保存对象",
"xpack.securitySolution.riskScore.technicalPreviewLabel": "技术预览",
"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.usersDashboardRestartTooltip": "风险分数计算可能需要一段时间运行。但是,通过按“重新启动”,您可以立即强制运行该计算。",
"xpack.securitySolution.riskScore.usersDashboardWarningPanelBody": "找不到任何用户风险分数数据。检查全局 KQL 搜索栏中是否具有任何全局筛选。如果刚刚启用了用户风险模块,风险引擎可能需要一小时才能生成并在此面板中显示用户风险分数数据。",

View file

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

View file

@ -30,11 +30,18 @@ import { login } from '../../tasks/login';
import { visitWithTimeRange } from '../../tasks/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
describe('Enrichment', { tags: ['@ess', '@serverless', '@brokenInServerless'] }, () => {
before(() => {
cleanKibana();
cy.task('esArchiverUnload', 'risk_scores_new');
cy.task('esArchiverUnload', 'risk_scores_new_updated');
cy.task('esArchiverLoad', { archiveName: 'risk_users' });
});
@ -43,44 +50,91 @@ describe('Enrichment', { tags: ['@ess', '@serverless', '@brokenInServerless'] },
});
describe('Custom query rule', () => {
beforeEach(() => {
disableExpandableFlyout();
cy.task('esArchiverLoad', { archiveName: 'risk_hosts' });
deleteAlertsAndRules();
createRule(getNewRule({ rule_id: 'rule1' }));
login();
visitWithTimeRange(ALERTS_URL);
waitForAlertsToPopulate();
describe('from legacy risk scores', () => {
beforeEach(() => {
disableExpandableFlyout();
cy.task('esArchiverLoad', { archiveName: 'risk_hosts' });
deleteAlertsAndRules();
createRule(getNewRule({ rule_id: 'rule1' }));
login();
deleteRiskEngineConfiguration();
visitWithTimeRange(ALERTS_URL);
waitForAlertsToPopulate();
});
afterEach(() => {
cy.task('esArchiverUnload', 'risk_hosts');
cy.task('esArchiverUnload', 'risk_hosts_updated');
});
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('Low');
scrollAlertTableColumnIntoView(USER_RISK_COLUMN);
cy.get(USER_RISK_COLUMN).contains('Low');
scrollAlertTableColumnIntoView(ACTION_COLUMN);
expandFirstAlert();
cy.get(ENRICHED_DATA_ROW).contains('Low');
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(ORIGINAL_HOST_RISK_CLASIFICATION).should('not.exist');
closeAlertFlyout();
cy.task('esArchiverUnload', 'risk_hosts');
cy.task('esArchiverLoad', { archiveName: 'risk_hosts_updated' });
expandFirstAlert();
cy.get(ENRICHED_DATA_ROW).contains('Critical');
cy.get(ENRICHED_DATA_ROW).contains(ORIGINAL_HOST_RISK_CLASIFICATION);
});
});
afterEach(() => {
cy.task('esArchiverUnload', 'risk_hosts');
cy.task('esArchiverUnload', 'risk_hosts_updated');
});
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();
});
it('Should has enrichment fields', 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('Low');
scrollAlertTableColumnIntoView(USER_RISK_COLUMN);
cy.get(USER_RISK_COLUMN).contains('Low');
scrollAlertTableColumnIntoView(ACTION_COLUMN);
expandFirstAlert();
cy.get(ENRICHED_DATA_ROW).contains('Low');
cy.get(ENRICHED_DATA_ROW).contains('Current host risk classification');
cy.get(ENRICHED_DATA_ROW).contains('Critical').should('not.exist');
cy.get(ENRICHED_DATA_ROW).contains('Original host risk classification').should('not.exist');
afterEach(() => {
cy.task('esArchiverUnload', 'risk_scores_new');
cy.task('esArchiverUnload', 'risk_scores_new_updated');
deleteRiskEngineConfiguration();
});
closeAlertFlyout();
cy.task('esArchiverUnload', 'risk_hosts');
cy.task('esArchiverLoad', { archiveName: 'risk_hosts_updated' });
expandFirstAlert();
cy.get(ENRICHED_DATA_ROW).contains('Critical');
cy.get(ENRICHED_DATA_ROW).contains('Original host risk classification');
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 { createRule } from '../../tasks/api_calls/rules';
import {
deleteConfiguration,
deleteRiskEngineConfiguration,
interceptRiskPreviewError,
interceptRiskPreviewSuccess,
interceptRiskInitError,
@ -35,8 +35,7 @@ import { updateDateRangeInLocalDatePickers } from '../../tasks/date_picker';
import { fillLocalSearchBar, submitLocalSearch } from '../../tasks/search_bar';
import {
riskEngineStatusChange,
updateRiskEngine,
updateRiskEngineConfirm,
upgradeRiskEngine,
previewErrorButtonClick,
} from '../../tasks/entity_analytics';
@ -44,9 +43,6 @@ import {
describe(
'Entity analytics management page',
{
env: {
ftrConfig: { enableExperimental: ['riskScoringRoutesEnabled', 'riskScoringPersistence'] },
},
tags: ['@ess', '@serverless', '@brokenInServerless'],
},
() => {
@ -58,7 +54,7 @@ describe(
beforeEach(() => {
login();
createRule(getNewRule({ query: 'user.name:* or host.name:*', risk_score: 70 }));
deleteConfiguration();
deleteRiskEngineConfiguration();
visit(ENTITY_ANALYTICS_MANAGEMENT_URL);
});
@ -147,10 +143,7 @@ describe(
cy.get(RISK_SCORE_STATUS).should('not.exist');
updateRiskEngine();
updateRiskEngineConfirm();
cy.get(RISK_SCORE_STATUS).should('have.text', 'On');
upgradeRiskEngine();
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_TABLE_ROWS,
HOST_RISK_SCORE_NO_DATA_DETECTED,
UPGRADE_HOST_RISK_SCORE_BUTTON,
UPGRADE_USER_RISK_SCORE_BUTTON,
USERS_DONUT_CHART,
USERS_TABLE,
USERS_TABLE_ROWS,
@ -35,7 +33,13 @@ import {
import {
openRiskTableFilterAndSelectTheLowOption,
removeLowFilterAndCloseRiskTableFilter,
openRiskTableFilterAndSelectTheCriticalOption,
removeCriticalFilterAndCloseRiskTableFilter,
} from '../../../tasks/host_risk';
import {
removeLowFilterAndCloseUserRiskTableFilter,
openUserRiskTableFilterAndSelectTheLowOption,
} from '../../../tasks/user_risk';
import { createRule } from '../../../tasks/api_calls/rules';
import { waitForAlertsToPopulate } from '../../../tasks/create_new_rule';
import { getNewRule } from '../../../objects/rule';
@ -49,6 +53,8 @@ import {
navigateToNextPage,
waitForAnomaliesToBeLoaded,
} 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_NAME = 'test';
@ -59,246 +65,476 @@ const END_DATE = 'Jan 19, 2019 @ 20:33:29.186';
describe('Entity Analytics Dashboard', { tags: ['@ess', '@brokenInServerless'] }, () => {
before(() => {
cleanKibana();
login();
deleteRiskEngineConfiguration();
});
describe('Without data', () => {
beforeEach(() => {
login();
visitWithTimeRange(ENTITY_ANALYTICS_URL);
describe('legcay risk score', () => {
describe('Without data', () => {
beforeEach(() => {
login();
visitWithTimeRange(ENTITY_ANALYTICS_URL);
});
it('shows enable host risk button', () => {
cy.get(ENABLE_HOST_RISK_SCORE_BUTTON).should('be.visible');
});
it('shows enable user risk button', () => {
cy.get(ENABLE_USER_RISK_SCORE_BUTTON).should('be.visible');
});
});
it('shows enable host risk button', () => {
cy.get(ENABLE_HOST_RISK_SCORE_BUTTON).should('be.visible');
});
it('shows enable user risk button', () => {
cy.get(ENABLE_USER_RISK_SCORE_BUTTON).should('be.visible');
});
});
describe('Risk Score enabled but still no data', () => {
before(() => {
cy.task('esArchiverLoad', { archiveName: 'risk_hosts_no_data' });
cy.task('esArchiverLoad', { archiveName: 'risk_users_no_data' });
});
beforeEach(() => {
login();
visitWithTimeRange(ENTITY_ANALYTICS_URL);
});
after(() => {
cy.task('esArchiverUnload', 'risk_hosts_no_data');
cy.task('esArchiverUnload', 'risk_users_no_data');
});
it('shows no data detected prompt for host risk score module', () => {
cy.get(HOST_RISK_SCORE_NO_DATA_DETECTED).should('be.visible');
});
it('shows no data detected prompt for user risk score module', () => {
cy.get(USER_RISK_SCORE_NO_DATA_DETECTED).should('be.visible');
});
});
describe('With Legacy data', () => {
before(() => {
cy.task('esArchiverLoad', { archiveName: 'risk_hosts_legacy_data' });
cy.task('esArchiverLoad', { archiveName: 'risk_users_legacy_data' });
});
beforeEach(() => {
login();
visitWithTimeRange(ENTITY_ANALYTICS_URL);
});
after(() => {
cy.task('esArchiverUnload', 'risk_hosts_legacy_data');
cy.task('esArchiverUnload', 'risk_users_legacy_data');
});
it('shows upgrade host risk button', () => {
cy.get(UPGRADE_HOST_RISK_SCORE_BUTTON).should('be.visible');
});
it('shows upgrade user risk button', () => {
cy.get(UPGRADE_USER_RISK_SCORE_BUTTON).should('be.visible');
});
});
describe('With host risk data', () => {
before(() => {
cy.task('esArchiverLoad', { archiveName: 'risk_hosts' });
});
beforeEach(() => {
login();
visitWithTimeRange(ENTITY_ANALYTICS_URL);
});
after(() => {
cy.task('esArchiverUnload', 'risk_hosts');
});
it('renders donut chart', () => {
cy.get(HOSTS_DONUT_CHART).should('include.text', '6Total');
});
it('renders table', () => {
cy.get(HOSTS_TABLE).should('be.visible');
cy.get(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', () => {
openRiskTableFilterAndSelectTheLowOption();
cy.get(HOSTS_DONUT_CHART).should('include.text', '1Total');
cy.get(HOSTS_TABLE_ROWS).should('have.length', 1);
removeLowFilterAndCloseRiskTableFilter();
});
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', () => {
describe('Risk Score enabled but still no data', () => {
before(() => {
createRule(getNewRule());
cy.task('esArchiverLoad', { archiveName: 'risk_hosts_no_data' });
cy.task('esArchiverLoad', { archiveName: 'risk_users_no_data' });
});
beforeEach(() => {
login();
visitWithTimeRange(ALERTS_URL);
waitForAlertsToPopulate();
visitWithTimeRange(ENTITY_ANALYTICS_URL);
});
after(() => {
deleteAlertsAndRules();
cy.task('esArchiverUnload', 'risk_hosts_no_data');
cy.task('esArchiverUnload', 'risk_users_no_data');
});
it('populates alerts column', () => {
cy.get(HOSTS_TABLE_ALERT_CELL).first().should('include.text', SIEM_KIBANA_HOST_ALERTS);
it('shows no data detected prompt for host risk score module', () => {
cy.get(HOST_RISK_SCORE_NO_DATA_DETECTED).should('be.visible');
});
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);
it('shows no data detected prompt for user risk score module', () => {
cy.get(USER_RISK_SCORE_NO_DATA_DETECTED).should('be.visible');
});
});
});
describe('With user risk data', () => {
before(() => {
cy.task('esArchiverLoad', { archiveName: 'risk_users' });
});
beforeEach(() => {
login();
visitWithTimeRange(ENTITY_ANALYTICS_URL);
});
after(() => {
cy.task('esArchiverUnload', 'risk_users');
});
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', () => {
openRiskTableFilterAndSelectTheLowOption();
cy.get(USERS_DONUT_CHART).should('include.text', '2Total');
cy.get(USERS_TABLE_ROWS).should('have.length', 2);
removeLowFilterAndCloseRiskTableFilter();
});
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', () => {
describe('With Legacy data', () => {
before(() => {
createRule(getNewRule());
cy.task('esArchiverLoad', { archiveName: 'risk_hosts_legacy_data' });
cy.task('esArchiverLoad', { archiveName: 'risk_users_legacy_data' });
});
beforeEach(() => {
login();
visitWithTimeRange(ALERTS_URL);
waitForAlertsToPopulate();
visitWithTimeRange(ENTITY_ANALYTICS_URL);
});
after(() => {
deleteAlertsAndRules();
cy.task('esArchiverUnload', 'risk_hosts_legacy_data');
cy.task('esArchiverUnload', 'risk_users_legacy_data');
});
it('populates alerts column', () => {
cy.get(USERS_TABLE_ALERT_CELL).first().should('include.text', TEST_USER_ALERTS);
it('shows enable host risk button', () => {
cy.get(ENABLE_HOST_RISK_SCORE_BUTTON).should('be.visible');
});
it('filters the alerts count with time range', () => {
setEndDate(END_DATE);
updateDates();
it('shows enable user risk button', () => {
cy.get(ENABLE_USER_RISK_SCORE_BUTTON).should('be.visible');
});
});
cy.get(USERS_TABLE_ALERT_CELL).first().should('include.text', 0);
// CLEAR DATES
setEndDateNow();
updateDates();
describe('With host risk data', () => {
before(() => {
cy.task('esArchiverLoad', { archiveName: 'risk_hosts' });
});
it('opens alerts page when alerts count is clicked', () => {
clickOnFirstUsersAlerts();
beforeEach(() => {
login();
visitWithTimeRange(ENTITY_ANALYTICS_URL);
});
cy.url().should('include', ALERTS_URL);
after(() => {
cy.task('esArchiverUnload', 'risk_hosts');
});
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);
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', () => {
openRiskTableFilterAndSelectTheLowOption();
cy.get(HOSTS_DONUT_CHART).should('include.text', '1Total');
cy.get(HOSTS_TABLE_ROWS).should('have.length', 1);
removeLowFilterAndCloseRiskTableFilter();
});
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_users' });
});
beforeEach(() => {
login();
visitWithTimeRange(ENTITY_ANALYTICS_URL);
});
after(() => {
cy.task('esArchiverUnload', 'risk_users');
});
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', () => {
openRiskTableFilterAndSelectTheLowOption();
cy.get(USERS_DONUT_CHART).should('include.text', '2Total');
cy.get(USERS_TABLE_ROWS).should('have.length', 2);
removeLowFilterAndCloseRiskTableFilter();
});
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('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);
});
});
});
});

View file

@ -7,35 +7,32 @@
import { getNewRule } from '../../../objects/rule';
import {
RISK_SCORE_INSTALLATION_SUCCESS_TOAST,
UPGRADE_HOST_RISK_SCORE_BUTTON,
UPGRADE_USER_RISK_SCORE_BUTTON,
UPGRADE_CANCELLATION_BUTTON,
UPGRADE_CONFIRMATION_MODAL,
RISK_SCORE_DASHBOARDS_INSTALLATION_SUCCESS_TOAST,
UPGRADE_RISK_SCORE_BUTTON,
USERS_TABLE,
HOSTS_TABLE_ROWS,
HOSTS_TABLE,
USERS_TABLE_ROWS,
HOST_RISK_SCORE_NO_DATA_DETECTED,
USER_RISK_SCORE_NO_DATA_DETECTED,
} from '../../../screens/entity_analytics';
import { PAGE_TITLE } from '../../../screens/entity_analytics_management';
import {
deleteRiskScore,
installLegacyRiskScoreModule,
installRiskScoreModule,
} 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 { cleanKibana } from '../../../tasks/common';
import { login } from '../../../tasks/login';
import { visitWithTimeRange } from '../../../tasks/navigation';
import {
clickUpgradeRiskScore,
clickUpgradeRiskScoreConfirmed,
interceptUpgradeRiskScoreModule,
waitForUpgradeRiskScoreModule,
} 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';
import { upgradeRiskEngine } from '../../../tasks/entity_analytics';
import { deleteRiskEngineConfiguration } from '../../../tasks/api_calls/risk_engine';
const spaceId = 'default';
@ -44,152 +41,69 @@ describe('Upgrade risk scores', { tags: ['@ess', '@serverless', '@brokenInServer
before(() => {
cleanKibana();
login();
deleteRiskEngineConfiguration();
createRule(getNewRule({ rule_id: 'rule1' }));
});
beforeEach(() => {
login();
deleteRiskScore({ riskScoreEntity: RiskScoreEntity.host, spaceId });
deleteRiskScore({ riskScoreEntity: RiskScoreEntity.user, spaceId });
installLegacyRiskScoreModule(RiskScoreEntity.host, spaceId);
installLegacyRiskScoreModule(RiskScoreEntity.user, spaceId);
visitWithTimeRange(ENTITY_ANALYTICS_URL);
});
it('shows upgrade risk button for host and user', () => {
cy.get(UPGRADE_HOST_RISK_SCORE_BUTTON).should('be.visible');
cy.get(UPGRADE_USER_RISK_SCORE_BUTTON).should('be.visible');
});
it(
'should show a confirmation modal for upgrading host risk score and display a link to host risk score Elastic doc',
{ tags: ['@brokenInServerless'] },
() => {
clickUpgradeRiskScore(RiskScoreEntity.host);
cy.get(UPGRADE_CONFIRMATION_MODAL(RiskScoreEntity.host)).should('exist');
cy.get(UPGRADE_CANCELLATION_BUTTON)
.get(`${UPGRADE_CONFIRMATION_MODAL(RiskScoreEntity.host)} a`)
.then((link) => {
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'];
versions.forEach((version) =>
describe(`handles version ${version} upgrades`, () => {
before(() => {
cleanKibana();
});
describe('show upgrade risk button', () => {
beforeEach(() => {
login();
createRule(getNewRule({ rule_id: 'rule1' }));
deleteRiskScore({ riskScoreEntity: RiskScoreEntity.host, spaceId });
deleteRiskScore({ riskScoreEntity: RiskScoreEntity.user, spaceId });
installLegacyRiskScoreModule(RiskScoreEntity.host, spaceId, version);
installLegacyRiskScoreModule(RiskScoreEntity.user, spaceId, version);
installLegacyRiskScoreModule(RiskScoreEntity.host, spaceId);
installLegacyRiskScoreModule(RiskScoreEntity.user, spaceId);
visitWithTimeRange(ENTITY_ANALYTICS_URL);
});
afterEach(() => {
deleteRiskScore({ riskScoreEntity: RiskScoreEntity.host, spaceId });
deleteRiskScore({ riskScoreEntity: RiskScoreEntity.user, spaceId });
cy.task('esArchiverUnload', 'risk_hosts');
cy.task('esArchiverUnload', 'risk_users');
});
it('should upgrade host risk score successfully', () => {
clickUpgradeRiskScore(RiskScoreEntity.host);
it('shows upgrade panel', () => {
cy.get(UPGRADE_RISK_SCORE_BUTTON).should('be.visible');
interceptUpgradeRiskScoreModule(RiskScoreEntity.host, version);
clickUpgradeRiskScore();
clickUpgradeRiskScoreConfirmed();
waitForUpgradeRiskScoreModule();
cy.get(PAGE_TITLE).should('have.text', 'Entity Risk Score');
});
});
cy.get(UPGRADE_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(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);
});
describe('upgrade risk engine', () => {
before(() => {
cy.task('esArchiverLoad', { archiveName: 'risk_hosts' });
cy.task('esArchiverLoad', { archiveName: 'risk_users' });
});
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);
});
beforeEach(() => {
login();
installRiskScoreModule();
visitWithTimeRange(ENTITY_ANALYTICS_URL);
});
})
);
after(() => {
cy.task('esArchiverUnload', 'risk_hosts');
cy.task('esArchiverUnload', 'risk_users');
deleteRiskScore({ riskScoreEntity: RiskScoreEntity.host, spaceId });
deleteRiskScore({ riskScoreEntity: RiskScoreEntity.user, spaceId });
deleteRiskEngineConfiguration();
});
it('show old risk score data before upgrade, and hide after', () => {
cy.get(HOSTS_TABLE).should('be.visible');
cy.get(HOSTS_TABLE_ROWS).should('have.length', 5);
cy.get(USERS_TABLE).should('be.visible');
cy.get(USERS_TABLE_ROWS).should('have.length', 5);
upgradeRiskEngine();
visitWithTimeRange(ENTITY_ANALYTICS_URL);
cy.get(HOST_RISK_SCORE_NO_DATA_DETECTED).should('be.visible');
cy.get(USER_RISK_SCORE_NO_DATA_DETECTED).should('be.visible');
});
});
});

View file

@ -10,43 +10,88 @@ import { visitHostDetailsPage } from '../../../tasks/navigation';
import { cleanKibana, waitForTableToLoad } from '../../../tasks/common';
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'] }, () => {
before(() => {
cleanKibana();
// illegal_argument_exception: unknown setting [index.lifecycle.rollover_alias]
cy.task('esArchiverLoad', { archiveName: 'risk_hosts' });
describe('with legacy risk score', () => {
before(() => {
cleanKibana();
// illegal_argument_exception: unknown setting [index.lifecycle.rollover_alias]
cy.task('esArchiverLoad', { archiveName: 'risk_hosts' });
});
beforeEach(() => {
login();
deleteRiskEngineConfiguration();
});
after(() => {
cy.task('esArchiverUnload', 'risk_hosts');
});
it('renders risk tab', () => {
visitHostDetailsPage('siem-kibana');
navigateToHostRiskDetailTab();
waitForTableToLoad();
cy.get('[data-test-subj="topRiskScoreContributors"]')
.find(TABLE_ROWS)
.within(() => {
cy.get(TABLE_CELL).contains('Unusual Linux Username');
});
});
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?');
});
});
beforeEach(() => {
login();
});
describe('with new risk score', () => {
before(() => {
cleanKibana();
cy.task('esArchiverLoad', { archiveName: 'risk_scores_new' });
cy.task('esArchiverLoad', { archiveName: 'query_alert' });
login();
enableRiskEngine();
});
after(() => {
cy.task('esArchiverUnload', 'risk_hosts');
});
beforeEach(() => {
login();
});
it('renders risk tab', () => {
visitHostDetailsPage('siem-kibana');
cy.get('[data-test-subj="navigation-hostRisk"]').click();
waitForTableToLoad();
after(() => {
cy.task('esArchiverUnload', 'risk_scores_new');
cy.task('esArchiverUnload', 'query_alert');
deleteRiskEngineConfiguration();
});
cy.get('[data-test-subj="topRiskScoreContributors"]')
.find(TABLE_ROWS)
.within(() => {
cy.get(TABLE_CELL).contains('Unusual Linux Username');
});
});
it('renders risk tab', () => {
visitHostDetailsPage('Host-fwarau82er');
navigateToHostRiskDetailTab();
waitForTableToLoad();
it('shows risk information overlay when button is clicked', () => {
visitHostDetailsPage('siem-kibana');
cy.get('[data-test-subj="navigation-hostRisk"]').click();
waitForTableToLoad();
cy.get(ALERTS_COUNT).should('have.text', '1 alert');
cy.get(ALERT_GRID_CELL).contains('Endpoint Security');
});
cy.get('[data-test-subj="open-risk-information-flyout-trigger"]').click();
it('shows risk information overlay when button is clicked', () => {
visitHostDetailsPage('siem-kibana');
navigateToHostRiskDetailTab();
waitForTableToLoad();
cy.get('[data-test-subj="open-risk-information-flyout"] .euiFlyoutHeader').contains(
'How is host risk calculated?'
);
openRiskInformationFlyout();
cy.get(RISK_INFORMATION_FLYOUT_HEADER).contains('How is host risk calculated?');
});
});
});

View file

@ -18,53 +18,114 @@ import {
HOST_BY_RISK_TABLE_NEXT_PAGE_BUTTON,
} from '../../../screens/hosts/host_risk';
import { login } from '../../../tasks/login';
import { visit } from '../../../tasks/navigation';
import { visitWithTimeRange } from '../../../tasks/navigation';
import { hostsUrl } from '../../../urls/navigation';
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
describe.skip('risk tab', { tags: ['@ess', '@brokenInServerless'] }, () => {
before(() => {
cleanKibana();
cy.task('esArchiverLoad', { archiveName: 'risk_hosts' });
describe('risk tab', { tags: ['@ess', '@brokenInServerless'] }, () => {
describe('with legacy risk score', () => {
before(() => {
cleanKibana();
login();
deleteRiskEngineConfiguration();
cy.task('esArchiverLoad', { archiveName: 'risk_hosts' });
});
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_hosts');
});
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', '21');
cy.get(HOST_BY_RISK_TABLE_CELL).eq(5).should('have.text', 'Low');
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();
});
});
beforeEach(() => {
login();
visit(hostsUrl('allHosts'));
navigateToHostRiskDetailTab();
});
describe('with new risk score', () => {
before(() => {
cleanKibana();
cy.task('esArchiverLoad', { archiveName: 'risk_scores_new' });
login();
enableRiskEngine();
});
after(() => {
cy.task('esArchiverUnload', 'risk_hosts');
});
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();
});
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', '21');
cy.get(HOST_BY_RISK_TABLE_CELL).eq(5).should('have.text', 'Low');
clearSearchBar();
});
after(() => {
cy.task('esArchiverUnload', 'risk_scores_new');
deleteRiskEngineConfiguration();
});
it.skip('filters the table', () => {
openRiskTableFilterAndSelectTheCriticalOption();
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();
});
cy.get(HOST_BY_RISK_TABLE_CELL).eq(3).should('not.have.text', 'siem-kibana');
it.skip('filters the table', () => {
openRiskTableFilterAndSelectTheCriticalOption();
removeCriticalFilterAndCloseRiskTableFilter();
});
cy.get(HOST_BY_RISK_TABLE_CELL).eq(3).should('not.have.text', 'siem-kibana');
// Flaky
it.skip('should be able to change items count per page', () => {
selectFiveItemsPerPageOption();
removeCriticalFilterAndCloseRiskTableFilter();
});
cy.get(HOST_BY_RISK_TABLE_HOSTNAME_CELL).should('have.length', 5);
});
// Flaky
it.skip('should be able to change items count per page', () => {
selectFiveItemsPerPageOption();
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();
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,27 +12,58 @@ import { hostsUrl } from '../../../urls/navigation';
import { cleanKibana } from '../../../tasks/common';
import { TABLE_CELL } from '../../../screens/alerts_details';
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'] }, () => {
before(() => {
cleanKibana();
// illegal_argument_exception: unknown setting [index.lifecycle.name]
cy.task('esArchiverLoad', { archiveName: 'risk_hosts' });
describe('with legacy risk score', () => {
before(() => {
cleanKibana();
// illegal_argument_exception: unknown setting [index.lifecycle.name]
cy.task('esArchiverLoad', { archiveName: 'risk_hosts' });
});
beforeEach(() => {
login();
deleteRiskEngineConfiguration();
});
after(() => {
cy.task('esArchiverUnload', 'risk_hosts');
});
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', 'Low');
});
});
beforeEach(() => {
login();
});
describe('with new risk score', () => {
before(() => {
cleanKibana();
// illegal_argument_exception: unknown setting [index.lifecycle.name]
cy.task('esArchiverLoad', { archiveName: 'risk_scores_new' });
});
after(() => {
cy.task('esArchiverUnload', 'risk_hosts');
});
beforeEach(() => {
login();
enableRiskEngine();
});
it('it renders risk column', () => {
visitWithTimeRange(hostsUrl('allHosts'));
kqlSearch('host.name: "siem-kibana" {enter}');
after(() => {
cy.task('esArchiverUnload', 'risk_scores_new');
deleteRiskEngineConfiguration();
});
cy.get('[data-test-subj="tableHeaderCell_node.risk_4"]').should('exist');
cy.get(`${TABLE_CELL} .euiTableCellContent`).eq(4).should('have.text', 'Low');
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_RISK_SCORE_BUTTON = '[data-test-subj="update-risk-score-button"]';
export const 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 =
'[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_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"]';

View file

@ -7,3 +7,6 @@
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 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.
*/
export const deleteConfiguration = () => {
export const deleteRiskEngineConfiguration = () => {
cy.request({
method: 'GET',
url: `/api/saved_objects/_find?type=risk-engine-configuration`,

View file

@ -10,11 +10,13 @@ import {
ANOMALIES_TABLE_ROWS,
ANOMALIES_TABLE_ENABLE_JOB_BUTTON,
ANOMALIES_TABLE_NEXT_PAGE_BUTTON,
OPEN_RISK_INFORMATION_FLYOUT_BUTTON,
} 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 {
RISK_SCORE_UPDATE_CONFIRM,
RISK_SCORE_UDATE_BUTTON,
RISK_SCORE_UPDATE_BUTTON,
RISK_SCORE_SWITCH,
RISK_PREVIEW_ERROR_BUTTON,
} from '../screens/entity_analytics_management';
@ -42,8 +44,14 @@ export const riskEngineStatusChange = () => {
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 = () => {
cy.get(RISK_SCORE_UDATE_BUTTON).click();
cy.get(RISK_SCORE_UPDATE_BUTTON).click();
};
export const updateRiskEngineConfirm = () => {
@ -53,3 +61,12 @@ export const updateRiskEngineConfirm = () => {
export const previewErrorButtonClick = () => {
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 = () => {
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();
};

View file

@ -10,8 +10,7 @@ import {
ENABLE_USER_RISK_SCORE_BUTTON,
HOSTS_TABLE_ALERT_CELL,
UPGRADE_CONFIRMATION_BUTTON,
UPGRADE_HOST_RISK_SCORE_BUTTON,
UPGRADE_USER_RISK_SCORE_BUTTON,
UPGRADE_RISK_SCORE_BUTTON,
USERS_TABLE_ALERT_CELL,
} from '../../screens/entity_analytics';
import {
@ -68,13 +67,8 @@ export const clickEnableRiskScore = (riskScoreEntity: RiskScoreEntity) => {
cy.get(button).click();
};
export const clickUpgradeRiskScore = (riskScoreEntity: RiskScoreEntity) => {
const button =
riskScoreEntity === RiskScoreEntity.user
? UPGRADE_USER_RISK_SCORE_BUTTON
: UPGRADE_HOST_RISK_SCORE_BUTTON;
cy.get(button).click();
export const clickUpgradeRiskScore = () => {
cy.get(UPGRADE_RISK_SCORE_BUTTON).click();
};
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",
"size": 3456
},
"user": {
"name": "user1"
},
"host": {
"architecture": "wtnozeqvub",
"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'),
'--serverless=security',
'--xpack.encryptedSavedObjects.encryptionKey="abcdefghijklmnopqrstuvwxyz123456"',
`--xpack.securitySolution.enableExperimental=${JSON.stringify([
'riskScoringRoutesEnabled',
'riskScoringPersistence',
])}`,
`--xpack.securitySolutionServerless.productTypes=${JSON.stringify([
{ product_line: 'security', product_tier: 'complete' },
{ product_line: 'endpoint', product_tier: 'complete' },