mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
[Security Solution] Added OpenAPI schema definitions for rules management (#162641)
**Related to: https://github.com/elastic/security-team/issues/7131** ## Summary This PR introduces OpenAPI declarations for our public Rules Management API endpoints. ⚠️ Please note, the added declarations are not final and are not complete. They are missing some common declarations, such as the `Rule` schema, the majority of rule types, the `RuleResponse` schema, etc. Furthermore, these declarations haven't been tested for correctness, as it is difficult to validate if the declared schemas match with our current endpoint implementation without code generation. This verification step will be necessary once we have schema generation in place. That said, the added OpenAPI declarations should be sufficient to unblock progress on the following tickets: - https://github.com/elastic/security-team/issues/7129 - https://github.com/elastic/security-team/issues/7134
This commit is contained in:
parent
8f1041c81a
commit
fda84111c2
50 changed files with 2535 additions and 710 deletions
|
@ -11,310 +11,125 @@ import { TimeDuration } from '.';
|
|||
import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils';
|
||||
|
||||
describe('TimeDuration', () => {
|
||||
describe('with allowedDurations', () => {
|
||||
test('it should validate a correctly formed TimeDuration with an allowed duration of 1s', () => {
|
||||
const payload = '1s';
|
||||
const decoded = TimeDuration({
|
||||
allowedDurations: [
|
||||
[1, 's'],
|
||||
[2, 'h'],
|
||||
[7, 'd'],
|
||||
],
|
||||
}).decode(payload);
|
||||
const message = foldLeftRight(decoded);
|
||||
test('it should validate a correctly formed TimeDuration with time unit of seconds', () => {
|
||||
const payload = '1s';
|
||||
const decoded = TimeDuration({ allowedUnits: ['s'] }).decode(payload);
|
||||
const message = foldLeftRight(decoded);
|
||||
|
||||
expect(getPaths(left(message.errors))).toEqual([]);
|
||||
expect(message.schema).toEqual(payload);
|
||||
});
|
||||
|
||||
test('it should validate a correctly formed TimeDuration with an allowed duration of 7d', () => {
|
||||
const payload = '1s';
|
||||
const decoded = TimeDuration({
|
||||
allowedDurations: [
|
||||
[1, 's'],
|
||||
[2, 'h'],
|
||||
[7, 'd'],
|
||||
],
|
||||
}).decode(payload);
|
||||
const message = foldLeftRight(decoded);
|
||||
|
||||
expect(getPaths(left(message.errors))).toEqual([]);
|
||||
expect(message.schema).toEqual(payload);
|
||||
});
|
||||
|
||||
test('it should NOT validate a time duration if the allowed durations does not include it', () => {
|
||||
const payload = '24h';
|
||||
const decoded = TimeDuration({
|
||||
allowedDurations: [
|
||||
[1, 's'],
|
||||
[2, 'h'],
|
||||
[7, 'd'],
|
||||
],
|
||||
}).decode(payload);
|
||||
const message = foldLeftRight(decoded);
|
||||
|
||||
expect(getPaths(left(message.errors))).toEqual([
|
||||
'Invalid value "24h" supplied to "TimeDuration"',
|
||||
]);
|
||||
expect(message.schema).toEqual({});
|
||||
});
|
||||
|
||||
test('it should NOT validate a an allowed duration with a negative number', () => {
|
||||
const payload = '10s';
|
||||
const decoded = TimeDuration({
|
||||
allowedDurations: [
|
||||
[1, 's'],
|
||||
[-7, 'd'],
|
||||
],
|
||||
}).decode(payload);
|
||||
const message = foldLeftRight(decoded);
|
||||
|
||||
expect(getPaths(left(message.errors))).toEqual([
|
||||
'Invalid value "[[1,"s"],[-7,"d"]]" supplied to "TimeDuration"',
|
||||
]);
|
||||
expect(message.schema).toEqual({});
|
||||
});
|
||||
|
||||
test('it should NOT validate an allowed duration with a fractional number', () => {
|
||||
const payload = '1.5s';
|
||||
const decoded = TimeDuration({
|
||||
allowedDurations: [
|
||||
[1, 's'],
|
||||
[-7, 'd'],
|
||||
],
|
||||
}).decode(payload);
|
||||
const message = foldLeftRight(decoded);
|
||||
|
||||
expect(getPaths(left(message.errors))).toEqual([
|
||||
'Invalid value "1.5s" supplied to "TimeDuration"',
|
||||
]);
|
||||
expect(message.schema).toEqual({});
|
||||
});
|
||||
|
||||
test('it should NOT validate a an allowed duration with a duration of 0', () => {
|
||||
const payload = '10s';
|
||||
const decoded = TimeDuration({
|
||||
allowedDurations: [
|
||||
[0, 's'],
|
||||
[7, 'd'],
|
||||
],
|
||||
}).decode(payload);
|
||||
const message = foldLeftRight(decoded);
|
||||
|
||||
expect(getPaths(left(message.errors))).toEqual([
|
||||
'Invalid value "[[0,"s"],[7,"d"]]" supplied to "TimeDuration"',
|
||||
]);
|
||||
expect(message.schema).toEqual({});
|
||||
});
|
||||
|
||||
test('it should NOT validate a TimeDuration with an invalid time unit', () => {
|
||||
const payload = '10000000days';
|
||||
const decoded = TimeDuration({
|
||||
allowedDurations: [
|
||||
[1, 'h'],
|
||||
[1, 'd'],
|
||||
[7, 'd'],
|
||||
],
|
||||
}).decode(payload);
|
||||
const message = foldLeftRight(decoded);
|
||||
|
||||
expect(getPaths(left(message.errors))).toEqual([
|
||||
'Invalid value "10000000days" supplied to "TimeDuration"',
|
||||
]);
|
||||
expect(message.schema).toEqual({});
|
||||
});
|
||||
|
||||
test('it should NOT validate a TimeDuration with a time interval with incorrect format', () => {
|
||||
const payload = '100ff0000w';
|
||||
const decoded = TimeDuration({
|
||||
allowedDurations: [
|
||||
[1, 'h'],
|
||||
[1, 'd'],
|
||||
[7, 'd'],
|
||||
],
|
||||
}).decode(payload);
|
||||
const message = foldLeftRight(decoded);
|
||||
|
||||
expect(getPaths(left(message.errors))).toEqual([
|
||||
'Invalid value "100ff0000w" supplied to "TimeDuration"',
|
||||
]);
|
||||
expect(message.schema).toEqual({});
|
||||
});
|
||||
|
||||
test('it should NOT validate an empty string', () => {
|
||||
const payload = '';
|
||||
const decoded = TimeDuration({
|
||||
allowedDurations: [
|
||||
[1, 'h'],
|
||||
[1, 'd'],
|
||||
[7, 'd'],
|
||||
],
|
||||
}).decode(payload);
|
||||
const message = foldLeftRight(decoded);
|
||||
|
||||
expect(getPaths(left(message.errors))).toEqual([
|
||||
'Invalid value "" supplied to "TimeDuration"',
|
||||
]);
|
||||
expect(message.schema).toEqual({});
|
||||
});
|
||||
|
||||
test('it should NOT validate an number', () => {
|
||||
const payload = 100;
|
||||
const decoded = TimeDuration({
|
||||
allowedDurations: [
|
||||
[1, 'h'],
|
||||
[1, 'd'],
|
||||
[7, 'd'],
|
||||
],
|
||||
}).decode(payload);
|
||||
const message = foldLeftRight(decoded);
|
||||
|
||||
expect(getPaths(left(message.errors))).toEqual([
|
||||
'Invalid value "100" supplied to "TimeDuration"',
|
||||
]);
|
||||
expect(message.schema).toEqual({});
|
||||
});
|
||||
|
||||
test('it should NOT validate an TimeDuration with a valid time unit but unsafe integer', () => {
|
||||
const payload = `${Math.pow(2, 53)}h`;
|
||||
const decoded = TimeDuration({
|
||||
allowedDurations: [
|
||||
[1, 'h'],
|
||||
[1, 'd'],
|
||||
[7, 'd'],
|
||||
],
|
||||
}).decode(payload);
|
||||
const message = foldLeftRight(decoded);
|
||||
|
||||
expect(getPaths(left(message.errors))).toEqual([
|
||||
`Invalid value "${Math.pow(2, 53)}h" supplied to "TimeDuration"`,
|
||||
]);
|
||||
expect(message.schema).toEqual({});
|
||||
});
|
||||
expect(getPaths(left(message.errors))).toEqual([]);
|
||||
expect(message.schema).toEqual(payload);
|
||||
});
|
||||
describe('with allowedUnits', () => {
|
||||
test('it should validate a correctly formed TimeDuration with time unit of seconds', () => {
|
||||
const payload = '1s';
|
||||
const decoded = TimeDuration({ allowedUnits: ['s'] }).decode(payload);
|
||||
const message = foldLeftRight(decoded);
|
||||
|
||||
expect(getPaths(left(message.errors))).toEqual([]);
|
||||
expect(message.schema).toEqual(payload);
|
||||
});
|
||||
test('it should validate a correctly formed TimeDuration with time unit of minutes', () => {
|
||||
const payload = '100m';
|
||||
const decoded = TimeDuration({ allowedUnits: ['s', 'm'] }).decode(payload);
|
||||
const message = foldLeftRight(decoded);
|
||||
|
||||
test('it should validate a correctly formed TimeDuration with time unit of minutes', () => {
|
||||
const payload = '100m';
|
||||
const decoded = TimeDuration({ allowedUnits: ['s', 'm'] }).decode(payload);
|
||||
const message = foldLeftRight(decoded);
|
||||
expect(getPaths(left(message.errors))).toEqual([]);
|
||||
expect(message.schema).toEqual(payload);
|
||||
});
|
||||
|
||||
expect(getPaths(left(message.errors))).toEqual([]);
|
||||
expect(message.schema).toEqual(payload);
|
||||
});
|
||||
test('it should validate a correctly formed TimeDuration with time unit of hours', () => {
|
||||
const payload = '10000000h';
|
||||
const decoded = TimeDuration({ allowedUnits: ['s', 'm', 'h'] }).decode(payload);
|
||||
const message = foldLeftRight(decoded);
|
||||
|
||||
test('it should validate a correctly formed TimeDuration with time unit of hours', () => {
|
||||
const payload = '10000000h';
|
||||
const decoded = TimeDuration({ allowedUnits: ['s', 'm', 'h'] }).decode(payload);
|
||||
const message = foldLeftRight(decoded);
|
||||
expect(getPaths(left(message.errors))).toEqual([]);
|
||||
expect(message.schema).toEqual(payload);
|
||||
});
|
||||
|
||||
expect(getPaths(left(message.errors))).toEqual([]);
|
||||
expect(message.schema).toEqual(payload);
|
||||
});
|
||||
test('it should validate a correctly formed TimeDuration with time unit of days', () => {
|
||||
const payload = '7d';
|
||||
const decoded = TimeDuration({ allowedUnits: ['s', 'm', 'h', 'd'] }).decode(payload);
|
||||
const message = foldLeftRight(decoded);
|
||||
|
||||
test('it should validate a correctly formed TimeDuration with time unit of days', () => {
|
||||
const payload = '7d';
|
||||
const decoded = TimeDuration({ allowedUnits: ['s', 'm', 'h', 'd'] }).decode(payload);
|
||||
const message = foldLeftRight(decoded);
|
||||
expect(getPaths(left(message.errors))).toEqual([]);
|
||||
expect(message.schema).toEqual(payload);
|
||||
});
|
||||
|
||||
expect(getPaths(left(message.errors))).toEqual([]);
|
||||
expect(message.schema).toEqual(payload);
|
||||
});
|
||||
test('it should NOT validate a correctly formed TimeDuration with time unit of seconds if it is not an allowed unit', () => {
|
||||
const payload = '30s';
|
||||
const decoded = TimeDuration({ allowedUnits: ['m', 'h', 'd'] }).decode(payload);
|
||||
const message = foldLeftRight(decoded);
|
||||
|
||||
test('it should NOT validate a correctly formed TimeDuration with time unit of seconds if it is not an allowed unit', () => {
|
||||
const payload = '30s';
|
||||
const decoded = TimeDuration({ allowedUnits: ['m', 'h', 'd'] }).decode(payload);
|
||||
const message = foldLeftRight(decoded);
|
||||
expect(getPaths(left(message.errors))).toEqual([
|
||||
'Invalid value "30s" supplied to "TimeDuration"',
|
||||
]);
|
||||
expect(message.schema).toEqual({});
|
||||
});
|
||||
|
||||
expect(getPaths(left(message.errors))).toEqual([
|
||||
'Invalid value "30s" supplied to "TimeDuration"',
|
||||
]);
|
||||
expect(message.schema).toEqual({});
|
||||
});
|
||||
test('it should NOT validate a negative TimeDuration', () => {
|
||||
const payload = '-10s';
|
||||
const decoded = TimeDuration({ allowedUnits: ['s', 'm', 'h', 'd'] }).decode(payload);
|
||||
const message = foldLeftRight(decoded);
|
||||
|
||||
test('it should NOT validate a negative TimeDuration', () => {
|
||||
const payload = '-10s';
|
||||
const decoded = TimeDuration({ allowedUnits: ['s', 'm', 'h', 'd'] }).decode(payload);
|
||||
const message = foldLeftRight(decoded);
|
||||
expect(getPaths(left(message.errors))).toEqual([
|
||||
'Invalid value "-10s" supplied to "TimeDuration"',
|
||||
]);
|
||||
expect(message.schema).toEqual({});
|
||||
});
|
||||
|
||||
expect(getPaths(left(message.errors))).toEqual([
|
||||
'Invalid value "-10s" supplied to "TimeDuration"',
|
||||
]);
|
||||
expect(message.schema).toEqual({});
|
||||
});
|
||||
test('it should NOT validate a fractional number', () => {
|
||||
const payload = '1.5s';
|
||||
const decoded = TimeDuration({ allowedUnits: ['s', 'm', 'h', 'd'] }).decode(payload);
|
||||
const message = foldLeftRight(decoded);
|
||||
|
||||
test('it should NOT validate a fractional number', () => {
|
||||
const payload = '1.5s';
|
||||
const decoded = TimeDuration({ allowedUnits: ['s', 'm', 'h', 'd'] }).decode(payload);
|
||||
const message = foldLeftRight(decoded);
|
||||
expect(getPaths(left(message.errors))).toEqual([
|
||||
'Invalid value "1.5s" supplied to "TimeDuration"',
|
||||
]);
|
||||
expect(message.schema).toEqual({});
|
||||
});
|
||||
|
||||
expect(getPaths(left(message.errors))).toEqual([
|
||||
'Invalid value "1.5s" supplied to "TimeDuration"',
|
||||
]);
|
||||
expect(message.schema).toEqual({});
|
||||
});
|
||||
test('it should NOT validate a TimeDuration with an invalid time unit', () => {
|
||||
const payload = '10000000days';
|
||||
const decoded = TimeDuration({ allowedUnits: ['s', 'm', 'h', 'd'] }).decode(payload);
|
||||
const message = foldLeftRight(decoded);
|
||||
|
||||
test('it should NOT validate a TimeDuration with an invalid time unit', () => {
|
||||
const payload = '10000000days';
|
||||
const decoded = TimeDuration({ allowedUnits: ['s', 'm', 'h', 'd'] }).decode(payload);
|
||||
const message = foldLeftRight(decoded);
|
||||
expect(getPaths(left(message.errors))).toEqual([
|
||||
'Invalid value "10000000days" supplied to "TimeDuration"',
|
||||
]);
|
||||
expect(message.schema).toEqual({});
|
||||
});
|
||||
|
||||
expect(getPaths(left(message.errors))).toEqual([
|
||||
'Invalid value "10000000days" supplied to "TimeDuration"',
|
||||
]);
|
||||
expect(message.schema).toEqual({});
|
||||
});
|
||||
test('it should NOT validate a TimeDuration with a time interval with incorrect format', () => {
|
||||
const payload = '100ff0000w';
|
||||
const decoded = TimeDuration({ allowedUnits: ['s', 'm', 'h'] }).decode(payload);
|
||||
const message = foldLeftRight(decoded);
|
||||
|
||||
test('it should NOT validate a TimeDuration with a time interval with incorrect format', () => {
|
||||
const payload = '100ff0000w';
|
||||
const decoded = TimeDuration({ allowedUnits: ['s', 'm', 'h'] }).decode(payload);
|
||||
const message = foldLeftRight(decoded);
|
||||
expect(getPaths(left(message.errors))).toEqual([
|
||||
'Invalid value "100ff0000w" supplied to "TimeDuration"',
|
||||
]);
|
||||
expect(message.schema).toEqual({});
|
||||
});
|
||||
|
||||
expect(getPaths(left(message.errors))).toEqual([
|
||||
'Invalid value "100ff0000w" supplied to "TimeDuration"',
|
||||
]);
|
||||
expect(message.schema).toEqual({});
|
||||
});
|
||||
test('it should NOT validate an empty string', () => {
|
||||
const payload = '';
|
||||
const decoded = TimeDuration({ allowedUnits: ['s', 'm', 'h'] }).decode(payload);
|
||||
const message = foldLeftRight(decoded);
|
||||
|
||||
test('it should NOT validate an empty string', () => {
|
||||
const payload = '';
|
||||
const decoded = TimeDuration({ allowedUnits: ['s', 'm', 'h'] }).decode(payload);
|
||||
const message = foldLeftRight(decoded);
|
||||
expect(getPaths(left(message.errors))).toEqual(['Invalid value "" supplied to "TimeDuration"']);
|
||||
expect(message.schema).toEqual({});
|
||||
});
|
||||
|
||||
expect(getPaths(left(message.errors))).toEqual([
|
||||
'Invalid value "" supplied to "TimeDuration"',
|
||||
]);
|
||||
expect(message.schema).toEqual({});
|
||||
});
|
||||
test('it should NOT validate an number', () => {
|
||||
const payload = 100;
|
||||
const decoded = TimeDuration({ allowedUnits: ['s', 'm', 'h'] }).decode(payload);
|
||||
const message = foldLeftRight(decoded);
|
||||
|
||||
test('it should NOT validate an number', () => {
|
||||
const payload = 100;
|
||||
const decoded = TimeDuration({ allowedUnits: ['s', 'm', 'h'] }).decode(payload);
|
||||
const message = foldLeftRight(decoded);
|
||||
expect(getPaths(left(message.errors))).toEqual([
|
||||
'Invalid value "100" supplied to "TimeDuration"',
|
||||
]);
|
||||
expect(message.schema).toEqual({});
|
||||
});
|
||||
|
||||
expect(getPaths(left(message.errors))).toEqual([
|
||||
'Invalid value "100" supplied to "TimeDuration"',
|
||||
]);
|
||||
expect(message.schema).toEqual({});
|
||||
});
|
||||
test('it should NOT validate an TimeDuration with a valid time unit but unsafe integer', () => {
|
||||
const payload = `${Math.pow(2, 53)}h`;
|
||||
const decoded = TimeDuration({ allowedUnits: ['s', 'm', 'h'] }).decode(payload);
|
||||
const message = foldLeftRight(decoded);
|
||||
|
||||
test('it should NOT validate an TimeDuration with a valid time unit but unsafe integer', () => {
|
||||
const payload = `${Math.pow(2, 53)}h`;
|
||||
const decoded = TimeDuration({ allowedUnits: ['s', 'm', 'h'] }).decode(payload);
|
||||
const message = foldLeftRight(decoded);
|
||||
|
||||
expect(getPaths(left(message.errors))).toEqual([
|
||||
`Invalid value "${Math.pow(2, 53)}h" supplied to "TimeDuration"`,
|
||||
]);
|
||||
expect(message.schema).toEqual({});
|
||||
});
|
||||
expect(getPaths(left(message.errors))).toEqual([
|
||||
`Invalid value "${Math.pow(2, 53)}h" supplied to "TimeDuration"`,
|
||||
]);
|
||||
expect(message.schema).toEqual({});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -16,20 +16,14 @@ import { Either } from 'fp-ts/lib/Either';
|
|||
*/
|
||||
|
||||
type TimeUnits = 's' | 'm' | 'h' | 'd' | 'w' | 'y';
|
||||
interface TimeDurationWithAllowedDurations {
|
||||
allowedDurations: Array<[number, TimeUnits]>;
|
||||
allowedUnits?: never;
|
||||
}
|
||||
interface TimeDurationWithAllowedUnits {
|
||||
allowedUnits: TimeUnits[];
|
||||
allowedDurations?: never;
|
||||
}
|
||||
|
||||
type TimeDurationType = TimeDurationWithAllowedDurations | TimeDurationWithAllowedUnits;
|
||||
interface TimeDurationType {
|
||||
allowedUnits: TimeUnits[];
|
||||
}
|
||||
|
||||
const isTimeSafe = (time: number) => time >= 1 && Number.isSafeInteger(time);
|
||||
|
||||
export const TimeDuration = ({ allowedUnits, allowedDurations }: TimeDurationType) => {
|
||||
export const TimeDuration = ({ allowedUnits }: TimeDurationType) => {
|
||||
return new t.Type<string, string, unknown>(
|
||||
'TimeDuration',
|
||||
t.string.is,
|
||||
|
@ -42,17 +36,7 @@ export const TimeDuration = ({ allowedUnits, allowedDurations }: TimeDurationTyp
|
|||
if (!isTimeSafe(time)) {
|
||||
return t.failure(input, context);
|
||||
}
|
||||
if (allowedDurations) {
|
||||
for (const [allowedTime, allowedUnit] of allowedDurations) {
|
||||
if (!isTimeSafe(allowedTime)) {
|
||||
return t.failure(allowedDurations, context);
|
||||
}
|
||||
if (allowedTime === time && allowedUnit === unit) {
|
||||
return t.success(input);
|
||||
}
|
||||
}
|
||||
return t.failure(input, context);
|
||||
} else if (allowedUnits.includes(unit as TimeUnits)) {
|
||||
if (allowedUnits.includes(unit as TimeUnits)) {
|
||||
return t.success(input);
|
||||
} else {
|
||||
return t.failure(input, context);
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
openapi: 3.0.0
|
||||
info:
|
||||
title: Error Schema
|
||||
version: 'not applicable'
|
||||
paths: {}
|
||||
components:
|
||||
schemas:
|
||||
ErrorSchema:
|
||||
type: object
|
||||
required:
|
||||
- error
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
rule_id:
|
||||
$ref: './rule_schema/common_attributes.schema.yaml#/components/schemas/RuleSignatureId'
|
||||
list_id:
|
||||
type: string
|
||||
minLength: 1
|
||||
item_id:
|
||||
type: string
|
||||
minLength: 1
|
||||
error:
|
||||
type: object
|
||||
required:
|
||||
- status_code
|
||||
- message
|
||||
properties:
|
||||
status_code:
|
||||
type: integer
|
||||
minimum: 400
|
||||
message:
|
||||
type: string
|
|
@ -5,13 +5,12 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils';
|
||||
import { left } from 'fp-ts/lib/Either';
|
||||
import { pipe } from 'fp-ts/lib/pipeable';
|
||||
|
||||
import type { ErrorSchema } from './error_schema';
|
||||
import { errorSchema } from './error_schema';
|
||||
import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils';
|
||||
import { getErrorSchemaMock } from './error_schema.mocks';
|
||||
import { getErrorSchemaMock } from './error_schema.mock';
|
||||
|
||||
describe('error_schema', () => {
|
||||
test('it should validate an error with a UUID given for id', () => {
|
||||
|
|
|
@ -0,0 +1,243 @@
|
|||
openapi: 3.0.0
|
||||
info:
|
||||
title: Common Rule Attributes
|
||||
version: 'not applicable'
|
||||
paths: {}
|
||||
components:
|
||||
schemas:
|
||||
UUID:
|
||||
type: string
|
||||
format: uuid
|
||||
description: A universally unique identifier
|
||||
|
||||
RuleObjectId:
|
||||
type: string
|
||||
|
||||
RuleSignatureId:
|
||||
type: string
|
||||
description: Could be any string, not necessarily a UUID
|
||||
|
||||
RuleName:
|
||||
type: string
|
||||
minLength: 1
|
||||
|
||||
RuleDescription:
|
||||
type: string
|
||||
minLength: 1
|
||||
|
||||
RuleVersion:
|
||||
type: string
|
||||
format: version
|
||||
|
||||
IsRuleImmutable:
|
||||
type: boolean
|
||||
|
||||
IsRuleEnabled:
|
||||
type: boolean
|
||||
|
||||
RuleTagArray:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
|
||||
RuleMetadata:
|
||||
type: object
|
||||
additionalProperties: true
|
||||
|
||||
RuleLicense:
|
||||
type: string
|
||||
|
||||
RuleAuthorArray:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
|
||||
RuleFalsePositiveArray:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
|
||||
RuleReferenceArray:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
|
||||
InvestigationGuide:
|
||||
type: string
|
||||
|
||||
SetupGuide:
|
||||
type: string
|
||||
|
||||
BuildingBlockType:
|
||||
type: string
|
||||
|
||||
AlertsIndex:
|
||||
type: string
|
||||
|
||||
AlertsIndexNamespace:
|
||||
type: string
|
||||
|
||||
MaxSignals:
|
||||
type: integer
|
||||
minimum: 1
|
||||
|
||||
Subtechnique:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
description: Subtechnique ID
|
||||
name:
|
||||
type: string
|
||||
description: Subtechnique name
|
||||
reference:
|
||||
type: string
|
||||
description: Subtechnique reference
|
||||
required:
|
||||
- id
|
||||
- name
|
||||
- reference
|
||||
|
||||
Technique:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
description: Technique ID
|
||||
name:
|
||||
type: string
|
||||
description: Technique name
|
||||
reference:
|
||||
type: string
|
||||
description: Technique reference
|
||||
subtechnique:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/Subtechnique'
|
||||
description: Array containing more specific information on the attack technique
|
||||
required:
|
||||
- id
|
||||
- name
|
||||
- reference
|
||||
|
||||
Threat:
|
||||
type: object
|
||||
properties:
|
||||
framework:
|
||||
type: string
|
||||
description: Relevant attack framework
|
||||
tactic:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
description: Tactic ID
|
||||
name:
|
||||
type: string
|
||||
description: Tactic name
|
||||
reference:
|
||||
type: string
|
||||
description: Tactic reference
|
||||
required:
|
||||
- id
|
||||
- name
|
||||
- reference
|
||||
technique:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/Technique'
|
||||
description: Array containing information on the attack techniques (optional)
|
||||
required:
|
||||
- framework
|
||||
- tactic
|
||||
|
||||
ThreatArray:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/Threat' # Assuming a schema named 'Threat' is defined in the components section.
|
||||
|
||||
IndexPatternArray:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
|
||||
DataViewId:
|
||||
type: string
|
||||
|
||||
RuleQuery:
|
||||
type: string
|
||||
|
||||
RuleFilterArray:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
additionalProperties: true
|
||||
|
||||
RuleNameOverride:
|
||||
type: string
|
||||
|
||||
TimestampOverride:
|
||||
type: string
|
||||
|
||||
TimestampOverrideFallbackDisabled:
|
||||
type: boolean
|
||||
|
||||
RequiredField:
|
||||
type: object
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
minLength: 1
|
||||
type:
|
||||
type: string
|
||||
minLength: 1
|
||||
ecs:
|
||||
type: boolean
|
||||
|
||||
RequiredFieldArray:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/RequiredField'
|
||||
|
||||
TimelineTemplateId:
|
||||
type: string
|
||||
|
||||
TimelineTemplateTitle:
|
||||
type: string
|
||||
|
||||
SavedObjectResolveOutcome:
|
||||
type: string
|
||||
enum:
|
||||
- exactMatch
|
||||
- aliasMatch
|
||||
- conflict
|
||||
|
||||
SavedObjectResolveAliasTargetId:
|
||||
type: string
|
||||
|
||||
SavedObjectResolveAliasPurpose:
|
||||
type: string
|
||||
enum:
|
||||
- savedObjectConversion
|
||||
- savedObjectImport
|
||||
|
||||
RelatedIntegration:
|
||||
type: object
|
||||
properties:
|
||||
package:
|
||||
type: string
|
||||
minLength: 1
|
||||
version:
|
||||
type: string
|
||||
minLength: 1
|
||||
integration:
|
||||
type: string
|
||||
minLength: 1
|
||||
required:
|
||||
- package
|
||||
- version
|
||||
|
||||
RelatedIntegrationArray:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/RelatedIntegration'
|
|
@ -0,0 +1,259 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import * as t from 'io-ts';
|
||||
import { listArray } from '@kbn/securitysolution-io-ts-list-types';
|
||||
import { NonEmptyString, version, UUID } from '@kbn/securitysolution-io-ts-types';
|
||||
import { max_signals, threat } from '@kbn/securitysolution-io-ts-alerting-types';
|
||||
|
||||
export type RuleObjectId = t.TypeOf<typeof RuleObjectId>;
|
||||
export const RuleObjectId = UUID;
|
||||
|
||||
/**
|
||||
* NOTE: Never make this a strict uuid, we allow the rule_id to be any string at the moment
|
||||
* in case we encounter 3rd party rule systems which might be using auto incrementing numbers
|
||||
* or other different things.
|
||||
*/
|
||||
export type RuleSignatureId = t.TypeOf<typeof RuleSignatureId>;
|
||||
export const RuleSignatureId = t.string; // should be non-empty string?
|
||||
|
||||
export type RuleName = t.TypeOf<typeof RuleName>;
|
||||
export const RuleName = NonEmptyString;
|
||||
|
||||
export type RuleDescription = t.TypeOf<typeof RuleDescription>;
|
||||
export const RuleDescription = NonEmptyString;
|
||||
|
||||
export type RuleVersion = t.TypeOf<typeof RuleVersion>;
|
||||
export const RuleVersion = version;
|
||||
|
||||
export type IsRuleImmutable = t.TypeOf<typeof IsRuleImmutable>;
|
||||
export const IsRuleImmutable = t.boolean;
|
||||
|
||||
export type IsRuleEnabled = t.TypeOf<typeof IsRuleEnabled>;
|
||||
export const IsRuleEnabled = t.boolean;
|
||||
|
||||
export type RuleTagArray = t.TypeOf<typeof RuleTagArray>;
|
||||
export const RuleTagArray = t.array(t.string); // should be non-empty strings?
|
||||
|
||||
/**
|
||||
* Note that this is a non-exact io-ts type as we allow extra meta information
|
||||
* to be added to the meta object
|
||||
*/
|
||||
export type RuleMetadata = t.TypeOf<typeof RuleMetadata>;
|
||||
export const RuleMetadata = t.object; // should be a more specific type?
|
||||
|
||||
export type RuleLicense = t.TypeOf<typeof RuleLicense>;
|
||||
export const RuleLicense = t.string;
|
||||
|
||||
export type RuleAuthorArray = t.TypeOf<typeof RuleAuthorArray>;
|
||||
export const RuleAuthorArray = t.array(t.string); // should be non-empty strings?
|
||||
|
||||
export type RuleFalsePositiveArray = t.TypeOf<typeof RuleFalsePositiveArray>;
|
||||
export const RuleFalsePositiveArray = t.array(t.string); // should be non-empty strings?
|
||||
|
||||
export type RuleReferenceArray = t.TypeOf<typeof RuleReferenceArray>;
|
||||
export const RuleReferenceArray = t.array(t.string); // should be non-empty strings?
|
||||
|
||||
export type InvestigationGuide = t.TypeOf<typeof InvestigationGuide>;
|
||||
export const InvestigationGuide = t.string;
|
||||
|
||||
/**
|
||||
* Any instructions for the user for setting up their environment in order to start receiving
|
||||
* source events for a given rule.
|
||||
*
|
||||
* It's a multiline text. Markdown is supported.
|
||||
*/
|
||||
export type SetupGuide = t.TypeOf<typeof SetupGuide>;
|
||||
export const SetupGuide = t.string;
|
||||
|
||||
export type BuildingBlockType = t.TypeOf<typeof BuildingBlockType>;
|
||||
export const BuildingBlockType = t.string;
|
||||
|
||||
export type AlertsIndex = t.TypeOf<typeof AlertsIndex>;
|
||||
export const AlertsIndex = t.string;
|
||||
|
||||
export type AlertsIndexNamespace = t.TypeOf<typeof AlertsIndexNamespace>;
|
||||
export const AlertsIndexNamespace = t.string;
|
||||
|
||||
export type ExceptionListArray = t.TypeOf<typeof ExceptionListArray>;
|
||||
export const ExceptionListArray = listArray;
|
||||
|
||||
export type MaxSignals = t.TypeOf<typeof MaxSignals>;
|
||||
export const MaxSignals = max_signals;
|
||||
|
||||
export type ThreatArray = t.TypeOf<typeof ThreatArray>;
|
||||
export const ThreatArray = t.array(threat);
|
||||
|
||||
export type IndexPatternArray = t.TypeOf<typeof IndexPatternArray>;
|
||||
export const IndexPatternArray = t.array(t.string);
|
||||
|
||||
export type DataViewId = t.TypeOf<typeof DataViewId>;
|
||||
export const DataViewId = t.string;
|
||||
|
||||
export type RuleQuery = t.TypeOf<typeof RuleQuery>;
|
||||
export const RuleQuery = t.string;
|
||||
|
||||
/**
|
||||
* TODO: Right now the filters is an "unknown", when it could more than likely
|
||||
* become the actual ESFilter as a type.
|
||||
*/
|
||||
export type RuleFilterArray = t.TypeOf<typeof RuleFilterArray>; // Filters are not easily type-able yet
|
||||
export const RuleFilterArray = t.array(t.unknown); // Filters are not easily type-able yet
|
||||
|
||||
export type RuleNameOverride = t.TypeOf<typeof RuleNameOverride>;
|
||||
export const RuleNameOverride = t.string; // should be non-empty string?
|
||||
|
||||
export type TimestampOverride = t.TypeOf<typeof TimestampOverride>;
|
||||
export const TimestampOverride = t.string; // should be non-empty string?
|
||||
|
||||
export type TimestampOverrideFallbackDisabled = t.TypeOf<typeof TimestampOverrideFallbackDisabled>;
|
||||
export const TimestampOverrideFallbackDisabled = t.boolean;
|
||||
|
||||
/**
|
||||
* Almost all types of Security rules check source event documents for a match to some kind of
|
||||
* query or filter. If a document has certain field with certain values, then it's a match and
|
||||
* the rule will generate an alert.
|
||||
*
|
||||
* Required field is an event field that must be present in the source indices of a given rule.
|
||||
*
|
||||
* @example
|
||||
* const standardEcsField: RequiredField = {
|
||||
* name: 'event.action',
|
||||
* type: 'keyword',
|
||||
* ecs: true,
|
||||
* };
|
||||
*
|
||||
* @example
|
||||
* const nonEcsField: RequiredField = {
|
||||
* name: 'winlog.event_data.AttributeLDAPDisplayName',
|
||||
* type: 'keyword',
|
||||
* ecs: false,
|
||||
* };
|
||||
*/
|
||||
export type RequiredField = t.TypeOf<typeof RequiredField>;
|
||||
export const RequiredField = t.exact(
|
||||
t.type({
|
||||
name: NonEmptyString,
|
||||
type: NonEmptyString,
|
||||
ecs: t.boolean,
|
||||
})
|
||||
);
|
||||
|
||||
/**
|
||||
* Array of event fields that must be present in the source indices of a given rule.
|
||||
*
|
||||
* @example
|
||||
* const x: RequiredFieldArray = [
|
||||
* {
|
||||
* name: 'event.action',
|
||||
* type: 'keyword',
|
||||
* ecs: true,
|
||||
* },
|
||||
* {
|
||||
* name: 'event.code',
|
||||
* type: 'keyword',
|
||||
* ecs: true,
|
||||
* },
|
||||
* {
|
||||
* name: 'winlog.event_data.AttributeLDAPDisplayName',
|
||||
* type: 'keyword',
|
||||
* ecs: false,
|
||||
* },
|
||||
* ];
|
||||
*/
|
||||
export type RequiredFieldArray = t.TypeOf<typeof RequiredFieldArray>;
|
||||
export const RequiredFieldArray = t.array(RequiredField);
|
||||
|
||||
export type TimelineTemplateId = t.TypeOf<typeof TimelineTemplateId>;
|
||||
export const TimelineTemplateId = t.string; // should be non-empty string?
|
||||
|
||||
export type TimelineTemplateTitle = t.TypeOf<typeof TimelineTemplateTitle>;
|
||||
export const TimelineTemplateTitle = t.string; // should be non-empty string?
|
||||
|
||||
/**
|
||||
* Outcome is a property of the saved object resolve api
|
||||
* will tell us info about the rule after 8.0 migrations
|
||||
*/
|
||||
export type SavedObjectResolveOutcome = t.TypeOf<typeof SavedObjectResolveOutcome>;
|
||||
export const SavedObjectResolveOutcome = t.union([
|
||||
t.literal('exactMatch'),
|
||||
t.literal('aliasMatch'),
|
||||
t.literal('conflict'),
|
||||
]);
|
||||
|
||||
export type SavedObjectResolveAliasTargetId = t.TypeOf<typeof SavedObjectResolveAliasTargetId>;
|
||||
export const SavedObjectResolveAliasTargetId = t.string;
|
||||
|
||||
export type SavedObjectResolveAliasPurpose = t.TypeOf<typeof SavedObjectResolveAliasPurpose>;
|
||||
export const SavedObjectResolveAliasPurpose = t.union([
|
||||
t.literal('savedObjectConversion'),
|
||||
t.literal('savedObjectImport'),
|
||||
]);
|
||||
|
||||
/**
|
||||
* Related integration is a potential dependency of a rule. It's assumed that if the user installs
|
||||
* one of the related integrations of a rule, the rule might start to work properly because it will
|
||||
* have source events (generated by this integration) potentially matching the rule's query.
|
||||
*
|
||||
* NOTE: Proper work is not guaranteed, because a related integration, if installed, can be
|
||||
* configured differently or generate data that is not necessarily relevant for this rule.
|
||||
*
|
||||
* Related integration is a combination of a Fleet package and (optionally) one of the
|
||||
* package's "integrations" that this package contains. It is represented by 3 properties:
|
||||
*
|
||||
* - `package`: name of the package (required, unique id)
|
||||
* - `version`: version of the package (required, semver-compatible)
|
||||
* - `integration`: name of the integration of this package (optional, id within the package)
|
||||
*
|
||||
* There are Fleet packages like `windows` that contain only one integration; in this case,
|
||||
* `integration` should be unspecified. There are also packages like `aws` and `azure` that contain
|
||||
* several integrations; in this case, `integration` should be specified.
|
||||
*
|
||||
* @example
|
||||
* const x: RelatedIntegration = {
|
||||
* package: 'windows',
|
||||
* version: '1.5.x',
|
||||
* };
|
||||
*
|
||||
* @example
|
||||
* const x: RelatedIntegration = {
|
||||
* package: 'azure',
|
||||
* version: '~1.1.6',
|
||||
* integration: 'activitylogs',
|
||||
* };
|
||||
*/
|
||||
export type RelatedIntegration = t.TypeOf<typeof RelatedIntegration>;
|
||||
export const RelatedIntegration = t.exact(
|
||||
t.intersection([
|
||||
t.type({
|
||||
package: NonEmptyString,
|
||||
version: NonEmptyString,
|
||||
}),
|
||||
t.partial({
|
||||
integration: NonEmptyString,
|
||||
}),
|
||||
])
|
||||
);
|
||||
|
||||
/**
|
||||
* Array of related integrations.
|
||||
*
|
||||
* @example
|
||||
* const x: RelatedIntegrationArray = [
|
||||
* {
|
||||
* package: 'windows',
|
||||
* version: '1.5.x',
|
||||
* },
|
||||
* {
|
||||
* package: 'azure',
|
||||
* version: '~1.1.6',
|
||||
* integration: 'activitylogs',
|
||||
* },
|
||||
* ];
|
||||
*/
|
||||
export type RelatedIntegrationArray = t.TypeOf<typeof RelatedIntegrationArray>;
|
||||
export const RelatedIntegrationArray = t.array(RelatedIntegration);
|
|
@ -1,17 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import * as t from 'io-ts';
|
||||
|
||||
export type RuleNameOverride = t.TypeOf<typeof RuleNameOverride>;
|
||||
export const RuleNameOverride = t.string; // should be non-empty string?
|
||||
|
||||
export type TimestampOverride = t.TypeOf<typeof TimestampOverride>;
|
||||
export const TimestampOverride = t.string; // should be non-empty string?
|
||||
|
||||
export type TimestampOverrideFallbackDisabled = t.TypeOf<typeof TimestampOverrideFallbackDisabled>;
|
||||
export const TimestampOverrideFallbackDisabled = t.boolean;
|
|
@ -1,105 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import * as t from 'io-ts';
|
||||
import { listArray } from '@kbn/securitysolution-io-ts-list-types';
|
||||
import { NonEmptyString, version, UUID } from '@kbn/securitysolution-io-ts-types';
|
||||
import { max_signals, threat } from '@kbn/securitysolution-io-ts-alerting-types';
|
||||
|
||||
export type RuleObjectId = t.TypeOf<typeof RuleObjectId>;
|
||||
export const RuleObjectId = UUID;
|
||||
|
||||
/**
|
||||
* NOTE: Never make this a strict uuid, we allow the rule_id to be any string at the moment
|
||||
* in case we encounter 3rd party rule systems which might be using auto incrementing numbers
|
||||
* or other different things.
|
||||
*/
|
||||
export type RuleSignatureId = t.TypeOf<typeof RuleSignatureId>;
|
||||
export const RuleSignatureId = t.string; // should be non-empty string?
|
||||
|
||||
export type RuleName = t.TypeOf<typeof RuleName>;
|
||||
export const RuleName = NonEmptyString;
|
||||
|
||||
export type RuleDescription = t.TypeOf<typeof RuleDescription>;
|
||||
export const RuleDescription = NonEmptyString;
|
||||
|
||||
export type RuleVersion = t.TypeOf<typeof RuleVersion>;
|
||||
export const RuleVersion = version;
|
||||
|
||||
export type IsRuleImmutable = t.TypeOf<typeof IsRuleImmutable>;
|
||||
export const IsRuleImmutable = t.boolean;
|
||||
|
||||
export type IsRuleEnabled = t.TypeOf<typeof IsRuleEnabled>;
|
||||
export const IsRuleEnabled = t.boolean;
|
||||
|
||||
export type RuleTagArray = t.TypeOf<typeof RuleTagArray>;
|
||||
export const RuleTagArray = t.array(t.string); // should be non-empty strings?
|
||||
|
||||
/**
|
||||
* Note that this is a non-exact io-ts type as we allow extra meta information
|
||||
* to be added to the meta object
|
||||
*/
|
||||
export type RuleMetadata = t.TypeOf<typeof RuleMetadata>;
|
||||
export const RuleMetadata = t.object; // should be a more specific type?
|
||||
|
||||
export type RuleLicense = t.TypeOf<typeof RuleLicense>;
|
||||
export const RuleLicense = t.string;
|
||||
|
||||
export type RuleAuthorArray = t.TypeOf<typeof RuleAuthorArray>;
|
||||
export const RuleAuthorArray = t.array(t.string); // should be non-empty strings?
|
||||
|
||||
export type RuleFalsePositiveArray = t.TypeOf<typeof RuleFalsePositiveArray>;
|
||||
export const RuleFalsePositiveArray = t.array(t.string); // should be non-empty strings?
|
||||
|
||||
export type RuleReferenceArray = t.TypeOf<typeof RuleReferenceArray>;
|
||||
export const RuleReferenceArray = t.array(t.string); // should be non-empty strings?
|
||||
|
||||
export type InvestigationGuide = t.TypeOf<typeof InvestigationGuide>;
|
||||
export const InvestigationGuide = t.string;
|
||||
|
||||
/**
|
||||
* Any instructions for the user for setting up their environment in order to start receiving
|
||||
* source events for a given rule.
|
||||
*
|
||||
* It's a multiline text. Markdown is supported.
|
||||
*/
|
||||
export type SetupGuide = t.TypeOf<typeof SetupGuide>;
|
||||
export const SetupGuide = t.string;
|
||||
|
||||
export type BuildingBlockType = t.TypeOf<typeof BuildingBlockType>;
|
||||
export const BuildingBlockType = t.string;
|
||||
|
||||
export type AlertsIndex = t.TypeOf<typeof AlertsIndex>;
|
||||
export const AlertsIndex = t.string;
|
||||
|
||||
export type AlertsIndexNamespace = t.TypeOf<typeof AlertsIndexNamespace>;
|
||||
export const AlertsIndexNamespace = t.string;
|
||||
|
||||
export type ExceptionListArray = t.TypeOf<typeof ExceptionListArray>;
|
||||
export const ExceptionListArray = listArray;
|
||||
|
||||
export type MaxSignals = t.TypeOf<typeof MaxSignals>;
|
||||
export const MaxSignals = max_signals;
|
||||
|
||||
export type ThreatArray = t.TypeOf<typeof ThreatArray>;
|
||||
export const ThreatArray = t.array(threat);
|
||||
|
||||
export type IndexPatternArray = t.TypeOf<typeof IndexPatternArray>;
|
||||
export const IndexPatternArray = t.array(t.string);
|
||||
|
||||
export type DataViewId = t.TypeOf<typeof DataViewId>;
|
||||
export const DataViewId = t.string;
|
||||
|
||||
export type RuleQuery = t.TypeOf<typeof RuleQuery>;
|
||||
export const RuleQuery = t.string;
|
||||
|
||||
/**
|
||||
* TODO: Right now the filters is an "unknown", when it could more than likely
|
||||
* become the actual ESFilter as a type.
|
||||
*/
|
||||
export type RuleFilterArray = t.TypeOf<typeof RuleFilterArray>; // Filters are not easily type-able yet
|
||||
export const RuleFilterArray = t.array(t.unknown); // Filters are not easily type-able yet
|
|
@ -1,73 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import * as t from 'io-ts';
|
||||
import { NonEmptyString } from '@kbn/securitysolution-io-ts-types';
|
||||
|
||||
/**
|
||||
* Related integration is a potential dependency of a rule. It's assumed that if the user installs
|
||||
* one of the related integrations of a rule, the rule might start to work properly because it will
|
||||
* have source events (generated by this integration) potentially matching the rule's query.
|
||||
*
|
||||
* NOTE: Proper work is not guaranteed, because a related integration, if installed, can be
|
||||
* configured differently or generate data that is not necessarily relevant for this rule.
|
||||
*
|
||||
* Related integration is a combination of a Fleet package and (optionally) one of the
|
||||
* package's "integrations" that this package contains. It is represented by 3 properties:
|
||||
*
|
||||
* - `package`: name of the package (required, unique id)
|
||||
* - `version`: version of the package (required, semver-compatible)
|
||||
* - `integration`: name of the integration of this package (optional, id within the package)
|
||||
*
|
||||
* There are Fleet packages like `windows` that contain only one integration; in this case,
|
||||
* `integration` should be unspecified. There are also packages like `aws` and `azure` that contain
|
||||
* several integrations; in this case, `integration` should be specified.
|
||||
*
|
||||
* @example
|
||||
* const x: RelatedIntegration = {
|
||||
* package: 'windows',
|
||||
* version: '1.5.x',
|
||||
* };
|
||||
*
|
||||
* @example
|
||||
* const x: RelatedIntegration = {
|
||||
* package: 'azure',
|
||||
* version: '~1.1.6',
|
||||
* integration: 'activitylogs',
|
||||
* };
|
||||
*/
|
||||
export type RelatedIntegration = t.TypeOf<typeof RelatedIntegration>;
|
||||
export const RelatedIntegration = t.exact(
|
||||
t.intersection([
|
||||
t.type({
|
||||
package: NonEmptyString,
|
||||
version: NonEmptyString,
|
||||
}),
|
||||
t.partial({
|
||||
integration: NonEmptyString,
|
||||
}),
|
||||
])
|
||||
);
|
||||
|
||||
/**
|
||||
* Array of related integrations.
|
||||
*
|
||||
* @example
|
||||
* const x: RelatedIntegrationArray = [
|
||||
* {
|
||||
* package: 'windows',
|
||||
* version: '1.5.x',
|
||||
* },
|
||||
* {
|
||||
* package: 'azure',
|
||||
* version: '~1.1.6',
|
||||
* integration: 'activitylogs',
|
||||
* },
|
||||
* ];
|
||||
*/
|
||||
export type RelatedIntegrationArray = t.TypeOf<typeof RelatedIntegrationArray>;
|
||||
export const RelatedIntegrationArray = t.array(RelatedIntegration);
|
|
@ -1,64 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import * as t from 'io-ts';
|
||||
import { NonEmptyString } from '@kbn/securitysolution-io-ts-types';
|
||||
|
||||
/**
|
||||
* Almost all types of Security rules check source event documents for a match to some kind of
|
||||
* query or filter. If a document has certain field with certain values, then it's a match and
|
||||
* the rule will generate an alert.
|
||||
*
|
||||
* Required field is an event field that must be present in the source indices of a given rule.
|
||||
*
|
||||
* @example
|
||||
* const standardEcsField: RequiredField = {
|
||||
* name: 'event.action',
|
||||
* type: 'keyword',
|
||||
* ecs: true,
|
||||
* };
|
||||
*
|
||||
* @example
|
||||
* const nonEcsField: RequiredField = {
|
||||
* name: 'winlog.event_data.AttributeLDAPDisplayName',
|
||||
* type: 'keyword',
|
||||
* ecs: false,
|
||||
* };
|
||||
*/
|
||||
export type RequiredField = t.TypeOf<typeof RequiredField>;
|
||||
export const RequiredField = t.exact(
|
||||
t.type({
|
||||
name: NonEmptyString,
|
||||
type: NonEmptyString,
|
||||
ecs: t.boolean,
|
||||
})
|
||||
);
|
||||
|
||||
/**
|
||||
* Array of event fields that must be present in the source indices of a given rule.
|
||||
*
|
||||
* @example
|
||||
* const x: RequiredFieldArray = [
|
||||
* {
|
||||
* name: 'event.action',
|
||||
* type: 'keyword',
|
||||
* ecs: true,
|
||||
* },
|
||||
* {
|
||||
* name: 'event.code',
|
||||
* type: 'keyword',
|
||||
* ecs: true,
|
||||
* },
|
||||
* {
|
||||
* name: 'winlog.event_data.AttributeLDAPDisplayName',
|
||||
* type: 'keyword',
|
||||
* ecs: false,
|
||||
* },
|
||||
* ];
|
||||
*/
|
||||
export type RequiredFieldArray = t.TypeOf<typeof RequiredFieldArray>;
|
||||
export const RequiredFieldArray = t.array(RequiredField);
|
|
@ -1,28 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import * as t from 'io-ts';
|
||||
|
||||
/**
|
||||
* Outcome is a property of the saved object resolve api
|
||||
* will tell us info about the rule after 8.0 migrations
|
||||
*/
|
||||
export type SavedObjectResolveOutcome = t.TypeOf<typeof SavedObjectResolveOutcome>;
|
||||
export const SavedObjectResolveOutcome = t.union([
|
||||
t.literal('exactMatch'),
|
||||
t.literal('aliasMatch'),
|
||||
t.literal('conflict'),
|
||||
]);
|
||||
|
||||
export type SavedObjectResolveAliasTargetId = t.TypeOf<typeof SavedObjectResolveAliasTargetId>;
|
||||
export const SavedObjectResolveAliasTargetId = t.string;
|
||||
|
||||
export type SavedObjectResolveAliasPurpose = t.TypeOf<typeof SavedObjectResolveAliasPurpose>;
|
||||
export const SavedObjectResolveAliasPurpose = t.union([
|
||||
t.literal('savedObjectConversion'),
|
||||
t.literal('savedObjectImport'),
|
||||
]);
|
|
@ -1,14 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import * as t from 'io-ts';
|
||||
|
||||
export type TimelineTemplateId = t.TypeOf<typeof TimelineTemplateId>;
|
||||
export const TimelineTemplateId = t.string; // should be non-empty string?
|
||||
|
||||
export type TimelineTemplateTitle = t.TypeOf<typeof TimelineTemplateTitle>;
|
||||
export const TimelineTemplateTitle = t.string; // should be non-empty string?
|
|
@ -5,12 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
export * from './common_attributes/field_overrides';
|
||||
export * from './common_attributes/misc_attributes';
|
||||
export * from './common_attributes/related_integrations';
|
||||
export * from './common_attributes/required_fields';
|
||||
export * from './common_attributes/saved_objects';
|
||||
export * from './common_attributes/timeline_template';
|
||||
export * from './common_attributes';
|
||||
|
||||
export * from './specific_attributes/eql_attributes';
|
||||
export * from './specific_attributes/new_terms_attributes';
|
||||
|
|
|
@ -0,0 +1,849 @@
|
|||
openapi: 3.0.0
|
||||
info:
|
||||
title: Security Rule Schema
|
||||
version: 'not applicable'
|
||||
paths: {}
|
||||
components:
|
||||
schemas:
|
||||
SortOrder:
|
||||
type: string
|
||||
enum:
|
||||
- asc
|
||||
- desc
|
||||
RuleExecutionStatus:
|
||||
type: string
|
||||
description: |-
|
||||
Custom execution status of Security rules that is different from the status used in the Alerting Framework. We merge our custom status with the Framework's status to determine the resulting status of a rule.
|
||||
- going to run - @deprecated Replaced by the 'running' status but left for backwards compatibility with rule execution events already written to Event Log in the prior versions of Kibana. Don't use when writing rule status changes.
|
||||
- running - Rule execution started but not reached any intermediate or final status.
|
||||
- partial failure - Rule can partially fail for various reasons either in the middle of an execution (in this case we update its status right away) or in the end of it. So currently this status can be both intermediate and final at the same time. A typical reason for a partial failure: not all the indices that the rule searches over actually exist.
|
||||
- failed - Rule failed to execute due to unhandled exception or a reason defined in the business logic of its executor function.
|
||||
- succeeded - Rule executed successfully without any issues. Note: this status is just an indication of a rule's "health". The rule might or might not generate any alerts despite of it.
|
||||
|
||||
enum:
|
||||
- going to run
|
||||
- running
|
||||
- partial failure
|
||||
- failed
|
||||
- succeeded
|
||||
|
||||
RuleExecutionResult:
|
||||
type: object
|
||||
description: |-
|
||||
Rule execution result is an aggregate that groups plain rule execution events by execution UUID.
|
||||
It contains such information as execution UUID, date, status and metrics.
|
||||
properties:
|
||||
execution_uuid:
|
||||
type: string
|
||||
timestamp:
|
||||
type: string
|
||||
format: date-time
|
||||
duration_ms:
|
||||
type: integer
|
||||
status:
|
||||
type: string
|
||||
message:
|
||||
type: string
|
||||
num_active_alerts:
|
||||
type: integer
|
||||
num_new_alerts:
|
||||
type: integer
|
||||
num_recovered_alerts:
|
||||
type: integer
|
||||
num_triggered_actions:
|
||||
type: integer
|
||||
num_succeeded_actions:
|
||||
type: integer
|
||||
num_errored_actions:
|
||||
type: integer
|
||||
total_search_duration_ms:
|
||||
type: integer
|
||||
es_search_duration_ms:
|
||||
type: integer
|
||||
schedule_delay_ms:
|
||||
type: integer
|
||||
timed_out:
|
||||
type: boolean
|
||||
indexing_duration_ms:
|
||||
type: integer
|
||||
search_duration_ms:
|
||||
type: integer
|
||||
gap_duration_s:
|
||||
type: integer
|
||||
security_status:
|
||||
type: string
|
||||
security_message:
|
||||
type: string
|
||||
required:
|
||||
- execution_uuid
|
||||
- timestamp
|
||||
- duration_ms
|
||||
- status
|
||||
- message
|
||||
- num_active_alerts
|
||||
- num_new_alerts
|
||||
- num_recovered_alerts
|
||||
- num_triggered_actions
|
||||
- num_succeeded_actions
|
||||
- num_errored_actions
|
||||
- total_search_duration_ms
|
||||
- es_search_duration_ms
|
||||
- schedule_delay_ms
|
||||
- timed_out
|
||||
- indexing_duration_ms
|
||||
- search_duration_ms
|
||||
- gap_duration_s
|
||||
- security_status
|
||||
- security_message
|
||||
|
||||
Action:
|
||||
type: object
|
||||
properties:
|
||||
action_type_id:
|
||||
type: string
|
||||
description: The action type used for sending notifications.
|
||||
group:
|
||||
type: string
|
||||
description: Optionally groups actions by use cases. Use `default` for alert notifications.
|
||||
id:
|
||||
type: string
|
||||
description: The connector ID.
|
||||
params:
|
||||
type: object
|
||||
description: Object containing the allowed connector fields, which varies according to the connector type.
|
||||
uuid:
|
||||
type: string
|
||||
alerts_filter:
|
||||
type: object
|
||||
description: TODO implement the schema type
|
||||
frequency:
|
||||
type: object
|
||||
description: TODO implement the schema type
|
||||
required:
|
||||
- action_type_id
|
||||
- group
|
||||
- id
|
||||
- params
|
||||
|
||||
AlertSuppression:
|
||||
type: object
|
||||
properties:
|
||||
group_by:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
minItems: 1
|
||||
maxItems: 3
|
||||
duration:
|
||||
type: object
|
||||
properties:
|
||||
value:
|
||||
type: integer
|
||||
minimum: 1
|
||||
unit:
|
||||
type: string
|
||||
enum:
|
||||
- s
|
||||
- m
|
||||
- h
|
||||
required:
|
||||
- value
|
||||
- unit
|
||||
missing_fields_strategy:
|
||||
type: string
|
||||
enum:
|
||||
- doNotSuppress
|
||||
- suppress
|
||||
required:
|
||||
- group_by
|
||||
|
||||
BaseRule:
|
||||
type: object
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
description: Rule name
|
||||
description:
|
||||
type: string
|
||||
description: Rule description
|
||||
risk_score:
|
||||
type: integer
|
||||
description: Risk score (0 to 100)
|
||||
minimum: 0
|
||||
maximum: 100
|
||||
severity:
|
||||
type: string
|
||||
enum: [low, medium, high, critical]
|
||||
description: Severity of the rule
|
||||
rule_name_override:
|
||||
type: string
|
||||
description: Sets the source field for the alert's signal.rule.name value
|
||||
timestamp_override:
|
||||
type: string
|
||||
description: Sets the time field used to query indices (optional)
|
||||
timeline_id:
|
||||
type: string
|
||||
description: Timeline template ID
|
||||
timeline_title:
|
||||
type: string
|
||||
description: Timeline template title
|
||||
outcome:
|
||||
type: string
|
||||
enum:
|
||||
- exactMatch
|
||||
- aliasMatch
|
||||
- conflict
|
||||
alias_target_id:
|
||||
type: string
|
||||
description: TODO
|
||||
alias_purpose:
|
||||
type: string
|
||||
enum:
|
||||
- savedObjectConversion
|
||||
- savedObjectImport
|
||||
description: TODO
|
||||
license:
|
||||
type: string
|
||||
description: The rule’s license.
|
||||
note:
|
||||
type: string
|
||||
description: Notes to help investigate alerts produced by the rule.
|
||||
building_block_type:
|
||||
type: string
|
||||
description: Determines if the rule acts as a building block. By default, building-block alerts are not displayed in the UI. These rules are used as a foundation for other rules that do generate alerts. Its value must be default.
|
||||
output_index:
|
||||
type: string
|
||||
description: (deprecated) Has no effect.
|
||||
namespace:
|
||||
type: string
|
||||
description: Has no effect.
|
||||
meta:
|
||||
type: object
|
||||
description: Stores rule metadata.
|
||||
throttle:
|
||||
type: string
|
||||
description: Defines the interval on which a rule's actions are executed.
|
||||
version:
|
||||
type: integer
|
||||
minimum: 1
|
||||
default: 1
|
||||
description: The rule’s version number. Defaults to 1.
|
||||
tags:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
default: []
|
||||
description: String array containing words and phrases to help categorize, filter, and search rules. Defaults to an empty array.
|
||||
enabled:
|
||||
type: boolean
|
||||
default: true
|
||||
description: Determines whether the rule is enabled. Defaults to true.
|
||||
risk_score_mapping:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
field:
|
||||
type: string
|
||||
operator:
|
||||
type: string
|
||||
enum:
|
||||
- equals
|
||||
value:
|
||||
type: string
|
||||
risk_score:
|
||||
type: integer
|
||||
minimum: 0
|
||||
maximum: 100
|
||||
required:
|
||||
- field
|
||||
- value
|
||||
- operator
|
||||
description: Overrides generated alerts' risk_score with a value from the source event
|
||||
default: []
|
||||
severity_mapping:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
field:
|
||||
type: string
|
||||
operator:
|
||||
type: string
|
||||
enum:
|
||||
- equals
|
||||
severity:
|
||||
type: string
|
||||
enum:
|
||||
- low
|
||||
- medium
|
||||
- high
|
||||
- critical
|
||||
value:
|
||||
type: string
|
||||
required:
|
||||
- field
|
||||
- operator
|
||||
- severity
|
||||
- value
|
||||
description: Overrides generated alerts' severity with values from the source event
|
||||
default: []
|
||||
interval:
|
||||
type: string
|
||||
description: Frequency of rule execution, using a date math range. For example, "1h" means the rule runs every hour. Defaults to 5m (5 minutes).
|
||||
default: 5m
|
||||
from:
|
||||
type: string
|
||||
description: Time from which data is analyzed each time the rule executes, using a date math range. For example, now-4200s means the rule analyzes data from 70 minutes before its start time. Defaults to now-6m (analyzes data from 6 minutes before the start time).
|
||||
default: now-6m
|
||||
to:
|
||||
type: string
|
||||
description: TODO
|
||||
default: now
|
||||
actions:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/Action'
|
||||
default: []
|
||||
exceptions_list:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
description: ID of the exception container
|
||||
minLength: 1
|
||||
list_id:
|
||||
type: string
|
||||
description: List ID of the exception container
|
||||
minLength: 1
|
||||
type:
|
||||
type: string
|
||||
description: The exception type
|
||||
enum:
|
||||
- detection
|
||||
- rule_default
|
||||
- endpoint
|
||||
- endpoint_trusted_apps
|
||||
- endpoint_events
|
||||
- endpoint_host_isolation_exceptions
|
||||
- endpoint_blocklists
|
||||
namespace_type:
|
||||
type: string
|
||||
description: Determines the exceptions validity in rule's Kibana space
|
||||
enum:
|
||||
- agnostic
|
||||
- single
|
||||
required:
|
||||
- id
|
||||
- list_id
|
||||
- type
|
||||
- namespace_type
|
||||
default: []
|
||||
author:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
default: []
|
||||
false_positives:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
default: []
|
||||
references:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
default: []
|
||||
max_signals:
|
||||
type: integer
|
||||
minimum: 1
|
||||
default: 100
|
||||
threat:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
framework:
|
||||
type: string
|
||||
description: Relevant attack framework
|
||||
tactic:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
reference:
|
||||
type: string
|
||||
required:
|
||||
- id
|
||||
- name
|
||||
- reference
|
||||
technique:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
reference:
|
||||
type: string
|
||||
subtechnique:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
reference:
|
||||
type: string
|
||||
required:
|
||||
- id
|
||||
- name
|
||||
- reference
|
||||
required:
|
||||
- id
|
||||
- name
|
||||
- reference
|
||||
required:
|
||||
- framework
|
||||
- tactic
|
||||
required:
|
||||
- id
|
||||
- name
|
||||
- description
|
||||
- risk_score
|
||||
- severity
|
||||
|
||||
QueryRule:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/BaseRule'
|
||||
- type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum: [query]
|
||||
description: Rule type
|
||||
index:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
data_view_id:
|
||||
type: string
|
||||
filters:
|
||||
type: array
|
||||
items: {} # unknown
|
||||
saved_id:
|
||||
type: string
|
||||
response_actions:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
description: TODO
|
||||
alert_suppression:
|
||||
$ref: '#/components/schemas/AlertSuppression'
|
||||
query:
|
||||
type: string
|
||||
description: Query to execute
|
||||
default: ''
|
||||
language:
|
||||
type: string
|
||||
enum:
|
||||
- kuery
|
||||
- lucene
|
||||
default: kuery
|
||||
description: Query language to use.
|
||||
required:
|
||||
- type
|
||||
|
||||
SavedQueryRule:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/BaseRule'
|
||||
- type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum: [saved_query]
|
||||
description: Rule type
|
||||
index:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
data_view_id:
|
||||
type: string
|
||||
filters:
|
||||
type: array
|
||||
items: {} # unknown
|
||||
saved_id:
|
||||
type: string
|
||||
response_actions:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
description: TODO
|
||||
alert_suppression:
|
||||
$ref: '#/components/schemas/AlertSuppression'
|
||||
query:
|
||||
type: string
|
||||
description: Query to execute
|
||||
language:
|
||||
type: string
|
||||
enum:
|
||||
- kuery
|
||||
- lucene
|
||||
default: kuery
|
||||
description: Query language to use.
|
||||
required:
|
||||
- type
|
||||
- saved_id
|
||||
|
||||
ThresholdRule:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/BaseRule'
|
||||
- type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum: [threshold]
|
||||
description: Rule type
|
||||
query:
|
||||
type: string
|
||||
threshold:
|
||||
type: object
|
||||
properties:
|
||||
field:
|
||||
oneOf:
|
||||
- type: string
|
||||
- type: array
|
||||
items:
|
||||
type: string
|
||||
description: Field to aggregate on
|
||||
value:
|
||||
type: integer
|
||||
minimum: 1
|
||||
description: Threshold value
|
||||
cardinality:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
field:
|
||||
type: string
|
||||
value:
|
||||
type: integer
|
||||
minimum: 0
|
||||
index:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
data_view_id:
|
||||
type: string
|
||||
filters:
|
||||
type: array
|
||||
items: {} # unknown
|
||||
saved_id:
|
||||
type: string
|
||||
language:
|
||||
type: string
|
||||
enum:
|
||||
- kuery
|
||||
- lucene
|
||||
default: kuery
|
||||
description: Query language to use.
|
||||
required:
|
||||
- type
|
||||
- query
|
||||
- threshold
|
||||
ThreatMatchRule:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/BaseRule'
|
||||
- type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum: [threat_match]
|
||||
description: Rule type
|
||||
query:
|
||||
type: string
|
||||
threat_query:
|
||||
type: string
|
||||
description: Query to execute
|
||||
threat_mapping:
|
||||
type: array
|
||||
minItems: 1
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
entries:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
field:
|
||||
type: string
|
||||
minLength: 1
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- mapping
|
||||
value:
|
||||
type: string
|
||||
minLength: 1
|
||||
threat_index:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
index:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
data_view_id:
|
||||
type: string
|
||||
filters:
|
||||
type: array
|
||||
items: {} # unknown
|
||||
saved_id:
|
||||
type: string
|
||||
threat_filters:
|
||||
type: array
|
||||
items:
|
||||
description: Query and filter context array used to filter documents from the Elasticsearch index containing the threat values
|
||||
threat_indicator_path:
|
||||
type: string
|
||||
description: Defines the path to the threat indicator in the indicator documents (optional)
|
||||
threat_language:
|
||||
type: string
|
||||
enum:
|
||||
- kuery
|
||||
- lucene
|
||||
description: Query language to use.
|
||||
concurrent_searches:
|
||||
type: integer
|
||||
minimum: 1
|
||||
items_per_search:
|
||||
type: integer
|
||||
minimum: 1
|
||||
language:
|
||||
type: string
|
||||
enum:
|
||||
- kuery
|
||||
- lucene
|
||||
default: kuery
|
||||
description: Query language to use.
|
||||
required:
|
||||
- type
|
||||
- query
|
||||
- threat_query
|
||||
- threat_mapping
|
||||
- threat_index
|
||||
MlRule:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/BaseRule'
|
||||
- type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum: [machine_learning]
|
||||
description: Rule type
|
||||
anomaly_threshold:
|
||||
type: integer
|
||||
minimum: 0
|
||||
description: Anomaly threshold
|
||||
machine_learning_job_id:
|
||||
oneOf:
|
||||
- type: string
|
||||
- type: array
|
||||
items:
|
||||
type: string
|
||||
minItems: 1
|
||||
description: Machine learning job ID
|
||||
required:
|
||||
- type
|
||||
- machine_learning_job_id
|
||||
- anomaly_threshold
|
||||
EqlRule:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/BaseRule'
|
||||
- type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum: [eql]
|
||||
description: Rule type
|
||||
language:
|
||||
type: string
|
||||
enum:
|
||||
- eql
|
||||
query:
|
||||
type: string
|
||||
description: EQL query to execute
|
||||
index:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
data_view_id:
|
||||
type: string
|
||||
filters:
|
||||
type: array
|
||||
items: {} # unknown
|
||||
event_category_field:
|
||||
type: string
|
||||
description: Contains the event classification
|
||||
tiebreaker_field:
|
||||
type: string
|
||||
description: Sets a secondary field for sorting events
|
||||
timestamp_field:
|
||||
type: string
|
||||
description: Contains the event timestamp used for sorting a sequence of events
|
||||
required:
|
||||
- type
|
||||
- language
|
||||
- query
|
||||
|
||||
NewTermsRule:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/BaseRule'
|
||||
- type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum: [new_terms]
|
||||
description: Rule type
|
||||
query:
|
||||
type: string
|
||||
new_terms_fields:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
minItems: 1
|
||||
maxItems: 3
|
||||
history_window_size:
|
||||
type: string
|
||||
minLength: 1
|
||||
index:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
data_view_id:
|
||||
type: string
|
||||
filters:
|
||||
type: array
|
||||
items: {} # unknown
|
||||
language:
|
||||
type: string
|
||||
enum:
|
||||
- kuery
|
||||
- lucene
|
||||
default: kuery
|
||||
required:
|
||||
- type
|
||||
- query
|
||||
- new_terms_fields
|
||||
- history_window_start
|
||||
|
||||
Rule:
|
||||
oneOf:
|
||||
- $ref: '#/components/schemas/QueryRule'
|
||||
- $ref: '#/components/schemas/SavedQueryRule'
|
||||
- $ref: '#/components/schemas/ThresholdRule'
|
||||
- $ref: '#/components/schemas/ThreatMatchRule'
|
||||
- $ref: '#/components/schemas/MlRule'
|
||||
- $ref: '#/components/schemas/EqlRule'
|
||||
- $ref: '#/components/schemas/NewTermsRule'
|
||||
|
||||
Throttle:
|
||||
type: string
|
||||
description: Defines the maximum interval in which a rule's actions are executed.
|
||||
enum:
|
||||
- rule
|
||||
- 1h
|
||||
- 1d
|
||||
- 7d
|
||||
|
||||
Subtechnique:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
description: Subtechnique ID
|
||||
name:
|
||||
type: string
|
||||
description: Subtechnique name
|
||||
reference:
|
||||
type: string
|
||||
description: Subtechnique reference
|
||||
required:
|
||||
- id
|
||||
- name
|
||||
- reference
|
||||
|
||||
Technique:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
description: Technique ID
|
||||
name:
|
||||
type: string
|
||||
description: Technique name
|
||||
reference:
|
||||
type: string
|
||||
description: Technique reference
|
||||
subtechnique:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/Subtechnique'
|
||||
description: Array containing more specific information on the attack technique
|
||||
required:
|
||||
- id
|
||||
- name
|
||||
- reference
|
||||
|
||||
Threat:
|
||||
type: object
|
||||
properties:
|
||||
framework:
|
||||
type: string
|
||||
description: Relevant attack framework
|
||||
tactic:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
description: Tactic ID
|
||||
name:
|
||||
type: string
|
||||
description: Tactic name
|
||||
reference:
|
||||
type: string
|
||||
description: Tactic reference
|
||||
required:
|
||||
- id
|
||||
- name
|
||||
- reference
|
||||
technique:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/Technique'
|
||||
description: Array containing information on the attack techniques (optional)
|
||||
required:
|
||||
- framework
|
||||
- tactic
|
||||
|
||||
RuleResponse:
|
||||
type: object
|
||||
|
||||
RuleCreateProps:
|
||||
type: object
|
||||
|
||||
RuleUpdateProps:
|
||||
type: object
|
||||
|
||||
RulePatchProps:
|
||||
type: object
|
|
@ -50,6 +50,8 @@ import {
|
|||
IsRuleEnabled,
|
||||
IsRuleImmutable,
|
||||
MaxSignals,
|
||||
RelatedIntegrationArray,
|
||||
RequiredFieldArray,
|
||||
RuleAuthorArray,
|
||||
RuleDescription,
|
||||
RuleFalsePositiveArray,
|
||||
|
@ -57,28 +59,23 @@ import {
|
|||
RuleLicense,
|
||||
RuleMetadata,
|
||||
RuleName,
|
||||
RuleNameOverride,
|
||||
RuleObjectId,
|
||||
RuleQuery,
|
||||
RuleReferenceArray,
|
||||
RuleSignatureId,
|
||||
RuleTagArray,
|
||||
RuleVersion,
|
||||
SetupGuide,
|
||||
ThreatArray,
|
||||
} from './common_attributes/misc_attributes';
|
||||
import {
|
||||
RuleNameOverride,
|
||||
TimestampOverride,
|
||||
TimestampOverrideFallbackDisabled,
|
||||
} from './common_attributes/field_overrides';
|
||||
import {
|
||||
SavedObjectResolveAliasPurpose,
|
||||
SavedObjectResolveAliasTargetId,
|
||||
SavedObjectResolveOutcome,
|
||||
} from './common_attributes/saved_objects';
|
||||
import { RelatedIntegrationArray } from './common_attributes/related_integrations';
|
||||
import { RequiredFieldArray } from './common_attributes/required_fields';
|
||||
import { TimelineTemplateId, TimelineTemplateTitle } from './common_attributes/timeline_template';
|
||||
SetupGuide,
|
||||
ThreatArray,
|
||||
TimelineTemplateId,
|
||||
TimelineTemplateTitle,
|
||||
TimestampOverride,
|
||||
TimestampOverrideFallbackDisabled,
|
||||
} from './common_attributes';
|
||||
import {
|
||||
EventCategoryOverride,
|
||||
TiebreakerField,
|
||||
|
@ -535,7 +532,7 @@ export const TypeSpecificResponse = t.union([
|
|||
// Final combined schemas
|
||||
|
||||
export type RuleCreateProps = t.TypeOf<typeof RuleCreateProps>;
|
||||
export const RuleCreateProps = t.intersection([SharedCreateProps, TypeSpecificCreateProps]);
|
||||
export const RuleCreateProps = t.intersection([TypeSpecificCreateProps, SharedCreateProps]);
|
||||
|
||||
export type RuleUpdateProps = t.TypeOf<typeof RuleUpdateProps>;
|
||||
export const RuleUpdateProps = t.intersection([TypeSpecificCreateProps, SharedUpdateProps]);
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
openapi: 3.0.0
|
||||
info:
|
||||
title: Warning Schema
|
||||
version: 'not applicable'
|
||||
paths: {}
|
||||
components:
|
||||
schemas:
|
||||
WarningSchema:
|
||||
type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
message:
|
||||
type: string
|
||||
actionPath:
|
||||
type: string
|
||||
buttonLabel:
|
||||
type: string
|
||||
required:
|
||||
- type
|
||||
- message
|
||||
- actionPath
|
|
@ -0,0 +1,61 @@
|
|||
openapi: 3.0.0
|
||||
info:
|
||||
title: Prebuilt Rules Status API endpoint
|
||||
version: 2023-10-31
|
||||
paths:
|
||||
/api/detection_engine/rules/prepackaged/_status:
|
||||
get:
|
||||
operationId: GetPrebuiltRulesStatus
|
||||
x-codegen-enabled: false
|
||||
summary: Get the status of Elastic prebuilt rules
|
||||
tags:
|
||||
- Prebuilt Rules API
|
||||
responses:
|
||||
200:
|
||||
description: Indicates a successful call
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/GetPrebuiltRulesStatusResponse'
|
||||
|
||||
components:
|
||||
schemas:
|
||||
GetPrebuiltRulesStatusResponse:
|
||||
type: object
|
||||
properties:
|
||||
rules_custom_installed:
|
||||
type: integer
|
||||
description: The total number of custom rules
|
||||
minimum: 0
|
||||
rules_installed:
|
||||
type: integer
|
||||
description: The total number of installed prebuilt rules
|
||||
minimum: 0
|
||||
rules_not_installed:
|
||||
type: integer
|
||||
description: The total number of available prebuilt rules that are not installed
|
||||
minimum: 0
|
||||
rules_not_updated:
|
||||
type: integer
|
||||
description: The total number of outdated prebuilt rules
|
||||
minimum: 0
|
||||
timelines_installed:
|
||||
type: integer
|
||||
description: The total number of installed prebuilt timelines
|
||||
minimum: 0
|
||||
timelines_not_installed:
|
||||
type: integer
|
||||
description: The total number of available prebuilt timelines that are not installed
|
||||
minimum: 0
|
||||
timelines_not_updated:
|
||||
type: integer
|
||||
description: The total number of outdated prebuilt timelines
|
||||
minimum: 0
|
||||
required:
|
||||
- rules_custom_installed
|
||||
- rules_installed
|
||||
- rules_not_installed
|
||||
- rules_not_updated
|
||||
- timelines_installed
|
||||
- timelines_not_installed
|
||||
- timelines_not_updated
|
|
@ -0,0 +1,46 @@
|
|||
openapi: 3.0.0
|
||||
info:
|
||||
title: Install Prebuilt Rules API endpoint
|
||||
version: 2023-10-31
|
||||
paths:
|
||||
/api/detection_engine/rules/prepackaged:
|
||||
put:
|
||||
operationId: InstallPrebuiltRules
|
||||
x-codegen-enabled: false
|
||||
summary: Installs all Elastic prebuilt rules and timelines
|
||||
tags:
|
||||
- Prebuilt Rules API
|
||||
responses:
|
||||
200:
|
||||
description: Indicates a successful call
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/InstallPrebuiltRulesResponse'
|
||||
|
||||
components:
|
||||
schemas:
|
||||
InstallPrebuiltRulesResponse:
|
||||
type: object
|
||||
properties:
|
||||
rules_installed:
|
||||
type: integer
|
||||
description: The number of rules installed
|
||||
minimum: 0
|
||||
rules_updated:
|
||||
type: integer
|
||||
description: The number of rules updated
|
||||
minimum: 0
|
||||
timelines_installed:
|
||||
type: integer
|
||||
description: The number of timelines installed
|
||||
minimum: 0
|
||||
timelines_updated:
|
||||
type: integer
|
||||
description: The number of timelines updated
|
||||
minimum: 0
|
||||
required:
|
||||
- rules_installed
|
||||
- rules_updated
|
||||
- timelines_installed
|
||||
- timelines_updated
|
|
@ -0,0 +1,461 @@
|
|||
openapi: 3.0.0
|
||||
info:
|
||||
title: Bulk Actions API endpoint
|
||||
version: 2023-10-31
|
||||
paths:
|
||||
/api/detection_engine/rules/_bulk_action:
|
||||
post:
|
||||
operationId: PerformBulkAction
|
||||
x-codegen-enabled: false
|
||||
summary: Applies a bulk action to multiple rules
|
||||
description: The bulk action is applied to all rules that match the filter or to the list of rules by their IDs.
|
||||
tags:
|
||||
- Bulk API
|
||||
parameters:
|
||||
- name: dry_run
|
||||
in: query
|
||||
description: Enables dry run mode for the request call.
|
||||
required: false
|
||||
schema:
|
||||
type: boolean
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/PerformBulkActionRequest'
|
||||
responses:
|
||||
200:
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/BulkEditActionResponse'
|
||||
|
||||
components:
|
||||
schemas:
|
||||
BulkEditSkipReason:
|
||||
type: string
|
||||
enum:
|
||||
- RULE_NOT_MODIFIED
|
||||
|
||||
BulkActionSkipResult:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
skip_reason:
|
||||
$ref: '#/components/schemas/BulkEditSkipReason'
|
||||
required:
|
||||
- id
|
||||
- skip_reason
|
||||
|
||||
RuleDetailsInError:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
required:
|
||||
- id
|
||||
|
||||
BulkActionsDryRunErrCode:
|
||||
type: string
|
||||
|
||||
NormalizedRuleError:
|
||||
type: object
|
||||
properties:
|
||||
message:
|
||||
type: string
|
||||
status_code:
|
||||
type: integer
|
||||
err_code:
|
||||
$ref: '#/components/schemas/BulkActionsDryRunErrCode'
|
||||
rules:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/RuleDetailsInError'
|
||||
required:
|
||||
- message
|
||||
- status_code
|
||||
- rules
|
||||
|
||||
BulkEditActionResults:
|
||||
type: object
|
||||
properties:
|
||||
updated:
|
||||
type: array
|
||||
items:
|
||||
$ref: '../../model/rule_schema/rule_schemas.schema.yaml#/components/schemas/RuleResponse'
|
||||
created:
|
||||
type: array
|
||||
items:
|
||||
$ref: '../../model/rule_schema/rule_schemas.schema.yaml#/components/schemas/RuleResponse'
|
||||
deleted:
|
||||
type: array
|
||||
items:
|
||||
$ref: '../../model/rule_schema/rule_schemas.schema.yaml#/components/schemas/RuleResponse'
|
||||
skipped:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/BulkActionSkipResult'
|
||||
required:
|
||||
- updated
|
||||
- created
|
||||
- deleted
|
||||
- skipped
|
||||
|
||||
BulkEditActionSummary:
|
||||
type: object
|
||||
properties:
|
||||
failed:
|
||||
type: integer
|
||||
skipped:
|
||||
type: integer
|
||||
succeeded:
|
||||
type: integer
|
||||
total:
|
||||
type: integer
|
||||
required:
|
||||
- failed
|
||||
- skipped
|
||||
- succeeded
|
||||
- total
|
||||
|
||||
BulkEditActionSuccessResponse:
|
||||
type: object
|
||||
properties:
|
||||
success:
|
||||
type: boolean
|
||||
rules_count:
|
||||
type: integer
|
||||
attributes:
|
||||
type: object
|
||||
properties:
|
||||
results:
|
||||
$ref: '#/components/schemas/BulkEditActionResults'
|
||||
summary:
|
||||
$ref: '#/components/schemas/BulkEditActionSummary'
|
||||
required:
|
||||
- results
|
||||
- summary
|
||||
required:
|
||||
- success
|
||||
- rules_count
|
||||
- attributes
|
||||
|
||||
BulkEditActionErrorResponse:
|
||||
type: object
|
||||
properties:
|
||||
status_code:
|
||||
type: integer
|
||||
message:
|
||||
type: string
|
||||
attributes:
|
||||
type: object
|
||||
properties:
|
||||
results:
|
||||
$ref: '#/components/schemas/BulkEditActionResults'
|
||||
summary:
|
||||
$ref: '#/components/schemas/BulkEditActionSummary'
|
||||
errors:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/NormalizedRuleError'
|
||||
required:
|
||||
- results
|
||||
- summary
|
||||
required:
|
||||
- status_code
|
||||
- message
|
||||
- attributes
|
||||
|
||||
BulkEditActionResponse:
|
||||
oneOf:
|
||||
- $ref: '#/components/schemas/BulkEditActionSuccessResponse'
|
||||
- $ref: '#/components/schemas/BulkEditActionErrorResponse'
|
||||
|
||||
BulkActionBase:
|
||||
oneOf:
|
||||
- type: object
|
||||
properties:
|
||||
query:
|
||||
type: string
|
||||
description: Query to filter rules
|
||||
required:
|
||||
- query
|
||||
additionalProperties: false
|
||||
|
||||
- type: object
|
||||
properties:
|
||||
ids:
|
||||
type: array
|
||||
description: Array of rule IDs
|
||||
minItems: 1
|
||||
items:
|
||||
type: string
|
||||
additionalProperties: false
|
||||
|
||||
BulkDeleteRules:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/BulkActionBase'
|
||||
- type: object
|
||||
properties:
|
||||
action:
|
||||
type: string
|
||||
enum: [delete]
|
||||
required:
|
||||
- action
|
||||
|
||||
BulkDisableRules:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/BulkActionBase'
|
||||
- type: object
|
||||
properties:
|
||||
action:
|
||||
type: string
|
||||
enum: [disable]
|
||||
required:
|
||||
- action
|
||||
|
||||
BulkEnableRules:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/BulkActionBase'
|
||||
- type: object
|
||||
properties:
|
||||
action:
|
||||
type: string
|
||||
enum: [enable]
|
||||
required:
|
||||
- action
|
||||
|
||||
BulkExportRules:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/BulkActionBase'
|
||||
- type: object
|
||||
properties:
|
||||
action:
|
||||
type: string
|
||||
enum: [export]
|
||||
required:
|
||||
- action
|
||||
|
||||
BulkDuplicateRules:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/BulkActionBase'
|
||||
- type: object
|
||||
properties:
|
||||
action:
|
||||
type: string
|
||||
enum: [duplicate]
|
||||
duplicate:
|
||||
type: object
|
||||
properties:
|
||||
include_exceptions:
|
||||
type: boolean
|
||||
description: Whether to copy exceptions from the original rule
|
||||
include_expired_exceptions:
|
||||
type: boolean
|
||||
description: Whether to copy expired exceptions from the original rule
|
||||
required:
|
||||
- action
|
||||
|
||||
RuleActionSummary:
|
||||
type: boolean
|
||||
description: Action summary indicates whether we will send a summary notification about all the generate alerts or notification per individual alert
|
||||
|
||||
RuleActionNotifyWhen:
|
||||
type: string
|
||||
description: "The condition for throttling the notification: 'onActionGroupChange', 'onActiveAlert', or 'onThrottleInterval'"
|
||||
enum:
|
||||
- onActionGroupChange
|
||||
- onActiveAlert
|
||||
- onThrottleInterval
|
||||
|
||||
RuleActionThrottle:
|
||||
type: string
|
||||
description: "The condition for throttling the notification: 'rule', 'no_actions', or time duration"
|
||||
|
||||
RuleActionFrequency:
|
||||
type: object
|
||||
properties:
|
||||
summary:
|
||||
$ref: '#/components/schemas/RuleActionSummary'
|
||||
notifyWhen:
|
||||
$ref: '#/components/schemas/RuleActionNotifyWhen'
|
||||
throttle:
|
||||
$ref: '#/components/schemas/RuleActionThrottle'
|
||||
nullable: true
|
||||
|
||||
BulkActionType:
|
||||
type: string
|
||||
enum:
|
||||
- enable
|
||||
- disable
|
||||
- export
|
||||
- delete
|
||||
- duplicate
|
||||
- edit
|
||||
|
||||
BulkActionEditType:
|
||||
type: string
|
||||
enum:
|
||||
- add_tags
|
||||
- delete_tags
|
||||
- set_tags
|
||||
- add_index_patterns
|
||||
- delete_index_patterns
|
||||
- set_index_patterns
|
||||
- set_timeline
|
||||
- add_rule_actions
|
||||
- set_rule_actions
|
||||
- set_schedule
|
||||
|
||||
BulkActionEditPayloadRuleActions:
|
||||
type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum: [add_rule_actions, set_rule_actions]
|
||||
value:
|
||||
type: object
|
||||
properties:
|
||||
throttle:
|
||||
$ref: '#/components/schemas/RuleActionThrottle'
|
||||
actions:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
group:
|
||||
type: string
|
||||
description: Action group
|
||||
id:
|
||||
type: string
|
||||
description: Action ID
|
||||
params:
|
||||
type: object
|
||||
description: Action parameters
|
||||
frequency:
|
||||
$ref: '#/components/schemas/RuleActionFrequency'
|
||||
description: Action frequency
|
||||
required:
|
||||
- group
|
||||
- id
|
||||
- params
|
||||
required:
|
||||
- actions
|
||||
required:
|
||||
- type
|
||||
- value
|
||||
|
||||
BulkActionEditPayloadSchedule:
|
||||
type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum: [set_schedule]
|
||||
value:
|
||||
type: object
|
||||
properties:
|
||||
interval:
|
||||
type: string
|
||||
description: Interval in which the rule is executed
|
||||
lookback:
|
||||
type: string
|
||||
description: Lookback time for the rule
|
||||
required:
|
||||
- interval
|
||||
- lookback
|
||||
|
||||
BulkActionEditPayloadIndexPatterns:
|
||||
type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- add_index_patterns
|
||||
- delete_index_patterns
|
||||
- set_index_patterns
|
||||
value:
|
||||
$ref: '../../model/rule_schema/common_attributes.schema.yaml#/components/schemas/IndexPatternArray'
|
||||
overwrite_data_views:
|
||||
type: boolean
|
||||
required:
|
||||
- type
|
||||
- value
|
||||
|
||||
BulkActionEditPayloadTags:
|
||||
type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- add_tags
|
||||
- delete_tags
|
||||
- set_tags
|
||||
value:
|
||||
$ref: '../../model/rule_schema/common_attributes.schema.yaml#/components/schemas/RuleTagArray'
|
||||
required:
|
||||
- type
|
||||
- value
|
||||
|
||||
BulkActionEditPayloadTimeline:
|
||||
type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- set_timeline
|
||||
value:
|
||||
type: object
|
||||
properties:
|
||||
timeline_id:
|
||||
$ref: '../../model/rule_schema/common_attributes.schema.yaml#/components/schemas/TimelineTemplateId'
|
||||
timeline_title:
|
||||
$ref: '../../model/rule_schema/common_attributes.schema.yaml#/components/schemas/TimelineTemplateTitle'
|
||||
required:
|
||||
- timeline_id
|
||||
- timeline_title
|
||||
required:
|
||||
- type
|
||||
- value
|
||||
|
||||
BulkActionEditPayload:
|
||||
anyOf:
|
||||
- $ref: '#/components/schemas/BulkActionEditPayloadTags'
|
||||
- $ref: '#/components/schemas/BulkActionEditPayloadIndexPatterns'
|
||||
- $ref: '#/components/schemas/BulkActionEditPayloadTimeline'
|
||||
- $ref: '#/components/schemas/BulkActionEditPayloadRuleActions'
|
||||
- $ref: '#/components/schemas/BulkActionEditPayloadSchedule'
|
||||
|
||||
BulkEditRules:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/BulkActionBase'
|
||||
- type: object
|
||||
properties:
|
||||
action:
|
||||
type: string
|
||||
x-type: literal
|
||||
enum: [edit]
|
||||
edit:
|
||||
type: array
|
||||
description: Array of objects containing the edit operations
|
||||
items:
|
||||
$ref: '#/components/schemas/BulkActionEditPayload'
|
||||
required:
|
||||
- action
|
||||
- rule
|
||||
|
||||
PerformBulkActionRequest:
|
||||
oneOf:
|
||||
- $ref: '#/components/schemas/BulkDeleteRules'
|
||||
- $ref: '#/components/schemas/BulkDisableRules'
|
||||
- $ref: '#/components/schemas/BulkEnableRules'
|
||||
- $ref: '#/components/schemas/BulkExportRules'
|
||||
- $ref: '#/components/schemas/BulkDuplicateRules'
|
||||
- $ref: '#/components/schemas/BulkEditRules'
|
|
@ -53,13 +53,9 @@ export enum BulkActionEditType {
|
|||
export type ThrottleForBulkActions = t.TypeOf<typeof ThrottleForBulkActions>;
|
||||
export const ThrottleForBulkActions = t.union([
|
||||
t.literal('rule'),
|
||||
TimeDuration({
|
||||
allowedDurations: [
|
||||
[1, 'h'],
|
||||
[1, 'd'],
|
||||
[7, 'd'],
|
||||
],
|
||||
}),
|
||||
t.literal('1h'),
|
||||
t.literal('1d'),
|
||||
t.literal('7d'),
|
||||
]);
|
||||
|
||||
type BulkActionEditPayloadTags = t.TypeOf<typeof BulkActionEditPayloadTags>;
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
openapi: 3.0.0
|
||||
info:
|
||||
title: Bulk Create API endpoint
|
||||
version: 2023-10-31
|
||||
paths:
|
||||
/api/detection_engine/rules/_bulk_create:
|
||||
post:
|
||||
operationId: CreateRulesBulk
|
||||
x-codegen-enabled: false
|
||||
deprecated: true
|
||||
description: Creates new detection rules in bulk.
|
||||
tags:
|
||||
- Bulk API
|
||||
requestBody:
|
||||
description: A JSON array of rules, where each rule contains the required fields.
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '../../../model/rule_schema/rule_schemas.schema.yaml#/components/schemas/RuleCreateProps'
|
||||
responses:
|
||||
200:
|
||||
description: Indicates a successful call.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '../response_schema.schema.yaml#/components/schemas/BulkCrudRulesResponse'
|
|
@ -0,0 +1,34 @@
|
|||
openapi: 3.0.0
|
||||
info:
|
||||
title: Bulk Delete API endpoint
|
||||
version: 2023-10-31
|
||||
paths:
|
||||
/api/detection_engine/rules/_bulk_delete:
|
||||
delete:
|
||||
operationId: DeleteRulesBulk
|
||||
x-codegen-enabled: false
|
||||
deprecated: true
|
||||
description: Deletes multiple rules.
|
||||
tags:
|
||||
- Bulk API
|
||||
requestBody:
|
||||
description: A JSON array of `id` or `rule_id` fields of the rules you want to delete.
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
$ref: '../../../model/rule_schema/common_attributes.schema.yaml#/components/schemas/RuleObjectId'
|
||||
rule_id:
|
||||
$ref: '../../../model/rule_schema/common_attributes.schema.yaml#/components/schemas/RuleSignatureId'
|
||||
responses:
|
||||
200:
|
||||
description: Indicates a successful call.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '../response_schema.schema.yaml#/components/schemas/BulkCrudRulesResponse'
|
|
@ -0,0 +1,29 @@
|
|||
openapi: 3.0.0
|
||||
info:
|
||||
title: Bulk Patch API endpoint
|
||||
version: 2023-10-31
|
||||
paths:
|
||||
/api/detection_engine/rules/_bulk_update:
|
||||
patch:
|
||||
operationId: PatchRulesBulk
|
||||
x-codegen-enabled: false
|
||||
deprecated: true
|
||||
description: Updates multiple rules using the `PATCH` method.
|
||||
tags:
|
||||
- Bulk API
|
||||
requestBody:
|
||||
description: A JSON array of rules, where each rule contains the required fields.
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '../../../model/rule_schema/rule_schemas.schema.yaml#/components/schemas/RulePatchProps'
|
||||
responses:
|
||||
200:
|
||||
description: Indicates a successful call.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '../response_schema.schema.yaml#/components/schemas/BulkCrudRulesResponse'
|
|
@ -6,10 +6,10 @@
|
|||
*/
|
||||
|
||||
import * as t from 'io-ts';
|
||||
import { PatchRuleRequestBody } from '../../crud/patch_rule/patch_rule_route';
|
||||
import { RulePatchProps } from '../../../model';
|
||||
|
||||
/**
|
||||
* Request body parameters of the API route.
|
||||
*/
|
||||
export type BulkPatchRulesRequestBody = t.TypeOf<typeof BulkPatchRulesRequestBody>;
|
||||
export const BulkPatchRulesRequestBody = t.array(PatchRuleRequestBody);
|
||||
export const BulkPatchRulesRequestBody = t.array(RulePatchProps);
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
openapi: 3.0.0
|
||||
info:
|
||||
title: Bulk Update API endpoint
|
||||
version: 2023-10-31
|
||||
paths:
|
||||
/api/detection_engine/rules/_bulk_update:
|
||||
put:
|
||||
operationId: UpdateRulesBulk
|
||||
x-codegen-enabled: false
|
||||
deprecated: true
|
||||
description: Updates multiple rules using the `PUT` method.
|
||||
tags:
|
||||
- Bulk API
|
||||
requestBody:
|
||||
description: A JSON array where each element includes the `id` or `rule_id` field of the rule you want to update and the fields you want to modify.
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '../../../model/rule_schema/rule_schemas.schema.yaml#/components/schemas/RuleUpdateProps'
|
||||
responses:
|
||||
200:
|
||||
description: Indicates a successful call.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '../response_schema.schema.yaml#/components/schemas/BulkCrudRulesResponse'
|
|
@ -0,0 +1,13 @@
|
|||
openapi: 3.0.0
|
||||
info:
|
||||
title: Bulk Response Schema
|
||||
version: 8.9.0
|
||||
paths: {}
|
||||
components:
|
||||
schemas:
|
||||
BulkCrudRulesResponse:
|
||||
type: array
|
||||
items:
|
||||
oneOf:
|
||||
- $ref: '../../model/rule_schema/rule_schemas.schema.yaml#/components/schemas/RuleResponse'
|
||||
- $ref: '../../model/error_schema.schema.yaml#/components/schemas/ErrorSchema'
|
|
@ -11,7 +11,7 @@ import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts
|
|||
|
||||
import type { RuleResponse, ErrorSchema } from '../../model';
|
||||
import { getRulesSchemaMock } from '../../model/rule_schema/mocks';
|
||||
import { getErrorSchemaMock } from '../../model/error_schema.mocks';
|
||||
import { getErrorSchemaMock } from '../../model/error_schema.mock';
|
||||
|
||||
import { BulkCrudRulesResponse } from './response_schema';
|
||||
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
openapi: 3.0.0
|
||||
info:
|
||||
title: Create Rule API endpoint
|
||||
version: 2023-10-31
|
||||
paths:
|
||||
/api/detection_engine/rules:
|
||||
post:
|
||||
operationId: CreateRule
|
||||
x-codegen-enabled: false
|
||||
description: Create a single detection rule
|
||||
tags:
|
||||
- Rules API
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '../../../model/rule_schema/rule_schemas.schema.yaml#/components/schemas/RuleCreateProps'
|
||||
responses:
|
||||
200:
|
||||
description: Indicates a successful call.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '../../../model/rule_schema/rule_schemas.schema.yaml#/components/schemas/RuleResponse'
|
|
@ -0,0 +1,32 @@
|
|||
openapi: 3.0.0
|
||||
info:
|
||||
title: Delete Rule API endpoint
|
||||
version: 2023-10-31
|
||||
paths:
|
||||
/api/detection_engine/rules:
|
||||
delete:
|
||||
operationId: DeleteRule
|
||||
x-codegen-enabled: false
|
||||
description: Deletes a single rule using the `rule_id` or `id` field.
|
||||
tags:
|
||||
- Rules API
|
||||
parameters:
|
||||
- name: id
|
||||
in: query
|
||||
required: false
|
||||
description: The rule's `id` value.
|
||||
schema:
|
||||
$ref: '../../../model/rule_schema/common_attributes.schema.yaml#/components/schemas/RuleSignatureId'
|
||||
- name: rule_id
|
||||
in: query
|
||||
required: false
|
||||
description: The rule's `rule_id` value.
|
||||
schema:
|
||||
$ref: '../../../model/rule_schema/common_attributes.schema.yaml#/components/schemas/RuleObjectId'
|
||||
responses:
|
||||
200:
|
||||
description: Indicates a successful call.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '../../../model/rule_schema/rule_schemas.schema.yaml#/components/schemas/RuleResponse'
|
|
@ -7,6 +7,10 @@
|
|||
|
||||
import type * as t from 'io-ts';
|
||||
import { RuleResponse } from '../../../model';
|
||||
import { QueryRuleByIds } from '../../model/query_rule_by_ids';
|
||||
|
||||
export const DeleteRuleRequestQuery = QueryRuleByIds;
|
||||
export type DeleteRuleRequestQuery = t.TypeOf<typeof DeleteRuleRequestQuery>;
|
||||
|
||||
export const DeleteRuleResponse = RuleResponse;
|
||||
export type DeleteRuleResponse = t.TypeOf<typeof DeleteRuleResponse>;
|
||||
|
|
|
@ -5,7 +5,8 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import type { PatchRuleRequestBody, ThresholdPatchRuleRequestBody } from './patch_rule_route';
|
||||
import type { ThresholdRulePatchProps } from '../../../model';
|
||||
import type { PatchRuleRequestBody } from './patch_rule_route';
|
||||
|
||||
export const getPatchRulesSchemaMock = (): PatchRuleRequestBody => ({
|
||||
description: 'some description',
|
||||
|
@ -18,7 +19,7 @@ export const getPatchRulesSchemaMock = (): PatchRuleRequestBody => ({
|
|||
rule_id: 'rule-1',
|
||||
});
|
||||
|
||||
export const getPatchThresholdRulesSchemaMock = (): ThresholdPatchRuleRequestBody => ({
|
||||
export const getPatchThresholdRulesSchemaMock = (): ThresholdRulePatchProps => ({
|
||||
description: 'some description',
|
||||
name: 'Query with a rule id',
|
||||
query: 'user.name: root or user.name: admin',
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
openapi: 3.0.0
|
||||
info:
|
||||
title: Patch Rule API endpoint
|
||||
version: 2023-10-31
|
||||
paths:
|
||||
/api/detection_engine/rules:
|
||||
patch:
|
||||
operationId: PatchRule
|
||||
x-codegen-enabled: false
|
||||
description: Patch a single rule
|
||||
tags:
|
||||
- Rules API
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '../../../model/rule_schema/rule_schemas.schema.yaml#/components/schemas/RulePatchProps'
|
||||
responses:
|
||||
200:
|
||||
description: Indicates a successful call.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '../../../model/rule_schema/rule_schemas.schema.yaml#/components/schemas/RuleResponse'
|
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
|
||||
import type * as t from 'io-ts';
|
||||
import { RulePatchProps, RuleResponse, ThresholdRulePatchProps } from '../../../model';
|
||||
import { RulePatchProps, RuleResponse } from '../../../model';
|
||||
|
||||
/**
|
||||
* Request body parameters of the API route.
|
||||
|
@ -15,8 +15,5 @@ import { RulePatchProps, RuleResponse, ThresholdRulePatchProps } from '../../../
|
|||
export type PatchRuleRequestBody = RulePatchProps;
|
||||
export const PatchRuleRequestBody = RulePatchProps;
|
||||
|
||||
export type ThresholdPatchRuleRequestBody = ThresholdRulePatchProps;
|
||||
export const ThresholdPatchRuleRequestBody = ThresholdRulePatchProps;
|
||||
|
||||
export const PatchRuleResponse = RuleResponse;
|
||||
export type PatchRuleResponse = t.TypeOf<typeof PatchRuleResponse>;
|
||||
|
|
|
@ -5,7 +5,8 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import type { PatchRuleRequestBody, ThresholdPatchRuleRequestBody } from './patch_rule_route';
|
||||
import type { ThresholdRulePatchProps } from '../../../model';
|
||||
import type { PatchRuleRequestBody } from './patch_rule_route';
|
||||
import { getPatchRulesSchemaMock, getPatchThresholdRulesSchemaMock } from './patch_rule_route.mock';
|
||||
import { validatePatchRuleRequestBody } from './request_schema_validation';
|
||||
|
||||
|
@ -72,7 +73,7 @@ describe('Patch rule request schema, additional validation', () => {
|
|||
});
|
||||
|
||||
test('threshold.value is required and has to be bigger than 0 when type is threshold and validates with it', () => {
|
||||
const schema: ThresholdPatchRuleRequestBody = {
|
||||
const schema: ThresholdRulePatchProps = {
|
||||
...getPatchThresholdRulesSchemaMock(),
|
||||
threshold: {
|
||||
field: '',
|
||||
|
@ -84,7 +85,7 @@ describe('Patch rule request schema, additional validation', () => {
|
|||
});
|
||||
|
||||
test('threshold.field should contain 3 items or less', () => {
|
||||
const schema: ThresholdPatchRuleRequestBody = {
|
||||
const schema: ThresholdRulePatchProps = {
|
||||
...getPatchThresholdRulesSchemaMock(),
|
||||
threshold: {
|
||||
field: ['field-1', 'field-2', 'field-3', 'field-4'],
|
||||
|
@ -96,7 +97,7 @@ describe('Patch rule request schema, additional validation', () => {
|
|||
});
|
||||
|
||||
test('threshold.cardinality[0].field should not be in threshold.field', () => {
|
||||
const schema: ThresholdPatchRuleRequestBody = {
|
||||
const schema: ThresholdRulePatchProps = {
|
||||
...getPatchThresholdRulesSchemaMock(),
|
||||
threshold: {
|
||||
field: ['field-1', 'field-2', 'field-3'],
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
openapi: 3.0.0
|
||||
info:
|
||||
title: Read Rule API endpoint
|
||||
version: 2023-10-31
|
||||
paths:
|
||||
/api/detection_engine/rules:
|
||||
get:
|
||||
operationId: ReadRule
|
||||
x-codegen-enabled: false
|
||||
description: Read a single rule
|
||||
tags:
|
||||
- Rules API
|
||||
parameters:
|
||||
- name: id
|
||||
in: query
|
||||
required: false
|
||||
description: The rule's `id` value.
|
||||
schema:
|
||||
$ref: '../../../model/rule_schema/common_attributes.schema.yaml#/components/schemas/RuleSignatureId'
|
||||
- name: rule_id
|
||||
in: query
|
||||
required: false
|
||||
description: The rule's `rule_id` value.
|
||||
schema:
|
||||
$ref: '../../../model/rule_schema/common_attributes.schema.yaml#/components/schemas/RuleObjectId'
|
||||
responses:
|
||||
200:
|
||||
description: Indicates a successful call.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '../../../model/rule_schema/rule_schemas.schema.yaml#/components/schemas/RuleResponse'
|
|
@ -0,0 +1,25 @@
|
|||
openapi: 3.0.0
|
||||
info:
|
||||
title: Update Rule API endpoint
|
||||
version: 2023-10-31
|
||||
paths:
|
||||
/api/detection_engine/rules:
|
||||
put:
|
||||
operationId: UpdateRule
|
||||
x-codegen-enabled: false
|
||||
description: Update a single rule
|
||||
tags:
|
||||
- Rules API
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '../../../model/rule_schema/rule_schemas.schema.yaml#/components/schemas/RuleUpdateProps'
|
||||
responses:
|
||||
200:
|
||||
description: Indicates a successful call.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '../../../model/rule_schema/rule_schemas.schema.yaml#/components/schemas/RuleResponse'
|
|
@ -0,0 +1,57 @@
|
|||
openapi: 3.0.0
|
||||
info:
|
||||
title: Export Rules API endpoint
|
||||
version: 2023-10-31
|
||||
paths:
|
||||
/api/detection_engine/rules/_export:
|
||||
summary: Exports rules to an `.ndjson` file
|
||||
post:
|
||||
operationId: ExportRules
|
||||
x-codegen-enabled: false
|
||||
summary: Export rules
|
||||
description: Exports rules to an `.ndjson` file. The following configuration items are also included in the `.ndjson` file - Actions, Exception lists. Prebuilt rules cannot be exported.
|
||||
tags:
|
||||
- Import/Export API
|
||||
parameters:
|
||||
- name: exclude_export_details
|
||||
in: query
|
||||
required: false
|
||||
description: Determines whether a summary of the exported rules is returned.
|
||||
schema:
|
||||
type: boolean
|
||||
default: false
|
||||
- name: file_name
|
||||
in: query
|
||||
required: false
|
||||
description: File name for saving the exported rules.
|
||||
schema:
|
||||
type: string
|
||||
default: export.ndjson
|
||||
requestBody:
|
||||
required: false
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required:
|
||||
- objects
|
||||
properties:
|
||||
objects:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required:
|
||||
- rule_id
|
||||
properties:
|
||||
rule_id:
|
||||
type: string
|
||||
description: Array of `rule_id` fields. Exports all rules when unspecified.
|
||||
responses:
|
||||
200:
|
||||
description: Indicates a successful call.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: string
|
||||
format: binary
|
||||
description: An `.ndjson` file containing the returned rules.
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
import * as t from 'io-ts';
|
||||
import { DefaultPerPage, DefaultPage } from '@kbn/securitysolution-io-ts-alerting-types';
|
||||
import type { PerPage, Page, RuleResponse } from '../../model';
|
||||
import type { RuleResponse } from '../../model';
|
||||
import { SortOrder, queryFilter, fields } from '../../model';
|
||||
|
||||
export type FindRulesSortField = t.TypeOf<typeof FindRulesSortField>;
|
||||
|
@ -46,11 +46,6 @@ export const FindRulesRequestQuery = t.exact(
|
|||
})
|
||||
);
|
||||
|
||||
export type FindRulesRequestQueryDecoded = Omit<FindRulesRequestQuery, 'per_page'> & {
|
||||
page: Page;
|
||||
per_page: PerPage;
|
||||
};
|
||||
|
||||
export interface FindRulesResponse {
|
||||
page: number;
|
||||
perPage: number;
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
openapi: 3.0.0
|
||||
info:
|
||||
title: Import Rules API endpoint
|
||||
version: 2023-10-31
|
||||
paths:
|
||||
/api/detection_engine/rules/_import:
|
||||
summary: Imports rules from an `.ndjson` file
|
||||
post:
|
||||
operationId: ImportRules
|
||||
x-codegen-enabled: false
|
||||
summary: Import rules
|
||||
description: Imports rules from an `.ndjson` file, including actions and exception lists.
|
||||
tags:
|
||||
- Import/Export API
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
multipart/form-data:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
file:
|
||||
type: string
|
||||
format: binary
|
||||
description: The `.ndjson` file containing the rules.
|
||||
parameters:
|
||||
- name: overwrite
|
||||
in: query
|
||||
required: false
|
||||
description: Determines whether existing rules with the same `rule_id` are overwritten.
|
||||
schema:
|
||||
type: boolean
|
||||
default: false
|
||||
- name: overwrite_exceptions
|
||||
in: query
|
||||
required: false
|
||||
description: Determines whether existing exception lists with the same `list_id` are overwritten.
|
||||
schema:
|
||||
type: boolean
|
||||
default: false
|
||||
- name: overwrite_action_connectors
|
||||
in: query
|
||||
required: false
|
||||
description: Determines whether existing actions with the same `kibana.alert.rule.actions.id` are overwritten.
|
||||
schema:
|
||||
type: boolean
|
||||
default: false
|
||||
responses:
|
||||
200:
|
||||
description: Indicates a successful call.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
|
@ -19,15 +19,12 @@ export const ImportRulesRequestQuery = t.exact(
|
|||
);
|
||||
|
||||
export type ImportRulesRequestQuery = t.TypeOf<typeof ImportRulesRequestQuery>;
|
||||
export type ImportRulesRequestQueryDecoded = Omit<
|
||||
ImportRulesRequestQuery,
|
||||
'overwrite' | 'overwrite_exceptions' | 'as_new_list' | 'overwrite_action_connectors'
|
||||
> & {
|
||||
export interface ImportRulesRequestQueryDecoded {
|
||||
overwrite: boolean;
|
||||
overwrite_exceptions: boolean;
|
||||
overwrite_action_connectors: boolean;
|
||||
as_new_list: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
export type ImportRulesResponse = t.TypeOf<typeof ImportRulesResponse>;
|
||||
export const ImportRulesResponse = t.exact(
|
||||
|
|
|
@ -31,4 +31,4 @@ export * from './import_rules/rule_to_import';
|
|||
export * from './model/query_rule_by_ids_validation';
|
||||
export * from './model/query_rule_by_ids';
|
||||
export * from './urls';
|
||||
export * from './tags/read_tags/read_tags_route';
|
||||
export * from './read_tags/read_tags_route';
|
||||
|
|
|
@ -10,11 +10,7 @@ import type { QueryRuleByIds } from './query_rule_by_ids';
|
|||
/**
|
||||
* Additional validation that is implemented outside of the schema itself.
|
||||
*/
|
||||
export const validateQueryRuleByIds = (schema: QueryRuleByIds): string[] => {
|
||||
return [...validateId(schema)];
|
||||
};
|
||||
|
||||
const validateId = (rule: QueryRuleByIds): string[] => {
|
||||
export const validateQueryRuleByIds = (rule: QueryRuleByIds): string[] => {
|
||||
if (rule.id != null && rule.rule_id != null) {
|
||||
return ['both "id" and "rule_id" cannot exist, choose one or the other'];
|
||||
} else if (rule.id == null && rule.rule_id == null) {
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
openapi: 3.0.0
|
||||
info:
|
||||
title: Tags API endpoint
|
||||
version: 2023-10-31
|
||||
paths:
|
||||
/api/detection_engine/tags:
|
||||
summary: Aggregates and returns rule tags
|
||||
get:
|
||||
operationId: GetTags
|
||||
x-codegen-enabled: false
|
||||
summary: Aggregates and returns all unique tags from all rules
|
||||
tags:
|
||||
- Tags API
|
||||
responses:
|
||||
200:
|
||||
description: Indicates a successful call
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '../../model/rule_schema/common_attributes.schema.yaml#/components/schemas/RuleTagArray'
|
|
@ -5,10 +5,9 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { chunk } from 'lodash';
|
||||
import type { AggregationsMultiBucketAggregateBase } from '@elastic/elasticsearch/lib/api/types';
|
||||
import type { AggregationsTopHitsAggregate } from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
|
||||
import type { SavedObjectsBulkCreateObject, SavedObjectsClientContract } from '@kbn/core/server';
|
||||
import type { SavedObjectsClientContract } from '@kbn/core/server';
|
||||
import { invariant } from '../../../../../../common/utils/invariant';
|
||||
import { withSecuritySpan } from '../../../../../utils/with_security_span';
|
||||
import type { PrebuiltRuleAsset } from '../../model/rule_assets/prebuilt_rule_asset';
|
||||
|
@ -17,7 +16,6 @@ import { PREBUILT_RULE_ASSETS_SO_TYPE } from './prebuilt_rule_assets_type';
|
|||
import type { RuleVersionSpecifier } from '../../model/rule_versions/rule_version_specifier';
|
||||
|
||||
const MAX_PREBUILT_RULES_COUNT = 10_000;
|
||||
const MAX_ASSETS_PER_BULK_CREATE_REQUEST = 500;
|
||||
|
||||
export interface IPrebuiltRuleAssetsClient {
|
||||
fetchLatestAssets: () => Promise<PrebuiltRuleAsset[]>;
|
||||
|
@ -25,8 +23,6 @@ export interface IPrebuiltRuleAssetsClient {
|
|||
fetchLatestVersions(): Promise<RuleVersionSpecifier[]>;
|
||||
|
||||
fetchAssetsByVersion(versions: RuleVersionSpecifier[]): Promise<PrebuiltRuleAsset[]>;
|
||||
|
||||
bulkCreateAssets(assets: PrebuiltRuleAsset[]): Promise<void>;
|
||||
}
|
||||
|
||||
export const createPrebuiltRuleAssetsClient = (
|
||||
|
@ -150,26 +146,5 @@ export const createPrebuiltRuleAssetsClient = (
|
|||
return validatePrebuiltRuleAssets(ruleAssets);
|
||||
});
|
||||
},
|
||||
|
||||
bulkCreateAssets: (assets: PrebuiltRuleAsset[]): Promise<void> => {
|
||||
return withSecuritySpan('IPrebuiltRuleAssetsClient.bulkCreateAssets', async () => {
|
||||
const validAssets = validatePrebuiltRuleAssets(assets);
|
||||
const bulkCreateObjects: Array<SavedObjectsBulkCreateObject<PrebuiltRuleAsset>> =
|
||||
validAssets.map((asset) => ({
|
||||
id: `${asset.rule_id}_${asset.version}`,
|
||||
type: PREBUILT_RULE_ASSETS_SO_TYPE,
|
||||
attributes: asset,
|
||||
}));
|
||||
|
||||
const bulkCreateChunks = chunk(bulkCreateObjects, MAX_ASSETS_PER_BULK_CREATE_REQUEST);
|
||||
|
||||
for (const chunkOfObjects of bulkCreateChunks) {
|
||||
await savedObjectsClient.bulkCreate<PrebuiltRuleAsset>(chunkOfObjects, {
|
||||
refresh: false,
|
||||
overwrite: true,
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
};
|
||||
};
|
||||
|
|
|
@ -5,11 +5,13 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { transformError } from '@kbn/securitysolution-es-utils';
|
||||
import type { IKibanaResponse } from '@kbn/core/server';
|
||||
import { RuleCreateProps } from '../../../../../../../common/api/detection_engine/model/rule_schema';
|
||||
import { transformError } from '@kbn/securitysolution-es-utils';
|
||||
import type { CreateRuleResponse } from '../../../../../../../common/api/detection_engine/rule_management';
|
||||
import { validateCreateRuleProps } from '../../../../../../../common/api/detection_engine/rule_management';
|
||||
import {
|
||||
CreateRuleRequestBody,
|
||||
validateCreateRuleProps,
|
||||
} from '../../../../../../../common/api/detection_engine/rule_management';
|
||||
import { DETECTION_ENGINE_RULES_URL } from '../../../../../../../common/constants';
|
||||
import type { SetupPlugins } from '../../../../../../plugin';
|
||||
import type { SecuritySolutionPluginRouter } from '../../../../../../types';
|
||||
|
@ -31,7 +33,7 @@ export const createRuleRoute = (
|
|||
{
|
||||
path: DETECTION_ENGINE_RULES_URL,
|
||||
validate: {
|
||||
body: buildRouteValidation(RuleCreateProps),
|
||||
body: buildRouteValidation(CreateRuleRequestBody),
|
||||
},
|
||||
options: {
|
||||
tags: ['access:securitySolution'],
|
||||
|
|
|
@ -5,20 +5,17 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { transformError } from '@kbn/securitysolution-es-utils';
|
||||
|
||||
import type { IKibanaResponse } from '@kbn/core/server';
|
||||
import { DETECTION_ENGINE_RULES_URL } from '../../../../../../../common/constants';
|
||||
import { transformError } from '@kbn/securitysolution-es-utils';
|
||||
import type { DeleteRuleResponse } from '../../../../../../../common/api/detection_engine/rule_management';
|
||||
import {
|
||||
QueryRuleByIds,
|
||||
DeleteRuleRequestQuery,
|
||||
validateQueryRuleByIds,
|
||||
} from '../../../../../../../common/api/detection_engine/rule_management';
|
||||
|
||||
import { DETECTION_ENGINE_RULES_URL } from '../../../../../../../common/constants';
|
||||
import type { SecuritySolutionPluginRouter } from '../../../../../../types';
|
||||
import { buildRouteValidation } from '../../../../../../utils/build_validation/route_validation';
|
||||
import { buildSiemResponse } from '../../../../routes/utils';
|
||||
|
||||
import { deleteRules } from '../../../logic/crud/delete_rules';
|
||||
import { readRules } from '../../../logic/crud/read_rules';
|
||||
import { getIdError, transform } from '../../../utils/utils';
|
||||
|
@ -28,7 +25,7 @@ export const deleteRuleRoute = (router: SecuritySolutionPluginRouter) => {
|
|||
{
|
||||
path: DETECTION_ENGINE_RULES_URL,
|
||||
validate: {
|
||||
query: buildRouteValidation(QueryRuleByIds),
|
||||
query: buildRouteValidation(DeleteRuleRequestQuery),
|
||||
},
|
||||
options: {
|
||||
tags: ['access:securitySolution'],
|
||||
|
|
|
@ -9,10 +9,7 @@ import type { IKibanaResponse, Logger } from '@kbn/core/server';
|
|||
import { transformError } from '@kbn/securitysolution-es-utils';
|
||||
|
||||
import { DETECTION_ENGINE_RULES_URL_FIND } from '../../../../../../../common/constants';
|
||||
import type {
|
||||
FindRulesRequestQueryDecoded,
|
||||
FindRulesResponse,
|
||||
} from '../../../../../../../common/api/detection_engine/rule_management';
|
||||
import type { FindRulesResponse } from '../../../../../../../common/api/detection_engine/rule_management';
|
||||
import {
|
||||
FindRulesRequestQuery,
|
||||
validateFindRulesRequestQuery,
|
||||
|
@ -29,9 +26,7 @@ export const findRulesRoute = (router: SecuritySolutionPluginRouter, logger: Log
|
|||
{
|
||||
path: DETECTION_ENGINE_RULES_URL_FIND,
|
||||
validate: {
|
||||
query: buildRouteValidation<typeof FindRulesRequestQuery, FindRulesRequestQueryDecoded>(
|
||||
FindRulesRequestQuery
|
||||
),
|
||||
query: buildRouteValidation(FindRulesRequestQuery),
|
||||
},
|
||||
options: {
|
||||
tags: ['access:securitySolution'],
|
||||
|
|
|
@ -7,9 +7,11 @@
|
|||
|
||||
import type { IKibanaResponse } from '@kbn/core/server';
|
||||
import { transformError } from '@kbn/securitysolution-es-utils';
|
||||
import { RuleUpdateProps } from '../../../../../../../common/api/detection_engine/model/rule_schema';
|
||||
import type { UpdateRuleResponse } from '../../../../../../../common/api/detection_engine/rule_management';
|
||||
import { validateUpdateRuleProps } from '../../../../../../../common/api/detection_engine/rule_management';
|
||||
import {
|
||||
UpdateRuleRequestBody,
|
||||
validateUpdateRuleProps,
|
||||
} from '../../../../../../../common/api/detection_engine/rule_management';
|
||||
import { DETECTION_ENGINE_RULES_URL } from '../../../../../../../common/constants';
|
||||
import type { SetupPlugins } from '../../../../../../plugin';
|
||||
import type { SecuritySolutionPluginRouter } from '../../../../../../types';
|
||||
|
@ -29,7 +31,7 @@ export const updateRuleRoute = (router: SecuritySolutionPluginRouter, ml: SetupP
|
|||
{
|
||||
path: DETECTION_ENGINE_RULES_URL,
|
||||
validate: {
|
||||
body: buildRouteValidation(RuleUpdateProps),
|
||||
body: buildRouteValidation(UpdateRuleRequestBody),
|
||||
},
|
||||
options: {
|
||||
tags: ['access:securitySolution'],
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue