From 22365e6d4a14e06c6de559bc98c117088ce4f37d Mon Sep 17 00:00:00 2001 From: Ievgen Sorokopud Date: Tue, 12 Mar 2024 11:55:37 +0100 Subject: [PATCH] [Security Solution] Cannot edit, add or remove filters on Custom Rule after upgrade to 8.12 (#177838) (#178207) ## Summary Addresses https://github.com/elastic/kibana/issues/177838 These changes fix the bug where users do not receive UI feedback on add/remove/edit filters inside security solution rules. It happens when user selects data view as a source and works correctly with index patterns. The issue was introduced with these changes https://github.com/elastic/kibana/pull/175433/files# where we update filters with the ad-hoc data view id. Since new state variable is updated only when current source is an index pattern. **Fix**: we should always update `searchBarFilters` state variable on source/filters updates. https://github.com/elastic/kibana/assets/2700761/5d8d3932-3fc7-4a5c-a647-4fa2ceda71b2 Also, I added e2e tests to verify that we are able to add filters on rule creation working with both source types. ### Checklist Delete any items that are not applicable to this PR. - [ ] [Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html) was added for features that require explanation or tutorials - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios - [x] [Flaky Test Runner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was used on any tests changed - [x] [ESS 50 times](https://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/5428) - [x] [Serverless 50 times](https://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/5410) --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../common/components/query_bar/index.tsx | 26 ++++++++++++------- .../rule_creation/custom_query_rule.cy.ts | 16 ++++++++++++ .../custom_query_rule_data_view.cy.ts | 16 ++++++++++++ .../cypress/screens/create_new_rule.ts | 3 +++ .../cypress/tasks/create_new_rule.ts | 11 +++++++- 5 files changed, 61 insertions(+), 11 deletions(-) diff --git a/x-pack/plugins/security_solution/public/common/components/query_bar/index.tsx b/x-pack/plugins/security_solution/public/common/components/query_bar/index.tsx index c71abe9b7f2f0..a711e8e8e222d 100644 --- a/x-pack/plugins/security_solution/public/common/components/query_bar/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/query_bar/index.tsx @@ -5,6 +5,7 @@ * 2.0. */ +import { cloneDeep } from 'lodash'; import React, { memo, useMemo, useCallback, useState, useEffect } from 'react'; import deepEqual from 'fast-deep-equal'; @@ -63,7 +64,6 @@ export const QueryBar = memo( }) => { const { data } = useKibana().services; const [dataView, setDataView] = useState(); - const [searchBarFilters, setSearchBarFilters] = useState(filters); const onQuerySubmit = useCallback( (payload: { dateRange: TimeRange; query?: Query | AggregateQuery }) => { if (payload.query != null && !deepEqual(payload.query, filterQuery)) { @@ -129,14 +129,6 @@ export const QueryBar = memo( const createDataView = async () => { dv = await data.dataViews.create({ id: indexPattern.title, title: indexPattern.title }); setDataView(dv); - - /** - * We update filters and set new data view id to make sure that SearchBar does not show data view picker - * More details in https://github.com/elastic/kibana/issues/174026 - */ - const updatedFilters = [...filters]; - updatedFilters.forEach((filter) => (filter.meta.index = indexPattern.title)); - setSearchBarFilters(updatedFilters); }; createDataView(); } @@ -145,7 +137,21 @@ export const QueryBar = memo( data.dataViews.clearInstanceCache(dv?.id); } }; - }, [data.dataViews, filters, indexPattern, isEsql]); + }, [data.dataViews, indexPattern, isEsql]); + + const searchBarFilters = useMemo(() => { + if (isDataView(indexPattern) || isEsql) { + return filters; + } + + /** + * We update filters and set new data view id to make sure that SearchBar does not show data view picker + * More details in https://github.com/elastic/kibana/issues/174026 + */ + const updatedFilters = cloneDeep(filters); + updatedFilters.forEach((filter) => (filter.meta.index = indexPattern.title)); + return updatedFilters; + }, [filters, indexPattern, isEsql]); const timeHistory = useMemo(() => new TimeHistory(new Storage(localStorage)), []); const arrDataView = useMemo(() => (dataView != null ? [dataView] : []), [dataView]); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/detection_engine/rule_creation/custom_query_rule.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/detection_engine/rule_creation/custom_query_rule.cy.ts index d5918e21fa105..047d56980b85e 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/detection_engine/rule_creation/custom_query_rule.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/detection_engine/rule_creation/custom_query_rule.cy.ts @@ -7,6 +7,7 @@ import { getNewRule } from '../../../../objects/rule'; import { RULE_NAME_HEADER } from '../../../../screens/rule_details'; +import { GLOBAL_SEARCH_BAR_FILTER_ITEM } from '../../../../screens/search_bar'; import { deleteAlertsAndRules } from '../../../../tasks/api_calls/common'; import { @@ -14,9 +15,12 @@ import { fillAboutRuleMinimumAndContinue, fillDefineCustomRuleAndContinue, createRuleWithoutEnabling, + fillDefineCustomRule, + openAddFilterPopover, } from '../../../../tasks/create_new_rule'; import { login } from '../../../../tasks/login'; import { visit } from '../../../../tasks/navigation'; +import { fillAddFilterForm } from '../../../../tasks/search_bar'; import { CREATE_RULE_URL } from '../../../../urls/navigation'; describe('Create custom query rule', { tags: ['@ess', '@serverless'] }, () => { @@ -42,5 +46,17 @@ describe('Create custom query rule', { tags: ['@ess', '@serverless'] }, () => { cy.log('Asserting we have a new rule created'); cy.get(RULE_NAME_HEADER).should('contain', rule.name); }); + + it('Adds filter on define step', () => { + visit(CREATE_RULE_URL); + fillDefineCustomRule(rule); + openAddFilterPopover(); + fillAddFilterForm({ + key: 'host.name', + operator: 'exists', + }); + // Check that newly added filter exists + cy.get(GLOBAL_SEARCH_BAR_FILTER_ITEM).should('have.text', 'host.name: exists'); + }); }); }); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/detection_engine/rule_creation/custom_query_rule_data_view.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/detection_engine/rule_creation/custom_query_rule_data_view.cy.ts index e93a06dd3ca66..bbb34c7a7997a 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/detection_engine/rule_creation/custom_query_rule_data_view.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/detection_engine/rule_creation/custom_query_rule_data_view.cy.ts @@ -47,6 +47,7 @@ import { DATA_VIEW_DETAILS, EDIT_RULE_SETTINGS_LINK, } from '../../../../screens/rule_details'; +import { GLOBAL_SEARCH_BAR_FILTER_ITEM } from '../../../../screens/search_bar'; import { getRulesManagementTableRows, @@ -61,8 +62,10 @@ import { createAndEnableRule, createRuleWithoutEnabling, fillAboutRuleAndContinue, + fillDefineCustomRule, fillDefineCustomRuleAndContinue, fillScheduleRuleAndContinue, + openAddFilterPopover, waitForAlertsToPopulate, } from '../../../../tasks/create_new_rule'; @@ -70,6 +73,7 @@ import { login } from '../../../../tasks/login'; import { visit } from '../../../../tasks/navigation'; import { openRuleManagementPageViaBreadcrumbs } from '../../../../tasks/rules_management'; import { getDetails, waitForTheRuleToBeExecuted } from '../../../../tasks/rule_details'; +import { fillAddFilterForm } from '../../../../tasks/search_bar'; import { CREATE_RULE_URL } from '../../../../urls/navigation'; @@ -176,5 +180,17 @@ describe('Custom query rules', { tags: ['@ess', '@serverless'] }, () => { cy.get(RULE_NAME_HEADER).should('contain', 'Edit rule settings'); }); + + it('Adds filter on define step', () => { + visit(CREATE_RULE_URL); + fillDefineCustomRule(rule); + openAddFilterPopover(); + fillAddFilterForm({ + key: 'host.name', + operator: 'exists', + }); + // Check that newly added filter exists + cy.get(GLOBAL_SEARCH_BAR_FILTER_ITEM).should('have.text', 'host.name: exists'); + }); }); }); diff --git a/x-pack/test/security_solution_cypress/cypress/screens/create_new_rule.ts b/x-pack/test/security_solution_cypress/cypress/screens/create_new_rule.ts index 0b521f68a787a..992b937135773 100644 --- a/x-pack/test/security_solution_cypress/cypress/screens/create_new_rule.ts +++ b/x-pack/test/security_solution_cypress/cypress/screens/create_new_rule.ts @@ -60,6 +60,9 @@ export const CUSTOM_QUERY_INPUT = '[data-test-subj="queryInput"]'; export const CUSTOM_QUERY_BAR = '[data-test-subj="detectionEngineStepDefineRuleQueryBar"]'; +export const QUERY_BAR_ADD_FILTER = + '[data-test-subj="detectionEngineStepDefineRuleQueryBar"] [data-test-subj="addFilter"]'; + export const THREAT_MAPPING_COMBO_BOX_INPUT = '[data-test-subj="threatMatchInput"] [data-test-subj="fieldAutocompleteComboBox"]'; diff --git a/x-pack/test/security_solution_cypress/cypress/tasks/create_new_rule.ts b/x-pack/test/security_solution_cypress/cypress/tasks/create_new_rule.ts index 62091e0e39a5f..c0d40a7bd7644 100644 --- a/x-pack/test/security_solution_cypress/cypress/tasks/create_new_rule.ts +++ b/x-pack/test/security_solution_cypress/cypress/tasks/create_new_rule.ts @@ -122,6 +122,7 @@ import { RULE_INDICES, ALERTS_INDEX_BUTTON, INVESTIGATIONS_INPUT, + QUERY_BAR_ADD_FILTER, } from '../screens/create_new_rule'; import { INDEX_SELECTOR, @@ -408,7 +409,7 @@ export const removeAlertsIndex = () => { }); }; -export const fillDefineCustomRuleAndContinue = (rule: QueryRuleCreateProps) => { +export const fillDefineCustomRule = (rule: QueryRuleCreateProps) => { if (rule.data_view_id !== undefined) { cy.get(DATA_VIEW_OPTION).click(); cy.get(DATA_VIEW_COMBO_BOX).type(`${rule.data_view_id}{enter}`); @@ -416,6 +417,10 @@ export const fillDefineCustomRuleAndContinue = (rule: QueryRuleCreateProps) => { cy.get(CUSTOM_QUERY_INPUT) .first() .type(rule.query || ''); +}; + +export const fillDefineCustomRuleAndContinue = (rule: QueryRuleCreateProps) => { + fillDefineCustomRule(rule); cy.get(DEFINE_CONTINUE_BUTTON).should('exist').click({ force: true }); }; @@ -878,3 +883,7 @@ export const uncheckLoadQueryDynamically = () => { cy.get(LOAD_QUERY_DYNAMICALLY_CHECKBOX).click({ force: true }); cy.get(LOAD_QUERY_DYNAMICALLY_CHECKBOX).should('not.be.checked'); }; + +export const openAddFilterPopover = () => { + cy.get(QUERY_BAR_ADD_FILTER).click(); +};