mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
[Security Solution] Replace PrebuiltRuleAsset schema construction with Zod transform (#188092)
## Summary Pending work from: https://github.com/elastic/kibana/pull/186615 - The previous implementation to create `PrebuiltRuleAsset` with some RuleResponse fields ommited from it had the disadvantage of being built with a discriminated union where all rule types had to be re-listed. If a new type was added, then it would have required manually adding the type to that union as well, which would have been surely forgotten. - This replaces that schema construction to use a Zod transform which simply eliminates the omitted fields using a Zod transform. ### For maintainers - [ ] This was checked for breaking API changes and was [labeled appropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)
This commit is contained in:
parent
a120c510b9
commit
ccfdd69223
2 changed files with 39 additions and 34 deletions
|
@ -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<PrebuiltRuleAsset> & Record<string, unknown> = {
|
||||
...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<PrebuiltRuleAsset> & Record<string, unknown> = {
|
||||
...getPrebuiltRuleMock(),
|
||||
[field]: 'some value',
|
||||
response_actions: [{ action_type_id: `.osquery`, params: {} }],
|
||||
};
|
||||
|
||||
const result = PrebuiltRuleAsset.safeParse(payload);
|
||||
|
|
|
@ -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<BaseCreateProps>(
|
|||
'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<T>() {
|
||||
return function <U extends keyof T>(props: U[]): Record<U, true> {
|
||||
|
@ -85,7 +76,7 @@ function zodMaskFor<T>() {
|
|||
*/
|
||||
export type PrebuiltRuleAsset = z.infer<typeof PrebuiltRuleAsset>;
|
||||
export const PrebuiltRuleAsset = BaseCreateProps.omit(BASE_PROPS_REMOVED_FROM_PREBUILT_RULE_ASSET)
|
||||
.and(RuleAssetTypeSpecificCreateProps)
|
||||
.and(TypeSpecificFields)
|
||||
.and(
|
||||
z.object({
|
||||
rule_id: RuleSignatureId,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue