Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[8.x] [Security Solution] Allow importing of prebuilt rules via the A…
…PI (#190198) (#196613) # Backport This will backport the following commits from `main` to `8.x`: - [[Security Solution] Allow importing of prebuilt rules via the API (#190198)](#190198) <!--- Backport version: 9.4.3 --> ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sqren/backport) <!--BACKPORT [{"author":{"name":"Ryland Herrick","email":"[email protected]"},"sourceCommit":{"committedDate":"2024-10-16T21:19:05Z","message":"[Security Solution] Allow importing of prebuilt rules via the API (#190198)\n\n## Summary\r\n\r\nThis PR introduces the backend functionality necessary to import\r\nprebuilt rules via our existing import API. The\r\n[RFC](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/docs/rfcs/detection_response/prebuilt_rules_customization.md)\r\ngoes into detail, and the import-specific issue is described\r\n[here](#180168), but at a high\r\nlevel we're adding two things in this PR:\r\n\r\n1. The logic to calculate the new `rule_source` field on import, which\r\ncontains the information about the rule's relationship to existing\r\nprebuilt rules.\r\n2. A new code path for importing rules, which respects the calculated\r\n`rule_source` field.\r\n\r\nIn order to maintain backwards compatibility with the existing import\r\nlogic, and because the existing import implementation is hard to\r\nmodify/extend, I opted to add a top-level switch on the feature flag in\r\nthe import route itself, which calls either the existing import function\r\n(now named `importRulesLegacy`), or the new function, `importRules`,\r\nwhich ultimately calls the new `DetectionRulesClient` method,\r\n`importRules`. Neither knows about the feature flag, and thanks to great\r\nsuggestions from @xcrzx there are nice, clean boundaries between the\r\nimport functions and the client methods.\r\n\r\nI went down the path of trying to write the new import code by reusing\r\nthe outer `importRules` function, but after discussion with the team we\r\ndecided it was simplest to simply bifurcate the code at that point, so\r\nthat we have:\r\n\r\n1. The legacy import code, which:\r\n * only supports custom rules (`immutable: false`)\r\n * accepts `version` as an optional parameter\r\n* calculates a legacy `rule_source` value based on the `immutable` field\r\n2. The new import code, which\r\n * Installs the prebuilt rules assets as necessary\r\n * Accepts both kinds of rules (`immutable: true/false`)\r\n * Requires `version` as a parameter for _prebuilt_ rules\r\n * Allows `version` to be optional for custom rules\r\n * calculates a proper `rule_source` (and `immutable`)\r\n\r\n\r\n### Deprecation of `immutable`\r\nThe RFC (and thus I) had initially thought that we'd be deprecating the\r\n`immutable` field as part of this PR/Epic. However, after\r\n[discussion](https://github.com/elastic/kibana/pull/190198#discussion_r1736021749)\r\nwe have opted to continue supporting `immutable` until such time as we\r\ncan drop it, compatibility-wise.\r\n\r\n\r\n## Steps to Review\r\n1. Enable the Feature Flag: `prebuiltRulesCustomizationEnabled`\r\n2. Install the prebuilt rules package via fleet\r\n3. Create and export a custom rule to serve as a template (or download\r\none:\r\n\r\ncurl -L -H 'Authorization: 8eef0fe5d7dfc52b' -o 'rules_export\r\n(1).ndjson'\r\nhttps://upload.elastic.co/d/4693e7fe4356ce7bcf7b7d6b72881a9fd189730c61bf5ef47c9930458d746979\r\n )\r\n \r\n4. Install some prebuilt rules, and obtain a prebuilt rule's `rule_id`,\r\ne.g. `ac8805f6-1e08-406c-962e-3937057fa86f`\r\n5. Edit the `rules_export.ndjson` to contain only the first line, and\r\nmodify the `rule_id` with the prebuilt rule's\r\n6. Import `rules_export.ndjson` and then retrieve the rule via the Dev\r\nConsole:\r\n\r\nGET\r\nkbn:api/detection_engine/rules?rule_id=ac8805f6-1e08-406c-962e-3937057fa86f\r\n\r\n7. Observe that the rule has the expected `rule_source` and `immutable`\r\nvalues\r\n8. Test other permutations of import by modifying `rules_export.ndjson`\r\nand re-importing; see ([the test\r\nplan](#191116) as well as a\r\n[reference table of\r\nscenarios](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/docs/rfcs/detection_response/prebuilt_rules_customization.md#importing-rules))\r\n\r\n### Checklist\r\n\r\nDelete any items that are not applicable to this PR.\r\n\r\n- [x] Any text added follows [EUI's writing\r\nguidelines](https://elastic.github.io/eui/#/guidelines/writing), uses\r\nsentence case text and includes [i18n\r\nsupport](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md)\r\n- [ ]\r\n[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)\r\nwas added for features that require explanation or tutorials\r\n- [x] [Unit or functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere updated or added to match the most common scenarios\r\n- [ ] [Flaky Test\r\nRunner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was\r\nused on any tests changed\r\n\r\n---------\r\n\r\nCo-authored-by: kibanamachine <[email protected]>\r\nCo-authored-by: Georgii Gorbachev <[email protected]>","sha":"c0b1301a21b74e8b643fc0e898b1d982fd85d98e","branchLabelMapping":{"^v9.0.0$":"main","^v8.16.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","v9.0.0","Team:Detections and Resp","Team: SecuritySolution","Team:Detection Rule Management","Feature:Prebuilt Detection Rules","v8.16.0","backport:version"],"title":"[Security Solution] Allow importing of prebuilt rules via the API","number":190198,"url":"https://github.com/elastic/kibana/pull/190198","mergeCommit":{"message":"[Security Solution] Allow importing of prebuilt rules via the API (#190198)\n\n## Summary\r\n\r\nThis PR introduces the backend functionality necessary to import\r\nprebuilt rules via our existing import API. The\r\n[RFC](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/docs/rfcs/detection_response/prebuilt_rules_customization.md)\r\ngoes into detail, and the import-specific issue is described\r\n[here](#180168), but at a high\r\nlevel we're adding two things in this PR:\r\n\r\n1. The logic to calculate the new `rule_source` field on import, which\r\ncontains the information about the rule's relationship to existing\r\nprebuilt rules.\r\n2. A new code path for importing rules, which respects the calculated\r\n`rule_source` field.\r\n\r\nIn order to maintain backwards compatibility with the existing import\r\nlogic, and because the existing import implementation is hard to\r\nmodify/extend, I opted to add a top-level switch on the feature flag in\r\nthe import route itself, which calls either the existing import function\r\n(now named `importRulesLegacy`), or the new function, `importRules`,\r\nwhich ultimately calls the new `DetectionRulesClient` method,\r\n`importRules`. Neither knows about the feature flag, and thanks to great\r\nsuggestions from @xcrzx there are nice, clean boundaries between the\r\nimport functions and the client methods.\r\n\r\nI went down the path of trying to write the new import code by reusing\r\nthe outer `importRules` function, but after discussion with the team we\r\ndecided it was simplest to simply bifurcate the code at that point, so\r\nthat we have:\r\n\r\n1. The legacy import code, which:\r\n * only supports custom rules (`immutable: false`)\r\n * accepts `version` as an optional parameter\r\n* calculates a legacy `rule_source` value based on the `immutable` field\r\n2. The new import code, which\r\n * Installs the prebuilt rules assets as necessary\r\n * Accepts both kinds of rules (`immutable: true/false`)\r\n * Requires `version` as a parameter for _prebuilt_ rules\r\n * Allows `version` to be optional for custom rules\r\n * calculates a proper `rule_source` (and `immutable`)\r\n\r\n\r\n### Deprecation of `immutable`\r\nThe RFC (and thus I) had initially thought that we'd be deprecating the\r\n`immutable` field as part of this PR/Epic. However, after\r\n[discussion](https://github.com/elastic/kibana/pull/190198#discussion_r1736021749)\r\nwe have opted to continue supporting `immutable` until such time as we\r\ncan drop it, compatibility-wise.\r\n\r\n\r\n## Steps to Review\r\n1. Enable the Feature Flag: `prebuiltRulesCustomizationEnabled`\r\n2. Install the prebuilt rules package via fleet\r\n3. Create and export a custom rule to serve as a template (or download\r\none:\r\n\r\ncurl -L -H 'Authorization: 8eef0fe5d7dfc52b' -o 'rules_export\r\n(1).ndjson'\r\nhttps://upload.elastic.co/d/4693e7fe4356ce7bcf7b7d6b72881a9fd189730c61bf5ef47c9930458d746979\r\n )\r\n \r\n4. Install some prebuilt rules, and obtain a prebuilt rule's `rule_id`,\r\ne.g. `ac8805f6-1e08-406c-962e-3937057fa86f`\r\n5. Edit the `rules_export.ndjson` to contain only the first line, and\r\nmodify the `rule_id` with the prebuilt rule's\r\n6. Import `rules_export.ndjson` and then retrieve the rule via the Dev\r\nConsole:\r\n\r\nGET\r\nkbn:api/detection_engine/rules?rule_id=ac8805f6-1e08-406c-962e-3937057fa86f\r\n\r\n7. Observe that the rule has the expected `rule_source` and `immutable`\r\nvalues\r\n8. Test other permutations of import by modifying `rules_export.ndjson`\r\nand re-importing; see ([the test\r\nplan](#191116) as well as a\r\n[reference table of\r\nscenarios](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/docs/rfcs/detection_response/prebuilt_rules_customization.md#importing-rules))\r\n\r\n### Checklist\r\n\r\nDelete any items that are not applicable to this PR.\r\n\r\n- [x] Any text added follows [EUI's writing\r\nguidelines](https://elastic.github.io/eui/#/guidelines/writing), uses\r\nsentence case text and includes [i18n\r\nsupport](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md)\r\n- [ ]\r\n[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)\r\nwas added for features that require explanation or tutorials\r\n- [x] [Unit or functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere updated or added to match the most common scenarios\r\n- [ ] [Flaky Test\r\nRunner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was\r\nused on any tests changed\r\n\r\n---------\r\n\r\nCo-authored-by: kibanamachine <[email protected]>\r\nCo-authored-by: Georgii Gorbachev <[email protected]>","sha":"c0b1301a21b74e8b643fc0e898b1d982fd85d98e"}},"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/190198","number":190198,"mergeCommit":{"message":"[Security Solution] Allow importing of prebuilt rules via the API (#190198)\n\n## Summary\r\n\r\nThis PR introduces the backend functionality necessary to import\r\nprebuilt rules via our existing import API. The\r\n[RFC](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/docs/rfcs/detection_response/prebuilt_rules_customization.md)\r\ngoes into detail, and the import-specific issue is described\r\n[here](#180168), but at a high\r\nlevel we're adding two things in this PR:\r\n\r\n1. The logic to calculate the new `rule_source` field on import, which\r\ncontains the information about the rule's relationship to existing\r\nprebuilt rules.\r\n2. A new code path for importing rules, which respects the calculated\r\n`rule_source` field.\r\n\r\nIn order to maintain backwards compatibility with the existing import\r\nlogic, and because the existing import implementation is hard to\r\nmodify/extend, I opted to add a top-level switch on the feature flag in\r\nthe import route itself, which calls either the existing import function\r\n(now named `importRulesLegacy`), or the new function, `importRules`,\r\nwhich ultimately calls the new `DetectionRulesClient` method,\r\n`importRules`. Neither knows about the feature flag, and thanks to great\r\nsuggestions from @xcrzx there are nice, clean boundaries between the\r\nimport functions and the client methods.\r\n\r\nI went down the path of trying to write the new import code by reusing\r\nthe outer `importRules` function, but after discussion with the team we\r\ndecided it was simplest to simply bifurcate the code at that point, so\r\nthat we have:\r\n\r\n1. The legacy import code, which:\r\n * only supports custom rules (`immutable: false`)\r\n * accepts `version` as an optional parameter\r\n* calculates a legacy `rule_source` value based on the `immutable` field\r\n2. The new import code, which\r\n * Installs the prebuilt rules assets as necessary\r\n * Accepts both kinds of rules (`immutable: true/false`)\r\n * Requires `version` as a parameter for _prebuilt_ rules\r\n * Allows `version` to be optional for custom rules\r\n * calculates a proper `rule_source` (and `immutable`)\r\n\r\n\r\n### Deprecation of `immutable`\r\nThe RFC (and thus I) had initially thought that we'd be deprecating the\r\n`immutable` field as part of this PR/Epic. However, after\r\n[discussion](https://github.com/elastic/kibana/pull/190198#discussion_r1736021749)\r\nwe have opted to continue supporting `immutable` until such time as we\r\ncan drop it, compatibility-wise.\r\n\r\n\r\n## Steps to Review\r\n1. Enable the Feature Flag: `prebuiltRulesCustomizationEnabled`\r\n2. Install the prebuilt rules package via fleet\r\n3. Create and export a custom rule to serve as a template (or download\r\none:\r\n\r\ncurl -L -H 'Authorization: 8eef0fe5d7dfc52b' -o 'rules_export\r\n(1).ndjson'\r\nhttps://upload.elastic.co/d/4693e7fe4356ce7bcf7b7d6b72881a9fd189730c61bf5ef47c9930458d746979\r\n )\r\n \r\n4. Install some prebuilt rules, and obtain a prebuilt rule's `rule_id`,\r\ne.g. `ac8805f6-1e08-406c-962e-3937057fa86f`\r\n5. Edit the `rules_export.ndjson` to contain only the first line, and\r\nmodify the `rule_id` with the prebuilt rule's\r\n6. Import `rules_export.ndjson` and then retrieve the rule via the Dev\r\nConsole:\r\n\r\nGET\r\nkbn:api/detection_engine/rules?rule_id=ac8805f6-1e08-406c-962e-3937057fa86f\r\n\r\n7. Observe that the rule has the expected `rule_source` and `immutable`\r\nvalues\r\n8. Test other permutations of import by modifying `rules_export.ndjson`\r\nand re-importing; see ([the test\r\nplan](#191116) as well as a\r\n[reference table of\r\nscenarios](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/docs/rfcs/detection_response/prebuilt_rules_customization.md#importing-rules))\r\n\r\n### Checklist\r\n\r\nDelete any items that are not applicable to this PR.\r\n\r\n- [x] Any text added follows [EUI's writing\r\nguidelines](https://elastic.github.io/eui/#/guidelines/writing), uses\r\nsentence case text and includes [i18n\r\nsupport](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md)\r\n- [ ]\r\n[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)\r\nwas added for features that require explanation or tutorials\r\n- [x] [Unit or functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere updated or added to match the most common scenarios\r\n- [ ] [Flaky Test\r\nRunner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was\r\nused on any tests changed\r\n\r\n---------\r\n\r\nCo-authored-by: kibanamachine <[email protected]>\r\nCo-authored-by: Georgii Gorbachev <[email protected]>","sha":"c0b1301a21b74e8b643fc0e898b1d982fd85d98e"}},{"branch":"8.x","label":"v8.16.0","branchLabelMappingKey":"^v8.16.0$","isSourceBranch":false,"state":"NOT_CREATED"}]}] BACKPORT--> Co-authored-by: Ryland Herrick <[email protected]>
- Loading branch information