From 3f53da76d9c45407cf31a21e224449f561900b05 Mon Sep 17 00:00:00 2001 From: Maxim Palenov Date: Fri, 21 Feb 2025 12:11:44 +0100 Subject: [PATCH] [Security Solution] Extend rule upgrade integration tests for prebuilt rule customization feature (#209260) **Addresses:** https://github.com/elastic/kibana/issues/202078 **Partially implements test plan:** https://github.com/elastic/kibana/pull/205922 ## Summary This PR implements the Rule Upgrade test plan added in https://github.com/elastic/kibana/pull/205922 and https://github.com/elastic/kibana/pull/203331. ## Details Tests cover only enabled customization and organized in a following way - `diffable_rule_fields` folder contains per field tests. It focuses on `DiffableRule`* fields. Each field has rule preview and upgrade scenarios throughly covered. Assertion on stats are included in rule preview tests to make sure the maximum coverage with reasonable execution time. **Diffable rule fields` tests were moved to a separate execution group to avoid exceeding execution limits.** - `preview_prebuilt_rules_upgrade.ts` integration tests on `/internal/prebuilt_rules/upgrade/_review` endpoint. It uses only `name` and `tags` fields to minimize tests complexity. Basically it should be considered as smoke tests. - `upgrade_prebuilt_rules` integrations test on `/internal/prebuilt_rules/upgrade/_perform` endpoint. It uses only `name` and `tags` fields to minimize tests complexity. Basically it should be considered as smoke tests. This PR supersedes https://github.com/elastic/kibana/pull/205217 and https://github.com/elastic/kibana/pull/205339. * `DiffableRule` was added in the scope of prebuilt rules customization epic to serve rule upgrades preview and performing upgrades. It represents slightly reorganized rule fields to simplify prebuilt rule upgrade workflow handling. There are utility functions transforming between `RuleResponse` and `DiffableRule`. ## Flaky test runner Flaky test runs for 100 iterations were successful (https://github.com/elastic/kibana/pull/209260#issuecomment-2649027038 and https://github.com/elastic/kibana/pull/209260#issuecomment-2649627389). (cherry picked from commit 4909770664a97f97bc38adc91dc852b5b1e6abf7) # Conflicts: # 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 # 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 --- .../ftr_security_serverless_configs.yml | 2 + .buildkite/ftr_security_stateful_configs.yml | 2 + .../rule_assets/prebuilt_rule_asset.mock.ts | 2 +- .../trial_license_complete_tier/index.ts | 12 - .../upgrade_prebuilt_rules.ts | 279 ---- ...prebuilt_rules_with_historical_versions.ts | 158 -- ...eview_prebuilt_rules.data_source_fields.ts | 972 ------------- ..._review_prebuilt_rules.eql_query_fields.ts | 505 ------- ...review_prebuilt_rules.esql_query_fields.ts | 472 ------ ..._review_prebuilt_rules.kql_query_fields.ts | 1278 ----------------- ...prebuilt_rules.multi_line_string_fields.ts | 444 ------ ...ade_review_prebuilt_rules.number_fields.ts | 336 ----- ..._review_prebuilt_rules.rule_type_fields.ts | 362 ----- ...view_prebuilt_rules.scalar_array_fields.ts | 486 ------- ...rebuilt_rules.single_line_string_fields.ts | 375 ----- .../upgrade_review_prebuilt_rules.stats.ts | 131 -- .../common_fields/alert_suppression.ts | 321 +++++ .../common_fields/building_block.ts | 321 +++++ .../common_fields/configs/ess.config.ts | 34 + .../configs/serverless.config.ts | 21 + .../common_fields/data_source.ts | 684 +++++++++ .../common_fields/description.ts | 332 +++++ .../common_fields/false_positives.ts | 321 +++++ .../common_fields/index.ts | 71 + .../common_fields/investigation_fields.ts | 321 +++++ .../common_fields/max_signals.ts | 321 +++++ .../common_fields/name.ts | 321 +++++ .../common_fields/note.ts | 321 +++++ .../common_fields/references.ts | 321 +++++ .../common_fields/related_integrations.ts | 652 +++++++++ .../common_fields/required_fields.ts | 657 +++++++++ .../common_fields/risk_score.ts | 321 +++++ .../common_fields/risk_score_mapping.ts | 726 ++++++++++ .../common_fields/rule_name_override.ts | 321 +++++ .../common_fields/rule_schedule.ts | 454 ++++++ .../common_fields/setup.ts | 321 +++++ .../common_fields/severity.ts | 321 +++++ .../common_fields/severity_mapping.ts | 726 ++++++++++ .../common_fields/tags.ts | 321 +++++ .../common_fields/threat.ts | 836 +++++++++++ .../common_fields/timeline_template.ts | 361 +++++ .../common_fields/timestamp_override.ts | 321 +++++ .../diffable_rule_fields/test_helpers.ts | 546 +++++++ .../type_specific_fields/anomaly_threshold.ts | 326 +++++ .../configs/ess.config.ts | 34 + .../configs/serverless.config.ts | 21 + .../type_specific_fields/eql_query.ts | 469 ++++++ .../type_specific_fields/esql_query.ts | 402 ++++++ .../history_window_start.ts | 326 +++++ .../type_specific_fields/index.ts | 65 + .../kql_query.inline_query.ts | 708 +++++++++ .../kql_query.saved_query.ts | 390 +++++ .../machine_learning_job_id.ts | 326 +++++ .../type_specific_fields/new_terms_fields.ts | 326 +++++ .../type_specific_fields/threat_index.ts | 326 +++++ .../threat_indicator_path.ts | 326 +++++ .../type_specific_fields/threat_mapping.ts | 374 +++++ .../type_specific_fields/threat_query.ts | 468 ++++++ .../type_specific_fields/threshold.ts | 326 +++++ .../customization_enabled/index.ts | 4 +- .../preview_prebuilt_rules_upgrade.ts | 530 +++++++ ...e_perform_prebuilt_rules.all_rules_mode.ts | 528 ------- ...form_prebuilt_rules.specific_rules_mode.ts | 860 ----------- .../bulk_upgrade_all_prebuilt_rules.ts | 368 +++++ .../bulk_upgrade_selected_prebuilt_rules.ts | 503 +++++++ .../upgrade_prebuilt_rules/index.ts | 30 + .../upgrade_single_prebuilt_rule.ts | 383 +++++ .../utils/rules/patch_rule.ts | 2 +- .../create_prebuilt_rule_saved_objects.ts | 13 +- .../review_upgrade_prebuilt_rules.ts | 9 + .../prebuilt_rules/set_up_rule_upgrade.ts | 86 ++ 71 files changed, 17734 insertions(+), 7205 deletions(-) delete mode 100644 x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/management/trial_license_complete_tier/upgrade_prebuilt_rules.ts delete mode 100644 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 delete mode 100644 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 delete mode 100644 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 delete mode 100644 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 delete mode 100644 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 delete mode 100644 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 delete mode 100644 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 delete mode 100644 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 delete mode 100644 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 delete mode 100644 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 delete mode 100644 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 create mode 100644 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 create mode 100644 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 create mode 100644 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 create mode 100644 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 create mode 100644 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 create mode 100644 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 create mode 100644 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 create mode 100644 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 create mode 100644 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 create mode 100644 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 create mode 100644 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 create mode 100644 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 create mode 100644 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 create mode 100644 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 create mode 100644 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 create mode 100644 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 create mode 100644 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 create mode 100644 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 create mode 100644 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 create mode 100644 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 create mode 100644 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 create mode 100644 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 create mode 100644 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 create mode 100644 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 create mode 100644 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 create mode 100644 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 create mode 100644 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 create mode 100644 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 create mode 100644 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 create mode 100644 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 create mode 100644 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 create mode 100644 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 create mode 100644 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 create mode 100644 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 create mode 100644 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 create mode 100644 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 create mode 100644 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 create mode 100644 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 create mode 100644 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 create mode 100644 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 create mode 100644 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 create mode 100644 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 create mode 100644 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 create mode 100644 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 delete mode 100644 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 delete mode 100644 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 create mode 100644 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 create mode 100644 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 create mode 100644 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 create mode 100644 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 create mode 100644 x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/prebuilt_rules/set_up_rule_upgrade.ts diff --git a/.buildkite/ftr_security_serverless_configs.yml b/.buildkite/ftr_security_serverless_configs.yml index 63978b531dbaa..d07ef57c18040 100644 --- a/.buildkite/ftr_security_serverless_configs.yml +++ b/.buildkite/ftr_security_serverless_configs.yml @@ -71,6 +71,8 @@ disabled: - 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 9ff2753dec6a3..d35c9b81a0921 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 e24e517c93459..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,528 +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/action').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 8da3f96d41d6c..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,860 +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/action').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..75d145960f206 --- /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,383 @@ +/* + * 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/action').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, + }), + ]); + } +}