diff --git a/x-pack/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules/installation_and_upgrade.md b/x-pack/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules/installation_and_upgrade.md index beda8a9517830a..e5479ec502865c 100644 --- a/x-pack/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules/installation_and_upgrade.md +++ b/x-pack/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules/installation_and_upgrade.md @@ -631,13 +631,9 @@ Given no prebuilt rules are installed in Kibana And there are X prebuilt rules of all types available to install When user opens the Add Rules page Then all X rules available for installation should be displayed in the table -When user opens the rule preview for the 1st rule -Then the preview should open -And all properties of the 1st rule should be displayed in the correct tab and section of the preview (see examples of rule properties above) -When user selects the 2nd rule in the table -Then the preview should be updated -And all properties of the 2nd rule should be displayed in the correct tab and section of the preview (see examples of rule properties above) -And user should be able to repeat this for all X rules +When user opens a rule preview for any rule +Then the preview should appear +And all properties of a rule should be displayed in the correct tab and section of the preview (see examples of rule properties above) ``` #### **Scenario: Tabs and sections without content should be hidden in preview before installing** @@ -783,15 +779,11 @@ And for all of the installed rules there are new versions available And user is on the Rule Management page When user opens the Rule Updates table Then all X rules available for upgrade should be displayed in the table -When user opens the rule preview for the 1st rule -Then the preview should open +When user opens a rule preview for any rule +Then the preview should appear And the "Updates" tab should be active When user selects the "Overview" tab -Then all properties of the new version of the 1st rule should be displayed in the correct tab and section of the preview (see examples of rule properties above) -When user selects the 2nd rule in the table -Then the preview should be updated -And all properties of the new version of the 2nd rule should be displayed in the correct tab and section of the preview (see examples of rule properties above) -And user should be able to repeat this for all X rules +Then all properties of the new version of a rule should be displayed in the correct tab and section of the preview (see examples of rule properties above) ``` #### **Scenario: Tabs and sections without content should be hidden in preview before upgrading** diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/prebuilt_rules/prebuilt_rules_preview.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/prebuilt_rules/prebuilt_rules_preview.cy.ts index fca78851ddf030..1ccb139133f360 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/prebuilt_rules/prebuilt_rules_preview.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/prebuilt_rules/prebuilt_rules_preview.cy.ts @@ -69,253 +69,87 @@ import { } from '../../../../tasks/api_calls/common'; import { enableRules, waitForRulesToFinishExecution } from '../../../../tasks/api_calls/rules'; -const TEST_ENV_TAGS = ['@ess', '@serverless']; - const PREVIEW_TABS = { OVERVIEW: 'Overview', JSON_VIEW: 'JSON view', UPDATES: 'Updates', // Currently open by default on upgrade }; -describe('Detection rules, Prebuilt Rules Installation and Update workflow', () => { - const commonProperties: Partial = { - author: ['Elastic', 'Another author'], - building_block_type: 'default', - severity: 'medium', - severity_mapping: [ - { - field: 'Ransomware.severity', - value: '50', - operator: 'equals', - severity: 'high', - }, - ], - risk_score: 20, - risk_score_mapping: [ - { - field: 'Ransomware.child_processes.score', - operator: 'equals', - risk_score: 30, - value: '', - }, - ], - references: ['https://www.example.com/1', 'https://www.example.com/2'], - false_positives: ['False positive example 1', 'False positive example 2'], - investigation_fields: { - field_names: ['Ransomware.files.path', 'Target.dll.name'], - }, - license: 'MIT', - rule_name_override: 'Endpoint.policy.applied.name', - threat: [ - { - framework: 'MITRE ATT&CK', - tactic: { - id: 'TA0009', - reference: 'https://attack.mitre.org/tactics/TA0009', - name: 'Collection', - }, - technique: [ - { - id: 'T1557', - reference: 'https://attack.mitre.org/techniques/T1557', - name: 'Adversary-in-the-Middle', - subtechnique: [ - { - id: 'T1557.002', - reference: 'https://attack.mitre.org/techniques/T1557/002', - name: 'ARP Cache Poisoning', - }, - ], - }, - ], - }, - ], - timestamp_override: 'Target.process.start', - tags: ['tag-a', 'tag-b'], - related_integrations: [ - { package: 'endpoint', version: '^8.2.0' }, - { package: 'windows', version: '^1.5.0' }, - ], - required_fields: [ - { name: 'event.type', type: 'keyword' }, - { name: 'file.extension', type: 'keyword' }, - ], - timeline_id: '3e827bab-838a-469f-bd1e-5e19a2bff2fd', - timeline_title: 'Alerts Involving a Single User Timeline', - interval: '5m', - from: 'now-360s', - note: 'Investigation guide content', - setup: 'Setup guide content', - }; - - const filters = [ - { - meta: { - disabled: false, - negate: false, - alias: null, - index: 'security-solution-default', - key: 'Endpoint.policy.applied.artifacts.global.identifiers.name', - field: 'Endpoint.policy.applied.artifacts.global.identifiers.name', - value: 'exists', - type: 'exists', - }, - query: { - exists: { - field: 'Endpoint.policy.applied.artifacts.global.identifiers.name', +describe( + 'Detection rules, Prebuilt Rules Installation and Update workflow', + { tags: ['@ess', '@serverless'] }, + () => { + const commonProperties: Partial = { + author: ['Elastic', 'Another author'], + building_block_type: 'default', + severity: 'medium', + severity_mapping: [ + { + field: 'Ransomware.severity', + value: '50', + operator: 'equals', + severity: 'high', }, - }, - $state: { store: 'appState' }, - }, - ]; - - const queryProperties: Partial = { - query: '_id : *', - language: 'kuery', - filters, - }; - - const CUSTOM_QUERY_INDEX_PATTERN_RULE = createRuleAssetSavedObject({ - name: 'Custom query index pattern rule', - rule_id: 'custom_query_index_pattern_rule', - ...(commonProperties as Record), - ...queryProperties, - type: 'query', - index: ['winlogbeat-*', 'logs-endpoint.events.*'], - alert_suppression: { - group_by: [ - 'Endpoint.policy.applied.artifacts.global.identifiers.name', - 'Endpoint.policy.applied.id', ], - duration: { unit: 'm', value: 5 }, - missing_fields_strategy: 'suppress', - }, - }); - - const SAVED_QUERY_DATA_VIEW_RULE = createRuleAssetSavedObject({ - name: 'Custom query data view rule', - rule_id: 'custom_query_data_view_rule', - ...(commonProperties as Record), - type: 'saved_query', - data_view_id: 'my-test-data-view-id', - saved_id: '', - language: 'kuery', - index: ['winlogbeat-*', 'logs-endpoint.events.*'], - alert_suppression: { - group_by: [ - 'Endpoint.policy.applied.artifacts.global.identifiers.name', - 'Endpoint.policy.applied.id', + risk_score: 20, + risk_score_mapping: [ + { + field: 'Ransomware.child_processes.score', + operator: 'equals', + risk_score: 30, + value: '', + }, ], - duration: { unit: 'm', value: 5 }, - missing_fields_strategy: 'suppress', - }, - query: '', - }); - - const MACHINE_LEARNING_RULE = omit( - createRuleAssetSavedObject({ - name: 'Machine learning rule', - rule_id: 'machine_learning_rule', - ...commonProperties, - type: 'machine_learning', - anomaly_threshold: 65, - machine_learning_job_id: ['auth_high_count_logon_events', 'auth_high_count_logon_fails'], - alert_suppression: { - group_by: ['host.name'], - duration: { unit: 'm', value: 5 }, - missing_fields_strategy: 'suppress', + references: ['https://www.example.com/1', 'https://www.example.com/2'], + false_positives: ['False positive example 1', 'False positive example 2'], + investigation_fields: { + field_names: ['Ransomware.files.path', 'Target.dll.name'], }, - }), - ['security-rule.query', 'security-rule.language'] - ) as Omit< - ReturnType, - 'security-rule.query' | 'security-rule.language' - >; - - const THRESHOLD_RULE_INDEX_PATTERN = createRuleAssetSavedObject({ - name: 'Threshold index pattern rule', - rule_id: 'threshold_index_pattern_rule', - ...commonProperties, - ...queryProperties, - type: 'threshold', - language: 'lucene', - index: ['winlogbeat-*', 'logs-endpoint.events.*'], - threshold: { - field: [ - 'Endpoint.policy.applied.artifacts.user.identifiers.name', - 'Endpoint.policy.applied.id', - ], - value: 200, - cardinality: [{ field: 'Ransomware.score', value: 3 }], - }, - alert_suppression: undefined, - }); - - const EQL_INDEX_PATTERN_RULE = createRuleAssetSavedObject({ - name: 'Event correlation index pattern rule', - rule_id: 'eql_index_pattern_rule', - ...commonProperties, - type: 'eql', - language: 'eql', - query: 'process where process.name == "regsvr32.exe"', - index: ['winlogbeat-*', 'logs-endpoint.events.*'], - filters, - alert_suppression: undefined, - }); - - const THREAT_MATCH_INDEX_PATTERN_RULE = createRuleAssetSavedObject({ - name: 'Threat match index pattern rule', - rule_id: 'threat_match_index_pattern_rule', - ...commonProperties, - ...queryProperties, - type: 'threat_match', - language: 'lucene', - index: ['winlogbeat-*', 'logs-endpoint.events.*'], - filters, - threat_query: '@timestamp >= "now-30d/d"', - threat_mapping: [ - { - entries: [ - { - field: 'file.hash.md5', - type: 'mapping', - value: 'threat.indicator.file.hash.md5', + license: 'MIT', + rule_name_override: 'Endpoint.policy.applied.name', + threat: [ + { + framework: 'MITRE ATT&CK', + tactic: { + id: 'TA0009', + reference: 'https://attack.mitre.org/tactics/TA0009', + name: 'Collection', }, - ], - }, - ], - threat_index: ['filebeat-*', 'logs-ti_*'], - threat_filters: [ - { - $state: { store: 'appState' }, - meta: { - disabled: false, - key: 'event.category', - negate: false, - params: { query: 'threat' }, - type: 'phrase', - alias: null, + technique: [ + { + id: 'T1557', + reference: 'https://attack.mitre.org/techniques/T1557', + name: 'Adversary-in-the-Middle', + subtechnique: [ + { + id: 'T1557.002', + reference: 'https://attack.mitre.org/techniques/T1557/002', + name: 'ARP Cache Poisoning', + }, + ], + }, + ], }, - query: { match_phrase: { 'event.category': 'threat' } }, - }, - ], - threat_language: 'kuery', - threat_indicator_path: 'threat.indicator', - alert_suppression: undefined, - }); - - const NEW_TERMS_INDEX_PATTERN_RULE = createRuleAssetSavedObject({ - name: 'New terms index pattern rule', - rule_id: 'new_terms_index_pattern_rule', - ...commonProperties, - ...queryProperties, - type: 'new_terms', - query: '_id: *', - new_terms_fields: ['Endpoint.policy.applied.id', 'Memory_protection.unique_key_v1'], - history_window_start: 'now-9d', - index: ['apm-*-transaction*', 'auditbeat-*'], - language: 'lucene', - filters: [ + ], + timestamp_override: 'Target.process.start', + tags: ['tag-a', 'tag-b'], + related_integrations: [ + { package: 'endpoint', version: '^8.2.0' }, + { package: 'windows', version: '^1.5.0' }, + ], + required_fields: [ + { name: 'event.type', type: 'keyword' }, + { name: 'file.extension', type: 'keyword' }, + ], + timeline_id: '3e827bab-838a-469f-bd1e-5e19a2bff2fd', + timeline_title: 'Alerts Involving a Single User Timeline', + interval: '5m', + from: 'now-360s', + note: 'Investigation guide content', + setup: 'Setup guide content', + }; + + const filters = [ { meta: { disabled: false, @@ -334,138 +168,304 @@ describe('Detection rules, Prebuilt Rules Installation and Update workflow', () }, $state: { store: 'appState' }, }, - ], - alert_suppression: undefined, - }); - - const ESQL_RULE = createRuleAssetSavedObject({ - name: 'ESQL rule', - rule_id: 'esql_rule', - ...commonProperties, - type: 'esql', - language: 'esql', - query: 'FROM .alerts-security.alerts-default | STATS count = COUNT(@timestamp) BY @timestamp', - alert_suppression: { - group_by: [ - 'Endpoint.policy.applied.artifacts.global.identifiers.name', - 'Endpoint.policy.applied.id', + ]; + + const queryProperties: Partial = { + query: '_id : *', + language: 'kuery', + filters, + }; + + const CUSTOM_QUERY_INDEX_PATTERN_RULE = createRuleAssetSavedObject({ + name: 'Custom query index pattern rule', + rule_id: 'custom_query_index_pattern_rule', + ...(commonProperties as Record), + ...queryProperties, + type: 'query', + index: ['winlogbeat-*', 'logs-endpoint.events.*'], + alert_suppression: { + group_by: [ + 'Endpoint.policy.applied.artifacts.global.identifiers.name', + 'Endpoint.policy.applied.id', + ], + duration: { unit: 'm', value: 5 }, + missing_fields_strategy: 'suppress', + }, + }); + + const SAVED_QUERY_DATA_VIEW_RULE = createRuleAssetSavedObject({ + name: 'Custom query data view rule', + rule_id: 'custom_query_data_view_rule', + ...(commonProperties as Record), + type: 'saved_query', + data_view_id: 'my-test-data-view-id', + saved_id: '', + language: 'kuery', + index: ['winlogbeat-*', 'logs-endpoint.events.*'], + alert_suppression: { + group_by: [ + 'Endpoint.policy.applied.artifacts.global.identifiers.name', + 'Endpoint.policy.applied.id', + ], + duration: { unit: 'm', value: 5 }, + missing_fields_strategy: 'suppress', + }, + query: '', + }); + + const MACHINE_LEARNING_RULE = omit( + createRuleAssetSavedObject({ + name: 'Machine learning rule', + rule_id: 'machine_learning_rule', + ...commonProperties, + type: 'machine_learning', + anomaly_threshold: 65, + machine_learning_job_id: ['auth_high_count_logon_events', 'auth_high_count_logon_fails'], + alert_suppression: { + group_by: ['host.name'], + duration: { unit: 'm', value: 5 }, + missing_fields_strategy: 'suppress', + }, + }), + ['security-rule.query', 'security-rule.language'] + ) as Omit< + ReturnType, + 'security-rule.query' | 'security-rule.language' + >; + + const THRESHOLD_RULE_INDEX_PATTERN = createRuleAssetSavedObject({ + name: 'Threshold index pattern rule', + rule_id: 'threshold_index_pattern_rule', + ...commonProperties, + ...queryProperties, + type: 'threshold', + language: 'lucene', + index: ['winlogbeat-*', 'logs-endpoint.events.*'], + threshold: { + field: [ + 'Endpoint.policy.applied.artifacts.user.identifiers.name', + 'Endpoint.policy.applied.id', + ], + value: 200, + cardinality: [{ field: 'Ransomware.score', value: 3 }], + }, + alert_suppression: undefined, + }); + + const EQL_INDEX_PATTERN_RULE = createRuleAssetSavedObject({ + name: 'Event correlation index pattern rule', + rule_id: 'eql_index_pattern_rule', + ...commonProperties, + type: 'eql', + language: 'eql', + query: 'process where process.name == "regsvr32.exe"', + index: ['winlogbeat-*', 'logs-endpoint.events.*'], + filters, + alert_suppression: undefined, + }); + + const THREAT_MATCH_INDEX_PATTERN_RULE = createRuleAssetSavedObject({ + name: 'Threat match index pattern rule', + rule_id: 'threat_match_index_pattern_rule', + ...commonProperties, + ...queryProperties, + type: 'threat_match', + language: 'lucene', + index: ['winlogbeat-*', 'logs-endpoint.events.*'], + filters, + threat_query: '@timestamp >= "now-30d/d"', + threat_mapping: [ + { + entries: [ + { + field: 'file.hash.md5', + type: 'mapping', + value: 'threat.indicator.file.hash.md5', + }, + ], + }, + ], + threat_index: ['filebeat-*', 'logs-ti_*'], + threat_filters: [ + { + $state: { store: 'appState' }, + meta: { + disabled: false, + key: 'event.category', + negate: false, + params: { query: 'threat' }, + type: 'phrase', + alias: null, + }, + query: { match_phrase: { 'event.category': 'threat' } }, + }, + ], + threat_language: 'kuery', + threat_indicator_path: 'threat.indicator', + alert_suppression: undefined, + }); + + const NEW_TERMS_INDEX_PATTERN_RULE = createRuleAssetSavedObject({ + name: 'New terms index pattern rule', + rule_id: 'new_terms_index_pattern_rule', + ...commonProperties, + ...queryProperties, + type: 'new_terms', + query: '_id: *', + new_terms_fields: ['Endpoint.policy.applied.id', 'Memory_protection.unique_key_v1'], + history_window_start: 'now-9d', + index: ['apm-*-transaction*', 'auditbeat-*'], + language: 'lucene', + filters: [ + { + meta: { + disabled: false, + negate: false, + alias: null, + index: 'security-solution-default', + key: 'Endpoint.policy.applied.artifacts.global.identifiers.name', + field: 'Endpoint.policy.applied.artifacts.global.identifiers.name', + value: 'exists', + type: 'exists', + }, + query: { + exists: { + field: 'Endpoint.policy.applied.artifacts.global.identifiers.name', + }, + }, + $state: { store: 'appState' }, + }, ], - duration: { unit: 'm', value: 5 }, - missing_fields_strategy: 'suppress', - }, - }); - - const RULE_WITHOUT_INVESTIGATION_AND_SETUP_GUIDES = createRuleAssetSavedObject({ - name: 'Rule with hidden tabs and sections', - rule_id: 'rule_without_investigation_and_setup_guides', - }); - - const testDataView = { - indexPattern: 'test-*', - name: 'My test data view', - id: 'my-test-data-view-id', - }; - - const testSavedQuery = { - query: 'agent.id: *', - name: 'My test saved query', - filterKey: 'agent.hostname', - }; - - beforeEach(() => { - login(); - resetRulesTableState(); - deleteAlertsAndRules(); - - visitRulesManagementTable(); - }); - - describe('Installation of prebuilt rules', () => { - const RULE_1 = createRuleAssetSavedObject({ - name: 'Test rule 1', - rule_id: 'rule_1', + alert_suppression: undefined, }); - const RULE_2 = createRuleAssetSavedObject({ - name: 'Test rule 2', - rule_id: 'rule_2', + const ESQL_RULE = createRuleAssetSavedObject({ + name: 'ESQL rule', + rule_id: 'esql_rule', + ...commonProperties, + type: 'esql', + language: 'esql', + query: 'FROM .alerts-security.alerts-default | STATS count = COUNT(@timestamp) BY @timestamp', + alert_suppression: { + group_by: [ + 'Endpoint.policy.applied.artifacts.global.identifiers.name', + 'Endpoint.policy.applied.id', + ], + duration: { unit: 'm', value: 5 }, + missing_fields_strategy: 'suppress', + }, + }); + + const RULE_WITHOUT_INVESTIGATION_AND_SETUP_GUIDES = createRuleAssetSavedObject({ + name: 'Rule with hidden tabs and sections', + rule_id: 'rule_without_investigation_and_setup_guides', }); + const testDataView = { + indexPattern: 'test-*', + name: 'My test data view', + id: 'my-test-data-view-id', + }; + + const testSavedQuery = { + query: 'agent.id: *', + name: 'My test saved query', + filterKey: 'agent.hostname', + }; + beforeEach(() => { - installPrebuiltRuleAssets([RULE_1, RULE_2]); - cy.intercept('POST', '/internal/detection_engine/prebuilt_rules/installation/_perform').as( - 'installPrebuiltRules' - ); + login(); + resetRulesTableState(); + deleteAlertsAndRules(); + + visitRulesManagementTable(); }); - describe('Basic functionality', { tags: TEST_ENV_TAGS }, () => { - it('User can preview rules available for installation', () => { - clickAddElasticRulesButton(); + describe('Installation of prebuilt rules', () => { + const RULE_1 = createRuleAssetSavedObject({ + name: 'Test rule 1', + rule_id: 'rule_1', + }); - openRuleInstallPreview(RULE_1['security-rule'].name); - closeRulePreview(); + const RULE_2 = createRuleAssetSavedObject({ + name: 'Test rule 2', + rule_id: 'rule_2', }); - it('User can install a rule using the rule preview', () => { - clickAddElasticRulesButton(); + beforeEach(() => { + installPrebuiltRuleAssets([RULE_1, RULE_2]); + cy.intercept('POST', '/internal/detection_engine/prebuilt_rules/installation/_perform').as( + 'installPrebuiltRules' + ); + }); - openRuleInstallPreview(RULE_1['security-rule'].name); - cy.get(INSTALL_PREBUILT_RULE_BUTTON).click(); - cy.wait('@installPrebuiltRules'); - assertRuleInstallationSuccessToastShown([RULE_1]); + describe('Basic functionality', () => { + it('User can preview rules available for installation', () => { + clickAddElasticRulesButton(); - // Go back to rules table and assert that the rules are installed - cy.get(RULE_MANAGEMENT_PAGE_BREADCRUMB).click(); - assertRulesPresentInInstalledRulesTable([RULE_1]); + openRuleInstallPreview(RULE_1['security-rule'].name); + closeRulePreview(); + }); - clickAddElasticRulesButton(); - assertRulesNotPresentInAddPrebuiltRulesTable([RULE_1]); - }); + it('User can install a rule using the rule preview', () => { + clickAddElasticRulesButton(); - it('Tabs and sections without content should be hidden in preview before installing', () => { - installPrebuiltRuleAssets([RULE_WITHOUT_INVESTIGATION_AND_SETUP_GUIDES]); + openRuleInstallPreview(RULE_1['security-rule'].name); + cy.get(INSTALL_PREBUILT_RULE_BUTTON).click(); + cy.wait('@installPrebuiltRules'); + assertRuleInstallationSuccessToastShown([RULE_1]); - clickAddElasticRulesButton(); + // Go back to rules table and assert that the rules are installed + cy.get(RULE_MANAGEMENT_PAGE_BREADCRUMB).click(); + assertRulesPresentInInstalledRulesTable([RULE_1]); - openRuleInstallPreview(RULE_WITHOUT_INVESTIGATION_AND_SETUP_GUIDES['security-rule'].name); + clickAddElasticRulesButton(); + assertRulesNotPresentInAddPrebuiltRulesTable([RULE_1]); + }); - cy.get(INSTALL_PREBUILT_RULE_PREVIEW).contains('Investigation guide').should('not.exist'); - cy.get(INSTALL_PREBUILT_RULE_PREVIEW).contains('Setup guide').should('not.exist'); - }); - }); + it('Tabs and sections without content should be hidden in preview before installing', () => { + installPrebuiltRuleAssets([RULE_WITHOUT_INVESTIGATION_AND_SETUP_GUIDES]); - describe('User can see correct rule information in preview before installing', () => { - beforeEach(() => { - deleteDataView(testDataView.id); - postDataView(testDataView.indexPattern, testDataView.name, testDataView.id); - - deleteSavedQueries(); - createSavedQuery(testSavedQuery.name, testSavedQuery.query, testSavedQuery.filterKey) - .its('body.id') - .then((id: string) => { - (SAVED_QUERY_DATA_VIEW_RULE['security-rule'] as { saved_id: string }).saved_id = id; - - installPrebuiltRuleAssets([ - CUSTOM_QUERY_INDEX_PATTERN_RULE, - SAVED_QUERY_DATA_VIEW_RULE, - MACHINE_LEARNING_RULE, - THRESHOLD_RULE_INDEX_PATTERN, - EQL_INDEX_PATTERN_RULE, - THREAT_MATCH_INDEX_PATTERN_RULE, - NEW_TERMS_INDEX_PATTERN_RULE, - ESQL_RULE, - RULE_WITHOUT_INVESTIGATION_AND_SETUP_GUIDES, - ]); - }); + clickAddElasticRulesButton(); - fetchMachineLearningModules() - .its('body') - .then((mlModules) => { - cy.wrap(mlModules).as('mlModules'); - }); + openRuleInstallPreview(RULE_WITHOUT_INVESTIGATION_AND_SETUP_GUIDES['security-rule'].name); + + cy.get(INSTALL_PREBUILT_RULE_PREVIEW).contains('Investigation guide').should('not.exist'); + cy.get(INSTALL_PREBUILT_RULE_PREVIEW).contains('Setup guide').should('not.exist'); + }); }); - describe('All environments', { tags: TEST_ENV_TAGS }, () => { + describe('User can see correct rule information in preview before installing', () => { + beforeEach(() => { + deleteDataView(testDataView.id); + postDataView(testDataView.indexPattern, testDataView.name, testDataView.id); + + deleteSavedQueries(); + createSavedQuery(testSavedQuery.name, testSavedQuery.query, testSavedQuery.filterKey) + .its('body.id') + .then((id: string) => { + (SAVED_QUERY_DATA_VIEW_RULE['security-rule'] as { saved_id: string }).saved_id = id; + + installPrebuiltRuleAssets([ + CUSTOM_QUERY_INDEX_PATTERN_RULE, + SAVED_QUERY_DATA_VIEW_RULE, + MACHINE_LEARNING_RULE, + THRESHOLD_RULE_INDEX_PATTERN, + EQL_INDEX_PATTERN_RULE, + THREAT_MATCH_INDEX_PATTERN_RULE, + NEW_TERMS_INDEX_PATTERN_RULE, + ESQL_RULE, + RULE_WITHOUT_INVESTIGATION_AND_SETUP_GUIDES, + ]); + }); + + fetchMachineLearningModules() + .its('body') + .then((mlModules) => { + cy.wrap(mlModules).as('mlModules'); + }); + }); + it('Custom query rule properties', () => { clickAddElasticRulesButton(); @@ -661,216 +661,215 @@ describe('Detection rules, Prebuilt Rules Installation and Update workflow', () }); }); }); - }); - - describe('Upgrade of prebuilt rules', () => { - const RULE_1_ID = 'rule_1'; - const RULE_2_ID = 'rule_2'; - const OUTDATED_RULE_1 = createRuleAssetSavedObject({ - name: 'Outdated rule 1', - rule_id: RULE_1_ID, - version: 1, - }); - const UPDATED_RULE_1 = createRuleAssetSavedObject({ - name: 'Updated rule 1', - rule_id: RULE_1_ID, - version: 2, - }); - const OUTDATED_RULE_2 = createRuleAssetSavedObject({ - name: 'Outdated rule 2', - rule_id: RULE_2_ID, - version: 1, - }); - const UPDATED_RULE_2 = createRuleAssetSavedObject({ - name: 'Updated rule 2', - rule_id: RULE_2_ID, - version: 2, - }); - beforeEach(() => { - cy.intercept('POST', '/internal/detection_engine/prebuilt_rules/upgrade/_perform').as( - 'updatePrebuiltRules' - ); - /* Create a new rule and install it */ - createAndInstallMockedPrebuiltRules([OUTDATED_RULE_1, OUTDATED_RULE_2]); - /* Create a second version of the rule, making it available for update */ - installPrebuiltRuleAssets([UPDATED_RULE_1, UPDATED_RULE_2]); - visitRulesManagementTable(); - }); + describe('Upgrade of prebuilt rules', () => { + const RULE_1_ID = 'rule_1'; + const RULE_2_ID = 'rule_2'; + const OUTDATED_RULE_1 = createRuleAssetSavedObject({ + name: 'Outdated rule 1', + rule_id: RULE_1_ID, + version: 1, + }); + const UPDATED_RULE_1 = createRuleAssetSavedObject({ + name: 'Updated rule 1', + rule_id: RULE_1_ID, + version: 2, + }); + const OUTDATED_RULE_2 = createRuleAssetSavedObject({ + name: 'Outdated rule 2', + rule_id: RULE_2_ID, + version: 1, + }); + const UPDATED_RULE_2 = createRuleAssetSavedObject({ + name: 'Updated rule 2', + rule_id: RULE_2_ID, + version: 2, + }); + beforeEach(() => { + cy.intercept('POST', '/internal/detection_engine/prebuilt_rules/upgrade/_perform').as( + 'updatePrebuiltRules' + ); + /* Create a new rule and install it */ + createAndInstallMockedPrebuiltRules([OUTDATED_RULE_1, OUTDATED_RULE_2]); + /* Create a second version of the rule, making it available for update */ + installPrebuiltRuleAssets([UPDATED_RULE_1, UPDATED_RULE_2]); + + visitRulesManagementTable(); + }); - describe('Basic functionality', { tags: TEST_ENV_TAGS }, () => { - it('User can preview rules available for upgrade', () => { - clickRuleUpdatesTab(); + describe('Basic functionality', () => { + it('User can preview rules available for upgrade', () => { + clickRuleUpdatesTab(); - openRuleUpdatePreview(OUTDATED_RULE_1['security-rule'].name); - cy.get(UPDATE_PREBUILT_RULE_BUTTON).click(); - cy.wait('@updatePrebuiltRules'); + openRuleUpdatePreview(OUTDATED_RULE_1['security-rule'].name); + cy.get(UPDATE_PREBUILT_RULE_BUTTON).click(); + cy.wait('@updatePrebuiltRules'); - assertRuleUpgradeSuccessToastShown([OUTDATED_RULE_1]); - cy.get(RULE_MANAGEMENT_PAGE_BREADCRUMB).click(); + assertRuleUpgradeSuccessToastShown([OUTDATED_RULE_1]); + cy.get(RULE_MANAGEMENT_PAGE_BREADCRUMB).click(); - assertRulesNotPresentInRuleUpdatesTable([OUTDATED_RULE_1]); - }); + assertRulesNotPresentInRuleUpdatesTable([OUTDATED_RULE_1]); + }); + + it('User can upgrade a rule using the rule preview', () => { + clickRuleUpdatesTab(); + + openRuleUpdatePreview(OUTDATED_RULE_1['security-rule'].name); + closeRulePreview(); + }); + + it('Tabs and sections without content should be hidden in preview before upgrading', () => { + const UPDATED_RULE_WITHOUT_INVESTIGATION_AND_SETUP_GUIDES = { + ...RULE_WITHOUT_INVESTIGATION_AND_SETUP_GUIDES, + ['security-rule']: { + ...RULE_WITHOUT_INVESTIGATION_AND_SETUP_GUIDES['security-rule'], + version: 2, + }, + }; + + createAndInstallMockedPrebuiltRules([RULE_WITHOUT_INVESTIGATION_AND_SETUP_GUIDES]); + + installPrebuiltRuleAssets([UPDATED_RULE_WITHOUT_INVESTIGATION_AND_SETUP_GUIDES]); + + cy.reload(); - it('User can upgrade a rule using the rule preview', () => { - clickRuleUpdatesTab(); + clickRuleUpdatesTab(); - openRuleUpdatePreview(OUTDATED_RULE_1['security-rule'].name); - closeRulePreview(); + openRuleUpdatePreview( + UPDATED_RULE_WITHOUT_INVESTIGATION_AND_SETUP_GUIDES['security-rule'].name + ); + cy.get(UPDATE_PREBUILT_RULE_PREVIEW).contains('Investigation guide').should('not.exist'); + cy.get(UPDATE_PREBUILT_RULE_PREVIEW).contains('Setup guide').should('not.exist'); + }); }); - it('Tabs and sections without content should be hidden in preview before upgrading', () => { - const UPDATED_RULE_WITHOUT_INVESTIGATION_AND_SETUP_GUIDES = { - ...RULE_WITHOUT_INVESTIGATION_AND_SETUP_GUIDES, + describe('User can see correct rule information in preview before upgrading', () => { + const UPDATED_CUSTOM_QUERY_INDEX_PATTERN_RULE = { + ...CUSTOM_QUERY_INDEX_PATTERN_RULE, ['security-rule']: { - ...RULE_WITHOUT_INVESTIGATION_AND_SETUP_GUIDES['security-rule'], + ...CUSTOM_QUERY_INDEX_PATTERN_RULE['security-rule'], + query: '_id : * and event.type: start', version: 2, }, }; - createAndInstallMockedPrebuiltRules([RULE_WITHOUT_INVESTIGATION_AND_SETUP_GUIDES]); - - installPrebuiltRuleAssets([UPDATED_RULE_WITHOUT_INVESTIGATION_AND_SETUP_GUIDES]); + const UPDATED_SAVED_QUERY_DATA_VIEW_RULE = { + ...SAVED_QUERY_DATA_VIEW_RULE, + ['security-rule']: { + ...SAVED_QUERY_DATA_VIEW_RULE['security-rule'], + alert_suppression: { + group_by: ['Endpoint.policy.applied.id'], + duration: { unit: 'm', value: 10 }, + missing_fields_strategy: 'suppress', + }, + version: 2, + }, + } as typeof SAVED_QUERY_DATA_VIEW_RULE; - cy.reload(); + const UPDATED_MACHINE_LEARNING_RULE = { + ...MACHINE_LEARNING_RULE, + ['security-rule']: { + ...MACHINE_LEARNING_RULE['security-rule'], + anomaly_threshold: 99, + version: 2, + }, + }; - clickRuleUpdatesTab(); + const UPDATED_THRESHOLD_RULE_INDEX_PATTERN = { + ...THRESHOLD_RULE_INDEX_PATTERN, + ['security-rule']: { + ...THRESHOLD_RULE_INDEX_PATTERN['security-rule'], + threshold: { + field: ['Endpoint.policy.applied.artifacts.user.identifiers.name'], + value: 999, + cardinality: [{ field: 'Ransomware.score', value: 10 }], + }, + version: 2, + }, + }; - openRuleUpdatePreview( - UPDATED_RULE_WITHOUT_INVESTIGATION_AND_SETUP_GUIDES['security-rule'].name - ); - cy.get(UPDATE_PREBUILT_RULE_PREVIEW).contains('Investigation guide').should('not.exist'); - cy.get(UPDATE_PREBUILT_RULE_PREVIEW).contains('Setup guide').should('not.exist'); - }); - }); + const UPDATED_EQL_INDEX_PATTERN_RULE = { + ...EQL_INDEX_PATTERN_RULE, + ['security-rule']: { + ...EQL_INDEX_PATTERN_RULE['security-rule'], + query: 'process where process.name == "regsvr32.exe" and process.pid == 1234', + version: 2, + }, + }; - describe('User can see correct rule information in preview before upgrading', () => { - const UPDATED_CUSTOM_QUERY_INDEX_PATTERN_RULE = { - ...CUSTOM_QUERY_INDEX_PATTERN_RULE, - ['security-rule']: { - ...CUSTOM_QUERY_INDEX_PATTERN_RULE['security-rule'], - query: '_id : * and event.type: start', - version: 2, - }, - }; - - const UPDATED_SAVED_QUERY_DATA_VIEW_RULE = { - ...SAVED_QUERY_DATA_VIEW_RULE, - ['security-rule']: { - ...SAVED_QUERY_DATA_VIEW_RULE['security-rule'], - alert_suppression: { - group_by: ['Endpoint.policy.applied.id'], - duration: { unit: 'm', value: 10 }, - missing_fields_strategy: 'suppress', + const UPDATED_THREAT_MATCH_INDEX_PATTERN_RULE = { + ...THREAT_MATCH_INDEX_PATTERN_RULE, + ['security-rule']: { + ...THREAT_MATCH_INDEX_PATTERN_RULE['security-rule'], + threat_query: '@timestamp >= "now-60d/d"', + version: 2, }, - version: 2, - }, - } as typeof SAVED_QUERY_DATA_VIEW_RULE; - - const UPDATED_MACHINE_LEARNING_RULE = { - ...MACHINE_LEARNING_RULE, - ['security-rule']: { - ...MACHINE_LEARNING_RULE['security-rule'], - anomaly_threshold: 99, - version: 2, - }, - }; - - const UPDATED_THRESHOLD_RULE_INDEX_PATTERN = { - ...THRESHOLD_RULE_INDEX_PATTERN, - ['security-rule']: { - ...THRESHOLD_RULE_INDEX_PATTERN['security-rule'], - threshold: { - field: ['Endpoint.policy.applied.artifacts.user.identifiers.name'], - value: 999, - cardinality: [{ field: 'Ransomware.score', value: 10 }], + }; + + const UPDATED_NEW_TERMS_INDEX_PATTERN_RULE = { + ...NEW_TERMS_INDEX_PATTERN_RULE, + ['security-rule']: { + ...NEW_TERMS_INDEX_PATTERN_RULE['security-rule'], + new_terms_fields: ['Endpoint.policy.applied.id', 'Memory_protection.unique_key_v2'], + history_window_start: 'now-10d', + version: 2, }, - version: 2, - }, - }; - - const UPDATED_EQL_INDEX_PATTERN_RULE = { - ...EQL_INDEX_PATTERN_RULE, - ['security-rule']: { - ...EQL_INDEX_PATTERN_RULE['security-rule'], - query: 'process where process.name == "regsvr32.exe" and process.pid == 1234', - version: 2, - }, - }; - - const UPDATED_THREAT_MATCH_INDEX_PATTERN_RULE = { - ...THREAT_MATCH_INDEX_PATTERN_RULE, - ['security-rule']: { - ...THREAT_MATCH_INDEX_PATTERN_RULE['security-rule'], - threat_query: '@timestamp >= "now-60d/d"', - version: 2, - }, - }; - - const UPDATED_NEW_TERMS_INDEX_PATTERN_RULE = { - ...NEW_TERMS_INDEX_PATTERN_RULE, - ['security-rule']: { - ...NEW_TERMS_INDEX_PATTERN_RULE['security-rule'], - new_terms_fields: ['Endpoint.policy.applied.id', 'Memory_protection.unique_key_v2'], - history_window_start: 'now-10d', - version: 2, - }, - }; - - const UPDATED_ESQL_RULE = { - ...ESQL_RULE, - ['security-rule']: { - ...ESQL_RULE['security-rule'], - query: - 'FROM .alerts-security.alerts-default | STATS count = COUNT(@timestamp) BY @timestamp, event.category', - version: 2, - }, - }; + }; - beforeEach(() => { - deleteDataView(testDataView.id); - postDataView(testDataView.indexPattern, testDataView.name, testDataView.id); - - deleteSavedQueries(); - createSavedQuery(testSavedQuery.name, testSavedQuery.query, testSavedQuery.filterKey) - .its('body.id') - .then((id: string) => { - (UPDATED_SAVED_QUERY_DATA_VIEW_RULE['security-rule'] as { saved_id: string }).saved_id = - id; - - createAndInstallMockedPrebuiltRules([ - CUSTOM_QUERY_INDEX_PATTERN_RULE, - SAVED_QUERY_DATA_VIEW_RULE, - MACHINE_LEARNING_RULE, - THRESHOLD_RULE_INDEX_PATTERN, - EQL_INDEX_PATTERN_RULE, - THREAT_MATCH_INDEX_PATTERN_RULE, - NEW_TERMS_INDEX_PATTERN_RULE, - ESQL_RULE, - ]); - - installPrebuiltRuleAssets([ - UPDATED_CUSTOM_QUERY_INDEX_PATTERN_RULE, - UPDATED_SAVED_QUERY_DATA_VIEW_RULE, - UPDATED_MACHINE_LEARNING_RULE, - UPDATED_THRESHOLD_RULE_INDEX_PATTERN, - UPDATED_EQL_INDEX_PATTERN_RULE, - UPDATED_THREAT_MATCH_INDEX_PATTERN_RULE, - UPDATED_NEW_TERMS_INDEX_PATTERN_RULE, - UPDATED_ESQL_RULE, - ]); - - cy.reload(); - }); + const UPDATED_ESQL_RULE = { + ...ESQL_RULE, + ['security-rule']: { + ...ESQL_RULE['security-rule'], + query: + 'FROM .alerts-security.alerts-default | STATS count = COUNT(@timestamp) BY @timestamp, event.category', + version: 2, + }, + }; - fetchMachineLearningModules() - .its('body') - .then((mlModules) => { - cy.wrap(mlModules).as('mlModules'); - }); - }); + beforeEach(() => { + deleteDataView(testDataView.id); + postDataView(testDataView.indexPattern, testDataView.name, testDataView.id); + + deleteSavedQueries(); + createSavedQuery(testSavedQuery.name, testSavedQuery.query, testSavedQuery.filterKey) + .its('body.id') + .then((id: string) => { + ( + UPDATED_SAVED_QUERY_DATA_VIEW_RULE['security-rule'] as { saved_id: string } + ).saved_id = id; + + createAndInstallMockedPrebuiltRules([ + CUSTOM_QUERY_INDEX_PATTERN_RULE, + SAVED_QUERY_DATA_VIEW_RULE, + MACHINE_LEARNING_RULE, + THRESHOLD_RULE_INDEX_PATTERN, + EQL_INDEX_PATTERN_RULE, + THREAT_MATCH_INDEX_PATTERN_RULE, + NEW_TERMS_INDEX_PATTERN_RULE, + ESQL_RULE, + ]); + + installPrebuiltRuleAssets([ + UPDATED_CUSTOM_QUERY_INDEX_PATTERN_RULE, + UPDATED_SAVED_QUERY_DATA_VIEW_RULE, + UPDATED_MACHINE_LEARNING_RULE, + UPDATED_THRESHOLD_RULE_INDEX_PATTERN, + UPDATED_EQL_INDEX_PATTERN_RULE, + UPDATED_THREAT_MATCH_INDEX_PATTERN_RULE, + UPDATED_NEW_TERMS_INDEX_PATTERN_RULE, + UPDATED_ESQL_RULE, + ]); + + cy.reload(); + }); + + fetchMachineLearningModules() + .its('body') + .then((mlModules) => { + cy.wrap(mlModules).as('mlModules'); + }); + }); - describe('All environments', { tags: TEST_ENV_TAGS }, () => { it('Custom query rule properties', () => { clickRuleUpdatesTab(); @@ -1087,166 +1086,138 @@ describe('Detection rules, Prebuilt Rules Installation and Update workflow', () assertAlertSuppressionPropertiesShown(alertSuppression); }); }); - }); - - describe('Viewing rule changes in JSON diff view', { tags: TEST_ENV_TAGS }, () => { - it('User can see changes in a side-by-side JSON diff view', () => { - clickRuleUpdatesTab(); - - openRuleUpdatePreview(OUTDATED_RULE_1['security-rule'].name); - selectPreviewTab(PREVIEW_TABS.JSON_VIEW); - - cy.get(UPDATE_PREBUILT_RULE_PREVIEW).contains('Current rule').should('be.visible'); - cy.get(UPDATE_PREBUILT_RULE_PREVIEW).contains('Elastic update').should('be.visible'); - - cy.get(UPDATE_PREBUILT_RULE_PREVIEW).contains('"version": 1').should('be.visible'); - cy.get(UPDATE_PREBUILT_RULE_PREVIEW).contains('"version": 2').should('be.visible'); - - cy.get(UPDATE_PREBUILT_RULE_PREVIEW) - .contains('"name": "Outdated rule 1"') - .should('be.visible'); - /* Select another rule without closing the preview for the current rule */ - openRuleUpdatePreview(OUTDATED_RULE_2['security-rule'].name); + describe('Viewing rule changes in JSON diff view', () => { + it('User can see changes in a side-by-side JSON diff view', () => { + clickRuleUpdatesTab(); - /* Make sure the JSON diff is displayed for the newly selected rule */ - cy.get(UPDATE_PREBUILT_RULE_PREVIEW) - .contains('"name": "Outdated rule 2"') - .should('be.visible'); - cy.get(UPDATE_PREBUILT_RULE_PREVIEW) - .contains('"name": "Outdated rule 1"') - .should('not.exist'); - }); + openRuleUpdatePreview(OUTDATED_RULE_1['security-rule'].name); + selectPreviewTab(PREVIEW_TABS.JSON_VIEW); - it('Dynamic properties should not be included in preview', () => { - const dateBeforeRuleExecution = new Date(); + cy.get(UPDATE_PREBUILT_RULE_PREVIEW).contains('Current rule').should('be.visible'); + cy.get(UPDATE_PREBUILT_RULE_PREVIEW).contains('Elastic update').should('be.visible'); - /* Enable a rule and wait for it to execute */ - enableRules({ names: [OUTDATED_RULE_1['security-rule'].name] }); - waitForRulesToFinishExecution( - [OUTDATED_RULE_1['security-rule'].rule_id], - dateBeforeRuleExecution - ); + cy.get(UPDATE_PREBUILT_RULE_PREVIEW).contains('"version": 1').should('be.visible'); + cy.get(UPDATE_PREBUILT_RULE_PREVIEW).contains('"version": 2').should('be.visible'); - cy.intercept('POST', '/internal/detection_engine/prebuilt_rules/upgrade/_review').as( - 'updatePrebuiltRulesReview' - ); + cy.get(UPDATE_PREBUILT_RULE_PREVIEW) + .contains('"name": "Outdated rule 1"') + .should('be.visible'); - clickRuleUpdatesTab(); + closeRulePreview(); - /* Check that API response contains dynamic properties, like "enabled" and "execution_summary" */ - cy.wait('@updatePrebuiltRulesReview') - .its('response.body') - .then((body: ReviewRuleUpgradeResponseBody) => { - const executedRuleInfo = body.rules.find( - (ruleInfo) => ruleInfo.rule_id === OUTDATED_RULE_1['security-rule'].rule_id - ); + openRuleUpdatePreview(OUTDATED_RULE_2['security-rule'].name); + selectPreviewTab(PREVIEW_TABS.JSON_VIEW); - const enabled = executedRuleInfo?.current_rule?.enabled; - expect(enabled).to.eql(true); + /* Make sure the JSON diff is displayed for the newly selected rule */ + cy.get(UPDATE_PREBUILT_RULE_PREVIEW) + .contains('"name": "Outdated rule 2"') + .should('be.visible'); + cy.get(UPDATE_PREBUILT_RULE_PREVIEW) + .contains('"name": "Outdated rule 1"') + .should('not.exist'); + }); - const executionSummary = executedRuleInfo?.current_rule?.execution_summary; - expect(executionSummary).to.not.eql(undefined); - }); + it('Dynamic properties should not be included in preview', () => { + const dateBeforeRuleExecution = new Date(); - /* Open the preview and check that dynamic properties are not shown in the diff */ - openRuleUpdatePreview(OUTDATED_RULE_1['security-rule'].name); + /* Enable a rule and wait for it to execute */ + enableRules({ names: [OUTDATED_RULE_1['security-rule'].name] }); + waitForRulesToFinishExecution( + [OUTDATED_RULE_1['security-rule'].rule_id], + dateBeforeRuleExecution + ); - cy.get(UPDATE_PREBUILT_RULE_PREVIEW).contains('enabled').should('not.exist'); - cy.get(UPDATE_PREBUILT_RULE_PREVIEW).contains('execution_summary').should('not.exist'); - }); - }); + cy.intercept('POST', '/internal/detection_engine/prebuilt_rules/upgrade/_review').as( + 'updatePrebuiltRulesReview' + ); - describe('Viewing rule changes in per-field diff view', { tags: TEST_ENV_TAGS }, () => { - it('User can see changes in a side-by-side per-field diff view', () => { - clickRuleUpdatesTab(); + clickRuleUpdatesTab(); - openRuleUpdatePreview(OUTDATED_RULE_1['security-rule'].name); - assertSelectedPreviewTab(PREVIEW_TABS.UPDATES); // Should be open by default + /* Check that API response contains dynamic properties, like "enabled" and "execution_summary" */ + cy.wait('@updatePrebuiltRulesReview') + .its('response.body') + .then((body: ReviewRuleUpgradeResponseBody) => { + const executedRuleInfo = body.rules.find( + (ruleInfo) => ruleInfo.rule_id === OUTDATED_RULE_1['security-rule'].rule_id + ); - cy.get(UPDATE_PREBUILT_RULE_PREVIEW).contains('Current rule').should('be.visible'); - cy.get(UPDATE_PREBUILT_RULE_PREVIEW).contains('Elastic update').should('be.visible'); + const enabled = executedRuleInfo?.current_rule?.enabled; + expect(enabled).to.eql(true); - cy.get(PER_FIELD_DIFF_WRAPPER).should('have.length', 2); + const executionSummary = executedRuleInfo?.current_rule?.execution_summary; + expect(executionSummary).to.not.eql(undefined); + }); - /* Version should be the first field in the order */ - cy.get(PER_FIELD_DIFF_WRAPPER).first().contains('Version').should('be.visible'); - cy.get(PER_FIELD_DIFF_WRAPPER).first().contains('1').should('be.visible'); - cy.get(PER_FIELD_DIFF_WRAPPER).first().contains('2').should('be.visible'); + /* Open the preview and check that dynamic properties are not shown in the diff */ + openRuleUpdatePreview(OUTDATED_RULE_1['security-rule'].name); - cy.get(PER_FIELD_DIFF_WRAPPER).last().contains('Name').should('be.visible'); - cy.get(PER_FIELD_DIFF_WRAPPER).last().contains('Outdated rule 1').should('be.visible'); - cy.get(PER_FIELD_DIFF_WRAPPER).last().contains('Updated rule 1').should('be.visible'); + cy.get(UPDATE_PREBUILT_RULE_PREVIEW).contains('enabled').should('not.exist'); + cy.get(UPDATE_PREBUILT_RULE_PREVIEW).contains('execution_summary').should('not.exist'); + }); }); - it('User can switch between rules upgrades without closing flyout', () => { - clickRuleUpdatesTab(); - - openRuleUpdatePreview(OUTDATED_RULE_1['security-rule'].name); - assertSelectedPreviewTab(PREVIEW_TABS.UPDATES); // Should be open by default - - /* Version should be the first field in the order */ - cy.get(PER_FIELD_DIFF_WRAPPER).first().contains('Version').should('be.visible'); - cy.get(PER_FIELD_DIFF_WRAPPER).first().contains('1').should('be.visible'); - cy.get(PER_FIELD_DIFF_WRAPPER).first().contains('2').should('be.visible'); + describe('Viewing rule changes in per-field diff view', () => { + it('User can see changes in a side-by-side per-field diff view', () => { + clickRuleUpdatesTab(); - cy.get(PER_FIELD_DIFF_WRAPPER).last().contains('Name').should('be.visible'); - cy.get(PER_FIELD_DIFF_WRAPPER).last().contains('Outdated rule 1').should('be.visible'); - cy.get(PER_FIELD_DIFF_WRAPPER).last().contains('Updated rule 1').should('be.visible'); + openRuleUpdatePreview(OUTDATED_RULE_1['security-rule'].name); + assertSelectedPreviewTab(PREVIEW_TABS.UPDATES); // Should be open by default - /* Select another rule without closing the preview for the current rule */ - openRuleUpdatePreview(OUTDATED_RULE_2['security-rule'].name); + cy.get(UPDATE_PREBUILT_RULE_PREVIEW).contains('Current rule').should('be.visible'); + cy.get(UPDATE_PREBUILT_RULE_PREVIEW).contains('Elastic update').should('be.visible'); - /* Make sure the per-field diff is displayed for the newly selected rule */ - cy.get(PER_FIELD_DIFF_WRAPPER).last().contains('Name').should('be.visible'); - cy.get(UPDATE_PREBUILT_RULE_PREVIEW).contains('Outdated rule 2').should('be.visible'); - cy.get(UPDATE_PREBUILT_RULE_PREVIEW).contains('Updated rule 2').should('be.visible'); - cy.get(UPDATE_PREBUILT_RULE_PREVIEW).contains('Outdated rule 1').should('not.exist'); - cy.get(UPDATE_PREBUILT_RULE_PREVIEW).contains('Updated rule 1').should('not.exist'); + cy.get(PER_FIELD_DIFF_WRAPPER).should('have.length', 2); - cy.get(PER_FIELD_DIFF_WRAPPER).first().contains('Version').should('be.visible'); - cy.get(PER_FIELD_DIFF_WRAPPER).first().contains('1').should('be.visible'); - cy.get(PER_FIELD_DIFF_WRAPPER).first().contains('2').should('be.visible'); - }); + /* Version should be the first field in the order */ + cy.get(PER_FIELD_DIFF_WRAPPER).first().contains('Version').should('be.visible'); + cy.get(PER_FIELD_DIFF_WRAPPER).first().contains('1').should('be.visible'); + cy.get(PER_FIELD_DIFF_WRAPPER).first().contains('2').should('be.visible'); - it('User can see changes when updated rule is a different rule type', () => { - const OUTDATED_RULE_WITH_QUERY_TYPE = createRuleAssetSavedObject({ - name: 'Query rule', - rule_id: 'rule_id', - version: 1, - type: 'query', - language: 'kuery', + cy.get(PER_FIELD_DIFF_WRAPPER).last().contains('Name').should('be.visible'); + cy.get(PER_FIELD_DIFF_WRAPPER).last().contains('Outdated rule 1').should('be.visible'); + cy.get(PER_FIELD_DIFF_WRAPPER).last().contains('Updated rule 1').should('be.visible'); }); - const UPDATED_RULE_WITH_EQL_TYPE = createRuleAssetSavedObject({ - language: 'eql', - name: 'EQL rule', - rule_id: 'rule_id', - version: 2, - type: 'eql', - }); - /* Create a new rule and install it */ - createAndInstallMockedPrebuiltRules([OUTDATED_RULE_WITH_QUERY_TYPE]); - /* Create a second version of the rule, making it available for update */ - installPrebuiltRuleAssets([UPDATED_RULE_WITH_EQL_TYPE]); - cy.reload(); - clickRuleUpdatesTab(); + it('User can see changes when updated rule is a different rule type', () => { + const OUTDATED_RULE_WITH_QUERY_TYPE = createRuleAssetSavedObject({ + name: 'Query rule', + rule_id: 'rule_id', + version: 1, + type: 'query', + language: 'kuery', + }); + const UPDATED_RULE_WITH_EQL_TYPE = createRuleAssetSavedObject({ + language: 'eql', + name: 'EQL rule', + rule_id: 'rule_id', + version: 2, + type: 'eql', + }); + /* Create a new rule and install it */ + createAndInstallMockedPrebuiltRules([OUTDATED_RULE_WITH_QUERY_TYPE]); + /* Create a second version of the rule, making it available for update */ + installPrebuiltRuleAssets([UPDATED_RULE_WITH_EQL_TYPE]); - openRuleUpdatePreview(OUTDATED_RULE_WITH_QUERY_TYPE['security-rule'].name); - assertSelectedPreviewTab(PREVIEW_TABS.UPDATES); // Should be open by default + cy.reload(); + clickRuleUpdatesTab(); + + openRuleUpdatePreview(OUTDATED_RULE_WITH_QUERY_TYPE['security-rule'].name); + assertSelectedPreviewTab(PREVIEW_TABS.UPDATES); // Should be open by default - cy.get(UPDATE_PREBUILT_RULE_PREVIEW).contains('Current rule').should('be.visible'); - cy.get(UPDATE_PREBUILT_RULE_PREVIEW).contains('Elastic update').should('be.visible'); + cy.get(UPDATE_PREBUILT_RULE_PREVIEW).contains('Current rule').should('be.visible'); + cy.get(UPDATE_PREBUILT_RULE_PREVIEW).contains('Elastic update').should('be.visible'); - cy.get(PER_FIELD_DIFF_WRAPPER).should('have.length', 5); + cy.get(PER_FIELD_DIFF_WRAPPER).should('have.length', 5); - cy.get(PER_FIELD_DIFF_DEFINITION_SECTION).contains('Type').should('be.visible'); - cy.get(PER_FIELD_DIFF_DEFINITION_SECTION).contains('query').should('be.visible'); - cy.get(PER_FIELD_DIFF_DEFINITION_SECTION).contains('eql').should('be.visible'); + cy.get(PER_FIELD_DIFF_DEFINITION_SECTION).contains('Type').should('be.visible'); + cy.get(PER_FIELD_DIFF_DEFINITION_SECTION).contains('query').should('be.visible'); + cy.get(PER_FIELD_DIFF_DEFINITION_SECTION).contains('eql').should('be.visible'); - cy.get(PER_FIELD_DIFF_DEFINITION_SECTION).contains('KQL query').should('exist'); - cy.get(PER_FIELD_DIFF_DEFINITION_SECTION).contains('EQL query').should('exist'); + cy.get(PER_FIELD_DIFF_DEFINITION_SECTION).contains('KQL query').should('exist'); + cy.get(PER_FIELD_DIFF_DEFINITION_SECTION).contains('EQL query').should('exist'); + }); }); }); - }); -}); + } +); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/prebuilt_rules/update_workflow.ts b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/prebuilt_rules/update_workflow.cy.ts similarity index 100% rename from x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/prebuilt_rules/update_workflow.ts rename to x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/prebuilt_rules/update_workflow.cy.ts diff --git a/x-pack/test/security_solution_cypress/cypress/screens/alerts_detection_rules.ts b/x-pack/test/security_solution_cypress/cypress/screens/alerts_detection_rules.ts index 2f59e9362f0515..bbc7a346b252f5 100644 --- a/x-pack/test/security_solution_cypress/cypress/screens/alerts_detection_rules.ts +++ b/x-pack/test/security_solution_cypress/cypress/screens/alerts_detection_rules.ts @@ -280,7 +280,7 @@ export const CUSTOM_QUERY_VALUE = '[data-test-subj="customQueryPropertyValue"]'; export const FILTERS_TITLE = '[data-test-subj="filtersPropertyTitle"]'; export const FILTERS_VALUE_ITEM = - '[data-test-subj="filtersPropertyValue"] [data-test-subj^="filterItem-"]'; + '[data-test-subj="filtersPropertyValue"] [data-test-subj*="filter-badge-"]'; export const ALERT_SUPPRESSION_GROUP_BY_TITLE = '[data-test-subj="alertSuppressionGroupByPropertyTitle"]'; @@ -308,7 +308,7 @@ export const SAVED_QUERY_CONTENT_VALUE = '[data-test-subj="savedQueryContentProp export const SAVED_QUERY_FILTERS_TITLE = '[data-test-subj="savedQueryFiltersPropertyTitle"]'; export const SAVED_QUERY_FILTERS_VALUE = - '[data-test-subj="savedQueryFiltersPropertyValue"] [data-test-subj^="filterItem-"]'; + '[data-test-subj="savedQueryFiltersPropertyValue"] [data-test-subj*="filter-badge-"]'; export const SAVED_QUERY_NAME_TITLE = '[data-test-subj="savedQueryNamePropertyTitle"]'; export const SAVED_QUERY_NAME_VALUE = '[data-test-subj="savedQueryNamePropertyValue"]'; @@ -333,7 +333,7 @@ export const THREAT_MAPPING_VALUE = '[data-test-subj="threatMappingPropertyValue export const THREAT_FILTERS_TITLE = '[data-test-subj="threatFiltersPropertyTitle"]'; export const THREAT_FILTERS_VALUE_ITEM = - '[data-test-subj="threatFiltersPropertyValue"] [data-test-subj^="filterItem-"]'; + '[data-test-subj="threatFiltersPropertyValue"] [data-test-subj*="filter-badge-"]'; export const THREAT_QUERY_TITLE = '[data-test-subj="threatQueryPropertyTitle"]'; export const THREAT_QUERY_VALUE = '[data-test-subj="threatQueryPropertyValue"]'; diff --git a/x-pack/test/security_solution_cypress/cypress/tasks/prebuilt_rules_preview.ts b/x-pack/test/security_solution_cypress/cypress/tasks/prebuilt_rules_preview.ts index 9ce0a1cd84bb64..6617b10ccc219e 100644 --- a/x-pack/test/security_solution_cypress/cypress/tasks/prebuilt_rules_preview.ts +++ b/x-pack/test/security_solution_cypress/cypress/tasks/prebuilt_rules_preview.ts @@ -222,7 +222,7 @@ export const assertCommonPropertiesShown = (properties: Partial