mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
[8.15] [EDR Workflows] Add warning for duplicated `event.category` for Process Descendant event filter (#187844) (#188071)
# Backport This will backport the following commits from `main` to `8.15`: - [[EDR Workflows] Add warning for duplicated `event.category` for Process Descendant event filter (#187844)](https://github.com/elastic/kibana/pull/187844) <!--- Backport version: 9.4.3 --> ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sqren/backport) <!--BACKPORT [{"author":{"name":"Gergő Ábrahám","email":"gergo.abraham@elastic.co"},"sourceCommit":{"committedDate":"2024-07-11T09:40:56Z","message":"[EDR Workflows] Add warning for duplicated `event.category` for Process Descendant event filter (#187844)\n\n## Summary\r\n\r\n\r\n\r\n\r\n\r\n### Checklist\r\n\r\nDelete any items that are not applicable to this PR.\r\n\r\n- [x] [Unit or functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere updated or added to match the most common scenarios\r\n\r\n---------\r\n\r\nCo-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>","sha":"a4cd90b6f328ba87a13416fd1266217bafb7d7cd","branchLabelMapping":{"^v8.16.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","Team:Defend Workflows","v8.15.0","v8.16.0"],"title":"[EDR Workflows] Add warning for duplicated `event.category` for Process Descendant event filter","number":187844,"url":"https://github.com/elastic/kibana/pull/187844","mergeCommit":{"message":"[EDR Workflows] Add warning for duplicated `event.category` for Process Descendant event filter (#187844)\n\n## Summary\r\n\r\n\r\n\r\n\r\n\r\n### Checklist\r\n\r\nDelete any items that are not applicable to this PR.\r\n\r\n- [x] [Unit or functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere updated or added to match the most common scenarios\r\n\r\n---------\r\n\r\nCo-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>","sha":"a4cd90b6f328ba87a13416fd1266217bafb7d7cd"}},"sourceBranch":"main","suggestedTargetBranches":["8.15"],"targetPullRequestStates":[{"branch":"8.15","label":"v8.15.0","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"main","label":"v8.16.0","branchLabelMappingKey":"^v8.16.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/187844","number":187844,"mergeCommit":{"message":"[EDR Workflows] Add warning for duplicated `event.category` for Process Descendant event filter (#187844)\n\n## Summary\r\n\r\n\r\n\r\n\r\n\r\n### Checklist\r\n\r\nDelete any items that are not applicable to this PR.\r\n\r\n- [x] [Unit or functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere updated or added to match the most common scenarios\r\n\r\n---------\r\n\r\nCo-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>","sha":"a4cd90b6f328ba87a13416fd1266217bafb7d7cd"}}]}] BACKPORT--> --------- Co-authored-by: Gergő Ábrahám <gergo.abraham@elastic.co> Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
This commit is contained in:
parent
8d6510f30e
commit
98cd57d9c9
2 changed files with 299 additions and 80 deletions
|
@ -546,90 +546,294 @@ describe('Event filter form', () => {
|
|||
});
|
||||
|
||||
describe('Warnings', () => {
|
||||
beforeEach(() => {
|
||||
render();
|
||||
describe('duplicate fields', () => {
|
||||
it('should not show warning text when unique fields are added', async () => {
|
||||
formProps.item.entries = [
|
||||
{
|
||||
field: 'event.action',
|
||||
operator: 'included',
|
||||
type: 'match',
|
||||
value: 'some value',
|
||||
},
|
||||
{
|
||||
field: 'file.name',
|
||||
operator: 'excluded',
|
||||
type: 'match',
|
||||
value: 'some other value',
|
||||
},
|
||||
];
|
||||
render();
|
||||
expect(await renderResult.findByDisplayValue('some value')).toBeInTheDocument();
|
||||
|
||||
expect(
|
||||
renderResult.queryByTestId('duplicate-fields-warning-message')
|
||||
).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should not show warning text when field values are not added', async () => {
|
||||
formProps.item.entries = [
|
||||
{
|
||||
field: 'event.action',
|
||||
operator: 'included',
|
||||
type: 'match',
|
||||
value: '',
|
||||
},
|
||||
{
|
||||
field: 'event.action',
|
||||
operator: 'excluded',
|
||||
type: 'match',
|
||||
value: '',
|
||||
},
|
||||
];
|
||||
render();
|
||||
expect((await renderResult.findAllByTestId('fieldAutocompleteComboBox')).length).toBe(2);
|
||||
|
||||
expect(
|
||||
renderResult.queryByTestId('duplicate-fields-warning-message')
|
||||
).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should show warning text when duplicate fields are added with values', async () => {
|
||||
formProps.item.entries = [
|
||||
{
|
||||
field: 'event.action',
|
||||
operator: 'included',
|
||||
type: 'match',
|
||||
value: 'some value',
|
||||
},
|
||||
{
|
||||
field: 'event.action',
|
||||
operator: 'excluded',
|
||||
type: 'match',
|
||||
value: 'some other value',
|
||||
},
|
||||
];
|
||||
render();
|
||||
|
||||
expect(
|
||||
await renderResult.findByTestId('duplicate-fields-warning-message')
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
describe('in relation with Process Descendant filtering', () => {
|
||||
it('should not show warning text when event.category is added but feature flag is disabled', async () => {
|
||||
mockedContext.setExperimentalFlag({
|
||||
filterProcessDescendantsForEventFiltersEnabled: false,
|
||||
});
|
||||
|
||||
formProps.item.entries = [
|
||||
{
|
||||
field: 'event.category',
|
||||
operator: 'included',
|
||||
type: 'match',
|
||||
value: 'some value 1',
|
||||
},
|
||||
];
|
||||
formProps.item.tags = [FILTER_PROCESS_DESCENDANTS_TAG];
|
||||
|
||||
render();
|
||||
expect(await renderResult.findByDisplayValue('some value 1')).toBeInTheDocument();
|
||||
|
||||
expect(
|
||||
renderResult.queryByTestId('duplicate-fields-warning-message')
|
||||
).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should not show warning text when event.category is added but process descendant filter is disabled', async () => {
|
||||
mockedContext.setExperimentalFlag({
|
||||
filterProcessDescendantsForEventFiltersEnabled: true,
|
||||
});
|
||||
|
||||
formProps.item.entries = [
|
||||
{
|
||||
field: 'event.category',
|
||||
operator: 'included',
|
||||
type: 'match',
|
||||
value: 'some value 2',
|
||||
},
|
||||
];
|
||||
formProps.item.tags = [];
|
||||
|
||||
render();
|
||||
expect(await renderResult.findByDisplayValue('some value 2')).toBeInTheDocument();
|
||||
|
||||
expect(
|
||||
renderResult.queryByTestId('duplicate-fields-warning-message')
|
||||
).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should not show warning text when event.category is NOT added and process descendant filter is enabled', async () => {
|
||||
mockedContext.setExperimentalFlag({
|
||||
filterProcessDescendantsForEventFiltersEnabled: true,
|
||||
});
|
||||
|
||||
formProps.item.entries = [
|
||||
{
|
||||
field: 'event.action',
|
||||
operator: 'included',
|
||||
type: 'match',
|
||||
value: 'some value 3',
|
||||
},
|
||||
];
|
||||
formProps.item.tags = [FILTER_PROCESS_DESCENDANTS_TAG];
|
||||
|
||||
render();
|
||||
expect(await renderResult.findByDisplayValue('some value 3')).toBeInTheDocument();
|
||||
|
||||
expect(
|
||||
renderResult.queryByTestId('duplicate-fields-warning-message')
|
||||
).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should show warning text when event.category is added and process descendant filter is enabled', async () => {
|
||||
mockedContext.setExperimentalFlag({
|
||||
filterProcessDescendantsForEventFiltersEnabled: true,
|
||||
});
|
||||
|
||||
formProps.item.entries = [
|
||||
{
|
||||
field: 'event.category',
|
||||
operator: 'included',
|
||||
type: 'match',
|
||||
value: 'some value 4',
|
||||
},
|
||||
];
|
||||
formProps.item.tags = [FILTER_PROCESS_DESCENDANTS_TAG];
|
||||
|
||||
render();
|
||||
expect(await renderResult.findByDisplayValue('some value 4')).toBeInTheDocument();
|
||||
|
||||
expect(
|
||||
await renderResult.findByTestId('duplicate-fields-warning-message')
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should add warning text when switching to process descendant filtering', async () => {
|
||||
mockedContext.setExperimentalFlag({
|
||||
filterProcessDescendantsForEventFiltersEnabled: true,
|
||||
});
|
||||
|
||||
formProps.item.entries = [
|
||||
{
|
||||
field: 'event.category',
|
||||
operator: 'included',
|
||||
type: 'match',
|
||||
value: 'some value 5',
|
||||
},
|
||||
];
|
||||
formProps.item.tags = [];
|
||||
|
||||
render();
|
||||
expect(await renderResult.findByDisplayValue('some value 5')).toBeInTheDocument();
|
||||
expect(
|
||||
renderResult.queryByTestId('duplicate-fields-warning-message')
|
||||
).not.toBeInTheDocument();
|
||||
|
||||
// switch to Process Descendant filtering
|
||||
userEvent.click(renderResult.getByTestId(`${formPrefix}-filterProcessDescendantsButton`));
|
||||
rerenderWithLatestProps();
|
||||
|
||||
expect(
|
||||
await renderResult.findByTestId('duplicate-fields-warning-message')
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should remove warning text when switching from process descendant filtering', async () => {
|
||||
mockedContext.setExperimentalFlag({
|
||||
filterProcessDescendantsForEventFiltersEnabled: true,
|
||||
});
|
||||
|
||||
formProps.item.entries = [
|
||||
{
|
||||
field: 'event.category',
|
||||
operator: 'included',
|
||||
type: 'match',
|
||||
value: 'some value 6',
|
||||
},
|
||||
];
|
||||
formProps.item.tags = [FILTER_PROCESS_DESCENDANTS_TAG];
|
||||
|
||||
render();
|
||||
|
||||
expect(
|
||||
await renderResult.findByTestId('duplicate-fields-warning-message')
|
||||
).toBeInTheDocument();
|
||||
|
||||
// switch to classic Event filtering
|
||||
userEvent.click(renderResult.getByTestId(`${formPrefix}-filterEventsButton`));
|
||||
rerenderWithLatestProps();
|
||||
|
||||
expect(await renderResult.findByDisplayValue('some value 6')).toBeInTheDocument();
|
||||
expect(
|
||||
renderResult.queryByTestId('duplicate-fields-warning-message')
|
||||
).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should remove warning text when removing `event.category`', async () => {
|
||||
mockedContext.setExperimentalFlag({
|
||||
filterProcessDescendantsForEventFiltersEnabled: true,
|
||||
});
|
||||
|
||||
formProps.item.entries = [
|
||||
{
|
||||
field: 'event.category',
|
||||
operator: 'included',
|
||||
type: 'match',
|
||||
value: 'some value 6',
|
||||
},
|
||||
];
|
||||
formProps.item.tags = [FILTER_PROCESS_DESCENDANTS_TAG];
|
||||
|
||||
render();
|
||||
|
||||
expect(
|
||||
await renderResult.findByTestId('duplicate-fields-warning-message')
|
||||
).toBeInTheDocument();
|
||||
|
||||
// switch to classic Event filtering
|
||||
userEvent.click(renderResult.getByTestId(`builderItemEntryDeleteButton`));
|
||||
rerenderWithLatestProps();
|
||||
|
||||
expect(
|
||||
renderResult.queryByTestId('duplicate-fields-warning-message')
|
||||
).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should not show warning text when unique fields are added', async () => {
|
||||
formProps.item.entries = [
|
||||
{
|
||||
field: 'event.category',
|
||||
operator: 'included',
|
||||
type: 'match',
|
||||
value: 'some value',
|
||||
},
|
||||
{
|
||||
field: 'file.name',
|
||||
operator: 'excluded',
|
||||
type: 'match',
|
||||
value: 'some other value',
|
||||
},
|
||||
];
|
||||
rerender();
|
||||
expect(renderResult.queryByTestId('duplicate-fields-warning-message')).toBeNull();
|
||||
});
|
||||
describe('wildcard with wrong operator', () => {
|
||||
it('should not show warning callout when wildcard is used with the "MATCHES" operator', async () => {
|
||||
formProps.item.entries = [
|
||||
{
|
||||
field: 'event.category',
|
||||
operator: 'included',
|
||||
type: 'wildcard',
|
||||
value: 'valuewithwildcard*',
|
||||
},
|
||||
];
|
||||
render();
|
||||
expect(await renderResult.findByDisplayValue('valuewithwildcard*')).toBeInTheDocument();
|
||||
|
||||
it('should not show warning text when field values are not added', async () => {
|
||||
formProps.item.entries = [
|
||||
{
|
||||
field: 'event.category',
|
||||
operator: 'included',
|
||||
type: 'match',
|
||||
value: '',
|
||||
},
|
||||
{
|
||||
field: 'event.category',
|
||||
operator: 'excluded',
|
||||
type: 'match',
|
||||
value: '',
|
||||
},
|
||||
];
|
||||
rerender();
|
||||
expect(renderResult.queryByTestId('duplicate-fields-warning-message')).toBeNull();
|
||||
});
|
||||
expect(
|
||||
renderResult.queryByTestId('wildcardWithWrongOperatorCallout')
|
||||
).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should show warning text when duplicate fields are added with values', async () => {
|
||||
formProps.item.entries = [
|
||||
{
|
||||
field: 'event.category',
|
||||
operator: 'included',
|
||||
type: 'match',
|
||||
value: 'some value',
|
||||
},
|
||||
{
|
||||
field: 'event.category',
|
||||
operator: 'excluded',
|
||||
type: 'match',
|
||||
value: 'some other value',
|
||||
},
|
||||
];
|
||||
rerender();
|
||||
expect(renderResult.findByTestId('duplicate-fields-warning-message')).not.toBeNull();
|
||||
});
|
||||
it('should show warning callout when wildcard is used with the "IS" operator', async () => {
|
||||
formProps.item.entries = [
|
||||
{
|
||||
field: 'event.category',
|
||||
operator: 'included',
|
||||
type: 'match',
|
||||
value: 'valuewithwildcard*',
|
||||
},
|
||||
];
|
||||
render();
|
||||
|
||||
it('should not show warning callout when wildcard is used with the "MATCHES" operator', async () => {
|
||||
formProps.item.entries = [
|
||||
{
|
||||
field: 'event.category',
|
||||
operator: 'included',
|
||||
type: 'wildcard',
|
||||
value: 'valuewithwildcard*',
|
||||
},
|
||||
];
|
||||
rerender();
|
||||
expect(renderResult.queryByTestId('wildcardWithWrongOperatorCallout')).toBeNull();
|
||||
});
|
||||
it('should show warning callout when wildcard is used with the "IS" operator', async () => {
|
||||
formProps.item.entries = [
|
||||
{
|
||||
field: 'event.category',
|
||||
operator: 'included',
|
||||
type: 'match',
|
||||
value: 'valuewithwildcard*',
|
||||
},
|
||||
];
|
||||
rerender();
|
||||
await expect(renderResult.findByTestId('wildcardWithWrongOperatorCallout')).not.toBeNull();
|
||||
expect(
|
||||
await renderResult.findByTestId('wildcardWithWrongOperatorCallout')
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -41,6 +41,7 @@ import { useIsExperimentalFeatureEnabled } from '../../../../../common/hooks/use
|
|||
import { useGetUpdatedTags } from '../../../../hooks/artifacts';
|
||||
import {
|
||||
FILTER_PROCESS_DESCENDANTS_TAG,
|
||||
PROCESS_DESCENDANT_EVENT_FILTER_EXTRA_ENTRY,
|
||||
PROCESS_DESCENDANT_EVENT_FILTER_EXTRA_ENTRY_TEXT,
|
||||
} from '../../../../../../common/endpoint/service/artifacts/constants';
|
||||
import {
|
||||
|
@ -545,11 +546,19 @@ export const EventFiltersForm: React.FC<ArtifactFormComponentProps & { allowSele
|
|||
const hasDuplicates =
|
||||
(!hasFormChanged && arg.exceptionItems[0] === undefined) ||
|
||||
isEqual(arg.exceptionItems[0]?.entries, exception?.entries);
|
||||
|
||||
if (hasDuplicates) {
|
||||
const addedFields = arg.exceptionItems[0]?.entries.map((e) => e.field) || [''];
|
||||
|
||||
if (isFilterProcessDescendantsFeatureEnabled && isFilterProcessDescendantsSelected) {
|
||||
addedFields.push(PROCESS_DESCENDANT_EVENT_FILTER_EXTRA_ENTRY.field);
|
||||
}
|
||||
|
||||
setHasDuplicateFields(computeHasDuplicateFields(getAddedFieldsCounts(addedFields)));
|
||||
if (!hasFormChanged) setHasFormChanged(true);
|
||||
return;
|
||||
} else {
|
||||
setHasDuplicateFields(false);
|
||||
}
|
||||
|
||||
// handle wildcard with wrong operator case
|
||||
|
@ -576,7 +585,13 @@ export const EventFiltersForm: React.FC<ArtifactFormComponentProps & { allowSele
|
|||
processChanged(updatedItem);
|
||||
if (!hasFormChanged) setHasFormChanged(true);
|
||||
},
|
||||
[exception, hasFormChanged, processChanged]
|
||||
[
|
||||
exception,
|
||||
hasFormChanged,
|
||||
isFilterProcessDescendantsFeatureEnabled,
|
||||
isFilterProcessDescendantsSelected,
|
||||
processChanged,
|
||||
]
|
||||
);
|
||||
const exceptionBuilderComponentMemo = useMemo(
|
||||
() =>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue