[EDR Workflows] Artifact Rollout - feature flag on, copy changes (#167489)

https://github.com/elastic/security-team/issues/7442

This PR:
1. Sets `protectionUpdatesEnabled` feature flag to `true`.
2. Text changes requested
[here](https://github.com/elastic/security-team/issues/7442)
3. Introduces ~~dismissable~~ callout that warns user about consequences
of turning auto updates off.
4. Adds cypress test that validates note persistance.

![Screenshot 2023-09-29 at 10 37
40](6879cc8c-beb9-4f0e-a378-357ae96ee80b)
![Screenshot 2023-09-29 at 10 37
17](48d2df33-9e9a-4b07-a589-ddd7e904e07b)
![Screenshot 2023-09-29 at 10 37
25](5691cc54-5b4e-4d32-a5a1-42ef801ba491)
This commit is contained in:
Konrad Szwarc 2023-09-29 16:59:05 +02:00 committed by GitHub
parent fbd820b6c6
commit 41cf85bee7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 66 additions and 17 deletions

View file

@ -108,7 +108,7 @@ export const allowedExperimentalValues = Object.freeze({
/**
* Enables Protection Updates tab in the Endpoint Policy Details page
*/
protectionUpdatesEnabled: false,
protectionUpdatesEnabled: true,
});
type ExperimentalConfigKeys = Array<keyof ExperimentalFeatures>;

View file

@ -20,7 +20,6 @@ describe(
'Policy Details',
{
tags: '@ess',
env: { ftrConfig: { enableExperimental: ['protectionUpdatesEnabled'] } },
},
() => {
describe('Protection updates', () => {
@ -57,10 +56,10 @@ describe(
it('should render the protection updates tab content', () => {
loadProtectionUpdatesUrl(policy.id);
cy.getByTestSubj('protection-updates-warning-callout');
cy.getByTestSubj('protection-updates-automatic-updates-enabled');
cy.getByTestSubj('protection-updates-manifest-switch');
cy.getByTestSubj('protection-updates-manifest-name-title');
cy.getByTestSubj('protection-updates-manifest-name');
cy.getByTestSubj('protectionUpdatesSaveButton').should('be.disabled');
cy.getByTestSubj('protection-updates-manifest-switch').click();
@ -201,6 +200,11 @@ describe(
cy.getByTestSubj('protection-updates-manifest-note').contains(updatedTestNote);
cy.getByTestSubj('protectionUpdatesSaveButton').should('be.disabled');
});
it('should preserve note', () => {
loadProtectionUpdatesUrl(policy.id);
cy.getByTestSubj('protection-updates-manifest-note').contains(updatedTestNote);
});
});
describe('Renders read only protection updates for user without write permissions', () => {
@ -238,7 +242,6 @@ describe(
cy.getByTestSubj('protection-updates-manifest-switch').should('not.exist');
cy.getByTestSubj('protection-updates-state-view-mode');
cy.getByTestSubj('protection-updates-manifest-name-title');
cy.getByTestSubj('protection-updates-manifest-name');
cy.getByTestSubj('protection-updates-manifest-name-deployed-version-title');
cy.getByTestSubj('protection-updates-deployed-version').contains(

View file

@ -12,7 +12,8 @@ import type { IndexedFleetEndpointPolicyResponse } from '../../../../../common/e
import { login } from '../../tasks/login';
import { createAgentPolicyTask, getEndpointIntegrationVersion } from '../../tasks/fleet';
describe('Disabled experimental features on: ', { tags: '@ess' }, () => {
// We need a way to disable experimental features in the Cypress tests
describe.skip('Disabled experimental features on: ', { tags: '@ess' }, () => {
describe('Policy list', () => {
describe('Renders policy list without protection updates feature flag', () => {
let indexedPolicy: IndexedFleetEndpointPolicyResponse;

View file

@ -0,0 +1,43 @@
/*
* 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 { EuiCallOut, EuiSpacer } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n-react';
import React from 'react';
export const ProtectionUpdatesWarningPanel = () => (
<EuiCallOut
title={i18n.translate('xpack.securitySolution.endpoint.protectionUpdates.warningPanel.title', {
defaultMessage: 'Attention',
})}
iconType="alert"
data-test-subj="protection-updates-warning-callout"
>
<FormattedMessage
id="xpack.securitySolution.endpoint.protectionUpdates.warningPanel.content"
defaultMessage="Elastic provides periodic updates to protections artifacts such as the global exception list, malware models, and rule packages to ensure your environment is up to date with latest protections. By default, these artifacts are updated automatically. Disable the automatic updates toggle to manually manage updates to the protections artifacts."
/>
<EuiSpacer size="s" />
<FormattedMessage
id="xpack.securitySolution.endpoint.protectionUpdates.warningPanel.content.note"
defaultMessage="{note} It is strongly advised to keep automatic updates enabled to ensure the highest level of security for your environment. Proceed with caution if you decide to disable automatic updates."
values={{
note: (
<strong>
{i18n.translate(
'xpack.securitySolution.endpoint.protectionUpdates.warningPanel.content.note.bold',
{
defaultMessage: 'Note:',
}
)}
</strong>
),
}}
/>
</EuiCallOut>
);

View file

@ -36,6 +36,7 @@ import { useUserPrivileges } from '../../../../../common/components/user_privile
import { useToasts } from '../../../../../common/lib/kibana';
import { useUpdateEndpointPolicy } from '../../../../hooks/policy/use_update_endpoint_policy';
import type { PolicyData, MaybeImmutable } from '../../../../../../common/endpoint/types';
import { ProtectionUpdatesWarningPanel } from './components/protection_updates_warning_panel';
interface ProtectionUpdatesLayoutProps {
policy: MaybeImmutable<PolicyData>;
@ -44,14 +45,14 @@ interface ProtectionUpdatesLayoutProps {
const AUTOMATIC_UPDATES_CHECKBOX_LABEL = i18n.translate(
'xpack.securitySolution.endpoint.protectionUpdates.useAutomaticUpdates',
{
defaultMessage: 'Use automatic updates',
defaultMessage: 'Automatic updates enabled',
}
);
const AUTOMATIC_UPDATES_OFF_CHECKBOX_LABEL = i18n.translate(
'xpack.securitySolution.endpoint.protectionUpdates.useAutomaticUpdatesOff',
{
defaultMessage: "Don't use automatic updates",
defaultMessage: 'Automatic updates disabled.',
}
);
@ -373,23 +374,22 @@ export const ProtectionUpdatesLayout = React.memo<ProtectionUpdatesLayoutProps>(
<EuiFlexItem grow={1}>
<EuiTitle size="xxs" data-test-subj={'protection-updates-manifest-name-title'}>
<h5>
{i18n.translate(
'xpack.securitySolution.endpoint.protectionUpdates.manifestName',
{
defaultMessage: 'Manifest name',
}
)}
{i18n.translate('xpack.securitySolution.endpoint.protectionUpdates.title', {
defaultMessage: 'Manage protection updates',
})}
</h5>
</EuiTitle>
<EuiText size="m" data-test-subj="protection-updates-manifest-name">
{'artifactsec'}
</EuiText>
</EuiFlexItem>
<EuiShowFor sizes={['l', 'xl', 'm']}>
{canWritePolicyManagement ? (
<EuiSwitch
disabled={isUpdating || createNoteInProgress || getNoteInProgress}
label={'Update manifest automatically'}
label={i18n.translate(
'xpack.securitySolution.endpoint.protectionUpdates.enableAutomaticUpdates',
{
defaultMessage: 'Enable automatic updates',
}
)}
labelProps={{ 'data-test-subj': 'protection-updates-manifest-switch-label' }}
checked={automaticUpdatesEnabled}
onChange={toggleAutomaticUpdates}
@ -406,6 +406,8 @@ export const ProtectionUpdatesLayout = React.memo<ProtectionUpdatesLayoutProps>(
<EuiHorizontalRule margin="m" />
<EuiSpacer size="m" />
<div style={{ padding: `0 ${paddingSize} ${paddingSize} ${paddingSize}` }}>
<ProtectionUpdatesWarningPanel />
<EuiSpacer size="m" />
{renderManifestOutdatedCallOut()}
{renderContent()}
</div>