mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
[8.x] [Security Solution][Event Filters] Adds banner about Linux eventing change for 8.16 upgrade (#195177) (#195917)
# Backport This will backport the following commits from `main` to `8.x`: - [[Security Solution][Event Filters] Adds banner about Linux eventing change for 8.16 upgrade (#195177)](https://github.com/elastic/kibana/pull/195177) <!--- Backport version: 9.4.3 --> ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sqren/backport) <!--BACKPORT [{"author":{"name":"Candace Park","email":"56409205+parkiino@users.noreply.github.com"},"sourceCommit":{"committedDate":"2024-10-11T13:25:58Z","message":"[Security Solution][Event Filters] Adds banner about Linux eventing change for 8.16 upgrade (#195177)\n\n## Summary\r\n\r\n- [x] Adds a banner notifying users about the Linux eventing changes for\r\n8.16\r\n- [x] Link to documentation opens in new tab \r\n- [x] Unit tests\r\n\r\n# Screenshot\r\n<img width=\"1662\" alt=\"image\"\r\nsrc=\"b2768462
-4343-4c85-ad98-36afaba0665c\r\n\r\n---------\r\n\r\nCo-authored-by: Gergő Ábrahám <gergo.abraham@elastic.co>","sha":"3f8a6d835a89eb2fb369a16f9210c22462113812","branchLabelMapping":{"^v9.0.0$":"main","^v8.16.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","v9.0.0","Team:Defend Workflows","v8.16.0","backport:version"],"title":"[Security Solution][Event Filters] Adds banner about Linux eventing change for 8.16 upgrade","number":195177,"url":"https://github.com/elastic/kibana/pull/195177","mergeCommit":{"message":"[Security Solution][Event Filters] Adds banner about Linux eventing change for 8.16 upgrade (#195177)\n\n## Summary\r\n\r\n- [x] Adds a banner notifying users about the Linux eventing changes for\r\n8.16\r\n- [x] Link to documentation opens in new tab \r\n- [x] Unit tests\r\n\r\n# Screenshot\r\n<img width=\"1662\" alt=\"image\"\r\nsrc=\"b2768462
-4343-4c85-ad98-36afaba0665c\r\n\r\n---------\r\n\r\nCo-authored-by: Gergő Ábrahám <gergo.abraham@elastic.co>","sha":"3f8a6d835a89eb2fb369a16f9210c22462113812"}},"sourceBranch":"main","suggestedTargetBranches":["8.x"],"targetPullRequestStates":[{"branch":"main","label":"v9.0.0","branchLabelMappingKey":"^v9.0.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/195177","number":195177,"mergeCommit":{"message":"[Security Solution][Event Filters] Adds banner about Linux eventing change for 8.16 upgrade (#195177)\n\n## Summary\r\n\r\n- [x] Adds a banner notifying users about the Linux eventing changes for\r\n8.16\r\n- [x] Link to documentation opens in new tab \r\n- [x] Unit tests\r\n\r\n# Screenshot\r\n<img width=\"1662\" alt=\"image\"\r\nsrc=\"b2768462
-4343-4c85-ad98-36afaba0665c\r\n\r\n---------\r\n\r\nCo-authored-by: Gergő Ábrahám <gergo.abraham@elastic.co>","sha":"3f8a6d835a89eb2fb369a16f9210c22462113812"}},{"branch":"8.x","label":"v8.16.0","branchLabelMappingKey":"^v8.16.0$","isSourceBranch":false,"state":"NOT_CREATED"}]}] BACKPORT--> Co-authored-by: Candace Park <56409205+parkiino@users.noreply.github.com>
This commit is contained in:
parent
d360231339
commit
00988326b5
8 changed files with 160 additions and 4 deletions
|
@ -479,6 +479,7 @@ export const getDocLinks = ({ kibanaBranch, buildFlavor }: GetDocLinkOptions): D
|
|||
blocklist: `${SECURITY_SOLUTION_DOCS}blocklist.html`,
|
||||
threatIntelInt: `${SECURITY_SOLUTION_DOCS}es-threat-intel-integrations.html`,
|
||||
endpointArtifacts: `${SECURITY_SOLUTION_DOCS}endpoint-artifacts.html`,
|
||||
eventMerging: `${SECURITY_SOLUTION_DOCS}endpoint-data-volume.html`,
|
||||
policyResponseTroubleshooting: {
|
||||
full_disk_access: `${SECURITY_SOLUTION_DOCS}deploy-elastic-endpoint.html#enable-fda-endpoint`,
|
||||
macos_system_ext: `${SECURITY_SOLUTION_DOCS}deploy-elastic-endpoint.html#system-extension-endpoint`,
|
||||
|
|
|
@ -346,6 +346,7 @@ export interface DocLinks {
|
|||
readonly avcResults: string;
|
||||
readonly trustedApps: string;
|
||||
readonly eventFilters: string;
|
||||
readonly eventMerging: string;
|
||||
readonly blocklist: string;
|
||||
readonly endpointArtifacts: string;
|
||||
readonly policyResponseTroubleshooting: {
|
||||
|
|
|
@ -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 type { RenderResult } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
import { createAppRootMockRenderer } from '../../../../../../common/mock/endpoint';
|
||||
import { EventMergingBanner, type EventMergingBannerProps } from './event_merging_banner';
|
||||
|
||||
describe('EventMergingBanner component', () => {
|
||||
let formProps: EventMergingBannerProps;
|
||||
let renderResult: RenderResult;
|
||||
|
||||
beforeEach(() => {
|
||||
const mockedContext = createAppRootMockRenderer();
|
||||
|
||||
formProps = {
|
||||
onDismiss: jest.fn(),
|
||||
};
|
||||
|
||||
renderResult = mockedContext.render(<EventMergingBanner {...formProps} />);
|
||||
});
|
||||
|
||||
it('should render event merging banner', () => {
|
||||
expect(renderResult.getByTestId('eventMergingCallout')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should contain a link to documentation', () => {
|
||||
const docLink = renderResult.getByTestId('eventMergingDocLink');
|
||||
|
||||
expect(docLink).toBeInTheDocument();
|
||||
expect(docLink.getAttribute('href')).toContain('endpoint-data-volume.html');
|
||||
});
|
||||
|
||||
it('should call `onDismiss` callback when user clicks dismiss', () => {
|
||||
renderResult.getByTestId('euiDismissCalloutButton').click();
|
||||
|
||||
expect(formProps.onDismiss).toBeCalled();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* 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 { i18n } from '@kbn/i18n';
|
||||
import { EuiCallOut, EuiLink, EuiText } from '@elastic/eui';
|
||||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import { useKibana } from '@kbn/kibana-react-plugin/public';
|
||||
|
||||
export interface EventMergingBannerProps {
|
||||
onDismiss: () => void;
|
||||
}
|
||||
|
||||
export const EventMergingBanner = memo<EventMergingBannerProps>(({ onDismiss }) => {
|
||||
const { docLinks } = useKibana().services;
|
||||
const bannerTitle = i18n.translate(
|
||||
'xpack.securitySolution.endpoint.policy.eventMergingBanner.title',
|
||||
{
|
||||
defaultMessage: "We've recently changed Linux event collection",
|
||||
}
|
||||
);
|
||||
|
||||
return (
|
||||
<EuiCallOut title={bannerTitle} onDismiss={onDismiss} data-test-subj="eventMergingCallout">
|
||||
<EuiText size="s">
|
||||
<FormattedMessage
|
||||
id="xpack.securitySolution.endpoint.policy.eventMergingBanner.body"
|
||||
defaultMessage="Elastic Agent 8.16+ produces less telemetry without reducing system visibility, which may impact existing event filters. For more about these changes and how to adjust your settings, visit our {documentation}."
|
||||
values={{
|
||||
documentation: (
|
||||
<EuiLink
|
||||
href={docLinks?.links.securitySolution.eventMerging}
|
||||
target="_blank"
|
||||
data-test-subj="eventMergingDocLink"
|
||||
>
|
||||
<FormattedMessage
|
||||
id="xpack.securitySolution.endpoint.eventMergingBanner.doc.link"
|
||||
defaultMessage="documentation"
|
||||
/>
|
||||
</EuiLink>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
</EuiText>
|
||||
</EuiCallOut>
|
||||
);
|
||||
});
|
||||
EventMergingBanner.displayName = 'EventMergingBanner';
|
|
@ -176,7 +176,7 @@ export const getPolicySettingsFormTestSubjects = (
|
|||
export const expectIsViewOnly = (elem: HTMLElement): void => {
|
||||
elem
|
||||
.querySelectorAll(
|
||||
'button:not(.euiLink, [data-test-subj*="advancedSection-showButton"]),input,select,textarea'
|
||||
'button:not(.euiLink, [data-test-subj*="advancedSection-showButton"], [data-test-subj="euiDismissCalloutButton"]),input,select,textarea'
|
||||
)
|
||||
.forEach((inputElement) => {
|
||||
expect(inputElement).toHaveAttribute('disabled');
|
||||
|
|
|
@ -23,6 +23,7 @@ import type { PolicyConfig } from '../../../../../../common/endpoint/types';
|
|||
import { AntivirusRegistrationModes } from '../../../../../../common/endpoint/types';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import { cloneDeep } from 'lodash';
|
||||
import type { IStorageWrapper } from '@kbn/kibana-utils-plugin/public';
|
||||
|
||||
jest.mock('../../../../../common/hooks/use_license');
|
||||
|
||||
|
@ -33,11 +34,13 @@ describe('Endpoint Policy Settings Form', () => {
|
|||
let render: () => ReturnType<AppContextTestRender['render']>;
|
||||
let renderResult: ReturnType<typeof render>;
|
||||
let upsellingService: UpsellingService;
|
||||
let storageMock: IStorageWrapper;
|
||||
|
||||
beforeEach(() => {
|
||||
const mockedContext = createAppRootMockRenderer();
|
||||
|
||||
upsellingService = mockedContext.startServices.upselling;
|
||||
storageMock = mockedContext.startServices.storage;
|
||||
|
||||
formProps = {
|
||||
policy: new FleetPackagePolicyGenerator('seed').generateEndpointPackagePolicy().inputs[0]
|
||||
|
@ -50,6 +53,45 @@ describe('Endpoint Policy Settings Form', () => {
|
|||
render = () => (renderResult = mockedContext.render(<PolicySettingsForm {...formProps} />));
|
||||
});
|
||||
|
||||
describe('event merging banner', () => {
|
||||
it('should show the event merging banner for 8.16 if it has never been dismissed', () => {
|
||||
render();
|
||||
|
||||
expect(renderResult.getByTestId('eventMergingCallout')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should show the event merging banner for 8.16 if `securitySolution.showEventMergingBanner` is `true`', () => {
|
||||
storageMock.set('securitySolution.showEventMergingBanner', true);
|
||||
render();
|
||||
|
||||
expect(renderResult.getByTestId('eventMergingCallout')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should hide the event merging banner when user dismisses it', () => {
|
||||
render();
|
||||
expect(renderResult.getByTestId('eventMergingCallout')).toBeInTheDocument();
|
||||
|
||||
renderResult.getByTestId('euiDismissCalloutButton').click();
|
||||
|
||||
expect(renderResult.queryByTestId('eventMergingCallout')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should persist that event merging banner have been dismissed', () => {
|
||||
render();
|
||||
|
||||
renderResult.getByTestId('euiDismissCalloutButton').click();
|
||||
|
||||
expect(storageMock.get('securitySolution.showEventMergingBanner')).toBe(false);
|
||||
});
|
||||
|
||||
it('should not show the banner if it was dismissed before', () => {
|
||||
storageMock.set('securitySolution.showEventMergingBanner', false);
|
||||
render();
|
||||
|
||||
expect(renderResult.queryByTestId('eventMergingCallout')).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
it.each([
|
||||
['malware', testSubj.malware.card],
|
||||
['ransomware', testSubj.ransomware.card],
|
||||
|
@ -91,7 +133,7 @@ describe('Endpoint Policy Settings Form', () => {
|
|||
])('should include %s card', (_, testSubjSelector) => {
|
||||
render();
|
||||
|
||||
expect(renderResult.queryByTestId(testSubjSelector)).toBeNull();
|
||||
expect(renderResult.queryByTestId(testSubjSelector)).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should display upselling component', () => {
|
||||
|
|
|
@ -6,11 +6,13 @@
|
|||
*/
|
||||
|
||||
import type { PropsWithChildren } from 'react';
|
||||
import React, { memo } from 'react';
|
||||
import React, { memo, useState, useCallback } from 'react';
|
||||
import { EuiSpacer, EuiText } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { useKibana } from '../../../../../common/lib/kibana';
|
||||
import { updateAntivirusRegistrationEnabled } from '../../../../../../common/endpoint/utils/update_antivirus_registration_enabled';
|
||||
import { useGetProtectionsUnavailableComponent } from './hooks/use_get_protections_unavailable_component';
|
||||
import { EventMergingBanner } from './components/event_merging_banner';
|
||||
import { AntivirusRegistrationCard } from './components/cards/antivirus_registration_card';
|
||||
import { LinuxEventCollectionCard } from './components/cards/linux_event_collection_card';
|
||||
import { MacEventCollectionCard } from './components/cards/mac_event_collection_card';
|
||||
|
@ -41,6 +43,15 @@ export const PolicySettingsForm = memo<PolicySettingsFormProps>((props) => {
|
|||
const getTestId = useTestIdGenerator(props['data-test-subj']);
|
||||
const ProtectionsUpSellingComponent = useGetProtectionsUnavailableComponent();
|
||||
|
||||
const { storage } = useKibana().services;
|
||||
const [showEventMergingBanner, setShowEventMergingBanner] = useState(
|
||||
storage.get('securitySolution.showEventMergingBanner') ?? true
|
||||
);
|
||||
const onBannerDismiss = useCallback(() => {
|
||||
setShowEventMergingBanner(false);
|
||||
storage.set('securitySolution.showEventMergingBanner', false);
|
||||
}, [storage]);
|
||||
|
||||
const onChangeProxy: PolicySettingsFormProps['onChange'] = ({ isValid, updatedPolicy }) => {
|
||||
// perform tasks that synchronises changes between settings
|
||||
updateAntivirusRegistrationEnabled(updatedPolicy);
|
||||
|
@ -50,8 +61,13 @@ export const PolicySettingsForm = memo<PolicySettingsFormProps>((props) => {
|
|||
|
||||
return (
|
||||
<div data-test-subj={getTestId()}>
|
||||
{showEventMergingBanner && (
|
||||
<>
|
||||
<EventMergingBanner onDismiss={onBannerDismiss} />
|
||||
<EuiSpacer size="s" />
|
||||
</>
|
||||
)}
|
||||
<FormSectionTitle>{PROTECTIONS_SECTION_TITLE}</FormSectionTitle>
|
||||
<EuiSpacer size="s" />
|
||||
|
||||
{ProtectionsUpSellingComponent && (
|
||||
<>
|
||||
|
|
|
@ -19,6 +19,7 @@ export function EndpointPageUtils({ getService }: FtrProviderContext) {
|
|||
*/
|
||||
async clickOnEuiCheckbox(euiCheckBoxTestId: string) {
|
||||
const euiCheckboxInput = await testSubjects.find(euiCheckBoxTestId);
|
||||
await euiCheckboxInput.scrollIntoView();
|
||||
await euiCheckboxInput.click();
|
||||
},
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue