mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 09:19:04 -04:00
[EDR Workflows][UI] Gate Agent Tamper Protection setting on Agent Policy Settings (#174278)
This PR is part of an effort to limit EDR Workflow features to the
Endpoint Complete tier on serverless and focuses on UI part of gating
Agent Tamper Protection.
Related PRs:
- [Agent Tamper Protection
API](https://github.com/elastic/kibana/pull/174400)
- [Protection updates](https://github.com/elastic/kibana/pull/175129)
Currently, the Agent tamper protection switch is in Fleet's agent policy
settings. Right now (for ESS and Serverless), we only control access to
this field with a license check (platinum). This PR adds an extra check
for AppFeature, which is included in the Complete tier PLI config. We
decided to stick with the existing Fleet privileges for this component,
and no extra changes are needed RBAC wise (confirmed with
@roxana-gheorghe).
Changes:
1. Added `endpointAgentTamperProtection` appFeature and linked it to the
endpoint:complete tier.
2. Made an upselling component and registered it with the Upselling
Service.
3. Passed the upselling component to Fleet using UIExtension.
4. Added Cypress end-to-end coverage for Essentials showing the
upselling component and Complete showing the form component.

This commit is contained in:
parent
04004ddaac
commit
2a030677ba
15 changed files with 398 additions and 71 deletions
|
@ -44,6 +44,11 @@ export enum AppFeatureSecurityKey {
|
|||
*/
|
||||
osqueryAutomatedResponseActions = 'osquery_automated_response_actions',
|
||||
|
||||
/**
|
||||
* Enables Agent Tamper Protection
|
||||
*/
|
||||
endpointAgentTamperProtection = 'endpoint_agent_tamper_protection',
|
||||
|
||||
/**
|
||||
* Enables managing endpoint exceptions on rules and alerts
|
||||
*/
|
||||
|
|
|
@ -106,6 +106,6 @@ export const securityDefaultAppFeaturesConfig: DefaultSecurityAppFeaturesConfig
|
|||
},
|
||||
|
||||
[AppFeatureSecurityKey.osqueryAutomatedResponseActions]: {},
|
||||
|
||||
[AppFeatureSecurityKey.endpointAgentTamperProtection]: {},
|
||||
[AppFeatureSecurityKey.externalRuleActions]: {},
|
||||
};
|
||||
|
|
|
@ -15,6 +15,7 @@ export type UpsellingSectionId =
|
|||
| 'entity_analytics_panel'
|
||||
| 'endpointPolicyProtections'
|
||||
| 'osquery_automated_response_actions'
|
||||
| 'endpoint_agent_tamper_protection'
|
||||
| 'ruleDetailsEndpointExceptions';
|
||||
|
||||
export type UpsellingMessageId =
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import React, { useState, useMemo } from 'react';
|
||||
import React, { useState, useMemo, Suspense } from 'react';
|
||||
import {
|
||||
EuiDescribedFormGroup,
|
||||
EuiFormRow,
|
||||
|
@ -35,7 +35,13 @@ import {
|
|||
DEFAULT_MAX_AGENT_POLICIES_WITH_INACTIVITY_TIMEOUT,
|
||||
} from '../../../../../../../common/constants';
|
||||
import type { NewAgentPolicy, AgentPolicy } from '../../../../types';
|
||||
import { useStartServices, useConfig, useGetAgentPolicies, useLicense } from '../../../../hooks';
|
||||
import {
|
||||
useStartServices,
|
||||
useConfig,
|
||||
useGetAgentPolicies,
|
||||
useLicense,
|
||||
useUIExtension,
|
||||
} from '../../../../hooks';
|
||||
|
||||
import { AgentPolicyPackageBadge } from '../../../../components';
|
||||
import { UninstallCommandFlyout } from '../../../../../../components';
|
||||
|
@ -67,11 +73,16 @@ export const AgentPolicyAdvancedOptionsContent: React.FunctionComponent<Props> =
|
|||
isEditing = false,
|
||||
}) => {
|
||||
const { docLinks } = useStartServices();
|
||||
const AgentTamperProtectionWrapper = useUIExtension(
|
||||
'endpoint',
|
||||
'endpoint-agent-tamper-protection'
|
||||
);
|
||||
const config = useConfig();
|
||||
const maxAgentPoliciesWithInactivityTimeout =
|
||||
config.developer?.maxAgentPoliciesWithInactivityTimeout ??
|
||||
DEFAULT_MAX_AGENT_POLICIES_WITH_INACTIVITY_TIMEOUT;
|
||||
const [touchedFields, setTouchedFields] = useState<{ [key: string]: boolean }>({});
|
||||
|
||||
const {
|
||||
dataOutputOptions,
|
||||
monitoringOutputOptions,
|
||||
|
@ -102,6 +113,98 @@ export const AgentPolicyAdvancedOptionsContent: React.FunctionComponent<Props> =
|
|||
const [isUninstallCommandFlyoutOpen, setIsUninstallCommandFlyoutOpen] = useState(false);
|
||||
const policyHasElasticDefend = useMemo(() => hasElasticDefend(agentPolicy), [agentPolicy]);
|
||||
|
||||
const AgentTamperProtectionSectionContent = useMemo(
|
||||
() => (
|
||||
<EuiDescribedFormGroup
|
||||
title={
|
||||
<h4>
|
||||
<FormattedMessage
|
||||
id="xpack.fleet.agentPolicyForm.tamperingLabel"
|
||||
defaultMessage="Agent tamper protection"
|
||||
/>
|
||||
</h4>
|
||||
}
|
||||
description={
|
||||
<FormattedMessage
|
||||
id="xpack.fleet.agentPolicyForm.tamperingDescription"
|
||||
defaultMessage="Prevent agents from being uninstalled locally. When enabled, agents can only be uninstalled using an authorization token in the uninstall command. Click { linkName } for the full command."
|
||||
values={{ linkName: <strong>Get uninstall command</strong> }}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<EuiSwitch
|
||||
label={
|
||||
<>
|
||||
<FormattedMessage
|
||||
id="xpack.fleet.agentPolicyForm.tamperingSwitchLabel"
|
||||
defaultMessage="Prevent agent tampering"
|
||||
/>
|
||||
{!policyHasElasticDefend && (
|
||||
<span data-test-subj="tamperMissingIntegrationTooltip">
|
||||
<EuiIconTip
|
||||
type="iInCircle"
|
||||
color="subdued"
|
||||
content={i18n.translate(
|
||||
'xpack.fleet.agentPolicyForm.tamperingSwitchLabel.disabledWarning',
|
||||
{
|
||||
defaultMessage:
|
||||
'Elastic Defend integration is required to enable this feature',
|
||||
}
|
||||
)}
|
||||
/>
|
||||
</span>
|
||||
)}
|
||||
</>
|
||||
}
|
||||
checked={agentPolicy.is_protected ?? false}
|
||||
onChange={(e) => {
|
||||
updateAgentPolicy({ is_protected: e.target.checked });
|
||||
}}
|
||||
disabled={!policyHasElasticDefend}
|
||||
data-test-subj="tamperProtectionSwitch"
|
||||
/>
|
||||
{agentPolicy.id && (
|
||||
<>
|
||||
<EuiSpacer size="s" />
|
||||
<EuiLink
|
||||
onClick={() => {
|
||||
setIsUninstallCommandFlyoutOpen(true);
|
||||
}}
|
||||
disabled={!agentPolicy.is_protected || !policyHasElasticDefend}
|
||||
data-test-subj="uninstallCommandLink"
|
||||
>
|
||||
{i18n.translate('xpack.fleet.agentPolicyForm.tamperingUninstallLink', {
|
||||
defaultMessage: 'Get uninstall command',
|
||||
})}
|
||||
</EuiLink>
|
||||
</>
|
||||
)}
|
||||
</EuiDescribedFormGroup>
|
||||
),
|
||||
[agentPolicy.id, agentPolicy.is_protected, policyHasElasticDefend, updateAgentPolicy]
|
||||
);
|
||||
|
||||
const AgentTamperProtectionSection = useMemo(() => {
|
||||
if (agentTamperProtectionEnabled && licenseService.isPlatinum() && !agentPolicy.is_managed) {
|
||||
if (AgentTamperProtectionWrapper) {
|
||||
return (
|
||||
<Suspense fallback={null}>
|
||||
<AgentTamperProtectionWrapper.Component>
|
||||
{AgentTamperProtectionSectionContent}
|
||||
</AgentTamperProtectionWrapper.Component>
|
||||
</Suspense>
|
||||
);
|
||||
}
|
||||
return AgentTamperProtectionSectionContent;
|
||||
}
|
||||
}, [
|
||||
agentTamperProtectionEnabled,
|
||||
licenseService,
|
||||
agentPolicy.is_managed,
|
||||
AgentTamperProtectionWrapper,
|
||||
AgentTamperProtectionSectionContent,
|
||||
]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<EuiDescribedFormGroup
|
||||
|
@ -293,73 +396,9 @@ export const AgentPolicyAdvancedOptionsContent: React.FunctionComponent<Props> =
|
|||
}}
|
||||
/>
|
||||
</EuiDescribedFormGroup>
|
||||
{agentTamperProtectionEnabled && licenseService.isPlatinum() && !agentPolicy.is_managed && (
|
||||
<EuiDescribedFormGroup
|
||||
title={
|
||||
<h4>
|
||||
<FormattedMessage
|
||||
id="xpack.fleet.agentPolicyForm.tamperingLabel"
|
||||
defaultMessage="Agent tamper protection"
|
||||
/>
|
||||
</h4>
|
||||
}
|
||||
description={
|
||||
<FormattedMessage
|
||||
id="xpack.fleet.agentPolicyForm.tamperingDescription"
|
||||
defaultMessage="Prevent agents from being uninstalled locally. When enabled, agents can only be uninstalled using an authorization token in the uninstall command. Click { linkName } for the full command."
|
||||
values={{ linkName: <strong>Get uninstall command</strong> }}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<EuiSwitch
|
||||
label={
|
||||
<>
|
||||
<FormattedMessage
|
||||
id="xpack.fleet.agentPolicyForm.tamperingSwitchLabel"
|
||||
defaultMessage="Prevent agent tampering"
|
||||
/>{' '}
|
||||
{!policyHasElasticDefend && (
|
||||
<span data-test-subj="tamperMissingIntegrationTooltip">
|
||||
<EuiIconTip
|
||||
type="iInCircle"
|
||||
color="subdued"
|
||||
content={i18n.translate(
|
||||
'xpack.fleet.agentPolicyForm.tamperingSwitchLabel.disabledWarning',
|
||||
{
|
||||
defaultMessage:
|
||||
'Elastic Defend integration is required to enable this feature',
|
||||
}
|
||||
)}
|
||||
/>
|
||||
</span>
|
||||
)}
|
||||
</>
|
||||
}
|
||||
checked={agentPolicy.is_protected ?? false}
|
||||
onChange={(e) => {
|
||||
updateAgentPolicy({ is_protected: e.target.checked });
|
||||
}}
|
||||
disabled={!policyHasElasticDefend}
|
||||
data-test-subj="tamperProtectionSwitch"
|
||||
/>
|
||||
{agentPolicy.id && (
|
||||
<>
|
||||
<EuiSpacer size="s" />
|
||||
<EuiLink
|
||||
onClick={() => {
|
||||
setIsUninstallCommandFlyoutOpen(true);
|
||||
}}
|
||||
disabled={!agentPolicy.is_protected || !policyHasElasticDefend}
|
||||
data-test-subj="uninstallCommandLink"
|
||||
>
|
||||
{i18n.translate('xpack.fleet.agentPolicyForm.tamperingUninstallLink', {
|
||||
defaultMessage: 'Get uninstall command',
|
||||
})}
|
||||
</EuiLink>
|
||||
</>
|
||||
)}
|
||||
</EuiDescribedFormGroup>
|
||||
)}
|
||||
|
||||
{AgentTamperProtectionSection}
|
||||
|
||||
<EuiDescribedFormGroup
|
||||
title={
|
||||
<h4>
|
||||
|
|
|
@ -113,6 +113,12 @@ export interface PackagePolicyResponseExtension {
|
|||
Component: LazyExoticComponent<PackagePolicyResponseExtensionComponent>;
|
||||
}
|
||||
|
||||
export interface EndpointAgentTamperProtectionExtension {
|
||||
package: string;
|
||||
view: 'endpoint-agent-tamper-protection';
|
||||
Component: LazyExoticComponent<ComponentType>;
|
||||
}
|
||||
|
||||
export interface PackageGenericErrorsListExtension {
|
||||
package: string;
|
||||
view: 'package-generic-errors-list';
|
||||
|
@ -219,4 +225,5 @@ export type UIExtensionPoint =
|
|||
| PackageAssetsExtension
|
||||
| PackageGenericErrorsListExtension
|
||||
| AgentEnrollmentFlyoutFinalStepExtension
|
||||
| PackagePolicyCreateMultiStepExtension;
|
||||
| PackagePolicyCreateMultiStepExtension
|
||||
| EndpointAgentTamperProtectionExtension;
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* 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 { login } from '../../../../tasks/login';
|
||||
import { createAgentPolicyTask, getEndpointIntegrationVersion } from '../../../../tasks/fleet';
|
||||
import type { IndexedFleetEndpointPolicyResponse } from '../../../../../../../common/endpoint/data_loaders/index_fleet_endpoint_policy';
|
||||
import type { PolicyData } from '../../../../../../../common/endpoint/types';
|
||||
import {
|
||||
checkForAgentTamperProtectionAvailability,
|
||||
navigateToFleetAgentPolicySettings,
|
||||
} from '../../../../screens/fleet/agent_settings';
|
||||
|
||||
describe(
|
||||
'Agent Policy Settings - Complete',
|
||||
{
|
||||
tags: ['@serverless'],
|
||||
env: {
|
||||
ftrConfig: {
|
||||
productTypes: [
|
||||
{ product_line: 'security', product_tier: 'complete' },
|
||||
{ product_line: 'endpoint', product_tier: 'complete' },
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
() => {
|
||||
describe('Agent Tamper Protection is available with no upselling component present', () => {
|
||||
let indexedPolicy: IndexedFleetEndpointPolicyResponse;
|
||||
let policy: PolicyData;
|
||||
|
||||
beforeEach(() => {
|
||||
getEndpointIntegrationVersion().then((version) =>
|
||||
createAgentPolicyTask(version).then((data) => {
|
||||
indexedPolicy = data;
|
||||
policy = indexedPolicy.integrationPolicies[0];
|
||||
})
|
||||
);
|
||||
login();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
if (indexedPolicy) {
|
||||
cy.task('deleteIndexedFleetEndpointPolicies', indexedPolicy);
|
||||
}
|
||||
});
|
||||
|
||||
it('should display upselling section for protections', () => {
|
||||
navigateToFleetAgentPolicySettings(policy.policy_id);
|
||||
checkForAgentTamperProtectionAvailability();
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* 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 { login } from '../../../../tasks/login';
|
||||
import { createAgentPolicyTask, getEndpointIntegrationVersion } from '../../../../tasks/fleet';
|
||||
import type { IndexedFleetEndpointPolicyResponse } from '../../../../../../../common/endpoint/data_loaders/index_fleet_endpoint_policy';
|
||||
import type { PolicyData } from '../../../../../../../common/endpoint/types';
|
||||
import {
|
||||
checkForAgentTamperProtectionAvailability,
|
||||
navigateToFleetAgentPolicySettings,
|
||||
} from '../../../../screens/fleet/agent_settings';
|
||||
|
||||
describe(
|
||||
'Agent Policy Settings - Essentials',
|
||||
{
|
||||
tags: ['@serverless'],
|
||||
env: {
|
||||
ftrConfig: {
|
||||
productTypes: [
|
||||
{ product_line: 'security', product_tier: 'essentials' },
|
||||
{ product_line: 'endpoint', product_tier: 'essentials' },
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
() => {
|
||||
describe('Agent Tamper Protection is unavailable with upselling component present', () => {
|
||||
let indexedPolicy: IndexedFleetEndpointPolicyResponse;
|
||||
let policy: PolicyData;
|
||||
|
||||
beforeEach(() => {
|
||||
getEndpointIntegrationVersion().then((version) =>
|
||||
createAgentPolicyTask(version).then((data) => {
|
||||
indexedPolicy = data;
|
||||
policy = indexedPolicy.integrationPolicies[0];
|
||||
})
|
||||
);
|
||||
login();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
if (indexedPolicy) {
|
||||
cy.task('deleteIndexedFleetEndpointPolicies', indexedPolicy);
|
||||
}
|
||||
});
|
||||
|
||||
it('should display upselling section for protections', () => {
|
||||
navigateToFleetAgentPolicySettings(policy.policy_id);
|
||||
checkForAgentTamperProtectionAvailability(false);
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* 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 { loadPage } from '../../tasks/common';
|
||||
|
||||
export const navigateToFleetAgentPolicySettings = (policyId: string) => {
|
||||
loadPage(`/app/fleet/policies/${policyId}/settings`);
|
||||
};
|
||||
|
||||
export const checkForAgentTamperProtectionAvailability = (
|
||||
isAgentTamperProtectionEnabled = true
|
||||
) => {
|
||||
const upsellElementVisibility = isAgentTamperProtectionEnabled ? 'not.exist' : 'exist';
|
||||
const componentElementVisibility = isAgentTamperProtectionEnabled ? 'exist' : 'not.exist';
|
||||
|
||||
cy.getByTestSubj('endpointSecurity-agentTamperProtectionLockedCard-badge').should(
|
||||
upsellElementVisibility
|
||||
);
|
||||
cy.getByTestSubj('endpointSecurity-agentTamperProtectionLockedCard-title').should(
|
||||
upsellElementVisibility
|
||||
);
|
||||
cy.getByTestSubj('endpointPolicy-agentTamperProtectionLockedCard').should(
|
||||
upsellElementVisibility
|
||||
);
|
||||
|
||||
cy.getByTestSubj('tamperProtectionSwitch').should(componentElementVisibility);
|
||||
cy.getByTestSubj('tamperMissingIntegrationTooltip').should('not.exist');
|
||||
cy.getByTestSubj('uninstallCommandLink').should(componentElementVisibility);
|
||||
};
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* 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 } from 'react';
|
||||
import { useUpsellingComponent } from '../../../../../common/hooks/use_upselling';
|
||||
|
||||
export const EndpointAgentTamperProtectionExtension = memo(({ children }) => {
|
||||
const Component = useUpsellingComponent('endpoint_agent_tamper_protection');
|
||||
if (!Component) {
|
||||
return <>{children}</>;
|
||||
}
|
||||
return <Component />;
|
||||
});
|
||||
|
||||
EndpointAgentTamperProtectionExtension.displayName = 'EndpointAgentTamperProtectionExtension';
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* 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 { lazy } from 'react';
|
||||
import type { FleetUiExtensionGetterOptions } from './types';
|
||||
|
||||
export const getLazyEndpointAgentTamperProtectionExtension = ({
|
||||
coreStart,
|
||||
depsStart,
|
||||
services,
|
||||
}: FleetUiExtensionGetterOptions) =>
|
||||
lazy(async () => {
|
||||
const [{ withSecurityContext }, { EndpointAgentTamperProtectionExtension }] = await Promise.all(
|
||||
[
|
||||
import('./components/with_security_context/with_security_context'),
|
||||
import('./endpoint_agent_tamper_protection_extension'),
|
||||
]
|
||||
);
|
||||
return {
|
||||
default: withSecurityContext({
|
||||
coreStart,
|
||||
depsStart,
|
||||
services,
|
||||
WrappedComponent: EndpointAgentTamperProtectionExtension,
|
||||
}),
|
||||
};
|
||||
});
|
|
@ -21,6 +21,7 @@ import type { DataPublicPluginStart } from '@kbn/data-plugin/public';
|
|||
import { NowProvider, QueryService } from '@kbn/data-plugin/public';
|
||||
import { DEFAULT_APP_CATEGORIES, AppNavLinkStatus } from '@kbn/core/public';
|
||||
import { Storage } from '@kbn/kibana-utils-plugin/public';
|
||||
import { getLazyEndpointAgentTamperProtectionExtension } from './management/pages/policy/view/ingest_manager_integration/lazy_endpoint_agent_tamper_protection_extension';
|
||||
import type { FleetUiExtensionGetterOptions } from './management/pages/policy/view/ingest_manager_integration/types';
|
||||
import type {
|
||||
PluginSetup,
|
||||
|
@ -337,6 +338,12 @@ export class Plugin implements IPlugin<PluginSetup, PluginStart, SetupPlugins, S
|
|||
view: 'package-detail-assets',
|
||||
Component: LazyEndpointCustomAssetsExtension,
|
||||
});
|
||||
|
||||
registerExtension({
|
||||
package: 'endpoint',
|
||||
view: 'endpoint-agent-tamper-protection',
|
||||
Component: getLazyEndpointAgentTamperProtectionExtension(registerOptions),
|
||||
});
|
||||
}
|
||||
|
||||
// Not using await to prevent blocking start execution
|
||||
|
|
|
@ -34,6 +34,7 @@ export const PLI_APP_FEATURES: PliAppFeatures = {
|
|||
complete: [
|
||||
AppFeatureKey.endpointResponseActions,
|
||||
AppFeatureKey.osqueryAutomatedResponseActions,
|
||||
AppFeatureKey.endpointAgentTamperProtection,
|
||||
AppFeatureKey.endpointExceptions,
|
||||
],
|
||||
},
|
||||
|
|
|
@ -18,6 +18,7 @@ import { UPGRADE_INVESTIGATION_GUIDE } from '@kbn/security-solution-upselling/me
|
|||
import { AppFeatureKey } from '@kbn/security-solution-features/keys';
|
||||
import type { AppFeatureKeyType } from '@kbn/security-solution-features';
|
||||
import {
|
||||
EndpointAgentTamperProtectionLazy,
|
||||
EndpointPolicyProtectionsLazy,
|
||||
RuleDetailsEndpointExceptionsLazy,
|
||||
} from './sections/endpoint_management';
|
||||
|
@ -130,6 +131,11 @@ export const upsellingSections: UpsellingSections = [
|
|||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
id: 'endpoint_agent_tamper_protection',
|
||||
pli: AppFeatureKey.endpointAgentTamperProtection,
|
||||
component: EndpointAgentTamperProtectionLazy,
|
||||
},
|
||||
{
|
||||
id: 'endpointPolicyProtections',
|
||||
pli: AppFeatureKey.endpointPolicyProtections,
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* 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 } from 'react';
|
||||
import { EuiCard, EuiIcon } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
const BADGE_TEXT = i18n.translate(
|
||||
'xpack.securitySolutionServerless.rules.endpointSecurity.agentTamperProtection.badgeText',
|
||||
{
|
||||
defaultMessage: 'Endpoint Complete',
|
||||
}
|
||||
);
|
||||
const CARD_TITLE = i18n.translate(
|
||||
'xpack.securitySolutionServerless.rules.endpointSecurity.agentTamperProtection.cardTitle',
|
||||
{
|
||||
defaultMessage: 'Do more with Security!',
|
||||
}
|
||||
);
|
||||
const CARD_MESSAGE = i18n.translate(
|
||||
'xpack.securitySolutionServerless.rules.endpointSecurity.agentTamperProtection.cardMessage',
|
||||
{
|
||||
defaultMessage: 'Upgrade your license to {productTypeRequired} to use Agent Tamper Protection.',
|
||||
values: { productTypeRequired: BADGE_TEXT },
|
||||
}
|
||||
);
|
||||
|
||||
const CardDescription = styled.p`
|
||||
padding: 0 33.3%;
|
||||
`;
|
||||
|
||||
export const EndpointAgentTamperProtection = memo(() => {
|
||||
return (
|
||||
<EuiCard
|
||||
data-test-subj="endpointPolicy-agentTamperProtectionLockedCard"
|
||||
isDisabled={true}
|
||||
description={false}
|
||||
icon={<EuiIcon size="xl" type="lock" />}
|
||||
betaBadgeProps={{
|
||||
'data-test-subj': 'endpointSecurity-agentTamperProtectionLockedCard-badge',
|
||||
label: BADGE_TEXT,
|
||||
}}
|
||||
title={
|
||||
<h3 data-test-subj="endpointSecurity-agentTamperProtectionLockedCard-title">
|
||||
<strong>{CARD_TITLE}</strong>
|
||||
</h3>
|
||||
}
|
||||
>
|
||||
<CardDescription>{CARD_MESSAGE}</CardDescription>
|
||||
</EuiCard>
|
||||
);
|
||||
});
|
||||
EndpointAgentTamperProtection.displayName = 'EndpointAgentTamperProtection';
|
|
@ -18,3 +18,9 @@ export const RuleDetailsEndpointExceptionsLazy = lazy(() =>
|
|||
default: RuleDetailsEndpointExceptions,
|
||||
}))
|
||||
);
|
||||
|
||||
export const EndpointAgentTamperProtectionLazy = lazy(() =>
|
||||
import('./endpoint_agent_tamper_protection').then(({ EndpointAgentTamperProtection }) => ({
|
||||
default: EndpointAgentTamperProtection,
|
||||
}))
|
||||
);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue