-
Notifications
You must be signed in to change notification settings - Fork 8.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Security Solution] Add InvestigationFields and AlertSuppression fields to the upgrade workflow #190597
Closed
Tracked by
#174168
Labels
8.16 candidate
Feature:Prebuilt Detection Rules
Security Solution Prebuilt Detection Rules area
Team:Detection Rule Management
Security Detection Rule Management Team
Team:Detections and Resp
Security Detection Response Team
Team: SecuritySolution
Security Solutions Team working on SIEM, Endpoint, Timeline, Resolver, etc.
Comments
Pinging @elastic/security-detections-response (Team:Detections and Resp) |
Pinging @elastic/security-solution (Team: SecuritySolution) |
Pinging @elastic/security-detection-rule-management (Team:Detection Rule Management) |
This was referenced Aug 15, 2024
1 task
jpdjere
added a commit
that referenced
this issue
Sep 12, 2024
…0128) ## Summary - Partially addresses #166376 (see step 1 of [plan](#166376 (comment))) - Partially addresses: #190597 - Creates a Map of the fields that are upgradable during the Upgrade workflow, by type. - Creating this Map dynamically, based of BaseCreateProps and TypeSpecificFields, ensures that we don't need to: - manually add rule types to this Map if they are created - manually add or remove any fields if they are added or removed to a specific rule type - manually add or remove any fields if we decide that they should not be part of the upgradable fields. - This Map will be used as part of the `/upgrade/_perform` endpoint handler logic to build the payload of fields that will be upgraded to their different versions (`BASE`, `CURRENT`, `TARGET`, `MERGED`,`RESOLVED`) - Creates `RuleFieldsToUpgrade` Zod schema and `FieldUpgradeSpecifier` type, part of the `/upgrade/_perform` payload, which defines which fields can be upgraded and how. <br> <details> <summary>See output: <b>UPGRADABLE_RULES_FIELDS_BY_TYPE_MAP</b></summary> ```ts new Map([ [ "eql", [ "name", "description", "risk_score", "severity", "rule_name_override", "timestamp_override", "timestamp_override_fallback_disabled", "timeline_id", "timeline_title", "license", "note", "building_block_type", "investigation_fields", "version", "tags", "enabled", "risk_score_mapping", "severity_mapping", "interval", "from", "to", "exceptions_list", "author", "false_positives", "references", "max_signals", "threat", "setup", "related_integrations", "required_fields", "type", "query", "language", "index", "data_view_id", "filters", "event_category_override", "tiebreaker_field", "timestamp_field", "alert_suppression" ] ], [ "query", [ "name", "description", "risk_score", "severity", "rule_name_override", "timestamp_override", "timestamp_override_fallback_disabled", "timeline_id", "timeline_title", "license", "note", "building_block_type", "investigation_fields", "version", "tags", "enabled", "risk_score_mapping", "severity_mapping", "interval", "from", "to", "exceptions_list", "author", "false_positives", "references", "max_signals", "threat", "setup", "related_integrations", "required_fields", "type", "index", "data_view_id", "filters", "saved_id", "alert_suppression", "query", "language" ] ], [ "saved_query", [ "name", "description", "risk_score", "severity", "rule_name_override", "timestamp_override", "timestamp_override_fallback_disabled", "timeline_id", "timeline_title", "license", "note", "building_block_type", "investigation_fields", "version", "tags", "enabled", "risk_score_mapping", "severity_mapping", "interval", "from", "to", "exceptions_list", "author", "false_positives", "references", "max_signals", "threat", "setup", "related_integrations", "required_fields", "type", "saved_id", "index", "data_view_id", "filters", "alert_suppression", "query", "language" ] ], [ "threshold", [ "name", "description", "risk_score", "severity", "rule_name_override", "timestamp_override", "timestamp_override_fallback_disabled", "timeline_id", "timeline_title", "license", "note", "building_block_type", "investigation_fields", "version", "tags", "enabled", "risk_score_mapping", "severity_mapping", "interval", "from", "to", "exceptions_list", "author", "false_positives", "references", "max_signals", "threat", "setup", "related_integrations", "required_fields", "type", "query", "threshold", "index", "data_view_id", "filters", "saved_id", "alert_suppression", "language" ] ], [ "threat_match", [ "name", "description", "risk_score", "severity", "rule_name_override", "timestamp_override", "timestamp_override_fallback_disabled", "timeline_id", "timeline_title", "license", "note", "building_block_type", "investigation_fields", "version", "tags", "enabled", "risk_score_mapping", "severity_mapping", "interval", "from", "to", "exceptions_list", "author", "false_positives", "references", "max_signals", "threat", "setup", "related_integrations", "required_fields", "type", "query", "threat_query", "threat_mapping", "threat_index", "index", "data_view_id", "filters", "saved_id", "threat_filters", "threat_indicator_path", "threat_language", "concurrent_searches", "items_per_search", "alert_suppression", "language" ] ], [ "machine_learning", [ "name", "description", "risk_score", "severity", "rule_name_override", "timestamp_override", "timestamp_override_fallback_disabled", "timeline_id", "timeline_title", "license", "note", "building_block_type", "investigation_fields", "version", "tags", "enabled", "risk_score_mapping", "severity_mapping", "interval", "from", "to", "exceptions_list", "author", "false_positives", "references", "max_signals", "threat", "setup", "related_integrations", "required_fields", "type", "anomaly_threshold", "machine_learning_job_id", "alert_suppression" ] ], [ "new_terms", [ "name", "description", "risk_score", "severity", "rule_name_override", "timestamp_override", "timestamp_override_fallback_disabled", "timeline_id", "timeline_title", "license", "note", "building_block_type", "investigation_fields", "version", "tags", "enabled", "risk_score_mapping", "severity_mapping", "interval", "from", "to", "exceptions_list", "author", "false_positives", "references", "max_signals", "threat", "setup", "related_integrations", "required_fields", "type", "query", "new_terms_fields", "history_window_start", "index", "data_view_id", "filters", "alert_suppression", "language" ] ], [ "esql", [ "name", "description", "risk_score", "severity", "rule_name_override", "timestamp_override", "timestamp_override_fallback_disabled", "timeline_id", "timeline_title", "license", "note", "building_block_type", "investigation_fields", "version", "tags", "enabled", "risk_score_mapping", "severity_mapping", "interval", "from", "to", "exceptions_list", "author", "false_positives", "references", "max_signals", "threat", "setup", "related_integrations", "required_fields", "alert_suppression", "type", "language", "query" ] ] ]) ``` </details> <br> ### For maintainers - [ ] This was checked for breaking API changes and was [labeled appropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process) --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
11 tasks
Merged
1 task
jpdjere
added a commit
that referenced
this issue
Oct 11, 2024
… to Rule Upgrade workflow (#195499) Resolves: #190597 ## Summary Adds `AlertSuppression` and `Investigation Fields` to Rule Upgrade workflow: - Fields had already been added to DiffableRule schema and diffing algorithms in #190128 - Current PR adds them to the UI field list so they get displayed in the diff ## Screenshots #### Investigation Fields  #### Alert Suppression  ## Testing Little bit tricky: no prebuilt rules have these fields, so no matter which packages you install you wont' see this upgrade. You'll need to tinker with the security-rule assets, for example: ```ts POST .kibana_security_solution/_update_by_query { "script": { "source": """ ctx._source['security-rule']['alert_suppression'] = [ 'group_by': ['agent.hostname'], 'missing_fields_strategy': 'suppress' ]; """, "lang": "painless" }, "query": { "bool": { "must": [ { "term": { "type": { "value": "security-rule" } } }, { "term": { "security-rule.rule_id": { "value": "0564fb9d-90b9-4234-a411-82a546dc1343" } } }, { "term": { "security-rule.version": { "value": "111" } } } ] } } } ``` ### For maintainers - [ ] This was checked for breaking API changes and was [labeled appropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)
kibanamachine
pushed a commit
to kibanamachine/kibana
that referenced
this issue
Oct 11, 2024
… to Rule Upgrade workflow (elastic#195499) Resolves: elastic#190597 ## Summary Adds `AlertSuppression` and `Investigation Fields` to Rule Upgrade workflow: - Fields had already been added to DiffableRule schema and diffing algorithms in elastic#190128 - Current PR adds them to the UI field list so they get displayed in the diff ## Screenshots #### Investigation Fields  #### Alert Suppression  ## Testing Little bit tricky: no prebuilt rules have these fields, so no matter which packages you install you wont' see this upgrade. You'll need to tinker with the security-rule assets, for example: ```ts POST .kibana_security_solution/_update_by_query { "script": { "source": """ ctx._source['security-rule']['alert_suppression'] = [ 'group_by': ['agent.hostname'], 'missing_fields_strategy': 'suppress' ]; """, "lang": "painless" }, "query": { "bool": { "must": [ { "term": { "type": { "value": "security-rule" } } }, { "term": { "security-rule.rule_id": { "value": "0564fb9d-90b9-4234-a411-82a546dc1343" } } }, { "term": { "security-rule.version": { "value": "111" } } } ] } } } ``` ### For maintainers - [ ] This was checked for breaking API changes and was [labeled appropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process) (cherry picked from commit ed144bd)
jpdjere
added a commit
that referenced
this issue
Oct 16, 2024
Fixes: #166376 (main ticket) Fixes: #186544 (handling of specific fields) Fixes: #180195 (replace PATCH with PUT logic on rule upgrade) ## Summary - Enhances the `/upgrade/_perform` endpoint to upgrade rules in a way that works with prebuilt rules customized by users and resolve conflicts between user customizations and updates from Elastic. - Handles special fields under the hood (see below) - Replaces the update prebuilt rule logic to work with PUT instead of PATCH. ### Rough implementation plan - For each `upgradeableRule`, we attempt to build the payload necessary to pass to `upgradePrebuiltRules()`, which is of type `PrebuiltRuleAsset`. So we retrieve the field names from `FIELDS_PAYLOAD_BY_RULE_TYPE` and loop through them. - If any of those `field`s are non-upgreadable, (i.e. its value needs to be handled under the hood) we do so in `determineFieldUpgradeStatus`. - Otherwise, we continue to build a `FieldUpgradeSpecifier` for each field, which will help us determine if that field needs to be set to the base, current, target version, OR if it needs to be calculated as a MERGED value, or it is passed in the request payload as a RESOLVED value. - Notice that we are iterating over "flat" (non-grouped) fields which are part of the `PrebuiltRuleAsset` schema. This means that mapping is necessary between these flat fields and the diffable (grouped) fields that are used in the API contract, part of `DiffableRule`. For example, if we try to determine the value for the `query` field, we will need to look up for its value in the `eql_query` field if the target rule is `eql` or in `esql_query` if the target rule is `esql`. All these mappings can be found in `diffable_rule_fields_mappings.ts`. - Once a `FieldUpgradeSpecifier` has been retrieved for each field of the payload we are building, retrieve its actual value: either fetching it from the base, current or target versions of the rule, from the three way diff calculation, or retrieving it from the request payload if it resolved. - Do this for all upgreadable rules, and the pass the payload array into `upgradePrebuiltRules()`. - **IMPORTANT:** The upgrade prebuilt rules logic has been changed from PATCH to PUT. That means that if the next version of a rule removes a field, and the user updates to that target version, those fields will be undefined in the resulting rule. **Additional example:** a installs a rule, and creates a `timeline_id` for it rule by modifying it. If neither the next version (target version) still does not have a `timeline_id` field for it, and the user updates to that target version fully (without resolving the conflict), that field will not exist anymore in the resulting rule. ## Acceptance criteria - [x] Extend the contract of the API endpoint according to the [POC](#144060): - [x] Add the ability to pick the `MERGED` version for rule upgrades. If the `MERGED` version is selected, the diffs are recalculated and the rule fields are updated to the result of the diff calculation. This is only possible if all field diffs return a `conflict` value of either `NO`. If any fields returns a value of `NON_SOLVABLE` or `SOLVABLE`, reject the request with an error specifying that there are conflicts, and that they must be resolved on a per-field basis. - [x] Calculate diffs inside this endpoint, when the value of `pick_version` is `MERGED`. - [x] Add the ability to specify rule field versions, to update specific fields to different `pick_versions`: `BASE' | 'CURRENT' | 'TARGET' | 'MERGED' | 'RESOLVED'` (See `FieldUpgradeRequest` in [PoC](#144060) for details) ## Handling of special fields Specific fields are handled under the hood based on #186544 See implementation in `x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_upgrade/determine_field_upgrade_status.ts`, which imports fields to handle under the hood: - `DiffableFieldsToOmit` - `FieldsToUpdateToCurrentVersion` ## Edge cases - [x] If target version of rule has a **rule type change**, check that all `pick_version`, at all levels, match `TARGET`. Otherwise, create new error and add to ruleErrors array. - [x] if a rule has a specific `targetVersion.type` (for example, EQL) and the user includes in its `fields` object of the request payload any fields which do not match that rule type (in this case, for example, sending in `machine_learning_job_id` as part of `fields`), throw an error for that rule. - [x] Calculation of field diffs: what happens if some fields have a conflict value of `NON_SOLVABLE`: - [x] If the whole rule is being updated to `MERGED`, and **ANY** fields return with a `NON_SOLVABLE` conflict, reject the whole update for that rule: create new error and add to ruleErrors array. - [x] **EXCEPTION** for case above: the whole rule is being updated to `MERGED`, and one or more of the fields return with a `NON_SOLVABLE` conflict, BUT those same fields have a specific `pick_version` for them in the `fields` object which **ARE NOT** `MERGED`. No error should be reported in this case. - [x] The whole rule is being updated to any `pick_version` other than MERGED, but any specific field in the `fields` object is set to upgrade to `MERGED`, and the diff for that fields returns a `NON_SOLVABLE` conflict. In that case, create new error and add to ruleErrors array. ### TODO - [[Security Solution] Add InvestigationFields and AlertSuppression fields to the upgrade workflow [#190597]](#190597): InvestigationFields is already working, but AlertSuppression is still currently handled under the hood to update to current version. ### For maintainers - [ ] This was checked for breaking API changes and was [labeled appropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process) --------- Co-authored-by: Maxim Palenov <maxim.palenov@elastic.co>
kibanamachine
pushed a commit
to kibanamachine/kibana
that referenced
this issue
Oct 16, 2024
…1439) Fixes: elastic#166376 (main ticket) Fixes: elastic#186544 (handling of specific fields) Fixes: elastic#180195 (replace PATCH with PUT logic on rule upgrade) ## Summary - Enhances the `/upgrade/_perform` endpoint to upgrade rules in a way that works with prebuilt rules customized by users and resolve conflicts between user customizations and updates from Elastic. - Handles special fields under the hood (see below) - Replaces the update prebuilt rule logic to work with PUT instead of PATCH. ### Rough implementation plan - For each `upgradeableRule`, we attempt to build the payload necessary to pass to `upgradePrebuiltRules()`, which is of type `PrebuiltRuleAsset`. So we retrieve the field names from `FIELDS_PAYLOAD_BY_RULE_TYPE` and loop through them. - If any of those `field`s are non-upgreadable, (i.e. its value needs to be handled under the hood) we do so in `determineFieldUpgradeStatus`. - Otherwise, we continue to build a `FieldUpgradeSpecifier` for each field, which will help us determine if that field needs to be set to the base, current, target version, OR if it needs to be calculated as a MERGED value, or it is passed in the request payload as a RESOLVED value. - Notice that we are iterating over "flat" (non-grouped) fields which are part of the `PrebuiltRuleAsset` schema. This means that mapping is necessary between these flat fields and the diffable (grouped) fields that are used in the API contract, part of `DiffableRule`. For example, if we try to determine the value for the `query` field, we will need to look up for its value in the `eql_query` field if the target rule is `eql` or in `esql_query` if the target rule is `esql`. All these mappings can be found in `diffable_rule_fields_mappings.ts`. - Once a `FieldUpgradeSpecifier` has been retrieved for each field of the payload we are building, retrieve its actual value: either fetching it from the base, current or target versions of the rule, from the three way diff calculation, or retrieving it from the request payload if it resolved. - Do this for all upgreadable rules, and the pass the payload array into `upgradePrebuiltRules()`. - **IMPORTANT:** The upgrade prebuilt rules logic has been changed from PATCH to PUT. That means that if the next version of a rule removes a field, and the user updates to that target version, those fields will be undefined in the resulting rule. **Additional example:** a installs a rule, and creates a `timeline_id` for it rule by modifying it. If neither the next version (target version) still does not have a `timeline_id` field for it, and the user updates to that target version fully (without resolving the conflict), that field will not exist anymore in the resulting rule. ## Acceptance criteria - [x] Extend the contract of the API endpoint according to the [POC](elastic#144060): - [x] Add the ability to pick the `MERGED` version for rule upgrades. If the `MERGED` version is selected, the diffs are recalculated and the rule fields are updated to the result of the diff calculation. This is only possible if all field diffs return a `conflict` value of either `NO`. If any fields returns a value of `NON_SOLVABLE` or `SOLVABLE`, reject the request with an error specifying that there are conflicts, and that they must be resolved on a per-field basis. - [x] Calculate diffs inside this endpoint, when the value of `pick_version` is `MERGED`. - [x] Add the ability to specify rule field versions, to update specific fields to different `pick_versions`: `BASE' | 'CURRENT' | 'TARGET' | 'MERGED' | 'RESOLVED'` (See `FieldUpgradeRequest` in [PoC](elastic#144060) for details) ## Handling of special fields Specific fields are handled under the hood based on elastic#186544 See implementation in `x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_upgrade/determine_field_upgrade_status.ts`, which imports fields to handle under the hood: - `DiffableFieldsToOmit` - `FieldsToUpdateToCurrentVersion` ## Edge cases - [x] If target version of rule has a **rule type change**, check that all `pick_version`, at all levels, match `TARGET`. Otherwise, create new error and add to ruleErrors array. - [x] if a rule has a specific `targetVersion.type` (for example, EQL) and the user includes in its `fields` object of the request payload any fields which do not match that rule type (in this case, for example, sending in `machine_learning_job_id` as part of `fields`), throw an error for that rule. - [x] Calculation of field diffs: what happens if some fields have a conflict value of `NON_SOLVABLE`: - [x] If the whole rule is being updated to `MERGED`, and **ANY** fields return with a `NON_SOLVABLE` conflict, reject the whole update for that rule: create new error and add to ruleErrors array. - [x] **EXCEPTION** for case above: the whole rule is being updated to `MERGED`, and one or more of the fields return with a `NON_SOLVABLE` conflict, BUT those same fields have a specific `pick_version` for them in the `fields` object which **ARE NOT** `MERGED`. No error should be reported in this case. - [x] The whole rule is being updated to any `pick_version` other than MERGED, but any specific field in the `fields` object is set to upgrade to `MERGED`, and the diff for that fields returns a `NON_SOLVABLE` conflict. In that case, create new error and add to ruleErrors array. ### TODO - [[Security Solution] Add InvestigationFields and AlertSuppression fields to the upgrade workflow [elastic#190597]](elastic#190597): InvestigationFields is already working, but AlertSuppression is still currently handled under the hood to update to current version. ### For maintainers - [ ] This was checked for breaking API changes and was [labeled appropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process) --------- Co-authored-by: Maxim Palenov <maxim.palenov@elastic.co> (cherry picked from commit 7c38873)
kibanamachine
added a commit
that referenced
this issue
Oct 16, 2024
) (#196471) # Backport This will backport the following commits from `main` to `8.x`: - [[Security Solution] Extend upgrade perform endpoint logic (#191439)](#191439) <!--- Backport version: 9.4.3 --> ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sqren/backport) <!--BACKPORT [{"author":{"name":"Juan Pablo Djeredjian","email":"jpdjeredjian@gmail.com"},"sourceCommit":{"committedDate":"2024-10-16T01:51:25Z","message":"[Security Solution] Extend upgrade perform endpoint logic (#191439)\n\nFixes: #166376 (main ticket)\r\nFixes: #186544 (handling of\r\nspecific fields)\r\nFixes: #180195 (replace PATCH\r\nwith PUT logic on rule upgrade)\r\n\r\n## Summary\r\n\r\n- Enhances the `/upgrade/_perform` endpoint to upgrade rules in a way\r\nthat works with prebuilt rules customized by users and resolve conflicts\r\nbetween user customizations and updates from Elastic.\r\n- Handles special fields under the hood (see below)\r\n- Replaces the update prebuilt rule logic to work with PUT instead of\r\nPATCH.\r\n\r\n### Rough implementation plan\r\n- For each `upgradeableRule`, we attempt to build the payload necessary\r\nto pass to `upgradePrebuiltRules()`, which is of type\r\n`PrebuiltRuleAsset`. So we retrieve the field names from\r\n`FIELDS_PAYLOAD_BY_RULE_TYPE` and loop through them.\r\n- If any of those `field`s are non-upgreadable, (i.e. its value needs to\r\nbe handled under the hood) we do so in `determineFieldUpgradeStatus`.\r\n- Otherwise, we continue to build a `FieldUpgradeSpecifier` for each\r\nfield, which will help us determine if that field needs to be set to the\r\nbase, current, target version, OR if it needs to be calculated as a\r\nMERGED value, or it is passed in the request payload as a RESOLVED\r\nvalue.\r\n- Notice that we are iterating over \"flat\" (non-grouped) fields which\r\nare part of the `PrebuiltRuleAsset` schema. This means that mapping is\r\nnecessary between these flat fields and the diffable (grouped) fields\r\nthat are used in the API contract, part of `DiffableRule`. For example,\r\nif we try to determine the value for the `query` field, we will need to\r\nlook up for its value in the `eql_query` field if the target rule is\r\n`eql` or in `esql_query` if the target rule is `esql`. All these\r\nmappings can be found in `diffable_rule_fields_mappings.ts`.\r\n- Once a `FieldUpgradeSpecifier` has been retrieved for each field of\r\nthe payload we are building, retrieve its actual value: either fetching\r\nit from the base, current or target versions of the rule, from the three\r\nway diff calculation, or retrieving it from the request payload if it\r\nresolved.\r\n- Do this for all upgreadable rules, and the pass the payload array into\r\n`upgradePrebuiltRules()`.\r\n- **IMPORTANT:** The upgrade prebuilt rules logic has been changed from\r\nPATCH to PUT. That means that if the next version of a rule removes a\r\nfield, and the user updates to that target version, those fields will be\r\nundefined in the resulting rule. **Additional example:** a installs a\r\nrule, and creates a `timeline_id` for it rule by modifying it. If\r\nneither the next version (target version) still does not have a\r\n`timeline_id` field for it, and the user updates to that target version\r\nfully (without resolving the conflict), that field will not exist\r\nanymore in the resulting rule.\r\n\r\n## Acceptance criteria\r\n\r\n- [x] Extend the contract of the API endpoint according to the\r\n[POC](https://github.com/elastic/kibana/pull/144060):\r\n- [x] Add the ability to pick the `MERGED` version for rule upgrades. If\r\nthe `MERGED` version is selected, the diffs are recalculated and the\r\nrule fields are updated to the result of the diff calculation. This is\r\nonly possible if all field diffs return a `conflict` value of either\r\n`NO`. If any fields returns a value of `NON_SOLVABLE` or `SOLVABLE`,\r\nreject the request with an error specifying that there are conflicts,\r\nand that they must be resolved on a per-field basis.\r\n- [x] Calculate diffs inside this endpoint, when the value of\r\n`pick_version` is `MERGED`.\r\n- [x] Add the ability to specify rule field versions, to update specific\r\nfields to different `pick_versions`: `BASE' | 'CURRENT' | 'TARGET' |\r\n'MERGED' | 'RESOLVED'` (See `FieldUpgradeRequest` in\r\n[PoC](#144060) for details)\r\n\r\n## Handling of special fields\r\n\r\nSpecific fields are handled under the hood based on\r\nhttps://github.com//issues/186544\r\n\r\nSee implementation in\r\n`x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_upgrade/determine_field_upgrade_status.ts`,\r\nwhich imports fields to handle under the hood:\r\n- `DiffableFieldsToOmit`\r\n- `FieldsToUpdateToCurrentVersion`\r\n\r\n## Edge cases\r\n\r\n- [x] If target version of rule has a **rule type change**, check that\r\nall `pick_version`, at all levels, match `TARGET`. Otherwise, create new\r\nerror and add to ruleErrors array.\r\n- [x] if a rule has a specific `targetVersion.type` (for example, EQL)\r\nand the user includes in its `fields` object of the request payload any\r\nfields which do not match that rule type (in this case, for example,\r\nsending in `machine_learning_job_id` as part of `fields`), throw an\r\nerror for that rule.\r\n- [x] Calculation of field diffs: what happens if some fields have a\r\nconflict value of `NON_SOLVABLE`:\r\n- [x] If the whole rule is being updated to `MERGED`, and **ANY** fields\r\nreturn with a `NON_SOLVABLE` conflict, reject the whole update for that\r\nrule: create new error and add to ruleErrors array.\r\n- [x] **EXCEPTION** for case above: the whole rule is being updated to\r\n`MERGED`, and one or more of the fields return with a `NON_SOLVABLE`\r\nconflict, BUT those same fields have a specific `pick_version` for them\r\nin the `fields` object which **ARE NOT** `MERGED`. No error should be\r\nreported in this case.\r\n- [x] The whole rule is being updated to any `pick_version` other than\r\nMERGED, but any specific field in the `fields` object is set to upgrade\r\nto `MERGED`, and the diff for that fields returns a `NON_SOLVABLE`\r\nconflict. In that case, create new error and add to ruleErrors array.\r\n\r\n### TODO\r\n\r\n- [[Security Solution] Add InvestigationFields and AlertSuppression\r\nfields to the upgrade workflow\r\n[#190597]](https://github.com/elastic/kibana/issues/190597):\r\nInvestigationFields is already working, but AlertSuppression is still\r\ncurrently handled under the hood to update to current version.\r\n\r\n\r\n### For maintainers\r\n\r\n- [ ] This was checked for breaking API changes and was [labeled\r\nappropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)\r\n\r\n---------\r\n\r\nCo-authored-by: Maxim Palenov <maxim.palenov@elastic.co>","sha":"7c3887309cec54cc21e1abf8a2522afa49147712","branchLabelMapping":{"^v9.0.0$":"main","^v8.16.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:enhancement","Team:Fleet","v9.0.0","Team:Detections and Resp","Team: SecuritySolution","Team:Detection Rule Management","Feature:Prebuilt Detection Rules","backport:prev-minor","v8.16.0"],"title":"[Security Solution] Extend upgrade perform endpoint logic","number":191439,"url":"https://github.com/elastic/kibana/pull/191439","mergeCommit":{"message":"[Security Solution] Extend upgrade perform endpoint logic (#191439)\n\nFixes: #166376 (main ticket)\r\nFixes: #186544 (handling of\r\nspecific fields)\r\nFixes: #180195 (replace PATCH\r\nwith PUT logic on rule upgrade)\r\n\r\n## Summary\r\n\r\n- Enhances the `/upgrade/_perform` endpoint to upgrade rules in a way\r\nthat works with prebuilt rules customized by users and resolve conflicts\r\nbetween user customizations and updates from Elastic.\r\n- Handles special fields under the hood (see below)\r\n- Replaces the update prebuilt rule logic to work with PUT instead of\r\nPATCH.\r\n\r\n### Rough implementation plan\r\n- For each `upgradeableRule`, we attempt to build the payload necessary\r\nto pass to `upgradePrebuiltRules()`, which is of type\r\n`PrebuiltRuleAsset`. So we retrieve the field names from\r\n`FIELDS_PAYLOAD_BY_RULE_TYPE` and loop through them.\r\n- If any of those `field`s are non-upgreadable, (i.e. its value needs to\r\nbe handled under the hood) we do so in `determineFieldUpgradeStatus`.\r\n- Otherwise, we continue to build a `FieldUpgradeSpecifier` for each\r\nfield, which will help us determine if that field needs to be set to the\r\nbase, current, target version, OR if it needs to be calculated as a\r\nMERGED value, or it is passed in the request payload as a RESOLVED\r\nvalue.\r\n- Notice that we are iterating over \"flat\" (non-grouped) fields which\r\nare part of the `PrebuiltRuleAsset` schema. This means that mapping is\r\nnecessary between these flat fields and the diffable (grouped) fields\r\nthat are used in the API contract, part of `DiffableRule`. For example,\r\nif we try to determine the value for the `query` field, we will need to\r\nlook up for its value in the `eql_query` field if the target rule is\r\n`eql` or in `esql_query` if the target rule is `esql`. All these\r\nmappings can be found in `diffable_rule_fields_mappings.ts`.\r\n- Once a `FieldUpgradeSpecifier` has been retrieved for each field of\r\nthe payload we are building, retrieve its actual value: either fetching\r\nit from the base, current or target versions of the rule, from the three\r\nway diff calculation, or retrieving it from the request payload if it\r\nresolved.\r\n- Do this for all upgreadable rules, and the pass the payload array into\r\n`upgradePrebuiltRules()`.\r\n- **IMPORTANT:** The upgrade prebuilt rules logic has been changed from\r\nPATCH to PUT. That means that if the next version of a rule removes a\r\nfield, and the user updates to that target version, those fields will be\r\nundefined in the resulting rule. **Additional example:** a installs a\r\nrule, and creates a `timeline_id` for it rule by modifying it. If\r\nneither the next version (target version) still does not have a\r\n`timeline_id` field for it, and the user updates to that target version\r\nfully (without resolving the conflict), that field will not exist\r\nanymore in the resulting rule.\r\n\r\n## Acceptance criteria\r\n\r\n- [x] Extend the contract of the API endpoint according to the\r\n[POC](https://github.com/elastic/kibana/pull/144060):\r\n- [x] Add the ability to pick the `MERGED` version for rule upgrades. If\r\nthe `MERGED` version is selected, the diffs are recalculated and the\r\nrule fields are updated to the result of the diff calculation. This is\r\nonly possible if all field diffs return a `conflict` value of either\r\n`NO`. If any fields returns a value of `NON_SOLVABLE` or `SOLVABLE`,\r\nreject the request with an error specifying that there are conflicts,\r\nand that they must be resolved on a per-field basis.\r\n- [x] Calculate diffs inside this endpoint, when the value of\r\n`pick_version` is `MERGED`.\r\n- [x] Add the ability to specify rule field versions, to update specific\r\nfields to different `pick_versions`: `BASE' | 'CURRENT' | 'TARGET' |\r\n'MERGED' | 'RESOLVED'` (See `FieldUpgradeRequest` in\r\n[PoC](#144060) for details)\r\n\r\n## Handling of special fields\r\n\r\nSpecific fields are handled under the hood based on\r\nhttps://github.com//issues/186544\r\n\r\nSee implementation in\r\n`x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_upgrade/determine_field_upgrade_status.ts`,\r\nwhich imports fields to handle under the hood:\r\n- `DiffableFieldsToOmit`\r\n- `FieldsToUpdateToCurrentVersion`\r\n\r\n## Edge cases\r\n\r\n- [x] If target version of rule has a **rule type change**, check that\r\nall `pick_version`, at all levels, match `TARGET`. Otherwise, create new\r\nerror and add to ruleErrors array.\r\n- [x] if a rule has a specific `targetVersion.type` (for example, EQL)\r\nand the user includes in its `fields` object of the request payload any\r\nfields which do not match that rule type (in this case, for example,\r\nsending in `machine_learning_job_id` as part of `fields`), throw an\r\nerror for that rule.\r\n- [x] Calculation of field diffs: what happens if some fields have a\r\nconflict value of `NON_SOLVABLE`:\r\n- [x] If the whole rule is being updated to `MERGED`, and **ANY** fields\r\nreturn with a `NON_SOLVABLE` conflict, reject the whole update for that\r\nrule: create new error and add to ruleErrors array.\r\n- [x] **EXCEPTION** for case above: the whole rule is being updated to\r\n`MERGED`, and one or more of the fields return with a `NON_SOLVABLE`\r\nconflict, BUT those same fields have a specific `pick_version` for them\r\nin the `fields` object which **ARE NOT** `MERGED`. No error should be\r\nreported in this case.\r\n- [x] The whole rule is being updated to any `pick_version` other than\r\nMERGED, but any specific field in the `fields` object is set to upgrade\r\nto `MERGED`, and the diff for that fields returns a `NON_SOLVABLE`\r\nconflict. In that case, create new error and add to ruleErrors array.\r\n\r\n### TODO\r\n\r\n- [[Security Solution] Add InvestigationFields and AlertSuppression\r\nfields to the upgrade workflow\r\n[#190597]](https://github.com/elastic/kibana/issues/190597):\r\nInvestigationFields is already working, but AlertSuppression is still\r\ncurrently handled under the hood to update to current version.\r\n\r\n\r\n### For maintainers\r\n\r\n- [ ] This was checked for breaking API changes and was [labeled\r\nappropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)\r\n\r\n---------\r\n\r\nCo-authored-by: Maxim Palenov <maxim.palenov@elastic.co>","sha":"7c3887309cec54cc21e1abf8a2522afa49147712"}},"sourceBranch":"main","suggestedTargetBranches":["8.x"],"targetPullRequestStates":[{"branch":"main","label":"v9.0.0","branchLabelMappingKey":"^v9.0.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/191439","number":191439,"mergeCommit":{"message":"[Security Solution] Extend upgrade perform endpoint logic (#191439)\n\nFixes: #166376 (main ticket)\r\nFixes: #186544 (handling of\r\nspecific fields)\r\nFixes: #180195 (replace PATCH\r\nwith PUT logic on rule upgrade)\r\n\r\n## Summary\r\n\r\n- Enhances the `/upgrade/_perform` endpoint to upgrade rules in a way\r\nthat works with prebuilt rules customized by users and resolve conflicts\r\nbetween user customizations and updates from Elastic.\r\n- Handles special fields under the hood (see below)\r\n- Replaces the update prebuilt rule logic to work with PUT instead of\r\nPATCH.\r\n\r\n### Rough implementation plan\r\n- For each `upgradeableRule`, we attempt to build the payload necessary\r\nto pass to `upgradePrebuiltRules()`, which is of type\r\n`PrebuiltRuleAsset`. So we retrieve the field names from\r\n`FIELDS_PAYLOAD_BY_RULE_TYPE` and loop through them.\r\n- If any of those `field`s are non-upgreadable, (i.e. its value needs to\r\nbe handled under the hood) we do so in `determineFieldUpgradeStatus`.\r\n- Otherwise, we continue to build a `FieldUpgradeSpecifier` for each\r\nfield, which will help us determine if that field needs to be set to the\r\nbase, current, target version, OR if it needs to be calculated as a\r\nMERGED value, or it is passed in the request payload as a RESOLVED\r\nvalue.\r\n- Notice that we are iterating over \"flat\" (non-grouped) fields which\r\nare part of the `PrebuiltRuleAsset` schema. This means that mapping is\r\nnecessary between these flat fields and the diffable (grouped) fields\r\nthat are used in the API contract, part of `DiffableRule`. For example,\r\nif we try to determine the value for the `query` field, we will need to\r\nlook up for its value in the `eql_query` field if the target rule is\r\n`eql` or in `esql_query` if the target rule is `esql`. All these\r\nmappings can be found in `diffable_rule_fields_mappings.ts`.\r\n- Once a `FieldUpgradeSpecifier` has been retrieved for each field of\r\nthe payload we are building, retrieve its actual value: either fetching\r\nit from the base, current or target versions of the rule, from the three\r\nway diff calculation, or retrieving it from the request payload if it\r\nresolved.\r\n- Do this for all upgreadable rules, and the pass the payload array into\r\n`upgradePrebuiltRules()`.\r\n- **IMPORTANT:** The upgrade prebuilt rules logic has been changed from\r\nPATCH to PUT. That means that if the next version of a rule removes a\r\nfield, and the user updates to that target version, those fields will be\r\nundefined in the resulting rule. **Additional example:** a installs a\r\nrule, and creates a `timeline_id` for it rule by modifying it. If\r\nneither the next version (target version) still does not have a\r\n`timeline_id` field for it, and the user updates to that target version\r\nfully (without resolving the conflict), that field will not exist\r\nanymore in the resulting rule.\r\n\r\n## Acceptance criteria\r\n\r\n- [x] Extend the contract of the API endpoint according to the\r\n[POC](https://github.com/elastic/kibana/pull/144060):\r\n- [x] Add the ability to pick the `MERGED` version for rule upgrades. If\r\nthe `MERGED` version is selected, the diffs are recalculated and the\r\nrule fields are updated to the result of the diff calculation. This is\r\nonly possible if all field diffs return a `conflict` value of either\r\n`NO`. If any fields returns a value of `NON_SOLVABLE` or `SOLVABLE`,\r\nreject the request with an error specifying that there are conflicts,\r\nand that they must be resolved on a per-field basis.\r\n- [x] Calculate diffs inside this endpoint, when the value of\r\n`pick_version` is `MERGED`.\r\n- [x] Add the ability to specify rule field versions, to update specific\r\nfields to different `pick_versions`: `BASE' | 'CURRENT' | 'TARGET' |\r\n'MERGED' | 'RESOLVED'` (See `FieldUpgradeRequest` in\r\n[PoC](#144060) for details)\r\n\r\n## Handling of special fields\r\n\r\nSpecific fields are handled under the hood based on\r\nhttps://github.com//issues/186544\r\n\r\nSee implementation in\r\n`x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_upgrade/determine_field_upgrade_status.ts`,\r\nwhich imports fields to handle under the hood:\r\n- `DiffableFieldsToOmit`\r\n- `FieldsToUpdateToCurrentVersion`\r\n\r\n## Edge cases\r\n\r\n- [x] If target version of rule has a **rule type change**, check that\r\nall `pick_version`, at all levels, match `TARGET`. Otherwise, create new\r\nerror and add to ruleErrors array.\r\n- [x] if a rule has a specific `targetVersion.type` (for example, EQL)\r\nand the user includes in its `fields` object of the request payload any\r\nfields which do not match that rule type (in this case, for example,\r\nsending in `machine_learning_job_id` as part of `fields`), throw an\r\nerror for that rule.\r\n- [x] Calculation of field diffs: what happens if some fields have a\r\nconflict value of `NON_SOLVABLE`:\r\n- [x] If the whole rule is being updated to `MERGED`, and **ANY** fields\r\nreturn with a `NON_SOLVABLE` conflict, reject the whole update for that\r\nrule: create new error and add to ruleErrors array.\r\n- [x] **EXCEPTION** for case above: the whole rule is being updated to\r\n`MERGED`, and one or more of the fields return with a `NON_SOLVABLE`\r\nconflict, BUT those same fields have a specific `pick_version` for them\r\nin the `fields` object which **ARE NOT** `MERGED`. No error should be\r\nreported in this case.\r\n- [x] The whole rule is being updated to any `pick_version` other than\r\nMERGED, but any specific field in the `fields` object is set to upgrade\r\nto `MERGED`, and the diff for that fields returns a `NON_SOLVABLE`\r\nconflict. In that case, create new error and add to ruleErrors array.\r\n\r\n### TODO\r\n\r\n- [[Security Solution] Add InvestigationFields and AlertSuppression\r\nfields to the upgrade workflow\r\n[#190597]](https://github.com/elastic/kibana/issues/190597):\r\nInvestigationFields is already working, but AlertSuppression is still\r\ncurrently handled under the hood to update to current version.\r\n\r\n\r\n### For maintainers\r\n\r\n- [ ] This was checked for breaking API changes and was [labeled\r\nappropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)\r\n\r\n---------\r\n\r\nCo-authored-by: Maxim Palenov <maxim.palenov@elastic.co>","sha":"7c3887309cec54cc21e1abf8a2522afa49147712"}},{"branch":"8.x","label":"v8.16.0","branchLabelMappingKey":"^v8.16.0$","isSourceBranch":false,"state":"NOT_CREATED"}]}] BACKPORT--> Co-authored-by: Juan Pablo Djeredjian <jpdjeredjian@gmail.com>
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Labels
8.16 candidate
Feature:Prebuilt Detection Rules
Security Solution Prebuilt Detection Rules area
Team:Detection Rule Management
Security Detection Rule Management Team
Team:Detections and Resp
Security Detection Response Team
Team: SecuritySolution
Security Solutions Team working on SIEM, Endpoint, Timeline, Resolver, etc.
Epics: https://github.com/elastic/security-team/issues/1974 (internal), #174168
Summary
Two fields have been left out of the Prebuilt Rules upgrade workflows and should be added:
InvestigationFields
AlertSuppression
: is actually two different fields:AlertSuppression
for all rule types except ThresholdThresholdAlertSuppression
for Threshold rule typesTo completely add these fields to the Upgrade Workflow the following sections in the codebase need to be edited:
/upgrade/_review
endpoint/upgrade/_perform
endpoint/upgrade/_perform
endpoint request payload typesUI
The text was updated successfully, but these errors were encountered: