mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
[Security Solution] Swap rule unions out for discriminated unions to improve validation error messages (#171452)
**Epics:** https://github.com/elastic/security-team/issues/8058, https://github.com/elastic/security-team/issues/6726 (internal) **Partially addresses:** https://github.com/elastic/security-team/issues/7991 (internal) ## Summary The main benefit of this PR is shown in `rule_request_schema.test.ts`, where the error messages are now more accurate and concise. With regular unions, `zod` has to try validating the input against all schemas in the union and reports the errors from every schema in the union. Switching to discriminated unions, with `type` as the discriminator, allows `zod` to pick the right rule type schema from the union and only validate against that rule type. This means the error message reports that either the discriminator is invalid, in any case where `type` is not valid, or if `type` is valid but another field is wrong for that type of rule then the error message is the validation result from only that rule type. To make it possible to use discriminated unions, we need to switch from using zod's `.and()` for intersections to `.merge()` because `.and()` returns an intersection type that is incompatible with discriminated unions in zod. Similarly, we need to remove the usage of `.transform()` because it returns a ZodEffect that is incompatible with `.merge()`. Instead of using `.transform()` to turn properties from optional to possibly undefined, we can use `requiredOptional` explicitly in specific places to convert the types. Similarly, the `RequiredOptional` type can be used on the return type of conversion functions between API and internal schemas to enforce that all properties are explicitly specified in the conversion. Future work: - better alignment of codegen with OpenAPI definitions of anyOf/oneOf. https://swagger.io/docs/specification/data-models/oneof-anyof-allof-not/#oneof oneOf requires that the input match exactly one schema from the list, which is different from z.union. anyOf should be z.union, oneOf should be z.discriminatedUnion - flatten the schema structure further to avoid `Type instantiation is excessively deep and possibly infinite`. Seems to be a common issue with zod (https://github.com/microsoft/TypeScript/issues/34933) Limiting the number of `.merge` and other zod operations needed to build a particular schema object seems to help resolve the error. Combining `ResponseRequiredFields` and `ResponseOptionalFields` into a single object rather than merging them solved the immediate problem. However, we may still be near the depth limit. Changing `RuleResponse` as seen below also solved the problem in testing, and may give us more headroom for future changes if we apply techniques like this here and in other places. The difference here is that `SharedResponseProps` is only intersected with the type specific schemas after they're combined in a discriminated union, whereas in `main` we merge `SharedResponseProps` with each individual schema then merge them all together. - combine other Required and Optional schemas, like QueryRuleRequiredFields and QueryRuleOptionalFields ```ts export type RuleResponse = z.infer<typeof RuleResponse>; export const RuleResponse = SharedResponseProps.and(z.discriminatedUnion('type', [ EqlRuleResponseFields, QueryRuleResponseFields, SavedQueryRuleResponseFields, ThresholdRuleResponseFields, ThreatMatchRuleResponseFields, MachineLearningRuleResponseFields, NewTermsRuleResponseFields, EsqlRuleResponseFields, ])); ``` --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
12a8e8b918
commit
6073eb6dcd
35 changed files with 272 additions and 333 deletions
|
@ -12,7 +12,6 @@
|
|||
{{~#if (defined default)}}.default({{{toJSON default}}}){{/if~}}
|
||||
{{~#if (eq x-modify "partial")}}.partial(){{/if~}}
|
||||
{{~#if (eq x-modify "required")}}.required(){{/if~}}
|
||||
{{~#if (eq x-modify "requiredOptional")}}.transform(requiredOptional){{/if~}}
|
||||
{{~/if~}}
|
||||
|
||||
{{~#if allOf~}}
|
||||
|
@ -20,26 +19,34 @@
|
|||
{{~#if @first~}}
|
||||
{{> zod_schema_item }}
|
||||
{{~else~}}
|
||||
.and({{> zod_schema_item }})
|
||||
.merge({{> zod_schema_item }})
|
||||
{{~/if~}}
|
||||
{{~/each~}}
|
||||
{{~/if~}}
|
||||
|
||||
{{~#if anyOf~}}
|
||||
z.union([
|
||||
{{~#each anyOf~}}
|
||||
{{#if discriminator}}
|
||||
z.discriminatedUnion('{{discriminator.propertyName}}', [
|
||||
{{else}}
|
||||
z.union([
|
||||
{{/if}}
|
||||
{{~#each anyOf~}}
|
||||
{{~> zod_schema_item ~}},
|
||||
{{~/each~}}
|
||||
{{~/each~}}
|
||||
])
|
||||
{{~#if nullable}}.nullable(){{/if~}}
|
||||
{{~#if (eq requiredBool false)}}.optional(){{/if~}}
|
||||
{{~/if~}}
|
||||
|
||||
{{~#if oneOf~}}
|
||||
z.union([
|
||||
{{~#each oneOf~}}
|
||||
{{#if discriminator}}
|
||||
z.discriminatedUnion('{{discriminator.propertyName}}', [
|
||||
{{else}}
|
||||
z.union([
|
||||
{{/if}}
|
||||
{{~#each oneOf~}}
|
||||
{{~> zod_schema_item ~}},
|
||||
{{~/each~}}
|
||||
{{~/each~}}
|
||||
])
|
||||
{{~#if nullable}}.nullable(){{/if~}}
|
||||
{{~#if (eq requiredBool false)}}.optional(){{/if~}}
|
||||
|
@ -97,7 +104,6 @@ z.unknown()
|
|||
{{~/if~}}
|
||||
{{~#if (eq x-modify "partial")}}.partial(){{/if~}}
|
||||
{{~#if (eq x-modify "required")}}.required(){{/if~}}
|
||||
{{~#if (eq x-modify "requiredOptional")}}.transform(requiredOptional){{/if~}}
|
||||
{{~/inline~}}
|
||||
|
||||
{{~#*inline "type_string"~}}
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
*/
|
||||
|
||||
import { z } from 'zod';
|
||||
import { requiredOptional } from '@kbn/zod-helpers';
|
||||
|
||||
/*
|
||||
* NOTICE: Do not edit this file manually.
|
||||
|
@ -27,48 +26,42 @@ export const EcsMapping = z.object({}).catchall(
|
|||
);
|
||||
|
||||
export type OsqueryQuery = z.infer<typeof OsqueryQuery>;
|
||||
export const OsqueryQuery = z
|
||||
.object({
|
||||
/**
|
||||
* Query ID
|
||||
*/
|
||||
id: z.string(),
|
||||
/**
|
||||
* Query to execute
|
||||
*/
|
||||
query: z.string(),
|
||||
ecs_mapping: EcsMapping.optional(),
|
||||
/**
|
||||
* Query version
|
||||
*/
|
||||
version: z.string().optional(),
|
||||
platform: z.string().optional(),
|
||||
removed: z.boolean().optional(),
|
||||
snapshot: z.boolean().optional(),
|
||||
})
|
||||
.transform(requiredOptional);
|
||||
export const OsqueryQuery = z.object({
|
||||
/**
|
||||
* Query ID
|
||||
*/
|
||||
id: z.string(),
|
||||
/**
|
||||
* Query to execute
|
||||
*/
|
||||
query: z.string(),
|
||||
ecs_mapping: EcsMapping.optional(),
|
||||
/**
|
||||
* Query version
|
||||
*/
|
||||
version: z.string().optional(),
|
||||
platform: z.string().optional(),
|
||||
removed: z.boolean().optional(),
|
||||
snapshot: z.boolean().optional(),
|
||||
});
|
||||
|
||||
export type OsqueryParams = z.infer<typeof OsqueryParams>;
|
||||
export const OsqueryParams = z
|
||||
.object({
|
||||
query: z.string().optional(),
|
||||
ecs_mapping: EcsMapping.optional(),
|
||||
queries: z.array(OsqueryQuery).optional(),
|
||||
pack_id: z.string().optional(),
|
||||
saved_query_id: z.string().optional(),
|
||||
})
|
||||
.transform(requiredOptional);
|
||||
export const OsqueryParams = z.object({
|
||||
query: z.string().optional(),
|
||||
ecs_mapping: EcsMapping.optional(),
|
||||
queries: z.array(OsqueryQuery).optional(),
|
||||
pack_id: z.string().optional(),
|
||||
saved_query_id: z.string().optional(),
|
||||
});
|
||||
|
||||
export type OsqueryParamsCamelCase = z.infer<typeof OsqueryParamsCamelCase>;
|
||||
export const OsqueryParamsCamelCase = z
|
||||
.object({
|
||||
query: z.string().optional(),
|
||||
ecsMapping: EcsMapping.optional(),
|
||||
queries: z.array(OsqueryQuery).optional(),
|
||||
packId: z.string().optional(),
|
||||
savedQueryId: z.string().optional(),
|
||||
})
|
||||
.transform(requiredOptional);
|
||||
export const OsqueryParamsCamelCase = z.object({
|
||||
query: z.string().optional(),
|
||||
ecsMapping: EcsMapping.optional(),
|
||||
queries: z.array(OsqueryQuery).optional(),
|
||||
packId: z.string().optional(),
|
||||
savedQueryId: z.string().optional(),
|
||||
});
|
||||
|
||||
export type OsqueryResponseAction = z.infer<typeof OsqueryResponseAction>;
|
||||
export const OsqueryResponseAction = z.object({
|
||||
|
@ -83,12 +76,10 @@ export const RuleResponseOsqueryAction = z.object({
|
|||
});
|
||||
|
||||
export type EndpointParams = z.infer<typeof EndpointParams>;
|
||||
export const EndpointParams = z
|
||||
.object({
|
||||
command: z.literal('isolate'),
|
||||
comment: z.string().optional(),
|
||||
})
|
||||
.transform(requiredOptional);
|
||||
export const EndpointParams = z.object({
|
||||
command: z.literal('isolate'),
|
||||
comment: z.string().optional(),
|
||||
});
|
||||
|
||||
export type EndpointResponseAction = z.infer<typeof EndpointResponseAction>;
|
||||
export const EndpointResponseAction = z.object({
|
||||
|
|
|
@ -49,7 +49,6 @@ components:
|
|||
required:
|
||||
- id
|
||||
- query
|
||||
x-modify: requiredOptional
|
||||
|
||||
OsqueryParams:
|
||||
type: object
|
||||
|
@ -66,7 +65,6 @@ components:
|
|||
type: string
|
||||
saved_query_id:
|
||||
type: string
|
||||
x-modify: requiredOptional
|
||||
|
||||
OsqueryParamsCamelCase:
|
||||
type: object
|
||||
|
@ -83,7 +81,6 @@ components:
|
|||
type: string
|
||||
savedQueryId:
|
||||
type: string
|
||||
x-modify: requiredOptional
|
||||
|
||||
OsqueryResponseAction:
|
||||
type: object
|
||||
|
@ -123,7 +120,6 @@ components:
|
|||
type: string
|
||||
required:
|
||||
- command
|
||||
x-modify: requiredOptional
|
||||
|
||||
EndpointResponseAction:
|
||||
type: object
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
|
||||
import { z } from 'zod';
|
||||
import { requiredOptional, isValidDateMath } from '@kbn/zod-helpers';
|
||||
import { isValidDateMath } from '@kbn/zod-helpers';
|
||||
|
||||
/*
|
||||
* NOTICE: Do not edit this file manually.
|
||||
|
@ -94,14 +94,12 @@ export const RiskScore = z.number().int().min(0).max(100);
|
|||
*/
|
||||
export type RiskScoreMapping = z.infer<typeof RiskScoreMapping>;
|
||||
export const RiskScoreMapping = z.array(
|
||||
z
|
||||
.object({
|
||||
field: z.string(),
|
||||
operator: z.literal('equals'),
|
||||
value: z.string(),
|
||||
risk_score: RiskScore.optional(),
|
||||
})
|
||||
.transform(requiredOptional)
|
||||
z.object({
|
||||
field: z.string(),
|
||||
operator: z.literal('equals'),
|
||||
value: z.string(),
|
||||
risk_score: RiskScore.optional(),
|
||||
})
|
||||
);
|
||||
|
||||
/**
|
||||
|
|
|
@ -95,7 +95,6 @@ components:
|
|||
- field
|
||||
- operator
|
||||
- value
|
||||
x-modify: requiredOptional
|
||||
description: Overrides generated alerts' risk_score with a value from the source event
|
||||
|
||||
Severity:
|
||||
|
|
|
@ -25,8 +25,8 @@ describe('rules schema', () => {
|
|||
|
||||
const result = RuleCreateProps.safeParse(payload);
|
||||
expectParseError(result);
|
||||
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
|
||||
`"name: Required, description: Required, risk_score: Required, severity: Required, type: Invalid literal value, expected \\"eql\\", and 52 more"`
|
||||
expect(stringifyZodError(result.error)).toEqual(
|
||||
"type: Invalid discriminator value. Expected 'eql' | 'query' | 'saved_query' | 'threshold' | 'threat_match' | 'machine_learning' | 'new_terms' | 'esql'"
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -48,8 +48,8 @@ describe('rules schema', () => {
|
|||
|
||||
const result = RuleCreateProps.safeParse(payload);
|
||||
expectParseError(result);
|
||||
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
|
||||
`"name: Required, description: Required, risk_score: Required, severity: Required, type: Invalid literal value, expected \\"eql\\", and 52 more"`
|
||||
expect(stringifyZodError(result.error)).toEqual(
|
||||
"type: Invalid discriminator value. Expected 'eql' | 'query' | 'saved_query' | 'threshold' | 'threat_match' | 'machine_learning' | 'new_terms' | 'esql'"
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -61,8 +61,8 @@ describe('rules schema', () => {
|
|||
|
||||
const result = RuleCreateProps.safeParse(payload);
|
||||
expectParseError(result);
|
||||
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
|
||||
`"name: Required, risk_score: Required, severity: Required, type: Invalid literal value, expected \\"eql\\", query: Required, and 44 more"`
|
||||
expect(stringifyZodError(result.error)).toEqual(
|
||||
"type: Invalid discriminator value. Expected 'eql' | 'query' | 'saved_query' | 'threshold' | 'threat_match' | 'machine_learning' | 'new_terms' | 'esql'"
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -75,8 +75,8 @@ describe('rules schema', () => {
|
|||
|
||||
const result = RuleCreateProps.safeParse(payload);
|
||||
expectParseError(result);
|
||||
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
|
||||
`"name: Required, risk_score: Required, severity: Required, type: Invalid literal value, expected \\"eql\\", query: Required, and 44 more"`
|
||||
expect(stringifyZodError(result.error)).toEqual(
|
||||
"type: Invalid discriminator value. Expected 'eql' | 'query' | 'saved_query' | 'threshold' | 'threat_match' | 'machine_learning' | 'new_terms' | 'esql'"
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -90,8 +90,8 @@ describe('rules schema', () => {
|
|||
|
||||
const result = RuleCreateProps.safeParse(payload);
|
||||
expectParseError(result);
|
||||
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
|
||||
`"name: Required, risk_score: Required, severity: Required, type: Invalid literal value, expected \\"eql\\", query: Required, and 44 more"`
|
||||
expect(stringifyZodError(result.error)).toEqual(
|
||||
"type: Invalid discriminator value. Expected 'eql' | 'query' | 'saved_query' | 'threshold' | 'threat_match' | 'machine_learning' | 'new_terms' | 'esql'"
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -106,8 +106,8 @@ describe('rules schema', () => {
|
|||
|
||||
const result = RuleCreateProps.safeParse(payload);
|
||||
expectParseError(result);
|
||||
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
|
||||
`"risk_score: Required, severity: Required, type: Invalid literal value, expected \\"eql\\", query: Required, language: Invalid literal value, expected \\"eql\\", and 36 more"`
|
||||
expect(stringifyZodError(result.error)).toEqual(
|
||||
"type: Invalid discriminator value. Expected 'eql' | 'query' | 'saved_query' | 'threshold' | 'threat_match' | 'machine_learning' | 'new_terms' | 'esql'"
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -123,8 +123,8 @@ describe('rules schema', () => {
|
|||
|
||||
const result = RuleCreateProps.safeParse(payload);
|
||||
expectParseError(result);
|
||||
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
|
||||
`"risk_score: Required, type: Invalid literal value, expected \\"eql\\", query: Required, language: Invalid literal value, expected \\"eql\\", risk_score: Required, and 28 more"`
|
||||
expect(stringifyZodError(result.error)).toEqual(
|
||||
"type: Invalid discriminator value. Expected 'eql' | 'query' | 'saved_query' | 'threshold' | 'threat_match' | 'machine_learning' | 'new_terms' | 'esql'"
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -141,9 +141,7 @@ describe('rules schema', () => {
|
|||
|
||||
const result = RuleCreateProps.safeParse(payload);
|
||||
expectParseError(result);
|
||||
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
|
||||
`"risk_score: Required, type: Invalid literal value, expected \\"eql\\", query: Required, language: Invalid literal value, expected \\"eql\\", risk_score: Required, and 27 more"`
|
||||
);
|
||||
expect(stringifyZodError(result.error)).toEqual('risk_score: Required');
|
||||
});
|
||||
|
||||
test('[rule_id, description, from, to, name, severity, type, interval] does not validate', () => {
|
||||
|
@ -160,9 +158,7 @@ describe('rules schema', () => {
|
|||
|
||||
const result = RuleCreateProps.safeParse(payload);
|
||||
expectParseError(result);
|
||||
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
|
||||
`"risk_score: Required, type: Invalid literal value, expected \\"eql\\", query: Required, language: Invalid literal value, expected \\"eql\\", risk_score: Required, and 27 more"`
|
||||
);
|
||||
expect(stringifyZodError(result.error)).toEqual('risk_score: Required');
|
||||
});
|
||||
|
||||
test('[rule_id, description, from, to, name, severity, type, interval, index] does not validate', () => {
|
||||
|
@ -180,9 +176,7 @@ describe('rules schema', () => {
|
|||
|
||||
const result = RuleCreateProps.safeParse(payload);
|
||||
expectParseError(result);
|
||||
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
|
||||
`"risk_score: Required, type: Invalid literal value, expected \\"eql\\", query: Required, language: Invalid literal value, expected \\"eql\\", risk_score: Required, and 27 more"`
|
||||
);
|
||||
expect(stringifyZodError(result.error)).toEqual('risk_score: Required');
|
||||
});
|
||||
|
||||
test('[rule_id, description, from, to, name, severity, type, query, index, interval] does validate', () => {
|
||||
|
@ -222,9 +216,7 @@ describe('rules schema', () => {
|
|||
|
||||
const result = RuleCreateProps.safeParse(payload);
|
||||
expectParseError(result);
|
||||
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
|
||||
`"risk_score: Required, type: Invalid literal value, expected \\"eql\\", language: Invalid literal value, expected \\"eql\\", risk_score: Required, risk_score: Required, and 22 more"`
|
||||
);
|
||||
expect(stringifyZodError(result.error)).toEqual('risk_score: Required');
|
||||
});
|
||||
|
||||
test('[rule_id, description, from, to, index, name, severity, interval, type, query, language, risk_score] does validate', () => {
|
||||
|
@ -390,8 +382,8 @@ describe('rules schema', () => {
|
|||
|
||||
const result = RuleCreateProps.safeParse(payload);
|
||||
expectParseError(result);
|
||||
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
|
||||
`"references.0: Expected string, received number, type: Invalid literal value, expected \\"eql\\", language: Invalid literal value, expected \\"eql\\", references.0: Expected string, received number, references.0: Expected string, received number, and 22 more"`
|
||||
expect(stringifyZodError(result.error)).toEqual(
|
||||
'references.0: Expected string, received number'
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -403,9 +395,7 @@ describe('rules schema', () => {
|
|||
|
||||
const result = RuleCreateProps.safeParse(payload);
|
||||
expectParseError(result);
|
||||
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
|
||||
`"type: Invalid literal value, expected \\"eql\\", language: Invalid literal value, expected \\"eql\\", index.0: Expected string, received number, index.0: Expected string, received number, type: Invalid literal value, expected \\"saved_query\\", and 20 more"`
|
||||
);
|
||||
expect(stringifyZodError(result.error)).toEqual('index.0: Expected string, received number');
|
||||
});
|
||||
|
||||
test('saved_query type can have filters with it', () => {
|
||||
|
@ -427,9 +417,7 @@ describe('rules schema', () => {
|
|||
|
||||
const result = RuleCreateProps.safeParse(payload);
|
||||
expectParseError(result);
|
||||
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
|
||||
`"type: Invalid literal value, expected \\"eql\\", language: Invalid literal value, expected \\"eql\\", filters: Expected array, received string, filters: Expected array, received string, type: Invalid literal value, expected \\"saved_query\\", and 20 more"`
|
||||
);
|
||||
expect(stringifyZodError(result.error)).toEqual('filters: Expected array, received string');
|
||||
});
|
||||
|
||||
test('language validates with kuery', () => {
|
||||
|
@ -462,8 +450,8 @@ describe('rules schema', () => {
|
|||
|
||||
const result = RuleCreateProps.safeParse(payload);
|
||||
expectParseError(result);
|
||||
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
|
||||
`"type: Invalid literal value, expected \\"eql\\", language: Invalid literal value, expected \\"eql\\", language: Invalid enum value. Expected 'kuery' | 'lucene', received 'something-made-up', type: Invalid literal value, expected \\"saved_query\\", saved_id: Required, and 19 more"`
|
||||
expect(stringifyZodError(result.error)).toEqual(
|
||||
"language: Invalid enum value. Expected 'kuery' | 'lucene', received 'something-made-up'"
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -523,8 +511,8 @@ describe('rules schema', () => {
|
|||
|
||||
const result = RuleCreateProps.safeParse(payload);
|
||||
expectParseError(result);
|
||||
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
|
||||
`"tags.0: Expected string, received number, tags.1: Expected string, received number, tags.2: Expected string, received number, type: Invalid literal value, expected \\"eql\\", language: Invalid literal value, expected \\"eql\\", and 38 more"`
|
||||
expect(stringifyZodError(result.error)).toEqual(
|
||||
'tags.0: Expected string, received number, tags.1: Expected string, received number, tags.2: Expected string, received number'
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -551,9 +539,7 @@ describe('rules schema', () => {
|
|||
|
||||
const result = RuleCreateProps.safeParse(payload);
|
||||
expectParseError(result);
|
||||
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
|
||||
`"threat.0.framework: Required, type: Invalid literal value, expected \\"eql\\", language: Invalid literal value, expected \\"eql\\", threat.0.framework: Required, threat.0.framework: Required, and 22 more"`
|
||||
);
|
||||
expect(stringifyZodError(result.error)).toEqual('threat.0.framework: Required');
|
||||
});
|
||||
|
||||
test('You cannot send in an array of threat that are missing "tactic"', () => {
|
||||
|
@ -575,9 +561,7 @@ describe('rules schema', () => {
|
|||
|
||||
const result = RuleCreateProps.safeParse(payload);
|
||||
expectParseError(result);
|
||||
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
|
||||
`"threat.0.tactic: Required, type: Invalid literal value, expected \\"eql\\", language: Invalid literal value, expected \\"eql\\", threat.0.tactic: Required, threat.0.tactic: Required, and 22 more"`
|
||||
);
|
||||
expect(stringifyZodError(result.error)).toEqual('threat.0.tactic: Required');
|
||||
});
|
||||
|
||||
test('You can send in an array of threat that are missing "technique"', () => {
|
||||
|
@ -619,8 +603,8 @@ describe('rules schema', () => {
|
|||
|
||||
const result = RuleCreateProps.safeParse(payload);
|
||||
expectParseError(result);
|
||||
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
|
||||
`"false_positives.0: Expected string, received number, false_positives.1: Expected string, received number, type: Invalid literal value, expected \\"eql\\", language: Invalid literal value, expected \\"eql\\", false_positives.0: Expected string, received number, and 30 more"`
|
||||
expect(stringifyZodError(result.error)).toEqual(
|
||||
'false_positives.0: Expected string, received number, false_positives.1: Expected string, received number'
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -693,9 +677,7 @@ describe('rules schema', () => {
|
|||
|
||||
const result = RuleCreateProps.safeParse(payload);
|
||||
expectParseError(result);
|
||||
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
|
||||
`"meta: Expected object, received string, type: Invalid literal value, expected \\"eql\\", language: Invalid literal value, expected \\"eql\\", meta: Expected object, received string, meta: Expected object, received string, and 22 more"`
|
||||
);
|
||||
expect(stringifyZodError(result.error)).toEqual('meta: Expected object, received string');
|
||||
});
|
||||
|
||||
test('You can omit the query string when filters are present', () => {
|
||||
|
@ -730,8 +712,8 @@ describe('rules schema', () => {
|
|||
|
||||
const result = RuleCreateProps.safeParse(payload);
|
||||
expectParseError(result);
|
||||
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
|
||||
`"severity: Invalid enum value. Expected 'low' | 'medium' | 'high' | 'critical', received 'junk', type: Invalid literal value, expected \\"eql\\", language: Invalid literal value, expected \\"eql\\", severity: Invalid enum value. Expected 'low' | 'medium' | 'high' | 'critical', received 'junk', severity: Invalid enum value. Expected 'low' | 'medium' | 'high' | 'critical', received 'junk', and 22 more"`
|
||||
expect(stringifyZodError(result.error)).toEqual(
|
||||
"severity: Invalid enum value. Expected 'low' | 'medium' | 'high' | 'critical', received 'junk'"
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -743,9 +725,7 @@ describe('rules schema', () => {
|
|||
|
||||
const result = RuleCreateProps.safeParse(payload);
|
||||
expectParseError(result);
|
||||
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
|
||||
`"actions.0.group: Required, type: Invalid literal value, expected \\"eql\\", language: Invalid literal value, expected \\"eql\\", actions.0.group: Required, actions.0.group: Required, and 22 more"`
|
||||
);
|
||||
expect(stringifyZodError(result.error)).toEqual('actions.0.group: Required');
|
||||
});
|
||||
|
||||
test('You cannot send in an array of actions that are missing "id"', () => {
|
||||
|
@ -756,9 +736,7 @@ describe('rules schema', () => {
|
|||
|
||||
const result = RuleCreateProps.safeParse(payload);
|
||||
expectParseError(result);
|
||||
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
|
||||
`"actions.0.id: Required, type: Invalid literal value, expected \\"eql\\", language: Invalid literal value, expected \\"eql\\", actions.0.id: Required, actions.0.id: Required, and 22 more"`
|
||||
);
|
||||
expect(stringifyZodError(result.error)).toEqual('actions.0.id: Required');
|
||||
});
|
||||
|
||||
test('You cannot send in an array of actions that are missing "action_type_id"', () => {
|
||||
|
@ -769,9 +747,7 @@ describe('rules schema', () => {
|
|||
|
||||
const result = RuleCreateProps.safeParse(payload);
|
||||
expectParseError(result);
|
||||
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
|
||||
`"actions.0.action_type_id: Required, type: Invalid literal value, expected \\"eql\\", language: Invalid literal value, expected \\"eql\\", actions.0.action_type_id: Required, actions.0.action_type_id: Required, and 22 more"`
|
||||
);
|
||||
expect(stringifyZodError(result.error)).toEqual('actions.0.action_type_id: Required');
|
||||
});
|
||||
|
||||
test('You cannot send in an array of actions that are missing "params"', () => {
|
||||
|
@ -782,9 +758,7 @@ describe('rules schema', () => {
|
|||
|
||||
const result = RuleCreateProps.safeParse(payload);
|
||||
expectParseError(result);
|
||||
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
|
||||
`"actions.0.params: Required, type: Invalid literal value, expected \\"eql\\", language: Invalid literal value, expected \\"eql\\", actions.0.params: Required, actions.0.params: Required, and 22 more"`
|
||||
);
|
||||
expect(stringifyZodError(result.error)).toEqual('actions.0.params: Required');
|
||||
});
|
||||
|
||||
test('You cannot send in an array of actions that are including "actionTypeId"', () => {
|
||||
|
@ -802,9 +776,7 @@ describe('rules schema', () => {
|
|||
|
||||
const result = RuleCreateProps.safeParse(payload);
|
||||
expectParseError(result);
|
||||
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
|
||||
`"actions.0.action_type_id: Required, type: Invalid literal value, expected \\"eql\\", language: Invalid literal value, expected \\"eql\\", actions.0.action_type_id: Required, actions.0.action_type_id: Required, and 22 more"`
|
||||
);
|
||||
expect(stringifyZodError(result.error)).toEqual('actions.0.action_type_id: Required');
|
||||
});
|
||||
|
||||
describe('note', () => {
|
||||
|
@ -840,9 +812,7 @@ describe('rules schema', () => {
|
|||
|
||||
const result = RuleCreateProps.safeParse(payload);
|
||||
expectParseError(result);
|
||||
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
|
||||
`"note: Expected string, received object, type: Invalid literal value, expected \\"eql\\", language: Invalid literal value, expected \\"eql\\", note: Expected string, received object, note: Expected string, received object, and 22 more"`
|
||||
);
|
||||
expect(stringifyZodError(result.error)).toEqual('note: Expected string, received object');
|
||||
});
|
||||
|
||||
test('empty name is not valid', () => {
|
||||
|
@ -926,9 +896,7 @@ describe('rules schema', () => {
|
|||
|
||||
const result = RuleCreateProps.safeParse(payload);
|
||||
expectParseError(result);
|
||||
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
|
||||
`"type: Invalid literal value, expected \\"eql\\", language: Invalid literal value, expected \\"eql\\", type: Invalid literal value, expected \\"query\\", saved_id: Required, type: Invalid literal value, expected \\"threshold\\", and 14 more"`
|
||||
);
|
||||
expect(stringifyZodError(result.error)).toEqual('saved_id: Required');
|
||||
});
|
||||
|
||||
test('threshold is required when type is threshold and will not validate without it', () => {
|
||||
|
@ -936,9 +904,7 @@ describe('rules schema', () => {
|
|||
|
||||
const result = RuleCreateProps.safeParse(payload);
|
||||
expectParseError(result);
|
||||
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
|
||||
`"type: Invalid literal value, expected \\"eql\\", language: Invalid literal value, expected \\"eql\\", type: Invalid literal value, expected \\"query\\", type: Invalid literal value, expected \\"saved_query\\", saved_id: Required, and 14 more"`
|
||||
);
|
||||
expect(stringifyZodError(result.error)).toEqual('threshold: Required');
|
||||
});
|
||||
|
||||
test('threshold rules fail validation if threshold is not greater than 0', () => {
|
||||
|
@ -1016,8 +982,8 @@ describe('rules schema', () => {
|
|||
|
||||
const result = RuleCreateProps.safeParse(payload);
|
||||
expectParseError(result);
|
||||
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
|
||||
`"exceptions_list.0.list_id: Required, exceptions_list.0.type: Required, exceptions_list.0.namespace_type: Invalid enum value. Expected 'agnostic' | 'single', received 'not a namespace type', type: Invalid literal value, expected \\"eql\\", query: Required, and 43 more"`
|
||||
expect(stringifyZodError(result.error)).toEqual(
|
||||
"exceptions_list.0.list_id: Required, exceptions_list.0.type: Required, exceptions_list.0.namespace_type: Invalid enum value. Expected 'agnostic' | 'single', received 'not a namespace type'"
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -1059,8 +1025,8 @@ describe('rules schema', () => {
|
|||
|
||||
const result = RuleCreateProps.safeParse(payload);
|
||||
expectParseError(result);
|
||||
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
|
||||
`"type: Invalid literal value, expected \\"eql\\", language: Invalid literal value, expected \\"eql\\", type: Invalid literal value, expected \\"query\\", type: Invalid literal value, expected \\"saved_query\\", saved_id: Required, and 14 more"`
|
||||
expect(stringifyZodError(result.error)).toEqual(
|
||||
'threat_query: Required, threat_mapping: Required, threat_index: Required'
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -1130,8 +1096,8 @@ describe('rules schema', () => {
|
|||
|
||||
const result = RuleCreateProps.safeParse(payload);
|
||||
expectParseError(result);
|
||||
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
|
||||
`"type: Invalid literal value, expected \\"eql\\", language: Invalid literal value, expected \\"eql\\", data_view_id: Expected string, received number, data_view_id: Expected string, received number, type: Invalid literal value, expected \\"saved_query\\", and 20 more"`
|
||||
expect(stringifyZodError(result.error)).toEqual(
|
||||
'data_view_id: Expected string, received number'
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -1195,9 +1161,7 @@ describe('rules schema', () => {
|
|||
|
||||
const result = RuleCreateProps.safeParse(payload);
|
||||
expectParseError(result);
|
||||
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
|
||||
`"investigation_fields.field_names: Required, type: Invalid literal value, expected \\"eql\\", language: Invalid literal value, expected \\"eql\\", investigation_fields.field_names: Required, investigation_fields.field_names: Required, and 22 more"`
|
||||
);
|
||||
expect(stringifyZodError(result.error)).toEqual('investigation_fields.field_names: Required');
|
||||
});
|
||||
|
||||
test('You can send in investigation_fields', () => {
|
||||
|
@ -1232,8 +1196,8 @@ describe('rules schema', () => {
|
|||
|
||||
const result = RuleCreateProps.safeParse(payload);
|
||||
expectParseError(result);
|
||||
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
|
||||
`"investigation_fields.field_names.0: Expected string, received number, investigation_fields.field_names.1: Expected string, received number, investigation_fields.field_names.2: Expected string, received number, type: Invalid literal value, expected \\"eql\\", language: Invalid literal value, expected \\"eql\\", and 38 more"`
|
||||
expect(stringifyZodError(result.error)).toEqual(
|
||||
'investigation_fields.field_names.0: Expected string, received number, investigation_fields.field_names.1: Expected string, received number, investigation_fields.field_names.2: Expected string, received number'
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -1245,9 +1209,7 @@ describe('rules schema', () => {
|
|||
|
||||
const result = RuleCreateProps.safeParse(payload);
|
||||
expectParseError(result);
|
||||
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
|
||||
`"investigation_fields.field_names: Required, type: Invalid literal value, expected \\"eql\\", language: Invalid literal value, expected \\"eql\\", investigation_fields.field_names: Required, investigation_fields.field_names: Required, and 22 more"`
|
||||
);
|
||||
expect(stringifyZodError(result.error)).toEqual('investigation_fields.field_names: Required');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -41,7 +41,7 @@ describe('Rule response schema', () => {
|
|||
const result = RuleResponse.safeParse(payload);
|
||||
expectParseError(result);
|
||||
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
|
||||
`"type: Invalid literal value, expected \\"eql\\", language: Invalid literal value, expected \\"eql\\", type: Invalid literal value, expected \\"query\\", type: Invalid literal value, expected \\"saved_query\\", saved_id: Required, and 15 more"`
|
||||
`"type: Invalid discriminator value. Expected 'eql' | 'query' | 'saved_query' | 'threshold' | 'threat_match' | 'machine_learning' | 'new_terms' | 'esql'"`
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -70,9 +70,7 @@ describe('Rule response schema', () => {
|
|||
|
||||
const result = RuleResponse.safeParse(payload);
|
||||
expectParseError(result);
|
||||
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
|
||||
`"type: Invalid literal value, expected \\"eql\\", language: Invalid literal value, expected \\"eql\\", type: Invalid literal value, expected \\"query\\", saved_id: Required, type: Invalid literal value, expected \\"threshold\\", and 14 more"`
|
||||
);
|
||||
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(`"saved_id: Required"`);
|
||||
});
|
||||
|
||||
test('it should validate a type of "timeline_id" if there is a "timeline_title" dependent', () => {
|
||||
|
@ -103,7 +101,7 @@ describe('Rule response schema', () => {
|
|||
const result = RuleResponse.safeParse(payload);
|
||||
expectParseError(result);
|
||||
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
|
||||
`"exceptions_list: Expected array, received string, type: Invalid literal value, expected \\"eql\\", language: Invalid literal value, expected \\"eql\\", exceptions_list: Expected array, received string, exceptions_list: Expected array, received string, and 22 more"`
|
||||
`"exceptions_list: Expected array, received string"`
|
||||
);
|
||||
});
|
||||
});
|
||||
|
@ -239,7 +237,7 @@ describe('investigation_fields', () => {
|
|||
const result = RuleResponse.safeParse(payload);
|
||||
expectParseError(result);
|
||||
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
|
||||
`"investigation_fields: Expected object, received string, type: Invalid literal value, expected \\"eql\\", language: Invalid literal value, expected \\"eql\\", investigation_fields: Expected object, received string, investigation_fields: Expected object, received string, and 22 more"`
|
||||
`"investigation_fields: Expected object, received string"`
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -131,20 +131,20 @@ export const BaseDefaultableFields = z.object({
|
|||
|
||||
export type BaseCreateProps = z.infer<typeof BaseCreateProps>;
|
||||
export const BaseCreateProps =
|
||||
BaseRequiredFields.and(BaseOptionalFields).and(BaseDefaultableFields);
|
||||
BaseRequiredFields.merge(BaseOptionalFields).merge(BaseDefaultableFields);
|
||||
|
||||
export type BasePatchProps = z.infer<typeof BasePatchProps>;
|
||||
export const BasePatchProps = BaseRequiredFields.partial()
|
||||
.and(BaseOptionalFields)
|
||||
.and(BaseDefaultableFields);
|
||||
.merge(BaseOptionalFields)
|
||||
.merge(BaseDefaultableFields);
|
||||
|
||||
export type BaseResponseProps = z.infer<typeof BaseResponseProps>;
|
||||
export const BaseResponseProps = BaseRequiredFields.and(BaseOptionalFields).and(
|
||||
export const BaseResponseProps = BaseRequiredFields.merge(BaseOptionalFields).merge(
|
||||
BaseDefaultableFields.required()
|
||||
);
|
||||
|
||||
export type ResponseRequiredFields = z.infer<typeof ResponseRequiredFields>;
|
||||
export const ResponseRequiredFields = z.object({
|
||||
export type ResponseFields = z.infer<typeof ResponseFields>;
|
||||
export const ResponseFields = z.object({
|
||||
id: RuleObjectId,
|
||||
rule_id: RuleSignatureId,
|
||||
immutable: IsRuleImmutable,
|
||||
|
@ -156,22 +156,18 @@ export const ResponseRequiredFields = z.object({
|
|||
related_integrations: RelatedIntegrationArray,
|
||||
required_fields: RequiredFieldArray,
|
||||
setup: SetupGuide,
|
||||
});
|
||||
|
||||
export type ResponseOptionalFields = z.infer<typeof ResponseOptionalFields>;
|
||||
export const ResponseOptionalFields = z.object({
|
||||
execution_summary: RuleExecutionSummary.optional(),
|
||||
});
|
||||
|
||||
export type SharedCreateProps = z.infer<typeof SharedCreateProps>;
|
||||
export const SharedCreateProps = BaseCreateProps.and(
|
||||
export const SharedCreateProps = BaseCreateProps.merge(
|
||||
z.object({
|
||||
rule_id: RuleSignatureId.optional(),
|
||||
})
|
||||
);
|
||||
|
||||
export type SharedUpdateProps = z.infer<typeof SharedUpdateProps>;
|
||||
export const SharedUpdateProps = BaseCreateProps.and(
|
||||
export const SharedUpdateProps = BaseCreateProps.merge(
|
||||
z.object({
|
||||
id: RuleObjectId.optional(),
|
||||
rule_id: RuleSignatureId.optional(),
|
||||
|
@ -179,7 +175,7 @@ export const SharedUpdateProps = BaseCreateProps.and(
|
|||
);
|
||||
|
||||
export type SharedPatchProps = z.infer<typeof SharedPatchProps>;
|
||||
export const SharedPatchProps = BasePatchProps.and(
|
||||
export const SharedPatchProps = BasePatchProps.merge(
|
||||
z.object({
|
||||
id: RuleObjectId.optional(),
|
||||
rule_id: RuleSignatureId.optional(),
|
||||
|
@ -187,8 +183,7 @@ export const SharedPatchProps = BasePatchProps.and(
|
|||
);
|
||||
|
||||
export type SharedResponseProps = z.infer<typeof SharedResponseProps>;
|
||||
export const SharedResponseProps =
|
||||
BaseResponseProps.and(ResponseRequiredFields).and(ResponseOptionalFields);
|
||||
export const SharedResponseProps = BaseResponseProps.merge(ResponseFields);
|
||||
|
||||
export type EqlQueryLanguage = z.infer<typeof EqlQueryLanguage>;
|
||||
export const EqlQueryLanguage = z.literal('eql');
|
||||
|
@ -220,25 +215,25 @@ export const EqlOptionalFields = z.object({
|
|||
});
|
||||
|
||||
export type EqlRuleCreateFields = z.infer<typeof EqlRuleCreateFields>;
|
||||
export const EqlRuleCreateFields = EqlRequiredFields.and(EqlOptionalFields);
|
||||
export const EqlRuleCreateFields = EqlRequiredFields.merge(EqlOptionalFields);
|
||||
|
||||
export type EqlRuleResponseFields = z.infer<typeof EqlRuleResponseFields>;
|
||||
export const EqlRuleResponseFields = EqlRequiredFields.and(EqlOptionalFields);
|
||||
export const EqlRuleResponseFields = EqlRequiredFields.merge(EqlOptionalFields);
|
||||
|
||||
export type EqlRulePatchFields = z.infer<typeof EqlRulePatchFields>;
|
||||
export const EqlRulePatchFields = EqlRequiredFields.partial().and(EqlOptionalFields);
|
||||
export const EqlRulePatchFields = EqlRequiredFields.partial().merge(EqlOptionalFields);
|
||||
|
||||
export type EqlRule = z.infer<typeof EqlRule>;
|
||||
export const EqlRule = SharedResponseProps.and(EqlRuleResponseFields);
|
||||
export const EqlRule = SharedResponseProps.merge(EqlRuleResponseFields);
|
||||
|
||||
export type EqlRuleCreateProps = z.infer<typeof EqlRuleCreateProps>;
|
||||
export const EqlRuleCreateProps = SharedCreateProps.and(EqlRuleCreateFields);
|
||||
export const EqlRuleCreateProps = SharedCreateProps.merge(EqlRuleCreateFields);
|
||||
|
||||
export type EqlRuleUpdateProps = z.infer<typeof EqlRuleUpdateProps>;
|
||||
export const EqlRuleUpdateProps = SharedUpdateProps.and(EqlRuleCreateFields);
|
||||
export const EqlRuleUpdateProps = SharedUpdateProps.merge(EqlRuleCreateFields);
|
||||
|
||||
export type EqlRulePatchProps = z.infer<typeof EqlRulePatchProps>;
|
||||
export const EqlRulePatchProps = SharedPatchProps.and(EqlRulePatchFields);
|
||||
export const EqlRulePatchProps = SharedPatchProps.merge(EqlRulePatchFields);
|
||||
|
||||
export type QueryRuleRequiredFields = z.infer<typeof QueryRuleRequiredFields>;
|
||||
export const QueryRuleRequiredFields = z.object({
|
||||
|
@ -265,31 +260,31 @@ export const QueryRuleDefaultableFields = z.object({
|
|||
});
|
||||
|
||||
export type QueryRuleCreateFields = z.infer<typeof QueryRuleCreateFields>;
|
||||
export const QueryRuleCreateFields = QueryRuleRequiredFields.and(QueryRuleOptionalFields).and(
|
||||
export const QueryRuleCreateFields = QueryRuleRequiredFields.merge(QueryRuleOptionalFields).merge(
|
||||
QueryRuleDefaultableFields
|
||||
);
|
||||
|
||||
export type QueryRulePatchFields = z.infer<typeof QueryRulePatchFields>;
|
||||
export const QueryRulePatchFields = QueryRuleRequiredFields.partial()
|
||||
.and(QueryRuleOptionalFields)
|
||||
.and(QueryRuleDefaultableFields);
|
||||
.merge(QueryRuleOptionalFields)
|
||||
.merge(QueryRuleDefaultableFields);
|
||||
|
||||
export type QueryRuleResponseFields = z.infer<typeof QueryRuleResponseFields>;
|
||||
export const QueryRuleResponseFields = QueryRuleRequiredFields.and(QueryRuleOptionalFields).and(
|
||||
export const QueryRuleResponseFields = QueryRuleRequiredFields.merge(QueryRuleOptionalFields).merge(
|
||||
QueryRuleDefaultableFields.required()
|
||||
);
|
||||
|
||||
export type QueryRule = z.infer<typeof QueryRule>;
|
||||
export const QueryRule = SharedResponseProps.and(QueryRuleResponseFields);
|
||||
export const QueryRule = SharedResponseProps.merge(QueryRuleResponseFields);
|
||||
|
||||
export type QueryRuleCreateProps = z.infer<typeof QueryRuleCreateProps>;
|
||||
export const QueryRuleCreateProps = SharedCreateProps.and(QueryRuleCreateFields);
|
||||
export const QueryRuleCreateProps = SharedCreateProps.merge(QueryRuleCreateFields);
|
||||
|
||||
export type QueryRuleUpdateProps = z.infer<typeof QueryRuleUpdateProps>;
|
||||
export const QueryRuleUpdateProps = SharedUpdateProps.and(QueryRuleCreateFields);
|
||||
export const QueryRuleUpdateProps = SharedUpdateProps.merge(QueryRuleCreateFields);
|
||||
|
||||
export type QueryRulePatchProps = z.infer<typeof QueryRulePatchProps>;
|
||||
export const QueryRulePatchProps = SharedPatchProps.and(QueryRulePatchFields);
|
||||
export const QueryRulePatchProps = SharedPatchProps.merge(QueryRulePatchFields);
|
||||
|
||||
export type SavedQueryRuleRequiredFields = z.infer<typeof SavedQueryRuleRequiredFields>;
|
||||
export const SavedQueryRuleRequiredFields = z.object({
|
||||
|
@ -316,31 +311,31 @@ export const SavedQueryRuleDefaultableFields = z.object({
|
|||
});
|
||||
|
||||
export type SavedQueryRuleCreateFields = z.infer<typeof SavedQueryRuleCreateFields>;
|
||||
export const SavedQueryRuleCreateFields = SavedQueryRuleRequiredFields.and(
|
||||
export const SavedQueryRuleCreateFields = SavedQueryRuleRequiredFields.merge(
|
||||
SavedQueryRuleOptionalFields
|
||||
).and(SavedQueryRuleDefaultableFields);
|
||||
).merge(SavedQueryRuleDefaultableFields);
|
||||
|
||||
export type SavedQueryRulePatchFields = z.infer<typeof SavedQueryRulePatchFields>;
|
||||
export const SavedQueryRulePatchFields = SavedQueryRuleRequiredFields.partial()
|
||||
.and(SavedQueryRuleOptionalFields)
|
||||
.and(SavedQueryRuleDefaultableFields);
|
||||
.merge(SavedQueryRuleOptionalFields)
|
||||
.merge(SavedQueryRuleDefaultableFields);
|
||||
|
||||
export type SavedQueryRuleResponseFields = z.infer<typeof SavedQueryRuleResponseFields>;
|
||||
export const SavedQueryRuleResponseFields = SavedQueryRuleRequiredFields.and(
|
||||
export const SavedQueryRuleResponseFields = SavedQueryRuleRequiredFields.merge(
|
||||
SavedQueryRuleOptionalFields
|
||||
).and(SavedQueryRuleDefaultableFields.required());
|
||||
).merge(SavedQueryRuleDefaultableFields.required());
|
||||
|
||||
export type SavedQueryRule = z.infer<typeof SavedQueryRule>;
|
||||
export const SavedQueryRule = SharedResponseProps.and(SavedQueryRuleResponseFields);
|
||||
export const SavedQueryRule = SharedResponseProps.merge(SavedQueryRuleResponseFields);
|
||||
|
||||
export type SavedQueryRuleCreateProps = z.infer<typeof SavedQueryRuleCreateProps>;
|
||||
export const SavedQueryRuleCreateProps = SharedCreateProps.and(SavedQueryRuleCreateFields);
|
||||
export const SavedQueryRuleCreateProps = SharedCreateProps.merge(SavedQueryRuleCreateFields);
|
||||
|
||||
export type SavedQueryRuleUpdateProps = z.infer<typeof SavedQueryRuleUpdateProps>;
|
||||
export const SavedQueryRuleUpdateProps = SharedUpdateProps.and(SavedQueryRuleCreateFields);
|
||||
export const SavedQueryRuleUpdateProps = SharedUpdateProps.merge(SavedQueryRuleCreateFields);
|
||||
|
||||
export type SavedQueryRulePatchProps = z.infer<typeof SavedQueryRulePatchProps>;
|
||||
export const SavedQueryRulePatchProps = SharedPatchProps.and(SavedQueryRulePatchFields);
|
||||
export const SavedQueryRulePatchProps = SharedPatchProps.merge(SavedQueryRulePatchFields);
|
||||
|
||||
export type ThresholdRuleRequiredFields = z.infer<typeof ThresholdRuleRequiredFields>;
|
||||
export const ThresholdRuleRequiredFields = z.object({
|
||||
|
@ -366,31 +361,31 @@ export const ThresholdRuleDefaultableFields = z.object({
|
|||
});
|
||||
|
||||
export type ThresholdRuleCreateFields = z.infer<typeof ThresholdRuleCreateFields>;
|
||||
export const ThresholdRuleCreateFields = ThresholdRuleRequiredFields.and(
|
||||
export const ThresholdRuleCreateFields = ThresholdRuleRequiredFields.merge(
|
||||
ThresholdRuleOptionalFields
|
||||
).and(ThresholdRuleDefaultableFields);
|
||||
).merge(ThresholdRuleDefaultableFields);
|
||||
|
||||
export type ThresholdRulePatchFields = z.infer<typeof ThresholdRulePatchFields>;
|
||||
export const ThresholdRulePatchFields = ThresholdRuleRequiredFields.partial()
|
||||
.and(ThresholdRuleOptionalFields)
|
||||
.and(ThresholdRuleDefaultableFields);
|
||||
.merge(ThresholdRuleOptionalFields)
|
||||
.merge(ThresholdRuleDefaultableFields);
|
||||
|
||||
export type ThresholdRuleResponseFields = z.infer<typeof ThresholdRuleResponseFields>;
|
||||
export const ThresholdRuleResponseFields = ThresholdRuleRequiredFields.and(
|
||||
export const ThresholdRuleResponseFields = ThresholdRuleRequiredFields.merge(
|
||||
ThresholdRuleOptionalFields
|
||||
).and(ThresholdRuleDefaultableFields.required());
|
||||
).merge(ThresholdRuleDefaultableFields.required());
|
||||
|
||||
export type ThresholdRule = z.infer<typeof ThresholdRule>;
|
||||
export const ThresholdRule = SharedResponseProps.and(ThresholdRuleResponseFields);
|
||||
export const ThresholdRule = SharedResponseProps.merge(ThresholdRuleResponseFields);
|
||||
|
||||
export type ThresholdRuleCreateProps = z.infer<typeof ThresholdRuleCreateProps>;
|
||||
export const ThresholdRuleCreateProps = SharedCreateProps.and(ThresholdRuleCreateFields);
|
||||
export const ThresholdRuleCreateProps = SharedCreateProps.merge(ThresholdRuleCreateFields);
|
||||
|
||||
export type ThresholdRuleUpdateProps = z.infer<typeof ThresholdRuleUpdateProps>;
|
||||
export const ThresholdRuleUpdateProps = SharedUpdateProps.and(ThresholdRuleCreateFields);
|
||||
export const ThresholdRuleUpdateProps = SharedUpdateProps.merge(ThresholdRuleCreateFields);
|
||||
|
||||
export type ThresholdRulePatchProps = z.infer<typeof ThresholdRulePatchProps>;
|
||||
export const ThresholdRulePatchProps = SharedPatchProps.and(ThresholdRulePatchFields);
|
||||
export const ThresholdRulePatchProps = SharedPatchProps.merge(ThresholdRulePatchFields);
|
||||
|
||||
export type ThreatMatchRuleRequiredFields = z.infer<typeof ThreatMatchRuleRequiredFields>;
|
||||
export const ThreatMatchRuleRequiredFields = z.object({
|
||||
|
@ -423,31 +418,31 @@ export const ThreatMatchRuleDefaultableFields = z.object({
|
|||
});
|
||||
|
||||
export type ThreatMatchRuleCreateFields = z.infer<typeof ThreatMatchRuleCreateFields>;
|
||||
export const ThreatMatchRuleCreateFields = ThreatMatchRuleRequiredFields.and(
|
||||
export const ThreatMatchRuleCreateFields = ThreatMatchRuleRequiredFields.merge(
|
||||
ThreatMatchRuleOptionalFields
|
||||
).and(ThreatMatchRuleDefaultableFields);
|
||||
).merge(ThreatMatchRuleDefaultableFields);
|
||||
|
||||
export type ThreatMatchRulePatchFields = z.infer<typeof ThreatMatchRulePatchFields>;
|
||||
export const ThreatMatchRulePatchFields = ThreatMatchRuleRequiredFields.partial()
|
||||
.and(ThreatMatchRuleOptionalFields)
|
||||
.and(ThreatMatchRuleDefaultableFields);
|
||||
.merge(ThreatMatchRuleOptionalFields)
|
||||
.merge(ThreatMatchRuleDefaultableFields);
|
||||
|
||||
export type ThreatMatchRuleResponseFields = z.infer<typeof ThreatMatchRuleResponseFields>;
|
||||
export const ThreatMatchRuleResponseFields = ThreatMatchRuleRequiredFields.and(
|
||||
export const ThreatMatchRuleResponseFields = ThreatMatchRuleRequiredFields.merge(
|
||||
ThreatMatchRuleOptionalFields
|
||||
).and(ThreatMatchRuleDefaultableFields.required());
|
||||
).merge(ThreatMatchRuleDefaultableFields.required());
|
||||
|
||||
export type ThreatMatchRule = z.infer<typeof ThreatMatchRule>;
|
||||
export const ThreatMatchRule = SharedResponseProps.and(ThreatMatchRuleResponseFields);
|
||||
export const ThreatMatchRule = SharedResponseProps.merge(ThreatMatchRuleResponseFields);
|
||||
|
||||
export type ThreatMatchRuleCreateProps = z.infer<typeof ThreatMatchRuleCreateProps>;
|
||||
export const ThreatMatchRuleCreateProps = SharedCreateProps.and(ThreatMatchRuleCreateFields);
|
||||
export const ThreatMatchRuleCreateProps = SharedCreateProps.merge(ThreatMatchRuleCreateFields);
|
||||
|
||||
export type ThreatMatchRuleUpdateProps = z.infer<typeof ThreatMatchRuleUpdateProps>;
|
||||
export const ThreatMatchRuleUpdateProps = SharedUpdateProps.and(ThreatMatchRuleCreateFields);
|
||||
export const ThreatMatchRuleUpdateProps = SharedUpdateProps.merge(ThreatMatchRuleCreateFields);
|
||||
|
||||
export type ThreatMatchRulePatchProps = z.infer<typeof ThreatMatchRulePatchProps>;
|
||||
export const ThreatMatchRulePatchProps = SharedPatchProps.and(ThreatMatchRulePatchFields);
|
||||
export const ThreatMatchRulePatchProps = SharedPatchProps.merge(ThreatMatchRulePatchFields);
|
||||
|
||||
export type MachineLearningRuleRequiredFields = z.infer<typeof MachineLearningRuleRequiredFields>;
|
||||
export const MachineLearningRuleRequiredFields = z.object({
|
||||
|
@ -469,20 +464,20 @@ export type MachineLearningRuleCreateFields = z.infer<typeof MachineLearningRule
|
|||
export const MachineLearningRuleCreateFields = MachineLearningRuleRequiredFields;
|
||||
|
||||
export type MachineLearningRule = z.infer<typeof MachineLearningRule>;
|
||||
export const MachineLearningRule = SharedResponseProps.and(MachineLearningRuleResponseFields);
|
||||
export const MachineLearningRule = SharedResponseProps.merge(MachineLearningRuleResponseFields);
|
||||
|
||||
export type MachineLearningRuleCreateProps = z.infer<typeof MachineLearningRuleCreateProps>;
|
||||
export const MachineLearningRuleCreateProps = SharedCreateProps.and(
|
||||
export const MachineLearningRuleCreateProps = SharedCreateProps.merge(
|
||||
MachineLearningRuleCreateFields
|
||||
);
|
||||
|
||||
export type MachineLearningRuleUpdateProps = z.infer<typeof MachineLearningRuleUpdateProps>;
|
||||
export const MachineLearningRuleUpdateProps = SharedUpdateProps.and(
|
||||
export const MachineLearningRuleUpdateProps = SharedUpdateProps.merge(
|
||||
MachineLearningRuleCreateFields
|
||||
);
|
||||
|
||||
export type MachineLearningRulePatchProps = z.infer<typeof MachineLearningRulePatchProps>;
|
||||
export const MachineLearningRulePatchProps = SharedPatchProps.and(MachineLearningRulePatchFields);
|
||||
export const MachineLearningRulePatchProps = SharedPatchProps.merge(MachineLearningRulePatchFields);
|
||||
|
||||
export type NewTermsRuleRequiredFields = z.infer<typeof NewTermsRuleRequiredFields>;
|
||||
export const NewTermsRuleRequiredFields = z.object({
|
||||
|
@ -509,30 +504,30 @@ export const NewTermsRuleDefaultableFields = z.object({
|
|||
|
||||
export type NewTermsRulePatchFields = z.infer<typeof NewTermsRulePatchFields>;
|
||||
export const NewTermsRulePatchFields = NewTermsRuleRequiredFields.partial()
|
||||
.and(NewTermsRuleOptionalFields)
|
||||
.and(NewTermsRuleDefaultableFields);
|
||||
.merge(NewTermsRuleOptionalFields)
|
||||
.merge(NewTermsRuleDefaultableFields);
|
||||
|
||||
export type NewTermsRuleResponseFields = z.infer<typeof NewTermsRuleResponseFields>;
|
||||
export const NewTermsRuleResponseFields = NewTermsRuleRequiredFields.and(
|
||||
export const NewTermsRuleResponseFields = NewTermsRuleRequiredFields.merge(
|
||||
NewTermsRuleOptionalFields
|
||||
).and(NewTermsRuleDefaultableFields.required());
|
||||
).merge(NewTermsRuleDefaultableFields.required());
|
||||
|
||||
export type NewTermsRuleCreateFields = z.infer<typeof NewTermsRuleCreateFields>;
|
||||
export const NewTermsRuleCreateFields = NewTermsRuleRequiredFields.and(
|
||||
export const NewTermsRuleCreateFields = NewTermsRuleRequiredFields.merge(
|
||||
NewTermsRuleOptionalFields
|
||||
).and(NewTermsRuleDefaultableFields);
|
||||
).merge(NewTermsRuleDefaultableFields);
|
||||
|
||||
export type NewTermsRule = z.infer<typeof NewTermsRule>;
|
||||
export const NewTermsRule = SharedResponseProps.and(NewTermsRuleResponseFields);
|
||||
export const NewTermsRule = SharedResponseProps.merge(NewTermsRuleResponseFields);
|
||||
|
||||
export type NewTermsRuleCreateProps = z.infer<typeof NewTermsRuleCreateProps>;
|
||||
export const NewTermsRuleCreateProps = SharedCreateProps.and(NewTermsRuleCreateFields);
|
||||
export const NewTermsRuleCreateProps = SharedCreateProps.merge(NewTermsRuleCreateFields);
|
||||
|
||||
export type NewTermsRuleUpdateProps = z.infer<typeof NewTermsRuleUpdateProps>;
|
||||
export const NewTermsRuleUpdateProps = SharedUpdateProps.and(NewTermsRuleCreateFields);
|
||||
export const NewTermsRuleUpdateProps = SharedUpdateProps.merge(NewTermsRuleCreateFields);
|
||||
|
||||
export type NewTermsRulePatchProps = z.infer<typeof NewTermsRulePatchProps>;
|
||||
export const NewTermsRulePatchProps = SharedPatchProps.and(NewTermsRulePatchFields);
|
||||
export const NewTermsRulePatchProps = SharedPatchProps.merge(NewTermsRulePatchFields);
|
||||
|
||||
export type EsqlQueryLanguage = z.infer<typeof EsqlQueryLanguage>;
|
||||
export const EsqlQueryLanguage = z.literal('esql');
|
||||
|
@ -560,19 +555,19 @@ export type EsqlRuleCreateFields = z.infer<typeof EsqlRuleCreateFields>;
|
|||
export const EsqlRuleCreateFields = EsqlRuleRequiredFields;
|
||||
|
||||
export type EsqlRule = z.infer<typeof EsqlRule>;
|
||||
export const EsqlRule = SharedResponseProps.and(EsqlRuleResponseFields);
|
||||
export const EsqlRule = SharedResponseProps.merge(EsqlRuleResponseFields);
|
||||
|
||||
export type EsqlRuleCreateProps = z.infer<typeof EsqlRuleCreateProps>;
|
||||
export const EsqlRuleCreateProps = SharedCreateProps.and(EsqlRuleCreateFields);
|
||||
export const EsqlRuleCreateProps = SharedCreateProps.merge(EsqlRuleCreateFields);
|
||||
|
||||
export type EsqlRuleUpdateProps = z.infer<typeof EsqlRuleUpdateProps>;
|
||||
export const EsqlRuleUpdateProps = SharedUpdateProps.and(EsqlRuleCreateFields);
|
||||
export const EsqlRuleUpdateProps = SharedUpdateProps.merge(EsqlRuleCreateFields);
|
||||
|
||||
export type EsqlRulePatchProps = z.infer<typeof EsqlRulePatchProps>;
|
||||
export const EsqlRulePatchProps = SharedPatchProps.and(EsqlRulePatchFields.partial());
|
||||
export const EsqlRulePatchProps = SharedPatchProps.merge(EsqlRulePatchFields.partial());
|
||||
|
||||
export type TypeSpecificCreateProps = z.infer<typeof TypeSpecificCreateProps>;
|
||||
export const TypeSpecificCreateProps = z.union([
|
||||
export const TypeSpecificCreateProps = z.discriminatedUnion('type', [
|
||||
EqlRuleCreateFields,
|
||||
QueryRuleCreateFields,
|
||||
SavedQueryRuleCreateFields,
|
||||
|
@ -596,7 +591,7 @@ export const TypeSpecificPatchProps = z.union([
|
|||
]);
|
||||
|
||||
export type TypeSpecificResponse = z.infer<typeof TypeSpecificResponse>;
|
||||
export const TypeSpecificResponse = z.union([
|
||||
export const TypeSpecificResponse = z.discriminatedUnion('type', [
|
||||
EqlRuleResponseFields,
|
||||
QueryRuleResponseFields,
|
||||
SavedQueryRuleResponseFields,
|
||||
|
@ -608,7 +603,7 @@ export const TypeSpecificResponse = z.union([
|
|||
]);
|
||||
|
||||
export type RuleCreateProps = z.infer<typeof RuleCreateProps>;
|
||||
export const RuleCreateProps = z.union([
|
||||
export const RuleCreateProps = z.discriminatedUnion('type', [
|
||||
EqlRuleCreateProps,
|
||||
QueryRuleCreateProps,
|
||||
SavedQueryRuleCreateProps,
|
||||
|
@ -620,7 +615,7 @@ export const RuleCreateProps = z.union([
|
|||
]);
|
||||
|
||||
export type RuleUpdateProps = z.infer<typeof RuleUpdateProps>;
|
||||
export const RuleUpdateProps = z.union([
|
||||
export const RuleUpdateProps = z.discriminatedUnion('type', [
|
||||
EqlRuleUpdateProps,
|
||||
QueryRuleUpdateProps,
|
||||
SavedQueryRuleUpdateProps,
|
||||
|
@ -644,7 +639,7 @@ export const RulePatchProps = z.union([
|
|||
]);
|
||||
|
||||
export type RuleResponse = z.infer<typeof RuleResponse>;
|
||||
export const RuleResponse = z.union([
|
||||
export const RuleResponse = z.discriminatedUnion('type', [
|
||||
EqlRule,
|
||||
QueryRule,
|
||||
SavedQueryRule,
|
||||
|
|
|
@ -152,7 +152,7 @@ components:
|
|||
- $ref: '#/components/schemas/BaseDefaultableFields'
|
||||
x-modify: required
|
||||
|
||||
ResponseRequiredFields:
|
||||
ResponseFields:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
|
@ -185,6 +185,8 @@ components:
|
|||
$ref: './common_attributes.schema.yaml#/components/schemas/RequiredFieldArray'
|
||||
setup:
|
||||
$ref: './common_attributes.schema.yaml#/components/schemas/SetupGuide'
|
||||
execution_summary:
|
||||
$ref: '../../rule_monitoring/model/execution_summary.schema.yaml#/components/schemas/RuleExecutionSummary'
|
||||
required:
|
||||
- id
|
||||
- rule_id
|
||||
|
@ -198,12 +200,6 @@ components:
|
|||
- required_fields
|
||||
- setup
|
||||
|
||||
ResponseOptionalFields:
|
||||
type: object
|
||||
properties:
|
||||
execution_summary:
|
||||
$ref: '../../rule_monitoring/model/execution_summary.schema.yaml#/components/schemas/RuleExecutionSummary'
|
||||
|
||||
SharedCreateProps:
|
||||
x-inline: true
|
||||
allOf:
|
||||
|
@ -239,8 +235,7 @@ components:
|
|||
x-inline: true
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/BaseResponseProps'
|
||||
- $ref: '#/components/schemas/ResponseRequiredFields'
|
||||
- $ref: '#/components/schemas/ResponseOptionalFields'
|
||||
- $ref: '#/components/schemas/ResponseFields'
|
||||
|
||||
############
|
||||
# EQL Rule #
|
||||
|
@ -851,6 +846,8 @@ components:
|
|||
##########################
|
||||
|
||||
TypeSpecificCreateProps:
|
||||
discriminator:
|
||||
propertyName: type
|
||||
anyOf:
|
||||
- $ref: '#/components/schemas/EqlRuleCreateFields'
|
||||
- $ref: '#/components/schemas/QueryRuleCreateFields'
|
||||
|
@ -873,6 +870,8 @@ components:
|
|||
- $ref: '#/components/schemas/EsqlRulePatchFields'
|
||||
|
||||
TypeSpecificResponse:
|
||||
discriminator:
|
||||
propertyName: type
|
||||
anyOf:
|
||||
- $ref: '#/components/schemas/EqlRuleResponseFields'
|
||||
- $ref: '#/components/schemas/QueryRuleResponseFields'
|
||||
|
@ -884,6 +883,8 @@ components:
|
|||
- $ref: '#/components/schemas/EsqlRuleResponseFields'
|
||||
|
||||
RuleCreateProps:
|
||||
discriminator:
|
||||
propertyName: type
|
||||
anyOf:
|
||||
- $ref: '#/components/schemas/EqlRuleCreateProps'
|
||||
- $ref: '#/components/schemas/QueryRuleCreateProps'
|
||||
|
@ -895,6 +896,8 @@ components:
|
|||
- $ref: '#/components/schemas/EsqlRuleCreateProps'
|
||||
|
||||
RuleUpdateProps:
|
||||
discriminator:
|
||||
propertyName: type
|
||||
anyOf:
|
||||
- $ref: '#/components/schemas/EqlRuleUpdateProps'
|
||||
- $ref: '#/components/schemas/QueryRuleUpdateProps'
|
||||
|
@ -917,6 +920,8 @@ components:
|
|||
- $ref: '#/components/schemas/EsqlRulePatchProps'
|
||||
|
||||
RuleResponse:
|
||||
discriminator:
|
||||
propertyName: type
|
||||
anyOf:
|
||||
- $ref: '#/components/schemas/EqlRule'
|
||||
- $ref: '#/components/schemas/QueryRule'
|
||||
|
|
|
@ -105,35 +105,35 @@ export const BulkActionBase = z.object({
|
|||
});
|
||||
|
||||
export type BulkDeleteRules = z.infer<typeof BulkDeleteRules>;
|
||||
export const BulkDeleteRules = BulkActionBase.and(
|
||||
export const BulkDeleteRules = BulkActionBase.merge(
|
||||
z.object({
|
||||
action: z.literal('delete'),
|
||||
})
|
||||
);
|
||||
|
||||
export type BulkDisableRules = z.infer<typeof BulkDisableRules>;
|
||||
export const BulkDisableRules = BulkActionBase.and(
|
||||
export const BulkDisableRules = BulkActionBase.merge(
|
||||
z.object({
|
||||
action: z.literal('disable'),
|
||||
})
|
||||
);
|
||||
|
||||
export type BulkEnableRules = z.infer<typeof BulkEnableRules>;
|
||||
export const BulkEnableRules = BulkActionBase.and(
|
||||
export const BulkEnableRules = BulkActionBase.merge(
|
||||
z.object({
|
||||
action: z.literal('enable'),
|
||||
})
|
||||
);
|
||||
|
||||
export type BulkExportRules = z.infer<typeof BulkExportRules>;
|
||||
export const BulkExportRules = BulkActionBase.and(
|
||||
export const BulkExportRules = BulkActionBase.merge(
|
||||
z.object({
|
||||
action: z.literal('export'),
|
||||
})
|
||||
);
|
||||
|
||||
export type BulkDuplicateRules = z.infer<typeof BulkDuplicateRules>;
|
||||
export const BulkDuplicateRules = BulkActionBase.and(
|
||||
export const BulkDuplicateRules = BulkActionBase.merge(
|
||||
z.object({
|
||||
action: z.literal('duplicate'),
|
||||
duplicate: z
|
||||
|
@ -254,7 +254,7 @@ export const BulkActionEditPayload = z.union([
|
|||
]);
|
||||
|
||||
export type BulkEditRules = z.infer<typeof BulkEditRules>;
|
||||
export const BulkEditRules = BulkActionBase.and(
|
||||
export const BulkEditRules = BulkActionBase.merge(
|
||||
z.object({
|
||||
action: z.literal('edit'),
|
||||
/**
|
||||
|
|
|
@ -27,7 +27,7 @@ describe('Bulk create rules request schema', () => {
|
|||
const result = BulkCreateRulesRequestBody.safeParse(payload);
|
||||
expectParseError(result);
|
||||
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
|
||||
`"0.name: Required, 0.description: Required, 0.risk_score: Required, 0.severity: Required, 0.type: Invalid literal value, expected \\"eql\\", and 52 more"`
|
||||
`"0.type: Invalid discriminator value. Expected 'eql' | 'query' | 'saved_query' | 'threshold' | 'threat_match' | 'machine_learning' | 'new_terms' | 'esql'"`
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -58,9 +58,7 @@ describe('Bulk create rules request schema', () => {
|
|||
|
||||
const result = BulkCreateRulesRequestBody.safeParse(payload);
|
||||
expectParseError(result);
|
||||
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
|
||||
`"0.risk_score: Required, 0.type: Invalid literal value, expected \\"eql\\", 0.language: Invalid literal value, expected \\"eql\\", 0.risk_score: Required, 0.risk_score: Required, and 22 more"`
|
||||
);
|
||||
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(`"0.risk_score: Required"`);
|
||||
});
|
||||
|
||||
test('two array elements where the first is valid but the second is invalid (risk_score) will not validate', () => {
|
||||
|
@ -72,9 +70,7 @@ describe('Bulk create rules request schema', () => {
|
|||
|
||||
const result = BulkCreateRulesRequestBody.safeParse(payload);
|
||||
expectParseError(result);
|
||||
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
|
||||
`"1.risk_score: Required, 1.type: Invalid literal value, expected \\"eql\\", 1.language: Invalid literal value, expected \\"eql\\", 1.risk_score: Required, 1.risk_score: Required, and 22 more"`
|
||||
);
|
||||
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(`"1.risk_score: Required"`);
|
||||
});
|
||||
|
||||
test('two array elements where the first is invalid (risk_score) but the second is valid will not validate', () => {
|
||||
|
@ -86,9 +82,7 @@ describe('Bulk create rules request schema', () => {
|
|||
|
||||
const result = BulkCreateRulesRequestBody.safeParse(payload);
|
||||
expectParseError(result);
|
||||
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
|
||||
`"0.risk_score: Required, 0.type: Invalid literal value, expected \\"eql\\", 0.language: Invalid literal value, expected \\"eql\\", 0.risk_score: Required, 0.risk_score: Required, and 22 more"`
|
||||
);
|
||||
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(`"0.risk_score: Required"`);
|
||||
});
|
||||
|
||||
test('two array elements where both are invalid (risk_score) will not validate', () => {
|
||||
|
@ -103,7 +97,7 @@ describe('Bulk create rules request schema', () => {
|
|||
const result = BulkCreateRulesRequestBody.safeParse(payload);
|
||||
expectParseError(result);
|
||||
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
|
||||
`"0.risk_score: Required, 0.type: Invalid literal value, expected \\"eql\\", 0.language: Invalid literal value, expected \\"eql\\", 0.risk_score: Required, 0.risk_score: Required, and 49 more"`
|
||||
`"0.risk_score: Required, 1.risk_score: Required"`
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -130,7 +124,7 @@ describe('Bulk create rules request schema', () => {
|
|||
const result = BulkCreateRulesRequestBody.safeParse(payload);
|
||||
expectParseError(result);
|
||||
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
|
||||
`"0.severity: Invalid enum value. Expected 'low' | 'medium' | 'high' | 'critical', received 'madeup', 0.type: Invalid literal value, expected \\"eql\\", 0.language: Invalid literal value, expected \\"eql\\", 0.severity: Invalid enum value. Expected 'low' | 'medium' | 'high' | 'critical', received 'madeup', 0.severity: Invalid enum value. Expected 'low' | 'medium' | 'high' | 'critical', received 'madeup', and 22 more"`
|
||||
`"0.severity: Invalid enum value. Expected 'low' | 'medium' | 'high' | 'critical', received 'madeup'"`
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -165,7 +159,7 @@ describe('Bulk create rules request schema', () => {
|
|||
const result = BulkCreateRulesRequestBody.safeParse(payload);
|
||||
expectParseError(result);
|
||||
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
|
||||
`"0.note: Expected string, received object, 0.type: Invalid literal value, expected \\"eql\\", 0.language: Invalid literal value, expected \\"eql\\", 0.note: Expected string, received object, 0.note: Expected string, received object, and 22 more"`
|
||||
`"0.note: Expected string, received object"`
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -28,7 +28,7 @@ describe('Bulk update rules request schema', () => {
|
|||
const result = BulkUpdateRulesRequestBody.safeParse(payload);
|
||||
expectParseError(result);
|
||||
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
|
||||
`"0.name: Required, 0.description: Required, 0.risk_score: Required, 0.severity: Required, 0.type: Invalid literal value, expected \\"eql\\", and 52 more"`
|
||||
`"0.type: Invalid discriminator value. Expected 'eql' | 'query' | 'saved_query' | 'threshold' | 'threat_match' | 'machine_learning' | 'new_terms' | 'esql'"`
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -59,9 +59,7 @@ describe('Bulk update rules request schema', () => {
|
|||
|
||||
const result = BulkUpdateRulesRequestBody.safeParse(payload);
|
||||
expectParseError(result);
|
||||
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
|
||||
`"0.risk_score: Required, 0.type: Invalid literal value, expected \\"eql\\", 0.language: Invalid literal value, expected \\"eql\\", 0.risk_score: Required, 0.risk_score: Required, and 22 more"`
|
||||
);
|
||||
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(`"0.risk_score: Required"`);
|
||||
});
|
||||
|
||||
test('two array elements where the first is valid but the second is invalid (risk_score) will not validate', () => {
|
||||
|
@ -73,9 +71,7 @@ describe('Bulk update rules request schema', () => {
|
|||
|
||||
const result = BulkUpdateRulesRequestBody.safeParse(payload);
|
||||
expectParseError(result);
|
||||
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
|
||||
`"1.risk_score: Required, 1.type: Invalid literal value, expected \\"eql\\", 1.language: Invalid literal value, expected \\"eql\\", 1.risk_score: Required, 1.risk_score: Required, and 22 more"`
|
||||
);
|
||||
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(`"1.risk_score: Required"`);
|
||||
});
|
||||
|
||||
test('two array elements where the first is invalid (risk_score) but the second is valid will not validate', () => {
|
||||
|
@ -87,9 +83,7 @@ describe('Bulk update rules request schema', () => {
|
|||
|
||||
const result = BulkUpdateRulesRequestBody.safeParse(payload);
|
||||
expectParseError(result);
|
||||
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
|
||||
`"0.risk_score: Required, 0.type: Invalid literal value, expected \\"eql\\", 0.language: Invalid literal value, expected \\"eql\\", 0.risk_score: Required, 0.risk_score: Required, and 22 more"`
|
||||
);
|
||||
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(`"0.risk_score: Required"`);
|
||||
});
|
||||
|
||||
test('two array elements where both are invalid (risk_score) will not validate', () => {
|
||||
|
@ -104,7 +98,7 @@ describe('Bulk update rules request schema', () => {
|
|||
const result = BulkUpdateRulesRequestBody.safeParse(payload);
|
||||
expectParseError(result);
|
||||
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
|
||||
`"0.risk_score: Required, 0.type: Invalid literal value, expected \\"eql\\", 0.language: Invalid literal value, expected \\"eql\\", 0.risk_score: Required, 0.risk_score: Required, and 49 more"`
|
||||
`"0.risk_score: Required, 1.risk_score: Required"`
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -131,7 +125,7 @@ describe('Bulk update rules request schema', () => {
|
|||
const result = BulkUpdateRulesRequestBody.safeParse(payload);
|
||||
expectParseError(result);
|
||||
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
|
||||
`"0.severity: Invalid enum value. Expected 'low' | 'medium' | 'high' | 'critical', received 'madeup', 0.type: Invalid literal value, expected \\"eql\\", 0.language: Invalid literal value, expected \\"eql\\", 0.severity: Invalid enum value. Expected 'low' | 'medium' | 'high' | 'critical', received 'madeup', 0.severity: Invalid enum value. Expected 'low' | 'medium' | 'high' | 'critical', received 'madeup', and 22 more"`
|
||||
`"0.severity: Invalid enum value. Expected 'low' | 'medium' | 'high' | 'critical', received 'madeup'"`
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -176,7 +170,7 @@ describe('Bulk update rules request schema', () => {
|
|||
const result = BulkUpdateRulesRequestBody.safeParse(payload);
|
||||
expectParseError(result);
|
||||
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
|
||||
`"0.note: Expected string, received object, 0.type: Invalid literal value, expected \\"eql\\", 0.language: Invalid literal value, expected \\"eql\\", 0.note: Expected string, received object, 0.note: Expected string, received object, and 22 more"`
|
||||
`"0.note: Expected string, received object"`
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -46,7 +46,7 @@ describe('Bulk CRUD rules response schema', () => {
|
|||
const result = BulkCrudRulesResponse.safeParse(payload);
|
||||
expectParseError(result);
|
||||
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
|
||||
`"0.error: Required, 0: Unrecognized key(s) in object: 'author', 'created_at', 'updated_at', 'created_by', 'description', 'enabled', 'false_positives', 'from', 'immutable', 'references', 'revision', 'severity', 'severity_mapping', 'updated_by', 'tags', 'to', 'threat', 'version', 'output_index', 'max_signals', 'risk_score', 'risk_score_mapping', 'interval', 'exceptions_list', 'related_integrations', 'required_fields', 'setup', 'throttle', 'actions', 'building_block_type', 'note', 'license', 'outcome', 'alias_target_id', 'alias_purpose', 'timeline_id', 'timeline_title', 'meta', 'rule_name_override', 'timestamp_override', 'timestamp_override_fallback_disabled', 'namespace', 'investigation_fields', 'query', 'type', 'language', 'index', 'data_view_id', 'filters', 'saved_id', 'response_actions', 'alert_suppression', 0.name: Required, 0.type: Invalid literal value, expected \\"eql\\", 0.language: Invalid literal value, expected \\"eql\\", and 24 more"`
|
||||
`"0.name: Required, 0.error: Required, 0: Unrecognized key(s) in object: 'author', 'created_at', 'updated_at', 'created_by', 'description', 'enabled', 'false_positives', 'from', 'immutable', 'references', 'revision', 'severity', 'severity_mapping', 'updated_by', 'tags', 'to', 'threat', 'version', 'output_index', 'max_signals', 'risk_score', 'risk_score_mapping', 'interval', 'exceptions_list', 'related_integrations', 'required_fields', 'setup', 'throttle', 'actions', 'building_block_type', 'note', 'license', 'outcome', 'alias_target_id', 'alias_purpose', 'timeline_id', 'timeline_title', 'meta', 'rule_name_override', 'timestamp_override', 'timestamp_override_fallback_disabled', 'namespace', 'investigation_fields', 'query', 'type', 'language', 'index', 'data_view_id', 'filters', 'saved_id', 'response_actions', 'alert_suppression'"`
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -59,7 +59,7 @@ describe('Bulk CRUD rules response schema', () => {
|
|||
const result = BulkCrudRulesResponse.safeParse(payload);
|
||||
expectParseError(result);
|
||||
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
|
||||
`"0.error: Required, 0.name: Required, 0.description: Required, 0.risk_score: Required, 0.severity: Required, and 267 more"`
|
||||
`"0.type: Invalid discriminator value. Expected 'eql' | 'query' | 'saved_query' | 'threshold' | 'threat_match' | 'machine_learning' | 'new_terms' | 'esql', 0.error: Required"`
|
||||
);
|
||||
});
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ describe('RuleToImport', () => {
|
|||
expectParseError(result);
|
||||
|
||||
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
|
||||
`"name: Required, description: Required, risk_score: Required, severity: Required, rule_id: Required, and 25 more"`
|
||||
`"name: Required, description: Required, risk_score: Required, severity: Required, type: Invalid discriminator value. Expected 'eql' | 'query' | 'saved_query' | 'threshold' | 'threat_match' | 'machine_learning' | 'new_terms' | 'esql', and 1 more"`
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -47,7 +47,7 @@ describe('RuleToImport', () => {
|
|||
expectParseError(result);
|
||||
|
||||
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
|
||||
`"name: Required, description: Required, risk_score: Required, severity: Required, type: Invalid literal value, expected \\"eql\\", and 24 more"`
|
||||
`"name: Required, description: Required, risk_score: Required, severity: Required, type: Invalid discriminator value. Expected 'eql' | 'query' | 'saved_query' | 'threshold' | 'threat_match' | 'machine_learning' | 'new_terms' | 'esql'"`
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -61,7 +61,7 @@ describe('RuleToImport', () => {
|
|||
expectParseError(result);
|
||||
|
||||
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
|
||||
`"name: Required, risk_score: Required, severity: Required, type: Invalid literal value, expected \\"eql\\", query: Required, and 23 more"`
|
||||
`"name: Required, risk_score: Required, severity: Required, type: Invalid discriminator value. Expected 'eql' | 'query' | 'saved_query' | 'threshold' | 'threat_match' | 'machine_learning' | 'new_terms' | 'esql'"`
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -76,7 +76,7 @@ describe('RuleToImport', () => {
|
|||
expectParseError(result);
|
||||
|
||||
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
|
||||
`"name: Required, risk_score: Required, severity: Required, type: Invalid literal value, expected \\"eql\\", query: Required, and 23 more"`
|
||||
`"name: Required, risk_score: Required, severity: Required, type: Invalid discriminator value. Expected 'eql' | 'query' | 'saved_query' | 'threshold' | 'threat_match' | 'machine_learning' | 'new_terms' | 'esql'"`
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -330,7 +330,7 @@ describe('RuleToImport', () => {
|
|||
expectParseError(result);
|
||||
|
||||
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
|
||||
`"type: Invalid literal value, expected \\"eql\\", language: Invalid literal value, expected \\"eql\\", index.0: Expected string, received number, index.0: Expected string, received number, type: Invalid literal value, expected \\"saved_query\\", and 20 more"`
|
||||
`"index.0: Expected string, received number"`
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -378,7 +378,7 @@ describe('RuleToImport', () => {
|
|||
expectParseError(result);
|
||||
|
||||
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
|
||||
`"type: Invalid literal value, expected \\"eql\\", language: Invalid literal value, expected \\"eql\\", filters: Expected array, received string, filters: Expected array, received string, type: Invalid literal value, expected \\"saved_query\\", and 20 more"`
|
||||
`"filters: Expected array, received string"`
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -414,7 +414,7 @@ describe('RuleToImport', () => {
|
|||
expectParseError(result);
|
||||
|
||||
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
|
||||
`"type: Invalid literal value, expected \\"eql\\", language: Invalid literal value, expected \\"eql\\", language: Invalid enum value. Expected 'kuery' | 'lucene', received 'something-made-up', type: Invalid literal value, expected \\"saved_query\\", saved_id: Required, and 19 more"`
|
||||
`"language: Invalid enum value. Expected 'kuery' | 'lucene', received 'something-made-up'"`
|
||||
);
|
||||
});
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
import * as z from 'zod';
|
||||
import {
|
||||
BaseCreateProps,
|
||||
ResponseRequiredFields,
|
||||
ResponseFields,
|
||||
RuleSignatureId,
|
||||
TypeSpecificCreateProps,
|
||||
} from '../../model/rule_schema';
|
||||
|
@ -26,7 +26,7 @@ import {
|
|||
export type RuleToImport = z.infer<typeof RuleToImport>;
|
||||
export type RuleToImportInput = z.input<typeof RuleToImport>;
|
||||
export const RuleToImport = BaseCreateProps.and(TypeSpecificCreateProps).and(
|
||||
ResponseRequiredFields.partial().extend({
|
||||
ResponseFields.partial().extend({
|
||||
rule_id: RuleSignatureId,
|
||||
immutable: z.literal(false).default(false),
|
||||
})
|
||||
|
|
|
@ -15,7 +15,7 @@ import { z } from 'zod';
|
|||
import { BaseActionSchema, Command, Timeout } from '../model/schema/common.gen';
|
||||
|
||||
export type ExecuteActionRequestBody = z.infer<typeof ExecuteActionRequestBody>;
|
||||
export const ExecuteActionRequestBody = BaseActionSchema.and(
|
||||
export const ExecuteActionRequestBody = BaseActionSchema.merge(
|
||||
z.object({
|
||||
parameters: z.object({
|
||||
command: Command,
|
||||
|
|
|
@ -15,7 +15,7 @@ import { z } from 'zod';
|
|||
import { BaseActionSchema } from '../model/schema/common.gen';
|
||||
|
||||
export type FileUploadActionRequestBody = z.infer<typeof FileUploadActionRequestBody>;
|
||||
export const FileUploadActionRequestBody = BaseActionSchema.and(
|
||||
export const FileUploadActionRequestBody = BaseActionSchema.merge(
|
||||
z.object({
|
||||
parameters: z.object({
|
||||
overwrite: z.boolean().optional().default(false),
|
||||
|
|
|
@ -15,7 +15,7 @@ import { z } from 'zod';
|
|||
import { BaseActionSchema } from '../model/schema/common.gen';
|
||||
|
||||
export type GetFileActionRequestBody = z.infer<typeof GetFileActionRequestBody>;
|
||||
export const GetFileActionRequestBody = BaseActionSchema.and(
|
||||
export const GetFileActionRequestBody = BaseActionSchema.merge(
|
||||
z.object({
|
||||
parameters: z.object({
|
||||
path: z.string(),
|
||||
|
|
|
@ -145,7 +145,7 @@ export const BaseActionSchema = z.object({
|
|||
});
|
||||
|
||||
export type ProcessActionSchemas = z.infer<typeof ProcessActionSchemas>;
|
||||
export const ProcessActionSchemas = BaseActionSchema.and(
|
||||
export const ProcessActionSchemas = BaseActionSchema.merge(
|
||||
z.object({
|
||||
parameters: z.union([
|
||||
z.object({
|
||||
|
|
|
@ -25,6 +25,7 @@ import type {
|
|||
Threats,
|
||||
} from '@kbn/securitysolution-io-ts-alerting-types';
|
||||
import { ALERT_RISK_SCORE } from '@kbn/rule-data-utils';
|
||||
import { requiredOptional } from '@kbn/zod-helpers';
|
||||
import type { RuleResponse } from '../../../../../common/api/detection_engine/model/rule_schema';
|
||||
import { SeverityBadge } from '../../../../detections/components/rules/severity_badge';
|
||||
import { defaultToEmptyTag } from '../../../../common/components/empty_value';
|
||||
|
@ -333,7 +334,9 @@ const prepareAboutSectionListItems = (
|
|||
) : (
|
||||
''
|
||||
),
|
||||
description: <RiskScoreMappingItem riskScoreMappingItem={riskScoreMappingItem} />,
|
||||
description: (
|
||||
<RiskScoreMappingItem riskScoreMappingItem={requiredOptional(riskScoreMappingItem)} />
|
||||
),
|
||||
};
|
||||
})
|
||||
);
|
||||
|
|
|
@ -21,6 +21,7 @@ import type {
|
|||
import { ENDPOINT_LIST_ID } from '@kbn/securitysolution-list-constants';
|
||||
import type { Filter } from '@kbn/es-query';
|
||||
import type { ActionVariables } from '@kbn/triggers-actions-ui-plugin/public';
|
||||
import { requiredOptional } from '@kbn/zod-helpers';
|
||||
import type { ResponseAction } from '../../../../../common/api/detection_engine/model/rule_response_actions';
|
||||
import { normalizeThresholdField } from '../../../../../common/detection_engine/utils';
|
||||
import { assertUnreachable } from '../../../../../common/utility_types';
|
||||
|
@ -253,7 +254,7 @@ export const getAboutStepsData = (rule: RuleResponse, detailsView: boolean): Abo
|
|||
tags,
|
||||
riskScore: {
|
||||
value: riskScore,
|
||||
mapping: riskScoreMapping,
|
||||
mapping: requiredOptional(riskScoreMapping),
|
||||
isMappingChecked: riskScoreMapping.length > 0,
|
||||
},
|
||||
falsePositives,
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
|
||||
import type { RuleActionArray } from '@kbn/securitysolution-io-ts-alerting-types';
|
||||
import { requiredOptional } from '@kbn/zod-helpers';
|
||||
import { DEFAULT_MAX_SIGNALS } from '../../../../../../../common/constants';
|
||||
import { assertUnreachable } from '../../../../../../../common/utility_types';
|
||||
import type {
|
||||
|
@ -123,7 +124,7 @@ const extractDiffableCommonFields = (
|
|||
severity: rule.severity,
|
||||
severity_mapping: rule.severity_mapping ?? [],
|
||||
risk_score: rule.risk_score,
|
||||
risk_score_mapping: rule.risk_score_mapping ?? [],
|
||||
risk_score_mapping: rule.risk_score_mapping?.map((mapping) => requiredOptional(mapping)) ?? [],
|
||||
|
||||
// About -> Advanced settings
|
||||
references: rule.references ?? [],
|
||||
|
|
|
@ -17,7 +17,7 @@ describe('Prebuilt rule asset schema', () => {
|
|||
const result = PrebuiltRuleAsset.safeParse(payload);
|
||||
expectParseError(result);
|
||||
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
|
||||
`"name: Required, description: Required, risk_score: Required, severity: Required, rule_id: Required, and 26 more"`
|
||||
`"name: Required, description: Required, risk_score: Required, severity: Required, type: Invalid discriminator value. Expected 'eql' | 'query' | 'saved_query' | 'threshold' | 'threat_match' | 'machine_learning' | 'new_terms' | 'esql', and 2 more"`
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -40,7 +40,7 @@ describe('Prebuilt rule asset schema', () => {
|
|||
const result = PrebuiltRuleAsset.safeParse(payload);
|
||||
expectParseError(result);
|
||||
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
|
||||
`"name: Required, description: Required, risk_score: Required, severity: Required, version: Required, and 25 more"`
|
||||
`"name: Required, description: Required, risk_score: Required, severity: Required, type: Invalid discriminator value. Expected 'eql' | 'query' | 'saved_query' | 'threshold' | 'threat_match' | 'machine_learning' | 'new_terms' | 'esql', and 1 more"`
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -177,7 +177,7 @@ describe('Prebuilt rule asset schema', () => {
|
|||
const result = PrebuiltRuleAsset.safeParse(payload);
|
||||
expectParseError(result);
|
||||
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
|
||||
`"type: Invalid literal value, expected \\"eql\\", language: Invalid literal value, expected \\"eql\\", index.0: Expected string, received number, index.0: Expected string, received number, type: Invalid literal value, expected \\"saved_query\\", and 20 more"`
|
||||
`"index.0: Expected string, received number"`
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -201,7 +201,7 @@ describe('Prebuilt rule asset schema', () => {
|
|||
const result = PrebuiltRuleAsset.safeParse(payload);
|
||||
expectParseError(result);
|
||||
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
|
||||
`"type: Invalid literal value, expected \\"eql\\", language: Invalid literal value, expected \\"eql\\", filters: Expected array, received string, filters: Expected array, received string, type: Invalid literal value, expected \\"saved_query\\", and 20 more"`
|
||||
`"filters: Expected array, received string"`
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -236,7 +236,7 @@ describe('Prebuilt rule asset schema', () => {
|
|||
const result = PrebuiltRuleAsset.safeParse(payload);
|
||||
expectParseError(result);
|
||||
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
|
||||
`"type: Invalid literal value, expected \\"eql\\", language: Invalid literal value, expected \\"eql\\", language: Invalid enum value. Expected 'kuery' | 'lucene', received 'something-made-up', type: Invalid literal value, expected \\"saved_query\\", saved_id: Required, and 19 more"`
|
||||
`"language: Invalid enum value. Expected 'kuery' | 'lucene', received 'something-made-up'"`
|
||||
);
|
||||
});
|
||||
|
||||
|
|
|
@ -237,7 +237,7 @@ describe('Create rule route', () => {
|
|||
});
|
||||
const result = await server.validate(request);
|
||||
expect(result.badRequest).toHaveBeenCalledWith(
|
||||
'type: Invalid literal value, expected "eql", language: Invalid literal value, expected "eql", type: Invalid literal value, expected "saved_query", saved_id: Required, type: Invalid literal value, expected "threshold", and 18 more'
|
||||
'response_actions.0.action_type_id: Invalid literal value, expected ".osquery", response_actions.0.params.command: Invalid literal value, expected "isolate"'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -284,7 +284,7 @@ describe('Update rule route', () => {
|
|||
});
|
||||
const result = await server.validate(request);
|
||||
expect(result.badRequest).toHaveBeenCalledWith(
|
||||
'type: Invalid literal value, expected "eql", language: Invalid literal value, expected "eql", type: Invalid literal value, expected "saved_query", saved_id: Required, type: Invalid literal value, expected "threshold", and 18 more'
|
||||
`response_actions.0.action_type_id: Invalid literal value, expected \".osquery\", response_actions.0.params.command: Invalid literal value, expected \"isolate\"`
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -283,7 +283,7 @@ describe('create_rules_stream_from_ndjson', () => {
|
|||
immutable: false,
|
||||
});
|
||||
expect(resultOrError[1].message).toContain(
|
||||
'name: Required, description: Required, risk_score: Required, severity: Required, rule_id: Required, and 25 more'
|
||||
`name: Required, description: Required, risk_score: Required, severity: Required, type: Invalid discriminator value. Expected 'eql' | 'query' | 'saved_query' | 'threshold' | 'threat_match' | 'machine_learning' | 'new_terms' | 'esql', and 1 more`
|
||||
);
|
||||
expect(resultOrError[2]).toEqual({
|
||||
rule_id: 'rule-2',
|
||||
|
|
|
@ -95,7 +95,7 @@ describe('validate', () => {
|
|||
delete ruleAlert.name;
|
||||
expect(() => {
|
||||
transformValidate(ruleAlert);
|
||||
}).toThrowError('Invalid input');
|
||||
}).toThrowError('Required');
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -113,8 +113,7 @@ describe('validate', () => {
|
|||
const validatedOrError = transformValidateBulkError('rule-1', ruleAlert);
|
||||
const expected: BulkError = {
|
||||
error: {
|
||||
message:
|
||||
'name: Required, type: Invalid literal value, expected "eql", language: Invalid literal value, expected "eql", name: Required, name: Required, and 22 more',
|
||||
message: 'name: Required',
|
||||
status_code: 500,
|
||||
},
|
||||
rule_id: 'rule-1',
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
import { each, map, some, uniq } from 'lodash';
|
||||
import { containsDynamicQuery } from '@kbn/osquery-plugin/common/utils/replace_params_query';
|
||||
import { requiredOptional } from '@kbn/zod-helpers';
|
||||
import type { ResponseActionAlerts } from './types';
|
||||
import type { SetupPlugins } from '../../../plugin_contract';
|
||||
import type { RuleResponseOsqueryAction } from '../../../../common/api/detection_engine/model/rule_response_actions';
|
||||
|
@ -32,7 +33,7 @@ export const osqueryResponseAction = (
|
|||
|
||||
return osqueryCreateActionService.create({
|
||||
...rest,
|
||||
queries,
|
||||
queries: requiredOptional(queries),
|
||||
ecs_mapping: ecsMapping,
|
||||
saved_query_id: savedQueryId,
|
||||
agent_ids: agentIds,
|
||||
|
@ -43,7 +44,7 @@ export const osqueryResponseAction = (
|
|||
return osqueryCreateActionService.create(
|
||||
{
|
||||
...rest,
|
||||
queries,
|
||||
queries: requiredOptional(queries),
|
||||
ecs_mapping: ecsMapping,
|
||||
saved_query_id: savedQueryId,
|
||||
agent_ids: alert.agent?.id ? [alert.agent.id] : [],
|
||||
|
|
|
@ -43,6 +43,7 @@ import {
|
|||
TIMESTAMP,
|
||||
} from '@kbn/rule-data-utils';
|
||||
import { flattenWithPrefix } from '@kbn/securitysolution-rules';
|
||||
import { requiredOptional } from '@kbn/zod-helpers';
|
||||
|
||||
import { createHash } from 'crypto';
|
||||
|
||||
|
@ -229,7 +230,7 @@ export const buildAlert = (
|
|||
[ALERT_RULE_NAMESPACE_FIELD]: params.namespace,
|
||||
[ALERT_RULE_NOTE]: params.note,
|
||||
[ALERT_RULE_REFERENCES]: params.references,
|
||||
[ALERT_RULE_RISK_SCORE_MAPPING]: params.riskScoreMapping,
|
||||
[ALERT_RULE_RISK_SCORE_MAPPING]: requiredOptional(params.riskScoreMapping),
|
||||
[ALERT_RULE_RULE_ID]: params.ruleId,
|
||||
[ALERT_RULE_RULE_NAME_OVERRIDE]: params.ruleNameOverride,
|
||||
[ALERT_RULE_SEVERITY_MAPPING]: params.severityMapping,
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
import { flattenWithPrefix } from '@kbn/securitysolution-rules';
|
||||
import type * as estypes from '@elastic/elasticsearch/lib/api/types';
|
||||
import { requiredOptional } from '@kbn/zod-helpers';
|
||||
|
||||
import type { BaseHit, SearchTypes } from '../../../../../../common/detection_engine/types';
|
||||
import type { ConfigType } from '../../../../../config';
|
||||
|
@ -92,7 +93,7 @@ export const buildBulkBody = (
|
|||
riskScoreOverride: buildRiskScoreFromMapping({
|
||||
eventSource: mergedDoc._source ?? {},
|
||||
riskScore: completeRule.ruleParams.riskScore,
|
||||
riskScoreMapping: completeRule.ruleParams.riskScoreMapping,
|
||||
riskScoreMapping: requiredOptional(completeRule.ruleParams.riskScoreMapping),
|
||||
}).riskScore,
|
||||
}
|
||||
: undefined;
|
||||
|
|
|
@ -447,7 +447,7 @@ export default ({ getService }: FtrProviderContext): void => {
|
|||
.expect(400);
|
||||
|
||||
expect(body.message).to.eql(
|
||||
'[request body]: 0.investigation_fields: Expected object, received array, 0.type: Invalid literal value, expected "eql", 0.language: Invalid literal value, expected "eql", 0.investigation_fields: Expected object, received array, 0.investigation_fields: Expected object, received array, and 22 more'
|
||||
'[request body]: 0.investigation_fields: Expected object, received array'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -411,11 +411,7 @@ export default ({ getService }: FtrProviderContext): void => {
|
|||
|
||||
expect(body.errors[0]).to.eql({
|
||||
rule_id: '(unknown id)',
|
||||
error: {
|
||||
message:
|
||||
'type: Invalid literal value, expected "eql", language: Invalid literal value, expected "eql", type: Invalid literal value, expected "query", type: Invalid literal value, expected "saved_query", saved_id: Required, and 14 more',
|
||||
status_code: 400,
|
||||
},
|
||||
error: { status_code: 400, message: 'threshold: Required' },
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -566,8 +566,7 @@ export default ({ getService }: FtrProviderContext) => {
|
|||
|
||||
expect(body).to.eql({
|
||||
error: 'Bad Request',
|
||||
message:
|
||||
'[request body]: type: Invalid literal value, expected "eql", language: Invalid literal value, expected "eql", type: Invalid literal value, expected "query", type: Invalid literal value, expected "saved_query", saved_id: Required, and 14 more',
|
||||
message: '[request body]: threshold: Required',
|
||||
statusCode: 400,
|
||||
});
|
||||
});
|
||||
|
@ -957,7 +956,7 @@ export default ({ getService }: FtrProviderContext) => {
|
|||
.expect(400);
|
||||
|
||||
expect(body.message).to.eql(
|
||||
'[request body]: investigation_fields: Expected object, received array, type: Invalid literal value, expected "eql", language: Invalid literal value, expected "eql", investigation_fields: Expected object, received array, investigation_fields: Expected object, received array, and 22 more'
|
||||
'[request body]: investigation_fields: Expected object, received array'
|
||||
);
|
||||
});
|
||||
|
||||
|
|
|
@ -854,7 +854,7 @@ export default ({ getService }: FtrProviderContext) => {
|
|||
.expect(400);
|
||||
|
||||
expect(body.message).to.eql(
|
||||
'[request body]: 0.investigation_fields: Expected object, received array, 0.type: Invalid literal value, expected "eql", 0.language: Invalid literal value, expected "eql", 0.investigation_fields: Expected object, received array, 0.investigation_fields: Expected object, received array, and 22 more'
|
||||
'[request body]: 0.investigation_fields: Expected object, received array'
|
||||
);
|
||||
});
|
||||
|
||||
|
|
|
@ -431,8 +431,7 @@ export default ({ getService }: FtrProviderContext) => {
|
|||
|
||||
expect(body).toEqual({
|
||||
error: 'Bad Request',
|
||||
message:
|
||||
'[request body]: type: Invalid literal value, expected "eql", language: Invalid literal value, expected "eql", type: Invalid literal value, expected "query", type: Invalid literal value, expected "saved_query", saved_id: Required, and 14 more',
|
||||
message: '[request body]: threshold: Required',
|
||||
statusCode: 400,
|
||||
});
|
||||
});
|
||||
|
@ -541,7 +540,7 @@ export default ({ getService }: FtrProviderContext) => {
|
|||
.expect(400);
|
||||
|
||||
expect(body.message).toBe(
|
||||
'[request body]: investigation_fields: Expected object, received array, type: Invalid literal value, expected "eql", language: Invalid literal value, expected "eql", investigation_fields: Expected object, received array, investigation_fields: Expected object, received array, and 22 more'
|
||||
'[request body]: investigation_fields: Expected object, received array'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue