diff --git a/.buildkite/ftr_security_serverless_configs.yml b/.buildkite/ftr_security_serverless_configs.yml index 57d0c977795fa..076442fe5132f 100644 --- a/.buildkite/ftr_security_serverless_configs.yml +++ b/.buildkite/ftr_security_serverless_configs.yml @@ -78,6 +78,8 @@ enabled: - x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/management/trial_license_complete_tier/configs/serverless.config.ts - x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/update_prebuilt_rules_package/trial_license_complete_tier/configs/serverless.config.ts - x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/configs/serverless.config.ts + - x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/configs/serverless.config.ts + - x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/type_specific_fields/configs/serverless.config.ts - x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_disabled/configs/serverless_complete_tier.config.ts - x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_disabled/configs/serverless_essentials_tier.config.ts - x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_bulk_actions/trial_license_complete_tier/configs/serverless.config.ts diff --git a/.buildkite/ftr_security_stateful_configs.yml b/.buildkite/ftr_security_stateful_configs.yml index 9dcc4cba31b4f..6484aefe16e4a 100644 --- a/.buildkite/ftr_security_stateful_configs.yml +++ b/.buildkite/ftr_security_stateful_configs.yml @@ -59,6 +59,8 @@ enabled: - x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/management/trial_license_complete_tier/configs/ess.config.ts - x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/update_prebuilt_rules_package/trial_license_complete_tier/configs/ess.config.ts - x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/configs/ess.config.ts + - x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/configs/ess.config.ts + - x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/type_specific_fields/configs/ess.config.ts - x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_disabled/configs/ess_basic_license.config.ts - x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_disabled/configs/ess_trial_license.config.ts - x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_bulk_actions/trial_license_complete_tier/configs/ess.config.ts diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/model/rule_assets/prebuilt_rule_asset.mock.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/model/rule_assets/prebuilt_rule_asset.mock.ts index 6442582c1b573..2b5d1d4701d7a 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/model/rule_assets/prebuilt_rule_asset.mock.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/model/rule_assets/prebuilt_rule_asset.mock.ts @@ -109,7 +109,7 @@ export const getPrebuiltNewTermsRuleSpecificFieldsMock = (): NewTermsRuleCreateF query: 'user.name: *', language: 'kuery', new_terms_fields: ['user.name'], - history_window_start: '1h', + history_window_start: 'now-1h', }); export const getPrebuiltEsqlRuleSpecificFieldsMock = (): EsqlRuleCreateFields => ({ diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/management/trial_license_complete_tier/index.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/management/trial_license_complete_tier/index.ts index 72707393c0527..0b57697c483b5 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/management/trial_license_complete_tier/index.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/management/trial_license_complete_tier/index.ts @@ -14,18 +14,6 @@ export default ({ loadTestFile }: FtrProviderContext): void => { loadTestFile(require.resolve('./get_prebuilt_timelines_status')); loadTestFile(require.resolve('./install_prebuilt_rules')); loadTestFile(require.resolve('./install_prebuilt_rules_with_historical_versions')); - loadTestFile(require.resolve('./upgrade_prebuilt_rules')); - loadTestFile(require.resolve('./upgrade_prebuilt_rules_with_historical_versions')); loadTestFile(require.resolve('./fleet_integration')); - loadTestFile(require.resolve('./upgrade_review_prebuilt_rules.rule_type_fields')); - loadTestFile(require.resolve('./upgrade_review_prebuilt_rules.number_fields')); - loadTestFile(require.resolve('./upgrade_review_prebuilt_rules.single_line_string_fields')); - loadTestFile(require.resolve('./upgrade_review_prebuilt_rules.scalar_array_fields')); - loadTestFile(require.resolve('./upgrade_review_prebuilt_rules.multi_line_string_fields')); - loadTestFile(require.resolve('./upgrade_review_prebuilt_rules.data_source_fields')); - loadTestFile(require.resolve('./upgrade_review_prebuilt_rules.kql_query_fields')); - loadTestFile(require.resolve('./upgrade_review_prebuilt_rules.eql_query_fields')); - loadTestFile(require.resolve('./upgrade_review_prebuilt_rules.esql_query_fields')); - loadTestFile(require.resolve('./upgrade_review_prebuilt_rules.stats')); }); }; diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/management/trial_license_complete_tier/upgrade_prebuilt_rules.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/management/trial_license_complete_tier/upgrade_prebuilt_rules.ts deleted file mode 100644 index a23ddf40979f6..0000000000000 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/management/trial_license_complete_tier/upgrade_prebuilt_rules.ts +++ /dev/null @@ -1,279 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ -import expect from 'expect'; -import { PRECONFIGURED_EMAIL_ACTION_CONNECTOR_ID } from '../../../../../../config/shared'; -import { FtrProviderContext } from '../../../../../../ftr_provider_context'; -import { - deleteAllTimelines, - deleteAllPrebuiltRuleAssets, - createRuleAssetSavedObject, - createPrebuiltRuleAssetSavedObjects, - installPrebuiltRulesAndTimelines, - getPrebuiltRulesAndTimelinesStatus, - getPrebuiltRulesStatus, - installPrebuiltRules, - performUpgradePrebuiltRules, - fetchRule, - patchRule, -} from '../../../../utils'; -import { deleteAllRules } from '../../../../../../../common/utils/security_solution'; - -export default ({ getService }: FtrProviderContext): void => { - const es = getService('es'); - const supertest = getService('supertest'); - const log = getService('log'); - - describe('@ess @serverless @skipInServerlessMKI upgrade prebuilt rules from package without historical versions with mock rule assets', () => { - const getRuleAssetSavedObjects = () => [ - createRuleAssetSavedObject({ rule_id: 'rule-1', version: 1 }), - createRuleAssetSavedObject({ rule_id: 'rule-2', version: 2 }), - createRuleAssetSavedObject({ rule_id: 'rule-3', version: 3 }), - createRuleAssetSavedObject({ rule_id: 'rule-4', version: 4 }), - ]; - - beforeEach(async () => { - await deleteAllRules(supertest, log); - await deleteAllTimelines(es, log); - await deleteAllPrebuiltRuleAssets(es, log); - }); - - describe('using legacy endpoint', () => { - it('should upgrade outdated prebuilt rules', async () => { - // Install all prebuilt detection rules - const ruleAssetSavedObjects = getRuleAssetSavedObjects(); - await createPrebuiltRuleAssetSavedObjects(es, ruleAssetSavedObjects); - await installPrebuiltRulesAndTimelines(es, supertest); - - // Clear previous rule assets - await deleteAllPrebuiltRuleAssets(es, log); - // Increment the version of one of the installed rules and create the new rule assets - ruleAssetSavedObjects[0]['security-rule'].version += 1; - await createPrebuiltRuleAssetSavedObjects(es, ruleAssetSavedObjects); - - // Check that one prebuilt rule status shows that one rule is outdated - const statusResponse = await getPrebuiltRulesAndTimelinesStatus(es, supertest); - expect(statusResponse.rules_not_updated).toBe(1); - - // Call the install prebuilt rules again and check that the outdated rule was updated - const response = await installPrebuiltRulesAndTimelines(es, supertest); - expect(response.rules_installed).toBe(0); - expect(response.rules_updated).toBe(1); - }); - - it('should not upgrade prebuilt rules if they are up to date', async () => { - // Install all prebuilt detection rules - await createPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects()); - await installPrebuiltRulesAndTimelines(es, supertest); - - // Check that all prebuilt rules were installed - const statusResponse = await getPrebuiltRulesAndTimelinesStatus(es, supertest); - expect(statusResponse.rules_not_installed).toBe(0); - expect(statusResponse.rules_not_updated).toBe(0); - - // Call the install prebuilt rules again and check that no rules were installed - const response = await installPrebuiltRulesAndTimelines(es, supertest); - expect(response.rules_installed).toBe(0); - expect(response.rules_updated).toBe(0); - }); - }); - - describe('using current endpoint', () => { - it('should upgrade outdated prebuilt rules', async () => { - // Install all prebuilt detection rules - const ruleAssetSavedObjects = getRuleAssetSavedObjects(); - await createPrebuiltRuleAssetSavedObjects(es, ruleAssetSavedObjects); - await installPrebuiltRules(es, supertest); - - // Clear previous rule assets - await deleteAllPrebuiltRuleAssets(es, log); - // Increment the version of one of the installed rules and create the new rule assets - ruleAssetSavedObjects[0]['security-rule'].version += 1; - await createPrebuiltRuleAssetSavedObjects(es, ruleAssetSavedObjects); - - // Check that one prebuilt rule status shows that one rule is outdated - const statusResponse = await getPrebuiltRulesStatus(es, supertest); - expect(statusResponse.stats.num_prebuilt_rules_to_install).toBe(0); - expect(statusResponse.stats.num_prebuilt_rules_to_upgrade).toBe(1); - - // Call the install prebuilt rules again and check that the outdated rule was updated - const response = await performUpgradePrebuiltRules(es, supertest, { - mode: 'ALL_RULES', - pick_version: 'TARGET', - }); - expect(response.summary.succeeded).toBe(1); - expect(response.summary.skipped).toBe(0); - }); - - it('should not upgrade prebuilt rules if they are up to date', async () => { - // Install all prebuilt detection rules - await createPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects()); - await installPrebuiltRules(es, supertest); - - // Check that all prebuilt rules were installed - const statusResponse = await getPrebuiltRulesStatus(es, supertest); - expect(statusResponse.stats.num_prebuilt_rules_to_install).toBe(0); - expect(statusResponse.stats.num_prebuilt_rules_to_upgrade).toBe(0); - - // Call the install prebuilt rules again and check that no rules were installed - const installResponse = await installPrebuiltRules(es, supertest); - expect(installResponse.summary.succeeded).toBe(0); - expect(installResponse.summary.skipped).toBe(0); - - // Call the upgrade prebuilt rules endpoint and check that no rules were updated - const upgradeResponse = await performUpgradePrebuiltRules(es, supertest, { - mode: 'ALL_RULES', - pick_version: 'TARGET', - }); - expect(upgradeResponse.summary.succeeded).toBe(0); - expect(upgradeResponse.summary.skipped).toBe(0); - }); - - describe('when upgrading a prebuilt rule to a newer version with the same rule type', () => { - it('preserves rule bound data', async () => { - await createPrebuiltRuleAssetSavedObjects(es, [ - createRuleAssetSavedObject({ - rule_id: 'rule-to-test-1', - enabled: true, - version: 1, - }), - ]); - const firstInstallResponse = await installPrebuiltRules(es, supertest); - const initialRuleSoId = firstInstallResponse.results.created[0].id; - - const actions = [ - // Use a preconfigured action connector to simplify the test and avoid action connector creation - { - id: PRECONFIGURED_EMAIL_ACTION_CONNECTOR_ID, - action_type_id: '.email', - group: 'default', - params: {}, - }, - ]; - const exceptionsList = [ - { - id: 'exception_list_1', - list_id: 'exception_list_1', - namespace_type: 'agnostic', - type: 'rule_default', - } as const, - ]; - - // Add some actions, exceptions list, and timeline reference - await patchRule(supertest, log, { - rule_id: 'rule-to-test-1', - enabled: false, - actions, - exceptions_list: exceptionsList, - timeline_id: 'some-timeline-id', - timeline_title: 'Some timeline title', - }); - - // Clear previous rule assets - await deleteAllPrebuiltRuleAssets(es, log); - // Create a new version with the same rule type asset - await createPrebuiltRuleAssetSavedObjects(es, [ - createRuleAssetSavedObject({ - rule_id: 'rule-to-test-1', - enabled: true, - version: 2, - }), - ]); - - // Upgrade to a newer version with the same type - await performUpgradePrebuiltRules(es, supertest, { - mode: 'ALL_RULES', - pick_version: 'TARGET', - }); - - expect(await fetchRule(supertest, { ruleId: 'rule-to-test-1' })).toMatchObject({ - id: initialRuleSoId, - // If a user disabled the rule it's expected to stay disabled after upgrade - enabled: false, - actions, - exceptions_list: exceptionsList, - // current values for timeline_id and timeline_title are lost when updating to TARGET version - }); - }); - }); - - describe('when upgrading a prebuilt rule to a newer version with a different rule type', () => { - it('preserves rule bound data', async () => { - await createPrebuiltRuleAssetSavedObjects(es, [ - createRuleAssetSavedObject({ - rule_id: 'rule-to-test-2', - type: 'query', - language: 'kuery', - query: '*:*', - enabled: true, - version: 1, - }), - ]); - const firstInstallResponse = await installPrebuiltRules(es, supertest); - const initialRuleSoId = firstInstallResponse.results.created[0].id; - - const actions = [ - // Use a preconfigured action connector to simplify the test and avoid action connector creation - { - id: PRECONFIGURED_EMAIL_ACTION_CONNECTOR_ID, - action_type_id: '.email', - group: 'default', - params: {}, - }, - ]; - const exceptionsList = [ - { - id: 'exception_list_1', - list_id: 'exception_list_1', - namespace_type: 'agnostic', - type: 'rule_default', - } as const, - ]; - - // Add some actions, exceptions list, and timeline reference - await patchRule(supertest, log, { - rule_id: 'rule-to-test-2', - enabled: false, - actions, - exceptions_list: exceptionsList, - timeline_id: 'some-timeline-id', - timeline_title: 'Some timeline title', - }); - - // Clear previous rule assets - await deleteAllPrebuiltRuleAssets(es, log); - // Create a new version with a different rule type asset - await createPrebuiltRuleAssetSavedObjects(es, [ - createRuleAssetSavedObject({ - rule_id: 'rule-to-test-2', - type: 'eql', - language: 'eql', - query: 'host where host == "something"', - enabled: true, - version: 2, - }), - ]); - - // Upgrade to a newer version with a different rule type - await performUpgradePrebuiltRules(es, supertest, { - mode: 'ALL_RULES', - pick_version: 'TARGET', - }); - - expect(await fetchRule(supertest, { ruleId: 'rule-to-test-2' })).toMatchObject({ - id: initialRuleSoId, - // If a user disabled the rule it's expected to stay disabled after upgrade - enabled: false, - actions, - exceptions_list: exceptionsList, - timeline_id: 'some-timeline-id', - timeline_title: 'Some timeline title', - }); - }); - }); - }); - }); -}; diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/management/trial_license_complete_tier/upgrade_prebuilt_rules_with_historical_versions.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/management/trial_license_complete_tier/upgrade_prebuilt_rules_with_historical_versions.ts deleted file mode 100644 index 0eb37b1112f27..0000000000000 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/management/trial_license_complete_tier/upgrade_prebuilt_rules_with_historical_versions.ts +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ -import expect from 'expect'; -import { FtrProviderContext } from '../../../../../../ftr_provider_context'; -import { - deleteAllTimelines, - deleteAllPrebuiltRuleAssets, - createRuleAssetSavedObject, - installPrebuiltRulesAndTimelines, - getPrebuiltRulesAndTimelinesStatus, - createHistoricalPrebuiltRuleAssetSavedObjects, - getPrebuiltRulesStatus, - installPrebuiltRules, - performUpgradePrebuiltRules, -} from '../../../../utils'; -import { deleteAllRules } from '../../../../../../../common/utils/security_solution'; - -export default ({ getService }: FtrProviderContext): void => { - const es = getService('es'); - const supertest = getService('supertest'); - const log = getService('log'); - - describe('@ess @serverless @skipInServerlessMKI upgrade prebuilt rules from package with historical versions with mock rule assets', () => { - beforeEach(async () => { - await deleteAllRules(supertest, log); - await deleteAllTimelines(es, log); - await deleteAllPrebuiltRuleAssets(es, log); - }); - - describe(`rule package with historical versions`, () => { - const getRuleAssetSavedObjects = () => [ - createRuleAssetSavedObject({ rule_id: 'rule-1', version: 1 }), - createRuleAssetSavedObject({ rule_id: 'rule-1', version: 2 }), - createRuleAssetSavedObject({ rule_id: 'rule-2', version: 1 }), - createRuleAssetSavedObject({ rule_id: 'rule-2', version: 2 }), - createRuleAssetSavedObject({ rule_id: 'rule-2', version: 3 }), - ]; - - describe('using legacy endpoint', () => { - it('should upgrade outdated prebuilt rules when previous historical versions available', async () => { - // Install all prebuilt detection rules - await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects()); - await installPrebuiltRulesAndTimelines(es, supertest); - - // Add a new version of one of the installed rules - await createHistoricalPrebuiltRuleAssetSavedObjects(es, [ - createRuleAssetSavedObject({ rule_id: 'rule-1', version: 3 }), - ]); - - // Check that one prebuilt rule status shows that one rule is outdated - const statusResponse = await getPrebuiltRulesAndTimelinesStatus(es, supertest); - expect(statusResponse.rules_not_updated).toBe(1); - - // Call the install prebuilt rules again and check that the outdated rule was updated - const response = await installPrebuiltRulesAndTimelines(es, supertest); - expect(response.rules_installed).toBe(0); - expect(response.rules_updated).toBe(1); - - const _statusResponse = await getPrebuiltRulesAndTimelinesStatus(es, supertest); - expect(_statusResponse.rules_not_installed).toBe(0); - expect(_statusResponse.rules_not_updated).toBe(0); - }); - - it('should upgrade outdated prebuilt rules when previous historical versions unavailable', async () => { - // Install all prebuilt detection rules - await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects()); - await installPrebuiltRulesAndTimelines(es, supertest); - - // Clear previous rule assets - await deleteAllPrebuiltRuleAssets(es, log); - - // Add a new rule version - await createHistoricalPrebuiltRuleAssetSavedObjects(es, [ - createRuleAssetSavedObject({ rule_id: 'rule-1', version: 3 }), - ]); - - // Check that one prebuilt rule status shows that one rule is outdated - const statusResponse = await getPrebuiltRulesAndTimelinesStatus(es, supertest); - expect(statusResponse.rules_not_updated).toBe(1); - expect(statusResponse.rules_not_installed).toBe(0); - - // Call the install prebuilt rules again and check that the outdated rule was updated - const response = await installPrebuiltRulesAndTimelines(es, supertest); - expect(response.rules_installed).toBe(0); - expect(response.rules_updated).toBe(1); - - const _statusResponse = await getPrebuiltRulesAndTimelinesStatus(es, supertest); - expect(_statusResponse.rules_not_updated).toBe(0); - expect(_statusResponse.rules_not_installed).toBe(0); - }); - }); - - describe('using current endpoint', () => { - it('should upgrade outdated prebuilt rules when previous historical versions available', async () => { - // Install all prebuilt detection rules - await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects()); - await installPrebuiltRules(es, supertest); - - // Add a new version of one of the installed rules - await createHistoricalPrebuiltRuleAssetSavedObjects(es, [ - createRuleAssetSavedObject({ rule_id: 'rule-1', version: 3 }), - ]); - - // Check that the prebuilt rule status shows that one rule is outdated - const statusResponse = await getPrebuiltRulesStatus(es, supertest); - expect(statusResponse.stats.num_prebuilt_rules_to_upgrade).toBe(1); - - // Call the upgrade prebuilt rules endpoint and check that the outdated rule was updated - const response = await performUpgradePrebuiltRules(es, supertest, { - mode: 'ALL_RULES', - pick_version: 'TARGET', - }); - expect(response.summary.succeeded).toBe(1); - expect(response.summary.total).toBe(1); - - const status = await getPrebuiltRulesStatus(es, supertest); - expect(status.stats.num_prebuilt_rules_to_install).toBe(0); - expect(status.stats.num_prebuilt_rules_to_upgrade).toBe(0); - }); - - it('should upgrade outdated prebuilt rules when previous historical versions unavailable', async () => { - // Install all prebuilt detection rules - await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects()); - await installPrebuiltRules(es, supertest); - - // Clear previous rule assets - await deleteAllPrebuiltRuleAssets(es, log); - - // Add a new rule version - await createHistoricalPrebuiltRuleAssetSavedObjects(es, [ - createRuleAssetSavedObject({ rule_id: 'rule-1', version: 3 }), - ]); - - // Check that the prebuilt rule status shows that one rule is outdated - const statusResponse = await getPrebuiltRulesStatus(es, supertest); - expect(statusResponse.stats.num_prebuilt_rules_to_upgrade).toBe(1); - expect(statusResponse.stats.num_prebuilt_rules_to_install).toBe(0); - - // Call the upgrade prebuilt rules endpoint and check that the outdated rule was updated - const response = await performUpgradePrebuiltRules(es, supertest, { - mode: 'ALL_RULES', - pick_version: 'TARGET', - }); - expect(response.summary.succeeded).toBe(1); - expect(response.summary.total).toBe(1); - - const status = await getPrebuiltRulesStatus(es, supertest); - expect(status.stats.num_prebuilt_rules_to_install).toBe(0); - expect(status.stats.num_prebuilt_rules_to_upgrade).toBe(0); - }); - }); - }); - }); -}; diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/management/trial_license_complete_tier/upgrade_review_prebuilt_rules.data_source_fields.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/management/trial_license_complete_tier/upgrade_review_prebuilt_rules.data_source_fields.ts deleted file mode 100644 index b95208856a275..0000000000000 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/management/trial_license_complete_tier/upgrade_review_prebuilt_rules.data_source_fields.ts +++ /dev/null @@ -1,972 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ -import expect from 'expect'; -import { - AllFieldsDiff, - DataSourceType, - RuleUpdateProps, - ThreeWayDiffConflict, - ThreeWayDiffOutcome, - ThreeWayMergeOutcome, -} from '@kbn/security-solution-plugin/common/api/detection_engine'; -import { getPrebuiltRuleMock } from '@kbn/security-solution-plugin/server/lib/detection_engine/prebuilt_rules/mocks'; -import { FtrProviderContext } from '../../../../../../ftr_provider_context'; -import { - deleteAllTimelines, - deleteAllPrebuiltRuleAssets, - createRuleAssetSavedObject, - installPrebuiltRules, - createPrebuiltRuleAssetSavedObjects, - reviewPrebuiltRulesToUpgrade, - createHistoricalPrebuiltRuleAssetSavedObjects, - updateRule, - patchRule, -} from '../../../../utils'; -import { deleteAllRules } from '../../../../../../../common/utils/security_solution'; - -export default ({ getService }: FtrProviderContext): void => { - const es = getService('es'); - const supertest = getService('supertest'); - const log = getService('log'); - - describe('@ess @serverless @skipInServerlessMKI review prebuilt rules updates from package with mock rule assets', () => { - beforeEach(async () => { - await deleteAllRules(supertest, log); - await deleteAllTimelines(es, log); - await deleteAllPrebuiltRuleAssets(es, log); - }); - - describe(`data_source fields`, () => { - const getIndexRuleAssetSavedObjects = () => [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 1, - index: ['one', 'two', 'three'], - }), - ]; - - const getDataViewIdRuleAssetSavedObjects = () => [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 1, - data_view_id: 'A', - }), - ]; - - describe("when rule field doesn't have an update and has no custom value - scenario AAA", () => { - describe('when all versions are index patterns', () => { - it('should not show in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects( - es, - getIndexRuleAssetSavedObjects() - ); - await installPrebuiltRules(es, supertest); - - // Increment the version of the installed rule, do NOT update the related data_source field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - index: ['one', 'three', 'two'], - version: 2, - }), - ]; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that there is 1 rule eligable for update but data_source field is NOT returned - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - const fieldDiffObject = reviewResponse.rules[0].diff.fields as AllFieldsDiff; - expect(fieldDiffObject.data_source).toBeUndefined(); - - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(1); - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(0); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(0); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(0); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(0); - }); - }); - - describe('when all versions are data view id', () => { - it('should not show in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects( - es, - getDataViewIdRuleAssetSavedObjects() - ); - await installPrebuiltRules(es, supertest); - - // Increment the version of the installed rule, do NOT update the related data_source field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - data_view_id: 'A', - version: 2, - }), - ]; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that there is 1 rule eligable for update but data_source field is NOT returned - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - const fieldDiffObject = reviewResponse.rules[0].diff.fields as AllFieldsDiff; - expect(fieldDiffObject.data_source).toBeUndefined(); - - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(1); - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(0); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(0); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(0); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(0); - }); - }); - }); - - describe("when rule field doesn't have an update but has a custom value - scenario ABA", () => { - describe('when current version is index pattern type', () => { - it('should show in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects( - es, - getDataViewIdRuleAssetSavedObjects() - ); - await installPrebuiltRules(es, supertest); - - // Customize a data_source field on the installed rule - await updateRule(supertest, { - ...getPrebuiltRuleMock(), - rule_id: 'rule-1', - index: ['one', 'two', 'four'], - data_view_id: undefined, - } as RuleUpdateProps); - - // Increment the version of the installed rule, do NOT update the related data_source field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - data_view_id: 'A', - version: 2, - }), - ]; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that data_source diff field is returned but field does not have an update - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - const fieldDiffObject = reviewResponse.rules[0].diff.fields as AllFieldsDiff; - expect(fieldDiffObject.data_source).toEqual({ - base_version: { - data_view_id: 'A', - type: DataSourceType.data_view, - }, - current_version: { - index_patterns: ['one', 'two', 'four'], - type: DataSourceType.index_patterns, - }, - target_version: { - data_view_id: 'A', - type: DataSourceType.data_view, - }, - merged_version: { - index_patterns: ['one', 'two', 'four'], - type: DataSourceType.index_patterns, - }, - diff_outcome: ThreeWayDiffOutcome.CustomizedValueNoUpdate, - merge_outcome: ThreeWayMergeOutcome.Current, - conflict: ThreeWayDiffConflict.NONE, - has_update: false, - has_base_version: true, - }); - - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(1); - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(0); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(0); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(0); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(0); - }); - }); - - describe('when current version is data view id type', () => { - it('should show in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects( - es, - getIndexRuleAssetSavedObjects() - ); - await installPrebuiltRules(es, supertest); - - // Customize a data_source field on the installed rule - await updateRule(supertest, { - ...getPrebuiltRuleMock(), - rule_id: 'rule-1', - index: undefined, - data_view_id: 'B', - } as RuleUpdateProps); - - // Increment the version of the installed rule, do NOT update the related data_source field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - index: ['one', 'two', 'three'], - version: 2, - }), - ]; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that data_source diff field is returned but field does not have an update - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - const fieldDiffObject = reviewResponse.rules[0].diff.fields as AllFieldsDiff; - expect(fieldDiffObject.data_source).toEqual({ - base_version: { - index_patterns: ['one', 'two', 'three'], - type: DataSourceType.index_patterns, - }, - current_version: { - data_view_id: 'B', - type: DataSourceType.data_view, - }, - target_version: { - index_patterns: ['one', 'two', 'three'], - type: DataSourceType.index_patterns, - }, - merged_version: { - data_view_id: 'B', - type: DataSourceType.data_view, - }, - diff_outcome: ThreeWayDiffOutcome.CustomizedValueNoUpdate, - merge_outcome: ThreeWayMergeOutcome.Current, - conflict: ThreeWayDiffConflict.NONE, - has_update: false, - has_base_version: true, - }); - - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(1); - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(0); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(0); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(0); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(0); - }); - }); - - describe('when current version is undefined', () => { - it('should show in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects( - es, - getIndexRuleAssetSavedObjects() - ); - await installPrebuiltRules(es, supertest); - - // Customize a data_source field on the installed rule - await updateRule(supertest, { - ...getPrebuiltRuleMock(), - rule_id: 'rule-1', - index: undefined, - } as RuleUpdateProps); - - // Increment the version of the installed rule, do NOT update the related data_source field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - index: ['one', 'two', 'three'], - version: 2, - }), - ]; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that data_source diff field is returned but field does not have an update - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - const fieldDiffObject = reviewResponse.rules[0].diff.fields as AllFieldsDiff; - expect(fieldDiffObject.data_source).toEqual({ - base_version: { - index_patterns: ['one', 'two', 'three'], - type: DataSourceType.index_patterns, - }, - current_version: undefined, - target_version: { - index_patterns: ['one', 'two', 'three'], - type: DataSourceType.index_patterns, - }, - merged_version: undefined, - diff_outcome: ThreeWayDiffOutcome.CustomizedValueNoUpdate, - merge_outcome: ThreeWayMergeOutcome.Current, - conflict: ThreeWayDiffConflict.NONE, - has_update: false, - has_base_version: true, - }); - - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(1); - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(0); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(0); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(0); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(0); - }); - }); - }); - - describe('when rule field has an update but does not have a custom value - scenario AAB', () => { - describe('when target version is index pattern type', () => { - it('should show in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects( - es, - getDataViewIdRuleAssetSavedObjects() - ); - await installPrebuiltRules(es, supertest); - - // Increment the version of the installed rule, update a data_source field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - index: ['one', 'two', 'four'], - }), - ]; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that one rule is eligible for update - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - const fieldDiffObject = reviewResponse.rules[0].diff.fields as AllFieldsDiff; - expect(fieldDiffObject.data_source).toEqual({ - base_version: { - data_view_id: 'A', - type: DataSourceType.data_view, - }, - current_version: { - data_view_id: 'A', - type: DataSourceType.data_view, - }, - target_version: { - index_patterns: ['one', 'two', 'four'], - type: DataSourceType.index_patterns, - }, - merged_version: { - index_patterns: ['one', 'two', 'four'], - type: DataSourceType.index_patterns, - }, - diff_outcome: ThreeWayDiffOutcome.StockValueCanUpdate, - merge_outcome: ThreeWayMergeOutcome.Target, - conflict: ThreeWayDiffConflict.NONE, - has_update: true, - has_base_version: true, - }); - - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(2); - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(0); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(0); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(0); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(0); - }); - }); - - describe('when target version is data view id type', () => { - it('should show in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects( - es, - getIndexRuleAssetSavedObjects() - ); - await installPrebuiltRules(es, supertest); - - // Increment the version of the installed rule, update a data_source field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - data_view_id: 'B', - }), - ]; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that one rule is eligible for update - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - const fieldDiffObject = reviewResponse.rules[0].diff.fields as AllFieldsDiff; - expect(fieldDiffObject.data_source).toEqual({ - base_version: { - index_patterns: ['one', 'two', 'three'], - type: DataSourceType.index_patterns, - }, - current_version: { - index_patterns: ['one', 'two', 'three'], - type: DataSourceType.index_patterns, - }, - target_version: { - data_view_id: 'B', - type: DataSourceType.data_view, - }, - merged_version: { - data_view_id: 'B', - type: DataSourceType.data_view, - }, - diff_outcome: ThreeWayDiffOutcome.StockValueCanUpdate, - merge_outcome: ThreeWayMergeOutcome.Target, - conflict: ThreeWayDiffConflict.NONE, - has_update: true, - has_base_version: true, - }); - - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(2); - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(0); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(0); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(0); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(0); - }); - }); - }); - - describe('when rule field has an update and a custom value that are the same - scenario ABB', () => { - describe('when current and target version are index pattern type', () => { - it('should show in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects( - es, - getDataViewIdRuleAssetSavedObjects() - ); - await installPrebuiltRules(es, supertest); - - // Customize a data_source field on the installed rule - await updateRule(supertest, { - ...getPrebuiltRuleMock(), - rule_id: 'rule-1', - index: ['one', 'two', 'four'], - data_view_id: undefined, - } as RuleUpdateProps); - - // Increment the version of the installed rule, update a data_source field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - index: ['one', 'two', 'four'], - }), - ]; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that one rule is eligible for update and contains data_source field - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - const fieldDiffObject = reviewResponse.rules[0].diff.fields as AllFieldsDiff; - expect(fieldDiffObject.data_source).toEqual({ - base_version: { - data_view_id: 'A', - type: DataSourceType.data_view, - }, - current_version: { - index_patterns: ['one', 'two', 'four'], - type: DataSourceType.index_patterns, - }, - target_version: { - index_patterns: ['one', 'two', 'four'], - type: DataSourceType.index_patterns, - }, - merged_version: { - index_patterns: ['one', 'two', 'four'], - type: DataSourceType.index_patterns, - }, - diff_outcome: ThreeWayDiffOutcome.CustomizedValueSameUpdate, - merge_outcome: ThreeWayMergeOutcome.Current, - conflict: ThreeWayDiffConflict.NONE, - has_update: false, - has_base_version: true, - }); - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(1); - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(0); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(0); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(0); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(0); - }); - }); - - describe('when current and target version are data view id type', () => { - it('should show in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects( - es, - getIndexRuleAssetSavedObjects() - ); - await installPrebuiltRules(es, supertest); - - // Customize a data_source field on the installed rule - await updateRule(supertest, { - ...getPrebuiltRuleMock(), - rule_id: 'rule-1', - index: undefined, - data_view_id: 'B', - } as RuleUpdateProps); - - // Increment the version of the installed rule, update a data_source field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - data_view_id: 'B', - }), - ]; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that one rule is eligible for update and contains data_source field - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - const fieldDiffObject = reviewResponse.rules[0].diff.fields as AllFieldsDiff; - expect(fieldDiffObject.data_source).toEqual({ - base_version: { - index_patterns: ['one', 'two', 'three'], - type: DataSourceType.index_patterns, - }, - current_version: { - data_view_id: 'B', - type: DataSourceType.data_view, - }, - target_version: { - data_view_id: 'B', - type: DataSourceType.data_view, - }, - merged_version: { - data_view_id: 'B', - type: DataSourceType.data_view, - }, - diff_outcome: ThreeWayDiffOutcome.CustomizedValueSameUpdate, - merge_outcome: ThreeWayMergeOutcome.Current, - conflict: ThreeWayDiffConflict.NONE, - has_update: false, - has_base_version: true, - }); - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(1); - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(0); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(0); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(0); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(0); - }); - }); - }); - - describe('when rule field has an update and a custom value that are different - scenario ABC', () => { - describe('when just current and target versions are index patterns', () => { - it('should show a solvable conflict in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects( - es, - getDataViewIdRuleAssetSavedObjects() - ); - await installPrebuiltRules(es, supertest); - - // Customize a data_source field on the installed rule - await updateRule(supertest, { - ...getPrebuiltRuleMock(), - rule_id: 'rule-1', - index: ['one', 'one', 'two', 'three'], - data_view_id: undefined, - } as RuleUpdateProps); - - // Increment the version of the installed rule, update a data_source field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - index: ['one', 'two', 'five'], - }), - ]; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that one rule is eligible for update - // and data_source field update has conflict - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - const fieldDiffObject = reviewResponse.rules[0].diff.fields as AllFieldsDiff; - expect(fieldDiffObject.data_source).toEqual({ - base_version: { - data_view_id: 'A', - type: DataSourceType.data_view, - }, - current_version: { - index_patterns: ['one', 'one', 'two', 'three'], - type: DataSourceType.index_patterns, - }, - target_version: { - index_patterns: ['one', 'two', 'five'], - type: DataSourceType.index_patterns, - }, - merged_version: { - index_patterns: ['one', 'two', 'three', 'five'], - type: DataSourceType.index_patterns, - }, - diff_outcome: ThreeWayDiffOutcome.CustomizedValueCanUpdate, - merge_outcome: ThreeWayMergeOutcome.Merged, - conflict: ThreeWayDiffConflict.SOLVABLE, - has_update: true, - has_base_version: true, - }); - - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(2); - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(1); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(0); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(1); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(0); - }); - }); - - describe('when all versions are index patterns', () => { - it('should show a solvable conflict in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects( - es, - getIndexRuleAssetSavedObjects() - ); - await installPrebuiltRules(es, supertest); - - // Customize a multi line string field on the installed rule - await patchRule(supertest, log, { - rule_id: 'rule-1', - index: ['one', 'two', 'four'], - }); - - // Increment the version of the installed rule, update a data_source field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - index: ['one', 'two', 'five'], - }), - ]; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that one rule is eligible for update - // and data_source field update has conflict - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - const fieldDiffObject = reviewResponse.rules[0].diff.fields as AllFieldsDiff; - expect(fieldDiffObject.data_source).toEqual({ - base_version: { - index_patterns: ['one', 'two', 'three'], - type: DataSourceType.index_patterns, - }, - current_version: { - index_patterns: ['one', 'two', 'four'], - type: DataSourceType.index_patterns, - }, - target_version: { - index_patterns: ['one', 'two', 'five'], - type: DataSourceType.index_patterns, - }, - merged_version: { - index_patterns: ['one', 'two', 'four', 'five'], - type: DataSourceType.index_patterns, - }, - diff_outcome: ThreeWayDiffOutcome.CustomizedValueCanUpdate, - merge_outcome: ThreeWayMergeOutcome.Merged, - conflict: ThreeWayDiffConflict.SOLVABLE, - has_update: true, - has_base_version: true, - }); - - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(2); - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(1); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(0); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(1); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(0); - }); - }); - - describe('when all versions are data view id types', () => { - it('should show a non-solvable conflict in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects( - es, - getDataViewIdRuleAssetSavedObjects() - ); - await installPrebuiltRules(es, supertest); - - // Customize a data_source field on the installed rule - await updateRule(supertest, { - ...getPrebuiltRuleMock(), - rule_id: 'rule-1', - index: undefined, - data_view_id: 'B', - } as RuleUpdateProps); - - // Increment the version of the installed rule, update a data_source field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - data_view_id: 'C', - }), - ]; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that one rule is eligible for update - // and data_source field update has conflict - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - const fieldDiffObject = reviewResponse.rules[0].diff.fields as AllFieldsDiff; - expect(fieldDiffObject.data_source).toEqual({ - base_version: { - data_view_id: 'A', - type: DataSourceType.data_view, - }, - current_version: { - data_view_id: 'B', - type: DataSourceType.data_view, - }, - target_version: { - data_view_id: 'C', - type: DataSourceType.data_view, - }, - merged_version: { - data_view_id: 'B', - type: DataSourceType.data_view, - }, - diff_outcome: ThreeWayDiffOutcome.CustomizedValueCanUpdate, - merge_outcome: ThreeWayMergeOutcome.Current, - conflict: ThreeWayDiffConflict.NON_SOLVABLE, - has_update: true, - has_base_version: true, - }); - - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(2); - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(1); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(1); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(1); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(1); - }); - }); - - describe('when current and target versions are different data types', () => { - it('should show a non-solvable conflict in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects( - es, - getDataViewIdRuleAssetSavedObjects() - ); - await installPrebuiltRules(es, supertest); - - // Customize a data_source field on the installed rule - await updateRule(supertest, { - ...getPrebuiltRuleMock(), - rule_id: 'rule-1', - index: ['one', 'two', 'four'], - data_view_id: undefined, - } as RuleUpdateProps); - - // Increment the version of the installed rule, update a data_source field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - data_view_id: 'C', - }), - ]; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that one rule is eligible for update - // and data_source field update has conflict - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - const fieldDiffObject = reviewResponse.rules[0].diff.fields as AllFieldsDiff; - expect(fieldDiffObject.data_source).toEqual({ - base_version: { - data_view_id: 'A', - type: DataSourceType.data_view, - }, - current_version: { - index_patterns: ['one', 'two', 'four'], - type: DataSourceType.index_patterns, - }, - target_version: { - data_view_id: 'C', - type: DataSourceType.data_view, - }, - merged_version: { - index_patterns: ['one', 'two', 'four'], - type: DataSourceType.index_patterns, - }, - diff_outcome: ThreeWayDiffOutcome.CustomizedValueCanUpdate, - merge_outcome: ThreeWayMergeOutcome.Current, - conflict: ThreeWayDiffConflict.NON_SOLVABLE, - has_update: true, - has_base_version: true, - }); - - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(2); - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(1); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(1); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(1); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(1); - }); - }); - - describe('when current version is undefined', () => { - it('should show a non-solvable conflict in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects( - es, - getDataViewIdRuleAssetSavedObjects() - ); - await installPrebuiltRules(es, supertest); - - // Customize a data_source field on the installed rule - await updateRule(supertest, { - ...getPrebuiltRuleMock(), - rule_id: 'rule-1', - data_view_id: undefined, - } as RuleUpdateProps); - - // Increment the version of the installed rule, update a data_source field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - data_view_id: 'C', - }), - ]; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that one rule is eligible for update - // and data_source field update has conflict - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - const fieldDiffObject = reviewResponse.rules[0].diff.fields as AllFieldsDiff; - expect(fieldDiffObject.data_source).toEqual({ - base_version: { - data_view_id: 'A', - type: DataSourceType.data_view, - }, - current_version: undefined, - target_version: { - data_view_id: 'C', - type: DataSourceType.data_view, - }, - merged_version: undefined, - diff_outcome: ThreeWayDiffOutcome.CustomizedValueCanUpdate, - merge_outcome: ThreeWayMergeOutcome.Current, - conflict: ThreeWayDiffConflict.NON_SOLVABLE, - has_update: true, - has_base_version: true, - }); - - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(2); - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(1); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(1); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(1); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(1); - }); - }); - }); - - describe('when rule base version does not exist', () => { - describe('when rule field has an update and a custom value that are the same - scenario -AA', () => { - it('should not show in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createPrebuiltRuleAssetSavedObjects(es, getIndexRuleAssetSavedObjects()); - await installPrebuiltRules(es, supertest); - - // Clear previous rule assets - await deleteAllPrebuiltRuleAssets(es, log); - - // Increment the version of the installed rule, but keep data_source field unchanged - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - index: ['one', 'two', 'three'], // unchanged - }), - ]; - await createPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that one rule is eligible for update - // but does NOT contain data_source field (tags is not present, since scenario -AA is not included in response) - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - const fieldDiffObject = reviewResponse.rules[0].diff.fields as AllFieldsDiff; - expect(fieldDiffObject.data_source).toBeUndefined(); - - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(1); - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(0); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(0); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(0); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(0); - }); - }); - - describe('when rule field has an update and a custom value that are different - scenario -AB', () => { - it('should show in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createPrebuiltRuleAssetSavedObjects(es, getIndexRuleAssetSavedObjects()); - await installPrebuiltRules(es, supertest); - - // Clear previous rule assets - await deleteAllPrebuiltRuleAssets(es, log); - - // Customize a data_source field on the installed rule - await updateRule(supertest, { - ...getPrebuiltRuleMock(), - rule_id: 'rule-1', - index: ['one', 'two', 'four'], - data_view_id: undefined, - } as RuleUpdateProps); - - // Increment the version of the installed rule, update a data_source field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - index: ['one', 'two', 'five'], - }), - ]; - await createPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that one rule is eligible for update - // and data_source field update does not have a conflict - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - const fieldDiffObject = reviewResponse.rules[0].diff.fields as AllFieldsDiff; - expect(fieldDiffObject.data_source).toEqual({ - current_version: { - index_patterns: ['one', 'two', 'four'], - type: DataSourceType.index_patterns, - }, - target_version: { - index_patterns: ['one', 'two', 'five'], - type: DataSourceType.index_patterns, - }, - merged_version: { - index_patterns: ['one', 'two', 'five'], - type: DataSourceType.index_patterns, - }, - diff_outcome: ThreeWayDiffOutcome.MissingBaseCanUpdate, - merge_outcome: ThreeWayMergeOutcome.Target, - conflict: ThreeWayDiffConflict.SOLVABLE, - has_update: true, - has_base_version: false, - }); - - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(2); - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(1); // tags - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(0); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(1); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(0); - }); - }); - }); - }); - }); -}; diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/management/trial_license_complete_tier/upgrade_review_prebuilt_rules.eql_query_fields.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/management/trial_license_complete_tier/upgrade_review_prebuilt_rules.eql_query_fields.ts deleted file mode 100644 index 6c49f8722abd4..0000000000000 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/management/trial_license_complete_tier/upgrade_review_prebuilt_rules.eql_query_fields.ts +++ /dev/null @@ -1,505 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ -import expect from 'expect'; -import { - AllFieldsDiff, - RuleUpdateProps, - ThreeWayDiffConflict, - ThreeWayDiffOutcome, - ThreeWayMergeOutcome, -} from '@kbn/security-solution-plugin/common/api/detection_engine'; -import { getPrebuiltRuleMock } from '@kbn/security-solution-plugin/server/lib/detection_engine/prebuilt_rules/mocks'; -import { FtrProviderContext } from '../../../../../../ftr_provider_context'; -import { - deleteAllTimelines, - deleteAllPrebuiltRuleAssets, - createRuleAssetSavedObject, - installPrebuiltRules, - createPrebuiltRuleAssetSavedObjects, - reviewPrebuiltRulesToUpgrade, - createHistoricalPrebuiltRuleAssetSavedObjects, - updateRule, -} from '../../../../utils'; -import { deleteAllRules } from '../../../../../../../common/utils/security_solution'; - -export default ({ getService }: FtrProviderContext): void => { - const es = getService('es'); - const supertest = getService('supertest'); - const log = getService('log'); - - describe('@ess @serverless @skipInServerlessMKI review prebuilt rules updates from package with mock rule assets', () => { - beforeEach(async () => { - await deleteAllRules(supertest, log); - await deleteAllTimelines(es, log); - await deleteAllPrebuiltRuleAssets(es, log); - }); - - describe(`eql_query fields`, () => { - const getRuleAssetSavedObjects = () => [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 1, - type: 'eql', - query: 'query where true', - language: 'eql', - filters: [], - }), - ]; - - describe("when rule field doesn't have an update and has no custom value - scenario AAA", () => { - it('should not show in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects()); - await installPrebuiltRules(es, supertest); - - // Add a v2 rule asset to make the upgrade possible, do NOT update the related eql_query field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - type: 'eql', - query: 'query where true', - language: 'eql', - filters: [], - }), - ]; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that there is 1 rule eligible for update but eql_query field is NOT returned - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - const fieldDiffObject = reviewResponse.rules[0].diff.fields as AllFieldsDiff; - expect(fieldDiffObject.eql_query).toBeUndefined(); - - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(1); // `version` is considered an updated field - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(0); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(0); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(0); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(0); - }); - - it('should trim all whitespace before version comparison', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects()); - await installPrebuiltRules(es, supertest); - - // Customize an eql_query field on the installed rule - await updateRule(supertest, { - ...getPrebuiltRuleMock(), - rule_id: 'rule-1', - type: 'eql', - query: '\nquery where true\n', - language: 'eql', - filters: [], - } as RuleUpdateProps); - - // Add a v2 rule asset to make the upgrade possible, do NOT update the related eql_query field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - type: 'eql', - query: '\nquery where true', - language: 'eql', - filters: [], - }), - ]; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that there is 1 rule eligible for update but eql_query field is NOT returned - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - const fieldDiffObject = reviewResponse.rules[0].diff.fields as AllFieldsDiff; - expect(fieldDiffObject.eql_query).toBeUndefined(); - - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(1); // `version` is considered an updated field - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(0); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(0); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(0); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(0); - }); - }); - - describe("when rule field doesn't have an update but has a custom value - scenario ABA", () => { - it('should show in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects()); - await installPrebuiltRules(es, supertest); - - // Customize an eql_query field on the installed rule - await updateRule(supertest, { - ...getPrebuiltRuleMock(), - rule_id: 'rule-1', - type: 'eql', - query: 'query where false', - language: 'eql', - filters: [], - } as RuleUpdateProps); - - // Add a v2 rule asset to make the upgrade possible, do NOT update the related eql_query field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - type: 'eql', - query: 'query where true', - language: 'eql', - filters: [], - }), - ]; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that eql_query diff field is returned but field does not have an update - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - const fieldDiffObject = reviewResponse.rules[0].diff.fields as AllFieldsDiff; - expect(fieldDiffObject.eql_query).toEqual({ - base_version: { - query: 'query where true', - language: 'eql', - filters: [], - }, - current_version: { - query: 'query where false', - language: 'eql', - filters: [], - }, - target_version: { - query: 'query where true', - language: 'eql', - filters: [], - }, - merged_version: { - query: 'query where false', - language: 'eql', - filters: [], - }, - diff_outcome: ThreeWayDiffOutcome.CustomizedValueNoUpdate, - merge_outcome: ThreeWayMergeOutcome.Current, - conflict: ThreeWayDiffConflict.NONE, - has_update: false, - has_base_version: true, - }); - - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(1); // `version` is considered an updated field - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(0); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(0); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(0); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(0); - }); - }); - - describe('when rule field has an update but does not have a custom value - scenario AAB', () => { - it('should show in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects()); - await installPrebuiltRules(es, supertest); - - // Add a v2 rule asset to make the upgrade possible, update an eql_query field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - type: 'eql', - query: 'query where false', - language: 'eql', - filters: [], - }), - ]; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that one rule is eligible for update - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - const fieldDiffObject = reviewResponse.rules[0].diff.fields as AllFieldsDiff; - expect(fieldDiffObject.eql_query).toEqual({ - base_version: { - query: 'query where true', - language: 'eql', - filters: [], - }, - current_version: { - query: 'query where true', - language: 'eql', - filters: [], - }, - target_version: { - query: 'query where false', - language: 'eql', - filters: [], - }, - merged_version: { - query: 'query where false', - language: 'eql', - filters: [], - }, - diff_outcome: ThreeWayDiffOutcome.StockValueCanUpdate, - merge_outcome: ThreeWayMergeOutcome.Target, - conflict: ThreeWayDiffConflict.NONE, - has_update: true, - has_base_version: true, - }); - - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(2); // `version` is considered an updated field - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(0); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(0); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(0); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(0); - }); - }); - - describe('when rule field has an update and a custom value that are the same - scenario ABB', () => { - it('should show in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects()); - await installPrebuiltRules(es, supertest); - - // Customize an eql_query field on the installed rule - await updateRule(supertest, { - ...getPrebuiltRuleMock(), - rule_id: 'rule-1', - type: 'eql', - query: 'query where false', - language: 'eql', - filters: [], - } as RuleUpdateProps); - - // Add a v2 rule asset to make the upgrade possible, update an eql_query field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - type: 'eql', - query: 'query where false', - language: 'eql', - filters: [], - }), - ]; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that one rule is eligible for update and contains eql_query field - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - const fieldDiffObject = reviewResponse.rules[0].diff.fields as AllFieldsDiff; - expect(fieldDiffObject.eql_query).toEqual({ - base_version: { - query: 'query where true', - language: 'eql', - filters: [], - }, - current_version: { - query: 'query where false', - language: 'eql', - filters: [], - }, - target_version: { - query: 'query where false', - language: 'eql', - filters: [], - }, - merged_version: { - query: 'query where false', - language: 'eql', - filters: [], - }, - diff_outcome: ThreeWayDiffOutcome.CustomizedValueSameUpdate, - merge_outcome: ThreeWayMergeOutcome.Current, - conflict: ThreeWayDiffConflict.NONE, - has_update: false, - has_base_version: true, - }); - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(1); // `version` is considered an updated field - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(0); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(0); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(0); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(0); - }); - }); - - describe('when rule field has an update and a custom value that are different - scenario ABC', () => { - it('should show a non-solvable conflict in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects()); - await installPrebuiltRules(es, supertest); - - // Customize an eql_query field on the installed rule - await updateRule(supertest, { - ...getPrebuiltRuleMock(), - rule_id: 'rule-1', - type: 'eql', - query: 'query where true', - language: 'eql', - filters: [{ field: 'query' }], - } as RuleUpdateProps); - - // Add a v2 rule asset to make the upgrade possible, update an eql_query field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - type: 'eql', - query: 'query where false', - language: 'eql', - filters: [], - }), - ]; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that one rule is eligible for update - // and eql_query field update has conflict - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - const fieldDiffObject = reviewResponse.rules[0].diff.fields as AllFieldsDiff; - expect(fieldDiffObject.eql_query).toEqual({ - base_version: { - query: 'query where true', - language: 'eql', - filters: [], - }, - current_version: { - query: 'query where true', - language: 'eql', - filters: [{ field: 'query' }], - }, - target_version: { - query: 'query where false', - language: 'eql', - filters: [], - }, - merged_version: { - query: 'query where true', - language: 'eql', - filters: [{ field: 'query' }], - }, - diff_outcome: ThreeWayDiffOutcome.CustomizedValueCanUpdate, - merge_outcome: ThreeWayMergeOutcome.Current, - conflict: ThreeWayDiffConflict.NON_SOLVABLE, - has_update: true, - has_base_version: true, - }); - - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(2); // `version` is considered an updated field - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(1); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(1); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(1); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(1); - }); - }); - - describe('when rule base version does not exist', () => { - describe('when rule field has an update and a custom value that are the same - scenario -AA', () => { - it('should not show in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects()); - await installPrebuiltRules(es, supertest); - - // Clear previous rule assets - await deleteAllPrebuiltRuleAssets(es, log); - - // Add a v2 rule asset to make the upgrade possible, but keep eql_query field unchanged - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - type: 'eql', - query: 'query where true', - language: 'eql', - filters: [], - }), - ]; - await createPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that one rule is eligible for update - // but does NOT contain eql_query field - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - const fieldDiffObject = reviewResponse.rules[0].diff.fields as AllFieldsDiff; - expect(fieldDiffObject.eql_query).toBeUndefined(); - - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(1); // `version` is considered an updated field - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(0); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(0); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(0); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(0); - }); - }); - - describe('when rule field has an update and a custom value that are different - scenario -AB', () => { - it('should show in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects()); - await installPrebuiltRules(es, supertest); - - // Clear previous rule assets - await deleteAllPrebuiltRuleAssets(es, log); - - // Customize an eql_query field on the installed rule - await updateRule(supertest, { - ...getPrebuiltRuleMock(), - rule_id: 'rule-1', - type: 'eql', - query: 'query where false', - language: 'eql', - filters: [], - } as RuleUpdateProps); - - // Add a v2 rule asset to make the upgrade possible, update an eql_query field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - type: 'eql', - query: 'new query where true', - language: 'eql', - filters: [], - }), - ]; - await createPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that one rule is eligible for update - // and eql_query field update does not have a conflict - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - const fieldDiffObject = reviewResponse.rules[0].diff.fields as AllFieldsDiff; - expect(fieldDiffObject.eql_query).toEqual({ - current_version: { - query: 'query where false', - language: 'eql', - filters: [], - }, - target_version: { - query: 'new query where true', - language: 'eql', - filters: [], - }, - merged_version: { - query: 'new query where true', - language: 'eql', - filters: [], - }, - diff_outcome: ThreeWayDiffOutcome.MissingBaseCanUpdate, - merge_outcome: ThreeWayMergeOutcome.Target, - conflict: ThreeWayDiffConflict.SOLVABLE, - has_update: true, - has_base_version: false, - }); - - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(2); // version + query - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(1); // query - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(0); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(1); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(0); - }); - }); - }); - }); - }); -}; diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/management/trial_license_complete_tier/upgrade_review_prebuilt_rules.esql_query_fields.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/management/trial_license_complete_tier/upgrade_review_prebuilt_rules.esql_query_fields.ts deleted file mode 100644 index d8329ce023ea6..0000000000000 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/management/trial_license_complete_tier/upgrade_review_prebuilt_rules.esql_query_fields.ts +++ /dev/null @@ -1,472 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ -import expect from 'expect'; -import { - AllFieldsDiff, - RuleUpdateProps, - ThreeWayDiffConflict, - ThreeWayDiffOutcome, - ThreeWayMergeOutcome, -} from '@kbn/security-solution-plugin/common/api/detection_engine'; -import { getPrebuiltRuleMock } from '@kbn/security-solution-plugin/server/lib/detection_engine/prebuilt_rules/mocks'; -import { FtrProviderContext } from '../../../../../../ftr_provider_context'; -import { - deleteAllTimelines, - deleteAllPrebuiltRuleAssets, - createRuleAssetSavedObject, - installPrebuiltRules, - createPrebuiltRuleAssetSavedObjects, - reviewPrebuiltRulesToUpgrade, - createHistoricalPrebuiltRuleAssetSavedObjects, - updateRule, -} from '../../../../utils'; -import { deleteAllRules } from '../../../../../../../common/utils/security_solution'; - -export default ({ getService }: FtrProviderContext): void => { - const es = getService('es'); - const supertest = getService('supertest'); - const log = getService('log'); - - describe('@ess @serverless @skipInServerlessMKI review prebuilt rules updates from package with mock rule assets', () => { - beforeEach(async () => { - await deleteAllRules(supertest, log); - await deleteAllTimelines(es, log); - await deleteAllPrebuiltRuleAssets(es, log); - }); - - describe(`esql_query fields`, () => { - const getRuleAssetSavedObjects = () => [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 1, - type: 'esql', - query: 'FROM query WHERE true', - language: 'esql', - }), - ]; - - describe("when rule field doesn't have an update and has no custom value - scenario AAA", () => { - it('should not show in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects()); - await installPrebuiltRules(es, supertest); - - // Add a v2 rule asset to make the upgrade possible, do NOT update the related esql_query field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - type: 'esql', - query: 'FROM query WHERE true', - language: 'esql', - }), - ]; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that there is 1 rule eligible for update but esql_query field is NOT returned - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - const fieldDiffObject = reviewResponse.rules[0].diff.fields as AllFieldsDiff; - expect(fieldDiffObject.esql_query).toBeUndefined(); - - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(1); // `version` is considered an updated field - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(0); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(0); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(0); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(0); - }); - - it('should trim all whitespace before version comparison', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects()); - await installPrebuiltRules(es, supertest); - - // Customize an esql_query field on the installed rule - await updateRule(supertest, { - ...getPrebuiltRuleMock(), - rule_id: 'rule-1', - type: 'esql', - query: '\tFROM query WHERE true\t', - language: 'esql', - } as RuleUpdateProps); - - // Add a v2 rule asset to make the upgrade possible, do NOT update the related esql_query field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - type: 'esql', - query: '\n\nFROM query WHERE true\n\n', - language: 'esql', - }), - ]; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that there is 1 rule eligible for update but esql_query field is NOT returned - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - const fieldDiffObject = reviewResponse.rules[0].diff.fields as AllFieldsDiff; - expect(fieldDiffObject.esql_query).toBeUndefined(); - - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(1); // `version` is considered an updated field - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(0); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(0); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(0); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(0); - }); - }); - - describe("when rule field doesn't have an update but has a custom value - scenario ABA", () => { - it('should show in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects()); - await installPrebuiltRules(es, supertest); - - // Customize an esql_query field on the installed rule - await updateRule(supertest, { - ...getPrebuiltRuleMock(), - rule_id: 'rule-1', - type: 'esql', - query: 'FROM query WHERE false', - language: 'esql', - } as RuleUpdateProps); - - // Add a v2 rule asset to make the upgrade possible, do NOT update the related esql_query field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - type: 'esql', - query: 'FROM query WHERE true', - language: 'esql', - }), - ]; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that esql_query diff field is returned but field does not have an update - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - const fieldDiffObject = reviewResponse.rules[0].diff.fields as AllFieldsDiff; - expect(fieldDiffObject.esql_query).toEqual({ - base_version: { - query: 'FROM query WHERE true', - language: 'esql', - }, - current_version: { - query: 'FROM query WHERE false', - language: 'esql', - }, - target_version: { - query: 'FROM query WHERE true', - language: 'esql', - }, - merged_version: { - query: 'FROM query WHERE false', - language: 'esql', - }, - diff_outcome: ThreeWayDiffOutcome.CustomizedValueNoUpdate, - merge_outcome: ThreeWayMergeOutcome.Current, - conflict: ThreeWayDiffConflict.NONE, - has_update: false, - has_base_version: true, - }); - - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(1); // `version` is considered an updated field - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(0); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(0); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(0); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(0); - }); - }); - - describe('when rule field has an update but does not have a custom value - scenario AAB', () => { - it('should show in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects()); - await installPrebuiltRules(es, supertest); - - // Add a v2 rule asset to make the upgrade possible, update an esql_query field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - type: 'esql', - query: 'FROM query WHERE false', - language: 'esql', - }), - ]; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that one rule is eligible for update - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - const fieldDiffObject = reviewResponse.rules[0].diff.fields as AllFieldsDiff; - expect(fieldDiffObject.esql_query).toEqual({ - base_version: { - query: 'FROM query WHERE true', - language: 'esql', - }, - current_version: { - query: 'FROM query WHERE true', - language: 'esql', - }, - target_version: { - query: 'FROM query WHERE false', - language: 'esql', - }, - merged_version: { - query: 'FROM query WHERE false', - language: 'esql', - }, - diff_outcome: ThreeWayDiffOutcome.StockValueCanUpdate, - merge_outcome: ThreeWayMergeOutcome.Target, - conflict: ThreeWayDiffConflict.NONE, - has_update: true, - has_base_version: true, - }); - - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(2); // `version` is considered an updated field - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(0); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(0); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(0); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(0); - }); - }); - - describe('when rule field has an update and a custom value that are the same - scenario ABB', () => { - it('should show in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects()); - await installPrebuiltRules(es, supertest); - - // Customize an esql_query field on the installed rule - await updateRule(supertest, { - ...getPrebuiltRuleMock(), - rule_id: 'rule-1', - type: 'esql', - query: 'FROM query WHERE false', - language: 'esql', - } as RuleUpdateProps); - - // Add a v2 rule asset to make the upgrade possible, update an esql_query field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - type: 'esql', - query: 'FROM query WHERE false', - language: 'esql', - }), - ]; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that one rule is eligible for update and contains esql_query field - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - const fieldDiffObject = reviewResponse.rules[0].diff.fields as AllFieldsDiff; - expect(fieldDiffObject.esql_query).toEqual({ - base_version: { - query: 'FROM query WHERE true', - language: 'esql', - }, - current_version: { - query: 'FROM query WHERE false', - language: 'esql', - }, - target_version: { - query: 'FROM query WHERE false', - language: 'esql', - }, - merged_version: { - query: 'FROM query WHERE false', - language: 'esql', - }, - diff_outcome: ThreeWayDiffOutcome.CustomizedValueSameUpdate, - merge_outcome: ThreeWayMergeOutcome.Current, - conflict: ThreeWayDiffConflict.NONE, - has_update: false, - has_base_version: true, - }); - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(1); // `version` is considered an updated field - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(0); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(0); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(0); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(0); - }); - }); - - describe('when rule field has an update and a custom value that are different - scenario ABC', () => { - it('should show a non-solvable conflict in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects()); - await installPrebuiltRules(es, supertest); - - // Customize an esql_query field on the installed rule - await updateRule(supertest, { - ...getPrebuiltRuleMock(), - rule_id: 'rule-1', - type: 'esql', - query: 'FROM query WHERE false', - language: 'esql', - } as RuleUpdateProps); - - // Add a v2 rule asset to make the upgrade possible, update an esql_query field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - type: 'esql', - query: 'FROM new query WHERE true', - language: 'esql', - }), - ]; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that one rule is eligible for update - // and esql_query field update has conflict - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - const fieldDiffObject = reviewResponse.rules[0].diff.fields as AllFieldsDiff; - expect(fieldDiffObject.esql_query).toEqual({ - base_version: { - query: 'FROM query WHERE true', - language: 'esql', - }, - current_version: { - query: 'FROM query WHERE false', - language: 'esql', - }, - target_version: { - query: 'FROM new query WHERE true', - language: 'esql', - }, - merged_version: { - query: 'FROM query WHERE false', - language: 'esql', - }, - diff_outcome: ThreeWayDiffOutcome.CustomizedValueCanUpdate, - merge_outcome: ThreeWayMergeOutcome.Current, - conflict: ThreeWayDiffConflict.NON_SOLVABLE, - has_update: true, - has_base_version: true, - }); - - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(2); // `version` is considered an updated field - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(1); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(1); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(1); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(1); - }); - }); - - describe('when rule base version does not exist', () => { - describe('when rule field has an update and a custom value that are the same - scenario -AA', () => { - it('should not show in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects()); - await installPrebuiltRules(es, supertest); - - // Clear previous rule assets - await deleteAllPrebuiltRuleAssets(es, log); - - // Add a v2 rule asset to make the upgrade possible, but keep esql_query field unchanged - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - type: 'esql', - query: 'FROM query WHERE true', - language: 'esql', - }), - ]; - await createPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that one rule is eligible for update - // but does NOT contain esql_query field - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - const fieldDiffObject = reviewResponse.rules[0].diff.fields as AllFieldsDiff; - expect(fieldDiffObject.esql_query).toBeUndefined(); - - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(1); - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(0); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(0); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(0); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(0); - }); - }); - - describe('when rule field has an update and a custom value that are different - scenario -AB', () => { - it('should show in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects()); - await installPrebuiltRules(es, supertest); - - // Clear previous rule assets - await deleteAllPrebuiltRuleAssets(es, log); - - // Customize an esql_query field on the installed rule - await updateRule(supertest, { - ...getPrebuiltRuleMock(), - rule_id: 'rule-1', - type: 'esql', - query: 'FROM query WHERE false', - language: 'esql', - } as RuleUpdateProps); - - // Add a v2 rule asset to make the upgrade possible, update an esql_query field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - type: 'esql', - query: 'FROM new query WHERE true', - language: 'esql', - }), - ]; - await createPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that one rule is eligible for update - // and esql_query field update does not have a conflict - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - const fieldDiffObject = reviewResponse.rules[0].diff.fields as AllFieldsDiff; - expect(fieldDiffObject.esql_query).toEqual({ - current_version: { - query: 'FROM query WHERE false', - language: 'esql', - }, - target_version: { - query: 'FROM new query WHERE true', - language: 'esql', - }, - merged_version: { - query: 'FROM new query WHERE true', - language: 'esql', - }, - diff_outcome: ThreeWayDiffOutcome.MissingBaseCanUpdate, - merge_outcome: ThreeWayMergeOutcome.Target, - conflict: ThreeWayDiffConflict.SOLVABLE, - has_update: true, - has_base_version: false, - }); - - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(2); - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(1); // query - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(0); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(1); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(0); - }); - }); - }); - }); - }); -}; diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/management/trial_license_complete_tier/upgrade_review_prebuilt_rules.kql_query_fields.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/management/trial_license_complete_tier/upgrade_review_prebuilt_rules.kql_query_fields.ts deleted file mode 100644 index 50bdb83744f04..0000000000000 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/management/trial_license_complete_tier/upgrade_review_prebuilt_rules.kql_query_fields.ts +++ /dev/null @@ -1,1278 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ -import expect from 'expect'; -import { - AllFieldsDiff, - KqlQueryType, - RuleUpdateProps, - ThreeWayDiffConflict, - ThreeWayDiffOutcome, - ThreeWayMergeOutcome, -} from '@kbn/security-solution-plugin/common/api/detection_engine'; -import { - getPrebuiltRuleMock, - getPrebuiltThreatMatchRuleMock, -} from '@kbn/security-solution-plugin/server/lib/detection_engine/prebuilt_rules/mocks'; -import { PrebuiltRuleAsset } from '@kbn/security-solution-plugin/server/lib/detection_engine/prebuilt_rules'; -import { FtrProviderContext } from '../../../../../../ftr_provider_context'; -import { - deleteAllTimelines, - deleteAllPrebuiltRuleAssets, - createRuleAssetSavedObject, - installPrebuiltRules, - createPrebuiltRuleAssetSavedObjects, - reviewPrebuiltRulesToUpgrade, - createHistoricalPrebuiltRuleAssetSavedObjects, - updateRule, - patchRule, -} from '../../../../utils'; -import { deleteAllRules } from '../../../../../../../common/utils/security_solution'; - -export default ({ getService }: FtrProviderContext): void => { - const es = getService('es'); - const supertest = getService('supertest'); - const log = getService('log'); - - describe('@ess @serverless @skipInServerlessMKI review prebuilt rules updates from package with mock rule assets', () => { - beforeEach(async () => { - await deleteAllRules(supertest, log); - await deleteAllTimelines(es, log); - await deleteAllPrebuiltRuleAssets(es, log); - }); - - describe(`kql_query fields`, () => { - const getQueryRuleAssetSavedObjects = () => [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 1, - type: 'query', - query: 'query string = true', - language: 'kuery', - filters: [], - }), - ]; - - const getSavedQueryRuleAssetSavedObjects = () => [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 1, - type: 'saved_query', - saved_id: 'saved-query-id', - }), - ]; - - describe("when rule field doesn't have an update and has no custom value - scenario AAA", () => { - describe('when all versions are inline query types', () => { - it('should not show in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects( - es, - getQueryRuleAssetSavedObjects() - ); - await installPrebuiltRules(es, supertest); - - // Add a v2 rule asset to make the upgrade possible, do NOT update the related kql_query field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - type: 'query', - query: 'query string = true', - language: 'kuery', - filters: [], - }), - ]; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that there is 1 rule eligible for update but kql_query field is NOT returned - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - const fieldDiffObject = reviewResponse.rules[0].diff.fields as AllFieldsDiff; - expect(fieldDiffObject.kql_query).toBeUndefined(); - - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(1); // `version` is considered an updated field - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(0); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(0); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(0); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(0); - }); - }); - - describe('when all versions are saved query types', () => { - it('should not show in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects( - es, - getSavedQueryRuleAssetSavedObjects() - ); - await installPrebuiltRules(es, supertest); - - // Add a v2 rule asset to make the upgrade possible, do NOT update the related kql_query field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - type: 'saved_query', - saved_id: 'saved-query-id', - }), - ]; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that there is 1 rule eligible for update but kql_query field is NOT returned - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - const fieldDiffObject = reviewResponse.rules[0].diff.fields as AllFieldsDiff; - expect(fieldDiffObject.kql_query).toBeUndefined(); - - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(1); // `version` is considered an updated field - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(0); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(0); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(0); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(0); - }); - }); - - describe('when all query versions have different surrounding whitespace', () => { - it('should not show in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects( - es, - getQueryRuleAssetSavedObjects() - ); - await installPrebuiltRules(es, supertest); - - // Customize a kql_query field on the installed rule - await updateRule(supertest, { - ...getPrebuiltRuleMock(), - rule_id: 'rule-1', - type: 'query', - query: '\nquery string = true', - language: 'kuery', - filters: [], - saved_id: undefined, - } as RuleUpdateProps); - - // Add a v2 rule asset to make the upgrade possible, do NOT update the related kql_query field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - type: 'query', - query: 'query string = true\n', - language: 'kuery', - filters: [], - }), - ]; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that there is 1 rule eligible for update but kql_query field is NOT returned - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - const fieldDiffObject = reviewResponse.rules[0].diff.fields as AllFieldsDiff; - expect(fieldDiffObject.kql_query).toBeUndefined(); - - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(1); // `version` is considered an updated field - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(0); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(0); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(0); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(0); - }); - }); - - describe('when all query versions have filters with alias fields set to null', () => { - it('should not show in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects(es, [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 1, - type: 'query', - query: 'query string = true', - language: 'kuery', - filters: [ - { - meta: { - negate: false, - disabled: false, - type: 'phrase', - key: 'test', - params: { - query: 'value', - }, - }, - query: { - term: { - field: 'value', - }, - }, - }, - ], - }), - ]); - await installPrebuiltRules(es, supertest); - - // Customize a kql_query field on the installed rule - await updateRule(supertest, { - ...getPrebuiltRuleMock(), - rule_id: 'rule-1', - type: 'query', - query: 'query string = true', - language: 'kuery', - filters: [ - { - meta: { - alias: null, - negate: false, - disabled: false, - type: 'phrase', - key: 'test', - params: { - query: 'value', - }, - }, - query: { - term: { - field: 'value', - }, - }, - }, - ], - saved_id: undefined, - } as RuleUpdateProps); - - // Add a v2 rule asset to make the upgrade possible, do NOT update the related kql_query field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - type: 'query', - query: 'query string = true', - language: 'kuery', - filters: [ - { - meta: { - negate: false, - disabled: false, - type: 'phrase', - key: 'test', - params: { - query: 'value', - }, - }, - query: { - term: { - field: 'value', - }, - }, - }, - ], - }), - ]; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that there is 1 rule eligible for update but kql_query field is NOT returned - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - const fieldDiffObject = reviewResponse.rules[0].diff.fields as AllFieldsDiff; - expect(fieldDiffObject.kql_query).toBeUndefined(); - - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(1); // `version` is considered an updated field - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(0); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(0); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(0); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(0); - }); - }); - }); - - describe("when rule field doesn't have an update but has a custom value - scenario ABA", () => { - describe('when current version is inline query type', () => { - it('should show in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects( - es, - getSavedQueryRuleAssetSavedObjects() - ); - await installPrebuiltRules(es, supertest); - - // Customize a kql_query field on the installed rule - await updateRule(supertest, { - ...getPrebuiltRuleMock(), - rule_id: 'rule-1', - type: 'query', - query: 'query string = true', - language: 'kuery', - filters: [], - saved_id: undefined, - } as RuleUpdateProps); - - // Add a v2 rule asset to make the upgrade possible, do NOT update the related kql_query field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - type: 'saved_query', - saved_id: 'saved-query-id', - }), - ]; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that kql_query diff field is returned but field does not have an update - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - const fieldDiffObject = reviewResponse.rules[0].diff.fields as AllFieldsDiff; - expect(fieldDiffObject.kql_query).toEqual({ - base_version: { - type: KqlQueryType.saved_query, - saved_query_id: 'saved-query-id', - }, - current_version: { - type: KqlQueryType.inline_query, - query: 'query string = true', - language: 'kuery', - filters: [], - }, - target_version: { - type: KqlQueryType.saved_query, - saved_query_id: 'saved-query-id', - }, - merged_version: { - type: KqlQueryType.inline_query, - query: 'query string = true', - language: 'kuery', - filters: [], - }, - diff_outcome: ThreeWayDiffOutcome.CustomizedValueNoUpdate, - merge_outcome: ThreeWayMergeOutcome.Current, - conflict: ThreeWayDiffConflict.NONE, - has_update: false, - has_base_version: true, - }); - - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(1); // `version` is considered an updated field - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(1); // `type` is considered to be a conflict - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(1); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(1); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(1); - }); - }); - - describe('when current version is saved query type', () => { - it('should show in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects( - es, - getQueryRuleAssetSavedObjects() - ); - await installPrebuiltRules(es, supertest); - - // Customize a kql_query field on the installed rule - await updateRule(supertest, { - ...getPrebuiltRuleMock(), - rule_id: 'rule-1', - type: 'saved_query', - query: undefined, - language: undefined, - filters: undefined, - saved_id: 'saved-query-id', - } as RuleUpdateProps); - - // Add a v2 rule asset to make the upgrade possible, do NOT update the related kql_query field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - type: 'query', - query: 'query string = true', - language: 'kuery', - filters: [], - }), - ]; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that kql_query diff field is returned but field does not have an update - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - const fieldDiffObject = reviewResponse.rules[0].diff.fields as AllFieldsDiff; - expect(fieldDiffObject.kql_query).toEqual({ - base_version: { - type: KqlQueryType.inline_query, - query: 'query string = true', - language: 'kuery', - filters: [], - }, - current_version: { - type: KqlQueryType.saved_query, - saved_query_id: 'saved-query-id', - }, - target_version: { - type: KqlQueryType.inline_query, - query: 'query string = true', - language: 'kuery', - filters: [], - }, - merged_version: { - type: KqlQueryType.saved_query, - saved_query_id: 'saved-query-id', - }, - diff_outcome: ThreeWayDiffOutcome.CustomizedValueNoUpdate, - merge_outcome: ThreeWayMergeOutcome.Current, - conflict: ThreeWayDiffConflict.NONE, - has_update: false, - has_base_version: true, - }); - - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(1); // `version` is considered an updated field - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(1); // `type` is considered to be a conflict - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(1); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(1); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(1); - }); - }); - }); - - describe('when rule field has an update but does not have a custom value - scenario AAB', () => { - describe('when all versions are inline query type', () => { - it('should show in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects( - es, - getQueryRuleAssetSavedObjects() - ); - await installPrebuiltRules(es, supertest); - - // Add a v2 rule asset to make the upgrade possible, update a kql_query field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - type: 'query', - query: 'query string = false', - }), - ]; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that one rule is eligible for update - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - const fieldDiffObject = reviewResponse.rules[0].diff.fields as AllFieldsDiff; - expect(fieldDiffObject.kql_query).toEqual({ - base_version: { - type: KqlQueryType.inline_query, - query: 'query string = true', - language: 'kuery', - filters: [], - }, - current_version: { - type: KqlQueryType.inline_query, - query: 'query string = true', - language: 'kuery', - filters: [], - }, - target_version: { - type: KqlQueryType.inline_query, - query: 'query string = false', - language: 'kuery', - filters: [], - }, - merged_version: { - type: KqlQueryType.inline_query, - query: 'query string = false', - language: 'kuery', - filters: [], - }, - diff_outcome: ThreeWayDiffOutcome.StockValueCanUpdate, - merge_outcome: ThreeWayMergeOutcome.Target, - conflict: ThreeWayDiffConflict.NONE, - has_update: true, - has_base_version: true, - }); - - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(2); // `version` is considered an updated field - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(0); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(0); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(0); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(0); - }); - }); - - describe('when all versions are saved query type', () => { - it('should show in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects( - es, - getSavedQueryRuleAssetSavedObjects() - ); - await installPrebuiltRules(es, supertest); - - // Add a v2 rule asset to make the upgrade possible, update a kql_query field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - type: 'saved_query', - saved_id: 'new-saved-query-id', - }), - ]; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that one rule is eligible for update - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - const fieldDiffObject = reviewResponse.rules[0].diff.fields as AllFieldsDiff; - expect(fieldDiffObject.kql_query).toEqual({ - base_version: { - type: KqlQueryType.saved_query, - saved_query_id: 'saved-query-id', - }, - current_version: { - type: KqlQueryType.saved_query, - saved_query_id: 'saved-query-id', - }, - target_version: { - type: KqlQueryType.saved_query, - saved_query_id: 'new-saved-query-id', - }, - merged_version: { - type: KqlQueryType.saved_query, - saved_query_id: 'new-saved-query-id', - }, - diff_outcome: ThreeWayDiffOutcome.StockValueCanUpdate, - merge_outcome: ThreeWayMergeOutcome.Target, - conflict: ThreeWayDiffConflict.NONE, - has_update: true, - has_base_version: true, - }); - - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(2); // `version` is considered an updated field - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(0); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(0); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(0); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(0); - }); - }); - }); - - describe('when rule field has an update and a custom value that are the same - scenario ABB', () => { - describe('when all versions are inline query type', () => { - it('should show in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects( - es, - getQueryRuleAssetSavedObjects() - ); - await installPrebuiltRules(es, supertest); - - // Customize a kql_query field on the installed rule - await patchRule(supertest, log, { - rule_id: 'rule-1', - query: 'query string = false', - }); - - // Add a v2 rule asset to make the upgrade possible, update a kql_query field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - type: 'query', - query: 'query string = false', - language: 'kuery', - filters: [], - }), - ]; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that one rule is eligible for update and contains kql_query field - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - const fieldDiffObject = reviewResponse.rules[0].diff.fields as AllFieldsDiff; - expect(fieldDiffObject.kql_query).toEqual({ - base_version: { - type: KqlQueryType.inline_query, - query: 'query string = true', - language: 'kuery', - filters: [], - }, - current_version: { - type: KqlQueryType.inline_query, - query: 'query string = false', - language: 'kuery', - filters: [], - }, - target_version: { - type: KqlQueryType.inline_query, - query: 'query string = false', - language: 'kuery', - filters: [], - }, - merged_version: { - type: KqlQueryType.inline_query, - query: 'query string = false', - language: 'kuery', - filters: [], - }, - diff_outcome: ThreeWayDiffOutcome.CustomizedValueSameUpdate, - merge_outcome: ThreeWayMergeOutcome.Current, - conflict: ThreeWayDiffConflict.NONE, - has_update: false, - has_base_version: true, - }); - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(1); // `version` is considered an updated field - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(0); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(0); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(0); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(0); - }); - }); - - describe('when all versions are saved query types', () => { - it('should show in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects( - es, - getSavedQueryRuleAssetSavedObjects() - ); - await installPrebuiltRules(es, supertest); - - // Customize a kql_query field on the installed rule - await updateRule(supertest, { - ...getPrebuiltRuleMock(), - rule_id: 'rule-1', - type: 'saved_query', - saved_id: 'new-saved-query-id', - } as RuleUpdateProps); - - // Add a v2 rule asset to make the upgrade possible, update a kql_query field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - type: 'saved_query', - saved_id: 'new-saved-query-id', - }), - ]; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that one rule is eligible for update and contains kql_query field - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - const fieldDiffObject = reviewResponse.rules[0].diff.fields as AllFieldsDiff; - expect(fieldDiffObject.kql_query).toEqual({ - base_version: { - type: KqlQueryType.saved_query, - saved_query_id: 'saved-query-id', - }, - current_version: { - type: KqlQueryType.saved_query, - saved_query_id: 'new-saved-query-id', - }, - target_version: { - type: KqlQueryType.saved_query, - saved_query_id: 'new-saved-query-id', - }, - merged_version: { - type: KqlQueryType.saved_query, - saved_query_id: 'new-saved-query-id', - }, - diff_outcome: ThreeWayDiffOutcome.CustomizedValueSameUpdate, - merge_outcome: ThreeWayMergeOutcome.Current, - conflict: ThreeWayDiffConflict.NONE, - has_update: false, - has_base_version: true, - }); - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(1); // `version` is considered an updated field - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(0); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(0); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(0); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(0); - }); - }); - }); - - describe('when rule field has an update and a custom value that are different - scenario ABC', () => { - describe('when current version is different type than base and target', () => { - it('should show a non-solvable conflict in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects( - es, - getQueryRuleAssetSavedObjects() - ); - await installPrebuiltRules(es, supertest); - - // Customize a kql_query field on the installed rule - await updateRule(supertest, { - ...getPrebuiltRuleMock(), - rule_id: 'rule-1', - type: 'saved_query', - query: undefined, - language: undefined, - filters: undefined, - saved_id: 'saved-query-id', - } as RuleUpdateProps); - - // Add a v2 rule asset to make the upgrade possible, update a kql_query field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - type: 'query', - query: 'query string = false', - language: 'kuery', - filters: [], - }), - ]; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that one rule is eligible for update - // and kql_query field update has conflict - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - const fieldDiffObject = reviewResponse.rules[0].diff.fields as AllFieldsDiff; - expect(fieldDiffObject.kql_query).toEqual({ - base_version: { - type: KqlQueryType.inline_query, - query: 'query string = true', - language: 'kuery', - filters: [], - }, - current_version: { - type: KqlQueryType.saved_query, - saved_query_id: 'saved-query-id', - }, - target_version: { - type: KqlQueryType.inline_query, - query: 'query string = false', - language: 'kuery', - filters: [], - }, - merged_version: { - type: KqlQueryType.saved_query, - saved_query_id: 'saved-query-id', - }, - diff_outcome: ThreeWayDiffOutcome.CustomizedValueCanUpdate, - merge_outcome: ThreeWayMergeOutcome.Current, - conflict: ThreeWayDiffConflict.NON_SOLVABLE, - has_update: true, - has_base_version: true, - }); - - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(2); // `version` is also considered an updated field - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(2); // `type` is also considered to be a conflict - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(2); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(1); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(1); - }); - }); - - describe('when all versions are inline query type', () => { - it('should show a non-solvable conflict in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects( - es, - getQueryRuleAssetSavedObjects() - ); - await installPrebuiltRules(es, supertest); - - // Customize a kql_query on the installed rule - await patchRule(supertest, log, { - rule_id: 'rule-1', - query: 'query string = false', - }); - - // Add a v2 rule asset to make the upgrade possible, update a kql_query field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - type: 'query', - query: 'query string = true', - language: 'kuery', - filters: [{ field: 'query' }], - }), - ]; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that one rule is eligible for update - // and kql_query field update has conflict - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - const fieldDiffObject = reviewResponse.rules[0].diff.fields as AllFieldsDiff; - expect(fieldDiffObject.kql_query).toEqual({ - base_version: { - type: KqlQueryType.inline_query, - query: 'query string = true', - language: 'kuery', - filters: [], - }, - current_version: { - type: KqlQueryType.inline_query, - query: 'query string = false', - language: 'kuery', - filters: [], - }, - target_version: { - type: KqlQueryType.inline_query, - query: 'query string = true', - language: 'kuery', - filters: [{ field: 'query' }], - }, - merged_version: { - type: KqlQueryType.inline_query, - query: 'query string = false', - language: 'kuery', - filters: [], - }, - diff_outcome: ThreeWayDiffOutcome.CustomizedValueCanUpdate, - merge_outcome: ThreeWayMergeOutcome.Current, - conflict: ThreeWayDiffConflict.NON_SOLVABLE, - has_update: true, - has_base_version: true, - }); - - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(2); // `version` is considered an updated field - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(1); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(1); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(1); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(1); - }); - }); - - describe('when all versions are saved query type', () => { - it('should show a non-solvable conflict in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects( - es, - getSavedQueryRuleAssetSavedObjects() - ); - await installPrebuiltRules(es, supertest); - - // Customize a kql_query field on the installed rule - await updateRule(supertest, { - ...getPrebuiltRuleMock(), - rule_id: 'rule-1', - type: 'saved_query', - saved_id: 'new-saved-query-id', - } as RuleUpdateProps); - - // Add a v2 rule asset to make the upgrade possible, update a kql_query field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - type: 'saved_query', - saved_id: 'even-newer-saved-query-id', - }), - ]; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that one rule is eligible for update - // and kql_query field update has conflict - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - const fieldDiffObject = reviewResponse.rules[0].diff.fields as AllFieldsDiff; - expect(fieldDiffObject.kql_query).toEqual({ - base_version: { - type: KqlQueryType.saved_query, - saved_query_id: 'saved-query-id', - }, - current_version: { - type: KqlQueryType.saved_query, - saved_query_id: 'new-saved-query-id', - }, - target_version: { - type: KqlQueryType.saved_query, - saved_query_id: 'even-newer-saved-query-id', - }, - merged_version: { - type: KqlQueryType.saved_query, - saved_query_id: 'new-saved-query-id', - }, - diff_outcome: ThreeWayDiffOutcome.CustomizedValueCanUpdate, - merge_outcome: ThreeWayMergeOutcome.Current, - conflict: ThreeWayDiffConflict.NON_SOLVABLE, - has_update: true, - has_base_version: true, - }); - - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(2); // `version` is considered an updated field - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(1); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(1); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(1); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(1); - }); - }); - - describe('when rule type is threat match', () => { - it('should show a non-solvable conflict in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects(es, [ - createRuleAssetSavedObject({ - ...getPrebuiltThreatMatchRuleMock(), - threat_filters: [], - } as PrebuiltRuleAsset), - ]); - await installPrebuiltRules(es, supertest); - - // Customize a threat_query on the installed rule - await updateRule(supertest, { - ...getPrebuiltThreatMatchRuleMock(), - rule_id: 'rule-1', - threat_query: '*', - threat_filters: [], - } as RuleUpdateProps); - - // Add a v2 rule asset to make the upgrade possible, update a threat_query field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - ...getPrebuiltThreatMatchRuleMock(), - threat_query: `*:'new query'`, - threat_filters: [], - version: 2, - } as PrebuiltRuleAsset), - ]; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that one rule is eligible for update - // and threat_query field update has conflict - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - const fieldDiffObject = reviewResponse.rules[0].diff.fields as AllFieldsDiff; - expect(fieldDiffObject.threat_query).toEqual({ - base_version: { - type: KqlQueryType.inline_query, - query: '*:*', - language: 'kuery', - filters: [], - }, - current_version: { - type: KqlQueryType.inline_query, - query: '*', - language: 'kuery', - filters: [], - }, - target_version: { - type: KqlQueryType.inline_query, - query: `*:'new query'`, - language: 'kuery', - filters: [], - }, - merged_version: { - type: KqlQueryType.inline_query, - query: '*', - language: 'kuery', - filters: [], - }, - diff_outcome: ThreeWayDiffOutcome.CustomizedValueCanUpdate, - merge_outcome: ThreeWayMergeOutcome.Current, - conflict: ThreeWayDiffConflict.NON_SOLVABLE, - has_update: true, - has_base_version: true, - }); - - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(2); // `version` is considered an updated field - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(1); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(1); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(1); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(1); - }); - }); - - describe('when rule type is threshold', () => { - it('should show a non-solvable conflict in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects(es, [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 1, - type: 'threshold', - query: 'query string = true', - threshold: { - field: 'some.field', - value: 4, - }, - }), - ]); - await installPrebuiltRules(es, supertest); - - // Customize a kql_query field on the installed rule - await updateRule(supertest, { - ...getPrebuiltRuleMock(), - rule_id: 'rule-1', - type: 'threshold', - query: 'query string = false', - threshold: { - field: 'some.field', - value: 4, - }, - } as RuleUpdateProps); - - // Add a v2 rule asset to make the upgrade possible, update a kql_query field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - type: 'threshold', - query: 'new query string = true', - threshold: { - field: 'some.field', - value: 4, - }, - }), - ]; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that one rule is eligible for update - // and kql_query field update has conflict - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - const fieldDiffObject = reviewResponse.rules[0].diff.fields as AllFieldsDiff; - expect(fieldDiffObject.kql_query).toEqual({ - base_version: { - type: KqlQueryType.inline_query, - query: 'query string = true', - language: 'kuery', - filters: [], - }, - current_version: { - type: KqlQueryType.inline_query, - query: 'query string = false', - language: 'kuery', - filters: [], - }, - target_version: { - type: KqlQueryType.inline_query, - query: 'new query string = true', - language: 'kuery', - filters: [], - }, - merged_version: { - type: KqlQueryType.inline_query, - query: 'query string = false', - language: 'kuery', - filters: [], - }, - diff_outcome: ThreeWayDiffOutcome.CustomizedValueCanUpdate, - merge_outcome: ThreeWayMergeOutcome.Current, - conflict: ThreeWayDiffConflict.NON_SOLVABLE, - has_update: true, - has_base_version: true, - }); - - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(2); // `version` is considered an updated field - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(1); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(1); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(1); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(1); - }); - }); - - describe('when rule type is new_terms', () => { - it('should show a non-solvable conflict in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects(es, [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 1, - type: 'new_terms', - query: 'query string = true', - new_terms_fields: ['user.name'], - history_window_start: 'now-7d', - }), - ]); - await installPrebuiltRules(es, supertest); - - // Customize a kql_query field on the installed rule - await updateRule(supertest, { - ...getPrebuiltRuleMock(), - rule_id: 'rule-1', - type: 'new_terms', - query: 'query string = false', - new_terms_fields: ['user.name'], - history_window_start: 'now-7d', - } as RuleUpdateProps); - - // Add a v2 rule asset to make the upgrade possible, update a kql_query field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - type: 'new_terms', - query: 'new query string = true', - new_terms_fields: ['user.name'], - history_window_start: 'now-7d', - }), - ]; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that one rule is eligible for update - // and kql_query field update has conflict - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - const fieldDiffObject = reviewResponse.rules[0].diff.fields as AllFieldsDiff; - expect(fieldDiffObject.kql_query).toEqual({ - base_version: { - type: KqlQueryType.inline_query, - query: 'query string = true', - language: 'kuery', - filters: [], - }, - current_version: { - type: KqlQueryType.inline_query, - query: 'query string = false', - language: 'kuery', - filters: [], - }, - target_version: { - type: KqlQueryType.inline_query, - query: 'new query string = true', - language: 'kuery', - filters: [], - }, - merged_version: { - type: KqlQueryType.inline_query, - query: 'query string = false', - language: 'kuery', - filters: [], - }, - diff_outcome: ThreeWayDiffOutcome.CustomizedValueCanUpdate, - merge_outcome: ThreeWayMergeOutcome.Current, - conflict: ThreeWayDiffConflict.NON_SOLVABLE, - has_update: true, - has_base_version: true, - }); - - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(2); // `version` is considered an updated field - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(1); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(1); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(1); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(1); - }); - }); - }); - - describe('when rule base version does not exist', () => { - describe('when rule field has an update and a custom value that are the same - scenario -AA', () => { - it('should not show in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createPrebuiltRuleAssetSavedObjects(es, getQueryRuleAssetSavedObjects()); - await installPrebuiltRules(es, supertest); - - // Clear previous rule assets - await deleteAllPrebuiltRuleAssets(es, log); - - // Add a v2 rule asset to make the upgrade possible, but keep kql_query field unchanged - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - type: 'query', - query: 'query string = true', - language: 'kuery', - filters: [], - }), - ]; - await createPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that one rule is eligible for update - // but does NOT contain kql_query field - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - const fieldDiffObject = reviewResponse.rules[0].diff.fields as AllFieldsDiff; - expect(fieldDiffObject.kql_query).toBeUndefined(); - - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(1); // `version` is considered an updated field - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(0); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(0); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(0); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(0); - }); - }); - - describe('when rule field has an update and a custom value that are different - scenario -AB', () => { - it('should show in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createPrebuiltRuleAssetSavedObjects(es, getQueryRuleAssetSavedObjects()); - await installPrebuiltRules(es, supertest); - - // Clear previous rule assets - await deleteAllPrebuiltRuleAssets(es, log); - - // Customize a kql_query field on the installed rule - await updateRule(supertest, { - ...getPrebuiltRuleMock(), - rule_id: 'rule-1', - type: 'query', - query: 'query string = false', - language: 'kuery', - filters: [], - } as RuleUpdateProps); - - // Add a v2 rule asset to make the upgrade possible, update a kql_query field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - type: 'query', - query: 'new query string = true', - language: 'kuery', - filters: [], - }), - ]; - await createPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that one rule is eligible for update - // and kql_query field update does not have a conflict - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - const fieldDiffObject = reviewResponse.rules[0].diff.fields as AllFieldsDiff; - expect(fieldDiffObject.kql_query).toEqual({ - current_version: { - type: KqlQueryType.inline_query, - query: 'query string = false', - language: 'kuery', - filters: [], - }, - target_version: { - type: KqlQueryType.inline_query, - query: 'new query string = true', - language: 'kuery', - filters: [], - }, - merged_version: { - type: KqlQueryType.inline_query, - query: 'new query string = true', - language: 'kuery', - filters: [], - }, - diff_outcome: ThreeWayDiffOutcome.MissingBaseCanUpdate, - merge_outcome: ThreeWayMergeOutcome.Target, - conflict: ThreeWayDiffConflict.SOLVABLE, - has_update: true, - has_base_version: false, - }); - - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(2); - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(1); // query - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(0); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(1); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(0); - }); - }); - }); - }); - }); -}; diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/management/trial_license_complete_tier/upgrade_review_prebuilt_rules.multi_line_string_fields.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/management/trial_license_complete_tier/upgrade_review_prebuilt_rules.multi_line_string_fields.ts deleted file mode 100644 index 23bfd08f5b520..0000000000000 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/management/trial_license_complete_tier/upgrade_review_prebuilt_rules.multi_line_string_fields.ts +++ /dev/null @@ -1,444 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ -import expect from 'expect'; -import { - ThreeWayDiffConflict, - ThreeWayDiffOutcome, - ThreeWayMergeOutcome, -} from '@kbn/security-solution-plugin/common/api/detection_engine'; -import { - TEXT_XL_A, - TEXT_XL_B, - TEXT_XL_C, - TEXT_XL_MERGED, -} from '@kbn/security-solution-plugin/server/lib/detection_engine/prebuilt_rules/logic/diff/calculation/algorithms/multi_line_string_diff_algorithm.mock'; -import { FtrProviderContext } from '../../../../../../ftr_provider_context'; -import { - deleteAllTimelines, - deleteAllPrebuiltRuleAssets, - createRuleAssetSavedObject, - installPrebuiltRules, - createPrebuiltRuleAssetSavedObjects, - reviewPrebuiltRulesToUpgrade, - patchRule, - createHistoricalPrebuiltRuleAssetSavedObjects, -} from '../../../../utils'; -import { deleteAllRules } from '../../../../../../../common/utils/security_solution'; - -export default ({ getService }: FtrProviderContext): void => { - const es = getService('es'); - const supertest = getService('supertest'); - const log = getService('log'); - - describe('@ess @serverless @skipInServerlessMKI review prebuilt rules updates from package with mock rule assets', () => { - beforeEach(async () => { - await deleteAllRules(supertest, log); - await deleteAllTimelines(es, log); - await deleteAllPrebuiltRuleAssets(es, log); - }); - - describe(`multi line string fields`, () => { - const getRuleAssetSavedObjects = () => [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 1, - description: 'My description.\nThis is a second line.', - }), - ]; - - describe("when rule field doesn't have an update and has no custom value - scenario AAA", () => { - it('should not show in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects()); - await installPrebuiltRules(es, supertest); - - // Increment the version of the installed rule, do NOT update the related multi line string field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - description: 'My description.\nThis is a second line.', - version: 2, - }), - ]; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that there is 1 rule eligible - // for update but multi-line string field (description) is NOT returned - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - expect(reviewResponse.rules[0].diff.fields.description).toBeUndefined(); - - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(1); // version - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(0); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(0); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(0); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(0); - }); - }); - - describe("when rule field doesn't have an update but has a custom value - scenario ABA", () => { - it('should show in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects()); - await installPrebuiltRules(es, supertest); - - // Customize a multi line string field on the installed rule - await patchRule(supertest, log, { - rule_id: 'rule-1', - description: 'My GREAT description.\nThis is a second line.', - }); - - // Increment the version of the installed rule, do NOT update the related multi line string field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - description: 'My description.\nThis is a second line.', - version: 2, - }), - ]; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that multi line string diff field is returned but field does not have an update - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - expect(reviewResponse.rules[0].diff.fields.description).toEqual({ - base_version: 'My description.\nThis is a second line.', - current_version: 'My GREAT description.\nThis is a second line.', - target_version: 'My description.\nThis is a second line.', - merged_version: 'My GREAT description.\nThis is a second line.', - diff_outcome: ThreeWayDiffOutcome.CustomizedValueNoUpdate, - merge_outcome: ThreeWayMergeOutcome.Current, - conflict: ThreeWayDiffConflict.NONE, - has_update: false, - has_base_version: true, - }); - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(1); - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(0); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(0); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(0); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(0); - }); - }); - - describe('when rule field has an update but does not have a custom value - scenario AAB', () => { - it('should show in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects()); - await installPrebuiltRules(es, supertest); - - // Increment the version of the installed rule, update a multi line string field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - description: 'My GREAT description.\nThis is a second line.', - }), - ]; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that one rule is eligible for update - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - expect(reviewResponse.rules[0].diff.fields.description).toEqual({ - base_version: 'My description.\nThis is a second line.', - current_version: 'My description.\nThis is a second line.', - target_version: 'My GREAT description.\nThis is a second line.', - merged_version: 'My GREAT description.\nThis is a second line.', - diff_outcome: ThreeWayDiffOutcome.StockValueCanUpdate, - merge_outcome: ThreeWayMergeOutcome.Target, - conflict: ThreeWayDiffConflict.NONE, - has_update: true, - has_base_version: true, - }); - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(2); - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(0); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(0); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(0); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(0); - }); - }); - - describe('when rule field has an update and a custom value that are the same - scenario ABB', () => { - it('should show in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects()); - await installPrebuiltRules(es, supertest); - - // Customize a multi line string field on the installed rule - await patchRule(supertest, log, { - rule_id: 'rule-1', - description: 'My GREAT description.\nThis is a second line.', - }); - - // Increment the version of the installed rule, update a multi line string field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - description: 'My GREAT description.\nThis is a second line.', - }), - ]; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that one rule is eligible for update - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - expect(reviewResponse.rules[0].diff.fields.description).toEqual({ - base_version: 'My description.\nThis is a second line.', - current_version: 'My GREAT description.\nThis is a second line.', - target_version: 'My GREAT description.\nThis is a second line.', - merged_version: 'My GREAT description.\nThis is a second line.', - diff_outcome: ThreeWayDiffOutcome.CustomizedValueSameUpdate, - merge_outcome: ThreeWayMergeOutcome.Current, - conflict: ThreeWayDiffConflict.NONE, - has_update: false, - has_base_version: true, - }); - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(1); - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(0); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(0); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(0); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(0); - }); - }); - - describe('when rule field has an update and a custom value that are different - scenario ABC', () => { - describe('when all versions are mergable', () => { - it('should show in the upgrade/_review API response with a solvable conflict', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects()); - await installPrebuiltRules(es, supertest); - - // Customize a multi line string field on the installed rule - await patchRule(supertest, log, { - rule_id: 'rule-1', - description: 'My GREAT description.\nThis is a second line.', - }); - - // Increment the version of the installed rule, update a multi line string field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - description: 'My description.\nThis is a second line, now longer.', - }), - ]; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that one rule is eligible for update - // and multi line string field update has no conflict - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - expect(reviewResponse.rules[0].diff.fields.description).toEqual({ - base_version: 'My description.\nThis is a second line.', - current_version: 'My GREAT description.\nThis is a second line.', - target_version: 'My description.\nThis is a second line, now longer.', - merged_version: 'My GREAT description.\nThis is a second line, now longer.', - diff_outcome: ThreeWayDiffOutcome.CustomizedValueCanUpdate, - merge_outcome: ThreeWayMergeOutcome.Merged, - conflict: ThreeWayDiffConflict.SOLVABLE, - has_update: true, - has_base_version: true, - }); - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(2); - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(1); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(0); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(1); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(0); - }); - - it('should handle long multi-line strings without timing out', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects(es, [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 1, - description: TEXT_XL_A, - }), - ]); - await installPrebuiltRules(es, supertest); - - // Customize a multi line string field on the installed rule - await patchRule(supertest, log, { - rule_id: 'rule-1', - description: TEXT_XL_B, - }); - - // Increment the version of the installed rule, update a multi line string field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - description: TEXT_XL_C, - }), - ]; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that one rule is eligible for update - // and multi line string field update has no conflict - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - expect(reviewResponse.rules[0].diff.fields.description).toEqual({ - base_version: TEXT_XL_A, - current_version: TEXT_XL_B, - target_version: TEXT_XL_C, - merged_version: TEXT_XL_MERGED, - diff_outcome: ThreeWayDiffOutcome.CustomizedValueCanUpdate, - merge_outcome: ThreeWayMergeOutcome.Merged, - conflict: ThreeWayDiffConflict.SOLVABLE, - has_update: true, - has_base_version: true, - }); - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(2); - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(1); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(0); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(1); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(0); - }); - }); - - describe('when all versions are not mergable', () => { - it('should show in the upgrade/_review API response with a non-solvable conflict', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects()); - await installPrebuiltRules(es, supertest); - - // Customize a multi line string field on the installed rule - await patchRule(supertest, log, { - rule_id: 'rule-1', - description: 'My GREAT description.\nThis is a third line.', - }); - - // Increment the version of the installed rule, update a multi line string field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - description: 'My EXCELLENT description.\nThis is a fourth.', - }), - ]; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that one rule is eligible for update - // and multi line string field update has conflict - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - expect(reviewResponse.rules[0].diff.fields.description).toEqual({ - base_version: 'My description.\nThis is a second line.', - current_version: 'My GREAT description.\nThis is a third line.', - target_version: 'My EXCELLENT description.\nThis is a fourth.', - merged_version: 'My GREAT description.\nThis is a third line.', - diff_outcome: ThreeWayDiffOutcome.CustomizedValueCanUpdate, - merge_outcome: ThreeWayMergeOutcome.Current, - conflict: ThreeWayDiffConflict.NON_SOLVABLE, - has_update: true, - has_base_version: true, - }); - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(2); - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(1); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(1); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(1); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(1); - }); - }); - }); - - describe('when rule base version does not exist', () => { - describe('when rule field has an update and a custom value that are the same - scenario -AA', () => { - it('should not show in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects()); - await installPrebuiltRules(es, supertest); - - // Clear previous rule assets - await deleteAllPrebuiltRuleAssets(es, log); - - // Customize a multi line string field on the installed rule - await patchRule(supertest, log, { - rule_id: 'rule-1', - description: 'My description.\nThis is a second line.', - }); - - // Increment the version of the installed rule, update a multi line string field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - description: 'My description.\nThis is a second line.', - }), - ]; - await createPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that one rule is eligible for update - // but does NOT contain multi line string field, since -AA is treated as AAA - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - expect(reviewResponse.rules[0].diff.fields.description).toBeUndefined(); - - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(1); - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(0); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(0); - }); - }); - - describe('when rule field has an update and a custom value that are different - scenario -AB', () => { - it('should show in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects()); - await installPrebuiltRules(es, supertest); - - // Clear previous rule assets - await deleteAllPrebuiltRuleAssets(es, log); - - // Customize a multi line string field on the installed rule - await patchRule(supertest, log, { - rule_id: 'rule-1', - description: 'My description.\nThis is a second line.', - }); - - // Increment the version of the installed rule, update a multi line string field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - description: 'My GREAT description.\nThis is a second line.', - }), - ]; - await createPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that one rule is eligible for update - // and multi line string field update does not have a conflict - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - expect(reviewResponse.rules[0].diff.fields.description).toEqual({ - current_version: 'My description.\nThis is a second line.', - target_version: 'My GREAT description.\nThis is a second line.', - merged_version: 'My GREAT description.\nThis is a second line.', - diff_outcome: ThreeWayDiffOutcome.MissingBaseCanUpdate, - merge_outcome: ThreeWayMergeOutcome.Target, - conflict: ThreeWayDiffConflict.SOLVABLE, - has_update: true, - has_base_version: false, - }); - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(2); - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(1); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(0); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(1); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(0); - }); - }); - }); - }); - }); -}; diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/management/trial_license_complete_tier/upgrade_review_prebuilt_rules.number_fields.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/management/trial_license_complete_tier/upgrade_review_prebuilt_rules.number_fields.ts deleted file mode 100644 index bd059ec137a96..0000000000000 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/management/trial_license_complete_tier/upgrade_review_prebuilt_rules.number_fields.ts +++ /dev/null @@ -1,336 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ -import expect from 'expect'; -import { - ThreeWayDiffConflict, - ThreeWayDiffOutcome, - ThreeWayMergeOutcome, -} from '@kbn/security-solution-plugin/common/api/detection_engine'; -import { FtrProviderContext } from '../../../../../../ftr_provider_context'; -import { - deleteAllTimelines, - deleteAllPrebuiltRuleAssets, - createRuleAssetSavedObject, - installPrebuiltRules, - createPrebuiltRuleAssetSavedObjects, - reviewPrebuiltRulesToUpgrade, - patchRule, - createHistoricalPrebuiltRuleAssetSavedObjects, -} from '../../../../utils'; -import { deleteAllRules } from '../../../../../../../common/utils/security_solution'; - -export default ({ getService }: FtrProviderContext): void => { - const es = getService('es'); - const supertest = getService('supertest'); - const log = getService('log'); - - describe('@ess @serverless @skipInServerlessMKI review prebuilt rules updates from package with mock rule assets', () => { - beforeEach(async () => { - await deleteAllRules(supertest, log); - await deleteAllTimelines(es, log); - await deleteAllPrebuiltRuleAssets(es, log); - }); - - describe(`number fields`, () => { - const getRuleAssetSavedObjects = () => [ - createRuleAssetSavedObject({ rule_id: 'rule-1', version: 1, risk_score: 1 }), - ]; - - describe("when rule field doesn't have an update and has no custom value - scenario AAA", () => { - it('should not show in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects()); - await installPrebuiltRules(es, supertest); - - // Increment the version of the installed rule, do NOT update the related number field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - risk_score: 1, - version: 2, - }), - ]; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that there is 1 rule eligible - // for update but number field (risk_score) is NOT returned - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - expect(reviewResponse.rules[0].diff.fields.risk_score).toBeUndefined(); - - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(1); // version - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(0); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(0); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(0); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(0); - }); - }); - - describe("when rule field doesn't have an update but has a custom value - scenario ABA", () => { - it('should show in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects()); - await installPrebuiltRules(es, supertest); - - // Customize a number field on the installed rule - await patchRule(supertest, log, { - rule_id: 'rule-1', - risk_score: 2, - }); - - // Increment the version of the installed rule, do NOT update the related number field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - risk_score: 1, - version: 2, - }), - ]; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that number diff field is returned but field does not have an update - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - expect(reviewResponse.rules[0].diff.fields.risk_score).toEqual({ - base_version: 1, - current_version: 2, - target_version: 1, - merged_version: 2, - diff_outcome: ThreeWayDiffOutcome.CustomizedValueNoUpdate, - merge_outcome: ThreeWayMergeOutcome.Current, - conflict: ThreeWayDiffConflict.NONE, - has_update: false, - has_base_version: true, - }); - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(1); - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(0); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(0); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(0); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(0); - }); - }); - - describe('when rule field has an update but does not have a custom value - scenario AAB', () => { - it('should show in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects()); - await installPrebuiltRules(es, supertest); - - // Increment the version of the installed rule, update a number field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - risk_score: 2, - }), - ]; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that one rule is eligible for update - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - expect(reviewResponse.rules[0].diff.fields.risk_score).toEqual({ - base_version: 1, - current_version: 1, - target_version: 2, - merged_version: 2, - diff_outcome: ThreeWayDiffOutcome.StockValueCanUpdate, - merge_outcome: ThreeWayMergeOutcome.Target, - conflict: ThreeWayDiffConflict.NONE, - has_update: true, - has_base_version: true, - }); - - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(2); - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(0); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(0); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(0); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(0); - }); - }); - - describe('when rule field has an update and a custom value that are the same - scenario ABB', () => { - it('should show in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects()); - await installPrebuiltRules(es, supertest); - - // Customize a number field on the installed rule - await patchRule(supertest, log, { - rule_id: 'rule-1', - risk_score: 2, - }); - - // Increment the version of the installed rule, update a number field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - risk_score: 2, - }), - ]; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that one rule is eligible for update and contains number field - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - expect(reviewResponse.rules[0].diff.fields.risk_score).toEqual({ - base_version: 1, - current_version: 2, - target_version: 2, - merged_version: 2, - diff_outcome: ThreeWayDiffOutcome.CustomizedValueSameUpdate, - merge_outcome: ThreeWayMergeOutcome.Current, - conflict: ThreeWayDiffConflict.NONE, - has_update: false, - has_base_version: true, - }); - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(1); - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(0); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(0); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(0); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(0); - }); - }); - - describe('when rule field has an update and a custom value that are different - scenario ABC', () => { - it('should show in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects()); - await installPrebuiltRules(es, supertest); - - // Customize a number field on the installed rule - await patchRule(supertest, log, { - rule_id: 'rule-1', - risk_score: 2, - }); - - // Increment the version of the installed rule, update a number field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - risk_score: 3, - }), - ]; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that one rule is eligible for update - // and number field update has conflict - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - expect(reviewResponse.rules[0].diff.fields.risk_score).toEqual({ - base_version: 1, - current_version: 2, - target_version: 3, - merged_version: 2, - diff_outcome: ThreeWayDiffOutcome.CustomizedValueCanUpdate, - merge_outcome: ThreeWayMergeOutcome.Current, - conflict: ThreeWayDiffConflict.NON_SOLVABLE, - has_update: true, - has_base_version: true, - }); - - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(2); - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(1); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(1); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(1); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(1); - }); - }); - - describe('when rule base version does not exist', () => { - describe('when rule field has an update and a custom value that are the same - scenario -AA', () => { - it('should not show in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects()); - await installPrebuiltRules(es, supertest); - - // Clear previous rule assets - await deleteAllPrebuiltRuleAssets(es, log); - - // Increment the version of the installed rule with the number field maintained - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - risk_score: 1, - }), - ]; - await createPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that one rule is eligible for update - // but does NOT contain the risk_score number field, since -AA is treated as AAA - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - expect(reviewResponse.rules[0].diff.fields.risk_score).toBeUndefined(); - - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(1); - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(0); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(0); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(0); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(0); - }); - }); - - describe('when rule field has an update and a custom value that are different - scenario -AB', () => { - it('should show in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects()); - await installPrebuiltRules(es, supertest); - - // Clear previous rule assets - await deleteAllPrebuiltRuleAssets(es, log); - - // Customize a number field on the installed rule - await patchRule(supertest, log, { - rule_id: 'rule-1', - risk_score: 2, - }); - - // Increment the version of the installed rule, update a number field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - risk_score: 3, - }), - ]; - await createPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that one rule is eligible for update - // and number field update does not have a conflict - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - expect(reviewResponse.rules[0].diff.fields.risk_score).toEqual({ - current_version: 2, - target_version: 3, - merged_version: 3, - diff_outcome: ThreeWayDiffOutcome.MissingBaseCanUpdate, - merge_outcome: ThreeWayMergeOutcome.Target, - conflict: ThreeWayDiffConflict.SOLVABLE, - has_update: true, - has_base_version: false, - }); - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(2); - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(1); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(0); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(1); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(0); - }); - }); - }); - }); - }); -}; diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/management/trial_license_complete_tier/upgrade_review_prebuilt_rules.rule_type_fields.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/management/trial_license_complete_tier/upgrade_review_prebuilt_rules.rule_type_fields.ts deleted file mode 100644 index 3f6784108487c..0000000000000 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/management/trial_license_complete_tier/upgrade_review_prebuilt_rules.rule_type_fields.ts +++ /dev/null @@ -1,362 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ -import expect from 'expect'; -import { - RuleUpdateProps, - ThreeWayDiffConflict, - ThreeWayDiffOutcome, - ThreeWayMergeOutcome, -} from '@kbn/security-solution-plugin/common/api/detection_engine'; -import { getPrebuiltRuleMock } from '@kbn/security-solution-plugin/server/lib/detection_engine/prebuilt_rules/mocks'; -import { FtrProviderContext } from '../../../../../../ftr_provider_context'; -import { - deleteAllTimelines, - deleteAllPrebuiltRuleAssets, - createRuleAssetSavedObject, - installPrebuiltRules, - createPrebuiltRuleAssetSavedObjects, - reviewPrebuiltRulesToUpgrade, - patchRule, - createHistoricalPrebuiltRuleAssetSavedObjects, - updateRule, -} from '../../../../utils'; -import { deleteAllRules } from '../../../../../../../common/utils/security_solution'; - -export default ({ getService }: FtrProviderContext): void => { - const es = getService('es'); - const supertest = getService('supertest'); - const log = getService('log'); - - describe('@ess @serverless @skipInServerlessMKI review prebuilt rules updates from package with mock rule assets', () => { - beforeEach(async () => { - await deleteAllRules(supertest, log); - await deleteAllTimelines(es, log); - await deleteAllPrebuiltRuleAssets(es, log); - }); - - describe(`rule type fields`, () => { - const getRuleAssetSavedObjects = () => [ - createRuleAssetSavedObject({ rule_id: 'rule-1', version: 1, type: 'query' }), - ]; - - describe("when rule field doesn't have an update and has no custom value - scenario AAA", () => { - it('should not show in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects()); - await installPrebuiltRules(es, supertest); - - // Increment the version of the installed rule, do NOT update the related type field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - type: 'query', - }), - ]; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that there is 1 rule eligible for update - // but type field is NOT returned - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - expect(reviewResponse.rules[0].diff.fields.type).toBeUndefined(); - - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(1); - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(0); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(0); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(0); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(0); - }); - }); - - describe("when rule field doesn't have an update but has a custom value - scenario ABA", () => { - it('should show in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects()); - await installPrebuiltRules(es, supertest); - - // Customize a type field on the installed rule - await updateRule(supertest, { - ...getPrebuiltRuleMock(), - rule_id: 'rule-1', - type: 'saved_query', - query: undefined, - language: undefined, - filters: undefined, - saved_id: 'saved-query-id', - } as RuleUpdateProps); - - // Increment the version of the installed rule, do NOT update the related type field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - type: 'query', - }), - ]; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that type diff field - // is returned but field does not have an update, and the merge outcome is "Target" - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - expect(reviewResponse.rules[0].diff.fields.type).toEqual({ - base_version: 'query', - current_version: 'saved_query', - target_version: 'query', - merged_version: 'query', - diff_outcome: ThreeWayDiffOutcome.CustomizedValueNoUpdate, - merge_outcome: ThreeWayMergeOutcome.Target, - conflict: ThreeWayDiffConflict.NON_SOLVABLE, - has_update: false, - has_base_version: true, - }); - - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(1); // version field counts as upgraded - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(1); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(1); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(1); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(1); - }); - }); - - describe('when rule field has an update but does not have a custom value - scenario AAB', () => { - it('should show in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects()); - await installPrebuiltRules(es, supertest); - - // Increment the version of the installed rule, update a type field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - type: 'saved_query', - saved_id: 'even-newer-saved-query-id', - }), - ]; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that one rule is eligible for update - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - expect(reviewResponse.rules[0].diff.fields.type).toEqual({ - base_version: 'query', - current_version: 'query', - target_version: 'saved_query', - merged_version: 'saved_query', - diff_outcome: ThreeWayDiffOutcome.StockValueCanUpdate, - merge_outcome: ThreeWayMergeOutcome.Target, - conflict: ThreeWayDiffConflict.NON_SOLVABLE, - has_update: true, - has_base_version: true, - }); - - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(3); // version and query fields also have updates - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(1); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(1); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(1); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(1); - }); - }); - - describe('when rule field has an update and a custom value that are the same - scenario ABB', () => { - it('should show in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects()); - await installPrebuiltRules(es, supertest); - - // Customize a type field on the installed rule - await updateRule(supertest, { - ...getPrebuiltRuleMock(), - rule_id: 'rule-1', - type: 'saved_query', - query: undefined, - language: undefined, - filters: undefined, - saved_id: 'saved-query-id', - } as RuleUpdateProps); - - // Increment the version of the installed rule, update a type field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - type: 'saved_query', - saved_id: 'saved-query-id', - }), - ]; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that one rule is eligible for update - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - expect(reviewResponse.rules[0].diff.fields.type).toEqual({ - base_version: 'query', - current_version: 'saved_query', - target_version: 'saved_query', - merged_version: 'saved_query', - diff_outcome: ThreeWayDiffOutcome.CustomizedValueSameUpdate, - merge_outcome: ThreeWayMergeOutcome.Target, - conflict: ThreeWayDiffConflict.NON_SOLVABLE, - has_update: false, - has_base_version: true, - }); - - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(1); - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(1); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(1); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(1); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(1); - }); - }); - - describe('when rule field has an update and a custom value that are different - scenario ABC', () => { - it('should show in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects()); - await installPrebuiltRules(es, supertest); - - // Customize a type field on the installed rule - await updateRule(supertest, { - ...getPrebuiltRuleMock(), - rule_id: 'rule-1', - type: 'saved_query', - query: undefined, - language: undefined, - filters: undefined, - saved_id: 'saved-query-id', - } as RuleUpdateProps); - - // Increment the version of the installed rule, update a type field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - type: 'esql', - language: 'esql', - }), - ]; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that one rule is eligible for update - // and type field update has NON_SOLVABLE conflict, and merged version is TARGET - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - expect(reviewResponse.rules[0].diff.fields.type).toEqual({ - base_version: 'query', - current_version: 'saved_query', - target_version: 'esql', - merged_version: 'esql', - diff_outcome: ThreeWayDiffOutcome.CustomizedValueCanUpdate, - merge_outcome: ThreeWayMergeOutcome.Target, - conflict: ThreeWayDiffConflict.NON_SOLVABLE, - has_update: true, - has_base_version: true, - }); - - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(4); // version + type + kql_query all considered updates - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(2); // type + kql_query both considered conflicts - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(2); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(1); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(1); - }); - }); - - describe('when rule base version does not exist', () => { - describe('when rule field has an update and a custom value that are the same - scenario -AA', () => { - it('should not show in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects()); - await installPrebuiltRules(es, supertest); - - // Clear previous rule assets - await deleteAllPrebuiltRuleAssets(es, log); - - // Increment the version of the installed rule, but keep type field unchanged - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - type: 'query', // unchanged - }), - ]; - await createPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that one rule is eligible for update - // but does NOT contain type field - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - expect(reviewResponse.rules[0].diff.fields.type).toBeUndefined(); - - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(1); - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(0); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(0); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(0); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(0); - }); - }); - - describe('when rule field has an update and a custom value that are different - scenario -AB', () => { - it('should show in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects()); - await installPrebuiltRules(es, supertest); - - // Clear previous rule assets - await deleteAllPrebuiltRuleAssets(es, log); - - // Customize a type field on the installed rule - await patchRule(supertest, log, { - rule_id: 'rule-1', - type: 'query', - }); - - // Increment the version of the installed rule, update a type field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - type: 'saved_query', - saved_id: 'saved-query-id', - }), - ]; - await createPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that one rule is eligible for update - // and type field update does have a non-solvable conflict - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - expect(reviewResponse.rules[0].diff.fields.type).toEqual({ - current_version: 'query', - target_version: 'saved_query', - merged_version: 'saved_query', - diff_outcome: ThreeWayDiffOutcome.MissingBaseCanUpdate, - merge_outcome: ThreeWayMergeOutcome.Target, - conflict: ThreeWayDiffConflict.NON_SOLVABLE, - has_update: true, - has_base_version: false, - }); - - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(3); - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(2); // type + query are all considered conflicts - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(1); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(1); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(1); - }); - }); - }); - }); - }); -}; diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/management/trial_license_complete_tier/upgrade_review_prebuilt_rules.scalar_array_fields.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/management/trial_license_complete_tier/upgrade_review_prebuilt_rules.scalar_array_fields.ts deleted file mode 100644 index 881e8e6122175..0000000000000 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/management/trial_license_complete_tier/upgrade_review_prebuilt_rules.scalar_array_fields.ts +++ /dev/null @@ -1,486 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ -import expect from 'expect'; -import { - ThreeWayDiffConflict, - ThreeWayDiffOutcome, - ThreeWayMergeOutcome, -} from '@kbn/security-solution-plugin/common/api/detection_engine'; -import { FtrProviderContext } from '../../../../../../ftr_provider_context'; -import { - deleteAllTimelines, - deleteAllPrebuiltRuleAssets, - createRuleAssetSavedObject, - installPrebuiltRules, - createPrebuiltRuleAssetSavedObjects, - reviewPrebuiltRulesToUpgrade, - patchRule, - createHistoricalPrebuiltRuleAssetSavedObjects, -} from '../../../../utils'; -import { deleteAllRules } from '../../../../../../../common/utils/security_solution'; - -export default ({ getService }: FtrProviderContext): void => { - const es = getService('es'); - const supertest = getService('supertest'); - const log = getService('log'); - - describe('@ess @serverless @skipInServerlessMKI review prebuilt rules updates from package with mock rule assets', () => { - beforeEach(async () => { - await deleteAllRules(supertest, log); - await deleteAllTimelines(es, log); - await deleteAllPrebuiltRuleAssets(es, log); - }); - - describe(`scalar array fields`, () => { - const getRuleAssetSavedObjects = () => [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 1, - tags: ['one', 'two', 'three'], - }), - ]; - - describe("when rule field doesn't have an update and has no custom value - scenario AAA", () => { - it('should not show in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects()); - await installPrebuiltRules(es, supertest); - - // Increment the version of the installed rule, do NOT update the related scalar array field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - tags: ['one', 'three', 'two'], - version: 2, - }), - ]; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that there is 1 rule eligable for update but scalar array field is NOT returned - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - expect(reviewResponse.rules[0].diff.fields.tags).toBeUndefined(); - - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(1); - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(0); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(0); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(0); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(0); - }); - }); - - describe("when rule field doesn't have an update but has a custom value - scenario ABA", () => { - it('should show in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects()); - await installPrebuiltRules(es, supertest); - - // Customize a scalar array field on the installed rule - await patchRule(supertest, log, { - rule_id: 'rule-1', - tags: ['one', 'two', 'four'], - }); - - // Increment the version of the installed rule, do NOT update the related scalar array field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - tags: ['one', 'two', 'three'], - version: 2, - }), - ]; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that scalar array diff field is returned but field does not have an update - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - expect(reviewResponse.rules[0].diff.fields.tags).toEqual({ - base_version: ['one', 'two', 'three'], - current_version: ['one', 'two', 'four'], - target_version: ['one', 'two', 'three'], - merged_version: ['one', 'two', 'four'], - diff_outcome: ThreeWayDiffOutcome.CustomizedValueNoUpdate, - merge_outcome: ThreeWayMergeOutcome.Current, - conflict: ThreeWayDiffConflict.NONE, - has_update: false, - has_base_version: true, - }); - - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(1); - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(0); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(0); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(0); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(0); - }); - }); - - describe('when rule field has an update but does not have a custom value - scenario AAB', () => { - it('should show in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects()); - await installPrebuiltRules(es, supertest); - - // Increment the version of the installed rule, update a scalar array field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - tags: ['one', 'two', 'four'], - }), - ]; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that one rule is eligible for update - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - expect(reviewResponse.rules[0].diff.fields.tags).toEqual({ - base_version: ['one', 'two', 'three'], - current_version: ['one', 'two', 'three'], - target_version: ['one', 'two', 'four'], - merged_version: ['one', 'two', 'four'], - diff_outcome: ThreeWayDiffOutcome.StockValueCanUpdate, - merge_outcome: ThreeWayMergeOutcome.Target, - conflict: ThreeWayDiffConflict.NONE, - has_update: true, - has_base_version: true, - }); - - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(2); - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(0); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(0); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(0); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(0); - }); - }); - - describe('when rule field has an update and a custom value that are the same - scenario ABB', () => { - it('should show in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects()); - await installPrebuiltRules(es, supertest); - - // Customize a scalar array field on the installed rule - await patchRule(supertest, log, { - rule_id: 'rule-1', - tags: ['one', 'two', 'four'], - }); - - // Increment the version of the installed rule, update a scalar array field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - tags: ['one', 'two', 'four'], - }), - ]; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that one rule is eligible for update and contains scalar array field - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - expect(reviewResponse.rules[0].diff.fields.tags).toEqual({ - base_version: ['one', 'two', 'three'], - current_version: ['one', 'two', 'four'], - target_version: ['one', 'two', 'four'], - merged_version: ['one', 'two', 'four'], - diff_outcome: ThreeWayDiffOutcome.CustomizedValueSameUpdate, - merge_outcome: ThreeWayMergeOutcome.Current, - conflict: ThreeWayDiffConflict.NONE, - has_update: false, - has_base_version: true, - }); - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(1); - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(0); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(0); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(0); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(0); - }); - }); - - describe('when rule field has an update and a custom value that are different - scenario ABC', () => { - it('should show in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects()); - await installPrebuiltRules(es, supertest); - - // Customize a scalar array field on the installed rule - await patchRule(supertest, log, { - rule_id: 'rule-1', - tags: ['one', 'two', 'four'], - }); - - // Increment the version of the installed rule, update a scalar array field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - tags: ['one', 'two', 'five'], - }), - ]; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that one rule is eligible for update - // and scalar array field update has conflict - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - expect(reviewResponse.rules[0].diff.fields.tags).toEqual({ - base_version: ['one', 'two', 'three'], - current_version: ['one', 'two', 'four'], - target_version: ['one', 'two', 'five'], - merged_version: ['one', 'two', 'four', 'five'], - diff_outcome: ThreeWayDiffOutcome.CustomizedValueCanUpdate, - merge_outcome: ThreeWayMergeOutcome.Merged, - conflict: ThreeWayDiffConflict.SOLVABLE, - has_update: true, - has_base_version: true, - }); - - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(2); - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(1); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(0); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(1); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(0); - }); - - it('should compare values after deduplication', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects(es, [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 1, - tags: ['one', 'two', 'two'], - }), - ]); - await installPrebuiltRules(es, supertest); - - // Customize a scalar array field on the installed rule - await patchRule(supertest, log, { - rule_id: 'rule-1', - tags: ['two', 'one', 'three'], - }); - - // Increment the version of the installed rule, update a scalar array field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - tags: ['three', 'three', 'one'], - }), - ]; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that one rule is eligible for update - // and scalar array field update has conflict - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - expect(reviewResponse.rules[0].diff.fields.tags).toEqual({ - base_version: ['one', 'two', 'two'], - current_version: ['two', 'one', 'three'], - target_version: ['three', 'three', 'one'], - merged_version: ['one', 'three'], - diff_outcome: ThreeWayDiffOutcome.CustomizedValueCanUpdate, - merge_outcome: ThreeWayMergeOutcome.Merged, - conflict: ThreeWayDiffConflict.SOLVABLE, - has_update: true, - has_base_version: true, - }); - - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(2); - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(1); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(0); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(1); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(0); - }); - - it('should compare values sensitive of case', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects(es, [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 1, - tags: ['ONE', 'TWO'], - }), - ]); - await installPrebuiltRules(es, supertest); - - // Customize a scalar array field on the installed rule - await patchRule(supertest, log, { - rule_id: 'rule-1', - tags: ['one', 'ONE'], - }); - - // Increment the version of the installed rule, update a scalar array field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - tags: ['ONE', 'THREE'], - }), - ]; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that one rule is eligible for update - // and scalar array field update has conflict - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - expect(reviewResponse.rules[0].diff.fields.tags).toEqual({ - base_version: ['ONE', 'TWO'], - current_version: ['one', 'ONE'], - target_version: ['ONE', 'THREE'], - merged_version: ['ONE', 'one', 'THREE'], - diff_outcome: ThreeWayDiffOutcome.CustomizedValueCanUpdate, - merge_outcome: ThreeWayMergeOutcome.Merged, - conflict: ThreeWayDiffConflict.SOLVABLE, - has_update: true, - has_base_version: true, - }); - - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(2); - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(1); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(0); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(1); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(0); - }); - - it('should handle empty arrays', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects()); - await installPrebuiltRules(es, supertest); - - // Customize a scalar array field on the installed rule - await patchRule(supertest, log, { - rule_id: 'rule-1', - tags: [], - }); - - // Increment the version of the installed rule, update a scalar array field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - tags: ['one', 'two', 'five'], - }), - ]; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that one rule is eligible for update - // and scalar array field update has conflict - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - expect(reviewResponse.rules[0].diff.fields.tags).toEqual({ - base_version: ['one', 'two', 'three'], - current_version: [], - target_version: ['one', 'two', 'five'], - merged_version: ['five'], - diff_outcome: ThreeWayDiffOutcome.CustomizedValueCanUpdate, - merge_outcome: ThreeWayMergeOutcome.Merged, - conflict: ThreeWayDiffConflict.SOLVABLE, - has_update: true, - has_base_version: true, - }); - - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(2); - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(1); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(0); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(1); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(0); - }); - }); - - describe('when rule base version does not exist', () => { - describe('when rule field has an update and a custom value that are the same - scenario -AA', () => { - it('should not show in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects()); - await installPrebuiltRules(es, supertest); - - // Clear previous rule assets - await deleteAllPrebuiltRuleAssets(es, log); - - // Increment the version of the installed rule, but keep scalar array field unchanged - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - tags: ['one', 'two', 'three'], // unchanged - }), - ]; - await createPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that one rule is eligible for update - // but does NOT contain scalar array field (tags is not present, since scenario -AA is not included in response) - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - expect(reviewResponse.rules[0].diff.fields.tags).toBeUndefined(); - - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(1); - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(0); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(0); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(0); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(0); - }); - }); - - describe('when rule field has an update and a custom value that are different - scenario -AB', () => { - it('should show in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects()); - await installPrebuiltRules(es, supertest); - - // Clear previous rule assets - await deleteAllPrebuiltRuleAssets(es, log); - - // Customize a scalar array field on the installed rule - await patchRule(supertest, log, { - rule_id: 'rule-1', - tags: ['one', 'two', 'four'], - }); - - // Increment the version of the installed rule, update a scalar array field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - tags: ['one', 'two', 'five'], - }), - ]; - await createPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that one rule is eligible for update - // and scalar array field update does not have a conflict - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - expect(reviewResponse.rules[0].diff.fields.tags).toEqual({ - current_version: ['one', 'two', 'four'], - target_version: ['one', 'two', 'five'], - merged_version: ['one', 'two', 'five'], - diff_outcome: ThreeWayDiffOutcome.MissingBaseCanUpdate, - merge_outcome: ThreeWayMergeOutcome.Target, - conflict: ThreeWayDiffConflict.SOLVABLE, - has_update: true, - has_base_version: false, - }); - - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(2); - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(1); // tags - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(0); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(1); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(0); - }); - }); - }); - }); - }); -}; diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/management/trial_license_complete_tier/upgrade_review_prebuilt_rules.single_line_string_fields.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/management/trial_license_complete_tier/upgrade_review_prebuilt_rules.single_line_string_fields.ts deleted file mode 100644 index 6d32d8df7bc72..0000000000000 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/management/trial_license_complete_tier/upgrade_review_prebuilt_rules.single_line_string_fields.ts +++ /dev/null @@ -1,375 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ -import expect from 'expect'; -import { - ThreeWayDiffConflict, - ThreeWayDiffOutcome, - ThreeWayMergeOutcome, -} from '@kbn/security-solution-plugin/common/api/detection_engine'; -import { FtrProviderContext } from '../../../../../../ftr_provider_context'; -import { - deleteAllTimelines, - deleteAllPrebuiltRuleAssets, - createRuleAssetSavedObject, - installPrebuiltRules, - createPrebuiltRuleAssetSavedObjects, - reviewPrebuiltRulesToUpgrade, - patchRule, - createHistoricalPrebuiltRuleAssetSavedObjects, -} from '../../../../utils'; -import { deleteAllRules } from '../../../../../../../common/utils/security_solution'; - -export default ({ getService }: FtrProviderContext): void => { - const es = getService('es'); - const supertest = getService('supertest'); - const log = getService('log'); - - describe('@ess @serverless @skipInServerlessMKI review prebuilt rules updates from package with mock rule assets', () => { - beforeEach(async () => { - await deleteAllRules(supertest, log); - await deleteAllTimelines(es, log); - await deleteAllPrebuiltRuleAssets(es, log); - }); - - describe(`single line string fields`, () => { - const getRuleAssetSavedObjects = () => [ - createRuleAssetSavedObject({ rule_id: 'rule-1', version: 1, name: 'A' }), - ]; - - describe("when rule field doesn't have an update and has no custom value - scenario AAA", () => { - it('should not show in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects()); - await installPrebuiltRules(es, supertest); - - // Increment the version of the installed rule, do NOT update the related single line string field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - name: 'A', - version: 2, - }), - ]; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that there is 1 rule eligible for update - // but single line string field (name) is NOT returned - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - expect(reviewResponse.rules[0].diff.fields.name).toBeUndefined(); - - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(1); - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(0); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(0); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(0); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(0); - }); - - it('should trim all whitespace before version comparison', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects()); - await installPrebuiltRules(es, supertest); - - // Customize a single line string field on the installed rule - await patchRule(supertest, log, { - rule_id: 'rule-1', - name: 'A\n', - }); - - // Increment the version of the installed rule, do NOT update the related single line string field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - name: '\nA', - version: 2, - }), - ]; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that there is 1 rule eligible for update - // but single line string field (name) is NOT returned - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - expect(reviewResponse.rules[0].diff.fields.name).toBeUndefined(); - - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(1); - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(0); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(0); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(0); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(0); - }); - }); - - describe("when rule field doesn't have an update but has a custom value - scenario ABA", () => { - it('should show in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects()); - await installPrebuiltRules(es, supertest); - - // Customize a single line string field on the installed rule - await patchRule(supertest, log, { - rule_id: 'rule-1', - name: 'B', - }); - - // Increment the version of the installed rule, do NOT update the related single line string field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - name: 'A', - version: 2, - }), - ]; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that single line string diff field - // is returned but field does not have an update, and the merge outcome is "Current" - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - expect(reviewResponse.rules[0].diff.fields.name).toEqual({ - base_version: 'A', - current_version: 'B', - target_version: 'A', - merged_version: 'B', - diff_outcome: ThreeWayDiffOutcome.CustomizedValueNoUpdate, - merge_outcome: ThreeWayMergeOutcome.Current, - conflict: ThreeWayDiffConflict.NONE, - has_update: false, - has_base_version: true, - }); - - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(1); - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(0); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(0); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(0); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(0); - }); - }); - - describe('when rule field has an update but does not have a custom value - scenario AAB', () => { - it('should show in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects()); - await installPrebuiltRules(es, supertest); - - // Increment the version of the installed rule, update a single line string field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - name: 'B', - }), - ]; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that one rule is eligible for update - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - expect(reviewResponse.rules[0].diff.fields.name).toEqual({ - base_version: 'A', - current_version: 'A', - target_version: 'B', - merged_version: 'B', - diff_outcome: ThreeWayDiffOutcome.StockValueCanUpdate, - merge_outcome: ThreeWayMergeOutcome.Target, - conflict: ThreeWayDiffConflict.NONE, - has_update: true, - has_base_version: true, - }); - - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(2); - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(0); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(0); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(0); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(0); - }); - }); - - describe('when rule field has an update and a custom value that are the same - scenario ABB', () => { - it('should show in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects()); - await installPrebuiltRules(es, supertest); - - // Customize a single line string field on the installed rule - await patchRule(supertest, log, { - rule_id: 'rule-1', - name: 'B', - }); - - // Increment the version of the installed rule, update a single line string field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - name: 'B', - }), - ]; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that one rule is eligible for update - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - expect(reviewResponse.rules[0].diff.fields.name).toEqual({ - base_version: 'A', - current_version: 'B', - target_version: 'B', - merged_version: 'B', - diff_outcome: ThreeWayDiffOutcome.CustomizedValueSameUpdate, - merge_outcome: ThreeWayMergeOutcome.Current, - conflict: ThreeWayDiffConflict.NONE, - has_update: false, - has_base_version: true, - }); - - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(1); - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(0); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(0); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(0); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(0); - }); - }); - - describe('when rule field has an update and a custom value that are different - scenario ABC', () => { - it('should show in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects()); - await installPrebuiltRules(es, supertest); - - // Customize a single line string field on the installed rule - await patchRule(supertest, log, { - rule_id: 'rule-1', - name: 'B', - }); - - // Increment the version of the installed rule, update a single line string field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - name: 'C', - }), - ]; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that one rule is eligible for update - // and single line string field update has NON_SOLVABLE conflict, and merged version is CURRENT - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - expect(reviewResponse.rules[0].diff.fields.name).toEqual({ - base_version: 'A', - current_version: 'B', - target_version: 'C', - merged_version: 'B', - diff_outcome: ThreeWayDiffOutcome.CustomizedValueCanUpdate, - merge_outcome: ThreeWayMergeOutcome.Current, - conflict: ThreeWayDiffConflict.NON_SOLVABLE, - has_update: true, - has_base_version: true, - }); - - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(2); - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(1); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(1); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(1); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(1); - }); - }); - - describe('when rule base version does not exist', () => { - describe('when rule field has an update and a custom value that are the same - scenario -AA', () => { - it('should not show in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects()); - await installPrebuiltRules(es, supertest); - - // Clear previous rule assets - await deleteAllPrebuiltRuleAssets(es, log); - - // Increment the version of the installed rule, but keep single line string field unchanged - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - name: 'A', // unchanged - }), - ]; - await createPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that one rule is eligible for update - // but does NOT contain single line string field - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - expect(reviewResponse.rules[0].diff.fields.name).toBeUndefined(); - - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(1); - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(0); - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(0); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(0); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(0); - }); - }); - - describe('when rule field has an update and a custom value that are different - scenario -AB', () => { - it('should show in the upgrade/_review API response', async () => { - // Install base prebuilt detection rule - await createPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects()); - await installPrebuiltRules(es, supertest); - - // Clear previous rule assets - await deleteAllPrebuiltRuleAssets(es, log); - - // Customize a single line string field on the installed rule - await patchRule(supertest, log, { - rule_id: 'rule-1', - name: 'B', - }); - - // Increment the version of the installed rule, update a single line string field, and create the new rule assets - const updatedRuleAssetSavedObjects = [ - createRuleAssetSavedObject({ - rule_id: 'rule-1', - version: 2, - name: 'C', - }), - ]; - await createPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - // Call the upgrade review prebuilt rules endpoint and check that one rule is eligible for update - // and single line string field update does not have a conflict - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - expect(reviewResponse.rules[0].diff.fields.name).toEqual({ - current_version: 'B', - target_version: 'C', - merged_version: 'C', - diff_outcome: ThreeWayDiffOutcome.MissingBaseCanUpdate, - merge_outcome: ThreeWayMergeOutcome.Target, - conflict: ThreeWayDiffConflict.SOLVABLE, - has_update: true, - has_base_version: false, - }); - - expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(2); - expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(1); // name is considered as a conflict - expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(0); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(1); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(0); - }); - }); - }); - }); - }); -}; diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/management/trial_license_complete_tier/upgrade_review_prebuilt_rules.stats.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/management/trial_license_complete_tier/upgrade_review_prebuilt_rules.stats.ts deleted file mode 100644 index 74010578da9f3..0000000000000 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/management/trial_license_complete_tier/upgrade_review_prebuilt_rules.stats.ts +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ -import expect from 'expect'; -import { FtrProviderContext } from '../../../../../../ftr_provider_context'; -import { - deleteAllTimelines, - deleteAllPrebuiltRuleAssets, - createRuleAssetSavedObject, - installPrebuiltRules, - // createPrebuiltRuleAssetSavedObjects, - reviewPrebuiltRulesToUpgrade, - // patchRule, - createHistoricalPrebuiltRuleAssetSavedObjects, - patchRule, -} from '../../../../utils'; -import { deleteAllRules } from '../../../../../../../common/utils/security_solution'; - -export default ({ getService }: FtrProviderContext): void => { - const es = getService('es'); - const supertest = getService('supertest'); - const log = getService('log'); - - describe('@ess @serverless @skipInServerlessMKI review prebuilt rules updates', () => { - beforeEach(async () => { - await deleteAllRules(supertest, log); - await deleteAllTimelines(es, log); - await deleteAllPrebuiltRuleAssets(es, log); - }); - - describe(`the endpoint stats -`, () => { - const getRuleAssetSavedObjects = () => [ - createRuleAssetSavedObject({ rule_id: 'rule-1', version: 1, name: 'A' }), - createRuleAssetSavedObject({ rule_id: 'rule-2', version: 1, name: 'A' }), - createRuleAssetSavedObject({ rule_id: 'rule-3', version: 1, name: 'A' }), - ]; - - it('should show how many rules have upgrades', async () => { - await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects()); - await installPrebuiltRules(es, supertest); - - const updatedRuleAssetSavedObjects = ['rule-1', 'rule-2', 'rule-3'].map((ruleId) => - createRuleAssetSavedObject({ - rule_id: ruleId, - name: 'A', - version: 2, - }) - ); - - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(3); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(0); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(0); - }); - - it('should show how many rules have updates with conflicts', async () => { - await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects()); - await installPrebuiltRules(es, supertest); - - // Customize a scalar array field on the installed rules to generate a solvable conflict - for (const ruleId of ['rule-1', 'rule-2', 'rule-3']) { - await patchRule(supertest, log, { - rule_id: ruleId, - tags: ['one', 'two', 'four'], - }); - } - - const updatedRuleAssetSavedObjects = ['rule-1', 'rule-2', 'rule-3'].map((ruleId) => - createRuleAssetSavedObject({ - rule_id: ruleId, - name: 'A', - version: 2, - tags: ['one', 'two', 'FOUR'], - }) - ); - - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(3); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(3); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(0); - }); - - it('should show how many rules have updates with non-solvable conflicts', async () => { - await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects()); - await installPrebuiltRules(es, supertest); - - // Customize a scalar array field on the installed rules to generate a solvable conflict - for (const ruleId of ['rule-1', 'rule-2', 'rule-3']) { - await patchRule(supertest, log, { - rule_id: ruleId, - tags: ['one', 'two', 'four'], - }); - } - - // Customize a single-line field on two installed rules to generate a non-solvable conflict - for (const ruleId of ['rule-2', 'rule-3']) { - await patchRule(supertest, log, { - rule_id: ruleId, - name: 'B', - }); - } - - const updatedRuleAssetSavedObjects = ['rule-1', 'rule-2', 'rule-3'].map((ruleId) => - createRuleAssetSavedObject({ - rule_id: ruleId, - name: 'C', - version: 2, - tags: ['one', 'two', 'FOUR'], - }) - ); - - await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects); - - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - - expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(3); - expect(reviewResponse.stats.num_rules_with_conflicts).toBe(3); - expect(reviewResponse.stats.num_rules_with_non_solvable_conflicts).toBe(2); - }); - }); - }); -}; diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/alert_suppression.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/alert_suppression.ts new file mode 100644 index 0000000000000..9b6fad04aeb71 --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/alert_suppression.ts @@ -0,0 +1,321 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { ThreeWayDiffOutcome } from '@kbn/security-solution-plugin/common/api/detection_engine'; +import { FtrProviderContext } from '../../../../../../../../ftr_provider_context'; +import type { TestFieldRuleUpgradeAssets } from '../test_helpers'; +import { + testFieldUpgradeReview, + testFieldUpgradesToMergedValue, + testFieldUpgradesToResolvedValue, +} from '../test_helpers'; + +export function alertSuppressionField({ getService }: FtrProviderContext): void { + describe('"alert_suppression"', () => { + describe('non-customized w/o an upgrade (AAA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + alert_suppression: { group_by: ['fieldA'] }, + }, + patch: {}, + upgrade: { + type: 'query', + alert_suppression: { group_by: ['fieldA'] }, + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'alert_suppression', + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueNoUpdate, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'alert_suppression', + resolvedValue: { group_by: ['fieldC'] }, + expectedFieldsAfterUpgrade: { alert_suppression: { group_by: ['fieldC'] } }, + }, + getService + ); + }); + + describe('non-customized w/ an upgrade (AAB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + alert_suppression: { group_by: ['fieldA'] }, + }, + patch: {}, + upgrade: { + type: 'query', + alert_suppression: { group_by: ['fieldB'] }, + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'alert_suppression', + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueCanUpdate, + expectedFieldDiffValues: { + base: { group_by: ['fieldA'] }, + current: { group_by: ['fieldA'] }, + target: { group_by: ['fieldB'] }, + merged: { group_by: ['fieldB'] }, + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'alert_suppression', + expectedFieldsAfterUpgrade: { alert_suppression: { group_by: ['fieldB'] } }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'alert_suppression', + resolvedValue: { group_by: ['fieldD'] }, + expectedFieldsAfterUpgrade: { alert_suppression: { group_by: ['fieldD'] } }, + }, + getService + ); + }); + + describe('customized w/o an upgrade (ABA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + alert_suppression: { group_by: ['fieldA'] }, + }, + patch: { + alert_suppression: { group_by: ['fieldB'] }, + }, + upgrade: { + type: 'query', + alert_suppression: { group_by: ['fieldA'] }, + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'alert_suppression', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueNoUpdate, + expectedFieldDiffValues: { + base: { group_by: ['fieldA'] }, + current: { group_by: ['fieldB'] }, + target: { group_by: ['fieldA'] }, + merged: { group_by: ['fieldB'] }, + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'alert_suppression', + expectedFieldsAfterUpgrade: { alert_suppression: { group_by: ['fieldB'] } }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'alert_suppression', + resolvedValue: { group_by: ['fieldD'] }, + expectedFieldsAfterUpgrade: { alert_suppression: { group_by: ['fieldD'] } }, + }, + getService + ); + }); + + describe('customized w/ the matching upgrade (ABB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + alert_suppression: { group_by: ['fieldA'] }, + }, + patch: { + alert_suppression: { group_by: ['fieldB'] }, + }, + upgrade: { + type: 'query', + alert_suppression: { group_by: ['fieldB'] }, + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'alert_suppression', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueSameUpdate, + expectedFieldDiffValues: { + base: { group_by: ['fieldA'] }, + current: { group_by: ['fieldB'] }, + target: { group_by: ['fieldB'] }, + merged: { group_by: ['fieldB'] }, + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'alert_suppression', + expectedFieldsAfterUpgrade: { alert_suppression: { group_by: ['fieldB'] } }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'alert_suppression', + resolvedValue: { group_by: ['fieldD'] }, + expectedFieldsAfterUpgrade: { alert_suppression: { group_by: ['fieldD'] } }, + }, + getService + ); + }); + + describe('customized w/ an upgrade resulting in a conflict (ABC diff case, non-solvable conflict)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + alert_suppression: { group_by: ['fieldA'] }, + }, + patch: { + alert_suppression: { group_by: ['fieldB'] }, + }, + upgrade: { + type: 'query', + alert_suppression: { group_by: ['fieldC'] }, + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'alert_suppression', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueCanUpdate, + isSolvableConflict: false, + expectedFieldDiffValues: { + base: { group_by: ['fieldA'] }, + current: { group_by: ['fieldB'] }, + target: { group_by: ['fieldC'] }, + merged: { group_by: ['fieldB'] }, + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'alert_suppression', + resolvedValue: { group_by: ['fieldD'] }, + expectedFieldsAfterUpgrade: { alert_suppression: { group_by: ['fieldD'] } }, + }, + getService + ); + }); + + describe('without historical versions', () => { + describe('customized w/ the matching upgrade (-AA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + alert_suppression: { group_by: ['fieldA'] }, + }, + patch: { + alert_suppression: { group_by: ['fieldB'] }, + }, + upgrade: { + type: 'query', + alert_suppression: { group_by: ['fieldB'] }, + }, + removeInstalledAssets: true, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'alert_suppression', + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseNoUpdate, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'alert_suppression', + resolvedValue: { group_by: ['fieldD'] }, + expectedFieldsAfterUpgrade: { alert_suppression: { group_by: ['fieldD'] } }, + }, + getService + ); + }); + + describe('customized w/ an upgrade (-AB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + alert_suppression: { group_by: ['fieldA'] }, + }, + patch: { + alert_suppression: { group_by: ['fieldB'] }, + }, + upgrade: { + type: 'query', + alert_suppression: { group_by: ['fieldC'] }, + }, + removeInstalledAssets: true, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'alert_suppression', + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseCanUpdate, + expectedFieldDiffValues: { + current: { group_by: ['fieldB'] }, + target: { group_by: ['fieldC'] }, + merged: { group_by: ['fieldC'] }, + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'alert_suppression', + resolvedValue: { group_by: ['fieldD'] }, + expectedFieldsAfterUpgrade: { alert_suppression: { group_by: ['fieldD'] } }, + }, + getService + ); + }); + }); + }); +} diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/building_block.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/building_block.ts new file mode 100644 index 0000000000000..a86153371dc28 --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/building_block.ts @@ -0,0 +1,321 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { ThreeWayDiffOutcome } from '@kbn/security-solution-plugin/common/api/detection_engine'; +import { FtrProviderContext } from '../../../../../../../../ftr_provider_context'; +import type { TestFieldRuleUpgradeAssets } from '../test_helpers'; +import { + testFieldUpgradeReview, + testFieldUpgradesToMergedValue, + testFieldUpgradesToResolvedValue, +} from '../test_helpers'; + +export function buildingBlockField({ getService }: FtrProviderContext): void { + describe('"building_block"', () => { + describe('non-customized w/o an upgrade (AAA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + building_block_type: 'default', + }, + patch: {}, + upgrade: { + type: 'query', + building_block_type: 'default', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'building_block', + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueNoUpdate, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'building_block', + resolvedValue: undefined, + expectedFieldsAfterUpgrade: { building_block_type: undefined }, + }, + getService + ); + }); + + describe('non-customized w/ an upgrade (AAB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + building_block_type: 'default', + }, + patch: {}, + upgrade: { + type: 'query', + building_block_type: undefined, + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'building_block', + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueCanUpdate, + expectedFieldDiffValues: { + base: { type: 'default' }, + current: { type: 'default' }, + target: undefined, + merged: undefined, + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'building_block', + expectedFieldsAfterUpgrade: { building_block_type: undefined }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'building_block', + resolvedValue: { type: 'resolved' }, + expectedFieldsAfterUpgrade: { building_block_type: 'resolved' }, + }, + getService + ); + }); + + describe('customized w/o an upgrade (ABA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + building_block_type: 'default', + }, + patch: { + building_block_type: '', + }, + upgrade: { + type: 'query', + building_block_type: 'default', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'building_block', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueNoUpdate, + expectedFieldDiffValues: { + base: { type: 'default' }, + current: undefined, + target: { type: 'default' }, + merged: undefined, + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'building_block', + expectedFieldsAfterUpgrade: { building_block_type: '' }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'building_block', + resolvedValue: { type: 'resolved' }, + expectedFieldsAfterUpgrade: { building_block_type: 'resolved' }, + }, + getService + ); + }); + + describe('customized w/ the matching upgrade (ABB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + building_block_type: 'default', + }, + patch: { + building_block_type: 'custom', + }, + upgrade: { + type: 'query', + building_block_type: 'custom', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'building_block', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueSameUpdate, + expectedFieldDiffValues: { + base: { type: 'default' }, + current: { type: 'custom' }, + target: { type: 'custom' }, + merged: { type: 'custom' }, + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'building_block', + expectedFieldsAfterUpgrade: { building_block_type: 'custom' }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'building_block', + resolvedValue: { type: 'resolved' }, + expectedFieldsAfterUpgrade: { building_block_type: 'resolved' }, + }, + getService + ); + }); + + describe('customized w/ an upgrade resulting in a conflict (ABC diff case, non-solvable conflict)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + building_block_type: 'default', + }, + patch: { + building_block_type: 'custom', + }, + upgrade: { + type: 'query', + building_block_type: undefined, + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'building_block', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueCanUpdate, + isSolvableConflict: false, + expectedFieldDiffValues: { + base: { type: 'default' }, + current: { type: 'custom' }, + target: undefined, + merged: { type: 'custom' }, + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'building_block', + resolvedValue: { type: 'resolved' }, + expectedFieldsAfterUpgrade: { building_block_type: 'resolved' }, + }, + getService + ); + }); + + describe('without historical versions', () => { + describe('customized w/ the matching upgrade (-AA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + building_block_type: 'default', + }, + patch: { + building_block_type: 'custom', + }, + upgrade: { + type: 'query', + building_block_type: 'custom', + }, + removeInstalledAssets: true, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'building_block', + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseNoUpdate, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'building_block', + resolvedValue: { type: 'resolved' }, + expectedFieldsAfterUpgrade: { building_block_type: 'resolved' }, + }, + getService + ); + }); + + describe('customized w/ an upgrade (-AB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + building_block_type: 'default', + }, + patch: { + building_block_type: 'custom', + }, + upgrade: { + type: 'query', + building_block_type: undefined, + }, + removeInstalledAssets: true, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'building_block', + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseCanUpdate, + expectedFieldDiffValues: { + current: { type: 'custom' }, + target: undefined, + merged: undefined, + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'building_block', + resolvedValue: { type: 'resolved' }, + expectedFieldsAfterUpgrade: { building_block_type: 'resolved' }, + }, + getService + ); + }); + }); + }); +} diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/configs/ess.config.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/configs/ess.config.ts new file mode 100644 index 0000000000000..944699b362cfe --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/configs/ess.config.ts @@ -0,0 +1,34 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile( + require.resolve('../../../../../../../../../config/ess/config.base.trial') + ); + + const testConfig = { + ...functionalConfig.getAll(), + testFiles: [require.resolve('..')], + junit: { + reportName: + 'Rules Management - Prebuilt Rule Customization Enabled Per Field Integration Tests - ESS Env', + }, + }; + testConfig.kbnTestServer.serverArgs = testConfig.kbnTestServer.serverArgs.map((arg: string) => { + // Override the default value of `--xpack.securitySolution.enableExperimental` to enable the prebuilt rules customization feature + if (arg.includes('--xpack.securitySolution.enableExperimental')) { + return `--xpack.securitySolution.enableExperimental=${JSON.stringify([ + 'prebuiltRulesCustomizationEnabled', + ])}`; + } + return arg; + }); + + return testConfig; +} diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/configs/serverless.config.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/configs/serverless.config.ts new file mode 100644 index 0000000000000..5fb299b71e58d --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/configs/serverless.config.ts @@ -0,0 +1,21 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { createTestConfig } from '../../../../../../../../../config/serverless/config.base'; + +export default createTestConfig({ + testFiles: [require.resolve('..')], + junit: { + reportName: + 'Rules Management - Prebuilt Rule Customization Enabled Per Field Integration Tests - Serverless Env', + }, + kbnTestServerArgs: [ + `--xpack.securitySolution.enableExperimental=${JSON.stringify([ + 'prebuiltRulesCustomizationEnabled', + ])}`, + ], +}); diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/data_source.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/data_source.ts new file mode 100644 index 0000000000000..e2890febe732a --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/data_source.ts @@ -0,0 +1,684 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { + DataSourceType, + ThreeWayDiffOutcome, +} from '@kbn/security-solution-plugin/common/api/detection_engine'; +import { FtrProviderContext } from '../../../../../../../../ftr_provider_context'; +import type { TestFieldRuleUpgradeAssets } from '../test_helpers'; +import { + testFieldUpgradeReview, + testFieldUpgradesToMergedValue, + testFieldUpgradesToResolvedValue, +} from '../test_helpers'; + +export function dataSourceField({ getService }: FtrProviderContext): void { + describe('"data_source" with index patterns', () => { + describe('non-customized w/o an upgrade (AAA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + index: ['indexA'], + }, + patch: {}, + upgrade: { + type: 'query', + index: ['indexA'], + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'data_source', + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueNoUpdate, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'data_source', + resolvedValue: { + type: DataSourceType.index_patterns, + index_patterns: ['indexResolved'], + }, + expectedFieldsAfterUpgrade: { index: ['indexResolved'] }, + }, + getService + ); + }); + + describe('non-customized w/ an upgrade (AAB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + index: ['indexA'], + }, + patch: {}, + upgrade: { + type: 'query', + index: ['indexB'], + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'data_source', + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueCanUpdate, + expectedFieldDiffValues: { + base: { type: DataSourceType.index_patterns, index_patterns: ['indexA'] }, + current: { type: DataSourceType.index_patterns, index_patterns: ['indexA'] }, + target: { type: DataSourceType.index_patterns, index_patterns: ['indexB'] }, + merged: { type: DataSourceType.index_patterns, index_patterns: ['indexB'] }, + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'data_source', + expectedFieldsAfterUpgrade: { index: ['indexB'] }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'data_source', + resolvedValue: { + type: DataSourceType.index_patterns, + index_patterns: ['indexResolved'], + }, + expectedFieldsAfterUpgrade: { index: ['indexResolved'] }, + }, + getService + ); + }); + + describe('customized w/o an upgrade (ABA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + index: ['indexA'], + }, + patch: { + index: ['indexB'], + }, + upgrade: { + type: 'query', + index: ['indexA'], + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'data_source', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueNoUpdate, + expectedFieldDiffValues: { + base: { type: DataSourceType.index_patterns, index_patterns: ['indexA'] }, + current: { type: DataSourceType.index_patterns, index_patterns: ['indexB'] }, + target: { type: DataSourceType.index_patterns, index_patterns: ['indexA'] }, + merged: { type: DataSourceType.index_patterns, index_patterns: ['indexB'] }, + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + + diffableRuleFieldName: 'data_source', + expectedFieldsAfterUpgrade: { index: ['indexB'] }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'data_source', + resolvedValue: { + type: DataSourceType.index_patterns, + index_patterns: ['indexResolved'], + }, + expectedFieldsAfterUpgrade: { index: ['indexResolved'] }, + }, + getService + ); + }); + + describe('customized w/ the matching upgrade (ABB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + index: ['indexA'], + }, + patch: { + index: ['indexB'], + }, + upgrade: { + type: 'query', + index: ['indexB'], + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'data_source', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueSameUpdate, + expectedFieldDiffValues: { + base: { type: DataSourceType.index_patterns, index_patterns: ['indexA'] }, + current: { type: DataSourceType.index_patterns, index_patterns: ['indexB'] }, + target: { type: DataSourceType.index_patterns, index_patterns: ['indexB'] }, + merged: { type: DataSourceType.index_patterns, index_patterns: ['indexB'] }, + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'data_source', + expectedFieldsAfterUpgrade: { index: ['indexB'] }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'data_source', + resolvedValue: { + type: DataSourceType.index_patterns, + index_patterns: ['indexResolved'], + }, + expectedFieldsAfterUpgrade: { index: ['indexResolved'] }, + }, + getService + ); + }); + + describe('customized w/ an upgrade resulting in a conflict (ABC diff case, solvable conflict)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + index: ['indexA'], + }, + patch: { + index: ['indexB'], + }, + upgrade: { + type: 'query', + index: ['indexA', 'indexC'], + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'data_source', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueCanUpdate, + isSolvableConflict: true, + expectedFieldDiffValues: { + base: { type: DataSourceType.index_patterns, index_patterns: ['indexA'] }, + current: { type: DataSourceType.index_patterns, index_patterns: ['indexB'] }, + target: { + type: DataSourceType.index_patterns, + index_patterns: ['indexA', 'indexC'], + }, + merged: { + type: DataSourceType.index_patterns, + index_patterns: ['indexB', 'indexC'], + }, + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'data_source', + resolvedValue: { + type: DataSourceType.index_patterns, + index_patterns: ['indexResolved'], + }, + expectedFieldsAfterUpgrade: { index: ['indexResolved'] }, + }, + getService + ); + }); + + describe('without historical versions', () => { + describe('customized w/ the matching upgrade (-AA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + index: ['indexA'], + }, + patch: { + index: ['indexB'], + }, + upgrade: { + type: 'query', + index: ['indexB'], + }, + removeInstalledAssets: true, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'data_source', + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseNoUpdate, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'data_source', + resolvedValue: { + type: DataSourceType.index_patterns, + index_patterns: ['indexResolved'], + }, + expectedFieldsAfterUpgrade: { index: ['indexResolved'] }, + }, + getService + ); + }); + + describe('customized w/ an upgrade (-AB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + index: ['indexA'], + }, + patch: { + index: ['indexB'], + }, + upgrade: { + type: 'query', + index: ['indexA', 'indexC'], + }, + removeInstalledAssets: true, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'data_source', + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseCanUpdate, + expectedFieldDiffValues: { + current: { type: DataSourceType.index_patterns, index_patterns: ['indexB'] }, + target: { + type: DataSourceType.index_patterns, + index_patterns: ['indexA', 'indexC'], + }, + merged: { + type: DataSourceType.index_patterns, + index_patterns: ['indexA', 'indexC'], + }, + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'data_source', + resolvedValue: { + type: DataSourceType.index_patterns, + index_patterns: ['indexResolved'], + }, + expectedFieldsAfterUpgrade: { index: ['indexResolved'] }, + }, + getService + ); + }); + }); + }); + + describe('"data_source" with data view', () => { + describe('non-customized w/o an upgrade (AAA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + data_view_id: 'dataViewA', + }, + patch: {}, + upgrade: { + type: 'query', + data_view_id: 'dataViewA', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'data_source', + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueNoUpdate, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'data_source', + resolvedValue: { + type: DataSourceType.data_view, + data_view_id: 'dataViewResolved', + }, + expectedFieldsAfterUpgrade: { data_view_id: 'dataViewResolved' }, + }, + getService + ); + }); + + describe('non-customized w/ an upgrade (AAB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + data_view_id: 'dataViewA', + }, + patch: {}, + upgrade: { + type: 'query', + data_view_id: 'dataViewB', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'data_source', + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueCanUpdate, + expectedFieldDiffValues: { + base: { type: DataSourceType.data_view, data_view_id: 'dataViewA' }, + current: { type: DataSourceType.data_view, data_view_id: 'dataViewA' }, + target: { type: DataSourceType.data_view, data_view_id: 'dataViewB' }, + merged: { type: DataSourceType.data_view, data_view_id: 'dataViewB' }, + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'data_source', + expectedFieldsAfterUpgrade: { data_view_id: 'dataViewB' }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'data_source', + resolvedValue: { + type: DataSourceType.data_view, + data_view_id: 'dataViewResolved', + }, + expectedFieldsAfterUpgrade: { data_view_id: 'dataViewResolved' }, + }, + getService + ); + }); + + describe('customized w/o an upgrade (ABA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + data_view_id: 'dataViewA', + }, + patch: { + data_view_id: 'dataViewB', + }, + upgrade: { + type: 'query', + data_view_id: 'dataViewA', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'data_source', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueNoUpdate, + expectedFieldDiffValues: { + base: { type: DataSourceType.data_view, data_view_id: 'dataViewA' }, + current: { type: DataSourceType.data_view, data_view_id: 'dataViewB' }, + target: { type: DataSourceType.data_view, data_view_id: 'dataViewA' }, + merged: { type: DataSourceType.data_view, data_view_id: 'dataViewB' }, + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + + diffableRuleFieldName: 'data_source', + expectedFieldsAfterUpgrade: { data_view_id: 'dataViewB' }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'data_source', + resolvedValue: { + type: DataSourceType.data_view, + data_view_id: 'dataViewResolved', + }, + expectedFieldsAfterUpgrade: { data_view_id: 'dataViewResolved' }, + }, + getService + ); + }); + + describe('customized w/ the matching upgrade (ABB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + data_view_id: 'dataViewA', + }, + patch: { + data_view_id: 'dataViewB', + }, + upgrade: { + type: 'query', + data_view_id: 'dataViewB', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'data_source', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueSameUpdate, + expectedFieldDiffValues: { + base: { type: DataSourceType.data_view, data_view_id: 'dataViewA' }, + current: { type: DataSourceType.data_view, data_view_id: 'dataViewB' }, + target: { type: DataSourceType.data_view, data_view_id: 'dataViewB' }, + merged: { type: DataSourceType.data_view, data_view_id: 'dataViewB' }, + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'data_source', + expectedFieldsAfterUpgrade: { data_view_id: 'dataViewB' }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'data_source', + resolvedValue: { + type: DataSourceType.data_view, + data_view_id: 'dataViewResolved', + }, + expectedFieldsAfterUpgrade: { data_view_id: 'dataViewResolved' }, + }, + getService + ); + }); + + describe('customized w/ an upgrade resulting in a conflict (ABC diff case, non-solvable conflict)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + data_view_id: 'dataViewA', + }, + patch: { + data_view_id: 'dataViewB', + }, + upgrade: { + type: 'query', + data_view_id: 'dataViewC', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'data_source', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueCanUpdate, + isSolvableConflict: false, + expectedFieldDiffValues: { + base: { type: DataSourceType.data_view, data_view_id: 'dataViewA' }, + current: { type: DataSourceType.data_view, data_view_id: 'dataViewB' }, + target: { type: DataSourceType.data_view, data_view_id: 'dataViewC' }, + merged: { type: DataSourceType.data_view, data_view_id: 'dataViewB' }, + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'data_source', + resolvedValue: { + type: DataSourceType.data_view, + data_view_id: 'dataViewResolved', + }, + expectedFieldsAfterUpgrade: { data_view_id: 'dataViewResolved' }, + }, + getService + ); + }); + + describe('without historical versions', () => { + describe('customized w/ the matching upgrade (-AA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + data_view_id: 'dataViewA', + }, + patch: { + data_view_id: 'dataViewB', + }, + upgrade: { + type: 'query', + data_view_id: 'dataViewB', + }, + removeInstalledAssets: true, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'data_source', + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseNoUpdate, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'data_source', + resolvedValue: { + type: DataSourceType.data_view, + data_view_id: 'dataViewResolved', + }, + expectedFieldsAfterUpgrade: { data_view_id: 'dataViewResolved' }, + }, + getService + ); + }); + + describe('customized w/ an upgrade (-AB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + data_view_id: 'dataViewA', + }, + patch: { + data_view_id: 'dataViewB', + }, + upgrade: { + type: 'query', + data_view_id: 'dataViewC', + }, + removeInstalledAssets: true, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'data_source', + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseCanUpdate, + expectedFieldDiffValues: { + current: { type: DataSourceType.data_view, data_view_id: 'dataViewB' }, + target: { type: DataSourceType.data_view, data_view_id: 'dataViewC' }, + merged: { type: DataSourceType.data_view, data_view_id: 'dataViewC' }, + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'data_source', + resolvedValue: { + type: DataSourceType.data_view, + data_view_id: 'dataViewResolved', + }, + expectedFieldsAfterUpgrade: { data_view_id: 'dataViewResolved' }, + }, + getService + ); + }); + }); + }); +} diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/description.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/description.ts new file mode 100644 index 0000000000000..3f06b6e6e8bbd --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/description.ts @@ -0,0 +1,332 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { ThreeWayDiffOutcome } from '@kbn/security-solution-plugin/common/api/detection_engine'; +import { FtrProviderContext } from '../../../../../../../../ftr_provider_context'; +import type { TestFieldRuleUpgradeAssets } from '../test_helpers'; +import { + testFieldUpgradeReview, + testFieldUpgradesToMergedValue, + testFieldUpgradesToResolvedValue, +} from '../test_helpers'; + +export function descriptionField({ getService }: FtrProviderContext): void { + describe('"description"', () => { + describe('non-customized w/o an upgrade (AAA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + description: 'Original description line 1\nOriginal description line 2', + }, + patch: {}, + upgrade: { + type: 'query', + description: 'Original description line 1\nOriginal description line 2', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'description', + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueNoUpdate, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'description', + resolvedValue: 'Resolved description', + expectedFieldsAfterUpgrade: { description: 'Resolved description' }, + }, + getService + ); + }); + + describe('non-customized w/ an upgrade (AAB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + description: 'Original description line 1\nOriginal description line 2', + }, + patch: {}, + upgrade: { + type: 'query', + description: 'Original description line 1\nOriginal description line 3', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'description', + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueCanUpdate, + expectedFieldDiffValues: { + base: 'Original description line 1\nOriginal description line 2', + current: 'Original description line 1\nOriginal description line 2', + target: 'Original description line 1\nOriginal description line 3', + merged: 'Original description line 1\nOriginal description line 3', + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'description', + expectedFieldsAfterUpgrade: { + description: 'Original description line 1\nOriginal description line 3', + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'description', + resolvedValue: 'Resolved description', + expectedFieldsAfterUpgrade: { description: 'Resolved description' }, + }, + getService + ); + }); + + describe('customized w/o an upgrade (ABA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + description: 'Original description line 1\nOriginal description line 2', + }, + patch: { + description: + 'Customized description\nOriginal description line 1\nOriginal description line 2', + }, + upgrade: { + type: 'query', + description: 'Original description line 1\nOriginal description line 2', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'description', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueNoUpdate, + expectedFieldDiffValues: { + base: 'Original description line 1\nOriginal description line 2', + current: + 'Customized description\nOriginal description line 1\nOriginal description line 2', + target: 'Original description line 1\nOriginal description line 2', + merged: + 'Customized description\nOriginal description line 1\nOriginal description line 2', + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'description', + expectedFieldsAfterUpgrade: { + description: + 'Customized description\nOriginal description line 1\nOriginal description line 2', + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'description', + resolvedValue: 'Resolved description', + expectedFieldsAfterUpgrade: { description: 'Resolved description' }, + }, + getService + ); + }); + + describe('customized w/ the matching upgrade (ABB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + description: 'Original description', + }, + patch: { + description: 'Updated description', + }, + upgrade: { + type: 'query', + description: 'Updated description', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'description', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueSameUpdate, + expectedFieldDiffValues: { + base: 'Original description', + current: 'Updated description', + target: 'Updated description', + merged: 'Updated description', + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'description', + expectedFieldsAfterUpgrade: { description: 'Updated description' }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'description', + resolvedValue: 'Resolved description', + expectedFieldsAfterUpgrade: { description: 'Resolved description' }, + }, + getService + ); + }); + + describe('customized w/ an upgrade resulting in a conflict (ABC diff case, solvable conflict)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + description: 'Original description line 1\nOriginal description line 2', + }, + patch: { + description: + 'Customized description\nOriginal description line 1\nOriginal description line 2', + }, + upgrade: { + type: 'query', + description: 'Original description line 1\nOriginal description line 3', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'description', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueCanUpdate, + isSolvableConflict: true, + expectedFieldDiffValues: { + base: 'Original description line 1\nOriginal description line 2', + current: + 'Customized description\nOriginal description line 1\nOriginal description line 2', + target: 'Original description line 1\nOriginal description line 3', + merged: + 'Customized description\nOriginal description line 1\nOriginal description line 3', + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'description', + resolvedValue: 'Resolved description', + expectedFieldsAfterUpgrade: { description: 'Resolved description' }, + }, + getService + ); + }); + + describe('without historical versions', () => { + describe('customized w/ the matching upgrade (-AA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + description: 'Original description', + }, + patch: { + description: 'Updated description', + }, + upgrade: { + type: 'query', + description: 'Updated description', + }, + removeInstalledAssets: true, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'description', + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseNoUpdate, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'description', + resolvedValue: 'Resolved description', + expectedFieldsAfterUpgrade: { description: 'Resolved description' }, + }, + getService + ); + }); + + describe('customized w/ an upgrade (-AB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + description: 'Original description', + }, + patch: { + description: 'Customized description', + }, + upgrade: { + type: 'query', + description: 'Updated description', + }, + removeInstalledAssets: true, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'description', + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseCanUpdate, + expectedFieldDiffValues: { + current: 'Customized description', + target: 'Updated description', + merged: 'Updated description', + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'description', + resolvedValue: 'Resolved description', + expectedFieldsAfterUpgrade: { description: 'Resolved description' }, + }, + getService + ); + }); + }); + }); +} diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/false_positives.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/false_positives.ts new file mode 100644 index 0000000000000..74ff45fae6b3e --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/false_positives.ts @@ -0,0 +1,321 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { ThreeWayDiffOutcome } from '@kbn/security-solution-plugin/common/api/detection_engine'; +import { FtrProviderContext } from '../../../../../../../../ftr_provider_context'; +import type { TestFieldRuleUpgradeAssets } from '../test_helpers'; +import { + testFieldUpgradeReview, + testFieldUpgradesToMergedValue, + testFieldUpgradesToResolvedValue, +} from '../test_helpers'; + +export function falsePositivesField({ getService }: FtrProviderContext): void { + describe('"false_positives"', () => { + describe('non-customized w/o an upgrade (AAA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + false_positives: ['example1'], + }, + patch: {}, + upgrade: { + type: 'query', + false_positives: ['example1'], + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'false_positives', + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueNoUpdate, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'false_positives', + resolvedValue: ['resolved'], + expectedFieldsAfterUpgrade: { false_positives: ['resolved'] }, + }, + getService + ); + }); + + describe('non-customized w/ an upgrade (AAB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + false_positives: ['example1'], + }, + patch: {}, + upgrade: { + type: 'query', + false_positives: ['example2'], + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'false_positives', + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueCanUpdate, + expectedFieldDiffValues: { + base: ['example1'], + current: ['example1'], + target: ['example2'], + merged: ['example2'], + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'false_positives', + expectedFieldsAfterUpgrade: { false_positives: ['example2'] }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'false_positives', + resolvedValue: ['resolved'], + expectedFieldsAfterUpgrade: { false_positives: ['resolved'] }, + }, + getService + ); + }); + + describe('customized w/o an upgrade (ABA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + false_positives: ['example1'], + }, + patch: { + false_positives: ['example3'], + }, + upgrade: { + type: 'query', + false_positives: ['example1'], + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'false_positives', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueNoUpdate, + expectedFieldDiffValues: { + base: ['example1'], + current: ['example3'], + target: ['example1'], + merged: ['example3'], + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'false_positives', + expectedFieldsAfterUpgrade: { false_positives: ['example3'] }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'false_positives', + resolvedValue: ['resolved'], + expectedFieldsAfterUpgrade: { false_positives: ['resolved'] }, + }, + getService + ); + }); + + describe('customized w/ the matching upgrade (ABB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + false_positives: ['example1'], + }, + patch: { + false_positives: ['example2'], + }, + upgrade: { + type: 'query', + false_positives: ['example2'], + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'false_positives', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueSameUpdate, + expectedFieldDiffValues: { + base: ['example1'], + current: ['example2'], + target: ['example2'], + merged: ['example2'], + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'false_positives', + expectedFieldsAfterUpgrade: { false_positives: ['example2'] }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'false_positives', + resolvedValue: ['resolved'], + expectedFieldsAfterUpgrade: { false_positives: ['resolved'] }, + }, + getService + ); + }); + + describe('customized w/ an upgrade resulting in a conflict (ABC diff case, non-solvable conflict)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + false_positives: ['example1'], + }, + patch: { + false_positives: ['example2'], + }, + upgrade: { + type: 'query', + false_positives: ['example3'], + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'false_positives', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueCanUpdate, + isSolvableConflict: false, + expectedFieldDiffValues: { + base: ['example1'], + current: ['example2'], + target: ['example3'], + merged: ['example2'], + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'false_positives', + resolvedValue: ['resolved'], + expectedFieldsAfterUpgrade: { false_positives: ['resolved'] }, + }, + getService + ); + }); + + describe('without historical versions', () => { + describe('customized w/ the matching upgrade (-AA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + false_positives: ['example1'], + }, + patch: { + false_positives: ['example2'], + }, + upgrade: { + type: 'query', + false_positives: ['example2'], + }, + removeInstalledAssets: true, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'false_positives', + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseNoUpdate, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'false_positives', + resolvedValue: ['resolved'], + expectedFieldsAfterUpgrade: { false_positives: ['resolved'] }, + }, + getService + ); + }); + + describe('customized w/ an upgrade (-AB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + false_positives: ['example1'], + }, + patch: { + false_positives: ['example2'], + }, + upgrade: { + type: 'query', + false_positives: ['example3'], + }, + removeInstalledAssets: true, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'false_positives', + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseCanUpdate, + expectedFieldDiffValues: { + current: ['example2'], + target: ['example3'], + merged: ['example3'], + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'false_positives', + resolvedValue: ['resolved'], + expectedFieldsAfterUpgrade: { false_positives: ['resolved'] }, + }, + getService + ); + }); + }); + }); +} diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/index.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/index.ts new file mode 100644 index 0000000000000..3e99193009a62 --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/index.ts @@ -0,0 +1,71 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrProviderContext } from '../../../../../../../../ftr_provider_context'; +import { deleteAllPrebuiltRuleAssets } from '../../../../../../utils'; +import { deleteAllRules } from '../../../../../../../../../common/utils/security_solution'; +import { nameField } from './name'; +import { descriptionField } from './description'; +import { tagsField } from './tags'; +import { severityField } from './severity'; +import { severityMappingField } from './severity_mapping'; +import { riskScoreField } from './risk_score'; +import { riskScoreMappingField } from './risk_score_mapping'; +import { referencesField } from './references'; +import { falsePositivesField } from './false_positives'; +import { threatField } from './threat'; +import { noteField } from './note'; +import { setupField } from './setup'; +import { relatedIntegrationsField } from './related_integrations'; +import { requiredFieldsField } from './required_fields'; +import { ruleScheduleField } from './rule_schedule'; +import { maxSignalsField } from './max_signals'; +import { ruleNameOverrideField } from './rule_name_override'; +import { timestampOverrideField } from './timestamp_override'; +import { timelineTemplateField } from './timeline_template'; +import { buildingBlockField } from './building_block'; +import { investigationFieldsField } from './investigation_fields'; +import { dataSourceField } from './data_source'; +import { alertSuppressionField } from './alert_suppression'; + +export default (context: FtrProviderContext): void => { + const es = context.getService('es'); + const supertest = context.getService('supertest'); + const log = context.getService('log'); + + describe('@ess @serverless @skipInServerlessMKI common diffable rule fields', () => { + beforeEach(async () => { + await deleteAllRules(supertest, log); + await deleteAllPrebuiltRuleAssets(es, log); + }); + + // Common fields + nameField(context); + descriptionField(context); + tagsField(context); + severityField(context); + severityMappingField(context); + riskScoreField(context); + riskScoreMappingField(context); + referencesField(context); + falsePositivesField(context); + threatField(context); + noteField(context); + setupField(context); + relatedIntegrationsField(context); + requiredFieldsField(context); + ruleScheduleField(context); + maxSignalsField(context); + ruleNameOverrideField(context); + timestampOverrideField(context); + timelineTemplateField(context); + buildingBlockField(context); + investigationFieldsField(context); + dataSourceField(context); + alertSuppressionField(context); + }); +}; diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/investigation_fields.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/investigation_fields.ts new file mode 100644 index 0000000000000..afed997049eb6 --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/investigation_fields.ts @@ -0,0 +1,321 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { ThreeWayDiffOutcome } from '@kbn/security-solution-plugin/common/api/detection_engine'; +import { FtrProviderContext } from '../../../../../../../../ftr_provider_context'; +import type { TestFieldRuleUpgradeAssets } from '../test_helpers'; +import { + testFieldUpgradeReview, + testFieldUpgradesToMergedValue, + testFieldUpgradesToResolvedValue, +} from '../test_helpers'; + +export function investigationFieldsField({ getService }: FtrProviderContext): void { + describe('"investigation_fields"', () => { + describe('non-customized w/o an upgrade (AAA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + investigation_fields: { field_names: ['fieldA'] }, + }, + patch: {}, + upgrade: { + type: 'query', + investigation_fields: { field_names: ['fieldA'] }, + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'investigation_fields', + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueNoUpdate, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'investigation_fields', + resolvedValue: { field_names: ['resolved'] }, + expectedFieldsAfterUpgrade: { investigation_fields: { field_names: ['resolved'] } }, + }, + getService + ); + }); + + describe('non-customized w/ an upgrade (AAB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + investigation_fields: { field_names: ['fieldA'] }, + }, + patch: {}, + upgrade: { + type: 'query', + investigation_fields: { field_names: ['fieldB'] }, + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'investigation_fields', + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueCanUpdate, + expectedFieldDiffValues: { + base: { field_names: ['fieldA'] }, + current: { field_names: ['fieldA'] }, + target: { field_names: ['fieldB'] }, + merged: { field_names: ['fieldB'] }, + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'investigation_fields', + expectedFieldsAfterUpgrade: { investigation_fields: { field_names: ['fieldB'] } }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'investigation_fields', + resolvedValue: { field_names: ['resolved'] }, + expectedFieldsAfterUpgrade: { investigation_fields: { field_names: ['resolved'] } }, + }, + getService + ); + }); + + describe('customized w/o an upgrade (ABA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + investigation_fields: { field_names: ['fieldA'] }, + }, + patch: { + investigation_fields: { field_names: ['fieldB'] }, + }, + upgrade: { + type: 'query', + investigation_fields: { field_names: ['fieldA'] }, + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'investigation_fields', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueNoUpdate, + expectedFieldDiffValues: { + base: { field_names: ['fieldA'] }, + current: { field_names: ['fieldB'] }, + target: { field_names: ['fieldA'] }, + merged: { field_names: ['fieldB'] }, + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'investigation_fields', + expectedFieldsAfterUpgrade: { investigation_fields: { field_names: ['fieldB'] } }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'investigation_fields', + resolvedValue: { field_names: ['resolved'] }, + expectedFieldsAfterUpgrade: { investigation_fields: { field_names: ['resolved'] } }, + }, + getService + ); + }); + + describe('customized w/ the matching upgrade (ABB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + investigation_fields: { field_names: ['fieldA'] }, + }, + patch: { + investigation_fields: { field_names: ['fieldB'] }, + }, + upgrade: { + type: 'query', + investigation_fields: { field_names: ['fieldB'] }, + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'investigation_fields', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueSameUpdate, + expectedFieldDiffValues: { + base: { field_names: ['fieldA'] }, + current: { field_names: ['fieldB'] }, + target: { field_names: ['fieldB'] }, + merged: { field_names: ['fieldB'] }, + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'investigation_fields', + expectedFieldsAfterUpgrade: { investigation_fields: { field_names: ['fieldB'] } }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'investigation_fields', + resolvedValue: { field_names: ['resolved'] }, + expectedFieldsAfterUpgrade: { investigation_fields: { field_names: ['resolved'] } }, + }, + getService + ); + }); + + describe('customized w/ an upgrade resulting in a conflict (ABC diff case, non-solvable conflict)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + investigation_fields: { field_names: ['fieldA'] }, + }, + patch: { + investigation_fields: { field_names: ['fieldB'] }, + }, + upgrade: { + type: 'query', + investigation_fields: { field_names: ['fieldC'] }, + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'investigation_fields', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueCanUpdate, + isSolvableConflict: false, + expectedFieldDiffValues: { + base: { field_names: ['fieldA'] }, + current: { field_names: ['fieldB'] }, + target: { field_names: ['fieldC'] }, + merged: { field_names: ['fieldB'] }, + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'investigation_fields', + resolvedValue: { field_names: ['resolved'] }, + expectedFieldsAfterUpgrade: { investigation_fields: { field_names: ['resolved'] } }, + }, + getService + ); + }); + + describe('without historical versions', () => { + describe('customized w/ the matching upgrade (-AA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + investigation_fields: { field_names: ['fieldA'] }, + }, + patch: { + investigation_fields: { field_names: ['fieldB'] }, + }, + upgrade: { + type: 'query', + investigation_fields: { field_names: ['fieldB'] }, + }, + removeInstalledAssets: true, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'investigation_fields', + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseNoUpdate, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'investigation_fields', + resolvedValue: { field_names: ['resolved'] }, + expectedFieldsAfterUpgrade: { investigation_fields: { field_names: ['resolved'] } }, + }, + getService + ); + }); + + describe('customized w/ an upgrade (-AB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + investigation_fields: { field_names: ['fieldA'] }, + }, + patch: { + investigation_fields: { field_names: ['fieldB'] }, + }, + upgrade: { + type: 'query', + investigation_fields: { field_names: ['fieldC'] }, + }, + removeInstalledAssets: true, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'investigation_fields', + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseCanUpdate, + expectedFieldDiffValues: { + current: { field_names: ['fieldB'] }, + target: { field_names: ['fieldC'] }, + merged: { field_names: ['fieldC'] }, + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'investigation_fields', + resolvedValue: { field_names: ['resolved'] }, + expectedFieldsAfterUpgrade: { investigation_fields: { field_names: ['resolved'] } }, + }, + getService + ); + }); + }); + }); +} diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/max_signals.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/max_signals.ts new file mode 100644 index 0000000000000..122b00022b47e --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/max_signals.ts @@ -0,0 +1,321 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { ThreeWayDiffOutcome } from '@kbn/security-solution-plugin/common/api/detection_engine'; +import { FtrProviderContext } from '../../../../../../../../ftr_provider_context'; +import type { TestFieldRuleUpgradeAssets } from '../test_helpers'; +import { + testFieldUpgradeReview, + testFieldUpgradesToMergedValue, + testFieldUpgradesToResolvedValue, +} from '../test_helpers'; + +export function maxSignalsField({ getService }: FtrProviderContext): void { + describe('"max_signals"', () => { + describe('non-customized w/o an upgrade (AAA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + max_signals: 100, + }, + patch: {}, + upgrade: { + type: 'query', + max_signals: 100, + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'max_signals', + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueNoUpdate, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'max_signals', + resolvedValue: 50, + expectedFieldsAfterUpgrade: { max_signals: 50 }, + }, + getService + ); + }); + + describe('non-customized w/ an upgrade (AAB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + max_signals: 100, + }, + patch: {}, + upgrade: { + type: 'query', + max_signals: 150, + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'max_signals', + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueCanUpdate, + expectedFieldDiffValues: { + base: 100, + current: 100, + target: 150, + merged: 150, + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'max_signals', + expectedFieldsAfterUpgrade: { max_signals: 150 }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'max_signals', + resolvedValue: 50, + expectedFieldsAfterUpgrade: { max_signals: 50 }, + }, + getService + ); + }); + + describe('customized w/o an upgrade (ABA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + max_signals: 100, + }, + patch: { + max_signals: 130, + }, + upgrade: { + type: 'query', + max_signals: 100, + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'max_signals', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueNoUpdate, + expectedFieldDiffValues: { + base: 100, + current: 130, + target: 100, + merged: 130, + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'max_signals', + expectedFieldsAfterUpgrade: { max_signals: 130 }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'max_signals', + resolvedValue: 50, + expectedFieldsAfterUpgrade: { max_signals: 50 }, + }, + getService + ); + }); + + describe('customized w/ the matching upgrade (ABB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + max_signals: 100, + }, + patch: { + max_signals: 130, + }, + upgrade: { + type: 'query', + max_signals: 130, + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'max_signals', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueSameUpdate, + expectedFieldDiffValues: { + base: 100, + current: 130, + target: 130, + merged: 130, + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'max_signals', + expectedFieldsAfterUpgrade: { max_signals: 130 }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'max_signals', + resolvedValue: 50, + expectedFieldsAfterUpgrade: { max_signals: 50 }, + }, + getService + ); + }); + + describe('customized w/ an upgrade resulting in a conflict (ABC diff case, non-solvable conflict)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + max_signals: 100, + }, + patch: { + max_signals: 130, + }, + upgrade: { + type: 'query', + max_signals: 150, + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'max_signals', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueCanUpdate, + isSolvableConflict: false, + expectedFieldDiffValues: { + base: 100, + current: 130, + target: 150, + merged: 130, + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'max_signals', + resolvedValue: 50, + expectedFieldsAfterUpgrade: { max_signals: 50 }, + }, + getService + ); + }); + + describe('without historical versions', () => { + describe('customized w/ the matching upgrade (-AA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + max_signals: 100, + }, + patch: { + max_signals: 130, + }, + upgrade: { + type: 'query', + max_signals: 130, + }, + removeInstalledAssets: true, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'max_signals', + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseNoUpdate, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'max_signals', + resolvedValue: 50, + expectedFieldsAfterUpgrade: { max_signals: 50 }, + }, + getService + ); + }); + + describe('customized w/ an upgrade (-AB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + max_signals: 100, + }, + patch: { + max_signals: 130, + }, + upgrade: { + type: 'query', + max_signals: 150, + }, + removeInstalledAssets: true, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'max_signals', + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseCanUpdate, + expectedFieldDiffValues: { + current: 130, + target: 150, + merged: 150, + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'max_signals', + resolvedValue: 50, + expectedFieldsAfterUpgrade: { max_signals: 50 }, + }, + getService + ); + }); + }); + }); +} diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/name.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/name.ts new file mode 100644 index 0000000000000..1030d8f774784 --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/name.ts @@ -0,0 +1,321 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { ThreeWayDiffOutcome } from '@kbn/security-solution-plugin/common/api/detection_engine'; +import { FtrProviderContext } from '../../../../../../../../ftr_provider_context'; +import type { TestFieldRuleUpgradeAssets } from '../test_helpers'; +import { + testFieldUpgradeReview, + testFieldUpgradesToMergedValue, + testFieldUpgradesToResolvedValue, +} from '../test_helpers'; + +export function nameField({ getService }: FtrProviderContext): void { + describe('"name"', () => { + describe('non-customized w/o an upgrade (AAA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + name: 'Original name', + }, + patch: {}, + upgrade: { + type: 'query', + name: 'Original name', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'name', + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueNoUpdate, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'name', + resolvedValue: 'Resolved name', + expectedFieldsAfterUpgrade: { name: 'Resolved name' }, + }, + getService + ); + }); + + describe('non-customized w/ an upgrade (AAB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + name: 'Original name', + }, + patch: {}, + upgrade: { + type: 'query', + name: 'Updated name', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'name', + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueCanUpdate, + expectedFieldDiffValues: { + base: 'Original name', + current: 'Original name', + target: 'Updated name', + merged: 'Updated name', + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'name', + expectedFieldsAfterUpgrade: { name: 'Updated name' }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'name', + resolvedValue: 'Resolved name', + expectedFieldsAfterUpgrade: { name: 'Resolved name' }, + }, + getService + ); + }); + + describe('customized w/o an upgrade (ABA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + name: 'Original name', + }, + patch: { + name: 'Customized name', + }, + upgrade: { + type: 'query', + name: 'Original name', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'name', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueNoUpdate, + expectedFieldDiffValues: { + base: 'Original name', + current: 'Customized name', + target: 'Original name', + merged: 'Customized name', + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'name', + expectedFieldsAfterUpgrade: { name: 'Customized name' }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'name', + resolvedValue: 'Resolved name', + expectedFieldsAfterUpgrade: { name: 'Resolved name' }, + }, + getService + ); + }); + + describe('customized w/ the matching upgrade (ABB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + name: 'Original name', + }, + patch: { + name: 'Updated name', + }, + upgrade: { + type: 'query', + name: 'Updated name', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'name', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueSameUpdate, + expectedFieldDiffValues: { + base: 'Original name', + current: 'Updated name', + target: 'Updated name', + merged: 'Updated name', + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'name', + expectedFieldsAfterUpgrade: { name: 'Updated name' }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'name', + resolvedValue: 'Resolved name', + expectedFieldsAfterUpgrade: { name: 'Resolved name' }, + }, + getService + ); + }); + + describe('customized w/ an upgrade resulting in a conflict (ABC diff case, non-solvable conflict)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + name: 'Original name', + }, + patch: { + name: 'Customized name', + }, + upgrade: { + type: 'query', + name: 'Updated name', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'name', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueCanUpdate, + isSolvableConflict: false, + expectedFieldDiffValues: { + base: 'Original name', + current: 'Customized name', + target: 'Updated name', + merged: 'Customized name', + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'name', + resolvedValue: 'Resolved name', + expectedFieldsAfterUpgrade: { name: 'Resolved name' }, + }, + getService + ); + }); + + describe('without historical versions', () => { + describe('customized w/ the matching upgrade (-AA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + name: 'Original name', + }, + patch: { + name: 'Updated name', + }, + upgrade: { + type: 'query', + name: 'Updated name', + }, + removeInstalledAssets: true, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'name', + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseNoUpdate, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'name', + resolvedValue: 'Resolved name', + expectedFieldsAfterUpgrade: { name: 'Resolved name' }, + }, + getService + ); + }); + + describe('customized w/ an upgrade (-AB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + name: 'Original name', + }, + patch: { + name: 'Customized name', + }, + upgrade: { + type: 'query', + name: 'Updated name', + }, + removeInstalledAssets: true, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'name', + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseCanUpdate, + expectedFieldDiffValues: { + current: 'Customized name', + target: 'Updated name', + merged: 'Updated name', + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'name', + resolvedValue: 'Resolved name', + expectedFieldsAfterUpgrade: { name: 'Resolved name' }, + }, + getService + ); + }); + }); + }); +} diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/note.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/note.ts new file mode 100644 index 0000000000000..5b7f1df6834b0 --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/note.ts @@ -0,0 +1,321 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { ThreeWayDiffOutcome } from '@kbn/security-solution-plugin/common/api/detection_engine'; +import { FtrProviderContext } from '../../../../../../../../ftr_provider_context'; +import type { TestFieldRuleUpgradeAssets } from '../test_helpers'; +import { + testFieldUpgradeReview, + testFieldUpgradesToMergedValue, + testFieldUpgradesToResolvedValue, +} from '../test_helpers'; + +export function noteField({ getService }: FtrProviderContext): void { + describe('"note"', () => { + describe('non-customized w/o an upgrade (AAA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + note: 'some note', + }, + patch: {}, + upgrade: { + type: 'query', + note: 'some note', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'note', + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueNoUpdate, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'note', + resolvedValue: 'Resolved note', + expectedFieldsAfterUpgrade: { note: 'Resolved note' }, + }, + getService + ); + }); + + describe('non-customized w/ an upgrade (AAB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + note: 'some note', + }, + patch: {}, + upgrade: { + type: 'query', + note: 'updated note', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'note', + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueCanUpdate, + expectedFieldDiffValues: { + base: 'some note', + current: 'some note', + target: 'updated note', + merged: 'updated note', + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'note', + expectedFieldsAfterUpgrade: { note: 'updated note' }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'note', + resolvedValue: 'Resolved note', + expectedFieldsAfterUpgrade: { note: 'Resolved note' }, + }, + getService + ); + }); + + describe('customized w/o an upgrade (ABA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + note: 'some note', + }, + patch: { + note: 'customized note', + }, + upgrade: { + type: 'query', + note: 'some note', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'note', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueNoUpdate, + expectedFieldDiffValues: { + base: 'some note', + current: 'customized note', + target: 'some note', + merged: 'customized note', + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'note', + expectedFieldsAfterUpgrade: { note: 'customized note' }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'note', + resolvedValue: 'Resolved note', + expectedFieldsAfterUpgrade: { note: 'Resolved note' }, + }, + getService + ); + }); + + describe('customized w/ the matching upgrade (ABB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + note: 'some note', + }, + patch: { + note: 'updated note', + }, + upgrade: { + type: 'query', + note: 'updated note', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'note', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueSameUpdate, + expectedFieldDiffValues: { + base: 'some note', + current: 'updated note', + target: 'updated note', + merged: 'updated note', + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'note', + expectedFieldsAfterUpgrade: { note: 'updated note' }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'note', + resolvedValue: 'Resolved note', + expectedFieldsAfterUpgrade: { note: 'Resolved note' }, + }, + getService + ); + }); + + describe('customized w/ an upgrade resulting in a conflict (ABC diff case, solvable conflict)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + note: 'line 1\nline 2', + }, + patch: { + note: 'Customized line\nline 1\nline 2', + }, + upgrade: { + type: 'query', + note: 'line 1\nline 3', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'note', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueCanUpdate, + isSolvableConflict: true, + expectedFieldDiffValues: { + base: 'line 1\nline 2', + current: 'Customized line\nline 1\nline 2', + target: 'line 1\nline 3', + merged: 'Customized line\nline 1\nline 3', + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'note', + resolvedValue: 'Resolved note', + expectedFieldsAfterUpgrade: { note: 'Resolved note' }, + }, + getService + ); + }); + + describe('without historical versions', () => { + describe('customized w/ the matching upgrade (-AA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + note: 'some note', + }, + patch: { + note: 'updated note', + }, + upgrade: { + type: 'query', + note: 'updated note', + }, + removeInstalledAssets: true, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'note', + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseNoUpdate, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'note', + resolvedValue: 'Resolved note', + expectedFieldsAfterUpgrade: { note: 'Resolved note' }, + }, + getService + ); + }); + + describe('customized w/ an upgrade (-AB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + note: 'some note', + }, + patch: { + note: 'customized note', + }, + upgrade: { + type: 'query', + note: 'updated note', + }, + removeInstalledAssets: true, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'note', + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseCanUpdate, + expectedFieldDiffValues: { + current: 'customized note', + target: 'updated note', + merged: 'updated note', + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'note', + resolvedValue: 'Resolved note', + expectedFieldsAfterUpgrade: { note: 'Resolved note' }, + }, + getService + ); + }); + }); + }); +} diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/references.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/references.ts new file mode 100644 index 0000000000000..cd778ad7a4e40 --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/references.ts @@ -0,0 +1,321 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { ThreeWayDiffOutcome } from '@kbn/security-solution-plugin/common/api/detection_engine'; +import { FtrProviderContext } from '../../../../../../../../ftr_provider_context'; +import type { TestFieldRuleUpgradeAssets } from '../test_helpers'; +import { + testFieldUpgradeReview, + testFieldUpgradesToMergedValue, + testFieldUpgradesToResolvedValue, +} from '../test_helpers'; + +export function referencesField({ getService }: FtrProviderContext): void { + describe('"references"', () => { + describe('non-customized w/o an upgrade (AAA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + references: ['http://url-1'], + }, + patch: {}, + upgrade: { + type: 'query', + references: ['http://url-1'], + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'references', + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueNoUpdate, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'references', + resolvedValue: ['https://resolved'], + expectedFieldsAfterUpgrade: { references: ['https://resolved'] }, + }, + getService + ); + }); + + describe('non-customized w/ an upgrade (AAB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + references: ['http://url-1'], + }, + patch: {}, + upgrade: { + type: 'query', + references: ['http://url-1', 'http://url-2'], + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'references', + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueCanUpdate, + expectedFieldDiffValues: { + base: ['http://url-1'], + current: ['http://url-1'], + target: ['http://url-1', 'http://url-2'], + merged: ['http://url-1', 'http://url-2'], + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'references', + expectedFieldsAfterUpgrade: { references: ['http://url-1', 'http://url-2'] }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'references', + resolvedValue: ['https://resolved'], + expectedFieldsAfterUpgrade: { references: ['https://resolved'] }, + }, + getService + ); + }); + + describe('customized w/o an upgrade (ABA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + references: ['http://url-1'], + }, + patch: { + references: ['http://url-2'], + }, + upgrade: { + type: 'query', + references: ['http://url-1'], + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'references', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueNoUpdate, + expectedFieldDiffValues: { + base: ['http://url-1'], + current: ['http://url-2'], + target: ['http://url-1'], + merged: ['http://url-2'], + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'references', + expectedFieldsAfterUpgrade: { references: ['http://url-2'] }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'references', + resolvedValue: ['https://resolved'], + expectedFieldsAfterUpgrade: { references: ['https://resolved'] }, + }, + getService + ); + }); + + describe('customized w/ the matching upgrade (ABB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + references: ['http://url-1'], + }, + patch: { + references: ['http://url-1', 'http://url-2'], + }, + upgrade: { + type: 'query', + references: ['http://url-1', 'http://url-2'], + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'references', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueSameUpdate, + expectedFieldDiffValues: { + base: ['http://url-1'], + current: ['http://url-1', 'http://url-2'], + target: ['http://url-1', 'http://url-2'], + merged: ['http://url-1', 'http://url-2'], + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'references', + expectedFieldsAfterUpgrade: { references: ['http://url-1', 'http://url-2'] }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'references', + resolvedValue: ['https://resolved'], + expectedFieldsAfterUpgrade: { references: ['https://resolved'] }, + }, + getService + ); + }); + + describe('customized w/ an upgrade resulting in a conflict (ABC diff case, solvable conflict)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + references: ['http://url-1'], + }, + patch: { + references: ['http://url-2'], + }, + upgrade: { + type: 'query', + references: ['http://url-1', 'http://url-3'], + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'references', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueCanUpdate, + isSolvableConflict: true, + expectedFieldDiffValues: { + base: ['http://url-1'], + current: ['http://url-2'], + target: ['http://url-1', 'http://url-3'], + merged: ['http://url-2', 'http://url-3'], + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'references', + resolvedValue: ['https://resolved'], + expectedFieldsAfterUpgrade: { references: ['https://resolved'] }, + }, + getService + ); + }); + + describe('without historical versions', () => { + describe('customized w/ the matching upgrade (-AA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + references: ['http://url-1'], + }, + patch: { + references: ['http://url-2'], + }, + upgrade: { + type: 'query', + references: ['http://url-2'], + }, + removeInstalledAssets: true, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'references', + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseNoUpdate, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'references', + resolvedValue: ['https://resolved'], + expectedFieldsAfterUpgrade: { references: ['https://resolved'] }, + }, + getService + ); + }); + + describe('customized w/ an upgrade (-AB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + references: ['http://url-1'], + }, + patch: { + references: ['http://url-3'], + }, + upgrade: { + type: 'query', + references: ['http://url-1', 'http://url-2'], + }, + removeInstalledAssets: true, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'references', + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseCanUpdate, + expectedFieldDiffValues: { + current: ['http://url-3'], + target: ['http://url-1', 'http://url-2'], + merged: ['http://url-1', 'http://url-2'], + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'references', + resolvedValue: ['https://resolved'], + expectedFieldsAfterUpgrade: { references: ['https://resolved'] }, + }, + getService + ); + }); + }); + }); +} diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/related_integrations.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/related_integrations.ts new file mode 100644 index 0000000000000..bdc4f0081c31e --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/related_integrations.ts @@ -0,0 +1,652 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { ThreeWayDiffOutcome } from '@kbn/security-solution-plugin/common/api/detection_engine'; +import { FtrProviderContext } from '../../../../../../../../ftr_provider_context'; +import type { TestFieldRuleUpgradeAssets } from '../test_helpers'; +import { + testFieldUpgradeReview, + testFieldUpgradesToMergedValue, + testFieldUpgradesToResolvedValue, +} from '../test_helpers'; + +export function relatedIntegrationsField({ getService }: FtrProviderContext): void { + describe('"related_integrations"', () => { + describe('non-customized w/o an upgrade (AAA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + related_integrations: [ + { + package: 'packageA', + version: '^1.0.0', + }, + ], + }, + patch: {}, + upgrade: { + type: 'query', + related_integrations: [ + { + package: 'packageA', + version: '^1.0.0', + }, + ], + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'related_integrations', + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueNoUpdate, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'related_integrations', + resolvedValue: [ + { + package: 'resolvedPackage', + version: '^1.0.0', + }, + ], + expectedFieldsAfterUpgrade: { + related_integrations: [ + { + package: 'resolvedPackage', + version: '^1.0.0', + }, + ], + }, + }, + getService + ); + }); + + describe('non-customized w/ an upgrade (AAB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + related_integrations: [ + { + package: 'packageA', + version: '^1.0.0', + }, + ], + }, + patch: {}, + upgrade: { + type: 'query', + related_integrations: [ + { + package: 'packageA', + version: '^2.0.0', + }, + { + package: 'packageB', + version: '^2.0.0', + }, + ], + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'related_integrations', + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueCanUpdate, + expectedFieldDiffValues: { + base: [ + { + package: 'packageA', + version: '^1.0.0', + }, + ], + current: [ + { + package: 'packageA', + version: '^1.0.0', + }, + ], + target: [ + { + package: 'packageA', + version: '^2.0.0', + }, + { + package: 'packageB', + version: '^2.0.0', + }, + ], + merged: [ + { + package: 'packageA', + version: '^2.0.0', + }, + { + package: 'packageB', + version: '^2.0.0', + }, + ], + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'related_integrations', + expectedFieldsAfterUpgrade: { + related_integrations: [ + { + package: 'packageA', + version: '^2.0.0', + }, + { + package: 'packageB', + version: '^2.0.0', + }, + ], + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'related_integrations', + resolvedValue: [ + { + package: 'resolvedPackage', + version: '^1.0.0', + }, + ], + expectedFieldsAfterUpgrade: { + related_integrations: [ + { + package: 'resolvedPackage', + version: '^1.0.0', + }, + ], + }, + }, + getService + ); + }); + + describe('customized w/o an upgrade (ABA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + related_integrations: [ + { + package: 'packageA', + version: '^1.0.0', + }, + ], + }, + patch: { + related_integrations: [ + { + package: 'packageB', + version: '^1.0.0', + }, + ], + }, + upgrade: { + type: 'query', + related_integrations: [ + { + package: 'packageA', + version: '^1.0.0', + }, + ], + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'related_integrations', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueNoUpdate, + expectedFieldDiffValues: { + base: [ + { + package: 'packageA', + version: '^1.0.0', + }, + ], + current: [ + { + package: 'packageB', + version: '^1.0.0', + }, + ], + target: [ + { + package: 'packageA', + version: '^1.0.0', + }, + ], + merged: [ + { + package: 'packageB', + version: '^1.0.0', + }, + ], + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'related_integrations', + expectedFieldsAfterUpgrade: { + related_integrations: [ + { + package: 'packageB', + version: '^1.0.0', + }, + ], + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'related_integrations', + resolvedValue: [ + { + package: 'resolvedPackage', + version: '^1.0.0', + }, + ], + expectedFieldsAfterUpgrade: { + related_integrations: [ + { + package: 'resolvedPackage', + version: '^1.0.0', + }, + ], + }, + }, + getService + ); + }); + + describe('customized w/ the matching upgrade (ABB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + related_integrations: [ + { + package: 'packageA', + version: '^1.0.0', + }, + ], + }, + patch: { + related_integrations: [ + { + package: 'packageB', + version: '^1.0.0', + }, + ], + }, + upgrade: { + type: 'query', + related_integrations: [ + { + package: 'packageB', + version: '^1.0.0', + }, + ], + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'related_integrations', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueSameUpdate, + expectedFieldDiffValues: { + base: [ + { + package: 'packageA', + version: '^1.0.0', + }, + ], + current: [ + { + package: 'packageB', + version: '^1.0.0', + }, + ], + target: [ + { + package: 'packageB', + version: '^1.0.0', + }, + ], + merged: [ + { + package: 'packageB', + version: '^1.0.0', + }, + ], + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'related_integrations', + expectedFieldsAfterUpgrade: { + related_integrations: [ + { + package: 'packageB', + version: '^1.0.0', + }, + ], + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'related_integrations', + resolvedValue: [ + { + package: 'resolvedPackage', + version: '^1.0.0', + }, + ], + expectedFieldsAfterUpgrade: { + related_integrations: [ + { + package: 'resolvedPackage', + version: '^1.0.0', + }, + ], + }, + }, + getService + ); + }); + + describe('customized w/ an upgrade resulting in a conflict (ABC diff case, non-solvable conflict)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + related_integrations: [ + { + package: 'packageA', + version: '^1.0.0', + }, + ], + }, + patch: { + related_integrations: [ + { + package: 'packageB', + version: '^1.0.0', + }, + ], + }, + upgrade: { + type: 'query', + related_integrations: [ + { + package: 'packageA', + version: '^2.0.0', + }, + { + package: 'packageB', + version: '^2.0.0', + }, + ], + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'related_integrations', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueCanUpdate, + isSolvableConflict: false, + expectedFieldDiffValues: { + base: [ + { + package: 'packageA', + version: '^1.0.0', + }, + ], + current: [ + { + package: 'packageB', + version: '^1.0.0', + }, + ], + target: [ + { + package: 'packageA', + version: '^2.0.0', + }, + { + package: 'packageB', + version: '^2.0.0', + }, + ], + merged: [ + { + package: 'packageB', + version: '^1.0.0', + }, + ], + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'related_integrations', + resolvedValue: [ + { + package: 'resolvedPackage', + version: '^1.0.0', + }, + ], + expectedFieldsAfterUpgrade: { + related_integrations: [ + { + package: 'resolvedPackage', + version: '^1.0.0', + }, + ], + }, + }, + getService + ); + }); + + describe('without historical versions', () => { + describe('customized w/ the matching upgrade (-AA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + related_integrations: [ + { + package: 'packageA', + version: '^1.0.0', + }, + ], + }, + patch: { + related_integrations: [ + { + package: 'packageB', + version: '^1.0.0', + }, + ], + }, + upgrade: { + type: 'query', + related_integrations: [ + { + package: 'packageB', + version: '^1.0.0', + }, + ], + }, + removeInstalledAssets: true, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'related_integrations', + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseNoUpdate, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'related_integrations', + resolvedValue: [ + { + package: 'resolvedPackage', + version: '^1.0.0', + }, + ], + expectedFieldsAfterUpgrade: { + related_integrations: [ + { + package: 'resolvedPackage', + version: '^1.0.0', + }, + ], + }, + }, + getService + ); + }); + + describe('customized w/ an upgrade (-AB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + related_integrations: [ + { + package: 'packageA', + version: '^1.0.0', + }, + ], + }, + patch: { + related_integrations: [ + { + package: 'packageB', + version: '^1.0.0', + }, + ], + }, + upgrade: { + type: 'query', + related_integrations: [ + { + package: 'packageA', + version: '^2.0.0', + }, + { + package: 'packageB', + version: '^2.0.0', + }, + ], + }, + removeInstalledAssets: true, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'related_integrations', + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseCanUpdate, + expectedFieldDiffValues: { + current: [ + { + package: 'packageB', + version: '^1.0.0', + }, + ], + target: [ + { + package: 'packageA', + version: '^2.0.0', + }, + { + package: 'packageB', + version: '^2.0.0', + }, + ], + merged: [ + { + package: 'packageA', + version: '^2.0.0', + }, + { + package: 'packageB', + version: '^2.0.0', + }, + ], + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'related_integrations', + resolvedValue: [ + { + package: 'resolvedPackage', + version: '^1.0.0', + }, + ], + expectedFieldsAfterUpgrade: { + related_integrations: [ + { + package: 'resolvedPackage', + version: '^1.0.0', + }, + ], + }, + }, + getService + ); + }); + }); + }); +} diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/required_fields.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/required_fields.ts new file mode 100644 index 0000000000000..5dbd464bc2435 --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/required_fields.ts @@ -0,0 +1,657 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { ThreeWayDiffOutcome } from '@kbn/security-solution-plugin/common/api/detection_engine'; +import { FtrProviderContext } from '../../../../../../../../ftr_provider_context'; +import type { TestFieldRuleUpgradeAssets } from '../test_helpers'; +import { + testFieldUpgradeReview, + testFieldUpgradesToMergedValue, + testFieldUpgradesToResolvedValue, +} from '../test_helpers'; + +export function requiredFieldsField({ getService }: FtrProviderContext): void { + describe('"required_fields"', () => { + describe('non-customized w/o an upgrade (AAA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + required_fields: [ + { + name: 'fieldA', + type: 'string', + }, + ], + }, + patch: {}, + upgrade: { + type: 'query', + required_fields: [ + { + name: 'fieldA', + type: 'string', + }, + ], + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'required_fields', + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueNoUpdate, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'required_fields', + resolvedValue: [ + { + name: 'resolved', + type: 'string', + ecs: false, + }, + ], + expectedFieldsAfterUpgrade: { + required_fields: [ + { + name: 'resolved', + type: 'string', + ecs: false, + }, + ], + }, + }, + getService + ); + }); + + describe('non-customized w/ an upgrade (AAB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + required_fields: [ + { + name: 'fieldA', + type: 'string', + }, + ], + }, + patch: {}, + upgrade: { + type: 'query', + required_fields: [ + { + name: 'fieldB', + type: 'string', + }, + ], + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'required_fields', + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueCanUpdate, + expectedFieldDiffValues: { + base: [ + { + name: 'fieldA', + type: 'string', + ecs: false, + }, + ], + current: [ + { + name: 'fieldA', + type: 'string', + ecs: false, + }, + ], + target: [ + { + name: 'fieldB', + type: 'string', + ecs: false, + }, + ], + merged: [ + { + name: 'fieldB', + type: 'string', + ecs: false, + }, + ], + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'required_fields', + expectedFieldsAfterUpgrade: { + required_fields: [ + { + name: 'fieldB', + type: 'string', + ecs: false, + }, + ], + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'required_fields', + resolvedValue: [ + { + name: 'resolved', + type: 'string', + ecs: false, + }, + ], + expectedFieldsAfterUpgrade: { + required_fields: [ + { + name: 'resolved', + type: 'string', + ecs: false, + }, + ], + }, + }, + getService + ); + }); + + describe('customized w/o an upgrade (ABA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + required_fields: [ + { + name: 'fieldA', + type: 'string', + }, + ], + }, + patch: { + required_fields: [ + { + name: 'fieldB', + type: 'string', + ecs: false, + }, + ], + }, + upgrade: { + type: 'query', + required_fields: [ + { + name: 'fieldA', + type: 'string', + }, + ], + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'required_fields', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueNoUpdate, + expectedFieldDiffValues: { + base: [ + { + name: 'fieldA', + type: 'string', + ecs: false, + }, + ], + current: [ + { + name: 'fieldB', + type: 'string', + ecs: false, + }, + ], + target: [ + { + name: 'fieldA', + type: 'string', + ecs: false, + }, + ], + merged: [ + { + name: 'fieldB', + type: 'string', + ecs: false, + }, + ], + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'required_fields', + expectedFieldsAfterUpgrade: { + required_fields: [ + { + name: 'fieldB', + type: 'string', + ecs: false, + }, + ], + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'required_fields', + resolvedValue: [ + { + name: 'resolved', + type: 'string', + ecs: false, + }, + ], + expectedFieldsAfterUpgrade: { + required_fields: [ + { + name: 'resolved', + type: 'string', + ecs: false, + }, + ], + }, + }, + getService + ); + }); + + describe('customized w/ the matching upgrade (ABB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + required_fields: [ + { + name: 'fieldA', + type: 'string', + }, + ], + }, + patch: { + required_fields: [ + { + name: 'fieldB', + type: 'string', + ecs: false, + }, + ], + }, + upgrade: { + type: 'query', + required_fields: [ + { + name: 'fieldB', + type: 'string', + }, + ], + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'required_fields', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueSameUpdate, + expectedFieldDiffValues: { + base: [ + { + name: 'fieldA', + type: 'string', + ecs: false, + }, + ], + current: [ + { + name: 'fieldB', + type: 'string', + ecs: false, + }, + ], + target: [ + { + name: 'fieldB', + type: 'string', + ecs: false, + }, + ], + merged: [ + { + name: 'fieldB', + type: 'string', + ecs: false, + }, + ], + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'required_fields', + expectedFieldsAfterUpgrade: { + required_fields: [ + { + name: 'fieldB', + type: 'string', + ecs: false, + }, + ], + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'required_fields', + resolvedValue: [ + { + name: 'resolved', + type: 'string', + ecs: false, + }, + ], + expectedFieldsAfterUpgrade: { + required_fields: [ + { + name: 'resolved', + type: 'string', + ecs: false, + }, + ], + }, + }, + getService + ); + }); + + describe('customized w/ an upgrade resulting in a conflict (ABC diff case, non-solvable conflict)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + required_fields: [ + { + name: 'fieldA', + type: 'string', + }, + ], + }, + patch: { + required_fields: [ + { + name: 'fieldB', + type: 'string', + ecs: false, + }, + ], + }, + upgrade: { + type: 'query', + required_fields: [ + { + name: 'fieldC', + type: 'string', + }, + ], + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'required_fields', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueCanUpdate, + isSolvableConflict: false, + expectedFieldDiffValues: { + base: [ + { + name: 'fieldA', + type: 'string', + ecs: false, + }, + ], + current: [ + { + name: 'fieldB', + type: 'string', + ecs: false, + }, + ], + target: [ + { + name: 'fieldC', + type: 'string', + ecs: false, + }, + ], + merged: [ + { + name: 'fieldB', + type: 'string', + ecs: false, + }, + ], + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'required_fields', + resolvedValue: [ + { + name: 'resolved', + type: 'string', + ecs: false, + }, + ], + expectedFieldsAfterUpgrade: { + required_fields: [ + { + name: 'resolved', + type: 'string', + ecs: false, + }, + ], + }, + }, + getService + ); + }); + + describe('without historical versions', () => { + describe('customized w/ the matching upgrade (-AA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + required_fields: [ + { + name: 'fieldA', + type: 'string', + }, + ], + }, + patch: { + required_fields: [ + { + name: 'fieldB', + type: 'string', + ecs: false, + }, + ], + }, + upgrade: { + type: 'query', + required_fields: [ + { + name: 'fieldB', + type: 'string', + }, + ], + }, + removeInstalledAssets: true, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'required_fields', + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseNoUpdate, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'required_fields', + resolvedValue: [ + { + name: 'resolved', + type: 'string', + ecs: false, + }, + ], + expectedFieldsAfterUpgrade: { + required_fields: [ + { + name: 'resolved', + type: 'string', + ecs: false, + }, + ], + }, + }, + getService + ); + }); + + describe('customized w/ an upgrade (-AB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + required_fields: [ + { + name: 'fieldA', + type: 'string', + }, + ], + }, + patch: { + required_fields: [ + { + name: 'fieldB', + type: 'string', + ecs: false, + }, + ], + }, + upgrade: { + type: 'query', + required_fields: [ + { + name: 'fieldC', + type: 'string', + }, + ], + }, + removeInstalledAssets: true, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'required_fields', + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseCanUpdate, + expectedFieldDiffValues: { + current: [ + { + name: 'fieldB', + type: 'string', + ecs: false, + }, + ], + target: [ + { + name: 'fieldC', + type: 'string', + ecs: false, + }, + ], + merged: [ + { + name: 'fieldC', + type: 'string', + ecs: false, + }, + ], + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'required_fields', + resolvedValue: [ + { + name: 'resolved', + type: 'string', + ecs: false, + }, + ], + expectedFieldsAfterUpgrade: { + required_fields: [ + { + name: 'resolved', + type: 'string', + ecs: false, + }, + ], + }, + }, + getService + ); + }); + }); + }); +} diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/risk_score.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/risk_score.ts new file mode 100644 index 0000000000000..e83d9d3a82876 --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/risk_score.ts @@ -0,0 +1,321 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { ThreeWayDiffOutcome } from '@kbn/security-solution-plugin/common/api/detection_engine'; +import { FtrProviderContext } from '../../../../../../../../ftr_provider_context'; +import type { TestFieldRuleUpgradeAssets } from '../test_helpers'; +import { + testFieldUpgradeReview, + testFieldUpgradesToMergedValue, + testFieldUpgradesToResolvedValue, +} from '../test_helpers'; + +export function riskScoreField({ getService }: FtrProviderContext): void { + describe('"risk_score"', () => { + describe('non-customized w/o an upgrade (AAA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + risk_score: 10, + }, + patch: {}, + upgrade: { + type: 'query', + risk_score: 10, + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'risk_score', + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueNoUpdate, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'risk_score', + resolvedValue: 50, + expectedFieldsAfterUpgrade: { risk_score: 50 }, + }, + getService + ); + }); + + describe('non-customized w/ an upgrade (AAB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + risk_score: 10, + }, + patch: {}, + upgrade: { + type: 'query', + risk_score: 30, + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'risk_score', + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueCanUpdate, + expectedFieldDiffValues: { + base: 10, + current: 10, + target: 30, + merged: 30, + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'risk_score', + expectedFieldsAfterUpgrade: { risk_score: 30 }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'risk_score', + resolvedValue: 50, + expectedFieldsAfterUpgrade: { risk_score: 50 }, + }, + getService + ); + }); + + describe('customized w/o an upgrade (ABA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + risk_score: 10, + }, + patch: { + risk_score: 50, + }, + upgrade: { + type: 'query', + risk_score: 10, + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'risk_score', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueNoUpdate, + expectedFieldDiffValues: { + base: 10, + current: 50, + target: 10, + merged: 50, + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'risk_score', + expectedFieldsAfterUpgrade: { risk_score: 50 }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'risk_score', + resolvedValue: 50, + expectedFieldsAfterUpgrade: { risk_score: 50 }, + }, + getService + ); + }); + + describe('customized w/ the matching upgrade (ABB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + risk_score: 10, + }, + patch: { + risk_score: 50, + }, + upgrade: { + type: 'query', + risk_score: 50, + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'risk_score', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueSameUpdate, + expectedFieldDiffValues: { + base: 10, + current: 50, + target: 50, + merged: 50, + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'risk_score', + expectedFieldsAfterUpgrade: { risk_score: 50 }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'risk_score', + resolvedValue: 50, + expectedFieldsAfterUpgrade: { risk_score: 50 }, + }, + getService + ); + }); + + describe('customized w/ an upgrade resulting in a conflict (ABC diff case, non-solvable conflict)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + risk_score: 10, + }, + patch: { + risk_score: 50, + }, + upgrade: { + type: 'query', + risk_score: 30, + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'risk_score', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueCanUpdate, + isSolvableConflict: false, + expectedFieldDiffValues: { + base: 10, + current: 50, + target: 30, + merged: 50, + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'risk_score', + resolvedValue: 50, + expectedFieldsAfterUpgrade: { risk_score: 50 }, + }, + getService + ); + }); + + describe('without historical versions', () => { + describe('customized w/ the matching upgrade (-AA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + risk_score: 10, + }, + patch: { + risk_score: 30, + }, + upgrade: { + type: 'query', + risk_score: 30, + }, + removeInstalledAssets: true, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'risk_score', + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseNoUpdate, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'risk_score', + resolvedValue: 50, + expectedFieldsAfterUpgrade: { risk_score: 50 }, + }, + getService + ); + }); + + describe('customized w/ an upgrade (-AB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + risk_score: 10, + }, + patch: { + risk_score: 50, + }, + upgrade: { + type: 'query', + risk_score: 30, + }, + removeInstalledAssets: true, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'risk_score', + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseCanUpdate, + expectedFieldDiffValues: { + current: 50, + target: 30, + merged: 30, + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'risk_score', + resolvedValue: 50, + expectedFieldsAfterUpgrade: { risk_score: 50 }, + }, + getService + ); + }); + }); + }); +} diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/risk_score_mapping.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/risk_score_mapping.ts new file mode 100644 index 0000000000000..77f68493254fe --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/risk_score_mapping.ts @@ -0,0 +1,726 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { ThreeWayDiffOutcome } from '@kbn/security-solution-plugin/common/api/detection_engine'; +import { FtrProviderContext } from '../../../../../../../../ftr_provider_context'; +import type { TestFieldRuleUpgradeAssets } from '../test_helpers'; +import { + testFieldUpgradeReview, + testFieldUpgradesToMergedValue, + testFieldUpgradesToResolvedValue, +} from '../test_helpers'; + +export function riskScoreMappingField({ getService }: FtrProviderContext): void { + describe('"risk_score_mapping"', () => { + describe('non-customized w/o an upgrade (AAA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + risk_score_mapping: [ + { + field: 'fieldA', + operator: 'equals', + value: '10', + risk_score: 10, + }, + ], + }, + patch: {}, + upgrade: { + type: 'query', + risk_score_mapping: [ + { + field: 'fieldA', + operator: 'equals', + value: '10', + risk_score: 10, + }, + ], + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'risk_score_mapping', + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueNoUpdate, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'risk_score_mapping', + resolvedValue: [ + { + field: 'resolved', + operator: 'equals', + value: '50', + risk_score: 50, + }, + ], + expectedFieldsAfterUpgrade: { + risk_score_mapping: [ + { + field: 'resolved', + operator: 'equals', + value: '50', + risk_score: 50, + }, + ], + }, + }, + getService + ); + }); + + describe('non-customized w/ an upgrade (AAB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + risk_score_mapping: [ + { + field: 'fieldA', + operator: 'equals', + value: '10', + risk_score: 10, + }, + ], + }, + patch: {}, + upgrade: { + type: 'query', + risk_score_mapping: [ + { + field: 'fieldB', + operator: 'equals', + value: '30', + risk_score: 30, + }, + ], + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'risk_score_mapping', + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueCanUpdate, + expectedFieldDiffValues: { + base: [ + { + field: 'fieldA', + operator: 'equals', + value: '10', + risk_score: 10, + }, + ], + current: [ + { + field: 'fieldA', + operator: 'equals', + value: '10', + risk_score: 10, + }, + ], + target: [ + { + field: 'fieldB', + operator: 'equals', + value: '30', + risk_score: 30, + }, + ], + merged: [ + { + field: 'fieldB', + operator: 'equals', + value: '30', + risk_score: 30, + }, + ], + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'risk_score_mapping', + expectedFieldsAfterUpgrade: { + risk_score_mapping: [ + { + field: 'fieldB', + operator: 'equals', + value: '30', + risk_score: 30, + }, + ], + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'risk_score_mapping', + resolvedValue: [ + { + field: 'resolved', + operator: 'equals', + value: '50', + risk_score: 50, + }, + ], + expectedFieldsAfterUpgrade: { + risk_score_mapping: [ + { + field: 'resolved', + operator: 'equals', + value: '50', + risk_score: 50, + }, + ], + }, + }, + getService + ); + }); + + describe('customized w/o an upgrade (ABA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + risk_score_mapping: [ + { + field: 'fieldA', + operator: 'equals', + value: '10', + risk_score: 10, + }, + ], + }, + patch: { + risk_score_mapping: [ + { + field: 'fieldB', + operator: 'equals', + value: '30', + risk_score: 30, + }, + ], + }, + upgrade: { + type: 'query', + risk_score_mapping: [ + { + field: 'fieldA', + operator: 'equals', + value: '10', + risk_score: 10, + }, + ], + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'risk_score_mapping', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueNoUpdate, + expectedFieldDiffValues: { + base: [ + { + field: 'fieldA', + operator: 'equals', + value: '10', + risk_score: 10, + }, + ], + current: [ + { + field: 'fieldB', + operator: 'equals', + value: '30', + risk_score: 30, + }, + ], + target: [ + { + field: 'fieldA', + operator: 'equals', + value: '10', + risk_score: 10, + }, + ], + merged: [ + { + field: 'fieldB', + operator: 'equals', + value: '30', + risk_score: 30, + }, + ], + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'risk_score_mapping', + expectedFieldsAfterUpgrade: { + risk_score_mapping: [ + { + field: 'fieldB', + operator: 'equals', + value: '30', + risk_score: 30, + }, + ], + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'risk_score_mapping', + resolvedValue: [ + { + field: 'resolved', + operator: 'equals', + value: '50', + risk_score: 50, + }, + ], + expectedFieldsAfterUpgrade: { + risk_score_mapping: [ + { + field: 'resolved', + operator: 'equals', + value: '50', + risk_score: 50, + }, + ], + }, + }, + getService + ); + }); + + describe('customized w/ the matching upgrade (ABB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + risk_score_mapping: [ + { + field: 'fieldA', + operator: 'equals', + value: '10', + risk_score: 10, + }, + ], + }, + patch: { + risk_score_mapping: [ + { + field: 'fieldB', + operator: 'equals', + value: '30', + risk_score: 30, + }, + ], + }, + upgrade: { + type: 'query', + risk_score_mapping: [ + { + field: 'fieldB', + operator: 'equals', + value: '30', + risk_score: 30, + }, + ], + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'risk_score_mapping', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueSameUpdate, + expectedFieldDiffValues: { + base: [ + { + field: 'fieldA', + operator: 'equals', + value: '10', + risk_score: 10, + }, + ], + current: [ + { + field: 'fieldB', + operator: 'equals', + value: '30', + risk_score: 30, + }, + ], + target: [ + { + field: 'fieldB', + operator: 'equals', + value: '30', + risk_score: 30, + }, + ], + merged: [ + { + field: 'fieldB', + operator: 'equals', + value: '30', + risk_score: 30, + }, + ], + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'risk_score_mapping', + expectedFieldsAfterUpgrade: { + risk_score_mapping: [ + { + field: 'fieldB', + operator: 'equals', + value: '30', + risk_score: 30, + }, + ], + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'risk_score_mapping', + resolvedValue: [ + { + field: 'resolved', + operator: 'equals', + value: '50', + risk_score: 50, + }, + ], + expectedFieldsAfterUpgrade: { + risk_score_mapping: [ + { + field: 'resolved', + operator: 'equals', + value: '50', + risk_score: 50, + }, + ], + }, + }, + getService + ); + }); + + describe('customized w/ an upgrade resulting in a conflict (ABC diff case, non-solvable conflict)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + risk_score_mapping: [ + { + field: 'fieldA', + operator: 'equals', + value: '10', + risk_score: 10, + }, + ], + }, + patch: { + risk_score_mapping: [ + { + field: 'fieldB', + operator: 'equals', + value: '30', + risk_score: 30, + }, + ], + }, + upgrade: { + type: 'query', + risk_score_mapping: [ + { + field: 'fieldC', + operator: 'equals', + value: '50', + risk_score: 50, + }, + ], + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'risk_score_mapping', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueCanUpdate, + isSolvableConflict: false, + expectedFieldDiffValues: { + base: [ + { + field: 'fieldA', + operator: 'equals', + value: '10', + risk_score: 10, + }, + ], + current: [ + { + field: 'fieldB', + operator: 'equals', + value: '30', + risk_score: 30, + }, + ], + target: [ + { + field: 'fieldC', + operator: 'equals', + value: '50', + risk_score: 50, + }, + ], + merged: [ + { + field: 'fieldB', + operator: 'equals', + value: '30', + risk_score: 30, + }, + ], + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'risk_score_mapping', + resolvedValue: [ + { + field: 'resolved', + operator: 'equals', + value: '50', + risk_score: 50, + }, + ], + expectedFieldsAfterUpgrade: { + risk_score_mapping: [ + { + field: 'resolved', + operator: 'equals', + value: '50', + risk_score: 50, + }, + ], + }, + }, + getService + ); + }); + + describe('without historical versions', () => { + describe('customized w/ the matching upgrade (-AA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + risk_score_mapping: [ + { + field: 'fieldA', + operator: 'equals', + value: '10', + risk_score: 10, + }, + ], + }, + patch: { + risk_score_mapping: [ + { + field: 'fieldB', + operator: 'equals', + value: '30', + risk_score: 30, + }, + ], + }, + upgrade: { + type: 'query', + risk_score_mapping: [ + { + field: 'fieldB', + operator: 'equals', + value: '30', + risk_score: 30, + }, + ], + }, + removeInstalledAssets: true, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'risk_score_mapping', + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseNoUpdate, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'risk_score_mapping', + resolvedValue: [ + { + field: 'resolved', + operator: 'equals', + value: '50', + risk_score: 50, + }, + ], + expectedFieldsAfterUpgrade: { + risk_score_mapping: [ + { + field: 'resolved', + operator: 'equals', + value: '50', + risk_score: 50, + }, + ], + }, + }, + getService + ); + }); + + describe('customized w/ an upgrade (-AB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + risk_score_mapping: [ + { + field: 'fieldA', + operator: 'equals', + value: '10', + risk_score: 10, + }, + ], + }, + patch: { + risk_score_mapping: [ + { + field: 'fieldB', + operator: 'equals', + value: '30', + risk_score: 30, + }, + ], + }, + upgrade: { + type: 'query', + risk_score_mapping: [ + { + field: 'fieldC', + operator: 'equals', + value: '50', + risk_score: 50, + }, + ], + }, + removeInstalledAssets: true, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'risk_score_mapping', + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseCanUpdate, + expectedFieldDiffValues: { + current: [ + { + field: 'fieldB', + operator: 'equals', + value: '30', + risk_score: 30, + }, + ], + target: [ + { + field: 'fieldC', + operator: 'equals', + value: '50', + risk_score: 50, + }, + ], + merged: [ + { + field: 'fieldC', + operator: 'equals', + value: '50', + risk_score: 50, + }, + ], + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'risk_score_mapping', + resolvedValue: [ + { + field: 'resolved', + operator: 'equals', + value: '50', + risk_score: 50, + }, + ], + expectedFieldsAfterUpgrade: { + risk_score_mapping: [ + { + field: 'resolved', + operator: 'equals', + value: '50', + risk_score: 50, + }, + ], + }, + }, + getService + ); + }); + }); + }); +} diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/rule_name_override.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/rule_name_override.ts new file mode 100644 index 0000000000000..afe5b1cac6821 --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/rule_name_override.ts @@ -0,0 +1,321 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { ThreeWayDiffOutcome } from '@kbn/security-solution-plugin/common/api/detection_engine'; +import { FtrProviderContext } from '../../../../../../../../ftr_provider_context'; +import type { TestFieldRuleUpgradeAssets } from '../test_helpers'; +import { + testFieldUpgradeReview, + testFieldUpgradesToMergedValue, + testFieldUpgradesToResolvedValue, +} from '../test_helpers'; + +export function ruleNameOverrideField({ getService }: FtrProviderContext): void { + describe('"rule_name_override"', () => { + describe('non-customized w/o an upgrade (AAA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + rule_name_override: 'fieldA', + }, + patch: {}, + upgrade: { + type: 'query', + rule_name_override: 'fieldA', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'rule_name_override', + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueNoUpdate, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'rule_name_override', + resolvedValue: { field_name: 'resolved' }, + expectedFieldsAfterUpgrade: { rule_name_override: 'resolved' }, + }, + getService + ); + }); + + describe('non-customized w/ an upgrade (AAB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + rule_name_override: 'fieldA', + }, + patch: {}, + upgrade: { + type: 'query', + rule_name_override: 'fieldB', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'rule_name_override', + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueCanUpdate, + expectedFieldDiffValues: { + base: { field_name: 'fieldA' }, + current: { field_name: 'fieldA' }, + target: { field_name: 'fieldB' }, + merged: { field_name: 'fieldB' }, + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'rule_name_override', + expectedFieldsAfterUpgrade: { rule_name_override: 'fieldB' }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'rule_name_override', + resolvedValue: { field_name: 'resolved' }, + expectedFieldsAfterUpgrade: { rule_name_override: 'resolved' }, + }, + getService + ); + }); + + describe('customized w/o an upgrade (ABA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + rule_name_override: 'fieldA', + }, + patch: { + rule_name_override: 'fieldB', + }, + upgrade: { + type: 'query', + rule_name_override: 'fieldA', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'rule_name_override', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueNoUpdate, + expectedFieldDiffValues: { + base: { field_name: 'fieldA' }, + current: { field_name: 'fieldB' }, + target: { field_name: 'fieldA' }, + merged: { field_name: 'fieldB' }, + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'rule_name_override', + expectedFieldsAfterUpgrade: { rule_name_override: 'fieldB' }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'rule_name_override', + resolvedValue: { field_name: 'resolved' }, + expectedFieldsAfterUpgrade: { rule_name_override: 'resolved' }, + }, + getService + ); + }); + + describe('customized w/ the matching upgrade (ABB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + rule_name_override: 'fieldA', + }, + patch: { + rule_name_override: 'fieldB', + }, + upgrade: { + type: 'query', + rule_name_override: 'fieldB', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'rule_name_override', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueSameUpdate, + expectedFieldDiffValues: { + base: { field_name: 'fieldA' }, + current: { field_name: 'fieldB' }, + target: { field_name: 'fieldB' }, + merged: { field_name: 'fieldB' }, + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'rule_name_override', + expectedFieldsAfterUpgrade: { rule_name_override: 'fieldB' }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'rule_name_override', + resolvedValue: { field_name: 'resolved' }, + expectedFieldsAfterUpgrade: { rule_name_override: 'resolved' }, + }, + getService + ); + }); + + describe('customized w/ an upgrade resulting in a conflict (ABC diff case, non-solvable conflict)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + rule_name_override: 'fieldA', + }, + patch: { + rule_name_override: 'fieldB', + }, + upgrade: { + type: 'query', + rule_name_override: 'fieldC', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'rule_name_override', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueCanUpdate, + isSolvableConflict: false, + expectedFieldDiffValues: { + base: { field_name: 'fieldA' }, + current: { field_name: 'fieldB' }, + target: { field_name: 'fieldC' }, + merged: { field_name: 'fieldB' }, + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'rule_name_override', + resolvedValue: { field_name: 'resolved' }, + expectedFieldsAfterUpgrade: { rule_name_override: 'resolved' }, + }, + getService + ); + }); + + describe('without historical versions', () => { + describe('customized w/ the matching upgrade (-AA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + rule_name_override: 'fieldA', + }, + patch: { + rule_name_override: 'fieldB', + }, + upgrade: { + type: 'query', + rule_name_override: 'fieldB', + }, + removeInstalledAssets: true, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'rule_name_override', + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseNoUpdate, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'rule_name_override', + resolvedValue: { field_name: 'resolved' }, + expectedFieldsAfterUpgrade: { rule_name_override: 'resolved' }, + }, + getService + ); + }); + + describe('customized w/ an upgrade (-AB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + rule_name_override: 'fieldA', + }, + patch: { + rule_name_override: 'fieldB', + }, + upgrade: { + type: 'query', + rule_name_override: 'fieldC', + }, + removeInstalledAssets: true, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'rule_name_override', + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseCanUpdate, + expectedFieldDiffValues: { + current: { field_name: 'fieldB' }, + target: { field_name: 'fieldC' }, + merged: { field_name: 'fieldC' }, + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'rule_name_override', + resolvedValue: { field_name: 'resolved' }, + expectedFieldsAfterUpgrade: { rule_name_override: 'resolved' }, + }, + getService + ); + }); + }); + }); +} diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/rule_schedule.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/rule_schedule.ts new file mode 100644 index 0000000000000..3efb3057920ab --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/rule_schedule.ts @@ -0,0 +1,454 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { ThreeWayDiffOutcome } from '@kbn/security-solution-plugin/common/api/detection_engine'; +import { FtrProviderContext } from '../../../../../../../../ftr_provider_context'; +import type { TestFieldRuleUpgradeAssets } from '../test_helpers'; +import { + testFieldUpgradeReview, + testFieldUpgradesToMergedValue, + testFieldUpgradesToResolvedValue, +} from '../test_helpers'; + +export function ruleScheduleField({ getService }: FtrProviderContext): void { + describe('"rule_schedule"', () => { + describe('non-customized w/o an upgrade (AAA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + interval: '5m', + from: 'now-10m', + to: 'now', + }, + patch: {}, + upgrade: { + type: 'query', + interval: '5m', + from: 'now-10m', + to: 'now', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'rule_schedule', + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueNoUpdate, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'rule_schedule', + resolvedValue: { interval: '1h', from: 'now-2h', to: 'now' }, + expectedFieldsAfterUpgrade: { + interval: '1h', + from: 'now-2h', + to: 'now', + }, + }, + getService + ); + }); + + describe('non-customized w/ an upgrade (AAB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + interval: '5m', + from: 'now-10m', + to: 'now', + }, + patch: {}, + upgrade: { + type: 'query', + interval: '5m', + from: 'now-15m', + to: 'now', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'rule_schedule', + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueCanUpdate, + expectedFieldDiffValues: { + base: { + interval: '5m', + from: 'now-10m', + to: 'now', + }, + current: { + interval: '5m', + from: 'now-10m', + to: 'now', + }, + target: { + interval: '5m', + from: 'now-15m', + to: 'now', + }, + merged: { + interval: '5m', + from: 'now-15m', + to: 'now', + }, + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'rule_schedule', + expectedFieldsAfterUpgrade: { interval: '5m', from: 'now-15m', to: 'now' }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'rule_schedule', + resolvedValue: { + interval: '1h', + from: 'now-2h', + to: 'now', + }, + expectedFieldsAfterUpgrade: { interval: '1h', from: 'now-2h', to: 'now' }, + }, + getService + ); + }); + + describe('customized w/o an upgrade (ABA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + interval: '5m', + from: 'now-10m', + to: 'now', + }, + patch: { + from: 'now-20m', + }, + upgrade: { + type: 'query', + interval: '5m', + from: 'now-10m', + to: 'now', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'rule_schedule', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueNoUpdate, + expectedFieldDiffValues: { + base: { + interval: '5m', + from: 'now-10m', + to: 'now', + }, + current: { + interval: '5m', + from: 'now-20m', + to: 'now', + }, + target: { + interval: '5m', + from: 'now-10m', + to: 'now', + }, + merged: { + interval: '5m', + from: 'now-20m', + to: 'now', + }, + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + + diffableRuleFieldName: 'rule_schedule', + expectedFieldsAfterUpgrade: { interval: '5m', from: 'now-20m', to: 'now' }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'rule_schedule', + resolvedValue: { + interval: '1h', + from: 'now-2h', + to: 'now', + }, + expectedFieldsAfterUpgrade: { interval: '1h', from: 'now-2h', to: 'now' }, + }, + getService + ); + }); + + describe('customized w/ the matching upgrade (ABB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + interval: '5m', + from: 'now-10m', + to: 'now', + }, + patch: { + from: 'now-20m', + }, + upgrade: { + type: 'query', + interval: '5m', + from: 'now-20m', + to: 'now', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'rule_schedule', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueSameUpdate, + expectedFieldDiffValues: { + base: { + interval: '5m', + from: 'now-10m', + to: 'now', + }, + current: { + interval: '5m', + from: 'now-20m', + to: 'now', + }, + target: { + interval: '5m', + from: 'now-20m', + to: 'now', + }, + merged: { + interval: '5m', + from: 'now-20m', + to: 'now', + }, + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'rule_schedule', + expectedFieldsAfterUpgrade: { interval: '5m', from: 'now-20m', to: 'now' }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'rule_schedule', + resolvedValue: { + interval: '1h', + from: 'now-2h', + to: 'now', + }, + expectedFieldsAfterUpgrade: { interval: '1h', from: 'now-2h', to: 'now' }, + }, + getService + ); + }); + + describe('customized w/ an upgrade resulting in a conflict (ABC diff case, non-solvable conflict)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + interval: '5m', + from: 'now-10m', + to: 'now', + }, + patch: { + from: 'now-20m', + }, + upgrade: { + type: 'query', + interval: '5m', + from: 'now-15m', + to: 'now', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'rule_schedule', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueCanUpdate, + isSolvableConflict: false, + expectedFieldDiffValues: { + base: { + interval: '5m', + from: 'now-10m', + to: 'now', + }, + current: { + interval: '5m', + from: 'now-20m', + to: 'now', + }, + target: { + interval: '5m', + from: 'now-15m', + to: 'now', + }, + merged: { + interval: '5m', + from: 'now-20m', + to: 'now', + }, + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'rule_schedule', + resolvedValue: { + interval: '1h', + from: 'now-2h', + to: 'now', + }, + expectedFieldsAfterUpgrade: { interval: '1h', from: 'now-2h', to: 'now' }, + }, + getService + ); + }); + + describe('without historical versions', () => { + describe('customized w/ the matching upgrade (-AA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + interval: '5m', + from: 'now-10m', + to: 'now', + }, + patch: { + from: 'now-20m', + }, + upgrade: { + type: 'query', + interval: '5m', + from: 'now-20m', + to: 'now', + }, + removeInstalledAssets: true, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'rule_schedule', + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseNoUpdate, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'rule_schedule', + resolvedValue: { + interval: '1h', + from: 'now-2h', + to: 'now', + }, + expectedFieldsAfterUpgrade: { interval: '1h', from: 'now-2h', to: 'now' }, + }, + getService + ); + }); + + describe('customized w/ an upgrade (-AB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + interval: '5m', + from: 'now-10m', + to: 'now', + }, + patch: { + from: 'now-20m', + }, + upgrade: { + type: 'query', + interval: '5m', + from: 'now-15m', + to: 'now', + }, + removeInstalledAssets: true, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'rule_schedule', + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseCanUpdate, + expectedFieldDiffValues: { + current: { + interval: '5m', + from: 'now-20m', + to: 'now', + }, + target: { + interval: '5m', + from: 'now-15m', + to: 'now', + }, + merged: { + interval: '5m', + from: 'now-15m', + to: 'now', + }, + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'rule_schedule', + resolvedValue: { + interval: '1h', + from: 'now-2h', + to: 'now', + }, + expectedFieldsAfterUpgrade: { interval: '1h', from: 'now-2h', to: 'now' }, + }, + getService + ); + }); + }); + }); +} diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/setup.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/setup.ts new file mode 100644 index 0000000000000..78c954fcc20f2 --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/setup.ts @@ -0,0 +1,321 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { ThreeWayDiffOutcome } from '@kbn/security-solution-plugin/common/api/detection_engine'; +import { FtrProviderContext } from '../../../../../../../../ftr_provider_context'; +import type { TestFieldRuleUpgradeAssets } from '../test_helpers'; +import { + testFieldUpgradeReview, + testFieldUpgradesToMergedValue, + testFieldUpgradesToResolvedValue, +} from '../test_helpers'; + +export function setupField({ getService }: FtrProviderContext): void { + describe('"setup"', () => { + describe('non-customized w/o an upgrade (AAA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + setup: 'some setup', + }, + patch: {}, + upgrade: { + type: 'query', + setup: 'some setup', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'setup', + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueNoUpdate, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'setup', + resolvedValue: 'Resolved setup', + expectedFieldsAfterUpgrade: { setup: 'Resolved setup' }, + }, + getService + ); + }); + + describe('non-customized w/ an upgrade (AAB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + setup: 'some setup', + }, + patch: {}, + upgrade: { + type: 'query', + setup: 'updated setup', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'setup', + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueCanUpdate, + expectedFieldDiffValues: { + base: 'some setup', + current: 'some setup', + target: 'updated setup', + merged: 'updated setup', + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'setup', + expectedFieldsAfterUpgrade: { setup: 'updated setup' }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'setup', + resolvedValue: 'Resolved setup', + expectedFieldsAfterUpgrade: { setup: 'Resolved setup' }, + }, + getService + ); + }); + + describe('customized w/o an upgrade (ABA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + setup: 'some setup', + }, + patch: { + setup: 'customized setup', + }, + upgrade: { + type: 'query', + setup: 'some setup', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'setup', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueNoUpdate, + expectedFieldDiffValues: { + base: 'some setup', + current: 'customized setup', + target: 'some setup', + merged: 'customized setup', + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'setup', + expectedFieldsAfterUpgrade: { setup: 'customized setup' }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'setup', + resolvedValue: 'Resolved setup', + expectedFieldsAfterUpgrade: { setup: 'Resolved setup' }, + }, + getService + ); + }); + + describe('customized w/ the matching upgrade (ABB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + setup: 'some setup', + }, + patch: { + setup: 'updated setup', + }, + upgrade: { + type: 'query', + setup: 'updated setup', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'setup', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueSameUpdate, + expectedFieldDiffValues: { + base: 'some setup', + current: 'updated setup', + target: 'updated setup', + merged: 'updated setup', + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'setup', + expectedFieldsAfterUpgrade: { setup: 'updated setup' }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'setup', + resolvedValue: 'Resolved setup', + expectedFieldsAfterUpgrade: { setup: 'Resolved setup' }, + }, + getService + ); + }); + + describe('customized w/ an upgrade resulting in a conflict (ABC diff case, solvable conflict)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + setup: 'line 1\nline 2', + }, + patch: { + setup: 'Customized line\nline 1\nline 2', + }, + upgrade: { + type: 'query', + setup: 'line 1\nline 3', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'setup', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueCanUpdate, + isSolvableConflict: true, + expectedFieldDiffValues: { + base: 'line 1\nline 2', + current: 'Customized line\nline 1\nline 2', + target: 'line 1\nline 3', + merged: 'Customized line\nline 1\nline 3', + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'setup', + resolvedValue: 'Resolved setup', + expectedFieldsAfterUpgrade: { setup: 'Resolved setup' }, + }, + getService + ); + }); + + describe('without historical versions', () => { + describe('customized w/ the matching upgrade (-AA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + setup: 'some setup', + }, + patch: { + setup: 'updated setup', + }, + upgrade: { + type: 'query', + setup: 'updated setup', + }, + removeInstalledAssets: true, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'setup', + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseNoUpdate, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'setup', + resolvedValue: 'Resolved setup', + expectedFieldsAfterUpgrade: { setup: 'Resolved setup' }, + }, + getService + ); + }); + + describe('customized w/ an upgrade (-AB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + setup: 'some setup', + }, + patch: { + setup: 'customized setup', + }, + upgrade: { + type: 'query', + setup: 'updated setup', + }, + removeInstalledAssets: true, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'setup', + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseCanUpdate, + expectedFieldDiffValues: { + current: 'customized setup', + target: 'updated setup', + merged: 'updated setup', + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'setup', + resolvedValue: 'Resolved setup', + expectedFieldsAfterUpgrade: { setup: 'Resolved setup' }, + }, + getService + ); + }); + }); + }); +} diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/severity.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/severity.ts new file mode 100644 index 0000000000000..57183c1f76870 --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/severity.ts @@ -0,0 +1,321 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { ThreeWayDiffOutcome } from '@kbn/security-solution-plugin/common/api/detection_engine'; +import { FtrProviderContext } from '../../../../../../../../ftr_provider_context'; +import type { TestFieldRuleUpgradeAssets } from '../test_helpers'; +import { + testFieldUpgradeReview, + testFieldUpgradesToMergedValue, + testFieldUpgradesToResolvedValue, +} from '../test_helpers'; + +export function severityField({ getService }: FtrProviderContext): void { + describe('"severity"', () => { + describe('non-customized w/o an upgrade (AAA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + severity: 'low', + }, + patch: {}, + upgrade: { + type: 'query', + severity: 'low', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'severity', + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueNoUpdate, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'severity', + resolvedValue: 'critical', + expectedFieldsAfterUpgrade: { severity: 'critical' }, + }, + getService + ); + }); + + describe('non-customized w/ an upgrade (AAB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + severity: 'low', + }, + patch: {}, + upgrade: { + type: 'query', + severity: 'high', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'severity', + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueCanUpdate, + expectedFieldDiffValues: { + base: 'low', + current: 'low', + target: 'high', + merged: 'high', + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'severity', + expectedFieldsAfterUpgrade: { severity: 'high' }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'severity', + resolvedValue: 'critical', + expectedFieldsAfterUpgrade: { severity: 'critical' }, + }, + getService + ); + }); + + describe('customized w/o an upgrade (ABA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + severity: 'low', + }, + patch: { + severity: 'medium', + }, + upgrade: { + type: 'query', + severity: 'low', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'severity', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueNoUpdate, + expectedFieldDiffValues: { + base: 'low', + current: 'medium', + target: 'low', + merged: 'medium', + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'severity', + expectedFieldsAfterUpgrade: { severity: 'medium' }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'severity', + resolvedValue: 'critical', + expectedFieldsAfterUpgrade: { severity: 'critical' }, + }, + getService + ); + }); + + describe('customized w/ the matching upgrade (ABB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + severity: 'low', + }, + patch: { + severity: 'medium', + }, + upgrade: { + type: 'query', + severity: 'medium', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'severity', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueSameUpdate, + expectedFieldDiffValues: { + base: 'low', + current: 'medium', + target: 'medium', + merged: 'medium', + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'severity', + expectedFieldsAfterUpgrade: { severity: 'medium' }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'severity', + resolvedValue: 'critical', + expectedFieldsAfterUpgrade: { severity: 'critical' }, + }, + getService + ); + }); + + describe('customized w/ an upgrade resulting in a conflict (ABC diff case, non-solvable conflict)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + severity: 'low', + }, + patch: { + severity: 'medium', + }, + upgrade: { + type: 'query', + severity: 'high', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'severity', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueCanUpdate, + isSolvableConflict: false, + expectedFieldDiffValues: { + base: 'low', + current: 'medium', + target: 'high', + merged: 'medium', + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'severity', + resolvedValue: 'critical', + expectedFieldsAfterUpgrade: { severity: 'critical' }, + }, + getService + ); + }); + + describe('without historical versions', () => { + describe('customized w/ the matching upgrade (-AA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + severity: 'low', + }, + patch: { + severity: 'medium', + }, + upgrade: { + type: 'query', + severity: 'medium', + }, + removeInstalledAssets: true, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'severity', + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseNoUpdate, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'severity', + resolvedValue: 'critical', + expectedFieldsAfterUpgrade: { severity: 'critical' }, + }, + getService + ); + }); + + describe('customized w/ an upgrade (-AB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + severity: 'low', + }, + patch: { + severity: 'medium', + }, + upgrade: { + type: 'query', + severity: 'high', + }, + removeInstalledAssets: true, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'severity', + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseCanUpdate, + expectedFieldDiffValues: { + current: 'medium', + target: 'high', + merged: 'high', + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'severity', + resolvedValue: 'critical', + expectedFieldsAfterUpgrade: { severity: 'critical' }, + }, + getService + ); + }); + }); + }); +} diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/severity_mapping.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/severity_mapping.ts new file mode 100644 index 0000000000000..6cd09f94d9650 --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/severity_mapping.ts @@ -0,0 +1,726 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { ThreeWayDiffOutcome } from '@kbn/security-solution-plugin/common/api/detection_engine'; +import { FtrProviderContext } from '../../../../../../../../ftr_provider_context'; +import type { TestFieldRuleUpgradeAssets } from '../test_helpers'; +import { + testFieldUpgradeReview, + testFieldUpgradesToMergedValue, + testFieldUpgradesToResolvedValue, +} from '../test_helpers'; + +export function severityMappingField({ getService }: FtrProviderContext): void { + describe('"severity_mapping"', () => { + describe('non-customized w/o an upgrade (AAA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + severity_mapping: [ + { + field: 'fieldA', + operator: 'equals', + severity: 'low', + value: '10', + }, + ], + }, + patch: {}, + upgrade: { + type: 'query', + severity_mapping: [ + { + field: 'fieldA', + operator: 'equals', + severity: 'low', + value: '10', + }, + ], + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'severity_mapping', + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueNoUpdate, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'severity_mapping', + resolvedValue: [ + { + field: 'resolved', + operator: 'equals', + severity: 'high', + value: '50', + }, + ], + expectedFieldsAfterUpgrade: { + severity_mapping: [ + { + field: 'resolved', + operator: 'equals', + severity: 'high', + value: '50', + }, + ], + }, + }, + getService + ); + }); + + describe('non-customized w/ an upgrade (AAB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + severity_mapping: [ + { + field: 'fieldA', + operator: 'equals', + severity: 'low', + value: '10', + }, + ], + }, + patch: {}, + upgrade: { + type: 'query', + severity_mapping: [ + { + field: 'fieldB', + operator: 'equals', + severity: 'high', + value: '20', + }, + ], + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'severity_mapping', + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueCanUpdate, + expectedFieldDiffValues: { + base: [ + { + field: 'fieldA', + operator: 'equals', + severity: 'low', + value: '10', + }, + ], + current: [ + { + field: 'fieldA', + operator: 'equals', + severity: 'low', + value: '10', + }, + ], + target: [ + { + field: 'fieldB', + operator: 'equals', + severity: 'high', + value: '20', + }, + ], + merged: [ + { + field: 'fieldB', + operator: 'equals', + severity: 'high', + value: '20', + }, + ], + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'severity_mapping', + expectedFieldsAfterUpgrade: { + severity_mapping: [ + { + field: 'fieldB', + operator: 'equals', + severity: 'high', + value: '20', + }, + ], + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'severity_mapping', + resolvedValue: [ + { + field: 'resolved', + operator: 'equals', + severity: 'high', + value: '50', + }, + ], + expectedFieldsAfterUpgrade: { + severity_mapping: [ + { + field: 'resolved', + operator: 'equals', + severity: 'high', + value: '50', + }, + ], + }, + }, + getService + ); + }); + + describe('customized w/o an upgrade (ABA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + severity_mapping: [ + { + field: 'fieldA', + operator: 'equals', + severity: 'low', + value: '10', + }, + ], + }, + patch: { + severity_mapping: [ + { + field: 'fieldB', + operator: 'equals', + severity: 'medium', + value: '30', + }, + ], + }, + upgrade: { + type: 'query', + severity_mapping: [ + { + field: 'fieldA', + operator: 'equals', + severity: 'low', + value: '10', + }, + ], + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'severity_mapping', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueNoUpdate, + expectedFieldDiffValues: { + base: [ + { + field: 'fieldA', + operator: 'equals', + severity: 'low', + value: '10', + }, + ], + current: [ + { + field: 'fieldB', + operator: 'equals', + severity: 'medium', + value: '30', + }, + ], + target: [ + { + field: 'fieldA', + operator: 'equals', + severity: 'low', + value: '10', + }, + ], + merged: [ + { + field: 'fieldB', + operator: 'equals', + severity: 'medium', + value: '30', + }, + ], + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'severity_mapping', + expectedFieldsAfterUpgrade: { + severity_mapping: [ + { + field: 'fieldB', + operator: 'equals', + severity: 'medium', + value: '30', + }, + ], + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'severity_mapping', + resolvedValue: [ + { + field: 'resolved', + operator: 'equals', + severity: 'high', + value: '50', + }, + ], + expectedFieldsAfterUpgrade: { + severity_mapping: [ + { + field: 'resolved', + operator: 'equals', + severity: 'high', + value: '50', + }, + ], + }, + }, + getService + ); + }); + + describe('customized w/ the matching upgrade (ABB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + severity_mapping: [ + { + field: 'fieldA', + operator: 'equals', + severity: 'low', + value: '10', + }, + ], + }, + patch: { + severity_mapping: [ + { + field: 'fieldB', + operator: 'equals', + severity: 'medium', + value: '30', + }, + ], + }, + upgrade: { + type: 'query', + severity_mapping: [ + { + field: 'fieldB', + operator: 'equals', + severity: 'medium', + value: '30', + }, + ], + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'severity_mapping', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueSameUpdate, + expectedFieldDiffValues: { + base: [ + { + field: 'fieldA', + operator: 'equals', + severity: 'low', + value: '10', + }, + ], + current: [ + { + field: 'fieldB', + operator: 'equals', + severity: 'medium', + value: '30', + }, + ], + target: [ + { + field: 'fieldB', + operator: 'equals', + severity: 'medium', + value: '30', + }, + ], + merged: [ + { + field: 'fieldB', + operator: 'equals', + severity: 'medium', + value: '30', + }, + ], + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'severity_mapping', + expectedFieldsAfterUpgrade: { + severity_mapping: [ + { + field: 'fieldB', + operator: 'equals', + severity: 'medium', + value: '30', + }, + ], + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'severity_mapping', + resolvedValue: [ + { + field: 'resolved', + operator: 'equals', + severity: 'high', + value: '50', + }, + ], + expectedFieldsAfterUpgrade: { + severity_mapping: [ + { + field: 'resolved', + operator: 'equals', + severity: 'high', + value: '50', + }, + ], + }, + }, + getService + ); + }); + + describe('customized w/ an upgrade resulting in a conflict (ABC diff case, non-solvable conflict)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + severity_mapping: [ + { + field: 'fieldA', + operator: 'equals', + severity: 'low', + value: '10', + }, + ], + }, + patch: { + severity_mapping: [ + { + field: 'fieldB', + operator: 'equals', + severity: 'medium', + value: '30', + }, + ], + }, + upgrade: { + type: 'query', + severity_mapping: [ + { + field: 'fieldC', + operator: 'equals', + severity: 'high', + value: '50', + }, + ], + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'severity_mapping', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueCanUpdate, + isSolvableConflict: false, + expectedFieldDiffValues: { + base: [ + { + field: 'fieldA', + operator: 'equals', + severity: 'low', + value: '10', + }, + ], + current: [ + { + field: 'fieldB', + operator: 'equals', + severity: 'medium', + value: '30', + }, + ], + target: [ + { + field: 'fieldC', + operator: 'equals', + severity: 'high', + value: '50', + }, + ], + merged: [ + { + field: 'fieldB', + operator: 'equals', + severity: 'medium', + value: '30', + }, + ], + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'severity_mapping', + resolvedValue: [ + { + field: 'resolved', + operator: 'equals', + severity: 'high', + value: '50', + }, + ], + expectedFieldsAfterUpgrade: { + severity_mapping: [ + { + field: 'resolved', + operator: 'equals', + severity: 'high', + value: '50', + }, + ], + }, + }, + getService + ); + }); + + describe('without historical versions', () => { + describe('customized w/ the matching upgrade (-AA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + severity_mapping: [ + { + field: 'fieldA', + operator: 'equals', + severity: 'low', + value: '10', + }, + ], + }, + patch: { + severity_mapping: [ + { + field: 'fieldB', + operator: 'equals', + severity: 'medium', + value: '30', + }, + ], + }, + upgrade: { + type: 'query', + severity_mapping: [ + { + field: 'fieldB', + operator: 'equals', + severity: 'medium', + value: '30', + }, + ], + }, + removeInstalledAssets: true, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'severity_mapping', + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseNoUpdate, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'severity_mapping', + resolvedValue: [ + { + field: 'resolved', + operator: 'equals', + severity: 'high', + value: '50', + }, + ], + expectedFieldsAfterUpgrade: { + severity_mapping: [ + { + field: 'resolved', + operator: 'equals', + severity: 'high', + value: '50', + }, + ], + }, + }, + getService + ); + }); + + describe('customized w/ an upgrade (-AB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + severity_mapping: [ + { + field: 'fieldA', + operator: 'equals', + severity: 'low', + value: '10', + }, + ], + }, + patch: { + severity_mapping: [ + { + field: 'fieldB', + operator: 'equals', + severity: 'medium', + value: '30', + }, + ], + }, + upgrade: { + type: 'query', + severity_mapping: [ + { + field: 'fieldC', + operator: 'equals', + severity: 'high', + value: '50', + }, + ], + }, + removeInstalledAssets: true, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'severity_mapping', + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseCanUpdate, + expectedFieldDiffValues: { + current: [ + { + field: 'fieldB', + operator: 'equals', + severity: 'medium', + value: '30', + }, + ], + target: [ + { + field: 'fieldC', + operator: 'equals', + severity: 'high', + value: '50', + }, + ], + merged: [ + { + field: 'fieldC', + operator: 'equals', + severity: 'high', + value: '50', + }, + ], + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'severity_mapping', + resolvedValue: [ + { + field: 'resolved', + operator: 'equals', + severity: 'high', + value: '50', + }, + ], + expectedFieldsAfterUpgrade: { + severity_mapping: [ + { + field: 'resolved', + operator: 'equals', + severity: 'high', + value: '50', + }, + ], + }, + }, + getService + ); + }); + }); + }); +} diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/tags.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/tags.ts new file mode 100644 index 0000000000000..880ec3ed29f3a --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/tags.ts @@ -0,0 +1,321 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { ThreeWayDiffOutcome } from '@kbn/security-solution-plugin/common/api/detection_engine'; +import { FtrProviderContext } from '../../../../../../../../ftr_provider_context'; +import type { TestFieldRuleUpgradeAssets } from '../test_helpers'; +import { + testFieldUpgradeReview, + testFieldUpgradesToMergedValue, + testFieldUpgradesToResolvedValue, +} from '../test_helpers'; + +export function tagsField({ getService }: FtrProviderContext): void { + describe('"tags"', () => { + describe('non-customized w/o an upgrade (AAA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + tags: ['tagA'], + }, + patch: {}, + upgrade: { + type: 'query', + tags: ['tagA'], + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'tags', + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueNoUpdate, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'tags', + resolvedValue: ['resolved'], + expectedFieldsAfterUpgrade: { tags: ['resolved'] }, + }, + getService + ); + }); + + describe('non-customized w/ an upgrade (AAB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + tags: ['tagA'], + }, + patch: {}, + upgrade: { + type: 'query', + tags: ['tagB'], + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'tags', + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueCanUpdate, + expectedFieldDiffValues: { + base: ['tagA'], + current: ['tagA'], + target: ['tagB'], + merged: ['tagB'], + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'tags', + expectedFieldsAfterUpgrade: { tags: ['tagB'] }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'tags', + resolvedValue: ['resolved'], + expectedFieldsAfterUpgrade: { tags: ['resolved'] }, + }, + getService + ); + }); + + describe('customized w/o an upgrade (ABA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + tags: ['tagA'], + }, + patch: { + tags: ['tagB'], + }, + upgrade: { + type: 'query', + tags: ['tagA'], + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'tags', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueNoUpdate, + expectedFieldDiffValues: { + base: ['tagA'], + current: ['tagB'], + target: ['tagA'], + merged: ['tagB'], + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'tags', + expectedFieldsAfterUpgrade: { tags: ['tagB'] }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'tags', + resolvedValue: ['resolved'], + expectedFieldsAfterUpgrade: { tags: ['resolved'] }, + }, + getService + ); + }); + + describe('customized w/ the matching upgrade (ABB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + tags: ['tagA'], + }, + patch: { + tags: ['tagB'], + }, + upgrade: { + type: 'query', + tags: ['tagB'], + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'tags', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueSameUpdate, + expectedFieldDiffValues: { + base: ['tagA'], + current: ['tagB'], + target: ['tagB'], + merged: ['tagB'], + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'tags', + expectedFieldsAfterUpgrade: { tags: ['tagB'] }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'tags', + resolvedValue: ['resolved'], + expectedFieldsAfterUpgrade: { tags: ['resolved'] }, + }, + getService + ); + }); + + describe('customized w/ an upgrade resulting in a conflict (ABC diff case, solvable conflict)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + tags: ['tagA'], + }, + patch: { + tags: ['tagB'], + }, + upgrade: { + type: 'query', + tags: ['tagC'], + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'tags', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueCanUpdate, + isSolvableConflict: true, + expectedFieldDiffValues: { + base: ['tagA'], + current: ['tagB'], + target: ['tagC'], + merged: ['tagB', 'tagC'], + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'tags', + resolvedValue: ['resolved'], + expectedFieldsAfterUpgrade: { tags: ['resolved'] }, + }, + getService + ); + }); + + describe('without historical versions', () => { + describe('customized w/ the matching upgrade (-AA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + tags: ['tagA'], + }, + patch: { + tags: ['tagB'], + }, + upgrade: { + type: 'query', + tags: ['tagB'], + }, + removeInstalledAssets: true, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'tags', + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseNoUpdate, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'tags', + resolvedValue: ['resolved'], + expectedFieldsAfterUpgrade: { tags: ['resolved'] }, + }, + getService + ); + }); + + describe('customized w/ an upgrade (-AB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + tags: ['tagA'], + }, + patch: { + tags: ['tagB'], + }, + upgrade: { + type: 'query', + tags: ['tagC'], + }, + removeInstalledAssets: true, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'tags', + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseCanUpdate, + expectedFieldDiffValues: { + current: ['tagB'], + target: ['tagC'], + merged: ['tagC'], + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'tags', + resolvedValue: ['resolved'], + expectedFieldsAfterUpgrade: { tags: ['resolved'] }, + }, + getService + ); + }); + }); + }); +} diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/threat.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/threat.ts new file mode 100644 index 0000000000000..2e001b5322de0 --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/threat.ts @@ -0,0 +1,836 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { ThreeWayDiffOutcome } from '@kbn/security-solution-plugin/common/api/detection_engine'; +import { FtrProviderContext } from '../../../../../../../../ftr_provider_context'; +import type { TestFieldRuleUpgradeAssets } from '../test_helpers'; +import { + testFieldUpgradeReview, + testFieldUpgradesToMergedValue, + testFieldUpgradesToResolvedValue, +} from '../test_helpers'; + +export function threatField({ getService }: FtrProviderContext): void { + describe('"threat"', () => { + describe('non-customized w/o an upgrade (AAA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + threat: [ + { + framework: 'something', + tactic: { + name: 'tacticA', + id: 'tacticA', + reference: 'reference', + }, + }, + ], + }, + patch: {}, + upgrade: { + type: 'query', + threat: [ + { + framework: 'something', + tactic: { + name: 'tacticA', + id: 'tacticA', + reference: 'reference', + }, + }, + ], + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat', + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueNoUpdate, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat', + resolvedValue: [ + { + framework: 'something', + tactic: { + name: 'resolved', + id: 'resolved', + reference: 'reference', + }, + }, + ], + expectedFieldsAfterUpgrade: { + threat: [ + { + framework: 'something', + tactic: { + name: 'resolved', + id: 'resolved', + reference: 'reference', + }, + }, + ], + }, + }, + getService + ); + }); + + describe('non-customized w/ an upgrade (AAB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + threat: [ + { + framework: 'something', + tactic: { + name: 'tacticA', + id: 'tacticA', + reference: 'reference', + }, + }, + ], + }, + patch: {}, + upgrade: { + type: 'query', + threat: [ + { + framework: 'something', + tactic: { + name: 'tacticB', + id: 'tacticB', + reference: 'reference', + }, + }, + ], + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat', + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueCanUpdate, + expectedFieldDiffValues: { + base: [ + { + framework: 'something', + tactic: { + name: 'tacticA', + id: 'tacticA', + reference: 'reference', + }, + }, + ], + current: [ + { + framework: 'something', + tactic: { + name: 'tacticA', + id: 'tacticA', + reference: 'reference', + }, + }, + ], + target: [ + { + framework: 'something', + tactic: { + name: 'tacticB', + id: 'tacticB', + reference: 'reference', + }, + }, + ], + merged: [ + { + framework: 'something', + tactic: { + name: 'tacticB', + id: 'tacticB', + reference: 'reference', + }, + }, + ], + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat', + expectedFieldsAfterUpgrade: { + threat: [ + { + framework: 'something', + tactic: { + name: 'tacticB', + id: 'tacticB', + reference: 'reference', + }, + }, + ], + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat', + resolvedValue: [ + { + framework: 'something', + tactic: { + name: 'resolved', + id: 'resolved', + reference: 'reference', + }, + }, + ], + expectedFieldsAfterUpgrade: { + threat: [ + { + framework: 'something', + tactic: { + name: 'resolved', + id: 'resolved', + reference: 'reference', + }, + }, + ], + }, + }, + getService + ); + }); + + describe('customized w/o an upgrade (ABA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + threat: [ + { + framework: 'something', + tactic: { + name: 'tacticA', + id: 'tacticA', + reference: 'reference', + }, + }, + ], + }, + patch: { + threat: [ + { + framework: 'something', + tactic: { + name: 'tacticB', + id: 'tacticB', + reference: 'reference', + }, + }, + ], + }, + upgrade: { + type: 'query', + threat: [ + { + framework: 'something', + tactic: { + name: 'tacticA', + id: 'tacticA', + reference: 'reference', + }, + }, + ], + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueNoUpdate, + expectedFieldDiffValues: { + base: [ + { + framework: 'something', + tactic: { + name: 'tacticA', + id: 'tacticA', + reference: 'reference', + }, + }, + ], + current: [ + { + framework: 'something', + tactic: { + name: 'tacticB', + id: 'tacticB', + reference: 'reference', + }, + }, + ], + target: [ + { + framework: 'something', + tactic: { + name: 'tacticA', + id: 'tacticA', + reference: 'reference', + }, + }, + ], + merged: [ + { + framework: 'something', + tactic: { + name: 'tacticB', + id: 'tacticB', + reference: 'reference', + }, + }, + ], + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat', + expectedFieldsAfterUpgrade: { + threat: [ + { + framework: 'something', + tactic: { + name: 'tacticB', + id: 'tacticB', + reference: 'reference', + }, + }, + ], + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat', + resolvedValue: [ + { + framework: 'something', + tactic: { + name: 'resolved', + id: 'resolved', + reference: 'reference', + }, + }, + ], + expectedFieldsAfterUpgrade: { + threat: [ + { + framework: 'something', + tactic: { + name: 'resolved', + id: 'resolved', + reference: 'reference', + }, + }, + ], + }, + }, + getService + ); + }); + + describe('customized w/ the matching upgrade (ABB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + threat: [ + { + framework: 'something', + tactic: { + name: 'tacticA', + id: 'tacticA', + reference: 'reference', + }, + }, + ], + }, + patch: { + threat: [ + { + framework: 'something', + tactic: { + name: 'tacticB', + id: 'tacticB', + reference: 'reference', + }, + }, + ], + }, + upgrade: { + type: 'query', + threat: [ + { + framework: 'something', + tactic: { + name: 'tacticB', + id: 'tacticB', + reference: 'reference', + }, + }, + ], + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueSameUpdate, + expectedFieldDiffValues: { + base: [ + { + framework: 'something', + tactic: { + name: 'tacticA', + id: 'tacticA', + reference: 'reference', + }, + }, + ], + current: [ + { + framework: 'something', + tactic: { + name: 'tacticB', + id: 'tacticB', + reference: 'reference', + }, + }, + ], + target: [ + { + framework: 'something', + tactic: { + name: 'tacticB', + id: 'tacticB', + reference: 'reference', + }, + }, + ], + merged: [ + { + framework: 'something', + tactic: { + name: 'tacticB', + id: 'tacticB', + reference: 'reference', + }, + }, + ], + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat', + expectedFieldsAfterUpgrade: { + threat: [ + { + framework: 'something', + tactic: { + name: 'tacticB', + id: 'tacticB', + reference: 'reference', + }, + }, + ], + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat', + resolvedValue: [ + { + framework: 'something', + tactic: { + name: 'resolved', + id: 'resolved', + reference: 'reference', + }, + }, + ], + expectedFieldsAfterUpgrade: { + threat: [ + { + framework: 'something', + tactic: { + name: 'resolved', + id: 'resolved', + reference: 'reference', + }, + }, + ], + }, + }, + getService + ); + }); + + describe('customized w/ an upgrade resulting in a conflict (ABC diff case, non-solvable conflict)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + threat: [ + { + framework: 'something', + tactic: { + name: 'tacticA', + id: 'tacticA', + reference: 'reference', + }, + }, + ], + }, + patch: { + threat: [ + { + framework: 'something', + tactic: { + name: 'tacticB', + id: 'tacticB', + reference: 'reference', + }, + }, + ], + }, + upgrade: { + type: 'query', + threat: [ + { + framework: 'something', + tactic: { + name: 'tacticC', + id: 'tacticC', + reference: 'reference', + }, + }, + ], + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueCanUpdate, + isSolvableConflict: false, + expectedFieldDiffValues: { + base: [ + { + framework: 'something', + tactic: { + name: 'tacticA', + id: 'tacticA', + reference: 'reference', + }, + }, + ], + current: [ + { + framework: 'something', + tactic: { + name: 'tacticB', + id: 'tacticB', + reference: 'reference', + }, + }, + ], + target: [ + { + framework: 'something', + tactic: { + name: 'tacticC', + id: 'tacticC', + reference: 'reference', + }, + }, + ], + merged: [ + { + framework: 'something', + tactic: { + name: 'tacticB', + id: 'tacticB', + reference: 'reference', + }, + }, + ], + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat', + resolvedValue: [ + { + framework: 'something', + tactic: { + name: 'resolved', + id: 'resolved', + reference: 'reference', + }, + }, + ], + expectedFieldsAfterUpgrade: { + threat: [ + { + framework: 'something', + tactic: { + name: 'resolved', + id: 'resolved', + reference: 'reference', + }, + }, + ], + }, + }, + getService + ); + }); + + describe('without historical versions', () => { + describe('customized w/ the matching upgrade (-AA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + threat: [ + { + framework: 'something', + tactic: { + name: 'tacticA', + id: 'tacticA', + reference: 'reference', + }, + }, + ], + }, + patch: { + threat: [ + { + framework: 'something', + tactic: { + name: 'tacticB', + id: 'tacticB', + reference: 'reference', + }, + }, + ], + }, + upgrade: { + type: 'query', + threat: [ + { + framework: 'something', + tactic: { + name: 'tacticB', + id: 'tacticB', + reference: 'reference', + }, + }, + ], + }, + removeInstalledAssets: true, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat', + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseNoUpdate, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat', + resolvedValue: [ + { + framework: 'something', + tactic: { + name: 'resolved', + id: 'resolved', + reference: 'reference', + }, + }, + ], + expectedFieldsAfterUpgrade: { + threat: [ + { + framework: 'something', + tactic: { + name: 'resolved', + id: 'resolved', + reference: 'reference', + }, + }, + ], + }, + }, + getService + ); + }); + + describe('customized w/ an upgrade (-AB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + threat: [ + { + framework: 'something', + tactic: { + name: 'tacticA', + id: 'tacticA', + reference: 'reference', + }, + }, + ], + }, + patch: { + threat: [ + { + framework: 'something', + tactic: { + name: 'tacticB', + id: 'tacticB', + reference: 'reference', + }, + }, + ], + }, + upgrade: { + type: 'query', + threat: [ + { + framework: 'something', + tactic: { + name: 'tacticC', + id: 'tacticC', + reference: 'reference', + }, + }, + ], + }, + removeInstalledAssets: true, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat', + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseCanUpdate, + expectedFieldDiffValues: { + current: [ + { + framework: 'something', + tactic: { + name: 'tacticB', + id: 'tacticB', + reference: 'reference', + }, + }, + ], + target: [ + { + framework: 'something', + tactic: { + name: 'tacticC', + id: 'tacticC', + reference: 'reference', + }, + }, + ], + merged: [ + { + framework: 'something', + tactic: { + name: 'tacticC', + id: 'tacticC', + reference: 'reference', + }, + }, + ], + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat', + resolvedValue: [ + { + framework: 'something', + tactic: { + name: 'resolved', + id: 'resolved', + reference: 'reference', + }, + }, + ], + expectedFieldsAfterUpgrade: { + threat: [ + { + framework: 'something', + tactic: { + name: 'resolved', + id: 'resolved', + reference: 'reference', + }, + }, + ], + }, + }, + getService + ); + }); + }); + }); +} diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/timeline_template.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/timeline_template.ts new file mode 100644 index 0000000000000..911500e0bb346 --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/timeline_template.ts @@ -0,0 +1,361 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { ThreeWayDiffOutcome } from '@kbn/security-solution-plugin/common/api/detection_engine'; +import { FtrProviderContext } from '../../../../../../../../ftr_provider_context'; +import type { TestFieldRuleUpgradeAssets } from '../test_helpers'; +import { + testFieldUpgradeReview, + testFieldUpgradesToMergedValue, + testFieldUpgradesToResolvedValue, +} from '../test_helpers'; + +export function timelineTemplateField({ getService }: FtrProviderContext): void { + describe('"timeline_template"', () => { + describe('non-customized w/o an upgrade (AAA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + timeline_id: 'A', + timeline_title: 'timelineA', + }, + patch: {}, + upgrade: { + type: 'query', + timeline_id: 'A', + timeline_title: 'timelineA', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'timeline_template', + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueNoUpdate, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'timeline_template', + resolvedValue: { timeline_id: 'resolved', timeline_title: 'timelineResolved' }, + expectedFieldsAfterUpgrade: { + timeline_id: 'resolved', + timeline_title: 'timelineResolved', + }, + }, + getService + ); + }); + + describe('non-customized w/ an upgrade (AAB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + timeline_id: 'A', + timeline_title: 'timelineA', + }, + patch: {}, + upgrade: { + type: 'query', + timeline_id: 'B', + timeline_title: 'timelineB', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'timeline_template', + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueCanUpdate, + expectedFieldDiffValues: { + base: { timeline_id: 'A', timeline_title: 'timelineA' }, + current: { timeline_id: 'A', timeline_title: 'timelineA' }, + target: { timeline_id: 'B', timeline_title: 'timelineB' }, + merged: { timeline_id: 'B', timeline_title: 'timelineB' }, + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'timeline_template', + expectedFieldsAfterUpgrade: { timeline_id: 'B', timeline_title: 'timelineB' }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'timeline_template', + resolvedValue: { timeline_id: 'resolved', timeline_title: 'timelineResolved' }, + expectedFieldsAfterUpgrade: { + timeline_id: 'resolved', + timeline_title: 'timelineResolved', + }, + }, + getService + ); + }); + + describe('customized w/o an upgrade (ABA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + timeline_id: 'A', + timeline_title: 'timelineA', + }, + patch: { + timeline_id: 'B', + timeline_title: 'timelineB', + }, + upgrade: { + type: 'query', + timeline_id: 'A', + timeline_title: 'timelineA', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'timeline_template', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueNoUpdate, + expectedFieldDiffValues: { + base: { timeline_id: 'A', timeline_title: 'timelineA' }, + current: { timeline_id: 'B', timeline_title: 'timelineB' }, + target: { timeline_id: 'A', timeline_title: 'timelineA' }, + merged: { timeline_id: 'B', timeline_title: 'timelineB' }, + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'timeline_template', + expectedFieldsAfterUpgrade: { timeline_id: 'B', timeline_title: 'timelineB' }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'timeline_template', + resolvedValue: { timeline_id: 'resolved', timeline_title: 'timelineResolved' }, + expectedFieldsAfterUpgrade: { + timeline_id: 'resolved', + timeline_title: 'timelineResolved', + }, + }, + getService + ); + }); + + describe('customized w/ the matching upgrade (ABB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + timeline_id: 'A', + timeline_title: 'timelineA', + }, + patch: { + timeline_id: 'B', + timeline_title: 'timelineB', + }, + upgrade: { + type: 'query', + timeline_id: 'B', + timeline_title: 'timelineB', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'timeline_template', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueSameUpdate, + expectedFieldDiffValues: { + base: { timeline_id: 'A', timeline_title: 'timelineA' }, + current: { timeline_id: 'B', timeline_title: 'timelineB' }, + target: { timeline_id: 'B', timeline_title: 'timelineB' }, + merged: { timeline_id: 'B', timeline_title: 'timelineB' }, + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'timeline_template', + expectedFieldsAfterUpgrade: { timeline_id: 'B', timeline_title: 'timelineB' }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'timeline_template', + resolvedValue: { timeline_id: 'resolved', timeline_title: 'timelineResolved' }, + expectedFieldsAfterUpgrade: { + timeline_id: 'resolved', + timeline_title: 'timelineResolved', + }, + }, + getService + ); + }); + + describe('customized w/ an upgrade resulting in a conflict (ABC diff case, non-solvable conflict)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + timeline_id: 'A', + timeline_title: 'timelineA', + }, + patch: { + timeline_id: 'B', + timeline_title: 'timelineB', + }, + upgrade: { + type: 'query', + timeline_id: 'C', + timeline_title: 'timelineC', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'timeline_template', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueCanUpdate, + isSolvableConflict: false, + expectedFieldDiffValues: { + base: { timeline_id: 'A', timeline_title: 'timelineA' }, + current: { timeline_id: 'B', timeline_title: 'timelineB' }, + target: { timeline_id: 'C', timeline_title: 'timelineC' }, + merged: { timeline_id: 'B', timeline_title: 'timelineB' }, + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'timeline_template', + resolvedValue: { timeline_id: 'resolved', timeline_title: 'timelineResolved' }, + expectedFieldsAfterUpgrade: { + timeline_id: 'resolved', + timeline_title: 'timelineResolved', + }, + }, + getService + ); + }); + + describe('without historical versions', () => { + describe('customized w/ the matching upgrade (-AA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + timeline_id: 'A', + timeline_title: 'timelineA', + }, + patch: { + timeline_id: 'B', + timeline_title: 'timelineB', + }, + upgrade: { + type: 'query', + timeline_id: 'B', + timeline_title: 'timelineB', + }, + removeInstalledAssets: true, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'timeline_template', + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseNoUpdate, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'timeline_template', + resolvedValue: { timeline_id: 'resolved', timeline_title: 'timelineResolved' }, + expectedFieldsAfterUpgrade: { + timeline_id: 'resolved', + timeline_title: 'timelineResolved', + }, + }, + getService + ); + }); + + describe('customized w/ an upgrade (-AB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + timeline_id: 'A', + timeline_title: 'timelineA', + }, + patch: { + timeline_id: 'B', + timeline_title: 'timelineB', + }, + upgrade: { + type: 'query', + timeline_id: 'C', + timeline_title: 'timelineC', + }, + removeInstalledAssets: true, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'timeline_template', + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseCanUpdate, + expectedFieldDiffValues: { + current: { timeline_id: 'B', timeline_title: 'timelineB' }, + target: { timeline_id: 'C', timeline_title: 'timelineC' }, + merged: { timeline_id: 'C', timeline_title: 'timelineC' }, + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'timeline_template', + resolvedValue: { timeline_id: 'resolved', timeline_title: 'timelineResolved' }, + expectedFieldsAfterUpgrade: { + timeline_id: 'resolved', + timeline_title: 'timelineResolved', + }, + }, + getService + ); + }); + }); + }); +} diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/timestamp_override.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/timestamp_override.ts new file mode 100644 index 0000000000000..a6529cfcd5c58 --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/common_fields/timestamp_override.ts @@ -0,0 +1,321 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { ThreeWayDiffOutcome } from '@kbn/security-solution-plugin/common/api/detection_engine'; +import { FtrProviderContext } from '../../../../../../../../ftr_provider_context'; +import type { TestFieldRuleUpgradeAssets } from '../test_helpers'; +import { + testFieldUpgradeReview, + testFieldUpgradesToMergedValue, + testFieldUpgradesToResolvedValue, +} from '../test_helpers'; + +export function timestampOverrideField({ getService }: FtrProviderContext): void { + describe('"timestamp_override"', () => { + describe('non-customized w/o an upgrade (AAA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + timestamp_override: 'fieldA', + }, + patch: {}, + upgrade: { + type: 'query', + timestamp_override: 'fieldA', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'timestamp_override', + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueNoUpdate, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'timestamp_override', + resolvedValue: { field_name: 'resolved', fallback_disabled: false }, + expectedFieldsAfterUpgrade: { timestamp_override: 'resolved' }, + }, + getService + ); + }); + + describe('non-customized w/ an upgrade (AAB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + timestamp_override: 'fieldA', + }, + patch: {}, + upgrade: { + type: 'query', + timestamp_override: 'fieldB', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'timestamp_override', + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueCanUpdate, + expectedFieldDiffValues: { + base: { field_name: 'fieldA', fallback_disabled: false }, + current: { field_name: 'fieldA', fallback_disabled: false }, + target: { field_name: 'fieldB', fallback_disabled: false }, + merged: { field_name: 'fieldB', fallback_disabled: false }, + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'timestamp_override', + expectedFieldsAfterUpgrade: { timestamp_override: 'fieldB' }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'timestamp_override', + resolvedValue: { field_name: 'resolved', fallback_disabled: false }, + expectedFieldsAfterUpgrade: { timestamp_override: 'resolved' }, + }, + getService + ); + }); + + describe('customized w/o an upgrade (ABA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + timestamp_override: 'fieldA', + }, + patch: { + timestamp_override: 'fieldB', + }, + upgrade: { + type: 'query', + timestamp_override: 'fieldA', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'timestamp_override', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueNoUpdate, + expectedFieldDiffValues: { + base: { field_name: 'fieldA', fallback_disabled: false }, + current: { field_name: 'fieldB', fallback_disabled: false }, + target: { field_name: 'fieldA', fallback_disabled: false }, + merged: { field_name: 'fieldB', fallback_disabled: false }, + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'timestamp_override', + expectedFieldsAfterUpgrade: { timestamp_override: 'fieldB' }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'timestamp_override', + resolvedValue: { field_name: 'resolved', fallback_disabled: false }, + expectedFieldsAfterUpgrade: { timestamp_override: 'resolved' }, + }, + getService + ); + }); + + describe('customized w/ the matching upgrade (ABB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + timestamp_override: 'fieldA', + }, + patch: { + timestamp_override: 'fieldB', + }, + upgrade: { + type: 'query', + timestamp_override: 'fieldB', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'timestamp_override', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueSameUpdate, + expectedFieldDiffValues: { + base: { field_name: 'fieldA', fallback_disabled: false }, + current: { field_name: 'fieldB', fallback_disabled: false }, + target: { field_name: 'fieldB', fallback_disabled: false }, + merged: { field_name: 'fieldB', fallback_disabled: false }, + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'timestamp_override', + expectedFieldsAfterUpgrade: { timestamp_override: 'fieldB' }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'timestamp_override', + resolvedValue: { field_name: 'resolved', fallback_disabled: false }, + expectedFieldsAfterUpgrade: { timestamp_override: 'resolved' }, + }, + getService + ); + }); + + describe('customized w/ an upgrade resulting in a conflict (ABC diff case, non-solvable conflict)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + timestamp_override: 'fieldA', + }, + patch: { + timestamp_override: 'fieldB', + }, + upgrade: { + type: 'query', + timestamp_override: 'fieldC', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'timestamp_override', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueCanUpdate, + isSolvableConflict: false, + expectedFieldDiffValues: { + base: { field_name: 'fieldA', fallback_disabled: false }, + current: { field_name: 'fieldB', fallback_disabled: false }, + target: { field_name: 'fieldC', fallback_disabled: false }, + merged: { field_name: 'fieldB', fallback_disabled: false }, + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'timestamp_override', + resolvedValue: { field_name: 'resolved', fallback_disabled: false }, + expectedFieldsAfterUpgrade: { timestamp_override: 'resolved' }, + }, + getService + ); + }); + + describe('without historical versions', () => { + describe('customized w/ the matching upgrade (-AA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + timestamp_override: 'fieldA', + }, + patch: { + timestamp_override: 'fieldB', + }, + upgrade: { + type: 'query', + timestamp_override: 'fieldB', + }, + removeInstalledAssets: true, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'timestamp_override', + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseNoUpdate, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'timestamp_override', + resolvedValue: { field_name: 'resolved', fallback_disabled: false }, + expectedFieldsAfterUpgrade: { timestamp_override: 'resolved' }, + }, + getService + ); + }); + + describe('customized w/ an upgrade (-AB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'query', + timestamp_override: 'fieldA', + }, + patch: { + timestamp_override: 'fieldB', + }, + upgrade: { + type: 'query', + timestamp_override: 'fieldC', + }, + removeInstalledAssets: true, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'timestamp_override', + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseCanUpdate, + expectedFieldDiffValues: { + current: { field_name: 'fieldB', fallback_disabled: false }, + target: { field_name: 'fieldC', fallback_disabled: false }, + merged: { field_name: 'fieldC', fallback_disabled: false }, + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'timestamp_override', + resolvedValue: { field_name: 'resolved', fallback_disabled: false }, + expectedFieldsAfterUpgrade: { timestamp_override: 'resolved' }, + }, + getService + ); + }); + }); + }); +} diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/test_helpers.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/test_helpers.ts new file mode 100644 index 0000000000000..48302fa6ef8a3 --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/test_helpers.ts @@ -0,0 +1,546 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import expect from 'expect'; +import { isUndefined, omitBy } from 'lodash'; +import type { + PartialRuleDiff, + RuleResponse, +} from '@kbn/security-solution-plugin/common/api/detection_engine'; +import { ModeEnum } from '@kbn/security-solution-plugin/common/api/detection_engine'; +import { + ThreeWayDiffConflict, + ThreeWayDiffOutcome, + ThreeWayMergeOutcome, +} from '@kbn/security-solution-plugin/common/api/detection_engine'; +import { + DEFAULT_RULE_UPDATE_VERSION, + DEFAULT_TEST_RULE_ID, + RuleUpgradeAssets, + setUpRuleUpgrade, +} from '../../../../../utils/rules/prebuilt_rules/set_up_rule_upgrade'; +import { + fetchFirstPrebuiltRuleUpgradeReviewDiff, + performUpgradePrebuiltRules, +} from '../../../../../utils'; +import { FtrProviderContext } from '../../../../../../../ftr_provider_context'; + +export interface TestFieldRuleUpgradeAssets extends RuleUpgradeAssets { + removeInstalledAssets?: boolean; +} + +interface FieldDiffValueVersions { + base: unknown; + current: unknown; + target: unknown; + merged: unknown; +} + +interface MissingHistoricalRuleVersionsFieldDiffValueVersions { + current: unknown; + target: unknown; + merged: unknown; +} + +interface TestFieldUpgradeReviewParams { + ruleUpgradeAssets: TestFieldRuleUpgradeAssets; + diffableRuleFieldName: string; +} + +type ExpectedDiffOutcome = + | { + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueNoUpdate; + } + | { + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueCanUpdate; + expectedFieldDiffValues: FieldDiffValueVersions; + } + | { + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueNoUpdate; + expectedFieldDiffValues: FieldDiffValueVersions; + } + | { + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueSameUpdate; + expectedFieldDiffValues: FieldDiffValueVersions; + } + | { + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueCanUpdate; + isSolvableConflict: boolean; + expectedFieldDiffValues: FieldDiffValueVersions; + } + | { + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseNoUpdate; + } + | { + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseCanUpdate; + expectedFieldDiffValues: MissingHistoricalRuleVersionsFieldDiffValueVersions; + }; + +/** + * Creates a test to assert rule upgrade review endpoint returns an expected result. + * + * CAUTION: The function expected provided `ruleUpgradeAssets` defined according to the `expectedDiffOutcome`. + * In the other words it means `ruleUpgradeAssets` should define a proper rule upgrade state for + * a `fieldName` like non-customized field without upgrade or customized field with an upgrade resulting + * in a conflict. + */ +export function testFieldUpgradeReview( + params: TestFieldUpgradeReviewParams & ExpectedDiffOutcome, + getService: FtrProviderContext['getService'] +): void { + const supertest = getService('supertest'); + const testName = + params.expectedDiffOutcome === ThreeWayDiffOutcome.StockValueNoUpdate || + params.expectedDiffOutcome === ThreeWayDiffOutcome.MissingBaseNoUpdate + ? 'does NOT return upgrade review' + : 'returns upgrade review'; + + it(testName, async () => { + await setUpRuleUpgrade({ + assets: params.ruleUpgradeAssets, + removeInstalledAssets: params.ruleUpgradeAssets.removeInstalledAssets ?? false, + deps: { + es: getService('es'), + supertest, + log: getService('log'), + }, + }); + + const diff = await fetchFirstPrebuiltRuleUpgradeReviewDiff(supertest); + + switch (params.expectedDiffOutcome) { + case ThreeWayDiffOutcome.StockValueNoUpdate: + expectAAAFieldDiff(diff, { diffableRuleFieldName: params.diffableRuleFieldName }); + break; + + case ThreeWayDiffOutcome.StockValueCanUpdate: + expectAABFieldDiff(diff, { + diffableRuleFieldName: params.diffableRuleFieldName, + valueVersions: params.expectedFieldDiffValues, + }); + break; + + case ThreeWayDiffOutcome.CustomizedValueNoUpdate: + expectABAFieldDiff(diff, { + diffableRuleFieldName: params.diffableRuleFieldName, + valueVersions: params.expectedFieldDiffValues, + }); + break; + + case ThreeWayDiffOutcome.CustomizedValueSameUpdate: + expectABBFieldDiff(diff, { + diffableRuleFieldName: params.diffableRuleFieldName, + valueVersions: params.expectedFieldDiffValues, + }); + break; + + case ThreeWayDiffOutcome.CustomizedValueCanUpdate: + if (params.isSolvableConflict) { + expectSolvableABCFieldDiff(diff, { + diffableRuleFieldName: params.diffableRuleFieldName, + valueVersions: params.expectedFieldDiffValues, + }); + } else { + expectNonSolvableABCFieldDiff(diff, { + diffableRuleFieldName: params.diffableRuleFieldName, + valueVersions: params.expectedFieldDiffValues, + }); + } + break; + + case ThreeWayDiffOutcome.MissingBaseNoUpdate: + expectMissingBaseAAFieldDiff(diff, { diffableRuleFieldName: params.diffableRuleFieldName }); + break; + + case ThreeWayDiffOutcome.MissingBaseCanUpdate: + expectMissingBaseABFieldDiff(diff, { + diffableRuleFieldName: params.diffableRuleFieldName, + valueVersions: params.expectedFieldDiffValues, + }); + break; + } + }); +} + +interface TestFieldUpgradesToMergedValueParams { + ruleUpgradeAssets: TestFieldRuleUpgradeAssets; + diffableRuleFieldName: string; + expectedFieldsAfterUpgrade: Partial; +} + +/** + * Creates a test to assert rule's `fieldName` upgrades to merged value. + * + * CAUTION: The function expected provided `ruleUpgradeAssets` defined according to the `expectedDiffOutcome`. + * In the other words it means `ruleUpgradeAssets` should define a proper rule upgrade state for + * a `fieldName` like non-customized field without upgrade or customized field with an upgrade resulting + * in a conflict. + * + * `mergedValue` must be conformed with `ruleUpgradeAssets`. + */ +export function testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName, + expectedFieldsAfterUpgrade, + }: TestFieldUpgradesToMergedValueParams, + getService: FtrProviderContext['getService'] +): void { + const es = getService('es'); + const supertest = getService('supertest'); + const log = getService('log'); + const securitySolutionApi = getService('securitySolutionApi'); + + const deps = { + es, + supertest, + log, + securitySolutionApi, + }; + + it('upgrades to MERGED value', async () => { + await setUpRuleUpgrade({ + assets: ruleUpgradeAssets, + removeInstalledAssets: ruleUpgradeAssets.removeInstalledAssets ?? false, + deps, + }); + + const hasRuleFieldsToPatch = Object.keys(ruleUpgradeAssets.patch).length > 0; + + const response = await performUpgradePrebuiltRules(es, supertest, { + mode: ModeEnum.SPECIFIC_RULES, + rules: [ + { + rule_id: ruleUpgradeAssets.upgrade.rule_id ?? DEFAULT_TEST_RULE_ID, + revision: hasRuleFieldsToPatch ? 1 : 0, + version: ruleUpgradeAssets.upgrade.version ?? DEFAULT_RULE_UPDATE_VERSION, + fields: { + [diffableRuleFieldName]: { + pick_version: 'MERGED', + }, + }, + }, + ], + }); + + const upgradedRule = await securitySolutionApi.readRule({ + query: { rule_id: DEFAULT_TEST_RULE_ID }, + }); + + expectRuleFields(response.results.updated[0], expectedFieldsAfterUpgrade); + expectRuleFields(upgradedRule.body, expectedFieldsAfterUpgrade); + }); +} + +interface TestFieldUpgradesToResolvedValueParams { + ruleUpgradeAssets: TestFieldRuleUpgradeAssets; + diffableRuleFieldName: string; + resolvedValue: unknown; + expectedFieldsAfterUpgrade: Partial; +} + +/** + * Creates a test to assert rule's `fieldName` upgrades to a resolved value. + * + * Since `mergedValue` depends on the input data and a diff algorithm the function + * expect `mergedValue` to be provided. + * + * CAUTION: The function expected provided `ruleUpgradeAssets` defined according to the `expectedDiffOutcome`. + * In the other words it means `ruleUpgradeAssets` should define a proper rule upgrade state for + * a `fieldName` like non-customized field without upgrade or customized field with an upgrade resulting + * in a conflict. + */ +export function testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName, + resolvedValue, + expectedFieldsAfterUpgrade, + }: TestFieldUpgradesToResolvedValueParams, + getService: FtrProviderContext['getService'] +): void { + const es = getService('es'); + const supertest = getService('supertest'); + const log = getService('log'); + const securitySolutionApi = getService('securitySolutionApi'); + + const deps = { + es, + supertest, + log, + securitySolutionApi, + }; + + it('upgrades to RESOLVED value', async () => { + await setUpRuleUpgrade({ + assets: ruleUpgradeAssets, + removeInstalledAssets: ruleUpgradeAssets.removeInstalledAssets ?? false, + deps, + }); + + const hasRuleFieldsToPatch = Object.keys(ruleUpgradeAssets.patch).length > 0; + + const response = await performUpgradePrebuiltRules(deps.es, deps.supertest, { + mode: ModeEnum.SPECIFIC_RULES, + rules: [ + { + rule_id: ruleUpgradeAssets.upgrade.rule_id ?? DEFAULT_TEST_RULE_ID, + revision: hasRuleFieldsToPatch ? 1 : 0, + version: ruleUpgradeAssets.upgrade.version ?? DEFAULT_RULE_UPDATE_VERSION, + fields: { + [diffableRuleFieldName]: { + pick_version: 'RESOLVED', + resolved_value: resolvedValue, + }, + }, + }, + ], + }); + + const upgradedRule = await deps.securitySolutionApi.readRule({ + query: { rule_id: DEFAULT_TEST_RULE_ID }, + }); + + expectRuleFields(response.results.updated[0], expectedFieldsAfterUpgrade); + expectRuleFields(upgradedRule.body, expectedFieldsAfterUpgrade); + }); +} + +interface FieldAbsenceAssertParams { + diffableRuleFieldName: string; +} + +/** + * Asserts provided non-customized `diffableRuleFieldName` isn't presented + * in the diff (`AAA` diff case) + */ +function expectAAAFieldDiff( + ruleDiff: PartialRuleDiff, + fieldAssertParams: FieldAbsenceAssertParams +): void { + expect(ruleDiff).toMatchObject({ + num_fields_with_updates: 1, // counts version field + num_fields_with_conflicts: 0, + num_fields_with_non_solvable_conflicts: 0, + }); + expect(ruleDiff.fields).not.toMatchObject({ + [fieldAssertParams.diffableRuleFieldName]: expect.anything(), + }); +} + +interface FieldAssertParams { + diffableRuleFieldName: string; + valueVersions: FieldDiffValueVersions; +} + +/** + * Asserts provided non-customized `diffableRuleFieldName` doesn't have a conflict + * and ready for upgrade (`AAB` diff case) + */ +function expectAABFieldDiff(ruleDiff: PartialRuleDiff, fieldAssertParams: FieldAssertParams): void { + expect(ruleDiff).toMatchObject({ + num_fields_with_updates: 2, // counts + version field + num_fields_with_conflicts: 0, + num_fields_with_non_solvable_conflicts: 0, + }); + expect(ruleDiff.fields).toMatchObject({ + [fieldAssertParams.diffableRuleFieldName]: omitBy( + { + base_version: fieldAssertParams.valueVersions.base, + current_version: fieldAssertParams.valueVersions.current, + target_version: fieldAssertParams.valueVersions.target, + merged_version: fieldAssertParams.valueVersions.merged, + diff_outcome: ThreeWayDiffOutcome.StockValueCanUpdate, + merge_outcome: ThreeWayMergeOutcome.Target, + conflict: ThreeWayDiffConflict.NONE, + }, + isUndefined + ), + }); +} + +/** + * Asserts provided customized `diffableRuleFieldName` without an upgrade doesn't have a conflict + * and ready for upgrade (`ABA` diff case) + */ +function expectABAFieldDiff(ruleDiff: PartialRuleDiff, fieldAssertParams: FieldAssertParams): void { + expect(ruleDiff).toMatchObject({ + num_fields_with_updates: 1, // counts version field + num_fields_with_conflicts: 0, + num_fields_with_non_solvable_conflicts: 0, + }); + expect(ruleDiff.fields).toMatchObject({ + [fieldAssertParams.diffableRuleFieldName]: omitBy( + { + base_version: fieldAssertParams.valueVersions.base, + current_version: fieldAssertParams.valueVersions.current, + target_version: fieldAssertParams.valueVersions.target, + merged_version: fieldAssertParams.valueVersions.merged, + diff_outcome: ThreeWayDiffOutcome.CustomizedValueNoUpdate, + merge_outcome: ThreeWayMergeOutcome.Current, + conflict: ThreeWayDiffConflict.NONE, + }, + isUndefined + ), + }); +} + +/** + * Asserts provided customized `diffableRuleFieldName` with the matching update + * doesn't have a conflict and is ready for upgrade (`ABB` diff case) + */ +function expectABBFieldDiff(ruleDiff: PartialRuleDiff, fieldAssertParams: FieldAssertParams): void { + expect(ruleDiff).toMatchObject({ + num_fields_with_updates: 1, // counts version field + num_fields_with_conflicts: 0, + num_fields_with_non_solvable_conflicts: 0, + }); + expect(ruleDiff.fields).toMatchObject({ + [fieldAssertParams.diffableRuleFieldName]: omitBy( + { + base_version: fieldAssertParams.valueVersions.base, + current_version: fieldAssertParams.valueVersions.current, + target_version: fieldAssertParams.valueVersions.target, + merged_version: fieldAssertParams.valueVersions.merged, + diff_outcome: ThreeWayDiffOutcome.CustomizedValueSameUpdate, + merge_outcome: ThreeWayMergeOutcome.Current, + conflict: ThreeWayDiffConflict.NONE, + }, + isUndefined + ), + }); +} + +/** + * Asserts provided customized `diffableRuleFieldName` with an upgrade + * has a solvable conflict (`ABC` diff case) + */ +function expectSolvableABCFieldDiff( + ruleDiff: PartialRuleDiff, + fieldAssertParams: FieldAssertParams +): void { + expect(ruleDiff).toMatchObject({ + num_fields_with_updates: 2, // counts + version field + num_fields_with_conflicts: 1, + num_fields_with_non_solvable_conflicts: 0, + }); + expect(ruleDiff.fields).toMatchObject({ + [fieldAssertParams.diffableRuleFieldName]: omitBy( + { + base_version: fieldAssertParams.valueVersions.base, + current_version: fieldAssertParams.valueVersions.current, + target_version: fieldAssertParams.valueVersions.target, + merged_version: fieldAssertParams.valueVersions.merged, + diff_outcome: ThreeWayDiffOutcome.CustomizedValueCanUpdate, + merge_outcome: ThreeWayMergeOutcome.Merged, + conflict: ThreeWayDiffConflict.SOLVABLE, + }, + isUndefined + ), + }); +} + +/** + * Asserts provided customized `diffableRuleFieldName` with an upgrade + * has a non-solvable conflict (`ABC` diff case) + */ +function expectNonSolvableABCFieldDiff( + ruleDiff: PartialRuleDiff, + fieldAssertParams: FieldAssertParams +): void { + expect(ruleDiff).toMatchObject({ + num_fields_with_updates: 2, // counts + version field + num_fields_with_conflicts: 1, + num_fields_with_non_solvable_conflicts: 1, + }); + expect(ruleDiff.fields).toMatchObject({ + [fieldAssertParams.diffableRuleFieldName]: omitBy( + { + base_version: fieldAssertParams.valueVersions.base, + current_version: fieldAssertParams.valueVersions.current, + target_version: fieldAssertParams.valueVersions.target, + merged_version: fieldAssertParams.valueVersions.merged, + diff_outcome: ThreeWayDiffOutcome.CustomizedValueCanUpdate, + merge_outcome: ThreeWayMergeOutcome.Current, + conflict: ThreeWayDiffConflict.NON_SOLVABLE, + }, + isUndefined + ), + }); +} + +/** + * With historical versions missing + * Asserts provided `diffableRuleFieldName` with an upgrade + * has the matching upgrade (`-AA` diff case) + */ +function expectMissingBaseAAFieldDiff( + ruleDiff: PartialRuleDiff, + fieldAssertParams: FieldAbsenceAssertParams +): void { + expect(ruleDiff).toMatchObject({ + num_fields_with_updates: 1, // counts version field + num_fields_with_conflicts: 0, + num_fields_with_non_solvable_conflicts: 0, + }); + expect(ruleDiff.fields).not.toMatchObject({ + [fieldAssertParams.diffableRuleFieldName]: expect.anything(), + }); +} + +interface MissingBaseFieldAssertParams { + diffableRuleFieldName: string; + valueVersions: MissingHistoricalRuleVersionsFieldDiffValueVersions; +} + +/** + * With historical versions missing + * Asserts provided `diffableRuleFieldName` with an upgrade + * has an upgrade (`-AB` diff case) + */ +function expectMissingBaseABFieldDiff( + ruleDiff: PartialRuleDiff, + fieldAssertParams: MissingBaseFieldAssertParams +): void { + expect(ruleDiff).toMatchObject({ + num_fields_with_updates: 2, // counts + version field + num_fields_with_conflicts: 1, + num_fields_with_non_solvable_conflicts: 0, + }); + expect(ruleDiff.fields).toMatchObject({ + [fieldAssertParams.diffableRuleFieldName]: omitBy( + { + current_version: fieldAssertParams.valueVersions.current, + target_version: fieldAssertParams.valueVersions.target, + merged_version: fieldAssertParams.valueVersions.merged, + diff_outcome: ThreeWayDiffOutcome.MissingBaseCanUpdate, + merge_outcome: ThreeWayMergeOutcome.Target, + conflict: ThreeWayDiffConflict.SOLVABLE, + }, + isUndefined + ), + }); +} + +/** + * Assertion helper to assert `fields` are presented in `maybeRule`. + * + * For any field's undefined value expectation is built to assert absence of the field. + */ +function expectRuleFields(maybeRule: Record, fields: Partial): void { + for (const [fieldName, value] of Object.entries(fields)) { + if (value === undefined) { + expect(maybeRule).not.toMatchObject({ + [fieldName]: expect.anything(), + }); + } else { + expect(maybeRule).toMatchObject({ + [fieldName]: value, + }); + } + } +} diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/type_specific_fields/anomaly_threshold.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/type_specific_fields/anomaly_threshold.ts new file mode 100644 index 0000000000000..16153505e5561 --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/type_specific_fields/anomaly_threshold.ts @@ -0,0 +1,326 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { ThreeWayDiffOutcome } from '@kbn/security-solution-plugin/common/api/detection_engine'; +import { FtrProviderContext } from '../../../../../../../../ftr_provider_context'; +import type { TestFieldRuleUpgradeAssets } from '../test_helpers'; +import { + testFieldUpgradeReview, + testFieldUpgradesToMergedValue, + testFieldUpgradesToResolvedValue, +} from '../test_helpers'; + +export function anomalyThresholdField({ getService }: FtrProviderContext): void { + describe('"anomaly_threshold"', () => { + describe('non-customized w/o an upgrade (AAA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'machine_learning', + anomaly_threshold: 10, + }, + patch: {}, + upgrade: { + type: 'machine_learning', + anomaly_threshold: 10, + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'anomaly_threshold', + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueNoUpdate, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'anomaly_threshold', + resolvedValue: 30, + expectedFieldsAfterUpgrade: { anomaly_threshold: 30 }, + }, + getService + ); + }); + + describe('non-customized w/ an upgrade (AAB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'machine_learning', + anomaly_threshold: 10, + }, + patch: {}, + upgrade: { + type: 'machine_learning', + anomaly_threshold: 20, + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'anomaly_threshold', + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueCanUpdate, + expectedFieldDiffValues: { + base: 10, + current: 10, + target: 20, + merged: 20, + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'anomaly_threshold', + expectedFieldsAfterUpgrade: { anomaly_threshold: 20 }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'anomaly_threshold', + resolvedValue: 30, + expectedFieldsAfterUpgrade: { anomaly_threshold: 30 }, + }, + getService + ); + }); + + describe('customized w/o an upgrade (ABA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'machine_learning', + anomaly_threshold: 10, + }, + patch: { + type: 'machine_learning', + anomaly_threshold: 20, + }, + upgrade: { + type: 'machine_learning', + anomaly_threshold: 10, + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'anomaly_threshold', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueNoUpdate, + expectedFieldDiffValues: { + base: 10, + current: 20, + target: 10, + merged: 20, + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'anomaly_threshold', + expectedFieldsAfterUpgrade: { anomaly_threshold: 20 }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'anomaly_threshold', + resolvedValue: 30, + expectedFieldsAfterUpgrade: { anomaly_threshold: 30 }, + }, + getService + ); + }); + + describe('customized w/ the matching upgrade (ABB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'machine_learning', + anomaly_threshold: 10, + }, + patch: { + type: 'machine_learning', + anomaly_threshold: 20, + }, + upgrade: { + type: 'machine_learning', + anomaly_threshold: 20, + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'anomaly_threshold', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueSameUpdate, + expectedFieldDiffValues: { + base: 10, + current: 20, + target: 20, + merged: 20, + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'anomaly_threshold', + expectedFieldsAfterUpgrade: { anomaly_threshold: 20 }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'anomaly_threshold', + resolvedValue: 30, + expectedFieldsAfterUpgrade: { anomaly_threshold: 30 }, + }, + getService + ); + }); + + describe('customized w/ an upgrade resulting in a conflict (ABC diff case, non-solvable conflict)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'machine_learning', + anomaly_threshold: 10, + }, + patch: { + type: 'machine_learning', + anomaly_threshold: 20, + }, + upgrade: { + type: 'machine_learning', + anomaly_threshold: 30, + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'anomaly_threshold', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueCanUpdate, + isSolvableConflict: false, + expectedFieldDiffValues: { + base: 10, + current: 20, + target: 30, + merged: 20, + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'anomaly_threshold', + resolvedValue: 50, + expectedFieldsAfterUpgrade: { anomaly_threshold: 50 }, + }, + getService + ); + }); + + describe('without historical versions', () => { + describe('customized w/ the matching upgrade (-AA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'machine_learning', + anomaly_threshold: 10, + }, + patch: { + type: 'machine_learning', + anomaly_threshold: 20, + }, + upgrade: { + type: 'machine_learning', + anomaly_threshold: 20, + }, + removeInstalledAssets: true, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'anomaly_threshold', + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseNoUpdate, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'anomaly_threshold', + resolvedValue: 50, + expectedFieldsAfterUpgrade: { anomaly_threshold: 50 }, + }, + getService + ); + }); + + describe('customized w/ an upgrade (-AB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'machine_learning', + anomaly_threshold: 10, + }, + patch: { + type: 'machine_learning', + anomaly_threshold: 20, + }, + upgrade: { + type: 'machine_learning', + anomaly_threshold: 30, + }, + removeInstalledAssets: true, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'anomaly_threshold', + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseCanUpdate, + expectedFieldDiffValues: { + current: 20, + target: 30, + merged: 30, + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'anomaly_threshold', + resolvedValue: 50, + expectedFieldsAfterUpgrade: { anomaly_threshold: 50 }, + }, + getService + ); + }); + }); + }); +} diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/type_specific_fields/configs/ess.config.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/type_specific_fields/configs/ess.config.ts new file mode 100644 index 0000000000000..944699b362cfe --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/type_specific_fields/configs/ess.config.ts @@ -0,0 +1,34 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile( + require.resolve('../../../../../../../../../config/ess/config.base.trial') + ); + + const testConfig = { + ...functionalConfig.getAll(), + testFiles: [require.resolve('..')], + junit: { + reportName: + 'Rules Management - Prebuilt Rule Customization Enabled Per Field Integration Tests - ESS Env', + }, + }; + testConfig.kbnTestServer.serverArgs = testConfig.kbnTestServer.serverArgs.map((arg: string) => { + // Override the default value of `--xpack.securitySolution.enableExperimental` to enable the prebuilt rules customization feature + if (arg.includes('--xpack.securitySolution.enableExperimental')) { + return `--xpack.securitySolution.enableExperimental=${JSON.stringify([ + 'prebuiltRulesCustomizationEnabled', + ])}`; + } + return arg; + }); + + return testConfig; +} diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/type_specific_fields/configs/serverless.config.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/type_specific_fields/configs/serverless.config.ts new file mode 100644 index 0000000000000..5fb299b71e58d --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/type_specific_fields/configs/serverless.config.ts @@ -0,0 +1,21 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { createTestConfig } from '../../../../../../../../../config/serverless/config.base'; + +export default createTestConfig({ + testFiles: [require.resolve('..')], + junit: { + reportName: + 'Rules Management - Prebuilt Rule Customization Enabled Per Field Integration Tests - Serverless Env', + }, + kbnTestServerArgs: [ + `--xpack.securitySolution.enableExperimental=${JSON.stringify([ + 'prebuiltRulesCustomizationEnabled', + ])}`, + ], +}); diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/type_specific_fields/eql_query.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/type_specific_fields/eql_query.ts new file mode 100644 index 0000000000000..1e1f6795c5408 --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/type_specific_fields/eql_query.ts @@ -0,0 +1,469 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { ThreeWayDiffOutcome } from '@kbn/security-solution-plugin/common/api/detection_engine'; +import { FtrProviderContext } from '../../../../../../../../ftr_provider_context'; +import type { TestFieldRuleUpgradeAssets } from '../test_helpers'; +import { + testFieldUpgradeReview, + testFieldUpgradesToMergedValue, + testFieldUpgradesToResolvedValue, +} from '../test_helpers'; + +export function eqlQueryField({ getService }: FtrProviderContext): void { + describe('"eql_query"', () => { + describe('non-customized w/o an upgrade (AAA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'eql', + query: 'any where true', + language: 'eql', + }, + patch: {}, + upgrade: { + type: 'eql', + query: 'any where true', + language: 'eql', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'eql_query', + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueNoUpdate, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'eql_query', + resolvedValue: { + query: 'process where process.name == "regsvr32.exe"', + language: 'eql', + filters: [], + }, + expectedFieldsAfterUpgrade: { + query: 'process where process.name == "regsvr32.exe"', + language: 'eql', + }, + }, + getService + ); + }); + + describe('non-customized w/ an upgrade (AAB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'eql', + query: 'any where true', + language: 'eql', + }, + patch: {}, + upgrade: { + type: 'eql', + query: 'process where process.name == "regsvr32.exe"', + language: 'eql', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'eql_query', + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueCanUpdate, + expectedFieldDiffValues: { + base: { + query: 'any where true', + language: 'eql', + filters: [], + }, + current: { + query: 'any where true', + language: 'eql', + filters: [], + }, + target: { + query: 'process where process.name == "regsvr32.exe"', + language: 'eql', + filters: [], + }, + merged: { + query: 'process where process.name == "regsvr32.exe"', + language: 'eql', + filters: [], + }, + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'eql_query', + expectedFieldsAfterUpgrade: { + query: 'process where process.name == "regsvr32.exe"', + language: 'eql', + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'eql_query', + resolvedValue: { + query: 'process where process.name == "regsvr32.exe"', + language: 'eql', + filters: [], + }, + expectedFieldsAfterUpgrade: { + query: 'process where process.name == "regsvr32.exe"', + language: 'eql', + }, + }, + getService + ); + }); + + describe('customized w/o an upgrade (ABA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'eql', + query: 'any where true', + language: 'eql', + }, + patch: { + query: 'process where process.name == "regsvr32.exe"', + }, + upgrade: { + type: 'eql', + query: 'any where true', + language: 'eql', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'eql_query', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueNoUpdate, + expectedFieldDiffValues: { + base: { + query: 'any where true', + language: 'eql', + filters: [], + }, + current: { + query: 'process where process.name == "regsvr32.exe"', + language: 'eql', + filters: [], + }, + target: { + query: 'any where true', + language: 'eql', + filters: [], + }, + merged: { + query: 'process where process.name == "regsvr32.exe"', + language: 'eql', + filters: [], + }, + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'eql_query', + expectedFieldsAfterUpgrade: { + query: 'process where process.name == "regsvr32.exe"', + language: 'eql', + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'eql_query', + resolvedValue: { + query: 'process where process.name == "regsvr32.exe"', + language: 'eql', + filters: [], + }, + expectedFieldsAfterUpgrade: { + query: 'process where process.name == "regsvr32.exe"', + language: 'eql', + }, + }, + getService + ); + }); + + describe('customized w/ the matching upgrade (ABB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'eql', + query: 'any where true', + language: 'eql', + }, + patch: { + query: 'process where process.name == "regsvr32.exe"', + }, + upgrade: { + type: 'eql', + query: 'process where process.name == "regsvr32.exe"', + language: 'eql', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'eql_query', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueSameUpdate, + expectedFieldDiffValues: { + base: { + query: 'any where true', + language: 'eql', + filters: [], + }, + current: { + query: 'process where process.name == "regsvr32.exe"', + language: 'eql', + filters: [], + }, + target: { + query: 'process where process.name == "regsvr32.exe"', + language: 'eql', + filters: [], + }, + merged: { + query: 'process where process.name == "regsvr32.exe"', + language: 'eql', + filters: [], + }, + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'eql_query', + expectedFieldsAfterUpgrade: { + query: 'process where process.name == "regsvr32.exe"', + language: 'eql', + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'eql_query', + resolvedValue: { + query: 'process where process.name == "regsvr32.exe"', + language: 'eql', + filters: [], + }, + expectedFieldsAfterUpgrade: { + query: 'process where process.name == "regsvr32.exe"', + language: 'eql', + }, + }, + getService + ); + }); + + describe('customized w/ an upgrade resulting in a conflict (ABC diff case, non-solvable conflict)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'eql', + query: 'any where true', + language: 'eql', + }, + patch: { + query: 'host where host.name == "something"', + }, + upgrade: { + type: 'eql', + query: 'process where process.name == "regsvr32.exe"', + language: 'eql', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'eql_query', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueCanUpdate, + isSolvableConflict: false, + expectedFieldDiffValues: { + base: { + query: 'any where true', + language: 'eql', + filters: [], + }, + current: { + query: 'host where host.name == "something"', + language: 'eql', + filters: [], + }, + target: { + query: 'process where process.name == "regsvr32.exe"', + language: 'eql', + filters: [], + }, + merged: { + query: 'host where host.name == "something"', + language: 'eql', + filters: [], + }, + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'eql_query', + resolvedValue: { + query: 'process where process.name == "regsvr32.exe"', + language: 'eql', + filters: [], + }, + expectedFieldsAfterUpgrade: { + query: 'process where process.name == "regsvr32.exe"', + language: 'eql', + }, + }, + getService + ); + }); + + describe('without historical versions', () => { + describe('customized w/ the matching upgrade (-AA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'eql', + query: 'any where true', + language: 'eql', + }, + patch: { + query: 'host where host.name == "something"', + }, + upgrade: { + type: 'eql', + query: 'host where host.name == "something"', + language: 'eql', + }, + removeInstalledAssets: true, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'eql_query', + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseNoUpdate, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'eql_query', + resolvedValue: { + query: 'process where process.name == "regsvr32.exe"', + language: 'eql', + filters: [], + }, + expectedFieldsAfterUpgrade: { + query: 'process where process.name == "regsvr32.exe"', + language: 'eql', + }, + }, + getService + ); + }); + + describe('customized w/ an upgrade (-AB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'eql', + query: 'any where true', + language: 'eql', + }, + patch: { + query: 'host where host.name == "something"', + }, + upgrade: { + type: 'eql', + query: 'process where process.name == "regsvr32.exe"', + language: 'eql', + }, + removeInstalledAssets: true, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'eql_query', + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseCanUpdate, + expectedFieldDiffValues: { + current: { + query: 'host where host.name == "something"', + language: 'eql', + filters: [], + }, + target: { + query: 'process where process.name == "regsvr32.exe"', + language: 'eql', + filters: [], + }, + merged: { + query: 'process where process.name == "regsvr32.exe"', + language: 'eql', + filters: [], + }, + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'eql_query', + resolvedValue: { + query: 'process where process.name == "regsvr32.exe"', + language: 'eql', + filters: [], + }, + expectedFieldsAfterUpgrade: { + query: 'process where process.name == "regsvr32.exe"', + language: 'eql', + }, + }, + getService + ); + }); + }); + }); +} diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/type_specific_fields/esql_query.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/type_specific_fields/esql_query.ts new file mode 100644 index 0000000000000..f59086d07560f --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/type_specific_fields/esql_query.ts @@ -0,0 +1,402 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { ThreeWayDiffOutcome } from '@kbn/security-solution-plugin/common/api/detection_engine'; +import { FtrProviderContext } from '../../../../../../../../ftr_provider_context'; +import type { TestFieldRuleUpgradeAssets } from '../test_helpers'; +import { + testFieldUpgradeReview, + testFieldUpgradesToMergedValue, + testFieldUpgradesToResolvedValue, +} from '../test_helpers'; + +export function esqlQueryField({ getService }: FtrProviderContext): void { + describe('"esql_query"', () => { + describe('non-customized w/o an upgrade (AAA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'esql', + query: 'FROM indexA METADATA _id', + language: 'esql', + }, + patch: {}, + upgrade: { + type: 'esql', + query: 'FROM indexA METADATA _id', + language: 'esql', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'esql_query', + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueNoUpdate, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'esql_query', + resolvedValue: { query: 'FROM resolved METADATA _id', language: 'esql' }, + expectedFieldsAfterUpgrade: { query: 'FROM resolved METADATA _id', language: 'esql' }, + }, + getService + ); + }); + + describe('non-customized w/ an upgrade (AAB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'esql', + query: 'FROM indexA METADATA _id', + language: 'esql', + }, + patch: {}, + upgrade: { + type: 'esql', + query: 'FROM indexB METADATA _id', + language: 'esql', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'esql_query', + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueCanUpdate, + expectedFieldDiffValues: { + base: { + query: 'FROM indexA METADATA _id', + language: 'esql', + }, + current: { + query: 'FROM indexA METADATA _id', + language: 'esql', + }, + target: { + query: 'FROM indexB METADATA _id', + language: 'esql', + }, + merged: { + query: 'FROM indexB METADATA _id', + language: 'esql', + }, + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'esql_query', + expectedFieldsAfterUpgrade: { query: 'FROM indexB METADATA _id', language: 'esql' }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'esql_query', + resolvedValue: { query: 'FROM resolved METADATA _id', language: 'esql' }, + expectedFieldsAfterUpgrade: { query: 'FROM resolved METADATA _id', language: 'esql' }, + }, + getService + ); + }); + + describe('customized w/o an upgrade (ABA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'esql', + query: 'FROM indexA METADATA _id', + language: 'esql', + }, + patch: { + type: 'esql', + query: 'FROM indexB METADATA _id', + language: 'esql', + }, + upgrade: { + type: 'esql', + query: 'FROM indexA METADATA _id', + language: 'esql', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'esql_query', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueNoUpdate, + expectedFieldDiffValues: { + base: { + query: 'FROM indexA METADATA _id', + language: 'esql', + }, + current: { + query: 'FROM indexB METADATA _id', + language: 'esql', + }, + target: { + query: 'FROM indexA METADATA _id', + language: 'esql', + }, + merged: { + query: 'FROM indexB METADATA _id', + language: 'esql', + }, + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'esql_query', + expectedFieldsAfterUpgrade: { query: 'FROM indexB METADATA _id', language: 'esql' }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'esql_query', + resolvedValue: { query: 'FROM resolved METADATA _id', language: 'esql' }, + expectedFieldsAfterUpgrade: { query: 'FROM resolved METADATA _id', language: 'esql' }, + }, + getService + ); + }); + + describe('customized w/ the matching upgrade (ABB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'esql', + query: 'FROM indexA METADATA _id', + language: 'esql', + }, + patch: { + type: 'esql', + query: 'FROM indexB METADATA _id', + language: 'esql', + }, + upgrade: { + type: 'esql', + query: 'FROM indexB METADATA _id', + language: 'esql', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'esql_query', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueSameUpdate, + expectedFieldDiffValues: { + base: { + query: 'FROM indexA METADATA _id', + language: 'esql', + }, + current: { + query: 'FROM indexB METADATA _id', + language: 'esql', + }, + target: { + query: 'FROM indexB METADATA _id', + language: 'esql', + }, + merged: { + query: 'FROM indexB METADATA _id', + language: 'esql', + }, + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'esql_query', + expectedFieldsAfterUpgrade: { query: 'FROM indexB METADATA _id', language: 'esql' }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'esql_query', + resolvedValue: { query: 'FROM resolved METADATA _id', language: 'esql' }, + expectedFieldsAfterUpgrade: { query: 'FROM resolved METADATA _id', language: 'esql' }, + }, + getService + ); + }); + + describe('customized w/ an upgrade resulting in a conflict (ABC diff case, non-solvable conflict)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'esql', + query: 'FROM indexA METADATA _id', + language: 'esql', + }, + patch: { + type: 'esql', + query: 'FROM indexB METADATA _id', + language: 'esql', + }, + upgrade: { + type: 'esql', + query: 'FROM indexC METADATA _id', + language: 'esql', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'esql_query', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueCanUpdate, + isSolvableConflict: false, + expectedFieldDiffValues: { + base: { + query: 'FROM indexA METADATA _id', + language: 'esql', + }, + current: { + query: 'FROM indexB METADATA _id', + language: 'esql', + }, + target: { + query: 'FROM indexC METADATA _id', + language: 'esql', + }, + merged: { + query: 'FROM indexB METADATA _id', + language: 'esql', + }, + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'esql_query', + resolvedValue: { query: 'FROM resolved METADATA _id', language: 'esql' }, + expectedFieldsAfterUpgrade: { query: 'FROM resolved METADATA _id', language: 'esql' }, + }, + getService + ); + }); + + describe('without historical versions', () => { + describe('customized w/ the matching upgrade (-AA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'esql', + query: 'FROM indexA METADATA _id', + language: 'esql', + }, + patch: { + type: 'esql', + query: 'FROM indexB METADATA _id', + language: 'esql', + }, + upgrade: { + type: 'esql', + query: 'FROM indexB METADATA _id', + language: 'esql', + }, + removeInstalledAssets: true, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'esql_query', + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseNoUpdate, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'esql_query', + resolvedValue: { query: 'FROM resolved METADATA _id', language: 'esql' }, + expectedFieldsAfterUpgrade: { query: 'FROM resolved METADATA _id', language: 'esql' }, + }, + getService + ); + }); + + describe('customized w/ an upgrade (-AB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'esql', + query: 'FROM indexA METADATA _id', + language: 'esql', + }, + patch: { + type: 'esql', + query: 'FROM indexB METADATA _id', + language: 'esql', + }, + upgrade: { + type: 'esql', + query: 'FROM indexC METADATA _id', + language: 'esql', + }, + removeInstalledAssets: true, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'esql_query', + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseCanUpdate, + expectedFieldDiffValues: { + current: { + query: 'FROM indexB METADATA _id', + language: 'esql', + }, + target: { + query: 'FROM indexC METADATA _id', + language: 'esql', + }, + merged: { + query: 'FROM indexC METADATA _id', + language: 'esql', + }, + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'esql_query', + resolvedValue: { query: 'FROM resolved METADATA _id', language: 'esql' }, + expectedFieldsAfterUpgrade: { query: 'FROM resolved METADATA _id', language: 'esql' }, + }, + getService + ); + }); + }); + }); +} diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/type_specific_fields/history_window_start.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/type_specific_fields/history_window_start.ts new file mode 100644 index 0000000000000..6362fd474b441 --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/type_specific_fields/history_window_start.ts @@ -0,0 +1,326 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { ThreeWayDiffOutcome } from '@kbn/security-solution-plugin/common/api/detection_engine'; +import { FtrProviderContext } from '../../../../../../../../ftr_provider_context'; +import type { TestFieldRuleUpgradeAssets } from '../test_helpers'; +import { + testFieldUpgradeReview, + testFieldUpgradesToMergedValue, + testFieldUpgradesToResolvedValue, +} from '../test_helpers'; + +export function historyWindowStartField({ getService }: FtrProviderContext): void { + describe('"history_window_start"', () => { + describe('non-customized w/o an upgrade (AAA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'new_terms', + history_window_start: 'now-1h', + }, + patch: {}, + upgrade: { + type: 'new_terms', + history_window_start: 'now-1h', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'history_window_start', + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueNoUpdate, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'history_window_start', + resolvedValue: 'now-30m', + expectedFieldsAfterUpgrade: { history_window_start: 'now-30m' }, + }, + getService + ); + }); + + describe('non-customized w/ an upgrade (AAB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'new_terms', + history_window_start: 'now-1h', + }, + patch: {}, + upgrade: { + type: 'new_terms', + history_window_start: 'now-30m', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'history_window_start', + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueCanUpdate, + expectedFieldDiffValues: { + base: 'now-1h', + current: 'now-1h', + target: 'now-30m', + merged: 'now-30m', + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'history_window_start', + expectedFieldsAfterUpgrade: { history_window_start: 'now-30m' }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'history_window_start', + resolvedValue: 'now-2h', + expectedFieldsAfterUpgrade: { history_window_start: 'now-2h' }, + }, + getService + ); + }); + + describe('customized w/o an upgrade (ABA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'new_terms', + history_window_start: 'now-1h', + }, + patch: { + type: 'new_terms', + history_window_start: 'now-2h', + }, + upgrade: { + type: 'new_terms', + history_window_start: 'now-1h', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'history_window_start', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueNoUpdate, + expectedFieldDiffValues: { + base: 'now-1h', + current: 'now-2h', + target: 'now-1h', + merged: 'now-2h', + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'history_window_start', + expectedFieldsAfterUpgrade: { history_window_start: 'now-2h' }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'history_window_start', + resolvedValue: 'now-5h', + expectedFieldsAfterUpgrade: { history_window_start: 'now-5h' }, + }, + getService + ); + }); + + describe('customized w/ the matching upgrade (ABB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'new_terms', + history_window_start: 'now-1h', + }, + patch: { + type: 'new_terms', + history_window_start: 'now-2h', + }, + upgrade: { + type: 'new_terms', + history_window_start: 'now-2h', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'history_window_start', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueSameUpdate, + expectedFieldDiffValues: { + base: 'now-1h', + current: 'now-2h', + target: 'now-2h', + merged: 'now-2h', + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'history_window_start', + expectedFieldsAfterUpgrade: { history_window_start: 'now-2h' }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'history_window_start', + resolvedValue: 'now-5h', + expectedFieldsAfterUpgrade: { history_window_start: 'now-5h' }, + }, + getService + ); + }); + + describe('customized w/ an upgrade resulting in a conflict (ABC diff case, non-solvable conflict)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'new_terms', + history_window_start: 'now-1h', + }, + patch: { + type: 'new_terms', + history_window_start: 'now-2h', + }, + upgrade: { + type: 'new_terms', + history_window_start: 'now-30m', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'history_window_start', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueCanUpdate, + isSolvableConflict: false, + expectedFieldDiffValues: { + base: 'now-1h', + current: 'now-2h', + target: 'now-30m', + merged: 'now-2h', + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'history_window_start', + resolvedValue: 'now-5h', + expectedFieldsAfterUpgrade: { history_window_start: 'now-5h' }, + }, + getService + ); + }); + + describe('without historical versions', () => { + describe('customized w/ the matching upgrade (-AA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'new_terms', + history_window_start: 'now-1h', + }, + patch: { + type: 'new_terms', + history_window_start: 'now-2h', + }, + upgrade: { + type: 'new_terms', + history_window_start: 'now-2h', + }, + removeInstalledAssets: true, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'history_window_start', + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseNoUpdate, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'history_window_start', + resolvedValue: 'now-5h', + expectedFieldsAfterUpgrade: { history_window_start: 'now-5h' }, + }, + getService + ); + }); + + describe('customized w/ an upgrade (-AB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'new_terms', + history_window_start: 'now-1h', + }, + patch: { + type: 'new_terms', + history_window_start: 'now-2h', + }, + upgrade: { + type: 'new_terms', + history_window_start: 'now-30m', + }, + removeInstalledAssets: true, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'history_window_start', + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseCanUpdate, + expectedFieldDiffValues: { + current: 'now-2h', + target: 'now-30m', + merged: 'now-30m', + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'history_window_start', + resolvedValue: 'now-5h', + expectedFieldsAfterUpgrade: { history_window_start: 'now-5h' }, + }, + getService + ); + }); + }); + }); +} diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/type_specific_fields/index.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/type_specific_fields/index.ts new file mode 100644 index 0000000000000..3412a151b14a7 --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/type_specific_fields/index.ts @@ -0,0 +1,65 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrProviderContext } from '../../../../../../../../ftr_provider_context'; +import { deleteAllPrebuiltRuleAssets } from '../../../../../../utils'; +import { deleteAllRules } from '../../../../../../../../../common/utils/security_solution'; +import { inlineQueryKqlQueryField } from './kql_query.inline_query'; +// import { savedQueryKqlQueryField } from './kql_query.saved_query'; +import { eqlQueryField } from './eql_query'; +import { esqlQueryField } from './esql_query'; +import { threatIndexField } from './threat_index'; +import { threatQueryField } from './threat_query'; +import { threatMappingField } from './threat_mapping'; +import { threatIndicatorPathField } from './threat_indicator_path'; +import { thresholdField } from './threshold'; +import { machineLearningJobIdField } from './machine_learning_job_id'; +import { anomalyThresholdField } from './anomaly_threshold'; +import { newTermsFieldsField } from './new_terms_fields'; +import { historyWindowStartField } from './history_window_start'; + +export default (context: FtrProviderContext): void => { + const es = context.getService('es'); + const supertest = context.getService('supertest'); + const log = context.getService('log'); + + describe('@ess @serverless @skipInServerlessMKI type specific diffable rule fields', () => { + beforeEach(async () => { + await deleteAllRules(supertest, log); + await deleteAllPrebuiltRuleAssets(es, log); + }); + + // Custom Query, Threat Match, Threshold, New Terms rule types + inlineQueryKqlQueryField(context); + + // Saved Query rule types + // savedQueryKqlQueryField(context); + + // EQL rule type + eqlQueryField(context); + + // ES|QL rule type + esqlQueryField(context); + + // Threat Match rule type + threatIndexField(context); + threatQueryField(context); + threatMappingField(context); + threatIndicatorPathField(context); + + // Threshold rule type + thresholdField(context); + + // Machine Learning rule type + machineLearningJobIdField(context); + anomalyThresholdField(context); + + // New Terms rule type + newTermsFieldsField(context); + historyWindowStartField(context); + }); +}; diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/type_specific_fields/kql_query.inline_query.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/type_specific_fields/kql_query.inline_query.ts new file mode 100644 index 0000000000000..6f2d4a8809a77 --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/type_specific_fields/kql_query.inline_query.ts @@ -0,0 +1,708 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { + KqlQueryType, + ThreeWayDiffOutcome, +} from '@kbn/security-solution-plugin/common/api/detection_engine'; +import { FtrProviderContext } from '../../../../../../../../ftr_provider_context'; +import type { TestFieldRuleUpgradeAssets } from '../test_helpers'; +import { + testFieldUpgradeReview, + testFieldUpgradesToMergedValue, + testFieldUpgradesToResolvedValue, +} from '../test_helpers'; + +const RULE_TYPES = ['query', 'threat_match', 'threshold', 'new_terms'] as const; + +export function inlineQueryKqlQueryField({ getService }: FtrProviderContext): void { + for (const ruleType of RULE_TYPES) { + describe(`"kql_query" with inline query for ${ruleType} rule`, () => { + describe('non-customized w/o an upgrade (AAA diff case)', () => { + describe('without filters', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: ruleType, + query: 'process.name:*.exe', + language: 'kuery', + }, + patch: {}, + upgrade: { + type: ruleType, + query: 'process.name:*.exe', + language: 'kuery', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'kql_query', + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueNoUpdate, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'kql_query', + resolvedValue: { + type: KqlQueryType.inline_query, + query: 'resolved:*', + language: 'kuery', + filters: [], + }, + expectedFieldsAfterUpgrade: { + type: ruleType, + query: 'resolved:*', + language: 'kuery', + }, + }, + getService + ); + }); + + describe('with filters', () => { + describe('and filters have "alias" field set to null for installed rules', () => { + const FILTER = { + meta: { + negate: false, + disabled: false, + type: 'phrase', + key: 'test', + params: { + query: 'value', + }, + }, + query: { + term: { + field: 'value', + }, + }, + }; + + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: ruleType, + filters: [FILTER], + ...(ruleType === 'threshold' + ? { + threshold: { + value: 10, + field: 'fieldA', + }, + } + : {}), + }, + patch: { + type: ruleType, + filters: [ + { + ...FILTER, + meta: { + ...FILTER.meta, + alias: null, + }, + }, + ], + ...(ruleType === 'threshold' + ? { + threshold: { + value: 10, + field: 'fieldA', + }, + } + : {}), + }, + upgrade: { + type: ruleType, + filters: [FILTER], + ...(ruleType === 'threshold' + ? { + threshold: { + value: 10, + field: 'fieldA', + }, + } + : {}), + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'kql_query', + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueNoUpdate, + }, + getService + ); + }); + }); + }); + + describe('non-customized w/ an upgrade (AAB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: ruleType, + query: 'process.name:*.exe', + language: 'kuery', + }, + patch: {}, + upgrade: { + type: ruleType, + query: 'process.name:*.sys', + language: 'kuery', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'kql_query', + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueCanUpdate, + expectedFieldDiffValues: { + base: { + query: 'process.name:*.exe', + language: 'kuery', + type: KqlQueryType.inline_query, + filters: [], + }, + current: { + query: 'process.name:*.exe', + language: 'kuery', + type: KqlQueryType.inline_query, + filters: [], + }, + target: { + query: 'process.name:*.sys', + language: 'kuery', + type: KqlQueryType.inline_query, + filters: [], + }, + merged: { + query: 'process.name:*.sys', + language: 'kuery', + type: KqlQueryType.inline_query, + filters: [], + }, + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'kql_query', + expectedFieldsAfterUpgrade: { + type: ruleType, + query: 'process.name:*.sys', + language: 'kuery', + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'kql_query', + resolvedValue: { + type: KqlQueryType.inline_query, + query: 'resolved:*', + language: 'kuery', + filters: [], + }, + expectedFieldsAfterUpgrade: { + type: ruleType, + query: 'resolved:*', + language: 'kuery', + }, + }, + getService + ); + }); + + describe('customized w/o an upgrade (ABA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: ruleType, + query: 'process.name:*.exe', + language: 'kuery', + ...(ruleType === 'threshold' + ? { + threshold: { + value: 10, + field: 'fieldA', + }, + } + : {}), + }, + patch: { + type: ruleType, + query: '*:*', + ...(ruleType === 'threshold' + ? { + threshold: { + value: 10, + field: 'fieldA', + }, + } + : {}), + }, + upgrade: { + type: ruleType, + query: 'process.name:*.exe', + language: 'kuery', + ...(ruleType === 'threshold' + ? { + threshold: { + value: 10, + field: 'fieldA', + }, + } + : {}), + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'kql_query', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueNoUpdate, + expectedFieldDiffValues: { + base: { + query: 'process.name:*.exe', + language: 'kuery', + type: KqlQueryType.inline_query, + filters: [], + }, + current: { + query: '*:*', + language: 'kuery', + type: KqlQueryType.inline_query, + filters: [], + }, + target: { + query: 'process.name:*.exe', + language: 'kuery', + type: KqlQueryType.inline_query, + filters: [], + }, + merged: { + query: '*:*', + language: 'kuery', + type: KqlQueryType.inline_query, + filters: [], + }, + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'kql_query', + expectedFieldsAfterUpgrade: { type: ruleType, query: '*:*', language: 'kuery' }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'kql_query', + resolvedValue: { + type: KqlQueryType.inline_query, + query: 'resolved:*', + language: 'kuery', + filters: [], + }, + expectedFieldsAfterUpgrade: { + type: ruleType, + query: 'resolved:*', + language: 'kuery', + }, + }, + getService + ); + }); + + describe('customized w/ the matching upgrade (ABB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: ruleType, + query: 'process.name:*.exe', + language: 'kuery', + ...(ruleType === 'threshold' + ? { + threshold: { + value: 10, + field: 'fieldA', + }, + } + : {}), + }, + patch: { + type: ruleType, + query: '*:*', + ...(ruleType === 'threshold' + ? { + threshold: { + value: 10, + field: 'fieldA', + }, + } + : {}), + }, + upgrade: { + type: ruleType, + query: '*:*', + language: 'kuery', + ...(ruleType === 'threshold' + ? { + threshold: { + value: 10, + field: 'fieldA', + }, + } + : {}), + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'kql_query', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueSameUpdate, + expectedFieldDiffValues: { + base: { + query: 'process.name:*.exe', + language: 'kuery', + type: KqlQueryType.inline_query, + filters: [], + }, + current: { + query: '*:*', + language: 'kuery', + type: KqlQueryType.inline_query, + filters: [], + }, + target: { + query: '*:*', + language: 'kuery', + type: KqlQueryType.inline_query, + filters: [], + }, + merged: { + query: '*:*', + language: 'kuery', + type: KqlQueryType.inline_query, + filters: [], + }, + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'kql_query', + expectedFieldsAfterUpgrade: { type: ruleType, query: '*:*', language: 'kuery' }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'kql_query', + resolvedValue: { + type: KqlQueryType.inline_query, + query: 'resolved:*', + language: 'kuery', + filters: [], + }, + expectedFieldsAfterUpgrade: { + type: ruleType, + query: 'resolved:*', + language: 'kuery', + }, + }, + getService + ); + }); + + describe('customized w/ an upgrade resulting in a conflict (ABC diff case, non-solvable conflict)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: ruleType, + query: 'process.name:*.exe', + language: 'kuery', + ...(ruleType === 'threshold' + ? { + threshold: { + value: 10, + field: 'fieldA', + }, + } + : {}), + }, + patch: { + type: ruleType, + query: '*:*', + ...(ruleType === 'threshold' + ? { + threshold: { + value: 10, + field: 'fieldA', + }, + } + : {}), + }, + upgrade: { + type: ruleType, + query: 'process.name:*.sys', + language: 'kuery', + ...(ruleType === 'threshold' + ? { + threshold: { + value: 10, + field: 'fieldA', + }, + } + : {}), + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'kql_query', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueCanUpdate, + isSolvableConflict: false, + expectedFieldDiffValues: { + base: { + query: 'process.name:*.exe', + language: 'kuery', + type: KqlQueryType.inline_query, + filters: [], + }, + current: { + query: '*:*', + language: 'kuery', + type: KqlQueryType.inline_query, + filters: [], + }, + target: { + query: 'process.name:*.sys', + language: 'kuery', + type: KqlQueryType.inline_query, + filters: [], + }, + merged: { + query: '*:*', + language: 'kuery', + type: KqlQueryType.inline_query, + filters: [], + }, + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'kql_query', + resolvedValue: { + type: KqlQueryType.inline_query, + query: 'resolved:*', + language: 'kuery', + filters: [], + }, + expectedFieldsAfterUpgrade: { + type: ruleType, + query: 'resolved:*', + language: 'kuery', + }, + }, + getService + ); + }); + + describe('without historical versions', () => { + describe('customized w/ the matching upgrade (-AA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: ruleType, + query: 'process.name:*.exe', + language: 'kuery', + ...(ruleType === 'threshold' + ? { + threshold: { + value: 10, + field: 'fieldA', + }, + } + : {}), + }, + patch: { + type: ruleType, + query: 'process.name:*.sys', + ...(ruleType === 'threshold' + ? { + threshold: { + value: 10, + field: 'fieldA', + }, + } + : {}), + }, + upgrade: { + type: ruleType, + query: 'process.name:*.sys', + language: 'kuery', + ...(ruleType === 'threshold' + ? { + threshold: { + value: 10, + field: 'fieldA', + }, + } + : {}), + }, + removeInstalledAssets: true, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'kql_query', + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseNoUpdate, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'kql_query', + resolvedValue: { + type: KqlQueryType.inline_query, + query: 'resolved:*', + language: 'kuery', + filters: [], + }, + expectedFieldsAfterUpgrade: { + type: ruleType, + query: 'resolved:*', + language: 'kuery', + }, + }, + getService + ); + }); + + describe('customized w/ an upgrade (-AB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: ruleType, + query: 'process.name:*.exe', + language: 'kuery', + ...(ruleType === 'threshold' + ? { + threshold: { + value: 10, + field: 'fieldA', + }, + } + : {}), + }, + patch: { + type: ruleType, + query: '*:*', + ...(ruleType === 'threshold' + ? { + threshold: { + value: 10, + field: 'fieldA', + }, + } + : {}), + }, + upgrade: { + type: ruleType, + query: 'process.name:*.sys', + language: 'kuery', + ...(ruleType === 'threshold' + ? { + threshold: { + value: 10, + field: 'fieldA', + }, + } + : {}), + }, + removeInstalledAssets: true, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'kql_query', + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseCanUpdate, + expectedFieldDiffValues: { + current: { + query: '*:*', + language: 'kuery', + type: KqlQueryType.inline_query, + filters: [], + }, + target: { + query: 'process.name:*.sys', + language: 'kuery', + type: KqlQueryType.inline_query, + filters: [], + }, + merged: { + query: 'process.name:*.sys', + language: 'kuery', + type: KqlQueryType.inline_query, + filters: [], + }, + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'kql_query', + resolvedValue: { + type: KqlQueryType.inline_query, + query: 'resolved:*', + language: 'kuery', + filters: [], + }, + expectedFieldsAfterUpgrade: { + type: ruleType, + query: 'resolved:*', + language: 'kuery', + }, + }, + getService + ); + }); + }); + }); + } +} diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/type_specific_fields/kql_query.saved_query.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/type_specific_fields/kql_query.saved_query.ts new file mode 100644 index 0000000000000..faacc1ea63ea8 --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/type_specific_fields/kql_query.saved_query.ts @@ -0,0 +1,390 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +// Temporally comment contents until https://github.com/elastic/kibana/issues/209343 is fixed + +import { + KqlQueryType, + ThreeWayDiffOutcome, +} from '@kbn/security-solution-plugin/common/api/detection_engine'; +import { FtrProviderContext } from '../../../../../../../../ftr_provider_context'; +import type { TestFieldRuleUpgradeAssets } from '../test_helpers'; +import { + testFieldUpgradeReview, + testFieldUpgradesToMergedValue, + testFieldUpgradesToResolvedValue, +} from '../test_helpers'; + +export function savedQueryKqlQueryField({ getService }: FtrProviderContext): void { + describe('"kql_query" with saved query', () => { + describe('non-customized w/o an upgrade (AAA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'saved_query', + saved_id: 'saved_query_id1', + }, + patch: {}, + upgrade: { + type: 'saved_query', + saved_id: 'saved_query_id1', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'kql_query', + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueNoUpdate, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'kql_query', + resolvedValue: { + type: KqlQueryType.saved_query, + saved_query_id: 'resolved', + }, + expectedFieldsAfterUpgrade: { saved_id: 'resolved' }, + }, + getService + ); + }); + + describe('non-customized w/ an upgrade (AAB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'saved_query', + saved_id: 'saved_query_id1', + }, + patch: {}, + upgrade: { + type: 'saved_query', + saved_id: 'saved_query_id2', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'kql_query', + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueCanUpdate, + expectedFieldDiffValues: { + base: { + saved_query_id: 'saved_query_id1', + }, + current: { + saved_query_id: 'saved_query_id1', + }, + target: { + saved_query_id: 'saved_query_id2', + }, + merged: { + saved_query_id: 'saved_query_id2', + }, + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'kql_query', + expectedFieldsAfterUpgrade: { saved_id: 'saved_query_id2' }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'kql_query', + resolvedValue: { + type: KqlQueryType.saved_query, + saved_query_id: 'resolved', + }, + expectedFieldsAfterUpgrade: { saved_id: 'resolved' }, + }, + getService + ); + }); + + describe('customized w/o an upgrade (ABA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'saved_query', + saved_id: 'saved_query_id1', + }, + patch: { + type: 'saved_query', + saved_id: 'saved_query_id2', + }, + upgrade: { + type: 'saved_query', + saved_id: 'saved_query_id1', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'kql_query', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueNoUpdate, + expectedFieldDiffValues: { + base: { + saved_query_id: 'saved_query_id1', + }, + current: { + saved_query_id: 'saved_query_id2', + }, + target: { + saved_query_id: 'saved_query_id1', + }, + merged: { + saved_query_id: 'saved_query_id2', + }, + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'kql_query', + expectedFieldsAfterUpgrade: { saved_id: 'saved_query_id2' }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'kql_query', + resolvedValue: { + type: KqlQueryType.saved_query, + saved_query_id: 'resolved', + }, + expectedFieldsAfterUpgrade: { saved_id: 'resolved' }, + }, + getService + ); + }); + + describe('customized w/ the matching upgrade (ABB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'saved_query', + saved_id: 'saved_query_id1', + }, + patch: { + type: 'saved_query', + saved_id: 'saved_query_id2', + }, + upgrade: { + type: 'saved_query', + saved_id: 'saved_query_id2', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'kql_query', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueSameUpdate, + expectedFieldDiffValues: { + base: { + saved_query_id: 'saved_query_id1', + }, + current: { + saved_query_id: 'saved_query_id2', + }, + target: { + saved_query_id: 'saved_query_id2', + }, + merged: { + saved_query_id: 'saved_query_id2', + }, + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'kql_query', + expectedFieldsAfterUpgrade: { saved_id: 'saved_query_id2' }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'kql_query', + resolvedValue: { + type: KqlQueryType.saved_query, + saved_query_id: 'resolved', + }, + expectedFieldsAfterUpgrade: { saved_id: 'resolved' }, + }, + getService + ); + }); + + describe('customized w/ an upgrade resulting in a conflict (ABC diff case, non-solvable conflict)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'saved_query', + saved_id: 'saved_query_id1', + }, + patch: { + type: 'saved_query', + saved_id: 'saved_query_id2', + }, + upgrade: { + type: 'saved_query', + saved_id: 'saved_query_id3', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'kql_query', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueCanUpdate, + isSolvableConflict: false, + expectedFieldDiffValues: { + base: { + saved_query_id: 'saved_query_id1', + }, + current: { + saved_query_id: 'saved_query_id2', + }, + target: { + saved_query_id: 'saved_query_id3', + }, + merged: { + saved_query_id: 'saved_query_id2', + }, + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'kql_query', + resolvedValue: { + type: KqlQueryType.saved_query, + saved_query_id: 'resolved', + }, + expectedFieldsAfterUpgrade: { saved_id: 'resolved' }, + }, + getService + ); + }); + + describe('without historical versions', () => { + describe('customized w/ the matching upgrade (-AA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'saved_query', + saved_id: 'saved_query_id1', + }, + patch: { + type: 'saved_query', + saved_id: 'saved_query_id2', + }, + upgrade: { + type: 'saved_query', + saved_id: 'saved_query_id2', + }, + removeInstalledAssets: true, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'kql_query', + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseNoUpdate, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'kql_query', + resolvedValue: { + type: KqlQueryType.saved_query, + saved_query_id: 'resolved', + }, + expectedFieldsAfterUpgrade: { saved_id: 'resolved' }, + }, + getService + ); + }); + + describe('customized w/ an upgrade (-AB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'saved_query', + saved_id: 'saved_query_id1', + }, + patch: { + type: 'saved_query', + saved_id: 'saved_query_id2', + }, + upgrade: { + type: 'saved_query', + saved_id: 'saved_query_id3', + }, + removeInstalledAssets: true, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'kql_query', + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseCanUpdate, + expectedFieldDiffValues: { + current: { + saved_query_id: 'saved_query_id2', + }, + target: { + saved_query_id: 'saved_query_id3', + }, + merged: { + saved_query_id: 'saved_query_id3', + }, + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'kql_query', + resolvedValue: { + type: KqlQueryType.saved_query, + saved_query_id: 'resolved', + }, + expectedFieldsAfterUpgrade: { saved_id: 'resolved' }, + }, + getService + ); + }); + }); + }); +} diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/type_specific_fields/machine_learning_job_id.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/type_specific_fields/machine_learning_job_id.ts new file mode 100644 index 0000000000000..64c08959eb016 --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/type_specific_fields/machine_learning_job_id.ts @@ -0,0 +1,326 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { ThreeWayDiffOutcome } from '@kbn/security-solution-plugin/common/api/detection_engine'; +import { FtrProviderContext } from '../../../../../../../../ftr_provider_context'; +import type { TestFieldRuleUpgradeAssets } from '../test_helpers'; +import { + testFieldUpgradeReview, + testFieldUpgradesToMergedValue, + testFieldUpgradesToResolvedValue, +} from '../test_helpers'; + +export function machineLearningJobIdField({ getService }: FtrProviderContext): void { + describe('"machine_learning_job_id"', () => { + describe('non-customized w/o an upgrade (AAA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'machine_learning', + machine_learning_job_id: 'jobA', + }, + patch: {}, + upgrade: { + type: 'machine_learning', + machine_learning_job_id: 'jobA', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'machine_learning_job_id', + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueNoUpdate, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'machine_learning_job_id', + resolvedValue: ['resolved'], + expectedFieldsAfterUpgrade: { machine_learning_job_id: ['resolved'] }, + }, + getService + ); + }); + + describe('non-customized w/ an upgrade (AAB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'machine_learning', + machine_learning_job_id: 'jobA', + }, + patch: {}, + upgrade: { + type: 'machine_learning', + machine_learning_job_id: 'jobB', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'machine_learning_job_id', + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueCanUpdate, + expectedFieldDiffValues: { + base: ['jobA'], + current: ['jobA'], + target: ['jobB'], + merged: ['jobB'], + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'machine_learning_job_id', + expectedFieldsAfterUpgrade: { machine_learning_job_id: ['jobB'] }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'machine_learning_job_id', + resolvedValue: ['resolved'], + expectedFieldsAfterUpgrade: { machine_learning_job_id: ['resolved'] }, + }, + getService + ); + }); + + describe('customized w/o an upgrade (ABA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'machine_learning', + machine_learning_job_id: 'jobA', + }, + patch: { + type: 'machine_learning', + machine_learning_job_id: 'jobB', + }, + upgrade: { + type: 'machine_learning', + machine_learning_job_id: 'jobA', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'machine_learning_job_id', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueNoUpdate, + expectedFieldDiffValues: { + base: ['jobA'], + current: ['jobB'], + target: ['jobA'], + merged: ['jobB'], + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'machine_learning_job_id', + expectedFieldsAfterUpgrade: { machine_learning_job_id: ['jobB'] }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'machine_learning_job_id', + resolvedValue: ['resolved'], + expectedFieldsAfterUpgrade: { machine_learning_job_id: ['resolved'] }, + }, + getService + ); + }); + + describe('customized w/ the matching upgrade (ABB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'machine_learning', + machine_learning_job_id: 'jobA', + }, + patch: { + type: 'machine_learning', + machine_learning_job_id: 'jobB', + }, + upgrade: { + type: 'machine_learning', + machine_learning_job_id: 'jobB', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'machine_learning_job_id', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueSameUpdate, + expectedFieldDiffValues: { + base: ['jobA'], + current: ['jobB'], + target: ['jobB'], + merged: ['jobB'], + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'machine_learning_job_id', + expectedFieldsAfterUpgrade: { machine_learning_job_id: ['jobB'] }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'machine_learning_job_id', + resolvedValue: ['resolved'], + expectedFieldsAfterUpgrade: { machine_learning_job_id: ['resolved'] }, + }, + getService + ); + }); + + describe('customized w/ an upgrade resulting in a conflict (ABC diff case, non-solvable conflict)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'machine_learning', + machine_learning_job_id: 'jobA', + }, + patch: { + type: 'machine_learning', + machine_learning_job_id: 'jobB', + }, + upgrade: { + type: 'machine_learning', + machine_learning_job_id: 'jobC', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'machine_learning_job_id', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueCanUpdate, + isSolvableConflict: false, + expectedFieldDiffValues: { + base: ['jobA'], + current: ['jobB'], + target: ['jobC'], + merged: ['jobB'], + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'machine_learning_job_id', + resolvedValue: ['resolved'], + expectedFieldsAfterUpgrade: { machine_learning_job_id: ['resolved'] }, + }, + getService + ); + }); + + describe('without historical versions', () => { + describe('customized w/ the matching upgrade (-AA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'machine_learning', + machine_learning_job_id: 'jobA', + }, + patch: { + type: 'machine_learning', + machine_learning_job_id: 'jobB', + }, + upgrade: { + type: 'machine_learning', + machine_learning_job_id: 'jobB', + }, + removeInstalledAssets: true, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'machine_learning_job_id', + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseNoUpdate, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'machine_learning_job_id', + resolvedValue: ['resolved'], + expectedFieldsAfterUpgrade: { machine_learning_job_id: ['resolved'] }, + }, + getService + ); + }); + + describe('customized w/ an upgrade (-AB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'machine_learning', + machine_learning_job_id: 'jobA', + }, + patch: { + type: 'machine_learning', + machine_learning_job_id: 'jobB', + }, + upgrade: { + type: 'machine_learning', + machine_learning_job_id: 'jobC', + }, + removeInstalledAssets: true, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'machine_learning_job_id', + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseCanUpdate, + expectedFieldDiffValues: { + current: ['jobB'], + target: ['jobC'], + merged: ['jobC'], + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'machine_learning_job_id', + resolvedValue: ['resolved'], + expectedFieldsAfterUpgrade: { machine_learning_job_id: ['resolved'] }, + }, + getService + ); + }); + }); + }); +} diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/type_specific_fields/new_terms_fields.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/type_specific_fields/new_terms_fields.ts new file mode 100644 index 0000000000000..3af660439c1ee --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/type_specific_fields/new_terms_fields.ts @@ -0,0 +1,326 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { ThreeWayDiffOutcome } from '@kbn/security-solution-plugin/common/api/detection_engine'; +import { FtrProviderContext } from '../../../../../../../../ftr_provider_context'; +import type { TestFieldRuleUpgradeAssets } from '../test_helpers'; +import { + testFieldUpgradeReview, + testFieldUpgradesToMergedValue, + testFieldUpgradesToResolvedValue, +} from '../test_helpers'; + +export function newTermsFieldsField({ getService }: FtrProviderContext): void { + describe('"new_terms_fields"', () => { + describe('non-customized w/o an upgrade (AAA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'new_terms', + new_terms_fields: ['fieldA'], + }, + patch: {}, + upgrade: { + type: 'new_terms', + new_terms_fields: ['fieldA'], + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'new_terms_fields', + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueNoUpdate, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'new_terms_fields', + resolvedValue: ['resolved'], + expectedFieldsAfterUpgrade: { new_terms_fields: ['resolved'] }, + }, + getService + ); + }); + + describe('non-customized w/ an upgrade (AAB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'new_terms', + new_terms_fields: ['fieldA'], + }, + patch: {}, + upgrade: { + type: 'new_terms', + new_terms_fields: ['fieldB'], + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'new_terms_fields', + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueCanUpdate, + expectedFieldDiffValues: { + base: ['fieldA'], + current: ['fieldA'], + target: ['fieldB'], + merged: ['fieldB'], + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'new_terms_fields', + expectedFieldsAfterUpgrade: { new_terms_fields: ['fieldB'] }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'new_terms_fields', + resolvedValue: ['resolved'], + expectedFieldsAfterUpgrade: { new_terms_fields: ['resolved'] }, + }, + getService + ); + }); + + describe('customized w/o an upgrade (ABA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'new_terms', + new_terms_fields: ['fieldA'], + }, + patch: { + type: 'new_terms', + new_terms_fields: ['fieldB'], + }, + upgrade: { + type: 'new_terms', + new_terms_fields: ['fieldA'], + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'new_terms_fields', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueNoUpdate, + expectedFieldDiffValues: { + base: ['fieldA'], + current: ['fieldB'], + target: ['fieldA'], + merged: ['fieldB'], + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'new_terms_fields', + expectedFieldsAfterUpgrade: { new_terms_fields: ['fieldB'] }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'new_terms_fields', + resolvedValue: ['resolved'], + expectedFieldsAfterUpgrade: { new_terms_fields: ['resolved'] }, + }, + getService + ); + }); + + describe('customized w/ the matching upgrade (ABB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'new_terms', + new_terms_fields: ['fieldA'], + }, + patch: { + type: 'new_terms', + new_terms_fields: ['fieldB'], + }, + upgrade: { + type: 'new_terms', + new_terms_fields: ['fieldB'], + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'new_terms_fields', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueSameUpdate, + expectedFieldDiffValues: { + base: ['fieldA'], + current: ['fieldB'], + target: ['fieldB'], + merged: ['fieldB'], + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'new_terms_fields', + expectedFieldsAfterUpgrade: { new_terms_fields: ['fieldB'] }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'new_terms_fields', + resolvedValue: ['resolved'], + expectedFieldsAfterUpgrade: { new_terms_fields: ['resolved'] }, + }, + getService + ); + }); + + describe('customized w/ an upgrade resulting in a conflict (ABC diff case, solvable conflict)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'new_terms', + new_terms_fields: ['fieldA'], + }, + patch: { + type: 'new_terms', + new_terms_fields: ['fieldB'], + }, + upgrade: { + type: 'new_terms', + new_terms_fields: ['fieldA', 'fieldC'], + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'new_terms_fields', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueCanUpdate, + isSolvableConflict: true, + expectedFieldDiffValues: { + base: ['fieldA'], + current: ['fieldB'], + target: ['fieldA', 'fieldC'], + merged: ['fieldB', 'fieldC'], + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'new_terms_fields', + resolvedValue: ['resolved'], + expectedFieldsAfterUpgrade: { new_terms_fields: ['resolved'] }, + }, + getService + ); + }); + + describe('without historical versions', () => { + describe('customized w/ the matching upgrade (-AA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'new_terms', + new_terms_fields: ['fieldA'], + }, + patch: { + type: 'new_terms', + new_terms_fields: ['fieldB'], + }, + upgrade: { + type: 'new_terms', + new_terms_fields: ['fieldB'], + }, + removeInstalledAssets: true, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'new_terms_fields', + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseNoUpdate, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'new_terms_fields', + resolvedValue: ['resolved'], + expectedFieldsAfterUpgrade: { new_terms_fields: ['resolved'] }, + }, + getService + ); + }); + + describe('customized w/ an upgrade (-AB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'new_terms', + new_terms_fields: ['fieldA'], + }, + patch: { + type: 'new_terms', + new_terms_fields: ['fieldB'], + }, + upgrade: { + type: 'new_terms', + new_terms_fields: ['fieldA', 'fieldC'], + }, + removeInstalledAssets: true, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'new_terms_fields', + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseCanUpdate, + expectedFieldDiffValues: { + current: ['fieldB'], + target: ['fieldA', 'fieldC'], + merged: ['fieldA', 'fieldC'], + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'new_terms_fields', + resolvedValue: ['resolved'], + expectedFieldsAfterUpgrade: { new_terms_fields: ['resolved'] }, + }, + getService + ); + }); + }); + }); +} diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/type_specific_fields/threat_index.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/type_specific_fields/threat_index.ts new file mode 100644 index 0000000000000..41c6c6f7cf2fd --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/type_specific_fields/threat_index.ts @@ -0,0 +1,326 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { ThreeWayDiffOutcome } from '@kbn/security-solution-plugin/common/api/detection_engine'; +import { FtrProviderContext } from '../../../../../../../../ftr_provider_context'; +import type { TestFieldRuleUpgradeAssets } from '../test_helpers'; +import { + testFieldUpgradeReview, + testFieldUpgradesToMergedValue, + testFieldUpgradesToResolvedValue, +} from '../test_helpers'; + +export function threatIndexField({ getService }: FtrProviderContext): void { + describe('"threat_index"', () => { + describe('non-customized w/o an upgrade (AAA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'threat_match', + threat_index: ['indexA'], + }, + patch: {}, + upgrade: { + type: 'threat_match', + threat_index: ['indexA'], + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat_index', + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueNoUpdate, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat_index', + resolvedValue: ['resolved'], + expectedFieldsAfterUpgrade: { threat_index: ['resolved'] }, + }, + getService + ); + }); + + describe('non-customized w/ an upgrade (AAB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'threat_match', + threat_index: ['indexA'], + }, + patch: {}, + upgrade: { + type: 'threat_match', + threat_index: ['indexB'], + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat_index', + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueCanUpdate, + expectedFieldDiffValues: { + base: ['indexA'], + current: ['indexA'], + target: ['indexB'], + merged: ['indexB'], + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat_index', + expectedFieldsAfterUpgrade: { threat_index: ['indexB'] }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat_index', + resolvedValue: ['resolved'], + expectedFieldsAfterUpgrade: { threat_index: ['resolved'] }, + }, + getService + ); + }); + + describe('customized w/o an upgrade (ABA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'threat_match', + threat_index: ['indexA'], + }, + patch: { + type: 'threat_match', + threat_index: ['indexB'], + }, + upgrade: { + type: 'threat_match', + threat_index: ['indexA'], + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat_index', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueNoUpdate, + expectedFieldDiffValues: { + base: ['indexA'], + current: ['indexB'], + target: ['indexA'], + merged: ['indexB'], + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat_index', + expectedFieldsAfterUpgrade: { threat_index: ['indexB'] }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat_index', + resolvedValue: ['resolved'], + expectedFieldsAfterUpgrade: { threat_index: ['resolved'] }, + }, + getService + ); + }); + + describe('customized w/ the matching upgrade (ABB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'threat_match', + threat_index: ['indexA'], + }, + patch: { + type: 'threat_match', + threat_index: ['indexB'], + }, + upgrade: { + type: 'threat_match', + threat_index: ['indexB'], + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat_index', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueSameUpdate, + expectedFieldDiffValues: { + base: ['indexA'], + current: ['indexB'], + target: ['indexB'], + merged: ['indexB'], + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat_index', + expectedFieldsAfterUpgrade: { threat_index: ['indexB'] }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat_index', + resolvedValue: ['resolved'], + expectedFieldsAfterUpgrade: { threat_index: ['resolved'] }, + }, + getService + ); + }); + + describe('customized w/ an upgrade resulting in a conflict (ABC diff case, solvable conflict)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'threat_match', + threat_index: ['indexA'], + }, + patch: { + type: 'threat_match', + threat_index: ['indexD'], + }, + upgrade: { + type: 'threat_match', + threat_index: ['indexB', 'indexC'], + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat_index', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueCanUpdate, + isSolvableConflict: true, + expectedFieldDiffValues: { + base: ['indexA'], + current: ['indexD'], + target: ['indexB', 'indexC'], + merged: ['indexD', 'indexB', 'indexC'], + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat_index', + resolvedValue: ['resolved'], + expectedFieldsAfterUpgrade: { threat_index: ['resolved'] }, + }, + getService + ); + }); + + describe('without historical versions', () => { + describe('customized w/ the matching upgrade (-AA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'threat_match', + threat_index: ['indexA'], + }, + patch: { + type: 'threat_match', + threat_index: ['indexD'], + }, + upgrade: { + type: 'threat_match', + threat_index: ['indexD'], + }, + removeInstalledAssets: true, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat_index', + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseNoUpdate, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat_index', + resolvedValue: ['resolved'], + expectedFieldsAfterUpgrade: { threat_index: ['resolved'] }, + }, + getService + ); + }); + + describe('customized w/ an upgrade (-AB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'threat_match', + threat_index: ['indexA'], + }, + patch: { + type: 'threat_match', + threat_index: ['indexD'], + }, + upgrade: { + type: 'threat_match', + threat_index: ['indexB', 'indexC'], + }, + removeInstalledAssets: true, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat_index', + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseCanUpdate, + expectedFieldDiffValues: { + current: ['indexD'], + target: ['indexB', 'indexC'], + merged: ['indexB', 'indexC'], + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat_index', + resolvedValue: ['resolved'], + expectedFieldsAfterUpgrade: { threat_index: ['resolved'] }, + }, + getService + ); + }); + }); + }); +} diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/type_specific_fields/threat_indicator_path.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/type_specific_fields/threat_indicator_path.ts new file mode 100644 index 0000000000000..de706df8c19b1 --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/type_specific_fields/threat_indicator_path.ts @@ -0,0 +1,326 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { ThreeWayDiffOutcome } from '@kbn/security-solution-plugin/common/api/detection_engine'; +import { FtrProviderContext } from '../../../../../../../../ftr_provider_context'; +import type { TestFieldRuleUpgradeAssets } from '../test_helpers'; +import { + testFieldUpgradeReview, + testFieldUpgradesToMergedValue, + testFieldUpgradesToResolvedValue, +} from '../test_helpers'; + +export function threatIndicatorPathField({ getService }: FtrProviderContext): void { + describe('"threat_indicator_path"', () => { + describe('non-customized w/o an upgrade (AAA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'threat_match', + threat_indicator_path: 'fieldA', + }, + patch: {}, + upgrade: { + type: 'threat_match', + threat_indicator_path: 'fieldA', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat_indicator_path', + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueNoUpdate, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat_indicator_path', + resolvedValue: 'resolved', + expectedFieldsAfterUpgrade: { threat_indicator_path: 'resolved' }, + }, + getService + ); + }); + + describe('non-customized w/ an upgrade (AAB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'threat_match', + threat_indicator_path: 'fieldA', + }, + patch: {}, + upgrade: { + type: 'threat_match', + threat_indicator_path: 'fieldB', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat_indicator_path', + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueCanUpdate, + expectedFieldDiffValues: { + base: 'fieldA', + current: 'fieldA', + target: 'fieldB', + merged: 'fieldB', + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat_indicator_path', + expectedFieldsAfterUpgrade: { threat_indicator_path: 'fieldB' }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat_indicator_path', + resolvedValue: 'resolved', + expectedFieldsAfterUpgrade: { threat_indicator_path: 'resolved' }, + }, + getService + ); + }); + + describe('customized w/o an upgrade (ABA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'threat_match', + threat_indicator_path: 'fieldA', + }, + patch: { + type: 'threat_match', + threat_indicator_path: 'fieldB', + }, + upgrade: { + type: 'threat_match', + threat_indicator_path: 'fieldA', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat_indicator_path', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueNoUpdate, + expectedFieldDiffValues: { + base: 'fieldA', + current: 'fieldB', + target: 'fieldA', + merged: 'fieldB', + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat_indicator_path', + expectedFieldsAfterUpgrade: { threat_indicator_path: 'fieldB' }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat_indicator_path', + resolvedValue: 'resolved', + expectedFieldsAfterUpgrade: { threat_indicator_path: 'resolved' }, + }, + getService + ); + }); + + describe('customized w/ the matching upgrade (ABB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'threat_match', + threat_indicator_path: 'fieldA', + }, + patch: { + type: 'threat_match', + threat_indicator_path: 'fieldB', + }, + upgrade: { + type: 'threat_match', + threat_indicator_path: 'fieldB', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat_indicator_path', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueSameUpdate, + expectedFieldDiffValues: { + base: 'fieldA', + current: 'fieldB', + target: 'fieldB', + merged: 'fieldB', + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat_indicator_path', + expectedFieldsAfterUpgrade: { threat_indicator_path: 'fieldB' }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat_indicator_path', + resolvedValue: 'resolved', + expectedFieldsAfterUpgrade: { threat_indicator_path: 'resolved' }, + }, + getService + ); + }); + + describe('customized w/ an upgrade resulting in a conflict (ABC diff case, non-solvable conflict)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'threat_match', + threat_indicator_path: 'fieldA', + }, + patch: { + type: 'threat_match', + threat_indicator_path: 'fieldB', + }, + upgrade: { + type: 'threat_match', + threat_indicator_path: 'fieldC', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat_indicator_path', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueCanUpdate, + isSolvableConflict: false, + expectedFieldDiffValues: { + base: 'fieldA', + current: 'fieldB', + target: 'fieldC', + merged: 'fieldB', + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat_indicator_path', + resolvedValue: 'resolved', + expectedFieldsAfterUpgrade: { threat_indicator_path: 'resolved' }, + }, + getService + ); + }); + + describe('without historical versions', () => { + describe('customized w/ the matching upgrade (-AA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'threat_match', + threat_indicator_path: 'fieldA', + }, + patch: { + type: 'threat_match', + threat_indicator_path: 'fieldB', + }, + upgrade: { + type: 'threat_match', + threat_indicator_path: 'fieldB', + }, + removeInstalledAssets: true, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat_indicator_path', + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseNoUpdate, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat_indicator_path', + resolvedValue: 'resolved', + expectedFieldsAfterUpgrade: { threat_indicator_path: 'resolved' }, + }, + getService + ); + }); + + describe('customized w/ an upgrade (-AB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'threat_match', + threat_indicator_path: 'fieldA', + }, + patch: { + type: 'threat_match', + threat_indicator_path: 'fieldB', + }, + upgrade: { + type: 'threat_match', + threat_indicator_path: 'fieldC', + }, + removeInstalledAssets: true, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat_indicator_path', + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseCanUpdate, + expectedFieldDiffValues: { + current: 'fieldB', + target: 'fieldC', + merged: 'fieldC', + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat_indicator_path', + resolvedValue: 'resolved', + expectedFieldsAfterUpgrade: { threat_indicator_path: 'resolved' }, + }, + getService + ); + }); + }); + }); +} diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/type_specific_fields/threat_mapping.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/type_specific_fields/threat_mapping.ts new file mode 100644 index 0000000000000..06763e06db802 --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/type_specific_fields/threat_mapping.ts @@ -0,0 +1,374 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { ThreeWayDiffOutcome } from '@kbn/security-solution-plugin/common/api/detection_engine'; +import { FtrProviderContext } from '../../../../../../../../ftr_provider_context'; +import type { TestFieldRuleUpgradeAssets } from '../test_helpers'; +import { + testFieldUpgradeReview, + testFieldUpgradesToMergedValue, + testFieldUpgradesToResolvedValue, +} from '../test_helpers'; + +export function threatMappingField({ getService }: FtrProviderContext): void { + describe('"threat_mapping"', () => { + describe('non-customized w/o an upgrade (AAA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'threat_match', + threat_mapping: [{ entries: [{ type: 'mapping', field: 'fieldA', value: 'fieldZ' }] }], + }, + patch: {}, + upgrade: { + type: 'threat_match', + threat_mapping: [{ entries: [{ type: 'mapping', field: 'fieldA', value: 'fieldZ' }] }], + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat_mapping', + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueNoUpdate, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat_mapping', + resolvedValue: [ + { entries: [{ type: 'mapping', field: 'resolvedA', value: 'resolvedB' }] }, + ], + expectedFieldsAfterUpgrade: { + threat_mapping: [ + { entries: [{ type: 'mapping', field: 'resolvedA', value: 'resolvedB' }] }, + ], + }, + }, + getService + ); + }); + + describe('non-customized w/ an upgrade (AAB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'threat_match', + threat_mapping: [{ entries: [{ type: 'mapping', field: 'fieldA', value: 'fieldZ' }] }], + }, + patch: {}, + upgrade: { + type: 'threat_match', + threat_mapping: [{ entries: [{ type: 'mapping', field: 'fieldB', value: 'fieldZ' }] }], + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat_mapping', + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueCanUpdate, + expectedFieldDiffValues: { + base: [{ entries: [{ type: 'mapping', field: 'fieldA', value: 'fieldZ' }] }], + current: [{ entries: [{ type: 'mapping', field: 'fieldA', value: 'fieldZ' }] }], + target: [{ entries: [{ type: 'mapping', field: 'fieldB', value: 'fieldZ' }] }], + merged: [{ entries: [{ type: 'mapping', field: 'fieldB', value: 'fieldZ' }] }], + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat_mapping', + expectedFieldsAfterUpgrade: { + threat_mapping: [{ entries: [{ type: 'mapping', field: 'fieldB', value: 'fieldZ' }] }], + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat_mapping', + resolvedValue: [ + { entries: [{ type: 'mapping', field: 'resolvedA', value: 'resolvedB' }] }, + ], + expectedFieldsAfterUpgrade: { + threat_mapping: [ + { entries: [{ type: 'mapping', field: 'resolvedA', value: 'resolvedB' }] }, + ], + }, + }, + getService + ); + }); + + describe('customized w/o an upgrade (ABA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'threat_match', + threat_mapping: [{ entries: [{ type: 'mapping', field: 'fieldA', value: 'fieldZ' }] }], + }, + patch: { + type: 'threat_match', + threat_mapping: [{ entries: [{ type: 'mapping', field: 'fieldB', value: 'fieldZ' }] }], + }, + upgrade: { + type: 'threat_match', + threat_mapping: [{ entries: [{ type: 'mapping', field: 'fieldA', value: 'fieldZ' }] }], + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat_mapping', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueNoUpdate, + expectedFieldDiffValues: { + base: [{ entries: [{ type: 'mapping', field: 'fieldA', value: 'fieldZ' }] }], + current: [{ entries: [{ type: 'mapping', field: 'fieldB', value: 'fieldZ' }] }], + target: [{ entries: [{ type: 'mapping', field: 'fieldA', value: 'fieldZ' }] }], + merged: [{ entries: [{ type: 'mapping', field: 'fieldB', value: 'fieldZ' }] }], + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat_mapping', + expectedFieldsAfterUpgrade: { + threat_mapping: [{ entries: [{ type: 'mapping', field: 'fieldB', value: 'fieldZ' }] }], + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat_mapping', + resolvedValue: [ + { entries: [{ type: 'mapping', field: 'resolvedA', value: 'resolvedB' }] }, + ], + expectedFieldsAfterUpgrade: { + threat_mapping: [ + { entries: [{ type: 'mapping', field: 'resolvedA', value: 'resolvedB' }] }, + ], + }, + }, + getService + ); + }); + + describe('customized w/ the matching upgrade (ABB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'threat_match', + threat_mapping: [{ entries: [{ type: 'mapping', field: 'fieldA', value: 'fieldZ' }] }], + }, + patch: { + type: 'threat_match', + threat_mapping: [{ entries: [{ type: 'mapping', field: 'fieldB', value: 'fieldZ' }] }], + }, + upgrade: { + type: 'threat_match', + threat_mapping: [{ entries: [{ type: 'mapping', field: 'fieldB', value: 'fieldZ' }] }], + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat_mapping', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueSameUpdate, + expectedFieldDiffValues: { + base: [{ entries: [{ type: 'mapping', field: 'fieldA', value: 'fieldZ' }] }], + current: [{ entries: [{ type: 'mapping', field: 'fieldB', value: 'fieldZ' }] }], + target: [{ entries: [{ type: 'mapping', field: 'fieldB', value: 'fieldZ' }] }], + merged: [{ entries: [{ type: 'mapping', field: 'fieldB', value: 'fieldZ' }] }], + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat_mapping', + expectedFieldsAfterUpgrade: { + threat_mapping: [{ entries: [{ type: 'mapping', field: 'fieldB', value: 'fieldZ' }] }], + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat_mapping', + resolvedValue: [ + { entries: [{ type: 'mapping', field: 'resolvedA', value: 'resolvedB' }] }, + ], + expectedFieldsAfterUpgrade: { + threat_mapping: [ + { entries: [{ type: 'mapping', field: 'resolvedA', value: 'resolvedB' }] }, + ], + }, + }, + getService + ); + }); + + describe('customized w/ an upgrade resulting in a conflict (ABC diff case, non-solvable conflict)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'threat_match', + threat_mapping: [{ entries: [{ type: 'mapping', field: 'fieldA', value: 'fieldZ' }] }], + }, + patch: { + type: 'threat_match', + threat_mapping: [{ entries: [{ type: 'mapping', field: 'fieldB', value: 'fieldZ' }] }], + }, + upgrade: { + type: 'threat_match', + threat_mapping: [{ entries: [{ type: 'mapping', field: 'fieldC', value: 'fieldZ' }] }], + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat_mapping', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueCanUpdate, + isSolvableConflict: false, + expectedFieldDiffValues: { + base: [{ entries: [{ type: 'mapping', field: 'fieldA', value: 'fieldZ' }] }], + current: [{ entries: [{ type: 'mapping', field: 'fieldB', value: 'fieldZ' }] }], + target: [{ entries: [{ type: 'mapping', field: 'fieldC', value: 'fieldZ' }] }], + merged: [{ entries: [{ type: 'mapping', field: 'fieldB', value: 'fieldZ' }] }], + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat_mapping', + resolvedValue: [ + { entries: [{ type: 'mapping', field: 'resolvedA', value: 'resolvedB' }] }, + ], + expectedFieldsAfterUpgrade: { + threat_mapping: [ + { entries: [{ type: 'mapping', field: 'resolvedA', value: 'resolvedB' }] }, + ], + }, + }, + getService + ); + }); + + describe('without historical versions', () => { + describe('customized w/ the matching upgrade (-AA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'threat_match', + threat_mapping: [{ entries: [{ type: 'mapping', field: 'fieldA', value: 'fieldZ' }] }], + }, + patch: { + type: 'threat_match', + threat_mapping: [{ entries: [{ type: 'mapping', field: 'fieldB', value: 'fieldZ' }] }], + }, + upgrade: { + type: 'threat_match', + threat_mapping: [{ entries: [{ type: 'mapping', field: 'fieldB', value: 'fieldZ' }] }], + }, + removeInstalledAssets: true, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat_mapping', + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseNoUpdate, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat_mapping', + resolvedValue: [ + { entries: [{ type: 'mapping', field: 'resolvedA', value: 'resolvedB' }] }, + ], + expectedFieldsAfterUpgrade: { + threat_mapping: [ + { entries: [{ type: 'mapping', field: 'resolvedA', value: 'resolvedB' }] }, + ], + }, + }, + getService + ); + }); + + describe('customized w/ an upgrade (-AB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'threat_match', + threat_mapping: [{ entries: [{ type: 'mapping', field: 'fieldA', value: 'fieldZ' }] }], + }, + patch: { + type: 'threat_match', + threat_mapping: [{ entries: [{ type: 'mapping', field: 'fieldB', value: 'fieldZ' }] }], + }, + upgrade: { + type: 'threat_match', + threat_mapping: [{ entries: [{ type: 'mapping', field: 'fieldC', value: 'fieldZ' }] }], + }, + removeInstalledAssets: true, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat_mapping', + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseCanUpdate, + expectedFieldDiffValues: { + current: [{ entries: [{ type: 'mapping', field: 'fieldB', value: 'fieldZ' }] }], + target: [{ entries: [{ type: 'mapping', field: 'fieldC', value: 'fieldZ' }] }], + merged: [{ entries: [{ type: 'mapping', field: 'fieldC', value: 'fieldZ' }] }], + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat_mapping', + resolvedValue: [ + { entries: [{ type: 'mapping', field: 'resolvedA', value: 'resolvedB' }] }, + ], + expectedFieldsAfterUpgrade: { + threat_mapping: [ + { entries: [{ type: 'mapping', field: 'resolvedA', value: 'resolvedB' }] }, + ], + }, + }, + getService + ); + }); + }); + }); +} diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/type_specific_fields/threat_query.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/type_specific_fields/threat_query.ts new file mode 100644 index 0000000000000..a30c3a4cb6cf9 --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/type_specific_fields/threat_query.ts @@ -0,0 +1,468 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { + KqlQueryType, + ThreeWayDiffOutcome, +} from '@kbn/security-solution-plugin/common/api/detection_engine'; +import { FtrProviderContext } from '../../../../../../../../ftr_provider_context'; +import type { TestFieldRuleUpgradeAssets } from '../test_helpers'; +import { + testFieldUpgradeReview, + testFieldUpgradesToMergedValue, + testFieldUpgradesToResolvedValue, +} from '../test_helpers'; + +export function threatQueryField({ getService }: FtrProviderContext): void { + describe('"threat_query"', () => { + describe('non-customized w/o an upgrade (AAA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'threat_match', + threat_query: 'process.name:*.exe', + }, + patch: {}, + upgrade: { + type: 'threat_match', + threat_query: 'process.name:*.exe', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat_query', + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueNoUpdate, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat_query', + resolvedValue: { + type: KqlQueryType.inline_query, + query: 'resolved:*', + language: 'kuery', + filters: [], + }, + expectedFieldsAfterUpgrade: { threat_query: 'resolved:*', threat_language: 'kuery' }, + }, + getService + ); + }); + + describe('non-customized w/ an upgrade (AAB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'threat_match', + threat_query: 'process.name:*.exe', + }, + patch: {}, + upgrade: { + type: 'threat_match', + threat_query: 'process.name:*.sys', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat_query', + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueCanUpdate, + expectedFieldDiffValues: { + base: { + type: KqlQueryType.inline_query, + query: 'process.name:*.exe', + language: 'kuery', + filters: [], + }, + current: { + type: KqlQueryType.inline_query, + query: 'process.name:*.exe', + language: 'kuery', + filters: [], + }, + target: { + type: KqlQueryType.inline_query, + query: 'process.name:*.sys', + language: 'kuery', + filters: [], + }, + merged: { + type: KqlQueryType.inline_query, + query: 'process.name:*.sys', + language: 'kuery', + filters: [], + }, + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat_query', + expectedFieldsAfterUpgrade: { + threat_query: 'process.name:*.sys', + threat_language: 'kuery', + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat_query', + resolvedValue: { + type: KqlQueryType.inline_query, + query: 'resolved:*', + language: 'kuery', + filters: [], + }, + expectedFieldsAfterUpgrade: { threat_query: 'resolved:*', threat_language: 'kuery' }, + }, + getService + ); + }); + + describe('customized w/o an upgrade (ABA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'threat_match', + threat_query: 'process.name:*.exe', + }, + patch: { + type: 'threat_match', + threat_query: 'process.name:*.sys', + }, + upgrade: { + type: 'threat_match', + threat_query: 'process.name:*.exe', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat_query', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueNoUpdate, + expectedFieldDiffValues: { + base: { + type: KqlQueryType.inline_query, + query: 'process.name:*.exe', + language: 'kuery', + filters: [], + }, + current: { + type: KqlQueryType.inline_query, + query: 'process.name:*.sys', + language: 'kuery', + filters: [], + }, + target: { + type: KqlQueryType.inline_query, + query: 'process.name:*.exe', + language: 'kuery', + filters: [], + }, + merged: { + type: KqlQueryType.inline_query, + query: 'process.name:*.sys', + language: 'kuery', + filters: [], + }, + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat_query', + expectedFieldsAfterUpgrade: { + threat_query: 'process.name:*.sys', + threat_language: 'kuery', + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat_query', + resolvedValue: { + type: KqlQueryType.inline_query, + query: 'resolved:*', + language: 'kuery', + filters: [], + }, + expectedFieldsAfterUpgrade: { threat_query: 'resolved:*', threat_language: 'kuery' }, + }, + getService + ); + }); + + describe('customized w/ the matching upgrade (ABB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'threat_match', + threat_query: 'process.name:*.exe', + }, + patch: { + type: 'threat_match', + threat_query: 'process.name:*.sys', + }, + upgrade: { + type: 'threat_match', + threat_query: 'process.name:*.sys', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat_query', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueSameUpdate, + expectedFieldDiffValues: { + base: { + type: KqlQueryType.inline_query, + query: 'process.name:*.exe', + language: 'kuery', + filters: [], + }, + current: { + type: KqlQueryType.inline_query, + query: 'process.name:*.sys', + language: 'kuery', + filters: [], + }, + target: { + type: KqlQueryType.inline_query, + query: 'process.name:*.sys', + language: 'kuery', + filters: [], + }, + merged: { + type: KqlQueryType.inline_query, + query: 'process.name:*.sys', + language: 'kuery', + filters: [], + }, + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat_query', + expectedFieldsAfterUpgrade: { + threat_query: 'process.name:*.sys', + threat_language: 'kuery', + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat_query', + resolvedValue: { + type: KqlQueryType.inline_query, + query: 'resolved:*', + language: 'kuery', + filters: [], + }, + expectedFieldsAfterUpgrade: { threat_query: 'resolved:*', threat_language: 'kuery' }, + }, + getService + ); + }); + + describe('customized w/ an upgrade resulting in a conflict (ABC diff case, non-solvable conflict)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'threat_match', + threat_query: 'process.name:*.exe', + }, + patch: { + type: 'threat_match', + threat_query: 'process.name:*.sys', + }, + upgrade: { + type: 'threat_match', + threat_query: 'process.name:*.com', + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat_query', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueCanUpdate, + isSolvableConflict: false, + expectedFieldDiffValues: { + base: { + type: KqlQueryType.inline_query, + query: 'process.name:*.exe', + language: 'kuery', + filters: [], + }, + current: { + type: KqlQueryType.inline_query, + query: 'process.name:*.sys', + language: 'kuery', + filters: [], + }, + target: { + type: KqlQueryType.inline_query, + query: 'process.name:*.com', + language: 'kuery', + filters: [], + }, + merged: { + type: KqlQueryType.inline_query, + query: 'process.name:*.sys', + language: 'kuery', + filters: [], + }, + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat_query', + resolvedValue: { + type: KqlQueryType.inline_query, + query: 'resolved:*', + language: 'kuery', + filters: [], + }, + expectedFieldsAfterUpgrade: { threat_query: 'resolved:*', threat_language: 'kuery' }, + }, + getService + ); + }); + + describe('without historical versions', () => { + describe('customized w/ the matching upgrade (-AA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'threat_match', + threat_query: 'process.name:*.exe', + }, + patch: { + type: 'threat_match', + threat_query: 'process.name:*.sys', + }, + upgrade: { + type: 'threat_match', + threat_query: 'process.name:*.sys', + }, + removeInstalledAssets: true, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat_query', + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseNoUpdate, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat_query', + resolvedValue: { + type: KqlQueryType.inline_query, + query: 'resolved:*', + language: 'kuery', + filters: [], + }, + expectedFieldsAfterUpgrade: { threat_query: 'resolved:*', threat_language: 'kuery' }, + }, + getService + ); + }); + + describe('customized w/ an upgrade (-AB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'threat_match', + threat_query: 'process.name:*.exe', + }, + patch: { + type: 'threat_match', + threat_query: 'process.name:*.sys', + }, + upgrade: { + type: 'threat_match', + threat_query: 'process.name:*.com', + }, + removeInstalledAssets: true, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat_query', + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseCanUpdate, + expectedFieldDiffValues: { + current: { + type: KqlQueryType.inline_query, + query: 'process.name:*.sys', + language: 'kuery', + filters: [], + }, + target: { + type: KqlQueryType.inline_query, + query: 'process.name:*.com', + language: 'kuery', + filters: [], + }, + merged: { + type: KqlQueryType.inline_query, + query: 'process.name:*.com', + language: 'kuery', + filters: [], + }, + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threat_query', + resolvedValue: { + type: KqlQueryType.inline_query, + query: 'resolved:*', + language: 'kuery', + filters: [], + }, + expectedFieldsAfterUpgrade: { threat_query: 'resolved:*', threat_language: 'kuery' }, + }, + getService + ); + }); + }); + }); +} diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/type_specific_fields/threshold.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/type_specific_fields/threshold.ts new file mode 100644 index 0000000000000..9469fda5f8ae6 --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/diffable_rule_fields/type_specific_fields/threshold.ts @@ -0,0 +1,326 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { ThreeWayDiffOutcome } from '@kbn/security-solution-plugin/common/api/detection_engine'; +import { FtrProviderContext } from '../../../../../../../../ftr_provider_context'; +import type { TestFieldRuleUpgradeAssets } from '../test_helpers'; +import { + testFieldUpgradeReview, + testFieldUpgradesToMergedValue, + testFieldUpgradesToResolvedValue, +} from '../test_helpers'; + +export function thresholdField({ getService }: FtrProviderContext): void { + describe('"threshold"', () => { + describe('non-customized w/o an upgrade (AAA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'threshold', + threshold: { value: 10, field: 'fieldA' }, + }, + patch: {}, + upgrade: { + type: 'threshold', + threshold: { value: 10, field: 'fieldA' }, + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threshold', + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueNoUpdate, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threshold', + resolvedValue: { value: 50, field: 'resolved' }, + expectedFieldsAfterUpgrade: { threshold: { value: 50, field: ['resolved'] } }, + }, + getService + ); + }); + + describe('non-customized w/ an upgrade (AAB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'threshold', + threshold: { value: 10, field: 'fieldA' }, + }, + patch: {}, + upgrade: { + type: 'threshold', + threshold: { value: 10, field: 'fieldB' }, + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threshold', + expectedDiffOutcome: ThreeWayDiffOutcome.StockValueCanUpdate, + expectedFieldDiffValues: { + base: { value: 10, field: ['fieldA'] }, + current: { value: 10, field: ['fieldA'] }, + target: { value: 10, field: ['fieldB'] }, + merged: { value: 10, field: ['fieldB'] }, + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threshold', + expectedFieldsAfterUpgrade: { threshold: { value: 10, field: ['fieldB'] } }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threshold', + resolvedValue: { value: 50, field: 'resolved' }, + expectedFieldsAfterUpgrade: { threshold: { value: 50, field: ['resolved'] } }, + }, + getService + ); + }); + + describe('customized w/o an upgrade (ABA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'threshold', + threshold: { value: 10, field: 'fieldA' }, + }, + patch: { + type: 'threshold', + threshold: { value: 10, field: 'fieldB' }, + }, + upgrade: { + type: 'threshold', + threshold: { value: 10, field: 'fieldA' }, + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threshold', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueNoUpdate, + expectedFieldDiffValues: { + base: { value: 10, field: ['fieldA'] }, + current: { value: 10, field: ['fieldB'] }, + target: { value: 10, field: ['fieldA'] }, + merged: { value: 10, field: ['fieldB'] }, + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threshold', + expectedFieldsAfterUpgrade: { threshold: { value: 10, field: ['fieldB'] } }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threshold', + resolvedValue: { value: 50, field: 'resolved' }, + expectedFieldsAfterUpgrade: { threshold: { value: 50, field: ['resolved'] } }, + }, + getService + ); + }); + + describe('customized w/ the matching upgrade (ABB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'threshold', + threshold: { value: 10, field: 'fieldA' }, + }, + patch: { + type: 'threshold', + threshold: { value: 10, field: 'fieldB' }, + }, + upgrade: { + type: 'threshold', + threshold: { value: 10, field: 'fieldB' }, + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threshold', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueSameUpdate, + expectedFieldDiffValues: { + base: { value: 10, field: ['fieldA'] }, + current: { value: 10, field: ['fieldB'] }, + target: { value: 10, field: ['fieldB'] }, + merged: { value: 10, field: ['fieldB'] }, + }, + }, + getService + ); + + testFieldUpgradesToMergedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threshold', + expectedFieldsAfterUpgrade: { threshold: { value: 10, field: ['fieldB'] } }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threshold', + resolvedValue: { value: 50, field: 'resolved' }, + expectedFieldsAfterUpgrade: { threshold: { value: 50, field: ['resolved'] } }, + }, + getService + ); + }); + + describe('customized w/ an upgrade resulting in a conflict (ABC diff case, non-solvable conflict)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'threshold', + threshold: { value: 10, field: 'fieldA' }, + }, + patch: { + type: 'threshold', + threshold: { value: 10, field: 'fieldB' }, + }, + upgrade: { + type: 'threshold', + threshold: { value: 10, field: 'fieldC' }, + }, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threshold', + expectedDiffOutcome: ThreeWayDiffOutcome.CustomizedValueCanUpdate, + isSolvableConflict: false, + expectedFieldDiffValues: { + base: { value: 10, field: ['fieldA'] }, + current: { value: 10, field: ['fieldB'] }, + target: { value: 10, field: ['fieldC'] }, + merged: { value: 10, field: ['fieldB'] }, + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threshold', + resolvedValue: { value: 50, field: 'resolved' }, + expectedFieldsAfterUpgrade: { threshold: { value: 50, field: ['resolved'] } }, + }, + getService + ); + }); + + describe('without historical versions', () => { + describe('customized w/ the matching upgrade (-AA diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'threshold', + threshold: { value: 10, field: 'fieldA' }, + }, + patch: { + type: 'threshold', + threshold: { value: 10, field: 'fieldB' }, + }, + upgrade: { + type: 'threshold', + threshold: { value: 10, field: 'fieldB' }, + }, + removeInstalledAssets: true, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threshold', + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseNoUpdate, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threshold', + resolvedValue: { value: 50, field: 'resolved' }, + expectedFieldsAfterUpgrade: { threshold: { value: 50, field: ['resolved'] } }, + }, + getService + ); + }); + + describe('customized w/ an upgrade (-AB diff case)', () => { + const ruleUpgradeAssets: TestFieldRuleUpgradeAssets = { + installed: { + type: 'threshold', + threshold: { value: 10, field: 'fieldA' }, + }, + patch: { + type: 'threshold', + threshold: { value: 10, field: 'fieldB' }, + }, + upgrade: { + type: 'threshold', + threshold: { value: 10, field: 'fieldC' }, + }, + removeInstalledAssets: true, + }; + + testFieldUpgradeReview( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threshold', + expectedDiffOutcome: ThreeWayDiffOutcome.MissingBaseCanUpdate, + expectedFieldDiffValues: { + current: { value: 10, field: ['fieldB'] }, + target: { value: 10, field: ['fieldC'] }, + merged: { value: 10, field: ['fieldC'] }, + }, + }, + getService + ); + + testFieldUpgradesToResolvedValue( + { + ruleUpgradeAssets, + diffableRuleFieldName: 'threshold', + resolvedValue: { value: 50, field: 'resolved' }, + expectedFieldsAfterUpgrade: { threshold: { value: 50, field: ['resolved'] } }, + }, + getService + ); + }); + }); + }); +} diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/index.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/index.ts index ea0633cce9bbd..0d811f57288ae 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/index.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/index.ts @@ -12,7 +12,7 @@ export default ({ loadTestFile }: FtrProviderContext): void => { loadTestFile(require.resolve('./is_customized_calculation')); loadTestFile(require.resolve('./import_rules')); loadTestFile(require.resolve('./rules_export')); - loadTestFile(require.resolve('./upgrade_perform_prebuilt_rules.all_rules_mode')); - loadTestFile(require.resolve('./upgrade_perform_prebuilt_rules.specific_rules_mode')); + loadTestFile(require.resolve('./preview_prebuilt_rules_upgrade')); + loadTestFile(require.resolve('./upgrade_prebuilt_rules')); }); }; diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/preview_prebuilt_rules_upgrade.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/preview_prebuilt_rules_upgrade.ts new file mode 100644 index 0000000000000..9d80d14257c37 --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/preview_prebuilt_rules_upgrade.ts @@ -0,0 +1,530 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import expect from 'expect'; +import { deleteAllRules } from '../../../../../../../common/utils/security_solution'; +import { FtrProviderContext } from '../../../../../../ftr_provider_context'; +import { + deleteAllPrebuiltRuleAssets, + fetchFirstPrebuiltRuleUpgradeReviewDiff, + reviewPrebuiltRulesToUpgrade, +} from '../../../../utils'; +import { setUpRuleUpgrade } from '../../../../utils/rules/prebuilt_rules/set_up_rule_upgrade'; + +export default ({ getService }: FtrProviderContext): void => { + const es = getService('es'); + const supertest = getService('supertest'); + const log = getService('log'); + + const deps = { + es, + supertest, + log, + }; + + describe('@ess @serverless @skipInServerlessMKI preview prebuilt rules upgrade', () => { + beforeEach(async () => { + await deleteAllRules(supertest, log); + await deleteAllPrebuiltRuleAssets(es, log); + }); + + for (const withHistoricalVersions of [true, false]) { + describe( + withHistoricalVersions ? 'with historical versions' : 'without historical versions', + () => { + describe('stats', () => { + it('returns num of rules with upgrades', async () => { + await setUpRuleUpgrade({ + assets: [ + { + installed: { + rule_id: 'query-rule', + type: 'query', + version: 1, + }, + patch: {}, + upgrade: { + rule_id: 'query-rule', + type: 'query', + version: 2, + }, + }, + { + installed: { + rule_id: 'saved-query-rule', + type: 'query', + version: 1, + }, + patch: {}, + upgrade: { + rule_id: 'saved-query-rule', + type: 'query', + version: 2, + }, + }, + ], + removeInstalledAssets: !withHistoricalVersions, + deps, + }); + + const response = await reviewPrebuiltRulesToUpgrade(supertest); + + expect(response.stats).toMatchObject({ + num_rules_to_upgrade_total: 2, + }); + }); + + it('returns zero conflicts when there are no conflicts', async () => { + await setUpRuleUpgrade({ + assets: [ + { + installed: { + rule_id: 'query-rule', + type: 'query', + version: 1, + }, + patch: {}, + upgrade: { + rule_id: 'query-rule', + type: 'query', + version: 2, + }, + }, + { + installed: { + rule_id: 'saved-query-rule', + type: 'query', + version: 1, + }, + patch: {}, + upgrade: { + rule_id: 'saved-query-rule', + type: 'query', + version: 2, + }, + }, + ], + removeInstalledAssets: !withHistoricalVersions, + deps, + }); + + const response = await reviewPrebuiltRulesToUpgrade(supertest); + + expect(response.stats).toMatchObject({ + num_rules_with_conflicts: 0, + num_rules_with_non_solvable_conflicts: 0, + }); + }); + + it('returns num of rules with conflicts', async () => { + await setUpRuleUpgrade({ + assets: [ + { + installed: { + rule_id: 'query-rule', + type: 'query', + name: 'Initial name', + version: 1, + }, + patch: { + rule_id: 'query-rule', + name: 'Customized name', + }, + upgrade: { + rule_id: 'query-rule', + type: 'query', + name: 'Updated name', + version: 2, + }, + }, + { + installed: { + rule_id: 'saved-query-rule', + type: 'query', + tags: ['tagA'], + version: 1, + }, + patch: { + rule_id: 'saved-query-rule', + tags: ['tagB'], + }, + upgrade: { + rule_id: 'saved-query-rule', + type: 'query', + tags: ['tagC'], + version: 2, + }, + }, + ], + removeInstalledAssets: !withHistoricalVersions, + deps, + }); + + const response = await reviewPrebuiltRulesToUpgrade(supertest); + + expect(response.stats).toMatchObject({ + num_rules_with_conflicts: 2, + }); + }); + + it('returns num of rules with non-solvable conflicts', async () => { + await setUpRuleUpgrade({ + assets: [ + // Name field has a non-solvable upgrade conflict + { + installed: { + rule_id: 'query-rule', + type: 'query', + name: 'Initial name', + version: 1, + }, + patch: { + rule_id: 'query-rule', + name: 'Customized name', + }, + upgrade: { + rule_id: 'query-rule', + type: 'query', + name: 'Updated name', + version: 2, + }, + }, + // tags field values are merged resulting in a solvable upgrade conflict + { + installed: { + rule_id: 'saved-query-rule', + type: 'query', + tags: ['tagA'], + version: 1, + }, + patch: { + rule_id: 'saved-query-rule', + tags: ['tagB'], + }, + upgrade: { + rule_id: 'saved-query-rule', + type: 'query', + tags: ['tagC'], + version: 2, + }, + }, + ], + removeInstalledAssets: !withHistoricalVersions, + deps, + }); + + const response = await reviewPrebuiltRulesToUpgrade(supertest); + + expect(response.stats).toMatchObject({ + // Missing rule's base version doesn't allow to detect non solvable conflicts + num_rules_with_non_solvable_conflicts: withHistoricalVersions ? 1 : 0, + }); + }); + + if (!withHistoricalVersions) { + it('returns num of rules with conflicts caused by missing historical versions', async () => { + await setUpRuleUpgrade({ + assets: [ + { + installed: { + rule_id: 'query-rule', + type: 'query', + name: 'Initial name', + version: 1, + }, + patch: {}, + upgrade: { + rule_id: 'query-rule', + type: 'query', + version: 2, + }, + }, + { + installed: { + rule_id: 'saved-query-rule', + type: 'query', + version: 1, + }, + patch: {}, + upgrade: { + rule_id: 'saved-query-rule', + type: 'query', + name: 'Updated name', + version: 2, + }, + }, + ], + removeInstalledAssets: true, + deps, + }); + + const response = await reviewPrebuiltRulesToUpgrade(supertest); + + expect(response.stats).toMatchObject({ + num_rules_with_conflicts: 2, + }); + }); + } + }); + + describe('fields diff stats', () => { + it('returns num of fields with updates', async () => { + await setUpRuleUpgrade({ + assets: [ + { + installed: { + rule_id: 'query-rule', + type: 'query', + name: 'Initial name', + tags: ['tabA'], + version: 1, + }, + patch: { + rule_id: 'query-rule', + name: 'Customized name', + }, + upgrade: { + rule_id: 'query-rule', + type: 'query', + name: 'Updated name', + tags: ['tabC'], + version: 2, + }, + }, + ], + deps, + }); + + const fieldsDiff = await fetchFirstPrebuiltRuleUpgradeReviewDiff(supertest); + + expect(fieldsDiff).toMatchObject({ + num_fields_with_updates: 3, // name + tags + version = 3 fields + }); + }); + + it('returns num of fields with conflicts', async () => { + await setUpRuleUpgrade({ + assets: [ + { + installed: { + rule_id: 'query-rule', + type: 'query', + name: 'Initial name', + tags: ['tabA'], + version: 1, + }, + patch: { + rule_id: 'query-rule', + name: 'Customized name', + tags: ['tabB'], + }, + upgrade: { + rule_id: 'query-rule', + type: 'query', + name: 'Updated name', + tags: ['tabC'], + version: 2, + }, + }, + ], + deps, + }); + + const fieldsDiff = await fetchFirstPrebuiltRuleUpgradeReviewDiff(supertest); + + expect(fieldsDiff).toMatchObject({ + num_fields_with_conflicts: 2, + }); + }); + + it('returns num of fields with non-solvable conflicts', async () => { + await setUpRuleUpgrade({ + assets: [ + { + installed: { + rule_id: 'query-rule', + type: 'query', + name: 'Initial name', + tags: ['tabA'], + version: 1, + }, + patch: { + rule_id: 'query-rule', + name: 'Customized name', + tags: ['tabB'], + }, + upgrade: { + rule_id: 'query-rule', + type: 'query', + name: 'Updated name', + tags: ['tabC'], + version: 2, + }, + }, + ], + deps, + }); + + const fieldsDiff = await fetchFirstPrebuiltRuleUpgradeReviewDiff(supertest); + + expect(fieldsDiff).toMatchObject({ + num_fields_with_non_solvable_conflicts: 1, + }); + }); + }); + + describe('fields diff', () => { + it('returns fields diff for fields with upgrades', async () => { + await setUpRuleUpgrade({ + assets: [ + // description - non-customized + // name - customized + // tags - customized + { + installed: { + rule_id: 'query-rule', + type: 'query', + name: 'Initial name', + description: 'Initial description', + tags: ['tabA'], + version: 1, + }, + patch: { + rule_id: 'query-rule', + name: 'Customized name', + }, + upgrade: { + rule_id: 'query-rule', + type: 'query', + name: 'Updated name', + description: 'Updated description', + tags: ['tabC'], + version: 2, + }, + }, + ], + removeInstalledAssets: !withHistoricalVersions, + deps, + }); + + const fieldsDiff = await fetchFirstPrebuiltRuleUpgradeReviewDiff(supertest); + + expect(fieldsDiff.fields).toMatchObject({ + name: { + has_update: true, + }, + description: { + has_update: true, + }, + tags: { + has_update: true, + }, + }); + }); + + it(`asserts "has_update" is ${!withHistoricalVersions} for customized fields w/o upgrades`, async () => { + await setUpRuleUpgrade({ + assets: [ + { + installed: { + rule_id: 'query-rule', + type: 'query', + alert_suppression: { group_by: ['fieldA'] }, + index: ['indexA'], + interval: '5m', + from: 'now-20m', + to: 'now', + version: 1, + }, + patch: { + rule_id: 'query-rule', + alert_suppression: { group_by: ['fieldB'] }, + index: ['indexB'], + interval: '3m', + from: 'now-10m', + }, + upgrade: { + rule_id: 'query-rule', + type: 'query', + alert_suppression: { group_by: ['fieldA'] }, + index: ['indexA'], + interval: '5m', + from: 'now-20m', + to: 'now', + version: 2, + }, + }, + ], + removeInstalledAssets: !withHistoricalVersions, + deps, + }); + + const fieldsDiff = await fetchFirstPrebuiltRuleUpgradeReviewDiff(supertest); + + expect(fieldsDiff.fields).toMatchObject({ + alert_suppression: { + has_update: !withHistoricalVersions, + }, + data_source: { + has_update: !withHistoricalVersions, + }, + rule_schedule: { + has_update: !withHistoricalVersions, + }, + }); + }); + + it('asserts returned fields diff have base version', async () => { + await setUpRuleUpgrade({ + assets: [ + { + installed: { + rule_id: 'query-rule', + type: 'query', + note: 'Initial note', + max_signals: 100, + risk_score: 10, + }, + patch: { + rule_id: 'query-rule', + max_signals: 150, + risk_score: 20, + }, + upgrade: { + rule_id: 'query-rule', + type: 'query', + note: 'Updated note', + max_signals: 100, + risk_score: 30, + version: 2, + }, + }, + ], + removeInstalledAssets: !withHistoricalVersions, + deps, + }); + + const fieldsDiff = await fetchFirstPrebuiltRuleUpgradeReviewDiff(supertest); + + expect(fieldsDiff.fields).toMatchObject({ + note: { + has_base_version: withHistoricalVersions, + }, + max_signals: { + has_base_version: withHistoricalVersions, + }, + risk_score: { + has_base_version: withHistoricalVersions, + }, + }); + }); + }); + } + ); + } + }); +}; diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/upgrade_perform_prebuilt_rules.all_rules_mode.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/upgrade_perform_prebuilt_rules.all_rules_mode.ts deleted file mode 100644 index 9ee99df7a977a..0000000000000 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/upgrade_perform_prebuilt_rules.all_rules_mode.ts +++ /dev/null @@ -1,533 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import expect from 'expect'; -import type SuperTest from 'supertest'; -import { cloneDeep } from 'lodash'; -import { - QueryRuleCreateFields, - EqlRuleCreateFields, - EsqlRuleCreateFields, - RuleResponse, - ThreatMatchRuleCreateFields, - ThreatMatchRule, - FIELDS_TO_UPGRADE_TO_CURRENT_VERSION, - ModeEnum, - AllFieldsDiff, - DataSourceIndexPatterns, - QueryRule, -} from '@kbn/security-solution-plugin/common/api/detection_engine'; -import { PrebuiltRuleAsset } from '@kbn/security-solution-plugin/server/lib/detection_engine/prebuilt_rules'; -import { FtrProviderContext } from '../../../../../../ftr_provider_context'; -import { - deleteAllTimelines, - deleteAllPrebuiltRuleAssets, - createRuleAssetSavedObjectOfType, - installPrebuiltRules, - performUpgradePrebuiltRules, - patchRule, - createHistoricalPrebuiltRuleAssetSavedObjects, - reviewPrebuiltRulesToUpgrade, - getInstalledRules, - createRuleAssetSavedObject, - getWebHookAction, -} from '../../../../utils'; -import { deleteAllRules } from '../../../../../../../common/utils/security_solution'; - -export default ({ getService }: FtrProviderContext): void => { - const es = getService('es'); - const supertest = getService('supertest'); - const log = getService('log'); - const securitySolutionApi = getService('securitySolutionApi'); - - describe('@ess @serverless @skipInServerlessMKI Perform Prebuilt Rules Upgrades - mode: ALL_RULES', () => { - beforeEach(async () => { - await deleteAllRules(supertest, log); - await deleteAllTimelines(es, log); - await deleteAllPrebuiltRuleAssets(es, log); - }); - - const CURRENT_NAME = 'My current name'; - const CURRENT_TAGS = ['current', 'tags']; - const TARGET_NAME = 'My target name'; - const TARGET_TAGS = ['target', 'tags']; - - describe(`successful updates`, () => { - const queryRule = createRuleAssetSavedObjectOfType('query'); - const eqlRule = createRuleAssetSavedObjectOfType('eql'); - const esqlRule = createRuleAssetSavedObjectOfType('esql'); - - const basePrebuiltAssets = [queryRule, eqlRule, esqlRule]; - const basePrebuiltAssetsMap = createIdToRuleMap( - basePrebuiltAssets.map((r) => r['security-rule']) - ); - - const targetPrebuiltAssets = basePrebuiltAssets.map((ruleAssetSavedObject) => { - const targetObject = cloneDeep(ruleAssetSavedObject); - targetObject['security-rule'].version += 1; - targetObject['security-rule'].name = TARGET_NAME; - targetObject['security-rule'].tags = TARGET_TAGS; - - return targetObject; - }); - - it('upgrades all upgreadeable rules fields to their BASE versions', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects(es, basePrebuiltAssets); - await installPrebuiltRules(es, supertest); - - // Create new versions of the assets of the installed rules - await createHistoricalPrebuiltRuleAssetSavedObjects(es, targetPrebuiltAssets); - - // Perform the upgrade, all rules' fields to their BASE versions - const performUpgradeResponse = await performUpgradePrebuiltRules(es, supertest, { - mode: ModeEnum.ALL_RULES, - pick_version: 'BASE', - }); - - expect(performUpgradeResponse.summary.succeeded).toEqual(3); - performUpgradeResponse.results.updated.forEach((updatedRule) => { - const matchingBaseAsset = basePrebuiltAssetsMap.get(updatedRule.rule_id); - if (!matchingBaseAsset) { - throw new Error(`Could not find matching base asset for rule ${updatedRule.rule_id}`); - } - - // Rule Version should be incremented by 1 - // Rule Name and Tags should match the base asset's values, not the Target asset's values - expect(updatedRule.version).toEqual(matchingBaseAsset.version + 1); - expect(updatedRule.name).toEqual(matchingBaseAsset.name); - expect(updatedRule.tags).toEqual(matchingBaseAsset.tags); - }); - - // Get installed rules - const installedRules = await getInstalledRules(supertest); - const installedRulesMap = createIdToRuleMap(installedRules.data); - - for (const [ruleId, installedRule] of installedRulesMap) { - const matchingBaseAsset = basePrebuiltAssetsMap.get(ruleId); - expect(installedRule.name).toEqual(matchingBaseAsset?.name); - expect(installedRule.tags).toEqual(matchingBaseAsset?.tags); - } - }); - - it('upgrades all upgreadeable rules fields to their CURRENT versions', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects(es, basePrebuiltAssets); - await installPrebuiltRules(es, supertest); - - // Patch all 3 installed rules to create a current version for each - for (const baseRule of basePrebuiltAssets) { - await patchRule(supertest, log, { - rule_id: baseRule['security-rule'].rule_id, - name: CURRENT_NAME, - tags: CURRENT_TAGS, - }); - } - - // Create new versions of the assets of the installed rules - await createHistoricalPrebuiltRuleAssetSavedObjects(es, targetPrebuiltAssets); - - // Perform the upgrade, all rules' fields to their CURRENT versions - const performUpgradeResponse = await performUpgradePrebuiltRules(es, supertest, { - mode: ModeEnum.ALL_RULES, - pick_version: 'CURRENT', - }); - - expect(performUpgradeResponse.summary.succeeded).toEqual(3); - - performUpgradeResponse.results.updated.forEach((updatedRule) => { - const matchingBaseAsset = basePrebuiltAssetsMap.get(updatedRule.rule_id); - // Rule Version should be incremented by 1 - // Rule Query should match the current's version query - if (matchingBaseAsset) { - expect(updatedRule.version).toEqual(matchingBaseAsset.version + 1); - expect(updatedRule.name).toEqual(CURRENT_NAME); - expect(updatedRule.tags).toEqual(CURRENT_TAGS); - } else { - throw new Error(`Matching base asset not found for rule_id: ${updatedRule.rule_id}`); - } - }); - - const installedRules = await getInstalledRules(supertest); - const installedRulesMap = createIdToRuleMap(installedRules.data); - - for (const [_, installedRule] of installedRulesMap) { - expect(installedRule.name).toEqual(CURRENT_NAME); - expect(installedRule.tags).toEqual(CURRENT_TAGS); - } - }); - - it('upgrades all upgreadeable rules fields to their TARGET versions', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects(es, basePrebuiltAssets); - await installPrebuiltRules(es, supertest); - - // Patch all 3 installed rules to create a current version for each - for (const baseRule of basePrebuiltAssets) { - await patchRule(supertest, log, { - rule_id: baseRule['security-rule'].rule_id, - query: CURRENT_NAME, - tags: CURRENT_TAGS, - }); - } - - // Create new versions of the assets of the installed rules - await createHistoricalPrebuiltRuleAssetSavedObjects(es, targetPrebuiltAssets); - - // Perform the upgrade, all rules' fields to their CURRENT versions - const performUpgradeResponse = await performUpgradePrebuiltRules(es, supertest, { - mode: ModeEnum.ALL_RULES, - pick_version: 'TARGET', - }); - - expect(performUpgradeResponse.summary.succeeded).toEqual(3); - - performUpgradeResponse.results.updated.forEach((updatedRule) => { - const matchingBaseAsset = basePrebuiltAssetsMap.get(updatedRule.rule_id); - - // Rule Version should be incremented by 1 - // Rule Query should match the current's version query - if (matchingBaseAsset) { - expect(updatedRule.version).toEqual(matchingBaseAsset.version + 1); - expect(updatedRule.name).toEqual(TARGET_NAME); - expect(updatedRule.tags).toEqual(TARGET_TAGS); - } else { - throw new Error(`Matching base asset not found for rule_id: ${updatedRule.rule_id}`); - } - }); - - const installedRules = await getInstalledRules(supertest); - const installedRulesMap = createIdToRuleMap(installedRules.data); - - for (const [_, installedRule] of installedRulesMap) { - expect(installedRule.name).toEqual(TARGET_NAME); - expect(installedRule.tags).toEqual(TARGET_TAGS); - } - }); - - it('upgrades all upgreadeable rules fields to their MERGED versions', async () => { - // Install base prebuilt detection rule - await createHistoricalPrebuiltRuleAssetSavedObjects(es, basePrebuiltAssets); - await installPrebuiltRules(es, supertest); - - // Create new versions of the assets of the installed rules - await createHistoricalPrebuiltRuleAssetSavedObjects(es, targetPrebuiltAssets); - - // Call the /upgrade/_review endpoint to save the calculated merged_versions - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - const reviewRuleResponseMap = new Map( - reviewResponse.rules.map((upgradeInfo) => [ - upgradeInfo.rule_id, - { - tags: upgradeInfo.diff.fields.tags?.merged_version, - name: upgradeInfo.diff.fields.name?.merged_version, - }, - ]) - ); - - // Perform the upgrade, all rules' fields to their MERGED versions - const performUpgradeResponse = await performUpgradePrebuiltRules(es, supertest, { - mode: ModeEnum.ALL_RULES, - pick_version: 'MERGED', - }); - const updatedRulesMap = createIdToRuleMap(performUpgradeResponse.results.updated); - - // All upgrades should succeed: neither query nor tags should have a merge conflict - expect(performUpgradeResponse.summary.succeeded).toEqual(3); - - const installedRules = await getInstalledRules(supertest); - const installedRulesMap = createIdToRuleMap(installedRules.data); - - for (const [ruleId, installedRule] of installedRulesMap) { - expect(installedRule.name).toEqual(updatedRulesMap.get(ruleId)?.name); - expect(installedRule.name).toEqual(reviewRuleResponseMap.get(ruleId)?.name); - expect(installedRule.tags).toEqual(updatedRulesMap.get(ruleId)?.tags); - expect(installedRule.tags).toEqual(reviewRuleResponseMap.get(ruleId)?.tags); - } - }); - - it('correctly upgrades rules with DataSource diffs to their MERGED versions', async () => { - await createHistoricalPrebuiltRuleAssetSavedObjects(es, [queryRule]); - await installPrebuiltRules(es, supertest); - - const targetObject = cloneDeep(queryRule); - targetObject['security-rule'].version += 1; - targetObject['security-rule'].name = TARGET_NAME; - targetObject['security-rule'].tags = TARGET_TAGS; - targetObject['security-rule'].index = ['auditbeat-*']; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, [targetObject]); - - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - const ruleDiffFields = reviewResponse.rules[0].diff.fields as AllFieldsDiff; - - const performUpgradeResponse = await performUpgradePrebuiltRules(es, supertest, { - mode: ModeEnum.ALL_RULES, - pick_version: 'MERGED', - }); - - expect(performUpgradeResponse.summary.succeeded).toEqual(1); - - const installedRules = await getInstalledRules(supertest); - const installedRule = installedRules.data[0] as QueryRule; - - expect(installedRule.name).toEqual(ruleDiffFields.name.merged_version); - expect(installedRule.tags).toEqual(ruleDiffFields.tags.merged_version); - - // Check that the updated rules has an `index` field which equals the output of the diff algorithm - // for the DataSource diffable field, and that the data_view_id is correspondingly set to undefined. - expect(installedRule.index).toEqual( - (ruleDiffFields.data_source.merged_version as DataSourceIndexPatterns).index_patterns - ); - expect(installedRule.data_view_id).toBe(undefined); - }); - }); - - describe('edge cases and unhappy paths', () => { - const firstQueryRule = createRuleAssetSavedObject({ - type: 'query', - language: 'kuery', - rule_id: 'query-rule-1', - }); - const secondQueryRule = createRuleAssetSavedObject({ - type: 'query', - language: 'kuery', - rule_id: 'query-rule-2', - }); - const eqlRule = createRuleAssetSavedObject({ - type: 'eql', - language: 'eql', - rule_id: 'eql-rule', - }); - - const basePrebuiltAssets = [firstQueryRule, eqlRule, secondQueryRule]; - - it('rejects all updates of rules which have a rule type change if the pick_version is not TARGET', async () => { - // Install base prebuilt detection rules - await createHistoricalPrebuiltRuleAssetSavedObjects(es, basePrebuiltAssets); - await installPrebuiltRules(es, supertest); - - // Mock a rule type change to 'ml' to the first two rules of the basePrebuiltAssets array - const targetMLPrebuiltAssets = basePrebuiltAssets - .slice(0, 2) - .map((ruleAssetSavedObject) => { - const targetObject = cloneDeep(ruleAssetSavedObject); - - return { - ...targetObject, - ...createRuleAssetSavedObject({ - rule_id: targetObject['security-rule'].rule_id, - version: targetObject['security-rule'].version + 1, - type: 'machine_learning', - machine_learning_job_id: 'job_id', - anomaly_threshold: 1, - }), - }; - }); - - // Mock an normal update of the rule 'query-rule-2', with NO rule type change - const targetAssetSameTypeUpdate = createRuleAssetSavedObject({ - type: 'query', - language: 'kuery', - rule_id: 'query-rule-2', - version: 2, - }); - - // Create new versions of the assets of the installed rules - await createHistoricalPrebuiltRuleAssetSavedObjects(es, [ - ...targetMLPrebuiltAssets, - targetAssetSameTypeUpdate, - ]); - - // Perform the upgrade, all rules' fields to their BASE versions - const performUpgradeResponse = await performUpgradePrebuiltRules(es, supertest, { - mode: ModeEnum.ALL_RULES, - pick_version: 'BASE', - }); - - expect(performUpgradeResponse.summary.succeeded).toEqual(1); // update of same type - expect(performUpgradeResponse.summary.failed).toEqual(2); // updates with rule type change - - expect(performUpgradeResponse.errors).toHaveLength(2); - performUpgradeResponse.errors.forEach((error) => { - const ruleId = error.rules[0].rule_id; - expect(error.message).toContain( - `Rule update for rule ${ruleId} has a rule type change. All 'pick_version' values for rule must match 'TARGET'` - ); - }); - }); - - it('rejects updates of rules with a pick_version of MERGED which have fields which result in conflicts in the three way diff calculations', async () => { - // Install base prebuilt detection rules - await createHistoricalPrebuiltRuleAssetSavedObjects(es, basePrebuiltAssets); - await installPrebuiltRules(es, supertest); - - // Patch all 3 installed rules to create a current version for each - for (const baseRule of basePrebuiltAssets) { - await patchRule(supertest, log, { - rule_id: baseRule['security-rule'].rule_id, - name: CURRENT_NAME, - tags: CURRENT_TAGS, - }); - } - - const targetPrebuiltAssets = basePrebuiltAssets.map((ruleAssetSavedObject) => { - const targetObject = cloneDeep(ruleAssetSavedObject); - targetObject['security-rule'].version += 1; - targetObject['security-rule'].name = TARGET_NAME; - targetObject['security-rule'].tags = TARGET_TAGS; - - return targetObject; - }); - - // Create new versions of the assets of the installed rules - await createHistoricalPrebuiltRuleAssetSavedObjects(es, targetPrebuiltAssets); - - // Perform the upgrade, all rules' fields to their MERGED versions - const performUpgradeResponse = await performUpgradePrebuiltRules(es, supertest, { - mode: ModeEnum.ALL_RULES, - pick_version: 'MERGED', - }); - - expect(performUpgradeResponse.summary.succeeded).toEqual(0); // all rules have conflicts - expect(performUpgradeResponse.summary.failed).toEqual(3); // all rules have conflicts - - performUpgradeResponse.errors.forEach((error) => { - const ruleId = error.rules[0].rule_id; - expect(error.message).toContain( - `Merge conflicts found in rule '${ruleId}' for fields: name, tags. Please resolve the conflict manually or choose another value for 'pick_version'` - ); - }); - }); - - it('preserves FIELDS_TO_UPGRADE_TO_CURRENT_VERSION when upgrading to TARGET version with undefined fields', async () => { - const baseRule = - createRuleAssetSavedObjectOfType('threat_match'); - await createHistoricalPrebuiltRuleAssetSavedObjects(es, [baseRule]); - await installPrebuiltRules(es, supertest); - - const ruleId = baseRule['security-rule'].rule_id; - - const installedBaseRule = ( - await securitySolutionApi.readRule({ - query: { - rule_id: ruleId, - }, - }) - ).body as ThreatMatchRule; - - // Patch the installed rule to set all FIELDS_TO_UPGRADE_TO_CURRENT_VERSION to some defined value - const currentValues: { [key: string]: unknown } = { - enabled: true, - exceptions_list: [ - { - id: 'test-list', - list_id: 'test-list', - type: 'detection', - namespace_type: 'single', - } as const, - ], - alert_suppression: { - group_by: ['host.name'], - duration: { value: 5, unit: 'm' as const }, - }, - actions: [await createAction(supertest)], - response_actions: [ - { - params: { - command: 'isolate' as const, - comment: 'comment', - }, - action_type_id: '.endpoint' as const, - }, - ], - meta: { some_key: 'some_value' }, - output_index: '.siem-signals-default', - namespace: 'default', - concurrent_searches: 5, - items_per_search: 100, - }; - - await securitySolutionApi.updateRule({ - body: { - ...installedBaseRule, - ...currentValues, - id: undefined, - }, - }); - - // Create a target version with undefined values for these fields - const targetRule = cloneDeep(baseRule); - targetRule['security-rule'].version += 1; - FIELDS_TO_UPGRADE_TO_CURRENT_VERSION.forEach((field) => { - // @ts-expect-error - targetRule['security-rule'][field] = undefined; - }); - await createHistoricalPrebuiltRuleAssetSavedObjects(es, [targetRule]); - - // Perform the upgrade - const performUpgradeResponse = await performUpgradePrebuiltRules(es, supertest, { - mode: ModeEnum.ALL_RULES, - pick_version: 'TARGET', - }); - - expect(performUpgradeResponse.summary.succeeded).toEqual(1); - const upgradedRule = performUpgradeResponse.results.updated[0] as ThreatMatchRule; - - // Check that all FIELDS_TO_UPGRADE_TO_CURRENT_VERSION still have their "current" values - FIELDS_TO_UPGRADE_TO_CURRENT_VERSION.forEach((field) => { - expect(upgradedRule[field]).toEqual(currentValues[field]); - }); - - // Verify the installed rule - const installedRules = await getInstalledRules(supertest); - const installedRule = installedRules.data.find( - (rule) => rule.rule_id === baseRule['security-rule'].rule_id - ) as ThreatMatchRule; - - FIELDS_TO_UPGRADE_TO_CURRENT_VERSION.forEach((field) => { - expect(installedRule[field]).toEqual(currentValues[field]); - }); - }); - }); - }); -}; - -function createIdToRuleMap(rules: Array) { - return new Map(rules.map((rule) => [rule.rule_id, rule])); -} - -async function createAction(supertest: SuperTest.Agent) { - const createConnector = async (payload: Record) => - ( - await supertest - .post('/api/actions/connector') - .set('kbn-xsrf', 'true') - .send(payload) - .expect(200) - ).body; - - const createWebHookConnector = () => createConnector(getWebHookAction()); - - const webHookAction = await createWebHookConnector(); - - const defaultRuleAction = { - id: webHookAction.id, - action_type_id: '.webhook' as const, - group: 'default' as const, - params: { - body: '{"test":"a default action"}', - }, - frequency: { - notifyWhen: 'onThrottleInterval' as const, - summary: true, - throttle: '1h' as const, - }, - uuid: 'd487ec3d-05f2-44ad-8a68-11c97dc92202', - }; - - return defaultRuleAction; -} diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/upgrade_perform_prebuilt_rules.specific_rules_mode.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/upgrade_perform_prebuilt_rules.specific_rules_mode.ts deleted file mode 100644 index d3884b12808c5..0000000000000 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/upgrade_perform_prebuilt_rules.specific_rules_mode.ts +++ /dev/null @@ -1,865 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import expect from 'expect'; -import type SuperTest from 'supertest'; -import { cloneDeep } from 'lodash'; -import { - QueryRuleCreateFields, - EqlRuleCreateFields, - EsqlRuleCreateFields, - ThreatMatchRuleCreateFields, - RuleResponse, - ModeEnum, - PickVersionValues, - RuleEqlQuery, - EqlRule, - FIELDS_TO_UPGRADE_TO_CURRENT_VERSION, -} from '@kbn/security-solution-plugin/common/api/detection_engine'; -import { PrebuiltRuleAsset } from '@kbn/security-solution-plugin/server/lib/detection_engine/prebuilt_rules'; -import { ThreatMatchRule } from '@kbn/security-solution-plugin/common/api/detection_engine/model/rule_schema/rule_schemas.gen'; -import { FtrProviderContext } from '../../../../../../ftr_provider_context'; -import { - deleteAllTimelines, - deleteAllPrebuiltRuleAssets, - createRuleAssetSavedObjectOfType, - installPrebuiltRules, - performUpgradePrebuiltRules, - patchRule, - getInstalledRules, - createHistoricalPrebuiltRuleAssetSavedObjects, - reviewPrebuiltRulesToUpgrade, - createRuleAssetSavedObject, - getWebHookAction, -} from '../../../../utils'; -import { deleteAllRules } from '../../../../../../../common/utils/security_solution'; - -export default ({ getService }: FtrProviderContext): void => { - const es = getService('es'); - const supertest = getService('supertest'); - const log = getService('log'); - const securitySolutionApi = getService('securitySolutionApi'); - - describe('@ess @serverless @skipInServerlessMKI Perform Prebuilt Rules Upgrades - mode: SPECIFIC_RULES', () => { - beforeEach(async () => { - await deleteAllRules(supertest, log); - await deleteAllTimelines(es, log); - await deleteAllPrebuiltRuleAssets(es, log); - }); - - const CURRENT_NAME = 'My current name'; - const CURRENT_TAGS = ['current', 'tags']; - const TARGET_NAME = 'My target name'; - const TARGET_TAGS = ['target', 'tags']; - - describe('successful updates', () => { - const queryRule = createRuleAssetSavedObjectOfType('query'); - const eqlRule = createRuleAssetSavedObjectOfType('eql'); - const esqlRule = createRuleAssetSavedObjectOfType('esql'); - - const basePrebuiltAssets = [queryRule, eqlRule, esqlRule]; - - const targetPrebuiltAssets = basePrebuiltAssets.map((ruleAssetSavedObject) => { - const targetObject = cloneDeep(ruleAssetSavedObject); - targetObject['security-rule'].version += 1; - targetObject['security-rule'].name = TARGET_NAME; - targetObject['security-rule'].tags = TARGET_TAGS; - return targetObject; - }); - - it('upgrades specific rules to their BASE versions', async () => { - await createHistoricalPrebuiltRuleAssetSavedObjects(es, basePrebuiltAssets); - await installPrebuiltRules(es, supertest); - await createHistoricalPrebuiltRuleAssetSavedObjects(es, targetPrebuiltAssets); - - const rulesToUpgrade = basePrebuiltAssets.map((rule) => ({ - rule_id: rule['security-rule'].rule_id, - revision: 0, - version: rule['security-rule'].version + 1, - })); - - const performUpgradeResponse = await performUpgradePrebuiltRules(es, supertest, { - mode: ModeEnum.SPECIFIC_RULES, - pick_version: 'BASE', - rules: rulesToUpgrade, - }); - - const expectedResults = basePrebuiltAssets.map((asset) => ({ - rule_id: asset['security-rule'].rule_id, - version: asset['security-rule'].version + 1, - name: asset['security-rule'].name, - tags: asset['security-rule'].tags, - })); - - expect(performUpgradeResponse.summary.succeeded).toEqual(basePrebuiltAssets.length); - - performUpgradeResponse.results.updated.forEach((updatedRule) => { - const expected = expectedResults.find((r) => r.rule_id === updatedRule.rule_id); - expect(updatedRule.version).toEqual(expected?.version); - expect(updatedRule.name).toEqual(expected?.name); - expect(updatedRule.tags).toEqual(expected?.tags); - }); - - const installedRules = await getInstalledRules(supertest); - const installedRulesMap = createIdToRuleMap(installedRules.data); - - expectedResults.forEach((expected) => { - const installedRule = installedRulesMap.get(expected.rule_id); - expect(installedRule?.name).toEqual(expected.name); - expect(installedRule?.tags).toEqual(expected.tags); - }); - }); - - it('upgrades specific rules to their CURRENT versions', async () => { - await createHistoricalPrebuiltRuleAssetSavedObjects(es, basePrebuiltAssets); - await installPrebuiltRules(es, supertest); - - for (const baseRule of basePrebuiltAssets) { - await patchRule(supertest, log, { - rule_id: baseRule['security-rule'].rule_id, - name: CURRENT_NAME, - tags: CURRENT_TAGS, - }); - } - - await createHistoricalPrebuiltRuleAssetSavedObjects(es, targetPrebuiltAssets); - - const rulesToUpgrade = basePrebuiltAssets.map((rule) => ({ - rule_id: rule['security-rule'].rule_id, - revision: 1, - version: rule['security-rule'].version + 1, - })); - - const performUpgradeResponse = await performUpgradePrebuiltRules(es, supertest, { - mode: ModeEnum.SPECIFIC_RULES, - pick_version: 'CURRENT', - rules: rulesToUpgrade, - }); - - const expectedResults = basePrebuiltAssets.map((asset) => ({ - rule_id: asset['security-rule'].rule_id, - name: CURRENT_NAME, - tags: CURRENT_TAGS, - })); - - expect(performUpgradeResponse.summary.succeeded).toEqual(basePrebuiltAssets.length); - - performUpgradeResponse.results.updated.forEach((updatedRule) => { - const expected = expectedResults.find((r) => r.rule_id === updatedRule.rule_id); - expect(updatedRule.name).toEqual(expected?.name); - expect(updatedRule.tags).toEqual(expected?.tags); - }); - - const installedRules = await getInstalledRules(supertest); - const installedRulesMap = createIdToRuleMap(installedRules.data); - - expectedResults.forEach((expected) => { - const installedRule = installedRulesMap.get(expected.rule_id); - expect(installedRule?.name).toEqual(expected.name); - expect(installedRule?.tags).toEqual(expected.tags); - }); - }); - - it('upgrades specific rules to their TARGET versions', async () => { - await createHistoricalPrebuiltRuleAssetSavedObjects(es, basePrebuiltAssets); - await installPrebuiltRules(es, supertest); - await createHistoricalPrebuiltRuleAssetSavedObjects(es, targetPrebuiltAssets); - - const rulesToUpgrade = basePrebuiltAssets.map((rule) => ({ - rule_id: rule['security-rule'].rule_id, - revision: 0, - version: rule['security-rule'].version + 1, - })); - - const expectedResults = basePrebuiltAssets.map((asset) => ({ - rule_id: asset['security-rule'].rule_id, - name: TARGET_NAME, - tags: TARGET_TAGS, - })); - - const performUpgradeResponse = await performUpgradePrebuiltRules(es, supertest, { - mode: ModeEnum.SPECIFIC_RULES, - pick_version: 'TARGET', - rules: rulesToUpgrade, - }); - - expect(performUpgradeResponse.summary.succeeded).toEqual(basePrebuiltAssets.length); - - performUpgradeResponse.results.updated.forEach((updatedRule) => { - const expected = expectedResults.find((r) => r.rule_id === updatedRule.rule_id); - expect(updatedRule.name).toEqual(expected?.name); - expect(updatedRule.tags).toEqual(expected?.tags); - }); - - const installedRules = await getInstalledRules(supertest); - const installedRulesMap = createIdToRuleMap(installedRules.data); - - expectedResults.forEach((expected) => { - const installedRule = installedRulesMap.get(expected.rule_id); - expect(installedRule?.name).toEqual(expected.name); - expect(installedRule?.tags).toEqual(expected.tags); - }); - }); - - it('upgrades specific rules to their MERGED versions', async () => { - await createHistoricalPrebuiltRuleAssetSavedObjects(es, basePrebuiltAssets); - await installPrebuiltRules(es, supertest); - - await createHistoricalPrebuiltRuleAssetSavedObjects(es, targetPrebuiltAssets); - - const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest); - const expectedResults = reviewResponse.rules.map((upgradeInfo) => ({ - rule_id: upgradeInfo.rule_id, - name: upgradeInfo.diff.fields.name?.merged_version, - tags: upgradeInfo.diff.fields.tags?.merged_version, - })); - - const rulesToUpgrade = basePrebuiltAssets.map((rule) => ({ - rule_id: rule['security-rule'].rule_id, - revision: 0, - version: rule['security-rule'].version + 1, - })); - - const performUpgradeResponse = await performUpgradePrebuiltRules(es, supertest, { - mode: ModeEnum.SPECIFIC_RULES, - pick_version: 'MERGED', - rules: rulesToUpgrade, - }); - - expect(performUpgradeResponse.summary.succeeded).toEqual(basePrebuiltAssets.length); - - performUpgradeResponse.results.updated.forEach((updatedRule) => { - const expected = expectedResults.find((r) => r.rule_id === updatedRule.rule_id); - expect(updatedRule.name).toEqual(expected?.name); - expect(updatedRule.tags).toEqual(expected?.tags); - }); - - const installedRules = await getInstalledRules(supertest); - const installedRulesMap = createIdToRuleMap(installedRules.data); - - expectedResults.forEach((expected) => { - const installedRule = installedRulesMap.get(expected.rule_id); - expect(installedRule?.name).toEqual(expected.name); - expect(installedRule?.tags).toEqual(expected.tags); - }); - }); - - it('upgrades specific rules to their TARGET versions but overrides some fields with `fields` in the request payload', async () => { - await createHistoricalPrebuiltRuleAssetSavedObjects(es, basePrebuiltAssets); - await installPrebuiltRules(es, supertest); - await createHistoricalPrebuiltRuleAssetSavedObjects(es, targetPrebuiltAssets); - - const rulesToUpgrade = basePrebuiltAssets.map((rule) => ({ - rule_id: rule['security-rule'].rule_id, - revision: 0, - version: rule['security-rule'].version + 1, - fields: { - name: { pick_version: 'BASE' as PickVersionValues }, - }, - })); - - const performUpgradeResponse = await performUpgradePrebuiltRules(es, supertest, { - mode: ModeEnum.SPECIFIC_RULES, - pick_version: 'TARGET', - rules: rulesToUpgrade, - }); - - const expectedResults = basePrebuiltAssets.map((asset) => ({ - rule_id: asset['security-rule'].rule_id, - name: asset['security-rule'].name, - tags: TARGET_TAGS, - })); - - expect(performUpgradeResponse.summary.succeeded).toEqual(basePrebuiltAssets.length); - - performUpgradeResponse.results.updated.forEach((updatedRule) => { - const expected = expectedResults.find((r) => r.rule_id === updatedRule.rule_id); - expect(updatedRule.name).toEqual(expected?.name); - expect(updatedRule.tags).toEqual(expected?.tags); - }); - - const installedRules = await getInstalledRules(supertest); - const installedRulesMap = createIdToRuleMap(installedRules.data); - - expectedResults.forEach((expected) => { - const installedRule = installedRulesMap.get(expected.rule_id); - expect(installedRule?.name).toEqual(expected.name); - expect(installedRule?.tags).toEqual(expected.tags); - }); - }); - - it('upgrades specific rules with different pick_version at global, rule, and field levels', async () => { - await createHistoricalPrebuiltRuleAssetSavedObjects(es, basePrebuiltAssets); - await installPrebuiltRules(es, supertest); - - for (const baseRule of basePrebuiltAssets) { - await patchRule(supertest, log, { - rule_id: baseRule['security-rule'].rule_id, - name: CURRENT_NAME, - tags: CURRENT_TAGS, - }); - } - - await createHistoricalPrebuiltRuleAssetSavedObjects(es, targetPrebuiltAssets); - - const rulesToUpgrade = [ - { - rule_id: basePrebuiltAssets[0]['security-rule'].rule_id, - revision: 1, - version: basePrebuiltAssets[0]['security-rule'].version + 1, - pick_version: 'CURRENT' as PickVersionValues, - }, - { - rule_id: basePrebuiltAssets[1]['security-rule'].rule_id, - revision: 1, - version: basePrebuiltAssets[1]['security-rule'].version + 1, - fields: { - name: { pick_version: 'TARGET' as PickVersionValues }, - tags: { pick_version: 'BASE' as PickVersionValues }, - }, - }, - { - rule_id: basePrebuiltAssets[2]['security-rule'].rule_id, - revision: 1, - version: basePrebuiltAssets[2]['security-rule'].version + 1, - }, - ]; - - const performUpgradeResponse = await performUpgradePrebuiltRules(es, supertest, { - mode: ModeEnum.SPECIFIC_RULES, - pick_version: 'BASE', - rules: rulesToUpgrade, - }); - - expect(performUpgradeResponse.summary.succeeded).toEqual(3); - const updatedRulesMap = createIdToRuleMap(performUpgradeResponse.results.updated); - - const expectedResults = [ - { name: CURRENT_NAME, tags: CURRENT_TAGS }, - { name: TARGET_NAME, tags: basePrebuiltAssets[1]['security-rule'].tags }, - { - name: basePrebuiltAssets[2]['security-rule'].name, - tags: basePrebuiltAssets[2]['security-rule'].tags, - }, - ]; - - basePrebuiltAssets.forEach((asset, index) => { - const ruleId = asset['security-rule'].rule_id; - const updatedRule = updatedRulesMap.get(ruleId); - expect(updatedRule?.name).toEqual(expectedResults[index].name); - expect(updatedRule?.tags).toEqual(expectedResults[index].tags); - }); - - const installedRules = await getInstalledRules(supertest); - const installedRulesMap = createIdToRuleMap(installedRules.data); - - basePrebuiltAssets.forEach((asset, index) => { - const ruleId = asset['security-rule'].rule_id; - const installedRule = installedRulesMap.get(ruleId); - expect(installedRule?.name).toEqual(expectedResults[index].name); - expect(installedRule?.tags).toEqual(expectedResults[index].tags); - }); - }); - - it('successfully resolves a non-resolvable conflict by using pick_version:RESOLVED for that field', async () => { - const baseEqlRule = createRuleAssetSavedObjectOfType('eql'); - await createHistoricalPrebuiltRuleAssetSavedObjects(es, [baseEqlRule]); - await installPrebuiltRules(es, supertest); - - // Patch the installed rule to edit its query - const patchedQuery = 'sequence by process.name [MY CURRENT QUERY]'; - await patchRule(supertest, log, { - rule_id: baseEqlRule['security-rule'].rule_id, - query: patchedQuery, - }); - - // Create a new version of the prebuilt rule asset with a different query and generate the conflict - const targetEqlRule = cloneDeep(baseEqlRule); - targetEqlRule['security-rule'].version += 1; - targetEqlRule['security-rule'].query = 'sequence by process.name [MY TARGET QUERY]'; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, [targetEqlRule]); - - const resolvedValue = { - query: 'sequence by process.name [MY RESOLVED QUERY]', - language: 'eql', - filters: [], - }; - - // Perform the upgrade with manual conflict resolution - const performUpgradeResponse = await performUpgradePrebuiltRules(es, supertest, { - mode: ModeEnum.SPECIFIC_RULES, - pick_version: 'MERGED', - rules: [ - { - rule_id: baseEqlRule['security-rule'].rule_id, - revision: 1, - version: baseEqlRule['security-rule'].version + 1, - fields: { - eql_query: { - pick_version: 'RESOLVED', - resolved_value: resolvedValue as RuleEqlQuery, - }, - }, - }, - ], - }); - - expect(performUpgradeResponse.summary.succeeded).toEqual(1); - const updatedRule = performUpgradeResponse.results.updated[0] as EqlRule; - expect(updatedRule.rule_id).toEqual(baseEqlRule['security-rule'].rule_id); - expect(updatedRule.query).toEqual(resolvedValue.query); - expect(updatedRule.filters).toEqual(resolvedValue.filters); - expect(updatedRule.language).toEqual(resolvedValue.language); - - const installedRules = await getInstalledRules(supertest); - const installedRule = installedRules.data.find( - (rule) => rule.rule_id === baseEqlRule['security-rule'].rule_id - ) as EqlRule; - expect(installedRule?.query).toEqual(resolvedValue.query); - expect(installedRule?.filters).toEqual(resolvedValue.filters); - expect(installedRule?.language).toEqual(resolvedValue.language); - }); - }); - - describe('edge cases and unhappy paths', () => { - const queryRule = createRuleAssetSavedObject({ - type: 'query', - language: 'kuery', - rule_id: 'query-rule', - }); - const eqlRule = createRuleAssetSavedObject({ - type: 'eql', - language: 'eql', - rule_id: 'eql-rule', - }); - - const basePrebuiltAssets = [queryRule, eqlRule]; - - it('rejects updates when rule type changes and pick_version is not TARGET at all levels', async () => { - await createHistoricalPrebuiltRuleAssetSavedObjects(es, basePrebuiltAssets); - await installPrebuiltRules(es, supertest); - - const targetMLRule = createRuleAssetSavedObject({ - rule_id: queryRule['security-rule'].rule_id, - version: queryRule['security-rule'].version + 1, - type: 'machine_learning', - machine_learning_job_id: 'job_id', - anomaly_threshold: 1, - }); - - await createHistoricalPrebuiltRuleAssetSavedObjects(es, [targetMLRule]); - - const performUpgradeResponse = await performUpgradePrebuiltRules(es, supertest, { - mode: ModeEnum.SPECIFIC_RULES, - pick_version: 'BASE', - rules: [ - { - rule_id: queryRule['security-rule'].rule_id, - revision: 0, - version: queryRule['security-rule'].version + 1, - }, - ], - }); - - expect(performUpgradeResponse.summary.failed).toEqual(1); - expect(performUpgradeResponse.errors[0].message).toContain( - 'Rule update for rule query-rule has a rule type change' - ); - }); - - it('rejects updates when incompatible fields are provided for a rule type', async () => { - const baseEqlRule = createRuleAssetSavedObjectOfType('eql'); - await createHistoricalPrebuiltRuleAssetSavedObjects(es, [baseEqlRule]); - await installPrebuiltRules(es, supertest); - - // Create a new version of the prebuilt rule asset with a different query and generate the conflict - const targetEqlRule = cloneDeep(baseEqlRule); - targetEqlRule['security-rule'].version += 1; - targetEqlRule['security-rule'].query = 'sequence by process.name [MY TARGET QUERY]'; - await createHistoricalPrebuiltRuleAssetSavedObjects(es, [targetEqlRule]); - - const performUpgradeResponse = await performUpgradePrebuiltRules(es, supertest, { - mode: ModeEnum.SPECIFIC_RULES, - pick_version: 'TARGET', - rules: [ - { - rule_id: baseEqlRule['security-rule'].rule_id, - revision: 0, - version: baseEqlRule['security-rule'].version + 1, - fields: { - machine_learning_job_id: { pick_version: 'TARGET' }, - }, - }, - ], - }); - - expect(performUpgradeResponse.summary.failed).toEqual(1); - expect(performUpgradeResponse.errors[0].message).toContain( - "machine_learning_job_id is not a valid upgradeable field for type 'eql'" - ); - }); - - it('rejects updates with NON_SOLVABLE conflicts when using MERGED pick_version', async () => { - await createHistoricalPrebuiltRuleAssetSavedObjects(es, basePrebuiltAssets); - await installPrebuiltRules(es, supertest); - - await patchRule(supertest, log, { - rule_id: queryRule['security-rule'].rule_id, - name: CURRENT_NAME, - }); - - const targetQueryRule = cloneDeep(queryRule); - targetQueryRule['security-rule'].version += 1; - targetQueryRule['security-rule'].name = TARGET_NAME; - - await createHistoricalPrebuiltRuleAssetSavedObjects(es, [targetQueryRule]); - - const performUpgradeResponse = await performUpgradePrebuiltRules(es, supertest, { - mode: ModeEnum.SPECIFIC_RULES, - pick_version: 'MERGED', - rules: [ - { - rule_id: queryRule['security-rule'].rule_id, - revision: 1, - version: queryRule['security-rule'].version + 1, - }, - ], - }); - - expect(performUpgradeResponse.summary.failed).toEqual(1); - expect(performUpgradeResponse.errors[0].message).toContain( - `Automatic merge calculation for field 'name' in rule of rule_id ${performUpgradeResponse.errors[0].rules[0].rule_id} resulted in a conflict. Please resolve the conflict manually or choose another value for 'pick_version'` - ); - }); - - it('allows updates with NON_SOLVABLE conflicts when specific fields have non-MERGED pick_version', async () => { - await createHistoricalPrebuiltRuleAssetSavedObjects(es, basePrebuiltAssets); - await installPrebuiltRules(es, supertest); - - await patchRule(supertest, log, { - rule_id: queryRule['security-rule'].rule_id, - name: CURRENT_NAME, - }); - - const targetQueryRule = cloneDeep(queryRule); - targetQueryRule['security-rule'].version += 1; - targetQueryRule['security-rule'].name = TARGET_NAME; - - await createHistoricalPrebuiltRuleAssetSavedObjects(es, [targetQueryRule]); - - const performUpgradeResponse = await performUpgradePrebuiltRules(es, supertest, { - mode: ModeEnum.SPECIFIC_RULES, - pick_version: 'MERGED', - rules: [ - { - rule_id: queryRule['security-rule'].rule_id, - revision: 1, - version: queryRule['security-rule'].version + 1, - fields: { - name: { pick_version: 'TARGET' }, - }, - }, - ], - }); - - expect(performUpgradeResponse.summary.succeeded).toEqual(1); - expect(performUpgradeResponse.results.updated[0].name).toEqual(TARGET_NAME); - - const installedRules = await getInstalledRules(supertest); - const installedRule = installedRules.data.find( - (rule) => rule.rule_id === queryRule['security-rule'].rule_id - ); - expect(installedRule?.name).toEqual(TARGET_NAME); - }); - - it('rejects updates for specific fields with MERGED pick_version and NON_SOLVABLE conflicts', async () => { - await createHistoricalPrebuiltRuleAssetSavedObjects(es, basePrebuiltAssets); - await installPrebuiltRules(es, supertest); - - await patchRule(supertest, log, { - rule_id: queryRule['security-rule'].rule_id, - name: CURRENT_NAME, - }); - - const targetQueryRule = cloneDeep(queryRule); - targetQueryRule['security-rule'].version += 1; - targetQueryRule['security-rule'].name = TARGET_NAME; - - await createHistoricalPrebuiltRuleAssetSavedObjects(es, [targetQueryRule]); - - const performUpgradeResponse = await performUpgradePrebuiltRules(es, supertest, { - mode: ModeEnum.SPECIFIC_RULES, - pick_version: 'TARGET', - rules: [ - { - rule_id: queryRule['security-rule'].rule_id, - revision: 1, - version: queryRule['security-rule'].version + 1, - fields: { - name: { pick_version: 'MERGED' }, - }, - }, - ], - }); - - expect(performUpgradeResponse.summary.failed).toEqual(1); - expect(performUpgradeResponse.errors[0].message).toContain( - `Automatic merge calculation for field 'name' in rule of rule_id ${performUpgradeResponse.errors[0].rules[0].rule_id} resulted in a conflict. Please resolve the conflict manually or choose another value for 'pick_version'.` - ); - }); - - it('preserves FIELDS_TO_UPGRADE_TO_CURRENT_VERSION when upgrading to TARGET version with undefined fields', async () => { - const baseRule = - createRuleAssetSavedObjectOfType('threat_match'); - await createHistoricalPrebuiltRuleAssetSavedObjects(es, [baseRule]); - await installPrebuiltRules(es, supertest); - - const ruleId = baseRule['security-rule'].rule_id; - - const installedBaseRule = ( - await securitySolutionApi.readRule({ - query: { - rule_id: ruleId, - }, - }) - ).body as ThreatMatchRule; - - // Patch the installed rule to set all FIELDS_TO_UPGRADE_TO_CURRENT_VERSION to some defined value - const currentValues: { [key: string]: unknown } = { - enabled: true, - exceptions_list: [ - { - id: 'test-list', - list_id: 'test-list', - type: 'detection', - namespace_type: 'single', - } as const, - ], - alert_suppression: { - group_by: ['host.name'], - duration: { value: 5, unit: 'm' as const }, - }, - actions: [await createAction(supertest)], - response_actions: [ - { - params: { - command: 'isolate' as const, - comment: 'comment', - }, - action_type_id: '.endpoint' as const, - }, - ], - meta: { some_key: 'some_value' }, - output_index: '.siem-signals-default', - namespace: 'default', - concurrent_searches: 5, - items_per_search: 100, - }; - - await securitySolutionApi.updateRule({ - body: { - ...installedBaseRule, - ...currentValues, - id: undefined, - }, - }); - - // Create a target version with undefined values for these fields - const targetRule = cloneDeep(baseRule); - targetRule['security-rule'].version += 1; - FIELDS_TO_UPGRADE_TO_CURRENT_VERSION.forEach((field) => { - // @ts-expect-error - targetRule['security-rule'][field] = undefined; - }); - await createHistoricalPrebuiltRuleAssetSavedObjects(es, [targetRule]); - - // Perform the upgrade - const performUpgradeResponse = await performUpgradePrebuiltRules(es, supertest, { - mode: ModeEnum.SPECIFIC_RULES, - pick_version: 'TARGET', - rules: [ - { - rule_id: baseRule['security-rule'].rule_id, - revision: 1, - version: baseRule['security-rule'].version + 1, - }, - ], - }); - - expect(performUpgradeResponse.summary.succeeded).toEqual(1); - const upgradedRule = performUpgradeResponse.results.updated[0] as ThreatMatchRule; - - // Check that all FIELDS_TO_UPGRADE_TO_CURRENT_VERSION still have their "current" values - FIELDS_TO_UPGRADE_TO_CURRENT_VERSION.forEach((field) => { - expect(upgradedRule[field]).toEqual(currentValues[field]); - }); - - // Verify the installed rule - const installedRules = await getInstalledRules(supertest); - const installedRule = installedRules.data.find( - (rule) => rule.rule_id === baseRule['security-rule'].rule_id - ) as ThreatMatchRule; - - FIELDS_TO_UPGRADE_TO_CURRENT_VERSION.forEach((field) => { - expect(installedRule[field]).toEqual(currentValues[field]); - }); - }); - - it('preserves FIELDS_TO_UPGRADE_TO_CURRENT_VERSION when fields are attempted to be updated via resolved values', async () => { - const baseRule = - createRuleAssetSavedObjectOfType('threat_match'); - await createHistoricalPrebuiltRuleAssetSavedObjects(es, [baseRule]); - await installPrebuiltRules(es, supertest); - - const ruleId = baseRule['security-rule'].rule_id; - - const installedBaseRule = ( - await securitySolutionApi.readRule({ - query: { - rule_id: ruleId, - }, - }) - ).body as ThreatMatchRule; - - // Set current values for FIELDS_TO_UPGRADE_TO_CURRENT_VERSION - const currentValues: { [key: string]: unknown } = { - enabled: true, - exceptions_list: [ - { - id: 'test-list', - list_id: 'test-list', - type: 'detection', - namespace_type: 'single', - } as const, - ], - alert_suppression: { - group_by: ['host.name'], - duration: { value: 5, unit: 'm' as const }, - }, - actions: [await createAction(supertest)], - response_actions: [ - { - params: { - command: 'isolate' as const, - comment: 'comment', - }, - action_type_id: '.endpoint' as const, - }, - ], - meta: { some_key: 'some_value' }, - output_index: '.siem-signals-default', - namespace: 'default', - concurrent_searches: 5, - items_per_search: 100, - }; - - await securitySolutionApi.updateRule({ - body: { - ...installedBaseRule, - ...currentValues, - id: undefined, - }, - }); - - // Create a target version with undefined values for these fields - const targetRule = cloneDeep(baseRule); - targetRule['security-rule'].version += 1; - FIELDS_TO_UPGRADE_TO_CURRENT_VERSION.forEach((field) => { - // @ts-expect-error - targetRule['security-rule'][field] = undefined; - }); - await createHistoricalPrebuiltRuleAssetSavedObjects(es, [targetRule]); - - // Create resolved values different from current values - const resolvedValues: { [key: string]: unknown } = { - alert_suppression: { - group_by: ['test'], - duration: { value: 10, unit: 'm' as const }, - }, - }; - - const fields = Object.fromEntries( - Object.keys(resolvedValues).map((field) => [ - field, - { - pick_version: 'RESOLVED' as PickVersionValues, - resolved_value: resolvedValues[field], - }, - ]) - ); - - // Perform the upgrade with resolved values - const performUpgradeResponse = await performUpgradePrebuiltRules(es, supertest, { - mode: ModeEnum.SPECIFIC_RULES, - pick_version: 'TARGET', - rules: [ - { - rule_id: baseRule['security-rule'].rule_id, - revision: 1, - version: baseRule['security-rule'].version + 1, - fields, - }, - ], - }); - - expect(performUpgradeResponse.summary.succeeded).toEqual(1); - const upgradedRule = performUpgradeResponse.results.updated[0] as ThreatMatchRule; - - // Check that all FIELDS_TO_UPGRADE_TO_CURRENT_VERSION still have their "current" values - FIELDS_TO_UPGRADE_TO_CURRENT_VERSION.forEach((field) => { - expect(upgradedRule[field]).toEqual(currentValues[field]); - }); - - // Verify the installed rule - const installedRules = await getInstalledRules(supertest); - const installedRule = installedRules.data.find( - (rule) => rule.rule_id === baseRule['security-rule'].rule_id - ) as ThreatMatchRule; - - FIELDS_TO_UPGRADE_TO_CURRENT_VERSION.forEach((field) => { - expect(installedRule[field]).toEqual(currentValues[field]); - }); - }); - }); - }); -}; - -function createIdToRuleMap(rules: Array) { - return new Map(rules.map((rule) => [rule.rule_id, rule])); -} - -async function createAction(supertest: SuperTest.Agent) { - const createConnector = async (payload: Record) => - ( - await supertest - .post('/api/actions/connector') - .set('kbn-xsrf', 'true') - .send(payload) - .expect(200) - ).body; - - const createWebHookConnector = () => createConnector(getWebHookAction()); - - const webHookAction = await createWebHookConnector(); - - const defaultRuleAction = { - id: webHookAction.id, - action_type_id: '.webhook' as const, - group: 'default' as const, - params: { - body: '{"test":"a default action"}', - }, - frequency: { - notifyWhen: 'onThrottleInterval' as const, - summary: true, - throttle: '1h' as const, - }, - uuid: 'd487ec3d-05f2-44ad-8a68-11c97dc92202', - }; - - return defaultRuleAction; -} diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/upgrade_prebuilt_rules/bulk_upgrade_all_prebuilt_rules.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/upgrade_prebuilt_rules/bulk_upgrade_all_prebuilt_rules.ts new file mode 100644 index 0000000000000..7f03101502f61 --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/upgrade_prebuilt_rules/bulk_upgrade_all_prebuilt_rules.ts @@ -0,0 +1,368 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import expect from 'expect'; +import { ModeEnum } from '@kbn/security-solution-plugin/common/api/detection_engine'; +import { setUpRuleUpgrade } from '../../../../../utils/rules/prebuilt_rules/set_up_rule_upgrade'; +import { FtrProviderContext } from '../../../../../../../ftr_provider_context'; +import { performUpgradePrebuiltRules } from '../../../../../utils'; + +export function bulkUpgradeAllPrebuiltRules({ getService }: FtrProviderContext): void { + const es = getService('es'); + const supertest = getService('supertest'); + const log = getService('log'); + const deps = { + es, + supertest, + log, + }; + + describe('all rules', () => { + describe('with historical versions', () => { + const TEST_DATA = [ + { pickVersion: 'BASE', expectedTags: ['tagA'] }, + { pickVersion: 'CURRENT', expectedTags: ['tagB'] }, + { pickVersion: 'TARGET', expectedTags: ['tagC'] }, + ] as const; + + for (const { pickVersion, expectedTags } of TEST_DATA) { + it(`upgrades to ${pickVersion} version`, async () => { + await setUpRuleUpgrade({ + assets: [ + { + installed: { + type: 'query', + tags: ['tagA'], + rule_id: 'rule_1', + version: 1, + }, + patch: { + rule_id: 'rule_1', + tags: ['tagB'], + }, + upgrade: { + type: 'query', + tags: ['tagC'], + rule_id: 'rule_1', + version: 2, + }, + }, + { + installed: { + type: 'query', + tags: ['tagA'], + rule_id: 'rule_2', + version: 1, + }, + patch: { + rule_id: 'rule_2', + tags: ['tagB'], + }, + upgrade: { + type: 'query', + tags: ['tagC'], + rule_id: 'rule_2', + version: 2, + }, + }, + ], + deps, + }); + + const response = await performUpgradePrebuiltRules(es, supertest, { + mode: ModeEnum.ALL_RULES, + pick_version: pickVersion, + }); + + expect(response.summary).toMatchObject({ + total: 2, + succeeded: 2, + skipped: 0, + failed: 0, + }); + expect(response.results.updated).toHaveLength(2); + expect(response.results.updated).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + rule_id: 'rule_1', + version: 2, + tags: expectedTags, + }), + expect.objectContaining({ + rule_id: 'rule_2', + version: 2, + tags: expectedTags, + }), + ]) + ); + }); + } + + it(`upgrades to TARGET version when is MERGED and there are no conflicts`, async () => { + await setUpRuleUpgrade({ + assets: [ + { + installed: { + type: 'query', + tags: ['tagA'], + rule_id: 'rule_1', + version: 1, + }, + patch: {}, + upgrade: { + type: 'query', + tags: ['tagC'], + rule_id: 'rule_1', + version: 2, + }, + }, + { + installed: { + type: 'query', + tags: ['tagA'], + rule_id: 'rule_2', + version: 1, + }, + patch: {}, + upgrade: { + type: 'query', + tags: ['tagC'], + rule_id: 'rule_2', + version: 2, + }, + }, + ], + deps, + }); + + const response = await performUpgradePrebuiltRules(es, supertest, { + mode: ModeEnum.ALL_RULES, + pick_version: 'MERGED', + }); + + expect(response.summary).toMatchObject({ + total: 2, + succeeded: 2, + skipped: 0, + failed: 0, + }); + expect(response.results.updated).toHaveLength(2); + expect(response.results.updated).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + rule_id: 'rule_1', + version: 2, + tags: ['tagC'], + }), + expect.objectContaining({ + rule_id: 'rule_2', + version: 2, + tags: ['tagC'], + }), + ]) + ); + }); + + it('UNABLE to upgrade in case of conflicts when is MERGED', async () => { + await setUpRuleUpgrade({ + assets: [ + { + installed: { + type: 'query', + tags: ['tagA'], + rule_id: 'rule_1', + version: 1, + }, + patch: { + rule_id: 'rule_1', + tags: ['tagB'], + }, + upgrade: { + type: 'query', + tags: ['tagC'], + rule_id: 'rule_1', + version: 2, + }, + }, + { + installed: { + type: 'query', + tags: ['tagA'], + rule_id: 'rule_2', + version: 1, + }, + patch: { + rule_id: 'rule_2', + tags: ['tagB'], + }, + upgrade: { + type: 'query', + tags: ['tagC'], + rule_id: 'rule_2', + version: 2, + }, + }, + ], + deps, + }); + + const response = await performUpgradePrebuiltRules(es, supertest, { + mode: ModeEnum.ALL_RULES, + pick_version: 'MERGED', + }); + + expect(response.summary).toMatchObject({ + total: 2, + succeeded: 0, + skipped: 0, + failed: 2, + }); + expect(response.errors).toHaveLength(2); + }); + }); + + describe('without historical versions', () => { + const TEST_DATA = [ + { pickVersion: 'CURRENT', expectedTags: ['tagB'] }, + { pickVersion: 'TARGET', expectedTags: ['tagC'] }, + ] as const; + + for (const { pickVersion, expectedTags } of TEST_DATA) { + it(`upgrades to ${pickVersion} version`, async () => { + await setUpRuleUpgrade({ + assets: [ + { + installed: { + type: 'query', + tags: ['tagA'], + rule_id: 'rule_1', + version: 1, + }, + patch: { + rule_id: 'rule_1', + tags: ['tagB'], + }, + upgrade: { + type: 'query', + tags: ['tagC'], + rule_id: 'rule_1', + version: 2, + }, + }, + { + installed: { + type: 'query', + tags: ['tagA'], + rule_id: 'rule_2', + version: 1, + }, + patch: { + rule_id: 'rule_2', + tags: ['tagB'], + }, + upgrade: { + type: 'query', + tags: ['tagC'], + rule_id: 'rule_2', + version: 2, + }, + }, + ], + removeInstalledAssets: true, + deps, + }); + + const response = await performUpgradePrebuiltRules(es, supertest, { + mode: ModeEnum.ALL_RULES, + pick_version: pickVersion, + }); + + expect(response.summary).toMatchObject({ + total: 2, + succeeded: 2, + skipped: 0, + failed: 0, + }); + expect(response.results.updated).toHaveLength(2); + expect(response.results.updated).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + rule_id: 'rule_1', + version: 2, + tags: expectedTags, + }), + expect.objectContaining({ + rule_id: 'rule_2', + version: 2, + tags: expectedTags, + }), + ]) + ); + }); + } + + for (const pickVersion of ['BASE', 'MERGED'] as const) { + it(`UNABLE to upgrade to ${pickVersion} version`, async () => { + await setUpRuleUpgrade({ + assets: [ + { + installed: { + type: 'query', + tags: ['tagA'], + rule_id: 'rule_1', + version: 1, + }, + patch: { + rule_id: 'rule_1', + tags: ['tagB'], + }, + upgrade: { + type: 'query', + tags: ['tagC'], + rule_id: 'rule_1', + version: 2, + }, + }, + { + installed: { + type: 'query', + tags: ['tagA'], + rule_id: 'rule_2', + version: 1, + }, + patch: { + rule_id: 'rule_2', + tags: ['tagB'], + }, + upgrade: { + type: 'query', + tags: ['tagC'], + rule_id: 'rule_2', + version: 2, + }, + }, + ], + removeInstalledAssets: true, + deps, + }); + + const response = await performUpgradePrebuiltRules(es, supertest, { + mode: ModeEnum.ALL_RULES, + pick_version: pickVersion, + }); + + expect(response.summary).toMatchObject({ + total: 2, + succeeded: 0, + skipped: 0, + failed: 2, + }); + }); + } + }); + }); +} diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/upgrade_prebuilt_rules/bulk_upgrade_selected_prebuilt_rules.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/upgrade_prebuilt_rules/bulk_upgrade_selected_prebuilt_rules.ts new file mode 100644 index 0000000000000..fc2f083a180ef --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/upgrade_prebuilt_rules/bulk_upgrade_selected_prebuilt_rules.ts @@ -0,0 +1,503 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import expect from 'expect'; +import { ModeEnum } from '@kbn/security-solution-plugin/common/api/detection_engine'; +import { setUpRuleUpgrade } from '../../../../../utils/rules/prebuilt_rules/set_up_rule_upgrade'; +import { FtrProviderContext } from '../../../../../../../ftr_provider_context'; +import { performUpgradePrebuiltRules } from '../../../../../utils'; + +export function bulkUpgradeSelectedPrebuiltRules({ getService }: FtrProviderContext): void { + const es = getService('es'); + const supertest = getService('supertest'); + const log = getService('log'); + const deps = { + es, + supertest, + log, + }; + + describe('selected rules', () => { + describe('with historical versions', () => { + describe('without customizations', () => { + beforeEach(async () => { + await setUpRuleUpgrade({ + assets: [ + { + installed: { + type: 'query', + name: 'Initial name', + tags: ['tagA'], + rule_id: 'rule_1', + version: 1, + }, + patch: {}, + upgrade: { + type: 'query', + name: 'Updated name', + tags: ['tagC'], + rule_id: 'rule_1', + version: 2, + }, + }, + { + installed: { + type: 'query', + name: 'Initial name', + tags: ['tagA'], + rule_id: 'rule_2', + version: 1, + }, + patch: {}, + upgrade: { + type: 'query', + name: 'Updated name', + tags: ['tagC'], + rule_id: 'rule_2', + version: 2, + }, + }, + // Rule rule_id: 'rule_3' isn't selected for upgrade + { + installed: { + type: 'query', + name: 'Initial name', + tags: ['tagA'], + rule_id: 'rule_3', + version: 1, + }, + patch: { + rule_id: 'rule_3', + name: 'Customized name', + tags: ['tagB'], + }, + upgrade: { + type: 'query', + name: 'Updated name', + tags: ['tagC'], + rule_id: 'rule_3', + version: 2, + }, + }, + ], + deps, + }); + }); + + for (const { pickVersion, expectedName, expectedTags } of [ + { + pickVersion: 'BASE', + expectedName: 'Initial name', + expectedTags: ['tagA'], + }, + { + pickVersion: 'CURRENT', + expectedName: 'Initial name', + expectedTags: ['tagA'], + }, + { + pickVersion: 'TARGET', + expectedName: 'Updated name', + expectedTags: ['tagC'], + }, + { + pickVersion: 'MERGED', + expectedName: 'Updated name', + expectedTags: ['tagC'], + }, + ] as const) { + it(`upgrades with is MERGED`, async () => { + const response = await performUpgradePrebuiltRules(es, supertest, { + mode: ModeEnum.SPECIFIC_RULES, + rules: [ + { + rule_id: 'rule_1', + revision: 0, + version: 2, + pick_version: pickVersion, + }, + { + rule_id: 'rule_2', + revision: 0, + version: 2, + pick_version: pickVersion, + }, + ], + }); + + expect(response.summary).toMatchObject({ + total: 2, + succeeded: 2, + skipped: 0, + failed: 0, + }); + expect(response.results.updated).toHaveLength(2); + expect(response.results.updated).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + rule_id: 'rule_1', + version: 2, + name: expectedName, + tags: expectedTags, + }), + expect.objectContaining({ + rule_id: 'rule_2', + version: 2, + name: expectedName, + tags: expectedTags, + }), + ]) + ); + }); + } + }); + + describe('with customizations resulting in conflicts', () => { + beforeEach(async () => { + await setUpRuleUpgrade({ + assets: [ + { + installed: { + type: 'query', + tags: ['tagA'], + rule_id: 'rule_1', + version: 1, + }, + patch: { + rule_id: 'rule_1', + tags: ['tagB'], + }, + upgrade: { + type: 'query', + tags: ['tagC'], + rule_id: 'rule_1', + version: 2, + }, + }, + { + installed: { + type: 'query', + tags: ['tagA'], + rule_id: 'rule_2', + version: 1, + }, + patch: { + rule_id: 'rule_2', + tags: ['tagB'], + }, + upgrade: { + type: 'query', + tags: ['tagC'], + rule_id: 'rule_2', + version: 2, + }, + }, + { + installed: { + type: 'query', + tags: ['tagA'], + rule_id: 'rule_3', + version: 1, + }, + patch: { + rule_id: 'rule_3', + tags: ['tagB'], + }, + upgrade: { + type: 'query', + tags: ['tagC'], + rule_id: 'rule_3', + version: 2, + }, + }, + ], + deps, + }); + }); + + const TEST_DATA = [ + { + globalPickVersion: 'BASE', + rulePickVersion: undefined, + expectedTags: ['tagA'], + }, + { + globalPickVersion: 'CURRENT', + rulePickVersion: undefined, + expectedTags: ['tagB'], + }, + { + globalPickVersion: 'TARGET', + rulePickVersion: undefined, + expectedTags: ['tagC'], + }, + { + globalPickVersion: undefined, + rulePickVersion: 'BASE', + expectedTags: ['tagA'], + }, + { + globalPickVersion: undefined, + rulePickVersion: 'CURRENT', + expectedPickVersion: 'CURRENT', + expectedTags: ['tagB'], + }, + { + globalPickVersion: undefined, + rulePickVersion: 'TARGET', + expectedTags: ['tagC'], + }, + { + globalPickVersion: 'BASE', + rulePickVersion: 'CURRENT', + expectedTags: ['tagB'], + }, + { + globalPickVersion: 'BASE', + rulePickVersion: 'TARGET', + expectedTags: ['tagC'], + }, + { + globalPickVersion: 'CURRENT', + rulePickVersion: 'BASE', + expectedTags: ['tagA'], + }, + { + globalPickVersion: 'CURRENT', + rulePickVersion: 'TARGET', + expectedTags: ['tagC'], + }, + { + globalPickVersion: 'TARGET', + rulePickVersion: 'BASE', + expectedTags: ['tagA'], + }, + { + globalPickVersion: 'TARGET', + rulePickVersion: 'CURRENT', + expectedTags: ['tagB'], + }, + ] as const; + + for (const { globalPickVersion, rulePickVersion, expectedTags } of TEST_DATA) { + it(`upgrades rule when "globalPickVersion is ${globalPickVersion}" and "rulePickVersion is ${rulePickVersion}"`, async () => { + const response = await performUpgradePrebuiltRules(es, supertest, { + mode: ModeEnum.SPECIFIC_RULES, + pick_version: globalPickVersion, + rules: [ + { + rule_id: 'rule_1', + revision: 1, + version: 2, + pick_version: rulePickVersion, + }, + { + rule_id: 'rule_2', + revision: 1, + version: 2, + pick_version: rulePickVersion, + }, + ], + }); + + expect(response.summary).toMatchObject({ + total: 2, + succeeded: 2, + skipped: 0, + failed: 0, + }); + expect(response.results.updated).toHaveLength(2); + expect(response.results.updated).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + rule_id: 'rule_1', + version: 2, + tags: expectedTags, + }), + expect.objectContaining({ + rule_id: 'rule_2', + version: 2, + tags: expectedTags, + }), + ]) + ); + }); + } + + it(`UNABLE to upgrade rules when is MERGED`, async () => { + const response = await performUpgradePrebuiltRules(es, supertest, { + mode: ModeEnum.SPECIFIC_RULES, + rules: [ + { + rule_id: 'rule_1', + revision: 0, + version: 2, + pick_version: 'MERGED', + }, + { + rule_id: 'rule_2', + revision: 0, + version: 2, + pick_version: 'MERGED', + }, + ], + }); + + expect(response.summary).toMatchObject({ + failed: 2, + }); + }); + }); + }); + + describe('without historical versions', () => { + const TEST_DATA = [ + { pickVersion: 'CURRENT', expectedTags: ['tagB'] }, + { pickVersion: 'TARGET', expectedTags: ['tagC'] }, + ] as const; + + for (const { pickVersion, expectedTags } of TEST_DATA) { + it(`upgrades to ${pickVersion} version`, async () => { + await setUpRuleUpgrade({ + assets: [ + { + installed: { + type: 'query', + tags: ['tagA'], + rule_id: 'rule_1', + version: 1, + }, + patch: { + rule_id: 'rule_1', + tags: ['tagB'], + }, + upgrade: { + type: 'query', + tags: ['tagC'], + rule_id: 'rule_1', + version: 2, + }, + }, + { + installed: { + type: 'query', + tags: ['tagA'], + rule_id: 'rule_2', + version: 1, + }, + patch: { + rule_id: 'rule_2', + tags: ['tagB'], + }, + upgrade: { + type: 'query', + tags: ['tagC'], + rule_id: 'rule_2', + version: 2, + }, + }, + ], + removeInstalledAssets: true, + deps, + }); + + const response = await performUpgradePrebuiltRules(es, supertest, { + mode: ModeEnum.SPECIFIC_RULES, + rules: [ + { + rule_id: 'rule_1', + revision: 1, + version: 2, + pick_version: pickVersion, + }, + ], + }); + + expect(response.summary).toMatchObject({ + total: 1, + succeeded: 1, + skipped: 0, + failed: 0, + }); + expect(response.results.updated).toEqual([ + expect.objectContaining({ + rule_id: 'rule_1', + version: 2, + tags: expectedTags, + }), + ]); + }); + } + + for (const pickVersion of ['BASE', 'MERGED'] as const) { + it(`UNABLE to upgrade rules when is ${pickVersion}`, async () => { + await setUpRuleUpgrade({ + assets: [ + { + installed: { + type: 'query', + tags: ['tagA'], + rule_id: 'rule_1', + version: 1, + }, + patch: { + rule_id: 'rule_1', + tags: ['tagB'], + }, + upgrade: { + type: 'query', + tags: ['tagC'], + rule_id: 'rule_1', + version: 2, + }, + }, + { + installed: { + type: 'query', + tags: ['tagA'], + rule_id: 'rule_2', + version: 1, + }, + patch: { + rule_id: 'rule_2', + tags: ['tagB'], + }, + upgrade: { + type: 'query', + tags: ['tagC'], + rule_id: 'rule_2', + version: 2, + }, + }, + ], + removeInstalledAssets: true, + deps, + }); + + const response = await performUpgradePrebuiltRules(es, supertest, { + mode: ModeEnum.SPECIFIC_RULES, + rules: [ + { + rule_id: 'rule_1', + revision: 1, + version: 2, + pick_version: pickVersion, + }, + ], + }); + + expect(response.summary).toMatchObject({ + total: 1, + succeeded: 0, + skipped: 0, + failed: 1, + }); + }); + } + }); + }); +} diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/upgrade_prebuilt_rules/index.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/upgrade_prebuilt_rules/index.ts new file mode 100644 index 0000000000000..03b0c28326f4b --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/upgrade_prebuilt_rules/index.ts @@ -0,0 +1,30 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrProviderContext } from '../../../../../../../ftr_provider_context'; +import { deleteAllPrebuiltRuleAssets } from '../../../../../utils'; +import { deleteAllRules } from '../../../../../../../../common/utils/security_solution'; +import { bulkUpgradeAllPrebuiltRules } from './bulk_upgrade_all_prebuilt_rules'; +import { bulkUpgradeSelectedPrebuiltRules } from './bulk_upgrade_selected_prebuilt_rules'; +import { upgradeSinglePrebuiltRule } from './upgrade_single_prebuilt_rule'; + +export default (context: FtrProviderContext): void => { + const es = context.getService('es'); + const supertest = context.getService('supertest'); + const log = context.getService('log'); + + describe('@ess @serverless @skipInServerlessMKI upgrade prebuilt rules', () => { + beforeEach(async () => { + await deleteAllRules(supertest, log); + await deleteAllPrebuiltRuleAssets(es, log); + }); + + bulkUpgradeAllPrebuiltRules(context); + bulkUpgradeSelectedPrebuiltRules(context); + upgradeSinglePrebuiltRule(context); + }); +}; diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/upgrade_prebuilt_rules/upgrade_single_prebuilt_rule.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/upgrade_prebuilt_rules/upgrade_single_prebuilt_rule.ts new file mode 100644 index 0000000000000..6f345365a4e2b --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/customization_enabled/upgrade_prebuilt_rules/upgrade_single_prebuilt_rule.ts @@ -0,0 +1,388 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import expect from 'expect'; +import type SuperTest from 'supertest'; +import { ModeEnum } from '@kbn/security-solution-plugin/common/api/detection_engine'; +import { + DEFAULT_TEST_RULE_ID, + setUpRuleUpgrade, +} from '../../../../../utils/rules/prebuilt_rules/set_up_rule_upgrade'; +import { FtrProviderContext } from '../../../../../../../ftr_provider_context'; +import { performUpgradePrebuiltRules, getWebHookAction } from '../../../../../utils'; + +export function upgradeSinglePrebuiltRule({ getService }: FtrProviderContext): void { + const es = getService('es'); + const supertest = getService('supertest'); + const log = getService('log'); + const securitySolutionApi = getService('securitySolutionApi'); + const deps = { + es, + supertest, + log, + }; + + const RULE_TYPES = [ + 'query', + 'saved_query', + 'eql', + 'esql', + 'threat_match', + 'threshold', + 'machine_learning', + 'new_terms', + ] as const; + + describe('single rule', () => { + for (const withHistoricalVersions of [true, false]) { + describe( + withHistoricalVersions ? 'with historical versions' : 'without historical versions', + () => { + for (const ruleType of RULE_TYPES) { + it(`upgrades non-customized ${ruleType} rule`, async () => { + await setUpRuleUpgrade({ + assets: { + installed: { + type: ruleType, + name: 'Initial name', + version: 1, + }, + patch: {}, + upgrade: { + type: ruleType, + name: 'Updated name', + version: 2, + }, + }, + removeInstalledAssets: !withHistoricalVersions, + deps, + }); + + const response = await performUpgradePrebuiltRules(es, supertest, { + mode: ModeEnum.SPECIFIC_RULES, + rules: [ + { + rule_id: DEFAULT_TEST_RULE_ID, + revision: 0, + version: 2, + pick_version: 'TARGET', + }, + ], + }); + const upgradedRule = await securitySolutionApi.readRule({ + query: { rule_id: DEFAULT_TEST_RULE_ID }, + }); + + const expected = { + rule_id: DEFAULT_TEST_RULE_ID, + version: 2, + name: 'Updated name', + }; + + expect(response.results.updated).toMatchObject([expected]); + expect(upgradedRule.body).toMatchObject(expected); + }); + + it(`upgrades customized ${ruleType} rule`, async () => { + await setUpRuleUpgrade({ + assets: { + installed: { + type: ruleType, + name: 'Initial name', + version: 1, + }, + patch: { + name: 'Customized name', + }, + upgrade: { + type: ruleType, + name: 'Updated name', + version: 2, + }, + }, + removeInstalledAssets: !withHistoricalVersions, + deps, + }); + + const response = await performUpgradePrebuiltRules(es, supertest, { + mode: ModeEnum.SPECIFIC_RULES, + rules: [ + { + rule_id: DEFAULT_TEST_RULE_ID, + revision: 1, + version: 2, + pick_version: 'TARGET', + }, + ], + }); + const upgradedRule = await securitySolutionApi.readRule({ + query: { rule_id: DEFAULT_TEST_RULE_ID }, + }); + + const expected = { + rule_id: DEFAULT_TEST_RULE_ID, + version: 2, + name: 'Updated name', + }; + + expect(response.results.updated).toMatchObject([expected]); + expect(upgradedRule.body).toMatchObject(expected); + }); + } + + const RULE_TYPE_CHANGES = RULE_TYPES.flatMap((ruleTypeA) => + RULE_TYPES.map((ruleTypeB) => [ruleTypeA, ruleTypeB] as const) + ).filter(([ruleTypeA, ruleTypeB]) => ruleTypeA !== ruleTypeB); + + for (const [ruleTypeA, ruleTypeB] of RULE_TYPE_CHANGES) { + it(`upgrades non-customized ${ruleTypeA} rule to ${ruleTypeB} rule`, async () => { + await setUpRuleUpgrade({ + assets: { + installed: { + type: ruleTypeA, + name: 'Initial name', + version: 1, + }, + patch: {}, + upgrade: { + type: ruleTypeB, + name: 'Updated name', + version: 2, + }, + }, + removeInstalledAssets: !withHistoricalVersions, + deps, + }); + + const response = await performUpgradePrebuiltRules(es, supertest, { + mode: ModeEnum.SPECIFIC_RULES, + rules: [ + { + rule_id: DEFAULT_TEST_RULE_ID, + revision: 0, + version: 2, + pick_version: 'TARGET', + }, + ], + }); + const upgradedRule = await securitySolutionApi.readRule({ + query: { rule_id: DEFAULT_TEST_RULE_ID }, + }); + + const expected = { + rule_id: DEFAULT_TEST_RULE_ID, + version: 2, + type: ruleTypeB, + name: 'Updated name', + }; + + expect(response.results.updated).toMatchObject([expected]); + expect(upgradedRule.body).toMatchObject(expected); + }); + + it(`upgrades customized ${ruleTypeA} rule to ${ruleTypeB} rule type`, async () => { + await setUpRuleUpgrade({ + assets: { + installed: { + type: ruleTypeA, + name: 'Initial name', + version: 1, + }, + patch: { + name: 'Customized name', + }, + upgrade: { + type: ruleTypeB, + name: 'Updated name', + version: 2, + }, + }, + removeInstalledAssets: !withHistoricalVersions, + deps, + }); + + const response = await performUpgradePrebuiltRules(es, supertest, { + mode: ModeEnum.SPECIFIC_RULES, + rules: [ + { + rule_id: DEFAULT_TEST_RULE_ID, + revision: 1, + version: 2, + pick_version: 'TARGET', + }, + ], + }); + const upgradedRule = await securitySolutionApi.readRule({ + query: { rule_id: DEFAULT_TEST_RULE_ID }, + }); + + const expected = { + rule_id: DEFAULT_TEST_RULE_ID, + version: 2, + type: ruleTypeB, + name: 'Updated name', + }; + + expect(response.results.updated).toMatchObject([expected]); + expect(upgradedRule.body).toMatchObject(expected); + }); + } + + for (const pickVersion of ['BASE', 'CURRENT', 'MERGED'] as const) { + it(`UNABLE to upgrade rule when rule type changed and is ${pickVersion}`, async () => { + await setUpRuleUpgrade({ + assets: { + installed: { + type: 'query', + name: 'Initial name', + version: 1, + }, + patch: { + name: 'Customized name', + }, + upgrade: { + type: 'saved_query', + name: 'Updated name', + version: 2, + }, + }, + removeInstalledAssets: !withHistoricalVersions, + deps, + }); + + const response = await performUpgradePrebuiltRules(es, supertest, { + mode: ModeEnum.SPECIFIC_RULES, + rules: [ + { + rule_id: DEFAULT_TEST_RULE_ID, + revision: 1, + version: 2, + pick_version: pickVersion, + }, + ], + }); + + expect(response.summary).toMatchObject({ + total: 1, + succeeded: 0, + skipped: 0, + failed: 1, + }); + expect(response.errors).toHaveLength(1); + }); + } + + for (const ruleType of RULE_TYPES) { + it(`UNABLE to upgrade non-upgradable fields for ${ruleType} rule`, async () => { + const NON_UPGRADABLE_FIELDS = { + enabled: true, + exceptions_list: [ + { + id: 'test-list', + list_id: 'test-list', + type: 'detection', + namespace_type: 'single', + } as const, + ], + actions: [await createAction(supertest)], + response_actions: [ + { + params: { + command: 'isolate' as const, + comment: 'comment', + }, + action_type_id: '.endpoint' as const, + }, + ], + meta: { some_key: 'some_value' }, + output_index: '.siem-signals-default', + namespace: 'default', + ...(ruleType === 'threat_match' + ? { concurrent_searches: 5, items_per_search: 100 } + : {}), + }; + + await setUpRuleUpgrade({ + assets: { + installed: { + version: 1, + type: ruleType, + }, + patch: { + type: ruleType, + ...NON_UPGRADABLE_FIELDS, + // Patch for Threshold rules fails without threshold specified + ...(ruleType === 'threshold' + ? { threshold: { value: 10, field: 'fieldA' } } + : {}), + }, + upgrade: { + version: 2, + type: ruleType, + }, + }, + removeInstalledAssets: !withHistoricalVersions, + deps, + }); + + const response = await performUpgradePrebuiltRules(es, supertest, { + mode: ModeEnum.ALL_RULES, + pick_version: 'TARGET', + }); + const upgradedRule = await securitySolutionApi.readRule({ + query: { rule_id: DEFAULT_TEST_RULE_ID }, + }); + + expect(response.results.updated).toMatchObject([ + { + ...NON_UPGRADABLE_FIELDS, + version: 2, + }, + ]); + expect(upgradedRule.body).toMatchObject({ + ...NON_UPGRADABLE_FIELDS, + version: 2, + }); + }); + } + } + ); + } + }); +} + +async function createAction(supertest: SuperTest.Agent) { + const createConnector = async (payload: Record) => + ( + await supertest + .post('/api/actions/connector') + .set('kbn-xsrf', 'true') + .send(payload) + .expect(200) + ).body; + + const createWebHookConnector = () => createConnector(getWebHookAction()); + + const webHookAction = await createWebHookConnector(); + + const defaultRuleAction = { + id: webHookAction.id, + action_type_id: '.webhook' as const, + group: 'default' as const, + params: { + body: '{"test":"a default action"}', + }, + frequency: { + notifyWhen: 'onThrottleInterval' as const, + summary: true, + throttle: '1h' as const, + }, + uuid: 'd487ec3d-05f2-44ad-8a68-11c97dc92202', + }; + + return defaultRuleAction; +} diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/patch_rule.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/patch_rule.ts index 44456c93a16cd..18ef05a4090f7 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/patch_rule.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/patch_rule.ts @@ -34,7 +34,7 @@ export const patchRule = async ( log.error( `Did not get an expected 200 "ok" when patching a rule (patchRule). CI issues could happen. Suspect this line if you are seeing CI issues. body: ${JSON.stringify( response.body - )}, status: ${JSON.stringify(response.status)}` + )}, status: ${JSON.stringify(response.status)}, body: ${JSON.stringify(response.body)}` ); } return response.body; diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/prebuilt_rules/create_prebuilt_rule_saved_objects.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/prebuilt_rules/create_prebuilt_rule_saved_objects.ts index 3ebd928123cc4..8780bf2b49353 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/prebuilt_rules/create_prebuilt_rule_saved_objects.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/prebuilt_rules/create_prebuilt_rule_saved_objects.ts @@ -42,9 +42,10 @@ export const createRuleAssetSavedObject = (overrideParams: Partial( - type: T['type'] + type: T['type'], + rewrites?: Partial ) => ({ - 'security-rule': getPrebuiltRuleMockOfType(type), + 'security-rule': { ...getPrebuiltRuleMockOfType(type), ...rewrites }, ...ruleAssetSavedObjectESFields, }); @@ -114,7 +115,7 @@ export const createHistoricalPrebuiltRuleAssetSavedObjects = async ( es: Client, rules = SAMPLE_PREBUILT_RULES_WITH_HISTORICAL_VERSIONS ): Promise => { - await es.bulk({ + const response = await es.bulk({ refresh: true, body: rules.flatMap((doc) => [ { @@ -126,4 +127,10 @@ export const createHistoricalPrebuiltRuleAssetSavedObjects = async ( doc, ]), }); + + if (response.errors) { + throw new Error( + `Unable to bulk create rule assets. Response items: ${JSON.stringify(response.items)}` + ); + } }; diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/prebuilt_rules/review_upgrade_prebuilt_rules.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/prebuilt_rules/review_upgrade_prebuilt_rules.ts index 17347ffcdd1e3..860d9951457a8 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/prebuilt_rules/review_upgrade_prebuilt_rules.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/prebuilt_rules/review_upgrade_prebuilt_rules.ts @@ -5,6 +5,7 @@ * 2.0. */ +import type { PartialRuleDiff } from '@kbn/security-solution-plugin/common/api/detection_engine'; import { REVIEW_RULE_UPGRADE_URL } from '@kbn/security-solution-plugin/common/api/detection_engine/prebuilt_rules/urls'; import { ReviewRuleUpgradeResponseBody } from '@kbn/security-solution-plugin/common/api/detection_engine/prebuilt_rules/review_rule_upgrade/review_rule_upgrade_route'; import type SuperTest from 'supertest'; @@ -28,3 +29,11 @@ export const reviewPrebuiltRulesToUpgrade = async ( return response.body; }; + +export async function fetchFirstPrebuiltRuleUpgradeReviewDiff( + supertest: SuperTest.Agent +): Promise { + const response = await reviewPrebuiltRulesToUpgrade(supertest); + + return response.rules[0].diff; +} diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/prebuilt_rules/set_up_rule_upgrade.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/prebuilt_rules/set_up_rule_upgrade.ts new file mode 100644 index 0000000000000..78a11f0ed7180 --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/prebuilt_rules/set_up_rule_upgrade.ts @@ -0,0 +1,86 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { ToolingLog } from '@kbn/tooling-log'; +import { RuleResponse } from '@kbn/security-solution-plugin/common/api/detection_engine'; +import { PrebuiltRuleAsset } from '@kbn/security-solution-plugin/server/lib/detection_engine/prebuilt_rules'; +import type { Client } from '@elastic/elasticsearch'; +import type SuperTest from 'supertest'; +import { + createHistoricalPrebuiltRuleAssetSavedObjects, + createRuleAssetSavedObjectOfType, +} from './create_prebuilt_rule_saved_objects'; +import { patchRule } from '../patch_rule'; +import { installPrebuiltRules } from './install_prebuilt_rules'; +import { deleteAllPrebuiltRuleAssets } from './delete_all_prebuilt_rule_assets'; + +interface SetUpRuleUpgradeDeps { + supertest: SuperTest.Agent; + log: ToolingLog; + es: Client; +} + +type PartialPrebuiltRuleAsset = Pick & Partial; + +export interface RuleUpgradeAssets { + installed: PartialPrebuiltRuleAsset; + patch: Partial; + upgrade: PartialPrebuiltRuleAsset; +} + +interface SetUpRuleUpgradeParams { + assets: RuleUpgradeAssets | RuleUpgradeAssets[]; + removeInstalledAssets?: boolean; + deps: SetUpRuleUpgradeDeps; +} + +export const DEFAULT_TEST_RULE_ID = 'test-rule'; +export const DEFAULT_INSTALLED_RULE_VERSION = 1; +export const DEFAULT_RULE_UPDATE_VERSION = 2; + +export async function setUpRuleUpgrade({ + assets, + removeInstalledAssets, + deps, +}: SetUpRuleUpgradeParams): Promise { + const rulesAssets = [assets].flat(); + + for (const ruleAssets of rulesAssets) { + await createHistoricalPrebuiltRuleAssetSavedObjects(deps.es, [ + createRuleAssetSavedObjectOfType(ruleAssets.installed.type, { + rule_id: DEFAULT_TEST_RULE_ID, + version: DEFAULT_INSTALLED_RULE_VERSION, + ...ruleAssets.installed, + }), + ]); + } + + await installPrebuiltRules(deps.es, deps.supertest); + + for (const ruleAssets of rulesAssets) { + if (Object.keys(ruleAssets.patch).length > 0) { + await patchRule(deps.supertest, deps.log, { + rule_id: DEFAULT_TEST_RULE_ID, + ...ruleAssets.patch, + }); + } + } + + if (removeInstalledAssets) { + await deleteAllPrebuiltRuleAssets(deps.es, deps.log); + } + + for (const ruleAssets of rulesAssets) { + await createHistoricalPrebuiltRuleAssetSavedObjects(deps.es, [ + createRuleAssetSavedObjectOfType(ruleAssets.upgrade.type, { + rule_id: DEFAULT_TEST_RULE_ID, + version: DEFAULT_RULE_UPDATE_VERSION, + ...ruleAssets.upgrade, + }), + ]); + } +}