-
Notifications
You must be signed in to change notification settings - Fork 8.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Security Solution] "Data view" selector is shown in "Edit filter" vi…
…ew on the Rule Editing page (#174026) (#174922) ## Summary Addresses #174026 These changes fix the issue with filter editing on the rule's editing page when using index patterns instead of data view. **Steps to reproduce**: 1. Create a custom query rule and add a filter 2. Save the rule 3. Edit the rule 4. Edit the filter **Current behaviour**: Right now when user tries to edit the filter the data view picking UI appears even though index patterns were not modified. <img width="1261" alt="Screenshot 2024-01-16 at 15 14 23" src="https://github.com/elastic/kibana/assets/2700761/b2d28b79-a7d8-482c-a2be-fa8e20cb9e25"> **Expected behaviour**: Data view picking UI should not be present and previously set field and value options should be shown in the filter editing dialog. <img width="1252" alt="Screenshot 2024-01-16 at 15 16 07" src="https://github.com/elastic/kibana/assets/2700761/bb99dd9f-aa6a-4003-b8c4-ccda344c4c5c"> **Cause**: The behaviour for the filter editing on rule’s editing page changed in `8.11` with these changes #166318. We convert `DataViewBase` object without ID set to a `DataView` object with auto-generated ID. This happens each time we try to edit the rule and leads to a different ID which is saved in `filter.meta.index`. Unified search internally checks those IDs to verify whether the filter belongs to provided data view. **Solution**: To solve this issue, we set the data view id explicitly on creating an in-memory data view that represents index patterns and update `filter.meta.index` to use the same ID. ~~**Known issue**: This does not resolve the issue for existing filters. In this case, user will need to update their filters manually.~~ (This was fixed by updating `filter.meta.index` field on rule editing) **Flaky test runner** [ESS 50 times](https://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/4927) [Serverless 50 times](https://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/4935) --------- Co-authored-by: Kibana Machine <[email protected]>
- Loading branch information
1 parent
4cc7583
commit f0f6274
Showing
3 changed files
with
129 additions
and
59 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,6 +5,12 @@ | |
* 2.0. | ||
*/ | ||
|
||
import { | ||
ADD_FILTER_FORM_FIELD_INPUT, | ||
ADD_FILTER_FORM_OPERATOR_FIELD, | ||
GLOBAL_SEARCH_BAR_EDIT_FILTER_MENU_ITEM, | ||
GLOBAL_SEARCH_BAR_FILTER_ITEM, | ||
} from '../../../../screens/search_bar'; | ||
import { getExistingRule, getEditedRule } from '../../../../objects/rule'; | ||
|
||
import { | ||
|
@@ -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_INPUT).should('have.value', 'host.name'); | ||
cy.get(ADD_FILTER_FORM_OPERATOR_FIELD).should('have.value', 'exists'); | ||
}); | ||
if (getEditedRule().interval) { | ||
cy.get(SCHEDULE_DETAILS).within(() => { | ||
getDetails(RUNS_EVERY_DETAILS).should('have.text', getEditedRule().interval); | ||
}); | ||
} | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters