From c0f2e0505e077ae38d26418c5f7109666ed80337 Mon Sep 17 00:00:00 2001 From: jpdjere Date: Thu, 23 Nov 2023 12:44:32 +0100 Subject: [PATCH 01/61] RFC for Prebuilt Rules Customization - Phase 3 - Part 1 --- .../rule/methods/bulk_edit/bulk_edit_rules.ts | 7 +- .../migrate_prebuilt_schema_on_bulk_edit.ts | 38 + .../rule_schema/common_attributes.gen.ts | 24 + .../rule_schema/common_attributes.schema.yaml | 21 + .../model/rule_schema/rule_schemas.gen.ts | 2 + .../rule_schema/rule_schemas.schema.yaml | 2 + .../import_rules/rule_to_import.ts | 7 +- .../rule_management/rule_fields.ts | 2 + .../rule_management/rule_filtering.ts | 11 +- .../docs/2023-12-01-14-13-07.png | Bin 0 -> 191177 bytes .../docs/prebuilt_rules_customization_rfc.md | 2399 +++++++++++++++++ .../pages/rule_editing/index.tsx | 3 - .../rules_table/use_rules_table_actions.tsx | 2 +- .../perform_rule_upgrade_route.ts | 4 +- .../review_rule_upgrade_route.ts | 5 + .../rule_objects/create_prebuilt_rules.ts | 2 +- .../upgrade_prebuilt_rules.test.ts | 13 +- .../rule_objects/upgrade_prebuilt_rules.ts | 27 +- .../model/rule_assets/prebuilt_rule_asset.ts | 2 + .../api/rules/bulk_actions/route.ts | 49 +- .../api/rules/bulk_create_rules/route.ts | 1 + .../api/rules/create_rule/route.ts | 1 + .../api/rules/filters/route.ts | 5 +- .../api/rules/find_rules/route.ts | 7 +- .../api/rules/import_rules/route.ts | 1 + .../logic/actions/duplicate_rule.ts | 27 +- .../logic/bulk_actions/bulk_edit_rules.ts | 1 + .../bulk_actions/rule_params_modifier.ts | 6 - .../logic/bulk_actions/validations.ts | 7 - .../logic/crud/create_rules.ts | 39 +- .../rule_management/logic/crud/patch_rules.ts | 30 +- .../logic/crud/update_rules.ts | 13 +- .../logic/import/import_rules_utils.ts | 10 + .../prebuilt_rule_schema_migrations.ts | 146 + .../normalization/rule_converters.ts | 63 +- .../rule_schema/model/rule_schemas.ts | 3 + 36 files changed, 2873 insertions(+), 107 deletions(-) create mode 100644 x-pack/plugins/alerting/server/application/rule/methods/bulk_edit/schemas/migrate_prebuilt_schema_on_bulk_edit.ts create mode 100644 x-pack/plugins/security_solution/docs/2023-12-01-14-13-07.png create mode 100644 x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md create mode 100644 x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/normalization/prebuilt_rule_schema_migrations.ts diff --git a/x-pack/plugins/alerting/server/application/rule/methods/bulk_edit/bulk_edit_rules.ts b/x-pack/plugins/alerting/server/application/rule/methods/bulk_edit/bulk_edit_rules.ts index 1a4898418a8c44..bfa604b7ce14b3 100644 --- a/x-pack/plugins/alerting/server/application/rule/methods/bulk_edit/bulk_edit_rules.ts +++ b/x-pack/plugins/alerting/server/application/rule/methods/bulk_edit/bulk_edit_rules.ts @@ -78,6 +78,7 @@ import { transformRuleDomainToRule, } from '../../transforms'; import { validateScheduleLimit, ValidateScheduleLimitResult } from '../get_schedule_frequency'; +import { migratePrebuiltSchemaOnRuleBulkEdit } from './schemas/migrate_prebuilt_schema_on_bulk_edit'; const isValidInterval = (interval: string | undefined): interval is string => { return interval !== undefined; @@ -512,9 +513,13 @@ async function updateRuleAttributesAndParamsInMemory( updatedRule.revision += 1; } + const isRuleUpdated = !(isAttributesUpdateSkipped && isParamsUpdateSkipped); + + migratePrebuiltSchemaOnRuleBulkEdit(ruleParams, isRuleUpdated); + // If neither attributes nor parameters were updated, mark // the rule as skipped and continue to the next rule. - if (isAttributesUpdateSkipped && isParamsUpdateSkipped) { + if (!isRuleUpdated) { skipped.push({ id: rule.id, name: rule.attributes.name, diff --git a/x-pack/plugins/alerting/server/application/rule/methods/bulk_edit/schemas/migrate_prebuilt_schema_on_bulk_edit.ts b/x-pack/plugins/alerting/server/application/rule/methods/bulk_edit/schemas/migrate_prebuilt_schema_on_bulk_edit.ts new file mode 100644 index 00000000000000..09ce6e26c97494 --- /dev/null +++ b/x-pack/plugins/alerting/server/application/rule/methods/bulk_edit/schemas/migrate_prebuilt_schema_on_bulk_edit.ts @@ -0,0 +1,38 @@ +/* + * 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 { RuleParams } from '../../../types'; + +const getPrebuiltValueForRuleBulkEdit = ( + ruleParams: RuleParams, + isRuleUpdatedDuringBulkUpdate: boolean +) => { + if (ruleParams?.prebuilt) { + return { + ...ruleParams.prebuilt, + isCustomized: ruleParams.prebuilt.isCustomized || isRuleUpdatedDuringBulkUpdate, + }; + } + + if (ruleParams.immutable) { + return { + isCustomized: isRuleUpdatedDuringBulkUpdate, + }; + } + + return undefined; +}; + +export const migratePrebuiltSchemaOnRuleBulkEdit = ( + ruleParams: RuleParams, + isRuleUpdatedDuringBulkUpdate: boolean +) => { + const immutable = Boolean(ruleParams.prebuilt) || ruleParams.immutable; + const prebuilt = getPrebuiltValueForRuleBulkEdit(ruleParams, isRuleUpdatedDuringBulkUpdate); + + ruleParams.prebuilt = prebuilt; + ruleParams.immutable = immutable; +}; diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/common_attributes.gen.ts b/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/common_attributes.gen.ts index e3401d4cf16bab..f812aa9d90af73 100644 --- a/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/common_attributes.gen.ts +++ b/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/common_attributes.gen.ts @@ -63,9 +63,33 @@ export const KqlQueryLanguage = z.enum(['kuery', 'lucene']); export type KqlQueryLanguageEnum = typeof KqlQueryLanguage.enum; export const KqlQueryLanguageEnum = KqlQueryLanguage.enum; +/** + * [DEPRECATION WARNING - This field is deprecated and will be removed in a future release. Use the prebuilt field to determine if a rule is an Elastic prebuilt rule or a custom rule.] - Determines whether the rule is immutable (i.e. cannot be modified by the user). + */ export type IsRuleImmutable = z.infer; export const IsRuleImmutable = z.boolean(); +/** + * Determines whether the prebuilt rule has been customized by the user (i.e. any of its fields have been modified and diverge from the base value). + */ +export type IsPrebuiltRuleCustomized = z.infer; +export const IsPrebuiltRuleCustomized = z.boolean(); + +/** + * The date and time that the prebuilt rule was last updated by Elastic. + */ +export type ElasticUpdateDate = z.infer; +export const ElasticUpdateDate = z.string().datetime(); + +/** + * Property whose existence determines whether the rule is an Elastic Prebuilt Rule that can receive upstream updates via Fleet. Contains information relating to prebuilt rules. + */ +export type Prebuilt = z.infer; +export const Prebuilt = z.object({ + isCustomized: IsPrebuiltRuleCustomized, + elasticUpdateDate: ElasticUpdateDate.optional(), +}); + /** * Determines whether the rule is enabled. */ diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/common_attributes.schema.yaml b/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/common_attributes.schema.yaml index 1387072bf99e88..03c95676877d57 100644 --- a/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/common_attributes.schema.yaml +++ b/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/common_attributes.schema.yaml @@ -53,6 +53,27 @@ components: IsRuleImmutable: type: boolean + description: '[DEPRECATION WARNING - This field is deprecated and will be removed in a future release. Use the prebuilt field to determine if a rule is an Elastic prebuilt rule or a custom rule.] - Determines whether the rule is immutable (i.e. cannot be modified by the user).' + + IsPrebuiltRuleCustomized: + type: boolean + description: Determines whether the prebuilt rule has been customized by the user (i.e. any of its fields have been modified and diverge from the base value). + + ElasticUpdateDate: + type: string + format: date-time + description: The date and time that the prebuilt rule was last updated by Elastic. + + Prebuilt: + type: object + description: Property whose existence determines whether the rule is an Elastic Prebuilt Rule that can receive upstream updates via Fleet. Contains information relating to prebuilt rules. + properties: + isCustomized: + $ref: '#/components/schemas/IsPrebuiltRuleCustomized' + elasticUpdateDate: + $ref: '#/components/schemas/ElasticUpdateDate' + required: + - isCustomized IsRuleEnabled: type: boolean diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/rule_schemas.gen.ts b/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/rule_schemas.gen.ts index 9d27297d11bbef..6a8585743d8f8d 100644 --- a/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/rule_schemas.gen.ts +++ b/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/rule_schemas.gen.ts @@ -55,6 +55,7 @@ import { RuleObjectId, RuleSignatureId, IsRuleImmutable, + Prebuilt, RelatedIntegrationArray, RequiredFieldArray, SetupGuide, @@ -155,6 +156,7 @@ export const ResponseFields = z.object({ id: RuleObjectId, rule_id: RuleSignatureId, immutable: IsRuleImmutable, + prebuilt: Prebuilt.optional(), updated_at: z.string().datetime(), updated_by: z.string(), created_at: z.string().datetime(), diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/rule_schemas.schema.yaml b/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/rule_schemas.schema.yaml index 22308557c3aaa8..2576bc2021fbaa 100644 --- a/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/rule_schemas.schema.yaml +++ b/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/rule_schemas.schema.yaml @@ -161,6 +161,8 @@ components: $ref: './common_attributes.schema.yaml#/components/schemas/RuleSignatureId' immutable: $ref: './common_attributes.schema.yaml#/components/schemas/IsRuleImmutable' + prebuilt: + $ref: './common_attributes.schema.yaml#/components/schemas/Prebuilt' updated_at: type: string format: date-time diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/import_rules/rule_to_import.ts b/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/import_rules/rule_to_import.ts index 9634d773b121dc..a2df931c5eaf05 100644 --- a/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/import_rules/rule_to_import.ts +++ b/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/import_rules/rule_to_import.ts @@ -5,12 +5,14 @@ * 2.0. */ -import * as z from 'zod'; +import type * as z from 'zod'; import { BaseCreateProps, ResponseFields, RuleSignatureId, TypeSpecificCreateProps, + IsRuleImmutable, + Prebuilt, } from '../../model/rule_schema'; /** @@ -28,6 +30,7 @@ export type RuleToImportInput = z.input; export const RuleToImport = BaseCreateProps.and(TypeSpecificCreateProps).and( ResponseFields.partial().extend({ rule_id: RuleSignatureId, - immutable: z.literal(false).default(false), + immutable: IsRuleImmutable.optional(), + prebuilt: Prebuilt.optional(), }) ); diff --git a/x-pack/plugins/security_solution/common/detection_engine/rule_management/rule_fields.ts b/x-pack/plugins/security_solution/common/detection_engine/rule_management/rule_fields.ts index 5d72cd15a96ae3..a9530cf08508df 100644 --- a/x-pack/plugins/security_solution/common/detection_engine/rule_management/rule_fields.ts +++ b/x-pack/plugins/security_solution/common/detection_engine/rule_management/rule_fields.ts @@ -21,4 +21,6 @@ export const ENABLED_FIELD = 'alert.attributes.enabled'; export const TAGS_FIELD = 'alert.attributes.tags'; export const PARAMS_TYPE_FIELD = 'alert.attributes.params.type'; export const PARAMS_IMMUTABLE_FIELD = 'alert.attributes.params.immutable'; +export const PARAMS_PREBUILT_FIELD = 'alert.attributes.params.prebuilt'; +export const PARAMS_PREBUILT_IS_CUSTOMIZED_FIELD = 'alert.attributes.params.prebuilt.isCustomized'; export const LAST_RUN_OUTCOME_FIELD = 'alert.attributes.lastRun.outcome'; diff --git a/x-pack/plugins/security_solution/common/detection_engine/rule_management/rule_filtering.ts b/x-pack/plugins/security_solution/common/detection_engine/rule_management/rule_filtering.ts index bfc31df88ec970..83a041fac760b1 100644 --- a/x-pack/plugins/security_solution/common/detection_engine/rule_management/rule_filtering.ts +++ b/x-pack/plugins/security_solution/common/detection_engine/rule_management/rule_filtering.ts @@ -13,12 +13,17 @@ import { ENABLED_FIELD, LAST_RUN_OUTCOME_FIELD, PARAMS_IMMUTABLE_FIELD, + PARAMS_PREBUILT_IS_CUSTOMIZED_FIELD, PARAMS_TYPE_FIELD, RULE_NAME_FIELD, RULE_PARAMS_FIELDS, TAGS_FIELD, } from './rule_fields'; +// KQL does not allow to search for existence of the prebuilt object field, since params is unmapped +// so we can search for the existence of the isCustomized subfield instead, which is required +export const KQL_FILTER_PREBUILT_RULES = `${PARAMS_PREBUILT_IS_CUSTOMIZED_FIELD}: *`; +export const KQL_FILTER_CUSTOM_RULES = `NOT ${PARAMS_PREBUILT_IS_CUSTOMIZED_FIELD}: *`; export const KQL_FILTER_IMMUTABLE_RULES = `${PARAMS_IMMUTABLE_FIELD}: true`; export const KQL_FILTER_MUTABLE_RULES = `${PARAMS_IMMUTABLE_FIELD}: false`; export const KQL_FILTER_ENABLED_RULES = `${ENABLED_FIELD}: true`; @@ -59,9 +64,11 @@ export function convertRulesFilterToKQL({ if (showCustomRules && showElasticRules) { // if both showCustomRules && showElasticRules selected we omit filter, as it includes all existing rules } else if (showElasticRules) { - kql.push(KQL_FILTER_IMMUTABLE_RULES); + kql.push(`${KQL_FILTER_PREBUILT_RULES}`); + // kql.push(`(${KQL_FILTER_PREBUILT_RULES} OR ${KQL_FILTER_IMMUTABLE_RULES})`); } else if (showCustomRules) { - kql.push(KQL_FILTER_MUTABLE_RULES); + kql.push(`${KQL_FILTER_CUSTOM_RULES}`); + // kql.push(`(${KQL_FILTER_CUSTOM_RULES} OR ${KQL_FILTER_MUTABLE_RULES})`); } if (enabled !== undefined) { diff --git a/x-pack/plugins/security_solution/docs/2023-12-01-14-13-07.png b/x-pack/plugins/security_solution/docs/2023-12-01-14-13-07.png new file mode 100644 index 0000000000000000000000000000000000000000..ce7f3321a0c0b2490891bcbb4463920cdbcfd961 GIT binary patch literal 191177 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

T0FPqx09r2$3$`stw06!s6 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 h9wckyad4XN^ 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%0DB$CE3X!!WKfn@xM5~ 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 z zE5B-+nuPa9tXl%J7He!4(z2YQd%|>Uq@LG2KuSH5IOK(C1Q)s2pUqTP4$wcq3daJ?)wvbaRo&s=+L%{Z%fXH^i zc3BCIpz^PS?q)sI_SP(4ASlq`Wk8Kd&#fF^Y(7;8!fU>q>#F&dovFCYcGz;QW_|tl zvWbkn_I#>@>P{S=M@LWdoDPoKB`kvyUuwF(QA~)7p^=vxR4<7+TSiEyh$tTJAoFeE zsBRPzrQec?!0sAa1}9qB$)@t*p>0p8UOzotIbS9^t1`CR3AIoV!>DSeep+U8O?(

nf9YAUQw99akNNKs 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 Rules UI](#via-the-stack-management-rules-ui) +- [List of things to fix (create tickets)](#list-of-things-to-fix-create-tickets) + - [Rule fields](#rule-fields) +- [Updating Prebuilt Rules](#updating-prebuilt-rules) + - [Changes to upgrade `_review` and `_perform` endpoints](#changes-to-upgrade-_review-and-_perform-endpoints) + - [Rule field diff algorithms](#rule-field-diff-algorithms) +- [Changes in UI](#changes-in-ui) +- [Scenarios for bulk accepting updates](#scenarios-for-bulk-accepting-updates) +- [Marking rules (and their fields) as customized](#marking-rules-and-their-fields-as-customized) +- [Other open questions](#other-open-questions) + +## Necessary rule schema changes + +In order to support the customization of Elastic Prebuilt Rules, we need to modify our rule schema. This involves introducing a new nested `prebuilt` field and deprecating the `immutable` field. + +### `prebuilt` and `immutable` fields + +The `prebuilt` field will be a top-level object field in our rule schema that will contain subfields with information relating to Elastic Prebuilt rules. + +It will be an optional field, which will only be present for Elastic prebuilt rules. + +Its existence within a rule object will determine if a rule is a prebuilt rule (and its absence will determine that it is a custom rule). + +This means that its presence in a rule object will determine whether the rule is an Elastic Prebuilt Rule that can receive upstream updates via Fleet. This field is intented to replace the currently existing `immutable` field, which is used today for the same purpose, but -as its name indicates- also currently determines if a rule's fields can be modified/customized. + +That means that, in the current state, rules with `immutable: false` are rules which are not Elastic Prebuilt Rules, i.e. custom rules, and can be modified. Meanwhile, `immutable: true` rules are Elastic Prebuilt Rules, created by the TRADE team, distributed via the `security_detection_engine` Fleet package, and cannot be modified once installed. + +When successfully implemented, the `prebuilt` field should replace the `immutable` field as a flag to mark Elastic prebuilt rules, but with one difference: the `prebuilt` field will determine if the rule is an Elastic Prebuilt Rule or not, but now all rules will be customizable by the user, i.e. independently of the existence (or absence) of `prebuilt`. + +Because of this difference in the behaviour of the `prebuilt` and `immutable` fields, we feel that a field called `immutable` will lose its meaning over time and become confusing, especially for consumers of the API who interact directly with the field name. That's why we want to eventually deprecate it and fully replace it with `prebuilt`. + +To ensure backward compatibility and avoid breaking changes, we will deprecate the `immutable` field but keep it within the rule schema, asking our users to stop relying on this field in Detection API responses. During the migration period, we want to keep the value of the `immutable` field in sync with the `prebuilt` field: this means that for all rules that have a `immutable` value of `true`, the `prebuilt` rule will always exist. Viceversa, rule with `immutable: false` will not have a `prebuilt` field. + +This means, however, that there will be a change in behaviour of the `immutable` field: with the release of the feature, rules with the `immutable: true` value will now be customizable by the user, which is not the current behaviour. + +In this first phase, the `prebuilt` will contain two subfields: `isCustomized` and `elasticUpdateDate`. + +```ts +// PSEUDOCODE - see complete schema in detail below +{ + prebuilt?: { + isCustomized: boolean; + elasticUpdateDate?: Date; + } +} +``` + +#### `isCustomized` subfield + +The `isCustomized` field will be a boolean field that determines whether a Prebuilt Rule has been customized by the user, i.e. if any of its fields have been modified and diverged from the base version of the rule, which is the version that is installed from the Prebuilt Rules `security_detection_engine` Fleet package. + +This means that the `isCustomized` subfield only makes sense and will be used for prebuilt rules, or rules whose `prebuilt` field exists. It is therefor a subfield of the `prebuilt` field. + +For prebuilt rules, the `prebuilt.isCustomized` value will be initially set to `false` when a brand new rule is installed, but will be rewritten to `true` if a rule's field is edited and diverges from the value from the base version of the rule. + +See section [Calculating the `isCustomized` flag]() + +#### `elasticUpdateDate` subfield + +The `elasticUpdateDate` will be a field containing a date in ISO 8601 format which describes the last time that an Elastic Prebuilt Detection rule was created and subsequently updated by the TRaDe team, the team responsible for creating detection rules. Its usage is detailed in this ticket. + +This field will be optional in both the API schema and the internal rule schema, since this value will not exist for prebuilt rules until a new version of each rule which includes this field in the prebuilt rule asset is published by the TRaDE team, and the user installs it or updates to it. + +### Changes needed in rule schema + +As detailed further down in the [Plan for carrying out migrations of rule SOs](#plan-for-carrying-out-migrations-of-rule-sos) section, we will be performing incremental migration-on-write on our saved objects to get to our new schemas (see details in linked section). + +This means that we need to differentiate between changes to the internal rule schema and the API schema. + +#### API schema + +**In the API schema** the `prebuilt` field will be optional, as it will exist for Elastic prebuilt rules, but won't for custom rules. The OpenAPI schema will need to be modified so: + +_Source: [x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/common_attributes.schema.yaml](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/common_attributes.schema.yaml)_ + +```yaml +# [... file continues above...] + +# Add deprecation warning to `immutable` field +IsRuleImmutable: + type: boolean + description: '[DEPRECATION WARNING - This field is deprecated and will be removed in a future release. Use the prebuilt field to determine if a rule is an Elastic prebuilt rule or a custom rule.] - Determines whether the rule is immutable (i.e. cannot be modified by the user).' + +# Add the top-level `prebuilt` object and its subfields `isCustomized` and `elasticUpdateDate` +IsPrebuiltRuleCustomized: + type: boolean + description: Determines whether the prebuilt rule has been customized by the user (i.e. any of its fields have been modified and diverge from the base value). + +ElasticUpdateDate: + type: string + format: date-time + description: The date and time that the prebuilt rule was last updated by Elastic. + +Prebuilt: + type: object + description: Property whose existence determines whether the rule is an Elastic Prebuilt Rule that can receive upstream updates via Fleet. Contains information relating to prebuilt rules. + properties: + isCustomized: + $ref: '#/components/schemas/IsPrebuiltRuleCustomized' + elasticUpdateDate: + $ref: '#/components/schemas/ElasticUpdateDate' + required: + - isCustomized +# [... file continues below ...] +``` + +_Source: [x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/rule_schemas.schema.yaml](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/rule_schemas.schema.yaml)_ + +```yaml +# [... file continues above...] + +ResponseFields: + type: object + properties: + id: + $ref: './common_attributes.schema.yaml#/components/schemas/RuleObjectId' + rule_id: + $ref: './common_attributes.schema.yaml#/components/schemas/RuleSignatureId' + immutable: + $ref: './common_attributes.schema.yaml#/components/schemas/IsRuleImmutable' + prebuilt: + $ref: './common_attributes.schema.yaml#/components/schemas/Prebuilt' + # [... more response fields ...] + required: + # notice `prebuilt` is not required + - id + - rule_id + - immutable + - updated_at + - updated_by + - created_at + - created_by + - revision + - related_integrations + - required_fields + - setup +# [... file continues below...] +``` + +When the OpenAPI code generator is run, this will result in the files: + +_Source: [x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/common_attributes.gen.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/common_attributes.gen.ts)_ + +```ts +// [... file continues above...] + +/** + * [DEPRECATION WARNING - This field is deprecated and will be removed in a future release. Use the prebuilt field to determine if a rule is an Elastic prebuilt rule or a custom rule.] - Determines whether the rule is immutable (i.e. cannot be modified by the user). + */ +export type IsRuleImmutable = z.infer; +export const IsRuleImmutable = z.boolean(); + +/** + * Determines whether the prebuilt rule has been customized by the user (i.e. any of its fields have been modified and diverge from the base value). + */ +export type IsPrebuiltRuleCustomized = z.infer; +export const IsPrebuiltRuleCustomized = z.boolean(); + +/** + * The date and time that the prebuilt rule was last updated by Elastic. + */ +export type ElasticUpdateDate = z.infer; +export const ElasticUpdateDate = z.string().datetime(); + +/** + * Property whose existence determines whether the rule is an Elastic Prebuilt Rule that can receive upstream updates via Fleet. Contains information relating to prebuilt rules. + */ +export type Prebuilt = z.infer; +export const Prebuilt = z.object({ + isCustomized: IsPrebuiltRuleCustomized, + elasticUpdateDate: ElasticUpdateDate.optional(), +}); + +// [... file continues below ...] +``` + +_Source: [x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/rule_schemas.gen.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/rule_schemas.gen.ts)_ + +```ts +// [... file continues above ...] + +export type ResponseFields = z.infer; +export const ResponseFields = z.object({ + id: RuleObjectId, + rule_id: RuleSignatureId, + immutable: IsRuleImmutable, + prebuilt: Prebuilt.optional(), + // [...] +}); + +// [... file continues below ...] +``` + +We also need to modify the `RuleToImport` schema, since now we will be allowing the importing of both custom rules and prebuilt rules. + +Currently, `RuleToImport` optionally accepts the `immutable` param, but rejects validation if its value is set to anything else than `false` - since we don't currently support importing prebuilt rules. We need to update this schema so that it accepts the `immutable` param with both boolean values, and also optionally accepts the new `prebuilt` field: + +_Source: [x-pack/plugins/security_solution/common/api/detection_engine/rule_management/import_rules/rule_to_import.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/import_rules/rule_to_import.ts)_ + +```ts +// [... file continues above...] +import { + // [...] + RuleSignatureId, + IsRuleImmutable, + Prebuilt, +} from '../../model/rule_schema'; + +export type RuleToImport = z.infer; +export type RuleToImportInput = z.input; +export const RuleToImport = BaseCreateProps.and(TypeSpecificCreateProps).and( + ResponseFields.partial().extend({ + rule_id: RuleSignatureId, + immutable: IsRuleImmutable.optional(), + prebuilt: Prebuilt.optional(), + }) +); +``` + +#### Internal rule schema + +**The internal rule schema** needs to represent that the new `prebuilt` field may not always exist, i.e. for rules yet to be migrated, so `prebuilt` must also be optional. + +_Source: [x-pack/plugins/security_solution/server/lib/detection_engine/rule_schema/model/rule_schemas.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_schema/model/rule_schemas.ts)_ + +```ts +// [... file continues above...] + +import { + // [...] + Prebuilt, + // [...] +} from '../../../../../common/api/detection_engine/model/rule_schema'; + +export type BaseRuleParams = z.infer; +export const BaseRuleParams = z.object({ + // [...] + + immutable: IsRuleImmutable, + prebuilt: Prebuilt.optional(), + + // [...] +}); +``` + +In the internal rule schema, there are two additional important reasons why we need to make sure that this values is optional: + +- When rules are executed, a call to the method `validateRuleTypeParams` is done, which is a method that validates the passed rule's parameters using the validators defined in `x-pack/plugins/security_solution/server/lib/detection_engine/rule_types`, within each of the rule query types files (for [EQL rules](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/eql/create_eql_alert_type.ts#L27), for example). The validation is done based on the internal rule schema `BaseRulesParams` displayed above. Having `prebuilt` as a required fields would cause custom rules to fail on runtime. +- The Rule Client `update` method also calls the `validateRuleTypeParams` to validate the rule's params. Since the Rule Client's `update` method is used in our endpoint handlers, such as and `/rules/patch` and `/_bulk_actions`, these would fail when executed against a payload of custom rule. + +Additionally, the `PrebuiltRuleAsset` type needs to be updated to include the new `elasticUpdateDate` date that will be progressively shipped with new versions of rules in the Elastic Prebuilt Rules package: + +_Source: [x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/model/rule_assets/prebuilt_rule_asset.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/model/rule_assets/prebuilt_rule_asset.ts)_ + +```ts +export const PrebuiltRuleAsset = BaseCreateProps.and(TypeSpecificCreateProps).and( + z.object({ + rule_id: RuleSignatureId, + version: RuleVersion, + related_integrations: RelatedIntegrationArray.optional(), + required_fields: RequiredFieldArray.optional(), + setup: SetupGuide.optional(), + source_updated_at: ElasticUpdateDate.optional(), // new optional field + }) +); +``` + +### Deprecating the `immutable` field + +In order to mark the `immutable` field as deprecated, and making sure that our application and API users are aware that the field has been deprecated and replaced by the `prebuilt` field, we will communicate this change in three ways: + +1. via updates to the documentation of all endpoints that return `RuleResponse` types +2. via a deprecation warning in the OpenAPI schema, as detailed above +3. by adding a custom response header in said endpoints. + +The `immutable` field will afterwards be actually removed from our API endpoint responses and our application after a deprecation period that should give our users enough time to adapt to this change. The length of this deprecation period can vary, but around 4 months, or roughly two ESS releases, is a good starting point. + +Both the docs and the custom response header should communicate that the `immutable` field: + +- has been replaced by the `prebuilt` field and users should rely on that new field onwards +- is maintained for backwards compatibility reasons only +- will be removed after a specific date/release + +The endpoints should be updated to include a custom response header like so: + +```http +Deprecation-Info: immutable field is deprecated and will be removed in version 8.XX (or date). Use prebuilt field instead. +``` + +## Mapping changes + +**Alert (rule objects) mapping** + +No changes will be needed for the [mapping of rule saved objects](https://github.com/elastic/kibana/blob/main/x-pack/plugins/alerting/common/saved_objects/rules/mappings.ts) (of type `alert`), since the new fields introduced will be part of the `params` field, which is a `flattened` field. + +**Security Rules (prebuilt rule assets) mapping** + +No changes will be needed either for the `security-rule` [mapping](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/rule_assets/prebuilt_rule_assets_type.ts), our prebuilt rule assets. We currently have mappings for the `rule_id` and `version` fields, since we perform aggregations and filtering on those in the rule install and upgrade endpoints. No additional fields needs to be mapped in this phase. + +## Plan for carrying out migrations of rule SOs + +### Context + +Historically, migrations to Elasticsearch saved objects were carried out by a procedure in which the changes in the SO were described in a migration operation that would be carried out **during an upgrade to a specific Kibana version**. See `x-pack/plugins/alerting/server/saved_objects/migrations/index.ts` for a list of migrations of SO that take place when a user updates Kibana to a specific version. + +However, this mechanism is no longer supported by the Alerting Framework team - which maintained it - and we therefore have to find an alternative strategy. Therefore, we will perform the migration of the saved objects directly in the Detection API's endpoints that interact with them. This means that, instead of all of a user's saved object being migrated in a single operation during a Kibana update, the SO will be migrated when the pertinent endpoints are called. In the next section, we describe which those endpoints are. + +Since the migration of rules will be performed as the user calls the pertinent endpoints, the migration of the saved objects will be carried out progressively and incrementally: the SO will be migrated only when a endpoint that handles it is called by the user. We therefore have to assume that, at any given point in time, a user may have a mix of migrated and non-migrated rule saved objects. Consequently, we must continue supporting both versions of SOs. + +### Migration strategy + +Our migration strategy will consist of two distinct types of migration: a **migration on write** that will update the SO on Elasticsearch, and a **normalization on read**, which will transform legacy rules to the new schema **in memory** on read operation, before returning it as a response from an API endpoint. + +#### Migration on write + +This type of migration will be in charge of updating saved object fields in Elasticsearch from the legacy form to the new form, and will be performed on all write operations of the rules (see list below). This means that we need to perform this type of migration of rules whenever any endpoint operation that writes/updates a rule saved object is called. + +> In Elasticsearch, the type of rule saved objects is called `alert`. + +This migration strategy of write/update operations means that a user's data will be migrated incrementally, and that both types of data (non-migrated and migrated saved objects) will coexist for an indeterminate amount of time. Therefore we have to maintain backwards data compatibility for the non-migrated data types. + +The migration logic should take place as a first step within the handler logic of all endpoints that carry out write/update endpoint operations, and the endpoint should return the already-migrated rule(s). + +##### Rule Management endpoints that should include migration-on-write logic + +All of the following endpoints either fetch the rule before updating it, or send the rule's params as part of the body in the request. Therefore, we can apply migraton logic to them -as described below- before saving the rules to Elasticsearch. + +- **Update Rule** - `PUT /rules`: used in the UI when updating/modifying a single rule via the Rule Editing page +- **Patch Rule** - `PATCH /rules`: used in the UI for attaching shared exceptions list to rules +- **Bulk Update Rules** - `PUT /rules/_bulk_update`: deprecated and unused by the UI. Might still be used by API users +- **Bulk Patch Rules** - `PATCH /rules/_bulk_update`: deprecated and unused by the UI. Might still be used by API users +- **Import Rules** - `POST /rules/_import`: + - See section [Importing rules](#importing-rules) +- **Perform Rule Upgrade** - `POST /prebuilt_rules/upgrade/_perform` (Internal): current way of upgrading a prebuilt rule +- **(LEGACY) Install Prebuilt Rules And Timelines** - `PUT /rules/prepackaged`: legacy endpoint for installing prebuilt rules. Also updates existing prebuilt rules package, so these rules should be migrated during update as well. +- **Bulk Actions** - `POST /rules/_bulk_action`: + This endpoint includes many types of actions, but only the **bulk edit** and the **duplicate** actions should perform a migration on write. + +This endpoint also includes a `dry_run` mode that is executed to evaluate preconditions and warn the user before executing the actual request. No migration logic should take place for dry run requests, i.e when `dry_run=true`, since we never write to ES when this parameter is set to `true`. + +For the **bulk edit** action, we can take advantage of the `ruleParamsModifier` to carry out the migration, regardless of the type of edit that is being performed. See implementation details in the below [Technical implementation of migration-on-write](#technical-implementation-of-migration-on-write) section. + +For the **duplicate** rule action: + +Since we will be creating a new rule on ES, we should create it with the new schema. Per definition, all duplicated rules will be `custom` rules. That means that for all rules -including prebuilt rules-, when duplicating, the `prebuilt` field will not be created on the newly created rule. +This action will not perform a migration-on-write of the original rule being duplicated for two reasons: + +- would violate the principle of least surprise for the endpoint +- the current implementation of the endpoint does not modify the original rule. This gives us no window of opportunity to migrate the rule and save to ES without adding performance overhead. +- See implementation details below. + +All other type of actions should **not** perform migration-on-write: + +- Enable +- Disable +- Delete +- Export: see Importing and Exporting Rules section below + +#### Normalization on read with `normalizePrebuiltSchemaOnRuleRead` + +All endpoints that respond with a rule Saved Object, typed as `RuleResponse`, will also perform **normalization on read**, which will transform legacy rules to the new schema **in memory** on read operation, before returning it as a response from an API endpoint. + +This means that the endpoints will always respond with the rules with the new schema, while the actual rule might still be stored with the legacy schema in Elasticsearch, if it still has not been migrated-on-write. + +The **normalization on read** will be carried out by a new `normalizePrebuiltSchemaOnRuleRead` normalization function. The `internalRuleToAPIResponse` method, which is used in our endpoints to convert a rule saved object as is stored in Elasticsearch to the `RuleResponse` type which is returned to the client, calls the `commonParamsCamelToSnake` methods to convert rule parameters that are common to all rule types to what's expected in `RuleResponse`. Inside this method, we will use `normalizePrebuiltSchemaOnRuleRead` to calculate the normalized values of `prebuilt` and `immutable`. + +_Source: [x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/normalization/rule_converters.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/normalization/rule_converters.ts)_ + +```ts +// [... file continues above...] + +export const internalRuleToAPIResponse = ( + rule: SanitizedRule | ResolvedSanitizedRule +): RequiredOptional => { + // [... more method implementation details...] + return { + name: rule.name, + tags: rule.tags, + + // [... more object properties ...] + + ...commonParamsCamelToSnake(rule.params), // <--- rule params are converted here + ...typeSpecificCamelToSnake(rule.params), + + // [... more object properties ...] + }; +}; + +// [... file continues here...] + +export const commonParamsCamelToSnake = (params: BaseRuleParams) => { + const { immutable, prebuilt } = normalizePrebuiltSchemaOnRuleRead(params); + + return { + description: params.description, + risk_score: params.riskScore, + + // [... more object properties ...] + + immutable, + prebuilt, + }; +}; + +// [... file continues below...] +``` + +And the `normalizePrebuiltSchemaOnRuleRead` is defined so: + +_Source: x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/normalization/prebuilt_rule_schema_migrations.ts_ (New file) + +```ts +interface MigrationResponse { + immutable: IsRuleImmutable; + prebuilt?: Prebuilt; +} + +const getPrebuiltValueForRuleRead = (ruleParams: BaseRuleParams): Prebuilt | undefined => { + if (ruleParams.prebuilt) { + return ruleParams.prebuilt; + } + + if (ruleParams.immutable) { + return { + isCustomized: false, + }; + } + + return undefined; +}; + +export const normalizePrebuiltSchemaOnRuleRead = ( + ruleParams: BaseRuleParams +): MigrationResponse => { + const immutable = Boolean(ruleParams.prebuilt) || ruleParams.immutable; + const prebuilt = getPrebuiltValueForRuleRead(ruleParams); + + return { + immutable, + prebuilt, + }; +}; +``` + +The logic for calculating the `immutable` and `prebuilt` fields for **normalization-on-read**, seen in the code above, is as follows: + +- For `immutable`: + + - Check if the `prebuilt` field exists in the rule's parameters, and set `immutable` to `true` if it does. + - Use case 1: rules that have already been migrated-on-write + - If it does not exist, set `immutable` to the current value of the params' `immutable` field. + - Use case 2: rules that have not yet been migrated on write + +- For `prebuilt`: + - If the `prebuilt` field already exists in the internal rule object params, use that value: + - Use case 1: prebuilt rules that have already been migrated-on-write + - If it does not exist, check the value `immutable` from the rules param: + - if it is `true`, create a new `prebuilt` object. This object will only have the `isCustomized` field, set to `false`. The `elasticUpdateDate` date will not be known and must be left undefined. + - Use case 2: prebuilt rules that have not been yet migrated-on-write + - otherwise, the field should be `undefined`. + - Use case 3L: custom rules + +##### Rule Management endpoints that will perform normalization-on-read + +- All endpoints that also perform migration-on-write, as listed above. All of them use the `internalRuleToAPIResponse` methods to transform the rule before returning the response, so the normalization on read will take place there. For these specific cases, however, the normalization-on-read will take place, but the data stored in ES for each rule should match the response given by the endpoint, i.e. the normalized in-memory value and the stored value of the rule should be the same. +- **Find Rules - `GET /rules/_find`**: transforms rules in response to `RuleResponse` type with the `internalRuleToAPIResponse` method. +- **Read Rule - GET /rules:**: transforms rule in response to `RuleResponse` type with the `internalRuleToAPIResponse` method. +- **Delete Rules - DELETE /rules**: transforms rule in response to `RuleResponse` type with the `internalRuleToAPIResponse` method. +- **Bulk Actions** - `POST /rules/_bulk_action`: all other action types not mentioned in the previous section will perform normalization-on-read before responding: + - Enable + - Disable + - Delete + - Export: see Importing and Exporting Rules section below +- **Export Rules** - `POST /rules/_export`: + - this endpoint is unused via the UI, but might still be used via the public API + - same logic as for `_bulk_action` with the `export` action explained in section [Exporting rules](#exporting-rules) below: only normalization-on-read will be performed before writing to the output `ndjson` file. + +### Technical implementation of migration-on-write + +The logic for the migration of the rule saved objects, which means the determination of the `immutable` and `prebuilt` fields before writing to ES, will be encapsulated in three helper methods: + +- `migratePrebuiltSchemaOnRuleCreation` for rule creation +- `migratePrebuiltSchemaOnRuleUpdate` for rule updates (including patching) +- `migratePrebuiltSchemaOnRuleBulkEdit` for bulk rule updates + +These three migrations applied to the handler logic of our endpoints will cover all endpoints and use cases where we want to perform migration-on-write. + +Same as the normalization helper, these three helpers will have a return type of: + +```ts +interface MigrationResponse { + immutable: IsRuleImmutable; + prebuilt?: Prebuilt; +} +``` + +#### `migratePrebuiltSchemaOnRuleCreation` + +This migration method will apply to the following use cases and endpoints: + +- Updating a prebuilt rule when there is a rule type change + - **Perform Rule Upgrade** - `POST /prebuilt_rules/upgrade/_perform` (Internal) + - **(LEGACY) Install Prebuilt Rules And Timelines** - `PUT /rules/prepackaged` +- Importing a rule/prebuilt rule without overwriting an existing rule + - **Import Rules** - `POST /rules/_import` +- Duplicating an existing rule + - **Bulk Actions endpoint** - `POST /rules/_bulk_action` (bulk duplicate action) + +Other non-migration scenarios and endpoints to which this helper will apply to are: + +- Installing a prebuilt rule: + - **Perform Rule Installation** - `POST /prebuilt_rules/install/_perform` (Internal) +- Creating a custom rule: + - **Create Rules** - `POST /rules` +- Bulk creating custom rules: + - **Bulk Create Rules** - `POST /rules/_bulk_create` + +_Source: x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/normalization/prebuilt_rule_schema_migrations.ts_ (New file) + +```ts +interface PrebuiltSchemaCreationMigrationProps { + input: CreateAPIInput; + isRuleToCreatePrebuilt: boolean; +} + +const getPrebuiltValueForRuleCreation = ( + input: CreateAPIInput, + isRuleToCreatePrebuilt: boolean +): Prebuilt | undefined => { + if (!isRuleToCreatePrebuilt) { + return undefined; + } + + if (input.prebuilt != null) { + return input.prebuilt; + } + + return { + isCustomized: false, + elasticUpdateDate: input.elasticUpdateDate, + }; +}; + +export const migratePrebuiltSchemaOnRuleCreation = ({ + input, + isRuleToCreatePrebuilt, +}: PrebuiltSchemaCreationMigrationProps): MigrationResponse => { + const immutable = isRuleToCreatePrebuilt; + const prebuilt = getPrebuiltValueForRuleCreation(input, isRuleToCreatePrebuilt); + + return { + immutable, + prebuilt, + }; +}; +``` + +In the code shown above, the `immutable` field is set to a boolean which equals the value of the passed `isRuleToCreatePrebuilt` boolean argument. The value of that argument will be passed as `true` or `false` depending on the use case: + +- creating a custom rule: `false` +- installing a prebuilt rule: `true` +- updating a prebuilt rule when there is a rule type change: `true` +- importing a rule: can be `true` or `false` depending on the imported rule + +The `prebuilt` field will be set in the following way: (see `getPrebuiltValueForRuleCreation` above) + +- set to `undefined` if the `isRuleToCreatePrebuilt` is parameter is `false`. Use case when: + - creating a custom rule +- if `isRuleToCreatePrebuilt` is passed as `true`: + - set it to `input.prebuilt` if defined. Use case when: + - importing a prebuilt rule + - updating a prebuilt rule with a rule type change + - set it to a new object with `isCustomized` set to `false` and `elasticUpdateDate` to the passed input, if it exists. Use case when: + - installing a prebuilt rule from scratch. In this case, `elasticUpdateDate` will come from the `PrebuiltRuleAsset` (or be undefined in historical version of rules). + +##### `convertCreateAPIToInternalSchema` and `createRules` + +For the first two use cases listed above ("Updating a prebuilt rule when there is a rule type change" and "Importing a rule/prebuilt rule without overwriting an existing rule") the `migratePrebuiltSchemaOnRuleCreation` helper method will be called by the `convertCreateAPIToInternalSchema` rule converter method, which transforms our API schema to the internal rule schema before saving to ES. We need to modify this method in the following way: + +_Source: [x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/normalization/rule_converters.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/normalization/rule_converters.ts)_ + +```ts +// [... file continues above ...] + +export type CreateAPIInput = RuleCreateProps & { + related_integrations?: RelatedIntegrationArray; + required_fields?: RequiredFieldArray; + setup?: SetupGuide; + prebuilt?: Prebuilt; + elasticUpdateDate?: ElasticUpdateDate; +}; + +// eslint-disable-next-line complexity +export const convertCreateAPIToInternalSchema = ( + input: CreateAPIInput, + isRuleToCreatePrebuilt = false +): InternalRuleCreate => { + // [...] + + const { immutable, prebuilt } = migratePrebuiltSchemaOnRuleCreation({ + input, + isRuleToCreatePrebuilt, + }); + + return { + name: input.name, + params: { + // [... other params ...] + immutable, + prebuilt, + // [... other params ...] + ...typeSpecificParams, + }, + actions, + }; +}; + +// [... file continues below ...] +``` + +Notice that the type for the `input` has been expaned to include the `prebuilt` field (which can now be passed in the case of importing rules), and the `elasticUpdateDate` (which is needed when installing a prebuilt rule from scratch). Additionally, the new `isRuleToCreatePrebuilt` parameter is passed to the helper, defaulting to `false`. + +Finally, the `convertCreateAPIToInternalSchema` helper is called by two different use cases: + +1. by the **Preview Rule - POST /detection_engine/rules/preview** endpoint, where no changes are needed. +2. by the `createRules` method, which will be modified in the following way: + +_Source: [x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/crud/create_rules.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/crud/create_rules.ts)_ + +```ts +// [... file continues above ...] + +export interface CreateRulesOptions { + rulesClient: RulesClient; + params: T; + id?: string; + isPrebuilt?: boolean; // renamed from "immutable" + defaultEnabled?: boolean; + allowMissingConnectorSecrets?: boolean; +} + +// New prop types with extended fields for allowing imports +type RuleCreateAndImportProps = RuleCreateProps & { + prebuilt?: Prebuilt; + immutable?: IsRuleImmutable; +}; + +const getIsRuleToCreatePrebuilt = ( + params: RuleCreateAndImportProps, + isPrebuilt?: boolean +): boolean => { + // If createRules is explicitly called with isPrebuilt, use that value. + // Use case when creating a custom rule or installing/updating a prebuilt rule. + if (isPrebuilt != null) { + return isPrebuilt; + } + + // Otherwise, check the passed prebuilt or immutable params for existence. + // Use case when importing a rule. Default to false if neither are passed. + return (Boolean(params.prebuilt) || params.immutable) ?? false; +}; + +export const createRules = async ({ + rulesClient, + params, + id, + isPrebuilt = false, // renamed from "immutable" +}: CreateRulesOptions): Promise> => { + const isRuleToCreatePrebuilt = getIsRuleToCreatePrebuilt(params, isPrebuilt); + const internalRule = convertCreateAPIToInternalSchema( + params, + isRuleToCreatePrebuilt, + defaultEnabled + ); + const rule = await rulesClient.create({ + // [...] + data: internalRule, + // [...] + }); + + return rule; +}; +``` + +Notice in the code above that the new optional `isPrebuilt` parameter, which replaces `immutable`: this can be used when we know with certainity whether the rule we are creating is prebuilt or not. We know this when: + +- creating a custom rule: the `isPrebuilt` argument should be `false` +- creating (installing) or updating a prebuilt rule: the `isPrebuilt` argument should be `true` + +However, when importing rules, we now don't have certaintiy whether the created rule should be prebuilt or not. In order to determine that, we should use the values passed in the `ndjson` file for the `prebuilt` field, or the `immutable` field, as backwards compatibility fallback. + +This logic is encapsulated in the `getIsRuleToCreatePrebuilt` method above. + +Notice, as well, that the `params` types have been extended to a new `RuleCreateAndImportProps` type to take in: + +- the `prebuilt` property, since when importing a prebuilt rule, this will be the value used for: + - for determining if a rule that is being imported is prebuilt or not + - setting the `prebuilt` field when creating the imported prebuilt rule. +- the `immutable` property, to decide whether a rule that is being imported is prebuilt or not (when the rule has not been migrated and has the old schema) + +##### `duplicateRule` + +The other use case for `migratePrebuiltSchemaOnRuleCreation` is when duplicating a rule via the **Bulk Actions endpoint** (`POST /rules/_bulk_action`) with a bulk duplicate action. + +In this case, we will need to modify the `duplicateRule` helper that is used in that endpoint handler and make use of `migratePrebuiltSchemaOnRuleCreation`: + +_Source: [x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/actions/duplicate_rule.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/actions/duplicate_rule.ts)_ + +```ts +// [... file continues above ...] +import { migratePrebuiltSchemaOnRuleCreation } from '../../normalization/prebuilt_rule_schema_migrations'; +import { internalRuleToAPIResponse } from '../../normalization/rule_converters'; + +// [...] + +export const duplicateRule = async ({ rule }: DuplicateRuleParams): Promise => { + // Generate a new static ruleId + const ruleId = uuidv4(); + + const isRuleToCreatePrebuilt = Boolean(rule.params.prebuilt) || rule.params.immutable; + + // [...] + + // Transform rule from internal to API format to pass + // it to the migration function with the correct types. + const ruleResponse = internalRuleToAPIResponse(rule); + const { immutable, prebuilt } = migratePrebuiltSchemaOnRuleCreation({ + input: ruleResponse, + isRuleToCreatePrebuilt, + }); + + return { + name: `${rule.name} [${DUPLICATE_TITLE}]`, + // [...] + params: { + ...rule.params, + immutable, + prebuilt, + // [...] + }, + // [...] + }; +}; +``` + +Notice in the code above, the `rule` object passed into the `duplicateRule` function is in the internal rule schema format, so we need to use `internalRuleToAPIResponse` to convert it and pass it intoo `migratePrebuiltSchemaOnRuleCreation` in the expected format, in order calculate the values of `immutable` and `prebuilt`. + +#### `migratePrebuiltSchemaOnRuleUpdate` + +This migration method will apply to the following use cases and endpoints: + +- **Rule Update**: + - Updating a rule via the rule editing page (or directly via API) + - **Update Rule** - `PUT /rules` + - Bulk updating rules via API + - **Bulk Update Rules** - `PUT /rules/_bulk_update` +- **Rule Patch**: + - Updating a prebuilt rule when there's NO rule type change: + - **Perform Rule Upgrade** - `POST /prebuilt_rules/upgrade/_perform` (Internal) + - **(LEGACY) Install Prebuilt Rules And Timelines** - `PUT /rules/prepackaged` + - Importing a rule/prebuilt rule overwriting an existing rule: + - **Import Rules** - `POST /rules/_import` + +Other non-migration scenarios and endpoints to which this helper will apply to are: + +- Managing shared exception lists + - **Patch Rule** - `PATCH /rules` +- Bulk patching rules (only via API) + - **Bulk Patch Rules** - `PATCH /rules/_bulk_update` (deprecated) +- Creating rule exceptions + - **Create Rule Exceptions** - `POST /rules/{id}/exceptions` + +_Source: x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/normalization/prebuilt_rule_schema_migrations.ts_ (New file) + +```ts +interface PrebuiltSchemaUpdateMigrationProps { + nextParams?: PatchAPINextParams; + existingParams: RuleParams; + isRuleCustomizedDuringUpdate: boolean; +} + +const getPrebuiltValueForRuleUpdate = ({ + nextParams, + existingParams, + isRuleCustomizedDuringUpdate, +}: PrebuiltSchemaUpdateMigrationProps): Prebuilt | undefined => { + if (nextParams?.prebuilt) { + return nextParams?.prebuilt; + } + + if (existingParams.prebuilt) { + return { + ...existingParams.prebuilt, + isCustomized: existingParams.prebuilt.isCustomized || isRuleCustomizedDuringUpdate, + }; + } + + if (existingParams.immutable) { + return { + isCustomized: isRuleCustomizedDuringUpdate, + }; + } + + return undefined; +}; + +export const migratePrebuiltSchemaOnRuleUpdate = ({ + nextParams, + existingParams, + isRuleCustomizedDuringUpdate, +}: PrebuiltSchemaUpdateMigrationProps): MigrationResponse => { + const immutable = (Boolean(existingParams.prebuilt) || existingParams.immutable) ?? false; + const prebuilt = getPrebuiltValueForRuleUpdate({ + nextParams, + existingParams, + isRuleCustomizedDuringUpdate, + }); + + return { + immutable, + prebuilt, + }; +}; +``` + +Notice that the `nextParams` argument of the `migratePrebuiltSchemaOnRuleUpdate` is optional: this is because this method can be used for both **patching** rules, where `nextParams` contains data that is needed for the calculation of the `prebuilt` and `immutable` fields, but also for the **updating** rules use case, when only the `existingParams` are necessary to calculate those fields. + +The logic for defining the `immutable` and `prebuilt` fields, implemented in the code above, is as follows: + +- for `immutable`: + + - if the `prebuilt` field exists in the existing rule, `immutable` should be `true`. + - Use case 1: updating an already migrated custom or prebuilt rule + - Use case 2: importing (and overwriting) a rule that has a `prebuilt` field in the `ndjson` file payload + - otherwise, rely on the value of the existing rule's `immutable` field. Use case: + - Use case 3: updating a custom or prebuilt rule that hasn't yet been migrated + - Use case 4: importing (and overwriting) a rule that has a `immutable` field but no `prebuilt` field in the `ndjson` file payload + - if both are undefined, default to `false`: + - Use case 5: importing (and overwriting) a rule that has no `prebuilt` or `immutable` fields in the `ndjson` file payload. + - Notice that for calculating `immutable` we don't rely on `nextParams` because a rule should never change from custom to prebuilt, or viceversa. + +- for `prebuilt` - see `getPrebuiltValueForRuleUpdate` method above: + + - take the `prebuilt` field as passed in the `nextParams`, if the object exists: + + - Use case 1: importing (and overwriting) a rule that has a `prebuilt` field in the `ndjson` file payload + - Use case 2: updating a prebuilt rule with no rule type change (TODO: the prebuilt object has to be built in the `upgradePrebuiltRules` and passed in the next params. Create a function that build it and show changes in this RFC) + + - If that is undefined, take the value from `prebuilt` from the `existingParams`, but with an updated value for `isCustomized`. This value should be true if the existing rule has already that prop as true, or if the rule was customized during the patch procedure (`isRuleCustomizedDuringUpdate` value passed as argument to `migratePrebuiltSchemaOnRuleUpdate`): + - Use case 3: patching already-migrated rules via API (`prebuilt` already exists in schema) + - If both `nextParams.prebuilt` and `existingParams.prebuilt` are undefined: check the value for the `immutable` field of the existing rule: + - if `immutable: true`: create a new `prebuilt` object where `isCustomized` has the value of `isRuleCustomizedDuringUpdate` and `elasticUpdateDate` is undefined: + - Use case 4: patching a non-migrated prebuilt rule via API + - if `immutable: false`, `prebuilt` should be undefined. + - Use case 5: patching a non-migrated custom rule via API + +This helper method will be called by two diffent functions: + +1. the `convertPatchAPIToInternalSchema` rule converter method, used in the use cases listed as **Rule Patch** at the beggining of this section +2. the `updateRules` method, used in the use cases listed as **Rule Update** at the beggining of this section + +```mermaid +graph TD; + +subgraph Call Stack + updateRules -->|calls| migratePrebuiltSchemaOnRuleUpgrade + patchRules -->|calls| convertPatchAPIToInternalSchema + convertPatchAPIToInternalSchema -->|calls| migratePrebuiltSchemaOnRuleUpgrade + migratePrebuiltSchemaOnRuleUpgrade +end +``` + +##### `convertPatchAPIToInternalSchema` and `patchRules` + +We need to modify the `convertPatchAPIToInternalSchema` in the following way: + +_Source: [x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/normalization/rule_converters.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/normalization/rule_converters.ts)_ + +```ts +// [... file continues above ...] +export type PatchAPINextParams = PatchRuleRequestBody & { + related_integrations?: RelatedIntegrationArray; + required_fields?: RequiredFieldArray; + setup?: SetupGuide; + prebuilt?: Prebuilt; +}; + +export const convertPatchAPIToInternalSchema = ( + nextParams: PatchAPINextParams, + existingRule: SanitizedRule, + isRuleCustomizedDuringUpdate = false +): InternalRuleUpdate => { + const typeSpecificParams = patchTypeSpecificSnakeToCamel(nextParams, existingRule.params); + const existingParams = existingRule.params; + + // [...] + + const { immutable, prebuilt } = migratePrebuiltSchemaOnRuleUpdate({ + nextParams, + existingParams, + isRuleCustomizedDuringUpdate, + }); + + return { + name: nextParams.name ?? existingRule.name, + tags: nextParams.tags ?? existingRule.tags, + params: { + // [...] + immutable, + prebuilt, + // [...] + ...typeSpecificParams, + }, + // [...] + }; +}; +// [... file continues above ...] +``` + +Notice that the type for the `nextParams` has been expaned to include the `prebuilt` field (which can now be passed in the case of importing rules). Additionally, the new `isRuleToCreatePrebuilt` parameter is passed to the helper, defaulting to `false`. + +The `convertPatchAPIToInternalSchema` helper is called only by the `patchRules` method, which will be modified in the following way: + +_Source:[x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/crud/patch_rules.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/crud/patch_rules.ts)_ + +```ts +// [... file continues above ...] + +import { convertPatchAPIToInternalSchema } from '../../normalization/rule_converters'; + +export interface PatchRulesOptions { + rulesClient: RulesClient; + nextParams: PatchRuleRequestBody & { + related_integrations?: RelatedIntegrationArray; + required_fields?: RequiredFieldArray; + setup?: SetupGuide; + prebuilt?: Prebuilt; // extend nextParams with `prebuilt` property + }; + existingRule: RuleAlertType | null | undefined; + isRuleCustomizedDuringUpdate?: boolean; // pass in new optional boolean +} + +export const patchRules = async ({ + rulesClient, + existingRule, + nextParams, + isRuleCustomizedDuringUpdate, +}: // [...] +PatchRulesOptions): Promise | null> => { + // [...] + + const patchedRule = convertPatchAPIToInternalSchema( + nextParams, + existingRule, + isRuleCustomizedDuringUpdate + ); + + const update = await rulesClient.update({ + id: existingRule.id, + data: patchedRule, + // [...] + }); + + // [...] +}; +``` + +As seen in the snippet above, the type of the arguments of `patchRule` method, `PatchRulesOptions` will need to be updated as well, in order to allow passing the new `prebuilt` field in its `nextParams` property, as well as the `isRuleCustomizedDuringUpdate` boolean. + +The method `patchRule` is used in all use cases mentioned at the beggining of this section, so we have covered all of them with the correspondent migration. + +##### `updateRules` + +The `updateRules` method is used only in the Update and Bulk Update endpoints. It needs to be updated to make use of `migratePrebuiltSchemaOnRuleUpdate`: + +_Source: [x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/crud/update_rules.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/crud/update_rules.ts)_ + +```ts +// [... file continues above...] +import { migratePrebuiltSchemaOnRuleUpdate } from '../../normalization/prebuilt_rule_schema_migrations'; + +export interface UpdateRulesOptions { + rulesClient: RulesClient; + existingRule: RuleAlertType | null | undefined; + ruleUpdate: RuleUpdateProps; +} + +export const updateRules = async ({ + rulesClient, + existingRule, + ruleUpdate, +}: UpdateRulesOptions): Promise | null> => { + // [...] + + // Calculate whether the rule was customized during the update + // TODO: Explain how this is calculated in all cases where it needs to be, in its own section + const isRuleCustomizedDuringUpdate = getIsRuleCustomizedDuringUpdate(existingRule, ruleUpdate); + + // Calculate the values of immutable and prebuilt based on the existing params + // and the isRuleCustomizedDuringUpdate boolean + const { immutable, prebuilt } = migratePrebuiltSchemaOnRuleUpdate({ + existingParams: existingRule.params, + isRuleCustomizedDuringUpdate, + }); + + const newInternalRule: InternalRuleUpdate = { + name: ruleUpdate.name, + // [...] + params: { + // [...] + immutable, + prebuilt, + // [...] + ...typeSpecificParams, + }, + // [...] + }; + + const update = await rulesClient.update({ + id: existingRule.id, + data: newInternalRule, + }); + + // [...] + return { ...update, enabled }; +}; +``` + +#### `migratePrebuiltSchemaOnRuleBulkEdit` + +This migration method will apply to the following use case and endpoints: + +- Bulk updating rules: + - Bulk adding or deleting index patterns + - Bulk adding or deleting tags + - Updating rule schedules + - Adding rules actions // _(TODO: Should this define prebuilt.isCustomized? The current rulesClient implementation counts it as a rule modification, but it looks like we shouldn't. Separating this from other types of modification will need some further work on the rulesClient side.)_ + - **Bulk Actions endpoint** - `POST /rules/_bulk_action` (bulk edit action) + +In contrast with the other migration methods, we will use the new `migratePrebuiltSchemaOnRuleBulkEdit` within the Alerting Framework's `RuleClient` since we need to migrate the rule's `prebuilt` and `immutable` parameters before the `RuleClient` does the saving of the rule into Elasticsearch. + +This however, gives us the advantage that the `RuleClient` already includes logic to calculate if a rule's attributes or parameters have been modified from its initial values, so we can rely on that to calculate the `prebuilt.isCustomized` field during the update. + +_Source: x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/normalization/prebuilt_rule_schema_migrations.ts_ (New file) + +```ts +import { RuleParams } from '../../../types'; + +const getPrebuiltValueForRuleBulkEdit = ( + ruleParams: RuleParams, + isRuleUpdatedDuringBulkUpdate: boolean +) => { + if (ruleParams?.prebuilt) { + return { + ...ruleParams.prebuilt, + isCustomized: ruleParams.prebuilt.isCustomized || isRuleUpdatedDuringBulkUpdate, + }; + } + + if (ruleParams.immutable) { + return { + isCustomized: isRuleUpdatedDuringBulkUpdate, + }; + } + + return undefined; +}; + +export const migratePrebuiltSchemaOnRuleBulkEdit = ( + ruleParams: RuleParams, + isRuleUpdatedDuringBulkUpdate: boolean +) => { + const immutable = Boolean(ruleParams.prebuilt) || ruleParams.immutable; + const prebuilt = getPrebuiltValueForRuleBulkEdit(ruleParams, isRuleUpdatedDuringBulkUpdate); + + ruleParams.prebuilt = prebuilt; + ruleParams.immutable = immutable; +}; +``` + +Notice that here we are migrating the `ruleParams` in-place; the object is later used to save the updated rules into Elasticsearch. + +The `RulesClient` class has a `bulkEdit` method, which is called by our **Bulk Actions endpoint** `POST /rules/_bulk_action`. That method includes complex logic, but we can focus on the `updateRuleAttributesAndParamsInMemory` method, where the rule attributes and parameters are updated before being saved to ES. This function also calculates the booleans `isAttributesUpdateSkipped` and `isParamsUpdateSkipped` which we can leverage to set the `prebuilt.isCustomized` field in our params. + +_Source: [x-pack/plugins/alerting/server/application/rule/methods/bulk_edit/bulk_edit_rules.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/alerting/server/application/rule/methods/bulk_edit/bulk_edit_rules.ts)_ + +```ts +export async function bulkEditRules() { + // calls bulkEditRulesOcc() +} + +function bulkEditRulesOcc() { + // calls updateRuleAttributesAndParamsInMemory() +} +async function updateRuleAttributesAndParamsInMemory( + { + // [...] + } +): Promise { + try { + // [...] + + const { + rule: updatedRule, + // [...] + isAttributesUpdateSkipped, + } = await getUpdatedAttributesFromOperations({ + // [...] + }); + + // [...] + + const { modifiedParams: ruleParams, isParamsUpdateSkipped } = paramsModifier + ? await paramsModifier(updatedRule.params) + : { + modifiedParams: updatedRule.params, + isParamsUpdateSkipped: true, + }; + + // [...] + + const isRuleUpdated = !(isAttributesUpdateSkipped && isParamsUpdateSkipped); + + // Migrate `ruleParams.prebuilt` and `ruleParams.immutable` in-place + migratePrebuiltSchemaOnRuleBulkEdit(ruleParams, isRuleUpdated); + + // [...] + } catch (error) { + // [...] + } +} +``` + +--- + +## Endpoints and utilities that will need to be adapted to the new schema + +### Utilities + +#### KQL filters and the `convertRulesFilterToKQL` method + +Across our application, both in the frontend and serverside, we use KQL filters to retrieve rules based on whether they are prebuilt rules or not - this means that the current behaviour of these values relies on the `immutable` field being set to either `true` or `false`. + +As we have mentioned before, we need to assume that at any point in time, there will be a mixture of rules whose saved object has already been migrated on Elasticsearch and others will not. This means that the retrieval of rules will need to maintain backwards compatibility: in order to determine if a rule is prebuilt, preferentially search for the existence of the `prebuilt` field; if that doesn't exist, fallback to the legacy logic of checking a rule's `immutable` value. + +This means that we will need to update the constants and KQL filters that we have hardcoded in our application to reflect the new schema: + +_Source: [x-pack/plugins/security_solution/common/detection_engine/rule_management/rule_fields.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/common/detection_engine/rule_management/rule_fields.ts)_ + +```ts +// [... file continues above...] + +export const PARAMS_IMMUTABLE_FIELD = 'alert.attributes.params.immutable'; +export const PARAMS_PREBUILT_FIELD = 'alert.attributes.params.prebuilt'; // new constant +export const PARAMS_PREBUILT_IS_CUSTOMIZED_FIELD = 'alert.attributes.params.prebuilt.isCustomized'; // new constant +``` + +And we will need to update the `x-pack/plugins/security_solution/common/detection_engine/rule_management/rule_filtering.ts` file, where the `convertRulesFilterToKQL` method is defined. This method is used both in the frontend and in the serverside, and translates rule filter options to KQL filters that Elasticsearch can understand. + +Here, we need to update the KQL filters and the logic for fetching Elastic prebuilt and custom rules, relying on `prebuilt` but with fallback to `immutable`: + +_Source: [x-pack/plugins/security_solution/common/detection_engine/rule_management/rule_filtering.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/common/detection_engine/rule_management/rule_filtering.ts)_ + +```ts +// [... file continues above...] + +// KQL does not allow to search for existence of the prebuilt object field by itself, since params is unmapped +// so we need to search for the existence of the isCustomized subfield instead, which is required +export const KQL_FILTER_PREBUILT_RULES = `${PARAMS_PREBUILT_IS_CUSTOMIZED_FIELD}: *`; +export const KQL_FILTER_CUSTOM_RULES = `NOT ${PARAMS_PREBUILT_IS_CUSTOMIZED_FIELD}: *`; +export const KQL_FILTER_IMMUTABLE_RULES = `${PARAMS_IMMUTABLE_FIELD}: true`; +export const KQL_FILTER_MUTABLE_RULES = `${PARAMS_IMMUTABLE_FIELD}: false`; + +interface RulesFilterOptions { + filter: string; + showCustomRules: boolean; + showElasticRules: boolean; + ... +} + +export function convertRulesFilterToKQL({ + filter: searchTerm, + showCustomRules, + showElasticRules, + ... +}: Partial): string { + const kql: string[] = []; + + // [... file continues ...] + + if (showCustomRules && showElasticRules) { + // if both showCustomRules && showElasticRules selected we omit filter, as it includes all existing rules + } else if (showElasticRules) { + kql.push(`(${KQL_FILTER_PREBUILT_RULES} OR ${KQL_FILTER_IMMUTABLE_RULES})`); + } else if (showCustomRules) { + kql.push(`(${KQL_FILTER_CUSTOM_RULES} OR ${KQL_FILTER_MUTABLE_RULES})`); + } + + // [... file continues below...] +``` + +Ntocie that in order to retrieve rules in which the `alert.attributes.params.prebuilt` field exists, we must rely instead on the existence of `alert.attributes.params.prebuilt.isCustomized`. This is so because the `prebuilt` field lives inside the unmapped `params` field, and KQL syntax does not allow searching for the existence of an object like `prebuilt` with the recommended syntax `alert.attributes.params.prebuilt: *`. + +But we can use the `prebuilt` field's `isCustomized` subfield instead, which will always exist within the object (it is required) and replace the KQL filter for `alert.attributes.params.prebuilt.isCustomized: *`. + +### Rule Management endpoints + +- **Create Rules** - `POST /rules` and **Bulk Create Rules** - `POST /rules/_bulk_create`: + +Currently, we don't support the `immutable` field in any of the endpoints' request parameters (except for the Import endpoint). We shouldn't support the `prebuilt` field either, because this value should be controlled by the app on the server side, and not by users. + +This is so because we will never want users to be able to create their own prebuilt rules, only install them, import them, and customize them. Also, a prebuilt rule should always be able to be compared to a `security-rule` asset distributed by Fleet, and receive updates from it, which would not be possible if a user creates its own prebuilt rules. + +Specifically, these two endpoints should be able to create only custom rules which means their `params` will look like: + +```ts +// [PSEUDOCODE] +{ + immutable: false, + // prebuilt should not be in the created rule object, + // since this endpoint should only create custom rules +} +``` + +Both endpoints used the already discussed `createRules` method to create rules. The only changes needed for both are explicitly passing the new `isPrebuilt` argument as `false`: + +_Source: [x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/create_rule/route.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/create_rule/route.ts)_ + +```ts +// [... file continues above ...] + +export const createRuleRoute = ( + router: SecuritySolutionPluginRouter, + ml: SetupPlugins['ml'] +): void => { + router.versioned + .post({ + access: 'public', + path: DETECTION_ENGINE_RULES_URL, + // [...] + }) + .addVersion( + { + // [...] + }, + async (context, request, response): Promise> => { + // [...] + try { + // [...] + + const createdRule = await createRules({ + rulesClient, + params: request.body, + isPrebuilt: false, // <-------- explicitly pass isPrebuilt: false + }); + + +// [... file continues below ...] +``` + +_Source: [x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_create_rules/route.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_create_rules/route.ts)_ + +```ts +export const bulkCreateRulesRoute = ( + router: SecuritySolutionPluginRouter, + // [...] +) => { + router.versioned + .post({ + access: 'public', + path: DETECTION_ENGINE_RULES_BULK_CREATE, + // [...] + }) + .addVersion( + { + // [...] + }, + async (context, request, response): Promise> => { + // [...] + const createdRule = await createRules({ + rulesClient, + params: payloadRule, + isPrebuilt: false, // <-------- explicitly pass isPrebuilt: false + }); +``` + +- **Rule Management Filters** - `GET /rules/_rule_management_filters` (Internal): + +This endpoint currently depends on rules `alert.attributes.params.immutable` to fetch number of custom rules and number of prebuilt rules. We need to adapt its logic to rely on new `alert.attributes.params.prebuilt` field, with fallback to the original, for backwards compatibility. + +Specifically, the endpoint handler uses the [`findRules` utility](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/search/find_rules.ts) to fetch rules based on their `immutable` param. + +This needs to be changed so that we rely on the `prebuilt` param, but fallback to `immutable` if that parameter doesn't exist - i.e., in the case of non-migrated-on-write rules. We need to modify the KQL queries in a similar way to the already described: + +_Source: [x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/filters/route.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/filters/route.ts)_ + +```ts +// [... file continues above ...] + +async function fetchRulesCount(rulesClient: RulesClient): Promise { + const [prebuiltRules, customRules] = await Promise.all([ + findRules({ + ...DEFAULT_FIND_RULES_COUNT_PARAMS, + rulesClient, + filter: `${KQL_FILTER_PREBUILT_RULES} OR ${KQL_FILTER_IMMUTABLE_RULES}`, + }), + findRules({ + ...DEFAULT_FIND_RULES_COUNT_PARAMS, + rulesClient, + filter: `${KQL_FILTER_CUSTOM_RULES} OR ${KQL_FILTER_MUTABLE_RULES}`, + }), + ]); + + return { + prebuilt: prebuiltRules.total, + custom: customRules.total, + }; +} +// [... file continues below ...] +``` + +The constants `KQL_FILTER_PREBUILT_RULES`, `KQL_FILTER_IMMUTABLE_RULES`,`KQL_FILTER_CUSTOM_RULES` and `KQL_FILTER_MUTABLE_RULES` are imported from `x-pack/plugins/security_solution/common/detection_engine/rule_management/rule_filtering.ts`. + +- **Coverage Overview** - `/rules_coverage_overview` (Internal): This endpoint is called to retrieve the data that populates the MITRE Coverage Overview table, and currently depends on the `immutable` field to fetch the user's installed rules. + +Similarly to what was described in the previous endpoint, we should update the logic so that we rely on the `prebuilt` param, but fallback to `immutable` if that parameter doesn't exist - i.e., in the case of non-migrated-on-write rules. + +This endpoint handler also uses the [`findRules` utility](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/search/find_rules.ts) to fetch rules, but the KQL filter that is passed to that utility is created by the reusable [`convertRulesFilterToKQL` utility function](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/common/detection_engine/rule_management/rule_filtering.ts): + +_Source: [x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/coverage_overview/handle_coverage_overview_request.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/coverage_overview/handle_coverage_overview_request.ts)_ + +```ts +// [... file continues above...] + +export async function handleCoverageOverviewRequest({ + params: { filter }, + deps: { rulesClient }, +}: HandleCoverageOverviewRequestArgs): Promise { + const activitySet = new Set(filter?.activity); + const kqlFilter = convertRulesFilterToKQL({ + filter: filter?.search_term, + showCustomRules: filter?.source?.includes(CoverageOverviewRuleSource.Custom) ?? false, + showElasticRules: filter?.source?.includes(CoverageOverviewRuleSource.Prebuilt) ?? false, + enabled: getIsEnabledFilter(activitySet), + }); + + const rules = await findRules({ + rulesClient, + filter: kqlFilter, + fields: ['name', 'enabled', 'params.threat'], + page: 1, + perPage: 10000, + sortField: undefined, + sortOrder: undefined, + }); + + // [... file continues below...] +``` + +We therefore need to modify the `convertRulesFilterToKQL` utility logic as was described in the section above: [KQL filters and the `convertRulesFilterToKQL` method](#kql-filters-and-the-convertrulesfiltertokql-method) + +### Prebuilt Rules endpoints + +- [**(LEGACY) Get Prebuilt Rules and Timeline Status** - `/rules/prepackaged/_status`](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/get_prebuilt_rules_and_timelines_status/get_prebuilt_rules_and_timelines_status_route.ts) + +This currently depends on rules `alert.attributes.params.immutable` to fetch the number of custom rules and number of prebuilt rules. We need to adapt this filters to rely on new `alert.attributes.params.prebuilt` field, with fallback to the original, for backwards compatibility: + +_Source: [x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/get_prebuilt_rules_and_timelines_status/get_prebuilt_rules_and_timelines_status_route.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/get_prebuilt_rules_and_timelines_status/get_prebuilt_rules_and_timelines_status_route.ts)_ + +```ts +// [... file continues above...] + +export const getPrebuiltRulesAndTimelinesStatusRoute = ( + router: SecuritySolutionPluginRouter, + security: SetupPlugins['security'] +) => { + router.versioned + .get({ + access: 'public', + path: PREBUILT_RULES_STATUS_URL, + // [...] + }) + .addVersion( + { + version: '2023-10-31', + validate: false, + }, + async (context, request, response) => { + + // [...] + + const customRules = await findRules({ + rulesClient, + perPage: 1, + page: 1, + sortField: 'enabled', + sortOrder: 'desc', + filter: `${KQL_FILTER_PREBUILT_RULES} OR ${KQL_FILTER_IMMUTABLE_RULES}`, + fields: undefined, + }); + + const installedPrebuiltRules = rulesToMap( + await getExistingPrepackagedRules({ rulesClient }) // needs modifying as well + ); + +// [... file continues below...] +``` + +As explained above, this endpoint fetches the installed prebuilt rules, as well, using the `getExistingPrepackagedRules` reusable utility. This function needs to be modified as well: + +_Source: [x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/search/get_existing_prepackaged_rules.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/search/get_existing_prepackaged_rules.ts)_ + +```ts +[... file continues above...] + +export const getExistingPrepackagedRules = async ({ + rulesClient, +}: { + rulesClient: RulesClient; +}): Promise => { + return getRules({ + rulesClient, + filter: `${KQL_FILTER_PREBUILT_RULES} OR ${KQL_FILTER_IMMUTABLE_RULES}`, + }); +}; +``` + +- [**Get Prebuilt Rules Status** - `GET /prebuilt_rules/status` (Internal)](https://github.com/elastic/kibana/blob/test-serverless-env-test-deployment/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/get_prebuilt_rules_status/get_prebuilt_rules_status_route.ts) + +Uses `IPrebuiltRuleObjectsClient` to retrieve instances of prebuilt rules according to the `immutable` field. The Prebuilt Rule Objects client fetches prebuilt rules using the `getExistingPrepackagedRules` function mentioned above, so modifying it as described above will suffice: +_Source: [x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/rule_objects/prebuilt_rule_objects_client.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/rule_objects/prebuilt_rule_objects_client.ts)_ + +```ts +// [... file continues above...] + +export const createPrebuiltRuleObjectsClient = ( + rulesClient: RulesClient +): IPrebuiltRuleObjectsClient => { + return { + fetchAllInstalledRules: (): Promise => { + return withSecuritySpan('IPrebuiltRuleObjectsClient.fetchInstalledRules', async () => { + const rulesData = await getExistingPrepackagedRules({ rulesClient }); + const rules = rulesData.map((rule) => internalRuleToAPIResponse(rule)); + return rules; + }); + }, + +// [... file continues below...] +``` + +- [**(LEGACY) Install Prebuilt Rules And Timelines** - `PUT /rules/prepackaged`](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/install_prebuilt_rules_and_timelines/install_prebuilt_rules_and_timelines_route.ts) + +This endpoint fetches the installed prebuilt rules using the `getExistingPrepackagedRules` reusable utility, as well: + +_Source: [x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/install_prebuilt_rules_and_timelines/install_prebuilt_rules_and_timelines_route.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/install_prebuilt_rules_and_timelines/install_prebuilt_rules_and_timelines_route.ts)_ + +```ts +// [... file continues above...] + +export const installPrebuiltRulesAndTimelinesRoute = (router: SecuritySolutionPluginRouter) => { + router.versioned + .put({ + path: PREBUILT_RULES_URL, + // [...] + }) + .addVersion( + // [...] + async (context, _, response) => { + const siemResponse = buildSiemResponse(response); + + try { + const rulesClient = (await context.alerting).getRulesClient(); + + const validated = await createPrepackagedRules(/* [...] */) + + // [...] + + +export const createPrepackagedRules = async ( + // [...] + ): Promise => { + // [...] + + const installedPrebuiltRules = rulesToMap(await getExistingPrepackagedRules({ rulesClient })); + +// [... file continues below ...] +``` + +Therefore, modifying the `getExistingPrepackagedRules` function as described above will suffice. + +- **Installation and Upgrade `_review` and `_perform` endpoints:** + +All four endpoints use the Prebuilt Rule Saved Objects client (`IPrebuiltRuleObjectsClient`) to retrieve instances of prebuilt rules according to the `immutable` field. This needs to be modified as described in the **Get Prebuilt Rules Status** - `GET /prebuilt_rules/status` section above. + +Additionally: + +- [**Review Rule Installation** - `POST /prebuilt_rules/installation/_review` (Internal)](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/review_rule_installation/review_rule_installation_route.ts) + +This endpoint uses the `convertPrebuiltRuleAssetToRuleResponse` method, which takes in a prebuilt rule asset and converts it to an object of type `RuleResponse`. This method has to be modified so that new prebuilt rules objects are returned by the endpoint with a `prebuilt` object and a legacy `immutable` value of `true`. + +_Source: [x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/normalization/rule_converters.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/normalization/rule_converters.ts)_ + +```ts +// [... file continues above ...] + +export const convertPrebuiltRuleAssetToRuleResponse = ( + prebuiltRuleAsset: PrebuiltRuleAsset +): RuleResponse => { + const prebuiltRuleAssetDefaults = { + enabled: false, + // [... other prebuilt rule asset defaults ...] + }; + + const ruleResponseSpecificFields = { + id: uuidv4(), + // [... other prebuilt rule fields ...] + immutable: true, + prebuilt: { + isCustomized: false, + elasticUpdateDate: prebuiltRuleAsset.elasticUpdateDate, + }, + revision: 1, + }; + + return RuleResponse.parse({ + ...prebuiltRuleAssetDefaults, + ...prebuiltRuleAsset, + ...ruleResponseSpecificFields, + }); +}; +``` + +- [**Perform Rule Installation** - `POST /prebuilt_rules/installation/_install` (Internal)](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_installation/perform_rule_installation_route.ts) + +To install a new prebuilt rule, this endpoint uses the [`createPrebuiltRules` method](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/rule_objects/create_prebuilt_rules.ts), which in turn calls the [`createRules` method](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/crud/create_rules.ts). + +So when calling `createRules` within `createPrebuiltRules`, we need to explictly pass in the `isPrebuilt` property set to `true`: + +_Source: [x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/rule_objects/create_prebuilt_rules.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/rule_objects/create_prebuilt_rules.ts)_ + +```ts +// [... file continues above ...] + +export const createPrebuiltRules = (rulesClient: RulesClient, rules: PrebuiltRuleAsset[]) => + withSecuritySpan('createPrebuiltRules', async () => { + const result = await initPromisePool({ + concurrency: MAX_RULES_TO_UPDATE_IN_PARALLEL, + items: rules, + executor: async (rule) => { + return createRules({ + rulesClient, + params: rule, + isPrebuilt: true, // renamed from "immutable" + defaultEnabled: false, + }); + }, + }); + + return result; + }); +``` + +- [**Review Rule Upgrade** - `POST /prebuilt_rules/upgrade/_review` (Internal)](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/review_rule_upgrade/review_rule_upgrade_route.ts) + +This endpoint uses the `convertPrebuiltRuleAssetToRuleResponse` method to get a `RuleResponse`-type object from a target version of a rule provided from upstream. This method needs to be modified as described in the section that details the changes needed for the **Review Rule Installation** - `POST /prebuilt_rules/installation/_review`. + +An additional change will be needed within the route handler, when calculating the `targetRule` that is returned in the response. Since the `prebuilt` rule field is calculated by the `convertPrebuiltRuleAssetToRuleResponse` method, the `prebuilt.isCustomized` field would always be set to `false`, even when updating rules that have been previously customized. Therefore, the `prebuilt` field needs to be overwritten to take as its value for `prebuilt.isCustomized` the current value that is set in the currently installed rule, or default to false it that value doesn't yet exist: + +_Source: [x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/review_rule_upgrade/review_rule_upgrade_route.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/review_rule_upgrade/review_rule_upgrade_route.ts)_ + +```ts +// [... file continues above ...] + +const calculateRuleInfos = (results: CalculateRuleDiffResult[]): RuleUpgradeInfoForReview[] => { + return results.map((result) => { + const { ruleDiff, ruleVersions } = result; + const installedCurrentVersion = ruleVersions.input.current; + const targetVersion = ruleVersions.input.target; + + // [... file continues ...] + + const targetRule: RuleResponse = { + ...convertPrebuiltRuleAssetToRuleResponse(targetVersion), + // Overwrite the prebuilt object returned from convertPrebuiltRuleAssetToRuleResponse + // to account for the currently installed rule's value of `isCustomized`. + prebuilt: { + isCustomized: installedCurrentVersion.prebuilt?.isCustomized ?? false, + elasticUpdateDate: targetVersion.elasticUpdateDate, + }, + // [... other props ...] + }; + + return { + // [... other props ...] + current_rule: installedCurrentVersion, + target_rule: targetRule, + diff: { + /* [...] */ + }, + }; + }); +}; +``` + +This endpoint will need further changes, which will be detailed further down, and are out of the scope of Saved Object, migration and rule schema updates. + +- [**Perform Rule Upgrade** - `POST /prebuilt_rules/upgrade/_perform` (Internal)](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_upgrade/perform_rule_upgrade_route.ts) + +This endpoint will require major changes to add the capability of letting users selecting a custom version of the rule with custom values for rule fields. This will be explained further below in the "Changes to upgrade `_review` and `_perform` endpoints" section. + +The calculation of the value for the `prebuilt.isCustomized` field for the updated rule will depend on that logic as well, so its calculation will be explained in that section. + +However, once that value is calculated by the endpoint handler logic, we will need to pass it to the `upgradePrebuiltRules` method that is used by the handler to actually upgrade the rules. This method either patches existing rules -for the normal case-, or deletes an existing rule and recreates it if the rule underwent a type change during the upgrade (for example, the previous version of the rule had type of `query` and the new version is `eql`). + +The changes in the `upgradePrebuiltRules` method need to take into account both paths. In the endpoint logic handler, when calculating if the rule was customized by the user, we will create a boolean called `isRuleCustomizedDuringUpgrade`, that we will pass as an argument to `upgradePrebuiltRules`: + +_Source: [x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_upgrade/perform_rule_upgrade_route.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_upgrade/perform_rule_upgrade_route.ts)_ + +```ts +// [... file continues above ...] + +export const performRuleUpgradeRoute = (router: SecuritySolutionPluginRouter) => { + router.versioned + .post({ + access: 'internal', + path: PERFORM_RULE_UPGRADE_URL, + // [...] + }) + .addVersion( + { + // [...] + }, + async (context, request, response) => { + // [...] + + try { + // [...] + + // Endpoint will include logic for calculating which rule version should the current rule be upgraded to, + // as well as calculating the isRuleCustomizedDuringUpgrade boolean. + // Details explained further below in this document. + + // Perform the upgrade, but pass in `isRuleCustomizedDuringUpgrade` as an argument + const { results: updatedRules, errors: installationErrors } = await upgradePrebuiltRules( + rulesClient, + targetRules, + isRuleCustomizedDuringUpgrade + ); + // [...] + + return response.ok({ body }); + } catch (err) { + // [...] + } + } + ); +}; +``` + +And the `isRuleCustomizedDuringUpgrade` argument , which defaults to `false`, will be used as follows: + +_Source: [x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/rule_objects/upgrade_prebuilt_rules.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/rule_objects/upgrade_prebuilt_rules.ts)_ + +```ts +// [... file continues above ...] + +export const upgradePrebuiltRules = async ( + rulesClient: RulesClient, + rules: PrebuiltRuleAsset[], + isRuleCustomizedDuringUpgrade = false +) => { + // [...] + return upgradeRule(rulesClient, rule, isRuleCustomizedDuringUpgrade); + // [...] +} + + +const upgradeRule = async ( + rulesClient: RulesClient, + rule: PrebuiltRuleAsset + isRuleCustomizedDuringUpgrade: boolean +): Promise> => { + const existingRule = await readRules({ + // [...] + }); + + // [...] + + // Set the value to true if the rule was customized during + // the current update. Otherwise, take the existing value from + // the currently installed value. Default to false. + const isCustomized = + (isRuleCustomizedDuringUpgrade || existingRule.params.prebuilt?.isCustomized) ?? false; + const prebuilt = { + isCustomized, + elasticUpdateDate: rule.elasticUpdateDate, + } + + if (rule.type !== existingRule.params.type) { + await deleteRules({ + ruleId: existingRule.id, + rulesClient, + }); + + return createRules({ + rulesClient, + isPrebuilt: true, + params: { + ...rule, + prebuilt, + // [...] + }, + }); + } else { + await patchRules({ + rulesClient, + existingRule, + nextParams: { + ...rule, + prebuilt, + // [...] + }, + }); + + // [...] + } +}; +``` + +### Rule monitoring endpoints + +- [**Detection Engine Health: Get Cluster Health** - `GET or POST /detection_engine/health/_cluster` (internal):](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/api/detection_engine_health/get_cluster_health/get_cluster_health_route.ts) + +This endpoint uses the [Detection Engine Health Client (`IDetectionEngineHealthClient`)](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/detection_engine_health/detection_engine_health_client_interface.ts), calling its [`calculateClusterHealth` method](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/detection_engine_health/detection_engine_health_client.ts) in the request handler. + +The Detection Engine Health client receives as its parameter the [Rule Objects Health client (`IRuleObjectsHealthClient`)](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/detection_engine_health/rule_objects/rule_objects_health_client.ts), whose method `calculateClusterHealth` performs an aggregation on rule stats based on different rule attributes and parameters. + +This is done in the [`getRuleStatsAggregation` method](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/detection_engine_health/rule_objects/aggregations/rule_stats.ts), where an aggration is done over the `immutable` param. This needs to be updated to the new `prebuilt` param, with a fallback to `immutable`: + +_Source: x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/detection_engine_health/rule_objects/aggregations/rule_stats.ts(https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/detection_engine_health/rule_objects/aggregations/rule_stats.ts)_ + +```ts +// [... file continues above ...] + +export const getRuleStatsAggregation = (): Record< + string, + estypes.AggregationsAggregationContainer +> => { + const rulesByEnabled: estypes.AggregationsAggregationContainer = { + terms: { + field: 'alert.attributes.enabled', + }, + }; + + return { + rulesByEnabled, + rulesByOrigin: { + terms: { + // TODO: How to make this aggregation by whether the `prebuilt` field exists and immutable as fallback? + field: `${PARAMS_PREBUILT_IS_CUSTOMIZED_FIELD} or alert.attributes.params.immutable`, + }, + aggs: { + rulesByEnabled, + }, + }, + // [... other aggrations ...] + }, + }; +}; +// [... file continues below ...] +``` + +- **Detection Engine Health: Get Space Health** - `GET or POST /detection_engine/health/_space` (internal): + +In this endpoint, the `getSpaceHealthAggregation` method of the Rule Objects Health client (`IRuleObjectsHealthClient`) is called instead, but it internally calls the same [`getRuleStatsAggregation` method](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/detection_engine_health/rule_objects/aggregations/rule_stats.ts) as in the previous endpoint. + +Therefore, the update described in the endpoint above would cover this endpoint too. + +- **Detection Engine Health: Get Rule Health** - `POST /detection_engine/health/_rule` (internal): + +This endpoint does not depend on any of the affected params, i.e. no changes are needed here. + +### Rule Execution Logs + +Rule execution logging works independently of whether the rules are prebuilt or not, so any changes to the rule schema won't affect these endpoints. + +## Exporting and importing rules + +**Current behaviour:** + +- Custom Rules can be exported and imported +- When trying to import a custom rule, if the request payload doesn't include an `overwrite: true` value, its `rule_id` should not already exist in any of the installed rules. Otherwise the import logic will fail : `rule_id: {rule_id} already exists`. If the request payload includes an `overwrite: true`, the rule will be overwritten. +- Prebuilt Rules cannot be exported +- Prebuilt Rules cannot be imported (if you try to import a rule that has been set the `immutable` field to `true` manually, the import endpoint will reject it as the `immutable` field is expected to be `false`) + +**Updated behaviour** + +We will now allow the user to export and import both **prebuilt** and **custom rules**. + +### Exporting rules + +The user will now be able to export both custom and prebuilt rules (including any customizations that might have been performed on its modifiable fields). + +The export endpoints (bulk export and bulk action in export mode) will not carry out any migration-on-write logic. Since these endpoints solely read the rules and generate an ndjson file for export purposes, introducing additional writing or patching logic to migrate the rule's schema in Elasticsearch would negatively impact the endpoints' performance and introduce unnecessary overhead. + +Instead, we will carry out a normalization-on-read process, as described above, when the rule to be exported is read from ES, and before writing the rule's fields to the `ndjson` file. This means that the rule will actually be exported with the updated schema, thus ensuring backwards compatibility for a subsequent import procedure of this rules, even if they are not yet migrated in ES. + +This normalization will take place within the `internalRuleToAPIResponse` method, which internally calls the `normalizePrebuiltSchemaOnRuleRead`, as described in the [Normalization on read](#normalization-on-read) section. + +There are two helper functions used for exporting: + +- [getExportByObjectIds](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/export/get_export_by_object_ids.ts) +- [getExportAll](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/export/get_export_all.ts) + +The **Export Rules** - `POST /rules/_export` endpoint uses either the first or the second helper depending on the request payload, while **Bulk Actions** - `POST /rules/_bulk_action` uses only `getExportByObjectIds`. + +Both of these methods use `internalRuleToAPIResponse` internally to transform rules into our API response schema, so the normalization will come out of the box when executing that transformation. + +Also, in order to allow the endpoint to export both custom **and** prebuilt rules, we need to update the logic and remove the checks that we currently do server-side in both of these methods, and which filter out prebuilt rules from the response payload: + +- **Bulk Actions** - `POST /rules/_bulk_action` with the **export action** +- **Export Rules** - `POST /rules/_export` + +_Source: [x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/export/get_export_by_object_ids.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/export/get_export_by_object_ids.ts)_ + +```ts +// [... file continues above ...] + +export const getRulesFromObjects = async ( + rulesClient: RulesClient, + savedObjectsClient: RuleExecutorServices['savedObjectsClient'], + objects: Array<{ rule_id: string }>, + logger: Logger +): Promise => { + const chunkedObjects = chunk(objects, 1024); + const filter = [...] + const rules = await findRules({[...]}); + + const alertsAndErrors = objects.map(({ rule_id: ruleId }) => { + const matchingRule = rules.data.find((rule) => rule.params.ruleId === ruleId); + if ( + matchingRule != null + && hasValidRuleType(matchingRule) + // && matchingRule.params.immutable !== true <--- Check which should be removed + ) { + return { + statusCode: 200, + rule: transformRuleToExportableFormat(internalRuleToAPIResponse(matchingRule)), + }; + } else { + return { + statusCode: 404, + missingRuleId: { rule_id: ruleId }, + }; + } + }); + +// [... file continues below ...] +``` + +Notice that the **Bulk Actions** - `POST /rules/_bulk_action` does not perform a **dry run** in order to filter out prebuilt rules when the user runs an **export** action; this is the only check that is performed. + +*Source: [x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/export/get_export_all.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/export/get_export_all.ts)* +```ts +// [... file continues above ...] +export const getExportAll = async ( + // [...] +): Promise<{ + rulesNdjson: string; + // [...] +}> => { + // const ruleAlertTypes = await getNonPackagedRules({ rulesClient }); <---- current code + const allRules = await getRules({ rulesClient }); // <------ get all rules now + const rules = transformAlertsToRules(allRules); + +// [... file continues below ...] +``` + +### Importing rules + +The user will now be able to import both custom and prebuilt rules (including any customizations that might have been performed on its modifiable fields). + +We want to handle the case of importing both migrated and non-migrated rules via an `ndjson` file. + +Importing rules with `immutable: false` "should" be the only case for non-migrated rules (since `immutable: true` rules cannot currently be exported), but we should also handle the case of users manually modifying the values of rules in the `ndjson` file. + +If a user attempts to import a rule with `immutable: true` and missing `prebuilt` (or viceversa, a `prebuilt` field but no `immutable` field), then the most likely scenario is of a user trying to import Elastic prebuilt rules from a modified `ndjson` file. So we should consider these rules to be prebuilt and attempt to track them to rules in the Fleet package via their `rule_id` and continue to provide updates to them. + +Given the requirements described above, the following table shows the behaviour of our endpoint for a combination of `prebuilt` and `immutable` fields in the `ndjson` file that a user attempts to import: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PrebuiltImmutableResultsUse case
+
{isCustomized: true, ...}
+
true
+
+          {
+            prebuilt: {
+              isCustomized: true,
+              ...
+            },
+            immutable: true
+          }
+        
+
User importing an already migrated/normalized exported rule
+
undefined
+
true
+
+          {
+            prebuilt: {
+              isCustomized: true,
+            },
+            immutable: true
+          }
+        
+
User importing an prebuilt rule with legacy schema
+
undefined
+
false
+
+          {
+            immutable: false
+          }
+        
+
User importing a custom rule with new or legacy schema
+
{isCustomized: false, ...}
+
false
or
undefined
+
+          {
+            prebuilt: {
+              isCustomized: false,
+              ...
+            },
+            immutable: true
+          }
+        
+
This combination shouldn't be possible, but can happen if user manually modifies an `ndjson` file. The prebuilt field takes precendence over the immutable field and the rule is imported as prebuilt.
+
undefined
+
undefined
+
+          {
+            immutable: false
+          }
+        
+
This combination shouldn't be possible, but can happen if user manually modifies an `ndjson` file. The rule is imported as a custom rule.
+ + +If a user imports a prebuilt rule (where either the `prebuilt` or `immutable` fields are `true`), it will continue to track the rule asset from the `security_detection_engine` package if the `rule_id` matches. This means that a user will be able to update a previously exported prebuilt rule, visualize any diffs on any customized fields, and continue to receive updates on the rule. + +With this migration strategy for the import endpoints we can guarantee backwards compatibility for all rules, and don't need to do additional changes to the export endpoints. + +The `importRules` helper method that our import endpoint handler use rely on the already discussed `createRules` and the `patchRules` - when a rule is created from scratch (no `rule_id` match), and when a `rule_id` matches and a rule is overwritten, respectively. + +Given that, when importing rules, we can be creating a custom rule or a prebuilt rule, we need to calculate and appropiately pass the `isPrebuilt` flag to the `createRules` method. The `importRules` helper thus needs to be modified so: + +*Source: [x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/import/import_rules_utils.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/import/import_rules_utils.ts)* +```ts +// [... file continues above ...] + +export const importRules = async ({ + // [...] +}: { + // [...] +}) => { + // [...] + + // Determine if the rule to import is prebuilt based on the payload + const isPrebuilt = Boolean(parsedRule.prebuilt) || parsedRule.immutable; + + // If the rule is prebuilt, the `version` is required + if (isPrebuilt && !parsedRule.version) { + createBulkErrorObject({ + ruleId: parsedRule.rule_id, + statusCode: 409, + message: `rule_id: "${parsedRule.rule_id}" is prebuilt but no version was provided`, + }); + } + + // If no rule_id matched, create a new rule. We need to calculate the isPrebuilt + // argument to pass it to `createRules` following the logic described above. + if (rule == null) { + + await createRules({ + rulesClient, + params: { + ...parsedRule, + exceptions_list: [...exceptions], + }, + isPrebuilt, + allowMissingConnectorSecrets, + }); + resolve({ + rule_id: parsedRule.rule_id, + status_code: 200, + }); + // If rule_id matches and the overwriteRules flag is true, patch the existing rule. + // The calculation of the prebuilt and immutable fields will be done by the + // `migratePrebuiltSchemaOnRuleUpdate` helper based on the payload from the ndjson + } else if (rule != null && overwriteRules) { + await patchRules({ + rulesClient, + existingRule: rule, + nextParams: { + ...parsedRule, + exceptions_list: [...exceptions], + }, + allowMissingConnectorSecrets, + shouldIncrementRevision: false, + }); + +// [... file continues below ...] +``` + +### Handling the `version` parameter + +In the code above, we made an additional check: if the rule to be imported is a prebuilt rule, then the `version` field will be required as part of the payload as well. Attempting to import a prebuilt rule without it will result in an error and the importing of that rule will be skipped. The `version` is necessary to be able to provide updates to the rule when a new version is available in the Prebuilt Rules package. Without it we don't know if the installed version is newer or older than the update being offered by the package. + +Since users will be importing rules via an `ndjson` file, they can potentially modify it as they please. If the `version` field of a prebuilt rule is changed by the user before importing, the update workflow could be broken. The possible scenarios are the following: + +**1. The user removes the `version` field from the importing payload:** as mentioned above, we won't be able to start the upgrading flow because we don't have a version number to compare to the version coming from the update. Therefore, we should **reject the import if the `version` is missing**. + +**2. The user lowers the `version` field from the importing payload:** for example, a user exports a prebuilt rule with `version: 5`, and, before importing it, modifies it to `version: 4`. This wouldn't represent a problem as a new version of the rule (i.e. `version: 6`) would still trigger the update workflow, and the rule field diffs would still work as expected. + +**3. The user increases the `version` field from the importing payload:** or example, a user exports a prebuilt rule with `version: 5`, and before importing it modifies it to `version: 6`. This would mean that when the actual rule with `version: 6` was released, we wouldn't trigger the update workflow, since the version from the target version (the update) needs to be higher than what is currently installed for that to happen. However, the update would eventually be triggered when the next update was released, i.e. when `version: 7` is released, and work as expected. + +**4. The user sets the `version` field from the importing payload to a number that does not exist in the Prebuilt Rules package**: this scenario would still depend on whether the `version` that the user modifies the rule to is higher or lower than the version of the update: + - If it was higher, then we would be back in **scenario 3**, where the update workflow wouldn't trigger. + - If it was lower, then we would be in **scenario 2**, but with the additional problem that we wouldn't be able to fetch the **base** version of the rule - the unmodified version of the rule as it exists in the Prebuilt Rules package. However, we would still be able to normally display the rule field diffs between the current rule and the target (next version) rule (which is the default behaviour), but not between the base and the target (which is a feature that we want to a add as part of this Milestone). + +$\space$ +$\space$ +$\space$ +$\space$ + +------------------------- end of reviewable part of RFC ------------------------------ + +$\space$ +$\space$ +$\space$ +$\space$ + +## Customizing Prebuilt Rules + +### Endpoints + +With the rule schema updated, we will allow users to **edit their prebuilt rules** in a similar way to how they currently edit/modify their custom rules. A full detail of which fields we will allow the users to edit can be found in the section "Rule fields" below. + +Endpoints that users will be able to use to modify rules are: + +- **Update Rule** - `PUT /rules`: called by the UI when updating/modifying a single rule via the Rule Details page +- **Patch Rule** - `PATCH /rules`: used for attaching shared exceptions list to rules +- **Bulk Patch Rules** - `PATCH /rules/_bulk_update`: deprecated and unused by the UI (might still be used by public API users) +- **Bulk Update Rules** - `PUT /rules/_bulk_update`: deprecated and unused by the UI (might still be used by public API users) +- **Bulk Actions** - `POST /rules/_bulk_action` - with `edit` action: called when applying bulk actions via the Rules Table + +The first four endpoints listed above **currently allow users to modify their Elastic prebuilt rules** as well, in (almost) all of their fields, and no difference is made between updating/patching prebuilt rules and custom rules in the docs. However, none of those four endpoints allow to change a prebuilt rule to a custom rule (or vice-versa) by changing the current `immutable` field (i.e. the field is maintained from the existing rule). + +> - **Will we want to allow users to modify (via API) a prebuilt rule to transform it into a Custom Rule, by modifying the `prebuilt` parameter?** +> - No. We want to keep the current endpoint logic where the `immutable` field for the updated value comes from the existing value of the rule. Allowing that modification would create issues with the corresponding `security_detection_engine` package rule, as it will clash with the modified rule if the `rule_id` is not modified as well. This requirement is therefore not needed anyway since will now offer users the option to customize a prebuilt rule, or alternatively, duplicate a prebuilt rule. + +The endpoint **Bulk Actions** - `POST /rules/_bulk_action` does provide validation in the endpoint logic itself: if a user attempts to edit prebuilt rule (`immutable: true`) the endpoint rejects that edit in two ways: + +- in `dryRun` mode, with an error: "editing prebuilt rules is not supported". +- in normal mode, with validation that throws the error "Elastic rule can't be edited". + +In both cases, the validation checks if the `immutable` param of the rule is `false`, or if the action sent in the payload is setting or adding actions to a rule. If any of those two conditions are true, the validation succeeds and the rule(s) can be edited. + +#### Changes needed to endpoints + +##### Update Rule - `PUT /rules` + +- Addition of rule schema migration logic (described above) +- Calculation of `customized` field +- No other changes needed as endpoint already allows modifying prebuilt rules + +##### Patch Rule - `PATCH /rules` + +- Addition of rule schema migration logic (described above) +- Calculation of `customized` field +- No other changes needed as endpoint already allows modifying prebuilt rules + +##### Bulk Patch Rules - `PATCH /rules/_bulk_update` + +- Addition of rule schema migration logic (described above) +- Calculation of `customized` field for each modified rule +- No other changes needed as endpoint already allows modifying prebuilt rules + +##### Bulk Update Rules - `PUT /rules/_bulk_update` + +- Addition of rule schema migration logic (described above) +- Calculation of `customized` field for each modified rule +- No other changes needed as endpoint already allows modifying prebuilt rules + +##### Bulk Actions - `POST /rules/_bulk_action` + +- Addition of rule schema migration logic (described above) +- Calculation of `customized` field for each modified rule +- Removal of the check that prevents modifying prebuilt rules. Customization should be possible for both prebuilt and custom rules, and for all bulk editing actions that are currently supported for custom rules. + - Remove check for whether the rules in the payload have an `immutable` value of `false` OR if the `BulkActionEditTypeEnum` is either `set_rule_actions` or `add_rule_actions`. Bulk editing should be possible for all rules (independently of their values for the `prebuilt` and now legacy `immutable` fields), and for all types of Bulk Action Edit Types: + ```ts + export const BulkActionEditType = z.enum([ + 'add_tags', + 'delete_tags', + 'set_tags', + 'add_index_patterns', + 'delete_index_patterns', + 'set_index_patterns', + 'set_timeline', + 'add_rule_actions', + 'set_rule_actions', + 'set_schedule', + ]); + ``` + - This change will apply to two validations performed when calling this endpoint: + - when `dryRun` is `true` + - when `dryRun` is `false` (normal mode) + +#### Updating the `customized` field + +The `customized` field is initialized to a value of `false` for any new prebuilt rule that is installed, as well as in prebuilt rules that are migrated from the legacy schema. + +On a first iteration, the field should be updated to `true` when at least one of its fields is updated to any new value that differs to its current value. This means that we want the update of this field to be one-way: from `false` it can be updated to `true`, but we don't want for the field to be able to be reverted back to `false`. + +The reasons for this decision are the following: + +- when updating a rule, we don't have the information of what the "base" values for a rule's field are in order to compare them to the updated values. We only have the values for the existing rules as they are stored in the saved object, and the updated values that are sent in the request payload. We can easily compare those two to see if any changes were actually made, and mark the `customized` field as `true` in that case. +- the UX "downside" of this approach is minimal and a very rare corner case: once a user has modified a value, it will very seldom happen that the they will update it an additional time to a value that matches the base version (and thus has no differences to the base version). + +On a next phase, we could consider fetching the base version of the rule and actually comparing the updated values to the base values to decide if the rule should be considered `customized` or not. However, we should consider the performance (and complexity) implications that this additional logic could have on the endpoints. + +### In the UI + +The current behaviour of the app allows to modify a rule's fields in the following ways: + +#### Via the Rule Edit Page + +The **Rule Edit Page** is currently split into four tabs: + +| Tab | Contains fields | +| -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **Definition** | - Rule type (cannot be changed)
- Data Source
- Query
- Machine Learning job (ML rules only)
- Anomaly score threshold (ML rules only)
- Group by (threshold rules only)
- Count (cardinality) (threshold rules only)
- Indicator index patterns (indicator match rules only)
- Indicator index query (indicator match rules only)
- Indicator mapping (indicator match rules only)
- New terms fields (new term rules only)
- History window size (new terms rules only)
- Alert Suppression (for custom query and threshold rules only)
- Timeline Template | +| **About** | - Name
- Description
- Severity
- Severity override
- Risk score
- Risk score override
- Tags
- Reference URLs
- False positive examples
- MITRE ATT&CK™ threats
- Custom highlighted fields
- Investigation guide
- Author
- License
- Elastic Endpoint exceptions
- Building block
- Rule name override
- Timestamp override | +| **Schedule** | - Interval
- Lookback time | +| **Actions** | - Actions
- Response actions (custom query rules only) | + +Out of these four tabs, only **Actions** is enabled and accesible when editing a prebuilt rule - since actions (and shared exceptions lists and snoozing) are the only fields that can currently be modified for prebuilt rules from the UI. + +All of the fields in the UI, listed above, are currently editable for custom rules, except for rule type, which is read only. + +Once done editing the rule, the user clicks on the "Save Changes" button, which calls the **Update Rule** - `PUT /rules` endpoint, passing the payload for the whole rule. + +**Expected behaviour for customizing prebuilt rules** + +- All four tabs of the Rule Edit page should be enabled, and all the fields within each tab should be editable, as they currently are for custom rules. +- The only field in the UI that should not be customizable is **Rule Type**, that should continue to be read-only. +- **Definition** should be the default open tab when opening the edit rule page for a prebuilt rule (current default is **Actions**) +- Field validation should continue to work as it does for custom rules. +- No fields should return a validation error for the values that come from the `security_detection_engine` package prebuilt rules. This means that a user should be able to successfully save the prebuilt rule with no changes. See **List of things to fix** below. + +#### Via Bulk Actions + +Custom rules can currently be updated via the Rule Table's **Bulk Actions**, which uses the **Bulk Actions** - `POST /rules/_bulk_action` endpoint. + +Apart from enabling/disabling a rule - the only other action that modifies a rule's saved object and is currently possible for prebuilt rules - the user can use bulk actions to: + +- Add, delete and overwrite **index patterns** +- Add, delete and overwrite **tags** +- Add and overwrite **rule actions** +- Update the rule's **schedule: interval and lookback time** +- Select a **timeline template** for the rule + +As explained above, the UI validates that the five actions listed above are only possible to custom rules by using the `dryRun` mode of the **bulk actions** endpoint. If any of the selected rules in the request payload is a prebuilt rule, a message is displayed to the user informing them that modifying prebuilt rules is not possible, and that rule is removed from the subsequent request that is made in normal mode to actually edit the rule. + +**Expected behaviour for customizing prebuilt rules** + +The Bulk Actions UI should now be able to edit prebuilt rules. + +All bulk actions actions listed above should now be applicable to prebuilt rules (adding and overwriting rule actions is currently possible). This means that the changes in the API for the validation done in `dryRun` mode should not remove the rules from the payload anymore, and the bulk editing of the prebuilt rules will be possible when the subsequent request, in normal mode (`dryRun: false`), is performed. + +> The `dryRun` mode request will still be necessary since we perform other checks that can still prevent prebuilt rules from being edited. For example, Machine Learning and ES|QL rules cannot be bulk edited to add or delete index patterns, since they don't have that field in their schema. + +#### Via the Rules Details Page + +The Rules Details page allows the user to modify the rule in two ways: + +- enable/disabling + - uses `POST /rules/_bulk_action` endpoint with enable/disable action +- setting rule snoozing + - uses `POST /alerting/rule/{rule_id}/_snooze` endpoint + +Both of these actions are already possible for prebuilt rules, **so no changes are necessary here.** + +#### Via the Shared Exception Lists page + +The Shared Exception Lists page allows a user to create shared exception lists and then attach them to (or remove them from) a user's security rules. + +This page calls the **Patch Rule** - `PATCH /rules` endpoint to modify only the `exceptions_list` field of a rule saved object. Since a user can append an exception list to multiple rules via the UI, the endpoint is called multiple times simultaneously, one for each rule that is attached to or removed from. + +There is no validation regarding prebuilt rules in the UI for this use case: both the endpoint and the application currently allow the user to attach exceptions lists to both custom and prebuilt rules. + +This means that **no changes will be needed in this page.** + +#### Via the Stack Management > Rules UI + +The Stack Management Rules UI provides a unified view across the Elastic stack, showing not only security rules, but also other types such as observability, ML, etc. + +All rules listed here can be modified in the following ways: + +- enabling and disabling +- snoozing/unsnoozing or scheduling/unscheduling snooze +- updating their API keys +- deleting them + +All of these actions are currently applicable for both prebuilt security rules as well as custom security rules, and they use the Alerting Framework endpoints of: + +- `POST /alerting/rules/_bulk_edit` +- `PATCH /alerting/rules/_bulk_delete` + +This means that **no changes will be needed in this page.** + +## List of things to fix (create tickets) + +1. Validation of EQL queries incorrectly fails: valid EQL queries that come with Prebuilt Rules are rejected by the EQL validator when trying to edit a rule. See [link](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/public/detections/components/rules/step_define_rule/schema.tsx#L186). +2. Custom Query field overflows the viewport and cannot be completely visualized/edited when the query is too long, i.e. occupies too many lines. This is often the case from Prebuilt Rules. The editable field also does not allow scrolling. See example: + ![](2023-12-01-14-13-07.png) + + + +### Rule fields + +- What rule fields will be customizable and for what fields we will disable customization? +- How are we going to handle various fields in the rule upgrade workflow? +- What concrete diff algorithms for what rule fields we will need to write? + +## Updating Prebuilt Rules + +### Changes to upgrade `_review` and `_perform` endpoints + +TODO + +### Rule field diff algorithms + +TODO + +## Changes in UI + +TODO + +## Scenarios for bulk accepting updates + +- At rules table level + Bulk accept all rule updates that have no conflicting fields at all → This would make the request to update all these rules with no conflicts at all. + Accept all rule updates for non-customized rules. + +- At rule (filed-per-field) level + Accept all fields that have no conflicting changes, but still requires the user to manually solve fields with conflicts. → Once all fields are solved, the user can make the request to update the rule. + Accept all fields that are not customized + +- User Config + Create a user config/setting that the user can turn on to accept updates automatically if there are no conflicts. + Or we should more concretely how we want this setting to behave + +## Marking rules (and their fields) as customized + +We’d like to know if the rules has been customized in any way (at least 1 field modified from the base version) in order to mark the rule as “customized” + +- Use the `customized` + IDEALLY: +- Know specifically which fields have been customized. +- How the fields have been customized, show their diffs. + +- To keep track of how the rule has changed + - Introduce a new endpoint that calculates the diffs for the required fields. We could have new tab in the Rules Flyout tab that only calls an endpoint when it is opened. This endpoint would calcualte which fields where modified and return the base and current versions for each. + - **\*\***PROs:**\*\*** + - We don’t need to keep track of which fields were customized in the SO, and no changes to the rule schema are changed. + - Most of the logic for the endpoint needed is already implemented. + - **\*\*\*\***CONs:**\*\*\*\*** + - We do not keep in the SO the list of which rules were customized. This stops us from showing, in the Rules Detail page, which fields were customized, at least wihtout making an additional call to the backend, to calculate diffs. + - We can solve this by making a non-blocking request to the endpoint after the page loads. Alternatively, show it only when the user opens a flyout desgined to show these diffs. + +## Other open questions + +3. Do we want the `customized` field to revert to `false` if the fields revert to match the base version after diverging? diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/pages/rule_editing/index.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/pages/rule_editing/index.tsx index ff96fd64f027f8..409c6c5cc906cf 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/pages/rule_editing/index.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/pages/rule_editing/index.tsx @@ -226,7 +226,6 @@ const EditRulePageComponent: FC<{ rule: RuleResponse }> = ({ rule }) => { 'data-test-subj': 'edit-rule-define-tab', id: RuleStep.defineRule, name: ruleI18n.DEFINITION, - disabled: rule?.immutable, content: (

= ({ rule }) => { 'data-test-subj': 'edit-rule-about-tab', id: RuleStep.aboutRule, name: ruleI18n.ABOUT, - disabled: rule?.immutable, content: (
= ({ rule }) => { 'data-test-subj': 'edit-rule-schedule-tab', id: RuleStep.scheduleRule, name: ruleI18n.SCHEDULE, - disabled: rule?.immutable, content: (
!rule.immutable, + enabled: (rule: Rule) => !rule.prebuilt, }, { type: 'icon', diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_upgrade/perform_rule_upgrade_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_upgrade/perform_rule_upgrade_route.ts index 3009495e322978..969fefa423d905 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_upgrade/perform_rule_upgrade_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_upgrade/perform_rule_upgrade_route.ts @@ -150,10 +150,12 @@ export const performRuleUpgradeRoute = (router: SecuritySolutionPluginRouter) => } }); + const isRuleCustomizedDuringUpgrade = false; // Perform the upgrade const { results: updatedRules, errors: installationErrors } = await upgradePrebuiltRules( rulesClient, - targetRules + targetRules, + isRuleCustomizedDuringUpgrade ); const ruleErrors = [...fetchErrors, ...installationErrors]; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/review_rule_upgrade/review_rule_upgrade_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/review_rule_upgrade/review_rule_upgrade_route.ts index 1fcb36b592d567..296cee146749fa 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/review_rule_upgrade/review_rule_upgrade_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/review_rule_upgrade/review_rule_upgrade_route.ts @@ -61,6 +61,7 @@ export const reviewRuleUpgradeRoute = (router: SecuritySolutionPluginRouter) => invariant(ruleVersions != null, 'ruleVersions not found'); return calculateRuleDiff(ruleVersions); }); + debugger; const body: ReviewRuleUpgradeResponseBody = { stats: calculateRuleStats(ruleDiffCalculationResults), @@ -99,6 +100,10 @@ const calculateRuleInfos = (results: CalculateRuleDiffResult[]): RuleUpgradeInfo const targetRule: RuleResponse = { ...convertPrebuiltRuleAssetToRuleResponse(targetVersion), + prebuilt: { + isCustomized: installedCurrentVersion.prebuilt?.isCustomized ?? false, + elasticUpdateDate: targetVersion.elasticUpdateDate, + }, id: installedCurrentVersion.id, revision: installedCurrentVersion.revision + 1, created_at: installedCurrentVersion.created_at, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/rule_objects/create_prebuilt_rules.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/rule_objects/create_prebuilt_rules.ts index 54b4361bf868bd..d57ba291d0f858 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/rule_objects/create_prebuilt_rules.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/rule_objects/create_prebuilt_rules.ts @@ -21,7 +21,7 @@ export const createPrebuiltRules = (rulesClient: RulesClient, rules: PrebuiltRul return createRules({ rulesClient, params: rule, - immutable: true, + isPrebuilt: true, defaultEnabled: false, }); }, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/rule_objects/upgrade_prebuilt_rules.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/rule_objects/upgrade_prebuilt_rules.test.ts index 2990533dc0f891..9650e8ebdb9d5d 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/rule_objects/upgrade_prebuilt_rules.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/rule_objects/upgrade_prebuilt_rules.test.ts @@ -19,6 +19,7 @@ jest.mock('../../../rule_management/logic/crud/patch_rules'); describe('updatePrebuiltRules', () => { let rulesClient: ReturnType; + const isRuleCustomizedDuringUpgrade = false; beforeEach(() => { rulesClient = rulesClientMock.create(); @@ -36,7 +37,11 @@ describe('updatePrebuiltRules', () => { const prepackagedRule = getPrebuiltRuleMock(); rulesClient.find.mockResolvedValue(getFindResultWithSingleHit()); - await upgradePrebuiltRules(rulesClient, [{ ...prepackagedRule, actions }]); + await upgradePrebuiltRules( + rulesClient, + [{ ...prepackagedRule, actions }], + isRuleCustomizedDuringUpgrade + ); expect(patchRules).toHaveBeenCalledWith( expect.objectContaining({ @@ -67,7 +72,11 @@ describe('updatePrebuiltRules', () => { data: [getRuleMock(getThreatRuleParams())], }); - await upgradePrebuiltRules(rulesClient, [{ ...prepackagedRule, ...updatedThreatParams }]); + await upgradePrebuiltRules( + rulesClient, + [{ ...prepackagedRule, ...updatedThreatParams }], + isRuleCustomizedDuringUpgrade + ); expect(patchRules).toHaveBeenCalledWith( expect.objectContaining({ diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/rule_objects/upgrade_prebuilt_rules.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/rule_objects/upgrade_prebuilt_rules.ts index a06b5dc17825f6..bb4f4373ce5c77 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/rule_objects/upgrade_prebuilt_rules.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/rule_objects/upgrade_prebuilt_rules.ts @@ -26,13 +26,17 @@ import type { PrebuiltRuleAsset } from '../../model/rule_assets/prebuilt_rule_as * @param rulesClient Alerting client * @param rules The rules to apply the update for */ -export const upgradePrebuiltRules = async (rulesClient: RulesClient, rules: PrebuiltRuleAsset[]) => +export const upgradePrebuiltRules = async ( + rulesClient: RulesClient, + rules: PrebuiltRuleAsset[], + isRuleCustomizedDuringUpgrade = false +) => withSecuritySpan('upgradePrebuiltRules', async () => { const result = await initPromisePool({ concurrency: MAX_RULES_TO_UPDATE_IN_PARALLEL, items: rules, executor: async (rule) => { - return upgradeRule(rulesClient, rule); + return upgradeRule(rulesClient, rule, isRuleCustomizedDuringUpgrade); }, }); @@ -48,7 +52,8 @@ export const upgradePrebuiltRules = async (rulesClient: RulesClient, rules: Preb */ const upgradeRule = async ( rulesClient: RulesClient, - rule: PrebuiltRuleAsset + rule: PrebuiltRuleAsset, + isRuleCustomizedDuringUpdate: boolean ): Promise> => { const existingRule = await readRules({ rulesClient, @@ -60,6 +65,17 @@ const upgradeRule = async ( throw new PrepackagedRulesError(`Failed to find rule ${rule.rule_id}`, 500); } + // When upgrading a prebuilt rule, we need to build the `prebuilt` field + // out of the PrebuiltRuleAsset before passing it to createRules or patchRules + // For isCustomized, set the value to true if the rule was customized during the current update. + // Otherwise, take the existing value from the currently installed value. + const isCustomized = + (isRuleCustomizedDuringUpdate || existingRule.params.prebuilt?.isCustomized) ?? false; + const prebuilt = { + isCustomized, + elasticUpdateDate: rule.elasticUpdateDate, + }; + // If we're trying to change the type of a prepackaged rule, we need to delete the old one // and replace it with the new rule, keeping the enabled setting, actions, throttle, id, // and exception lists from the old rule @@ -71,9 +87,10 @@ const upgradeRule = async ( return createRules({ rulesClient, - immutable: true, + isPrebuilt: true, params: { ...rule, + prebuilt, // Force the prepackaged rule to use the enabled state from the existing rule, // regardless of what the prepackaged rule says enabled: existingRule.enabled, @@ -86,10 +103,12 @@ const upgradeRule = async ( existingRule, nextParams: { ...rule, + prebuilt, // Force enabled to use the enabled state from the existing rule by passing in undefined to patchRules enabled: undefined, actions: undefined, }, + isRuleCustomizedDuringUpdate, }); const updatedRule = await readRules({ diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/model/rule_assets/prebuilt_rule_asset.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/model/rule_assets/prebuilt_rule_asset.ts index 07fb5640eb482a..191d8edcd3de50 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/model/rule_assets/prebuilt_rule_asset.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/model/rule_assets/prebuilt_rule_asset.ts @@ -9,6 +9,7 @@ import * as z from 'zod'; import { RelatedIntegrationArray, RequiredFieldArray, + ElasticUpdateDate, SetupGuide, RuleSignatureId, RuleVersion, @@ -38,5 +39,6 @@ export const PrebuiltRuleAsset = BaseCreateProps.and(TypeSpecificCreateProps).an related_integrations: RelatedIntegrationArray.optional(), required_fields: RequiredFieldArray.optional(), setup: SetupGuide.optional(), + elasticUpdateDate: ElasticUpdateDate.optional(), }) ); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_actions/route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_actions/route.ts index d09c11d1289bd3..d76b643f82a60f 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_actions/route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_actions/route.ts @@ -257,25 +257,31 @@ export const performBulkActionRoute = ( }, }, async (context, request, response): Promise> => { + // function delay(ms) { + // return new Promise((resolve) => setTimeout(resolve, ms)); + // } + + // await delay(5000); // Wait for 2000 milliseconds (2 seconds) + + // return siemResponse.error({ + // body: 'error.message', + // statusCode: 500, + // }); const { body } = request; const siemResponse = buildSiemResponse(response); - if (body?.ids && body.ids.length > RULES_TABLE_MAX_PAGE_SIZE) { return siemResponse.error({ body: `More than ${RULES_TABLE_MAX_PAGE_SIZE} ids sent for bulk edit action.`, statusCode: 400, }); } - if (body?.ids && body.query !== undefined) { return siemResponse.error({ body: `Both query and ids are sent. Define either ids or query in request payload.`, statusCode: 400, }); } - const isDryRun = request.query.dry_run; - // dry run is not supported for export, as it doesn't change ES state and has different response format(exported JSON file) if (isDryRun && body.action === BulkActionTypeEnum.export) { return siemResponse.error({ @@ -283,9 +289,7 @@ export const performBulkActionRoute = ( statusCode: 400, }); } - const abortController = new AbortController(); - // subscribing to completed$, because it handles both cases when request was completed and aborted. // when route is finished by timeout, aborted$ is not getting fired request.events.completed$.subscribe(() => abortController.abort()); @@ -298,26 +302,20 @@ export const performBulkActionRoute = ( 'lists', 'actions', ]); - const rulesClient = ctx.alerting.getRulesClient(); const exceptionsClient = ctx.lists?.getExceptionListClient(); const savedObjectsClient = ctx.core.savedObjects.client; const actionsClient = (await ctx.actions)?.getActionsClient(); - const { getExporter, getClient } = (await ctx.core).savedObjects; const client = getClient({ includedHiddenTypes: ['action'] }); - const exporter = getExporter(client); - const mlAuthz = buildMlAuthz({ license: ctx.licensing.license, ml, request, savedObjectsClient, }); - const query = body.query !== '' ? body.query : undefined; - // handling this action before switch statement as bulkEditRules fetch rules within // rulesClient method, hence there is no need to use fetchRulesByQueryOrIds utility if (body.action === BulkActionTypeEnum.edit && !isDryRun) { @@ -328,27 +326,23 @@ export const performBulkActionRoute = ( actions: body.edit, mlAuthz, }); - return buildBulkResponse(response, { updated: rules, skipped, errors, }); } - const fetchRulesOutcome = await fetchRulesByQueryOrIds({ rulesClient, query, ids: body.ids, abortSignal: abortController.signal, }); - const rules = fetchRulesOutcome.results.map(({ result }) => result); let bulkActionOutcome: PromisePoolOutcome; let updated: RuleAlertType[] = []; let created: RuleAlertType[] = []; let deleted: RuleAlertType[] = []; - switch (body.action) { case BulkActionTypeEnum.enable: bulkActionOutcome = await initPromisePool({ @@ -356,16 +350,13 @@ export const performBulkActionRoute = ( items: rules, executor: async (rule) => { await validateBulkEnableRule({ mlAuthz, rule }); - // during dry run only validation is getting performed and rule is not saved in ES, thus return early if (isDryRun) { return rule; } - if (!rule.enabled) { await rulesClient.enable({ id: rule.id }); } - return { ...rule, enabled: true, @@ -383,16 +374,13 @@ export const performBulkActionRoute = ( items: rules, executor: async (rule) => { await validateBulkDisableRule({ mlAuthz, rule }); - // during dry run only validation is getting performed and rule is not saved in ES, thus return early if (isDryRun) { return rule; } - if (rule.enabled) { await rulesClient.disable({ id: rule.id }); } - return { ...rule, enabled: false, @@ -404,7 +392,6 @@ export const performBulkActionRoute = ( .map(({ result }) => result) .filter((rule): rule is RuleAlertType => rule !== null); break; - case BulkActionTypeEnum.delete: bulkActionOutcome = await initPromisePool({ concurrency: MAX_RULES_TO_UPDATE_IN_PARALLEL, @@ -414,12 +401,10 @@ export const performBulkActionRoute = ( if (isDryRun) { return null; } - await deleteRules({ ruleId: rule.id, rulesClient, }); - return null; }, abortSignal: abortController.signal, @@ -428,26 +413,22 @@ export const performBulkActionRoute = ( .map(({ item }) => item) .filter((rule): rule is RuleAlertType => rule !== null); break; - case BulkActionTypeEnum.duplicate: bulkActionOutcome = await initPromisePool({ concurrency: MAX_RULES_TO_UPDATE_IN_PARALLEL, items: rules, executor: async (rule) => { await validateBulkDuplicateRule({ mlAuthz, rule }); - // during dry run only validation is getting performed and rule is not saved in ES, thus return early if (isDryRun) { return rule; } - let shouldDuplicateExceptions = true; let shouldDuplicateExpiredExceptions = true; if (body.duplicate !== undefined) { shouldDuplicateExceptions = body.duplicate.include_exceptions; shouldDuplicateExpiredExceptions = body.duplicate.include_expired_exceptions; } - const duplicateRuleToCreate = await duplicateRule({ rule, }); @@ -455,7 +436,6 @@ export const performBulkActionRoute = ( const createdRule = await rulesClient.create({ data: duplicateRuleToCreate, }); - // we try to create exceptions after rule created, and then update rule const exceptions = shouldDuplicateExceptions ? await duplicateExceptions({ @@ -465,7 +445,6 @@ export const performBulkActionRoute = ( exceptionsClient, }) : []; - const updatedRule = await rulesClient.update({ id: createdRule.id, data: { @@ -477,7 +456,6 @@ export const performBulkActionRoute = ( }, shouldIncrementRevision: () => false, }); - // TODO: figureout why types can't return just updatedRule return { ...createdRule, ...updatedRule }; }, @@ -487,7 +465,6 @@ export const performBulkActionRoute = ( .map(({ result }) => result) .filter((rule): rule is RuleAlertType => rule !== null); break; - case BulkActionTypeEnum.export: const exported = await getExportByObjectIds( rulesClient, @@ -497,9 +474,7 @@ export const performBulkActionRoute = ( request, actionsClient ); - const responseBody = `${exported.rulesNdjson}${exported.exceptionLists}${exported.actionConnectors}${exported.exportDetails}`; - return response.ok({ headers: { 'Content-Disposition': `attachment; filename="rules_export.ndjson"`, @@ -507,7 +482,6 @@ export const performBulkActionRoute = ( }, body: responseBody, }); - // will be processed only when isDryRun === true // during dry run only validation is getting performed and rule is not saved in ES case BulkActionTypeEnum.edit: @@ -516,7 +490,6 @@ export const performBulkActionRoute = ( items: rules, executor: async (rule) => { await dryRunValidateBulkEditRule({ mlAuthz, rule, edit: body.edit }); - return rule; }, abortSignal: abortController.signal, @@ -525,11 +498,9 @@ export const performBulkActionRoute = ( .map(({ result }) => result) .filter((rule): rule is RuleAlertType => rule !== null); } - if (abortController.signal.aborted === true) { throw new AbortError('Bulk action was aborted'); } - return buildBulkResponse(response, { updated, deleted, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_create_rules/route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_create_rules/route.ts index 7ab03f2ac7dcd4..af4c4226172f72 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_create_rules/route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_create_rules/route.ts @@ -127,6 +127,7 @@ export const bulkCreateRulesRoute = ( const createdRule = await createRules({ rulesClient, params: payloadRule, + isPrebuilt: false, }); return transformValidateBulkError(createdRule.params.ruleId, createdRule); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/create_rule/route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/create_rule/route.ts index e9c84c1c50f5cb..11b13b0491fff3 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/create_rule/route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/create_rule/route.ts @@ -107,6 +107,7 @@ export const createRuleRoute = ( const createdRule = await createRules({ rulesClient, params: request.body, + isPrebuilt: false, }); return response.ok({ diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/filters/route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/filters/route.ts index 183d4f8e2f78d3..ba78bee8449697 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/filters/route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/filters/route.ts @@ -9,6 +9,7 @@ import { transformError } from '@kbn/securitysolution-es-utils'; import { validate } from '@kbn/securitysolution-io-ts-utils'; import type { RulesClient } from '@kbn/alerting-plugin/server'; import type { IKibanaResponse } from '@kbn/core/server'; +import { KQL_FILTER_PREBUILT_RULES } from '../../../../../../../common/detection_engine/rule_management/rule_filtering'; import { GetRuleManagementFiltersResponse, RULE_MANAGEMENT_FILTERS_URL, @@ -36,12 +37,12 @@ async function fetchRulesCount(rulesClient: RulesClient): Promise { findRules({ ...DEFAULT_FIND_RULES_COUNT_PARAMS, rulesClient, - filter: 'alert.attributes.params.immutable: true', + filter: KQL_FILTER_PREBUILT_RULES, }), findRules({ ...DEFAULT_FIND_RULES_COUNT_PARAMS, rulesClient, - filter: 'alert.attributes.params.immutable: false', + filter: `NOT ${KQL_FILTER_PREBUILT_RULES}`, }), ]); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/find_rules/route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/find_rules/route.ts index 3cbd164586a9df..fe04a375960c43 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/find_rules/route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/find_rules/route.ts @@ -14,7 +14,6 @@ import { FindRulesRequestQuery, validateFindRulesRequestQuery, } from '../../../../../../../common/api/detection_engine/rule_management'; - import type { SecuritySolutionPluginRouter } from '../../../../../../types'; import { findRules } from '../../../logic/search/find_rules'; import { buildSiemResponse } from '../../../../routes/utils'; @@ -63,7 +62,11 @@ export const findRulesRoute = (router: SecuritySolutionPluginRouter, logger: Log }); const transformed = transformFindAlerts(rules); - return response.ok({ body: transformed ?? {} }); + + return response.ok({ + body: transformed ?? {}, + headers: { 'Deprecation-Info': 'Warning 22' }, + }); } catch (err) { const error = transformError(err); return siemResponse.error({ diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/import_rules/route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/import_rules/route.ts index 5867d099fb8def..981431dcc63dea 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/import_rules/route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/import_rules/route.ts @@ -176,6 +176,7 @@ export const importRulesRoute = ( return false; } }); + const importRules: ImportRulesResponse = { success: errorsResp.length === 0, success_count: successes.length, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/actions/duplicate_rule.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/actions/duplicate_rule.ts index 315517504def47..ffe9bbeddc225a 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/actions/duplicate_rule.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/actions/duplicate_rule.ts @@ -12,6 +12,8 @@ import type { SanitizedRule } from '@kbn/alerting-plugin/common'; import { SERVER_APP_ID } from '../../../../../../common/constants'; import type { InternalRuleCreate, RuleParams } from '../../../rule_schema'; import { transformToActionFrequency } from '../../normalization/rule_actions'; +import { migratePrebuiltSchemaOnRuleCreation } from '../../normalization/prebuilt_rule_schema_migrations'; +import { internalRuleToAPIResponse } from '../../normalization/rule_converters'; const DUPLICATE_TITLE = i18n.translate( 'xpack.securitySolution.detectionEngine.rules.cloneRule.duplicateTitle', @@ -28,14 +30,18 @@ export const duplicateRule = async ({ rule }: DuplicateRuleParams): Promise { await throwMlAuthError(mlAuthz, ruleType); - - // if rule can't be edited error will be thrown - const canRuleBeEdited = !immutable || istEditApplicableToImmutableRule(edit); - await throwDryRunError( - () => invariant(canRuleBeEdited, "Elastic rule can't be edited"), - BulkActionsDryRunErrCode.IMMUTABLE - ); }; /** diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/crud/create_rules.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/crud/create_rules.ts index 0c39d0f39411fd..7608a90da4ed44 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/crud/create_rules.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/crud/create_rules.ts @@ -8,7 +8,11 @@ import type { SanitizedRule } from '@kbn/alerting-plugin/common'; import type { RulesClient } from '@kbn/alerting-plugin/server'; -import type { RuleCreateProps } from '../../../../../../common/api/detection_engine/model/rule_schema'; +import type { + RuleCreateProps, + Prebuilt, + IsRuleImmutable, +} from '../../../../../../common/api/detection_engine/model/rule_schema'; import { convertCreateAPIToInternalSchema } from '../../normalization/rule_converters'; import type { RuleParams } from '../../../rule_schema'; @@ -16,20 +20,45 @@ export interface CreateRulesOptions rulesClient: RulesClient; params: T; id?: string; - immutable?: boolean; + isPrebuilt?: boolean; defaultEnabled?: boolean; allowMissingConnectorSecrets?: boolean; } +export type RuleCreateAndImportProps = RuleCreateProps & { + prebuilt?: Prebuilt; + immutable?: IsRuleImmutable; +}; + +const getIsRuleToCreatePrebuilt = ( + params: RuleCreateAndImportProps, + isPrebuilt?: boolean +): boolean => { + // If createRules is explicitly called with isPrebuilt, use that value. + // Use case when creating a custom rule or installing/updating a prebuilt rule. + if (isPrebuilt != null) { + return isPrebuilt; + } + + // Otherwise, check the passed prebuilt or immutable params for existence. + // Use case when importing a rule. Default to false if neither are passed. + return (Boolean(params.prebuilt) || params.immutable) ?? false; +}; + export const createRules = async ({ rulesClient, params, id, - immutable = false, + isPrebuilt, defaultEnabled = true, allowMissingConnectorSecrets, -}: CreateRulesOptions): Promise> => { - const internalRule = convertCreateAPIToInternalSchema(params, immutable, defaultEnabled); +}: CreateRulesOptions): Promise> => { + const isRuleToCreatePrebuilt = getIsRuleToCreatePrebuilt(params, isPrebuilt); + const internalRule = convertCreateAPIToInternalSchema( + params, + isRuleToCreatePrebuilt, + defaultEnabled + ); const rule = await rulesClient.create({ options: { id, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/crud/patch_rules.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/crud/patch_rules.ts index ede7b86bd737e1..fb4df148a708d4 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/crud/patch_rules.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/crud/patch_rules.ts @@ -6,6 +6,12 @@ */ import type { PartialRule, RulesClient } from '@kbn/alerting-plugin/server'; +import type { + RelatedIntegrationArray, + RequiredFieldArray, + SetupGuide, + Prebuilt, +} from '../../../../../../common/api/detection_engine'; import type { PatchRuleRequestBody } from '../../../../../../common/api/detection_engine/rule_management'; import type { RuleAlertType, RuleParams } from '../../../rule_schema'; @@ -13,25 +19,43 @@ import { convertPatchAPIToInternalSchema } from '../../normalization/rule_conver export interface PatchRulesOptions { rulesClient: RulesClient; - nextParams: PatchRuleRequestBody; + nextParams: PatchRuleRequestBody & { + related_integrations?: RelatedIntegrationArray; + required_fields?: RequiredFieldArray; + setup?: SetupGuide; + prebuilt?: Prebuilt; + }; existingRule: RuleAlertType | null | undefined; allowMissingConnectorSecrets?: boolean; - shouldIncrementRevision?: boolean; + isRuleCustomizedDuringUpdate?: boolean; // pass in new optional boolean } +/** + * Used when: + * - Updating a prebuilt rule with no type change + * - Importing rules and overwriting an existing rule + * - Patching rules (DETECTION_ENGINE_RULES_URL patch endpoint --> managing shared exceptions lists) + * - Bulk Patching rules (deprecated DETECTION_ENGINE_RULES_BULK_UPDATE endpoint) + * - Creating rule exceptions (CREATE_RULE_EXCEPTIONS_URL endpoint) + **/ export const patchRules = async ({ rulesClient, existingRule, nextParams, allowMissingConnectorSecrets, shouldIncrementRevision = true, + isRuleCustomizedDuringUpdate = false, }: PatchRulesOptions): Promise | null> => { if (existingRule == null) { return null; } - const patchedRule = convertPatchAPIToInternalSchema(nextParams, existingRule); + const patchedRule = convertPatchAPIToInternalSchema( + nextParams, + existingRule, + isRuleCustomizedDuringUpdate + ); const update = await rulesClient.update({ id: existingRule.id, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/crud/update_rules.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/crud/update_rules.ts index cfbf6a639bb5ed..74936f09421cbc 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/crud/update_rules.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/crud/update_rules.ts @@ -14,6 +14,7 @@ import { transformRuleToAlertAction } from '../../../../../../common/detection_e import type { InternalRuleUpdate, RuleParams, RuleAlertType } from '../../../rule_schema'; import { transformToActionFrequency } from '../../normalization/rule_actions'; import { typeSpecificSnakeToCamel } from '../../normalization/rule_converters'; +import { migratePrebuiltSchemaOnRuleUpdate } from '../../normalization/prebuilt_rule_schema_migrations'; export interface UpdateRulesOptions { rulesClient: RulesClient; @@ -36,6 +37,14 @@ export const updateRules = async ({ const typeSpecificParams = typeSpecificSnakeToCamel(ruleUpdate); const enabled = ruleUpdate.enabled ?? true; + + const isRuleCustomizedDuringUpdate = false; + + const { immutable, prebuilt } = migratePrebuiltSchemaOnRuleUpdate({ + existingParams: existingRule.params, + isRuleCustomizedDuringUpdate, + }); + const newInternalRule: InternalRuleUpdate = { name: ruleUpdate.name, tags: ruleUpdate.tags ?? [], @@ -47,8 +56,8 @@ export const updateRules = async ({ falsePositives: ruleUpdate.false_positives ?? [], from: ruleUpdate.from ?? 'now-6m', investigationFields: ruleUpdate.investigation_fields, - // Unlike the create route, immutable comes from the existing rule here - immutable: existingRule.params.immutable, + immutable, + prebuilt, license: ruleUpdate.license, outputIndex: ruleUpdate.output_index ?? '', timelineId: ruleUpdate.timeline_id, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/import/import_rules_utils.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/import/import_rules_utils.ts index 81940848b7dc47..57949531b69fa1 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/import/import_rules_utils.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/import/import_rules_utils.ts @@ -102,6 +102,15 @@ export const importRules = async ({ id: undefined, }); + const isPrebuilt = Boolean(parsedRule.prebuilt) || parsedRule.immutable; + if (isPrebuilt && !parsedRule.version) { + createBulkErrorObject({ + ruleId: parsedRule.rule_id, + statusCode: 409, + message: `rule_id: "${parsedRule.rule_id}" is prebuilt but no version was provided`, + }); + } + if (rule == null) { await createRules({ rulesClient, @@ -109,6 +118,7 @@ export const importRules = async ({ ...parsedRule, exceptions_list: [...exceptions], }, + isPrebuilt, allowMissingConnectorSecrets, }); resolve({ diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/normalization/prebuilt_rule_schema_migrations.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/normalization/prebuilt_rule_schema_migrations.ts new file mode 100644 index 00000000000000..b5a3f90549d1cc --- /dev/null +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/normalization/prebuilt_rule_schema_migrations.ts @@ -0,0 +1,146 @@ +/* + * 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 { + Prebuilt, + IsRuleImmutable, +} from '../../../../../common/api/detection_engine/model/rule_schema'; +import type { BaseRuleParams, RuleParams } from '../../rule_schema'; +import type { CreateAPIInput, PatchAPINextParams } from './rule_converters'; + +interface MigrationResponse { + immutable: IsRuleImmutable; + prebuilt?: Prebuilt; +} + +const getPrebuiltValueForRuleRead = (ruleParams: BaseRuleParams): Prebuilt | undefined => { + if (ruleParams.prebuilt) { + return ruleParams.prebuilt; + } + + if (ruleParams.immutable) { + return { + isCustomized: false, + }; + } + + return undefined; +}; + +export const normalizePrebuiltSchemaOnRuleRead = ( + ruleParams: BaseRuleParams +): MigrationResponse => { + const immutable = Boolean(ruleParams.prebuilt) || ruleParams.immutable; + const prebuilt = getPrebuiltValueForRuleRead(ruleParams); + + return { + immutable, + prebuilt, + }; +}; + +interface PrebuiltSchemaCreationMigrationProps { + input: CreateAPIInput; + isRuleToCreatePrebuilt: boolean; +} + +/** + * Used when: + * - Creating a custom rule (DETECTION_ENGINE_RULES_URL POST endpoint) + * - Bulk creating custom rules (DETECTION_ENGINE_RULES_BULK_CREATE deprecated endpoint) + * - Creating Prebuilt Rules (Installation) + * - Updating a prebuilt rule when there is a type change (deletes and recreates the rule) + * - Importing rules without overwriting an existing rule + **/ + +const getPrebuiltValueForRuleCreation = ( + input: CreateAPIInput, + isRuleToCreatePrebuilt: boolean +): Prebuilt | undefined => { + if (!isRuleToCreatePrebuilt) { + return undefined; + } + + if (input.prebuilt != null) { + return input.prebuilt; + } + + return { + isCustomized: false, + elasticUpdateDate: input.elasticUpdateDate, + }; +}; + +export const migratePrebuiltSchemaOnRuleCreation = ({ + input, + isRuleToCreatePrebuilt, +}: PrebuiltSchemaCreationMigrationProps): MigrationResponse => { + const immutable = isRuleToCreatePrebuilt; + const prebuilt = getPrebuiltValueForRuleCreation(input, isRuleToCreatePrebuilt); + + return { + immutable, + prebuilt, + }; +}; + +interface PrebuiltSchemaUpdateMigrationProps { + nextParams?: PatchAPINextParams; + existingParams: RuleParams; + isRuleCustomizedDuringUpdate: boolean; +} + +const getPrebuiltValueForRuleUpdate = ({ + nextParams, + existingParams, + isRuleCustomizedDuringUpdate, +}: PrebuiltSchemaUpdateMigrationProps): Prebuilt | undefined => { + if (nextParams?.prebuilt) { + return nextParams?.prebuilt; + } + + if (existingParams.prebuilt) { + return { + ...existingParams.prebuilt, + isCustomized: existingParams.prebuilt.isCustomized || isRuleCustomizedDuringUpdate, + }; + } + + if (existingParams.immutable) { + return { + isCustomized: isRuleCustomizedDuringUpdate, + }; + } + + return undefined; +}; + +/** + * Used when: + * - Updating a prebuilt rule with no type change + * - Importing rules and overwriting an existing rule + * - Patching rules (DETECTION_ENGINE_RULES_URL patch endpoint --> managing shared exceptions lists) + * - Bulk Patching rules (deprecated DETECTION_ENGINE_RULES_BULK_UPDATE endpoint) + * - Creating rule exceptions (CREATE_RULE_EXCEPTIONS_URL endpoint) + **/ +export const migratePrebuiltSchemaOnRuleUpdate = ({ + nextParams, + existingParams, + isRuleCustomizedDuringUpdate, +}: PrebuiltSchemaUpdateMigrationProps): MigrationResponse => { + const immutable = (Boolean(existingParams.prebuilt) || existingParams.immutable) ?? false; + const prebuilt = getPrebuiltValueForRuleUpdate({ + nextParams, + existingParams, + isRuleCustomizedDuringUpdate, + }); + + return { + immutable, + prebuilt, + }; +}; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/normalization/rule_converters.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/normalization/rule_converters.ts index 64311d65fe5d1f..ef6b8d2476efc2 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/normalization/rule_converters.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/normalization/rule_converters.ts @@ -27,6 +27,8 @@ import type { RuleCreateProps, TypeSpecificCreateProps, TypeSpecificResponse, + Prebuilt, + ElasticUpdateDate, } from '../../../../../common/api/detection_engine/model/rule_schema'; import { EqlRulePatchFields, @@ -85,6 +87,11 @@ import { } from '../utils/utils'; import { createRuleExecutionSummary } from '../../rule_monitoring'; import type { PrebuiltRuleAsset } from '../../prebuilt_rules'; +import { + migratePrebuiltSchemaOnRuleCreation, + migratePrebuiltSchemaOnRuleUpdate, + normalizePrebuiltSchemaOnRuleRead, +} from './prebuilt_rule_schema_migrations'; const DEFAULT_FROM = 'now-6m' as const; const DEFAULT_TO = 'now' as const; @@ -421,14 +428,18 @@ export const patchTypeSpecificSnakeToCamel = ( } }; +export type PatchAPINextParams = PatchRuleRequestBody & { + related_integrations?: RelatedIntegrationArray; + required_fields?: RequiredFieldArray; + setup?: SetupGuide; + prebuilt?: Prebuilt; +}; + // eslint-disable-next-line complexity export const convertPatchAPIToInternalSchema = ( - nextParams: PatchRuleRequestBody & { - related_integrations?: RelatedIntegrationArray; - required_fields?: RequiredFieldArray; - setup?: SetupGuide; - }, - existingRule: SanitizedRule + nextParams: PatchAPINextParams, + existingRule: SanitizedRule, + isRuleCustomizedDuringUpdate = false ): InternalRuleUpdate => { const typeSpecificParams = patchTypeSpecificSnakeToCamel(nextParams, existingRule.params); const existingParams = existingRule.params; @@ -438,6 +449,12 @@ export const convertPatchAPIToInternalSchema = ( const throttle = nextParams.throttle ?? transformFromAlertThrottle(existingRule); const actions = transformToActionFrequency(alertActions, throttle); + const { immutable, prebuilt } = migratePrebuiltSchemaOnRuleUpdate({ + nextParams, + existingParams, + isRuleCustomizedDuringUpdate, + }); + return { name: nextParams.name ?? existingRule.name, tags: nextParams.tags ?? existingRule.tags, @@ -449,7 +466,8 @@ export const convertPatchAPIToInternalSchema = ( falsePositives: nextParams.false_positives ?? existingParams.falsePositives, investigationFields: nextParams.investigation_fields ?? existingParams.investigationFields, from: nextParams.from ?? existingParams.from, - immutable: existingParams.immutable, + immutable, + prebuilt, license: nextParams.license ?? existingParams.license, outputIndex: nextParams.output_index ?? existingParams.outputIndex, timelineId: nextParams.timeline_id ?? existingParams.timelineId, @@ -482,14 +500,18 @@ export const convertPatchAPIToInternalSchema = ( }; }; +export type CreateAPIInput = RuleCreateProps & { + related_integrations?: RelatedIntegrationArray; + required_fields?: RequiredFieldArray; + setup?: SetupGuide; + prebuilt?: Prebuilt; + elasticUpdateDate?: ElasticUpdateDate; +}; + // eslint-disable-next-line complexity export const convertCreateAPIToInternalSchema = ( - input: RuleCreateProps & { - related_integrations?: RelatedIntegrationArray; - required_fields?: RequiredFieldArray; - setup?: SetupGuide; - }, - immutable = false, + input: CreateAPIInput, + isRuleToCreatePrebuilt = false, defaultEnabled = true ): InternalRuleCreate => { const typeSpecificParams = typeSpecificSnakeToCamel(input); @@ -498,6 +520,11 @@ export const convertCreateAPIToInternalSchema = ( const alertActions = input.actions?.map((action) => transformRuleToAlertAction(action)) ?? []; const actions = transformToActionFrequency(alertActions, input.throttle); + const { immutable, prebuilt } = migratePrebuiltSchemaOnRuleCreation({ + input, + isRuleToCreatePrebuilt, + }); + return { name: input.name, tags: input.tags ?? [], @@ -512,6 +539,7 @@ export const convertCreateAPIToInternalSchema = ( investigationFields: input.investigation_fields, from: input.from ?? DEFAULT_FROM, immutable, + prebuilt, license: input.license, outputIndex: input.output_index ?? '', timelineId: input.timeline_id, @@ -657,6 +685,8 @@ export const typeSpecificCamelToSnake = ( // TODO: separate out security solution defined common params from Alerting framework common params // so we can explicitly specify the return type of this function export const commonParamsCamelToSnake = (params: BaseRuleParams) => { + const { immutable, prebuilt } = normalizePrebuiltSchemaOnRuleRead(params); + return { description: params.description, risk_score: params.riskScore, @@ -685,7 +715,8 @@ export const commonParamsCamelToSnake = (params: BaseRuleParams) => { references: params.references, version: params.version, exceptions_list: params.exceptionsList, - immutable: params.immutable, + immutable, + prebuilt, related_integrations: params.relatedIntegrations ?? [], required_fields: params.requiredFields ?? [], setup: params.setup ?? '', @@ -763,6 +794,10 @@ export const convertPrebuiltRuleAssetToRuleResponse = ( created_at: new Date(0).toISOString(), created_by: '', immutable: true, + prebuilt: { + isCustomized: false, + elasticUpdateDate: prebuiltRuleAsset.elasticUpdateDate, + }, revision: 1, }; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_schema/model/rule_schemas.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_schema/model/rule_schemas.ts index deb853335bf24a..c175ed3a7cab56 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_schema/model/rule_schemas.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_schema/model/rule_schemas.ts @@ -29,6 +29,7 @@ import type { RuleName, RuleTagArray, } from '../../../../../common/api/detection_engine/model/rule_schema'; + import { AlertsIndex, AlertsIndexNamespace, @@ -38,6 +39,7 @@ import { InvestigationFields, InvestigationGuide, IsRuleImmutable, + Prebuilt, MaxSignals, RelatedIntegrationArray, RequiredFieldArray, @@ -119,6 +121,7 @@ export const BaseRuleParams = z.object({ ruleId: RuleSignatureId, investigationFields: InvestigationFieldsCombined.optional(), immutable: IsRuleImmutable, + prebuilt: Prebuilt.optional(), license: RuleLicense.optional(), outputIndex: AlertsIndex, timelineId: TimelineTemplateId.optional(), From 053ecd60e3ac357b56ff5955dc9cfa2ec73f0269 Mon Sep 17 00:00:00 2001 From: jpdjere Date: Tue, 13 Feb 2024 15:18:56 +0100 Subject: [PATCH 02/61] Refactor: Updated schema definitions --- .../docs/prebuilt_rules_customization_rfc.md | 190 ++++++++---------- 1 file changed, 83 insertions(+), 107 deletions(-) diff --git a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md index e9a1cc0e787d51..3836c94f96810d 100644 --- a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md +++ b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md @@ -27,6 +27,14 @@ _Pending_: ## Table of Contents +The following TOC was created using the [Pandoc](https://pandoc.org/installing.html) tool. + +You can create it by navigating to the directory of the markdown file and running the command below and pasting the generated table from the output document into the current one: + +``` +pandoc prebuilt_rules_customization_rfc.md --toc --toc-depth=6 --wrap=none -s -o output.md +``` + - [Necessary rule schema changes](#necessary-rule-schema-changes) - [`prebuilt` and `immutable` fields](#prebuilt-and-immutable-fields) - [`isCustomized` subfield](#iscustomized-subfield) @@ -87,55 +95,71 @@ _Pending_: - [Marking rules (and their fields) as customized](#marking-rules-and-their-fields-as-customized) - [Other open questions](#other-open-questions) +## Note about scope of RFC + +This RFC was initially planned to have a scope strictly limited to the Customization of Prebuilt Rules epic. However, another epic is, in parallel, in the discussion phase: the [Detections-as-Code (DaC) epic](https://docs.google.com/document/d/1MfPFa3Io82S91rRfdQde8Xi_9AGEbE44Z2MkIYWD10U/edit). + +Both epics have many areas of contact, and features/decisions in one need to take account features in the others. + +This RFC includes some decision that will be taken in order to future-proof our archtecture for the upcoming DaC epic, but the vast majority will refer specifically to the Prebuilt Rules Customization epic. Elastic prebuilt rules will become a specific case of externally sourced rules: in the future, rules can be installed as Elastic prebuilt rules from our `detection-rules` repo, but also from any other repository handled by the user. + +During this RFC, we will explicitly refer to case of Elastic prebuilt rules, but take into account that this will be only a specific case of all the possible external sources for rules. + ## Necessary rule schema changes -In order to support the customization of Elastic Prebuilt Rules, we need to modify our rule schema. This involves introducing a new nested `prebuilt` field and deprecating the `immutable` field. +In order to support the customization of Elastic Prebuilt Rules, we need to modify our rule schema. This involves introducing a new nested `external_source` field and deprecating the `immutable` field. -### `prebuilt` and `immutable` fields +```ts +// PSEUDOCODE - see complete schema in detail below +{ + external_source?: { + repo_name: string; + is_customized: boolean; + source_updated_at?: Date; + } +} +``` + +### `external_source` and `immutable` fields -The `prebuilt` field will be a top-level object field in our rule schema that will contain subfields with information relating to Elastic Prebuilt rules. +The `external_source` field will be a top-level object field in our rule schema that will contain subfields with information relating to Elastic Prebuilt rules. -It will be an optional field, which will only be present for Elastic prebuilt rules. +It will be an optional field, which will only be present for Elastic prebuilt rules (i.e. rules that are externally soruced). -Its existence within a rule object will determine if a rule is a prebuilt rule (and its absence will determine that it is a custom rule). +Its existence within a rule object will determine if a rule is a prebuilt rule, and its absence will determine that it is a custom rule. This means that its presence in a rule object will determine whether the rule is an Elastic Prebuilt Rule that can receive upstream updates via Fleet. This field is intented to replace the currently existing `immutable` field, which is used today for the same purpose, but -as its name indicates- also currently determines if a rule's fields can be modified/customized. -That means that, in the current state, rules with `immutable: false` are rules which are not Elastic Prebuilt Rules, i.e. custom rules, and can be modified. Meanwhile, `immutable: true` rules are Elastic Prebuilt Rules, created by the TRADE team, distributed via the `security_detection_engine` Fleet package, and cannot be modified once installed. +That means that, in the current state, rules with `immutable: false` are rules which are not Elastic Prebuilt Rules, i.e. custom rules, and can be modified. Meanwhile, `immutable: true` rules are Elastic Prebuilt Rules, created by the TRaDE team, distributed via the `security_detection_engine` Fleet package, and cannot be modified once installed. -When successfully implemented, the `prebuilt` field should replace the `immutable` field as a flag to mark Elastic prebuilt rules, but with one difference: the `prebuilt` field will determine if the rule is an Elastic Prebuilt Rule or not, but now all rules will be customizable by the user, i.e. independently of the existence (or absence) of `prebuilt`. +When successfully implemented, the `external_source` field should replace the `immutable` field as a flag to mark Elastic prebuilt rules, but with one difference: the `external_source` field will determine if the rule is an Elastic Prebuilt Rule or not, but now all rules will be customizable by the user, i.e. independently of the existence (or absence) of `external_source`. -Because of this difference in the behaviour of the `prebuilt` and `immutable` fields, we feel that a field called `immutable` will lose its meaning over time and become confusing, especially for consumers of the API who interact directly with the field name. That's why we want to eventually deprecate it and fully replace it with `prebuilt`. +Because of this difference in the behaviour of the `external_source` and `immutable` fields, we feel that a field called `immutable` will lose its meaning over time and become confusing, especially for consumers of the API who interact directly with the field name. That's why we want to eventually deprecate it and fully replace it with `external_source`. -To ensure backward compatibility and avoid breaking changes, we will deprecate the `immutable` field but keep it within the rule schema, asking our users to stop relying on this field in Detection API responses. During the migration period, we want to keep the value of the `immutable` field in sync with the `prebuilt` field: this means that for all rules that have a `immutable` value of `true`, the `prebuilt` rule will always exist. Viceversa, rule with `immutable: false` will not have a `prebuilt` field. +To ensure backward compatibility and avoid breaking changes, we will deprecate the `immutable` field but keep it within the rule schema, asking our users to stop relying on this field in Detection API responses. During the migration period, we want to keep the value of the `immutable` field in sync with the `external_source` field: this means that for all rules that have a `immutable` value of `true`, the `external_source` rule will always exist. Viceversa, rule with `immutable: false` will not have a `external_source` field. This means, however, that there will be a change in behaviour of the `immutable` field: with the release of the feature, rules with the `immutable: true` value will now be customizable by the user, which is not the current behaviour. -In this first phase, the `prebuilt` will contain two subfields: `isCustomized` and `elasticUpdateDate`. +In this first phase, the `external_source` will contain three subfields: `repo_name`, `is_customized` and `source_updated_at`. -```ts -// PSEUDOCODE - see complete schema in detail below -{ - prebuilt?: { - isCustomized: boolean; - elasticUpdateDate?: Date; - } -} -``` +#### `repo_name` subfield -#### `isCustomized` subfield +The `repo_name` will be a required string field that specifies the origin repo of the rule. For Elastic prebuilt rules, its value will be `elastic_prebuilt`. The field is required since it will be the leaf node used when searching/filtering for externally sourced rules when using KQL. More details about that below. -The `isCustomized` field will be a boolean field that determines whether a Prebuilt Rule has been customized by the user, i.e. if any of its fields have been modified and diverged from the base version of the rule, which is the version that is installed from the Prebuilt Rules `security_detection_engine` Fleet package. -This means that the `isCustomized` subfield only makes sense and will be used for prebuilt rules, or rules whose `prebuilt` field exists. It is therefor a subfield of the `prebuilt` field. +#### `is_customized` subfield -For prebuilt rules, the `prebuilt.isCustomized` value will be initially set to `false` when a brand new rule is installed, but will be rewritten to `true` if a rule's field is edited and diverges from the value from the base version of the rule. +The `is_customized` field will be a boolean field that determines whether a Prebuilt Rule has been customized by the user, i.e. if any of its fields have been modified and diverged from the base version of the rule, which is the version that is installed from the Prebuilt Rules `security_detection_engine` Fleet package. + +This means that the `is_customized` subfield only makes sense and will be used for prebuilt rules, or rules whose `external_source` field exists. It is therefore a subfield of the `external_source` field. + +For prebuilt rules, the `external_source.is_customized` value will be initially set to `false` when a brand new rule is installed, but will be rewritten to `true` if a rule's field is edited and diverges from the value from the base version of the rule. See section [Calculating the `isCustomized` flag]() -#### `elasticUpdateDate` subfield +#### `source_updated_at` subfield -The `elasticUpdateDate` will be a field containing a date in ISO 8601 format which describes the last time that an Elastic Prebuilt Detection rule was created and subsequently updated by the TRaDe team, the team responsible for creating detection rules. Its usage is detailed in this ticket. +The `source_updated_at` will be a field containing a date in ISO 8601 format which describes the last time that an Elastic Prebuilt Detection rule was created and subsequently updated by the TRaDe team, the team responsible for creating detection rules. Its usage is detailed in this [ticket](https://github.com/elastic/detection-rules/issues/2826). This field will be optional in both the API schema and the internal rule schema, since this value will not exist for prebuilt rules until a new version of each rule which includes this field in the prebuilt rule asset is published by the TRaDE team, and the user installs it or updates to it. @@ -147,7 +171,7 @@ This means that we need to differentiate between changes to the internal rule sc #### API schema -**In the API schema** the `prebuilt` field will be optional, as it will exist for Elastic prebuilt rules, but won't for custom rules. The OpenAPI schema will need to be modified so: +**In the API schema** the `external_source` field will be optional, as it will exist for Elastic prebuilt rules, but won't for custom rules. The OpenAPI schema will need to be modified so: _Source: [x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/common_attributes.schema.yaml](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/common_attributes.schema.yaml)_ @@ -159,25 +183,32 @@ IsRuleImmutable: type: boolean description: '[DEPRECATION WARNING - This field is deprecated and will be removed in a future release. Use the prebuilt field to determine if a rule is an Elastic prebuilt rule or a custom rule.] - Determines whether the rule is immutable (i.e. cannot be modified by the user).' -# Add the top-level `prebuilt` object and its subfields `isCustomized` and `elasticUpdateDate` -IsPrebuiltRuleCustomized: +# Add the top-level `external_source` object and its subfields `repo_name`, `is_customized` and `source_updated_at` +ExternalSourceRepoName: + type: string + description: Name of the external origin repo where rule originated from. For rules created by Elastic and originating from the `detection-rules` repo, the value should be `elastic_prebuilt`. + +IsExternalRuleCustomized: type: boolean - description: Determines whether the prebuilt rule has been customized by the user (i.e. any of its fields have been modified and diverge from the base value). + description: Determines whether an external/prebuilt rule has been customized by the user (i.e. any of its fields have been modified and diverged from the base value). -ElasticUpdateDate: +SourceUpdatedAt: type: string format: date-time - description: The date and time that the prebuilt rule was last updated by Elastic. + description: The date and time that the external/prebuilt rule was last updated in its source repository. -Prebuilt: +ExternalSourceAttributes: type: object - description: Property whose existence determines whether the rule is an Elastic Prebuilt Rule that can receive upstream updates via Fleet. Contains information relating to prebuilt rules. + description: Property whose existence determines whether the rule is an externally sourced rule. Contains information relating to externally sourced rules. Elastic Prebuilt rules are a specific case of externally sourced rules. properties: - isCustomized: - $ref: '#/components/schemas/IsPrebuiltRuleCustomized' - elasticUpdateDate: - $ref: '#/components/schemas/ElasticUpdateDate' + repo_name: + $ref: + is_customized: + $ref: '#/components/schemas/IsExternalRuleCustomized' + source_updated_at: + $ref: '#/components/schemas/SourceUpdatedAt' required: + - repo_name - isCustomized # [... file continues below ...] ``` @@ -196,11 +227,11 @@ ResponseFields: $ref: './common_attributes.schema.yaml#/components/schemas/RuleSignatureId' immutable: $ref: './common_attributes.schema.yaml#/components/schemas/IsRuleImmutable' - prebuilt: - $ref: './common_attributes.schema.yaml#/components/schemas/Prebuilt' + external_source: + $ref: './common_attributes.schema.yaml#/components/schemas/ExternalSourceAttributes' # [... more response fields ...] required: - # notice `prebuilt` is not required + # notice `external_source` is not required - id - rule_id - immutable @@ -215,63 +246,9 @@ ResponseFields: # [... file continues below...] ``` -When the OpenAPI code generator is run, this will result in the files: - -_Source: [x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/common_attributes.gen.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/common_attributes.gen.ts)_ - -```ts -// [... file continues above...] - -/** - * [DEPRECATION WARNING - This field is deprecated and will be removed in a future release. Use the prebuilt field to determine if a rule is an Elastic prebuilt rule or a custom rule.] - Determines whether the rule is immutable (i.e. cannot be modified by the user). - */ -export type IsRuleImmutable = z.infer; -export const IsRuleImmutable = z.boolean(); - -/** - * Determines whether the prebuilt rule has been customized by the user (i.e. any of its fields have been modified and diverge from the base value). - */ -export type IsPrebuiltRuleCustomized = z.infer; -export const IsPrebuiltRuleCustomized = z.boolean(); - -/** - * The date and time that the prebuilt rule was last updated by Elastic. - */ -export type ElasticUpdateDate = z.infer; -export const ElasticUpdateDate = z.string().datetime(); - -/** - * Property whose existence determines whether the rule is an Elastic Prebuilt Rule that can receive upstream updates via Fleet. Contains information relating to prebuilt rules. - */ -export type Prebuilt = z.infer; -export const Prebuilt = z.object({ - isCustomized: IsPrebuiltRuleCustomized, - elasticUpdateDate: ElasticUpdateDate.optional(), -}); - -// [... file continues below ...] -``` - -_Source: [x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/rule_schemas.gen.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/rule_schemas.gen.ts)_ - -```ts -// [... file continues above ...] - -export type ResponseFields = z.infer; -export const ResponseFields = z.object({ - id: RuleObjectId, - rule_id: RuleSignatureId, - immutable: IsRuleImmutable, - prebuilt: Prebuilt.optional(), - // [...] -}); - -// [... file continues below ...] -``` - We also need to modify the `RuleToImport` schema, since now we will be allowing the importing of both custom rules and prebuilt rules. -Currently, `RuleToImport` optionally accepts the `immutable` param, but rejects validation if its value is set to anything else than `false` - since we don't currently support importing prebuilt rules. We need to update this schema so that it accepts the `immutable` param with both boolean values, and also optionally accepts the new `prebuilt` field: +Currently, `RuleToImport` optionally accepts the `immutable` param, but rejects validation if its value is set to anything else than `false` - since we don't currently support importing prebuilt rules. We need to update this schema so that it accepts the `immutable` param with both boolean values, and also optionally accepts the new `external_source` field: _Source: [x-pack/plugins/security_solution/common/api/detection_engine/rule_management/import_rules/rule_to_import.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/import_rules/rule_to_import.ts)_ @@ -281,7 +258,7 @@ import { // [...] RuleSignatureId, IsRuleImmutable, - Prebuilt, + ExternalSourceAttributes, } from '../../model/rule_schema'; export type RuleToImport = z.infer; @@ -290,14 +267,14 @@ export const RuleToImport = BaseCreateProps.and(TypeSpecificCreateProps).and( ResponseFields.partial().extend({ rule_id: RuleSignatureId, immutable: IsRuleImmutable.optional(), - prebuilt: Prebuilt.optional(), + external_source: ExternalSourceAttributes.optional(), }) ); ``` #### Internal rule schema -**The internal rule schema** needs to represent that the new `prebuilt` field may not always exist, i.e. for rules yet to be migrated, so `prebuilt` must also be optional. +**The internal rule schema** needs to represent that the new `external_source` field may not always exist, so `external_source` must also be optional. _Source: [x-pack/plugins/security_solution/server/lib/detection_engine/rule_schema/model/rule_schemas.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_schema/model/rule_schemas.ts)_ @@ -306,7 +283,7 @@ _Source: [x-pack/plugins/security_solution/server/lib/detection_engine/rule_sche import { // [...] - Prebuilt, + ExternalSourceAttributes, // [...] } from '../../../../../common/api/detection_engine/model/rule_schema'; @@ -315,18 +292,20 @@ export const BaseRuleParams = z.object({ // [...] immutable: IsRuleImmutable, - prebuilt: Prebuilt.optional(), + external_soruce: ExternalSourceAttributes.transform(camelize).optional(), // [...] }); ``` -In the internal rule schema, there are two additional important reasons why we need to make sure that this values is optional: +> Notice that in the internal schema we cannot simply reuse the `ExternalSourceAttributes` attribute defined for the API schema, since it should have CamelCase and the API schema uses snake_case. We need to apply a transformation to our Zod type. See this [issue](https://github.com/colinhacks/zod/issues/486#issuecomment-1567296747). + +In the internal rule schema, there are two additional important reasons why we need to make sure that this value is optional: - When rules are executed, a call to the method `validateRuleTypeParams` is done, which is a method that validates the passed rule's parameters using the validators defined in `x-pack/plugins/security_solution/server/lib/detection_engine/rule_types`, within each of the rule query types files (for [EQL rules](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/eql/create_eql_alert_type.ts#L27), for example). The validation is done based on the internal rule schema `BaseRulesParams` displayed above. Having `prebuilt` as a required fields would cause custom rules to fail on runtime. - The Rule Client `update` method also calls the `validateRuleTypeParams` to validate the rule's params. Since the Rule Client's `update` method is used in our endpoint handlers, such as and `/rules/patch` and `/_bulk_actions`, these would fail when executed against a payload of custom rule. -Additionally, the `PrebuiltRuleAsset` type needs to be updated to include the new `elasticUpdateDate` date that will be progressively shipped with new versions of rules in the Elastic Prebuilt Rules package: +Additionally, the `PrebuiltRuleAsset` type needs to be updated to include the new `source_updated_at` date that will be progressively shipped with new versions of rules in the Elastic Prebuilt Rules package: _Source: [x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/model/rule_assets/prebuilt_rule_asset.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/model/rule_assets/prebuilt_rule_asset.ts)_ @@ -338,7 +317,7 @@ export const PrebuiltRuleAsset = BaseCreateProps.and(TypeSpecificCreateProps).an related_integrations: RelatedIntegrationArray.optional(), required_fields: RequiredFieldArray.optional(), setup: SetupGuide.optional(), - source_updated_at: ElasticUpdateDate.optional(), // new optional field + source_updated_at: SourceUpdatedAt.optional(), // new optional field }) ); ``` @@ -359,11 +338,8 @@ Both the docs and the custom response header should communicate that the `immuta - is maintained for backwards compatibility reasons only - will be removed after a specific date/release -The endpoints should be updated to include a custom response header like so: +The endpoints should be updated to include a custom response header, using the [format we already use for our bulk CRUD endpoints.](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/deprecation.ts#L34-L43) -```http -Deprecation-Info: immutable field is deprecated and will be removed in version 8.XX (or date). Use prebuilt field instead. -``` ## Mapping changes From 308709df67ee293cee821c9eaae4c75e390b9ecf Mon Sep 17 00:00:00 2001 From: jpdjere Date: Tue, 13 Feb 2024 15:39:20 +0100 Subject: [PATCH 03/61] Refactor: Updated migration context --- .../docs/prebuilt_rules_customization_rfc.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md index 3836c94f96810d..394f911e7b003d 100644 --- a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md +++ b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md @@ -357,7 +357,9 @@ No changes will be needed either for the `security-rule` [mapping](https://githu Historically, migrations to Elasticsearch saved objects were carried out by a procedure in which the changes in the SO were described in a migration operation that would be carried out **during an upgrade to a specific Kibana version**. See `x-pack/plugins/alerting/server/saved_objects/migrations/index.ts` for a list of migrations of SO that take place when a user updates Kibana to a specific version. -However, this mechanism is no longer supported by the Alerting Framework team - which maintained it - and we therefore have to find an alternative strategy. Therefore, we will perform the migration of the saved objects directly in the Detection API's endpoints that interact with them. This means that, instead of all of a user's saved object being migrated in a single operation during a Kibana update, the SO will be migrated when the pertinent endpoints are called. In the next section, we describe which those endpoints are. +However, this mechanism is no longer supported by the Alerting Framework team - which maintained it -, and the new migration mechanism introduced to replace that, the [Model Version API](https://github.com/elastic/kibana/blob/main/packages/core/saved-objects/core-saved-objects-server/docs/model_versions.md), which is Serverless-compatible, doesn't support migrating encrypted saved objects. + +Since our alerting rules are encrypted saved objects, we have to find an alternative strategy to migrate them. Therefore, we will perform the migration of the saved objects directly in the Detection API's endpoints that interact with them. This means that, instead of all of a user's saved object being migrated in a single operation during a Kibana update, the SO will be migrated when the pertinent endpoints are called. In the next section, we describe which those endpoints are. Since the migration of rules will be performed as the user calls the pertinent endpoints, the migration of the saved objects will be carried out progressively and incrementally: the SO will be migrated only when a endpoint that handles it is called by the user. We therefore have to assume that, at any given point in time, a user may have a mix of migrated and non-migrated rule saved objects. Consequently, we must continue supporting both versions of SOs. From b95a52947090ff50853094b16df3609a3485ab07 Mon Sep 17 00:00:00 2001 From: jpdjere Date: Tue, 13 Feb 2024 16:01:08 +0100 Subject: [PATCH 04/61] Refactor: Normalization on write --- .../docs/prebuilt_rules_customization_rfc.md | 85 +++++++------------ 1 file changed, 33 insertions(+), 52 deletions(-) diff --git a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md index 394f911e7b003d..275165daa614ca 100644 --- a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md +++ b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md @@ -375,7 +375,7 @@ This type of migration will be in charge of updating saved object fields in Elas This migration strategy of write/update operations means that a user's data will be migrated incrementally, and that both types of data (non-migrated and migrated saved objects) will coexist for an indeterminate amount of time. Therefore we have to maintain backwards data compatibility for the non-migrated data types. -The migration logic should take place as a first step within the handler logic of all endpoints that carry out write/update endpoint operations, and the endpoint should return the already-migrated rule(s). +The migration logic should take place within the handler logic of all endpoints that carry out write/update endpoint operations, and the endpoint should return the already-migrated rule(s). ##### Rule Management endpoints that should include migration-on-write logic @@ -418,66 +418,57 @@ All endpoints that respond with a rule Saved Object, typed as `RuleResponse`, wi This means that the endpoints will always respond with the rules with the new schema, while the actual rule might still be stored with the legacy schema in Elasticsearch, if it still has not been migrated-on-write. -The **normalization on read** will be carried out by a new `normalizePrebuiltSchemaOnRuleRead` normalization function. The `internalRuleToAPIResponse` method, which is used in our endpoints to convert a rule saved object as is stored in Elasticsearch to the `RuleResponse` type which is returned to the client, calls the `commonParamsCamelToSnake` methods to convert rule parameters that are common to all rule types to what's expected in `RuleResponse`. Inside this method, we will use `normalizePrebuiltSchemaOnRuleRead` to calculate the normalized values of `prebuilt` and `immutable`. +The **normalization on read** will be carried out by a new `normalizePrebuiltSchemaOnRuleRead` normalization function. The `internalRuleToAPIResponse` method, which is used in our endpoints to convert a rule saved object as is stored in Elasticsearch to the `RuleResponse` type which is returned to the client, calls the `commonParamsCamelToSnake` methods to convert rule parameters that are common to all rule types to what's expected in `RuleResponse`. Inside this method, we will use `normalizePrebuiltSchemaOnRuleRead` to calculate the normalized values of `external_source` and `immutable`. _Source: [x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/normalization/rule_converters.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/normalization/rule_converters.ts)_ ```ts -// [... file continues above...] -export const internalRuleToAPIResponse = ( - rule: SanitizedRule | ResolvedSanitizedRule -): RequiredOptional => { - // [... more method implementation details...] +export const internalRuleToAPIResponse = (rule) => { return { - name: rule.name, - tags: rule.tags, - - // [... more object properties ...] - ...commonParamsCamelToSnake(rule.params), // <--- rule params are converted here ...typeSpecificCamelToSnake(rule.params), - // [... more object properties ...] }; }; -// [... file continues here...] - export const commonParamsCamelToSnake = (params: BaseRuleParams) => { - const { immutable, prebuilt } = normalizePrebuiltSchemaOnRuleRead(params); + const { immutable, external_source } = normalizePrebuiltSchemaOnRuleRead(params); return { - description: params.description, - risk_score: params.riskScore, - - // [... more object properties ...] - immutable, - prebuilt, + external_source, + // [... more object properties ...] }; }; -// [... file continues below...] ``` -And the `normalizePrebuiltSchemaOnRuleRead` is defined so: +And the `normalizePrebuiltSchemaOnRuleRead` can be defined so: _Source: x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/normalization/prebuilt_rule_schema_migrations.ts_ (New file) ```ts -interface MigrationResponse { +interface OnReadNormalizationResult { immutable: IsRuleImmutable; - prebuilt?: Prebuilt; + external_source?: ExternalSourceAttributes; } -const getPrebuiltValueForRuleRead = (ruleParams: BaseRuleParams): Prebuilt | undefined => { - if (ruleParams.prebuilt) { - return ruleParams.prebuilt; +/** + * To calculate `external_source`: + * - Use `external_source` field if already exists in the internal rule object params. + * - If it does not exist, check the value `immutable` from the rules param: + * - if it is `true`, create a new `external_source` object, with `isCustomized` set to `false` and `repoNam` set to `elastic_prebuilt` (Use case of external_source rules that have not been yet migrated-on-write) + * - otherwise, the field should be `undefined` (use case of custom rules). + */ +const getExternalSourceValueForRuleRead = (ruleParams: BaseRuleParams): ExternalSourceAttributes | undefined => { + if (ruleParams.external_source) { + return ruleParams.external_source; } if (ruleParams.immutable) { return { + repoName: 'elastic_prebuilt' isCustomized: false, }; } @@ -487,35 +478,25 @@ const getPrebuiltValueForRuleRead = (ruleParams: BaseRuleParams): Prebuilt | und export const normalizePrebuiltSchemaOnRuleRead = ( ruleParams: BaseRuleParams -): MigrationResponse => { - const immutable = Boolean(ruleParams.prebuilt) || ruleParams.immutable; - const prebuilt = getPrebuiltValueForRuleRead(ruleParams); +): OnReadNormalizationResult => { + + +/** + * To calculate `immutable`: + * - Checks if the `external_source` field exists in the rule's parameters. + * - If `external_source` exists, sets `immutable` to `true`. (Use case of Rules that have already been migrated-on-write) + * - If `external_source` does not exist, return the value of the params' `immutable` field. (Use case of Rules that have not yet been migrated on write.) + */ + const immutable = Boolean(ruleParams.external_source) || Boolean(ruleParams.immutable); + const external_source = getExternalSourceValueForRuleRead(ruleParams); return { immutable, - prebuilt, + external_source, }; }; ``` -The logic for calculating the `immutable` and `prebuilt` fields for **normalization-on-read**, seen in the code above, is as follows: - -- For `immutable`: - - - Check if the `prebuilt` field exists in the rule's parameters, and set `immutable` to `true` if it does. - - Use case 1: rules that have already been migrated-on-write - - If it does not exist, set `immutable` to the current value of the params' `immutable` field. - - Use case 2: rules that have not yet been migrated on write - -- For `prebuilt`: - - If the `prebuilt` field already exists in the internal rule object params, use that value: - - Use case 1: prebuilt rules that have already been migrated-on-write - - If it does not exist, check the value `immutable` from the rules param: - - if it is `true`, create a new `prebuilt` object. This object will only have the `isCustomized` field, set to `false`. The `elasticUpdateDate` date will not be known and must be left undefined. - - Use case 2: prebuilt rules that have not been yet migrated-on-write - - otherwise, the field should be `undefined`. - - Use case 3L: custom rules - ##### Rule Management endpoints that will perform normalization-on-read - All endpoints that also perform migration-on-write, as listed above. All of them use the `internalRuleToAPIResponse` methods to transform the rule before returning the response, so the normalization on read will take place there. For these specific cases, however, the normalization-on-read will take place, but the data stored in ES for each rule should match the response given by the endpoint, i.e. the normalized in-memory value and the stored value of the rule should be the same. @@ -533,7 +514,7 @@ The logic for calculating the `immutable` and `prebuilt` fields for **normalizat ### Technical implementation of migration-on-write -The logic for the migration of the rule saved objects, which means the determination of the `immutable` and `prebuilt` fields before writing to ES, will be encapsulated in three helper methods: +The logic for the migration of the rule saved objects, which means the determination of the `immutable` and `external_source` fields before writing to ES, will be encapsulated in three helper methods: - `migratePrebuiltSchemaOnRuleCreation` for rule creation - `migratePrebuiltSchemaOnRuleUpdate` for rule updates (including patching) From a461cf58a04c79c555ccfaa230b0a697ae6ca89c Mon Sep 17 00:00:00 2001 From: jpdjere Date: Tue, 13 Feb 2024 16:38:43 +0100 Subject: [PATCH 05/61] Refactor: Add table for updating actions --- .../docs/prebuilt_rules_customization_rfc.md | 452 ++++++++++++------ 1 file changed, 319 insertions(+), 133 deletions(-) diff --git a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md index 275165daa614ca..1e945599de2199 100644 --- a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md +++ b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md @@ -1,13 +1,14 @@ # RFC: Prebuilt Rules Customization _Status_: Finished Part 1, which includes sections from `Necessary rule schema changes` up until -and including- `Exporting and importing rules`. - - Covers: - - rule schema changes - - mappings - - migration strategy and technical implementation - - exporting and importing rules - - schema-related changes needed in endpoints + +Covers: + +- rule schema changes +- mappings +- migration strategy and technical implementation +- exporting and importing rules +- schema-related changes needed in endpoints _Pending_: @@ -35,65 +36,65 @@ You can create it by navigating to the directory of the markdown file and runnin pandoc prebuilt_rules_customization_rfc.md --toc --toc-depth=6 --wrap=none -s -o output.md ``` -- [Necessary rule schema changes](#necessary-rule-schema-changes) - - [`prebuilt` and `immutable` fields](#prebuilt-and-immutable-fields) - - [`isCustomized` subfield](#iscustomized-subfield) - - [`elasticUpdateDate` subfield](#elasticupdatedate-subfield) - - [Changes needed in rule schema](#changes-needed-in-rule-schema) - - [API schema](#api-schema) - - [Internal rule schema](#internal-rule-schema) - - [Deprecating the `immutable` field](#deprecating-the-immutable-field) -- [Mapping changes](#mapping-changes) -- [Plan for carrying out migrations of rule SOs](#plan-for-carrying-out-migrations-of-rule-sos) - - [Context](#context) - - [Migration strategy](#migration-strategy) - - [Migration on write](#migration-on-write) - - [Rule Management endpoints that should include migration-on-write logic](#rule-management-endpoints-that-should-include-migration-on-write-logic) - - [Normalization on read](#normalization-on-read) - - [Rule Management endpoints that will perform normalization-on-read](#rule-management-endpoints-that-will-perform-normalization-on-read) - - [Technical implementation of migration-on-write](#technical-implementation-of-migration-on-write) - - [`migratePrebuiltSchemaOnRuleCreation`](#migrateprebuiltschemaonrulecreation) - - [`convertCreateAPIToInternalSchema` and `createRules`](#convertcreateapitointernalschema-and-createrules) - - [`duplicateRule`](#duplicaterule) - - [`migratePrebuiltSchemaOnRuleUpdate`](#migrateprebuiltschemaonruleupdate) - - [`convertPatchAPIToInternalSchema` and `patchRules`](#convertpatchapitointernalschema-and-patchrules) - - [`updateRules`](#updaterules) - - [`migratePrebuiltSchemaOnRuleBulkEdit`](#migrateprebuiltschemaonrulebulkedit) -- [Other endpoints and utilities that will need to be adapted to the new schema](#other-endpoints-and-utilities-that-will-need-to-be-adapted-to-the-new-schema) - - [Utilities](#utilities) - - [KQL filters and the `convertRulesFilterToKQL` method](#kql-filters-and-the-convertrulesfiltertokql-method) - - [Rule Management endpoints](#rule-management-endpoints) - - [Prebuilt Rules endpoints](#prebuilt-rules-endpoints) - - [Rule monitoring endpoints](#rule-monitoring-endpoints) - - [Rule Execution Logs](#rule-execution-logs) -- [Exporting and importing rules](#exporting-and-importing-rules) - - [Exporting rules](#exporting-rules) - - [Importing rules](#importing-rules) - - [Handling the `version` parameter](#handling-the-version-parameter) -- [Customizing Prebuilt Rules](#customizing-prebuilt-rules) - - [Endpoints](#endpoints) - - [Changes needed to endpoints](#changes-needed-to-endpoints) - - [Update Rule - `PUT /rules`](#update-rule---put-rules) - - [Patch Rule - `PATCH /rules`](#patch-rule---patch-rules) - - [Bulk Patch Rules - `PATCH /rules/_bulk_update`](#bulk-patch-rules---patch-rules_bulk_update) - - [Bulk Update Rules - `PUT /rules/_bulk_update`](#bulk-update-rules---put-rules_bulk_update) - - [Bulk Actions - `POST /rules/_bulk_action`](#bulk-actions---post-rules_bulk_action) - - [Updating the `customized` field](#updating-the-customized-field) - - [In the UI](#in-the-ui) - - [Via the Rule Edit Page](#via-the-rule-edit-page) - - [Via Bulk Actions](#via-bulk-actions) - - [Via the Rules Details Page](#via-the-rules-details-page) - - [Via the Shared Exception Lists page](#via-the-shared-exception-lists-page) - - [Via the Stack Management \> Rules UI](#via-the-stack-management-rules-ui) -- [List of things to fix (create tickets)](#list-of-things-to-fix-create-tickets) - - [Rule fields](#rule-fields) -- [Updating Prebuilt Rules](#updating-prebuilt-rules) - - [Changes to upgrade `_review` and `_perform` endpoints](#changes-to-upgrade-_review-and-_perform-endpoints) - - [Rule field diff algorithms](#rule-field-diff-algorithms) -- [Changes in UI](#changes-in-ui) -- [Scenarios for bulk accepting updates](#scenarios-for-bulk-accepting-updates) -- [Marking rules (and their fields) as customized](#marking-rules-and-their-fields-as-customized) -- [Other open questions](#other-open-questions) +- [Necessary rule schema changes](#necessary-rule-schema-changes) + - [`prebuilt` and `immutable` fields](#prebuilt-and-immutable-fields) + - [`isCustomized` subfield](#iscustomized-subfield) + - [`elasticUpdateDate` subfield](#elasticupdatedate-subfield) + - [Changes needed in rule schema](#changes-needed-in-rule-schema) + - [API schema](#api-schema) + - [Internal rule schema](#internal-rule-schema) + - [Deprecating the `immutable` field](#deprecating-the-immutable-field) +- [Mapping changes](#mapping-changes) +- [Plan for carrying out migrations of rule SOs](#plan-for-carrying-out-migrations-of-rule-sos) + - [Context](#context) + - [Migration strategy](#migration-strategy) + - [Migration on write](#migration-on-write) + - [Rule Management endpoints that should include migration-on-write logic](#rule-management-endpoints-that-should-include-migration-on-write-logic) + - [Normalization on read](#normalization-on-read) + - [Rule Management endpoints that will perform normalization-on-read](#rule-management-endpoints-that-will-perform-normalization-on-read) + - [Technical implementation of migration-on-write](#technical-implementation-of-migration-on-write) + - [`migratePrebuiltSchemaOnRuleCreation`](#migrateprebuiltschemaonrulecreation) + - [`convertCreateAPIToInternalSchema` and `createRules`](#convertcreateapitointernalschema-and-createrules) + - [`duplicateRule`](#duplicaterule) + - [`migratePrebuiltSchemaOnRuleUpdate`](#migrateprebuiltschemaonruleupdate) + - [`convertPatchAPIToInternalSchema` and `patchRules`](#convertpatchapitointernalschema-and-patchrules) + - [`updateRules`](#updaterules) + - [`migratePrebuiltSchemaOnRuleBulkEdit`](#migrateprebuiltschemaonrulebulkedit) +- [Other endpoints and utilities that will need to be adapted to the new schema](#other-endpoints-and-utilities-that-will-need-to-be-adapted-to-the-new-schema) + - [Utilities](#utilities) + - [KQL filters and the `convertRulesFilterToKQL` method](#kql-filters-and-the-convertrulesfiltertokql-method) + - [Rule Management endpoints](#rule-management-endpoints) + - [Prebuilt Rules endpoints](#prebuilt-rules-endpoints) + - [Rule monitoring endpoints](#rule-monitoring-endpoints) + - [Rule Execution Logs](#rule-execution-logs) +- [Exporting and importing rules](#exporting-and-importing-rules) + - [Exporting rules](#exporting-rules) + - [Importing rules](#importing-rules) + - [Handling the `version` parameter](#handling-the-version-parameter) +- [Customizing Prebuilt Rules](#customizing-prebuilt-rules) + - [Endpoints](#endpoints) + - [Changes needed to endpoints](#changes-needed-to-endpoints) + - [Update Rule - `PUT /rules`](#update-rule---put-rules) + - [Patch Rule - `PATCH /rules`](#patch-rule---patch-rules) + - [Bulk Patch Rules - `PATCH /rules/_bulk_update`](#bulk-patch-rules---patch-rules_bulk_update) + - [Bulk Update Rules - `PUT /rules/_bulk_update`](#bulk-update-rules---put-rules_bulk_update) + - [Bulk Actions - `POST /rules/_bulk_action`](#bulk-actions---post-rules_bulk_action) + - [Updating the `customized` field](#updating-the-customized-field) + - [In the UI](#in-the-ui) + - [Via the Rule Edit Page](#via-the-rule-edit-page) + - [Via Bulk Actions](#via-bulk-actions) + - [Via the Rules Details Page](#via-the-rules-details-page) + - [Via the Shared Exception Lists page](#via-the-shared-exception-lists-page) + - [Via the Stack Management \> Rules UI](#via-the-stack-management-rules-ui) +- [List of things to fix (create tickets)](#list-of-things-to-fix-create-tickets) + - [Rule fields](#rule-fields) +- [Updating Prebuilt Rules](#updating-prebuilt-rules) + - [Changes to upgrade `_review` and `_perform` endpoints](#changes-to-upgrade-_review-and-_perform-endpoints) + - [Rule field diff algorithms](#rule-field-diff-algorithms) +- [Changes in UI](#changes-in-ui) +- [Scenarios for bulk accepting updates](#scenarios-for-bulk-accepting-updates) +- [Marking rules (and their fields) as customized](#marking-rules-and-their-fields-as-customized) +- [Other open questions](#other-open-questions) ## Note about scope of RFC @@ -146,7 +147,6 @@ In this first phase, the `external_source` will contain three subfields: `repo_n The `repo_name` will be a required string field that specifies the origin repo of the rule. For Elastic prebuilt rules, its value will be `elastic_prebuilt`. The field is required since it will be the leaf node used when searching/filtering for externally sourced rules when using KQL. More details about that below. - #### `is_customized` subfield The `is_customized` field will be a boolean field that determines whether a Prebuilt Rule has been customized by the user, i.e. if any of its fields have been modified and diverged from the base version of the rule, which is the version that is installed from the Prebuilt Rules `security_detection_engine` Fleet package. @@ -202,7 +202,7 @@ ExternalSourceAttributes: description: Property whose existence determines whether the rule is an externally sourced rule. Contains information relating to externally sourced rules. Elastic Prebuilt rules are a specific case of externally sourced rules. properties: repo_name: - $ref: + $ref: is_customized: $ref: '#/components/schemas/IsExternalRuleCustomized' source_updated_at: @@ -340,7 +340,6 @@ Both the docs and the custom response header should communicate that the `immuta The endpoints should be updated to include a custom response header, using the [format we already use for our bulk CRUD endpoints.](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/deprecation.ts#L34-L43) - ## Mapping changes **Alert (rule objects) mapping** @@ -367,54 +366,9 @@ Since the migration of rules will be performed as the user calls the pertinent e Our migration strategy will consist of two distinct types of migration: a **migration on write** that will update the SO on Elasticsearch, and a **normalization on read**, which will transform legacy rules to the new schema **in memory** on read operation, before returning it as a response from an API endpoint. -#### Migration on write - -This type of migration will be in charge of updating saved object fields in Elasticsearch from the legacy form to the new form, and will be performed on all write operations of the rules (see list below). This means that we need to perform this type of migration of rules whenever any endpoint operation that writes/updates a rule saved object is called. - -> In Elasticsearch, the type of rule saved objects is called `alert`. - -This migration strategy of write/update operations means that a user's data will be migrated incrementally, and that both types of data (non-migrated and migrated saved objects) will coexist for an indeterminate amount of time. Therefore we have to maintain backwards data compatibility for the non-migrated data types. - -The migration logic should take place within the handler logic of all endpoints that carry out write/update endpoint operations, and the endpoint should return the already-migrated rule(s). - -##### Rule Management endpoints that should include migration-on-write logic - -All of the following endpoints either fetch the rule before updating it, or send the rule's params as part of the body in the request. Therefore, we can apply migraton logic to them -as described below- before saving the rules to Elasticsearch. - -- **Update Rule** - `PUT /rules`: used in the UI when updating/modifying a single rule via the Rule Editing page -- **Patch Rule** - `PATCH /rules`: used in the UI for attaching shared exceptions list to rules -- **Bulk Update Rules** - `PUT /rules/_bulk_update`: deprecated and unused by the UI. Might still be used by API users -- **Bulk Patch Rules** - `PATCH /rules/_bulk_update`: deprecated and unused by the UI. Might still be used by API users -- **Import Rules** - `POST /rules/_import`: - - See section [Importing rules](#importing-rules) -- **Perform Rule Upgrade** - `POST /prebuilt_rules/upgrade/_perform` (Internal): current way of upgrading a prebuilt rule -- **(LEGACY) Install Prebuilt Rules And Timelines** - `PUT /rules/prepackaged`: legacy endpoint for installing prebuilt rules. Also updates existing prebuilt rules package, so these rules should be migrated during update as well. -- **Bulk Actions** - `POST /rules/_bulk_action`: - This endpoint includes many types of actions, but only the **bulk edit** and the **duplicate** actions should perform a migration on write. - -This endpoint also includes a `dry_run` mode that is executed to evaluate preconditions and warn the user before executing the actual request. No migration logic should take place for dry run requests, i.e when `dry_run=true`, since we never write to ES when this parameter is set to `true`. - -For the **bulk edit** action, we can take advantage of the `ruleParamsModifier` to carry out the migration, regardless of the type of edit that is being performed. See implementation details in the below [Technical implementation of migration-on-write](#technical-implementation-of-migration-on-write) section. - -For the **duplicate** rule action: - -Since we will be creating a new rule on ES, we should create it with the new schema. Per definition, all duplicated rules will be `custom` rules. That means that for all rules -including prebuilt rules-, when duplicating, the `prebuilt` field will not be created on the newly created rule. -This action will not perform a migration-on-write of the original rule being duplicated for two reasons: - -- would violate the principle of least surprise for the endpoint -- the current implementation of the endpoint does not modify the original rule. This gives us no window of opportunity to migrate the rule and save to ES without adding performance overhead. -- See implementation details below. - -All other type of actions should **not** perform migration-on-write: - -- Enable -- Disable -- Delete -- Export: see Importing and Exporting Rules section below - -#### Normalization on read with `normalizePrebuiltSchemaOnRuleRead` +#### Normalization on read -All endpoints that respond with a rule Saved Object, typed as `RuleResponse`, will also perform **normalization on read**, which will transform legacy rules to the new schema **in memory** on read operation, before returning it as a response from an API endpoint. +All endpoints that respond with a rule Saved Object, typed as `RuleResponse`, will perform **normalization on read**, which will transform legacy rules to the new schema **in memory** on read operation, before returning it as a response from an API endpoint. This means that the endpoints will always respond with the rules with the new schema, while the actual rule might still be stored with the legacy schema in Elasticsearch, if it still has not been migrated-on-write. @@ -423,7 +377,6 @@ The **normalization on read** will be carried out by a new `normalizePrebuiltSch _Source: [x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/normalization/rule_converters.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/normalization/rule_converters.ts)_ ```ts - export const internalRuleToAPIResponse = (rule) => { return { ...commonParamsCamelToSnake(rule.params), // <--- rule params are converted here @@ -441,7 +394,6 @@ export const commonParamsCamelToSnake = (params: BaseRuleParams) => { // [... more object properties ...] }; }; - ``` And the `normalizePrebuiltSchemaOnRuleRead` can be defined so: @@ -479,15 +431,14 @@ const getExternalSourceValueForRuleRead = (ruleParams: BaseRuleParams): External export const normalizePrebuiltSchemaOnRuleRead = ( ruleParams: BaseRuleParams ): OnReadNormalizationResult => { - - + /** * To calculate `immutable`: * - Checks if the `external_source` field exists in the rule's parameters. * - If `external_source` exists, sets `immutable` to `true`. (Use case of Rules that have already been migrated-on-write) * - If `external_source` does not exist, return the value of the params' `immutable` field. (Use case of Rules that have not yet been migrated on write.) */ - const immutable = Boolean(ruleParams.external_source) || Boolean(ruleParams.immutable); + const immutable = Boolean(ruleParams.external_source) || Boolean(ruleParams.immutable); const external_source = getExternalSourceValueForRuleRead(ruleParams); return { @@ -499,10 +450,10 @@ export const normalizePrebuiltSchemaOnRuleRead = ( ##### Rule Management endpoints that will perform normalization-on-read -- All endpoints that also perform migration-on-write, as listed above. All of them use the `internalRuleToAPIResponse` methods to transform the rule before returning the response, so the normalization on read will take place there. For these specific cases, however, the normalization-on-read will take place, but the data stored in ES for each rule should match the response given by the endpoint, i.e. the normalized in-memory value and the stored value of the rule should be the same. -- **Find Rules - `GET /rules/_find`**: transforms rules in response to `RuleResponse` type with the `internalRuleToAPIResponse` method. -- **Read Rule - GET /rules:**: transforms rule in response to `RuleResponse` type with the `internalRuleToAPIResponse` method. -- **Delete Rules - DELETE /rules**: transforms rule in response to `RuleResponse` type with the `internalRuleToAPIResponse` method. +- All endpoints that also perform migration-on-write, as listed in the below `Migration on write` section. All of them use the `internalRuleToAPIResponse` methods to transform the rule before returning the response, so the normalization on read will take place there. For these specific cases, however, the normalization-on-read will take place, but the data stored in ES for each rule should match the response given by the endpoint, i.e. the normalized in-memory value and the stored value of the rule should be the same. +- **Find Rules - `GET /rules/_find`** +- **Read Rule - GET /rules:** +- **Delete Rules - DELETE /rules** - **Bulk Actions** - `POST /rules/_bulk_action`: all other action types not mentioned in the previous section will perform normalization-on-read before responding: - Enable - Disable @@ -512,9 +463,244 @@ export const normalizePrebuiltSchemaOnRuleRead = ( - this endpoint is unused via the UI, but might still be used via the public API - same logic as for `_bulk_action` with the `export` action explained in section [Exporting rules](#exporting-rules) below: only normalization-on-read will be performed before writing to the output `ndjson` file. +#### Migration on write + +This type of migration will be in charge of updating saved object fields in Elasticsearch from the legacy form to the new form, and will be performed on all write operations of the rules (see list below). This means that we need to perform this type of migration of rules whenever any endpoint operation that writes/updates a rule saved object is called. + +> In Elasticsearch, the type of rule saved objects is called `alert`. + +This migration strategy of write/update operations means that a user's data will be migrated incrementally, and that both types of data (non-migrated and migrated saved objects) will coexist for an indeterminate amount of time. Therefore we have to maintain backwards data compatibility for the non-migrated data types. + +The migration logic should take place within the handler logic of all endpoints that carry out write/update endpoint operations, and the endpoint should return the already-migrated rule(s). + +##### Rule Management endpoints that should include migration-on-write logic + +All of the following endpoints either fetch the rule before updating it, or send the rule's params as part of the body in the request. Therefore, we can apply migraton logic to them -as described below- before saving the rules to Elasticsearch. + +- **Update Rule** - `PUT /rules`: used in the UI when updating/modifying a single rule via the Rule Editing page +- **Patch Rule** - `PATCH /rules`: used in the UI for attaching shared exceptions list to rules +- **Bulk Update Rules** - `PUT /rules/_bulk_update`: deprecated and unused by the UI. Might still be used by API users +- **Bulk Patch Rules** - `PATCH /rules/_bulk_update`: deprecated and unused by the UI. Might still be used by API users +- **Import Rules** - `POST /rules/_import`: + - See section [Importing rules](#importing-rules) +- **Perform Rule Upgrade** - `POST /prebuilt_rules/upgrade/_perform` (Internal): current way of upgrading a prebuilt rule +- **(LEGACY) Install Prebuilt Rules And Timelines** - `PUT /rules/prepackaged`: legacy endpoint for installing prebuilt rules. Also updates existing prebuilt rules package, so these rules should be migrated during update as well. +- **Bulk Actions** - `POST /rules/_bulk_action`: + This endpoint includes many types of actions, but only the **bulk edit** and the **duplicate** actions should perform a migration on write. + +This endpoint also includes a `dry_run` mode that is executed to evaluate preconditions and warn the user before executing the actual request. No migration logic should take place for dry run requests, i.e when `dry_run=true`, since we never write to ES when this parameter is set to `true`. + +For the **bulk edit** action, we can take advantage of the `ruleParamsModifier` to carry out the migration, regardless of the type of edit that is being performed. See implementation details in the below [Technical implementation of migration-on-write](#technical-implementation-of-migration-on-write) section. + +For the **duplicate** rule action: + +Since we will be creating a new rule on ES, we should create it with the new schema. Per definition, all duplicated rules will be `custom` rules. That means that for all rules -including prebuilt rules-, when duplicating, the `prebuilt` field will not be created on the newly created rule. +This action will not perform a migration-on-write of the original rule being duplicated for two reasons: + +- would violate the principle of least surprise for the endpoint +- the current implementation of the endpoint does not modify the original rule. This gives us no window of opportunity to migrate the rule and save to ES without adding performance overhead. +- See implementation details below. + +All other type of actions should **not** perform migration-on-write: + +- Enable +- Disable +- Delete +- Export: see Importing and Exporting Rules section below + ### Technical implementation of migration-on-write -The logic for the migration of the rule saved objects, which means the determination of the `immutable` and `external_source` fields before writing to ES, will be encapsulated in three helper methods: +The logic for the migration of the rule saved objects, which means the determination of the `immutable` and `external_source` fields before writing to ES, might differ depending on the action being performed by the user. + +Let's see all possible use cases that will require migration-on-write, the endpoints that they apply to, and the expected resulting migrated field, based on the action and their input. + +#### Upgrading rules + +Upgrading rules can currently be performed via four endpoints: + +- **Update Rule** - `PUT /rules` +- **Patch Rule** - `PATCH /rules` +- **Bulk Update Rules** - `PUT /rules/_bulk_update` +- **Bulk Patch Rules** - `PATCH /rules/_bulk_update` + +The resulting values for `immutable` and `external_source` when calling these endpoints, and the migration being performed in the background, should be as follows: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Use caseCurrent value of
external_source
Current value of
immutable
Any field diverges
from base version during update?
Results
Migrating a custom rule (migrated or not yet) +
undefined
+
false
N/A - Doesn't apply for custom rules +
+          {
+            immutable: false
+          }
+        
+
Migrating a non yet migrated prebuilt rule, with customizations +
undefined
+
true
Yes +
+          {
+            external_source: {
+              repoName: 'elastic_prebuilt',
+              isCustomized: true,
+              ...
+            },
+            immutable: true
+          }
+        
+
Migrating a non yet migrated prebuilt rule, with customizations +
undefined
+
true
Yes +
+          {
+            external_source: {
+              repoName: 'elastic_prebuilt',
+              isCustomized: true,
+              ...
+            },
+            immutable: true
+          }
+        
+
Migrating a migrated non-customized prebuilt rule, no customizations +
 
+          {
+            repoName: 'elastic_prebuilt',
+            isCustomized: false,
+              ...
+          }
+          
+
true
No +
+          {
+            external_source: {
+              repoName: 'elastic_prebuilt',
+              isCustomized: false,
+              ...
+            },
+            immutable: true
+          }
+        
+
Migrating a migrated customized prebuilt rule, no customizations +
 
+          {
+            repoName: 'elastic_prebuilt',
+            isCustomized: true,
+              ...
+          }
+          
+
true
No +
+          {
+            external_source: {
+              repoName: 'elastic_prebuilt',
+              isCustomized: true,
+              ...
+            },
+            immutable: true
+          }
+        
+
Migrating a migrated customized prebuilt rule, with customizations +
 
+          {
+            repoName: 'elastic_prebuilt',
+            isCustomized: true,
+              ...
+          }
+          
+
true
Yes +
+          {
+            external_source: {
+              repoName: 'elastic_prebuilt',
+              isCustomized: true,
+              ...
+            },
+            immutable: true
+          }
+        
+
Invalid case: Migrating a migrated non-customized prebuilt rule, with customizations.

`immutable` should never be false if `external_source` is defined. Migration should correct this inconsistency.
+
 
+          {
+            repoName: 'elastic_prebuilt',
+            isCustomized: false,
+              ...
+          }
+          
+
false
Yes +
+          {
+            external_source: {
+              repoName: 'elastic_prebuilt',
+              isCustomized: true,
+              ...
+            },
+            immutable: true
+          }
+        
+
+ +--- - `migratePrebuiltSchemaOnRuleCreation` for rule creation - `migratePrebuiltSchemaOnRuleUpdate` for rule updates (including patching) @@ -1897,7 +2083,8 @@ export const getRulesFromObjects = async ( Notice that the **Bulk Actions** - `POST /rules/_bulk_action` does not perform a **dry run** in order to filter out prebuilt rules when the user runs an **export** action; this is the only check that is performed. -*Source: [x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/export/get_export_all.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/export/get_export_all.ts)* +_Source: [x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/export/get_export_all.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/export/get_export_all.ts)_ + ```ts // [... file continues above ...] export const getExportAll = async ( @@ -2019,7 +2206,6 @@ Given the requirements described above, the following table shows the behaviour - If a user imports a prebuilt rule (where either the `prebuilt` or `immutable` fields are `true`), it will continue to track the rule asset from the `security_detection_engine` package if the `rule_id` matches. This means that a user will be able to update a previously exported prebuilt rule, visualize any diffs on any customized fields, and continue to receive updates on the rule. With this migration strategy for the import endpoints we can guarantee backwards compatibility for all rules, and don't need to do additional changes to the export endpoints. @@ -2028,7 +2214,8 @@ The `importRules` helper method that our import endpoint handler use rely on the Given that, when importing rules, we can be creating a custom rule or a prebuilt rule, we need to calculate and appropiately pass the `isPrebuilt` flag to the `createRules` method. The `importRules` helper thus needs to be modified so: -*Source: [x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/import/import_rules_utils.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/import/import_rules_utils.ts)* +_Source: [x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/import/import_rules_utils.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/import/import_rules_utils.ts)_ + ```ts // [... file continues above ...] @@ -2099,8 +2286,9 @@ Since users will be importing rules via an `ndjson` file, they can potentially m **3. The user increases the `version` field from the importing payload:** or example, a user exports a prebuilt rule with `version: 5`, and before importing it modifies it to `version: 6`. This would mean that when the actual rule with `version: 6` was released, we wouldn't trigger the update workflow, since the version from the target version (the update) needs to be higher than what is currently installed for that to happen. However, the update would eventually be triggered when the next update was released, i.e. when `version: 7` is released, and work as expected. **4. The user sets the `version` field from the importing payload to a number that does not exist in the Prebuilt Rules package**: this scenario would still depend on whether the `version` that the user modifies the rule to is higher or lower than the version of the update: - - If it was higher, then we would be back in **scenario 3**, where the update workflow wouldn't trigger. - - If it was lower, then we would be in **scenario 2**, but with the additional problem that we wouldn't be able to fetch the **base** version of the rule - the unmodified version of the rule as it exists in the Prebuilt Rules package. However, we would still be able to normally display the rule field diffs between the current rule and the target (next version) rule (which is the default behaviour), but not between the base and the target (which is a feature that we want to a add as part of this Milestone). + +- If it was higher, then we would be back in **scenario 3**, where the update workflow wouldn't trigger. +- If it was lower, then we would be in **scenario 2**, but with the additional problem that we wouldn't be able to fetch the **base** version of the rule - the unmodified version of the rule as it exists in the Prebuilt Rules package. However, we would still be able to normally display the rule field diffs between the current rule and the target (next version) rule (which is the default behaviour), but not between the base and the target (which is a feature that we want to a add as part of this Milestone). $\space$ $\space$ @@ -2299,8 +2487,6 @@ This means that **no changes will be needed in this page.** 2. Custom Query field overflows the viewport and cannot be completely visualized/edited when the query is too long, i.e. occupies too many lines. This is often the case from Prebuilt Rules. The editable field also does not allow scrolling. See example: ![](2023-12-01-14-13-07.png) - - ### Rule fields - What rule fields will be customizable and for what fields we will disable customization? From a29bea1d32021bf40272dbf784641f049b926599 Mon Sep 17 00:00:00 2001 From: jpdjere Date: Tue, 13 Feb 2024 16:58:36 +0100 Subject: [PATCH 06/61] Refactor: removed code implementation details for update migrations --- .../docs/prebuilt_rules_customization_rfc.md | 586 +----------------- 1 file changed, 27 insertions(+), 559 deletions(-) diff --git a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md index 1e945599de2199..f95cc393ea61f8 100644 --- a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md +++ b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md @@ -514,14 +514,30 @@ The logic for the migration of the rule saved objects, which means the determina Let's see all possible use cases that will require migration-on-write, the endpoints that they apply to, and the expected resulting migrated field, based on the action and their input. -#### Upgrading rules +#### Updating and upgrading rules -Upgrading rules can currently be performed via four endpoints: +Updating rules can currently be performed via five endpoints: - **Update Rule** - `PUT /rules` - **Patch Rule** - `PATCH /rules` - **Bulk Update Rules** - `PUT /rules/_bulk_update` - **Bulk Patch Rules** - `PATCH /rules/_bulk_update` +- **Bulk Actions** - `POST /rules/_bulk_action`: with **bulk edit** action + +Upgrading prebuilt rules to their newer version is done by two endpoints: + +- **(LEGACY) Install Prebuilt Rules And Timelines** - `PUT /rules/prepackaged` +- **Perform Rule Upgrade** - `POST /prebuilt_rules/upgrade/_perform` (Internal) + +The legacy endpoint does not allow for customization of fields during the upgrade, but the new rule upgrade customization endpoint does. + +Additionally: + +- **Bulk Actions** - `POST /rules/_bulk_action`: with **duplicate** action + +will perform migration but does not allow for customization during the duplication proces. + +So we can analyze the expected outputs of the migration of all these 8 endpoints together. The resulting values for `immutable` and `external_source` when calling these endpoints, and the migration being performed in the background, should be as follows: @@ -537,7 +553,7 @@ The resulting values for `immutable` and `external_source` when calling these en - Migrating a custom rule (migrated or not yet) + Migrating a custom rule (migrated or not yet)
undefined
@@ -552,18 +568,18 @@ The resulting values for `immutable` and `external_source` when calling these en - Migrating a non yet migrated prebuilt rule, with customizations + Migrating a non yet migrated prebuilt rule, no customizations
undefined
true
- Yes + No
           {
             external_source: {
               repoName: 'elastic_prebuilt',
-              isCustomized: true,
+              isCustomized: false,
               ...
             },
             immutable: true
@@ -618,7 +634,7 @@ The resulting values for `immutable` and `external_source` when calling these en
       
     
     
-      Migrating a migrated customized prebuilt rule, no customizations
+      Migrating a migrated customized prebuilt rule, with customizations
       
         
 
           {
@@ -629,7 +645,7 @@ The resulting values for `immutable` and `external_source` when calling these en
           
true
- No + Yes
           {
@@ -644,7 +660,7 @@ The resulting values for `immutable` and `external_source` when calling these en
       
     
     
-      Migrating a migrated customized prebuilt rule, with customizations
+      Migrating a migrated customized prebuilt rule, no customizations
       
         
 
           {
@@ -655,13 +671,13 @@ The resulting values for `immutable` and `external_source` when calling these en
           
true
- Yes + No
           {
             external_source: {
               repoName: 'elastic_prebuilt',
-              isCustomized: true,
+              isCustomized: false,
               ...
             },
             immutable: true
@@ -694,7 +710,6 @@ The resulting values for `immutable` and `external_source` when calling these en
           }
         
- @@ -702,553 +717,6 @@ The resulting values for `immutable` and `external_source` when calling these en --- -- `migratePrebuiltSchemaOnRuleCreation` for rule creation -- `migratePrebuiltSchemaOnRuleUpdate` for rule updates (including patching) -- `migratePrebuiltSchemaOnRuleBulkEdit` for bulk rule updates - -These three migrations applied to the handler logic of our endpoints will cover all endpoints and use cases where we want to perform migration-on-write. - -Same as the normalization helper, these three helpers will have a return type of: - -```ts -interface MigrationResponse { - immutable: IsRuleImmutable; - prebuilt?: Prebuilt; -} -``` - -#### `migratePrebuiltSchemaOnRuleCreation` - -This migration method will apply to the following use cases and endpoints: - -- Updating a prebuilt rule when there is a rule type change - - **Perform Rule Upgrade** - `POST /prebuilt_rules/upgrade/_perform` (Internal) - - **(LEGACY) Install Prebuilt Rules And Timelines** - `PUT /rules/prepackaged` -- Importing a rule/prebuilt rule without overwriting an existing rule - - **Import Rules** - `POST /rules/_import` -- Duplicating an existing rule - - **Bulk Actions endpoint** - `POST /rules/_bulk_action` (bulk duplicate action) - -Other non-migration scenarios and endpoints to which this helper will apply to are: - -- Installing a prebuilt rule: - - **Perform Rule Installation** - `POST /prebuilt_rules/install/_perform` (Internal) -- Creating a custom rule: - - **Create Rules** - `POST /rules` -- Bulk creating custom rules: - - **Bulk Create Rules** - `POST /rules/_bulk_create` - -_Source: x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/normalization/prebuilt_rule_schema_migrations.ts_ (New file) - -```ts -interface PrebuiltSchemaCreationMigrationProps { - input: CreateAPIInput; - isRuleToCreatePrebuilt: boolean; -} - -const getPrebuiltValueForRuleCreation = ( - input: CreateAPIInput, - isRuleToCreatePrebuilt: boolean -): Prebuilt | undefined => { - if (!isRuleToCreatePrebuilt) { - return undefined; - } - - if (input.prebuilt != null) { - return input.prebuilt; - } - - return { - isCustomized: false, - elasticUpdateDate: input.elasticUpdateDate, - }; -}; - -export const migratePrebuiltSchemaOnRuleCreation = ({ - input, - isRuleToCreatePrebuilt, -}: PrebuiltSchemaCreationMigrationProps): MigrationResponse => { - const immutable = isRuleToCreatePrebuilt; - const prebuilt = getPrebuiltValueForRuleCreation(input, isRuleToCreatePrebuilt); - - return { - immutable, - prebuilt, - }; -}; -``` - -In the code shown above, the `immutable` field is set to a boolean which equals the value of the passed `isRuleToCreatePrebuilt` boolean argument. The value of that argument will be passed as `true` or `false` depending on the use case: - -- creating a custom rule: `false` -- installing a prebuilt rule: `true` -- updating a prebuilt rule when there is a rule type change: `true` -- importing a rule: can be `true` or `false` depending on the imported rule - -The `prebuilt` field will be set in the following way: (see `getPrebuiltValueForRuleCreation` above) - -- set to `undefined` if the `isRuleToCreatePrebuilt` is parameter is `false`. Use case when: - - creating a custom rule -- if `isRuleToCreatePrebuilt` is passed as `true`: - - set it to `input.prebuilt` if defined. Use case when: - - importing a prebuilt rule - - updating a prebuilt rule with a rule type change - - set it to a new object with `isCustomized` set to `false` and `elasticUpdateDate` to the passed input, if it exists. Use case when: - - installing a prebuilt rule from scratch. In this case, `elasticUpdateDate` will come from the `PrebuiltRuleAsset` (or be undefined in historical version of rules). - -##### `convertCreateAPIToInternalSchema` and `createRules` - -For the first two use cases listed above ("Updating a prebuilt rule when there is a rule type change" and "Importing a rule/prebuilt rule without overwriting an existing rule") the `migratePrebuiltSchemaOnRuleCreation` helper method will be called by the `convertCreateAPIToInternalSchema` rule converter method, which transforms our API schema to the internal rule schema before saving to ES. We need to modify this method in the following way: - -_Source: [x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/normalization/rule_converters.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/normalization/rule_converters.ts)_ - -```ts -// [... file continues above ...] - -export type CreateAPIInput = RuleCreateProps & { - related_integrations?: RelatedIntegrationArray; - required_fields?: RequiredFieldArray; - setup?: SetupGuide; - prebuilt?: Prebuilt; - elasticUpdateDate?: ElasticUpdateDate; -}; - -// eslint-disable-next-line complexity -export const convertCreateAPIToInternalSchema = ( - input: CreateAPIInput, - isRuleToCreatePrebuilt = false -): InternalRuleCreate => { - // [...] - - const { immutable, prebuilt } = migratePrebuiltSchemaOnRuleCreation({ - input, - isRuleToCreatePrebuilt, - }); - - return { - name: input.name, - params: { - // [... other params ...] - immutable, - prebuilt, - // [... other params ...] - ...typeSpecificParams, - }, - actions, - }; -}; - -// [... file continues below ...] -``` - -Notice that the type for the `input` has been expaned to include the `prebuilt` field (which can now be passed in the case of importing rules), and the `elasticUpdateDate` (which is needed when installing a prebuilt rule from scratch). Additionally, the new `isRuleToCreatePrebuilt` parameter is passed to the helper, defaulting to `false`. - -Finally, the `convertCreateAPIToInternalSchema` helper is called by two different use cases: - -1. by the **Preview Rule - POST /detection_engine/rules/preview** endpoint, where no changes are needed. -2. by the `createRules` method, which will be modified in the following way: - -_Source: [x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/crud/create_rules.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/crud/create_rules.ts)_ - -```ts -// [... file continues above ...] - -export interface CreateRulesOptions { - rulesClient: RulesClient; - params: T; - id?: string; - isPrebuilt?: boolean; // renamed from "immutable" - defaultEnabled?: boolean; - allowMissingConnectorSecrets?: boolean; -} - -// New prop types with extended fields for allowing imports -type RuleCreateAndImportProps = RuleCreateProps & { - prebuilt?: Prebuilt; - immutable?: IsRuleImmutable; -}; - -const getIsRuleToCreatePrebuilt = ( - params: RuleCreateAndImportProps, - isPrebuilt?: boolean -): boolean => { - // If createRules is explicitly called with isPrebuilt, use that value. - // Use case when creating a custom rule or installing/updating a prebuilt rule. - if (isPrebuilt != null) { - return isPrebuilt; - } - - // Otherwise, check the passed prebuilt or immutable params for existence. - // Use case when importing a rule. Default to false if neither are passed. - return (Boolean(params.prebuilt) || params.immutable) ?? false; -}; - -export const createRules = async ({ - rulesClient, - params, - id, - isPrebuilt = false, // renamed from "immutable" -}: CreateRulesOptions): Promise> => { - const isRuleToCreatePrebuilt = getIsRuleToCreatePrebuilt(params, isPrebuilt); - const internalRule = convertCreateAPIToInternalSchema( - params, - isRuleToCreatePrebuilt, - defaultEnabled - ); - const rule = await rulesClient.create({ - // [...] - data: internalRule, - // [...] - }); - - return rule; -}; -``` - -Notice in the code above that the new optional `isPrebuilt` parameter, which replaces `immutable`: this can be used when we know with certainity whether the rule we are creating is prebuilt or not. We know this when: - -- creating a custom rule: the `isPrebuilt` argument should be `false` -- creating (installing) or updating a prebuilt rule: the `isPrebuilt` argument should be `true` - -However, when importing rules, we now don't have certaintiy whether the created rule should be prebuilt or not. In order to determine that, we should use the values passed in the `ndjson` file for the `prebuilt` field, or the `immutable` field, as backwards compatibility fallback. - -This logic is encapsulated in the `getIsRuleToCreatePrebuilt` method above. - -Notice, as well, that the `params` types have been extended to a new `RuleCreateAndImportProps` type to take in: - -- the `prebuilt` property, since when importing a prebuilt rule, this will be the value used for: - - for determining if a rule that is being imported is prebuilt or not - - setting the `prebuilt` field when creating the imported prebuilt rule. -- the `immutable` property, to decide whether a rule that is being imported is prebuilt or not (when the rule has not been migrated and has the old schema) - -##### `duplicateRule` - -The other use case for `migratePrebuiltSchemaOnRuleCreation` is when duplicating a rule via the **Bulk Actions endpoint** (`POST /rules/_bulk_action`) with a bulk duplicate action. - -In this case, we will need to modify the `duplicateRule` helper that is used in that endpoint handler and make use of `migratePrebuiltSchemaOnRuleCreation`: - -_Source: [x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/actions/duplicate_rule.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/actions/duplicate_rule.ts)_ - -```ts -// [... file continues above ...] -import { migratePrebuiltSchemaOnRuleCreation } from '../../normalization/prebuilt_rule_schema_migrations'; -import { internalRuleToAPIResponse } from '../../normalization/rule_converters'; - -// [...] - -export const duplicateRule = async ({ rule }: DuplicateRuleParams): Promise => { - // Generate a new static ruleId - const ruleId = uuidv4(); - - const isRuleToCreatePrebuilt = Boolean(rule.params.prebuilt) || rule.params.immutable; - - // [...] - - // Transform rule from internal to API format to pass - // it to the migration function with the correct types. - const ruleResponse = internalRuleToAPIResponse(rule); - const { immutable, prebuilt } = migratePrebuiltSchemaOnRuleCreation({ - input: ruleResponse, - isRuleToCreatePrebuilt, - }); - - return { - name: `${rule.name} [${DUPLICATE_TITLE}]`, - // [...] - params: { - ...rule.params, - immutable, - prebuilt, - // [...] - }, - // [...] - }; -}; -``` - -Notice in the code above, the `rule` object passed into the `duplicateRule` function is in the internal rule schema format, so we need to use `internalRuleToAPIResponse` to convert it and pass it intoo `migratePrebuiltSchemaOnRuleCreation` in the expected format, in order calculate the values of `immutable` and `prebuilt`. - -#### `migratePrebuiltSchemaOnRuleUpdate` - -This migration method will apply to the following use cases and endpoints: - -- **Rule Update**: - - Updating a rule via the rule editing page (or directly via API) - - **Update Rule** - `PUT /rules` - - Bulk updating rules via API - - **Bulk Update Rules** - `PUT /rules/_bulk_update` -- **Rule Patch**: - - Updating a prebuilt rule when there's NO rule type change: - - **Perform Rule Upgrade** - `POST /prebuilt_rules/upgrade/_perform` (Internal) - - **(LEGACY) Install Prebuilt Rules And Timelines** - `PUT /rules/prepackaged` - - Importing a rule/prebuilt rule overwriting an existing rule: - - **Import Rules** - `POST /rules/_import` - -Other non-migration scenarios and endpoints to which this helper will apply to are: - -- Managing shared exception lists - - **Patch Rule** - `PATCH /rules` -- Bulk patching rules (only via API) - - **Bulk Patch Rules** - `PATCH /rules/_bulk_update` (deprecated) -- Creating rule exceptions - - **Create Rule Exceptions** - `POST /rules/{id}/exceptions` - -_Source: x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/normalization/prebuilt_rule_schema_migrations.ts_ (New file) - -```ts -interface PrebuiltSchemaUpdateMigrationProps { - nextParams?: PatchAPINextParams; - existingParams: RuleParams; - isRuleCustomizedDuringUpdate: boolean; -} - -const getPrebuiltValueForRuleUpdate = ({ - nextParams, - existingParams, - isRuleCustomizedDuringUpdate, -}: PrebuiltSchemaUpdateMigrationProps): Prebuilt | undefined => { - if (nextParams?.prebuilt) { - return nextParams?.prebuilt; - } - - if (existingParams.prebuilt) { - return { - ...existingParams.prebuilt, - isCustomized: existingParams.prebuilt.isCustomized || isRuleCustomizedDuringUpdate, - }; - } - - if (existingParams.immutable) { - return { - isCustomized: isRuleCustomizedDuringUpdate, - }; - } - - return undefined; -}; - -export const migratePrebuiltSchemaOnRuleUpdate = ({ - nextParams, - existingParams, - isRuleCustomizedDuringUpdate, -}: PrebuiltSchemaUpdateMigrationProps): MigrationResponse => { - const immutable = (Boolean(existingParams.prebuilt) || existingParams.immutable) ?? false; - const prebuilt = getPrebuiltValueForRuleUpdate({ - nextParams, - existingParams, - isRuleCustomizedDuringUpdate, - }); - - return { - immutable, - prebuilt, - }; -}; -``` - -Notice that the `nextParams` argument of the `migratePrebuiltSchemaOnRuleUpdate` is optional: this is because this method can be used for both **patching** rules, where `nextParams` contains data that is needed for the calculation of the `prebuilt` and `immutable` fields, but also for the **updating** rules use case, when only the `existingParams` are necessary to calculate those fields. - -The logic for defining the `immutable` and `prebuilt` fields, implemented in the code above, is as follows: - -- for `immutable`: - - - if the `prebuilt` field exists in the existing rule, `immutable` should be `true`. - - Use case 1: updating an already migrated custom or prebuilt rule - - Use case 2: importing (and overwriting) a rule that has a `prebuilt` field in the `ndjson` file payload - - otherwise, rely on the value of the existing rule's `immutable` field. Use case: - - Use case 3: updating a custom or prebuilt rule that hasn't yet been migrated - - Use case 4: importing (and overwriting) a rule that has a `immutable` field but no `prebuilt` field in the `ndjson` file payload - - if both are undefined, default to `false`: - - Use case 5: importing (and overwriting) a rule that has no `prebuilt` or `immutable` fields in the `ndjson` file payload. - - Notice that for calculating `immutable` we don't rely on `nextParams` because a rule should never change from custom to prebuilt, or viceversa. - -- for `prebuilt` - see `getPrebuiltValueForRuleUpdate` method above: - - - take the `prebuilt` field as passed in the `nextParams`, if the object exists: - - - Use case 1: importing (and overwriting) a rule that has a `prebuilt` field in the `ndjson` file payload - - Use case 2: updating a prebuilt rule with no rule type change (TODO: the prebuilt object has to be built in the `upgradePrebuiltRules` and passed in the next params. Create a function that build it and show changes in this RFC) - - - If that is undefined, take the value from `prebuilt` from the `existingParams`, but with an updated value for `isCustomized`. This value should be true if the existing rule has already that prop as true, or if the rule was customized during the patch procedure (`isRuleCustomizedDuringUpdate` value passed as argument to `migratePrebuiltSchemaOnRuleUpdate`): - - Use case 3: patching already-migrated rules via API (`prebuilt` already exists in schema) - - If both `nextParams.prebuilt` and `existingParams.prebuilt` are undefined: check the value for the `immutable` field of the existing rule: - - if `immutable: true`: create a new `prebuilt` object where `isCustomized` has the value of `isRuleCustomizedDuringUpdate` and `elasticUpdateDate` is undefined: - - Use case 4: patching a non-migrated prebuilt rule via API - - if `immutable: false`, `prebuilt` should be undefined. - - Use case 5: patching a non-migrated custom rule via API - -This helper method will be called by two diffent functions: - -1. the `convertPatchAPIToInternalSchema` rule converter method, used in the use cases listed as **Rule Patch** at the beggining of this section -2. the `updateRules` method, used in the use cases listed as **Rule Update** at the beggining of this section - -```mermaid -graph TD; - -subgraph Call Stack - updateRules -->|calls| migratePrebuiltSchemaOnRuleUpgrade - patchRules -->|calls| convertPatchAPIToInternalSchema - convertPatchAPIToInternalSchema -->|calls| migratePrebuiltSchemaOnRuleUpgrade - migratePrebuiltSchemaOnRuleUpgrade -end -``` - -##### `convertPatchAPIToInternalSchema` and `patchRules` - -We need to modify the `convertPatchAPIToInternalSchema` in the following way: - -_Source: [x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/normalization/rule_converters.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/normalization/rule_converters.ts)_ - -```ts -// [... file continues above ...] -export type PatchAPINextParams = PatchRuleRequestBody & { - related_integrations?: RelatedIntegrationArray; - required_fields?: RequiredFieldArray; - setup?: SetupGuide; - prebuilt?: Prebuilt; -}; - -export const convertPatchAPIToInternalSchema = ( - nextParams: PatchAPINextParams, - existingRule: SanitizedRule, - isRuleCustomizedDuringUpdate = false -): InternalRuleUpdate => { - const typeSpecificParams = patchTypeSpecificSnakeToCamel(nextParams, existingRule.params); - const existingParams = existingRule.params; - - // [...] - - const { immutable, prebuilt } = migratePrebuiltSchemaOnRuleUpdate({ - nextParams, - existingParams, - isRuleCustomizedDuringUpdate, - }); - - return { - name: nextParams.name ?? existingRule.name, - tags: nextParams.tags ?? existingRule.tags, - params: { - // [...] - immutable, - prebuilt, - // [...] - ...typeSpecificParams, - }, - // [...] - }; -}; -// [... file continues above ...] -``` - -Notice that the type for the `nextParams` has been expaned to include the `prebuilt` field (which can now be passed in the case of importing rules). Additionally, the new `isRuleToCreatePrebuilt` parameter is passed to the helper, defaulting to `false`. - -The `convertPatchAPIToInternalSchema` helper is called only by the `patchRules` method, which will be modified in the following way: - -_Source:[x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/crud/patch_rules.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/crud/patch_rules.ts)_ - -```ts -// [... file continues above ...] - -import { convertPatchAPIToInternalSchema } from '../../normalization/rule_converters'; - -export interface PatchRulesOptions { - rulesClient: RulesClient; - nextParams: PatchRuleRequestBody & { - related_integrations?: RelatedIntegrationArray; - required_fields?: RequiredFieldArray; - setup?: SetupGuide; - prebuilt?: Prebuilt; // extend nextParams with `prebuilt` property - }; - existingRule: RuleAlertType | null | undefined; - isRuleCustomizedDuringUpdate?: boolean; // pass in new optional boolean -} - -export const patchRules = async ({ - rulesClient, - existingRule, - nextParams, - isRuleCustomizedDuringUpdate, -}: // [...] -PatchRulesOptions): Promise | null> => { - // [...] - - const patchedRule = convertPatchAPIToInternalSchema( - nextParams, - existingRule, - isRuleCustomizedDuringUpdate - ); - - const update = await rulesClient.update({ - id: existingRule.id, - data: patchedRule, - // [...] - }); - - // [...] -}; -``` - -As seen in the snippet above, the type of the arguments of `patchRule` method, `PatchRulesOptions` will need to be updated as well, in order to allow passing the new `prebuilt` field in its `nextParams` property, as well as the `isRuleCustomizedDuringUpdate` boolean. - -The method `patchRule` is used in all use cases mentioned at the beggining of this section, so we have covered all of them with the correspondent migration. - -##### `updateRules` - -The `updateRules` method is used only in the Update and Bulk Update endpoints. It needs to be updated to make use of `migratePrebuiltSchemaOnRuleUpdate`: - -_Source: [x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/crud/update_rules.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/crud/update_rules.ts)_ - -```ts -// [... file continues above...] -import { migratePrebuiltSchemaOnRuleUpdate } from '../../normalization/prebuilt_rule_schema_migrations'; - -export interface UpdateRulesOptions { - rulesClient: RulesClient; - existingRule: RuleAlertType | null | undefined; - ruleUpdate: RuleUpdateProps; -} - -export const updateRules = async ({ - rulesClient, - existingRule, - ruleUpdate, -}: UpdateRulesOptions): Promise | null> => { - // [...] - - // Calculate whether the rule was customized during the update - // TODO: Explain how this is calculated in all cases where it needs to be, in its own section - const isRuleCustomizedDuringUpdate = getIsRuleCustomizedDuringUpdate(existingRule, ruleUpdate); - - // Calculate the values of immutable and prebuilt based on the existing params - // and the isRuleCustomizedDuringUpdate boolean - const { immutable, prebuilt } = migratePrebuiltSchemaOnRuleUpdate({ - existingParams: existingRule.params, - isRuleCustomizedDuringUpdate, - }); - - const newInternalRule: InternalRuleUpdate = { - name: ruleUpdate.name, - // [...] - params: { - // [...] - immutable, - prebuilt, - // [...] - ...typeSpecificParams, - }, - // [...] - }; - - const update = await rulesClient.update({ - id: existingRule.id, - data: newInternalRule, - }); - - // [...] - return { ...update, enabled }; -}; -``` - #### `migratePrebuiltSchemaOnRuleBulkEdit` This migration method will apply to the following use case and endpoints: From 5c727392f4c90457593cf1c4207215a63f34f51d Mon Sep 17 00:00:00 2001 From: jpdjere Date: Tue, 13 Feb 2024 17:59:40 +0100 Subject: [PATCH 07/61] Refactor: Added Bulk editing rules section --- .../docs/prebuilt_rules_customization_rfc.md | 109 +++--------------- 1 file changed, 17 insertions(+), 92 deletions(-) diff --git a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md index f95cc393ea61f8..437633327ac716 100644 --- a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md +++ b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md @@ -717,110 +717,35 @@ The resulting values for `immutable` and `external_source` when calling these en --- -#### `migratePrebuiltSchemaOnRuleBulkEdit` +#### Bulk editing rules -This migration method will apply to the following use case and endpoints: +The endpoint **Bulk Actions** - `POST /rules/_bulk_action` has the same outputs from the migration logic as the endpoints listed in the above section, so it was included in the scenarios in the table above. -- Bulk updating rules: +However, this endpoint has some specific details that should be mentioned. + +Firstly, when bulk editing rules, the migration should apply for the following use cases: - Bulk adding or deleting index patterns - Bulk adding or deleting tags - Updating rule schedules - - Adding rules actions // _(TODO: Should this define prebuilt.isCustomized? The current rulesClient implementation counts it as a rule modification, but it looks like we shouldn't. Separating this from other types of modification will need some further work on the rulesClient side.)_ - - **Bulk Actions endpoint** - `POST /rules/_bulk_action` (bulk edit action) - -In contrast with the other migration methods, we will use the new `migratePrebuiltSchemaOnRuleBulkEdit` within the Alerting Framework's `RuleClient` since we need to migrate the rule's `prebuilt` and `immutable` parameters before the `RuleClient` does the saving of the rule into Elasticsearch. - -This however, gives us the advantage that the `RuleClient` already includes logic to calculate if a rule's attributes or parameters have been modified from its initial values, so we can rely on that to calculate the `prebuilt.isCustomized` field during the update. - -_Source: x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/normalization/prebuilt_rule_schema_migrations.ts_ (New file) - -```ts -import { RuleParams } from '../../../types'; + - Adding rules actions + - Duplicating a rule (migration applied only to the new rule) -const getPrebuiltValueForRuleBulkEdit = ( - ruleParams: RuleParams, - isRuleUpdatedDuringBulkUpdate: boolean -) => { - if (ruleParams?.prebuilt) { - return { - ...ruleParams.prebuilt, - isCustomized: ruleParams.prebuilt.isCustomized || isRuleUpdatedDuringBulkUpdate, - }; - } - - if (ruleParams.immutable) { - return { - isCustomized: isRuleUpdatedDuringBulkUpdate, - }; - } +Out of the actions mentioned above, the only use cases that should possibily result in the migration having a result of `external_source.isCustomized = true` are the first three: + - Bulk adding or deleting index patterns + - Bulk adding or deleting tags + - Updating rule schedules - return undefined; -}; +That is, updating a rule's actions or duplicating a rule should not be considered a customization of a prebuilt rule. -export const migratePrebuiltSchemaOnRuleBulkEdit = ( - ruleParams: RuleParams, - isRuleUpdatedDuringBulkUpdate: boolean -) => { - const immutable = Boolean(ruleParams.prebuilt) || ruleParams.immutable; - const prebuilt = getPrebuiltValueForRuleBulkEdit(ruleParams, isRuleUpdatedDuringBulkUpdate); +Secondly, in contrast with other endpoints, the migration for bulk editing rules needs to be carried within the Alerting Framework's `RuleClient` since we need to migrate the rule's `external_source` and `immutable` parameters before the `RuleClient` does the saving of the rule into Elasticsearch. - ruleParams.prebuilt = prebuilt; - ruleParams.immutable = immutable; -}; -``` +This however, gives us the advantage that the `RuleClient` already includes logic to calculate if a rule's attributes or parameters have been modified from its initial values, so we can rely on that to calculate the `external_source.isCustomized` field during the update. Notice that here we are migrating the `ruleParams` in-place; the object is later used to save the updated rules into Elasticsearch. -The `RulesClient` class has a `bulkEdit` method, which is called by our **Bulk Actions endpoint** `POST /rules/_bulk_action`. That method includes complex logic, but we can focus on the `updateRuleAttributesAndParamsInMemory` method, where the rule attributes and parameters are updated before being saved to ES. This function also calculates the booleans `isAttributesUpdateSkipped` and `isParamsUpdateSkipped` which we can leverage to set the `prebuilt.isCustomized` field in our params. - -_Source: [x-pack/plugins/alerting/server/application/rule/methods/bulk_edit/bulk_edit_rules.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/alerting/server/application/rule/methods/bulk_edit/bulk_edit_rules.ts)_ +The `RulesClient` class has a `bulkEdit` method, which is called by our **Bulk Actions endpoint** `POST /rules/_bulk_action`. That method includes complex logic, but we can focus on the `updateRuleAttributesAndParamsInMemory` method, where the rule attributes and parameters are updated before being saved to ES. This function also calculates the booleans `isAttributesUpdateSkipped` and `isParamsUpdateSkipped` which we can leverage to calculate the new value of the `external_source.isCustomized` field in our params. -```ts -export async function bulkEditRules() { - // calls bulkEditRulesOcc() -} - -function bulkEditRulesOcc() { - // calls updateRuleAttributesAndParamsInMemory() -} -async function updateRuleAttributesAndParamsInMemory( - { - // [...] - } -): Promise { - try { - // [...] - - const { - rule: updatedRule, - // [...] - isAttributesUpdateSkipped, - } = await getUpdatedAttributesFromOperations({ - // [...] - }); - - // [...] - - const { modifiedParams: ruleParams, isParamsUpdateSkipped } = paramsModifier - ? await paramsModifier(updatedRule.params) - : { - modifiedParams: updatedRule.params, - isParamsUpdateSkipped: true, - }; - - // [...] - - const isRuleUpdated = !(isAttributesUpdateSkipped && isParamsUpdateSkipped); - - // Migrate `ruleParams.prebuilt` and `ruleParams.immutable` in-place - migratePrebuiltSchemaOnRuleBulkEdit(ruleParams, isRuleUpdated); - - // [...] - } catch (error) { - // [...] - } -} -``` +_See Source: [x-pack/plugins/alerting/server/application/rule/methods/bulk_edit/bulk_edit_rules.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/alerting/server/application/rule/methods/bulk_edit/bulk_edit_rules.ts)_ --- @@ -832,7 +757,7 @@ async function updateRuleAttributesAndParamsInMemory( Across our application, both in the frontend and serverside, we use KQL filters to retrieve rules based on whether they are prebuilt rules or not - this means that the current behaviour of these values relies on the `immutable` field being set to either `true` or `false`. -As we have mentioned before, we need to assume that at any point in time, there will be a mixture of rules whose saved object has already been migrated on Elasticsearch and others will not. This means that the retrieval of rules will need to maintain backwards compatibility: in order to determine if a rule is prebuilt, preferentially search for the existence of the `prebuilt` field; if that doesn't exist, fallback to the legacy logic of checking a rule's `immutable` value. +As we have mentioned before, we need to assume that at any point in time, there will be a mixture of rules whose saved object has already been migrated on Elasticsearch and others will not. This means that the retrieval of rules will need to maintain backwards compatibility: in order to determine if a rule is prebuilt, preferentially search for the existence of the `external_source` field; if that doesn't exist, we should fall back to the legacy logic of checking a rule's `immutable` value. This means that we will need to update the constants and KQL filters that we have hardcoded in our application to reflect the new schema: From 499dc4c5f3175d75a78ae5af27806dd571c6b9c6 Mon Sep 17 00:00:00 2001 From: jpdjere Date: Tue, 13 Feb 2024 18:13:56 +0100 Subject: [PATCH 08/61] Refactor: KQL filters and the method section --- .../docs/prebuilt_rules_customization_rfc.md | 60 +++---------------- 1 file changed, 8 insertions(+), 52 deletions(-) diff --git a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md index 437633327ac716..8c21bfc971bc5c 100644 --- a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md +++ b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md @@ -757,67 +757,23 @@ _See Source: [x-pack/plugins/alerting/server/application/rule/methods/bulk_edit/ Across our application, both in the frontend and serverside, we use KQL filters to retrieve rules based on whether they are prebuilt rules or not - this means that the current behaviour of these values relies on the `immutable` field being set to either `true` or `false`. -As we have mentioned before, we need to assume that at any point in time, there will be a mixture of rules whose saved object has already been migrated on Elasticsearch and others will not. This means that the retrieval of rules will need to maintain backwards compatibility: in order to determine if a rule is prebuilt, preferentially search for the existence of the `external_source` field; if that doesn't exist, we should fall back to the legacy logic of checking a rule's `immutable` value. +As mentioned before, we need to assume that at any point in time, there will be a mixture of rules whose saved object has already been migrated on Elasticsearch and others will not. This means that the retrieval of rules will need to maintain backwards compatibility: in order to determine if a rule is prebuilt, preferentially search for the existence of the `external_source` field; if that doesn't exist, we should fall back to the legacy logic of checking a rule's `immutable` value. This means that we will need to update the constants and KQL filters that we have hardcoded in our application to reflect the new schema: -_Source: [x-pack/plugins/security_solution/common/detection_engine/rule_management/rule_fields.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/common/detection_engine/rule_management/rule_fields.ts)_ +_See source of rule params keys: [x-pack/plugins/security_solution/common/detection_engine/rule_management/rule_fields.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/common/detection_engine/rule_management/rule_fields.ts)_ -```ts -// [... file continues above...] - -export const PARAMS_IMMUTABLE_FIELD = 'alert.attributes.params.immutable'; -export const PARAMS_PREBUILT_FIELD = 'alert.attributes.params.prebuilt'; // new constant -export const PARAMS_PREBUILT_IS_CUSTOMIZED_FIELD = 'alert.attributes.params.prebuilt.isCustomized'; // new constant -``` - -And we will need to update the `x-pack/plugins/security_solution/common/detection_engine/rule_management/rule_filtering.ts` file, where the `convertRulesFilterToKQL` method is defined. This method is used both in the frontend and in the serverside, and translates rule filter options to KQL filters that Elasticsearch can understand. - -Here, we need to update the KQL filters and the logic for fetching Elastic prebuilt and custom rules, relying on `prebuilt` but with fallback to `immutable`: - -_Source: [x-pack/plugins/security_solution/common/detection_engine/rule_management/rule_filtering.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/common/detection_engine/rule_management/rule_filtering.ts)_ +Will need to update the `x-pack/plugins/security_solution/common/detection_engine/rule_management/rule_filtering.ts` file, where the `convertRulesFilterToKQL` method is defined. This method is used both in the frontend and in the serverside, and translates rule filter options to KQL filters that Elasticsearch can understand. -```ts -// [... file continues above...] +Here, we need to update the KQL filters and the logic for fetching Elastic prebuilt and custom rules, relying on `external_rules` but with fallback to `immutable`: -// KQL does not allow to search for existence of the prebuilt object field by itself, since params is unmapped -// so we need to search for the existence of the isCustomized subfield instead, which is required -export const KQL_FILTER_PREBUILT_RULES = `${PARAMS_PREBUILT_IS_CUSTOMIZED_FIELD}: *`; -export const KQL_FILTER_CUSTOM_RULES = `NOT ${PARAMS_PREBUILT_IS_CUSTOMIZED_FIELD}: *`; -export const KQL_FILTER_IMMUTABLE_RULES = `${PARAMS_IMMUTABLE_FIELD}: true`; -export const KQL_FILTER_MUTABLE_RULES = `${PARAMS_IMMUTABLE_FIELD}: false`; - -interface RulesFilterOptions { - filter: string; - showCustomRules: boolean; - showElasticRules: boolean; - ... -} +_Source for `convertRulesFilterToKQL`: [x-pack/plugins/security_solution/common/detection_engine/rule_management/rule_filtering.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/common/detection_engine/rule_management/rule_filtering.ts)_ -export function convertRulesFilterToKQL({ - filter: searchTerm, - showCustomRules, - showElasticRules, - ... -}: Partial): string { - const kql: string[] = []; - - // [... file continues ...] - - if (showCustomRules && showElasticRules) { - // if both showCustomRules && showElasticRules selected we omit filter, as it includes all existing rules - } else if (showElasticRules) { - kql.push(`(${KQL_FILTER_PREBUILT_RULES} OR ${KQL_FILTER_IMMUTABLE_RULES})`); - } else if (showCustomRules) { - kql.push(`(${KQL_FILTER_CUSTOM_RULES} OR ${KQL_FILTER_MUTABLE_RULES})`); - } - - // [... file continues below...] -``` +In order to retrieve rules in which the `alert.attributes.params.external_source` field exists, we must rely instead on the existence of `alert.attributes.params.external_source.repo_name`. This is so because KQL syntax does not allow searching for the existence of an object like `external_source` with the recommended syntax `alert.attributes.params.external_source: *`. -Ntocie that in order to retrieve rules in which the `alert.attributes.params.prebuilt` field exists, we must rely instead on the existence of `alert.attributes.params.prebuilt.isCustomized`. This is so because the `prebuilt` field lives inside the unmapped `params` field, and KQL syntax does not allow searching for the existence of an object like `prebuilt` with the recommended syntax `alert.attributes.params.prebuilt: *`. +But we can use the `external_source` field's `repo_name` subfield instead, which will always exist within the object (it is required) and replace the KQL filter for `alert.attributes.params.external_source.repo_name: *`. -But we can use the `prebuilt` field's `isCustomized` subfield instead, which will always exist within the object (it is required) and replace the KQL filter for `alert.attributes.params.prebuilt.isCustomized: *`. +This will allow us to retrieve all rules that originate from an external source, or conditionally, from a specific source. For example, using the filter `alert.attributes.params.external_source.repo_name: elastic_prebuilt` should return only prebuilt rules created by Elastic. ### Rule Management endpoints From 2265ba1da8aae362e74ff4b896b6ee6162cf3362 Mon Sep 17 00:00:00 2001 From: jpdjere Date: Wed, 14 Feb 2024 11:51:59 +0100 Subject: [PATCH 09/61] Refactor: Clean up endpoint modifications --- .../docs/prebuilt_rules_customization_rfc.md | 256 +----------------- 1 file changed, 13 insertions(+), 243 deletions(-) diff --git a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md index 8c21bfc971bc5c..3c380673830b79 100644 --- a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md +++ b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md @@ -779,285 +779,55 @@ This will allow us to retrieve all rules that originate from an external source, - **Create Rules** - `POST /rules` and **Bulk Create Rules** - `POST /rules/_bulk_create`: -Currently, we don't support the `immutable` field in any of the endpoints' request parameters (except for the Import endpoint). We shouldn't support the `prebuilt` field either, because this value should be controlled by the app on the server side, and not by users. +Currently, we don't support the `immutable` field in any of the endpoints' request parameters (except for the Import endpoint). We shouldn't support the `external_source` field either, because this value should be controlled by the app on the server side, and not by users. This is so because we will never want users to be able to create their own prebuilt rules, only install them, import them, and customize them. Also, a prebuilt rule should always be able to be compared to a `security-rule` asset distributed by Fleet, and receive updates from it, which would not be possible if a user creates its own prebuilt rules. -Specifically, these two endpoints should be able to create only custom rules which means their `params` will look like: - -```ts -// [PSEUDOCODE] -{ - immutable: false, - // prebuilt should not be in the created rule object, - // since this endpoint should only create custom rules -} -``` - -Both endpoints used the already discussed `createRules` method to create rules. The only changes needed for both are explicitly passing the new `isPrebuilt` argument as `false`: - -_Source: [x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/create_rule/route.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/create_rule/route.ts)_ - -```ts -// [... file continues above ...] - -export const createRuleRoute = ( - router: SecuritySolutionPluginRouter, - ml: SetupPlugins['ml'] -): void => { - router.versioned - .post({ - access: 'public', - path: DETECTION_ENGINE_RULES_URL, - // [...] - }) - .addVersion( - { - // [...] - }, - async (context, request, response): Promise> => { - // [...] - try { - // [...] - - const createdRule = await createRules({ - rulesClient, - params: request.body, - isPrebuilt: false, // <-------- explicitly pass isPrebuilt: false - }); - - -// [... file continues below ...] -``` - -_Source: [x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_create_rules/route.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_create_rules/route.ts)_ - -```ts -export const bulkCreateRulesRoute = ( - router: SecuritySolutionPluginRouter, - // [...] -) => { - router.versioned - .post({ - access: 'public', - path: DETECTION_ENGINE_RULES_BULK_CREATE, - // [...] - }) - .addVersion( - { - // [...] - }, - async (context, request, response): Promise> => { - // [...] - const createdRule = await createRules({ - rulesClient, - params: payloadRule, - isPrebuilt: false, // <-------- explicitly pass isPrebuilt: false - }); -``` - - **Rule Management Filters** - `GET /rules/_rule_management_filters` (Internal): -This endpoint currently depends on rules `alert.attributes.params.immutable` to fetch number of custom rules and number of prebuilt rules. We need to adapt its logic to rely on new `alert.attributes.params.prebuilt` field, with fallback to the original, for backwards compatibility. +This endpoint currently depends on rules `alert.attributes.params.immutable` to fetch number of custom rules and number of prebuilt rules. We need to adapt its logic to rely on new `alert.attributes.params.external_source` field, with fallback to the original, for backwards compatibility. Specifically, the endpoint handler uses the [`findRules` utility](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/search/find_rules.ts) to fetch rules based on their `immutable` param. -This needs to be changed so that we rely on the `prebuilt` param, but fallback to `immutable` if that parameter doesn't exist - i.e., in the case of non-migrated-on-write rules. We need to modify the KQL queries in a similar way to the already described: +This needs to be changed so that we rely on the `external_source` param, but fallback to `immutable` if that parameter doesn't exist - i.e., in the case of non-migrated-on-write rules. We need to modify the KQL queries in a similar way to the already described in the section `KQL filters and the convertRulesFilterToKQL`. -_Source: [x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/filters/route.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/filters/route.ts)_ +We need to modify the `x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/filters/route.ts` file; specifically the `fetchRulesCount` function, which contains the KQL query filters that should be updated. -```ts -// [... file continues above ...] - -async function fetchRulesCount(rulesClient: RulesClient): Promise { - const [prebuiltRules, customRules] = await Promise.all([ - findRules({ - ...DEFAULT_FIND_RULES_COUNT_PARAMS, - rulesClient, - filter: `${KQL_FILTER_PREBUILT_RULES} OR ${KQL_FILTER_IMMUTABLE_RULES}`, - }), - findRules({ - ...DEFAULT_FIND_RULES_COUNT_PARAMS, - rulesClient, - filter: `${KQL_FILTER_CUSTOM_RULES} OR ${KQL_FILTER_MUTABLE_RULES}`, - }), - ]); - - return { - prebuilt: prebuiltRules.total, - custom: customRules.total, - }; -} -// [... file continues below ...] -``` - -The constants `KQL_FILTER_PREBUILT_RULES`, `KQL_FILTER_IMMUTABLE_RULES`,`KQL_FILTER_CUSTOM_RULES` and `KQL_FILTER_MUTABLE_RULES` are imported from `x-pack/plugins/security_solution/common/detection_engine/rule_management/rule_filtering.ts`. +_See Source: [x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/filters/route.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/filters/route.ts)_ - **Coverage Overview** - `/rules_coverage_overview` (Internal): This endpoint is called to retrieve the data that populates the MITRE Coverage Overview table, and currently depends on the `immutable` field to fetch the user's installed rules. -Similarly to what was described in the previous endpoint, we should update the logic so that we rely on the `prebuilt` param, but fallback to `immutable` if that parameter doesn't exist - i.e., in the case of non-migrated-on-write rules. +Similarly to what was described in the previous endpoint, we should update the logic so that we rely on the `external_source` param, but fallback to `immutable` if that parameter doesn't exist - i.e., in the case of non-migrated-on-write rules. This endpoint handler also uses the [`findRules` utility](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/search/find_rules.ts) to fetch rules, but the KQL filter that is passed to that utility is created by the reusable [`convertRulesFilterToKQL` utility function](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/common/detection_engine/rule_management/rule_filtering.ts): -_Source: [x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/coverage_overview/handle_coverage_overview_request.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/coverage_overview/handle_coverage_overview_request.ts)_ +_See Source: [x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/coverage_overview/handle_coverage_overview_request.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/coverage_overview/handle_coverage_overview_request.ts)_ -```ts -// [... file continues above...] - -export async function handleCoverageOverviewRequest({ - params: { filter }, - deps: { rulesClient }, -}: HandleCoverageOverviewRequestArgs): Promise { - const activitySet = new Set(filter?.activity); - const kqlFilter = convertRulesFilterToKQL({ - filter: filter?.search_term, - showCustomRules: filter?.source?.includes(CoverageOverviewRuleSource.Custom) ?? false, - showElasticRules: filter?.source?.includes(CoverageOverviewRuleSource.Prebuilt) ?? false, - enabled: getIsEnabledFilter(activitySet), - }); - - const rules = await findRules({ - rulesClient, - filter: kqlFilter, - fields: ['name', 'enabled', 'params.threat'], - page: 1, - perPage: 10000, - sortField: undefined, - sortOrder: undefined, - }); - - // [... file continues below...] -``` - -We therefore need to modify the `convertRulesFilterToKQL` utility logic as was described in the section above: [KQL filters and the `convertRulesFilterToKQL` method](#kql-filters-and-the-convertrulesfiltertokql-method) +Therefor, it is enough to modify the `convertRulesFilterToKQL` utility logic as was described in the section above: [KQL filters and the `convertRulesFilterToKQL` method](#kql-filters-and-the-convertrulesfiltertokql-method) ### Prebuilt Rules endpoints - [**(LEGACY) Get Prebuilt Rules and Timeline Status** - `/rules/prepackaged/_status`](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/get_prebuilt_rules_and_timelines_status/get_prebuilt_rules_and_timelines_status_route.ts) -This currently depends on rules `alert.attributes.params.immutable` to fetch the number of custom rules and number of prebuilt rules. We need to adapt this filters to rely on new `alert.attributes.params.prebuilt` field, with fallback to the original, for backwards compatibility: - -_Source: [x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/get_prebuilt_rules_and_timelines_status/get_prebuilt_rules_and_timelines_status_route.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/get_prebuilt_rules_and_timelines_status/get_prebuilt_rules_and_timelines_status_route.ts)_ +This currently depends on rules `alert.attributes.params.immutable` to fetch the number of custom rules and number of prebuilt rules. We need to adapt these filters used in the `findRules` method used in the endpoint handler to rely on new `alert.attributes.params.external_source` field, with fallback to the original, for backwards compatibility: -```ts -// [... file continues above...] +_See Source: [x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/get_prebuilt_rules_and_timelines_status/get_prebuilt_rules_and_timelines_status_route.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/get_prebuilt_rules_and_timelines_status/get_prebuilt_rules_and_timelines_status_route.ts)_ -export const getPrebuiltRulesAndTimelinesStatusRoute = ( - router: SecuritySolutionPluginRouter, - security: SetupPlugins['security'] -) => { - router.versioned - .get({ - access: 'public', - path: PREBUILT_RULES_STATUS_URL, - // [...] - }) - .addVersion( - { - version: '2023-10-31', - validate: false, - }, - async (context, request, response) => { +As explained above, this endpoint fetches the installed prebuilt rules, as well, using the `getExistingPrepackagedRules` reusable utility. This function needs to be modified as well to update its KQL query filters: - // [...] - - const customRules = await findRules({ - rulesClient, - perPage: 1, - page: 1, - sortField: 'enabled', - sortOrder: 'desc', - filter: `${KQL_FILTER_PREBUILT_RULES} OR ${KQL_FILTER_IMMUTABLE_RULES}`, - fields: undefined, - }); - - const installedPrebuiltRules = rulesToMap( - await getExistingPrepackagedRules({ rulesClient }) // needs modifying as well - ); - -// [... file continues below...] -``` - -As explained above, this endpoint fetches the installed prebuilt rules, as well, using the `getExistingPrepackagedRules` reusable utility. This function needs to be modified as well: - -_Source: [x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/search/get_existing_prepackaged_rules.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/search/get_existing_prepackaged_rules.ts)_ - -```ts -[... file continues above...] - -export const getExistingPrepackagedRules = async ({ - rulesClient, -}: { - rulesClient: RulesClient; -}): Promise => { - return getRules({ - rulesClient, - filter: `${KQL_FILTER_PREBUILT_RULES} OR ${KQL_FILTER_IMMUTABLE_RULES}`, - }); -}; -``` +_See source for `getExistingPrepackagedRules`: [x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/search/get_existing_prepackaged_rules.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/search/get_existing_prepackaged_rules.ts)_ -- [**Get Prebuilt Rules Status** - `GET /prebuilt_rules/status` (Internal)](https://github.com/elastic/kibana/blob/test-serverless-env-test-deployment/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/get_prebuilt_rules_status/get_prebuilt_rules_status_route.ts) +- [**Get Prebuilt Rules Status** - `GET /prebuilt_rules/status` (Internal)](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/get_prebuilt_rules_status/get_prebuilt_rules_status_route.ts) Uses `IPrebuiltRuleObjectsClient` to retrieve instances of prebuilt rules according to the `immutable` field. The Prebuilt Rule Objects client fetches prebuilt rules using the `getExistingPrepackagedRules` function mentioned above, so modifying it as described above will suffice: _Source: [x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/rule_objects/prebuilt_rule_objects_client.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/rule_objects/prebuilt_rule_objects_client.ts)_ -```ts -// [... file continues above...] - -export const createPrebuiltRuleObjectsClient = ( - rulesClient: RulesClient -): IPrebuiltRuleObjectsClient => { - return { - fetchAllInstalledRules: (): Promise => { - return withSecuritySpan('IPrebuiltRuleObjectsClient.fetchInstalledRules', async () => { - const rulesData = await getExistingPrepackagedRules({ rulesClient }); - const rules = rulesData.map((rule) => internalRuleToAPIResponse(rule)); - return rules; - }); - }, - -// [... file continues below...] -``` - - [**(LEGACY) Install Prebuilt Rules And Timelines** - `PUT /rules/prepackaged`](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/install_prebuilt_rules_and_timelines/install_prebuilt_rules_and_timelines_route.ts) This endpoint fetches the installed prebuilt rules using the `getExistingPrepackagedRules` reusable utility, as well: _Source: [x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/install_prebuilt_rules_and_timelines/install_prebuilt_rules_and_timelines_route.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/install_prebuilt_rules_and_timelines/install_prebuilt_rules_and_timelines_route.ts)_ -```ts -// [... file continues above...] - -export const installPrebuiltRulesAndTimelinesRoute = (router: SecuritySolutionPluginRouter) => { - router.versioned - .put({ - path: PREBUILT_RULES_URL, - // [...] - }) - .addVersion( - // [...] - async (context, _, response) => { - const siemResponse = buildSiemResponse(response); - - try { - const rulesClient = (await context.alerting).getRulesClient(); - - const validated = await createPrepackagedRules(/* [...] */) - - // [...] - - -export const createPrepackagedRules = async ( - // [...] - ): Promise => { - // [...] - - const installedPrebuiltRules = rulesToMap(await getExistingPrepackagedRules({ rulesClient })); - -// [... file continues below ...] -``` - Therefore, modifying the `getExistingPrepackagedRules` function as described above will suffice. - **Installation and Upgrade `_review` and `_perform` endpoints:** From 0647a4ff86ab0ad34f60206a98aa512a82db5783 Mon Sep 17 00:00:00 2001 From: jpdjere Date: Wed, 14 Feb 2024 12:33:36 +0100 Subject: [PATCH 10/61] Refactor: Add section --- .../docs/prebuilt_rules_customization_rfc.md | 103 ++++++------------ 1 file changed, 33 insertions(+), 70 deletions(-) diff --git a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md index 3c380673830b79..1e315afebda1e5 100644 --- a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md +++ b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md @@ -362,6 +362,31 @@ Since our alerting rules are encrypted saved objects, we have to find an alterna Since the migration of rules will be performed as the user calls the pertinent endpoints, the migration of the saved objects will be carried out progressively and incrementally: the SO will be migrated only when a endpoint that handles it is called by the user. We therefore have to assume that, at any given point in time, a user may have a mix of migrated and non-migrated rule saved objects. Consequently, we must continue supporting both versions of SOs. +### Problem with tightly coupled logic in our endpoints + +All endpoints belonging to Detection Rules Management that create and update -including upgrade of prebuilt rules to new version- use three CRUD methods under the hood: + +- [`createRules`](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/crud/create_rules.ts) +- [`patchRules`](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/crud/patch_rules.ts) +- [`updateRules`](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/crud/update_rules.ts) + +This "overuse" of these 3 methods for a variety of user actions makes their logic tightly coupled and creates a considerable amount of complexity to CRUD functions that should remain logically simple. + +For example: the `createRules` method is used in 3 use cases: +1. when creating custom rules with our Rule Creation endpoints +2. when importing rules, when the imported `rule_id` does not already exist in Kibana +3. when upgrading rules, if a rule undergoes a `type` change, the existing rule is deleted a new one is created. + +The same happens with `patchRules`. It is used: +1. when patching rules via our Rule Patch endpoints +2. when importing rules, when the imported `rule_id` is brand new +3. when upgrading rules, if a rule maintains its `type`. + +This causes these 3 CRUD functions to have an unnecessary complex interfaces and logic in order to handle all these different use cases. + +As part of the epic, we should move away from this practice and create new CRUD methods that handle the different cases mentioned above specifically. This will help simplify our existing methods, keep logic in all of our CRUD methods simple and logically uncoupled from one another. + + ### Migration strategy Our migration strategy will consist of two distinct types of migration: a **migration on write** that will update the SO on Elasticsearch, and a **normalization on read**, which will transform legacy rules to the new schema **in memory** on read operation, before returning it as a response from an API endpoint. @@ -541,7 +566,7 @@ So we can analyze the expected outputs of the migration of all these 8 endpoints The resulting values for `immutable` and `external_source` when calling these endpoints, and the migration being performed in the background, should be as follows: - +
@@ -838,7 +863,7 @@ Additionally: - [**Review Rule Installation** - `POST /prebuilt_rules/installation/_review` (Internal)](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/review_rule_installation/review_rule_installation_route.ts) -This endpoint uses the `convertPrebuiltRuleAssetToRuleResponse` method, which takes in a prebuilt rule asset and converts it to an object of type `RuleResponse`. This method has to be modified so that new prebuilt rules objects are returned by the endpoint with a `prebuilt` object and a legacy `immutable` value of `true`. +This endpoint uses the `convertPrebuiltRuleAssetToRuleResponse` method, which takes in a prebuilt rule asset and converts it to an object of type `RuleResponse`. This method has to be modified so that new prebuilt rules objects are returned by the endpoint with an `external_source` object and a legacy `immutable` value of `true`. _Source: [x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/normalization/rule_converters.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/normalization/rule_converters.ts)_ @@ -854,12 +879,12 @@ export const convertPrebuiltRuleAssetToRuleResponse = ( }; const ruleResponseSpecificFields = { - id: uuidv4(), // [... other prebuilt rule fields ...] immutable: true, - prebuilt: { + external_source: { + repoName: 'elastic_prebuilt', isCustomized: false, - elasticUpdateDate: prebuiltRuleAsset.elasticUpdateDate, + sourceUpdatedAt: prebuiltRuleAsset.sourceUpdatedAt, }, revision: 1, }; @@ -876,83 +901,21 @@ export const convertPrebuiltRuleAssetToRuleResponse = ( To install a new prebuilt rule, this endpoint uses the [`createPrebuiltRules` method](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/rule_objects/create_prebuilt_rules.ts), which in turn calls the [`createRules` method](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/crud/create_rules.ts). -So when calling `createRules` within `createPrebuiltRules`, we need to explictly pass in the `isPrebuilt` property set to `true`: - -_Source: [x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/rule_objects/create_prebuilt_rules.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/rule_objects/create_prebuilt_rules.ts)_ - -```ts -// [... file continues above ...] - -export const createPrebuiltRules = (rulesClient: RulesClient, rules: PrebuiltRuleAsset[]) => - withSecuritySpan('createPrebuiltRules', async () => { - const result = await initPromisePool({ - concurrency: MAX_RULES_TO_UPDATE_IN_PARALLEL, - items: rules, - executor: async (rule) => { - return createRules({ - rulesClient, - params: rule, - isPrebuilt: true, // renamed from "immutable" - defaultEnabled: false, - }); - }, - }); - - return result; - }); -``` +This endpoint suffers from the issue of tightly coupled logic explained above: using th `createRules` method for creating, importing and upgrading -in some cases- rules. We need to create a new CRUD method specifically for installing prebuilt rules, that extracts that responsibility out of the `createRules` method. - [**Review Rule Upgrade** - `POST /prebuilt_rules/upgrade/_review` (Internal)](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/review_rule_upgrade/review_rule_upgrade_route.ts) This endpoint uses the `convertPrebuiltRuleAssetToRuleResponse` method to get a `RuleResponse`-type object from a target version of a rule provided from upstream. This method needs to be modified as described in the section that details the changes needed for the **Review Rule Installation** - `POST /prebuilt_rules/installation/_review`. -An additional change will be needed within the route handler, when calculating the `targetRule` that is returned in the response. Since the `prebuilt` rule field is calculated by the `convertPrebuiltRuleAssetToRuleResponse` method, the `prebuilt.isCustomized` field would always be set to `false`, even when updating rules that have been previously customized. Therefore, the `prebuilt` field needs to be overwritten to take as its value for `prebuilt.isCustomized` the current value that is set in the currently installed rule, or default to false it that value doesn't yet exist: - -_Source: [x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/review_rule_upgrade/review_rule_upgrade_route.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/review_rule_upgrade/review_rule_upgrade_route.ts)_ - -```ts -// [... file continues above ...] - -const calculateRuleInfos = (results: CalculateRuleDiffResult[]): RuleUpgradeInfoForReview[] => { - return results.map((result) => { - const { ruleDiff, ruleVersions } = result; - const installedCurrentVersion = ruleVersions.input.current; - const targetVersion = ruleVersions.input.target; - - // [... file continues ...] - - const targetRule: RuleResponse = { - ...convertPrebuiltRuleAssetToRuleResponse(targetVersion), - // Overwrite the prebuilt object returned from convertPrebuiltRuleAssetToRuleResponse - // to account for the currently installed rule's value of `isCustomized`. - prebuilt: { - isCustomized: installedCurrentVersion.prebuilt?.isCustomized ?? false, - elasticUpdateDate: targetVersion.elasticUpdateDate, - }, - // [... other props ...] - }; - - return { - // [... other props ...] - current_rule: installedCurrentVersion, - target_rule: targetRule, - diff: { - /* [...] */ - }, - }; - }); -}; -``` - This endpoint will need further changes, which will be detailed further down, and are out of the scope of Saved Object, migration and rule schema updates. - [**Perform Rule Upgrade** - `POST /prebuilt_rules/upgrade/_perform` (Internal)](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_upgrade/perform_rule_upgrade_route.ts) This endpoint will require major changes to add the capability of letting users selecting a custom version of the rule with custom values for rule fields. This will be explained further below in the "Changes to upgrade `_review` and `_perform` endpoints" section. -The calculation of the value for the `prebuilt.isCustomized` field for the updated rule will depend on that logic as well, so its calculation will be explained in that section. +The calculation of the value for the `external_source.isCustomized` field for the updated rule will depend on that logic as well, so its calculation will be explained in that section. -However, once that value is calculated by the endpoint handler logic, we will need to pass it to the `upgradePrebuiltRules` method that is used by the handler to actually upgrade the rules. This method either patches existing rules -for the normal case-, or deletes an existing rule and recreates it if the rule underwent a type change during the upgrade (for example, the previous version of the rule had type of `query` and the new version is `eql`). +Again, this endpoint suffers from tightly coupled logic: it uses the `upgradePrebuiltRules` method to actually upgrade the rules, but this method either patches existing rules -for the normal case-, or deletes an existing rule and recreates it if the rule underwent a type change, using the `patchRules` and `createRules` methods respectively. Decouple that logic by introducing a new CRUD method with a specific use case for upgrading prebuilt rule. The changes in the `upgradePrebuiltRules` method need to take into account both paths. In the endpoint logic handler, when calculating if the rule was customized by the user, we will create a boolean called `isRuleCustomizedDuringUpgrade`, that we will pass as an argument to `upgradePrebuiltRules`: From 15795cbff6bd10545e1842df7610f4312aa31e60 Mon Sep 17 00:00:00 2001 From: jpdjere Date: Wed, 14 Feb 2024 15:16:21 +0100 Subject: [PATCH 11/61] Refactor: Further simplified endpoints --- .../docs/prebuilt_rules_customization_rfc.md | 249 ++---------------- 1 file changed, 29 insertions(+), 220 deletions(-) diff --git a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md index 1e315afebda1e5..4395913a23ce84 100644 --- a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md +++ b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md @@ -37,7 +37,7 @@ pandoc prebuilt_rules_customization_rfc.md --toc --toc-depth=6 --wrap=none -s - ``` - [Necessary rule schema changes](#necessary-rule-schema-changes) - - [`prebuilt` and `immutable` fields](#prebuilt-and-immutable-fields) + - [`external_source` and `immutable` fields](#prebuilt-and-immutable-fields) - [`isCustomized` subfield](#iscustomized-subfield) - [`elasticUpdateDate` subfield](#elasticupdatedate-subfield) - [Changes needed in rule schema](#changes-needed-in-rule-schema) @@ -302,7 +302,7 @@ export const BaseRuleParams = z.object({ In the internal rule schema, there are two additional important reasons why we need to make sure that this value is optional: -- When rules are executed, a call to the method `validateRuleTypeParams` is done, which is a method that validates the passed rule's parameters using the validators defined in `x-pack/plugins/security_solution/server/lib/detection_engine/rule_types`, within each of the rule query types files (for [EQL rules](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/eql/create_eql_alert_type.ts#L27), for example). The validation is done based on the internal rule schema `BaseRulesParams` displayed above. Having `prebuilt` as a required fields would cause custom rules to fail on runtime. +- When rules are executed, a call to the method `validateRuleTypeParams` is done, which is a method that validates the passed rule's parameters using the validators defined in `x-pack/plugins/security_solution/server/lib/detection_engine/rule_types`, within each of the rule query types files (for [EQL rules](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/eql/create_eql_alert_type.ts#L27), for example). The validation is done based on the internal rule schema `BaseRulesParams` displayed above. Having `external_source` as a required field would cause custom rules to fail on runtime. - The Rule Client `update` method also calls the `validateRuleTypeParams` to validate the rule's params. Since the Rule Client's `update` method is used in our endpoint handlers, such as and `/rules/patch` and `/_bulk_actions`, these would fail when executed against a payload of custom rule. Additionally, the `PrebuiltRuleAsset` type needs to be updated to include the new `source_updated_at` date that will be progressively shipped with new versions of rules in the Elastic Prebuilt Rules package: @@ -324,7 +324,7 @@ export const PrebuiltRuleAsset = BaseCreateProps.and(TypeSpecificCreateProps).an ### Deprecating the `immutable` field -In order to mark the `immutable` field as deprecated, and making sure that our application and API users are aware that the field has been deprecated and replaced by the `prebuilt` field, we will communicate this change in three ways: +In order to mark the `immutable` field as deprecated, and making sure that our application and API users are aware that the field has been deprecated and replaced by the `external_source` field, we will communicate this change in three ways: 1. via updates to the documentation of all endpoints that return `RuleResponse` types 2. via a deprecation warning in the OpenAPI schema, as detailed above @@ -334,7 +334,7 @@ The `immutable` field will afterwards be actually removed from our API endpoint Both the docs and the custom response header should communicate that the `immutable` field: -- has been replaced by the `prebuilt` field and users should rely on that new field onwards +- has been replaced by the `external_source` field and users should rely on that new field onwards - is maintained for backwards compatibility reasons only - will be removed after a specific date/release @@ -515,16 +515,15 @@ All of the following endpoints either fetch the rule before updating it, or send This endpoint also includes a `dry_run` mode that is executed to evaluate preconditions and warn the user before executing the actual request. No migration logic should take place for dry run requests, i.e when `dry_run=true`, since we never write to ES when this parameter is set to `true`. -For the **bulk edit** action, we can take advantage of the `ruleParamsModifier` to carry out the migration, regardless of the type of edit that is being performed. See implementation details in the below [Technical implementation of migration-on-write](#technical-implementation-of-migration-on-write) section. +For the **bulk edit** action, we can take advantage of the `ruleParamsModifier` to carry out the migration, regardless of the type of edit that is being performed. See implementation details in the below [Bulk editing rules](#bulk-editing-rules) section. For the **duplicate** rule action: -Since we will be creating a new rule on ES, we should create it with the new schema. Per definition, all duplicated rules will be `custom` rules. That means that for all rules -including prebuilt rules-, when duplicating, the `prebuilt` field will not be created on the newly created rule. +Since we will be creating a new rule on ES, we should create it with the new schema. Per definition, all duplicated rules will be `custom` rules. That means that for all rules -including prebuilt rules-, when duplicating, the `external_source` field will not be created on the newly created rule. This action will not perform a migration-on-write of the original rule being duplicated for two reasons: -- would violate the principle of least surprise for the endpoint +- it would violate the principle of least surprise for the endpoint - the current implementation of the endpoint does not modify the original rule. This gives us no window of opportunity to migrate the rule and save to ES without adding performance overhead. -- See implementation details below. All other type of actions should **not** perform migration-on-write: @@ -740,6 +739,10 @@ The resulting values for `immutable` and `external_source` when calling these en
Use case
+As explained before, all these endpoints suffer from the tightly-coupled logic problem described in the section [`Problem with tightly coupled logic in our endpoints`](#problem-with-tightly-coupled-logic-in-our-endpoints). + +We should therefore create new CRUD methods as needed to uncouple them logically and cleanly apply migrations to them. + --- #### Bulk editing rules @@ -748,26 +751,24 @@ The endpoint **Bulk Actions** - `POST /rules/_bulk_action` has the same outputs However, this endpoint has some specific details that should be mentioned. -Firstly, when bulk editing rules, the migration should apply for the following use cases: +Firstly, when bulk editing rules, the migration should be carried out for the following use cases: - Bulk adding or deleting index patterns - Bulk adding or deleting tags - Updating rule schedules - Adding rules actions - - Duplicating a rule (migration applied only to the new rule) + - Duplicating a rule (with the migration applied only to the new rule) -Out of the actions mentioned above, the only use cases that should possibily result in the migration having a result of `external_source.isCustomized = true` are the first three: +Out of the actions mentioned above, the only use cases that should possibly result in the migration having a result of `external_source.isCustomized = true` are the first three: - Bulk adding or deleting index patterns - Bulk adding or deleting tags - Updating rule schedules -That is, updating a rule's actions or duplicating a rule should not be considered a customization of a prebuilt rule. +That means that updating a rule's actions or duplicating a rule should not be considered a customization of a prebuilt rule. Secondly, in contrast with other endpoints, the migration for bulk editing rules needs to be carried within the Alerting Framework's `RuleClient` since we need to migrate the rule's `external_source` and `immutable` parameters before the `RuleClient` does the saving of the rule into Elasticsearch. This however, gives us the advantage that the `RuleClient` already includes logic to calculate if a rule's attributes or parameters have been modified from its initial values, so we can rely on that to calculate the `external_source.isCustomized` field during the update. -Notice that here we are migrating the `ruleParams` in-place; the object is later used to save the updated rules into Elasticsearch. - The `RulesClient` class has a `bulkEdit` method, which is called by our **Bulk Actions endpoint** `POST /rules/_bulk_action`. That method includes complex logic, but we can focus on the `updateRuleAttributesAndParamsInMemory` method, where the rule attributes and parameters are updated before being saved to ES. This function also calculates the booleans `isAttributesUpdateSkipped` and `isParamsUpdateSkipped` which we can leverage to calculate the new value of the `external_source.isCustomized` field in our params. _See Source: [x-pack/plugins/alerting/server/application/rule/methods/bulk_edit/bulk_edit_rules.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/alerting/server/application/rule/methods/bulk_edit/bulk_edit_rules.ts)_ @@ -808,6 +809,10 @@ Currently, we don't support the `immutable` field in any of the endpoints' reque This is so because we will never want users to be able to create their own prebuilt rules, only install them, import them, and customize them. Also, a prebuilt rule should always be able to be compared to a `security-rule` asset distributed by Fleet, and receive updates from it, which would not be possible if a user creates its own prebuilt rules. +Again, as mentioned in the [`Problem with tightly coupled logic in our endpoints`](#problem-with-tightly-coupled-logic-in-our-endpoints) section, the `createRules` CRUD method used in these two endpoints is re-used in other unrelated use cases, like upgrading rules and importing rules. + +Creating new methods for those unrelated actions should help clean the `createRules` method's interface and logic, and make sure it is only used in these two endpoints. + - **Rule Management Filters** - `GET /rules/_rule_management_filters` (Internal): This endpoint currently depends on rules `alert.attributes.params.immutable` to fetch number of custom rules and number of prebuilt rules. We need to adapt its logic to rely on new `alert.attributes.params.external_source` field, with fallback to the original, for backwards compatibility. @@ -901,7 +906,7 @@ export const convertPrebuiltRuleAssetToRuleResponse = ( To install a new prebuilt rule, this endpoint uses the [`createPrebuiltRules` method](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/rule_objects/create_prebuilt_rules.ts), which in turn calls the [`createRules` method](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/crud/create_rules.ts). -This endpoint suffers from the issue of tightly coupled logic explained above: using th `createRules` method for creating, importing and upgrading -in some cases- rules. We need to create a new CRUD method specifically for installing prebuilt rules, that extracts that responsibility out of the `createRules` method. +This endpoint also suffers from the issue of tightly coupled logic explained above: using th `createRules` method for creating, importing and upgrading -in some cases- rules. We need to create a new CRUD method specifically for installing prebuilt rules, that extracts that responsibility out of the `createRules` method. - [**Review Rule Upgrade** - `POST /prebuilt_rules/upgrade/_review` (Internal)](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/review_rule_upgrade/review_rule_upgrade_route.ts) @@ -915,123 +920,12 @@ This endpoint will require major changes to add the capability of letting users The calculation of the value for the `external_source.isCustomized` field for the updated rule will depend on that logic as well, so its calculation will be explained in that section. -Again, this endpoint suffers from tightly coupled logic: it uses the `upgradePrebuiltRules` method to actually upgrade the rules, but this method either patches existing rules -for the normal case-, or deletes an existing rule and recreates it if the rule underwent a type change, using the `patchRules` and `createRules` methods respectively. Decouple that logic by introducing a new CRUD method with a specific use case for upgrading prebuilt rule. +Again, this endpoint suffers from tightly coupled logic explained in [`Problem with tightly coupled logic in our endpoints`](#problem-with-tightly-coupled-logic-in-our-endpoints): it uses the `upgradePrebuiltRules` method to actually upgrade the rules, but this method either patches existing rules -for the normal case-, or deletes an existing rule and recreates it if the rule underwent a type change, using the `patchRules` and `createRules` methods respectively. We should decouple that logic by introducing a new CRUD method with a specific use case for upgrading prebuilt rule. The changes in the `upgradePrebuiltRules` method need to take into account both paths. In the endpoint logic handler, when calculating if the rule was customized by the user, we will create a boolean called `isRuleCustomizedDuringUpgrade`, that we will pass as an argument to `upgradePrebuiltRules`: _Source: [x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_upgrade/perform_rule_upgrade_route.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_upgrade/perform_rule_upgrade_route.ts)_ -```ts -// [... file continues above ...] - -export const performRuleUpgradeRoute = (router: SecuritySolutionPluginRouter) => { - router.versioned - .post({ - access: 'internal', - path: PERFORM_RULE_UPGRADE_URL, - // [...] - }) - .addVersion( - { - // [...] - }, - async (context, request, response) => { - // [...] - - try { - // [...] - - // Endpoint will include logic for calculating which rule version should the current rule be upgraded to, - // as well as calculating the isRuleCustomizedDuringUpgrade boolean. - // Details explained further below in this document. - - // Perform the upgrade, but pass in `isRuleCustomizedDuringUpgrade` as an argument - const { results: updatedRules, errors: installationErrors } = await upgradePrebuiltRules( - rulesClient, - targetRules, - isRuleCustomizedDuringUpgrade - ); - // [...] - - return response.ok({ body }); - } catch (err) { - // [...] - } - } - ); -}; -``` - -And the `isRuleCustomizedDuringUpgrade` argument , which defaults to `false`, will be used as follows: - -_Source: [x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/rule_objects/upgrade_prebuilt_rules.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/rule_objects/upgrade_prebuilt_rules.ts)_ - -```ts -// [... file continues above ...] - -export const upgradePrebuiltRules = async ( - rulesClient: RulesClient, - rules: PrebuiltRuleAsset[], - isRuleCustomizedDuringUpgrade = false -) => { - // [...] - return upgradeRule(rulesClient, rule, isRuleCustomizedDuringUpgrade); - // [...] -} - - -const upgradeRule = async ( - rulesClient: RulesClient, - rule: PrebuiltRuleAsset - isRuleCustomizedDuringUpgrade: boolean -): Promise> => { - const existingRule = await readRules({ - // [...] - }); - - // [...] - - // Set the value to true if the rule was customized during - // the current update. Otherwise, take the existing value from - // the currently installed value. Default to false. - const isCustomized = - (isRuleCustomizedDuringUpgrade || existingRule.params.prebuilt?.isCustomized) ?? false; - const prebuilt = { - isCustomized, - elasticUpdateDate: rule.elasticUpdateDate, - } - - if (rule.type !== existingRule.params.type) { - await deleteRules({ - ruleId: existingRule.id, - rulesClient, - }); - - return createRules({ - rulesClient, - isPrebuilt: true, - params: { - ...rule, - prebuilt, - // [...] - }, - }); - } else { - await patchRules({ - rulesClient, - existingRule, - nextParams: { - ...rule, - prebuilt, - // [...] - }, - }); - - // [...] - } -}; -``` - ### Rule monitoring endpoints - [**Detection Engine Health: Get Cluster Health** - `GET or POST /detection_engine/health/_cluster` (internal):](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/api/detection_engine_health/get_cluster_health/get_cluster_health_route.ts) @@ -1040,41 +934,10 @@ This endpoint uses the [Detection Engine Health Client (`IDetectionEngineHealthC The Detection Engine Health client receives as its parameter the [Rule Objects Health client (`IRuleObjectsHealthClient`)](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/detection_engine_health/rule_objects/rule_objects_health_client.ts), whose method `calculateClusterHealth` performs an aggregation on rule stats based on different rule attributes and parameters. -This is done in the [`getRuleStatsAggregation` method](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/detection_engine_health/rule_objects/aggregations/rule_stats.ts), where an aggration is done over the `immutable` param. This needs to be updated to the new `prebuilt` param, with a fallback to `immutable`: +This is done in the [`getRuleStatsAggregation` method](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/detection_engine_health/rule_objects/aggregations/rule_stats.ts), where an aggration is done over the `immutable` param. This needs to be updated to the new `external_source` param, with a fallback to `immutable`: _Source: x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/detection_engine_health/rule_objects/aggregations/rule_stats.ts(https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/detection_engine_health/rule_objects/aggregations/rule_stats.ts)_ -```ts -// [... file continues above ...] - -export const getRuleStatsAggregation = (): Record< - string, - estypes.AggregationsAggregationContainer -> => { - const rulesByEnabled: estypes.AggregationsAggregationContainer = { - terms: { - field: 'alert.attributes.enabled', - }, - }; - - return { - rulesByEnabled, - rulesByOrigin: { - terms: { - // TODO: How to make this aggregation by whether the `prebuilt` field exists and immutable as fallback? - field: `${PARAMS_PREBUILT_IS_CUSTOMIZED_FIELD} or alert.attributes.params.immutable`, - }, - aggs: { - rulesByEnabled, - }, - }, - // [... other aggrations ...] - }, - }; -}; -// [... file continues below ...] -``` - - **Detection Engine Health: Get Space Health** - `GET or POST /detection_engine/health/_space` (internal): In this endpoint, the `getSpaceHealthAggregation` method of the Rule Objects Health client (`IRuleObjectsHealthClient`) is called instead, but it internally calls the same [`getRuleStatsAggregation` method](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/detection_engine_health/rule_objects/aggregations/rule_stats.ts) as in the previous endpoint. @@ -1123,64 +986,10 @@ Both of these methods use `internalRuleToAPIResponse` internally to transform ru Also, in order to allow the endpoint to export both custom **and** prebuilt rules, we need to update the logic and remove the checks that we currently do server-side in both of these methods, and which filter out prebuilt rules from the response payload: -- **Bulk Actions** - `POST /rules/_bulk_action` with the **export action** -- **Export Rules** - `POST /rules/_export` - -_Source: [x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/export/get_export_by_object_ids.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/export/get_export_by_object_ids.ts)_ - -```ts -// [... file continues above ...] - -export const getRulesFromObjects = async ( - rulesClient: RulesClient, - savedObjectsClient: RuleExecutorServices['savedObjectsClient'], - objects: Array<{ rule_id: string }>, - logger: Logger -): Promise => { - const chunkedObjects = chunk(objects, 1024); - const filter = [...] - const rules = await findRules({[...]}); - - const alertsAndErrors = objects.map(({ rule_id: ruleId }) => { - const matchingRule = rules.data.find((rule) => rule.params.ruleId === ruleId); - if ( - matchingRule != null - && hasValidRuleType(matchingRule) - // && matchingRule.params.immutable !== true <--- Check which should be removed - ) { - return { - statusCode: 200, - rule: transformRuleToExportableFormat(internalRuleToAPIResponse(matchingRule)), - }; - } else { - return { - statusCode: 404, - missingRuleId: { rule_id: ruleId }, - }; - } - }); - -// [... file continues below ...] -``` - -Notice that the **Bulk Actions** - `POST /rules/_bulk_action` does not perform a **dry run** in order to filter out prebuilt rules when the user runs an **export** action; this is the only check that is performed. +_Source for `getRulesFromObjects`: [x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/export/get_export_by_object_ids.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/export/get_export_by_object_ids.ts)_ -_Source: [x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/export/get_export_all.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/export/get_export_all.ts)_ - -```ts -// [... file continues above ...] -export const getExportAll = async ( - // [...] -): Promise<{ - rulesNdjson: string; - // [...] -}> => { - // const ruleAlertTypes = await getNonPackagedRules({ rulesClient }); <---- current code - const allRules = await getRules({ rulesClient }); // <------ get all rules now - const rules = transformAlertsToRules(allRules); -// [... file continues below ...] -``` +_Source for `getExportAll`: [x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/export/get_export_all.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/export/get_export_all.ts)_ ### Importing rules @@ -1190,9 +999,9 @@ We want to handle the case of importing both migrated and non-migrated rules via Importing rules with `immutable: false` "should" be the only case for non-migrated rules (since `immutable: true` rules cannot currently be exported), but we should also handle the case of users manually modifying the values of rules in the `ndjson` file. -If a user attempts to import a rule with `immutable: true` and missing `prebuilt` (or viceversa, a `prebuilt` field but no `immutable` field), then the most likely scenario is of a user trying to import Elastic prebuilt rules from a modified `ndjson` file. So we should consider these rules to be prebuilt and attempt to track them to rules in the Fleet package via their `rule_id` and continue to provide updates to them. +If a user attempts to import a rule with `immutable: true` and missing `external_source` (or viceversa, a `external_source` field but no `immutable` field), then the most likely scenario is of a user trying to import Elastic prebuilt rules from a modified `ndjson` file. So we should consider these rules to be prebuilt and attempt to track them to rules in the Fleet package via their `rule_id` and continue to provide updates to them. -Given the requirements described above, the following table shows the behaviour of our endpoint for a combination of `prebuilt` and `immutable` fields in the `ndjson` file that a user attempts to import: +Given the requirements described above, the following table shows the behaviour of our endpoint for a combination of `external_source` and `immutable` fields in the `ndjson` file that a user attempts to import: @@ -1288,7 +1097,7 @@ Given the requirements described above, the following table shows the behaviour
-If a user imports a prebuilt rule (where either the `prebuilt` or `immutable` fields are `true`), it will continue to track the rule asset from the `security_detection_engine` package if the `rule_id` matches. This means that a user will be able to update a previously exported prebuilt rule, visualize any diffs on any customized fields, and continue to receive updates on the rule. +If a user imports a prebuilt rule (where either the `external_source` or `immutable` fields are `true`), it will continue to track the rule asset from the `security_detection_engine` package if the `rule_id` matches. This means that a user will be able to update a previously exported prebuilt rule, visualize any diffs on any customized fields, and continue to receive updates on the rule. With this migration strategy for the import endpoints we can guarantee backwards compatibility for all rules, and don't need to do additional changes to the export endpoints. @@ -1400,7 +1209,7 @@ Endpoints that users will be able to use to modify rules are: The first four endpoints listed above **currently allow users to modify their Elastic prebuilt rules** as well, in (almost) all of their fields, and no difference is made between updating/patching prebuilt rules and custom rules in the docs. However, none of those four endpoints allow to change a prebuilt rule to a custom rule (or vice-versa) by changing the current `immutable` field (i.e. the field is maintained from the existing rule). -> - **Will we want to allow users to modify (via API) a prebuilt rule to transform it into a Custom Rule, by modifying the `prebuilt` parameter?** +> - **Will we want to allow users to modify (via API) a prebuilt rule to transform it into a Custom Rule, by modifying the `external_source` parameter?** > - No. We want to keep the current endpoint logic where the `immutable` field for the updated value comes from the existing value of the rule. Allowing that modification would create issues with the corresponding `security_detection_engine` package rule, as it will clash with the modified rule if the `rule_id` is not modified as well. This requirement is therefore not needed anyway since will now offer users the option to customize a prebuilt rule, or alternatively, duplicate a prebuilt rule. The endpoint **Bulk Actions** - `POST /rules/_bulk_action` does provide validation in the endpoint logic itself: if a user attempts to edit prebuilt rule (`immutable: true`) the endpoint rejects that edit in two ways: @@ -1441,7 +1250,7 @@ In both cases, the validation checks if the `immutable` param of the rule is `fa - Addition of rule schema migration logic (described above) - Calculation of `customized` field for each modified rule - Removal of the check that prevents modifying prebuilt rules. Customization should be possible for both prebuilt and custom rules, and for all bulk editing actions that are currently supported for custom rules. - - Remove check for whether the rules in the payload have an `immutable` value of `false` OR if the `BulkActionEditTypeEnum` is either `set_rule_actions` or `add_rule_actions`. Bulk editing should be possible for all rules (independently of their values for the `prebuilt` and now legacy `immutable` fields), and for all types of Bulk Action Edit Types: + - Remove check for whether the rules in the payload have an `immutable` value of `false` OR if the `BulkActionEditTypeEnum` is either `set_rule_actions` or `add_rule_actions`. Bulk editing should be possible for all rules (independently of their values for the `external_source` and now legacy `immutable` fields), and for all types of Bulk Action Edit Types: ```ts export const BulkActionEditType = z.enum([ 'add_tags', From eab1c4b3fa443aa59f131d997bb0d677c4755119 Mon Sep 17 00:00:00 2001 From: jpdjere Date: Thu, 15 Feb 2024 18:14:53 +0100 Subject: [PATCH 12/61] Refactor: Deleted importing cases table --- .../docs/prebuilt_rules_customization_rfc.md | 152 +----------------- 1 file changed, 1 insertion(+), 151 deletions(-) diff --git a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md index 4395913a23ce84..5cc5d3bfe53bdf 100644 --- a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md +++ b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md @@ -971,7 +971,7 @@ The user will now be able to export both custom and prebuilt rules (including an The export endpoints (bulk export and bulk action in export mode) will not carry out any migration-on-write logic. Since these endpoints solely read the rules and generate an ndjson file for export purposes, introducing additional writing or patching logic to migrate the rule's schema in Elasticsearch would negatively impact the endpoints' performance and introduce unnecessary overhead. -Instead, we will carry out a normalization-on-read process, as described above, when the rule to be exported is read from ES, and before writing the rule's fields to the `ndjson` file. This means that the rule will actually be exported with the updated schema, thus ensuring backwards compatibility for a subsequent import procedure of this rules, even if they are not yet migrated in ES. +Instead, we will carry out a normalization-on-read process, as described above, when the rule to be exported is read from ES, and before writing the rule's fields to the `ndjson` file. This means that the rule will actually be exported with the updated schema. This normalization will take place within the `internalRuleToAPIResponse` method, which internally calls the `normalizePrebuiltSchemaOnRuleRead`, as described in the [Normalization on read](#normalization-on-read) section. @@ -1003,100 +1003,6 @@ If a user attempts to import a rule with `immutable: true` and missing `external Given the requirements described above, the following table shows the behaviour of our endpoint for a combination of `external_source` and `immutable` fields in the `ndjson` file that a user attempts to import: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PrebuiltImmutableResultsUse case
-
{isCustomized: true, ...}
-
true
-
-          {
-            prebuilt: {
-              isCustomized: true,
-              ...
-            },
-            immutable: true
-          }
-        
-
User importing an already migrated/normalized exported rule
-
undefined
-
true
-
-          {
-            prebuilt: {
-              isCustomized: true,
-            },
-            immutable: true
-          }
-        
-
User importing an prebuilt rule with legacy schema
-
undefined
-
false
-
-          {
-            immutable: false
-          }
-        
-
User importing a custom rule with new or legacy schema
-
{isCustomized: false, ...}
-
false
or
undefined
-
-          {
-            prebuilt: {
-              isCustomized: false,
-              ...
-            },
-            immutable: true
-          }
-        
-
This combination shouldn't be possible, but can happen if user manually modifies an `ndjson` file. The prebuilt field takes precendence over the immutable field and the rule is imported as prebuilt.
-
undefined
-
undefined
-
-          {
-            immutable: false
-          }
-        
-
This combination shouldn't be possible, but can happen if user manually modifies an `ndjson` file. The rule is imported as a custom rule.
- If a user imports a prebuilt rule (where either the `external_source` or `immutable` fields are `true`), it will continue to track the rule asset from the `security_detection_engine` package if the `rule_id` matches. This means that a user will be able to update a previously exported prebuilt rule, visualize any diffs on any customized fields, and continue to receive updates on the rule. With this migration strategy for the import endpoints we can guarantee backwards compatibility for all rules, and don't need to do additional changes to the export endpoints. @@ -1107,62 +1013,6 @@ Given that, when importing rules, we can be creating a custom rule or a prebuilt _Source: [x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/import/import_rules_utils.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/import/import_rules_utils.ts)_ -```ts -// [... file continues above ...] - -export const importRules = async ({ - // [...] -}: { - // [...] -}) => { - // [...] - - // Determine if the rule to import is prebuilt based on the payload - const isPrebuilt = Boolean(parsedRule.prebuilt) || parsedRule.immutable; - - // If the rule is prebuilt, the `version` is required - if (isPrebuilt && !parsedRule.version) { - createBulkErrorObject({ - ruleId: parsedRule.rule_id, - statusCode: 409, - message: `rule_id: "${parsedRule.rule_id}" is prebuilt but no version was provided`, - }); - } - - // If no rule_id matched, create a new rule. We need to calculate the isPrebuilt - // argument to pass it to `createRules` following the logic described above. - if (rule == null) { - - await createRules({ - rulesClient, - params: { - ...parsedRule, - exceptions_list: [...exceptions], - }, - isPrebuilt, - allowMissingConnectorSecrets, - }); - resolve({ - rule_id: parsedRule.rule_id, - status_code: 200, - }); - // If rule_id matches and the overwriteRules flag is true, patch the existing rule. - // The calculation of the prebuilt and immutable fields will be done by the - // `migratePrebuiltSchemaOnRuleUpdate` helper based on the payload from the ndjson - } else if (rule != null && overwriteRules) { - await patchRules({ - rulesClient, - existingRule: rule, - nextParams: { - ...parsedRule, - exceptions_list: [...exceptions], - }, - allowMissingConnectorSecrets, - shouldIncrementRevision: false, - }); - -// [... file continues below ...] -``` ### Handling the `version` parameter From 6363547f85d8dcdb021ad6fbbfd0f4f2f54447fb Mon Sep 17 00:00:00 2001 From: jpdjere Date: Thu, 15 Feb 2024 19:01:57 +0100 Subject: [PATCH 13/61] Refactor: Minor fix --- .../docs/prebuilt_rules_customization_rfc.md | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md index 5cc5d3bfe53bdf..5d317439a38987 100644 --- a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md +++ b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md @@ -279,20 +279,12 @@ export const RuleToImport = BaseCreateProps.and(TypeSpecificCreateProps).and( _Source: [x-pack/plugins/security_solution/server/lib/detection_engine/rule_schema/model/rule_schemas.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_schema/model/rule_schemas.ts)_ ```ts -// [... file continues above...] - -import { - // [...] - ExternalSourceAttributes, - // [...] -} from '../../../../../common/api/detection_engine/model/rule_schema'; - export type BaseRuleParams = z.infer; export const BaseRuleParams = z.object({ // [...] immutable: IsRuleImmutable, - external_soruce: ExternalSourceAttributes.transform(camelize).optional(), + externalSource: ExternalSourceAttributes.transform(camelize).optional(), // [...] }); From 26c7fadba107a3179c7f8b3a24019a98321fec80 Mon Sep 17 00:00:00 2001 From: jpdjere Date: Mon, 19 Feb 2024 12:35:32 +0100 Subject: [PATCH 14/61] Refactor: Started rewriting based on rule_source_type and import feedback --- .../import_rules/rule_to_import.ts | 6 +- .../docs/prebuilt_rules_customization_rfc.md | 141 ++++++++++++------ .../model/rule_assets/prebuilt_rule_asset.ts | 2 +- 3 files changed, 101 insertions(+), 48 deletions(-) diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/import_rules/rule_to_import.ts b/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/import_rules/rule_to_import.ts index a2df931c5eaf05..f982fdc62c1a69 100644 --- a/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/import_rules/rule_to_import.ts +++ b/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/import_rules/rule_to_import.ts @@ -11,8 +11,7 @@ import { ResponseFields, RuleSignatureId, TypeSpecificCreateProps, - IsRuleImmutable, - Prebuilt, + RuleVersion, } from '../../model/rule_schema'; /** @@ -30,7 +29,6 @@ export type RuleToImportInput = z.input; export const RuleToImport = BaseCreateProps.and(TypeSpecificCreateProps).and( ResponseFields.partial().extend({ rule_id: RuleSignatureId, - immutable: IsRuleImmutable.optional(), - prebuilt: Prebuilt.optional(), + version: RuleVersion, }) ); diff --git a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md index 5d317439a38987..7d146d956c54b6 100644 --- a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md +++ b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md @@ -108,44 +108,53 @@ During this RFC, we will explicitly refer to case of Elastic prebuilt rules, but ## Necessary rule schema changes -In order to support the customization of Elastic Prebuilt Rules, we need to modify our rule schema. This involves introducing a new nested `external_source` field and deprecating the `immutable` field. +In order to support the customization of Elastic Prebuilt Rules, we need to modify our rule schema. This involves introducing the new top level fields: `rule_source_type` and the nested `external_source` field, as well deprecating the `immutable` field. ```ts // PSEUDOCODE - see complete schema in detail below { + rule_source_type: 'external' | 'internal', external_source?: { - repo_name: string; is_customized: boolean; source_updated_at?: Date; - } + }, } ``` -### `external_source` and `immutable` fields +### `rule_source_type` field + +The `rule_source_type` field will be a required top-level string field that can take two values: `internal` or `external`. + +Rules with value of `internal` are rules generated internally in the Kibana application and which don't have an external origin outside of it. -The `external_source` field will be a top-level object field in our rule schema that will contain subfields with information relating to Elastic Prebuilt rules. +Rules with value of `external` are rules who have an external origin or source. Elastic prebuilt rules are a case of `external` rule, with the `detection-rules` repository handled by the TRaDE team being their external source origin. -It will be an optional field, which will only be present for Elastic prebuilt rules (i.e. rules that are externally soruced). -Its existence within a rule object will determine if a rule is a prebuilt rule, and its absence will determine that it is a custom rule. +### `external_source` field -This means that its presence in a rule object will determine whether the rule is an Elastic Prebuilt Rule that can receive upstream updates via Fleet. This field is intented to replace the currently existing `immutable` field, which is used today for the same purpose, but -as its name indicates- also currently determines if a rule's fields can be modified/customized. +The `external_source` field will be a top-level object field in our rule schema that will contain subfields with information relating to Elastic Prebuilt rules (or rules with an external source, in general). -That means that, in the current state, rules with `immutable: false` are rules which are not Elastic Prebuilt Rules, i.e. custom rules, and can be modified. Meanwhile, `immutable: true` rules are Elastic Prebuilt Rules, created by the TRaDE team, distributed via the `security_detection_engine` Fleet package, and cannot be modified once installed. +It will be an optional field, which will only be present for Elastic prebuilt rules (i.e. rules that are externally sourced). -When successfully implemented, the `external_source` field should replace the `immutable` field as a flag to mark Elastic prebuilt rules, but with one difference: the `external_source` field will determine if the rule is an Elastic Prebuilt Rule or not, but now all rules will be customizable by the user, i.e. independently of the existence (or absence) of `external_source`. +The field will only exist when `rule_source_type` has a value of `external`, and should never be defined for rules with `rule_source_type` with value of `internal`. + +This means that its presence in a rule object will determine whether the rule is an Elastic Prebuilt Rule that can receive upstream updates via Fleet. This field is intented to partly replace the currently existing `immutable` field, which is used today for the same purpose, but -as its name indicates- also currently determines if a rule's fields can be modified/customized. + +### Deprecating the `immutable` field + +In the current application's state, rules with `immutable: false` are rules which are not Elastic Prebuilt Rules, i.e. custom rules, and can be modified. Meanwhile, `immutable: true` rules are Elastic Prebuilt Rules, created by the TRaDE team, distributed via the `security_detection_engine` Fleet package, and cannot be modified once installed. + +When successfully implemented, the `external_source` field, together with `rule_source_type` field, should replace the `immutable` field as a flag to mark Elastic prebuilt rules, but with one difference: the `external_source` field will determine if the rule is an Elastic Prebuilt Rule or not, but now all rules will be customizable by the user in Kibana, i.e. independently of the existence (or absence) of `external_source`. Because of this difference in the behaviour of the `external_source` and `immutable` fields, we feel that a field called `immutable` will lose its meaning over time and become confusing, especially for consumers of the API who interact directly with the field name. That's why we want to eventually deprecate it and fully replace it with `external_source`. -To ensure backward compatibility and avoid breaking changes, we will deprecate the `immutable` field but keep it within the rule schema, asking our users to stop relying on this field in Detection API responses. During the migration period, we want to keep the value of the `immutable` field in sync with the `external_source` field: this means that for all rules that have a `immutable` value of `true`, the `external_source` rule will always exist. Viceversa, rule with `immutable: false` will not have a `external_source` field. +To ensure backward compatibility and avoid breaking changes, we will deprecate the `immutable` field but keep it within the rule schema, asking our users to stop relying on this field in Detection API responses. During the migration period, we want to keep the value of the `immutable` field in sync with the`rule_source_type` and `external_source` fields: this means that for all rules that have a `immutable` value of `true`, the `rule_source_type` will be `external` and the `external_source` field will always exist. Viceversa, rules with `immutable: false` will have a `rule_source_type` of `internal` and will not have a `external_source` field. This means, however, that there will be a change in behaviour of the `immutable` field: with the release of the feature, rules with the `immutable: true` value will now be customizable by the user, which is not the current behaviour. -In this first phase, the `external_source` will contain three subfields: `repo_name`, `is_customized` and `source_updated_at`. - -#### `repo_name` subfield +### Subfields in the `external_source` field -The `repo_name` will be a required string field that specifies the origin repo of the rule. For Elastic prebuilt rules, its value will be `elastic_prebuilt`. The field is required since it will be the leaf node used when searching/filtering for externally sourced rules when using KQL. More details about that below. +In this first phase, the `external_source` will contain two subfields: `is_customized` and `source_updated_at`. #### `is_customized` subfield @@ -171,7 +180,13 @@ This means that we need to differentiate between changes to the internal rule sc #### API schema -**In the API schema** the `external_source` field will be optional, as it will exist for Elastic prebuilt rules, but won't for custom rules. The OpenAPI schema will need to be modified so: +##### API request and response rule schema + +**In the API schema** the `rule_source_type` will be required, but the `external_source` field will be optional, as it will exist for Elastic prebuilt rules, but won't for custom rules. + +Notice, as well, that `immutable` and `external_source` will continue to be part **only of the API response schema**, and never form part of the **request parameters**. + +The OpenAPI schema will need to be modified so: _Source: [x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/common_attributes.schema.yaml](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/common_attributes.schema.yaml)_ @@ -183,11 +198,6 @@ IsRuleImmutable: type: boolean description: '[DEPRECATION WARNING - This field is deprecated and will be removed in a future release. Use the prebuilt field to determine if a rule is an Elastic prebuilt rule or a custom rule.] - Determines whether the rule is immutable (i.e. cannot be modified by the user).' -# Add the top-level `external_source` object and its subfields `repo_name`, `is_customized` and `source_updated_at` -ExternalSourceRepoName: - type: string - description: Name of the external origin repo where rule originated from. For rules created by Elastic and originating from the `detection-rules` repo, the value should be `elastic_prebuilt`. - IsExternalRuleCustomized: type: boolean description: Determines whether an external/prebuilt rule has been customized by the user (i.e. any of its fields have been modified and diverged from the base value). @@ -201,15 +211,19 @@ ExternalSourceAttributes: type: object description: Property whose existence determines whether the rule is an externally sourced rule. Contains information relating to externally sourced rules. Elastic Prebuilt rules are a specific case of externally sourced rules. properties: - repo_name: - $ref: is_customized: $ref: '#/components/schemas/IsExternalRuleCustomized' source_updated_at: $ref: '#/components/schemas/SourceUpdatedAt' required: - - repo_name - isCustomized + +RuleSourceType: + description: Indicates whether the rules is internally sourced (created within the Kibana app) or has an external source, such as the Elastic Prebuilt rules repo. + type: string + enum: + - internal + - external # [... file continues below ...] ``` @@ -229,6 +243,8 @@ ResponseFields: $ref: './common_attributes.schema.yaml#/components/schemas/IsRuleImmutable' external_source: $ref: './common_attributes.schema.yaml#/components/schemas/ExternalSourceAttributes' + rule_source_type: + $ref: './common_attributes.schema.yaml#/components/schemas/RuleSourceType' # [... more response fields ...] required: # notice `external_source` is not required @@ -240,15 +256,21 @@ ResponseFields: - created_at - created_by - revision - - related_integrations - - required_fields - - setup + - rule_source_type # [... file continues below...] ``` +##### Rule Import request schema + We also need to modify the `RuleToImport` schema, since now we will be allowing the importing of both custom rules and prebuilt rules. -Currently, `RuleToImport` optionally accepts the `immutable` param, but rejects validation if its value is set to anything else than `false` - since we don't currently support importing prebuilt rules. We need to update this schema so that it accepts the `immutable` param with both boolean values, and also optionally accepts the new `external_source` field: +Currently, `RuleToImport` optionally accepts the `immutable` param, but rejects validation if its value is set to anything else than `false` - since we don't currently support importing prebuilt rules. + +We will be changing the mechanism for importing rules so that, besides the `rule_id`, the `version` of the rule is also a required parameter. These two parameters will be used to determine if the rule is prebuilt or not, and dynamically calculate the `external_source` and `rule_source_type` during import. + +See the detailed explanation for this mechanism in the [Exporting and importing rules](#exporting-and-importing-rules) sections. + +The `immutable` and `external_source` fields will be ignored if passed in the request payload. _Source: [x-pack/plugins/security_solution/common/api/detection_engine/rule_management/import_rules/rule_to_import.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/import_rules/rule_to_import.ts)_ @@ -259,6 +281,7 @@ import { RuleSignatureId, IsRuleImmutable, ExternalSourceAttributes, + RuleVersion, } from '../../model/rule_schema'; export type RuleToImport = z.infer; @@ -266,15 +289,14 @@ export type RuleToImportInput = z.input; export const RuleToImport = BaseCreateProps.and(TypeSpecificCreateProps).and( ResponseFields.partial().extend({ rule_id: RuleSignatureId, - immutable: IsRuleImmutable.optional(), - external_source: ExternalSourceAttributes.optional(), + version: RuleVersion, }) ); ``` #### Internal rule schema -**The internal rule schema** needs to represent that the new `external_source` field may not always exist, so `external_source` must also be optional. +**The internal rule schema** needs to represent that the new `ruleSourceType` and `externalSource` field may not always exist, so both need to be optional. _Source: [x-pack/plugins/security_solution/server/lib/detection_engine/rule_schema/model/rule_schemas.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_schema/model/rule_schemas.ts)_ @@ -285,19 +307,23 @@ export const BaseRuleParams = z.object({ immutable: IsRuleImmutable, externalSource: ExternalSourceAttributes.transform(camelize).optional(), - + ruleSourceType: RuleSourceType.optional() // [...] }); ``` > Notice that in the internal schema we cannot simply reuse the `ExternalSourceAttributes` attribute defined for the API schema, since it should have CamelCase and the API schema uses snake_case. We need to apply a transformation to our Zod type. See this [issue](https://github.com/colinhacks/zod/issues/486#issuecomment-1567296747). -In the internal rule schema, there are two additional important reasons why we need to make sure that this value is optional: +In the internal rule schema, there are two additional important reasons why we need to make sure that these two fields optional: -- When rules are executed, a call to the method `validateRuleTypeParams` is done, which is a method that validates the passed rule's parameters using the validators defined in `x-pack/plugins/security_solution/server/lib/detection_engine/rule_types`, within each of the rule query types files (for [EQL rules](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/eql/create_eql_alert_type.ts#L27), for example). The validation is done based on the internal rule schema `BaseRulesParams` displayed above. Having `external_source` as a required field would cause custom rules to fail on runtime. +- When rules are executed, a call to the method `validateRuleTypeParams` is done, which is a method that validates the passed rule's parameters using the validators defined in `x-pack/plugins/security_solution/server/lib/detection_engine/rule_types`, within each of the rule query types files (for [EQL rules](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/eql/create_eql_alert_type.ts#L27), for example). The validation is done based on the internal rule schema `BaseRulesParams` displayed above. Having `ruleSourceType` or `externalSource` as required fields would cause custom rules or prebuilt rules that haven't had their schema migrated to fail during runtime. - The Rule Client `update` method also calls the `validateRuleTypeParams` to validate the rule's params. Since the Rule Client's `update` method is used in our endpoint handlers, such as and `/rules/patch` and `/_bulk_actions`, these would fail when executed against a payload of custom rule. -Additionally, the `PrebuiltRuleAsset` type needs to be updated to include the new `source_updated_at` date that will be progressively shipped with new versions of rules in the Elastic Prebuilt Rules package: +##### Prebuilt Rule asset schema + +The `PrebuiltRuleAsset` type needs to be updated to include the new `source_updated_at` date that will be progressively shipped with new versions of rules in the Elastic Prebuilt Rules package. + +Notice that this field will be a **top-level field in the Prebuilt Rule asset** schema, but will be part of the `external_source` field in the API rule schema and internal rule schema. _Source: [x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/model/rule_assets/prebuilt_rule_asset.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/model/rule_assets/prebuilt_rule_asset.ts)_ @@ -322,11 +348,11 @@ In order to mark the `immutable` field as deprecated, and making sure that our a 2. via a deprecation warning in the OpenAPI schema, as detailed above 3. by adding a custom response header in said endpoints. -The `immutable` field will afterwards be actually removed from our API endpoint responses and our application after a deprecation period that should give our users enough time to adapt to this change. The length of this deprecation period can vary, but around 4 months, or roughly two ESS releases, is a good starting point. +The `immutable` field will afterwards be actually removed from our API endpoint responses and our application after a deprecation period that should give our users enough time to adapt to this change. The length of this deprecation period can vary depending on adoption or other factors, but around 18 monthscan be a good starting point. Both the docs and the custom response header should communicate that the `immutable` field: -- has been replaced by the `external_source` field and users should rely on that new field onwards +- has been replaced by the `rule_source_type` and `external_source` fields and users should rely on that new field onwards - is maintained for backwards compatibility reasons only - will be removed after a specific date/release @@ -381,15 +407,17 @@ As part of the epic, we should move away from this practice and create new CRUD ### Migration strategy -Our migration strategy will consist of two distinct types of migration: a **migration on write** that will update the SO on Elasticsearch, and a **normalization on read**, which will transform legacy rules to the new schema **in memory** on read operation, before returning it as a response from an API endpoint. +Our migration strategy will consist of two distinct types of migration: a **migration on write** that will update the SO on Elasticsearch, and a **normalization on read**, which will transform legacy rules to the new schema **in memory** on read operations, before returning it as a response from an API endpoint. #### Normalization on read All endpoints that respond with a rule Saved Object, typed as `RuleResponse`, will perform **normalization on read**, which will transform legacy rules to the new schema **in memory** on read operation, before returning it as a response from an API endpoint. -This means that the endpoints will always respond with the rules with the new schema, while the actual rule might still be stored with the legacy schema in Elasticsearch, if it still has not been migrated-on-write. +This means that the endpoints will always respond with the rules with the new schema, while the actual rule saved object might still be stored with the legacy schema in Elasticsearch, if it still has not been migrated-on-write. + +The **normalization on read** will be carried out by a new `normalizePrebuiltSchemaOnRuleRead` normalization function. The `internalRuleToAPIResponse` method, which is used in our endpoints to convert a rule saved object as is stored in Elasticsearch to the `RuleResponse` type which is returned to the client, calls the `commonParamsCamelToSnake` methods to convert rule parameters that are common to all rule types to what's expected in `RuleResponse`. -The **normalization on read** will be carried out by a new `normalizePrebuiltSchemaOnRuleRead` normalization function. The `internalRuleToAPIResponse` method, which is used in our endpoints to convert a rule saved object as is stored in Elasticsearch to the `RuleResponse` type which is returned to the client, calls the `commonParamsCamelToSnake` methods to convert rule parameters that are common to all rule types to what's expected in `RuleResponse`. Inside this method, we will use `normalizePrebuiltSchemaOnRuleRead` to calculate the normalized values of `external_source` and `immutable`. +Inside this method, we will use `normalizePrebuiltSchemaOnRuleRead` to calculate the normalized values of `rule_source_type`, `external_source` and `immutable`. _Source: [x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/normalization/rule_converters.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/normalization/rule_converters.ts)_ @@ -421,6 +449,7 @@ _Source: x-pack/plugins/security_solution/server/lib/detection_engine/rule_manag interface OnReadNormalizationResult { immutable: IsRuleImmutable; external_source?: ExternalSourceAttributes; + rule_source_type: RuleSourceType } /** @@ -456,11 +485,13 @@ export const normalizePrebuiltSchemaOnRuleRead = ( * - If `external_source` does not exist, return the value of the params' `immutable` field. (Use case of Rules that have not yet been migrated on write.) */ const immutable = Boolean(ruleParams.external_source) || Boolean(ruleParams.immutable); + const rule_source_type = immutable ? 'external' : 'internal'; const external_source = getExternalSourceValueForRuleRead(ruleParams); return { immutable, external_source, + rule_source_type }; }; ``` @@ -526,7 +557,7 @@ All other type of actions should **not** perform migration-on-write: ### Technical implementation of migration-on-write -The logic for the migration of the rule saved objects, which means the determination of the `immutable` and `external_source` fields before writing to ES, might differ depending on the action being performed by the user. +The logic for the migration of the rule saved objects, which means the determination of the `immutable`, `rule_source_type` and `external_source` fields before writing to ES, might differ depending on the action being performed by the user. Let's see all possible use cases that will require migration-on-write, the endpoints that they apply to, and the expected resulting migrated field, based on the action and their input. @@ -562,6 +593,7 @@ The resulting values for `immutable` and `external_source` when calling these en Use case Current value of
external_source
+ Current value of
rule_source_type
Current value of
immutable
Any field diverges
from base version during update? Results @@ -569,7 +601,10 @@ The resulting values for `immutable` and `external_source` when calling these en - Migrating a custom rule (migrated or not yet) + Migrating a custom rule (not migrated yet) + +
undefined
+
undefined
@@ -578,7 +613,27 @@ The resulting values for `immutable` and `external_source` when calling these en
           {
-            immutable: false
+            immutable: false,
+            rule_source_type: 'internal'
+          }
+        
+ + + + Migrating a custom rule (already migrated) + +
undefined
+ + +
'internal'
+ +
false
+ N/A - Doesn't apply for custom rules + +
+          {
+            immutable: false,
+            rule_source_type: 'internal'
           }
         
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/model/rule_assets/prebuilt_rule_asset.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/model/rule_assets/prebuilt_rule_asset.ts index 191d8edcd3de50..ce9bf62d53a6b1 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/model/rule_assets/prebuilt_rule_asset.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/model/rule_assets/prebuilt_rule_asset.ts @@ -39,6 +39,6 @@ export const PrebuiltRuleAsset = BaseCreateProps.and(TypeSpecificCreateProps).an related_integrations: RelatedIntegrationArray.optional(), required_fields: RequiredFieldArray.optional(), setup: SetupGuide.optional(), - elasticUpdateDate: ElasticUpdateDate.optional(), + source_updated_at: ElasticUpdateDate.optional(), }) ); From f2f5ffb1d9dba2438458d66062f95a9689f36dac Mon Sep 17 00:00:00 2001 From: jpdjere Date: Mon, 19 Feb 2024 13:30:06 +0100 Subject: [PATCH 15/61] Refactor: Modified migration table and KQL filters to account for ruleSourceType --- .../docs/prebuilt_rules_customization_rfc.md | 51 ++++++++++--------- 1 file changed, 27 insertions(+), 24 deletions(-) diff --git a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md index 7d146d956c54b6..baf9dd028ea11d 100644 --- a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md +++ b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md @@ -591,7 +591,7 @@ The resulting values for `immutable` and `external_source` when calling these en - + @@ -601,7 +601,7 @@ The resulting values for `immutable` and `external_source` when calling these en - + @@ -613,14 +613,14 @@ The resulting values for `immutable` and `external_source` when calling these en - + @@ -632,44 +632,46 @@ The resulting values for `immutable` and `external_source` when calling these en - + + - + + - + + - + + - + + - + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Use caseMigration use case Current value of
external_source
Current value of
rule_source_type
Current value of
immutable
Migrating a custom rule (not migrated yet)Custom rule (not migrated yet)
undefined
           {
+            rule_source_type: 'internal',
             immutable: false,
-            rule_source_type: 'internal'
           }
         
Migrating a custom rule (already migrated)Custom rule (already migrated)
undefined
           {
+            rule_source_type: 'internal',
             immutable: false,
-            rule_source_type: 'internal'
           }
         
Migrating a non yet migrated prebuilt rule, no customizationsPrebuilt rule (not yet migrated, no customizations)
undefined
undefined
true
No
           {
+            rule_source_type: 'external',
             external_source: {
-              repoName: 'elastic_prebuilt',
               isCustomized: false,
               ...
             },
-            immutable: true
+            immutable: true,
           }
         
Migrating a non yet migrated prebuilt rule, with customizationsPrebuilt rule (not yet migrated, with customizations)
undefined
undefined
true
Yes
           {
+            rule_source_type: 'external',
             external_source: {
-              repoName: 'elastic_prebuilt',
               isCustomized: true,
               ...
             },
@@ -679,23 +681,23 @@ The resulting values for `immutable` and `external_source` when calling these en
       
Migrating a migrated non-customized prebuilt rule, no customizationsPrebuilt rule (already migrated, no customizations)
 
           {
-            repoName: 'elastic_prebuilt',
             isCustomized: false,
               ...
           }
           
'external'
true
No
           {
+            rule_source_type: 'external',
             external_source: {
-              repoName: 'elastic_prebuilt',
               isCustomized: false,
               ...
             },
@@ -705,7 +707,7 @@ The resulting values for `immutable` and `external_source` when calling these en
       
Migrating a migrated customized prebuilt rule, with customizationsPrebuilt rule (already migrated, with customizations)
 
           {
@@ -715,11 +717,13 @@ The resulting values for `immutable` and `external_source` when calling these en
           }
           
'external'
true
Yes
           {
+            rule_source_type: 'external',
             external_source: {
               repoName: 'elastic_prebuilt',
               isCustomized: true,
@@ -731,23 +735,23 @@ The resulting values for `immutable` and `external_source` when calling these en
       
Migrating a migrated customized prebuilt rule, no customizationsCustomized Prebuilt rule (already migrated, no new customizations)
 
           {
-            repoName: 'elastic_prebuilt',
             isCustomized: true,
               ...
           }
           
'external'
true
No
           {
+            rule_source_type: 'external',
             external_source: {
-              repoName: 'elastic_prebuilt',
               isCustomized: false,
               ...
             },
@@ -757,7 +761,7 @@ The resulting values for `immutable` and `external_source` when calling these en
       
Invalid case: Migrating a migrated non-customized prebuilt rule, with customizations.

`immutable` should never be false if `external_source` is defined. Migration should correct this inconsistency.
Invalid case: Migrating a migrated non-customized prebuilt rule, with customizations.

`immutable` should never be false if `rule_source_type` is 'internal' or `external_source` is defined. Migration should correct this inconsistency.
 
           {
@@ -767,13 +771,14 @@ The resulting values for `immutable` and `external_source` when calling these en
           }
           
'internal'
false
Yes
           {
+            rule_source_type: 'external',
             external_source: {
-              repoName: 'elastic_prebuilt',
               isCustomized: true,
               ...
             },
@@ -838,15 +843,13 @@ _See source of rule params keys: [x-pack/plugins/security_solution/common/detect
 
 Will need to update the `x-pack/plugins/security_solution/common/detection_engine/rule_management/rule_filtering.ts` file, where the `convertRulesFilterToKQL` method is defined. This method is used both in the frontend and in the serverside, and translates rule filter options to KQL filters that Elasticsearch can understand.
 
-Here, we need to update the KQL filters and the logic for fetching Elastic prebuilt and custom rules, relying on `external_rules` but with fallback to `immutable`:
+Here, we need to update the KQL filters and the logic for fetching Elastic prebuilt and custom rules, relying on `rule_source_type` but with fallback to `immutable`:
 
 _Source for `convertRulesFilterToKQL`: [x-pack/plugins/security_solution/common/detection_engine/rule_management/rule_filtering.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/common/detection_engine/rule_management/rule_filtering.ts)_
 
-In order to retrieve rules in which the `alert.attributes.params.external_source` field exists, we must rely instead on the existence of `alert.attributes.params.external_source.repo_name`. This is so because  KQL syntax does not allow searching for the existence of an object like `external_source` with the recommended syntax `alert.attributes.params.external_source: *`.
-
-But we can use the `external_source` field's `repo_name` subfield instead, which will always exist within the object (it is required) and replace the KQL filter for `alert.attributes.params.external_source.repo_name: *`. 
+In order to retrieve Elastic prebuilt rules, we can filter for rules in which `alert.attributes.params.rule_source_type` is `external`, with a fallback to rules in which `alert.attributes.params.immutable` is `true`, for rules which have not had their schema migrated and `rule_source_type` does not still exists for them.
 
-This will allow us to retrieve all rules that originate from an external source, or conditionally, from a specific source. For example, using the filter `alert.attributes.params.external_source.repo_name: elastic_prebuilt` should return only prebuilt rules created by Elastic.
+> In the future, we can further distinguish between `external` rules by their source origin. If we introduce a new field within `external_source` that defines their origin (such as `repo_name`, `repo_id`, or similar), we can further filter by Elastic prebuilt rules, or rules that are externally sourced from a repository handled by the user, etc.
 
 ### Rule Management endpoints
 

From e0ec4e078c9ee4a8ba4317201a2afc836e7c8642 Mon Sep 17 00:00:00 2001
From: jpdjere 
Date: Mon, 19 Feb 2024 14:15:30 +0100
Subject: [PATCH 16/61] Refactor: Started rewriting import logic

---
 .../docs/prebuilt_rules_customization_rfc.md  | 44 ++++++++++++++-----
 1 file changed, 33 insertions(+), 11 deletions(-)

diff --git a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md
index baf9dd028ea11d..de0b04605eb4f7 100644
--- a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md
+++ b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md
@@ -431,11 +431,12 @@ export const internalRuleToAPIResponse = (rule) => {
 };
 
 export const commonParamsCamelToSnake = (params: BaseRuleParams) => {
-  const { immutable, external_source } = normalizePrebuiltSchemaOnRuleRead(params);
+  const { immutable, external_source, rule_source_type } = normalizePrebuiltSchemaOnRuleRead(params);
 
   return {
     immutable,
     external_source,
+    rule_source_type
     // [... more object properties ...]
   };
 };
@@ -918,7 +919,7 @@ Additionally:
 
 - [**Review Rule Installation** - `POST /prebuilt_rules/installation/_review` (Internal)](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/review_rule_installation/review_rule_installation_route.ts)
 
-This endpoint uses the `convertPrebuiltRuleAssetToRuleResponse` method, which takes in a prebuilt rule asset and converts it to an object of type `RuleResponse`. This method has to be modified so that new prebuilt rules objects are returned by the endpoint with an `external_source` object and a legacy `immutable` value of `true`.
+This endpoint uses the `convertPrebuiltRuleAssetToRuleResponse` method, which takes in a prebuilt rule asset and converts it to an object of type `RuleResponse`. This method has to be modified so that new prebuilt rules objects are returned by the endpoint with a `rule_source_type` field of value `external`, an `external_source` object and a legacy `immutable` value of `true`.
 
 _Source: [x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/normalization/rule_converters.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/normalization/rule_converters.ts)_
 
@@ -936,8 +937,8 @@ export const convertPrebuiltRuleAssetToRuleResponse = (
   const ruleResponseSpecificFields = {
     // [... other prebuilt rule fields ...]
     immutable: true,
+    rule_source_type: 'external',
     external_source: {
-      repoName: 'elastic_prebuilt',
       isCustomized: false,
       sourceUpdatedAt: prebuiltRuleAsset.sourceUpdatedAt,
     },
@@ -1047,21 +1048,42 @@ The user will now be able to import both custom and prebuilt rules (including an
 
 We want to handle the case of importing both migrated and non-migrated rules via an `ndjson` file.
 
-Importing rules with `immutable: false` "should" be the only case for non-migrated rules (since `immutable: true` rules cannot currently be exported), but we should also handle the case of users manually modifying the values of rules in the `ndjson` file.
 
-If a user attempts to import a rule with `immutable: true` and missing `external_source` (or viceversa, a `external_source` field but no `immutable` field), then the most likely scenario is of a user trying to import Elastic prebuilt rules from a modified `ndjson` file. So we should consider these rules to be prebuilt and attempt to track them to rules in the Fleet package via their `rule_id` and continue to provide updates to them.
+If a user imports a prebuilt rule, Kibana should continue to track the rule asset from the `security_detection_engine` package if the `rule_id` matches. This means that a user will be able to update a previously exported prebuilt rule, visualize any diffs on any customized fields, and continue to receive updates on the rule.
 
-Given the requirements described above, the following table shows the behaviour of our endpoint for a combination of `external_source` and `immutable` fields in the `ndjson` file that a user attempts to import:
+To allow for importing of Elastic prebuilt rules, we will **not rely** in the `rule_source_type` or `external_source` fields (which are not part of the import endpoint parameters), but we will rather **calculate them dynamically based on the `rule_id` and `version` request parameters**.
 
-If a user imports a prebuilt rule (where either the `external_source` or `immutable` fields are `true`), it will continue to track the rule asset from the `security_detection_engine` package if the `rule_id` matches. This means that a user will be able to update a previously exported prebuilt rule, visualize any diffs on any customized fields, and continue to receive updates on the rule.
+The logic to importing a rule is as follows:
 
-With this migration strategy for the import endpoints we can guarantee backwards compatibility for all rules, and don't need to do additional changes to the export endpoints.
+First, read the import endpoint request parameters `rule_id` and `version`. These two are the two required parameters in the endpoint, while all other rule fields are optional.
+
+Secondly, check that the `security_detection_engine` Fleet package is installed and install it if it isn't. We will need the package to be installed to check if a rule that is being imported is an Elastic prebuilt rule.
+
+Then, using the `rule_id` and `version`, attempt to fetch the corresponding `security-rule` asset from ES. 
+
+**If a matching `rule_id` and `version` is found**, that means that the rule is an Elastic prebuilt rule, and we should therefore dynamically calculate the rule's `external_source` and `rule_source_type` fields.
+
+- `rule_source_type`: should always be `'external'` if rule is Elastic prebuilt.
+- `external_source`:
+  - `source_updated_at`: can be retrieved from the corresponding `security-rule` asset.
+  - `is_customized`: should be calculated based on the `security-rule` asset's field and the field rules that were part of the import request parameters. If any of them are different, i.e. have diverged from the base version, `is_customized` should be true.
+
+Finally, using the import payload, plus the rule's `security-rule` asset fields and the calculated `rule_source_type` and `external_source` fields, create the rule, or update it if already exists in Kibana.
 
-The `importRules` helper method that our import endpoint handler use rely on the already discussed `createRules` and the `patchRules` - when a rule is created from scratch (no `rule_id` match), and when a `rule_id` matches and a rule is overwritten, respectively.
+**If a matching `rule_id` is found, but the `version` is not found**, reject the import for that rule. Without a version, we cannot dynamically calculate `external_source`.
 
-Given that, when importing rules, we can be creating a custom rule or a prebuilt rule, we need to calculate and appropiately pass the `isPrebuilt` flag to the `createRules` method. The `importRules` helper thus needs to be modified so:
+**If a matching `rule_id` is NOT found**, that means that the rule is a custom rule:
+- `rule_source_type`: should be `internal`
+- `external_source`: doesn't need calculation.
 
-_Source: [x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/import/import_rules_utils.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/import/import_rules_utils.ts)_
+And we can finally create or updated an existing rule using the request payload and the calculated `rule_source_type` field.
+
+
+Given the requirements described above, the following table shows the behaviour of our endpoint for a combination of inputs and Kibana states:
+
+
+
+With this migration strategy for the import endpoints we can guarantee backwards compatibility for all rules, and don't need to do additional changes to the export endpoints.
 
 
 ### Handling the `version` parameter

From 28f5380d887d6ccfd9a4014c5674e058680092df Mon Sep 17 00:00:00 2001
From: jpdjere 
Date: Wed, 21 Feb 2024 12:13:26 +0100
Subject: [PATCH 17/61] Refactor: Rewrote all sections to account for
 'rule_source'

---
 .../rule_schema/common_attributes.gen.ts      |   37 +-
 .../rule_schema/common_attributes.schema.yaml |   44 +-
 .../model/rule_schema/rule_schemas.gen.ts     |    4 +-
 .../rule_schema/rule_schemas.schema.yaml      |    4 +-
 .../docs/prebuilt_rules_customization_rfc.md  | 1113 +++++++++++++----
 .../review_rule_upgrade_route.ts              |    1 -
 6 files changed, 921 insertions(+), 282 deletions(-)

diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/common_attributes.gen.ts b/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/common_attributes.gen.ts
index f812aa9d90af73..ce5bdcc7284d44 100644
--- a/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/common_attributes.gen.ts
+++ b/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/common_attributes.gen.ts
@@ -70,26 +70,41 @@ export type IsRuleImmutable = z.infer;
 export const IsRuleImmutable = z.boolean();
 
 /**
- * Determines whether the prebuilt rule has been customized by the user (i.e. any of its fields have been modified and diverge from the base value).
+ * Determines whether an external/prebuilt rule has been customized by the user (i.e. any of its fields have been modified and diverged from the base value).
  */
-export type IsPrebuiltRuleCustomized = z.infer;
-export const IsPrebuiltRuleCustomized = z.boolean();
+export type IsExternalRuleCustomized = z.infer;
+export const IsExternalRuleCustomized = z.boolean();
 
 /**
- * The date and time that the prebuilt rule was last updated by Elastic.
+ * The date and time that the external/prebuilt rule was last updated in its source repository.
  */
-export type ElasticUpdateDate = z.infer;
-export const ElasticUpdateDate = z.string().datetime();
+export type ExternalSourceUpdatedAt = z.infer;
+export const ExternalSourceUpdatedAt = z.string().datetime();
 
 /**
- * Property whose existence  determines whether the rule is an Elastic Prebuilt Rule that can receive upstream updates via Fleet. Contains information relating to prebuilt rules.
+ * Type of rule source for internally sourced rules, i.e. created within the Kibana apps.
  */
-export type Prebuilt = z.infer;
-export const Prebuilt = z.object({
-  isCustomized: IsPrebuiltRuleCustomized,
-  elasticUpdateDate: ElasticUpdateDate.optional(),
+export type InternalRuleSource = z.infer;
+export const InternalRuleSource = z.object({
+  type: z.literal('internal'),
 });
 
+/**
+ * Type of rule source for externally sourced rules, i.e. rules that have an external source, such as the Elastic Prebuilt rules repo.
+ */
+export type ExternalRuleSource = z.infer;
+export const ExternalRuleSource = z.object({
+  type: z.literal('external'),
+  is_customized: IsExternalRuleCustomized,
+  source_updated_at: ExternalSourceUpdatedAt.optional(),
+});
+
+/**
+ * Discriminated union that determines whether the rule is internally sourced (created within the Kibana app) or has an external source, such as the Elastic Prebuilt rules repo.
+ */
+export type RuleSource = z.infer;
+export const RuleSource = z.union([ExternalRuleSource, InternalRuleSource]);
+
 /**
  * Determines whether the rule is enabled.
  */
diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/common_attributes.schema.yaml b/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/common_attributes.schema.yaml
index 03c95676877d57..099f68c2f265d7 100644
--- a/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/common_attributes.schema.yaml
+++ b/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/common_attributes.schema.yaml
@@ -55,25 +55,47 @@ components:
       type: boolean
       description: '[DEPRECATION WARNING - This field is deprecated and will be removed in a future release. Use the prebuilt field to determine if a rule is an Elastic prebuilt rule or a custom rule.] - Determines whether the rule is immutable (i.e. cannot be modified by the user).'
 
-    IsPrebuiltRuleCustomized:
+    IsExternalRuleCustomized:
       type: boolean
-      description: Determines whether the prebuilt rule has been customized by the user (i.e. any of its fields have been modified and diverge from the base value).
+      description: Determines whether an external/prebuilt rule has been customized by the user (i.e. any of its fields have been modified and diverged from the base value).
 
-    ElasticUpdateDate:
+    ExternalSourceUpdatedAt:
       type: string
       format: date-time
-      description: The date and time that the prebuilt rule was last updated by Elastic.
+      description: The date and time that the external/prebuilt rule was last updated in its source repository.
 
-    Prebuilt:
+    InternalRuleSource:
+      description: Type of rule source for internally sourced rules, i.e. created within the Kibana apps.
       type: object
-      description: Property whose existence  determines whether the rule is an Elastic Prebuilt Rule that can receive upstream updates via Fleet. Contains information relating to prebuilt rules.
       properties:
-        isCustomized:
-          $ref: '#/components/schemas/IsPrebuiltRuleCustomized'
-        elasticUpdateDate:
-          $ref: '#/components/schemas/ElasticUpdateDate'
+        type:
+          type: string
+          enum:
+            - internal
+      required:
+        - type
+
+    ExternalRuleSource:
+      description: Type of rule source for externally sourced rules, i.e. rules that have an external source, such as the Elastic Prebuilt rules repo.
+      type: object
+      properties:
+        type:
+          type: string
+          enum:
+            - external
+        is_customized:
+          $ref: '#/components/schemas/IsExternalRuleCustomized'
+        source_updated_at:
+          $ref: '#/components/schemas/ExternalSourceUpdatedAt'
       required:
-        - isCustomized
+        - type
+        - is_customized
+
+    RuleSource:
+      description: Discriminated union that determines whether the rule is internally sourced (created within the Kibana app) or has an external source, such as the Elastic Prebuilt rules repo.
+      oneOf:
+        - $ref: '#/components/schemas/ExternalRuleSource'
+        - $ref: '#/components/schemas/InternalRuleSource'
 
     IsRuleEnabled:
       type: boolean
diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/rule_schemas.gen.ts b/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/rule_schemas.gen.ts
index 6a8585743d8f8d..374f6c646606b7 100644
--- a/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/rule_schemas.gen.ts
+++ b/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/rule_schemas.gen.ts
@@ -55,7 +55,7 @@ import {
   RuleObjectId,
   RuleSignatureId,
   IsRuleImmutable,
-  Prebuilt,
+  RuleSource,
   RelatedIntegrationArray,
   RequiredFieldArray,
   SetupGuide,
@@ -156,7 +156,7 @@ export const ResponseFields = z.object({
   id: RuleObjectId,
   rule_id: RuleSignatureId,
   immutable: IsRuleImmutable,
-  prebuilt: Prebuilt.optional(),
+  rule_source: RuleSource.optional(),
   updated_at: z.string().datetime(),
   updated_by: z.string(),
   created_at: z.string().datetime(),
diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/rule_schemas.schema.yaml b/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/rule_schemas.schema.yaml
index 2576bc2021fbaa..a6457f12cde7b7 100644
--- a/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/rule_schemas.schema.yaml
+++ b/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/rule_schemas.schema.yaml
@@ -161,8 +161,8 @@ components:
           $ref: './common_attributes.schema.yaml#/components/schemas/RuleSignatureId'
         immutable:
           $ref: './common_attributes.schema.yaml#/components/schemas/IsRuleImmutable'
-        prebuilt:
-          $ref: './common_attributes.schema.yaml#/components/schemas/Prebuilt'
+        rule_source:
+          $ref: './common_attributes.schema.yaml#/components/schemas/RuleSource'
         updated_at:
           type: string
           format: date-time
diff --git a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md
index de0b04605eb4f7..ece47e93d57ecb 100644
--- a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md
+++ b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md
@@ -36,65 +36,73 @@ You can create it by navigating to the directory of the markdown file and runnin
 pandoc prebuilt_rules_customization_rfc.md --toc --toc-depth=6 --wrap=none  -s -o output.md
 ```
 
-- [Necessary rule schema changes](#necessary-rule-schema-changes)
-  - [`external_source` and `immutable` fields](#prebuilt-and-immutable-fields)
-    - [`isCustomized` subfield](#iscustomized-subfield)
-    - [`elasticUpdateDate` subfield](#elasticupdatedate-subfield)
-  - [Changes needed in rule schema](#changes-needed-in-rule-schema)
-    - [API schema](#api-schema)
-    - [Internal rule schema](#internal-rule-schema)
-  - [Deprecating the `immutable` field](#deprecating-the-immutable-field)
-- [Mapping changes](#mapping-changes)
-- [Plan for carrying out migrations of rule SOs](#plan-for-carrying-out-migrations-of-rule-sos)
-  - [Context](#context)
-  - [Migration strategy](#migration-strategy)
-    - [Migration on write](#migration-on-write)
-      - [Rule Management endpoints that should include migration-on-write logic](#rule-management-endpoints-that-should-include-migration-on-write-logic)
-    - [Normalization on read](#normalization-on-read)
-      - [Rule Management endpoints that will perform normalization-on-read](#rule-management-endpoints-that-will-perform-normalization-on-read)
-  - [Technical implementation of migration-on-write](#technical-implementation-of-migration-on-write)
-    - [`migratePrebuiltSchemaOnRuleCreation`](#migrateprebuiltschemaonrulecreation)
-      - [`convertCreateAPIToInternalSchema` and `createRules`](#convertcreateapitointernalschema-and-createrules)
-      - [`duplicateRule`](#duplicaterule)
-    - [`migratePrebuiltSchemaOnRuleUpdate`](#migrateprebuiltschemaonruleupdate)
-      - [`convertPatchAPIToInternalSchema` and `patchRules`](#convertpatchapitointernalschema-and-patchrules)
-      - [`updateRules`](#updaterules)
-    - [`migratePrebuiltSchemaOnRuleBulkEdit`](#migrateprebuiltschemaonrulebulkedit)
-- [Other endpoints and utilities that will need to be adapted to the new schema](#other-endpoints-and-utilities-that-will-need-to-be-adapted-to-the-new-schema)
-  - [Utilities](#utilities)
-    - [KQL filters and the `convertRulesFilterToKQL` method](#kql-filters-and-the-convertrulesfiltertokql-method)
-  - [Rule Management endpoints](#rule-management-endpoints)
-  - [Prebuilt Rules endpoints](#prebuilt-rules-endpoints)
-  - [Rule monitoring endpoints](#rule-monitoring-endpoints)
-  - [Rule Execution Logs](#rule-execution-logs)
-- [Exporting and importing rules](#exporting-and-importing-rules)
-  - [Exporting rules](#exporting-rules)
-  - [Importing rules](#importing-rules)
-  - [Handling the `version` parameter](#handling-the-version-parameter)
-- [Customizing Prebuilt Rules](#customizing-prebuilt-rules)
-  - [Endpoints](#endpoints)
-    - [Changes needed to endpoints](#changes-needed-to-endpoints)
-      - [Update Rule - `PUT /rules`](#update-rule---put-rules)
-      - [Patch Rule - `PATCH /rules`](#patch-rule---patch-rules)
-      - [Bulk Patch Rules - `PATCH /rules/_bulk_update`](#bulk-patch-rules---patch-rules_bulk_update)
-      - [Bulk Update Rules - `PUT /rules/_bulk_update`](#bulk-update-rules---put-rules_bulk_update)
-      - [Bulk Actions - `POST /rules/_bulk_action`](#bulk-actions---post-rules_bulk_action)
-    - [Updating the `customized` field](#updating-the-customized-field)
-  - [In the UI](#in-the-ui)
-    - [Via the Rule Edit Page](#via-the-rule-edit-page)
-    - [Via Bulk Actions](#via-bulk-actions)
-    - [Via the Rules Details Page](#via-the-rules-details-page)
-    - [Via the Shared Exception Lists page](#via-the-shared-exception-lists-page)
-    - [Via the Stack Management \> Rules UI](#via-the-stack-management-rules-ui)
-- [List of things to fix (create tickets)](#list-of-things-to-fix-create-tickets)
-  - [Rule fields](#rule-fields)
-- [Updating Prebuilt Rules](#updating-prebuilt-rules)
-  - [Changes to upgrade `_review` and `_perform` endpoints](#changes-to-upgrade-_review-and-_perform-endpoints)
-  - [Rule field diff algorithms](#rule-field-diff-algorithms)
-- [Changes in UI](#changes-in-ui)
-- [Scenarios for bulk accepting updates](#scenarios-for-bulk-accepting-updates)
-- [Marking rules (and their fields) as customized](#marking-rules-and-their-fields-as-customized)
-- [Other open questions](#other-open-questions)
+-   [RFC: Prebuilt Rules Customization](#rfc-prebuilt-rules-customization)
+    -   [Table of Contents](#table-of-contents)
+    -   [Note about scope of RFC](#note-about-scope-of-rfc)
+    -   [Necessary rule schema changes](#necessary-rule-schema-changes)
+        -   [`rule_source` field](#rule_source-field)
+        -   [Deprecating the `immutable` field](#deprecating-the-immutable-field)
+        -   [Subfields in the `rule_source` field](#subfields-in-the-rule_source-field)
+            -   [`type` subfield](#type-subfield)
+            -   [`is_customized` subfield](#is_customized-subfield)
+            -   [`source_updated_at` subfield](#source_updated_at-subfield)
+        -   [Changes needed in rule schema](#changes-needed-in-rule-schema)
+            -   [API schema](#api-schema)
+                -   [API request and response rule schema](#api-request-and-response-rule-schema)
+                -   [Rule Import request schema](#rule-import-request-schema)
+            -   [Internal rule schema](#internal-rule-schema)
+                -   [Prebuilt Rule asset schema](#prebuilt-rule-asset-schema)
+        -   [Deprecating the `immutable` field](#deprecating-the-immutable-field-1)
+    -   [Mapping changes](#mapping-changes)
+    -   [Plan for carrying out migrations of rule SOs](#plan-for-carrying-out-migrations-of-rule-sos)
+        -   [Context](#context)
+        -   [Problem with tightly coupled logic in our endpoints](#problem-with-tightly-coupled-logic-in-our-endpoints)
+        -   [Migration strategy](#migration-strategy)
+            -   [Normalization on read](#normalization-on-read)
+                -   [Rule Management endpoints that will perform normalization-on-read](#rule-management-endpoints-that-will-perform-normalization-on-read)
+            -   [Migration on write](#migration-on-write)
+                -   [Rule Management endpoints that should include migration-on-write logic](#rule-management-endpoints-that-should-include-migration-on-write-logic)
+        -   [Technical implementation of migration-on-write](#technical-implementation-of-migration-on-write)
+            -   [Updating and upgrading rules](#updating-and-upgrading-rules)
+            -   [Bulk editing rules](#bulk-editing-rules)
+    -   [Endpoints and utilities that will need to be adapted to the new schema](#endpoints-and-utilities-that-will-need-to-be-adapted-to-the-new-schema)
+        -   [Utilities](#utilities)
+            -   [KQL filters and the `convertRulesFilterToKQL` method](#kql-filters-and-the-convertrulesfiltertokql-method)
+        -   [Rule Management endpoints](#rule-management-endpoints)
+        -   [Prebuilt Rules endpoints](#prebuilt-rules-endpoints)
+        -   [Rule monitoring endpoints](#rule-monitoring-endpoints)
+        -   [Rule Execution Logs](#rule-execution-logs)
+    -   [Exporting and importing rules](#exporting-and-importing-rules)
+        -   [Exporting rules](#exporting-rules)
+        -   [Importing rules](#importing-rules)
+        -   [Handling the `version` parameter](#handling-the-version-parameter)
+    -   [Customizing Prebuilt Rules](#customizing-prebuilt-rules)
+        -   [Endpoints](#endpoints)
+            -   [Changes needed to endpoints](#changes-needed-to-endpoints)
+                -   [Update Rule - `PUT /rules`](#update-rule---put-rules)
+                -   [Patch Rule - `PATCH /rules`](#patch-rule---patch-rules)
+                -   [Bulk Patch Rules - `PATCH /rules/_bulk_update`](#bulk-patch-rules---patch-rules_bulk_update)
+                -   [Bulk Update Rules - `PUT /rules/_bulk_update`](#bulk-update-rules---put-rules_bulk_update)
+                -   [Bulk Actions - `POST /rules/_bulk_action`](#bulk-actions---post-rules_bulk_action)
+            -   [Updating the `is_customized` field](#updating-the-is_customized-field)
+        -   [In the UI](#in-the-ui)
+            -   [Via the Rule Edit Page](#via-the-rule-edit-page)
+            -   [Via Bulk Actions](#via-bulk-actions)
+            -   [Via the Rules Details Page](#via-the-rules-details-page)
+            -   [Via the Shared Exception Lists page](#via-the-shared-exception-lists-page)
+            -   [Via the Stack Management \> Rules UI](#via-the-stack-management-rules-ui)
+    -   [List of things to fix (create tickets)](#list-of-things-to-fix-create-tickets)
+        -   [Rule fields](#rule-fields)
+    -   [Upgrading Prebuilt Rules](#upgrading-prebuilt-rules)
+        -   [Changes to upgrade `_review` endpoint](#changes-to-upgrade-_review-endpoint)
+            -   [Concrete field diff algorithm by type](#concrete-field-diff-algorithm-by-type)
+                -   [String fields](#string-fields)
+        -   [Changes to upgrade `_perform` endpoints](#changes-to-upgrade-_perform-endpoints)
+        -   [Rule field diff algorithms](#rule-field-diff-algorithms)
+    -   [Changes in UI](#changes-in-ui)
+    -   [Scenarios for bulk accepting updates](#scenarios-for-bulk-accepting-updates)
+    -   [Marking rules (and their fields) as customized](#marking-rules-and-their-fields-as-customized)
+    -   [Other open questions](#other-open-questions)
 
 ## Note about scope of RFC
 
@@ -108,63 +116,63 @@ During this RFC, we will explicitly refer to case of Elastic prebuilt rules, but
 
 ## Necessary rule schema changes
 
-In order to support the customization of Elastic Prebuilt Rules, we need to modify our rule schema. This involves introducing the new top level fields: `rule_source_type` and the nested `external_source` field, as well deprecating the `immutable` field.
+In order to support the customization of Elastic Prebuilt Rules, we need to modify our rule schema. This involves introducing the new top level field: the nested `rule_source` field, as well deprecating the `immutable` field.
 
 ```ts
 // PSEUDOCODE - see complete schema in detail below
 {
-  rule_source_type: 'external' | 'internal',
-  external_source?: {
+  rule_source: {
+    type: 'external'
     is_customized: boolean;
     source_updated_at?: Date;
+  } | {
+    type: 'internal'
   },
 }
 ```
 
-### `rule_source_type` field
 
-The `rule_source_type` field will be a required top-level string field that can take two values: `internal` or `external`.
+### `rule_source` field
 
-Rules with value of `internal` are rules generated internally in the Kibana application and which don't have an external origin outside of it.
+The `rule_source` field will be a required top-level object field in our rule schema that will be a discriminated union of two types: `'internal'` and `'external'`.
 
-Rules with value of `external` are rules who have an external origin or source. Elastic prebuilt rules are a case of `external` rule, with the `detection-rules` repository handled by the TRaDE team being their external source origin.
+Rules with `rule_source` of type `internal` are rules generated internally in the Kibana application and which don't have an external origin outside of it.
 
+Rules with `rule_source` of type `external` are rules who have an external origin or source. Elastic prebuilt rules are a case of `external` rule, with the `detection-rules` repository handled by the TRaDE team being their external source origin.
 
-### `external_source` field
+This also means that a rule with this type of `rule_source` will determine that the rule is an Elastic Prebuilt Rule that can receive upstream updates via Fleet. This field is intented to partly replace the currently existing `immutable` field, which is used today for the same purpose, but -as its name indicates- also currently determines if a rule's fields can be modified/customized.
 
-The `external_source` field will be a top-level object field in our rule schema that will contain subfields with information relating to Elastic Prebuilt rules (or rules with an external source, in general).
-
-It will be an optional field, which will only be present for Elastic prebuilt rules (i.e. rules that are externally sourced).
-
-The field will only exist when `rule_source_type` has a value of `external`, and should never be defined for rules with `rule_source_type` with value of `internal`.
-
-This means that its presence in a rule object will determine whether the rule is an Elastic Prebuilt Rule that can receive upstream updates via Fleet. This field is intented to partly replace the currently existing `immutable` field, which is used today for the same purpose, but -as its name indicates- also currently determines if a rule's fields can be modified/customized.
+As seen in the schema, when the `rule_source` has type `'external'`, the object can contain two other subfields as well, `is_customized` and `source_updated_at`, explained below. If the object has type `'internal'`, no other fields should be present (subject to change in the future).
 
 ### Deprecating the `immutable` field
 
 In the current application's state, rules with `immutable: false` are rules which are not Elastic Prebuilt Rules, i.e. custom rules, and can be modified. Meanwhile, `immutable: true` rules are Elastic Prebuilt Rules, created by the TRaDE team, distributed via the `security_detection_engine` Fleet package, and cannot be modified once installed.
 
-When successfully implemented, the `external_source` field, together with `rule_source_type` field, should replace the `immutable` field as a flag to mark Elastic prebuilt rules, but with one difference: the `external_source` field will determine if the rule is an Elastic Prebuilt Rule or not, but now all rules will be customizable by the user in Kibana, i.e. independently of the existence (or absence) of `external_source`.
+When successfully implemented, the `rule_source` field should replace the `immutable` field as a mechanism to mark Elastic prebuilt rules, but with one difference: the `rule_source` field will determine if the rule is an Elastic Prebuilt Rule or not, but now all rules will be customizable by the user in Kibana, i.e. independently of the existence (or absence) of `rule_source`.
 
-Because of this difference in the behaviour of the `external_source` and `immutable` fields, we feel that a field called `immutable` will lose its meaning over time and become confusing, especially for consumers of the API who interact directly with the field name. That's why we want to eventually deprecate it and fully replace it with `external_source`.
+Because of this difference in the behaviour of the `rule_source` and `immutable` fields, we feel that a field called `immutable` will lose its meaning over time and become confusing, especially for consumers of the API who interact directly with the field name. That's why we want to eventually deprecate it and fully replace it with `rule_source`.
 
-To ensure backward compatibility and avoid breaking changes, we will deprecate the `immutable` field but keep it within the rule schema, asking our users to stop relying on this field in Detection API responses. During the migration period, we want to keep the value of the `immutable` field in sync with the`rule_source_type` and `external_source` fields: this means that for all rules that have a `immutable` value of `true`, the `rule_source_type` will be `external` and the `external_source` field will always exist. Viceversa, rules with `immutable: false` will have a `rule_source_type` of `internal` and will not have a `external_source` field.
+To ensure backward compatibility and avoid breaking changes, we will deprecate the `immutable` field but keep it within the rule schema, asking our users to stop relying on this field in Detection API responses. During the migration period, we want to keep the value of the `immutable` field in sync with the `rule_source` fields: this means that for all rules that have a `immutable` value of `true`, the `rule_source` field will always be of type `'external'`. Viceversa, rules with `immutable: false` will have a `rule_source` field of type `'internal'`.
 
 This means, however, that there will be a change in behaviour of the `immutable` field: with the release of the feature, rules with the `immutable: true` value will now be customizable by the user, which is not the current behaviour.
 
-### Subfields in the `external_source` field
+### Subfields in the `rule_source` field
+
+In this first phase, the `rule_source` will conditionally contain three subfields: the desciminant `type`, and the `is_customized` and `source_updated_at` values, only present when `type` is `'external'`.
 
-In this first phase, the `external_source` will contain two subfields: `is_customized` and `source_updated_at`.
+#### `type` subfield
+
+The `type` subfield serves as the discriminat to the disciminated union field `rule_source` and can take two values, as explained above: `'internal'` and `'external'`.
 
 #### `is_customized` subfield
 
-The `is_customized` field will be a boolean field that determines whether a Prebuilt Rule has been customized by the user, i.e. if any of its fields have been modified and diverged from the base version of the rule, which is the version that is installed from the Prebuilt Rules `security_detection_engine` Fleet package.
+The `is_customized` field will be a boolean field that determines whether an external/Prebuilt Rule has been customized by the user, i.e. if any of its fields have been modified and diverged from the base version of the rule, which is the version that is installed from the Prebuilt Rules `security_detection_engine` Fleet package.
 
-This means that the `is_customized` subfield only makes sense and will be used for prebuilt rules, or rules whose `external_source` field exists. It is therefore a subfield of the `external_source` field.
+This means that the `is_customized` subfield only makes sense and will be used for prebuilt rules, or rules whose `rule_source` field is of type `'external'`.
 
-For prebuilt rules, the `external_source.is_customized` value will be initially set to `false` when a brand new rule is installed, but will be rewritten to `true` if a rule's field is edited and diverges from the value from the base version of the rule.
+For prebuilt rules, the `rule_source.is_customized` value will be initially set to `false` when a brand new rule is installed, but will be rewritten to `true` if a rule's field is edited and diverges from the value from the base version of the rule.
 
-See section [Calculating the `isCustomized` flag]()
+See section [Updating the `isCustomized` flag](#updating-the-is_customized-field)
 
 #### `source_updated_at` subfield
 
@@ -182,9 +190,9 @@ This means that we need to differentiate between changes to the internal rule sc
 
 ##### API request and response rule schema
 
-**In the API schema** the `rule_source_type` will be required, but the `external_source` field will be optional, as it will exist for Elastic prebuilt rules, but won't for custom rules. 
+**In the API schema** the `rule_source` will be a required, as it will allow us to differentiate between Elastic prebuilt rules, and custom rules. 
 
-Notice, as well, that `immutable` and `external_source` will continue to be part **only of the API response schema**, and never form part of the **request parameters**.
+Notice, as well, that `immutable` and `rule_source` will continue to be part **only of the API response schema**, and never form part of the **request parameters**.
 
 The OpenAPI schema will need to be modified so:
 
@@ -202,28 +210,43 @@ IsExternalRuleCustomized:
   type: boolean
   description: Determines whether an external/prebuilt rule has been customized by the user (i.e. any of its fields have been modified and diverged from the base value).
 
-SourceUpdatedAt:
+ExternalSourceUpdatedAt:
   type: string
   format: date-time
   description: The date and time that the external/prebuilt rule was last updated in its source repository.
 
-ExternalSourceAttributes:
+InternalRuleSource:
+  description: Type of rule source for internally sourced rules, i.e. created within the Kibana apps.
+  type: object
+  properties:
+    type:
+      type: string
+      enum:
+        - internal
+  required:
+    - type
+
+ExternalRuleSource:
+  description: Type of rule source for externally sourced rules, i.e. rules that have an external source, such as the Elastic Prebuilt rules repo.
   type: object
-  description: Property whose existence determines whether the rule is an externally sourced rule. Contains information relating to externally sourced rules. Elastic Prebuilt rules are a specific case of externally sourced rules.
   properties:
+    type:
+      type: string
+      enum:
+        - external
     is_customized:
       $ref: '#/components/schemas/IsExternalRuleCustomized'
     source_updated_at:
-      $ref: '#/components/schemas/SourceUpdatedAt'
+      $ref: '#/components/schemas/ExternalSourceUpdatedAt'
   required:
-    - isCustomized
-
-RuleSourceType:
-  description: Indicates whether the rules is internally sourced (created within the Kibana app) or has an external source, such as the Elastic Prebuilt rules repo.
-  type: string
-  enum:
-    - internal
-    - external
+    - type
+    - is_customized
+
+RuleSource:
+  description: Discriminated union that determines whether the rule is internally sourced (created within the Kibana app) or has an external source, such as the Elastic Prebuilt rules repo.
+  oneOf:
+    - $ref: '#/components/schemas/ExternalRuleSource'
+    - $ref: '#/components/schemas/InternalRuleSource'
 #  [... file continues below ...]
 ```
 
@@ -241,13 +264,10 @@ ResponseFields:
       $ref: './common_attributes.schema.yaml#/components/schemas/RuleSignatureId'
     immutable:
       $ref: './common_attributes.schema.yaml#/components/schemas/IsRuleImmutable'
-    external_source:
-      $ref: './common_attributes.schema.yaml#/components/schemas/ExternalSourceAttributes'
-    rule_source_type:
-      $ref: './common_attributes.schema.yaml#/components/schemas/RuleSourceType'
+    rule_source:
+      $ref: './common_attributes.schema.yaml#/components/schemas/RuleSource'
     #  [...  more response fields ...]
   required:
-    # notice `external_source` is not required
     - id
     - rule_id
     - immutable
@@ -256,7 +276,7 @@ ResponseFields:
     - created_at
     - created_by
     - revision
-    - rule_source_type
+    - rule_source
 #  [... file continues below...]
 ```
 
@@ -266,11 +286,11 @@ We also need to modify the `RuleToImport` schema, since now we will be allowing
 
 Currently, `RuleToImport` optionally accepts the `immutable` param, but rejects validation if its value is set to anything else than `false` - since we don't currently support importing prebuilt rules. 
 
-We will be changing the mechanism for importing rules so that, besides the `rule_id`, the `version` of the rule is also a required parameter. These two parameters will be used to determine if the rule is prebuilt or not, and dynamically calculate the `external_source` and `rule_source_type` during import.
+We will be changing the mechanism for importing rules so that, besides the `rule_id`, the `version` of the rule is also a required parameter. These two parameters will be used to determine if the rule is prebuilt or not, and dynamically calculate `rule_source` during import.
 
 See the detailed explanation for this mechanism in the [Exporting and importing rules](#exporting-and-importing-rules) sections.
 
-The `immutable` and `external_source` fields will be ignored if passed in the request payload.
+The `immutable` and `rule_source` fields will be ignored if passed in the request payload.
 
 _Source: [x-pack/plugins/security_solution/common/api/detection_engine/rule_management/import_rules/rule_to_import.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/import_rules/rule_to_import.ts)_
 
@@ -296,7 +316,7 @@ export const RuleToImport = BaseCreateProps.and(TypeSpecificCreateProps).and(
 
 #### Internal rule schema
 
-**The internal rule schema** needs to represent that the new `ruleSourceType` and `externalSource` field may not always exist, so both need to be optional.
+**The internal rule schema** needs to represent that the new `ruleSource` field may not always exist, so both need to be optional.
 
 _Source: [x-pack/plugins/security_solution/server/lib/detection_engine/rule_schema/model/rule_schemas.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_schema/model/rule_schemas.ts)_
 
@@ -306,24 +326,23 @@ export const BaseRuleParams = z.object({
   // [...]
 
   immutable: IsRuleImmutable,
-  externalSource: ExternalSourceAttributes.transform(camelize).optional(),
-  ruleSourceType: RuleSourceType.optional()
+  ruleSource: RuleSource.transform(camelize).optional(),
   // [...]
 });
 ```
 
-> Notice that in the internal schema we cannot simply reuse the `ExternalSourceAttributes` attribute defined for the API schema, since it should have CamelCase and the API schema uses snake_case. We need to apply a transformation to our Zod type. See this [issue](https://github.com/colinhacks/zod/issues/486#issuecomment-1567296747).
+> Notice that in the internal schema we cannot simply reuse the `RuleSource` attribute defined for the API schema, since it should have CamelCase and the API schema uses snake_case. We need to apply a transformation to our Zod type. See this [issue](https://github.com/colinhacks/zod/issues/486#issuecomment-1567296747).
 
 In the internal rule schema, there are two additional important reasons why we need to make sure that these two fields optional:
 
-- When rules are executed, a call to the method `validateRuleTypeParams` is done, which is a method that validates the passed rule's parameters using the validators defined in `x-pack/plugins/security_solution/server/lib/detection_engine/rule_types`, within each of the rule query types files (for [EQL rules](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/eql/create_eql_alert_type.ts#L27), for example). The validation is done based on the internal rule schema `BaseRulesParams` displayed above. Having `ruleSourceType` or `externalSource` as required fields would cause custom rules or prebuilt rules that haven't had their schema migrated to fail during runtime.
+- When rules are executed, a call to the method `validateRuleTypeParams` is done, which is a method that validates the passed rule's parameters using the validators defined in `x-pack/plugins/security_solution/server/lib/detection_engine/rule_types`, within each of the rule query types files (for [EQL rules](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/eql/create_eql_alert_type.ts#L27), for example). The validation is done based on the internal rule schema `BaseRulesParams` displayed above. Having `ruleSource` as required field would cause custom rules or prebuilt rules that haven't had their schema migrated to fail during runtime.
 - The Rule Client `update` method also calls the `validateRuleTypeParams` to validate the rule's params. Since the Rule Client's `update` method is used in our endpoint handlers, such as and `/rules/patch` and `/_bulk_actions`, these would fail when executed against a payload of custom rule.
 
 ##### Prebuilt Rule asset schema
 
 The `PrebuiltRuleAsset` type needs to be updated to include the new `source_updated_at` date that will be progressively shipped with new versions of rules in the Elastic Prebuilt Rules package.
 
-Notice that this field will be a **top-level field in the Prebuilt Rule asset** schema, but will be part of the `external_source` field in the API rule schema and internal rule schema.
+Notice that this field will be a **top-level field in the Prebuilt Rule asset** schema, but will be part of the `rule_source` field in the API rule schema and internal rule schema.
 
 _Source: [x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/model/rule_assets/prebuilt_rule_asset.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/model/rule_assets/prebuilt_rule_asset.ts)_
 
@@ -342,7 +361,7 @@ export const PrebuiltRuleAsset = BaseCreateProps.and(TypeSpecificCreateProps).an
 
 ### Deprecating the `immutable` field
 
-In order to mark the `immutable` field as deprecated, and making sure that our application and API users are aware that the field has been deprecated and replaced by the `external_source` field, we will communicate this change in three ways:
+In order to mark the `immutable` field as deprecated, and making sure that our application and API users are aware that the field has been deprecated and replaced by the `rule_source` field, we will communicate this change in three ways:
 
 1. via updates to the documentation of all endpoints that return `RuleResponse` types
 2. via a deprecation warning in the OpenAPI schema, as detailed above
@@ -352,7 +371,7 @@ The `immutable` field will afterwards be actually removed from our API endpoint
 
 Both the docs and the custom response header should communicate that the `immutable` field:
 
-- has been replaced by the `rule_source_type` and `external_source` fields and users should rely on that new field onwards
+- has been replaced by the `rule_source` field and users should rely on that new field onwards
 - is maintained for backwards compatibility reasons only
 - will be removed after a specific date/release
 
@@ -415,9 +434,9 @@ All endpoints that respond with a rule Saved Object, typed as `RuleResponse`, wi
 
 This means that the endpoints will always respond with the rules with the new schema, while the actual rule saved object might still be stored with the legacy schema in Elasticsearch, if it still has not been migrated-on-write.
 
-The **normalization on read** will be carried out by a new `normalizePrebuiltSchemaOnRuleRead` normalization function. The `internalRuleToAPIResponse` method, which is used in our endpoints to convert a rule saved object as is stored in Elasticsearch to the `RuleResponse` type which is returned to the client, calls the `commonParamsCamelToSnake` methods to convert rule parameters that are common to all rule types to what's expected in `RuleResponse`. 
+The **normalization on read** will be carried out by a new `normalizeRuleSourceSchemaOnRuleRead` normalization function. The `internalRuleToAPIResponse` method, which is used in our endpoints to convert a rule saved object as is stored in Elasticsearch to the `RuleResponse` type which is returned to the client, calls the `commonParamsCamelToSnake` methods to convert rule parameters that are common to all rule types to what's expected in `RuleResponse`. 
 
-Inside this method, we will use `normalizePrebuiltSchemaOnRuleRead` to calculate the normalized values of `rule_source_type`, `external_source` and `immutable`.
+Inside this method, we will use `normalizeRuleSourceSchemaOnRuleRead` to calculate the normalized values of `rule_source` and `immutable`.
 
 _Source: [x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/normalization/rule_converters.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/normalization/rule_converters.ts)_
 
@@ -431,48 +450,48 @@ export const internalRuleToAPIResponse = (rule) => {
 };
 
 export const commonParamsCamelToSnake = (params: BaseRuleParams) => {
-  const { immutable, external_source, rule_source_type } = normalizePrebuiltSchemaOnRuleRead(params);
+  const { immutable, rule_source } = normalizeRuleSourceSchemaOnRuleRead(params);
 
   return {
     immutable,
-    external_source,
-    rule_source_type
+    rule_source,
     // [... more object properties ...]
   };
 };
 ```
 
-And the `normalizePrebuiltSchemaOnRuleRead` can be defined so:
+And the `normalizeRuleSourceSchemaOnRuleRead` can be defined so:
 
 _Source: x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/normalization/prebuilt_rule_schema_migrations.ts_ (New file)
 
 ```ts
 interface OnReadNormalizationResult {
   immutable: IsRuleImmutable;
-  external_source?: ExternalSourceAttributes;
-  rule_source_type: RuleSourceType
+  rule_source: RuleSource
 }
 
 /**
- * To calculate `external_source`:
- * - Use `external_source` field  if already exists in the internal rule object params.
+ * To calculate `rule_source`:
+ * - Use `rule_source` field  if already exists in the internal rule object params.
  * - If it does not exist, check the value `immutable` from the rules param:
- *   - if it is `true`, create a new `external_source` object, with `isCustomized` set to `false` and `repoNam` set to `elastic_prebuilt` (Use case of external_source rules that have not been yet migrated-on-write)
+ *   - if it is `true`, create a new `rule_source` object, with `isCustomized` set to `false` and `repoNam` set to `elastic_prebuilt` (Use case of rule_source rules that have not been yet migrated-on-write)
  *   - otherwise, the field should be `undefined` (use case of custom rules).
  */
-const getExternalSourceValueForRuleRead = (ruleParams: BaseRuleParams): ExternalSourceAttributes | undefined => {
-  if (ruleParams.external_source) {
-    return ruleParams.external_source;
+const getRuleSourceValueForRuleRead = (ruleParams: BaseRuleParams): RuleSource | undefined => {
+  if (ruleParams.rule_source) {
+    return ruleParams.rule_source;
   }
 
   if (ruleParams.immutable) {
     return {
-      repoName: 'elastic_prebuilt'
+      type: 'external'
       isCustomized: false,
     };
   }
 
-  return undefined;
+  return {
+    type: 'internal'
+  };
 };
 
 export const normalizePrebuiltSchemaOnRuleRead = (
@@ -481,18 +500,17 @@ export const normalizePrebuiltSchemaOnRuleRead = (
 
 /**
  * To calculate `immutable`:
- * - Checks if the `external_source` field exists in the rule's parameters.
- *   - If `external_source` exists, sets `immutable` to `true`. (Use case of Rules that have already been migrated-on-write)
- *   - If `external_source` does not exist, return the value of the params' `immutable` field. (Use case of Rules that have not yet been migrated on write.)
+ * - Checks if the `rule_source` field exists in the rule's parameters.
+ *   - If `rule_source` exists and its type is external, sets `immutable` to `true`. (Use case of Rules that have already been migrated-on-write)
+ *   - If `rule_source` does not exist, return the value of the params' `immutable` field. (Use case of Rules that have not yet been migrated on write.)
  */
-  const immutable = Boolean(ruleParams.external_source) || Boolean(ruleParams.immutable);
-  const rule_source_type = immutable ? 'external' : 'internal';
-  const external_source = getExternalSourceValueForRuleRead(ruleParams);
+  const isRuleSourceExternal = ruleParams.rule_source && ruleParams.rule_source.type === 'external';
+  const immutable = Boolean(isRuleSourceExternal) || Boolean(ruleParams.immutable);
+  const rule_source = getRuleSourceValueForRuleRead(ruleParams);
 
   return {
     immutable,
-    external_source,
-    rule_source_type
+    rule_source,
   };
 };
 ```
@@ -543,7 +561,7 @@ For the **bulk edit** action, we can take advantage of the `ruleParamsModifier`
 
 For the **duplicate** rule action:
 
-Since we will be creating a new rule on ES, we should create it with the new schema. Per definition, all duplicated rules will be `custom` rules. That means that for all rules -including prebuilt rules-, when duplicating, the `external_source` field will not be created on the newly created rule.
+Since we will be creating a new rule on ES, we should create it with the new schema. Per definition, all duplicated rules will be `custom` rules. That means that for all rules -including prebuilt rules-, when duplicating, the `rule_source` field will not be created on the newly created rule.
 This action will not perform a migration-on-write of the original rule being duplicated for two reasons:
 
 - it would violate the principle of least surprise for the endpoint
@@ -558,7 +576,7 @@ All other type of actions should **not** perform migration-on-write:
 
 ### Technical implementation of migration-on-write
 
-The logic for the migration of the rule saved objects, which means the determination of the `immutable`, `rule_source_type` and `external_source` fields before writing to ES, might differ depending on the action being performed by the user.
+The logic for the migration of the rule saved objects, which means the determination of the `immutable` and `rule_source` fields before writing to ES, might differ depending on the action being performed by the user.
 
 Let's see all possible use cases that will require migration-on-write, the endpoints that they apply to, and the expected resulting migrated field, based on the action and their input.
 
@@ -587,16 +605,15 @@ will perform migration but does not allow for customization during the duplicati
 
 So we can analyze the expected outputs of the migration of all these 8 endpoints together.
 
-The resulting values for `immutable` and `external_source` when calling these endpoints, and the migration being performed in the background, should be as follows:
+The resulting values for `immutable` and `rule_source` when calling these endpoints, and the migration being performed in the background, should be as follows:
 
 
-      
-      
+      
-      
+      
@@ -606,15 +623,14 @@ The resulting values for `immutable` and `external_source` when calling these en
       
-      
-      
-      
-      
@@ -686,23 +703,23 @@ The resulting values for `immutable` and `external_source` when calling these en
       
-      
@@ -712,78 +729,75 @@ The resulting values for `immutable` and `external_source` when calling these en
       
-      
-      
+      
-      
-      
+      
-      
@@ -811,18 +825,18 @@ Firstly, when bulk editing rules, the migration should be carried out for the fo
   - Adding rules actions
   - Duplicating a rule (with the migration applied only to the new rule)
 
-Out of the actions mentioned above, the only use cases that should possibly result in the migration having a result of `external_source.isCustomized = true` are the first three:
+Out of the actions mentioned above, the only use cases that should possibly result in the migration having a result of `rule_source.isCustomized = true` are the first three:
   - Bulk adding or deleting index patterns
   - Bulk adding or deleting tags
   - Updating rule schedules
 
 That means that updating a rule's actions or duplicating a rule should not be considered a customization of a prebuilt rule.
 
-Secondly, in contrast with other endpoints, the migration for bulk editing rules needs to be carried within the Alerting Framework's `RuleClient` since we need to migrate the rule's `external_source` and `immutable` parameters before the `RuleClient` does the saving of the rule into Elasticsearch.
+Secondly, in contrast with other endpoints, the migration for bulk editing rules needs to be carried within the Alerting Framework's `RuleClient` since we need to migrate the rule's `rule_source` and `immutable` parameters before the `RuleClient` does the saving of the rule into Elasticsearch.
 
-This however, gives us the advantage that the `RuleClient` already includes logic to calculate if a rule's attributes or parameters have been modified from its initial values, so we can rely on that to calculate the `external_source.isCustomized` field during the update.
+This however, gives us the advantage that the `RuleClient` already includes logic to calculate if a rule's attributes or parameters have been modified from its initial values, so we can rely on that to calculate the `rule_source.is_customized` field during the update.
 
-The `RulesClient` class has a `bulkEdit` method, which is called by our **Bulk Actions endpoint** `POST /rules/_bulk_action`. That method includes complex logic, but we can focus on the `updateRuleAttributesAndParamsInMemory` method, where the rule attributes and parameters are updated before being saved to ES. This function also calculates the booleans `isAttributesUpdateSkipped` and `isParamsUpdateSkipped` which we can leverage to calculate the new value of the `external_source.isCustomized` field in our params.
+The `RulesClient` class has a `bulkEdit` method, which is called by our **Bulk Actions endpoint** `POST /rules/_bulk_action`. That method includes complex logic, but we can focus on the `updateRuleAttributesAndParamsInMemory` method, where the rule attributes and parameters are updated before being saved to ES. This function also calculates the booleans `isAttributesUpdateSkipped` and `isParamsUpdateSkipped` which we can leverage to calculate the new value of the `rule_source.is_customized` field in our params.
 
 _See Source: [x-pack/plugins/alerting/server/application/rule/methods/bulk_edit/bulk_edit_rules.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/alerting/server/application/rule/methods/bulk_edit/bulk_edit_rules.ts)_
 
@@ -836,7 +850,7 @@ _See Source: [x-pack/plugins/alerting/server/application/rule/methods/bulk_edit/
 
 Across our application, both in the frontend and serverside, we use KQL filters to retrieve rules based on whether they are prebuilt rules or not - this means that the current behaviour of these values relies on the `immutable` field being set to either `true` or `false`.
 
-As mentioned before, we need to assume that at any point in time, there will be a mixture of rules whose saved object has already been migrated on Elasticsearch and others will not. This means that the retrieval of rules will need to maintain backwards compatibility: in order to determine if a rule is prebuilt, preferentially search for the existence of the `external_source` field; if that doesn't exist,  we should fall back to the legacy logic of checking a rule's `immutable` value.
+As mentioned before, we need to assume that at any point in time, there will be a mixture of rules whose saved object has already been migrated on Elasticsearch and others will not. This means that the retrieval of rules will need to maintain backwards compatibility: in order to determine if a rule is prebuilt, preferentially search for the existence of the `rule_source` field and check its `type` subfield; if that doesn't exist, we should fall back to the legacy logic of checking a rule's `immutable` value.
 
 This means that we will need to update the constants and KQL filters that we have hardcoded in our application to reflect the new schema:
 
@@ -844,19 +858,19 @@ _See source of rule params keys: [x-pack/plugins/security_solution/common/detect
 
 Will need to update the `x-pack/plugins/security_solution/common/detection_engine/rule_management/rule_filtering.ts` file, where the `convertRulesFilterToKQL` method is defined. This method is used both in the frontend and in the serverside, and translates rule filter options to KQL filters that Elasticsearch can understand.
 
-Here, we need to update the KQL filters and the logic for fetching Elastic prebuilt and custom rules, relying on `rule_source_type` but with fallback to `immutable`:
+Here, we need to update the KQL filters and the logic for fetching Elastic prebuilt and custom rules, relying on `rule_source` but with fallback to `immutable`:
 
 _Source for `convertRulesFilterToKQL`: [x-pack/plugins/security_solution/common/detection_engine/rule_management/rule_filtering.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/common/detection_engine/rule_management/rule_filtering.ts)_
 
-In order to retrieve Elastic prebuilt rules, we can filter for rules in which `alert.attributes.params.rule_source_type` is `external`, with a fallback to rules in which `alert.attributes.params.immutable` is `true`, for rules which have not had their schema migrated and `rule_source_type` does not still exists for them.
+In order to retrieve Elastic prebuilt rules, we can filter for rules in which `alert.attributes.params.rule_source.type` is `external`, with a fallback to rules in which `alert.attributes.params.immutable` is `true`, for rules which have not had their schema migrated and `rule_source` does not still exists for them.
 
-> In the future, we can further distinguish between `external` rules by their source origin. If we introduce a new field within `external_source` that defines their origin (such as `repo_name`, `repo_id`, or similar), we can further filter by Elastic prebuilt rules, or rules that are externally sourced from a repository handled by the user, etc.
+> In the future, we can further distinguish between `type: external` rules by their source origin. If we introduce a new field within `rule_source` that defines their origin (such as `repo_name`, `repo_id`, or similar), we can further filter by Elastic prebuilt rules, or rules that are externally sourced from a repository handled by the user, etc.
 
 ### Rule Management endpoints
 
 - **Create Rules** - `POST /rules` and **Bulk Create Rules** - `POST /rules/_bulk_create`:
 
-Currently, we don't support the `immutable` field in any of the endpoints' request parameters (except for the Import endpoint). We shouldn't support the `external_source` field either, because this value should be controlled by the app on the server side, and not by users.
+Currently, we don't support the `immutable` field in any of the endpoints' request parameters (except for the Import endpoint). We shouldn't support the `rule_source` field either, because this value should be controlled by the app on the server side, and not by users.
 
 This is so because we will never want users to be able to create their own prebuilt rules, only install them, import them, and customize them. Also, a prebuilt rule should always be able to be compared to a `security-rule` asset distributed by Fleet, and receive updates from it, which would not be possible if a user creates its own prebuilt rules.
 
@@ -866,11 +880,11 @@ Creating new methods for those unrelated actions should help clean the `createRu
 
 - **Rule Management Filters** - `GET /rules/_rule_management_filters` (Internal):
 
-This endpoint currently depends on rules `alert.attributes.params.immutable` to fetch number of custom rules and number of prebuilt rules. We need to adapt its logic to rely on new `alert.attributes.params.external_source` field, with fallback to the original, for backwards compatibility.
+This endpoint currently depends on rules `alert.attributes.params.immutable` to fetch number of custom rules and number of prebuilt rules. We need to adapt its logic to rely on new `alert.attributes.params.rule_source` field, with fallback to the original, for backwards compatibility.
 
 Specifically, the endpoint handler uses the [`findRules` utility](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/search/find_rules.ts) to fetch rules based on their `immutable` param.
 
-This needs to be changed so that we rely on the `external_source` param, but fallback to `immutable` if that parameter doesn't exist - i.e., in the case of non-migrated-on-write rules. We need to modify the KQL queries in a similar way to the already described in the section `KQL filters and the convertRulesFilterToKQL`.
+This needs to be changed so that we rely on the `rule_source.type` param, but fallback to `immutable` if that parameter doesn't exist - i.e., in the case of non-migrated-on-write rules. We need to modify the KQL queries in a similar way to the already described in the section `KQL filters and the convertRulesFilterToKQL`.
 
 We need to modify the `x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/filters/route.ts` file; specifically the `fetchRulesCount` function, which contains the KQL query filters that should be updated.
 
@@ -878,7 +892,7 @@ _See Source: [x-pack/plugins/security_solution/server/lib/detection_engine/rule_
 
 - **Coverage Overview** - `/rules_coverage_overview` (Internal): This endpoint is called to retrieve the data that populates the MITRE Coverage Overview table, and currently depends on the `immutable` field to fetch the user's installed rules.
 
-Similarly to what was described in the previous endpoint, we should update the logic so that we rely on the `external_source` param, but fallback to `immutable` if that parameter doesn't exist - i.e., in the case of non-migrated-on-write rules.
+Similarly to what was described in the previous endpoint, we should update the logic so that we rely on the `rule_source.type` field, but fallback to `immutable` if that parameter doesn't exist - i.e., in the case of non-migrated-on-write rules.
 
 This endpoint handler also uses the [`findRules` utility](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/search/find_rules.ts) to fetch rules, but the KQL filter that is passed to that utility is created by the reusable [`convertRulesFilterToKQL` utility function](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/common/detection_engine/rule_management/rule_filtering.ts):
 
@@ -890,7 +904,7 @@ Therefor, it is enough to modify the `convertRulesFilterToKQL` utility logic as
 
 - [**(LEGACY) Get Prebuilt Rules and Timeline Status** - `/rules/prepackaged/_status`](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/get_prebuilt_rules_and_timelines_status/get_prebuilt_rules_and_timelines_status_route.ts)
 
-This currently depends on rules `alert.attributes.params.immutable` to fetch the number of custom rules and number of prebuilt rules. We need to adapt these filters used in the `findRules` method used in the endpoint handler to rely on new `alert.attributes.params.external_source` field, with fallback to the original, for backwards compatibility:
+This currently depends on rules `alert.attributes.params.immutable` to fetch the number of custom rules and number of prebuilt rules. We need to adapt these filters used in the `findRules` method used in the endpoint handler to rely on new `alert.attributes.params.rule_source.type` field, with fallback to the original, for backwards compatibility:
 
 _See Source: [x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/get_prebuilt_rules_and_timelines_status/get_prebuilt_rules_and_timelines_status_route.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/get_prebuilt_rules_and_timelines_status/get_prebuilt_rules_and_timelines_status_route.ts)_
 
@@ -919,7 +933,7 @@ Additionally:
 
 - [**Review Rule Installation** - `POST /prebuilt_rules/installation/_review` (Internal)](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/review_rule_installation/review_rule_installation_route.ts)
 
-This endpoint uses the `convertPrebuiltRuleAssetToRuleResponse` method, which takes in a prebuilt rule asset and converts it to an object of type `RuleResponse`. This method has to be modified so that new prebuilt rules objects are returned by the endpoint with a `rule_source_type` field of value `external`, an `external_source` object and a legacy `immutable` value of `true`.
+This endpoint uses the `convertPrebuiltRuleAssetToRuleResponse` method, which takes in a prebuilt rule asset and converts it to an object of type `RuleResponse`. This method has to be modified so that new prebuilt rules objects are returned by the endpoint with a `rule_source` field of type `external` and its other corresponding subfields, as well as the legacy `immutable` value of `true`.
 
 _Source: [x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/normalization/rule_converters.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/normalization/rule_converters.ts)_
 
@@ -937,8 +951,8 @@ export const convertPrebuiltRuleAssetToRuleResponse = (
   const ruleResponseSpecificFields = {
     // [... other prebuilt rule fields ...]
     immutable: true,
-    rule_source_type: 'external',
-    external_source: {
+    rule_source: {
+      type: 'external',
       isCustomized: false,
       sourceUpdatedAt: prebuiltRuleAsset.sourceUpdatedAt,
     },
@@ -969,11 +983,11 @@ This endpoint will need further changes, which will be detailed further down, an
 
 This endpoint will require major changes to add the capability of letting users selecting a custom version of the rule with custom values for rule fields. This will be explained further below in the "Changes to upgrade `_review` and `_perform` endpoints" section.
 
-The calculation of the value for the `external_source.isCustomized` field for the updated rule will depend on that logic as well, so its calculation will be explained in that section.
+The calculation of the value for the `rule_source.is_customized` field for the updated rule will depend on that logic as well, so its calculation will be explained in that section.
 
 Again, this endpoint suffers from tightly coupled logic explained in [`Problem with tightly coupled logic in our endpoints`](#problem-with-tightly-coupled-logic-in-our-endpoints): it uses the `upgradePrebuiltRules` method to actually upgrade the rules, but this method either patches existing rules -for the normal case-, or deletes an existing rule and recreates it if the rule underwent a type change, using the `patchRules` and `createRules` methods respectively. We should decouple that logic by introducing a new CRUD method with a specific use case for upgrading prebuilt rule.
 
-The changes in the `upgradePrebuiltRules` method need to take into account both paths. In the endpoint logic handler, when calculating if the rule was customized by the user, we will create a boolean called `isRuleCustomizedDuringUpgrade`, that we will pass as an argument to `upgradePrebuiltRules`:
+The changes in the `upgradePrebuiltRules` method need to take into account both paths. In the endpoint logic handler, when calculating if the rule was customized by the user, we will create a boolean called `isRuleCustomizedDuringUpgrade`, that can be passed as an argument to `upgradePrebuiltRules`:
 
 _Source: [x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_upgrade/perform_rule_upgrade_route.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_upgrade/perform_rule_upgrade_route.ts)_
 
@@ -985,7 +999,7 @@ This endpoint uses the [Detection Engine Health Client (`IDetectionEngineHealthC
 
 The Detection Engine Health client receives as its parameter the [Rule Objects Health client (`IRuleObjectsHealthClient`)](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/detection_engine_health/rule_objects/rule_objects_health_client.ts), whose method `calculateClusterHealth` performs an aggregation on rule stats based on different rule attributes and parameters.
 
-This is done in the [`getRuleStatsAggregation` method](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/detection_engine_health/rule_objects/aggregations/rule_stats.ts), where an aggration is done over the `immutable` param. This needs to be updated to the new `external_source` param, with a fallback to `immutable`:
+This is done in the [`getRuleStatsAggregation` method](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/detection_engine_health/rule_objects/aggregations/rule_stats.ts), where an aggregation is done over the `immutable` param. This needs to be updated to the new `rule_source.type` param, with a fallback to `immutable`:
 
 _Source: x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/detection_engine_health/rule_objects/aggregations/rule_stats.ts(https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/detection_engine_health/rule_objects/aggregations/rule_stats.ts)_
 
@@ -1024,7 +1038,7 @@ The export endpoints (bulk export and bulk action in export mode) will not carry
 
 Instead, we will carry out a normalization-on-read process, as described above, when the rule to be exported is read from ES, and before writing the rule's fields to the `ndjson` file. This means that the rule will actually be exported with the updated schema.
 
-This normalization will take place within the `internalRuleToAPIResponse` method, which internally calls the `normalizePrebuiltSchemaOnRuleRead`, as described in the [Normalization on read](#normalization-on-read) section.
+This normalization will take place within the `internalRuleToAPIResponse` method, which internally calls the `normalizeRuleSourceSchemaOnRuleRead`, as described in the [Normalization on read](#normalization-on-read) section.
 
 There are two helper functions used for exporting:
 
@@ -1048,42 +1062,379 @@ The user will now be able to import both custom and prebuilt rules (including an
 
 We want to handle the case of importing both migrated and non-migrated rules via an `ndjson` file.
 
-
 If a user imports a prebuilt rule, Kibana should continue to track the rule asset from the `security_detection_engine` package if the `rule_id` matches. This means that a user will be able to update a previously exported prebuilt rule, visualize any diffs on any customized fields, and continue to receive updates on the rule.
 
-To allow for importing of Elastic prebuilt rules, we will **not rely** in the `rule_source_type` or `external_source` fields (which are not part of the import endpoint parameters), but we will rather **calculate them dynamically based on the `rule_id` and `version` request parameters**.
+To allow for importing of Elastic prebuilt rules, we will **not rely** in the `rule_source` or the legacy `immutable` fields (which are not part of the import endpoint parameters), but we will rather **calculate them dynamically based on the `rule_id` and `version` request parameters**.
 
 The logic to importing a rule is as follows:
 
-First, read the import endpoint request parameters `rule_id` and `version`. These two are the two required parameters in the endpoint, while all other rule fields are optional.
-
-Secondly, check that the `security_detection_engine` Fleet package is installed and install it if it isn't. We will need the package to be installed to check if a rule that is being imported is an Elastic prebuilt rule.
+ - First, read the import endpoint request parameters `rule_id` and `version`. These two are the two required parameters in the endpoint, while all other rule fields are optional.
 
-Then, using the `rule_id` and `version`, attempt to fetch the corresponding `security-rule` asset from ES. 
+- Secondly, check that the `security_detection_engine` Fleet package is installed and install it if it isn't. We will need the package to be installed to check if a rule that is being imported is an Elastic prebuilt rule.
 
-**If a matching `rule_id` and `version` is found**, that means that the rule is an Elastic prebuilt rule, and we should therefore dynamically calculate the rule's `external_source` and `rule_source_type` fields.
+- Then, using the `rule_id` and `version`, attempt to fetch the corresponding `security-rule` asset from ES. 
 
-- `rule_source_type`: should always be `'external'` if rule is Elastic prebuilt.
-- `external_source`:
+- **If a matching `rule_id` and `version` is found**, that means that the rule is an Elastic prebuilt rule, and we should therefore dynamically calculate the rule's `rule_source` field and its subfields:
+  - `type`: should be always `external` since a matching external `security-rule` was found.
   - `source_updated_at`: can be retrieved from the corresponding `security-rule` asset.
   - `is_customized`: should be calculated based on the `security-rule` asset's field and the field rules that were part of the import request parameters. If any of them are different, i.e. have diverged from the base version, `is_customized` should be true.
 
-Finally, using the import payload, plus the rule's `security-rule` asset fields and the calculated `rule_source_type` and `external_source` fields, create the rule, or update it if already exists in Kibana.
+- Finally, using the import payload, plus the rule's `security-rule` asset fields and the calculated `rule_source` fields, create the rule, or update it if already exists in Kibana.
+
+**If a matching `rule_id` is found, but the `version` is not found**, reject the import for that rule. Without a version, we cannot dynamically calculate `rule_source`.
+
+**If a matching `rule_id` is NOT found**, that means that the rule is a custom rule. And `rule_source` will be simply:
+```
+{
+  type: 'internal'
+}
+```
+
+And we can finally create a rule or update an existing rule using the request payload and the calculated `rule_source` field.
+
+--- 
+Given the requirements described above, the following table shows the behaviour of our endpoint for a combination of inputs and Kibana states.
+
+(All situation assume that the Elastic prebuilt rules package will be installed, since we have set this as a precondition of the endpoint)
+
+
Migration use caseCurrent value of
external_source
Current value of
rule_source_type
Current value of
rule_source
Current value of
immutable
Any field diverges
from base version during update?
Any field diverges
from base version after update?
Results
undefined
-
undefined
-
false
N/A - Doesn't apply for custom rules
           {
-            rule_source_type: 'internal',
+            rule_source: {
+              type: 'internal'
+            },
             immutable: false,
           }
         
@@ -623,17 +639,20 @@ The resulting values for `immutable` and `external_source` when calling these en
Custom rule (already migrated) -
undefined
-
-
'internal'
+
+{
+  type: 'internal'
+}
+        
false
N/A - Doesn't apply for custom rules
           {
-            rule_source_type: 'internal',
+            rule_source: {
+              type: 'internal'
+            },
             immutable: false,
           }
         
@@ -644,14 +663,13 @@ The resulting values for `immutable` and `external_source` when calling these en
undefined
undefined
true
No
           {
-            rule_source_type: 'external',
-            external_source: {
+            rule_source: {
+              type: 'external',
               isCustomized: false,
               ...
             },
@@ -665,18 +683,17 @@ The resulting values for `immutable` and `external_source` when calling these en
       
undefined
undefined
true
Yes
           {
-            rule_source_type: 'external',
-            external_source: {
+            rule_source: {
+              type: 'external',
               isCustomized: true,
               ...
             },
-            immutable: true
+            immutable: true,
           }
         
 
           {
+            type: 'external',
             isCustomized: false,
               ...
           }
           
'external'
true
No
           {
-            rule_source_type: 'external',
-            external_source: {
+            rule_source: {
+              type: 'external',
               isCustomized: false,
               ...
             },
-            immutable: true
+            immutable: true,
           }
         
 
           {
-            repoName: 'elastic_prebuilt',
+            type: 'external',
             isCustomized: true,
               ...
           }
           
'external'
true
Yes
           {
-            rule_source_type: 'external',
-            external_source: {
-              repoName: 'elastic_prebuilt',
+            rule_source: {
+              type: 'external',
               isCustomized: true,
               ...
             },
-            immutable: true
+            immutable: true,
           }
         
Customized Prebuilt rule (already migrated, no new customizations)Customized Prebuilt rule (already migrated, no customizations after update)
 
           {
+            type: 'external',
             isCustomized: true,
               ...
           }
           
'external'
true
No
           {
-            rule_source_type: 'external',
-            external_source: {
+            rule_source: {
+              type: 'external',
               isCustomized: false,
               ...
             },
-            immutable: true
+            immutable: true,
           }
         
Invalid case: Migrating a migrated non-customized prebuilt rule, with customizations.

`immutable` should never be false if `rule_source_type` is 'internal' or `external_source` is defined. Migration should correct this inconsistency.
Invalid case: Migrating a migrated non-customized prebuilt rule, with customizations.

`immutable` should never be false if `rule_source.type' is 'external'. Migration should correct this inconsistency.
 
           {
-            repoName: 'elastic_prebuilt',
+            type: 'external',
             isCustomized: false,
               ...
           }
           
'internal'
false
Yes
           {
-            rule_source_type: 'external',
-            external_source: {
+            rule_source: {
+              type: 'external',
               isCustomized: true,
               ...
             },
-            immutable: true
+            immutable: true,
           }
         
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -**If a matching `rule_id` is found, but the `version` is not found**, reject the import for that rule. Without a version, we cannot dynamically calculate `external_source`. -**If a matching `rule_id` is NOT found**, that means that the rule is a custom rule: -- `rule_source_type`: should be `internal` -- `external_source`: doesn't need calculation. + + + + + + + + + + + + + + + + + + -And we can finally create or updated an existing rule using the request payload and the calculated `rule_source_type` field. -Given the requirements described above, the following table shows the behaviour of our endpoint for a combination of inputs and Kibana states: + + + + + + + + + -With this migration strategy for the import endpoints we can guarantee backwards compatibility for all rules, and don't need to do additional changes to the export endpoints. + + + + + + + + + + + + + + + + +
Current state of rule
(match by rule_id)
Matching rule_id found as security-rule asset?Matching version found for security-rule asset?Example field in import payloadOverwrite existing rule?Output
Not installedNoN/A +
+{
+  name: "My custom rule",
+} 
+
+
N/A +
+{
+  name: "My custom rule",
+  rule_source: {
+    type: "internal"
+  }
+} 
+
+
+
+{
+  name: "My custom rule",
+} 
+
+
NoN/A +
+{
+  name: "My edited rule",
+} 
+
+
+ No + + Rule import rejected
because of rule_id match +
+
+{
+  name: "My custom rule",
+} 
+
+
NoN/A +
+{
+  name: "My edited rule",
+} 
+
+
+ Yes + +
+{
+  name: "My edited rule",
+  rule_source: {
+    type: "internal"
+  }
+} 
+
+
+ Not installed + +
+{
+  name: "My prebuilt rule",
+  source_updated_at: "2024-05-..."
+} 
+
+
No +
+{
+  name: "My prebuilt rule",
+} 
+
+
N/A + Prebuilt rule import rejected because no matching
+ version found for existing rule_id security-asset +
+ Not installed + +
+{
+  name: "My prebuilt rule",
+  source_updated_at: "2024-05-..."
+} 
+
+
Yes +
+{
+  name: "My prebuilt rule",
+} 
+
+
N/A +
+{
+  name: "My prebuilt rule",
+  rule_source: {
+    type: "external",
+    is_customized: false,
+    source_updated_at: "2024-05-..."
+  }
+} 
+
+
+ Not installed + +
+{
+  name: "My prebuilt rule",
+  source_updated_at: "2024-05-..."
+} 
+
+
Yes +
+{
+  name: "My custom prebuilt rule",
+} 
+
+
N/A +
+{
+  name: "My custom prebuilt rule",
+  rule_source: {
+    type: "external",
+    is_customized: true,
+    source_updated_at: "2024-05-..."
+  }
+} 
+
+
+
+{
+  name: "My prebuilt rule",
+  rule_source: {
+    type: "external",
+    is_customized: false,
+    source_updated_at: "2024-05-..."
+  }
+} 
+
+
+
+{
+  name: "My prebuilt rule",
+  source_updated_at: "2024-05-..."
+} 
+
+
Yes +
+{
+  name: "My custom prebuilt rule",
+} 
+
+
No + Rule import rejected
because of rule_id match +
+
+{
+  name: "My prebuilt rule",
+  rule_source: {
+    type: "external",
+    is_customized: false,
+    source_updated_at: "2024-05-..."
+  }
+} 
+
+
+
+{
+  name: "My prebuilt rule",
+  source_updated_at: "2024-05-..."
+} 
+
+
Yes +
+{
+  name: "My custom prebuilt rule",
+} 
+
+
Yes +
+{
+  name: "My custom prebuilt rule",
+  rule_source: {
+    type: "external",
+    is_customized: true,
+    source_updated_at: "2024-05-..."
+  }
+} 
+
+
+
+{
+  name: "My custom prebuilt rule",
+  rule_source: {
+    type: "external",
+    is_customized: true,
+    source_updated_at: "2024-05-..."
+  }
+} 
+
+
+
+{
+  name: "My prebuilt rule",
+  source_updated_at: "2024-05-..."
+} 
+
+
Yes +
+{
+  name: "My prebuilt rule",
+} 
+
+
Yes +
+{
+  name: "My prebuilt rule",
+  rule_source: {
+    type: "external",
+    is_customized: false,
+    source_updated_at: "2024-05-..."
+  }
+} 
+
+
### Handling the `version` parameter @@ -1094,26 +1445,17 @@ Since users will be importing rules via an `ndjson` file, they can potentially m **1. The user removes the `version` field from the importing payload:** as mentioned above, we won't be able to start the upgrading flow because we don't have a version number to compare to the version coming from the update. Therefore, we should **reject the import if the `version` is missing**. -**2. The user lowers the `version` field from the importing payload:** for example, a user exports a prebuilt rule with `version: 5`, and, before importing it, modifies it to `version: 4`. This wouldn't represent a problem as a new version of the rule (i.e. `version: 6`) would still trigger the update workflow, and the rule field diffs would still work as expected. +**2. The user lowers the `version` field in the importing payload:** for example, a user exports a prebuilt rule with `version: 5`, and, before importing it, modifies it to `version: 4`. This wouldn't represent a problem as a new version of the rule (i.e. `version: 6`) would still trigger the update workflow, and the rule field diffs would still work as expected. -**3. The user increases the `version` field from the importing payload:** or example, a user exports a prebuilt rule with `version: 5`, and before importing it modifies it to `version: 6`. This would mean that when the actual rule with `version: 6` was released, we wouldn't trigger the update workflow, since the version from the target version (the update) needs to be higher than what is currently installed for that to happen. However, the update would eventually be triggered when the next update was released, i.e. when `version: 7` is released, and work as expected. +**3. The user increases the `version` field in the importing payload:** for example, a user exports a prebuilt rule with `version: 5`, and before importing it modifies it to `version: 6`. This would mean that when the actual rule with `version: 6` was released, we wouldn't trigger the update workflow, since the version from the target version (the update) needs to be higher than what is currently installed for that to happen. However, the update would eventually be triggered when the next update was released, i.e. when `version: 7` is released, and work as expected. **4. The user sets the `version` field from the importing payload to a number that does not exist in the Prebuilt Rules package**: this scenario would still depend on whether the `version` that the user modifies the rule to is higher or lower than the version of the update: - If it was higher, then we would be back in **scenario 3**, where the update workflow wouldn't trigger. - If it was lower, then we would be in **scenario 2**, but with the additional problem that we wouldn't be able to fetch the **base** version of the rule - the unmodified version of the rule as it exists in the Prebuilt Rules package. However, we would still be able to normally display the rule field diffs between the current rule and the target (next version) rule (which is the default behaviour), but not between the base and the target (which is a feature that we want to a add as part of this Milestone). -$\space$ -$\space$ -$\space$ $\space$ -------------------------- end of reviewable part of RFC ------------------------------ - -$\space$ -$\space$ -$\space$ -$\space$ ## Customizing Prebuilt Rules @@ -1131,8 +1473,8 @@ Endpoints that users will be able to use to modify rules are: The first four endpoints listed above **currently allow users to modify their Elastic prebuilt rules** as well, in (almost) all of their fields, and no difference is made between updating/patching prebuilt rules and custom rules in the docs. However, none of those four endpoints allow to change a prebuilt rule to a custom rule (or vice-versa) by changing the current `immutable` field (i.e. the field is maintained from the existing rule). -> - **Will we want to allow users to modify (via API) a prebuilt rule to transform it into a Custom Rule, by modifying the `external_source` parameter?** -> - No. We want to keep the current endpoint logic where the `immutable` field for the updated value comes from the existing value of the rule. Allowing that modification would create issues with the corresponding `security_detection_engine` package rule, as it will clash with the modified rule if the `rule_id` is not modified as well. This requirement is therefore not needed anyway since will now offer users the option to customize a prebuilt rule, or alternatively, duplicate a prebuilt rule. +> - **Will we want to allow users to modify (via API) a prebuilt rule to transform it into a Custom Rule, by modifying the `rule_source` parameter?** +> - No. We want to keep the current endpoint logic, where the `immutable` field for the updated value comes from the existing value of the rule and is not modifiable. Allowing that modification would create issues with the corresponding `security_detection_engine` package rule, as it will clash with the modified rule if the `rule_id` is not modified as well. This requirement is therefore not needed anyway since will now offer users the option to customize a prebuilt rule, or alternatively, duplicate a prebuilt rule. The endpoint **Bulk Actions** - `POST /rules/_bulk_action` does provide validation in the endpoint logic itself: if a user attempts to edit prebuilt rule (`immutable: true`) the endpoint rejects that edit in two ways: @@ -1146,33 +1488,33 @@ In both cases, the validation checks if the `immutable` param of the rule is `fa ##### Update Rule - `PUT /rules` - Addition of rule schema migration logic (described above) -- Calculation of `customized` field +- Calculation of `is_customized` field - No other changes needed as endpoint already allows modifying prebuilt rules ##### Patch Rule - `PATCH /rules` - Addition of rule schema migration logic (described above) -- Calculation of `customized` field +- Calculation of `is_customized` field - No other changes needed as endpoint already allows modifying prebuilt rules ##### Bulk Patch Rules - `PATCH /rules/_bulk_update` - Addition of rule schema migration logic (described above) -- Calculation of `customized` field for each modified rule +- Calculation of `is_customized` field for each modified rule - No other changes needed as endpoint already allows modifying prebuilt rules ##### Bulk Update Rules - `PUT /rules/_bulk_update` - Addition of rule schema migration logic (described above) -- Calculation of `customized` field for each modified rule +- Calculation of `is_customized` field for each modified rule - No other changes needed as endpoint already allows modifying prebuilt rules ##### Bulk Actions - `POST /rules/_bulk_action` - Addition of rule schema migration logic (described above) -- Calculation of `customized` field for each modified rule +- Calculation of `is_customized` field for each modified rule - Removal of the check that prevents modifying prebuilt rules. Customization should be possible for both prebuilt and custom rules, and for all bulk editing actions that are currently supported for custom rules. - - Remove check for whether the rules in the payload have an `immutable` value of `false` OR if the `BulkActionEditTypeEnum` is either `set_rule_actions` or `add_rule_actions`. Bulk editing should be possible for all rules (independently of their values for the `external_source` and now legacy `immutable` fields), and for all types of Bulk Action Edit Types: + - This means we need to remove check for whether the rules in the payload have an `immutable` value of `false` OR if the `BulkActionEditTypeEnum` is either `set_rule_actions` or `add_rule_actions`. Bulk editing should be possible for all rules (independently of their values for the `rule_source` and now legacy `immutable` fields), and for all types of Bulk Action Edit Types: ```ts export const BulkActionEditType = z.enum([ 'add_tags', @@ -1187,22 +1529,276 @@ In both cases, the validation checks if the `immutable` param of the rule is `fa 'set_schedule', ]); ``` - - This change will apply to two validations performed when calling this endpoint: - - when `dryRun` is `true` - - when `dryRun` is `false` (normal mode) -#### Updating the `customized` field +#### Updating the `is_customized` field + +The `is_customized` field is initialized to a value of `false` for any new prebuilt rule that is installed, as well as in prebuilt rules that are migrated from the legacy schema. + +For all of the endpoints that allow for modifying a prebuilt rule, the five endpoints mentioned in the last section, we will want to calculate if: when the modifications are applied to the current state of the rule, does the rule result in a customized version of the prebuilt rule? + +This means, specifically: **do any of the rule's resulting fields differ from the base version of the rule?** + +In order to determine this, each time a user attempts to customize a prebuilt rule, we will need to pull its corresponding version of the `security-rule` asset, and compare the end result of the customization with the assets field's. If any of them are different, the `rule_source.is_customized` field should be set to `true`. Otherwise, it should be set to `false`. + +Notice that this can therefore result in a two-way operation: a prebuilt rule that is non-customized can end up as being customized (`is_customized: true`), while a rule that is customized at the beggining of the operation can result in a non-customized rule after the modification (if the changes made by the user make the rule match its base version). + +The following use cases should be covered in the calculation of `is_customized`: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -The `customized` field is initialized to a value of `false` for any new prebuilt rule that is installed, as well as in prebuilt rules that are migrated from the legacy schema. -On a first iteration, the field should be updated to `true` when at least one of its fields is updated to any new value that differs to its current value. This means that we want the update of this field to be one-way: from `false` it can be updated to `true`, but we don't want for the field to be able to be reverted back to `false`. -The reasons for this decision are the following: -- when updating a rule, we don't have the information of what the "base" values for a rule's field are in order to compare them to the updated values. We only have the values for the existing rules as they are stored in the saved object, and the updated values that are sent in the request payload. We can easily compare those two to see if any changes were actually made, and mark the `customized` field as `true` in that case. -- the UX "downside" of this approach is minimal and a very rare corner case: once a user has modified a value, it will very seldom happen that the they will update it an additional time to a value that matches the base version (and thus has no differences to the base version). -On a next phase, we could consider fetching the base version of the rule and actually comparing the updated values to the base values to decide if the rule should be considered `customized` or not. However, we should consider the performance (and complexity) implications that this additional logic could have on the endpoints. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Use caseCurrent state of rulesecurity-rule assetPUT Endpoint payloadOutput
Modified field value diverges from base asset +
+{
+  name: "Original name",
+  rule_source: {
+    type: "external",
+    is_customized: false,
+    ...
+  }
+}
+
+
+
+{
+  name: "Original name",
+}
+
+
+{
+  name: "My custom name",
+}
+
+
+{
+  name: "My custom name",
+  rule_source: {
+    type: "external",
+    is_customized: true,
+    ...
+  }
+}
+
+
New field added, not existing in base asset +
+{
+  name: "Original name",
+  rule_source: {
+    type: "external",
+    is_customized: false,
+    ...
+  }
+}
+
+
+
+{
+  name: "Original name",
+}
+
+
+{
+  name: "Original name",
+  note: "My investigation guide",
+}
+
+
+{
+  name: "Original name",
+  note: "My investigation guide",
+  rule_source: {
+    type: "external",
+    is_customized: true,
+    ...
+  }
+}
+
+
Modified matches value in base asset +
+{
+  name: "My custom name",
+  rule_source: {
+    type: "external",
+    is_customized: true,
+    ...
+  }
+}
+
+
+
+{
+  name: "Original name",
+}
+
+
+{
+  name: "Original name",
+}
+
+
+{
+  name: "Original name",
+  rule_source: {
+    type: "external",
+    is_customized: false,
+    ...
+  }
+}
+
+
Field existing in base asset is removed +
+{
+  name: "Original name",
+  "tags": ["Linux", "Windows"]
+  rule_source: {
+    type: "external",
+    is_customized: false,
+    ...
+  }
+}
+
+
+
+{
+  name: "Original name",
+  "tags": ["Linux", "Windows"]
+}
+      
+
+
+{
+  name: "Original name",
+}
+      
+
+
+{
+  name: "Original name",
+  rule_source: {
+    type: "external",
+    is_customized: true,
+    ...
+  }
+}
+
+
Edge case: base asset not found +
+{
+  name: "Original name",
+  rule_source: {
+    type: "external",
+    is_customized: false,
+    ...
+  }
+}
+
+
+
Not found
+
+
+{
+  name: "Original name",
+}
+
+
+{
+  name: "Original name",
+  rule_source: {
+    type: "external",
+    is_customized: true,
+    ...
+  }
+}
+
+
+ +Notice the last scenario from the table, which deals with the edge case of the corresponding version of the `security-rule` asset not being found. This would prevent from doing a comparison of the fields to calculate if the rule should be considered customized or not. + +So, if the corresponding rule asset is not found, do not attempt to do any comparisons and mark the rule as `is_customized: true`; ignoring the current values of the rules, the payload and the end result. + +Reasons: +- A prebuilt rule which is being modified has a much higher chance of ending up as `is_customized: true` than `false`. Given that we cannot know this for certain, marking it as customized is the best educated guess. +- If we ended up making a wrong assumption in that previous point, it can be corrected the next time the rule is upgraded, or if the rule is modified again and the rule asset is found this time. +- A rule which is missing its base version makes more sense being customized than non-customized from a domain-modelling poitn of view. +- The alternative of rejecting the update on a simple field name change is just bad UX: a user just wants to change a rule's name and probably doesn't care that the corresponding `security-rule` asset is not installed. ### In the UI @@ -1231,7 +1827,7 @@ Once done editing the rule, the user clicks on the "Save Changes" button, which - The only field in the UI that should not be customizable is **Rule Type**, that should continue to be read-only. - **Definition** should be the default open tab when opening the edit rule page for a prebuilt rule (current default is **Actions**) - Field validation should continue to work as it does for custom rules. -- No fields should return a validation error for the values that come from the `security_detection_engine` package prebuilt rules. This means that a user should be able to successfully save the prebuilt rule with no changes. See **List of things to fix** below. +- No fields should return a validation error for the values that come from the `security_detection_engine` package prebuilt rules. This means that a user should be able to successfully save the prebuilt rule with no changes. See **List of issues to fix** below. #### Via Bulk Actions @@ -1249,9 +1845,8 @@ As explained above, the UI validates that the five actions listed above are only **Expected behaviour for customizing prebuilt rules** -The Bulk Actions UI should now be able to edit prebuilt rules. - -All bulk actions actions listed above should now be applicable to prebuilt rules (adding and overwriting rule actions is currently possible). This means that the changes in the API for the validation done in `dryRun` mode should not remove the rules from the payload anymore, and the bulk editing of the prebuilt rules will be possible when the subsequent request, in normal mode (`dryRun: false`), is performed. +- The Bulk Actions UI should now allow users to edit prebuilt rules. +- All bulk actions actions listed above should now be applicable to prebuilt rules (This means that the changes in the API for the validation done in `dryRun` mode should not remove the rules from the payload anymore). > The `dryRun` mode request will still be necessary since we perform other checks that can still prevent prebuilt rules from being edited. For example, Machine Learning and ES|QL rules cannot be bulk edited to add or delete index patterns, since they don't have that field in their schema. @@ -1306,11 +1901,21 @@ This means that **no changes will be needed in this page.** - How are we going to handle various fields in the rule upgrade workflow? - What concrete diff algorithms for what rule fields we will need to write? -## Updating Prebuilt Rules +## Upgrading Prebuilt Rules -### Changes to upgrade `_review` and `_perform` endpoints +### Changes to upgrade `_review` endpoint -TODO +The algorithm for calculating rule version diffs' core structure is [fully implemented](https://github.com/elastic/kibana/pull/148392) and operational. However, the current method for calculating field differences is basic: it currently simply compares field values across versions and flags a conflict if the base version, the current version and the target versions differ from one another. In this conflict scenario, the `mergedVersion` of the field proposed by the algorithmalways equals the `targetVersion`. + +We propose developing more adaptable diff algorithms tailored to specific rule fields or rule field types. These more specific algorithms aim to minimize conflicts and automate merging of changes, doing the best effort to keep the intended customizationa applied by the user, as well as the updates proposed by Elastic. Hopefully, the user will be able to simply review the proposal and accept it. + +#### Concrete field diff algorithm by type + +##### String fields + + + +### Changes to upgrade `_perform` endpoints ### Rule field diff algorithms @@ -1353,5 +1958,3 @@ We’d like to know if the rules has been customized in any way (at least 1 fiel - We can solve this by making a non-blocking request to the endpoint after the page loads. Alternatively, show it only when the user opens a flyout desgined to show these diffs. ## Other open questions - -3. Do we want the `customized` field to revert to `false` if the fields revert to match the base version after diverging? diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/review_rule_upgrade/review_rule_upgrade_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/review_rule_upgrade/review_rule_upgrade_route.ts index 296cee146749fa..955b069b0c005d 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/review_rule_upgrade/review_rule_upgrade_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/review_rule_upgrade/review_rule_upgrade_route.ts @@ -61,7 +61,6 @@ export const reviewRuleUpgradeRoute = (router: SecuritySolutionPluginRouter) => invariant(ruleVersions != null, 'ruleVersions not found'); return calculateRuleDiff(ruleVersions); }); - debugger; const body: ReviewRuleUpgradeResponseBody = { stats: calculateRuleStats(ruleDiffCalculationResults), From 6b6578a783169eac5be70a08bfd83e8a71687349 Mon Sep 17 00:00:00 2001 From: jpdjere Date: Wed, 21 Feb 2024 17:29:58 +0100 Subject: [PATCH 18/61] Part 2: Started concrete diffs implementation --- .../docs/prebuilt_rules_customization_rfc.md | 152 ++++++++++++------ 1 file changed, 104 insertions(+), 48 deletions(-) diff --git a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md index ece47e93d57ecb..fe348d1e8fe9e7 100644 --- a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md +++ b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md @@ -1485,50 +1485,76 @@ In both cases, the validation checks if the `immutable` param of the rule is `fa #### Changes needed to endpoints -##### Update Rule - `PUT /rules` - -- Addition of rule schema migration logic (described above) -- Calculation of `is_customized` field -- No other changes needed as endpoint already allows modifying prebuilt rules - -##### Patch Rule - `PATCH /rules` - -- Addition of rule schema migration logic (described above) -- Calculation of `is_customized` field -- No other changes needed as endpoint already allows modifying prebuilt rules - -##### Bulk Patch Rules - `PATCH /rules/_bulk_update` - -- Addition of rule schema migration logic (described above) -- Calculation of `is_customized` field for each modified rule -- No other changes needed as endpoint already allows modifying prebuilt rules - -##### Bulk Update Rules - `PUT /rules/_bulk_update` - -- Addition of rule schema migration logic (described above) -- Calculation of `is_customized` field for each modified rule -- No other changes needed as endpoint already allows modifying prebuilt rules - -##### Bulk Actions - `POST /rules/_bulk_action` - -- Addition of rule schema migration logic (described above) -- Calculation of `is_customized` field for each modified rule -- Removal of the check that prevents modifying prebuilt rules. Customization should be possible for both prebuilt and custom rules, and for all bulk editing actions that are currently supported for custom rules. - - This means we need to remove check for whether the rules in the payload have an `immutable` value of `false` OR if the `BulkActionEditTypeEnum` is either `set_rule_actions` or `add_rule_actions`. Bulk editing should be possible for all rules (independently of their values for the `rule_source` and now legacy `immutable` fields), and for all types of Bulk Action Edit Types: - ```ts - export const BulkActionEditType = z.enum([ - 'add_tags', - 'delete_tags', - 'set_tags', - 'add_index_patterns', - 'delete_index_patterns', - 'set_index_patterns', - 'set_timeline', - 'add_rule_actions', - 'set_rule_actions', - 'set_schedule', - ]); - ``` +Depending on the endpoint, we will have to modify it to address multiple changes. These are: + +**1. Introduction of migration logic**: as explained in the first section of this document, endpoints should have the additional reponsibility of migrating our rule schema. +**2. Calculation of the `is_customized` field**: this field which is part of the `rule_source` field for external rules needs to be recalculated whenever a rule's field is possibly modified. See implementation details in the [Updating the `is_customized` field](#updating-the-is_customized-field) section. +**3. Removing checks that block modifying prebuilt rules:** some of our endpoints prevent users from modifying prebuilt rules. This check needs to be removed from all endpoints to allow the customization of prebuilt rules. +**4. Blocking the update of non-customizable fields:** while the goal of this epic is to allow users to modify their prebuilt rule fields, there are certain rule fields that we will still want to prevent the user from modifying via endpoints, since we will not provide support for resolving conflicts for them via the UI or API if they arise during an update. See the **Customizable** column in [this ticket](https://github.com/elastic/kibana/issues/147239) for a detailed list of fields that should be blocked from modification via the endpoints. + +The table below shows which of these changes need to be applied to our endpoints: (✅ change needed - ❌ no change needed) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EndpointsMigration logicis_customized calculationRemoving prebuilt checksBlocking non-customizable fields updates
Update Rule - PUT /rules
Patch Rule - PATCH /rules
Bulk Patch Rules - PATCH /rules/_bulk_update
Bulk Update Rules - PUT /rules/_bulk_update
Bulk Actions - POST /rules/_bulk_action
Perform Rule Upgrade - POST /prebuilt_rules/upgrade/_perform
Import Rules POST /rules/_import
#### Updating the `is_customized` field @@ -1907,12 +1933,45 @@ This means that **no changes will be needed in this page.** The algorithm for calculating rule version diffs' core structure is [fully implemented](https://github.com/elastic/kibana/pull/148392) and operational. However, the current method for calculating field differences is basic: it currently simply compares field values across versions and flags a conflict if the base version, the current version and the target versions differ from one another. In this conflict scenario, the `mergedVersion` of the field proposed by the algorithmalways equals the `targetVersion`. -We propose developing more adaptable diff algorithms tailored to specific rule fields or rule field types. These more specific algorithms aim to minimize conflicts and automate merging of changes, doing the best effort to keep the intended customizationa applied by the user, as well as the updates proposed by Elastic. Hopefully, the user will be able to simply review the proposal and accept it. +We propose developing more adaptable diff algorithms tailored to specific rule fields or rule field types. These more specific algorithms aim to minimize conflicts and automate merging of changes, doing the best effort to keep the intended customizations applied by the user, as well as the updates proposed by Elastic. Hopefully, the user will be able to simply review the proposal and accept it. #### Concrete field diff algorithm by type +Depending on the specific field or type of field we might want to apply a specific merging algorithm when conflicts arise. Let's propose different types. + ##### String fields +Examples: `name`, `description`, `setup`, `note` (Investigation guide) + + + + + + + + + + + + + + + + + + + + +
Use caseBase versionCurrent versionTarget versionMerged version (output)
Keep customizations on conflicts, but add updates in parts with no conflictsThis is a prebuilt rule nameThis is a customized prebuilt rule nameThis is an updated prebuilt rule name. Much better.This is a customized prebuilt rule name. Much better.
+ + + + + + + + + ### Changes to upgrade `_perform` endpoints @@ -1921,9 +1980,6 @@ We propose developing more adaptable diff algorithms tailored to specific rule f TODO -## Changes in UI - -TODO ## Scenarios for bulk accepting updates From 89fe78acfbbbea37daa210e16abfe4e4a632ec2f Mon Sep 17 00:00:00 2001 From: jpdjere Date: Thu, 22 Feb 2024 14:45:25 +0100 Subject: [PATCH 19/61] Part 2: Add algorithm use cases --- .../docs/prebuilt_rules_customization_rfc.md | 383 +++++++++++++++++- .../model/rule_assets/prebuilt_rule_asset.ts | 4 +- .../rule_schema/model/rule_schemas.ts | 4 +- 3 files changed, 381 insertions(+), 10 deletions(-) diff --git a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md index fe348d1e8fe9e7..da49e695014cb9 100644 --- a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md +++ b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md @@ -1955,19 +1955,390 @@ Examples: `name`, `description`, `setup`, `note` (Investigation guide)
Keep customizations on conflicts, but add updates in parts with no conflictsThis is a prebuilt rule nameThis is a customized prebuilt rule nameThis is an updated prebuilt rule name. Much better.This is a customized prebuilt rule name. Much better.Keep user customizations when whole string conflictsPrebuilt rule nameCompletely different stringUpdated prebuilt rule nameCompletely different string
Keep user-added prefixes and accept other modificationsPrebuilt rule name[Security Solution] Prebuilt rule nameUpdated prebuilt rule name[Security Solution] Updated prebuilt rule name
Keep user-added suffixes and accept other modificationsPrebuilt rule namePrebuilt rule name - (Custom version 3)Updated prebuilt rule nameUpdated prebuilt rule name - (Custom version 3)
Keep user customizations on conflicts, but add updates in sections with no conflictsPrebuilt rule nameCustomized prebuilt rule nameUpdated prebuilt rule name. Much better.Customized prebuilt rule name. Much better.
+ +##### Array fields + +For array fields, conflict resolution will take place on an element by element basis - that means that the algorithm will not consider or try to solve changes within a single element. For example: + +``` +base: [test1] +current: [my-test1] +target: [test2] +output: [my-test1] +``` +The example above shows that the algorithm should understand the above scenario as a conflict and not try to merge the single element by breaking it into parts. + +Example fields: `index`, `tags`, `references`, + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Use caseBase versionCurrent versionTarget versionMerged version (output)
Keep user changes if all elements conflict +
+[
+  logs-*,
+  logstash-*
+]
+        
+
+
+[
+  cluster_one:logs-*,
+  cluster_one:logstash-*
+]
+        
+
+
+[
+  new-index1-*,
+  new-index2-*,
+]
+        
+
+
+[
+  cluster_one:logs-*,
+  cluster_one:logstash-*
+]
+        
+
Keep user changes to any element, but add appended elements +
+[
+  logs-*,
+  logstash-*
+]
+        
+
+
+[
+  logs-*,
+  cluster_one:logstash-*
+]
+        
+
+
+[
+  logs-*,
+  logstash-*,
+  new-target
+]
+        
+
+
+[
+  logs-*,
+  cluster_one:logstash-*,
+  new-target
+]
+        
+
Keep user changes to any element, but add prepended elements +
+[
+  logs-*,
+  logstash-*
+]
+        
+
+
+[
+  logs-*,
+  cluster_one:logstash-*
+]
+        
+
+
+[
+  pre-target,
+  logs-*,
+  logstash-*,
+]
+        
+
+
+[
+  pre-target,
+  logs-*,
+  cluster_one:logstash-*,
+]
+        
+
Keep user changes to any element, but add insertions in middle +
+[
+  logs-*,
+  logstash-*
+]
+        
+
+
+[
+  cluster_one:logs-*,
+  cluster_one:logstash-*
+]
+        
+
+
+[
+  logs-*,
+  middle-target,
+  logstash-*,
+]
+        
+
+
+[
+  cluster_one:logs-*,
+  middle-target,
+  cluster_one:logstash-*
+]
+        
+
Keep elements removed in the target version if they have been customized by user +
+[
+  logs-*,
+  logstash-*
+]
+        
+
+
+[
+  cluster_one:logs-*,
+  cluster_one:logstash-*
+]
+        
+
+
+[
+  logs-*,
+]
+        
+
+
+[
+  cluster_one:logs-*,
+  cluster_one:logstash-*
+]
+        
+
+ +##### Number fields + +Examples: `risk_score`, `max_signals` + + + + + + + + + + + + + + + + + +
Use caseBase versionCurrent versionTarget versionMerged version (output)
Keep customizations if conflict50652065
+##### Complex objects or array of objects fields +Examples: `threat` (Mitre Threat), `required_fields` + + + + + + + + + + + + + + + + + + + +
Use caseBase versionCurrent versionTarget versionMerged version (output)
Keep user customizations on conflicts, but update sections with no conflicts +
+{
+    "framework":"MITRE ATT&CK",
+    "tactic":{
+      "id":"TA0003",
+      "name":"Persistence",
+      "reference":"https://attack.mitre.org/tactics/TA0003/"
+    },
+    "technique":[
+      {
+          "id":"T1098",
+          "name":"Account Manipulation",
+          "reference":"https://attack.mitre.org/techniques/T1098/"
+      }
+    ]
+}
+        
+
+
+{
+    "framework":"MITRE ATT&CK",
+    "tactic":{
+      "id":"TA0003",
+      "name":"My customized name",
+      "reference":"https://attack.mitre.org/tactics/TA0003/My_custom_url"
+    },
+    "technique":[
+      {
+          "id":"T1098",
+          "name":"Account Manipulation",
+          "reference":"https://attack.mitre.org/techniques/T1098/"
+      }
+    ]
+}
+        
+
+
+{
+    "framework":"MITRE ATT&CK",
+    "tactic":{
+      "id":"TA0003",
+      "name":"Persistence",
+      "reference":"https://attack.mitre.org/tactics/TA0003/"
+    },
+    "technique":[
+      {
+          "id":"T1556",
+          "name":"Modify Authentication Process",
+          "reference":"https://attack.mitre.org/techniques/T1556/",
+          "subtechnique":[
+            {
+                "id":"T1556.006",
+                "name":"Multi-Factor Authentication",
+                "reference":"https://attack.mitre.org/techniques/T1556/006/"
+            }
+          ]
+      }
+    ]
+}
+        
+
+
+{
+    "framework":"MITRE ATT&CK",
+    "tactic":{
+      "id":"TA0003",
+      "name":"My customized name",
+      "reference":"https://attack.mitre.org/tactics/TA0003/My_custom_url"
+    },
+    "technique":[
+      {
+          "id":"T1556",
+          "name":"Modify Authentication Process",
+          "reference":"https://attack.mitre.org/techniques/T1556/",
+          "subtechnique":[
+            {
+                "id":"T1556.006",
+                "name":"Multi-Factor Authentication",
+                "reference":"https://attack.mitre.org/techniques/T1556/006/"
+            }
+          ]
+      }
+    ]
+}
+        
+
+**TODO:** +- Add examples to the above tables for `strings` +- Add a new table for `arrays` +- Think about how to solve: + - complex objects + - numbers +- Add tentative algorithms for all the above. Already something tentative for: + - strings + - arrays @@ -1978,7 +2349,7 @@ Examples: `name`, `description`, `setup`, `note` (Investigation guide) ### Rule field diff algorithms -TODO + ## Scenarios for bulk accepting updates diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/model/rule_assets/prebuilt_rule_asset.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/model/rule_assets/prebuilt_rule_asset.ts index ce9bf62d53a6b1..101679122d546d 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/model/rule_assets/prebuilt_rule_asset.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/model/rule_assets/prebuilt_rule_asset.ts @@ -9,7 +9,7 @@ import * as z from 'zod'; import { RelatedIntegrationArray, RequiredFieldArray, - ElasticUpdateDate, + ExternalSourceUpdatedAt, SetupGuide, RuleSignatureId, RuleVersion, @@ -39,6 +39,6 @@ export const PrebuiltRuleAsset = BaseCreateProps.and(TypeSpecificCreateProps).an related_integrations: RelatedIntegrationArray.optional(), required_fields: RequiredFieldArray.optional(), setup: SetupGuide.optional(), - source_updated_at: ElasticUpdateDate.optional(), + source_updated_at: ExternalSourceUpdatedAt.optional(), }) ); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_schema/model/rule_schemas.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_schema/model/rule_schemas.ts index c175ed3a7cab56..f65fef4cbe7c27 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_schema/model/rule_schemas.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_schema/model/rule_schemas.ts @@ -39,7 +39,7 @@ import { InvestigationFields, InvestigationGuide, IsRuleImmutable, - Prebuilt, + RuleSource, MaxSignals, RelatedIntegrationArray, RequiredFieldArray, @@ -121,7 +121,7 @@ export const BaseRuleParams = z.object({ ruleId: RuleSignatureId, investigationFields: InvestigationFieldsCombined.optional(), immutable: IsRuleImmutable, - prebuilt: Prebuilt.optional(), + ruleSource: RuleSource.optional(), license: RuleLicense.optional(), outputIndex: AlertsIndex, timelineId: TimelineTemplateId.optional(), From 275c36d3878e36c3228290dd9868956466955021 Mon Sep 17 00:00:00 2001 From: jpdjere Date: Thu, 22 Feb 2024 17:51:18 +0100 Subject: [PATCH 20/61] Part 2: Add algorithm for solving array changes --- .../docs/prebuilt_rules_customization_rfc.md | 451 +++++++++++++++++- 1 file changed, 427 insertions(+), 24 deletions(-) diff --git a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md index da49e695014cb9..6ed439f1e7f683 100644 --- a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md +++ b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md @@ -1985,9 +1985,9 @@ Examples: `name`, `description`, `setup`, `note` (Investigation guide) -##### Array fields +##### Array of string fields -For array fields, conflict resolution will take place on an element by element basis - that means that the algorithm will not consider or try to solve changes within a single element. For example: +For array of strings fields, conflict resolution will take place on an element by element basis - that means that the algorithm will not consider or try to solve changes within a single element. For example: ``` base: [test1] @@ -2218,11 +2218,426 @@ Examples: `risk_score`, `max_signals` -##### Complex objects or array of objects fields +##### Array of objects fields + +Since the fields in each object within the array are highly dependent on one another, the whole object should be treated as a block, and not attempt to diff or merge changes to individual fields within each element. + +For example: in a `required_fields` update, if the `type` is updated from `unknown` in the base version to `keyword` in the `target` version, but in the same object the user has updated the base `name` of the field, the change of type will have a high probability of not making sense anymore - there is no way of knowing if the change proposed by Elastic will also apply to the field name that the user is now referring through its customization. Therefore, we should prefer to keep the user's version for the whole block.(See the first element of the array in the first row of the column below). + +Examples: `related_integrations,` `required_fields` + +###### Proposed algorithm + +- Do element by element comparison: + - If element index exists in the three versions and the values: + - do not differ between all versions (base, current and target), **keep current** version. (A A A) + - do not differ between base and current, but updates target, **keep target** version. (A A B) + - differ between base and current, but doesn't update target, **keep current** version. (A B A) + - differ between base and current, updates target, **keep current** version. (A B B) + - differ between all version (base, current and target), **keep current** version. (A B C) + - If element index exists in base and current version, but not in target: + - If base differs from current: **keep current** version. (A B _) + - If base equals current: **remove element**. (A A _) + - If element index exists in base and target version, but not in current: + - Remove element. (A _ B) and (A _ A) + - If element index exists in current and target version, but not in base: + - If base equals current: **add element/keep target**. (_ A A) + - If base differs from current: **keep both current and target**. (_ A B) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Use caseBase versionCurrent versionTarget versionMerged version (output)
Keep user changes if element conflicts, but apply changes in elements with clean updates
(A B C - keep current) and (A A B - keep target)

Same for:
  • (A B C) and (A B A - keep current)
  • (A B C) and (A B B - keep current/target)
+
+[
+  {
+    ecs: true,
+    name: "event.action",
+    type: "unknown"
+  },
+  {
+    ecs: false,
+    name: "host.os.type",
+    type: "keyword"
+  },
+]
+        
+
+
+[
+  {
+    ecs: true,
+    name: "event.UPDATED",
+    type: "unknown"
+  },
+  {
+    ecs: false,
+    name: "host.os.type",
+    type: "keyword"
+  },
+]
+        
+
+
+[
+  {
+    ecs: true,
+    name: "event.action",
+    type: "keyword"
+  },
+  {
+    ecs: false,
+    name: "host.user.id",
+    type: "keyword"
+  },
+]
+        
+
+
+[
+  {
+    ecs: true,
+    name: "event.UPDATED",
+    type: "unknown"
+  },
+  {
+    ecs: false,
+    name: "host.user.id",
+    type: "keyword"
+  },
+]
+        
+
Keep user changes if element conflicts, and remove any uncustomized elements if removed in update

(A B C) and (A A _ - remove element)
+
+[
+  {
+    ecs: true,
+    name: "event.action",
+    type: "unknown"
+  },
+  {
+    ecs: false,
+    name: "host.os.type",
+    type: "keyword"
+  },
+]
+        
+
+
+[
+  {
+    ecs: true,
+    name: "event.UPDATED",
+    type: "unknown"
+  },
+  {
+    ecs: false,
+    name: "host.os.type",
+    type: "keyword"
+  },
+]
+        
+
+
+[
+  {
+    ecs: true,
+    name: "event.action",
+    type: "keyword"
+  }
+]
+        
+
+
+[
+  {
+    ecs: true,
+    name: "event.UPDATED",
+    type: "unknown"
+  }
+]
+        
+
Keep user changes if element conflicts, but keep any customized elements if removed in update

(A B C) and (A B _ - keep current)
+
+[
+  {
+    ecs: true,
+    name: "event.action",
+    type: "unknown"
+  },
+  {
+    ecs: false,
+    name: "host.os.type",
+    type: "keyword"
+  },
+]
+        
+
+
+[
+  {
+    ecs: true,
+    name: "event.UPDATED",
+    type: "unknown"
+  },
+  {
+    ecs: false,
+    name: "host.user.id",
+    type: "keyword"
+  },
+]
+        
+
+
+[
+  {
+    ecs: true,
+    name: "event.action",
+    type: "keyword"
+  }
+]
+        
+
+
+[
+  {
+    ecs: true,
+    name: "event.UPDATED",
+    type: "unknown"
+  },
+  {
+    ecs: false,
+    name: "host.user.id",
+    type: "keyword"
+  },
+]
+        
+
Keep user changes if element conflicts and add new matching element

(A B C) and (_ A A - keep current/target)
+
+[
+  {
+    ecs: true,
+    name: "event.action",
+    type: "unknown"
+  }
+]
+        
+
+
+[
+  {
+    ecs: true,
+    name: "event.UPDATED",
+    type: "unknown"
+  },
+  {
+    ecs: false,
+    name: "my.new.field",
+    type: "keyword"
+  }
+]
+        
+
+
+[
+  {
+    ecs: true,
+    name: "event.action",
+    type: "keyword"
+  },
+  {
+    ecs: false,
+    name: "my.new.field",
+    type: "keyword"
+  },
+]
+        
+
+
+[
+  {
+    ecs: true,
+    name: "event.UPDATED",
+    type: "unknown"
+  },
+  {
+    ecs: false,
+    name: "my.new.field",
+    type: "keyword"
+  } ,
+]
+        
+
Keep user changes if element conflicts and add both new conflicting elements

(A B C) and (_ A B - keep both current and target)
+
+[
+  {
+    ecs: true,
+    name: "event.action",
+    type: "unknown"
+  }
+]
+        
+
+
+[
+  {
+    ecs: true,
+    name: "event.UPDATED",
+    type: "unknown"
+  },
+  {
+    ecs: false,
+    name: "my.new.field",
+    type: "keyword"
+  },
+]
+        
+
+
+[
+  {
+    ecs: true,
+    name: "event.action",
+    type: "keyword"
+  },
+  {
+    ecs: true,
+    name: "new.elastic.ip",
+    type: "ip"
+  }
+]
+        
+
+
+[
+  {
+    ecs: true,
+    name: "event.UPDATED",
+    type: "unknown"
+  },
+  {
+    ecs: false,
+    name: "host.user.id",
+    type: "keyword"
+  },
+  {
+    ecs: true,
+    name: "process.executable",
+    type: "keyword"
+  },
+]
+        
+
Keep user changes if element conflicts and remove element removed by user

(A B C) and (A _ A - remove element)
(A B C) and (A _ B - remove element)
+
+[
+  {
+    ecs: true,
+    name: "event.action",
+    type: "unknown"
+  },
+  {
+    ecs: true,
+    name: "process.executable",
+    type: "string"
+  }
+]
+        
+
+
+[
+  {
+    ecs: true,
+    name: "event.UPDATED",
+    type: "unknown"
+  }
+]
+        
+
+
+[
+  {
+    ecs: true,
+    name: "event.action",
+    type: "keyword"
+  },
+  {
+    ecs: true,
+    name: "process.executable.ip",
+    type: "ip"
+  }
+]
+        
+
+
+[
+  {
+    ecs: true,
+    name: "event.UPDATED",
+    type: "unknown"
+  }
+]
+        
+
-Examples: `threat` (Mitre Threat), `required_fields` +##### MITRE ATT&CK framework (`threat` field) +The `threat` field has a specific [schema](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/common_attributes.gen.ts#L250) that can be handled with its own algorithm in case of conflicts, in order to try to obtain the most reasonable merge between versions. + +The `threat`` + +Examples: `threat` (Mitre Threat), `required_fields` @@ -2238,7 +2653,7 @@ Examples: `threat` (Mitre Threat), `required_fields`
Keep user customizations on conflicts, but update sections with no conflicts
-{
+[{
     "framework":"MITRE ATT&CK",
     "tactic":{
       "id":"TA0003",
@@ -2252,12 +2667,12 @@ Examples: `threat` (Mitre Threat), `required_fields`
           "reference":"https://attack.mitre.org/techniques/T1098/"
       }
     ]
-}
+}]
         
-{
+[{
     "framework":"MITRE ATT&CK",
     "tactic":{
       "id":"TA0003",
@@ -2271,12 +2686,12 @@ Examples: `threat` (Mitre Threat), `required_fields`
           "reference":"https://attack.mitre.org/techniques/T1098/"
       }
     ]
-}
+}]
         
-{
+[{
     "framework":"MITRE ATT&CK",
     "tactic":{
       "id":"TA0003",
@@ -2297,12 +2712,12 @@ Examples: `threat` (Mitre Threat), `required_fields`
           ]
       }
     ]
-}
+}]
         
-{
+[{
     "framework":"MITRE ATT&CK",
     "tactic":{
       "id":"TA0003",
@@ -2323,25 +2738,13 @@ Examples: `threat` (Mitre Threat), `required_fields`
           ]
       }
     ]
-}
+}]
         
-**TODO:** -- Add examples to the above tables for `strings` -- Add a new table for `arrays` -- Think about how to solve: - - complex objects - - numbers -- Add tentative algorithms for all the above. Already something tentative for: - - strings - - arrays - - - From 440ac2abdbf02e57b711786cdeb1584a0ebc061c Mon Sep 17 00:00:00 2001 From: jpdjere Date: Thu, 22 Feb 2024 17:54:55 +0100 Subject: [PATCH 21/61] Part 2: Typo --- .../docs/prebuilt_rules_customization_rfc.md | 25 ++----------------- 1 file changed, 2 insertions(+), 23 deletions(-) diff --git a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md index 6ed439f1e7f683..9649fb71c92580 100644 --- a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md +++ b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md @@ -1935,7 +1935,7 @@ The algorithm for calculating rule version diffs' core structure is [fully imple We propose developing more adaptable diff algorithms tailored to specific rule fields or rule field types. These more specific algorithms aim to minimize conflicts and automate merging of changes, doing the best effort to keep the intended customizations applied by the user, as well as the updates proposed by Elastic. Hopefully, the user will be able to simply review the proposal and accept it. -#### Concrete field diff algorithm by type +#### Concrete field diff algorithms by type Depending on the specific field or type of field we might want to apply a specific merging algorithm when conflicts arise. Let's propose different types. @@ -2635,9 +2635,8 @@ Examples: `related_integrations,` `required_fields` The `threat` field has a specific [schema](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/common_attributes.gen.ts#L250) that can be handled with its own algorithm in case of conflicts, in order to try to obtain the most reasonable merge between versions. -The `threat`` +TODO: write algorithm specific to this field -Examples: `threat` (Mitre Threat), `required_fields` @@ -2750,8 +2749,6 @@ Examples: `threat` (Mitre Threat), `required_fields` ### Changes to upgrade `_perform` endpoints -### Rule field diff algorithms - @@ -2769,22 +2766,4 @@ Examples: `threat` (Mitre Threat), `required_fields` Create a user config/setting that the user can turn on to accept updates automatically if there are no conflicts. Or we should more concretely how we want this setting to behave -## Marking rules (and their fields) as customized - -We’d like to know if the rules has been customized in any way (at least 1 field modified from the base version) in order to mark the rule as “customized” - -- Use the `customized` - IDEALLY: -- Know specifically which fields have been customized. -- How the fields have been customized, show their diffs. - -- To keep track of how the rule has changed - - Introduce a new endpoint that calculates the diffs for the required fields. We could have new tab in the Rules Flyout tab that only calls an endpoint when it is opened. This endpoint would calcualte which fields where modified and return the base and current versions for each. - - **\*\***PROs:**\*\*** - - We don’t need to keep track of which fields were customized in the SO, and no changes to the rule schema are changed. - - Most of the logic for the endpoint needed is already implemented. - - **\*\*\*\***CONs:**\*\*\*\*** - - We do not keep in the SO the list of which rules were customized. This stops us from showing, in the Rules Detail page, which fields were customized, at least wihtout making an additional call to the backend, to calculate diffs. - - We can solve this by making a non-blocking request to the endpoint after the page loads. Alternatively, show it only when the user opens a flyout desgined to show these diffs. - ## Other open questions From 5842ce7f153f28bb78a86c72fecee314eb8ab8db Mon Sep 17 00:00:00 2001 From: jpdjere Date: Fri, 23 Feb 2024 12:33:55 +0100 Subject: [PATCH 22/61] Part 2: Merged array of strings and objects algorithms --- .../docs/prebuilt_rules_customization_rfc.md | 415 ++++++++++-------- 1 file changed, 222 insertions(+), 193 deletions(-) diff --git a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md index 9649fb71c92580..e3e3438aa534d5 100644 --- a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md +++ b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md @@ -1941,6 +1941,8 @@ Depending on the specific field or type of field we might want to apply a specif ##### String fields +For string fields, in case of three-way conflicts, we will make a best effort to reconcile any modifications done by the user and any updates proposed by Elastic. + Examples: `name`, `description`, `setup`, `note` (Investigation guide)
@@ -1985,9 +1987,39 @@ Examples: `name`, `description`, `setup`, `note` (Investigation guide)
-##### Array of string fields -For array of strings fields, conflict resolution will take place on an element by element basis - that means that the algorithm will not consider or try to solve changes within a single element. For example: +##### Number fields + +Number fields should be treated as a whole unit, i.e. not breakable by digits. Therefore, there is only one possibility of conflicts, the scenario (A B C). In that case, **keep the current version** with the user customization. + +Examples: `risk_score`, `max_signals` + + + + + + + + + + + + + + + + + + + + +
Use caseBase versionCurrent versionTarget versionMerged version (output)
Keep customizations if conflict50652065
+ +##### Array fields + +###### Array of strings fields + +For **array of strings** fields, conflict resolution will take place on an element by element basis - that means that the algorithm will not consider or try to solve changes within a single element. For example: ``` base: [test1] @@ -1995,10 +2027,44 @@ current: [my-test1] target: [test2] output: [my-test1] ``` -The example above shows that the algorithm should understand the above scenario as a conflict and not try to merge the single element by breaking it into parts. +Therefor the example above, the algorithm should not try to merge the single string element by breaking it into parts. + +Example **array of strings** fields: `index`, `tags`, `references`, + +###### Array of objects fields + +Since the properties in each object within the array are highly dependent on one another, the whole object should be treated as a block, and not attempt to diff or merge changes to individual fields within each element. + +For example: in a `required_fields` update, if the `type` is updated from `unknown` in the base version to `keyword` in the `target` version, but in the same object the user has updated the base `name` of the field, the change of type will have a high probability of not making sense anymore - there is no way of knowing if the change proposed by Elastic will also apply to the field name that the user is now referring through its customization. -Example fields: `index`, `tags`, `references`, +Therefore, we should prefer to keep the user's version for the whole block.(See this example in the first element of the array in the first row of the table below). +Examples: `related_integrations,` `required_fields` + +###### Proposed algorithm + +- Do element by element comparison: + - If element index exists in the three versions and the values: + - do not differ between all versions (base, current and target), **keep current** version. (A A A) + - do not differ between base and current, but updates target, **keep target** version. (A A B) + - differ between base and current, but doesn't update target, **keep current** version. (A B A) + - differ between base and current, updates target, **keep current** version. (A B B) + - differ between all version (base, current and target), **keep current** version. (A B C) + - If element index exists in base and current version, but not in target: + - If base differs from current: **keep current** version. (A B _) + - If base equals current: **remove element**. (A A _) + - If element index exists in base and target version, but not in current: + - **Remove element**. (A _ B) and (A _ A) + - If element index exists in current and target version, but not in base: + - If base equals current: **add element/keep target**. (_ A A) + - If base differs from current: **keep both current and target**. (_ A B) + - If element index exists only in base version: + - **Remove element** (A _ _) + - If element index exists only in current version: + - **Keep current version** (_ A _) + - If element index exists only in target version: + - **Keep target version** (_ _ A) + @@ -2011,7 +2077,7 @@ Example fields: `index`, `tags`, `references`, - + - - + - - + @@ -2190,73 +2302,7 @@ Example fields: `index`, `tags`, `references`, - -
Keep user changes if all elements conflictKeep user changes if element conflicts, but apply changes in elements with clean updates

  • 1st elem: (A B C - keep current)
  • 2nd elem: (A A B - keep target)


Same for:
  • 1st elem: (A B C) + 2nd elem: (A B A - keep current)
  • 1st elem: (A B C) + 2nd elem: (A B B - keep current/target)
 [
@@ -2046,44 +2112,73 @@ Example fields: `index`, `tags`, `references`,
       
Keep user changes to any element, but add appended elements
 [
-  logs-*,
-  logstash-*
+  {
+    ecs: true,
+    name: "event.action",
+    type: "unknown"
+  },
+  {
+    ecs: false,
+    name: "host.os.type",
+    type: "keyword"
+  },
 ]
         
 [
-  logs-*,
-  cluster_one:logstash-*
+  {
+    ecs: true,
+    name: "event.UPDATED",
+    type: "unknown"
+  },
+  {
+    ecs: false,
+    name: "host.os.type",
+    type: "keyword"
+  },
 ]
         
 [
-  logs-*,
-  logstash-*,
-  new-target
+  {
+    ecs: true,
+    name: "event.action",
+    type: "keyword"
+  },
+  {
+    ecs: false,
+    name: "host.user.id",
+    type: "keyword"
+  },
 ]
         
 [
-  logs-*,
-  cluster_one:logstash-*,
-  new-target
+  {
+    ecs: true,
+    name: "event.UPDATED",
+    type: "unknown"
+  },
+  {
+    ecs: false,
+    name: "host.user.id",
+    type: "keyword"
+  },
 ]
         
Keep user changes to any element, but add prepended elementsKeep user changes if element conflicts, and remove any uncustomized elements if removed in update

  • 1st elem: (A B C - keep current)
  • 2nd elem: (A A _ - remove element)
 [
@@ -2095,69 +2190,86 @@ Example fields: `index`, `tags`, `references`,
       
 [
-  logs-*,
-  cluster_one:logstash-*
+  cluster_one:logs-*,
+  logstash-*
 ]
         
 [
-  pre-target,
-  logs-*,
-  logstash-*,
+  logs-new-*,
 ]
         
 [
-  pre-target,
-  logs-*,
-  cluster_one:logstash-*,
+  cluster_one:logs-*
 ]
         
Keep user changes to any element, but add insertions in middle
 [
-  logs-*,
-  logstash-*
+  {
+    ecs: true,
+    name: "event.action",
+    type: "unknown"
+  },
+  {
+    ecs: false,
+    name: "host.os.type",
+    type: "keyword"
+  },
 ]
         
 [
-  cluster_one:logs-*,
-  cluster_one:logstash-*
+  {
+    ecs: true,
+    name: "event.UPDATED",
+    type: "unknown"
+  },
+  {
+    ecs: false,
+    name: "host.os.type",
+    type: "keyword"
+  },
 ]
         
 [
-  logs-*,
-  middle-target,
-  logstash-*,
+  {
+    ecs: true,
+    name: "event.action",
+    type: "keyword"
+  }
 ]
         
 [
-  cluster_one:logs-*,
-  middle-target,
-  cluster_one:logstash-*
+  {
+    ecs: true,
+    name: "event.UPDATED",
+    type: "unknown"
+  }
 ]
         
Keep elements removed in the target version if they have been customized by userKeep user changes if element conflicts, but keep any customized elements if removed in update

+
  • 1st elem: (A B C - keep current)
  • 2nd elem: (A B _ - keep current)
+
 [
@@ -2177,7 +2289,7 @@ Example fields: `index`, `tags`, `references`,
       
 [
-  logs-*,
+  logs-new-*,
 ]
         
- -##### Number fields - -Examples: `risk_score`, `max_signals` - - - - - - - - - - - - - - - - - - - - -
Use caseBase versionCurrent versionTarget versionMerged version (output)
Keep customizations if conflict50652065
- -##### Array of objects fields - -Since the fields in each object within the array are highly dependent on one another, the whole object should be treated as a block, and not attempt to diff or merge changes to individual fields within each element. - -For example: in a `required_fields` update, if the `type` is updated from `unknown` in the base version to `keyword` in the `target` version, but in the same object the user has updated the base `name` of the field, the change of type will have a high probability of not making sense anymore - there is no way of knowing if the change proposed by Elastic will also apply to the field name that the user is now referring through its customization. Therefore, we should prefer to keep the user's version for the whole block.(See the first element of the array in the first row of the column below). - -Examples: `related_integrations,` `required_fields` - -###### Proposed algorithm - -- Do element by element comparison: - - If element index exists in the three versions and the values: - - do not differ between all versions (base, current and target), **keep current** version. (A A A) - - do not differ between base and current, but updates target, **keep target** version. (A A B) - - differ between base and current, but doesn't update target, **keep current** version. (A B A) - - differ between base and current, updates target, **keep current** version. (A B B) - - differ between all version (base, current and target), **keep current** version. (A B C) - - If element index exists in base and current version, but not in target: - - If base differs from current: **keep current** version. (A B _) - - If base equals current: **remove element**. (A A _) - - If element index exists in base and target version, but not in current: - - Remove element. (A _ B) and (A _ A) - - If element index exists in current and target version, but not in base: - - If base equals current: **add element/keep target**. (_ A A) - - If base differs from current: **keep both current and target**. (_ A B) - - - - - - - - - - - - - @@ -2323,64 +2364,42 @@ Examples: `related_integrations,` `required_fields` - + - @@ -2407,9 +2421,9 @@ Examples: `related_integrations,` `required_fields` }, { ecs: false, - name: "host.user.id", + name: "my.new.field", type: "keyword" - }, + } ] @@ -2420,7 +2434,12 @@ Examples: `related_integrations,` `required_fields` ecs: true, name: "event.action", type: "keyword" - } + }, + { + ecs: false, + name: "my.new.field", + type: "keyword" + }, ] @@ -2434,77 +2453,51 @@ Examples: `related_integrations,` `required_fields` }, { ecs: false, - name: "host.user.id", + name: "my.new.field", type: "keyword" - }, + } , ] - + - - + + + + + + + @@ -633,12 +657,12 @@ The resulting values for `immutable` and `rule_source` when calling these endpoi @@ -651,14 +675,14 @@ The resulting values for `immutable` and `rule_source` when calling these endpoi @@ -671,14 +695,14 @@ The resulting values for `immutable` and `rule_source` when calling these endpoi @@ -686,25 +710,25 @@ The resulting values for `immutable` and `rule_source` when calling these endpoi @@ -712,25 +736,25 @@ The resulting values for `immutable` and `rule_source` when calling these endpoi @@ -738,25 +762,25 @@ The resulting values for `immutable` and `rule_source` when calling these endpoi @@ -764,25 +788,25 @@ The resulting values for `immutable` and `rule_source` when calling these endpoi From e722c10a65ae92ca956005a53629f81f9a6f6886 Mon Sep 17 00:00:00 2001 From: Juan Pablo Djeredjian Date: Mon, 18 Mar 2024 17:02:47 +0100 Subject: [PATCH 35/61] Addressing feedback --- .../docs/prebuilt_rules_customization_rfc.md | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md index d627a9968b8a29..c2b8ab56109320 100644 --- a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md +++ b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md @@ -180,7 +180,7 @@ Custom rules will have: }; } ``` -### Deprecating the `immutable` field +### `immutable` field In the current application's state, rules with `immutable: false` are rules which are not Elastic Prebuilt Rules, i.e. custom rules, and can be modified. Meanwhile, `immutable: true` rules are Elastic Prebuilt Rules, created by the TRaDE team, distributed via the `security_detection_engine` Fleet package, and cannot be modified once installed. @@ -188,10 +188,6 @@ When successfully implemented, the `rule_source` field should replace the `immut Because of this difference between the `rule_source` and `immutable` fields, the `immutable` field will lose its original meaning as soon as we allow users to customize prebuilt rules, which might become confusing for those API consumers who interact directly with this field. That's why we want to first deprecate it and later after a large enough deprecation period we could consider removing it completely from the API. -To ensure backward compatibility and avoid breaking changes, we will deprecate the `immutable` field but keep it within the rule schema, asking our users to stop relying on this field in Detection API responses. During the migration period, we want to keep the value of the `immutable` field in sync with the `rule_source` fields: this means that for all rules that have a `immutable` value of `true`, the `rule_source` field will always be of type `'external'`. Viceversa, rules with `immutable: false` will have a `rule_source` field of type `'internal'`. - -This means, however, that there will be a change in behaviour of the `immutable` field: with the release of the feature, rules with the `immutable: true` value will now be customizable by the user, which is not the current behaviour. - ### Changes needed in rule schema As detailed further down in the [Plan for carrying out migrations of rule SOs](#plan-for-carrying-out-migrations-of-rule-sos) section, we will be performing incremental migration-on-write on our saved objects to get to our new schemas (see details in linked section). @@ -369,6 +365,10 @@ export const PrebuiltRuleAsset = BaseCreateProps.and(TypeSpecificCreateProps).an ### Deprecating the `immutable` field +To ensure backward compatibility and avoid breaking changes, we will deprecate the `immutable` field but keep it within the rule schema, asking our users to stop relying on this field in Detection API responses. During the migration period, we want to keep the value of the `immutable` field in sync with the `rule_source` fields: this means that for all rules that have a `immutable` value of `true`, the `rule_source` field will always be of type `'external'`. Viceversa, rules with `immutable: false` will have a `rule_source` field of type `'internal'`. + +This means, however, that there will be a change in behaviour of the `immutable` field: with the release of the feature, rules with the `immutable: true` value will now be customizable by the user, which is not the current behaviour. + In order to mark the `immutable` field as deprecated, and making sure that our application and API users are aware that the field has been deprecated and replaced by the `rule_source` field, we will communicate this change in three ways: 1. via updates to the documentation of all endpoints that return `RuleResponse` types @@ -478,13 +478,6 @@ interface OnReadNormalizationResult { rule_source: RuleSource } -/** - * To calculate `rule_source`: - * - Use `rule_source` field if already exists in the internal rule object params. - * - If it does not exist, check the value `immutable` from the rules param: - * - if it is `true`, create a new `rule_source` object, with `isCustomized` set to `false` and `repoNam` set to `elastic_prebuilt` (Use case of rule_source rules that have not been yet migrated-on-write) - * - otherwise, the field should be `undefined` (use case of custom rules). - */ const getRuleSourceValueForRuleRead = (ruleParams: BaseRuleParams): RuleSource | undefined => { if (ruleParams.rule_source) { return ruleParams.rule_source; From 072d0092a8d1ddc531519615622a70872c080bd1 Mon Sep 17 00:00:00 2001 From: jpdjere Date: Mon, 18 Mar 2024 17:29:09 +0100 Subject: [PATCH 36/61] Addressing feedback --- .../security_solution/docs/prebuilt_rules_customization_rfc.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md index c2b8ab56109320..58759a31b2d0f0 100644 --- a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md +++ b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md @@ -320,7 +320,7 @@ export const RuleToImport = BaseCreateProps.and(TypeSpecificCreateProps).and( #### Internal rule schema -**The internal rule schema** needs to represent that the new `ruleSource` field may not always exist, so both need to be optional. +**The internal rule schema** needs to represent that the new `ruleSource` field may not always exist, so it must be optional. _Source: [x-pack/plugins/security_solution/server/lib/detection_engine/rule_schema/model/rule_schemas.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_schema/model/rule_schemas.ts)_ From 9481602fd68f0cfc7753e58aa557c8b35eef520d Mon Sep 17 00:00:00 2001 From: Juan Pablo Djeredjian Date: Mon, 18 Mar 2024 17:58:06 +0100 Subject: [PATCH 37/61] Addressing feedback --- .../docs/prebuilt_rules_customization_rfc.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md index 58759a31b2d0f0..93030aad70f6f7 100644 --- a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md +++ b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md @@ -535,9 +535,7 @@ export const normalizePrebuiltSchemaOnRuleRead = ( This type of migration will be in charge of updating saved object fields in Elasticsearch from the legacy form to the new form, and will be performed on all write operations of the rules (see list below). This means that we need to perform this type of migration of rules whenever any endpoint operation that writes/updates a rule saved object is called. -> In Elasticsearch, the type of rule saved objects is called `alert`. - -This migration strategy of write/update operations means that a user's data will be migrated incrementally, and that both types of data (non-migrated and migrated saved objects) will coexist for an indeterminate amount of time. Therefore we have to maintain backwards data compatibility for the non-migrated data types. +This migration strategy means that rules will be migrated incrementally, and that both non-migrated and migrated rules will coexist for an indeterminate amount of time. Therefore we have to maintain backwards compatibility with non-migrated rules. The migration logic should take place within the handler logic of all endpoints that carry out write/update endpoint operations, and the endpoint should return the already-migrated rule(s). @@ -562,7 +560,7 @@ For the **bulk edit** action, we can take advantage of the `ruleParamsModifier` For the **duplicate** rule action: -Since we will be creating a new rule on ES, we should create it with the new schema. Per definition, all duplicated rules will be `custom` rules. That means that for all rules -including prebuilt rules-, when duplicating, the `rule_source` field will not be created on the newly created rule. +Since we will be creating a new rule on ES, we should create it with the new schema. Per definition, all duplicated rules will be `custom` rules. That means that all duplicated rules (the duplicates) should get a `rule_source` of type `internal`. This action will not perform a migration-on-write of the original rule being duplicated for two reasons: - it would violate the principle of least surprise for the endpoint From c0da34f447ca56f5186839b3e4c07c97801a32d5 Mon Sep 17 00:00:00 2001 From: jpdjere Date: Mon, 18 Mar 2024 18:52:02 +0100 Subject: [PATCH 38/61] Added table for migration type --- .../docs/prebuilt_rules_customization_rfc.md | 71 +++++++------------ 1 file changed, 24 insertions(+), 47 deletions(-) diff --git a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md index 93030aad70f6f7..9f9cdd44ade498 100644 --- a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md +++ b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md @@ -436,6 +436,29 @@ As part of the epic, we should move away from this practice and create new CRUD Our migration strategy will consist of two distinct types of migration: a **migration on write** that will update the SO on Elasticsearch, and a **normalization on read**, which will transform legacy rules to the new schema **in memory** on read operations, before returning it as a response from an API endpoint. + + +| API endpoint | Normalization-on-read | Migration-on-write | Comments | +|-|-|-|-| +| **Find Rules** - `GET /rules/_find` |
|
| | +| **Read Rule** - `GET /rules` |
|
| | +| **Delete Rules** - `DELETE /rules` |
|
| | +| **Export Rules** - `POST /rules/_export` |
|
| - Endpoints is unused in UI, still used via public API
- See section [Exporting rules](#exporting-rules) | +| **Import Rules** - `POST /rules/_import` |
|
| - See section [Importing rules](#importing-rules) | +| **Update Rule** - `PUT /rules`|
|
| - Used in the UI when updating/modifying a single rule via the Rule Editing page | +| **Patch Rule** - `PATCH /rules`|
|
| - Used in the UI for attaching shared exceptions list to rules | +| **Bulk Update Rules** - `PUT /rules/_bulk_update`|
|
| - Deprecated and unused by the UI. Might still be used by API users | +| **Bulk Patch Rules** - `PATCH /rules/_bulk_update`|
|
| - Deprecated and unused by the UI. Might still be used by API users | +| **Perform Rule Upgrade** - `POST /prebuilt_rules/upgrade/_perform` (Internal) |
|
| - Current way of upgrading a prebuilt rule | +| **(LEGACY) Install Prebuilt Rules And Timelines** - `PUT /rules/prepackaged` |
|
| - Legacy endpoint for installing prebuilt rules and updating rules. | +|**Bulk Actions** - `POST /rules/_bulk_action`: | | | This endpoint includes a `dry_run` mode that is executed to evaluate preconditions and warn the user before executing the actual request. No migration logic should take place for dry run requests, i.e when `dry_run=true`, since we never write to ES when this parameter is set to `true`.| +|
  • _**Enable and disable action**_
  • |
    |
    | - Migration-on-write is technically possible but should be done on Alerting Framework side. | +|
  • _**Delete action**_
  • |
    |
    | - Deletes ES object but returns deleted rules data, so so normalization-on-read is enough. | +|
  • _**Export action**_
  • |
    |
    | - See section [Exporting rules](#exporting-rules) | +|
  • _**Duplicate rule action**_
  • |
    |
    | - Per definition, all duplicated rules will be `custom` rules. That means that all duplicated rules (the duplicates) are newly created and should get a `rule_source` of type `internal`, and no migration or normalization is neccessary. | +|
  • _**Edit rule action**_
  • |
    |
    | - No normalization-on-read is needed since endpoint doesn't return whole rule object
    - We can take advantage of the `ruleParamsModifier` to carry out the migration-on-write, regardless of the type of edit that is being performed.
    - See implementation details in the [Bulk editing rules](#bulk-editing-rules) section. + + #### Normalization on read All endpoints that respond with a rule Saved Object, typed as `RuleResponse`, will perform **normalization on read**, which will transform legacy rules to the new schema **in memory** on read operation, before returning it as a response from an API endpoint. @@ -516,20 +539,6 @@ export const normalizePrebuiltSchemaOnRuleRead = ( }; ``` -##### Rule Management endpoints that will perform normalization-on-read - -- All endpoints that also perform migration-on-write, as listed in the below `Migration on write` section. All of them use the `internalRuleToAPIResponse` methods to transform the rule before returning the response, so the normalization on read will take place there. For these specific cases, however, the normalization-on-read will take place, but the data stored in ES for each rule should match the response given by the endpoint, i.e. the normalized in-memory value and the stored value of the rule should be the same. -- **Find Rules - `GET /rules/_find`** -- **Read Rule - GET /rules:** -- **Delete Rules - DELETE /rules** -- **Bulk Actions** - `POST /rules/_bulk_action`: all other action types not mentioned in the previous section will perform normalization-on-read before responding: - - Enable - - Disable - - Delete - - Export: see Importing and Exporting Rules section below -- **Export Rules** - `POST /rules/_export`: - - this endpoint is unused via the UI, but might still be used via the public API - - same logic as for `_bulk_action` with the `export` action explained in section [Exporting rules](#exporting-rules) below: only normalization-on-read will be performed before writing to the output `ndjson` file. #### Migration on write @@ -539,39 +548,7 @@ This migration strategy means that rules will be migrated incrementally, and tha The migration logic should take place within the handler logic of all endpoints that carry out write/update endpoint operations, and the endpoint should return the already-migrated rule(s). -##### Rule Management endpoints that should include migration-on-write logic - -All of the following endpoints either fetch the rule before updating it, or send the rule's params as part of the body in the request. Therefore, we can apply migraton logic to them -as described below- before saving the rules to Elasticsearch. - -- **Update Rule** - `PUT /rules`: used in the UI when updating/modifying a single rule via the Rule Editing page -- **Patch Rule** - `PATCH /rules`: used in the UI for attaching shared exceptions list to rules -- **Bulk Update Rules** - `PUT /rules/_bulk_update`: deprecated and unused by the UI. Might still be used by API users -- **Bulk Patch Rules** - `PATCH /rules/_bulk_update`: deprecated and unused by the UI. Might still be used by API users -- **Import Rules** - `POST /rules/_import`: - - See section [Importing rules](#importing-rules) -- **Perform Rule Upgrade** - `POST /prebuilt_rules/upgrade/_perform` (Internal): current way of upgrading a prebuilt rule -- **(LEGACY) Install Prebuilt Rules And Timelines** - `PUT /rules/prepackaged`: legacy endpoint for installing prebuilt rules. Also updates existing prebuilt rules package, so these rules should be migrated during update as well. -- **Bulk Actions** - `POST /rules/_bulk_action`: - This endpoint includes many types of actions, but only the **bulk edit** and the **duplicate** actions should perform a migration on write. - -This endpoint also includes a `dry_run` mode that is executed to evaluate preconditions and warn the user before executing the actual request. No migration logic should take place for dry run requests, i.e when `dry_run=true`, since we never write to ES when this parameter is set to `true`. - -For the **bulk edit** action, we can take advantage of the `ruleParamsModifier` to carry out the migration, regardless of the type of edit that is being performed. See implementation details in the below [Bulk editing rules](#bulk-editing-rules) section. - -For the **duplicate** rule action: - -Since we will be creating a new rule on ES, we should create it with the new schema. Per definition, all duplicated rules will be `custom` rules. That means that all duplicated rules (the duplicates) should get a `rule_source` of type `internal`. -This action will not perform a migration-on-write of the original rule being duplicated for two reasons: - -- it would violate the principle of least surprise for the endpoint -- the current implementation of the endpoint does not modify the original rule. This gives us no window of opportunity to migrate the rule and save to ES without adding performance overhead. - -All other type of actions should **not** perform migration-on-write: - -- Enable -- Disable -- Delete -- Export: see Importing and Exporting Rules section below +Endpoints that perform migration-on-write either fetch the rule before updating it, or send the rule's params as part of the body in the request. Therefore, we can apply migraton logic to them -as described below- before saving the rules to Elasticsearch. ### Technical implementation of migration-on-write From 582bd8e8969d392dffb38b26e72ec3157ea72448 Mon Sep 17 00:00:00 2001 From: jpdjere Date: Mon, 18 Mar 2024 23:05:58 +0100 Subject: [PATCH 39/61] Addressing feedback --- .../docs/prebuilt_rules_customization_rfc.md | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md index 9f9cdd44ade498..020c0eadb2611e 100644 --- a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md +++ b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md @@ -799,14 +799,13 @@ Firstly, when bulk editing rules, the migration should be carried out for the fo - Bulk adding or deleting tags - Updating rule schedules - Adding rules actions - - Duplicating a rule (with the migration applied only to the new rule) Out of the actions mentioned above, the only use cases that should possibly result in the migration having a result of `rule_source.isCustomized = true` are the first three: - Bulk adding or deleting index patterns - Bulk adding or deleting tags - Updating rule schedules -That means that updating a rule's actions or duplicating a rule should not be considered a customization of a prebuilt rule. +That means that updating a rule's actions should not be considered a customization of a prebuilt rule. Secondly, in contrast with other endpoints, the migration for bulk editing rules needs to be carried within the Alerting Framework's `RuleClient` since we need to migrate the rule's `rule_source` and `immutable` parameters before the `RuleClient` does the saving of the rule into Elasticsearch. @@ -963,10 +962,6 @@ The calculation of the value for the `rule_source.is_customized` field for the u Again, this endpoint suffers from tightly coupled logic explained in [`Problem with tightly coupled logic in our endpoints`](#problem-with-tightly-coupled-logic-in-our-endpoints): it uses the `upgradePrebuiltRules` method to actually upgrade the rules, but this method either patches existing rules -for the normal case-, or deletes an existing rule and recreates it if the rule underwent a type change, using the `patchRules` and `createRules` methods respectively. We should decouple that logic by introducing a new CRUD method with a specific use case for upgrading prebuilt rule. -The changes in the `upgradePrebuiltRules` method need to take into account both paths. In the endpoint logic handler, when calculating if the rule was customized by the user, we will create a boolean called `isRuleCustomizedDuringUpgrade`, that can be passed as an argument to `upgradePrebuiltRules`: - -_Source: [x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_upgrade/perform_rule_upgrade_route.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_upgrade/perform_rule_upgrade_route.ts)_ - ### Rule monitoring endpoints - [**Detection Engine Health: Get Cluster Health** - `GET or POST /detection_engine/health/_cluster` (internal):](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/api/detection_engine_health/get_cluster_health/get_cluster_health_route.ts) @@ -1038,13 +1033,13 @@ The user will now be able to import both custom and prebuilt rules (including an We want to handle the case of importing both migrated and non-migrated rules via an `ndjson` file. -If a user imports a prebuilt rule, Kibana should continue to track the rule asset from the `security_detection_engine` package if the `rule_id` matches. This means that a user will be able to update a previously exported prebuilt rule, visualize any diffs on any customized fields, and continue to receive updates on the rule. +If a user imports a prebuilt rule, Kibana should continue to track the rule asset from the `security_detection_engine` package if the `rule_id` matches. This means that a user will be able to upgrade a previously imported prebuilt rule, visualize any diffs on any customized fields, and continue to receive updates on the rule. To allow for importing of Elastic prebuilt rules, we will **not rely** in the `rule_source` or the legacy `immutable` fields (which are not part of the import endpoint parameters), but we will rather **calculate them dynamically based on the `rule_id` and `version` request parameters**. The logic to importing a rule is as follows: - - First, read the import endpoint request parameters `rule_id` and `version`. These two are the two required parameters in the endpoint, while all other rule fields are optional. + - First, read the import endpoint request parameters `rule_id` and `version`. These two are two required parameters in the endpoint. - Secondly, check that the `security_detection_engine` Fleet package is installed and install it if it isn't. We will need the package to be installed to check if a rule that is being imported is an Elastic prebuilt rule. @@ -1053,7 +1048,7 @@ The logic to importing a rule is as follows: - **If a matching `rule_id` and `version` is found**, that means that the rule is an Elastic prebuilt rule, and we should therefore dynamically calculate the rule's `rule_source` field and its subfields: - `type`: should be always `external` since a matching external `security-rule` was found. - `source_updated_at`: can be retrieved from the corresponding `security-rule` asset. - - `is_customized`: should be calculated based on the `security-rule` asset's field and the field rules that were part of the import request parameters. If any of them are different, i.e. have diverged from the base version, `is_customized` should be true. + - `is_customized`: should be calculated based on the differences between the `security-rule` asset's fields and the rule fields from the import request. If any of them are different, i.e. have diverged from the base version, `is_customized` should be true. - Finally, using the import payload, plus the rule's `security-rule` asset fields and the calculated `rule_source` fields, create the rule, or update it if already exists in Kibana. From ac6ac12ddd838f6a195bd2c00d50572f56f5337d Mon Sep 17 00:00:00 2001 From: jpdjere Date: Mon, 18 Mar 2024 23:43:48 +0100 Subject: [PATCH 40/61] Addressing feedback --- .../docs/prebuilt_rules_customization_rfc.md | 28 +++++++++++++------ 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md index 020c0eadb2611e..bd4731bc210151 100644 --- a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md +++ b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md @@ -1052,7 +1052,19 @@ The logic to importing a rule is as follows: - Finally, using the import payload, plus the rule's `security-rule` asset fields and the calculated `rule_source` fields, create the rule, or update it if already exists in Kibana. -**If a matching `rule_id` is found, but the `version` is not found**, reject the import for that rule. Without a version, we cannot dynamically calculate `rule_source`. +**If a matching `rule_id` is found, but the `version` is not found**, it means there are some versions of this prebuilt rule known to Kibana, which means we should identify the rule being imported as prebuilt. The prebuilt rules package has a limit on the number of historical rule versions, and we can't assume that for a given rule_id we will always have ALL historical versions available as security-rule assets. + +In this case, we will the rule's params to be: +``` +{ + rule_source: { + type: 'external', + is_customized: false + }, + immutable: true +} +``` + **If a matching `rule_id` is NOT found**, that means that the rule is a custom rule. And `rule_source` will be simply: ``` @@ -1301,7 +1313,7 @@ Given the requirements described above, the following table shows the behaviour
    @@ -1458,10 +1470,10 @@ In both cases, the validation checks if the `immutable` param of the rule is `fa Depending on the endpoint, we will have to modify it to address multiple changes. These are: -**1. Introduction of migration logic**: as explained in the first section of this document, endpoints should have the additional reponsibility of migrating our rule schema. -**2. Calculation of the `is_customized` field**: this field which is part of the `rule_source` field for external rules needs to be recalculated whenever a rule's field is possibly modified. See implementation details in the [Updating the `is_customized` field](#updating-the-is_customized-field) section. -**3. Removing checks that block modifying prebuilt rules:** some of our endpoints prevent users from modifying prebuilt rules. This check needs to be removed from all endpoints to allow the customization of prebuilt rules. -**4. Blocking the update of non-customizable fields:** while the goal of this epic is to allow users to modify their prebuilt rule fields, there are certain rule fields that we will still want to prevent the user from modifying via endpoints, since we will not provide support for resolving conflicts for them via the UI or API if they arise during an update. See the **Customizable** column in [this ticket](https://github.com/elastic/kibana/issues/147239) for a detailed list of fields that should be blocked from modification via the endpoints. +1. **Introduction of migration logic**: as explained in the first section of this document, endpoints should have the additional responsibility of migrating our rule schema. +2. **Calculation of the `is_customized` field**: this field which is part of the `rule_source` field for external rules needs to be recalculated whenever a rule's field is possibly modified. See implementation details in the [Updating the `is_customized` field](#updating-the-is_customized-field) section. +3. **Removing checks that block modifying prebuilt rules:** some of our endpoints prevent users from modifying prebuilt rules. This check needs to be removed from all endpoints to allow the customization of prebuilt rules. +4. **Blocking the update of non-customizable fields:** while the goal of this epic is to allow users to modify their prebuilt rule fields, there are certain rule fields that we will still want to prevent the user from modifying via endpoints, since we will not provide support for resolving conflicts for them via the UI or API if they arise during an update. See the **Customizable** column in [this ticket](https://github.com/elastic/kibana/issues/147239) for a detailed list of fields that should be blocked from modification via the endpoints. The table below shows which of these changes need to be applied to our endpoints: (✅ change needed - ❌ no change needed) @@ -1794,7 +1806,7 @@ So, if the corresponding rule asset is not found, do not attempt to do any compa Reasons: - A prebuilt rule which is being modified has a much higher chance of ending up as `is_customized: true` than `false`. Given that we cannot know this for certain, marking it as customized is the best educated guess. - If we ended up making a wrong assumption in that previous point, it can be corrected the next time the rule is upgraded, or if the rule is modified again and the rule asset is found this time. -- A rule which is missing its base version makes more sense being customized than non-customized from a domain-modelling poitn of view. +- A rule which is missing its base version makes more sense being customized than non-customized from a domain-modelling point of view. - The alternative of rejecting the update on a simple field name change is just bad UX: a user just wants to change a rule's name and probably doesn't care that the corresponding `security-rule` asset is not installed. ### In the UI @@ -1812,7 +1824,7 @@ The **Rule Edit Page** is currently split into four tabs: | **Schedule** | - Interval
    - Lookback time | | **Actions** | - Actions
    - Response actions (custom query rules only) | -Out of these four tabs, only **Actions** is enabled and accesible when editing a prebuilt rule - since actions (and shared exceptions lists and snoozing) are the only fields that can currently be modified for prebuilt rules from the UI. +Out of these four tabs, only **Actions** is enabled and accessible when editing a prebuilt rule - since actions (and shared exceptions lists and snoozing) are the only fields that can currently be modified for prebuilt rules from the UI. All of the fields in the UI, listed above, are currently editable for custom rules, except for rule type, which is read only. From 08c945e2af32f890f31b2b15245ca8c7ee702a5d Mon Sep 17 00:00:00 2001 From: jpdjere Date: Mon, 18 Mar 2024 23:58:06 +0100 Subject: [PATCH 41/61] Addressing feedback --- .../docs/prebuilt_rules_customization_rfc.md | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md index bd4731bc210151..38abecd8d01abd 100644 --- a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md +++ b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md @@ -1547,10 +1547,26 @@ For all of the endpoints that allow for modifying a prebuilt rule, the five endp This means, specifically: **do any of the rule's resulting fields differ from the base version of the rule?** -In order to determine this, each time a user attempts to customize a prebuilt rule, we will need to pull its corresponding version of the `security-rule` asset, and compare the end result of the customization with the assets field's. If any of them are different, the `rule_source.is_customized` field should be set to `true`. Otherwise, it should be set to `false`. +In order to determine this, each time a user attempts to customize a prebuilt rule, we will need to pull its corresponding version of the `security-rule` asset, and compare the end result of the customization with the assets field's. If any of them are different, the `rule_source.is_customized` field should be set to `true`. Otherwise, it should be set to `false`. Notice that this can therefore result in a two-way operation: a prebuilt rule that is non-customized can end up as being customized (`is_customized: true`), while a rule that is customized at the beggining of the operation can result in a non-customized rule after the modification (if the changes made by the user make the rule match its base version). +The rule's fields that should be taken into account to determine if the rule has been customized are any of the fields in `BaseRequiredFields`, `BaseOptionalFields` or `BaseDefaultableFields` from the rule schema with the exception of: + +- exceptions +- actions (not part of `security-rule` asset for now anyways) +- `author` and `license` (which shouldn't be customizable anyways) +- `output_index` and `namespace` (deprecated) +- `meta` (to be deprecated) + +In the case of exceptions, all type of changes related to rule exceptions should be ignored during the calculation of `is_customized`: + +- a new shared exception list is added to the rule +- a shared exception list is removed from the rule +- an exception item is added to the rule's shared exception list +- a default exception list is created for the rule and an exception is added to it +- an exception item is removed from the rule's default exception list + The following use cases should be covered in the calculation of `is_customized`:
    Use caseBase versionCurrent versionTarget versionMerged version (output)
    Keep user changes if element conflicts, but apply changes in elements with clean updates
    (A B C - keep current) and (A A B - keep target)

    Same for:
    • (A B C) and (A B A - keep current)
    • (A B C) and (A B B - keep current/target)
     [
    @@ -2283,7 +2329,7 @@ Examples: `related_integrations,` `required_fields`
       },
       {
         ecs: false,
    -    name: "host.os.type",
    +    name: "host.user.id",
         type: "keyword"
       },
     ]
    @@ -2296,12 +2342,7 @@ Examples: `related_integrations,` `required_fields`
         ecs: true,
         name: "event.action",
         type: "keyword"
    -  },
    -  {
    -    ecs: false,
    -    name: "host.user.id",
    -    type: "keyword"
    -  },
    +  }
     ]
             
    Keep user changes if element conflicts, and remove any uncustomized elements if removed in update

    (A B C) and (A A _ - remove element)
    Keep user changes if element conflicts and add new matching element

    +
    • 1st elem: (A B C - keep current)
    • 2nd elem: (_ A A - keep current/target)
    +
     [
    -  {
    -    ecs: true,
    -    name: "event.action",
    -    type: "unknown"
    -  },
    -  {
    -    ecs: false,
    -    name: "host.os.type",
    -    type: "keyword"
    -  },
    +  logs-*,
     ]
             
     [
    -  {
    -    ecs: true,
    -    name: "event.UPDATED",
    -    type: "unknown"
    -  },
    -  {
    -    ecs: false,
    -    name: "host.os.type",
    -    type: "keyword"
    -  },
    +  cluster_one:logs-*,
    +  new-target
     ]
             
     [
    -  {
    -    ecs: true,
    -    name: "event.action",
    -    type: "keyword"
    -  }
    +  logs-new-*,
    +  new-target
     ]
             
     [
    -  {
    -    ecs: true,
    -    name: "event.UPDATED",
    -    type: "unknown"
    -  }
    +  cluster_one:logs-*,
    +  new-target
     ]
             
    Keep user changes if element conflicts, but keep any customized elements if removed in update

    (A B C) and (A B _ - keep current)
     [
    @@ -2388,12 +2407,7 @@ Examples: `related_integrations,` `required_fields`
         ecs: true,
         name: "event.action",
         type: "unknown"
    -  },
    -  {
    -    ecs: false,
    -    name: "host.os.type",
    -    type: "keyword"
    -  },
    +  }
     ]
             
    Keep user changes if element conflicts and add new matching element

    (A B C) and (_ A A - keep current/target)
    Keep user changes if element conflicts and add both new conflicting elements

    +
    • 1st elem: (A B C - keep current)
    • 2nd elem: (_ A B - keep both current and target)
    +
     [
    -  {
    -    ecs: true,
    -    name: "event.action",
    -    type: "unknown"
    -  }
    +  logs-*,
     ]
             
     [
    -  {
    -    ecs: true,
    -    name: "event.UPDATED",
    -    type: "unknown"
    -  },
    -  {
    -    ecs: false,
    -    name: "my.new.field",
    -    type: "keyword"
    -  }
    +  cluster_one:logs-*,
    +  new-target
     ]
             
     [
    -  {
    -    ecs: true,
    -    name: "event.action",
    -    type: "keyword"
    -  },
    -  {
    -    ecs: false,
    -    name: "my.new.field",
    -    type: "keyword"
    -  },
    +  logs-new-*,
    +  elastic-index
     ]
             
     [
    -  {
    -    ecs: true,
    -    name: "event.UPDATED",
    -    type: "unknown"
    -  },
    -  {
    -    ecs: false,
    -    name: "my.new.field",
    -    type: "keyword"
    -  } ,
    +  cluster_one:logs-*,
    +  new-target,
    +  elastic-index
     ]
             
    Keep user changes if element conflicts and add both new conflicting elements

    (A B C) and (_ A B - keep both current and target)
     [
    @@ -2571,7 +2564,43 @@ Examples: `related_integrations,` `required_fields`
           
    Keep user changes if element conflicts and remove element removed by user

    (A B C) and (A _ A - remove element)
    (A B C) and (A _ B - remove element)
    Keep user changes if element conflicts and remove element removed by user

    +
    • 1st elem: (A B C - keep current)
    • 2nd elem: (A _ A - remove element)
    + And: +
    • 1st elem: (A B C - keep current)
    • 2nd elem: (A _ B - remove element
    +
    +
    +[
    +  logs-*,
    +  logstash-*
    +]
    +        
    +
    +
    +[
    +  cluster_one:logs-*,
    +]
    +        
    +
    +
    +[
    +  logs-new-*,
    +  logstash-*
    +]
    +        
    +
    +
    +[
    +  cluster_one:logs-*,
    +]
    +        
    +
     [
    @@ -2635,7 +2664,7 @@ Examples: `related_integrations,` `required_fields`
     
     The `threat` field has a specific [schema](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/common_attributes.gen.ts#L250) that can be handled with its own algorithm in case of conflicts, in order to try to obtain the most reasonable merge between versions. 
     
    -TODO: write algorithm specific to this field
    +**TODO: write algorithm specific to this field**
     
       
    
    From 794d3bb2528e1acb84ed8b334722f8a6fd477059 Mon Sep 17 00:00:00 2001
    From: jpdjere 
    Date: Fri, 23 Feb 2024 17:38:24 +0100
    Subject: [PATCH 23/61] Part 2: Added changes to upgrade /_review and /_perform
     endpoints
    
    ---
     .../perform_rule_upgrade/attempt1.ts          |  52 +++
     .../perform_rule_upgrade/attempt2.ts          |  39 +++
     .../perform_rule_upgrade_route.ts             |   3 +-
     .../review_rule_upgrade_route.ts              |   3 +-
     .../docs/2024-02-23-14-09-16.png              | Bin 0 -> 316654 bytes
     .../docs/prebuilt_rules_customization_rfc.md  | 304 +++++++++++++++++-
     .../perform_rule_upgrade_route.ts             |   2 +
     .../review_rule_upgrade_route.ts              |   5 +-
     .../logic/diff/calculate_rule_diff.ts         |  12 +
     9 files changed, 411 insertions(+), 9 deletions(-)
     create mode 100644 x-pack/plugins/security_solution/common/api/detection_engine/prebuilt_rules/perform_rule_upgrade/attempt1.ts
     create mode 100644 x-pack/plugins/security_solution/common/api/detection_engine/prebuilt_rules/perform_rule_upgrade/attempt2.ts
     create mode 100644 x-pack/plugins/security_solution/docs/2024-02-23-14-09-16.png
    
    diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/prebuilt_rules/perform_rule_upgrade/attempt1.ts b/x-pack/plugins/security_solution/common/api/detection_engine/prebuilt_rules/perform_rule_upgrade/attempt1.ts
    new file mode 100644
    index 00000000000000..e320caa8fdc69e
    --- /dev/null
    +++ b/x-pack/plugins/security_solution/common/api/detection_engine/prebuilt_rules/perform_rule_upgrade/attempt1.ts
    @@ -0,0 +1,52 @@
    +/*
    + * 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 { RuleResponse } from '../../model';
    +import type { AggregatedPrebuiltRuleError } from '../model';
    +
    +export enum PickVersionValues {
    +  BASE = 'BASE',
    +  CURRENT = 'CURRENT',
    +  TARGET = 'TARGET',
    +}
    +
    +export type TPickVersionValues = keyof typeof PickVersionValues;
    +
    +export interface RuleUpgradeSpecifier {
    +  rule_id: string;
    +  /**
    +   * This parameter is needed for handling race conditions with Optimistic Concurrency Control.
    +   * Two or more users can call upgrade/_review and upgrade/_perform endpoints concurrently.
    +   * Also, in general, the time between these two calls can be anything.
    +   * The idea is to only allow the user to install a rule if the user has reviewed the exact version
    +   * of it that had been returned from the _review endpoint. If the version changed on the BE,
    +   * upgrade/_perform endpoint will return a version mismatch error for this rule.
    +   */
    +  revision: number;
    +  /**
    +   * The target version to upgrade to.
    +   */
    +  version: number;
    +  pick_version?: TPickVersionValues;
    +}
    +
    +export interface UpgradeSpecificRulesRequest {
    +  mode: 'SPECIFIC_RULES';
    +  rules: RuleUpgradeSpecifier[];
    +  pick_version?: TPickVersionValues;
    +}
    +
    +export interface UpgradeAllRulesRequest {
    +  mode: 'ALL_RULES';
    +  pick_version?: TPickVersionValues;
    +}
    +
    +export type PerformRuleUpgradeRequestBody = UpgradeSpecificRulesRequest | UpgradeAllRulesRequest;
    +
    +export enum SkipRuleUpgradeReason {
    +  RULE_UP_TO_DATE = 'RULE_UP_TO_DATE',
    +}
    diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/prebuilt_rules/perform_rule_upgrade/attempt2.ts b/x-pack/plugins/security_solution/common/api/detection_engine/prebuilt_rules/perform_rule_upgrade/attempt2.ts
    new file mode 100644
    index 00000000000000..3bc89fddfdf598
    --- /dev/null
    +++ b/x-pack/plugins/security_solution/common/api/detection_engine/prebuilt_rules/perform_rule_upgrade/attempt2.ts
    @@ -0,0 +1,39 @@
    +/*
    + * 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 { RuleResponse } from '../../model';
    +import { AggregatedPrebuiltRuleError } from '../model';
    +
    +enum PickVersionValues {
    +  BASE = 'BASE',
    +  CURRENT = 'CURRENT',
    +  TARGET = 'TARGET',
    +}
    +
    +interface RuleUpgradeSpecifier {
    +  rule_id: string;
    +  revision: number;
    +  version: number;
    +  pick_version?: PickVersionValues;
    +}
    +
    +interface UpgradeSpecificRulesRequest {
    +  mode: 'SPECIFIC_RULES';
    +  rules: RuleUpgradeSpecifier[];
    +  pick_version?: PickVersionValues;
    +}
    +
    +interface UpgradeAllRulesRequest {
    +  mode: 'ALL_RULES';
    +  pick_version?: PickVersionValues;
    +}
    +
    +type PerformRuleUpgradeRequestBody = UpgradeAllRulesRequest | UpgradeSpecificRulesRequest;
    +
    +enum SkipRuleUpgradeReason {
    +  RULE_UP_TO_DATE = 'RULE_UP_TO_DATE',
    +}
    diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/prebuilt_rules/perform_rule_upgrade/perform_rule_upgrade_route.ts b/x-pack/plugins/security_solution/common/api/detection_engine/prebuilt_rules/perform_rule_upgrade/perform_rule_upgrade_route.ts
    index b1d3b166a513ea..549c2ddcff483b 100644
    --- a/x-pack/plugins/security_solution/common/api/detection_engine/prebuilt_rules/perform_rule_upgrade/perform_rule_upgrade_route.ts
    +++ b/x-pack/plugins/security_solution/common/api/detection_engine/prebuilt_rules/perform_rule_upgrade/perform_rule_upgrade_route.ts
    @@ -15,6 +15,7 @@ export enum PickVersionValues {
       BASE = 'BASE',
       CURRENT = 'CURRENT',
       TARGET = 'TARGET',
    +  MERGE = 'MERGE',
     }
     
     export const TPickVersionValues = enumeration('PickVersionValues', PickVersionValues);
    @@ -95,4 +96,4 @@ export interface PerformRuleUpgradeResponseBody {
         skipped: SkippedRuleUpgrade[];
       };
       errors: AggregatedPrebuiltRuleError[];
    -}
    +}
    \ No newline at end of file
    diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/prebuilt_rules/review_rule_upgrade/review_rule_upgrade_route.ts b/x-pack/plugins/security_solution/common/api/detection_engine/prebuilt_rules/review_rule_upgrade/review_rule_upgrade_route.ts
    index 09067a2e152e14..92c8514d88994f 100644
    --- a/x-pack/plugins/security_solution/common/api/detection_engine/prebuilt_rules/review_rule_upgrade/review_rule_upgrade_route.ts
    +++ b/x-pack/plugins/security_solution/common/api/detection_engine/prebuilt_rules/review_rule_upgrade/review_rule_upgrade_route.ts
    @@ -30,6 +30,7 @@ export interface RuleUpgradeInfoForReview {
       rule_id: RuleSignatureId;
       current_rule: RuleResponse;
       target_rule: RuleResponse;
    +  merged_rule: RuleResponse; // ADDED in POC
       diff: PartialRuleDiff;
       revision: number;
    -}
    +}
    \ No newline at end of file
    diff --git a/x-pack/plugins/security_solution/docs/2024-02-23-14-09-16.png b/x-pack/plugins/security_solution/docs/2024-02-23-14-09-16.png
    new file mode 100644
    index 0000000000000000000000000000000000000000..edc1575c382924b6023fd934c478ab6032d641e6
    GIT binary patch
    literal 316654
    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

    x1xtL;{$pweS)viV7lqQ7CH@O)Tks1u{)OwBl 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

    2-OyHWc%e1;*ItdYwf03pG+-<@&J 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

    Y#E1{vp6RK#v)l!f)Ys1_=U+LRPao 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 literal 0 HcmV?d00001 diff --git a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md index e3e3438aa534d5..a30d8cd639d771 100644 --- a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md +++ b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md @@ -1931,7 +1931,7 @@ This means that **no changes will be needed in this page.** ### Changes to upgrade `_review` endpoint -The algorithm for calculating rule version diffs' core structure is [fully implemented](https://github.com/elastic/kibana/pull/148392) and operational. However, the current method for calculating field differences is basic: it currently simply compares field values across versions and flags a conflict if the base version, the current version and the target versions differ from one another. In this conflict scenario, the `mergedVersion` of the field proposed by the algorithmalways equals the `targetVersion`. +The algorithm for calculating rule version diffs' core structure is [fully implemented](https://github.com/elastic/kibana/pull/148392) and operational. However, the current method for calculating field differences is basic: it currently simply compares field values across versions and flags a conflict if the base version, the current version and the target versions differ from one another. In this conflict scenario, the `mergedVersion` of the field proposed by the algorithm always equals the `targetVersion`. We propose developing more adaptable diff algorithms tailored to specific rule fields or rule field types. These more specific algorithms aim to minimize conflicts and automate merging of changes, doing the best effort to keep the intended customizations applied by the user, as well as the updates proposed by Elastic. Hopefully, the user will be able to simply review the proposal and accept it. @@ -2773,15 +2773,313 @@ The `threat` field has a specific [schema](https://github.com/elastic/kibana/blo

    +#### Changes to `/upgrade/_review` endpoint contract + +The current response body of the `/upgrade/_review` endpoint looks as follows: + +_Source: [x-pack/plugins/security_solution/common/api/detection_engine/prebuilt_rules/review_rule_upgrade/review_rule_upgrade_route.ts](x-pack/plugins/security_solution/common/api/detection_engine/prebuilt_rules/review_rule_upgrade/review_rule_upgrade_route.ts)_ +```ts +export interface ReviewRuleUpgradeResponseBody { + stats: .... + /** Info about individual rules: one object per each rule available for upgrade */ + rules: RuleUpgradeInfoForReview[]; +} + +export interface RuleUpgradeInfoForReview { + id: RuleObjectId; + rule_id: RuleSignatureId; + current_rule: RuleResponse; + target_rule: RuleResponse; + diff: PartialRuleDiff; + revision: number; +}; +``` + +We currently use: + +- the `current_rule` and `target_rule` fields, both of type `RuleResponse` to display the **whole rule JSON diff**. +- the `diff` object to display the **Per-field rule diff**. + +However, the endpoint does not currently return a `merged_rule` version of the rule, which should represent the end result of the merge, in `RuleResponse` type. + +This `merged_rule` is needed to send back to the server in a subsequent call to a **Perform Upgrade - `/upgrade/_perform`** endpoint, using it as its payload. + +`merged_rule` can be modified in the frontend by the user before sending it back to the server, to account for conflict resolution of fields or simple customizations that the user might want to perform on rule fields during the upgrade. + +The additional `merged_rule` property should be included in the `RuleUpgradeInfoForReview` interface, and have type `RuleResponse`: + +```ts +export interface RuleUpgradeInfoForReview { + id: RuleObjectId; + rule_id: RuleSignatureId; + current_rule: RuleResponse; + target_rule: RuleResponse; + merged_rule: RuleResponse; // New field + diff: PartialRuleDiff; + revision: number; +}; +``` + +This `merged_rule` can be calculated in the endpoint logic by making use of the `fieldsDiff` object calculated by the `calculateRuleFieldsDiff` within the `calculateRuleDiff` function: + +_Source: [x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/diff/calculate_rule_diff.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/diff/calculate_rule_diff.ts)_ +```ts + // [PSEUDOCODE] + + const fieldsDiff = calculateRuleFieldsDiff({ + base_version: diffableBaseVersion || MissingVersion, + current_version: diffableCurrentVersion, + target_version: diffableTargetVersion, + }); + + const mergedVersion = Object.entries(fieldsDiff).reduce((acc, field) => { + + const ungroupedFields = convertDiffableToRule(field); + return { + ...acc, + ...ungroupedFields, + }; + }, {}); +``` + +The method `calculateRuleFieldsDiff` returns all needed fields needed for each rule type, but some of them are grouped since they have a `Diffable` type. We need to create function such as `convertDiffableToRule` that inputs a `DiffableRule` and outputs the field types that are needed in a rule object of type `RuleResponse`. + +This is the inverse of field grouping process that is done in the `convertRuleToDiffable` in the [`x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/diff/normalization/convert_rule_to_diffable.ts`](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/diff/normalization/convert_rule_to_diffable.ts). + +This `merge_rule` will contain all fields updated to the version that the different algorithms has decided is the optimal based on the `ThreeWayDiffOutcome`. See the existing `simpleDiffAlgorithm` and the `mergeVersions` used within it: [x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/diff/calculation/algorithms/simple_diff_algorithm.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/diff/calculation/algorithms/simple_diff_algorithm.ts) + + + + + + + + + + +### Changes to `/upgrade/_perform` endpoint + +#### Changes to `/upgrade/_perform` endpoint contract + +The endpoint current's request payload contract looks so: + +_Source: [x-pack/plugins/security_solution/common/api/detection_engine/prebuilt_rules/perform_rule_upgrade/perform_rule_upgrade_route.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/common/api/detection_engine/prebuilt_rules/perform_rule_upgrade/perform_rule_upgrade_route.ts)_ +```ts +export enum PickVersionValues { + BASE = 'BASE', + CURRENT = 'CURRENT', + TARGET = 'TARGET', +} + +export const TPickVersionValues = enumeration('PickVersionValues', PickVersionValues); + +export const RuleUpgradeSpecifier = t.exact( + t.intersection([ + t.type({ + rule_id: t.string, + revision: t.number, + /** + * The target version to upgrade to. + */ + version: t.number, + }), + t.partial({ + pick_version: TPickVersionValues, + + }), + ]) +); + +export const UpgradeSpecificRulesRequest = t.exact( + t.intersection([ + t.type({ + mode: t.literal(`SPECIFIC_RULES`), + rules: t.array(RuleUpgradeSpecifier), + }), + t.partial({ + pick_version: TPickVersionValues, + }), + ]) +); + +export const UpgradeAllRulesRequest = t.exact( + t.intersection([ + t.type({ + mode: t.literal(`ALL_RULES`), + }), + t.partial({ + pick_version: TPickVersionValues, + }), + ]) +); + +export const PerformRuleUpgradeRequestBody = t.union([ + UpgradeAllRulesRequest, + UpgradeSpecificRulesRequest, +]); +``` + +The endpoint offers two modes of updating rules: updating all rules to a specified version (`BASE`, `CURRENT` or `TARGET`) or updating individual rules (sent in the payload) to any of those 3 specific versions. + +We need to expand this contract as follows: + +- The `PickVersionValues` enum now includes the `MERGE` version as an option: +```ts +export enum PickVersionValues { + BASE = 'BASE', + CURRENT = 'CURRENT', + TARGET = 'TARGET', + MERGE = 'MERGE', +} +``` + + +- The `ALL_RULES` mode of the endpoint stays unchanged, except that it can only take the values `BASE`, `CURRENT` or `TARGET`: since this mode upgrades all upgradable rules, without passing a list of `rule_id`s, we cannot pass in a `merged_version` to each, which would be required to solve upgrade conflicts. +```ts +export const UpgradeAllRulesRequest = t.exact( + t.intersection([ + t.type({ + mode: t.literal(`ALL_RULES`), + }), + t.partial({ + pick_version: TPickVersionValuesWithoutMerge, // BASE, CURRENT or TARGET + }), + ]) +); +``` +- The `SPECIFIC_RULES` mode should change so that: + +1. The `UpgradeSpecificRulesRequest` payload can now take a `pick_version` of value `MERGE`. +```ts +export const UpgradeSpecificRulesRequest = t.exact( + t.intersection([ + t.type({ + mode: t.literal(`SPECIFIC_RULES`), + rules: t.array(RuleUpgradeSpecifier), + }), + t.partial({ + pick_version: TPickVersionValues, // BASE, CURRENT, TARGET or MERGE + }), + ]) +); +``` + +2. The `RuleUpgradeSpecifier` payload: + - can also take a `pick_version` of value `MERGE`. + - includes an optional `merged_version` property that is only valid and used by the endpoint handler when `pick_version` is `MERGE`. +```ts +export const RuleUpgradeSpecifier = t.exact( + t.intersection([ + t.type({ + rule_id: t.string, + revision: t.number, + version: t.number, + }), + t.partial({ + pick_version: TPickVersionValues, // BASE, CURRENT, TARGET or MERGE + merged_version: RuleResponse, + }), + ]) +); +``` + +#### Changes to `/upgrade/_perform` endpoint logic + +Since the `PickVersionValues` enum only currently allows for the values `BASE`, `CURRENT` or `TARGET`, the logic to handle the `MERGE` case needs to be handled. + +Currently, if `PickVersionValues` is: + +- `BASE`: the rule set for upgrade is the `base` version as pulled from the corresponding `security-asset`, of type `PrebuiltRuleAsset`, but with its `version` updated to the next version of the rule. +- `CURRENT`: the rule set for upgrade is the `current` version as pulled from Elasticsearch, corresponding to the existing `alert`, of type `RuleResponse`, but with its `version` updated to the next version of the rule. +- `TARGET`: the rule set for upgrade is the `base` version as pulled from the corresponding `security-asset`, which already includes the updated `version`. + +Now, the case of `PickVersionValues` being `MERGE` should handled as follows: + +1. Perform an additional check that asserts that, if `PickVersionValues: MERGE`, then the `RuleUpgradeSpecifier` payload should contain a `merged_version`. If absent, return the particular rule in the `failed` property of `PerformRuleUpgradeResponseBody` +// TODO: Is this better handled via io-ts/Zod? We don't want to make the whole request fail if `merged_version` is missing for only one rule. + + +2. set the rule upgrade to be the `merged_version` passed in the payload, but overwrite the `rule_id`, `revision` and `version` to what's defined in the `RuleUpgradeSpecifier` iin the request body: +```ts +[PSEUDOCODE] + +const body: PerformRuleUpgradeRequestBody = request.body; + +const ruleToUpgrade = rules[0]; + +const { rule_id, version, revision, merged_version } = ruleToUpgrade; + +const upgradedRulePayload = { + ...merged_version, + rule_id, + version, + revision +} + +await upgradePrebuiltRules( + rulesClient, + upgradedRulePayload +); +``` + +### Changes to Rule Upgrade UX/UI flow + +#### Bulk accepting upgrades with no conflicts + +Making prebuilt rules customizable, plus the changes introduced to the `/upgrade/_review` update described above means that the Upgrade Review endpoint will now determine that some of the rules have `CONFLICT`s that cannot be automatically resolved (the current behaviour is updating all rules to their `target` version). + +However, since we still want to give the users the ability to update all of their rules that have updates with no conflicts in an easy and fast way, we need to introduce a distinct UI that allows for this behaviour. + +The current UI of the **Rule Updates** page has an button with the label "Update all" which currently simply updates all rules to their `target` version: + +![](2024-02-23-14-09-16.png) + +We can replace this button for an **Update rules with no conflicts** button. Clicking this button would make a request to `/upgrade/_perform` with a payload that includes only rules that have no conflicts. That payload can be built out of the response of the `/upgrade/_review` endpoint, including only rules with no conflicts and specifying that all rules should be updated to their `MERGED` version, which represents the "clean" (conflictless) update. + +```ts +// [PSEUDOCODE] +const reviewUpgradeResponse: ReviewRuleUpgradeResponseBody = await fetch( + '/internal/detection_engine/prebuilt_rules/upgrade/_review', + { method: 'POST' } +); + +// Filter out rules with conflicts, and create payload pointing all to 'MERGE' version +const performUpgradePayload = { + mode: 'SPECIFIC_RULES', + rules: reviewUpgradeResponse.rules + .filter((rule) => !rule.diff.has_conflict) + .map((rule) => ({ + rule_id: rule.rule_id, + revision: rule.revision, + version: rule.version, + merged_version: rule.merged_version, + })), + pick_version: 'MERGE', +}; + + +const performUpgradeResponse: PerformRuleUpgradeResponseBody = await fetch( + '/internal/detection_engine/prebuilt_rules/upgrade/_perform', + { method: 'POST', body: performUpgradePayload } +); +``` + +#### Upgrading rules with conflicts + +Rules whose upgrade + + + + -### Changes to upgrade `_perform` endpoints +---- end of RFC ----- -## Scenarios for bulk accepting updates +## Scenario for bulk accepting updates - At rules table level Bulk accept all rule updates that have no conflicting fields at all → This would make the request to update all these rules with no conflicts at all. diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_upgrade/perform_rule_upgrade_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_upgrade/perform_rule_upgrade_route.ts index 969fefa423d905..d8eb0e72022871 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_upgrade/perform_rule_upgrade_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_upgrade/perform_rule_upgrade_route.ts @@ -144,6 +144,8 @@ export const performRuleUpgradeRoute = (router: SecuritySolutionPluginRouter) => break; case PickVersionValues.TARGET: targetRules.push(target); + case PickVersionValues.MERGE: + targetRules.push(target); break; default: assertUnreachable(rulePickVersion); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/review_rule_upgrade/review_rule_upgrade_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/review_rule_upgrade/review_rule_upgrade_route.ts index 955b069b0c005d..5fac8b0fbd9a25 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/review_rule_upgrade/review_rule_upgrade_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/review_rule_upgrade/review_rule_upgrade_route.ts @@ -99,10 +99,6 @@ const calculateRuleInfos = (results: CalculateRuleDiffResult[]): RuleUpgradeInfo const targetRule: RuleResponse = { ...convertPrebuiltRuleAssetToRuleResponse(targetVersion), - prebuilt: { - isCustomized: installedCurrentVersion.prebuilt?.isCustomized ?? false, - elasticUpdateDate: targetVersion.elasticUpdateDate, - }, id: installedCurrentVersion.id, revision: installedCurrentVersion.revision + 1, created_at: installedCurrentVersion.created_at, @@ -117,6 +113,7 @@ const calculateRuleInfos = (results: CalculateRuleDiffResult[]): RuleUpgradeInfo revision: installedCurrentVersion.revision, current_rule: installedCurrentVersion, target_rule: targetRule, + merged_rule: ruleVersions.mergedVersion, diff: { fields: pickBy>( ruleDiff.fields, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/diff/calculate_rule_diff.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/diff/calculate_rule_diff.ts index 337a510c3b4b2e..b1ab79b717db99 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/diff/calculate_rule_diff.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/diff/calculate_rule_diff.ts @@ -33,6 +33,7 @@ export interface CalculateRuleDiffResult { base?: DiffableRule; target: DiffableRule; }; + mergedVersion: RuleResponse; // ADDED in POC }; } @@ -75,6 +76,16 @@ export const calculateRuleDiff = (args: RuleVersions): CalculateRuleDiffResult = target_version: diffableTargetVersion, }); + const mergedVersion = Object.entries(fieldsDiff).reduce((acc, field) => { + + debugger; + const ungroupedFields = getUngroupedFields(field); + return { + ...acc, + ...ungroupedFields, + }; + }, {}); + const hasAnyFieldConflict = Object.values>(fieldsDiff).some( (fieldDiff) => fieldDiff.has_conflict ); @@ -95,6 +106,7 @@ export const calculateRuleDiff = (args: RuleVersions): CalculateRuleDiffResult = base: diffableBaseVersion, target: diffableTargetVersion, }, + mergedVersion: mergedVersion as RuleResponse, }, }; }; From 283c706e49eb65405a5fd0015d8a5d463ade77b1 Mon Sep 17 00:00:00 2001 From: jpdjere Date: Fri, 23 Feb 2024 20:58:21 +0100 Subject: [PATCH 24/61] Part 2: Remove changes for endpoints and link to POC --- .../docs/prebuilt_rules_customization_rfc.md | 199 ++++-------------- 1 file changed, 36 insertions(+), 163 deletions(-) diff --git a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md index a30d8cd639d771..909ecb8e361541 100644 --- a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md +++ b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md @@ -1921,11 +1921,7 @@ This means that **no changes will be needed in this page.** 2. Custom Query field overflows the viewport and cannot be completely visualized/edited when the query is too long, i.e. occupies too many lines. This is often the case from Prebuilt Rules. The editable field also does not allow scrolling. See example: ![](2023-12-01-14-13-07.png) -### Rule fields -- What rule fields will be customizable and for what fields we will disable customization? -- How are we going to handle various fields in the rule upgrade workflow? -- What concrete diff algorithms for what rule fields we will need to write? ## Upgrading Prebuilt Rules @@ -2775,6 +2771,36 @@ The `threat` field has a specific [schema](https://github.com/elastic/kibana/blo #### Changes to `/upgrade/_review` endpoint contract +The endpoint currently implemented contract needs to be updated as described in this [PoC](https://github.com/elastic/kibana/pull/144060). + +--- +**QUESTION:** is the following change needed? + +Do we need a `merged_rule` in the respose, since `diff` already contains a `merged_version` for each field which has a conflict? + +But what about fields that don't have conflicts, and the algorithm decides which version to return? Don't we need that information back at the client, to form the payload for the /_perform endpoint? + +The POC says for the /_perform endpoint: + +```ts +export interface SingleRuleUpgradeRequest { + id: RuleObjectId; + pick_version?: 'BASE' | 'CURRENT' | 'TARGET' | 'MERGED'; + fields?: { + name?: FieldUpgradeRequest; + description?: FieldUpgradeRequest; + // etc + // Every non-specified field will default to pick_version: 'MERGED'. + // If pick_version is MERGED and there's a merge conflict the endpoint will throw. + }; + rule_content_version: SemanticVersion; + rule_revision: number; +} +``` +But the _perform endpoint does not know what the /_review endpoint calculated for each field for all other fields not specified in the payload. It would have to do the diff again. + +--- + The current response body of the `/upgrade/_review` endpoint looks as follows: _Source: [x-pack/plugins/security_solution/common/api/detection_engine/prebuilt_rules/review_rule_upgrade/review_rule_upgrade_route.ts](x-pack/plugins/security_solution/common/api/detection_engine/prebuilt_rules/review_rule_upgrade/review_rule_upgrade_route.ts)_ @@ -2861,166 +2887,9 @@ This `merge_rule` will contain all fields updated to the version that the differ #### Changes to `/upgrade/_perform` endpoint contract -The endpoint current's request payload contract looks so: +The endpoint currently implemented contract needs to be updated as described in this [PoC](https://github.com/elastic/kibana/pull/144060). -_Source: [x-pack/plugins/security_solution/common/api/detection_engine/prebuilt_rules/perform_rule_upgrade/perform_rule_upgrade_route.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/common/api/detection_engine/prebuilt_rules/perform_rule_upgrade/perform_rule_upgrade_route.ts)_ -```ts -export enum PickVersionValues { - BASE = 'BASE', - CURRENT = 'CURRENT', - TARGET = 'TARGET', -} -export const TPickVersionValues = enumeration('PickVersionValues', PickVersionValues); - -export const RuleUpgradeSpecifier = t.exact( - t.intersection([ - t.type({ - rule_id: t.string, - revision: t.number, - /** - * The target version to upgrade to. - */ - version: t.number, - }), - t.partial({ - pick_version: TPickVersionValues, - - }), - ]) -); - -export const UpgradeSpecificRulesRequest = t.exact( - t.intersection([ - t.type({ - mode: t.literal(`SPECIFIC_RULES`), - rules: t.array(RuleUpgradeSpecifier), - }), - t.partial({ - pick_version: TPickVersionValues, - }), - ]) -); - -export const UpgradeAllRulesRequest = t.exact( - t.intersection([ - t.type({ - mode: t.literal(`ALL_RULES`), - }), - t.partial({ - pick_version: TPickVersionValues, - }), - ]) -); - -export const PerformRuleUpgradeRequestBody = t.union([ - UpgradeAllRulesRequest, - UpgradeSpecificRulesRequest, -]); -``` - -The endpoint offers two modes of updating rules: updating all rules to a specified version (`BASE`, `CURRENT` or `TARGET`) or updating individual rules (sent in the payload) to any of those 3 specific versions. - -We need to expand this contract as follows: - -- The `PickVersionValues` enum now includes the `MERGE` version as an option: -```ts -export enum PickVersionValues { - BASE = 'BASE', - CURRENT = 'CURRENT', - TARGET = 'TARGET', - MERGE = 'MERGE', -} -``` - - -- The `ALL_RULES` mode of the endpoint stays unchanged, except that it can only take the values `BASE`, `CURRENT` or `TARGET`: since this mode upgrades all upgradable rules, without passing a list of `rule_id`s, we cannot pass in a `merged_version` to each, which would be required to solve upgrade conflicts. -```ts -export const UpgradeAllRulesRequest = t.exact( - t.intersection([ - t.type({ - mode: t.literal(`ALL_RULES`), - }), - t.partial({ - pick_version: TPickVersionValuesWithoutMerge, // BASE, CURRENT or TARGET - }), - ]) -); -``` -- The `SPECIFIC_RULES` mode should change so that: - -1. The `UpgradeSpecificRulesRequest` payload can now take a `pick_version` of value `MERGE`. -```ts -export const UpgradeSpecificRulesRequest = t.exact( - t.intersection([ - t.type({ - mode: t.literal(`SPECIFIC_RULES`), - rules: t.array(RuleUpgradeSpecifier), - }), - t.partial({ - pick_version: TPickVersionValues, // BASE, CURRENT, TARGET or MERGE - }), - ]) -); -``` - -2. The `RuleUpgradeSpecifier` payload: - - can also take a `pick_version` of value `MERGE`. - - includes an optional `merged_version` property that is only valid and used by the endpoint handler when `pick_version` is `MERGE`. -```ts -export const RuleUpgradeSpecifier = t.exact( - t.intersection([ - t.type({ - rule_id: t.string, - revision: t.number, - version: t.number, - }), - t.partial({ - pick_version: TPickVersionValues, // BASE, CURRENT, TARGET or MERGE - merged_version: RuleResponse, - }), - ]) -); -``` - -#### Changes to `/upgrade/_perform` endpoint logic - -Since the `PickVersionValues` enum only currently allows for the values `BASE`, `CURRENT` or `TARGET`, the logic to handle the `MERGE` case needs to be handled. - -Currently, if `PickVersionValues` is: - -- `BASE`: the rule set for upgrade is the `base` version as pulled from the corresponding `security-asset`, of type `PrebuiltRuleAsset`, but with its `version` updated to the next version of the rule. -- `CURRENT`: the rule set for upgrade is the `current` version as pulled from Elasticsearch, corresponding to the existing `alert`, of type `RuleResponse`, but with its `version` updated to the next version of the rule. -- `TARGET`: the rule set for upgrade is the `base` version as pulled from the corresponding `security-asset`, which already includes the updated `version`. - -Now, the case of `PickVersionValues` being `MERGE` should handled as follows: - -1. Perform an additional check that asserts that, if `PickVersionValues: MERGE`, then the `RuleUpgradeSpecifier` payload should contain a `merged_version`. If absent, return the particular rule in the `failed` property of `PerformRuleUpgradeResponseBody` -// TODO: Is this better handled via io-ts/Zod? We don't want to make the whole request fail if `merged_version` is missing for only one rule. - - -2. set the rule upgrade to be the `merged_version` passed in the payload, but overwrite the `rule_id`, `revision` and `version` to what's defined in the `RuleUpgradeSpecifier` iin the request body: -```ts -[PSEUDOCODE] - -const body: PerformRuleUpgradeRequestBody = request.body; - -const ruleToUpgrade = rules[0]; - -const { rule_id, version, revision, merged_version } = ruleToUpgrade; - -const upgradedRulePayload = { - ...merged_version, - rule_id, - version, - revision -} - -await upgradePrebuiltRules( - rulesClient, - upgradedRulePayload -); -``` ### Changes to Rule Upgrade UX/UI flow @@ -3066,7 +2935,11 @@ const performUpgradeResponse: PerformRuleUpgradeResponseBody = await fetch( #### Upgrading rules with conflicts -Rules whose upgrade +Rules whose diffing algorithm resulted in a `CONFLICT` need to be manually resolved or confirmed by the user via the UI before making the API request to upgrade the rule. + +> See [Three-Way-Diff Component ticket](https://github.com/elastic/kibana/issues/171520) that details UI for solving conflicts. + +> See [designs](https://www.figma.com/file/gLHm8LpTtSkAUQHrkG3RHU/%5B8.7%5D-%5BRules%5D-Rule-Immutability%2FCustomization?type=design&mode=design&t=LkauhLzUKUatF6cL-0#712870904). From 2ed015e2c2988b880b4ac5f48adb78d0d549cb67 Mon Sep 17 00:00:00 2001 From: jpdjere Date: Mon, 26 Feb 2024 00:24:18 +0100 Subject: [PATCH 25/61] Part 2: cleanup --- .../docs/prebuilt_rules_customization_rfc.md | 181 +----------------- 1 file changed, 4 insertions(+), 177 deletions(-) diff --git a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md index 909ecb8e361541..50dd972fff732d 100644 --- a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md +++ b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md @@ -26,6 +26,9 @@ _Pending_: - Frontend Logic - Other UI changes: list changes in Rule Editing, Rule Tables, etc + + + ## Table of Contents The following TOC was created using the [Pandoc](https://pandoc.org/installing.html) tool. @@ -36,74 +39,6 @@ You can create it by navigating to the directory of the markdown file and runnin pandoc prebuilt_rules_customization_rfc.md --toc --toc-depth=6 --wrap=none -s -o output.md ``` -- [RFC: Prebuilt Rules Customization](#rfc-prebuilt-rules-customization) - - [Table of Contents](#table-of-contents) - - [Note about scope of RFC](#note-about-scope-of-rfc) - - [Necessary rule schema changes](#necessary-rule-schema-changes) - - [`rule_source` field](#rule_source-field) - - [Deprecating the `immutable` field](#deprecating-the-immutable-field) - - [Subfields in the `rule_source` field](#subfields-in-the-rule_source-field) - - [`type` subfield](#type-subfield) - - [`is_customized` subfield](#is_customized-subfield) - - [`source_updated_at` subfield](#source_updated_at-subfield) - - [Changes needed in rule schema](#changes-needed-in-rule-schema) - - [API schema](#api-schema) - - [API request and response rule schema](#api-request-and-response-rule-schema) - - [Rule Import request schema](#rule-import-request-schema) - - [Internal rule schema](#internal-rule-schema) - - [Prebuilt Rule asset schema](#prebuilt-rule-asset-schema) - - [Deprecating the `immutable` field](#deprecating-the-immutable-field-1) - - [Mapping changes](#mapping-changes) - - [Plan for carrying out migrations of rule SOs](#plan-for-carrying-out-migrations-of-rule-sos) - - [Context](#context) - - [Problem with tightly coupled logic in our endpoints](#problem-with-tightly-coupled-logic-in-our-endpoints) - - [Migration strategy](#migration-strategy) - - [Normalization on read](#normalization-on-read) - - [Rule Management endpoints that will perform normalization-on-read](#rule-management-endpoints-that-will-perform-normalization-on-read) - - [Migration on write](#migration-on-write) - - [Rule Management endpoints that should include migration-on-write logic](#rule-management-endpoints-that-should-include-migration-on-write-logic) - - [Technical implementation of migration-on-write](#technical-implementation-of-migration-on-write) - - [Updating and upgrading rules](#updating-and-upgrading-rules) - - [Bulk editing rules](#bulk-editing-rules) - - [Endpoints and utilities that will need to be adapted to the new schema](#endpoints-and-utilities-that-will-need-to-be-adapted-to-the-new-schema) - - [Utilities](#utilities) - - [KQL filters and the `convertRulesFilterToKQL` method](#kql-filters-and-the-convertrulesfiltertokql-method) - - [Rule Management endpoints](#rule-management-endpoints) - - [Prebuilt Rules endpoints](#prebuilt-rules-endpoints) - - [Rule monitoring endpoints](#rule-monitoring-endpoints) - - [Rule Execution Logs](#rule-execution-logs) - - [Exporting and importing rules](#exporting-and-importing-rules) - - [Exporting rules](#exporting-rules) - - [Importing rules](#importing-rules) - - [Handling the `version` parameter](#handling-the-version-parameter) - - [Customizing Prebuilt Rules](#customizing-prebuilt-rules) - - [Endpoints](#endpoints) - - [Changes needed to endpoints](#changes-needed-to-endpoints) - - [Update Rule - `PUT /rules`](#update-rule---put-rules) - - [Patch Rule - `PATCH /rules`](#patch-rule---patch-rules) - - [Bulk Patch Rules - `PATCH /rules/_bulk_update`](#bulk-patch-rules---patch-rules_bulk_update) - - [Bulk Update Rules - `PUT /rules/_bulk_update`](#bulk-update-rules---put-rules_bulk_update) - - [Bulk Actions - `POST /rules/_bulk_action`](#bulk-actions---post-rules_bulk_action) - - [Updating the `is_customized` field](#updating-the-is_customized-field) - - [In the UI](#in-the-ui) - - [Via the Rule Edit Page](#via-the-rule-edit-page) - - [Via Bulk Actions](#via-bulk-actions) - - [Via the Rules Details Page](#via-the-rules-details-page) - - [Via the Shared Exception Lists page](#via-the-shared-exception-lists-page) - - [Via the Stack Management \> Rules UI](#via-the-stack-management-rules-ui) - - [List of things to fix (create tickets)](#list-of-things-to-fix-create-tickets) - - [Rule fields](#rule-fields) - - [Upgrading Prebuilt Rules](#upgrading-prebuilt-rules) - - [Changes to upgrade `_review` endpoint](#changes-to-upgrade-_review-endpoint) - - [Concrete field diff algorithm by type](#concrete-field-diff-algorithm-by-type) - - [String fields](#string-fields) - - [Changes to upgrade `_perform` endpoints](#changes-to-upgrade-_perform-endpoints) - - [Rule field diff algorithms](#rule-field-diff-algorithms) - - [Changes in UI](#changes-in-ui) - - [Scenarios for bulk accepting updates](#scenarios-for-bulk-accepting-updates) - - [Marking rules (and their fields) as customized](#marking-rules-and-their-fields-as-customized) - - [Other open questions](#other-open-questions) - ## Note about scope of RFC This RFC was initially planned to have a scope strictly limited to the Customization of Prebuilt Rules epic. However, another epic is, in parallel, in the discussion phase: the [Detections-as-Code (DaC) epic](https://docs.google.com/document/d/1MfPFa3Io82S91rRfdQde8Xi_9AGEbE44Z2MkIYWD10U/edit). @@ -2773,113 +2708,6 @@ The `threat` field has a specific [schema](https://github.com/elastic/kibana/blo The endpoint currently implemented contract needs to be updated as described in this [PoC](https://github.com/elastic/kibana/pull/144060). ---- -**QUESTION:** is the following change needed? - -Do we need a `merged_rule` in the respose, since `diff` already contains a `merged_version` for each field which has a conflict? - -But what about fields that don't have conflicts, and the algorithm decides which version to return? Don't we need that information back at the client, to form the payload for the /_perform endpoint? - -The POC says for the /_perform endpoint: - -```ts -export interface SingleRuleUpgradeRequest { - id: RuleObjectId; - pick_version?: 'BASE' | 'CURRENT' | 'TARGET' | 'MERGED'; - fields?: { - name?: FieldUpgradeRequest; - description?: FieldUpgradeRequest; - // etc - // Every non-specified field will default to pick_version: 'MERGED'. - // If pick_version is MERGED and there's a merge conflict the endpoint will throw. - }; - rule_content_version: SemanticVersion; - rule_revision: number; -} -``` -But the _perform endpoint does not know what the /_review endpoint calculated for each field for all other fields not specified in the payload. It would have to do the diff again. - ---- - -The current response body of the `/upgrade/_review` endpoint looks as follows: - -_Source: [x-pack/plugins/security_solution/common/api/detection_engine/prebuilt_rules/review_rule_upgrade/review_rule_upgrade_route.ts](x-pack/plugins/security_solution/common/api/detection_engine/prebuilt_rules/review_rule_upgrade/review_rule_upgrade_route.ts)_ -```ts -export interface ReviewRuleUpgradeResponseBody { - stats: .... - /** Info about individual rules: one object per each rule available for upgrade */ - rules: RuleUpgradeInfoForReview[]; -} - -export interface RuleUpgradeInfoForReview { - id: RuleObjectId; - rule_id: RuleSignatureId; - current_rule: RuleResponse; - target_rule: RuleResponse; - diff: PartialRuleDiff; - revision: number; -}; -``` - -We currently use: - -- the `current_rule` and `target_rule` fields, both of type `RuleResponse` to display the **whole rule JSON diff**. -- the `diff` object to display the **Per-field rule diff**. - -However, the endpoint does not currently return a `merged_rule` version of the rule, which should represent the end result of the merge, in `RuleResponse` type. - -This `merged_rule` is needed to send back to the server in a subsequent call to a **Perform Upgrade - `/upgrade/_perform`** endpoint, using it as its payload. - -`merged_rule` can be modified in the frontend by the user before sending it back to the server, to account for conflict resolution of fields or simple customizations that the user might want to perform on rule fields during the upgrade. - -The additional `merged_rule` property should be included in the `RuleUpgradeInfoForReview` interface, and have type `RuleResponse`: - -```ts -export interface RuleUpgradeInfoForReview { - id: RuleObjectId; - rule_id: RuleSignatureId; - current_rule: RuleResponse; - target_rule: RuleResponse; - merged_rule: RuleResponse; // New field - diff: PartialRuleDiff; - revision: number; -}; -``` - -This `merged_rule` can be calculated in the endpoint logic by making use of the `fieldsDiff` object calculated by the `calculateRuleFieldsDiff` within the `calculateRuleDiff` function: - -_Source: [x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/diff/calculate_rule_diff.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/diff/calculate_rule_diff.ts)_ -```ts - // [PSEUDOCODE] - - const fieldsDiff = calculateRuleFieldsDiff({ - base_version: diffableBaseVersion || MissingVersion, - current_version: diffableCurrentVersion, - target_version: diffableTargetVersion, - }); - - const mergedVersion = Object.entries(fieldsDiff).reduce((acc, field) => { - - const ungroupedFields = convertDiffableToRule(field); - return { - ...acc, - ...ungroupedFields, - }; - }, {}); -``` - -The method `calculateRuleFieldsDiff` returns all needed fields needed for each rule type, but some of them are grouped since they have a `Diffable` type. We need to create function such as `convertDiffableToRule` that inputs a `DiffableRule` and outputs the field types that are needed in a rule object of type `RuleResponse`. - -This is the inverse of field grouping process that is done in the `convertRuleToDiffable` in the [`x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/diff/normalization/convert_rule_to_diffable.ts`](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/diff/normalization/convert_rule_to_diffable.ts). - -This `merge_rule` will contain all fields updated to the version that the different algorithms has decided is the optimal based on the `ThreeWayDiffOutcome`. See the existing `simpleDiffAlgorithm` and the `mergeVersions` used within it: [x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/diff/calculation/algorithms/simple_diff_algorithm.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/diff/calculation/algorithms/simple_diff_algorithm.ts) - - - - - - - @@ -2887,7 +2715,7 @@ This `merge_rule` will contain all fields updated to the version that the differ #### Changes to `/upgrade/_perform` endpoint contract -The endpoint currently implemented contract needs to be updated as described in this [PoC](https://github.com/elastic/kibana/pull/144060). +The endpoint's currently impled as deemented contract needs to be updatscribed in this [PoC](https://github.com/elastic/kibana/pull/144060). @@ -2921,7 +2749,6 @@ const performUpgradePayload = { rule_id: rule.rule_id, revision: rule.revision, version: rule.version, - merged_version: rule.merged_version, })), pick_version: 'MERGE', }; From 3aa1ac57b05008c6b7689c6b26179c69a5784401 Mon Sep 17 00:00:00 2001 From: jpdjere Date: Mon, 4 Mar 2024 10:24:45 +0100 Subject: [PATCH 26/61] Removed line --- .../review_rule_upgrade/review_rule_upgrade_route.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/prebuilt_rules/review_rule_upgrade/review_rule_upgrade_route.ts b/x-pack/plugins/security_solution/common/api/detection_engine/prebuilt_rules/review_rule_upgrade/review_rule_upgrade_route.ts index 92c8514d88994f..d044c434ab4ec8 100644 --- a/x-pack/plugins/security_solution/common/api/detection_engine/prebuilt_rules/review_rule_upgrade/review_rule_upgrade_route.ts +++ b/x-pack/plugins/security_solution/common/api/detection_engine/prebuilt_rules/review_rule_upgrade/review_rule_upgrade_route.ts @@ -30,7 +30,6 @@ export interface RuleUpgradeInfoForReview { rule_id: RuleSignatureId; current_rule: RuleResponse; target_rule: RuleResponse; - merged_rule: RuleResponse; // ADDED in POC diff: PartialRuleDiff; revision: number; } \ No newline at end of file From 08ac3324adc1093ac14592abd446ecd102e3b856 Mon Sep 17 00:00:00 2001 From: jpdjere Date: Mon, 4 Mar 2024 14:29:44 +0100 Subject: [PATCH 27/61] Rework status --- .../docs/prebuilt_rules_customization_rfc.md | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md index 50dd972fff732d..809acaf5e14a6c 100644 --- a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md +++ b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md @@ -9,22 +9,15 @@ Covers: - migration strategy and technical implementation - exporting and importing rules - schema-related changes needed in endpoints +- calculation of `isCustomized` field on endpoints that update/patch rules. +- additional changes needed to `/upgrade/_review` and `/upgrade/_perform` endpoints +- UI Changes _Pending_: -- Calculation of `isCustomized` field on endpoints that update/patch rules. Encapsulated reusable logic and how to implement it on those endpoints. -- Rework `Changes needed in the UI` -- Additional changes needed to `/upgrade/_review` and `/upgrade/_perform` endpoints - - `/upgrade/_review`: - - Concrete conflict solving algorithms for calculating merged versions - - Update algorithms used for each field - - `/upgrade/_perform`: - - Change payload to allow user to select `merge` version of a rule, and send payload with customized values - - (This is already described in previous RFC! Link to it, the rest is implementation detail) -- Three Way Diff Component: - - UI - - Frontend Logic -- Other UI changes: list changes in Rule Editing, Rule Tables, etc + +- Additional details on `Changes needed in the UI`: Rule Details page, Rules Table +- Update `/upgrade/_perform` endpoint description to match POC proposal From c7418a286955cf0ea39ebd48c9d0f20759fade65 Mon Sep 17 00:00:00 2001 From: jpdjere Date: Mon, 4 Mar 2024 14:36:58 +0100 Subject: [PATCH 28/61] Add ToC --- .../docs/prebuilt_rules_customization_rfc.md | 72 ++++++++++++++++++- 1 file changed, 69 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md index 809acaf5e14a6c..230dd2c12b7d5c 100644 --- a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md +++ b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md @@ -19,9 +19,6 @@ _Pending_: - Additional details on `Changes needed in the UI`: Rule Details page, Rules Table - Update `/upgrade/_perform` endpoint description to match POC proposal - - - ## Table of Contents The following TOC was created using the [Pandoc](https://pandoc.org/installing.html) tool. @@ -32,6 +29,75 @@ You can create it by navigating to the directory of the markdown file and runnin pandoc prebuilt_rules_customization_rfc.md --toc --toc-depth=6 --wrap=none -s -o output.md ``` +- [Table of Contents](#table-of-contents) +- [Note about scope of RFC](#note-about-scope-of-rfc) +- [Necessary rule schema changes](#necessary-rule-schema-changes) + - [`rule_source` field](#rule_source-field) + - [Deprecating the `immutable` field](#deprecating-the-immutable-field) + - [Subfields in the `rule_source` field](#subfields-in-the-rule_source-field) + - [`type` subfield](#type-subfield) + - [`is_customized` subfield](#is_customized-subfield) + - [`source_updated_at` subfield](#source_updated_at-subfield) + - [Changes needed in rule schema](#changes-needed-in-rule-schema) + - [API schema](#api-schema) + - [API request and response rule schema](#api-request-and-response-rule-schema) + - [Rule Import request schema](#rule-import-request-schema) + - [Internal rule schema](#internal-rule-schema) + - [Prebuilt Rule asset schema](#prebuilt-rule-asset-schema) + - [Deprecating the `immutable` field](#deprecating-the-immutable-field-1) +- [Mapping changes](#mapping-changes) +- [Plan for carrying out migrations of rule SOs](#plan-for-carrying-out-migrations-of-rule-sos) + - [Context](#context) + - [Problem with tightly coupled logic in our endpoints](#problem-with-tightly-coupled-logic-in-our-endpoints) + - [Migration strategy](#migration-strategy) + - [Normalization on read](#normalization-on-read) + - [Rule Management endpoints that will perform normalization-on-read](#rule-management-endpoints-that-will-perform-normalization-on-read) + - [Migration on write](#migration-on-write) + - [Rule Management endpoints that should include migration-on-write logic](#rule-management-endpoints-that-should-include-migration-on-write-logic) + - [Technical implementation of migration-on-write](#technical-implementation-of-migration-on-write) + - [Updating and upgrading rules](#updating-and-upgrading-rules) + - [Bulk editing rules](#bulk-editing-rules) +- [Endpoints and utilities that will need to be adapted to the new schema](#endpoints-and-utilities-that-will-need-to-be-adapted-to-the-new-schema) + - [Utilities](#utilities) + - [KQL filters and the `convertRulesFilterToKQL` method](#kql-filters-and-the-convertrulesfiltertokql-method) + - [Rule Management endpoints](#rule-management-endpoints) + - [Prebuilt Rules endpoints](#prebuilt-rules-endpoints) + - [Rule monitoring endpoints](#rule-monitoring-endpoints) + - [Rule Execution Logs](#rule-execution-logs) +- [Exporting and importing rules](#exporting-and-importing-rules) + - [Exporting rules](#exporting-rules) + - [Importing rules](#importing-rules) + - [Handling the `version` parameter](#handling-the-version-parameter) +- [Customizing Prebuilt Rules](#customizing-prebuilt-rules) + - [Endpoints](#endpoints) + - [Changes needed to endpoints](#changes-needed-to-endpoints) + - [Updating the `is_customized` field](#updating-the-is_customized-field) + - [In the UI](#in-the-ui) + - [Via the Rule Edit Page](#via-the-rule-edit-page) + - [Via Bulk Actions](#via-bulk-actions) + - [Via the Rules Details Page](#via-the-rules-details-page) + - [Via the Shared Exception Lists page](#via-the-shared-exception-lists-page) + - [Via the Stack Management \> Rules UI](#via-the-stack-management-rules-ui) +- [List of things to fix (create tickets)](#list-of-things-to-fix-create-tickets) +- [Upgrading Prebuilt Rules](#upgrading-prebuilt-rules) + - [Changes to upgrade `_review` endpoint](#changes-to-upgrade-_review-endpoint) + - [Concrete field diff algorithms by type](#concrete-field-diff-algorithms-by-type) + - [String fields](#string-fields) + - [Number fields](#number-fields) + - [Array fields](#array-fields) + - [Array of strings fields](#array-of-strings-fields) + - [Array of objects fields](#array-of-objects-fields) + - [Proposed algorithm](#proposed-algorithm) + - [MITRE ATT&CK framework (`threat` field)](#mitre-attck-framework-threat-field) + - [Changes to `/upgrade/_review` endpoint contract](#changes-to-upgrade_review-endpoint-contract) + - [Changes to `/upgrade/_perform` endpoint](#changes-to-upgrade_perform-endpoint) + - [Changes to `/upgrade/_perform` endpoint contract](#changes-to-upgrade_perform-endpoint-contract) + - [Changes to Rule Upgrade UX/UI flow](#changes-to-rule-upgrade-uxui-flow) + - [Bulk accepting upgrades with no conflicts](#bulk-accepting-upgrades-with-no-conflicts) + - [Upgrading rules with conflicts](#upgrading-rules-with-conflicts) +- [Scenario for bulk accepting updates](#scenario-for-bulk-accepting-updates) +- [Other open questions](#other-open-questions) + ## Note about scope of RFC This RFC was initially planned to have a scope strictly limited to the Customization of Prebuilt Rules epic. However, another epic is, in parallel, in the discussion phase: the [Detections-as-Code (DaC) epic](https://docs.google.com/document/d/1MfPFa3Io82S91rRfdQde8Xi_9AGEbE44Z2MkIYWD10U/edit). From 9a18e166e96a2a17e281c2b283e8e21ab0337cd5 Mon Sep 17 00:00:00 2001 From: jpdjere Date: Tue, 12 Mar 2024 17:59:37 +0100 Subject: [PATCH 29/61] Added pending changes --- .../docs/prebuilt_rules_customization_rfc.md | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md index 230dd2c12b7d5c..b156b00dc9fb36 100644 --- a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md +++ b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md @@ -102,9 +102,9 @@ pandoc prebuilt_rules_customization_rfc.md --toc --toc-depth=6 --wrap=none -s - This RFC was initially planned to have a scope strictly limited to the Customization of Prebuilt Rules epic. However, another epic is, in parallel, in the discussion phase: the [Detections-as-Code (DaC) epic](https://docs.google.com/document/d/1MfPFa3Io82S91rRfdQde8Xi_9AGEbE44Z2MkIYWD10U/edit). -Both epics have many areas of contact, and features/decisions in one need to take account features in the others. +Both epics have many areas of contact, and features/decisions in one need to take account features in the other. -This RFC includes some decision that will be taken in order to future-proof our archtecture for the upcoming DaC epic, but the vast majority will refer specifically to the Prebuilt Rules Customization epic. Elastic prebuilt rules will become a specific case of externally sourced rules: in the future, rules can be installed as Elastic prebuilt rules from our `detection-rules` repo, but also from any other repository handled by the user. +This RFC includes some decisions that will be taken in order to future-proof our archtecture for the upcoming DaC epic, but the vast majority will refer specifically to the Prebuilt Rules Customization epic. Elastic prebuilt rules will become a specific case of externally sourced rules: in the future, rules can be installed as Elastic prebuilt rules from our `detection-rules` repo, but also from any other repository handled by the user. During this RFC, we will explicitly refer to case of Elastic prebuilt rules, but take into account that this will be only a specific case of all the possible external sources for rules. @@ -2774,7 +2774,7 @@ The endpoint currently implemented contract needs to be updated as described in #### Changes to `/upgrade/_perform` endpoint contract -The endpoint's currently impled as deemented contract needs to be updatscribed in this [PoC](https://github.com/elastic/kibana/pull/144060). +The endpoint's currently implemented contract needs to be updated as described in this [PoC](https://github.com/elastic/kibana/pull/144060). @@ -2827,7 +2827,19 @@ Rules whose diffing algorithm resulted in a `CONFLICT` need to be manually resol > See [designs](https://www.figma.com/file/gLHm8LpTtSkAUQHrkG3RHU/%5B8.7%5D-%5BRules%5D-Rule-Immutability%2FCustomization?type=design&mode=design&t=LkauhLzUKUatF6cL-0#712870904). +## Other changes to UX/UI +### Rules Table page + +- The Rules Table's filter should be updated so that rules can be fitlered according to their status as **custom**, **Elastic prebuilt** and **customized Elastic prebuilt**. Notice that **customized Elastic prebuilt** will be a subset of **Elastic prebuilt**. + +### Rule Details page + +- The Rule Details page shouls include some kind of indication or text field that lets the user know if the current rules is **custom**, **Elastic prebuilt** and **customized Elastic prebuilt**. + +## Design Discussion link + +For an up-to-date discussion on the design changes needed for Milestone 3, please see [this ticket](https://github.com/elastic/kibana/issues/178211). From f27c13d67ad055e57c27adf3815912bd69305656 Mon Sep 17 00:00:00 2001 From: jpdjere Date: Mon, 18 Mar 2024 11:51:50 +0100 Subject: [PATCH 30/61] Update status --- .../docs/prebuilt_rules_customization_rfc.md | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md index b156b00dc9fb36..612f5b647899d2 100644 --- a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md +++ b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md @@ -1,6 +1,6 @@ # RFC: Prebuilt Rules Customization -_Status_: Finished Part 1, which includes sections from `Necessary rule schema changes` up until -and including- `Exporting and importing rules`. +_Status_: Completed, pending correction over team's feedback. Covers: @@ -13,12 +13,6 @@ Covers: - additional changes needed to `/upgrade/_review` and `/upgrade/_perform` endpoints - UI Changes -_Pending_: - - -- Additional details on `Changes needed in the UI`: Rule Details page, Rules Table -- Update `/upgrade/_perform` endpoint description to match POC proposal - ## Table of Contents The following TOC was created using the [Pandoc](https://pandoc.org/installing.html) tool. From 30fc99f9ccb4c0885fe29cf6c6a72b07625f1841 Mon Sep 17 00:00:00 2001 From: jpdjere Date: Mon, 18 Mar 2024 11:59:19 +0100 Subject: [PATCH 31/61] Addressing feedback --- .../docs/prebuilt_rules_customization_rfc.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md index 612f5b647899d2..ba5a9203301e38 100644 --- a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md +++ b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md @@ -122,13 +122,13 @@ In order to support the customization of Elastic Prebuilt Rules, we need to modi ### `rule_source` field -The `rule_source` field will be a required top-level object field in our rule schema that will be a discriminated union of two types: `'internal'` and `'external'`. +The `rule_source` field will be a top-level object field in our rule schema that will be a discriminated union of two types: `'internal'` and `'external'`. Rules with `rule_source` of type `internal` are rules generated internally in the Kibana application and which don't have an external origin outside of it. Rules with `rule_source` of type `external` are rules who have an external origin or source. Elastic prebuilt rules are a case of `external` rule, with the `detection-rules` repository handled by the TRaDE team being their external source origin. -This also means that a rule with this type of `rule_source` will determine that the rule is an Elastic Prebuilt Rule that can receive upstream updates via Fleet. This field is intented to partly replace the currently existing `immutable` field, which is used today for the same purpose, but -as its name indicates- also currently determines if a rule's fields can be modified/customized. +This also means that a rule with this type of `rule_source` will determine that the rule is an Elastic Prebuilt Rule that can receive upstream updates via Fleet. This field is intended to partly replace the currently existing `immutable` field, which is used today for the same purpose, but -as its name indicates- also currently determines if a rule's fields can be modified/customized. As seen in the schema, when the `rule_source` has type `'external'`, the object can contain two other subfields as well, `is_customized` and `source_updated_at`, explained below. If the object has type `'internal'`, no other fields should be present (subject to change in the future). From 2e0cd2671859c6979e70920664de95a936266a7f Mon Sep 17 00:00:00 2001 From: jpdjere Date: Mon, 18 Mar 2024 13:33:18 +0100 Subject: [PATCH 32/61] Addressing feedback --- .../docs/prebuilt_rules_customization_rfc.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md index ba5a9203301e38..d98fb913c9ae69 100644 --- a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md +++ b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md @@ -130,15 +130,13 @@ Rules with `rule_source` of type `external` are rules who have an external origi This also means that a rule with this type of `rule_source` will determine that the rule is an Elastic Prebuilt Rule that can receive upstream updates via Fleet. This field is intended to partly replace the currently existing `immutable` field, which is used today for the same purpose, but -as its name indicates- also currently determines if a rule's fields can be modified/customized. -As seen in the schema, when the `rule_source` has type `'external'`, the object can contain two other subfields as well, `is_customized` and `source_updated_at`, explained below. If the object has type `'internal'`, no other fields should be present (subject to change in the future). - ### Deprecating the `immutable` field In the current application's state, rules with `immutable: false` are rules which are not Elastic Prebuilt Rules, i.e. custom rules, and can be modified. Meanwhile, `immutable: true` rules are Elastic Prebuilt Rules, created by the TRaDE team, distributed via the `security_detection_engine` Fleet package, and cannot be modified once installed. When successfully implemented, the `rule_source` field should replace the `immutable` field as a mechanism to mark Elastic prebuilt rules, but with one difference: the `rule_source` field will determine if the rule is an Elastic Prebuilt Rule or not, but now all rules will be customizable by the user in Kibana, i.e. independently of the existence (or absence) of `rule_source`. -Because of this difference in the behaviour of the `rule_source` and `immutable` fields, we feel that a field called `immutable` will lose its meaning over time and become confusing, especially for consumers of the API who interact directly with the field name. That's why we want to eventually deprecate it and fully replace it with `rule_source`. +Because of this difference between the `rule_source` and `immutable` fields, the `immutable` field will lose its original meaning as soon as we allow users to customize prebuilt rules, which might become confusing for those API consumers who interact directly with this field. That's why we want to first deprecate it and later after a large enough deprecation period we could consider removing it completely from the API. To ensure backward compatibility and avoid breaking changes, we will deprecate the `immutable` field but keep it within the rule schema, asking our users to stop relying on this field in Detection API responses. During the migration period, we want to keep the value of the `immutable` field in sync with the `rule_source` fields: this means that for all rules that have a `immutable` value of `true`, the `rule_source` field will always be of type `'external'`. Viceversa, rules with `immutable: false` will have a `rule_source` field of type `'internal'`. @@ -146,11 +144,11 @@ This means, however, that there will be a change in behaviour of the `immutable` ### Subfields in the `rule_source` field -In this first phase, the `rule_source` will conditionally contain three subfields: the desciminant `type`, and the `is_customized` and `source_updated_at` values, only present when `type` is `'external'`. +In this first phase, the `rule_source` will conditionally contain three subfields: the discriminant `type`, and the `is_customized` and `source_updated_at` values, only present when `type` is `'external'`. #### `type` subfield -The `type` subfield serves as the discriminat to the disciminated union field `rule_source` and can take two values, as explained above: `'internal'` and `'external'`. +The `type` subfield serves as the discriminant to the discriminated union field `rule_source` and can take two values, as explained above: `'internal'` and `'external'`. #### `is_customized` subfield @@ -192,7 +190,7 @@ _Source: [x-pack/plugins/security_solution/common/api/detection_engine/model/rul # Add deprecation warning to `immutable` field IsRuleImmutable: type: boolean - description: '[DEPRECATION WARNING - This field is deprecated and will be removed in a future release. Use the prebuilt field to determine if a rule is an Elastic prebuilt rule or a custom rule.] - Determines whether the rule is immutable (i.e. cannot be modified by the user).' + description: '[DEPRECATION WARNING! This field is deprecated and... ] - Determines whether the rule is a prebuilt Elastic rule.' IsExternalRuleCustomized: type: boolean From 184eb0236182d3115fae3a3eefefffd52ca49c75 Mon Sep 17 00:00:00 2001 From: jpdjere Date: Mon, 18 Mar 2024 13:37:48 +0100 Subject: [PATCH 33/61] Addressing feedback --- .../docs/prebuilt_rules_customization_rfc.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md index d98fb913c9ae69..62b038f9a542f9 100644 --- a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md +++ b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md @@ -166,17 +166,15 @@ The `source_updated_at` will be a field containing a date in ISO 8601 format whi This field will be optional in both the API schema and the internal rule schema, since this value will not exist for prebuilt rules until a new version of each rule which includes this field in the prebuilt rule asset is published by the TRaDE team, and the user installs it or updates to it. +**NOTE:** the field will not be included in first iteration of the implementation. There is a dependency with the TRaDE team that has blocked the inclusion of this field in the `security-rule` SO, and the change has therefore been postponed. See ticket https://github.com/elastic/detection-rules/issues/2826 for details. + ### Changes needed in rule schema As detailed further down in the [Plan for carrying out migrations of rule SOs](#plan-for-carrying-out-migrations-of-rule-sos) section, we will be performing incremental migration-on-write on our saved objects to get to our new schemas (see details in linked section). This means that we need to differentiate between changes to the internal rule schema and the API schema. -#### API schema - -##### API request and response rule schema - -**In the API schema** the `rule_source` will be a required, as it will allow us to differentiate between Elastic prebuilt rules, and custom rules. +#### API request and response rule schema Notice, as well, that `immutable` and `rule_source` will continue to be part **only of the API response schema**, and never form part of the **request parameters**. @@ -266,7 +264,7 @@ ResponseFields: # [... file continues below...] ``` -##### Rule Import request schema +#### Rule Import request schema We also need to modify the `RuleToImport` schema, since now we will be allowing the importing of both custom rules and prebuilt rules. From c073689635746b1f1f3103d466f6a6c8288988f0 Mon Sep 17 00:00:00 2001 From: jpdjere Date: Mon, 18 Mar 2024 16:42:49 +0100 Subject: [PATCH 34/61] Addressing feedback --- .../docs/prebuilt_rules_customization_rfc.md | 240 ++++++++++-------- 1 file changed, 132 insertions(+), 108 deletions(-) diff --git a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md index 62b038f9a542f9..d627a9968b8a29 100644 --- a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md +++ b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md @@ -130,6 +130,56 @@ Rules with `rule_source` of type `external` are rules who have an external origi This also means that a rule with this type of `rule_source` will determine that the rule is an Elastic Prebuilt Rule that can receive upstream updates via Fleet. This field is intended to partly replace the currently existing `immutable` field, which is used today for the same purpose, but -as its name indicates- also currently determines if a rule's fields can be modified/customized. +Prebuilt rules will have: + +```ts +{ + rule_source: { + /** + * The discriminant of the discriminated union type of the `rule_source` field. + */ + type: 'external'; + + /** + * Determines whether the rule (which is prebuilt/external) has been customized by the user, + * i.e. if any of its fields have been modified and diverged from the base version of the rule, + * which is the version that is installed from the `security_detection_engine` Fleet package. + * The value will be initially set to `false` when a brand new prebuilt rule is installed, + * but will be rewritten to `true` if a rule's field is edited and diverges from the value + * from the base version of the rule. + * See section "Updating the `isCustomized` flag" + */ + is_customized: boolean; + + /** + * A date in ISO 8601 format which describes the last time that this prebuilt rule was created + * and subsequently updated by the TRaDE team, the team responsible for creating prebuilt rules. + * Its usage is detailed in https://github.com/elastic/detection-rules/issues/2826. + * This field will be optional in both the API schema and the internal rule schema, since + * this value will not exist for prebuilt rules until a new version of each rule which includes + * this field in the prebuilt rule asset is published by the TRaDE team, and the user installs + * it or updates to it. + * NOTE: the field will not be included in first iteration of the implementation. There is a + * dependency with the TRaDE team that has blocked the inclusion of this field in the `security-rule` SO, + * and the change has therefore been postponed. + * See ticket https://github.com/elastic/detection-rules/issues/2826 for details. + */ + source_updated_at?: Date; + }; +} +``` + +Custom rules will have: +```ts +{ + rule_source: { + /** + * The discriminant of the discriminated union type of the `rule_source` field. + */ + type: 'internal'; + }; +} +``` ### Deprecating the `immutable` field In the current application's state, rules with `immutable: false` are rules which are not Elastic Prebuilt Rules, i.e. custom rules, and can be modified. Meanwhile, `immutable: true` rules are Elastic Prebuilt Rules, created by the TRaDE team, distributed via the `security_detection_engine` Fleet package, and cannot be modified once installed. @@ -142,32 +192,6 @@ To ensure backward compatibility and avoid breaking changes, we will deprecate t This means, however, that there will be a change in behaviour of the `immutable` field: with the release of the feature, rules with the `immutable: true` value will now be customizable by the user, which is not the current behaviour. -### Subfields in the `rule_source` field - -In this first phase, the `rule_source` will conditionally contain three subfields: the discriminant `type`, and the `is_customized` and `source_updated_at` values, only present when `type` is `'external'`. - -#### `type` subfield - -The `type` subfield serves as the discriminant to the discriminated union field `rule_source` and can take two values, as explained above: `'internal'` and `'external'`. - -#### `is_customized` subfield - -The `is_customized` field will be a boolean field that determines whether an external/Prebuilt Rule has been customized by the user, i.e. if any of its fields have been modified and diverged from the base version of the rule, which is the version that is installed from the Prebuilt Rules `security_detection_engine` Fleet package. - -This means that the `is_customized` subfield only makes sense and will be used for prebuilt rules, or rules whose `rule_source` field is of type `'external'`. - -For prebuilt rules, the `rule_source.is_customized` value will be initially set to `false` when a brand new rule is installed, but will be rewritten to `true` if a rule's field is edited and diverges from the value from the base version of the rule. - -See section [Updating the `isCustomized` flag](#updating-the-is_customized-field) - -#### `source_updated_at` subfield - -The `source_updated_at` will be a field containing a date in ISO 8601 format which describes the last time that an Elastic Prebuilt Detection rule was created and subsequently updated by the TRaDe team, the team responsible for creating detection rules. Its usage is detailed in this [ticket](https://github.com/elastic/detection-rules/issues/2826). - -This field will be optional in both the API schema and the internal rule schema, since this value will not exist for prebuilt rules until a new version of each rule which includes this field in the prebuilt rule asset is published by the TRaDE team, and the user installs it or updates to it. - -**NOTE:** the field will not be included in first iteration of the implementation. There is a dependency with the TRaDE team that has blocked the inclusion of this field in the `security-rule` SO, and the change has therefore been postponed. See ticket https://github.com/elastic/detection-rules/issues/2826 for details. - ### Changes needed in rule schema As detailed further down in the [Plan for carrying out migrations of rule SOs](#plan-for-carrying-out-migrations-of-rule-sos) section, we will be performing incremental migration-on-write on our saved objects to get to our new schemas (see details in linked section). @@ -322,7 +346,7 @@ In the internal rule schema, there are two additional important reasons why we n - When rules are executed, a call to the method `validateRuleTypeParams` is done, which is a method that validates the passed rule's parameters using the validators defined in `x-pack/plugins/security_solution/server/lib/detection_engine/rule_types`, within each of the rule query types files (for [EQL rules](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/eql/create_eql_alert_type.ts#L27), for example). The validation is done based on the internal rule schema `BaseRulesParams` displayed above. Having `ruleSource` as required field would cause custom rules or prebuilt rules that haven't had their schema migrated to fail during runtime. - The Rule Client `update` method also calls the `validateRuleTypeParams` to validate the rule's params. Since the Rule Client's `update` method is used in our endpoint handlers, such as and `/rules/patch` and `/_bulk_actions`, these would fail when executed against a payload of custom rule. -##### Prebuilt Rule asset schema +#### Prebuilt Rule asset schema The `PrebuiltRuleAsset` type needs to be updated to include the new `source_updated_at` date that will be progressively shipped with new versions of rules in the Elastic Prebuilt Rules package. @@ -585,7 +609,7 @@ Additionally: - **Bulk Actions** - `POST /rules/_bulk_action`: with **duplicate** action -will perform migration but does not allow for customization during the duplication proces. +will perform migration but does not allow for customization during the duplication process. So we can analyze the expected outputs of the migration of all these 8 endpoints together. @@ -611,12 +635,12 @@ The resulting values for `immutable` and `rule_source` when calling these endpoi
    N/A - Doesn't apply for custom rules
    -          {
    -            rule_source: {
    -              type: 'internal'
    -            },
    -            immutable: false,
    -          }
    +{
    +  rule_source: {
    +    type: 'internal'
    +  },
    +  immutable: false,
    +}
             
    N/A - Doesn't apply for custom rules
    -          {
    -            rule_source: {
    -              type: 'internal'
    -            },
    -            immutable: false,
    -          }
    +{
    +  rule_source: {
    +    type: 'internal'
    +  },
    +  immutable: false,
    +}
             
    No
    -          {
    -            rule_source: {
    -              type: 'external',
    -              isCustomized: false,
    -              ...
    -            },
    -            immutable: true,
    -          }
    +{
    +  rule_source: {
    +    type: 'external',
    +    isCustomized: false,
    +    ...
    +  },
    +  immutable: true,
    +}
             
    Yes
    -          {
    -            rule_source: {
    -              type: 'external',
    -              isCustomized: true,
    -              ...
    -            },
    -            immutable: true,
    -          }
    +{
    +  rule_source: {
    +    type: 'external',
    +    isCustomized: true,
    +    ...
    +  },
    +  immutable: true,
    +}
             
    Prebuilt rule (already migrated, no customizations)
     
    -          {
    -            type: 'external',
    -            isCustomized: false,
    -              ...
    -          }
    +{
    +  type: 'external',
    +  isCustomized: false,
    +    ...
    +}
               
    true
    No
    -          {
    -            rule_source: {
    -              type: 'external',
    -              isCustomized: false,
    -              ...
    -            },
    -            immutable: true,
    -          }
    +{
    +  rule_source: {
    +    type: 'external',
    +    isCustomized: false,
    +    ...
    +  },
    +  immutable: true,
    +}
             
    Prebuilt rule (already migrated, with customizations)
     
    -          {
    -            type: 'external',
    -            isCustomized: true,
    -              ...
    -          }
    +{
    +  type: 'external',
    +  isCustomized: true,
    +    ...
    +}
               
    true
    Yes
    -          {
    -            rule_source: {
    -              type: 'external',
    -              isCustomized: true,
    -              ...
    -            },
    -            immutable: true,
    -          }
    +{
    +  rule_source: {
    +    type: 'external',
    +    isCustomized: true,
    +    ...
    +  },
    +  immutable: true,
    +}
             
    Customized Prebuilt rule (already migrated, no customizations after update)
     
    -          {
    -            type: 'external',
    -            isCustomized: true,
    -              ...
    -          }
    +{
    +  type: 'external',
    +  isCustomized: true,
    +    ...
    +}
               
    true
    No
    -          {
    -            rule_source: {
    -              type: 'external',
    -              isCustomized: false,
    -              ...
    -            },
    -            immutable: true,
    -          }
    +{
    +  rule_source: {
    +    type: 'external',
    +    isCustomized: false,
    +    ...
    +  },
    +  immutable: true,
    +}
             
    Invalid case: Migrating a migrated non-customized prebuilt rule, with customizations.

    `immutable` should never be false if `rule_source.type' is 'external'. Migration should correct this inconsistency.
     
    -          {
    -            type: 'external',
    -            isCustomized: false,
    -              ...
    -          }
    +{
    +  type: 'external',
    +  isCustomized: false,
    +    ...
    +}
               
    false
    Yes
    -          {
    -            rule_source: {
    -              type: 'external',
    -              isCustomized: true,
    -              ...
    -            },
    -            immutable: true,
    -          }
    +{
    +  rule_source: {
    +    type: 'external',
    +    isCustomized: true,
    +    ...
    +  },
    +  immutable: true,
    +}
             
    No - Rule import rejected
    because of rule_id match + Rule import rejected
    because of rule_id match and overwrite flag is false
    @@ -1833,7 +1849,7 @@ Once done editing the rule, the user clicks on the "Save Changes" button, which **Expected behaviour for customizing prebuilt rules** - All four tabs of the Rule Edit page should be enabled, and all the fields within each tab should be editable, as they currently are for custom rules. -- The only field in the UI that should not be customizable is **Rule Type**, that should continue to be read-only. +- The only fields in the UI that should not be customizable are: **Rule Type**, **Author** and **License**, which should continue to be read-only. - **Definition** should be the default open tab when opening the edit rule page for a prebuilt rule (current default is **Actions**) - Field validation should continue to work as it does for custom rules. - No fields should return a validation error for the values that come from the `security_detection_engine` package prebuilt rules. This means that a user should be able to successfully save the prebuilt rule with no changes. See **List of issues to fix** below. From 826c239b21fe1ea13408998b0bedc621239e3eba Mon Sep 17 00:00:00 2001 From: jpdjere Date: Tue, 19 Mar 2024 00:08:22 +0100 Subject: [PATCH 42/61] Addressing feedback --- .../docs/prebuilt_rules_customization_rfc.md | 30 +++++++------------ 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md index 38abecd8d01abd..3daedacde9cdb9 100644 --- a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md +++ b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md @@ -1854,6 +1854,10 @@ Once done editing the rule, the user clicks on the "Save Changes" button, which - Field validation should continue to work as it does for custom rules. - No fields should return a validation error for the values that come from the `security_detection_engine` package prebuilt rules. This means that a user should be able to successfully save the prebuilt rule with no changes. See **List of issues to fix** below. +#### Via Rules Table page + +- The Rules Table's filter should be updated so that rules can be fitlered according to their status as **custom**, **Elastic prebuilt** and **customized Elastic prebuilt**. Notice that **customized Elastic prebuilt** will be a subset of **Elastic prebuilt**. + #### Via Bulk Actions Custom rules can currently be updated via the Rule Table's **Bulk Actions**, which uses the **Bulk Actions** - `POST /rules/_bulk_action` endpoint. @@ -1871,7 +1875,7 @@ As explained above, the UI validates that the five actions listed above are only **Expected behaviour for customizing prebuilt rules** - The Bulk Actions UI should now allow users to edit prebuilt rules. -- All bulk actions actions listed above should now be applicable to prebuilt rules (This means that the changes in the API for the validation done in `dryRun` mode should not remove the rules from the payload anymore). +- All bulk actions listed above should now be applicable to prebuilt rules (This means that the changes in the API for the validation done in `dryRun` mode should not remove the rules from the payload anymore). > The `dryRun` mode request will still be necessary since we perform other checks that can still prevent prebuilt rules from being edited. For example, Machine Learning and ES|QL rules cannot be bulk edited to add or delete index patterns, since they don't have that field in their schema. @@ -1884,7 +1888,9 @@ The Rules Details page allows the user to modify the rule in two ways: - setting rule snoozing - uses `POST /alerting/rule/{rule_id}/_snooze` endpoint -Both of these actions are already possible for prebuilt rules, **so no changes are necessary here.** +Both of these actions are already possible for prebuilt rules. + +- The Rule Details page should include a text field that lets the user know if the current rules is **custom**, **Elastic prebuilt** and **customized Elastic prebuilt**. #### Via the Shared Exception Lists page @@ -1914,12 +1920,9 @@ All of these actions are currently applicable for both prebuilt security rules a This means that **no changes will be needed in this page.** -## List of things to fix (create tickets) - -1. Validation of EQL queries incorrectly fails: valid EQL queries that come with Prebuilt Rules are rejected by the EQL validator when trying to edit a rule. See [link](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/public/detections/components/rules/step_define_rule/schema.tsx#L186). -2. Custom Query field overflows the viewport and cannot be completely visualized/edited when the query is too long, i.e. occupies too many lines. This is often the case from Prebuilt Rules. The editable field also does not allow scrolling. See example: - ![](2023-12-01-14-13-07.png) +## Design Discussion link +For an up-to-date discussion on the design changes needed for Milestone 3, please see [this ticket](https://github.com/elastic/kibana/issues/178211). ## Upgrading Prebuilt Rules @@ -2834,19 +2837,6 @@ Rules whose diffing algorithm resulted in a `CONFLICT` need to be manually resol ## Other changes to UX/UI -### Rules Table page - -- The Rules Table's filter should be updated so that rules can be fitlered according to their status as **custom**, **Elastic prebuilt** and **customized Elastic prebuilt**. Notice that **customized Elastic prebuilt** will be a subset of **Elastic prebuilt**. - -### Rule Details page - -- The Rule Details page shouls include some kind of indication or text field that lets the user know if the current rules is **custom**, **Elastic prebuilt** and **customized Elastic prebuilt**. - -## Design Discussion link - -For an up-to-date discussion on the design changes needed for Milestone 3, please see [this ticket](https://github.com/elastic/kibana/issues/178211). - - From d92ebd6296fc0f8404818462f0bee6c7c307e3e8 Mon Sep 17 00:00:00 2001 From: jpdjere Date: Fri, 22 Mar 2024 16:31:29 +0100 Subject: [PATCH 43/61] Started fixing concrete diff algorithms section --- .../docs/prebuilt_rules_customization_rfc.md | 212 +++++++++++++----- 1 file changed, 151 insertions(+), 61 deletions(-) diff --git a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md index 3daedacde9cdb9..a3532a73b31e58 100644 --- a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md +++ b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md @@ -1200,9 +1200,15 @@ Given the requirements described above, the following table shows the behaviour - @@ -1217,7 +1223,6 @@ Given the requirements described above, the following table shows the behaviour
     {
       name: "My prebuilt rule",
    -  source_updated_at: "2024-05-..."
     } 
     
    @@ -1237,7 +1242,6 @@ Given the requirements described above, the following table shows the behaviour rule_source: { type: "external", is_customized: false, - source_updated_at: "2024-05-..." } } @@ -1254,7 +1258,6 @@ Given the requirements described above, the following table shows the behaviour
     {
       name: "My prebuilt rule",
    -  source_updated_at: "2024-05-..."
     } 
     
    @@ -1274,7 +1277,6 @@ Given the requirements described above, the following table shows the behaviour rule_source: { type: "external", is_customized: true, - source_updated_at: "2024-05-..." } } @@ -1290,7 +1292,6 @@ Given the requirements described above, the following table shows the behaviour rule_source: { type: "external", is_customized: false, - source_updated_at: "2024-05-..." } } @@ -1299,7 +1300,6 @@ Given the requirements described above, the following table shows the behaviour
     {
       name: "My prebuilt rule",
    -  source_updated_at: "2024-05-..."
     } 
     
    @@ -1328,7 +1328,6 @@ Given the requirements described above, the following table shows the behaviour rule_source: { type: "external", is_customized: false, - source_updated_at: "2024-05-..." } } @@ -1337,7 +1336,6 @@ Given the requirements described above, the following table shows the behaviour
     {
       name: "My prebuilt rule",
    -  source_updated_at: "2024-05-..."
     } 
     
    @@ -1357,7 +1355,6 @@ Given the requirements described above, the following table shows the behaviour rule_source: { type: "external", is_customized: true, - source_updated_at: "2024-05-..." } } @@ -1377,7 +1374,6 @@ Given the requirements described above, the following table shows the behaviour rule_source: { type: "external", is_customized: true, - source_updated_at: "2024-05-..." } } @@ -1386,7 +1382,6 @@ Given the requirements described above, the following table shows the behaviour
     {
       name: "My prebuilt rule",
    -  source_updated_at: "2024-05-..."
     } 
     
    @@ -1406,7 +1401,6 @@ Given the requirements described above, the following table shows the behaviour rule_source: { type: "external", is_customized: false, - source_updated_at: "2024-05-..." } } @@ -1890,7 +1884,7 @@ The Rules Details page allows the user to modify the rule in two ways: Both of these actions are already possible for prebuilt rules. -- The Rule Details page should include a text field that lets the user know if the current rules is **custom**, **Elastic prebuilt** and **customized Elastic prebuilt**. +- The Rule Details page should include a text field that lets the user know if the current rules is **custom**, **Elastic prebuilt** and **customized Elastic prebuilt**. #### Via the Shared Exception Lists page @@ -1937,60 +1931,156 @@ We propose developing more adaptable diff algorithms tailored to specific rule f Depending on the specific field or type of field we might want to apply a specific merging algorithm when conflicts arise. Let's propose different types. -##### String fields +##### Single-line string fields + +> Examples: `name`, `query` + +For single-line string fields we will continue to use the existing simple diff algorithm: + +- if `base` !== `current` !== target, we mark the diff as a conflict and use the current version as the merge proposal +- if `base` === `target` && `base` !== `current`, we set merge proposal to be the current version, without a conflict +- if `base` === `current` && `base` !== `target`, we set merge proposal to be the target version, without a conflict + +Reasons why we'll continue to use the simple diff algorithm for single-line string fields: +- Merging keywords (especially enums) should never be done, because it could generate an invalid value. +- Changes to a rule's name might indicate some semantical changes to the whole rule (e.g. related to its source data, query/filters logic, etc). So, if both Elastic and user changed the name of the same rule, this could be an indication that the two versions of these rule are not compatible with each other, and the changes need to be reviewed by the user. Generating a conflict in this case would help the user to pay attention to all the changes. + +
    N/A - Prebuilt rule import rejected because no matching
    - version found for existing rule_id security-asset +
    +{
    +  name: "My prebuilt rule",
    +  rule_source: {
    +    type: "external",
    +    is_customized: false,
    +  }
    +} 
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Use caseBase versionCurrent versionTarget versionMerged version (output)Conflict?
    No customization, no updates (AAA)My rule nameMy rule nameMy rule nameMy rule nameNO
    User customization, no updates (ABA)My rule nameMy CUSTOM rule nameMy rule nameMy CUSTOM rule nameNO
    No customization, upstream update (AAB)My rule nameMy rule nameMy UPDATED rule nameMy UPDATED rule nameNO
    Customization and upstream update match (ABB)My rule nameMy GREAT rule nameMy GREAT rule nameMy GREAT rule nameNO
    Customization and upstream update conflict (ABC)My rule nameMy GREAT rule nameMy EXCELLENT rule nameMy GREAT rule nameYES
    + + +##### Multi-line string fields + +> Examples: `description`, `setup`, `note` (Investigation guide) + + in case of three-way conflicts, we will make a best effort to reconcile any modifications done by the user and any updates proposed by Elastic. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Use caseBase versionCurrent versionTarget versionMerged version (output)Mark as conflict?
    No customization, no updates (AAA)
    My description. 
    This is a second line.
    My description. 
    This is a second line.
    My description. 
    This is a second line.
    My description. 
    This is a second line.
    NO
    User customization, no updates (ABA)
    My description. 
    This is a second line.
    My CUSTOM description. 
    This is a second line.
    My description. 
    This is a second line.
    My CUSTOM description. 
    This is a second line.
    NO
    No customization, upstream update (AAB)
    My description. 
    This is a second line.
    My description. 
    This is a second line.
    My UDPATED description. 
    This is a second line.
    My UDPATED description. 
    This is a second line.
    NO
    Customization and upstream update match (ABB)
    My description. 
    This is a second line.
    My GREAT description. 
    This is a second line.
    My GREAT description. 
    This is a second line.
    My GREAT description. 
    This is a second line.
    NO
    Customization and upstream update solvable conflict (ABC)
    My description. 
    This is a second line.
    My GREAT description. 
    This is a second line.
    My description. 
    This is a second line, now longer.
    My GREAT description. 
    This is a second line, now longer.
    YES
    Customization and upstream update non-solvable conflict (ABC)
    My description. 
    This is a second line.
    My GREAT description. 
    This is a third line.
    My EXCELLENT description. 
    This is a fourth line.
    My GREAT description. 
    This is a third line.
    YES
    -For string fields, in case of three-way conflicts, we will make a best effort to reconcile any modifications done by the user and any updates proposed by Elastic. -Examples: `name`, `description`, `setup`, `note` (Investigation guide) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Use caseBase versionCurrent versionTarget versionMerged version (output)
    Keep user customizations when whole string conflictsPrebuilt rule nameCompletely different stringUpdated prebuilt rule nameCompletely different string
    Keep user-added prefixes and accept other modificationsPrebuilt rule name[Security Solution] Prebuilt rule nameUpdated prebuilt rule name[Security Solution] Updated prebuilt rule name
    Keep user-added suffixes and accept other modificationsPrebuilt rule namePrebuilt rule name - (Custom version 3)Updated prebuilt rule nameUpdated prebuilt rule name - (Custom version 3)
    Keep user customizations on conflicts, but add updates in sections with no conflictsPrebuilt rule nameCustomized prebuilt rule nameUpdated prebuilt rule name. Much better.Customized prebuilt rule name. Much better.
    ##### Number fields +> Examples: `risk_score`, `max_signals` + Number fields should be treated as a whole unit, i.e. not breakable by digits. Therefore, there is only one possibility of conflicts, the scenario (A B C). In that case, **keep the current version** with the user customization. -Examples: `risk_score`, `max_signals` + From 5ef3901005b9bfcee13a329674d918acaa768367 Mon Sep 17 00:00:00 2001 From: jpdjere Date: Fri, 22 Mar 2024 16:45:02 +0100 Subject: [PATCH 44/61] Fix Numbers algorithm --- .../docs/prebuilt_rules_customization_rfc.md | 118 +++++++++++------- 1 file changed, 70 insertions(+), 48 deletions(-) diff --git a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md index a3532a73b31e58..72da1d215ff5b4 100644 --- a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md +++ b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md @@ -1921,17 +1921,23 @@ For an up-to-date discussion on the design changes needed for Milestone 3, pleas ## Upgrading Prebuilt Rules -### Changes to upgrade `_review` endpoint +### Changes to `/upgrade/_perform` endpoint -The algorithm for calculating rule version diffs' core structure is [fully implemented](https://github.com/elastic/kibana/pull/148392) and operational. However, the current method for calculating field differences is basic: it currently simply compares field values across versions and flags a conflict if the base version, the current version and the target versions differ from one another. In this conflict scenario, the `mergedVersion` of the field proposed by the algorithm always equals the `targetVersion`. +The endpoint's currently implemented contract needs to be updated as described in this [PoC](https://github.com/elastic/kibana/pull/144060). -We propose developing more adaptable diff algorithms tailored to specific rule fields or rule field types. These more specific algorithms aim to minimize conflicts and automate merging of changes, doing the best effort to keep the intended customizations applied by the user, as well as the updates proposed by Elastic. Hopefully, the user will be able to simply review the proposal and accept it. +### Changes to `/upgrade/_review` endpoint + +The endpoint currently implemented contract needs to be updated as described in this [PoC](https://github.com/elastic/kibana/pull/144060). -#### Concrete field diff algorithms by type +### Concrete field diff algorithms by type + +The algorithm used in the `/upgrade/_review` endpoint for calculating rule version diffs' core structure is [fully implemented](https://github.com/elastic/kibana/pull/148392) and operational. However, the current method for calculating field differences is basic: it currently simply compares field values across versions and flags a conflict if the base version, the current version and the target versions differ from one another. In this conflict scenario, the `mergedVersion` of the field proposed by the algorithm always equals the `targetVersion`. + +We propose developing more adaptable diff algorithms tailored to specific rule fields or rule field types. These more specific algorithms aim to minimize conflicts and automate merging of changes, doing the best effort to keep the intended customizations applied by the user, as well as the updates proposed by Elastic. Hopefully, the user will be able to simply review the proposal and accept it. Depending on the specific field or type of field we might want to apply a specific merging algorithm when conflicts arise. Let's propose different types. -##### Single-line string fields +#### Single-line string fields > Examples: `name`, `query` @@ -1953,7 +1959,7 @@ Reasons why we'll continue to use the simple diff algorithm for single-line stri - + @@ -2001,7 +2007,7 @@ Reasons why we'll continue to use the simple diff algorithm for single-line stri
    Current version Target version Merged version (output)Conflict?Mark as conflict?
    -##### Multi-line string fields +#### Multi-line string fields > Examples: `description`, `setup`, `note` (Investigation guide) @@ -2072,40 +2078,68 @@ Reasons why we'll continue to use the simple diff algorithm for single-line stri - - -##### Number fields +#### Number fields > Examples: `risk_score`, `max_signals` -Number fields should be treated as a whole unit, i.e. not breakable by digits. Therefore, there is only one possibility of conflicts, the scenario (A B C). In that case, **keep the current version** with the user customization. - - +Number fields should be treated as a whole unit, i.e. not breakable by digits. Therefore, there is only one possibility of conflicts, the scenario (A B C), which is not solvable. In that case, **keep the current version** with the user customization. - - - - - - - - - - - - - - - - - - - -
    Use caseBase versionCurrent versionTarget versionMerged version (output)
    Keep customizations if conflict50652065
    - -##### Array fields + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Use caseBase versionCurrent versionTarget versionMerged version (output)Mark as conflict?
    No customization, no updates (AAA)10101010NO
    User customization, no updates (ABA)10151015NO
    No customization, upstream update (AAB)10101515NO
    Customization and upstream update match (ABB)10202020NO
    Customization and upstream update conflict (ABC)10203020YES
    -###### Array of strings fields +#### Array of strings fields For **array of strings** fields, conflict resolution will take place on an element by element basis - that means that the algorithm will not consider or try to solve changes within a single element. For example: @@ -2861,18 +2895,6 @@ The `threat` field has a specific [schema](https://github.com/elastic/kibana/blo -#### Changes to `/upgrade/_review` endpoint contract - -The endpoint currently implemented contract needs to be updated as described in this [PoC](https://github.com/elastic/kibana/pull/144060). - - - - -### Changes to `/upgrade/_perform` endpoint - -#### Changes to `/upgrade/_perform` endpoint contract - -The endpoint's currently implemented contract needs to be updated as described in this [PoC](https://github.com/elastic/kibana/pull/144060). From d38964cca71cd372de0c6d7c3b39498f6628e2a0 Mon Sep 17 00:00:00 2001 From: jpdjere Date: Fri, 22 Mar 2024 17:08:52 +0100 Subject: [PATCH 45/61] Change --- .../security_solution/docs/prebuilt_rules_customization_rfc.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md index 72da1d215ff5b4..4a8b7712045c03 100644 --- a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md +++ b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md @@ -1,6 +1,6 @@ # RFC: Prebuilt Rules Customization -_Status_: Completed, pending correction over team's feedback. +_Status_: Completed, pending correction after team's feedback. Covers: From f7972664457d66bbb795a4da3a1b322fb4be1c00 Mon Sep 17 00:00:00 2001 From: jpdjere Date: Fri, 22 Mar 2024 17:14:19 +0100 Subject: [PATCH 46/61] Add explanation --- .../docs/prebuilt_rules_customization_rfc.md | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md index 4a8b7712045c03..8a9f84866e1ecc 100644 --- a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md +++ b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md @@ -1935,17 +1935,23 @@ The algorithm used in the `/upgrade/_review` endpoint for calculating rule versi We propose developing more adaptable diff algorithms tailored to specific rule fields or rule field types. These more specific algorithms aim to minimize conflicts and automate merging of changes, doing the best effort to keep the intended customizations applied by the user, as well as the updates proposed by Elastic. Hopefully, the user will be able to simply review the proposal and accept it. +In general, for all types of fields, we will follow the heuristic: + +- if `base` === `target` && `base` !== `current`, we set merge proposal to be the current version, without a conflict +- if `base` === `current` && `base` !== `target`, we set merge proposal to be the target version, without a conflict +- if `base` !== `current` !== target: mark the diff as a conflict AND: + - **if conflict is non-solvable**: use the `current` version as the merge proposal + - **if conflict is solvable** use the generated merged version as the merge proposal (possible only in a few types, detailed below - see tables) + Depending on the specific field or type of field we might want to apply a specific merging algorithm when conflicts arise. Let's propose different types. #### Single-line string fields > Examples: `name`, `query` -For single-line string fields we will continue to use the existing simple diff algorithm: +For single-line string fields we will continue to use the existing simple diff algorithm because: + -- if `base` !== `current` !== target, we mark the diff as a conflict and use the current version as the merge proposal -- if `base` === `target` && `base` !== `current`, we set merge proposal to be the current version, without a conflict -- if `base` === `current` && `base` !== `target`, we set merge proposal to be the target version, without a conflict Reasons why we'll continue to use the simple diff algorithm for single-line string fields: - Merging keywords (especially enums) should never be done, because it could generate an invalid value. From e44c5705ea1ecc7b09990a6e72269d1d5ef74f93 Mon Sep 17 00:00:00 2001 From: jpdjere Date: Fri, 22 Mar 2024 17:39:00 +0100 Subject: [PATCH 47/61] Added references to nodeDiff3 --- .../docs/prebuilt_rules_customization_rfc.md | 101 ++++++++++++++++-- 1 file changed, 95 insertions(+), 6 deletions(-) diff --git a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md index 8a9f84866e1ecc..66a7614e6293b6 100644 --- a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md +++ b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md @@ -1949,11 +1949,7 @@ Depending on the specific field or type of field we might want to apply a specif > Examples: `name`, `query` -For single-line string fields we will continue to use the existing simple diff algorithm because: - - - -Reasons why we'll continue to use the simple diff algorithm for single-line string fields: +For single-line string fields we will continue to use the existing simple diff algorithm, with all non-solvable scenarios in case of conflict, because: - Merging keywords (especially enums) should never be done, because it could generate an invalid value. - Changes to a rule's name might indicate some semantical changes to the whole rule (e.g. related to its source data, query/filters logic, etc). So, if both Elastic and user changed the name of the same rule, this could be an indication that the two versions of these rule are not compatible with each other, and the changes need to be reviewed by the user. Generating a conflict in this case would help the user to pay attention to all the changes. @@ -2017,8 +2013,101 @@ Reasons why we'll continue to use the simple diff algorithm for single-line stri > Examples: `description`, `setup`, `note` (Investigation guide) - in case of three-way conflicts, we will make a best effort to reconcile any modifications done by the user and any updates proposed by Elastic. +For multi-line string fields, in case of scenarios where the `base`, `current` and `target` versions are different, the scenario is marked as conflict. +However, in some cases the merged proposal can be successfully calculated and solved, while in other cases not. + +These two types of scenarios are found in the last two rows of the table, but let's see an example of each in detail: + +**Solvable conflict** +**BASE:** +``` +My description. +This is a second line. +``` +**CURRENT** +``` +My GREAT description. +This is a second line. +``` +**TARGET** +``` +My description. +This is a second line, now longer. +``` + +Using a diffing library such as `nodeDiff3`, we can attempt to create a merge proposal out of the 3 versions: +```ts +const nodeDiff3 = require("node-diff3"); +const base = "My description. \nThis is a second line."; +const current = "My GREAT description. \nThis is a second line."; +const target = "My description. \nThis is a second line, now longer."; + +const nodeDiff3.diff3Merge(current, base, target) // Order is not a typo, that's how the library works + +// OUTPUTS: +// [ +// { +// ok: [ +// 'My', 'GREAT', +// 'description.', 'This', +// 'is', 'a', +// 'second', 'line,', +// 'now', 'longer.' +// ] +// } +// ] +``` +The library is able to solve the changes of the two sentences individually and produces an acceptable merge proposal. We should still mark it as a conflict to drive the user's attention to the result and allow them to decide if it makes sense or not. + +**Non-Solvable conflict** +**BASE:** +``` +My description. +This is a second line. +``` +**CURRENT** +``` +My GREAT description. +This is a third line. +``` +**TARGET** +``` +My EXCELLENT description. +This is a fourth. +``` + +```ts +const base = "My description. \nThis is a second line."; +const current = "My GREAT description. \nThis is a third line."; +const target = "My EXCELLENT description. \nThis is a fourth line."; + +nodeDiff3.diff3Merge(current, base, target); + +// OUTPUTS: +// [ +// { ok: [ 'My' ] }, +// { +// conflict: { a: [Array], aIndex: 1, o: [], oIndex: 1, b: [Array], bIndex: 1 } +// }, +// { ok: [ 'description.', 'This', 'is', 'a' ] }, +// { +// conflict: { +// a: [Array], +// aIndex: 6, +// o: [Array], +// oIndex: 5, +// b: [Array], +// bIndex: 6 +// } +// }, +// { ok: [ 'line.' ] } +// ] +``` +The library marks multiple sections of the string as conflicts, since the same sentences have diverged in different way in the current and target version from the original base version. + +Since in this kind of scenarios we cannot provide a satisfactory merge proposal, we will mark it as a conflict and propose the `current` version as the `merge` version. +In summary: From 820034ec415c20f1d7426041cbb633a9f6111101 Mon Sep 17 00:00:00 2001 From: jpdjere Date: Fri, 22 Mar 2024 17:48:16 +0100 Subject: [PATCH 48/61] Cleanup --- .../docs/prebuilt_rules_customization_rfc.md | 134 +----------------- 1 file changed, 1 insertion(+), 133 deletions(-) diff --git a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md index 66a7614e6293b6..45c94108f8c968 100644 --- a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md +++ b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md @@ -2877,119 +2877,6 @@ Examples: `related_integrations,` `required_fields`
    -##### MITRE ATT&CK framework (`threat` field) - -The `threat` field has a specific [schema](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/common_attributes.gen.ts#L250) that can be handled with its own algorithm in case of conflicts, in order to try to obtain the most reasonable merge between versions. - -**TODO: write algorithm specific to this field** - - - - - - - - - - - - - - - - - - - - -
    Use caseBase versionCurrent versionTarget versionMerged version (output)
    Keep user customizations on conflicts, but update sections with no conflicts -
    -[{
    -    "framework":"MITRE ATT&CK",
    -    "tactic":{
    -      "id":"TA0003",
    -      "name":"Persistence",
    -      "reference":"https://attack.mitre.org/tactics/TA0003/"
    -    },
    -    "technique":[
    -      {
    -          "id":"T1098",
    -          "name":"Account Manipulation",
    -          "reference":"https://attack.mitre.org/techniques/T1098/"
    -      }
    -    ]
    -}]
    -        
    -
    -
    -[{
    -    "framework":"MITRE ATT&CK",
    -    "tactic":{
    -      "id":"TA0003",
    -      "name":"My customized name",
    -      "reference":"https://attack.mitre.org/tactics/TA0003/My_custom_url"
    -    },
    -    "technique":[
    -      {
    -          "id":"T1098",
    -          "name":"Account Manipulation",
    -          "reference":"https://attack.mitre.org/techniques/T1098/"
    -      }
    -    ]
    -}]
    -        
    -
    -
    -[{
    -    "framework":"MITRE ATT&CK",
    -    "tactic":{
    -      "id":"TA0003",
    -      "name":"Persistence",
    -      "reference":"https://attack.mitre.org/tactics/TA0003/"
    -    },
    -    "technique":[
    -      {
    -          "id":"T1556",
    -          "name":"Modify Authentication Process",
    -          "reference":"https://attack.mitre.org/techniques/T1556/",
    -          "subtechnique":[
    -            {
    -                "id":"T1556.006",
    -                "name":"Multi-Factor Authentication",
    -                "reference":"https://attack.mitre.org/techniques/T1556/006/"
    -            }
    -          ]
    -      }
    -    ]
    -}]
    -        
    -
    -
    -[{
    -    "framework":"MITRE ATT&CK",
    -    "tactic":{
    -      "id":"TA0003",
    -      "name":"My customized name",
    -      "reference":"https://attack.mitre.org/tactics/TA0003/My_custom_url"
    -    },
    -    "technique":[
    -      {
    -          "id":"T1556",
    -          "name":"Modify Authentication Process",
    -          "reference":"https://attack.mitre.org/techniques/T1556/",
    -          "subtechnique":[
    -            {
    -                "id":"T1556.006",
    -                "name":"Multi-Factor Authentication",
    -                "reference":"https://attack.mitre.org/techniques/T1556/006/"
    -            }
    -          ]
    -      }
    -    ]
    -}]
    -        
    -
    - @@ -3022,7 +2909,7 @@ const performUpgradePayload = { .map((rule) => ({ rule_id: rule.rule_id, revision: rule.revision, - version: rule.version, + version: rule.target_rule.version, })), pick_version: 'MERGE', }; @@ -3042,28 +2929,9 @@ Rules whose diffing algorithm resulted in a `CONFLICT` need to be manually resol > See [designs](https://www.figma.com/file/gLHm8LpTtSkAUQHrkG3RHU/%5B8.7%5D-%5BRules%5D-Rule-Immutability%2FCustomization?type=design&mode=design&t=LkauhLzUKUatF6cL-0#712870904). -## Other changes to UX/UI - - - - - - ----- end of RFC ----- -## Scenario for bulk accepting updates -- At rules table level - Bulk accept all rule updates that have no conflicting fields at all → This would make the request to update all these rules with no conflicts at all. - Accept all rule updates for non-customized rules. -- At rule (filed-per-field) level - Accept all fields that have no conflicting changes, but still requires the user to manually solve fields with conflicts. → Once all fields are solved, the user can make the request to update the rule. - Accept all fields that are not customized -- User Config - Create a user config/setting that the user can turn on to accept updates automatically if there are no conflicts. - Or we should more concretely how we want this setting to behave -## Other open questions From 473c1dcb9023f4bd956099e6aba19104977707dc Mon Sep 17 00:00:00 2001 From: jpdjere Date: Mon, 25 Mar 2024 11:13:13 +0100 Subject: [PATCH 49/61] Fixed Array of strings section --- .../docs/prebuilt_rules_customization_rfc.md | 120 ++++++++++++++++-- 1 file changed, 112 insertions(+), 8 deletions(-) diff --git a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md index 45c94108f8c968..c86c57207ff9a6 100644 --- a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md +++ b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md @@ -2236,17 +2236,121 @@ Number fields should be treated as a whole unit, i.e. not breakable by digits. T #### Array of strings fields -For **array of strings** fields, conflict resolution will take place on an element by element basis - that means that the algorithm will not consider or try to solve changes within a single element. For example: +> Examples: `index`, `tags`, `references`, +For **array of strings** fields, conflict resolution will take place on an element by element basis - that means that the algorithm will not consider or try to solve changes within a single element. + +Instead, we can create a Set-based logic to caclulate what the additions and removals where applied to the `base` version onto the `current` and `target` versions and do set manipulations to get a merged versions. + +For example: + +**base**: [linux, network] +**current**: [windows, host] +**target**: [linux, ml] +**expected output**: [windows, host, ml] + +The logic is as follows: + +Changes to **current** compared against **base**: +- Added: [windows, host] +- Removed: [linux, network] + + +Changes to **target** compared against **base**: +- Added: [ml] +- Removed: [network] + +Combining both modifications: +- Added: [windows, host, ml] +- Removed: [network] (which elements were removed in both?) + +Applying these combined modifications to base results in: +- **[windows, host, ml]** + +This logic can be achieved using built-in Javascript `Set` logic: + +```js +const base = new Set(["linux", "network"]); +const current = new Set(["windows", "host"]); +const target = new Set(["linux", "ml"]); +const output = new Set(["windows", "host", "ml"]); + + +const addedCurrent = current.difference(base); // [windows, host] +const removedCurrent = base.difference(current); // [linux, network] + +const addedTarget = target.difference(base); // [ml] +const removedTarget = base.difference(target); // [network] + +const bothRemoved = removedCurrent.intersection(removedTarget); // [network] + +const merged = base + .difference(bothRemoved) + .union(addedCurrent) + .union(addedTarget) + +// Results in: [windows, host, ml] ``` -base: [test1] -current: [my-test1] -target: [test2] -output: [my-test1] -``` -Therefor the example above, the algorithm should not try to merge the single string element by breaking it into parts. -Example **array of strings** fields: `index`, `tags`, `references`, +The possible scenarios are: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Use caseBase versionCurrent versionTarget versionMerged version (output)Mark as conflict?
    No customization, no updates (AAA)[linux,network][linux,network][linux,network][linux,network]NO
    User customization, no updates (ABA)[linux,network][windows, host][linux,network][windows, host]NO
    No customization, upstream update (AAB)[linux,network][linux,network][windows, host][windows, host]NO
    Customization and upstream update match (ABB)[linux,network][linux,ml][linux,ml][linux,ml]NO
    Customization and upstream update conflict (ABC)[linux,network][linux,ml,security][aws, cloudfront][linux,ml,security,
    aws,cloudfront]
    NO
    + +Notice that with this logic we would never mark a merge scenario as a conflict. + ###### Array of objects fields From c1e97d5dbb04ec7779c5bd4c04c4adcfa1a728b8 Mon Sep 17 00:00:00 2001 From: jpdjere Date: Mon, 25 Mar 2024 11:36:29 +0100 Subject: [PATCH 50/61] Fix --- .../docs/prebuilt_rules_customization_rfc.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md index c86c57207ff9a6..708f77d91b1850 100644 --- a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md +++ b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md @@ -2341,9 +2341,9 @@ The possible scenarios are: Customization and upstream update conflict (ABC) [linux,network] - [linux,ml,security] - [aws, cloudfront] - [linux,ml,security,
    aws,cloudfront]
    + [windows, host] + [linux, ml] + [windows, host, ml] NO From 01ed741072651b2baa044dc218ddd491a8c4b3ca Mon Sep 17 00:00:00 2001 From: jpdjere Date: Mon, 25 Mar 2024 12:32:58 +0100 Subject: [PATCH 51/61] Fixed 'Array of objects' section --- .../docs/prebuilt_rules_customization_rfc.md | 650 ++++++------------ 1 file changed, 212 insertions(+), 438 deletions(-) diff --git a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md index 708f77d91b1850..8e5a8cc0c0545e 100644 --- a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md +++ b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md @@ -2234,13 +2234,11 @@ Number fields should be treated as a whole unit, i.e. not breakable by digits. T -#### Array of strings fields +#### Array of scalar value (strings/numbers) fields > Examples: `index`, `tags`, `references`, -For **array of strings** fields, conflict resolution will take place on an element by element basis - that means that the algorithm will not consider or try to solve changes within a single element. - -Instead, we can create a Set-based logic to caclulate what the additions and removals where applied to the `base` version onto the `current` and `target` versions and do set manipulations to get a merged versions. +For **arrays of scalar values** fields, we can create a Set-based logic to caclulate what the additions and removals where applied to the `base` version onto the `current` and `target` versions and do set manipulations to get a merged version. For example: @@ -2352,89 +2350,69 @@ The possible scenarios are: Notice that with this logic we would never mark a merge scenario as a conflict. -###### Array of objects fields +#### Array of objects fields + +> Examples: `related_integrations,` `required_fields` Since the properties in each object within the array are highly dependent on one another, the whole object should be treated as a block, and not attempt to diff or merge changes to individual fields within each element. For example: in a `required_fields` update, if the `type` is updated from `unknown` in the base version to `keyword` in the `target` version, but in the same object the user has updated the base `name` of the field, the change of type will have a high probability of not making sense anymore - there is no way of knowing if the change proposed by Elastic will also apply to the field name that the user is now referring through its customization. -Therefore, we should prefer to keep the user's version for the whole block.(See this example in the first element of the array in the first row of the table below). - -Examples: `related_integrations,` `required_fields` - -###### Proposed algorithm - -- Do element by element comparison: - - If element index exists in the three versions and the values: - - do not differ between all versions (base, current and target), **keep current** version. (A A A) - - do not differ between base and current, but updates target, **keep target** version. (A A B) - - differ between base and current, but doesn't update target, **keep current** version. (A B A) - - differ between base and current, updates target, **keep current** version. (A B B) - - differ between all version (base, current and target), **keep current** version. (A B C) - - If element index exists in base and current version, but not in target: - - If base differs from current: **keep current** version. (A B _) - - If base equals current: **remove element**. (A A _) - - If element index exists in base and target version, but not in current: - - **Remove element**. (A _ B) and (A _ A) - - If element index exists in current and target version, but not in base: - - If base equals current: **add element/keep target**. (_ A A) - - If base differs from current: **keep both current and target**. (_ A B) - - If element index exists only in base version: - - **Remove element** (A _ _) - - If element index exists only in current version: - - **Keep current version** (_ A _) - - If element index exists only in target version: - - **Keep target version** (_ _ A) - +Therefore, to calculate a merged version, we will use a similar approach to the one used for "Array of strings", but instead of using `Set` logic, we will use `Maps` so that we can keep track of each objects based on an `id` and thus carry out algebraic operations on them to arrive to a merged version. + +The `id` will vary depending on the type of the field: + +|Field|Example object|Key used as `id`| +|---|---|---| +| `required_fields` | `{ ecs: true, name: 'host.name', type: 'keyword' }` | `name` | +| `related_integrations` | `{ "package": "aws", "version": "^2.0.0", "integration": "cloudtrail" }` | `package`+`integration` | + +---- +As an example - `A`, `B` and `C` are the keys of the objects in the array, and `modified` means that an object kept it's key id value, but some other propery of the object was modified: + +**base**: [`A`, `B`] +**current**: [`modified B `, `C`] +**target**: [`modified B`, `D`] + +The logic is as follows: + +Changes to **current** compared against **base**: +- Added: [`C`] +- Removed: [`A`] +- Modified: [`B`] + +Changes to **target** compared against **base**: +- Added: [`D`] +- Removed: [`A`] +- Modified: [`B`] + +In combination: +- Added: [`C`, `D`] (no conflicts) +- Removed: [`A`] (no conflicts) +- Modified: [`B`] (no conflict ONLY if the 2 objects were modified in exactly the same way) + +So there are two possible results: + +- No conflict: [`B`, `C`, `D`] +- Conflict: no acceptable merge proposal can be built, mark as `conflict` and propose the `current` version + +---- + - - - - - - - - - - + - - - - - + + + + + + + + - + - + - + - + - - - - - - - +] + + - + - + + - + - - - - - - - - + ecs: false, + name: "host.os.ip", + type: "ip" + }, +] + + - + - + - + - + - - - - - - - +] + + - + - + - + - + - - - - - - - + name: "host.os.ip", + type: "ip" + }, +] + + - + - + - + - + - - - - - - - + + - + - - + + - + + +
    Use caseBase versionCurrent versionTarget versionMerged version (output)
    Keep user changes if element conflicts, but apply changes in elements with clean updates

    • 1st elem: (A B C - keep current)
    • 2nd elem: (A A B - keep target)


    Same for:
    • 1st elem: (A B C) + 2nd elem: (A B A - keep current)
    • 1st elem: (A B C) + 2nd elem: (A B B - keep current/target)
    -
    -[
    -  logs-*,
    -  logstash-*
    -]
    -        
    -
    -
    -[
    -  cluster_one:logs-*,
    -  cluster_one:logstash-*
    -]
    -        
    -
    -
    -[
    -  new-index1-*,
    -  new-index2-*,
    -]
    -        
    -
    -
    -[
    -  cluster_one:logs-*,
    -  cluster_one:logstash-*
    -]
    -        
    -
    Use caseBase versionCurrent versionTarget versionMerged version (output)Mark as conflict?
    -
    +      
    No customization, no updates (AAA)
     [
       {
         ecs: true,
    @@ -2446,15 +2424,13 @@ Examples: `related_integrations,` `required_fields`
         name: "host.os.type",
         type: "keyword"
       },
    -]
    -        
    -
    -
    +]      
    +      
     [
       {
         ecs: true,
    -    name: "event.UPDATED",
    +    name: "event.action",
         type: "unknown"
       },
       {
    @@ -2462,78 +2438,41 @@ Examples: `related_integrations,` `required_fields`
         name: "host.os.type",
         type: "keyword"
       },
    -]
    -        
    -
    -
    +]      
    +      
     [
       {
         ecs: true,
         name: "event.action",
    -    type: "keyword"
    +    type: "unknown"
       },
       {
         ecs: false,
    -    name: "host.user.id",
    +    name: "host.os.type",
         type: "keyword"
       },
    -]
    -        
    -
    -
    +]      
    +      
     [
       {
         ecs: true,
    -    name: "event.UPDATED",
    +    name: "event.action",
         type: "unknown"
       },
       {
         ecs: false,
    -    name: "host.user.id",
    +    name: "host.os.type",
         type: "keyword"
       },
    -]
    -        
    -
    Keep user changes if element conflicts, and remove any uncustomized elements if removed in update

    • 1st elem: (A B C - keep current)
    • 2nd elem: (A A _ - remove element)
    -
    -[
    -  logs-*,
    -  logstash-*
    -]
    -        
    -
    -
    -[
    -  cluster_one:logs-*,
    -  logstash-*
    -]
    -        
    -
    -
    -[
    -  logs-new-*,
    -]
    -        
    -
    -
    -[
    -  cluster_one:logs-*
    -]
    -        
    -
    NO
    -
    +      
    User customization, no updates (ABA)
     [
       {
         ecs: true,
    @@ -2545,15 +2484,27 @@ Examples: `related_integrations,` `required_fields`
         name: "host.os.type",
         type: "keyword"
       },
    -]
    -        
    -
    -
    +]      
    +      
     [
       {
         ecs: true,
    -    name: "event.UPDATED",
    +    name: "event.action",
    +    type: "keyword"
    +  },
    +  {
    +    ecs: false,
    +    name: "host.os.ip",
    +    type: "ip"
    +  },
    +]      
    +      
    +[
    +  {
    +    ecs: true,
    +    name: "event.action",
         type: "unknown"
       },
       {
    @@ -2561,71 +2512,27 @@ Examples: `related_integrations,` `required_fields`
         name: "host.os.type",
         type: "keyword"
       },
    -]
    -        
    -
    -
    +]      
    +      
     [
       {
         ecs: true,
         name: "event.action",
         type: "keyword"
    -  }
    -]
    -        
    -
    -
    -[
    +  },
       {
    -    ecs: true,
    -    name: "event.UPDATED",
    -    type: "unknown"
    -  }
    -]
    -        
    -
    Keep user changes if element conflicts, but keep any customized elements if removed in update

    -
    • 1st elem: (A B C - keep current)
    • 2nd elem: (A B _ - keep current)
    -
    -
    -[
    -  logs-*,
    -  logstash-*
    -]
    -        
    -
    -
    -[
    -  cluster_one:logs-*,
    -  cluster_one:logstash-*
    -]
    -        
    -
    -
    -[
    -  logs-new-*,
    -]
    -        
    -
    -
    -[
    -  cluster_one:logs-*,
    -  cluster_one:logstash-*
    -]
    -        
    -
    NO
    -
    +      
    No customization, upstream update (AAB)
     [
       {
         ecs: true,
    @@ -2637,119 +2544,83 @@ Examples: `related_integrations,` `required_fields`
         name: "host.os.type",
         type: "keyword"
       },
    -]
    -        
    -
    -
    +]      
    +      
     [
       {
         ecs: true,
    -    name: "event.UPDATED",
    +    name: "event.action",
         type: "unknown"
       },
       {
         ecs: false,
    -    name: "host.user.id",
    +    name: "host.os.type",
         type: "keyword"
       },
    -]
    -        
    -
    -
    +]      
    +      
     [
       {
         ecs: true,
         name: "event.action",
         type: "keyword"
    -  }
    -]
    -        
    -
    -
    +  },
    +  {
    +    ecs: false,
    +    name: "host.os.ip",
    +    type: "ip"
    +  },
    +]    
    +      
     [
       {
         ecs: true,
    -    name: "event.UPDATED",
    -    type: "unknown"
    +    name: "event.action",
    +    type: "keyword"
       },
       {
         ecs: false,
    -    name: "host.user.id",
    -    type: "keyword"
    +    name: "host.os.ip",
    +    type: "ip"
       },
    -]
    -        
    -
    Keep user changes if element conflicts and add new matching element

    -
    • 1st elem: (A B C - keep current)
    • 2nd elem: (_ A A - keep current/target)
    -
    -
    -[
    -  logs-*,
    -]
    -        
    -
    -
    -[
    -  cluster_one:logs-*,
    -  new-target
    -]
    -        
    -
    -
    -[
    -  logs-new-*,
    -  new-target
    -]
    -        
    -
    -
    -[
    -  cluster_one:logs-*,
    -  new-target
    -]
    -        
    -
    NO
    -
    +      
    Customization and upstream update match (ABB)
     [
       {
         ecs: true,
         name: "event.action",
         type: "unknown"
    -  }
    -]
    -        
    -
    -
    +  },
    +  {
    +    ecs: false,
    +    name: "host.os.type",
    +    type: "keyword"
    +  },
    +]      
    +      
     [
       {
         ecs: true,
    -    name: "event.UPDATED",
    -    type: "unknown"
    +    name: "event.action",
    +    type: "keyword"
       },
       {
         ecs: false,
    -    name: "my.new.field",
    -    type: "keyword"
    -  }
    -]
    -        
    -
    -
    +    name: "host.os.ip",
    +    type: "ip"
    +  },
    +]    
    +      
     [
       {
         ecs: true,
    @@ -2758,96 +2629,58 @@ Examples: `related_integrations,` `required_fields`
       },
       {
         ecs: false,
    -    name: "my.new.field",
    -    type: "keyword"
    +    name: "host.os.ip",
    +    type: "ip"
       },
    -]
    -        
    -
    -
    +]    
    +      
     [
       {
         ecs: true,
    -    name: "event.UPDATED",
    -    type: "unknown"
    +    name: "event.action",
    +    type: "keyword"
       },
       {
         ecs: false,
    -    name: "my.new.field",
    -    type: "keyword"
    -  } ,
    -]
    -        
    -
    Keep user changes if element conflicts and add both new conflicting elements

    -
    • 1st elem: (A B C - keep current)
    • 2nd elem: (_ A B - keep both current and target)
    -
    -
    -[
    -  logs-*,
    -]
    -        
    -
    -
    -[
    -  cluster_one:logs-*,
    -  new-target
    -]
    -        
    -
    -
    -[
    -  logs-new-*,
    -  elastic-index
    -]
    -        
    -
    -
    -[
    -  cluster_one:logs-*,
    -  new-target,
    -  elastic-index
    -]
    -        
    -
    NO
    -
    +      
    Customization and upstream update solvable conflict (ABC)

    Object A modified in matching way
     [
       {
         ecs: true,
         name: "event.action",
         type: "unknown"
    -  }
    -]
    -        
    -
    -
    +  },
    +  {
    +    ecs: false,
    +    name: "host.os.type",
    +    type: "keyword"
    +  },
    +]      
    +      
     [
       {
         ecs: true,
    -    name: "event.UPDATED",
    -    type: "unknown"
    +    name: "event.action",
    +    type: "keyword"
       },
       {
         ecs: false,
    -    name: "my.new.field",
    +    name: "new.field.name",
         type: "keyword"
       },
    -]
    -        
    -
    -
    +]    
    +      
     [
       {
         ecs: true,
    @@ -2855,135 +2688,76 @@ Examples: `related_integrations,` `required_fields`
         type: "keyword"
       },
       {
    -    ecs: true,
    -    name: "new.elastic.ip",
    +    ecs: false,
    +    name: "new.field.ip",
         type: "ip"
    -  }
    -]
    -        
    -
    -
    +  },
    +]   
    +      
     [
       {
         ecs: true,
    -    name: "event.UPDATED",
    +    name: "event.action",
         type: "unknown"
       },
    -  {
    +    {
         ecs: false,
    -    name: "host.user.id",
    +    name: "new.field.name",
         type: "keyword"
       },
       {
    -    ecs: true,
    -    name: "process.executable",
    -    type: "keyword"
    +    ecs: false,
    +    name: "new.field.ip",
    +    type: "ip"
       },
     ]
    -        
    -
    Keep user changes if element conflicts and remove element removed by user

    -
    • 1st elem: (A B C - keep current)
    • 2nd elem: (A _ A - remove element)
    - And: -
    • 1st elem: (A B C - keep current)
    • 2nd elem: (A _ B - remove element
    -
    -
    -[
    -  logs-*,
    -  logstash-*
    -]
    -        
    -
    -
    -[
    -  cluster_one:logs-*,
    -]
    -        
    -
    -
    -[
    -  logs-new-*,
    -  logstash-*
    -]
    -        
    -
    -
    -[
    -  cluster_one:logs-*,
    -]
    -        
    -
    NO
    -
    +      
    Customization and upstream update non-solvable conflict (ABC)

    Object A modified in diverging ways, propose current version
     [
       {
         ecs: true,
         name: "event.action",
         type: "unknown"
    -  },
    -  {
    -    ecs: true,
    -    name: "process.executable",
    -    type: "string"
       }
    -]
    -        
    -
    -
    -[
    -  {
    -    ecs: true,
    -    name: "event.UPDATED",
    -    type: "unknown"
    -  }
    -]
    -        
    -
    -
    +]      
    +      
     [
       {
         ecs: true,
         name: "event.action",
         type: "keyword"
       },
    +]    
    +      
    +[
       {
         ecs: true,
    -    name: "process.executable.ip",
    -    type: "ip"
    -  }
    -]
    -        
    -
    -
    +    name: "event.action",
    +    type: "string"
    +  },
    +]   
    +      
     [
       {
         ecs: true,
    -    name: "event.UPDATED",
    -    type: "unknown"
    +    name: "event.action",
    +    type: "keyword"
       }
     ]
    -        
    -
    YES
    - - - - ### Changes to Rule Upgrade UX/UI flow #### Bulk accepting upgrades with no conflicts From c3c9e7ef017812a1bc1c048523a2f2c59cd0b540 Mon Sep 17 00:00:00 2001 From: jpdjere Date: Mon, 25 Mar 2024 12:57:09 +0100 Subject: [PATCH 52/61] Finished correction --- .../docs/prebuilt_rules_customization_rfc.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md index 8e5a8cc0c0545e..0ade8698dc6c90 100644 --- a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md +++ b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md @@ -2396,7 +2396,9 @@ So there are two possible results: - No conflict: [`B`, `C`, `D`] - Conflict: no acceptable merge proposal can be built, mark as `conflict` and propose the `current` version ----- + +--- +The possible scenarios are: From bc14d2447f8ae57bc462a0783483a2ac4b84adc7 Mon Sep 17 00:00:00 2001 From: jpdjere Date: Tue, 26 Mar 2024 14:58:51 +0100 Subject: [PATCH 53/61] Fix TOC --- .../docs/prebuilt_rules_customization_rfc.md | 79 +++++-------------- 1 file changed, 18 insertions(+), 61 deletions(-) diff --git a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md index 0ade8698dc6c90..7c602155fcf7b1 100644 --- a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md +++ b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md @@ -1,6 +1,6 @@ # RFC: Prebuilt Rules Customization -_Status_: Completed, pending correction after team's feedback. +_Status_: Completed, feedback addressed. Awaiting further feedback, or closing off. Covers: @@ -27,27 +27,20 @@ pandoc prebuilt_rules_customization_rfc.md --toc --toc-depth=6 --wrap=none -s - - [Note about scope of RFC](#note-about-scope-of-rfc) - [Necessary rule schema changes](#necessary-rule-schema-changes) - [`rule_source` field](#rule_source-field) - - [Deprecating the `immutable` field](#deprecating-the-immutable-field) - - [Subfields in the `rule_source` field](#subfields-in-the-rule_source-field) - - [`type` subfield](#type-subfield) - - [`is_customized` subfield](#is_customized-subfield) - - [`source_updated_at` subfield](#source_updated_at-subfield) + - [`immutable` field](#immutable-field) - [Changes needed in rule schema](#changes-needed-in-rule-schema) - - [API schema](#api-schema) - - [API request and response rule schema](#api-request-and-response-rule-schema) - - [Rule Import request schema](#rule-import-request-schema) + - [API request and response rule schema](#api-request-and-response-rule-schema) + - [Rule Import request schema](#rule-import-request-schema) - [Internal rule schema](#internal-rule-schema) - - [Prebuilt Rule asset schema](#prebuilt-rule-asset-schema) - - [Deprecating the `immutable` field](#deprecating-the-immutable-field-1) + - [Prebuilt Rule asset schema](#prebuilt-rule-asset-schema) + - [Deprecating the `immutable` field](#deprecating-the-immutable-field) - [Mapping changes](#mapping-changes) - [Plan for carrying out migrations of rule SOs](#plan-for-carrying-out-migrations-of-rule-sos) - [Context](#context) - [Problem with tightly coupled logic in our endpoints](#problem-with-tightly-coupled-logic-in-our-endpoints) - [Migration strategy](#migration-strategy) - [Normalization on read](#normalization-on-read) - - [Rule Management endpoints that will perform normalization-on-read](#rule-management-endpoints-that-will-perform-normalization-on-read) - [Migration on write](#migration-on-write) - - [Rule Management endpoints that should include migration-on-write logic](#rule-management-endpoints-that-should-include-migration-on-write-logic) - [Technical implementation of migration-on-write](#technical-implementation-of-migration-on-write) - [Updating and upgrading rules](#updating-and-upgrading-rules) - [Bulk editing rules](#bulk-editing-rules) @@ -68,29 +61,24 @@ pandoc prebuilt_rules_customization_rfc.md --toc --toc-depth=6 --wrap=none -s - - [Updating the `is_customized` field](#updating-the-is_customized-field) - [In the UI](#in-the-ui) - [Via the Rule Edit Page](#via-the-rule-edit-page) + - [Via Rules Table page](#via-rules-table-page) - [Via Bulk Actions](#via-bulk-actions) - [Via the Rules Details Page](#via-the-rules-details-page) - [Via the Shared Exception Lists page](#via-the-shared-exception-lists-page) - [Via the Stack Management \> Rules UI](#via-the-stack-management-rules-ui) -- [List of things to fix (create tickets)](#list-of-things-to-fix-create-tickets) +- [Design Discussion link](#design-discussion-link) - [Upgrading Prebuilt Rules](#upgrading-prebuilt-rules) - - [Changes to upgrade `_review` endpoint](#changes-to-upgrade-_review-endpoint) - - [Concrete field diff algorithms by type](#concrete-field-diff-algorithms-by-type) - - [String fields](#string-fields) - - [Number fields](#number-fields) - - [Array fields](#array-fields) - - [Array of strings fields](#array-of-strings-fields) - - [Array of objects fields](#array-of-objects-fields) - - [Proposed algorithm](#proposed-algorithm) - - [MITRE ATT&CK framework (`threat` field)](#mitre-attck-framework-threat-field) - - [Changes to `/upgrade/_review` endpoint contract](#changes-to-upgrade_review-endpoint-contract) - [Changes to `/upgrade/_perform` endpoint](#changes-to-upgrade_perform-endpoint) - - [Changes to `/upgrade/_perform` endpoint contract](#changes-to-upgrade_perform-endpoint-contract) + - [Changes to `/upgrade/_review` endpoint](#changes-to-upgrade_review-endpoint) + - [Concrete field diff algorithms by type](#concrete-field-diff-algorithms-by-type) + - [Single-line string fields](#single-line-string-fields) + - [Multi-line string fields](#multi-line-string-fields) + - [Number fields](#number-fields) + - [Array of scalar value (strings/numbers) fields](#array-of-scalar-value-stringsnumbers-fields) + - [Array of objects fields](#array-of-objects-fields) - [Changes to Rule Upgrade UX/UI flow](#changes-to-rule-upgrade-uxui-flow) - [Bulk accepting upgrades with no conflicts](#bulk-accepting-upgrades-with-no-conflicts) - [Upgrading rules with conflicts](#upgrading-rules-with-conflicts) -- [Scenario for bulk accepting updates](#scenario-for-bulk-accepting-updates) -- [Other open questions](#other-open-questions) ## Note about scope of RFC @@ -786,7 +774,7 @@ As explained before, all these endpoints suffer from the tightly-coupled logic p We should therefore create new CRUD methods as needed to uncouple them logically and cleanly apply migrations to them. ---- +---- #### Bulk editing rules @@ -815,7 +803,7 @@ The `RulesClient` class has a `bulkEdit` method, which is called by our **Bulk A _See Source: [x-pack/plugins/alerting/server/application/rule/methods/bulk_edit/bulk_edit_rules.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/alerting/server/application/rule/methods/bulk_edit/bulk_edit_rules.ts)_ ---- +---- ## Endpoints and utilities that will need to be adapted to the new schema @@ -1075,7 +1063,6 @@ In this case, we will the rule's params to be: And we can finally create a rule or update an existing rule using the request payload and the calculated `rule_source` field. ---- Given the requirements described above, the following table shows the behaviour of our endpoint for a combination of inputs and Kibana states. (All situation assume that the Elastic prebuilt rules package will be installed, since we have set this as a precondition of the endpoint) @@ -1092,8 +1079,6 @@ Given the requirements described above, the following table shows the behaviour - - @@ -1117,9 +1102,6 @@ Given the requirements described above, the following table shows the behaviour - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Not installed No
    @@ -1177,8 +1159,6 @@ Given the requirements described above, the following table shows the behaviour
     
    Not installed @@ -1211,10 +1191,6 @@ Given the requirements described above, the following table shows the behaviour
    Not installed @@ -1247,9 +1223,6 @@ Given the requirements described above, the following table shows the behaviour
    Not installed @@ -1282,8 +1255,6 @@ Given the requirements described above, the following table shows the behaviour
    @@ -1316,10 +1287,6 @@ Given the requirements described above, the following table shows the behaviour
         Rule import rejected
    because of rule_id match and overwrite flag is false
    @@ -1360,12 +1327,6 @@ Given the requirements described above, the following table shows the behaviour
     
    @@ -1406,10 +1367,6 @@ Given the requirements described above, the following table shows the behaviour
     
    @@ -2397,7 +2354,7 @@ So there are two possible results: - Conflict: no acceptable merge proposal can be built, mark as `conflict` and propose the `current` version ---- +---- The possible scenarios are: From 484f97722b5159a047c7de04d37b800d4cf525dc Mon Sep 17 00:00:00 2001 From: jpdjere Date: Wed, 27 Mar 2024 12:05:45 +0100 Subject: [PATCH 54/61] Address further feedback --- .../docs/prebuilt_rules_customization_rfc.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md index 7c602155fcf7b1..cb386111a40f3b 100644 --- a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md +++ b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md @@ -1784,12 +1784,12 @@ The current behaviour of the app allows to modify a rule's fields in the followi The **Rule Edit Page** is currently split into four tabs: -| Tab | Contains fields | -| -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Tab | Contains fields| +| -------------- | -------------- | | **Definition** | - Rule type (cannot be changed)
    - Data Source
    - Query
    - Machine Learning job (ML rules only)
    - Anomaly score threshold (ML rules only)
    - Group by (threshold rules only)
    - Count (cardinality) (threshold rules only)
    - Indicator index patterns (indicator match rules only)
    - Indicator index query (indicator match rules only)
    - Indicator mapping (indicator match rules only)
    - New terms fields (new term rules only)
    - History window size (new terms rules only)
    - Alert Suppression (for custom query and threshold rules only)
    - Timeline Template | -| **About** | - Name
    - Description
    - Severity
    - Severity override
    - Risk score
    - Risk score override
    - Tags
    - Reference URLs
    - False positive examples
    - MITRE ATT&CK™ threats
    - Custom highlighted fields
    - Investigation guide
    - Author
    - License
    - Elastic Endpoint exceptions
    - Building block
    - Rule name override
    - Timestamp override | -| **Schedule** | - Interval
    - Lookback time | -| **Actions** | - Actions
    - Response actions (custom query rules only) | +| **About** | - Name
    - Description
    - Severity
    - Severity override
    - Risk score
    - Risk score override
    - Tags
    - Reference URLs
    - False positive examples
    - MITRE ATT&CK™ threats
    - Custom highlighted fields
    - Investigation guide
    - Author
    - License
    - Elastic Endpoint exceptions
    - Building block
    - Rule name override
    - Timestamp override| +| **Schedule** | - Interval
    - Lookback time| +| **Actions** | - Actions
    - Response actions (custom query rules only)| Out of these four tabs, only **Actions** is enabled and accessible when editing a prebuilt rule - since actions (and shared exceptions lists and snoozing) are the only fields that can currently be modified for prebuilt rules from the UI. @@ -1894,9 +1894,9 @@ We propose developing more adaptable diff algorithms tailored to specific rule f In general, for all types of fields, we will follow the heuristic: -- if `base` === `target` && `base` !== `current`, we set merge proposal to be the current version, without a conflict -- if `base` === `current` && `base` !== `target`, we set merge proposal to be the target version, without a conflict -- if `base` !== `current` !== target: mark the diff as a conflict AND: +- if `target` === `base` && `current` !== `base`, we set merge proposal to be the current version, without a conflict +- if `current` === `base` && `target` !== `base`, we set merge proposal to be the target version, without a conflict +- if `base` !== `current` !== `target`: mark the diff as a conflict AND: - **if conflict is non-solvable**: use the `current` version as the merge proposal - **if conflict is solvable** use the generated merged version as the merge proposal (possible only in a few types, detailed below - see tables) From 8da0a9d2a6361a6829eb5c5d8dbcd2489b744854 Mon Sep 17 00:00:00 2001 From: jpdjere Date: Wed, 27 Mar 2024 12:23:45 +0100 Subject: [PATCH 55/61] Further fix --- .../docs/prebuilt_rules_customization_rfc.md | 61 ++++++++++--------- 1 file changed, 32 insertions(+), 29 deletions(-) diff --git a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md index cb386111a40f3b..9b7553fc0e0e77 100644 --- a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md +++ b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md @@ -1426,7 +1426,10 @@ Depending on the endpoint, we will have to modify it to address multiple changes 3. **Removing checks that block modifying prebuilt rules:** some of our endpoints prevent users from modifying prebuilt rules. This check needs to be removed from all endpoints to allow the customization of prebuilt rules. 4. **Blocking the update of non-customizable fields:** while the goal of this epic is to allow users to modify their prebuilt rule fields, there are certain rule fields that we will still want to prevent the user from modifying via endpoints, since we will not provide support for resolving conflicts for them via the UI or API if they arise during an update. See the **Customizable** column in [this ticket](https://github.com/elastic/kibana/issues/147239) for a detailed list of fields that should be blocked from modification via the endpoints. -The table below shows which of these changes need to be applied to our endpoints: (✅ change needed - ❌ no change needed) +The table below shows which of these changes need to be applied to our endpoints: ( + +- ✏️ Changes needed +- ➖ No changes needed
    @@ -1441,52 +1444,52 @@ The table below shows which of these changes need to be applied to our endpoints - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + +
    Update Rule - PUT /rules✏️✏️✏️
    Patch Rule - PATCH /rules✏️✏️✏️
    Bulk Patch Rules - PATCH /rules/_bulk_update✏️✏️✏️
    Bulk Update Rules - PUT /rules/_bulk_update✏️✏️✏️
    Bulk Actions - POST /rules/_bulk_action✏️✏️✏️
    Perform Rule Upgrade - POST /prebuilt_rules/upgrade/_perform✏️✏️
    Import Rules POST /rules/_import✏️✏️✏️
    From e710787aec2980075b0957999a1b26bb2c770474 Mon Sep 17 00:00:00 2001 From: jpdjere Date: Mon, 1 Apr 2024 23:06:46 +0200 Subject: [PATCH 56/61] Address feedback --- .../docs/prebuilt_rules_customization_rfc.md | 148 +++++++++++------- 1 file changed, 88 insertions(+), 60 deletions(-) diff --git a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md index 9b7553fc0e0e77..64b2fc7e3ff294 100644 --- a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md +++ b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md @@ -278,7 +278,12 @@ We also need to modify the `RuleToImport` schema, since now we will be allowing Currently, `RuleToImport` optionally accepts the `immutable` param, but rejects validation if its value is set to anything else than `false` - since we don't currently support importing prebuilt rules. -We will be changing the mechanism for importing rules so that, besides the `rule_id`, the `version` of the rule is also a required parameter. These two parameters will be used to determine if the rule is prebuilt or not, and dynamically calculate `rule_source` during import. +We will be changing the mechanism for importing rules so that onlt the `rule_id` is required parameter. This parameters will be used to determine if the rule is prebuilt or not, and dynamically calculate `rule_source` during import. + +The rule import endpoint should: + +- for custom rules being imported, if `version` is not specified, set it to `1`. +- for prebuilt rules being imported, if `version` is not specified, throw an error. See the detailed explanation for this mechanism in the [Exporting and importing rules](#exporting-and-importing-rules) sections. @@ -301,7 +306,6 @@ export type RuleToImportInput = z.input; export const RuleToImport = BaseCreateProps.and(TypeSpecificCreateProps).and( ResponseFields.partial().extend({ rule_id: RuleSignatureId, - version: RuleVersion, }) ); ``` @@ -363,7 +367,7 @@ In order to mark the `immutable` field as deprecated, and making sure that our a 2. via a deprecation warning in the OpenAPI schema, as detailed above 3. by adding a custom response header in said endpoints. -The `immutable` field will afterwards be actually removed from our API endpoint responses and our application after a deprecation period that should give our users enough time to adapt to this change. The length of this deprecation period can vary depending on adoption or other factors, but around 18 monthscan be a good starting point. +The `immutable` field will afterwards be actually removed from our API endpoint responses and our application after a deprecation period that should give our users enough time to adapt to this change. The length of this deprecation period can vary depending on adoption or other factors, but should be at least 24 months. Both the docs and the custom response header should communicate that the `immutable` field: @@ -412,7 +416,6 @@ For example: the `createRules` method is used in 3 use cases: The same happens with `patchRules`. It is used: 1. when patching rules via our Rule Patch endpoints -2. when importing rules, when the imported `rule_id` is brand new 3. when upgrading rules, if a rule maintains its `type`. This causes these 3 CRUD functions to have an unnecessary complex interfaces and logic in order to handle all these different use cases. @@ -443,8 +446,12 @@ Our migration strategy will consist of two distinct types of migration: a **migr |
  • _**Enable and disable action**_
  • |
    |
    | - Migration-on-write is technically possible but should be done on Alerting Framework side. | |
  • _**Delete action**_
  • |
    |
    | - Deletes ES object but returns deleted rules data, so so normalization-on-read is enough. | |
  • _**Export action**_
  • |
    |
    | - See section [Exporting rules](#exporting-rules) | -|
  • _**Duplicate rule action**_
  • |
    |
    | - Per definition, all duplicated rules will be `custom` rules. That means that all duplicated rules (the duplicates) are newly created and should get a `rule_source` of type `internal`, and no migration or normalization is neccessary. | -|
  • _**Edit rule action**_
  • |
    |
    | - No normalization-on-read is needed since endpoint doesn't return whole rule object
    - We can take advantage of the `ruleParamsModifier` to carry out the migration-on-write, regardless of the type of edit that is being performed.
    - See implementation details in the [Bulk editing rules](#bulk-editing-rules) section. +|
  • _**Duplicate rule action**_
  • |
    |
    | - Per definition, all duplicated rules will be `custom` rules. That means that all duplicated rules (the duplicates) are newly created and should get a `rule_source` of type `internal`, and no migration-on-write is neccessary. | +|
  • _**Edit rule action**_
  • |
    |
    | - We can take advantage of the `ruleParamsModifier` to carry out the migration-on-write, regardless of the type of edit that is being performed.
    - See implementation details in the [Bulk editing rules](#bulk-editing-rules) section. +| **Review Rule Installation** - `POST /prebuilt_rules/installation/_review`|
    |
    | | +| **Perform Rule Installation** - `POST /prebuilt_rules/installation/_install`|
    |
    | - Newly installed rules will be installed with new schema; but no migration-on-write should happen in this endpoint. | +| **Review Rule Upgrade** - `POST /prebuilt_rules/upgrade/_review` |
    |
    | | +| **Perform Rule Upgrade** - `POST /prebuilt_rules/upgrade/_perform`|
    |
    | | #### Normalization on read @@ -575,8 +582,7 @@ The resulting values for `immutable` and `rule_source` when calling these endpoi Migration use case - Current value of
    rule_source
    - Current value of
    immutable
    + Current value of rule_source and immutable Any field diverges
    from base version after update? Results @@ -585,14 +591,17 @@ The resulting values for `immutable` and `rule_source` when calling these endpoi Custom rule (not migrated yet) -
    undefined
    +
    +{
    +  immutable: false,
    +}
    +        
    -
    false
    N/A - Doesn't apply for custom rules
     {
    -  rule_source: {
    +  ruleSource: {
         type: 'internal'
       },
       immutable: false,
    @@ -605,16 +614,18 @@ The resulting values for `immutable` and `rule_source` when calling these endpoi
           
             
     {
    -  type: 'internal'
    +  ruleSource: {
    +    type: 'internal'
    +  },
    +  immutable: false,
     }
             
    -
    false
    N/A - Doesn't apply for custom rules
     {
    -  rule_source: {
    +  ruleSource: {
         type: 'internal'
       },
       immutable: false,
    @@ -625,14 +636,17 @@ The resulting values for `immutable` and `rule_source` when calling these endpoi
         
           Prebuilt rule (not yet migrated, no customizations)
           
    -        
    undefined
    +
    +{
    +  immutable: true,
    +}
    +        
    -
    true
    No
     {
    -  rule_source: {
    +  ruleSource: {
         type: 'external',
         isCustomized: false,
         ...
    @@ -645,14 +659,17 @@ The resulting values for `immutable` and `rule_source` when calling these endpoi
         
           Prebuilt rule (not yet migrated, with customizations)
           
    -        
    undefined
    +
    +{
    +  immutable: true,
    +}
    +        
    -
    true
    Yes
     {
    -  rule_source: {
    +  ruleSource: {
         type: 'external',
         isCustomized: true,
         ...
    @@ -665,20 +682,22 @@ The resulting values for `immutable` and `rule_source` when calling these endpoi
         
           Prebuilt rule (already migrated, no customizations)
           
    -        
     
    +        
     {
    -  type: 'external',
    -  isCustomized: false,
    +  ruleSource: {
    +    type: 'external',
    +    isCustomized: false,
         ...
    +  },
    +  immutable: true,
     }
    -          
    +
    -
    true
    No
     {
    -  rule_source: {
    +  ruleSource: {
         type: 'external',
         isCustomized: false,
         ...
    @@ -691,20 +710,22 @@ The resulting values for `immutable` and `rule_source` when calling these endpoi
         
           Prebuilt rule (already migrated, with customizations)
           
    -        
     
    +        
     {
    -  type: 'external',
    -  isCustomized: true,
    +  ruleSource: {
    +    type: 'external',
    +    isCustomized: true,
         ...
    +  },
    +  immutable: true,
     }
    -          
    +
    -
    true
    Yes
     {
    -  rule_source: {
    +  ruleSource: {
         type: 'external',
         isCustomized: true,
         ...
    @@ -717,20 +738,22 @@ The resulting values for `immutable` and `rule_source` when calling these endpoi
         
           Customized Prebuilt rule (already migrated, no customizations after update)
           
    -        
     
    +        
     {
    -  type: 'external',
    -  isCustomized: true,
    +  ruleSource: {
    +    type: 'external',
    +    isCustomized: true,
         ...
    +  },
    +  immutable: true,
     }
    -          
    +
    -
    true
    No
     {
    -  rule_source: {
    +  ruleSource: {
         type: 'external',
         isCustomized: false,
         ...
    @@ -741,22 +764,24 @@ The resulting values for `immutable` and `rule_source` when calling these endpoi
           
         
         
    -      Invalid case: Migrating a migrated non-customized prebuilt rule, with customizations. 

    `immutable` should never be false if `rule_source.type' is 'external'. Migration should correct this inconsistency. + Invalid case: Migrating a migrated non-customized prebuilt rule, with customizations.

    `immutable` should never be false if `ruleSource.type' is 'external'. Migration should correct this inconsistency. -
     
    +        
     {
    -  type: 'external',
    -  isCustomized: false,
    +  ruleSource: {
    +    type: 'external',
    +    isCustomized: false,
         ...
    +  },
    +  immutable: false,
     }
    -          
    +
    -
    false
    Yes
     {
    -  rule_source: {
    +  ruleSource: {
         type: 'external',
         isCustomized: true,
         ...
    @@ -1399,7 +1424,7 @@ With the rule schema updated, we will allow users to **edit their prebuilt rules
     
     Endpoints that users will be able to use to modify rules are:
     
    -- **Update Rule** - `PUT /rules`: called by the UI when updating/modifying a single rule via the Rule Details page
    +- **Update Rule** - `PUT /rules`: called by the UI when updating/modifying a single rule via the Rule Editing page
     - **Patch Rule** - `PATCH /rules`: used for attaching shared exceptions list to rules
     - **Bulk Patch Rules** - `PATCH /rules/_bulk_update`: deprecated and unused by the UI (might still be used by public API users)
     - **Bulk Update Rules** - `PUT /rules/_bulk_update`: deprecated and unused by the UI (might still be used by public API users)
    @@ -1806,11 +1831,14 @@ Once done editing the rule, the user clicks on the "Save Changes" button, which
     - The only fields in the UI that should not be customizable are: **Rule Type**, **Author** and **License**, which should continue to be read-only.
     - **Definition** should be the default open tab when opening the edit rule page for a prebuilt rule (current default is **Actions**)
     - Field validation should continue to work as it does for custom rules.
    -- No fields should return a validation error for the values that come from the `security_detection_engine` package prebuilt rules. This means that a user should be able to successfully save the prebuilt rule with no changes. See **List of issues to fix** below.
    +- No fields should return a validation error for the values that come from the `security_detection_engine` package with prebuilt rules. This means that a user should be able to successfully save any stock prebuilt rule with no changes.
     
    -#### Via Rules Table page
    +#### Via the Rule Management page
     
    -- The Rules Table's filter should be updated so that rules can be fitlered according to their status as **custom**, **Elastic prebuilt** and **customized Elastic prebuilt**. Notice that **customized Elastic prebuilt** will be a subset of **Elastic prebuilt**.
    +The existing filter in the Rules table should be updated so that rules can be filtered by:
    +- custom rules
    +- non-customized prebuilt rules
    +- customized prebuilt rules
     
     #### Via Bulk Actions
     
    @@ -1921,7 +1949,7 @@ For single-line string fields we will continue to use the existing simple diff a
           Current version
           Target version
           Merged version (output)
    -      Mark as conflict?
    +      Conflict
         
       
       
    @@ -1963,7 +1991,7 @@ For single-line string fields we will continue to use the existing simple diff a
           My GREAT rule name
           My EXCELLENT rule name
           My GREAT rule name
    -      YES
    +      NON_SOLVABLE
         
       
     
    @@ -2076,7 +2104,7 @@ In summary:
           Current version
           Target version
           Merged version (output)
    -      Mark as conflict?
    +      Conflict
         
       
       
    @@ -2118,7 +2146,7 @@ In summary:
           
    My GREAT description. 
    This is a second line.
    My description. 
    This is a second line, now longer.
    My GREAT description. 
    This is a second line, now longer.
    -
    YES
    +
    SOLVABLE
    Customization and upstream update non-solvable conflict (ABC) @@ -2126,7 +2154,7 @@ In summary:
    My GREAT description. 
    This is a third line.
    My EXCELLENT description. 
    This is a fourth line.
    My GREAT description. 
    This is a third line.
    -
    YES
    +
    NON_SOLVABLE
    @@ -2147,7 +2175,7 @@ Number fields should be treated as a whole unit, i.e. not breakable by digits. T Current version Target version Merged version (output) - Mark as conflict? + Conflict @@ -2189,7 +2217,7 @@ Number fields should be treated as a whole unit, i.e. not breakable by digits. T 20 30 20 - YES + NON_SOLVABLE @@ -2260,7 +2288,7 @@ The possible scenarios are: Current version Target version Merged version (output) - Mark as conflict? + Conflict @@ -2368,7 +2396,7 @@ The possible scenarios are: Current version Target version Merged version (output) - Mark as conflict? + Conflict @@ -2661,7 +2689,7 @@ The possible scenarios are: { ecs: true, name: "event.action", - type: "unknown" + type: "keyword" }, { ecs: false, @@ -2732,7 +2760,7 @@ The current UI of the **Rule Updates** page has an button with the label "Update ![](2024-02-23-14-09-16.png) -We can replace this button for an **Update rules with no conflicts** button. Clicking this button would make a request to `/upgrade/_perform` with a payload that includes only rules that have no conflicts. That payload can be built out of the response of the `/upgrade/_review` endpoint, including only rules with no conflicts and specifying that all rules should be updated to their `MERGED` version, which represents the "clean" (conflictless) update. +We can replace this button for an **Update rules with no conflicts** button. Clicking this button would make a request to `/upgrade/_perform` with a payload that includes only rules that don't have non-solvable conflicts. That payload can be built out of the response of the `/upgrade/_review` endpoint, including ids of such rules and specifying that all rules should be updated to their `MERGED` version. ```ts // [PSEUDOCODE] From 30ac113d742ba3fc6e65b7aaaae378045db5e050 Mon Sep 17 00:00:00 2001 From: jpdjere Date: Tue, 2 Apr 2024 17:57:09 +0200 Subject: [PATCH 57/61] Addressed final feedback round --- .../api_client_mock_responses.handlebars | 16 ++++ .../docs/prebuilt_rules_customization_rfc.md | 75 +++++++++---------- .../public/common/api_client/client.mock.ts | 32 ++++++++ 3 files changed, 84 insertions(+), 39 deletions(-) create mode 100644 packages/kbn-openapi-generator/src/template_service/templates/api_client_mock_responses.handlebars create mode 100644 x-pack/plugins/security_solution/public/common/api_client/client.mock.ts diff --git a/packages/kbn-openapi-generator/src/template_service/templates/api_client_mock_responses.handlebars b/packages/kbn-openapi-generator/src/template_service/templates/api_client_mock_responses.handlebars new file mode 100644 index 00000000000000..e790c4480b75ce --- /dev/null +++ b/packages/kbn-openapi-generator/src/template_service/templates/api_client_mock_responses.handlebars @@ -0,0 +1,16 @@ +/* + * 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. + */ +/* eslint-disable @typescript-eslint/no-duplicate-imports */ + +{{> disclaimer}} + +{{#each operations}} +{{#if responseExample}} +export const {{operationId}}MockResponse = {{{toJSON responseExample}}}; +export const get{{operationId}}MockResponse = () => {{operationId}}MockResponse; +{{/if}} +{{/each}} \ No newline at end of file diff --git a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md index 64b2fc7e3ff294..cbb025badc1070 100644 --- a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md +++ b/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md @@ -172,7 +172,7 @@ Custom rules will have: In the current application's state, rules with `immutable: false` are rules which are not Elastic Prebuilt Rules, i.e. custom rules, and can be modified. Meanwhile, `immutable: true` rules are Elastic Prebuilt Rules, created by the TRaDE team, distributed via the `security_detection_engine` Fleet package, and cannot be modified once installed. -When successfully implemented, the `rule_source` field should replace the `immutable` field as a mechanism to mark Elastic prebuilt rules, but with one difference: the `rule_source` field will determine if the rule is an Elastic Prebuilt Rule or not, but now all rules will be customizable by the user in Kibana, i.e. independently of the existence (or absence) of `rule_source`. +When successfully implemented, the `rule_source` field should replace the `immutable` field as a mechanism to mark Elastic prebuilt rules, but with one difference: the `rule_source` field will determine if the rule is an Elastic Prebuilt Rule or not, but now all rules will be customizable by the user in Kibana, i.e. independently of the `type` of `rule_source`. Because of this difference between the `rule_source` and `immutable` fields, the `immutable` field will lose its original meaning as soon as we allow users to customize prebuilt rules, which might become confusing for those API consumers who interact directly with this field. That's why we want to first deprecate it and later after a large enough deprecation period we could consider removing it completely from the API. @@ -443,7 +443,7 @@ Our migration strategy will consist of two distinct types of migration: a **migr | **Perform Rule Upgrade** - `POST /prebuilt_rules/upgrade/_perform` (Internal) |
    |
    | - Current way of upgrading a prebuilt rule | | **(LEGACY) Install Prebuilt Rules And Timelines** - `PUT /rules/prepackaged` |
    |
    | - Legacy endpoint for installing prebuilt rules and updating rules. | |**Bulk Actions** - `POST /rules/_bulk_action`: | | | This endpoint includes a `dry_run` mode that is executed to evaluate preconditions and warn the user before executing the actual request. No migration logic should take place for dry run requests, i.e when `dry_run=true`, since we never write to ES when this parameter is set to `true`.| -|
  • _**Enable and disable action**_
  • |
    |
    | - Migration-on-write is technically possible but should be done on Alerting Framework side. | +|
  • _**Enable and disable action**_
  • |
    |
    | - Migration-on-write is technically possible but we have decided to avoid implementing the additional logic in the AF side. Also, logic should be [migrated](https://github.com/elastic/kibana/issues/177634) soon. | |
  • _**Delete action**_
  • |
    |
    | - Deletes ES object but returns deleted rules data, so so normalization-on-read is enough. | |
  • _**Export action**_
  • |
    |
    | - See section [Exporting rules](#exporting-rules) | |
  • _**Duplicate rule action**_
  • |
    |
    | - Per definition, all duplicated rules will be `custom` rules. That means that all duplicated rules (the duplicates) are newly created and should get a `rule_source` of type `internal`, and no migration-on-write is neccessary. | @@ -547,7 +547,12 @@ Endpoints that perform migration-on-write either fetch the rule before updating ### Technical implementation of migration-on-write -The logic for the migration of the rule saved objects, which means the determination of the `immutable` and `rule_source` fields before writing to ES, might differ depending on the action being performed by the user. +The migration-on-write process implements two changes: + +- creates the `ruleSource` field in the SO in Elasticsearch. +- deletes the `immutable` field in the SO in Elasticsearch (although this field is maintained in the API and calculated via normalization-on-read) + +The logic for the migration of the rule saved objects might differ depending on the action being performed by the user. Let's see all possible use cases that will require migration-on-write, the endpoints that they apply to, and the expected resulting migrated field, based on the action and their input. @@ -603,8 +608,7 @@ The resulting values for `immutable` and `rule_source` when calling these endpoi { ruleSource: { type: 'internal' - }, - immutable: false, + } }
    @@ -616,8 +620,7 @@ The resulting values for `immutable` and `rule_source` when calling these endpoi { ruleSource: { type: 'internal' - }, - immutable: false, + } }
    @@ -627,8 +630,7 @@ The resulting values for `immutable` and `rule_source` when calling these endpoi { ruleSource: { type: 'internal' - }, - immutable: false, + } }
    @@ -650,8 +652,7 @@ The resulting values for `immutable` and `rule_source` when calling these endpoi type: 'external', isCustomized: false, ... - }, - immutable: true, + } }
    @@ -673,8 +674,7 @@ The resulting values for `immutable` and `rule_source` when calling these endpoi type: 'external', isCustomized: true, ... - }, - immutable: true, + } }
    @@ -688,8 +688,7 @@ The resulting values for `immutable` and `rule_source` when calling these endpoi type: 'external', isCustomized: false, ... - }, - immutable: true, + } }
    @@ -701,8 +700,7 @@ The resulting values for `immutable` and `rule_source` when calling these endpoi type: 'external', isCustomized: false, ... - }, - immutable: true, + } }
    @@ -714,10 +712,9 @@ The resulting values for `immutable` and `rule_source` when calling these endpoi { ruleSource: { type: 'external', - isCustomized: true, + isCustomized: false, ... - }, - immutable: true, + } }
    @@ -729,8 +726,7 @@ The resulting values for `immutable` and `rule_source` when calling these endpoi type: 'external', isCustomized: true, ... - }, - immutable: true, + } }
    @@ -744,8 +740,7 @@ The resulting values for `immutable` and `rule_source` when calling these endpoi type: 'external', isCustomized: true, ... - }, - immutable: true, + } }
    @@ -757,8 +752,7 @@ The resulting values for `immutable` and `rule_source` when calling these endpoi type: 'external', isCustomized: false, ... - }, - immutable: true, + } } @@ -820,13 +814,10 @@ Out of the actions mentioned above, the only use cases that should possibly resu That means that updating a rule's actions should not be considered a customization of a prebuilt rule. -Secondly, in contrast with other endpoints, the migration for bulk editing rules needs to be carried within the Alerting Framework's `RuleClient` since we need to migrate the rule's `rule_source` and `immutable` parameters before the `RuleClient` does the saving of the rule into Elasticsearch. - -This however, gives us the advantage that the `RuleClient` already includes logic to calculate if a rule's attributes or parameters have been modified from its initial values, so we can rely on that to calculate the `rule_source.is_customized` field during the update. - -The `RulesClient` class has a `bulkEdit` method, which is called by our **Bulk Actions endpoint** `POST /rules/_bulk_action`. That method includes complex logic, but we can focus on the `updateRuleAttributesAndParamsInMemory` method, where the rule attributes and parameters are updated before being saved to ES. This function also calculates the booleans `isAttributesUpdateSkipped` and `isParamsUpdateSkipped` which we can leverage to calculate the new value of the `rule_source.is_customized` field in our params. +Secondly, in order to migrate the `is_customized` value for rule edits, we can follow two approaches: -_See Source: [x-pack/plugins/alerting/server/application/rule/methods/bulk_edit/bulk_edit_rules.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/alerting/server/application/rule/methods/bulk_edit/bulk_edit_rules.ts)_ +1. Calculate it in the `paramsModifier` callback that is passed to the `rulesClient.bulkEdit` method. This will need to modify the parameters of the callback to take as parameter the whole rule and the operations on the attributes, in order to have access to the values of the rule's field before and after of the edit. +2. Calculate it as part of the `validateMutatedRuleTypeParams` method in `x-pack/plugins/alerting/server/lib/validate_mutated_rule_type_params.ts` where we have access to the original params and the modified params. ---- @@ -1796,6 +1787,12 @@ The following use cases should be covered in the calculation of `is_customized`: Notice the last scenario from the table, which deals with the edge case of the corresponding version of the `security-rule` asset not being found. This would prevent from doing a comparison of the fields to calculate if the rule should be considered customized or not. +Scenarios in which this could happen are: + +- A user manually deletes package and assets +- A user imports a prebuilt rule with matching `rule_id` but no matching version (base version missing) +- A user imports a prebuilt rule from a newer version of Kibana and the Elastic prebuilt rules package into an older version of Kibana where that `version` of the rule does not exist or hasn't been created yet. + So, if the corresponding rule asset is not found, do not attempt to do any comparisons and mark the rule as `is_customized: true`; ignoring the current values of the rules, the payload and the end result. Reasons: @@ -2248,7 +2245,7 @@ Changes to **target** compared against **base**: Combining both modifications: - Added: [windows, host, ml] -- Removed: [network] (which elements were removed in both?) +- Removed: [linux, network] (which elements were removed in both?) Applying these combined modifications to base results in: - **[windows, host, ml]** @@ -2268,12 +2265,12 @@ const removedCurrent = base.difference(current); // [linux, network] const addedTarget = target.difference(base); // [ml] const removedTarget = base.difference(target); // [network] -const bothRemoved = removedCurrent.intersection(removedTarget); // [network] +const bothAdded = addedCurrent.union(addedTarget); // [network] +const bothRemoved = removedCurrent.union(removedTarget); // [network] const merged = base - .difference(bothRemoved) - .union(addedCurrent) .union(addedTarget) + .difference(bothRemoved); // Results in: [windows, host, ml] ``` @@ -2330,7 +2327,7 @@ The possible scenarios are: [windows, host] [linux, ml] [windows, host, ml] - NO + SOLVABLE @@ -2703,7 +2700,7 @@ The possible scenarios are: }, ] -
    NO
    +
    SOLVABLE
    Customization and upstream update non-solvable conflict (ABC)

    Object A modified in diverging ways, propose current version @@ -2743,7 +2740,7 @@ The possible scenarios are: } ] -
    YES
    +
    NON_SOLVABLE
    diff --git a/x-pack/plugins/security_solution/public/common/api_client/client.mock.ts b/x-pack/plugins/security_solution/public/common/api_client/client.mock.ts new file mode 100644 index 00000000000000..e7d825f5236a13 --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/api_client/client.mock.ts @@ -0,0 +1,32 @@ +/* + * 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. + */ + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + * + * info: + * title: API client response mocks + * version: Bundle (no version) + */ + +export const CreateRuleMockResponse = { + rule_id: 'MY_RULE_ID', + description: 'Detecting root and admin users', + name: 'Query with a rule id', + query: 'user.name: root or user.name: admin', + severity: 'high', + type: 'query', + risk_score: 55, + language: 'kuery', + enabled: true, + references: [1, 2, 'test'], + pepe: { pipo: 1, juan: 'hola' }, + arra: [1, 2, 'papapap'], + my_object: { hi: ['you'] }, +}; +export const getCreateRuleMockResponse = () => CreateRuleMockResponse; From ee728023c780ea9e5367bdd8f4b45eb9d6aebe85 Mon Sep 17 00:00:00 2001 From: jpdjere Date: Wed, 3 Apr 2024 13:02:02 +0200 Subject: [PATCH 58/61] Removed test changes --- .../api_client_mock_responses.handlebars | 16 -- .../rule/methods/bulk_edit/bulk_edit_rules.ts | 7 +- .../migrate_prebuilt_schema_on_bulk_edit.ts | 38 ----- .../rule_schema/common_attributes.gen.ts | 39 ----- .../rule_schema/common_attributes.schema.yaml | 43 ------ .../model/rule_schema/rule_schemas.gen.ts | 4 +- .../rule_schema/rule_schemas.schema.yaml | 2 - .../perform_rule_upgrade/attempt1.ts | 52 ------- .../perform_rule_upgrade/attempt2.ts | 39 ----- .../perform_rule_upgrade_route.ts | 3 +- .../review_rule_upgrade_route.ts | 2 +- .../import_rules/rule_to_import.ts | 2 +- .../rule_management/rule_fields.ts | 2 - .../rule_management/rule_filtering.ts | 13 +- .../public/common/api_client/client.mock.ts | 32 ---- .../pages/rule_editing/index.tsx | 3 + .../rules_table/use_rules_table_actions.tsx | 2 +- .../perform_rule_upgrade_route.ts | 6 +- .../review_rule_upgrade_route.ts | 1 - .../logic/diff/calculate_rule_diff.ts | 13 +- .../rule_objects/create_prebuilt_rules.ts | 2 +- .../upgrade_prebuilt_rules.test.ts | 13 +- .../rule_objects/upgrade_prebuilt_rules.ts | 27 +--- .../model/rule_assets/prebuilt_rule_asset.ts | 6 +- .../api/rules/bulk_actions/route.ts | 49 ++++-- .../api/rules/bulk_create_rules/route.ts | 1 - .../api/rules/create_rule/route.ts | 1 - .../api/rules/filters/route.ts | 5 +- .../api/rules/find_rules/route.ts | 7 +- .../api/rules/import_rules/route.ts | 1 - .../logic/actions/duplicate_rule.ts | 27 ++-- .../logic/bulk_actions/bulk_edit_rules.ts | 1 - .../bulk_actions/rule_params_modifier.ts | 6 + .../logic/bulk_actions/validations.ts | 7 + .../logic/crud/create_rules.ts | 39 +---- .../rule_management/logic/crud/patch_rules.ts | 30 +--- .../logic/crud/update_rules.ts | 13 +- .../logic/import/import_rules_utils.ts | 10 -- .../prebuilt_rule_schema_migrations.ts | 146 ------------------ .../normalization/rule_converters.ts | 63 ++------ .../rule_schema/model/rule_schemas.ts | 3 - 41 files changed, 113 insertions(+), 663 deletions(-) delete mode 100644 packages/kbn-openapi-generator/src/template_service/templates/api_client_mock_responses.handlebars delete mode 100644 x-pack/plugins/alerting/server/application/rule/methods/bulk_edit/schemas/migrate_prebuilt_schema_on_bulk_edit.ts delete mode 100644 x-pack/plugins/security_solution/common/api/detection_engine/prebuilt_rules/perform_rule_upgrade/attempt1.ts delete mode 100644 x-pack/plugins/security_solution/common/api/detection_engine/prebuilt_rules/perform_rule_upgrade/attempt2.ts delete mode 100644 x-pack/plugins/security_solution/public/common/api_client/client.mock.ts delete mode 100644 x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/normalization/prebuilt_rule_schema_migrations.ts diff --git a/packages/kbn-openapi-generator/src/template_service/templates/api_client_mock_responses.handlebars b/packages/kbn-openapi-generator/src/template_service/templates/api_client_mock_responses.handlebars deleted file mode 100644 index e790c4480b75ce..00000000000000 --- a/packages/kbn-openapi-generator/src/template_service/templates/api_client_mock_responses.handlebars +++ /dev/null @@ -1,16 +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. - */ -/* eslint-disable @typescript-eslint/no-duplicate-imports */ - -{{> disclaimer}} - -{{#each operations}} -{{#if responseExample}} -export const {{operationId}}MockResponse = {{{toJSON responseExample}}}; -export const get{{operationId}}MockResponse = () => {{operationId}}MockResponse; -{{/if}} -{{/each}} \ No newline at end of file diff --git a/x-pack/plugins/alerting/server/application/rule/methods/bulk_edit/bulk_edit_rules.ts b/x-pack/plugins/alerting/server/application/rule/methods/bulk_edit/bulk_edit_rules.ts index bfa604b7ce14b3..1a4898418a8c44 100644 --- a/x-pack/plugins/alerting/server/application/rule/methods/bulk_edit/bulk_edit_rules.ts +++ b/x-pack/plugins/alerting/server/application/rule/methods/bulk_edit/bulk_edit_rules.ts @@ -78,7 +78,6 @@ import { transformRuleDomainToRule, } from '../../transforms'; import { validateScheduleLimit, ValidateScheduleLimitResult } from '../get_schedule_frequency'; -import { migratePrebuiltSchemaOnRuleBulkEdit } from './schemas/migrate_prebuilt_schema_on_bulk_edit'; const isValidInterval = (interval: string | undefined): interval is string => { return interval !== undefined; @@ -513,13 +512,9 @@ async function updateRuleAttributesAndParamsInMemory( updatedRule.revision += 1; } - const isRuleUpdated = !(isAttributesUpdateSkipped && isParamsUpdateSkipped); - - migratePrebuiltSchemaOnRuleBulkEdit(ruleParams, isRuleUpdated); - // If neither attributes nor parameters were updated, mark // the rule as skipped and continue to the next rule. - if (!isRuleUpdated) { + if (isAttributesUpdateSkipped && isParamsUpdateSkipped) { skipped.push({ id: rule.id, name: rule.attributes.name, diff --git a/x-pack/plugins/alerting/server/application/rule/methods/bulk_edit/schemas/migrate_prebuilt_schema_on_bulk_edit.ts b/x-pack/plugins/alerting/server/application/rule/methods/bulk_edit/schemas/migrate_prebuilt_schema_on_bulk_edit.ts deleted file mode 100644 index 09ce6e26c97494..00000000000000 --- a/x-pack/plugins/alerting/server/application/rule/methods/bulk_edit/schemas/migrate_prebuilt_schema_on_bulk_edit.ts +++ /dev/null @@ -1,38 +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 { RuleParams } from '../../../types'; - -const getPrebuiltValueForRuleBulkEdit = ( - ruleParams: RuleParams, - isRuleUpdatedDuringBulkUpdate: boolean -) => { - if (ruleParams?.prebuilt) { - return { - ...ruleParams.prebuilt, - isCustomized: ruleParams.prebuilt.isCustomized || isRuleUpdatedDuringBulkUpdate, - }; - } - - if (ruleParams.immutable) { - return { - isCustomized: isRuleUpdatedDuringBulkUpdate, - }; - } - - return undefined; -}; - -export const migratePrebuiltSchemaOnRuleBulkEdit = ( - ruleParams: RuleParams, - isRuleUpdatedDuringBulkUpdate: boolean -) => { - const immutable = Boolean(ruleParams.prebuilt) || ruleParams.immutable; - const prebuilt = getPrebuiltValueForRuleBulkEdit(ruleParams, isRuleUpdatedDuringBulkUpdate); - - ruleParams.prebuilt = prebuilt; - ruleParams.immutable = immutable; -}; diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/common_attributes.gen.ts b/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/common_attributes.gen.ts index ce5bdcc7284d44..e3401d4cf16bab 100644 --- a/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/common_attributes.gen.ts +++ b/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/common_attributes.gen.ts @@ -63,48 +63,9 @@ export const KqlQueryLanguage = z.enum(['kuery', 'lucene']); export type KqlQueryLanguageEnum = typeof KqlQueryLanguage.enum; export const KqlQueryLanguageEnum = KqlQueryLanguage.enum; -/** - * [DEPRECATION WARNING - This field is deprecated and will be removed in a future release. Use the prebuilt field to determine if a rule is an Elastic prebuilt rule or a custom rule.] - Determines whether the rule is immutable (i.e. cannot be modified by the user). - */ export type IsRuleImmutable = z.infer; export const IsRuleImmutable = z.boolean(); -/** - * Determines whether an external/prebuilt rule has been customized by the user (i.e. any of its fields have been modified and diverged from the base value). - */ -export type IsExternalRuleCustomized = z.infer; -export const IsExternalRuleCustomized = z.boolean(); - -/** - * The date and time that the external/prebuilt rule was last updated in its source repository. - */ -export type ExternalSourceUpdatedAt = z.infer; -export const ExternalSourceUpdatedAt = z.string().datetime(); - -/** - * Type of rule source for internally sourced rules, i.e. created within the Kibana apps. - */ -export type InternalRuleSource = z.infer; -export const InternalRuleSource = z.object({ - type: z.literal('internal'), -}); - -/** - * Type of rule source for externally sourced rules, i.e. rules that have an external source, such as the Elastic Prebuilt rules repo. - */ -export type ExternalRuleSource = z.infer; -export const ExternalRuleSource = z.object({ - type: z.literal('external'), - is_customized: IsExternalRuleCustomized, - source_updated_at: ExternalSourceUpdatedAt.optional(), -}); - -/** - * Discriminated union that determines whether the rule is internally sourced (created within the Kibana app) or has an external source, such as the Elastic Prebuilt rules repo. - */ -export type RuleSource = z.infer; -export const RuleSource = z.union([ExternalRuleSource, InternalRuleSource]); - /** * Determines whether the rule is enabled. */ diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/common_attributes.schema.yaml b/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/common_attributes.schema.yaml index 099f68c2f265d7..1387072bf99e88 100644 --- a/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/common_attributes.schema.yaml +++ b/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/common_attributes.schema.yaml @@ -53,49 +53,6 @@ components: IsRuleImmutable: type: boolean - description: '[DEPRECATION WARNING - This field is deprecated and will be removed in a future release. Use the prebuilt field to determine if a rule is an Elastic prebuilt rule or a custom rule.] - Determines whether the rule is immutable (i.e. cannot be modified by the user).' - - IsExternalRuleCustomized: - type: boolean - description: Determines whether an external/prebuilt rule has been customized by the user (i.e. any of its fields have been modified and diverged from the base value). - - ExternalSourceUpdatedAt: - type: string - format: date-time - description: The date and time that the external/prebuilt rule was last updated in its source repository. - - InternalRuleSource: - description: Type of rule source for internally sourced rules, i.e. created within the Kibana apps. - type: object - properties: - type: - type: string - enum: - - internal - required: - - type - - ExternalRuleSource: - description: Type of rule source for externally sourced rules, i.e. rules that have an external source, such as the Elastic Prebuilt rules repo. - type: object - properties: - type: - type: string - enum: - - external - is_customized: - $ref: '#/components/schemas/IsExternalRuleCustomized' - source_updated_at: - $ref: '#/components/schemas/ExternalSourceUpdatedAt' - required: - - type - - is_customized - - RuleSource: - description: Discriminated union that determines whether the rule is internally sourced (created within the Kibana app) or has an external source, such as the Elastic Prebuilt rules repo. - oneOf: - - $ref: '#/components/schemas/ExternalRuleSource' - - $ref: '#/components/schemas/InternalRuleSource' IsRuleEnabled: type: boolean diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/rule_schemas.gen.ts b/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/rule_schemas.gen.ts index 374f6c646606b7..6196e904626224 100644 --- a/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/rule_schemas.gen.ts +++ b/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/rule_schemas.gen.ts @@ -55,7 +55,6 @@ import { RuleObjectId, RuleSignatureId, IsRuleImmutable, - RuleSource, RelatedIntegrationArray, RequiredFieldArray, SetupGuide, @@ -156,8 +155,7 @@ export const ResponseFields = z.object({ id: RuleObjectId, rule_id: RuleSignatureId, immutable: IsRuleImmutable, - rule_source: RuleSource.optional(), - updated_at: z.string().datetime(), + updated_at: z.string().datetime(), updated_by: z.string(), created_at: z.string().datetime(), created_by: z.string(), diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/rule_schemas.schema.yaml b/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/rule_schemas.schema.yaml index a6457f12cde7b7..22308557c3aaa8 100644 --- a/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/rule_schemas.schema.yaml +++ b/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/rule_schemas.schema.yaml @@ -161,8 +161,6 @@ components: $ref: './common_attributes.schema.yaml#/components/schemas/RuleSignatureId' immutable: $ref: './common_attributes.schema.yaml#/components/schemas/IsRuleImmutable' - rule_source: - $ref: './common_attributes.schema.yaml#/components/schemas/RuleSource' updated_at: type: string format: date-time diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/prebuilt_rules/perform_rule_upgrade/attempt1.ts b/x-pack/plugins/security_solution/common/api/detection_engine/prebuilt_rules/perform_rule_upgrade/attempt1.ts deleted file mode 100644 index e320caa8fdc69e..00000000000000 --- a/x-pack/plugins/security_solution/common/api/detection_engine/prebuilt_rules/perform_rule_upgrade/attempt1.ts +++ /dev/null @@ -1,52 +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 type { RuleResponse } from '../../model'; -import type { AggregatedPrebuiltRuleError } from '../model'; - -export enum PickVersionValues { - BASE = 'BASE', - CURRENT = 'CURRENT', - TARGET = 'TARGET', -} - -export type TPickVersionValues = keyof typeof PickVersionValues; - -export interface RuleUpgradeSpecifier { - rule_id: string; - /** - * This parameter is needed for handling race conditions with Optimistic Concurrency Control. - * Two or more users can call upgrade/_review and upgrade/_perform endpoints concurrently. - * Also, in general, the time between these two calls can be anything. - * The idea is to only allow the user to install a rule if the user has reviewed the exact version - * of it that had been returned from the _review endpoint. If the version changed on the BE, - * upgrade/_perform endpoint will return a version mismatch error for this rule. - */ - revision: number; - /** - * The target version to upgrade to. - */ - version: number; - pick_version?: TPickVersionValues; -} - -export interface UpgradeSpecificRulesRequest { - mode: 'SPECIFIC_RULES'; - rules: RuleUpgradeSpecifier[]; - pick_version?: TPickVersionValues; -} - -export interface UpgradeAllRulesRequest { - mode: 'ALL_RULES'; - pick_version?: TPickVersionValues; -} - -export type PerformRuleUpgradeRequestBody = UpgradeSpecificRulesRequest | UpgradeAllRulesRequest; - -export enum SkipRuleUpgradeReason { - RULE_UP_TO_DATE = 'RULE_UP_TO_DATE', -} diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/prebuilt_rules/perform_rule_upgrade/attempt2.ts b/x-pack/plugins/security_solution/common/api/detection_engine/prebuilt_rules/perform_rule_upgrade/attempt2.ts deleted file mode 100644 index 3bc89fddfdf598..00000000000000 --- a/x-pack/plugins/security_solution/common/api/detection_engine/prebuilt_rules/perform_rule_upgrade/attempt2.ts +++ /dev/null @@ -1,39 +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 { RuleResponse } from '../../model'; -import { AggregatedPrebuiltRuleError } from '../model'; - -enum PickVersionValues { - BASE = 'BASE', - CURRENT = 'CURRENT', - TARGET = 'TARGET', -} - -interface RuleUpgradeSpecifier { - rule_id: string; - revision: number; - version: number; - pick_version?: PickVersionValues; -} - -interface UpgradeSpecificRulesRequest { - mode: 'SPECIFIC_RULES'; - rules: RuleUpgradeSpecifier[]; - pick_version?: PickVersionValues; -} - -interface UpgradeAllRulesRequest { - mode: 'ALL_RULES'; - pick_version?: PickVersionValues; -} - -type PerformRuleUpgradeRequestBody = UpgradeAllRulesRequest | UpgradeSpecificRulesRequest; - -enum SkipRuleUpgradeReason { - RULE_UP_TO_DATE = 'RULE_UP_TO_DATE', -} diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/prebuilt_rules/perform_rule_upgrade/perform_rule_upgrade_route.ts b/x-pack/plugins/security_solution/common/api/detection_engine/prebuilt_rules/perform_rule_upgrade/perform_rule_upgrade_route.ts index 549c2ddcff483b..b1d3b166a513ea 100644 --- a/x-pack/plugins/security_solution/common/api/detection_engine/prebuilt_rules/perform_rule_upgrade/perform_rule_upgrade_route.ts +++ b/x-pack/plugins/security_solution/common/api/detection_engine/prebuilt_rules/perform_rule_upgrade/perform_rule_upgrade_route.ts @@ -15,7 +15,6 @@ export enum PickVersionValues { BASE = 'BASE', CURRENT = 'CURRENT', TARGET = 'TARGET', - MERGE = 'MERGE', } export const TPickVersionValues = enumeration('PickVersionValues', PickVersionValues); @@ -96,4 +95,4 @@ export interface PerformRuleUpgradeResponseBody { skipped: SkippedRuleUpgrade[]; }; errors: AggregatedPrebuiltRuleError[]; -} \ No newline at end of file +} diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/prebuilt_rules/review_rule_upgrade/review_rule_upgrade_route.ts b/x-pack/plugins/security_solution/common/api/detection_engine/prebuilt_rules/review_rule_upgrade/review_rule_upgrade_route.ts index d044c434ab4ec8..09067a2e152e14 100644 --- a/x-pack/plugins/security_solution/common/api/detection_engine/prebuilt_rules/review_rule_upgrade/review_rule_upgrade_route.ts +++ b/x-pack/plugins/security_solution/common/api/detection_engine/prebuilt_rules/review_rule_upgrade/review_rule_upgrade_route.ts @@ -32,4 +32,4 @@ export interface RuleUpgradeInfoForReview { target_rule: RuleResponse; diff: PartialRuleDiff; revision: number; -} \ No newline at end of file +} diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/import_rules/rule_to_import.ts b/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/import_rules/rule_to_import.ts index f982fdc62c1a69..e11ae24d284f7a 100644 --- a/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/import_rules/rule_to_import.ts +++ b/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/import_rules/rule_to_import.ts @@ -29,6 +29,6 @@ export type RuleToImportInput = z.input; export const RuleToImport = BaseCreateProps.and(TypeSpecificCreateProps).and( ResponseFields.partial().extend({ rule_id: RuleSignatureId, - version: RuleVersion, + immutable: z.literal(false).default(false), }) ); diff --git a/x-pack/plugins/security_solution/common/detection_engine/rule_management/rule_fields.ts b/x-pack/plugins/security_solution/common/detection_engine/rule_management/rule_fields.ts index a9530cf08508df..5d72cd15a96ae3 100644 --- a/x-pack/plugins/security_solution/common/detection_engine/rule_management/rule_fields.ts +++ b/x-pack/plugins/security_solution/common/detection_engine/rule_management/rule_fields.ts @@ -21,6 +21,4 @@ export const ENABLED_FIELD = 'alert.attributes.enabled'; export const TAGS_FIELD = 'alert.attributes.tags'; export const PARAMS_TYPE_FIELD = 'alert.attributes.params.type'; export const PARAMS_IMMUTABLE_FIELD = 'alert.attributes.params.immutable'; -export const PARAMS_PREBUILT_FIELD = 'alert.attributes.params.prebuilt'; -export const PARAMS_PREBUILT_IS_CUSTOMIZED_FIELD = 'alert.attributes.params.prebuilt.isCustomized'; export const LAST_RUN_OUTCOME_FIELD = 'alert.attributes.lastRun.outcome'; diff --git a/x-pack/plugins/security_solution/common/detection_engine/rule_management/rule_filtering.ts b/x-pack/plugins/security_solution/common/detection_engine/rule_management/rule_filtering.ts index 83a041fac760b1..6cb924d5ebdc8d 100644 --- a/x-pack/plugins/security_solution/common/detection_engine/rule_management/rule_filtering.ts +++ b/x-pack/plugins/security_solution/common/detection_engine/rule_management/rule_filtering.ts @@ -13,17 +13,12 @@ import { ENABLED_FIELD, LAST_RUN_OUTCOME_FIELD, PARAMS_IMMUTABLE_FIELD, - PARAMS_PREBUILT_IS_CUSTOMIZED_FIELD, - PARAMS_TYPE_FIELD, + PARAMS_TYPE_FIELD, RULE_NAME_FIELD, RULE_PARAMS_FIELDS, TAGS_FIELD, } from './rule_fields'; -// KQL does not allow to search for existence of the prebuilt object field, since params is unmapped -// so we can search for the existence of the isCustomized subfield instead, which is required -export const KQL_FILTER_PREBUILT_RULES = `${PARAMS_PREBUILT_IS_CUSTOMIZED_FIELD}: *`; -export const KQL_FILTER_CUSTOM_RULES = `NOT ${PARAMS_PREBUILT_IS_CUSTOMIZED_FIELD}: *`; export const KQL_FILTER_IMMUTABLE_RULES = `${PARAMS_IMMUTABLE_FIELD}: true`; export const KQL_FILTER_MUTABLE_RULES = `${PARAMS_IMMUTABLE_FIELD}: false`; export const KQL_FILTER_ENABLED_RULES = `${ENABLED_FIELD}: true`; @@ -64,11 +59,9 @@ export function convertRulesFilterToKQL({ if (showCustomRules && showElasticRules) { // if both showCustomRules && showElasticRules selected we omit filter, as it includes all existing rules } else if (showElasticRules) { - kql.push(`${KQL_FILTER_PREBUILT_RULES}`); - // kql.push(`(${KQL_FILTER_PREBUILT_RULES} OR ${KQL_FILTER_IMMUTABLE_RULES})`); + kql.push(KQL_FILTER_IMMUTABLE_RULES); } else if (showCustomRules) { - kql.push(`${KQL_FILTER_CUSTOM_RULES}`); - // kql.push(`(${KQL_FILTER_CUSTOM_RULES} OR ${KQL_FILTER_MUTABLE_RULES})`); + kql.push(KQL_FILTER_MUTABLE_RULES); } if (enabled !== undefined) { diff --git a/x-pack/plugins/security_solution/public/common/api_client/client.mock.ts b/x-pack/plugins/security_solution/public/common/api_client/client.mock.ts deleted file mode 100644 index e7d825f5236a13..00000000000000 --- a/x-pack/plugins/security_solution/public/common/api_client/client.mock.ts +++ /dev/null @@ -1,32 +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. - */ - -/* - * NOTICE: Do not edit this file manually. - * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. - * - * info: - * title: API client response mocks - * version: Bundle (no version) - */ - -export const CreateRuleMockResponse = { - rule_id: 'MY_RULE_ID', - description: 'Detecting root and admin users', - name: 'Query with a rule id', - query: 'user.name: root or user.name: admin', - severity: 'high', - type: 'query', - risk_score: 55, - language: 'kuery', - enabled: true, - references: [1, 2, 'test'], - pepe: { pipo: 1, juan: 'hola' }, - arra: [1, 2, 'papapap'], - my_object: { hi: ['you'] }, -}; -export const getCreateRuleMockResponse = () => CreateRuleMockResponse; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/pages/rule_editing/index.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/pages/rule_editing/index.tsx index 409c6c5cc906cf..ff96fd64f027f8 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/pages/rule_editing/index.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/pages/rule_editing/index.tsx @@ -226,6 +226,7 @@ const EditRulePageComponent: FC<{ rule: RuleResponse }> = ({ rule }) => { 'data-test-subj': 'edit-rule-define-tab', id: RuleStep.defineRule, name: ruleI18n.DEFINITION, + disabled: rule?.immutable, content: (
    = ({ rule }) => { 'data-test-subj': 'edit-rule-about-tab', id: RuleStep.aboutRule, name: ruleI18n.ABOUT, + disabled: rule?.immutable, content: (
    = ({ rule }) => { 'data-test-subj': 'edit-rule-schedule-tab', id: RuleStep.scheduleRule, name: ruleI18n.SCHEDULE, + disabled: rule?.immutable, content: (
    !rule.prebuilt, + enabled: (rule: Rule) => !rule.immutable, }, { type: 'icon', diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_upgrade/perform_rule_upgrade_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_upgrade/perform_rule_upgrade_route.ts index d8eb0e72022871..3009495e322978 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_upgrade/perform_rule_upgrade_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_upgrade/perform_rule_upgrade_route.ts @@ -144,20 +144,16 @@ export const performRuleUpgradeRoute = (router: SecuritySolutionPluginRouter) => break; case PickVersionValues.TARGET: targetRules.push(target); - case PickVersionValues.MERGE: - targetRules.push(target); break; default: assertUnreachable(rulePickVersion); } }); - const isRuleCustomizedDuringUpgrade = false; // Perform the upgrade const { results: updatedRules, errors: installationErrors } = await upgradePrebuiltRules( rulesClient, - targetRules, - isRuleCustomizedDuringUpgrade + targetRules ); const ruleErrors = [...fetchErrors, ...installationErrors]; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/review_rule_upgrade/review_rule_upgrade_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/review_rule_upgrade/review_rule_upgrade_route.ts index 5fac8b0fbd9a25..1fcb36b592d567 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/review_rule_upgrade/review_rule_upgrade_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/review_rule_upgrade/review_rule_upgrade_route.ts @@ -113,7 +113,6 @@ const calculateRuleInfos = (results: CalculateRuleDiffResult[]): RuleUpgradeInfo revision: installedCurrentVersion.revision, current_rule: installedCurrentVersion, target_rule: targetRule, - merged_rule: ruleVersions.mergedVersion, diff: { fields: pickBy>( ruleDiff.fields, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/diff/calculate_rule_diff.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/diff/calculate_rule_diff.ts index b1ab79b717db99..652d54dc8f6668 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/diff/calculate_rule_diff.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/diff/calculate_rule_diff.ts @@ -33,8 +33,7 @@ export interface CalculateRuleDiffResult { base?: DiffableRule; target: DiffableRule; }; - mergedVersion: RuleResponse; // ADDED in POC - }; + }; } /** @@ -76,16 +75,6 @@ export const calculateRuleDiff = (args: RuleVersions): CalculateRuleDiffResult = target_version: diffableTargetVersion, }); - const mergedVersion = Object.entries(fieldsDiff).reduce((acc, field) => { - - debugger; - const ungroupedFields = getUngroupedFields(field); - return { - ...acc, - ...ungroupedFields, - }; - }, {}); - const hasAnyFieldConflict = Object.values>(fieldsDiff).some( (fieldDiff) => fieldDiff.has_conflict ); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/rule_objects/create_prebuilt_rules.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/rule_objects/create_prebuilt_rules.ts index d57ba291d0f858..54b4361bf868bd 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/rule_objects/create_prebuilt_rules.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/rule_objects/create_prebuilt_rules.ts @@ -21,7 +21,7 @@ export const createPrebuiltRules = (rulesClient: RulesClient, rules: PrebuiltRul return createRules({ rulesClient, params: rule, - isPrebuilt: true, + immutable: true, defaultEnabled: false, }); }, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/rule_objects/upgrade_prebuilt_rules.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/rule_objects/upgrade_prebuilt_rules.test.ts index 9650e8ebdb9d5d..2990533dc0f891 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/rule_objects/upgrade_prebuilt_rules.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/rule_objects/upgrade_prebuilt_rules.test.ts @@ -19,7 +19,6 @@ jest.mock('../../../rule_management/logic/crud/patch_rules'); describe('updatePrebuiltRules', () => { let rulesClient: ReturnType; - const isRuleCustomizedDuringUpgrade = false; beforeEach(() => { rulesClient = rulesClientMock.create(); @@ -37,11 +36,7 @@ describe('updatePrebuiltRules', () => { const prepackagedRule = getPrebuiltRuleMock(); rulesClient.find.mockResolvedValue(getFindResultWithSingleHit()); - await upgradePrebuiltRules( - rulesClient, - [{ ...prepackagedRule, actions }], - isRuleCustomizedDuringUpgrade - ); + await upgradePrebuiltRules(rulesClient, [{ ...prepackagedRule, actions }]); expect(patchRules).toHaveBeenCalledWith( expect.objectContaining({ @@ -72,11 +67,7 @@ describe('updatePrebuiltRules', () => { data: [getRuleMock(getThreatRuleParams())], }); - await upgradePrebuiltRules( - rulesClient, - [{ ...prepackagedRule, ...updatedThreatParams }], - isRuleCustomizedDuringUpgrade - ); + await upgradePrebuiltRules(rulesClient, [{ ...prepackagedRule, ...updatedThreatParams }]); expect(patchRules).toHaveBeenCalledWith( expect.objectContaining({ diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/rule_objects/upgrade_prebuilt_rules.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/rule_objects/upgrade_prebuilt_rules.ts index bb4f4373ce5c77..a06b5dc17825f6 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/rule_objects/upgrade_prebuilt_rules.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/rule_objects/upgrade_prebuilt_rules.ts @@ -26,17 +26,13 @@ import type { PrebuiltRuleAsset } from '../../model/rule_assets/prebuilt_rule_as * @param rulesClient Alerting client * @param rules The rules to apply the update for */ -export const upgradePrebuiltRules = async ( - rulesClient: RulesClient, - rules: PrebuiltRuleAsset[], - isRuleCustomizedDuringUpgrade = false -) => +export const upgradePrebuiltRules = async (rulesClient: RulesClient, rules: PrebuiltRuleAsset[]) => withSecuritySpan('upgradePrebuiltRules', async () => { const result = await initPromisePool({ concurrency: MAX_RULES_TO_UPDATE_IN_PARALLEL, items: rules, executor: async (rule) => { - return upgradeRule(rulesClient, rule, isRuleCustomizedDuringUpgrade); + return upgradeRule(rulesClient, rule); }, }); @@ -52,8 +48,7 @@ export const upgradePrebuiltRules = async ( */ const upgradeRule = async ( rulesClient: RulesClient, - rule: PrebuiltRuleAsset, - isRuleCustomizedDuringUpdate: boolean + rule: PrebuiltRuleAsset ): Promise> => { const existingRule = await readRules({ rulesClient, @@ -65,17 +60,6 @@ const upgradeRule = async ( throw new PrepackagedRulesError(`Failed to find rule ${rule.rule_id}`, 500); } - // When upgrading a prebuilt rule, we need to build the `prebuilt` field - // out of the PrebuiltRuleAsset before passing it to createRules or patchRules - // For isCustomized, set the value to true if the rule was customized during the current update. - // Otherwise, take the existing value from the currently installed value. - const isCustomized = - (isRuleCustomizedDuringUpdate || existingRule.params.prebuilt?.isCustomized) ?? false; - const prebuilt = { - isCustomized, - elasticUpdateDate: rule.elasticUpdateDate, - }; - // If we're trying to change the type of a prepackaged rule, we need to delete the old one // and replace it with the new rule, keeping the enabled setting, actions, throttle, id, // and exception lists from the old rule @@ -87,10 +71,9 @@ const upgradeRule = async ( return createRules({ rulesClient, - isPrebuilt: true, + immutable: true, params: { ...rule, - prebuilt, // Force the prepackaged rule to use the enabled state from the existing rule, // regardless of what the prepackaged rule says enabled: existingRule.enabled, @@ -103,12 +86,10 @@ const upgradeRule = async ( existingRule, nextParams: { ...rule, - prebuilt, // Force enabled to use the enabled state from the existing rule by passing in undefined to patchRules enabled: undefined, actions: undefined, }, - isRuleCustomizedDuringUpdate, }); const updatedRule = await readRules({ diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/model/rule_assets/prebuilt_rule_asset.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/model/rule_assets/prebuilt_rule_asset.ts index 101679122d546d..0b1ec37f053eb0 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/model/rule_assets/prebuilt_rule_asset.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/model/rule_assets/prebuilt_rule_asset.ts @@ -9,8 +9,7 @@ import * as z from 'zod'; import { RelatedIntegrationArray, RequiredFieldArray, - ExternalSourceUpdatedAt, - SetupGuide, + SetupGuide, RuleSignatureId, RuleVersion, BaseCreateProps, @@ -39,6 +38,5 @@ export const PrebuiltRuleAsset = BaseCreateProps.and(TypeSpecificCreateProps).an related_integrations: RelatedIntegrationArray.optional(), required_fields: RequiredFieldArray.optional(), setup: SetupGuide.optional(), - source_updated_at: ExternalSourceUpdatedAt.optional(), - }) + }) ); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_actions/route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_actions/route.ts index d76b643f82a60f..d09c11d1289bd3 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_actions/route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_actions/route.ts @@ -257,31 +257,25 @@ export const performBulkActionRoute = ( }, }, async (context, request, response): Promise> => { - // function delay(ms) { - // return new Promise((resolve) => setTimeout(resolve, ms)); - // } - - // await delay(5000); // Wait for 2000 milliseconds (2 seconds) - - // return siemResponse.error({ - // body: 'error.message', - // statusCode: 500, - // }); const { body } = request; const siemResponse = buildSiemResponse(response); + if (body?.ids && body.ids.length > RULES_TABLE_MAX_PAGE_SIZE) { return siemResponse.error({ body: `More than ${RULES_TABLE_MAX_PAGE_SIZE} ids sent for bulk edit action.`, statusCode: 400, }); } + if (body?.ids && body.query !== undefined) { return siemResponse.error({ body: `Both query and ids are sent. Define either ids or query in request payload.`, statusCode: 400, }); } + const isDryRun = request.query.dry_run; + // dry run is not supported for export, as it doesn't change ES state and has different response format(exported JSON file) if (isDryRun && body.action === BulkActionTypeEnum.export) { return siemResponse.error({ @@ -289,7 +283,9 @@ export const performBulkActionRoute = ( statusCode: 400, }); } + const abortController = new AbortController(); + // subscribing to completed$, because it handles both cases when request was completed and aborted. // when route is finished by timeout, aborted$ is not getting fired request.events.completed$.subscribe(() => abortController.abort()); @@ -302,20 +298,26 @@ export const performBulkActionRoute = ( 'lists', 'actions', ]); + const rulesClient = ctx.alerting.getRulesClient(); const exceptionsClient = ctx.lists?.getExceptionListClient(); const savedObjectsClient = ctx.core.savedObjects.client; const actionsClient = (await ctx.actions)?.getActionsClient(); + const { getExporter, getClient } = (await ctx.core).savedObjects; const client = getClient({ includedHiddenTypes: ['action'] }); + const exporter = getExporter(client); + const mlAuthz = buildMlAuthz({ license: ctx.licensing.license, ml, request, savedObjectsClient, }); + const query = body.query !== '' ? body.query : undefined; + // handling this action before switch statement as bulkEditRules fetch rules within // rulesClient method, hence there is no need to use fetchRulesByQueryOrIds utility if (body.action === BulkActionTypeEnum.edit && !isDryRun) { @@ -326,23 +328,27 @@ export const performBulkActionRoute = ( actions: body.edit, mlAuthz, }); + return buildBulkResponse(response, { updated: rules, skipped, errors, }); } + const fetchRulesOutcome = await fetchRulesByQueryOrIds({ rulesClient, query, ids: body.ids, abortSignal: abortController.signal, }); + const rules = fetchRulesOutcome.results.map(({ result }) => result); let bulkActionOutcome: PromisePoolOutcome; let updated: RuleAlertType[] = []; let created: RuleAlertType[] = []; let deleted: RuleAlertType[] = []; + switch (body.action) { case BulkActionTypeEnum.enable: bulkActionOutcome = await initPromisePool({ @@ -350,13 +356,16 @@ export const performBulkActionRoute = ( items: rules, executor: async (rule) => { await validateBulkEnableRule({ mlAuthz, rule }); + // during dry run only validation is getting performed and rule is not saved in ES, thus return early if (isDryRun) { return rule; } + if (!rule.enabled) { await rulesClient.enable({ id: rule.id }); } + return { ...rule, enabled: true, @@ -374,13 +383,16 @@ export const performBulkActionRoute = ( items: rules, executor: async (rule) => { await validateBulkDisableRule({ mlAuthz, rule }); + // during dry run only validation is getting performed and rule is not saved in ES, thus return early if (isDryRun) { return rule; } + if (rule.enabled) { await rulesClient.disable({ id: rule.id }); } + return { ...rule, enabled: false, @@ -392,6 +404,7 @@ export const performBulkActionRoute = ( .map(({ result }) => result) .filter((rule): rule is RuleAlertType => rule !== null); break; + case BulkActionTypeEnum.delete: bulkActionOutcome = await initPromisePool({ concurrency: MAX_RULES_TO_UPDATE_IN_PARALLEL, @@ -401,10 +414,12 @@ export const performBulkActionRoute = ( if (isDryRun) { return null; } + await deleteRules({ ruleId: rule.id, rulesClient, }); + return null; }, abortSignal: abortController.signal, @@ -413,22 +428,26 @@ export const performBulkActionRoute = ( .map(({ item }) => item) .filter((rule): rule is RuleAlertType => rule !== null); break; + case BulkActionTypeEnum.duplicate: bulkActionOutcome = await initPromisePool({ concurrency: MAX_RULES_TO_UPDATE_IN_PARALLEL, items: rules, executor: async (rule) => { await validateBulkDuplicateRule({ mlAuthz, rule }); + // during dry run only validation is getting performed and rule is not saved in ES, thus return early if (isDryRun) { return rule; } + let shouldDuplicateExceptions = true; let shouldDuplicateExpiredExceptions = true; if (body.duplicate !== undefined) { shouldDuplicateExceptions = body.duplicate.include_exceptions; shouldDuplicateExpiredExceptions = body.duplicate.include_expired_exceptions; } + const duplicateRuleToCreate = await duplicateRule({ rule, }); @@ -436,6 +455,7 @@ export const performBulkActionRoute = ( const createdRule = await rulesClient.create({ data: duplicateRuleToCreate, }); + // we try to create exceptions after rule created, and then update rule const exceptions = shouldDuplicateExceptions ? await duplicateExceptions({ @@ -445,6 +465,7 @@ export const performBulkActionRoute = ( exceptionsClient, }) : []; + const updatedRule = await rulesClient.update({ id: createdRule.id, data: { @@ -456,6 +477,7 @@ export const performBulkActionRoute = ( }, shouldIncrementRevision: () => false, }); + // TODO: figureout why types can't return just updatedRule return { ...createdRule, ...updatedRule }; }, @@ -465,6 +487,7 @@ export const performBulkActionRoute = ( .map(({ result }) => result) .filter((rule): rule is RuleAlertType => rule !== null); break; + case BulkActionTypeEnum.export: const exported = await getExportByObjectIds( rulesClient, @@ -474,7 +497,9 @@ export const performBulkActionRoute = ( request, actionsClient ); + const responseBody = `${exported.rulesNdjson}${exported.exceptionLists}${exported.actionConnectors}${exported.exportDetails}`; + return response.ok({ headers: { 'Content-Disposition': `attachment; filename="rules_export.ndjson"`, @@ -482,6 +507,7 @@ export const performBulkActionRoute = ( }, body: responseBody, }); + // will be processed only when isDryRun === true // during dry run only validation is getting performed and rule is not saved in ES case BulkActionTypeEnum.edit: @@ -490,6 +516,7 @@ export const performBulkActionRoute = ( items: rules, executor: async (rule) => { await dryRunValidateBulkEditRule({ mlAuthz, rule, edit: body.edit }); + return rule; }, abortSignal: abortController.signal, @@ -498,9 +525,11 @@ export const performBulkActionRoute = ( .map(({ result }) => result) .filter((rule): rule is RuleAlertType => rule !== null); } + if (abortController.signal.aborted === true) { throw new AbortError('Bulk action was aborted'); } + return buildBulkResponse(response, { updated, deleted, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_create_rules/route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_create_rules/route.ts index af4c4226172f72..7ab03f2ac7dcd4 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_create_rules/route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_create_rules/route.ts @@ -127,7 +127,6 @@ export const bulkCreateRulesRoute = ( const createdRule = await createRules({ rulesClient, params: payloadRule, - isPrebuilt: false, }); return transformValidateBulkError(createdRule.params.ruleId, createdRule); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/create_rule/route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/create_rule/route.ts index 11b13b0491fff3..e9c84c1c50f5cb 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/create_rule/route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/create_rule/route.ts @@ -107,7 +107,6 @@ export const createRuleRoute = ( const createdRule = await createRules({ rulesClient, params: request.body, - isPrebuilt: false, }); return response.ok({ diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/filters/route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/filters/route.ts index ba78bee8449697..183d4f8e2f78d3 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/filters/route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/filters/route.ts @@ -9,7 +9,6 @@ import { transformError } from '@kbn/securitysolution-es-utils'; import { validate } from '@kbn/securitysolution-io-ts-utils'; import type { RulesClient } from '@kbn/alerting-plugin/server'; import type { IKibanaResponse } from '@kbn/core/server'; -import { KQL_FILTER_PREBUILT_RULES } from '../../../../../../../common/detection_engine/rule_management/rule_filtering'; import { GetRuleManagementFiltersResponse, RULE_MANAGEMENT_FILTERS_URL, @@ -37,12 +36,12 @@ async function fetchRulesCount(rulesClient: RulesClient): Promise { findRules({ ...DEFAULT_FIND_RULES_COUNT_PARAMS, rulesClient, - filter: KQL_FILTER_PREBUILT_RULES, + filter: 'alert.attributes.params.immutable: true', }), findRules({ ...DEFAULT_FIND_RULES_COUNT_PARAMS, rulesClient, - filter: `NOT ${KQL_FILTER_PREBUILT_RULES}`, + filter: 'alert.attributes.params.immutable: false', }), ]); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/find_rules/route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/find_rules/route.ts index fe04a375960c43..3cbd164586a9df 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/find_rules/route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/find_rules/route.ts @@ -14,6 +14,7 @@ import { FindRulesRequestQuery, validateFindRulesRequestQuery, } from '../../../../../../../common/api/detection_engine/rule_management'; + import type { SecuritySolutionPluginRouter } from '../../../../../../types'; import { findRules } from '../../../logic/search/find_rules'; import { buildSiemResponse } from '../../../../routes/utils'; @@ -62,11 +63,7 @@ export const findRulesRoute = (router: SecuritySolutionPluginRouter, logger: Log }); const transformed = transformFindAlerts(rules); - - return response.ok({ - body: transformed ?? {}, - headers: { 'Deprecation-Info': 'Warning 22' }, - }); + return response.ok({ body: transformed ?? {} }); } catch (err) { const error = transformError(err); return siemResponse.error({ diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/import_rules/route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/import_rules/route.ts index 981431dcc63dea..5867d099fb8def 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/import_rules/route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/import_rules/route.ts @@ -176,7 +176,6 @@ export const importRulesRoute = ( return false; } }); - const importRules: ImportRulesResponse = { success: errorsResp.length === 0, success_count: successes.length, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/actions/duplicate_rule.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/actions/duplicate_rule.ts index ffe9bbeddc225a..315517504def47 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/actions/duplicate_rule.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/actions/duplicate_rule.ts @@ -12,8 +12,6 @@ import type { SanitizedRule } from '@kbn/alerting-plugin/common'; import { SERVER_APP_ID } from '../../../../../../common/constants'; import type { InternalRuleCreate, RuleParams } from '../../../rule_schema'; import { transformToActionFrequency } from '../../normalization/rule_actions'; -import { migratePrebuiltSchemaOnRuleCreation } from '../../normalization/prebuilt_rule_schema_migrations'; -import { internalRuleToAPIResponse } from '../../normalization/rule_converters'; const DUPLICATE_TITLE = i18n.translate( 'xpack.securitySolution.detectionEngine.rules.cloneRule.duplicateTitle', @@ -30,18 +28,14 @@ export const duplicateRule = async ({ rule }: DuplicateRuleParams): Promise { await throwMlAuthError(mlAuthz, ruleType); + + // if rule can't be edited error will be thrown + const canRuleBeEdited = !immutable || istEditApplicableToImmutableRule(edit); + await throwDryRunError( + () => invariant(canRuleBeEdited, "Elastic rule can't be edited"), + BulkActionsDryRunErrCode.IMMUTABLE + ); }; /** diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/crud/create_rules.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/crud/create_rules.ts index 7608a90da4ed44..0c39d0f39411fd 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/crud/create_rules.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/crud/create_rules.ts @@ -8,11 +8,7 @@ import type { SanitizedRule } from '@kbn/alerting-plugin/common'; import type { RulesClient } from '@kbn/alerting-plugin/server'; -import type { - RuleCreateProps, - Prebuilt, - IsRuleImmutable, -} from '../../../../../../common/api/detection_engine/model/rule_schema'; +import type { RuleCreateProps } from '../../../../../../common/api/detection_engine/model/rule_schema'; import { convertCreateAPIToInternalSchema } from '../../normalization/rule_converters'; import type { RuleParams } from '../../../rule_schema'; @@ -20,45 +16,20 @@ export interface CreateRulesOptions rulesClient: RulesClient; params: T; id?: string; - isPrebuilt?: boolean; + immutable?: boolean; defaultEnabled?: boolean; allowMissingConnectorSecrets?: boolean; } -export type RuleCreateAndImportProps = RuleCreateProps & { - prebuilt?: Prebuilt; - immutable?: IsRuleImmutable; -}; - -const getIsRuleToCreatePrebuilt = ( - params: RuleCreateAndImportProps, - isPrebuilt?: boolean -): boolean => { - // If createRules is explicitly called with isPrebuilt, use that value. - // Use case when creating a custom rule or installing/updating a prebuilt rule. - if (isPrebuilt != null) { - return isPrebuilt; - } - - // Otherwise, check the passed prebuilt or immutable params for existence. - // Use case when importing a rule. Default to false if neither are passed. - return (Boolean(params.prebuilt) || params.immutable) ?? false; -}; - export const createRules = async ({ rulesClient, params, id, - isPrebuilt, + immutable = false, defaultEnabled = true, allowMissingConnectorSecrets, -}: CreateRulesOptions): Promise> => { - const isRuleToCreatePrebuilt = getIsRuleToCreatePrebuilt(params, isPrebuilt); - const internalRule = convertCreateAPIToInternalSchema( - params, - isRuleToCreatePrebuilt, - defaultEnabled - ); +}: CreateRulesOptions): Promise> => { + const internalRule = convertCreateAPIToInternalSchema(params, immutable, defaultEnabled); const rule = await rulesClient.create({ options: { id, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/crud/patch_rules.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/crud/patch_rules.ts index fb4df148a708d4..ede7b86bd737e1 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/crud/patch_rules.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/crud/patch_rules.ts @@ -6,12 +6,6 @@ */ import type { PartialRule, RulesClient } from '@kbn/alerting-plugin/server'; -import type { - RelatedIntegrationArray, - RequiredFieldArray, - SetupGuide, - Prebuilt, -} from '../../../../../../common/api/detection_engine'; import type { PatchRuleRequestBody } from '../../../../../../common/api/detection_engine/rule_management'; import type { RuleAlertType, RuleParams } from '../../../rule_schema'; @@ -19,43 +13,25 @@ import { convertPatchAPIToInternalSchema } from '../../normalization/rule_conver export interface PatchRulesOptions { rulesClient: RulesClient; - nextParams: PatchRuleRequestBody & { - related_integrations?: RelatedIntegrationArray; - required_fields?: RequiredFieldArray; - setup?: SetupGuide; - prebuilt?: Prebuilt; - }; + nextParams: PatchRuleRequestBody; existingRule: RuleAlertType | null | undefined; allowMissingConnectorSecrets?: boolean; + shouldIncrementRevision?: boolean; - isRuleCustomizedDuringUpdate?: boolean; // pass in new optional boolean } -/** - * Used when: - * - Updating a prebuilt rule with no type change - * - Importing rules and overwriting an existing rule - * - Patching rules (DETECTION_ENGINE_RULES_URL patch endpoint --> managing shared exceptions lists) - * - Bulk Patching rules (deprecated DETECTION_ENGINE_RULES_BULK_UPDATE endpoint) - * - Creating rule exceptions (CREATE_RULE_EXCEPTIONS_URL endpoint) - **/ export const patchRules = async ({ rulesClient, existingRule, nextParams, allowMissingConnectorSecrets, shouldIncrementRevision = true, - isRuleCustomizedDuringUpdate = false, }: PatchRulesOptions): Promise | null> => { if (existingRule == null) { return null; } - const patchedRule = convertPatchAPIToInternalSchema( - nextParams, - existingRule, - isRuleCustomizedDuringUpdate - ); + const patchedRule = convertPatchAPIToInternalSchema(nextParams, existingRule); const update = await rulesClient.update({ id: existingRule.id, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/crud/update_rules.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/crud/update_rules.ts index 74936f09421cbc..cfbf6a639bb5ed 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/crud/update_rules.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/crud/update_rules.ts @@ -14,7 +14,6 @@ import { transformRuleToAlertAction } from '../../../../../../common/detection_e import type { InternalRuleUpdate, RuleParams, RuleAlertType } from '../../../rule_schema'; import { transformToActionFrequency } from '../../normalization/rule_actions'; import { typeSpecificSnakeToCamel } from '../../normalization/rule_converters'; -import { migratePrebuiltSchemaOnRuleUpdate } from '../../normalization/prebuilt_rule_schema_migrations'; export interface UpdateRulesOptions { rulesClient: RulesClient; @@ -37,14 +36,6 @@ export const updateRules = async ({ const typeSpecificParams = typeSpecificSnakeToCamel(ruleUpdate); const enabled = ruleUpdate.enabled ?? true; - - const isRuleCustomizedDuringUpdate = false; - - const { immutable, prebuilt } = migratePrebuiltSchemaOnRuleUpdate({ - existingParams: existingRule.params, - isRuleCustomizedDuringUpdate, - }); - const newInternalRule: InternalRuleUpdate = { name: ruleUpdate.name, tags: ruleUpdate.tags ?? [], @@ -56,8 +47,8 @@ export const updateRules = async ({ falsePositives: ruleUpdate.false_positives ?? [], from: ruleUpdate.from ?? 'now-6m', investigationFields: ruleUpdate.investigation_fields, - immutable, - prebuilt, + // Unlike the create route, immutable comes from the existing rule here + immutable: existingRule.params.immutable, license: ruleUpdate.license, outputIndex: ruleUpdate.output_index ?? '', timelineId: ruleUpdate.timeline_id, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/import/import_rules_utils.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/import/import_rules_utils.ts index 57949531b69fa1..81940848b7dc47 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/import/import_rules_utils.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/import/import_rules_utils.ts @@ -102,15 +102,6 @@ export const importRules = async ({ id: undefined, }); - const isPrebuilt = Boolean(parsedRule.prebuilt) || parsedRule.immutable; - if (isPrebuilt && !parsedRule.version) { - createBulkErrorObject({ - ruleId: parsedRule.rule_id, - statusCode: 409, - message: `rule_id: "${parsedRule.rule_id}" is prebuilt but no version was provided`, - }); - } - if (rule == null) { await createRules({ rulesClient, @@ -118,7 +109,6 @@ export const importRules = async ({ ...parsedRule, exceptions_list: [...exceptions], }, - isPrebuilt, allowMissingConnectorSecrets, }); resolve({ diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/normalization/prebuilt_rule_schema_migrations.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/normalization/prebuilt_rule_schema_migrations.ts deleted file mode 100644 index b5a3f90549d1cc..00000000000000 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/normalization/prebuilt_rule_schema_migrations.ts +++ /dev/null @@ -1,146 +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 type { - Prebuilt, - IsRuleImmutable, -} from '../../../../../common/api/detection_engine/model/rule_schema'; -import type { BaseRuleParams, RuleParams } from '../../rule_schema'; -import type { CreateAPIInput, PatchAPINextParams } from './rule_converters'; - -interface MigrationResponse { - immutable: IsRuleImmutable; - prebuilt?: Prebuilt; -} - -const getPrebuiltValueForRuleRead = (ruleParams: BaseRuleParams): Prebuilt | undefined => { - if (ruleParams.prebuilt) { - return ruleParams.prebuilt; - } - - if (ruleParams.immutable) { - return { - isCustomized: false, - }; - } - - return undefined; -}; - -export const normalizePrebuiltSchemaOnRuleRead = ( - ruleParams: BaseRuleParams -): MigrationResponse => { - const immutable = Boolean(ruleParams.prebuilt) || ruleParams.immutable; - const prebuilt = getPrebuiltValueForRuleRead(ruleParams); - - return { - immutable, - prebuilt, - }; -}; - -interface PrebuiltSchemaCreationMigrationProps { - input: CreateAPIInput; - isRuleToCreatePrebuilt: boolean; -} - -/** - * Used when: - * - Creating a custom rule (DETECTION_ENGINE_RULES_URL POST endpoint) - * - Bulk creating custom rules (DETECTION_ENGINE_RULES_BULK_CREATE deprecated endpoint) - * - Creating Prebuilt Rules (Installation) - * - Updating a prebuilt rule when there is a type change (deletes and recreates the rule) - * - Importing rules without overwriting an existing rule - **/ - -const getPrebuiltValueForRuleCreation = ( - input: CreateAPIInput, - isRuleToCreatePrebuilt: boolean -): Prebuilt | undefined => { - if (!isRuleToCreatePrebuilt) { - return undefined; - } - - if (input.prebuilt != null) { - return input.prebuilt; - } - - return { - isCustomized: false, - elasticUpdateDate: input.elasticUpdateDate, - }; -}; - -export const migratePrebuiltSchemaOnRuleCreation = ({ - input, - isRuleToCreatePrebuilt, -}: PrebuiltSchemaCreationMigrationProps): MigrationResponse => { - const immutable = isRuleToCreatePrebuilt; - const prebuilt = getPrebuiltValueForRuleCreation(input, isRuleToCreatePrebuilt); - - return { - immutable, - prebuilt, - }; -}; - -interface PrebuiltSchemaUpdateMigrationProps { - nextParams?: PatchAPINextParams; - existingParams: RuleParams; - isRuleCustomizedDuringUpdate: boolean; -} - -const getPrebuiltValueForRuleUpdate = ({ - nextParams, - existingParams, - isRuleCustomizedDuringUpdate, -}: PrebuiltSchemaUpdateMigrationProps): Prebuilt | undefined => { - if (nextParams?.prebuilt) { - return nextParams?.prebuilt; - } - - if (existingParams.prebuilt) { - return { - ...existingParams.prebuilt, - isCustomized: existingParams.prebuilt.isCustomized || isRuleCustomizedDuringUpdate, - }; - } - - if (existingParams.immutable) { - return { - isCustomized: isRuleCustomizedDuringUpdate, - }; - } - - return undefined; -}; - -/** - * Used when: - * - Updating a prebuilt rule with no type change - * - Importing rules and overwriting an existing rule - * - Patching rules (DETECTION_ENGINE_RULES_URL patch endpoint --> managing shared exceptions lists) - * - Bulk Patching rules (deprecated DETECTION_ENGINE_RULES_BULK_UPDATE endpoint) - * - Creating rule exceptions (CREATE_RULE_EXCEPTIONS_URL endpoint) - **/ -export const migratePrebuiltSchemaOnRuleUpdate = ({ - nextParams, - existingParams, - isRuleCustomizedDuringUpdate, -}: PrebuiltSchemaUpdateMigrationProps): MigrationResponse => { - const immutable = (Boolean(existingParams.prebuilt) || existingParams.immutable) ?? false; - const prebuilt = getPrebuiltValueForRuleUpdate({ - nextParams, - existingParams, - isRuleCustomizedDuringUpdate, - }); - - return { - immutable, - prebuilt, - }; -}; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/normalization/rule_converters.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/normalization/rule_converters.ts index ef6b8d2476efc2..64311d65fe5d1f 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/normalization/rule_converters.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/normalization/rule_converters.ts @@ -27,8 +27,6 @@ import type { RuleCreateProps, TypeSpecificCreateProps, TypeSpecificResponse, - Prebuilt, - ElasticUpdateDate, } from '../../../../../common/api/detection_engine/model/rule_schema'; import { EqlRulePatchFields, @@ -87,11 +85,6 @@ import { } from '../utils/utils'; import { createRuleExecutionSummary } from '../../rule_monitoring'; import type { PrebuiltRuleAsset } from '../../prebuilt_rules'; -import { - migratePrebuiltSchemaOnRuleCreation, - migratePrebuiltSchemaOnRuleUpdate, - normalizePrebuiltSchemaOnRuleRead, -} from './prebuilt_rule_schema_migrations'; const DEFAULT_FROM = 'now-6m' as const; const DEFAULT_TO = 'now' as const; @@ -428,18 +421,14 @@ export const patchTypeSpecificSnakeToCamel = ( } }; -export type PatchAPINextParams = PatchRuleRequestBody & { - related_integrations?: RelatedIntegrationArray; - required_fields?: RequiredFieldArray; - setup?: SetupGuide; - prebuilt?: Prebuilt; -}; - // eslint-disable-next-line complexity export const convertPatchAPIToInternalSchema = ( - nextParams: PatchAPINextParams, - existingRule: SanitizedRule, - isRuleCustomizedDuringUpdate = false + nextParams: PatchRuleRequestBody & { + related_integrations?: RelatedIntegrationArray; + required_fields?: RequiredFieldArray; + setup?: SetupGuide; + }, + existingRule: SanitizedRule ): InternalRuleUpdate => { const typeSpecificParams = patchTypeSpecificSnakeToCamel(nextParams, existingRule.params); const existingParams = existingRule.params; @@ -449,12 +438,6 @@ export const convertPatchAPIToInternalSchema = ( const throttle = nextParams.throttle ?? transformFromAlertThrottle(existingRule); const actions = transformToActionFrequency(alertActions, throttle); - const { immutable, prebuilt } = migratePrebuiltSchemaOnRuleUpdate({ - nextParams, - existingParams, - isRuleCustomizedDuringUpdate, - }); - return { name: nextParams.name ?? existingRule.name, tags: nextParams.tags ?? existingRule.tags, @@ -466,8 +449,7 @@ export const convertPatchAPIToInternalSchema = ( falsePositives: nextParams.false_positives ?? existingParams.falsePositives, investigationFields: nextParams.investigation_fields ?? existingParams.investigationFields, from: nextParams.from ?? existingParams.from, - immutable, - prebuilt, + immutable: existingParams.immutable, license: nextParams.license ?? existingParams.license, outputIndex: nextParams.output_index ?? existingParams.outputIndex, timelineId: nextParams.timeline_id ?? existingParams.timelineId, @@ -500,18 +482,14 @@ export const convertPatchAPIToInternalSchema = ( }; }; -export type CreateAPIInput = RuleCreateProps & { - related_integrations?: RelatedIntegrationArray; - required_fields?: RequiredFieldArray; - setup?: SetupGuide; - prebuilt?: Prebuilt; - elasticUpdateDate?: ElasticUpdateDate; -}; - // eslint-disable-next-line complexity export const convertCreateAPIToInternalSchema = ( - input: CreateAPIInput, - isRuleToCreatePrebuilt = false, + input: RuleCreateProps & { + related_integrations?: RelatedIntegrationArray; + required_fields?: RequiredFieldArray; + setup?: SetupGuide; + }, + immutable = false, defaultEnabled = true ): InternalRuleCreate => { const typeSpecificParams = typeSpecificSnakeToCamel(input); @@ -520,11 +498,6 @@ export const convertCreateAPIToInternalSchema = ( const alertActions = input.actions?.map((action) => transformRuleToAlertAction(action)) ?? []; const actions = transformToActionFrequency(alertActions, input.throttle); - const { immutable, prebuilt } = migratePrebuiltSchemaOnRuleCreation({ - input, - isRuleToCreatePrebuilt, - }); - return { name: input.name, tags: input.tags ?? [], @@ -539,7 +512,6 @@ export const convertCreateAPIToInternalSchema = ( investigationFields: input.investigation_fields, from: input.from ?? DEFAULT_FROM, immutable, - prebuilt, license: input.license, outputIndex: input.output_index ?? '', timelineId: input.timeline_id, @@ -685,8 +657,6 @@ export const typeSpecificCamelToSnake = ( // TODO: separate out security solution defined common params from Alerting framework common params // so we can explicitly specify the return type of this function export const commonParamsCamelToSnake = (params: BaseRuleParams) => { - const { immutable, prebuilt } = normalizePrebuiltSchemaOnRuleRead(params); - return { description: params.description, risk_score: params.riskScore, @@ -715,8 +685,7 @@ export const commonParamsCamelToSnake = (params: BaseRuleParams) => { references: params.references, version: params.version, exceptions_list: params.exceptionsList, - immutable, - prebuilt, + immutable: params.immutable, related_integrations: params.relatedIntegrations ?? [], required_fields: params.requiredFields ?? [], setup: params.setup ?? '', @@ -794,10 +763,6 @@ export const convertPrebuiltRuleAssetToRuleResponse = ( created_at: new Date(0).toISOString(), created_by: '', immutable: true, - prebuilt: { - isCustomized: false, - elasticUpdateDate: prebuiltRuleAsset.elasticUpdateDate, - }, revision: 1, }; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_schema/model/rule_schemas.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_schema/model/rule_schemas.ts index f65fef4cbe7c27..deb853335bf24a 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_schema/model/rule_schemas.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_schema/model/rule_schemas.ts @@ -29,7 +29,6 @@ import type { RuleName, RuleTagArray, } from '../../../../../common/api/detection_engine/model/rule_schema'; - import { AlertsIndex, AlertsIndexNamespace, @@ -39,7 +38,6 @@ import { InvestigationFields, InvestigationGuide, IsRuleImmutable, - RuleSource, MaxSignals, RelatedIntegrationArray, RequiredFieldArray, @@ -121,7 +119,6 @@ export const BaseRuleParams = z.object({ ruleId: RuleSignatureId, investigationFields: InvestigationFieldsCombined.optional(), immutable: IsRuleImmutable, - ruleSource: RuleSource.optional(), license: RuleLicense.optional(), outputIndex: AlertsIndex, timelineId: TimelineTemplateId.optional(), From 74d4f8d3b8b89b5823281f0174c959b6b903a529 Mon Sep 17 00:00:00 2001 From: jpdjere Date: Wed, 3 Apr 2024 13:03:36 +0200 Subject: [PATCH 59/61] Other changes reverted --- .../detection_engine/model/rule_schema/rule_schemas.gen.ts | 2 +- .../rule_management/import_rules/rule_to_import.ts | 3 +-- .../common/detection_engine/rule_management/rule_filtering.ts | 2 +- .../prebuilt_rules/logic/diff/calculate_rule_diff.ts | 3 +-- .../prebuilt_rules/model/rule_assets/prebuilt_rule_asset.ts | 4 ++-- 5 files changed, 6 insertions(+), 8 deletions(-) diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/rule_schemas.gen.ts b/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/rule_schemas.gen.ts index 6196e904626224..9d27297d11bbef 100644 --- a/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/rule_schemas.gen.ts +++ b/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/rule_schemas.gen.ts @@ -155,7 +155,7 @@ export const ResponseFields = z.object({ id: RuleObjectId, rule_id: RuleSignatureId, immutable: IsRuleImmutable, - updated_at: z.string().datetime(), + updated_at: z.string().datetime(), updated_by: z.string(), created_at: z.string().datetime(), created_by: z.string(), diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/import_rules/rule_to_import.ts b/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/import_rules/rule_to_import.ts index e11ae24d284f7a..9634d773b121dc 100644 --- a/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/import_rules/rule_to_import.ts +++ b/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/import_rules/rule_to_import.ts @@ -5,13 +5,12 @@ * 2.0. */ -import type * as z from 'zod'; +import * as z from 'zod'; import { BaseCreateProps, ResponseFields, RuleSignatureId, TypeSpecificCreateProps, - RuleVersion, } from '../../model/rule_schema'; /** diff --git a/x-pack/plugins/security_solution/common/detection_engine/rule_management/rule_filtering.ts b/x-pack/plugins/security_solution/common/detection_engine/rule_management/rule_filtering.ts index 6cb924d5ebdc8d..bfc31df88ec970 100644 --- a/x-pack/plugins/security_solution/common/detection_engine/rule_management/rule_filtering.ts +++ b/x-pack/plugins/security_solution/common/detection_engine/rule_management/rule_filtering.ts @@ -13,7 +13,7 @@ import { ENABLED_FIELD, LAST_RUN_OUTCOME_FIELD, PARAMS_IMMUTABLE_FIELD, - PARAMS_TYPE_FIELD, + PARAMS_TYPE_FIELD, RULE_NAME_FIELD, RULE_PARAMS_FIELDS, TAGS_FIELD, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/diff/calculate_rule_diff.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/diff/calculate_rule_diff.ts index 652d54dc8f6668..337a510c3b4b2e 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/diff/calculate_rule_diff.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/diff/calculate_rule_diff.ts @@ -33,7 +33,7 @@ export interface CalculateRuleDiffResult { base?: DiffableRule; target: DiffableRule; }; - }; + }; } /** @@ -95,7 +95,6 @@ export const calculateRuleDiff = (args: RuleVersions): CalculateRuleDiffResult = base: diffableBaseVersion, target: diffableTargetVersion, }, - mergedVersion: mergedVersion as RuleResponse, }, }; }; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/model/rule_assets/prebuilt_rule_asset.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/model/rule_assets/prebuilt_rule_asset.ts index 0b1ec37f053eb0..07fb5640eb482a 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/model/rule_assets/prebuilt_rule_asset.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/model/rule_assets/prebuilt_rule_asset.ts @@ -9,7 +9,7 @@ import * as z from 'zod'; import { RelatedIntegrationArray, RequiredFieldArray, - SetupGuide, + SetupGuide, RuleSignatureId, RuleVersion, BaseCreateProps, @@ -38,5 +38,5 @@ export const PrebuiltRuleAsset = BaseCreateProps.and(TypeSpecificCreateProps).an related_integrations: RelatedIntegrationArray.optional(), required_fields: RequiredFieldArray.optional(), setup: SetupGuide.optional(), - }) + }) ); From 924e393476bf0ef83254a0a09a584de7485cac09 Mon Sep 17 00:00:00 2001 From: jpdjere Date: Wed, 3 Apr 2024 13:09:13 +0200 Subject: [PATCH 60/61] Add CODEOWNERS --- .github/CODEOWNERS | 1 + .../docs/2023-12-01-14-13-07.png | Bin 191177 -> 0 bytes .../docs/2024-02-23-14-09-16.png | Bin 316654 -> 0 bytes .../prebuilt_rules_customization.md} | 4 +--- 4 files changed, 2 insertions(+), 3 deletions(-) delete mode 100644 x-pack/plugins/security_solution/docs/2023-12-01-14-13-07.png delete mode 100644 x-pack/plugins/security_solution/docs/2024-02-23-14-09-16.png rename x-pack/plugins/security_solution/docs/{prebuilt_rules_customization_rfc.md => rfcs/detection_response/prebuilt_rules_customization.md} (99%) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index dcfce13388c7aa..d3fd469c610d0a 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1396,6 +1396,7 @@ x-pack/test/security_solution_cypress/cypress/tasks/expandable_flyout @elastic/ /x-pack/plugins/security_solution/common/detection_engine/rule_management @elastic/security-detection-rule-management /x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management @elastic/security-detection-rule-management +/x-pack/plugins/security_solution/docs/rfcs/detection_response @elastic/security-detection-rule-management @elastic/security-detection-engine /x-pack/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules @elastic/security-detection-rule-management /x-pack/plugins/security_solution/docs/testing/test_plans/detection_response/rule_management @elastic/security-detection-rule-management /x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management @elastic/security-detection-rule-management diff --git a/x-pack/plugins/security_solution/docs/2023-12-01-14-13-07.png b/x-pack/plugins/security_solution/docs/2023-12-01-14-13-07.png deleted file mode 100644 index ce7f3321a0c0b2490891bcbb4463920cdbcfd961..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 191177 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

    T0FPqx09r2$3$`stw06!s6 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 h9wckyad4XN^ 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%0DB$CE3X!!WKfn@xM5~ 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 z zE5B-+nuPa9tXl%J7He!4(z2YQd%|>Uq@LG2KuSH5IOK(C1Q)s2pUqTP4$wcq3daJ?)wvbaRo&s=+L%{Z%fXH^i zc3BCIpz^PS?q)sI_SP(4ASlq`Wk8Kd&#fF^Y(7;8!fU>q>#F&dovFCYcGz;QW_|tl zvWbkn_I#>@>P{S=M@LWdoDPoKB`kvyUuwF(QA~)7p^=vxR4<7+TSiEyh$tTJAoFeE zsBRPzrQec?!0sAa1}9qB$)@t*p>0p8UOzotIbS9^t1`CR3AIoV!>DSeep+U8O?(

    nf9YAUQw99akNNKs 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

    x1xtL;{$pweS)viV7lqQ7CH@O)Tks1u{)OwBl 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

    2-OyHWc%e1;*ItdYwf03pG+-<@&J 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

    Y#E1{vp6RK#v)l!f)Ys1_=U+LRPao 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 diff --git a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md b/x-pack/plugins/security_solution/docs/rfcs/detection_response/prebuilt_rules_customization.md similarity index 99% rename from x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md rename to x-pack/plugins/security_solution/docs/rfcs/detection_response/prebuilt_rules_customization.md index cbb025badc1070..63813e184c3cb4 100644 --- a/x-pack/plugins/security_solution/docs/prebuilt_rules_customization_rfc.md +++ b/x-pack/plugins/security_solution/docs/rfcs/detection_response/prebuilt_rules_customization.md @@ -2753,9 +2753,7 @@ Making prebuilt rules customizable, plus the changes introduced to the `/upgrade However, since we still want to give the users the ability to update all of their rules that have updates with no conflicts in an easy and fast way, we need to introduce a distinct UI that allows for this behaviour. -The current UI of the **Rule Updates** page has an button with the label "Update all" which currently simply updates all rules to their `target` version: - -![](2024-02-23-14-09-16.png) +The current UI of the **Rule Updates** page has an button with the label "Update all" which currently simply updates all rules to their `target` version. We can replace this button for an **Update rules with no conflicts** button. Clicking this button would make a request to `/upgrade/_perform` with a payload that includes only rules that don't have non-solvable conflicts. That payload can be built out of the response of the `/upgrade/_review` endpoint, including ids of such rules and specifying that all rules should be updated to their `MERGED` version. From bc67346a12656dd02f2ce110b6f70ad04698590c Mon Sep 17 00:00:00 2001 From: jpdjere Date: Thu, 4 Apr 2024 10:52:55 +0200 Subject: [PATCH 61/61] Fixes --- .../prebuilt_rules_customization.md | 47 +++++++++---------- 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/x-pack/plugins/security_solution/docs/rfcs/detection_response/prebuilt_rules_customization.md b/x-pack/plugins/security_solution/docs/rfcs/detection_response/prebuilt_rules_customization.md index 63813e184c3cb4..97f7be2b8cd69a 100644 --- a/x-pack/plugins/security_solution/docs/rfcs/detection_response/prebuilt_rules_customization.md +++ b/x-pack/plugins/security_solution/docs/rfcs/detection_response/prebuilt_rules_customization.md @@ -312,7 +312,7 @@ export const RuleToImport = BaseCreateProps.and(TypeSpecificCreateProps).and( #### Internal rule schema -**The internal rule schema** needs to represent that the new `ruleSource` field may not always exist, so it must be optional. +**The internal rule schema** needs to represent that the `immutable` and the new `ruleSource` field may not always exist, so they must be optional. _Source: [x-pack/plugins/security_solution/server/lib/detection_engine/rule_schema/model/rule_schemas.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_schema/model/rule_schemas.ts)_ @@ -321,7 +321,7 @@ export type BaseRuleParams = z.infer; export const BaseRuleParams = z.object({ // [...] - immutable: IsRuleImmutable, + immutable: IsRuleImmutable.optional(), ruleSource: RuleSource.transform(camelize).optional(), // [...] }); @@ -1058,14 +1058,13 @@ The logic to importing a rule is as follows: **If a matching `rule_id` is found, but the `version` is not found**, it means there are some versions of this prebuilt rule known to Kibana, which means we should identify the rule being imported as prebuilt. The prebuilt rules package has a limit on the number of historical rule versions, and we can't assume that for a given rule_id we will always have ALL historical versions available as security-rule assets. -In this case, we will the rule's params to be: +In this case, we will set the rule's params to be: ``` { - rule_source: { + ruleSource: { type: 'external', - is_customized: false - }, - immutable: true + isCustomized: false + } } ``` @@ -1168,7 +1167,7 @@ Given the requirements described above, the following table shows the behaviour

     {
       name: "My edited rule",
    -  rule_source: {
    +  ruleSource: {
         type: "internal"
       }
     } 
    @@ -1199,9 +1198,9 @@ Given the requirements described above, the following table shows the behaviour
         
     {
       name: "My prebuilt rule",
    -  rule_source: {
    +  ruleSource: {
         type: "external",
    -    is_customized: false,
    +    isCustomized: false,
       }
     } 
     
    @@ -1231,9 +1230,9 @@ Given the requirements described above, the following table shows the behaviour
     {
       name: "My prebuilt rule",
    -  rule_source: {
    +  ruleSource: {
         type: "external",
    -    is_customized: false,
    +    isCustomized: false,
       }
     } 
     
    @@ -1263,9 +1262,9 @@ Given the requirements described above, the following table shows the behaviour
     {
       name: "My custom prebuilt rule",
    -  rule_source: {
    +  ruleSource: {
         type: "external",
    -    is_customized: true,
    +    isCustomized: true,
       }
     } 
     
    @@ -1276,9 +1275,9 @@ Given the requirements described above, the following table shows the behaviour
     {
       name: "My prebuilt rule",
    -  rule_source: {
    +  ruleSource: {
         type: "external",
    -    is_customized: false,
    +    isCustomized: false,
       }
     } 
     
    @@ -1308,9 +1307,9 @@ Given the requirements described above, the following table shows the behaviour
     {
       name: "My prebuilt rule",
    -  rule_source: {
    +  ruleSource: {
         type: "external",
    -    is_customized: false,
    +    isCustomized: false,
       }
     } 
     
    @@ -1335,9 +1334,9 @@ Given the requirements described above, the following table shows the behaviour
     {
       name: "My custom prebuilt rule",
    -  rule_source: {
    +  ruleSource: {
         type: "external",
    -    is_customized: true,
    +    isCustomized: true,
       }
     } 
     
    @@ -1348,9 +1347,9 @@ Given the requirements described above, the following table shows the behaviour
     {
       name: "My custom prebuilt rule",
    -  rule_source: {
    +  ruleSource: {
         type: "external",
    -    is_customized: true,
    +    isCustomized: true,
       }
     } 
     
    @@ -1375,9 +1374,9 @@ Given the requirements described above, the following table shows the behaviour
     {
       name: "My prebuilt rule",
    -  rule_source: {
    +  ruleSource: {
         type: "external",
    -    is_customized: false,
    +    isCustomized: false,
       }
     }