Skip to content

Commit

Permalink
integrate rule preview generated artifacts
Browse files Browse the repository at this point in the history
  • Loading branch information
maximpn committed Jul 12, 2024
1 parent a094063 commit 8530c90
Show file tree
Hide file tree
Showing 10 changed files with 109 additions and 54 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,4 @@
* 2.0.
*/

export * from './preview_rules_route';
export * from './rule_preview.gen';

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,24 @@

import { z } from 'zod';

import {
EqlRuleCreateProps,
QueryRuleCreateProps,
SavedQueryRuleCreateProps,
ThresholdRuleCreateProps,
ThreatMatchRuleCreateProps,
MachineLearningRuleCreateProps,
NewTermsRuleCreateProps,
EsqlRuleCreateProps,
} from '../model/rule_schema/rule_schemas.gen';
import { NonEmptyString } from '../../model/primitives.gen';

export type RulePreviewParams = z.infer<typeof RulePreviewParams>;
export const RulePreviewParams = z.object({
invocationCount: z.number().int(),
timeframeEnd: z.string().datetime(),
});

export type RulePreviewLogs = z.infer<typeof RulePreviewLogs>;
export const RulePreviewLogs = z.object({
errors: z.array(NonEmptyString),
Expand All @@ -28,3 +44,23 @@ export const RulePreviewLogs = z.object({
duration: z.number().int(),
startedAt: NonEmptyString.optional(),
});

export type RulePreviewRequestBody = z.infer<typeof RulePreviewRequestBody>;
export const RulePreviewRequestBody = z.discriminatedUnion('type', [
EqlRuleCreateProps.merge(RulePreviewParams),
QueryRuleCreateProps.merge(RulePreviewParams),
SavedQueryRuleCreateProps.merge(RulePreviewParams),
ThresholdRuleCreateProps.merge(RulePreviewParams),
ThreatMatchRuleCreateProps.merge(RulePreviewParams),
MachineLearningRuleCreateProps.merge(RulePreviewParams),
NewTermsRuleCreateProps.merge(RulePreviewParams),
EsqlRuleCreateProps.merge(RulePreviewParams),
]);
export type RulePreviewRequestBodyInput = z.input<typeof RulePreviewRequestBody>;

export type RulePreviewResponse = z.infer<typeof RulePreviewResponse>;
export const RulePreviewResponse = z.object({
logs: z.array(RulePreviewLogs),
previewId: NonEmptyString.optional(),
isAborted: z.boolean().optional(),
});
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,7 @@ paths:
post:
x-labels: [serverless, ess]
operationId: RulePreview
# Code generator changes are required to build a valid request body Zod schema
# TypeSpecificCreateProps gets transformed to a discriminated union which
# doesn't have `merge` method code generator uses for `allOf`
# `preview_rules_route.ts` contains manually written Zod schemas
x-codegen-enabled: false
x-codegen-enabled: true
summary: Preview rule alerts generated on specified time range
tags:
- Rule preview API
Expand All @@ -21,18 +17,33 @@ paths:
content:
application/json:
schema:
allOf:
- type: object
properties:
invocationCount:
type: integer
minimum: 1
timeframeEnd:
type: string
format: date-time
required: [invocationCount, timeframeEnd]
- $ref: '../model/rule_schema/rule_schemas.schema.yaml#/components/schemas/SharedCreateProps'
- $ref: '../model/rule_schema/rule_schemas.schema.yaml#/components/schemas/TypeSpecificCreateProps'
discriminator:
propertyName: type
anyOf:
- allOf:
- $ref: '../model/rule_schema/rule_schemas.schema.yaml#/components/schemas/EqlRuleCreateProps'
- $ref: '#/components/schemas/RulePreviewParams'
- allOf:
- $ref: '../model/rule_schema/rule_schemas.schema.yaml#/components/schemas/QueryRuleCreateProps'
- $ref: '#/components/schemas/RulePreviewParams'
- allOf:
- $ref: '../model/rule_schema/rule_schemas.schema.yaml#/components/schemas/SavedQueryRuleCreateProps'
- $ref: '#/components/schemas/RulePreviewParams'
- allOf:
- $ref: '../model/rule_schema/rule_schemas.schema.yaml#/components/schemas/ThresholdRuleCreateProps'
- $ref: '#/components/schemas/RulePreviewParams'
- allOf:
- $ref: '../model/rule_schema/rule_schemas.schema.yaml#/components/schemas/ThreatMatchRuleCreateProps'
- $ref: '#/components/schemas/RulePreviewParams'
- allOf:
- $ref: '../model/rule_schema/rule_schemas.schema.yaml#/components/schemas/MachineLearningRuleCreateProps'
- $ref: '#/components/schemas/RulePreviewParams'
- allOf:
- $ref: '../model/rule_schema/rule_schemas.schema.yaml#/components/schemas/NewTermsRuleCreateProps'
- $ref: '#/components/schemas/RulePreviewParams'
- allOf:
- $ref: '../model/rule_schema/rule_schemas.schema.yaml#/components/schemas/EsqlRuleCreateProps'
- $ref: '#/components/schemas/RulePreviewParams'
responses:
200:
description: Successful response
Expand All @@ -42,7 +53,9 @@ paths:
type: object
properties:
logs:
$ref: '#/components/schemas/RulePreviewLogs'
type: array
items:
$ref: '#/components/schemas/RulePreviewLogs'
previewId:
$ref: '../../model/primitives.schema.yaml#/components/schemas/NonEmptyString'
isAborted:
Expand Down Expand Up @@ -71,6 +84,16 @@ paths:

components:
schemas:
RulePreviewParams:
type: object
properties:
invocationCount:
type: integer
timeframeEnd:
type: string
format: date-time
required: [invocationCount, timeframeEnd]

RulePreviewLogs:
type: object
properties:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,18 @@
import { useEffect, useMemo, useState } from 'react';

import { useAppToasts } from '../../../../common/hooks/use_app_toasts';
import type { PreviewResponse, RuleCreateProps } from '../../../../../common/api/detection_engine';
import type {
RuleCreateProps,
RulePreviewResponse,
} from '../../../../../common/api/detection_engine';

import { previewRule } from '../../../rule_management/api/api';
import { transformOutput } from '../../../../detections/containers/detection_engine/rules/transforms';
import type { TimeframePreviewOptions } from '../../../../detections/pages/detection_engine/rules/types';
import { usePreviewInvocationCount } from './use_preview_invocation_count';
import * as i18n from './translations';

const emptyPreviewRule: PreviewResponse = {
const emptyPreviewRule: RulePreviewResponse = {
previewId: undefined,
logs: [],
isAborted: false,
Expand All @@ -28,7 +31,7 @@ export const usePreviewRule = ({
timeframeOptions: TimeframePreviewOptions;
}) => {
const [rule, setRule] = useState<RuleCreateProps | null>(null);
const [response, setResponse] = useState<PreviewResponse>(emptyPreviewRule);
const [response, setResponse] = useState<RulePreviewResponse>(emptyPreviewRule);
const [isLoading, setIsLoading] = useState(false);
const { addError } = useAppToasts();
const { invocationCount, interval, from } = usePreviewInvocationCount({ timeframeOptions });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ import {
import type { RulesReferencedByExceptionListsSchema } from '../../../../common/api/detection_engine/rule_exceptions';
import { DETECTION_ENGINE_RULES_EXCEPTIONS_REFERENCE_URL } from '../../../../common/api/detection_engine/rule_exceptions';

import type { PreviewResponse, RuleResponse } from '../../../../common/api/detection_engine';
import type { RulePreviewResponse, RuleResponse } from '../../../../common/api/detection_engine';

import { KibanaServices } from '../../../common/lib/kibana';
import * as i18n from '../../../detections/pages/detection_engine/rules/translations';
Expand Down Expand Up @@ -149,8 +149,11 @@ export const patchRule = async ({
*
* @throws An error if response is not OK
*/
export const previewRule = async ({ rule, signal }: PreviewRulesProps): Promise<PreviewResponse> =>
KibanaServices.get().http.fetch<PreviewResponse>(DETECTION_ENGINE_RULES_PREVIEW, {
export const previewRule = async ({
rule,
signal,
}: PreviewRulesProps): Promise<RulePreviewResponse> =>
KibanaServices.get().http.fetch<RulePreviewResponse>(DETECTION_ENGINE_RULES_PREVIEW, {
method: 'POST',
version: '2023-10-31',
body: JSON.stringify(rule),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,10 @@ import {
import { validateCreateRuleProps } from '../../../../../../common/api/detection_engine/rule_management';
import { RuleExecutionStatusEnum } from '../../../../../../common/api/detection_engine/rule_monitoring';
import type {
PreviewResponse,
RulePreviewResponse,
RulePreviewLogs,
} from '../../../../../../common/api/detection_engine';
import { PreviewRulesSchema } from '../../../../../../common/api/detection_engine';
import { RulePreviewRequestBody } from '../../../../../../common/api/detection_engine';

import type { StartPlugins, SetupPlugins } from '../../../../../plugin';
import { buildSiemResponse } from '../../../routes/utils';
Expand Down Expand Up @@ -92,9 +92,9 @@ export const previewRulesRoute = (
.addVersion(
{
version: '2023-10-31',
validate: { request: { body: buildRouteValidationWithZod(PreviewRulesSchema) } },
validate: { request: { body: buildRouteValidationWithZod(RulePreviewRequestBody) } },
},
async (context, request, response): Promise<IKibanaResponse<PreviewResponse>> => {
async (context, request, response): Promise<IKibanaResponse<RulePreviewResponse>> => {
const siemResponse = buildSiemResponse(response);
const validationErrors = validateCreateRuleProps(request.body);
const coreContext = await context.core;
Expand Down
12 changes: 12 additions & 0 deletions x-pack/test/api_integration/services/security_solution_api.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ import {
PerformBulkActionRequestBodyInput,
} from '@kbn/security-solution-plugin/common/api/detection_engine/rule_management/bulk_actions/bulk_actions_route.gen';
import { ReadRuleRequestQueryInput } from '@kbn/security-solution-plugin/common/api/detection_engine/rule_management/crud/read_rule/read_rule_route.gen';
import { RulePreviewRequestBodyInput } from '@kbn/security-solution-plugin/common/api/detection_engine/rule_preview/rule_preview.gen';
import { SearchAlertsRequestBodyInput } from '@kbn/security-solution-plugin/common/api/detection_engine/signals/query_signals/query_signals_route.gen';
import { SetAlertAssigneesRequestBodyInput } from '@kbn/security-solution-plugin/common/api/detection_engine/alert_assignees/set_alert_assignees_route.gen';
import { SetAlertsStatusRequestBodyInput } from '@kbn/security-solution-plugin/common/api/detection_engine/signals/set_signal_status/set_signals_status_route.gen';
Expand Down Expand Up @@ -409,6 +410,14 @@ detection engine rules.
.set(ELASTIC_HTTP_VERSION_HEADER, '2023-10-31')
.set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana');
},
rulePreview(props: RulePreviewProps) {
return supertest
.post('/api/detection_engine/rules/preview')
.set('kbn-xsrf', 'true')
.set(ELASTIC_HTTP_VERSION_HEADER, '2023-10-31')
.set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana')
.send(props.body as object);
},
searchAlerts(props: SearchAlertsProps) {
return supertest
.post('/api/detection_engine/signals/search')
Expand Down Expand Up @@ -548,6 +557,9 @@ export interface PerformBulkActionProps {
export interface ReadRuleProps {
query: ReadRuleRequestQueryInput;
}
export interface RulePreviewProps {
body: RulePreviewRequestBodyInput;
}
export interface SearchAlertsProps {
body: SearchAlertsRequestBodyInput;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* 2.0.
*/

import type { PreviewRulesSchema } from '@kbn/security-solution-plugin/common/api/detection_engine';
import type { RulePreviewRequestBody } from '@kbn/security-solution-plugin/common/api/detection_engine';

/**
* This is a typical simple preview rule for testing that is easy for most basic testing
Expand All @@ -16,7 +16,7 @@ import type { PreviewRulesSchema } from '@kbn/security-solution-plugin/common/ap
export const getSimplePreviewRule = (
ruleId = 'preview-rule-1',
invocationCount = 12
): PreviewRulesSchema => ({
): RulePreviewRequestBody => ({
name: 'Simple Rule Query',
description: 'Simple Rule Query',
risk_score: 1,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import type SuperTest from 'supertest';
import type {
RuleCreateProps,
PreviewRulesSchema,
RulePreviewRequestBody,
RulePreviewLogs,
} from '@kbn/security-solution-plugin/common/api/detection_engine';

Expand Down Expand Up @@ -36,7 +36,7 @@ export const previewRule = async ({
logs: RulePreviewLogs[];
isAborted: boolean;
}> => {
const previewRequest: PreviewRulesSchema = {
const previewRequest: RulePreviewRequestBody = {
...rule,
invocationCount,
timeframeEnd: timeframeEnd.toISOString(),
Expand Down

0 comments on commit 8530c90

Please sign in to comment.