Skip to content

Commit

Permalink
[8.12] [Security Solution] "Data view" selector is shown in…
Browse files Browse the repository at this point in the history
… "Edit filter" view on the Rule Editing page (#174026) (#174922) (#175433)

# Backport

This will backport the following commits from `main` to `8.12`:
- [[Security Solution] "Data view" selector is shown in
"Edit filter" view on the Rule Editing page (#174026)
(#174922)](#174922)

<!--- Backport version: 9.4.3 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sqren/backport)

<!--BACKPORT [{"author":{"name":"Ievgen
Sorokopud","email":"[email protected]"},"sourceCommit":{"committedDate":"2024-01-24T13:34:54Z","message":"[Security
Solution] \"Data view\" selector is shown in \"Edit filter\" view on the
Rule Editing page (#174026) (#174922)\n\n## Summary\r\n\r\nAddresses
https://github.com/elastic/kibana/issues/174026\r\n\r\nThese changes fix
the issue with filter editing on the rule's editing\r\npage when using
index patterns instead of data view.\r\n\r\n**Steps to
reproduce**:\r\n1. Create a custom query rule and add a filter\r\n2.
Save the rule\r\n3. Edit the rule\r\n4. Edit the filter\r\n\r\n**Current
behaviour**:\r\nRight now when user tries to edit the filter the data
view picking UI\r\nappears even though index patterns were not
modified.\r\n\r\n<img width=\"1261\" alt=\"Screenshot 2024-01-16 at 15
14
23\"\r\nsrc=\"https://github.com/elastic/kibana/assets/2700761/b2d28b79-a7d8-482c-a2be-fa8e20cb9e25\">\r\n\r\n**Expected
behaviour**:\r\nData view picking UI should not be present and
previously set field and\r\nvalue options should be shown in the filter
editing dialog.\r\n\r\n<img width=\"1252\" alt=\"Screenshot 2024-01-16
at 15 16
07\"\r\nsrc=\"https://github.com/elastic/kibana/assets/2700761/bb99dd9f-aa6a-4003-b8c4-ccda344c4c5c\">\r\n\r\n**Cause**:\r\nThe
behaviour for the filter editing on rule’s editing page changed
in\r\n`8.11` with these changes
https://github.com/elastic/kibana/pull/166318.\r\nWe convert
`DataViewBase` object without ID set to a `DataView` object\r\nwith
auto-generated ID. This happens each time we try to edit the rule\r\nand
leads to a different ID which is saved in
`filter.meta.index`.\r\nUnified search internally checks those IDs to
verify whether the filter\r\nbelongs to provided data
view.\r\n\r\n**Solution**:\r\nTo solve this issue, we set the data view
id explicitly on creating an\r\nin-memory data view that represents
index patterns and update\r\n`filter.meta.index` to use the same
ID.\r\n\r\n~~**Known issue**:\r\nThis does not resolve the issue for
existing filters. In this case, user\r\nwill need to update their
filters manually.~~ (This was fixed by\r\nupdating `filter.meta.index`
field on rule editing)\r\n\r\n**Flaky test runner**\r\n[ESS
50\r\ntimes](https://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/4927)\r\n[Serverless
50\r\ntimes](https://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/4935)\r\n\r\n---------\r\n\r\nCo-authored-by:
Kibana Machine
<[email protected]>","sha":"f0f6274b9563cc453a11a937fe66f3bfbe8311bf","branchLabelMapping":{"^v8.13.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:fix","Team:
SecuritySolution","backport:prev-minor","Team:Detection
Engine","v8.13.0"],"title":"[Security Solution] \"Data view\" selector
is shown in \"Edit filter\" view on the Rule Editing page
(#174026)","number":174922,"url":"https://github.com/elastic/kibana/pull/174922","mergeCommit":{"message":"[Security
Solution] \"Data view\" selector is shown in \"Edit filter\" view on the
Rule Editing page (#174026) (#174922)\n\n## Summary\r\n\r\nAddresses
https://github.com/elastic/kibana/issues/174026\r\n\r\nThese changes fix
the issue with filter editing on the rule's editing\r\npage when using
index patterns instead of data view.\r\n\r\n**Steps to
reproduce**:\r\n1. Create a custom query rule and add a filter\r\n2.
Save the rule\r\n3. Edit the rule\r\n4. Edit the filter\r\n\r\n**Current
behaviour**:\r\nRight now when user tries to edit the filter the data
view picking UI\r\nappears even though index patterns were not
modified.\r\n\r\n<img width=\"1261\" alt=\"Screenshot 2024-01-16 at 15
14
23\"\r\nsrc=\"https://github.com/elastic/kibana/assets/2700761/b2d28b79-a7d8-482c-a2be-fa8e20cb9e25\">\r\n\r\n**Expected
behaviour**:\r\nData view picking UI should not be present and
previously set field and\r\nvalue options should be shown in the filter
editing dialog.\r\n\r\n<img width=\"1252\" alt=\"Screenshot 2024-01-16
at 15 16
07\"\r\nsrc=\"https://github.com/elastic/kibana/assets/2700761/bb99dd9f-aa6a-4003-b8c4-ccda344c4c5c\">\r\n\r\n**Cause**:\r\nThe
behaviour for the filter editing on rule’s editing page changed
in\r\n`8.11` with these changes
https://github.com/elastic/kibana/pull/166318.\r\nWe convert
`DataViewBase` object without ID set to a `DataView` object\r\nwith
auto-generated ID. This happens each time we try to edit the rule\r\nand
leads to a different ID which is saved in
`filter.meta.index`.\r\nUnified search internally checks those IDs to
verify whether the filter\r\nbelongs to provided data
view.\r\n\r\n**Solution**:\r\nTo solve this issue, we set the data view
id explicitly on creating an\r\nin-memory data view that represents
index patterns and update\r\n`filter.meta.index` to use the same
ID.\r\n\r\n~~**Known issue**:\r\nThis does not resolve the issue for
existing filters. In this case, user\r\nwill need to update their
filters manually.~~ (This was fixed by\r\nupdating `filter.meta.index`
field on rule editing)\r\n\r\n**Flaky test runner**\r\n[ESS
50\r\ntimes](https://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/4927)\r\n[Serverless
50\r\ntimes](https://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/4935)\r\n\r\n---------\r\n\r\nCo-authored-by:
Kibana Machine
<[email protected]>","sha":"f0f6274b9563cc453a11a937fe66f3bfbe8311bf"}},"sourceBranch":"main","suggestedTargetBranches":[],"targetPullRequestStates":[{"branch":"main","label":"v8.13.0","branchLabelMappingKey":"^v8.13.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/174922","number":174922,"mergeCommit":{"message":"[Security
Solution] \"Data view\" selector is shown in \"Edit filter\" view on the
Rule Editing page (#174026) (#174922)\n\n## Summary\r\n\r\nAddresses
https://github.com/elastic/kibana/issues/174026\r\n\r\nThese changes fix
the issue with filter editing on the rule's editing\r\npage when using
index patterns instead of data view.\r\n\r\n**Steps to
reproduce**:\r\n1. Create a custom query rule and add a filter\r\n2.
Save the rule\r\n3. Edit the rule\r\n4. Edit the filter\r\n\r\n**Current
behaviour**:\r\nRight now when user tries to edit the filter the data
view picking UI\r\nappears even though index patterns were not
modified.\r\n\r\n<img width=\"1261\" alt=\"Screenshot 2024-01-16 at 15
14
23\"\r\nsrc=\"https://github.com/elastic/kibana/assets/2700761/b2d28b79-a7d8-482c-a2be-fa8e20cb9e25\">\r\n\r\n**Expected
behaviour**:\r\nData view picking UI should not be present and
previously set field and\r\nvalue options should be shown in the filter
editing dialog.\r\n\r\n<img width=\"1252\" alt=\"Screenshot 2024-01-16
at 15 16
07\"\r\nsrc=\"https://github.com/elastic/kibana/assets/2700761/bb99dd9f-aa6a-4003-b8c4-ccda344c4c5c\">\r\n\r\n**Cause**:\r\nThe
behaviour for the filter editing on rule’s editing page changed
in\r\n`8.11` with these changes
https://github.com/elastic/kibana/pull/166318.\r\nWe convert
`DataViewBase` object without ID set to a `DataView` object\r\nwith
auto-generated ID. This happens each time we try to edit the rule\r\nand
leads to a different ID which is saved in
`filter.meta.index`.\r\nUnified search internally checks those IDs to
verify whether the filter\r\nbelongs to provided data
view.\r\n\r\n**Solution**:\r\nTo solve this issue, we set the data view
id explicitly on creating an\r\nin-memory data view that represents
index patterns and update\r\n`filter.meta.index` to use the same
ID.\r\n\r\n~~**Known issue**:\r\nThis does not resolve the issue for
existing filters. In this case, user\r\nwill need to update their
filters manually.~~ (This was fixed by\r\nupdating `filter.meta.index`
field on rule editing)\r\n\r\n**Flaky test runner**\r\n[ESS
50\r\ntimes](https://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/4927)\r\n[Serverless
50\r\ntimes](https://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/4935)\r\n\r\n---------\r\n\r\nCo-authored-by:
Kibana Machine
<[email protected]>","sha":"f0f6274b9563cc453a11a937fe66f3bfbe8311bf"}}]}]
BACKPORT-->

---------

Co-authored-by: Ievgen Sorokopud <[email protected]>
  • Loading branch information
kibanamachine and e40pud authored Jan 25, 2024
1 parent 4dc81df commit 0217287
Show file tree
Hide file tree
Showing 3 changed files with 139 additions and 60 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ export const QueryBar = memo<QueryBarComponentProps>(
}) => {
const { data } = useKibana().services;
const [dataView, setDataView] = useState<DataView>();
const [searchBarFilters, setSearchBarFilters] = useState<Filter[]>(filters);
const onQuerySubmit = useCallback(
(payload: { dateRange: TimeRange; query?: Query | AggregateQuery }) => {
if (payload.query != null && !deepEqual(payload.query, filterQuery)) {
Expand Down Expand Up @@ -126,8 +127,16 @@ export const QueryBar = memo<QueryBarComponentProps>(
setDataView(indexPattern);
} else if (!isEsql) {
const createDataView = async () => {
dv = await data.dataViews.create({ title: indexPattern.title });
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();
}
Expand All @@ -136,7 +145,7 @@ export const QueryBar = memo<QueryBarComponentProps>(
data.dataViews.clearInstanceCache(dv?.id);
}
};
}, [data.dataViews, indexPattern, isEsql]);
}, [data.dataViews, filters, indexPattern, isEsql]);

const timeHistory = useMemo(() => new TimeHistory(new Storage(localStorage)), []);
const arrDataView = useMemo(() => (dataView != null ? [dataView] : []), [dataView]);
Expand All @@ -145,7 +154,7 @@ export const QueryBar = memo<QueryBarComponentProps>(
showSubmitButton={false}
dateRangeFrom={dateRangeFrom}
dateRangeTo={dateRangeTo}
filters={filters}
filters={searchBarFilters}
indexPatterns={arrDataView}
isLoading={isLoading}
isRefreshPaused={isRefreshPaused}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@
* 2.0.
*/

import {
ADD_FILTER_FORM_FIELD_SELECTED_VALUE,
ADD_FILTER_FORM_OPERATOR_FIELD_SELECTED_VALUE,
GLOBAL_SEARCH_BAR_EDIT_FILTER_MENU_ITEM,
GLOBAL_SEARCH_BAR_FILTER_ITEM,
} from '../../../../screens/search_bar';
import { getExistingRule, getEditedRule } from '../../../../objects/rule';

import {
Expand Down Expand Up @@ -63,81 +69,137 @@ describe('Custom query rules', { tags: ['@ess', '@serverless', '@brokenInServerl
deleteConnectors();
deleteAlertsAndRules();
login();
createRule(getExistingRule({ rule_id: 'rule1', enabled: true })).then((createdRule) => {
visitEditRulePage(createdRule.body.id);
});
});

it('Allows a rule to be edited', () => {
const existingRule = getExistingRule();
context('Basics', () => {
beforeEach(() => {
createRule(getExistingRule({ rule_id: 'rule1', enabled: true })).then((createdRule) => {
visitEditRulePage(createdRule.body.id);
});
});

it('Allows a rule to be edited', () => {
const existingRule = getExistingRule();

// expect define step to populate
cy.get(CUSTOM_QUERY_INPUT).should('have.value', existingRule.query);

// expect define step to populate
cy.get(CUSTOM_QUERY_INPUT).should('have.value', existingRule.query);
cy.get(DEFINE_INDEX_INPUT).should('have.text', existingRule.index?.join(''));

cy.get(DEFINE_INDEX_INPUT).should('have.text', existingRule.index?.join(''));
goToAboutStepTab();

goToAboutStepTab();
// expect about step to populate
cy.get(RULE_NAME_INPUT).invoke('val').should('eql', existingRule.name);
cy.get(RULE_DESCRIPTION_INPUT).should('have.text', existingRule.description);
cy.get(TAGS_FIELD).should('have.text', existingRule.tags?.join(''));
cy.get(SEVERITY_DROPDOWN).should('have.text', 'High');
cy.get(DEFAULT_RISK_SCORE_INPUT).invoke('val').should('eql', `${existingRule.risk_score}`);

// expect about step to populate
cy.get(RULE_NAME_INPUT).invoke('val').should('eql', existingRule.name);
cy.get(RULE_DESCRIPTION_INPUT).should('have.text', existingRule.description);
cy.get(TAGS_FIELD).should('have.text', existingRule.tags?.join(''));
cy.get(SEVERITY_DROPDOWN).should('have.text', 'High');
cy.get(DEFAULT_RISK_SCORE_INPUT).invoke('val').should('eql', `${existingRule.risk_score}`);
goToScheduleStepTab();

goToScheduleStepTab();
// expect schedule step to populate
const interval = existingRule.interval;
const intervalParts = interval != null && interval.match(/[0-9]+|[a-zA-Z]+/g);
if (intervalParts) {
const [amount, unit] = intervalParts;
cy.get(SCHEDULE_INTERVAL_AMOUNT_INPUT).invoke('val').should('eql', amount);
cy.get(SCHEDULE_INTERVAL_UNITS_INPUT).invoke('val').should('eql', unit);
} else {
throw new Error('Cannot assert scheduling info on a rule without an interval');
}

// expect schedule step to populate
const interval = existingRule.interval;
const intervalParts = interval != null && interval.match(/[0-9]+|[a-zA-Z]+/g);
if (intervalParts) {
const [amount, unit] = intervalParts;
cy.get(SCHEDULE_INTERVAL_AMOUNT_INPUT).invoke('val').should('eql', amount);
cy.get(SCHEDULE_INTERVAL_UNITS_INPUT).invoke('val').should('eql', unit);
} else {
throw new Error('Cannot assert scheduling info on a rule without an interval');
}
goToActionsStepTab();

goToActionsStepTab();
addEmailConnectorAndRuleAction('[email protected]', 'Subject');

addEmailConnectorAndRuleAction('[email protected]', 'Subject');
cy.get(ACTIONS_SUMMARY_BUTTON).should('have.text', 'Summary of alerts');
cy.get(ACTIONS_NOTIFY_WHEN_BUTTON).should('have.text', 'Per rule run');

cy.get(ACTIONS_SUMMARY_BUTTON).should('have.text', 'Summary of alerts');
cy.get(ACTIONS_NOTIFY_WHEN_BUTTON).should('have.text', 'Per rule run');
goToAboutStepTab();
cy.get(TAGS_CLEAR_BUTTON).click();
fillAboutRule(getEditedRule());

goToAboutStepTab();
cy.get(TAGS_CLEAR_BUTTON).click();
fillAboutRule(getEditedRule());
cy.intercept('GET', '/api/detection_engine/rules?id*').as('getRule');

cy.intercept('GET', '/api/detection_engine/rules?id*').as('getRule');
saveEditedRule();

saveEditedRule();
cy.wait('@getRule').then(({ response }) => {
cy.wrap(response?.statusCode).should('eql', 200);
// ensure that editing rule does not modify max_signals
cy.wrap(response?.body.max_signals).should('eql', existingRule.max_signals);
});

cy.wait('@getRule').then(({ response }) => {
cy.wrap(response?.statusCode).should('eql', 200);
// ensure that editing rule does not modify max_signals
cy.wrap(response?.body.max_signals).should('eql', existingRule.max_signals);
cy.get(RULE_NAME_HEADER).should('contain', `${getEditedRule().name}`);
cy.get(ABOUT_RULE_DESCRIPTION).should('have.text', getEditedRule().description);
cy.get(ABOUT_DETAILS).within(() => {
getDetails(SEVERITY_DETAILS).should('have.text', 'Medium');
getDetails(RISK_SCORE_DETAILS).should('have.text', `${getEditedRule().risk_score}`);
getDetails(TAGS_DETAILS).should('have.text', expectedEditedtags);
});
cy.get(INVESTIGATION_NOTES_TOGGLE).click();
cy.get(ABOUT_INVESTIGATION_NOTES).should('have.text', getEditedRule().note);
cy.get(DEFINITION_DETAILS).within(() => {
getDetails(INDEX_PATTERNS_DETAILS).should(
'have.text',
expectedEditedIndexPatterns?.join('')
);
getDetails(CUSTOM_QUERY_DETAILS).should('have.text', getEditedRule().query);
getDetails(RULE_TYPE_DETAILS).should('have.text', 'Query');
getDetails(TIMELINE_TEMPLATE_DETAILS).should('have.text', 'None');
});
if (getEditedRule().interval) {
cy.get(SCHEDULE_DETAILS).within(() => {
getDetails(RUNS_EVERY_DETAILS).should('have.text', getEditedRule().interval);
});
}
});
});

cy.get(RULE_NAME_HEADER).should('contain', `${getEditedRule().name}`);
cy.get(ABOUT_RULE_DESCRIPTION).should('have.text', getEditedRule().description);
cy.get(ABOUT_DETAILS).within(() => {
getDetails(SEVERITY_DETAILS).should('have.text', 'Medium');
getDetails(RISK_SCORE_DETAILS).should('have.text', `${getEditedRule().risk_score}`);
getDetails(TAGS_DETAILS).should('have.text', expectedEditedtags);
context('With filters', () => {
beforeEach(() => {
createRule(
getExistingRule({
rule_id: 'rule1',
enabled: true,
filters: [
{
meta: {
disabled: false,
negate: false,
alias: null,
index: expectedEditedIndexPatterns?.join(','),
key: 'host.name',
field: 'host.name',
type: 'exists',
value: 'exists',
},
query: {
exists: {
field: 'host.name',
},
},
$state: {
store: 'appState',
},
},
],
})
).then((createdRule) => {
visitEditRulePage(createdRule.body.id);
});
});
cy.get(INVESTIGATION_NOTES_TOGGLE).click();
cy.get(ABOUT_INVESTIGATION_NOTES).should('have.text', getEditedRule().note);
cy.get(DEFINITION_DETAILS).within(() => {
getDetails(INDEX_PATTERNS_DETAILS).should('have.text', expectedEditedIndexPatterns?.join(''));
getDetails(CUSTOM_QUERY_DETAILS).should('have.text', getEditedRule().query);
getDetails(RULE_TYPE_DETAILS).should('have.text', 'Query');
getDetails(TIMELINE_TEMPLATE_DETAILS).should('have.text', 'None');

it('Filter properly stores index information', () => {
// Check that filter exists on rule edit page
cy.get(GLOBAL_SEARCH_BAR_FILTER_ITEM).should('have.text', 'host.name: exists');

// Edit the filter
cy.get(GLOBAL_SEARCH_BAR_FILTER_ITEM).click();
cy.get(GLOBAL_SEARCH_BAR_EDIT_FILTER_MENU_ITEM).click();

// Check that correct values are propagated in the filter editing dialog
cy.get(ADD_FILTER_FORM_FIELD_SELECTED_VALUE).should('contain.text', 'host.name');
cy.get(ADD_FILTER_FORM_OPERATOR_FIELD_SELECTED_VALUE).should('contain.text', 'exists');
});
if (getEditedRule().interval) {
cy.get(SCHEDULE_DETAILS).within(() => {
getDetails(RUNS_EVERY_DETAILS).should('have.text', getEditedRule().interval);
});
}
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,18 @@ export const GET_LOCAL_SEARCH_BAR_SUBMIT_BUTTON = (localSearchBarSelector: strin
export const ADD_FILTER_FORM_FIELD_INPUT =
'[data-test-subj="filterFieldSuggestionList"] input[data-test-subj="comboBoxSearchInput"]';

export const ADD_FILTER_FORM_FIELD_SELECTED_VALUE =
'[data-test-subj="filterFieldSuggestionList"] [data-test-subj="euiComboBoxPill"]';

export const ADD_FILTER_FORM_FIELD_OPTION = (value: string) =>
`[data-test-subj="comboBoxOptionsList filterFieldSuggestionList-optionsList"] button[title="${value}"]`;

export const ADD_FILTER_FORM_OPERATOR_FIELD =
'[data-test-subj="filterOperatorList"] input[data-test-subj="comboBoxSearchInput"]';

export const ADD_FILTER_FORM_OPERATOR_FIELD_SELECTED_VALUE =
'[data-test-subj="filterOperatorList"] [data-test-subj="euiComboBoxPill"]';

export const ADD_FILTER_FORM_FILTER_VALUE_INPUT = '[data-test-subj="filterParams"] input';

export const ADD_FILTER_FORM_SAVE_BUTTON = '[data-test-subj="saveFilter"]';
Expand All @@ -38,6 +44,8 @@ export const GLOBAL_SEARCH_BAR_FILTER_ITEM_DELETE = '#popoverFor_filter0 button[

export const GLOBAL_SEARCH_BAR_PINNED_FILTER = '.globalFilterItem-isPinned';

export const GLOBAL_SEARCH_BAR_EDIT_FILTER_MENU_ITEM = '[data-test-subj="editFilter"]';

export const LOCAL_KQL_INPUT = `[data-test-subj="unifiedQueryInput"] textarea`;

export const GLOBAL_KQL_INPUT = `[data-test-subj="filters-global-container"] ${LOCAL_KQL_INPUT}`;
Expand Down

0 comments on commit 0217287

Please sign in to comment.