diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/model/rule_assets/prebuilt_rule_asset.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/model/rule_assets/prebuilt_rule_asset.test.ts index e4d9255dc2b95..9190bb873e81b 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/model/rule_assets/prebuilt_rule_asset.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/model/rule_assets/prebuilt_rule_asset.test.ts @@ -36,7 +36,7 @@ describe('Prebuilt rule asset schema', () => { // The PrebuiltRuleAsset schema is built out of the rule schema, // but the following fields are manually omitted. // See: detection_engine/prebuilt_rules/model/rule_assets/prebuilt_rule_asset.ts - const omittedFields = [ + const omittedBaseFields = [ 'actions', 'throttle', 'meta', @@ -47,10 +47,24 @@ describe('Prebuilt rule asset schema', () => { 'outcome', ]; - test.each(omittedFields)('ignores %s since it`s an omitted field', (field) => { + test.each(omittedBaseFields)( + 'ignores the base %s field since it`s an omitted field', + (field) => { + const payload: Partial & Record = { + ...getPrebuiltRuleMock(), + [field]: 'some value', + }; + + const result = PrebuiltRuleAsset.safeParse(payload); + expectParseSuccess(result); + expect(result.data).toEqual(getPrebuiltRuleMock()); + } + ); + + test('ignores the type specific response_actions field since it`s an omitted field', () => { const payload: Partial & Record = { ...getPrebuiltRuleMock(), - [field]: 'some value', + response_actions: [{ action_type_id: `.osquery`, params: {} }], }; const result = PrebuiltRuleAsset.safeParse(payload); 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 056a3998e3b3e..c41d24660462e 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 @@ -10,14 +10,7 @@ import { RuleSignatureId, RuleVersion, BaseCreateProps, - EqlRuleCreateFields, - EsqlRuleCreateFields, - MachineLearningRuleCreateFields, - NewTermsRuleCreateFields, - QueryRuleCreateFields, - SavedQueryRuleCreateFields, - ThreatMatchRuleCreateFields, - ThresholdRuleCreateFields, + TypeSpecificCreateProps, } from '../../../../../../common/api/detection_engine/model/rule_schema'; /** @@ -37,28 +30,26 @@ const BASE_PROPS_REMOVED_FROM_PREBUILT_RULE_ASSET = zodMaskFor( 'outcome', ]); -// `response_actions` is only part of the optional fields in QueryRuleCreateFields and SavedQueryRuleCreateFields -const TYPE_SPECIFIC_PROPS_REMOVED_FROM_PREBUILT_RULE_ASSET = zodMaskFor< - QueryRuleCreateFields | SavedQueryRuleCreateFields ->()(['response_actions']); - -const QueryRuleAssetFields = QueryRuleCreateFields.omit( - TYPE_SPECIFIC_PROPS_REMOVED_FROM_PREBUILT_RULE_ASSET -); -const SavedQueryRuleAssetFields = SavedQueryRuleCreateFields.omit( - TYPE_SPECIFIC_PROPS_REMOVED_FROM_PREBUILT_RULE_ASSET -); - -export const RuleAssetTypeSpecificCreateProps = z.discriminatedUnion('type', [ - EqlRuleCreateFields, - QueryRuleAssetFields, - SavedQueryRuleAssetFields, - ThresholdRuleCreateFields, - ThreatMatchRuleCreateFields, - MachineLearningRuleCreateFields, - NewTermsRuleCreateFields, - EsqlRuleCreateFields, -]); +/** + * Aditionally remove fields which are part only of the optional fields in the rule types that make up + * the TypeSpecificCreateProps discriminatedUnion, by using a Zod transformation which extracts out the + * necessary fields in the rules types where they exist. Fields to extract: + * - response_actions: from Query and SavedQuery rules + */ +const TypeSpecificFields = TypeSpecificCreateProps.transform((val) => { + switch (val.type) { + case 'query': { + const { response_actions: _, ...rest } = val; + return rest; + } + case 'saved_query': { + const { response_actions: _, ...rest } = val; + return rest; + } + default: + return val; + } +}); function zodMaskFor() { return function (props: U[]): Record { @@ -85,7 +76,7 @@ function zodMaskFor() { */ export type PrebuiltRuleAsset = z.infer; export const PrebuiltRuleAsset = BaseCreateProps.omit(BASE_PROPS_REMOVED_FROM_PREBUILT_RULE_ASSET) - .and(RuleAssetTypeSpecificCreateProps) + .and(TypeSpecificFields) .and( z.object({ rule_id: RuleSignatureId,