mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[Security solution] Risk score platinum CTA (#140863)
This commit is contained in:
parent
51699fa21a
commit
e7b4063057
8 changed files with 158 additions and 49 deletions
|
@ -54,6 +54,16 @@ Object {
|
|||
"name": "Cloud Posture",
|
||||
"onClick": [Function],
|
||||
},
|
||||
Object {
|
||||
"data-href": "securitySolutionUI/entity-analytics",
|
||||
"data-test-subj": "navigation-entity-analytics",
|
||||
"disabled": false,
|
||||
"href": "securitySolutionUI/entity-analytics",
|
||||
"id": "entity-analytics",
|
||||
"isSelected": false,
|
||||
"name": "Entity Analytics",
|
||||
"onClick": [Function],
|
||||
},
|
||||
],
|
||||
"name": "Dashboards",
|
||||
},
|
||||
|
|
|
@ -92,17 +92,6 @@ describe('useSecuritySolutionNavigation', () => {
|
|||
expect(result.current).toMatchSnapshot();
|
||||
});
|
||||
|
||||
// TODO: Steph/users remove when no longer experimental
|
||||
it('should include users when feature flag is on', async () => {
|
||||
(useIsExperimentalFeatureEnabled as jest.Mock).mockReturnValue(true);
|
||||
const { result } = renderHook<{}, KibanaPageTemplateProps['solutionNav']>(
|
||||
() => useSecuritySolutionNavigation(),
|
||||
{ wrapper: TestProviders }
|
||||
);
|
||||
|
||||
expect(result?.current?.items?.[4].items?.[2].id).toEqual(SecurityPageName.users);
|
||||
});
|
||||
|
||||
// TODO: [kubernetes] remove when no longer experimental
|
||||
it('should include kubernetes when feature flag is on', async () => {
|
||||
(useIsExperimentalFeatureEnabled as jest.Mock).mockReturnValue(true);
|
||||
|
@ -110,7 +99,7 @@ describe('useSecuritySolutionNavigation', () => {
|
|||
() => useSecuritySolutionNavigation(),
|
||||
{ wrapper: TestProviders }
|
||||
);
|
||||
expect(result?.current?.items?.[1].items?.[3].id).toEqual(SecurityPageName.kubernetes);
|
||||
expect(result?.current?.items?.[1].items?.[4].id).toEqual(SecurityPageName.kubernetes);
|
||||
});
|
||||
|
||||
it('should omit host isolation exceptions if hook reports false', () => {
|
||||
|
|
|
@ -21,9 +21,6 @@ import { SecurityPageName } from '../../../../../common/constants';
|
|||
import { useCanSeeHostIsolationExceptionsMenu } from '../../../../management/pages/host_isolation_exceptions/view/hooks';
|
||||
import { useIsExperimentalFeatureEnabled } from '../../../hooks/use_experimental_features';
|
||||
import { useGlobalQueryString } from '../../../utils/global_query_string';
|
||||
import { useMlCapabilities } from '../../ml/hooks/use_ml_capabilities';
|
||||
import { hasMlUserPermissions } from '../../../../../common/machine_learning/has_ml_user_permissions';
|
||||
import { hasMlLicense } from '../../../../../common/machine_learning/has_ml_license';
|
||||
|
||||
export const usePrimaryNavigationItems = ({
|
||||
navTabs,
|
||||
|
@ -75,8 +72,6 @@ function usePrimaryNavigationItemsToDisplay(navTabs: Record<string, NavTab>) {
|
|||
const hasCasesReadPermissions = useGetUserCasesPermissions().read;
|
||||
const canSeeHostIsolationExceptions = useCanSeeHostIsolationExceptionsMenu();
|
||||
const isPolicyListEnabled = useIsExperimentalFeatureEnabled('policyListEnabled');
|
||||
const mlCapabilities = useMlCapabilities();
|
||||
const hasMlPermissions = hasMlLicense(mlCapabilities) && hasMlUserPermissions(mlCapabilities);
|
||||
|
||||
const uiCapabilities = useKibana().services.application.capabilities;
|
||||
return useMemo(
|
||||
|
@ -94,10 +89,10 @@ function usePrimaryNavigationItemsToDisplay(navTabs: Record<string, NavTab>) {
|
|||
navTabs[SecurityPageName.overview],
|
||||
navTabs[SecurityPageName.detectionAndResponse],
|
||||
navTabs[SecurityPageName.cloudSecurityPostureDashboard],
|
||||
navTabs[SecurityPageName.entityAnalytics],
|
||||
...(navTabs[SecurityPageName.kubernetes] != null
|
||||
? [navTabs[SecurityPageName.kubernetes]]
|
||||
: []),
|
||||
...(hasMlPermissions ? [navTabs[SecurityPageName.entityAnalytics]] : []),
|
||||
],
|
||||
},
|
||||
{
|
||||
|
@ -162,7 +157,6 @@ function usePrimaryNavigationItemsToDisplay(navTabs: Record<string, NavTab>) {
|
|||
hasCasesReadPermissions,
|
||||
canSeeHostIsolationExceptions,
|
||||
isPolicyListEnabled,
|
||||
hasMlPermissions,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import React, { memo, useCallback } from 'react';
|
||||
import {
|
||||
EuiCard,
|
||||
EuiIcon,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiText,
|
||||
EuiButton,
|
||||
EuiTextColor,
|
||||
} from '@elastic/eui';
|
||||
import styled from 'styled-components';
|
||||
import { useNavigation } from '../../lib/kibana';
|
||||
import * as i18n from './translations';
|
||||
|
||||
const PaywallDiv = styled.div`
|
||||
max-width: 85%;
|
||||
margin: 0 auto;
|
||||
.euiCard__betaBadgeWrapper {
|
||||
.euiCard__betaBadge {
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
.platinumCardDescription {
|
||||
padding: 0 15%;
|
||||
}
|
||||
`;
|
||||
|
||||
export const Paywall = memo(({ featureDescription }: { featureDescription?: string }) => {
|
||||
const { getAppUrl, navigateTo } = useNavigation();
|
||||
const subscriptionUrl = getAppUrl({
|
||||
appId: 'management',
|
||||
path: 'stack/license_management',
|
||||
});
|
||||
const goToSubscription = useCallback(() => {
|
||||
navigateTo({ url: subscriptionUrl });
|
||||
}, [navigateTo, subscriptionUrl]);
|
||||
return (
|
||||
<PaywallDiv>
|
||||
<EuiCard
|
||||
data-test-subj="platinumCard"
|
||||
betaBadgeProps={{ label: i18n.PLATINUM }}
|
||||
icon={<EuiIcon size="xl" type="lock" />}
|
||||
display="subdued"
|
||||
title={
|
||||
<h3>
|
||||
<strong>{i18n.UPGRADE_CTA}</strong>
|
||||
</h3>
|
||||
}
|
||||
description={false}
|
||||
>
|
||||
<EuiFlexGroup className="platinumCardDescription" direction="column" gutterSize="none">
|
||||
<EuiText>
|
||||
<EuiFlexItem>
|
||||
<p>
|
||||
<EuiTextColor color="subdued">
|
||||
{i18n.UPGRADE_MESSAGE(featureDescription)}
|
||||
</EuiTextColor>
|
||||
</p>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<div>
|
||||
<EuiButton onClick={goToSubscription} fill>
|
||||
{i18n.UPGRADE_BUTTON}
|
||||
</EuiButton>
|
||||
</div>
|
||||
</EuiFlexItem>
|
||||
</EuiText>
|
||||
</EuiFlexGroup>
|
||||
</EuiCard>
|
||||
</PaywallDiv>
|
||||
);
|
||||
});
|
||||
|
||||
Paywall.displayName = 'Paywall';
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* 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 { i18n } from '@kbn/i18n';
|
||||
|
||||
export const PLATINUM = i18n.translate('xpack.securitySolution.paywall.platinum', {
|
||||
defaultMessage: 'Platinum',
|
||||
});
|
||||
|
||||
export const UPGRADE_CTA = i18n.translate('xpack.securitySolution.paywall.upgradeButton', {
|
||||
defaultMessage: 'Available from Platinum',
|
||||
});
|
||||
|
||||
export const UPGRADE_MESSAGE = (description?: string) =>
|
||||
i18n.translate('xpack.securitySolution.paywall.upgradeMessage', {
|
||||
values: { description: description ? description : 'this feature' },
|
||||
defaultMessage:
|
||||
'To turn use {description}, you must upgrade your license to Platinum, start a free 30-days trial, or spin up a cloud deployment on AWS, GCP, or Azure.',
|
||||
});
|
||||
|
||||
export const UPGRADE_BUTTON = i18n.translate('xpack.securitySolution.paywall.upgradeCta', {
|
||||
defaultMessage: 'Upgrade to Platinum',
|
||||
});
|
|
@ -83,7 +83,6 @@ export const entityAnalyticsLinks: LinkItem = {
|
|||
}),
|
||||
path: ENTITY_ANALYTICS_PATH,
|
||||
capabilities: [`${SERVER_APP_ID}.show`],
|
||||
licenseType: 'platinum',
|
||||
isBeta: true,
|
||||
betaOptions: {
|
||||
text: i18n.translate('xpack.securitySolution.appLinks.technicalPreview', {
|
||||
|
|
|
@ -7,6 +7,9 @@
|
|||
import React from 'react';
|
||||
import { EuiFlexGroup, EuiFlexItem, EuiLoadingSpinner } from '@elastic/eui';
|
||||
|
||||
import { ENTITY_ANALYTICS } from '../../app/translations';
|
||||
import { Paywall } from '../../common/components/paywall';
|
||||
import { useMlCapabilities } from '../../common/components/ml/hooks/use_ml_capabilities';
|
||||
import { SpyRoute } from '../../common/utils/route/spy_routes';
|
||||
import { SecurityPageName } from '../../app/types';
|
||||
import { useSourcererDataView } from '../../common/containers/sourcerer';
|
||||
|
@ -25,13 +28,14 @@ import { InputsModelId } from '../../common/store/inputs/constants';
|
|||
const EntityAnalyticsComponent = () => {
|
||||
const { indicesExist, loading: isSourcererLoading, indexPattern } = useSourcererDataView();
|
||||
|
||||
const isPlatinumOrTrialLicense = useMlCapabilities().isPlatinumOrTrialLicense;
|
||||
return (
|
||||
<>
|
||||
{indicesExist ? (
|
||||
<>
|
||||
<SecuritySolutionPageWrapper data-test-subj="entityAnalyticsPage">
|
||||
<HeaderPage
|
||||
title={i18n.ENTITY_ANALYTICS_TITLE}
|
||||
title={ENTITY_ANALYTICS}
|
||||
badgeOptions={{
|
||||
text: i18n.TECHNICAL_PREVIEW,
|
||||
color: 'white',
|
||||
|
@ -39,34 +43,39 @@ const EntityAnalyticsComponent = () => {
|
|||
beta: true,
|
||||
}}
|
||||
>
|
||||
<SiemSearchBar
|
||||
id={InputsModelId.global}
|
||||
indexPattern={indexPattern}
|
||||
hideFilterBar
|
||||
hideQueryInput
|
||||
/>
|
||||
{isPlatinumOrTrialLicense && (
|
||||
<SiemSearchBar
|
||||
id={InputsModelId.global}
|
||||
indexPattern={indexPattern}
|
||||
hideFilterBar
|
||||
hideQueryInput
|
||||
/>
|
||||
)}
|
||||
</HeaderPage>
|
||||
{isPlatinumOrTrialLicense ? (
|
||||
isSourcererLoading ? (
|
||||
<EuiLoadingSpinner size="l" data-test-subj="entityAnalyticsLoader" />
|
||||
) : (
|
||||
<EuiFlexGroup direction="column" data-test-subj="entityAnalyticsSections">
|
||||
<EuiFlexItem>
|
||||
<EntityAnalyticsHeader />
|
||||
</EuiFlexItem>
|
||||
|
||||
{isSourcererLoading ? (
|
||||
<EuiLoadingSpinner size="l" data-test-subj="entityAnalyticsLoader" />
|
||||
<EuiFlexItem>
|
||||
<EntityAnalyticsHostRiskScores />
|
||||
</EuiFlexItem>
|
||||
|
||||
<EuiFlexItem>
|
||||
<EntityAnalyticsUserRiskScores />
|
||||
</EuiFlexItem>
|
||||
|
||||
<EuiFlexItem>
|
||||
<EntityAnalyticsAnomalies />
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
)
|
||||
) : (
|
||||
<EuiFlexGroup direction="column" data-test-subj="entityAnalyticsSections">
|
||||
<EuiFlexItem>
|
||||
<EntityAnalyticsHeader />
|
||||
</EuiFlexItem>
|
||||
|
||||
<EuiFlexItem>
|
||||
<EntityAnalyticsHostRiskScores />
|
||||
</EuiFlexItem>
|
||||
|
||||
<EuiFlexItem>
|
||||
<EntityAnalyticsUserRiskScores />
|
||||
</EuiFlexItem>
|
||||
|
||||
<EuiFlexItem>
|
||||
<EntityAnalyticsAnomalies />
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
<Paywall featureDescription={i18n.ENTITY_ANALYTICS_LICENSE_DESC} />
|
||||
)}
|
||||
</SecuritySolutionPageWrapper>
|
||||
</>
|
||||
|
|
|
@ -50,10 +50,10 @@ export const DETECTION_RESPONSE_TITLE = i18n.translate(
|
|||
}
|
||||
);
|
||||
|
||||
export const ENTITY_ANALYTICS_TITLE = i18n.translate(
|
||||
'xpack.securitySolution.entityAnalytics.pageTitle',
|
||||
export const ENTITY_ANALYTICS_LICENSE_DESC = i18n.translate(
|
||||
'xpack.securitySolution.entityAnalytics.pageDesc',
|
||||
{
|
||||
defaultMessage: 'Entity Analytics',
|
||||
defaultMessage: 'Entity Analytics features',
|
||||
}
|
||||
);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue