Skip to content

Commit

Permalink
[8.x] [Security Solution][Event Filters] Adds banner about Linux even…
Browse files Browse the repository at this point in the history
…ting change for 8.16 upgrade (elastic#195177) (elastic#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
(elastic#195177)](elastic#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":"[email protected]"},"sourceCommit":{"committedDate":"2024-10-11T13:25:58Z","message":"[Security
Solution][Event Filters] Adds banner about Linux eventing change for
8.16 upgrade (elastic#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=\"https://github.com/user-attachments/assets/e94176b1-e57a-426e-8ebc-135f54a57be0\">\r\n\r\n\r\nhttps://github.com/user-attachments/assets/b2768462-4343-4c85-ad98-36afaba0665c\r\n\r\n---------\r\n\r\nCo-authored-by:
Gergő Ábrahám
<[email protected]>","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 (elastic#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=\"https://github.com/user-attachments/assets/e94176b1-e57a-426e-8ebc-135f54a57be0\">\r\n\r\n\r\nhttps://github.com/user-attachments/assets/b2768462-4343-4c85-ad98-36afaba0665c\r\n\r\n---------\r\n\r\nCo-authored-by:
Gergő Ábrahám
<[email protected]>","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 (elastic#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=\"https://github.com/user-attachments/assets/e94176b1-e57a-426e-8ebc-135f54a57be0\">\r\n\r\n\r\nhttps://github.com/user-attachments/assets/b2768462-4343-4c85-ad98-36afaba0665c\r\n\r\n---------\r\n\r\nCo-authored-by:
Gergő Ábrahám
<[email protected]>","sha":"3f8a6d835a89eb2fb369a16f9210c22462113812"}},{"branch":"8.x","label":"v8.16.0","branchLabelMappingKey":"^v8.16.0$","isSourceBranch":false,"state":"NOT_CREATED"}]}]
BACKPORT-->

Co-authored-by: Candace Park <[email protected]>
  • Loading branch information
kibanamachine and parkiino authored Oct 11, 2024
1 parent d360231 commit 0098832
Show file tree
Hide file tree
Showing 8 changed files with 160 additions and 4 deletions.
1 change: 1 addition & 0 deletions packages/kbn-doc-links/src/get_doc_links.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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`,
Expand Down
1 change: 1 addition & 0 deletions packages/kbn-doc-links/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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: {
Expand Down
Original file line number Diff line number Diff line change
@@ -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();
});
});
Original file line number Diff line number Diff line change
@@ -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';
Original file line number Diff line number Diff line change
Expand Up @@ -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');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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');

Expand All @@ -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]
Expand All @@ -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],
Expand Down Expand Up @@ -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', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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);
Expand All @@ -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 && (
<>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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();
},

Expand Down

0 comments on commit 0098832

Please sign in to comment.