mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
[RAM] Add HTTP versioning to resolve, snooze, and unsnooze APIs (#168886)
## Summary **REOPENED version of https://github.com/elastic/kibana/pull/163359, git history got too complicated and triggered too many codeowners** Part of #157883 Converts `_resolve`, `_snooze`, `_unsnooze` to new HTTP versioned model ### Checklist - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
3cf19b2e4b
commit
ce430e56f1
89 changed files with 1059 additions and 561 deletions
|
@ -38,10 +38,10 @@ export const rRuleResponseSchema = schema.object({
|
|||
byweekday: schema.maybe(schema.arrayOf(schema.oneOf([schema.string(), schema.number()]))),
|
||||
bymonth: schema.maybe(schema.arrayOf(schema.number())),
|
||||
bysetpos: schema.maybe(schema.arrayOf(schema.number())),
|
||||
bymonthday: schema.arrayOf(schema.number()),
|
||||
byyearday: schema.arrayOf(schema.number()),
|
||||
byweekno: schema.arrayOf(schema.number()),
|
||||
byhour: schema.arrayOf(schema.number()),
|
||||
byminute: schema.arrayOf(schema.number()),
|
||||
bysecond: schema.arrayOf(schema.number()),
|
||||
bymonthday: schema.maybe(schema.arrayOf(schema.number())),
|
||||
byyearday: schema.maybe(schema.arrayOf(schema.number())),
|
||||
byweekno: schema.maybe(schema.arrayOf(schema.number())),
|
||||
byhour: schema.maybe(schema.arrayOf(schema.number())),
|
||||
byminute: schema.maybe(schema.arrayOf(schema.number())),
|
||||
bysecond: schema.maybe(schema.arrayOf(schema.number())),
|
||||
});
|
||||
|
|
|
@ -5,24 +5,14 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
export {
|
||||
ruleSnoozeScheduleSchema,
|
||||
bulkEditOperationsSchema,
|
||||
bulkEditRulesRequestBodySchema,
|
||||
} from './schemas/latest';
|
||||
export type {
|
||||
RuleSnoozeSchedule,
|
||||
BulkEditRulesRequestBody,
|
||||
BulkEditRulesResponse,
|
||||
} from './types/latest';
|
||||
export { bulkEditOperationsSchema, bulkEditRulesRequestBodySchema } from './schemas/latest';
|
||||
export type { BulkEditRulesRequestBody, BulkEditRulesResponse } from './types/latest';
|
||||
|
||||
export {
|
||||
ruleSnoozeScheduleSchema as ruleSnoozeScheduleSchemaV1,
|
||||
bulkEditOperationsSchema as bulkEditOperationsSchemaV1,
|
||||
bulkEditRulesRequestBodySchema as bulkEditRulesRequestBodySchemaV1,
|
||||
} from './schemas/v1';
|
||||
export type {
|
||||
RuleSnoozeSchedule as RuleSnoozeScheduleV1,
|
||||
BulkEditRulesRequestBody as BulkEditRulesRequestBodyV1,
|
||||
BulkEditRulesResponse as BulkEditRulesResponseV1,
|
||||
} from './types/v1';
|
||||
|
|
|
@ -6,19 +6,10 @@
|
|||
*/
|
||||
|
||||
import { schema } from '@kbn/config-schema';
|
||||
import { validateDurationV1, validateNotifyWhenV1 } from '../../../validation';
|
||||
import { validateSnoozeScheduleV1 } from '../validation';
|
||||
import { validateDurationV1 } from '../../../validation';
|
||||
import { rRuleRequestSchemaV1 } from '../../../../r_rule';
|
||||
import { ruleNotifyWhenV1 } from '../../../response';
|
||||
|
||||
const notifyWhenSchema = schema.oneOf(
|
||||
[
|
||||
schema.literal(ruleNotifyWhenV1.CHANGE),
|
||||
schema.literal(ruleNotifyWhenV1.ACTIVE),
|
||||
schema.literal(ruleNotifyWhenV1.THROTTLE),
|
||||
],
|
||||
{ validate: validateNotifyWhenV1 }
|
||||
);
|
||||
import { notifyWhenSchemaV1, scheduleIdsSchemaV1 } from '../../../response';
|
||||
import { ruleSnoozeScheduleSchemaV1 } from '../../../request';
|
||||
|
||||
export const scheduleIdsSchema = schema.maybe(schema.arrayOf(schema.string()));
|
||||
|
||||
|
@ -28,15 +19,6 @@ export const ruleSnoozeScheduleSchema = schema.object({
|
|||
rRule: rRuleRequestSchemaV1,
|
||||
});
|
||||
|
||||
const ruleSnoozeScheduleSchemaWithValidation = schema.object(
|
||||
{
|
||||
id: schema.maybe(schema.string()),
|
||||
duration: schema.number(),
|
||||
rRule: rRuleRequestSchemaV1,
|
||||
},
|
||||
{ validate: validateSnoozeScheduleV1 }
|
||||
);
|
||||
|
||||
const ruleActionSchema = schema.object({
|
||||
group: schema.string(),
|
||||
id: schema.string(),
|
||||
|
@ -46,7 +28,7 @@ const ruleActionSchema = schema.object({
|
|||
schema.object({
|
||||
summary: schema.boolean(),
|
||||
throttle: schema.nullable(schema.string()),
|
||||
notifyWhen: notifyWhenSchema,
|
||||
notifyWhen: notifyWhenSchemaV1,
|
||||
})
|
||||
),
|
||||
});
|
||||
|
@ -80,17 +62,17 @@ export const bulkEditOperationsSchema = schema.arrayOf(
|
|||
schema.object({
|
||||
operation: schema.literal('set'),
|
||||
field: schema.literal('notifyWhen'),
|
||||
value: notifyWhenSchema,
|
||||
value: notifyWhenSchemaV1,
|
||||
}),
|
||||
schema.object({
|
||||
operation: schema.oneOf([schema.literal('set')]),
|
||||
field: schema.literal('snoozeSchedule'),
|
||||
value: ruleSnoozeScheduleSchemaWithValidation,
|
||||
value: ruleSnoozeScheduleSchemaV1,
|
||||
}),
|
||||
schema.object({
|
||||
operation: schema.oneOf([schema.literal('delete')]),
|
||||
field: schema.literal('snoozeSchedule'),
|
||||
value: schema.maybe(scheduleIdsSchema),
|
||||
value: schema.maybe(scheduleIdsSchemaV1),
|
||||
}),
|
||||
schema.object({
|
||||
operation: schema.literal('set'),
|
||||
|
|
|
@ -6,9 +6,8 @@
|
|||
*/
|
||||
import type { TypeOf } from '@kbn/config-schema';
|
||||
import { RuleParamsV1, RuleResponseV1 } from '../../../response';
|
||||
import { ruleSnoozeScheduleSchemaV1, bulkEditRulesRequestBodySchemaV1 } from '..';
|
||||
import { bulkEditRulesRequestBodySchemaV1 } from '..';
|
||||
|
||||
export type RuleSnoozeSchedule = TypeOf<typeof ruleSnoozeScheduleSchemaV1>;
|
||||
export type BulkEditRulesRequestBody = TypeOf<typeof bulkEditRulesRequestBodySchemaV1>;
|
||||
|
||||
interface BulkEditActionSkippedResult {
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
*/
|
||||
|
||||
export {
|
||||
notifyWhenSchema,
|
||||
actionFrequencySchema,
|
||||
actionAlertsFilterSchema,
|
||||
actionSchema,
|
||||
|
@ -23,7 +22,6 @@ export type {
|
|||
} from './types/latest';
|
||||
|
||||
export {
|
||||
notifyWhenSchema as notifyWhenSchemaV1,
|
||||
actionFrequencySchema as actionFrequencySchemaV1,
|
||||
actionAlertsFilterSchema as actionAlertsFilterSchemaV1,
|
||||
actionSchema as actionSchemaV1,
|
||||
|
|
|
@ -6,26 +6,12 @@
|
|||
*/
|
||||
|
||||
import { schema } from '@kbn/config-schema';
|
||||
import { ruleNotifyWhenV1 } from '../../../response';
|
||||
import {
|
||||
validateNotifyWhenV1,
|
||||
validateDurationV1,
|
||||
validateHoursV1,
|
||||
validateTimezoneV1,
|
||||
} from '../../../validation';
|
||||
|
||||
export const notifyWhenSchema = schema.oneOf(
|
||||
[
|
||||
schema.literal(ruleNotifyWhenV1.CHANGE),
|
||||
schema.literal(ruleNotifyWhenV1.ACTIVE),
|
||||
schema.literal(ruleNotifyWhenV1.THROTTLE),
|
||||
],
|
||||
{ validate: validateNotifyWhenV1 }
|
||||
);
|
||||
import { validateDurationV1, validateHoursV1, validateTimezoneV1 } from '../../../validation';
|
||||
import { notifyWhenSchemaV1 } from '../../../response';
|
||||
|
||||
export const actionFrequencySchema = schema.object({
|
||||
summary: schema.boolean(),
|
||||
notify_when: notifyWhenSchema,
|
||||
notify_when: notifyWhenSchemaV1,
|
||||
throttle: schema.nullable(schema.string({ validate: validateDurationV1 })),
|
||||
});
|
||||
|
||||
|
@ -91,7 +77,7 @@ export const createBodySchema = schema.object({
|
|||
interval: schema.string({ validate: validateDurationV1 }),
|
||||
}),
|
||||
actions: schema.arrayOf(actionSchema, { defaultValue: [] }),
|
||||
notify_when: schema.maybe(schema.nullable(notifyWhenSchema)),
|
||||
notify_when: schema.maybe(schema.nullable(notifyWhenSchemaV1)),
|
||||
});
|
||||
|
||||
export const createParamsSchema = schema.object({
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export { resolveParamsSchema } from './schemas/latest';
|
||||
|
||||
export { resolveParamsSchema as resolveParamsSchemaV1 } from './schemas/v1';
|
||||
|
||||
export type { ResolveRuleResponse } from './types/latest';
|
||||
|
||||
export type { ResolveRuleResponse as ResolveRuleResponseV1 } from './types/v1';
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* 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 { schema } from '@kbn/config-schema';
|
||||
|
||||
export const resolveParamsSchema = schema.object({
|
||||
id: schema.string(),
|
||||
});
|
|
@ -0,0 +1,11 @@
|
|||
/*
|
||||
* 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 { RuleParamsV1, RuleResponseV1 } from '../../../response';
|
||||
|
||||
export interface ResolveRuleResponse<Params extends RuleParamsV1 = never> {
|
||||
body: RuleResponseV1<Params>;
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export { snoozeParamsSchema, snoozeBodySchema } from './schemas/latest';
|
||||
|
||||
export {
|
||||
snoozeParamsSchema as snoozeParamsSchemaV1,
|
||||
snoozeBodySchema as snoozeBodySchemaV1,
|
||||
} from './schemas/v1';
|
|
@ -0,0 +1,8 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export * from './v1';
|
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* 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 { schema } from '@kbn/config-schema';
|
||||
import { ruleSnoozeScheduleSchemaV1 } from '../../../request';
|
||||
|
||||
export const snoozeParamsSchema = schema.object({
|
||||
id: schema.string(),
|
||||
});
|
||||
|
||||
export const snoozeBodySchema = schema.object({
|
||||
snooze_schedule: ruleSnoozeScheduleSchemaV1,
|
||||
});
|
|
@ -0,0 +1,13 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export { unsnoozeParamsSchema, unsnoozeBodySchema } from './schemas/latest';
|
||||
|
||||
export {
|
||||
unsnoozeParamsSchema as unsnoozeParamsSchemaV1,
|
||||
unsnoozeBodySchema as unsnoozeBodySchemaV1,
|
||||
} from './schemas/v1';
|
|
@ -0,0 +1,8 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export * from './v1';
|
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
* 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 { schema } from '@kbn/config-schema';
|
||||
|
||||
export const unsnoozeParamsSchema = schema.object({
|
||||
id: schema.string(),
|
||||
});
|
||||
|
||||
const scheduleIdsSchema = schema.maybe(schema.arrayOf(schema.string()));
|
||||
|
||||
export const unsnoozeBodySchema = schema.object({
|
||||
schedule_ids: scheduleIdsSchema,
|
||||
});
|
|
@ -0,0 +1,8 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export * from './v1';
|
38
x-pack/plugins/alerting/common/routes/rule/common/index.ts
Normal file
38
x-pack/plugins/alerting/common/routes/rule/common/index.ts
Normal file
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export {
|
||||
ruleNotifyWhen,
|
||||
ruleLastRunOutcomeValues,
|
||||
ruleExecutionStatusValues,
|
||||
ruleExecutionStatusErrorReason,
|
||||
ruleExecutionStatusWarningReason,
|
||||
} from './constants/latest';
|
||||
|
||||
export type {
|
||||
RuleNotifyWhen,
|
||||
RuleLastRunOutcomeValues,
|
||||
RuleExecutionStatusValues,
|
||||
RuleExecutionStatusErrorReason,
|
||||
RuleExecutionStatusWarningReason,
|
||||
} from './constants/latest';
|
||||
|
||||
export {
|
||||
ruleNotifyWhen as ruleNotifyWhenV1,
|
||||
ruleLastRunOutcomeValues as ruleLastRunOutcomeValuesV1,
|
||||
ruleExecutionStatusValues as ruleExecutionStatusValuesV1,
|
||||
ruleExecutionStatusErrorReason as ruleExecutionStatusErrorReasonV1,
|
||||
ruleExecutionStatusWarningReason as ruleExecutionStatusWarningReasonV1,
|
||||
} from './constants/v1';
|
||||
|
||||
export type {
|
||||
RuleNotifyWhen as RuleNotifyWhenV1,
|
||||
RuleLastRunOutcomeValues as RuleLastRunOutcomeValuesV1,
|
||||
RuleExecutionStatusValues as RuleExecutionStatusValuesV1,
|
||||
RuleExecutionStatusErrorReason as RuleExecutionStatusErrorReasonV1,
|
||||
RuleExecutionStatusWarningReason as RuleExecutionStatusWarningReasonV1,
|
||||
} from './constants/v1';
|
|
@ -5,6 +5,6 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
export { validateSnoozeSchedule } from './validate_snooze_schedule/latest';
|
||||
export { ruleSnoozeScheduleSchema } from './schemas/latest';
|
||||
|
||||
export { validateSnoozeSchedule as validateSnoozeScheduleV1 } from './validate_snooze_schedule/v1';
|
||||
export { ruleSnoozeScheduleSchema as ruleSnoozeScheduleSchemaV1 } from './schemas/v1';
|
|
@ -0,0 +1,8 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export * from './v1';
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* 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 { schema } from '@kbn/config-schema';
|
||||
import { rRuleRequestSchemaV1 } from '../../../r_rule';
|
||||
import { validateSnoozeScheduleV1 } from '../../validation';
|
||||
|
||||
export const ruleSnoozeScheduleSchema = schema.object(
|
||||
{
|
||||
id: schema.maybe(schema.string()),
|
||||
duration: schema.number(),
|
||||
rRule: rRuleRequestSchemaV1,
|
||||
},
|
||||
{ validate: validateSnoozeScheduleV1 }
|
||||
);
|
|
@ -14,6 +14,8 @@ export {
|
|||
monitoringSchema,
|
||||
ruleResponseSchema,
|
||||
ruleSnoozeScheduleSchema,
|
||||
notifyWhenSchema,
|
||||
scheduleIdsSchema,
|
||||
} from './schemas/latest';
|
||||
|
||||
export type {
|
||||
|
@ -24,22 +26,6 @@ export type {
|
|||
Monitoring,
|
||||
} from './types/latest';
|
||||
|
||||
export {
|
||||
ruleNotifyWhen,
|
||||
ruleLastRunOutcomeValues,
|
||||
ruleExecutionStatusValues,
|
||||
ruleExecutionStatusErrorReason,
|
||||
ruleExecutionStatusWarningReason,
|
||||
} from './constants/latest';
|
||||
|
||||
export type {
|
||||
RuleNotifyWhen,
|
||||
RuleLastRunOutcomeValues,
|
||||
RuleExecutionStatusValues,
|
||||
RuleExecutionStatusErrorReason,
|
||||
RuleExecutionStatusWarningReason,
|
||||
} from './constants/latest';
|
||||
|
||||
export {
|
||||
ruleParamsSchema as ruleParamsSchemaV1,
|
||||
actionParamsSchema as actionParamsSchemaV1,
|
||||
|
@ -49,24 +35,10 @@ export {
|
|||
monitoringSchema as monitoringSchemaV1,
|
||||
ruleResponseSchema as ruleResponseSchemaV1,
|
||||
ruleSnoozeScheduleSchema as ruleSnoozeScheduleSchemaV1,
|
||||
notifyWhenSchema as notifyWhenSchemaV1,
|
||||
scheduleIdsSchema as scheduleIdsSchemaV1,
|
||||
} from './schemas/v1';
|
||||
|
||||
export {
|
||||
ruleNotifyWhen as ruleNotifyWhenV1,
|
||||
ruleLastRunOutcomeValues as ruleLastRunOutcomeValuesV1,
|
||||
ruleExecutionStatusValues as ruleExecutionStatusValuesV1,
|
||||
ruleExecutionStatusErrorReason as ruleExecutionStatusErrorReasonV1,
|
||||
ruleExecutionStatusWarningReason as ruleExecutionStatusWarningReasonV1,
|
||||
} from './constants/v1';
|
||||
|
||||
export type {
|
||||
RuleNotifyWhen as RuleNotifyWhenV1,
|
||||
RuleLastRunOutcomeValues as RuleLastRunOutcomeValuesV1,
|
||||
RuleExecutionStatusValues as RuleExecutionStatusValuesV1,
|
||||
RuleExecutionStatusErrorReason as RuleExecutionStatusErrorReasonV1,
|
||||
RuleExecutionStatusWarningReason as RuleExecutionStatusWarningReasonV1,
|
||||
} from './constants/v1';
|
||||
|
||||
export type {
|
||||
RuleParams as RuleParamsV1,
|
||||
RuleResponse as RuleResponseV1,
|
||||
|
|
|
@ -13,17 +13,21 @@ import {
|
|||
ruleExecutionStatusErrorReason as ruleExecutionStatusErrorReasonV1,
|
||||
ruleExecutionStatusWarningReason as ruleExecutionStatusWarningReasonV1,
|
||||
ruleLastRunOutcomeValues as ruleLastRunOutcomeValuesV1,
|
||||
} from '../constants/v1';
|
||||
} from '../../common/constants/v1';
|
||||
import { validateNotifyWhenV1 } from '../../validation';
|
||||
|
||||
export const ruleParamsSchema = schema.recordOf(schema.string(), schema.maybe(schema.any()));
|
||||
export const actionParamsSchema = schema.recordOf(schema.string(), schema.maybe(schema.any()));
|
||||
export const mappedParamsSchema = schema.recordOf(schema.string(), schema.maybe(schema.any()));
|
||||
|
||||
const notifyWhenSchema = schema.oneOf([
|
||||
schema.literal(ruleNotifyWhenV1.CHANGE),
|
||||
schema.literal(ruleNotifyWhenV1.ACTIVE),
|
||||
schema.literal(ruleNotifyWhenV1.THROTTLE),
|
||||
]);
|
||||
export const notifyWhenSchema = schema.oneOf(
|
||||
[
|
||||
schema.literal(ruleNotifyWhenV1.CHANGE),
|
||||
schema.literal(ruleNotifyWhenV1.ACTIVE),
|
||||
schema.literal(ruleNotifyWhenV1.THROTTLE),
|
||||
],
|
||||
{ validate: validateNotifyWhenV1 }
|
||||
);
|
||||
|
||||
const intervalScheduleSchema = schema.object({
|
||||
interval: schema.string(),
|
||||
|
@ -182,9 +186,9 @@ export const monitoringSchema = schema.object({
|
|||
});
|
||||
|
||||
export const ruleSnoozeScheduleSchema = schema.object({
|
||||
id: schema.maybe(schema.string()),
|
||||
duration: schema.number(),
|
||||
rRule: rRuleResponseSchemaV1,
|
||||
id: schema.maybe(schema.string()),
|
||||
skipRecurrences: schema.maybe(schema.arrayOf(schema.string())),
|
||||
});
|
||||
|
||||
|
@ -221,3 +225,5 @@ export const ruleResponseSchema = schema.object({
|
|||
running: schema.maybe(schema.nullable(schema.boolean())),
|
||||
view_in_app_relative_url: schema.maybe(schema.nullable(schema.string())),
|
||||
});
|
||||
|
||||
export const scheduleIdsSchema = schema.maybe(schema.arrayOf(schema.string()));
|
||||
|
|
|
@ -7,10 +7,11 @@
|
|||
|
||||
export { validateDuration } from './validate_duration/latest';
|
||||
export { validateHours } from './validate_hours/latest';
|
||||
export { validateNotifyWhen } from './validate_notify_when/latest';
|
||||
export { validateTimezone } from './validate_timezone/latest';
|
||||
export { validateSnoozeSchedule } from './validate_snooze_schedule/latest';
|
||||
|
||||
export { validateDuration as validateDurationV1 } from './validate_duration/v1';
|
||||
export { validateHours as validateHoursV1 } from './validate_hours/v1';
|
||||
export { validateNotifyWhen as validateNotifyWhenV1 } from './validate_notify_when/v1';
|
||||
export { validateTimezone as validateTimezoneV1 } from './validate_timezone/v1';
|
||||
export { validateSnoozeSchedule as validateSnoozeScheduleV1 } from './validate_snooze_schedule/v1';
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { ruleNotifyWhenV1, RuleNotifyWhenV1 } from '../../response';
|
||||
import { ruleNotifyWhenV1, RuleNotifyWhenV1 } from '../../common';
|
||||
|
||||
export function validateNotifyWhen(notifyWhen: string) {
|
||||
if (Object.values(ruleNotifyWhenV1).includes(notifyWhen as RuleNotifyWhenV1)) {
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export * from './v1';
|
|
@ -5,11 +5,15 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { TypeOf } from '@kbn/config-schema';
|
||||
import { Frequency } from '@kbn/rrule';
|
||||
import moment from 'moment';
|
||||
import { RuleSnoozeScheduleV1 } from '../..';
|
||||
import { rRuleRequestSchema } from '../../../r_rule';
|
||||
|
||||
export const validateSnoozeSchedule = (schedule: RuleSnoozeScheduleV1) => {
|
||||
export const validateSnoozeSchedule = (schedule: {
|
||||
rRule: TypeOf<typeof rRuleRequestSchema>;
|
||||
duration: number;
|
||||
}) => {
|
||||
const intervalIsDaily = schedule.rRule.freq === Frequency.DAILY;
|
||||
const durationInDays = moment.duration(schedule.duration, 'milliseconds').asDays();
|
||||
if (intervalIsDaily && schedule.rRule.interval && durationInDays >= schedule.rRule.interval) {
|
|
@ -191,7 +191,10 @@ export type SanitizedRule<Params extends RuleTypeParams = never> = Omit<
|
|||
> & { actions: SanitizedRuleAction[] };
|
||||
|
||||
export type ResolvedSanitizedRule<Params extends RuleTypeParams = never> = SanitizedRule<Params> &
|
||||
Omit<SavedObjectsResolveResponse, 'saved_object'>;
|
||||
Omit<SavedObjectsResolveResponse, 'saved_object'> & {
|
||||
outcome: string;
|
||||
alias_target_id?: string;
|
||||
};
|
||||
|
||||
export type SanitizedRuleConfig = Pick<
|
||||
SanitizedRule,
|
||||
|
|
|
@ -37,10 +37,10 @@ export const rRuleSchema = schema.object({
|
|||
byweekday: schema.maybe(schema.arrayOf(schema.oneOf([schema.string(), schema.number()]))),
|
||||
bymonth: schema.maybe(schema.arrayOf(schema.number())),
|
||||
bysetpos: schema.maybe(schema.arrayOf(schema.number())),
|
||||
bymonthday: schema.arrayOf(schema.number()),
|
||||
byyearday: schema.arrayOf(schema.number()),
|
||||
byweekno: schema.arrayOf(schema.number()),
|
||||
byhour: schema.arrayOf(schema.number()),
|
||||
byminute: schema.arrayOf(schema.number()),
|
||||
bysecond: schema.arrayOf(schema.number()),
|
||||
bymonthday: schema.maybe(schema.arrayOf(schema.number())),
|
||||
byyearday: schema.maybe(schema.arrayOf(schema.number())),
|
||||
byweekno: schema.maybe(schema.arrayOf(schema.number())),
|
||||
byhour: schema.maybe(schema.arrayOf(schema.number())),
|
||||
byminute: schema.maybe(schema.arrayOf(schema.number())),
|
||||
bysecond: schema.maybe(schema.arrayOf(schema.number())),
|
||||
});
|
||||
|
|
|
@ -45,7 +45,7 @@ export type BulkEditOptionsFilter<Params extends RuleParams> = BulkEditOptionsCo
|
|||
};
|
||||
|
||||
export type BulkEditOptionsIds<Params extends RuleParams> = BulkEditOptionsCommon<Params> & {
|
||||
ids: string[];
|
||||
ids?: string[];
|
||||
};
|
||||
|
||||
export type BulkEditSkipReason = 'RULE_NOT_MODIFIED';
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export type { ResolveParams } from './resolve_rule';
|
||||
export { resolveRule } from './resolve_rule';
|
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
* 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 Boom from '@hapi/boom';
|
||||
import { withSpan } from '@kbn/apm-utils';
|
||||
import { AlertConsumers } from '@kbn/rule-data-utils';
|
||||
import { resolveRuleSavedObject } from '../../../../rules_client/lib';
|
||||
import { ruleAuditEvent, RuleAuditAction } from '../../../../rules_client/common/audit_events';
|
||||
import { RuleTypeParams } from '../../../../types';
|
||||
import { ReadOperations, AlertingAuthorizationEntity } from '../../../../authorization';
|
||||
import { RulesClientContext } from '../../../../rules_client/types';
|
||||
import { formatLegacyActions } from '../../../../rules_client/lib';
|
||||
import { transformRuleAttributesToRuleDomain, transformRuleDomainToRule } from '../../transforms';
|
||||
import { Rule } from '../../types';
|
||||
import { ruleSchema } from '../../schemas';
|
||||
import { resolveRuleParamsSchema } from './schemas';
|
||||
import type { ResolvedSanitizedRule } from '../../../../types';
|
||||
|
||||
export interface ResolveParams {
|
||||
id: string;
|
||||
includeSnoozeData?: boolean;
|
||||
}
|
||||
|
||||
export async function resolveRule<Params extends RuleTypeParams = never>(
|
||||
context: RulesClientContext,
|
||||
{ id, includeSnoozeData = false }: ResolveParams
|
||||
): // TODO (http-versioning): This should be of type Rule, change this when all rule types are fixed
|
||||
Promise<ResolvedSanitizedRule<Params>> {
|
||||
try {
|
||||
resolveRuleParamsSchema.validate({ id });
|
||||
} catch (error) {
|
||||
throw Boom.badRequest(`Error validating resolve params - ${error.message}`);
|
||||
}
|
||||
const { saved_object: result, ...resolveResponse } = await withSpan(
|
||||
{ name: 'resolveRuleSavedObject', type: 'rules' },
|
||||
() =>
|
||||
resolveRuleSavedObject(context, {
|
||||
ruleId: id,
|
||||
})
|
||||
);
|
||||
try {
|
||||
await context.authorization.ensureAuthorized({
|
||||
ruleTypeId: result.attributes.alertTypeId,
|
||||
consumer: result.attributes.consumer,
|
||||
operation: ReadOperations.Get,
|
||||
entity: AlertingAuthorizationEntity.Rule,
|
||||
});
|
||||
} catch (error) {
|
||||
context.auditLogger?.log(
|
||||
ruleAuditEvent({
|
||||
action: RuleAuditAction.RESOLVE,
|
||||
savedObject: { type: 'alert', id },
|
||||
error,
|
||||
})
|
||||
);
|
||||
throw error;
|
||||
}
|
||||
context.auditLogger?.log(
|
||||
ruleAuditEvent({
|
||||
action: RuleAuditAction.RESOLVE,
|
||||
savedObject: { type: 'alert', id },
|
||||
})
|
||||
);
|
||||
|
||||
const ruleDomain = transformRuleAttributesToRuleDomain(result.attributes, {
|
||||
id: result.id,
|
||||
logger: context.logger,
|
||||
ruleType: context.ruleTypeRegistry.get(result.attributes.alertTypeId),
|
||||
references: result.references,
|
||||
includeSnoozeData,
|
||||
});
|
||||
|
||||
const rule = transformRuleDomainToRule(ruleDomain);
|
||||
|
||||
try {
|
||||
ruleSchema.validate(rule);
|
||||
} catch (error) {
|
||||
context.logger.warn(`Error validating resolve data - ${error.message}`);
|
||||
}
|
||||
|
||||
// format legacy actions for SIEM rules
|
||||
if (result.attributes.consumer === AlertConsumers.SIEM) {
|
||||
// @ts-expect-error formatLegacyActions uses common Rule type instead of server; wontfix as this function is deprecated
|
||||
const [migratedRule] = await formatLegacyActions([rule], {
|
||||
savedObjectsClient: context.unsecuredSavedObjectsClient,
|
||||
logger: context.logger,
|
||||
});
|
||||
|
||||
return {
|
||||
...(migratedRule as Rule<never>),
|
||||
...resolveResponse,
|
||||
// TODO (http-versioning): Remove this cast, this enables us to move forward
|
||||
// without fixing all of other solution types
|
||||
} as ResolvedSanitizedRule;
|
||||
}
|
||||
|
||||
return {
|
||||
...rule,
|
||||
...resolveResponse,
|
||||
// TODO (http-versioning): Remove this cast, this enables us to move forward
|
||||
// without fixing all of other solution types
|
||||
} as ResolvedSanitizedRule;
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export { resolveRuleParamsSchema } from './resolve_rule_params_schema';
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* 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 { schema } from '@kbn/config-schema';
|
||||
|
||||
export const resolveRuleParamsSchema = schema.object({
|
||||
id: schema.string(),
|
||||
});
|
|
@ -0,0 +1,8 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export * from './resolved_rule';
|
|
@ -0,0 +1,9 @@
|
|||
/*
|
||||
* 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 type { Rule } from '../../../types';
|
||||
|
||||
export type ResolvedRule<Params> = Rule<Params> & { outcome: string; alias_target_id?: string };
|
|
@ -0,0 +1,9 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export type { SnoozeRuleOptions } from './types';
|
||||
export { snoozeRule } from './snooze_rule';
|
|
@ -0,0 +1,9 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export { snoozeRuleParamsSchema } from './snooze_rule_params_schema';
|
||||
export { snoozeRuleBodySchema } from './snooze_rule_body_schema';
|
|
@ -0,0 +1,13 @@
|
|||
/*
|
||||
* 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 { schema } from '@kbn/config-schema';
|
||||
import { ruleSnoozeScheduleSchema as ruleSnoozeScheduleRequestSchema } from '../../../../../../common/routes/rule/request';
|
||||
|
||||
export const snoozeRuleBodySchema = schema.object({
|
||||
snoozeSchedule: ruleSnoozeScheduleRequestSchema,
|
||||
});
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* 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 { schema } from '@kbn/config-schema';
|
||||
|
||||
export const snoozeRuleParamsSchema = schema.object({
|
||||
id: schema.string(),
|
||||
});
|
|
@ -6,26 +6,32 @@
|
|||
*/
|
||||
|
||||
import Boom from '@hapi/boom';
|
||||
import { RawRule, RuleSnoozeSchedule } from '../../types';
|
||||
import { WriteOperations, AlertingAuthorizationEntity } from '../../authorization';
|
||||
import { retryIfConflicts } from '../../lib/retry_if_conflicts';
|
||||
import { partiallyUpdateAlert } from '../../saved_objects';
|
||||
import { ruleAuditEvent, RuleAuditAction } from '../common/audit_events';
|
||||
import { validateSnoozeStartDate } from '../../lib/validate_snooze_date';
|
||||
import { RuleMutedError } from '../../lib/errors/rule_muted';
|
||||
import { RulesClientContext } from '../types';
|
||||
import { getSnoozeAttributes, verifySnoozeAttributeScheduleLimit } from '../common';
|
||||
import { updateMeta } from '../lib';
|
||||
import { withSpan } from '@kbn/apm-utils';
|
||||
import { getRuleSavedObject } from '../../../../rules_client/lib';
|
||||
import { ruleAuditEvent, RuleAuditAction } from '../../../../rules_client/common/audit_events';
|
||||
import { WriteOperations, AlertingAuthorizationEntity } from '../../../../authorization';
|
||||
import { retryIfConflicts } from '../../../../lib/retry_if_conflicts';
|
||||
import { validateSnoozeStartDate } from '../../../../lib/validate_snooze_date';
|
||||
import { RuleMutedError } from '../../../../lib/errors/rule_muted';
|
||||
import { RulesClientContext } from '../../../../rules_client/types';
|
||||
import {
|
||||
getSnoozeAttributes,
|
||||
verifySnoozeAttributeScheduleLimit,
|
||||
} from '../../../../rules_client/common';
|
||||
import { updateRuleSo } from '../../../../data/rule';
|
||||
import { updateMetaAttributes } from '../../../../rules_client/lib/update_meta_attributes';
|
||||
import { snoozeRuleParamsSchema } from './schemas';
|
||||
import type { SnoozeRuleOptions } from './types';
|
||||
|
||||
export interface SnoozeParams {
|
||||
id: string;
|
||||
snoozeSchedule: RuleSnoozeSchedule;
|
||||
}
|
||||
|
||||
export async function snooze(
|
||||
export async function snoozeRule(
|
||||
context: RulesClientContext,
|
||||
{ id, snoozeSchedule }: SnoozeParams
|
||||
{ id, snoozeSchedule }: SnoozeRuleOptions
|
||||
): Promise<void> {
|
||||
try {
|
||||
snoozeRuleParamsSchema.validate({ id });
|
||||
} catch (error) {
|
||||
throw Boom.badRequest(`Error validating snooze params - ${error.message}`);
|
||||
}
|
||||
const snoozeDateValidationMsg = validateSnoozeStartDate(snoozeSchedule.rRule.dtstart);
|
||||
if (snoozeDateValidationMsg) {
|
||||
throw new RuleMutedError(snoozeDateValidationMsg);
|
||||
|
@ -40,17 +46,14 @@ export async function snooze(
|
|||
|
||||
async function snoozeWithOCC(
|
||||
context: RulesClientContext,
|
||||
{
|
||||
id,
|
||||
snoozeSchedule,
|
||||
}: {
|
||||
id: string;
|
||||
snoozeSchedule: RuleSnoozeSchedule;
|
||||
}
|
||||
{ id, snoozeSchedule }: SnoozeRuleOptions
|
||||
) {
|
||||
const { attributes, version } = await context.unsecuredSavedObjectsClient.get<RawRule>(
|
||||
'alert',
|
||||
id
|
||||
const { attributes, version } = await withSpan(
|
||||
{ name: 'getRuleSavedObject', type: 'rules' },
|
||||
() =>
|
||||
getRuleSavedObject(context, {
|
||||
ruleId: id,
|
||||
})
|
||||
);
|
||||
|
||||
try {
|
||||
|
@ -93,17 +96,14 @@ async function snoozeWithOCC(
|
|||
throw Boom.badRequest(error.message);
|
||||
}
|
||||
|
||||
const updateAttributes = updateMeta(context, {
|
||||
...newAttrs,
|
||||
updatedBy: await context.getUserName(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
});
|
||||
const updateOptions = { version };
|
||||
|
||||
await partiallyUpdateAlert(
|
||||
context.unsecuredSavedObjectsClient,
|
||||
await updateRuleSo({
|
||||
savedObjectsClient: context.unsecuredSavedObjectsClient,
|
||||
savedObjectsUpdateOptions: { version },
|
||||
id,
|
||||
updateAttributes,
|
||||
updateOptions
|
||||
);
|
||||
updateRuleAttributes: updateMetaAttributes(context, {
|
||||
...newAttrs,
|
||||
updatedBy: await context.getUserName(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
}),
|
||||
});
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export * from './snooze_rule_options';
|
|
@ -0,0 +1,13 @@
|
|||
/*
|
||||
* 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 { TypeOf } from '@kbn/config-schema';
|
||||
import { ruleSnoozeScheduleSchema as ruleSnoozeScheduleRequestSchema } from '../../../../../../common/routes/rule/request';
|
||||
|
||||
export interface SnoozeRuleOptions {
|
||||
id: string;
|
||||
snoozeSchedule: TypeOf<typeof ruleSnoozeScheduleRequestSchema>;
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export type { UnsnoozeParams } from './unsnooze_rule';
|
||||
export { unsnoozeRule } from './unsnooze_rule';
|
|
@ -0,0 +1,8 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export { unsnoozeRuleParamsSchema } from './unsnooze_rule_params_schema';
|
|
@ -0,0 +1,13 @@
|
|||
/*
|
||||
* 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 { schema } from '@kbn/config-schema';
|
||||
|
||||
export const unsnoozeRuleParamsSchema = schema.object({
|
||||
id: schema.string(),
|
||||
scheduleIds: schema.maybe(schema.arrayOf(schema.string())),
|
||||
});
|
|
@ -5,21 +5,24 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { RawRule } from '../../types';
|
||||
import { WriteOperations, AlertingAuthorizationEntity } from '../../authorization';
|
||||
import { retryIfConflicts } from '../../lib/retry_if_conflicts';
|
||||
import { partiallyUpdateAlert } from '../../saved_objects';
|
||||
import { ruleAuditEvent, RuleAuditAction } from '../common/audit_events';
|
||||
import { RulesClientContext } from '../types';
|
||||
import { updateMeta } from '../lib';
|
||||
import { getUnsnoozeAttributes } from '../common';
|
||||
import Boom from '@hapi/boom';
|
||||
import { withSpan } from '@kbn/apm-utils';
|
||||
import { ruleAuditEvent, RuleAuditAction } from '../../../../rules_client/common/audit_events';
|
||||
import { getRuleSavedObject } from '../../../../rules_client/lib';
|
||||
import { WriteOperations, AlertingAuthorizationEntity } from '../../../../authorization';
|
||||
import { retryIfConflicts } from '../../../../lib/retry_if_conflicts';
|
||||
import { RulesClientContext } from '../../../../rules_client/types';
|
||||
import { getUnsnoozeAttributes } from '../../../../rules_client/common';
|
||||
import { updateRuleSo } from '../../../../data/rule';
|
||||
import { updateMetaAttributes } from '../../../../rules_client/lib/update_meta_attributes';
|
||||
import { unsnoozeRuleParamsSchema } from './schemas';
|
||||
|
||||
export interface UnsnoozeParams {
|
||||
id: string;
|
||||
scheduleIds?: string[];
|
||||
}
|
||||
|
||||
export async function unsnooze(
|
||||
export async function unsnoozeRule(
|
||||
context: RulesClientContext,
|
||||
{ id, scheduleIds }: UnsnoozeParams
|
||||
): Promise<void> {
|
||||
|
@ -31,9 +34,17 @@ export async function unsnooze(
|
|||
}
|
||||
|
||||
async function unsnoozeWithOCC(context: RulesClientContext, { id, scheduleIds }: UnsnoozeParams) {
|
||||
const { attributes, version } = await context.unsecuredSavedObjectsClient.get<RawRule>(
|
||||
'alert',
|
||||
id
|
||||
try {
|
||||
unsnoozeRuleParamsSchema.validate({ id, scheduleIds });
|
||||
} catch (error) {
|
||||
throw Boom.badRequest(`Error validating unsnooze params - ${error.message}`);
|
||||
}
|
||||
const { attributes, version } = await withSpan(
|
||||
{ name: 'getRuleSavedObject', type: 'rules' },
|
||||
() =>
|
||||
getRuleSavedObject(context, {
|
||||
ruleId: id,
|
||||
})
|
||||
);
|
||||
|
||||
try {
|
||||
|
@ -69,17 +80,14 @@ async function unsnoozeWithOCC(context: RulesClientContext, { id, scheduleIds }:
|
|||
context.ruleTypeRegistry.ensureRuleTypeEnabled(attributes.alertTypeId);
|
||||
const newAttrs = getUnsnoozeAttributes(attributes, scheduleIds);
|
||||
|
||||
const updateAttributes = updateMeta(context, {
|
||||
...newAttrs,
|
||||
updatedBy: await context.getUserName(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
});
|
||||
const updateOptions = { version };
|
||||
|
||||
await partiallyUpdateAlert(
|
||||
context.unsecuredSavedObjectsClient,
|
||||
await updateRuleSo({
|
||||
savedObjectsClient: context.unsecuredSavedObjectsClient,
|
||||
savedObjectsUpdateOptions: { version },
|
||||
id,
|
||||
updateAttributes,
|
||||
updateOptions
|
||||
);
|
||||
updateRuleAttributes: updateMetaAttributes(context, {
|
||||
...newAttrs,
|
||||
updatedBy: await context.getUserName(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
}),
|
||||
});
|
||||
}
|
|
@ -20,10 +20,10 @@ export interface RRuleAttributes {
|
|||
byweekday?: Array<string | number>;
|
||||
bymonth?: number[];
|
||||
bysetpos?: number[];
|
||||
bymonthday: number[];
|
||||
byyearday: number[];
|
||||
byweekno: number[];
|
||||
byhour: number[];
|
||||
byminute: number[];
|
||||
bysecond: number[];
|
||||
bymonthday?: number[];
|
||||
byyearday?: number[];
|
||||
byweekno?: number[];
|
||||
byhour?: number[];
|
||||
byminute?: number[];
|
||||
bysecond?: number[];
|
||||
}
|
||||
|
|
|
@ -17,5 +17,9 @@ export { bulkCreateRulesSo } from './methods/bulk_create_rule_so';
|
|||
export type { BulkCreateRulesSoParams } from './methods/bulk_create_rule_so';
|
||||
export { bulkDeleteRulesSo } from './methods/bulk_delete_rules_so';
|
||||
export type { BulkDeleteRulesSoParams } from './methods/bulk_delete_rules_so';
|
||||
export { resolveRuleSo } from './methods/resolve_rule_so';
|
||||
export type { ResolveRuleSoParams } from './methods/resolve_rule_so';
|
||||
export { getRuleSo } from './methods/get_rule_so';
|
||||
export type { GetRuleSoParams } from './methods/get_rule_so';
|
||||
export { bulkDisableRulesSo } from './methods/bulk_disable_rules_so';
|
||||
export type { BulkDisableRulesSoParams } from './methods/bulk_disable_rules_so';
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* 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 { SavedObjectsClientContract, SavedObject } from '@kbn/core/server';
|
||||
import { SavedObjectsGetOptions } from '@kbn/core-saved-objects-api-server';
|
||||
import { RuleAttributes } from '../types';
|
||||
|
||||
export interface GetRuleSoParams {
|
||||
savedObjectsClient: SavedObjectsClientContract;
|
||||
id: string;
|
||||
savedObjectsGetOptions?: SavedObjectsGetOptions;
|
||||
}
|
||||
|
||||
export const getRuleSo = (params: GetRuleSoParams): Promise<SavedObject<RuleAttributes>> => {
|
||||
const { savedObjectsClient, id, savedObjectsGetOptions } = params;
|
||||
|
||||
return savedObjectsClient.get<RuleAttributes>('alert', id, savedObjectsGetOptions);
|
||||
};
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* 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 { SavedObjectsClientContract, SavedObjectsResolveResponse } from '@kbn/core/server';
|
||||
import { SavedObjectsResolveOptions } from '@kbn/core-saved-objects-api-server';
|
||||
import { RuleAttributes } from '../types';
|
||||
|
||||
export interface ResolveRuleSoParams {
|
||||
savedObjectsClient: SavedObjectsClientContract;
|
||||
id: string;
|
||||
savedObjectsResolveOptions?: SavedObjectsResolveOptions;
|
||||
}
|
||||
|
||||
export const resolveRuleSo = (
|
||||
params: ResolveRuleSoParams
|
||||
): Promise<SavedObjectsResolveResponse<RuleAttributes>> => {
|
||||
const { savedObjectsClient, id, savedObjectsResolveOptions } = params;
|
||||
|
||||
return savedObjectsClient.resolve('alert', id, savedObjectsResolveOptions);
|
||||
};
|
|
@ -29,7 +29,7 @@ import { getActionErrorLogRoute } from './get_action_error_log';
|
|||
import { getRuleExecutionKPIRoute } from './get_rule_execution_kpi';
|
||||
import { getRuleStateRoute } from './get_rule_state';
|
||||
import { healthRoute } from './health';
|
||||
import { resolveRuleRoute } from './resolve_rule';
|
||||
import { resolveRuleRoute } from './rule/apis/resolve';
|
||||
import { ruleTypesRoute } from './rule_types';
|
||||
import { muteAllRuleRoute } from './mute_all_rule';
|
||||
import { muteAlertRoute } from './rule/apis/mute_alert/mute_alert';
|
||||
|
@ -37,8 +37,8 @@ import { unmuteAllRuleRoute } from './unmute_all_rule';
|
|||
import { unmuteAlertRoute } from './unmute_alert';
|
||||
import { updateRuleApiKeyRoute } from './update_rule_api_key';
|
||||
import { bulkEditInternalRulesRoute } from './rule/apis/bulk_edit/bulk_edit_rules_route';
|
||||
import { snoozeRuleRoute } from './snooze_rule';
|
||||
import { unsnoozeRuleRoute } from './unsnooze_rule';
|
||||
import { snoozeRuleRoute } from './rule/apis/snooze';
|
||||
import { unsnoozeRuleRoute } from './rule/apis/unsnooze';
|
||||
import { runSoonRoute } from './run_soon';
|
||||
import { bulkDeleteRulesRoute } from './rule/apis/bulk_delete/bulk_delete_rules_route';
|
||||
import { bulkEnableRulesRoute } from './bulk_enable_rules';
|
||||
|
|
|
@ -1,91 +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 { omit } from 'lodash';
|
||||
import { schema } from '@kbn/config-schema';
|
||||
import { IRouter } from '@kbn/core/server';
|
||||
import { ILicenseState } from '../lib';
|
||||
import {
|
||||
verifyAccessAndContext,
|
||||
RewriteResponseCase,
|
||||
rewriteRuleLastRun,
|
||||
rewriteActionsRes,
|
||||
} from './lib';
|
||||
import {
|
||||
RuleTypeParams,
|
||||
AlertingRequestHandlerContext,
|
||||
INTERNAL_BASE_ALERTING_API_PATH,
|
||||
ResolvedSanitizedRule,
|
||||
} from '../types';
|
||||
|
||||
const paramSchema = schema.object({
|
||||
id: schema.string(),
|
||||
});
|
||||
|
||||
const rewriteBodyRes: RewriteResponseCase<ResolvedSanitizedRule<RuleTypeParams>> = ({
|
||||
alertTypeId,
|
||||
createdBy,
|
||||
updatedBy,
|
||||
createdAt,
|
||||
updatedAt,
|
||||
apiKeyOwner,
|
||||
apiKeyCreatedByUser,
|
||||
notifyWhen,
|
||||
muteAll,
|
||||
mutedInstanceIds,
|
||||
executionStatus,
|
||||
actions,
|
||||
scheduledTaskId,
|
||||
lastRun,
|
||||
nextRun,
|
||||
...rest
|
||||
}) => ({
|
||||
...rest,
|
||||
rule_type_id: alertTypeId,
|
||||
created_by: createdBy,
|
||||
updated_by: updatedBy,
|
||||
created_at: createdAt,
|
||||
updated_at: updatedAt,
|
||||
api_key_owner: apiKeyOwner,
|
||||
notify_when: notifyWhen,
|
||||
mute_all: muteAll,
|
||||
muted_alert_ids: mutedInstanceIds,
|
||||
scheduled_task_id: scheduledTaskId,
|
||||
execution_status: executionStatus && {
|
||||
...omit(executionStatus, 'lastExecutionDate', 'lastDuration'),
|
||||
last_execution_date: executionStatus.lastExecutionDate,
|
||||
last_duration: executionStatus.lastDuration,
|
||||
},
|
||||
actions: rewriteActionsRes(actions),
|
||||
...(lastRun ? { last_run: rewriteRuleLastRun(lastRun) } : {}),
|
||||
...(nextRun ? { next_run: nextRun } : {}),
|
||||
...(apiKeyCreatedByUser !== undefined ? { api_key_created_by_user: apiKeyCreatedByUser } : {}),
|
||||
});
|
||||
|
||||
export const resolveRuleRoute = (
|
||||
router: IRouter<AlertingRequestHandlerContext>,
|
||||
licenseState: ILicenseState
|
||||
) => {
|
||||
router.get(
|
||||
{
|
||||
path: `${INTERNAL_BASE_ALERTING_API_PATH}/rule/{id}/_resolve`,
|
||||
validate: {
|
||||
params: paramSchema,
|
||||
},
|
||||
},
|
||||
router.handleLegacyErrors(
|
||||
verifyAccessAndContext(licenseState, async function (context, req, res) {
|
||||
const rulesClient = (await context.alerting).getRulesClient();
|
||||
const { id } = req.params;
|
||||
const rule = await rulesClient.resolve({ id, includeSnoozeData: true });
|
||||
return res.ok({
|
||||
body: rewriteBodyRes(rule),
|
||||
});
|
||||
})
|
||||
)
|
||||
);
|
||||
};
|
|
@ -0,0 +1,8 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export { resolveRuleRoute } from './resolve_rule_route';
|
|
@ -6,17 +6,17 @@
|
|||
*/
|
||||
|
||||
import { pick } from 'lodash';
|
||||
import { resolveRuleRoute } from './resolve_rule';
|
||||
import { resolveRuleRoute } from './resolve_rule_route';
|
||||
import { httpServiceMock } from '@kbn/core/server/mocks';
|
||||
import { licenseStateMock } from '../lib/license_state.mock';
|
||||
import { verifyApiAccess } from '../lib/license_api_access';
|
||||
import { mockHandlerArguments } from './_mock_handler_arguments';
|
||||
import { rulesClientMock } from '../rules_client.mock';
|
||||
import { ResolvedSanitizedRule } from '../types';
|
||||
import { AsApiContract } from './lib';
|
||||
import { licenseStateMock } from '../../../../lib/license_state.mock';
|
||||
import { verifyApiAccess } from '../../../../lib/license_api_access';
|
||||
import { mockHandlerArguments } from '../../../_mock_handler_arguments';
|
||||
import { rulesClientMock } from '../../../../rules_client.mock';
|
||||
import { ResolvedRule } from '../../../../application/rule/methods/resolve/types';
|
||||
import { ResolvedSanitizedRule } from '../../../../../common';
|
||||
|
||||
const rulesClient = rulesClientMock.create();
|
||||
jest.mock('../lib/license_api_access', () => ({
|
||||
jest.mock('../../../../lib/license_api_access', () => ({
|
||||
verifyApiAccess: jest.fn(),
|
||||
}));
|
||||
|
||||
|
@ -25,7 +25,7 @@ beforeEach(() => {
|
|||
});
|
||||
|
||||
describe('resolveRuleRoute', () => {
|
||||
const mockedRule: ResolvedSanitizedRule<{
|
||||
const mockedRule: ResolvedRule<{
|
||||
bar: boolean;
|
||||
}> = {
|
||||
id: '1',
|
||||
|
@ -67,7 +67,7 @@ describe('resolveRuleRoute', () => {
|
|||
revision: 0,
|
||||
};
|
||||
|
||||
const resolveResult: AsApiContract<ResolvedSanitizedRule<{ bar: boolean }>> = {
|
||||
const resolveResult = {
|
||||
...pick(
|
||||
mockedRule,
|
||||
'consumer',
|
||||
|
@ -86,13 +86,13 @@ describe('resolveRuleRoute', () => {
|
|||
updated_by: mockedRule.updatedBy,
|
||||
api_key_owner: mockedRule.apiKeyOwner,
|
||||
muted_alert_ids: mockedRule.mutedInstanceIds,
|
||||
created_at: mockedRule.createdAt,
|
||||
updated_at: mockedRule.updatedAt,
|
||||
created_at: mockedRule.createdAt.toISOString(),
|
||||
updated_at: mockedRule.updatedAt.toISOString(),
|
||||
id: mockedRule.id,
|
||||
revision: mockedRule.revision,
|
||||
execution_status: {
|
||||
status: mockedRule.executionStatus.status,
|
||||
last_execution_date: mockedRule.executionStatus.lastExecutionDate,
|
||||
last_execution_date: mockedRule.executionStatus.lastExecutionDate.toISOString(),
|
||||
},
|
||||
actions: [
|
||||
{
|
||||
|
@ -115,7 +115,9 @@ describe('resolveRuleRoute', () => {
|
|||
|
||||
expect(config.path).toMatchInlineSnapshot(`"/internal/alerting/rule/{id}/_resolve"`);
|
||||
|
||||
rulesClient.resolve.mockResolvedValueOnce(mockedRule);
|
||||
// TODO (http-versioning): Remove this cast, this enables us to move forward
|
||||
// without fixing all of other solution types
|
||||
rulesClient.resolve.mockResolvedValueOnce(mockedRule as ResolvedSanitizedRule);
|
||||
|
||||
const [context, req, res] = mockHandlerArguments(
|
||||
{ rulesClient },
|
||||
|
@ -142,7 +144,9 @@ describe('resolveRuleRoute', () => {
|
|||
|
||||
const [, handler] = router.get.mock.calls[0];
|
||||
|
||||
rulesClient.resolve.mockResolvedValueOnce(mockedRule);
|
||||
// TODO (http-versioning): Remove this cast, this enables us to move forward
|
||||
// without fixing all of other solution types
|
||||
rulesClient.resolve.mockResolvedValueOnce(mockedRule as ResolvedSanitizedRule);
|
||||
|
||||
const [context, req, res] = mockHandlerArguments(
|
||||
{ rulesClient },
|
||||
|
@ -169,7 +173,9 @@ describe('resolveRuleRoute', () => {
|
|||
|
||||
const [, handler] = router.get.mock.calls[0];
|
||||
|
||||
rulesClient.resolve.mockResolvedValueOnce(mockedRule);
|
||||
// TODO (http-versioning): Remove this cast, this enables us to move forward
|
||||
// without fixing all of other solution types
|
||||
rulesClient.resolve.mockResolvedValueOnce(mockedRule as ResolvedSanitizedRule);
|
||||
|
||||
const [context, req, res] = mockHandlerArguments(
|
||||
{ rulesClient },
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* 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 { TypeOf } from '@kbn/config-schema';
|
||||
import { IRouter } from '@kbn/core/server';
|
||||
import { RuleParamsV1 } from '../../../../../common/routes/rule/response';
|
||||
import { ResolvedRule } from '../../../../application/rule/methods/resolve/types';
|
||||
import {
|
||||
resolveParamsSchemaV1,
|
||||
ResolveRuleResponseV1,
|
||||
} from '../../../../../common/routes/rule/apis/resolve';
|
||||
import { ILicenseState } from '../../../../lib';
|
||||
import { verifyAccessAndContext } from '../../../lib';
|
||||
import { AlertingRequestHandlerContext, INTERNAL_BASE_ALERTING_API_PATH } from '../../../../types';
|
||||
import { transformResolveResponseV1 } from './transforms';
|
||||
|
||||
export type ResolveRuleRequestParamsV1 = TypeOf<typeof resolveParamsSchemaV1>;
|
||||
|
||||
export const resolveRuleRoute = (
|
||||
router: IRouter<AlertingRequestHandlerContext>,
|
||||
licenseState: ILicenseState
|
||||
) => {
|
||||
router.get(
|
||||
{
|
||||
path: `${INTERNAL_BASE_ALERTING_API_PATH}/rule/{id}/_resolve`,
|
||||
validate: {
|
||||
params: resolveParamsSchemaV1,
|
||||
},
|
||||
},
|
||||
router.handleLegacyErrors(
|
||||
verifyAccessAndContext(licenseState, async function (context, req, res) {
|
||||
const rulesClient = (await context.alerting).getRulesClient();
|
||||
const params: ResolveRuleRequestParamsV1 = req.params;
|
||||
const { id } = params;
|
||||
// TODO (http-versioning): Remove this cast, this enables us to move forward
|
||||
// without fixing all of other solution types
|
||||
const rule = (await rulesClient.resolve({
|
||||
id,
|
||||
includeSnoozeData: true,
|
||||
})) as ResolvedRule<RuleParamsV1>;
|
||||
const response: ResolveRuleResponseV1<RuleParamsV1> = {
|
||||
body: transformResolveResponseV1<RuleParamsV1>(rule),
|
||||
};
|
||||
return res.ok(response);
|
||||
})
|
||||
)
|
||||
);
|
||||
};
|
|
@ -0,0 +1,10 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export { transformResolveResponse } from './transform_resolve_response/latest';
|
||||
|
||||
export { transformResolveResponse as transformResolveResponseV1 } from './transform_resolve_response/v1';
|
|
@ -0,0 +1,8 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export * from './v1';
|
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
* 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 { ResolvedRule } from '../../../../../../application/rule/methods/resolve/types';
|
||||
import { RuleParams } from '../../../../../../application/rule/types';
|
||||
import { transformRuleToRuleResponseV1 } from '../../../../transforms';
|
||||
|
||||
export const transformResolveResponse = <Params extends RuleParams = never>(
|
||||
rule: ResolvedRule<Params>
|
||||
) => ({
|
||||
...transformRuleToRuleResponseV1<Params>(rule),
|
||||
outcome: rule.outcome,
|
||||
alias_target_id: rule.alias_target_id,
|
||||
});
|
|
@ -0,0 +1,8 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export { snoozeRuleRoute } from './snooze_rule_route';
|
|
@ -5,15 +5,15 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { snoozeRuleRoute } from './snooze_rule';
|
||||
import { snoozeRuleRoute } from './snooze_rule_route';
|
||||
import { httpServiceMock } from '@kbn/core/server/mocks';
|
||||
import { licenseStateMock } from '../lib/license_state.mock';
|
||||
import { mockHandlerArguments } from './_mock_handler_arguments';
|
||||
import { rulesClientMock } from '../rules_client.mock';
|
||||
import { RuleTypeDisabledError } from '../lib/errors/rule_type_disabled';
|
||||
import { licenseStateMock } from '../../../../lib/license_state.mock';
|
||||
import { mockHandlerArguments } from '../../../_mock_handler_arguments';
|
||||
import { rulesClientMock } from '../../../../rules_client.mock';
|
||||
import { RuleTypeDisabledError } from '../../../../lib/errors/rule_type_disabled';
|
||||
|
||||
const rulesClient = rulesClientMock.create();
|
||||
jest.mock('../lib/license_api_access', () => ({
|
||||
jest.mock('../../../../lib/license_api_access', () => ({
|
||||
verifyApiAccess: jest.fn(),
|
||||
}));
|
||||
|
|
@ -5,36 +5,18 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { TypeOf } from '@kbn/config-schema';
|
||||
import { IRouter } from '@kbn/core/server';
|
||||
import { schema } from '@kbn/config-schema';
|
||||
import { ILicenseState, RuleMutedError } from '../lib';
|
||||
import { verifyAccessAndContext, rRuleSchema } from './lib';
|
||||
import { SnoozeOptions } from '../rules_client';
|
||||
import { AlertingRequestHandlerContext, INTERNAL_ALERTING_SNOOZE_RULE } from '../types';
|
||||
import { validateSnoozeSchedule } from '../lib/validate_snooze_schedule';
|
||||
import {
|
||||
snoozeBodySchema,
|
||||
snoozeParamsSchema,
|
||||
} from '../../../../../common/routes/rule/apis/snooze';
|
||||
import { ILicenseState, RuleMutedError } from '../../../../lib';
|
||||
import { verifyAccessAndContext } from '../../../lib';
|
||||
import { AlertingRequestHandlerContext, INTERNAL_ALERTING_SNOOZE_RULE } from '../../../../types';
|
||||
import { transformSnoozeBodyV1 } from './transforms';
|
||||
|
||||
const paramSchema = schema.object({
|
||||
id: schema.string(),
|
||||
});
|
||||
|
||||
export const snoozeScheduleSchema = schema.object(
|
||||
{
|
||||
id: schema.maybe(schema.string()),
|
||||
duration: schema.number(),
|
||||
rRule: rRuleSchema,
|
||||
},
|
||||
{ validate: validateSnoozeSchedule }
|
||||
);
|
||||
|
||||
const bodySchema = schema.object({
|
||||
snooze_schedule: snoozeScheduleSchema,
|
||||
});
|
||||
|
||||
const rewriteBodyReq: (opts: {
|
||||
snooze_schedule: SnoozeOptions['snoozeSchedule'];
|
||||
}) => SnoozeOptions = ({ snooze_schedule: snoozeSchedule }) => ({
|
||||
snoozeSchedule,
|
||||
});
|
||||
export type SnoozeRuleRequestParamsV1 = TypeOf<typeof snoozeParamsSchema>;
|
||||
|
||||
export const snoozeRuleRoute = (
|
||||
router: IRouter<AlertingRequestHandlerContext>,
|
||||
|
@ -44,15 +26,15 @@ export const snoozeRuleRoute = (
|
|||
{
|
||||
path: INTERNAL_ALERTING_SNOOZE_RULE,
|
||||
validate: {
|
||||
params: paramSchema,
|
||||
body: bodySchema,
|
||||
params: snoozeParamsSchema,
|
||||
body: snoozeBodySchema,
|
||||
},
|
||||
},
|
||||
router.handleLegacyErrors(
|
||||
verifyAccessAndContext(licenseState, async function (context, req, res) {
|
||||
const rulesClient = (await context.alerting).getRulesClient();
|
||||
const params = req.params;
|
||||
const body = rewriteBodyReq(req.body);
|
||||
const params: SnoozeRuleRequestParamsV1 = req.params;
|
||||
const body = transformSnoozeBodyV1(req.body);
|
||||
try {
|
||||
await rulesClient.snooze({ ...params, ...body });
|
||||
return res.noContent();
|
|
@ -0,0 +1,10 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export { transformSnoozeBody } from './transform_snooze_body/latest';
|
||||
|
||||
export { transformSnoozeBody as transformSnoozeBodyV1 } from './transform_snooze_body/v1';
|
|
@ -0,0 +1,8 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export * from './v1';
|
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* 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 { TypeOf } from '@kbn/config-schema';
|
||||
import { snoozeBodySchemaV1 } from '../../../../../../../common/routes/rule/apis/snooze';
|
||||
|
||||
type SnoozeBodySchema = TypeOf<typeof snoozeBodySchemaV1>;
|
||||
|
||||
export const transformSnoozeBody: (opts: SnoozeBodySchema) => {
|
||||
snoozeSchedule: SnoozeBodySchema['snooze_schedule'];
|
||||
} = ({ snooze_schedule: snoozeSchedule }) => ({
|
||||
snoozeSchedule,
|
||||
});
|
|
@ -0,0 +1,8 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export { unsnoozeRuleRoute } from './unsnooze_rule_route';
|
|
@ -0,0 +1,10 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export { transformUnsnoozeBody } from './transform_unsnooze_body/latest';
|
||||
|
||||
export { transformUnsnoozeBody as transformUnsnoozeBodyV1 } from './transform_unsnooze_body/v1';
|
|
@ -0,0 +1,8 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export * from './v1';
|
|
@ -0,0 +1,10 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export const transformUnsnoozeBody: (opts: { schedule_ids?: string[] }) => {
|
||||
scheduleIds?: string[];
|
||||
} = ({ schedule_ids: scheduleIds }) => (scheduleIds ? { scheduleIds } : {});
|
|
@ -5,15 +5,15 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { unsnoozeRuleRoute } from './unsnooze_rule';
|
||||
import { unsnoozeRuleRoute } from './unsnooze_rule_route';
|
||||
import { httpServiceMock } from '@kbn/core/server/mocks';
|
||||
import { licenseStateMock } from '../lib/license_state.mock';
|
||||
import { mockHandlerArguments } from './_mock_handler_arguments';
|
||||
import { rulesClientMock } from '../rules_client.mock';
|
||||
import { RuleTypeDisabledError } from '../lib/errors/rule_type_disabled';
|
||||
import { licenseStateMock } from '../../../../lib/license_state.mock';
|
||||
import { mockHandlerArguments } from '../../../_mock_handler_arguments';
|
||||
import { rulesClientMock } from '../../../../rules_client.mock';
|
||||
import { RuleTypeDisabledError } from '../../../../lib/errors/rule_type_disabled';
|
||||
|
||||
const rulesClient = rulesClientMock.create();
|
||||
jest.mock('../lib/license_api_access', () => ({
|
||||
jest.mock('../../../../lib/license_api_access', () => ({
|
||||
verifyApiAccess: jest.fn(),
|
||||
}));
|
||||
|
|
@ -5,25 +5,18 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { TypeOf } from '@kbn/config-schema';
|
||||
import { IRouter } from '@kbn/core/server';
|
||||
import { schema } from '@kbn/config-schema';
|
||||
import { ILicenseState, RuleMutedError } from '../lib';
|
||||
import { verifyAccessAndContext, RewriteRequestCase } from './lib';
|
||||
import { AlertingRequestHandlerContext, INTERNAL_BASE_ALERTING_API_PATH } from '../types';
|
||||
import {
|
||||
unsnoozeBodySchema,
|
||||
unsnoozeParamsSchema,
|
||||
} from '../../../../../common/routes/rule/apis/unsnooze';
|
||||
import { ILicenseState, RuleMutedError } from '../../../../lib';
|
||||
import { verifyAccessAndContext } from '../../../lib';
|
||||
import { AlertingRequestHandlerContext, INTERNAL_BASE_ALERTING_API_PATH } from '../../../../types';
|
||||
import { transformUnsnoozeBodyV1 } from './transforms';
|
||||
|
||||
const paramSchema = schema.object({
|
||||
id: schema.string(),
|
||||
});
|
||||
|
||||
export const scheduleIdsSchema = schema.maybe(schema.arrayOf(schema.string()));
|
||||
|
||||
const bodySchema = schema.object({
|
||||
schedule_ids: scheduleIdsSchema,
|
||||
});
|
||||
|
||||
const rewriteBodyReq: RewriteRequestCase<{ scheduleIds?: string[] }> = ({
|
||||
schedule_ids: scheduleIds,
|
||||
}) => (scheduleIds ? { scheduleIds } : {});
|
||||
export type UnsnoozeRuleRequestParamsV1 = TypeOf<typeof unsnoozeParamsSchema>;
|
||||
|
||||
export const unsnoozeRuleRoute = (
|
||||
router: IRouter<AlertingRequestHandlerContext>,
|
||||
|
@ -33,15 +26,15 @@ export const unsnoozeRuleRoute = (
|
|||
{
|
||||
path: `${INTERNAL_BASE_ALERTING_API_PATH}/rule/{id}/_unsnooze`,
|
||||
validate: {
|
||||
params: paramSchema,
|
||||
body: bodySchema,
|
||||
params: unsnoozeParamsSchema,
|
||||
body: unsnoozeBodySchema,
|
||||
},
|
||||
},
|
||||
router.handleLegacyErrors(
|
||||
verifyAccessAndContext(licenseState, async function (context, req, res) {
|
||||
const rulesClient = (await context.alerting).getRulesClient();
|
||||
const params = req.params;
|
||||
const body = rewriteBodyReq(req.body);
|
||||
const params: UnsnoozeRuleRequestParamsV1 = req.params;
|
||||
const body = transformUnsnoozeBodyV1(req.body);
|
||||
try {
|
||||
await rulesClient.unsnooze({ ...params, ...body });
|
||||
return res.noContent();
|
|
@ -82,6 +82,7 @@ export const transformRuleToRuleResponse = <Params extends RuleParams = never>(
|
|||
mute_all: rule.muteAll,
|
||||
...(rule.notifyWhen !== undefined ? { notify_when: rule.notifyWhen } : {}),
|
||||
muted_alert_ids: rule.mutedInstanceIds,
|
||||
...(rule.scheduledTaskId !== undefined ? { scheduled_task_id: rule.scheduledTaskId } : {}),
|
||||
execution_status: {
|
||||
status: rule.executionStatus.status,
|
||||
...(rule.executionStatus.error ? { error: rule.executionStatus.error } : {}),
|
||||
|
|
|
@ -6,18 +6,19 @@
|
|||
*/
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { RawRule, RuleSnoozeSchedule } from '../../types';
|
||||
import {
|
||||
Rule,
|
||||
RuleDomain,
|
||||
RuleParams,
|
||||
RuleSnoozeSchedule as RuleDomainSnoozeSchedule,
|
||||
} from '../../application/rule/types';
|
||||
import { RuleAttributes } from '../../data/rule/types';
|
||||
import { getActiveScheduledSnoozes } from '../../lib/is_rule_snoozed';
|
||||
|
||||
/**
|
||||
* @deprecated TODO (http-versioning): Deprecate this once we fix all RawRule types
|
||||
*/
|
||||
export function getSnoozeAttributes(attributes: RawRule, snoozeSchedule: RuleSnoozeSchedule) {
|
||||
export function getSnoozeAttributes(
|
||||
attributes: RuleAttributes,
|
||||
snoozeSchedule: RuleDomainSnoozeSchedule
|
||||
) {
|
||||
// If duration is -1, instead mute all
|
||||
const { id: snoozeId, duration } = snoozeSchedule;
|
||||
|
||||
|
@ -69,10 +70,7 @@ export function getBulkSnooze<Params extends RuleParams>(
|
|||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated TODO (http-versioning): Deprecate this once we fix all RawRule types
|
||||
*/
|
||||
export function getUnsnoozeAttributes(attributes: RawRule, scheduleIds?: string[]) {
|
||||
export function getUnsnoozeAttributes(attributes: RuleAttributes, scheduleIds?: string[]) {
|
||||
const snoozeSchedule = scheduleIds
|
||||
? clearScheduledSnoozesAttributesById(attributes, scheduleIds)
|
||||
: clearCurrentActiveSnoozeAttributes(attributes);
|
||||
|
@ -106,10 +104,7 @@ export function getBulkUnsnooze<Params extends RuleParams>(
|
|||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated TODO (http-versioning): Deprecate this once we fix all RawRule types
|
||||
*/
|
||||
export function clearUnscheduledSnoozeAttributes(attributes: RawRule) {
|
||||
export function clearUnscheduledSnoozeAttributes(attributes: RuleAttributes) {
|
||||
// Clear any snoozes that have no ID property. These are "simple" snoozes created with the quick UI, e.g. snooze for 3 days starting now
|
||||
return attributes.snoozeSchedule
|
||||
? attributes.snoozeSchedule.filter((s) => typeof s.id !== 'undefined')
|
||||
|
@ -120,10 +115,7 @@ export function clearUnscheduledSnooze<Params extends RuleParams>(rule: RuleDoma
|
|||
return rule.snoozeSchedule ? rule.snoozeSchedule.filter((s) => typeof s.id !== 'undefined') : [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated TODO (http-versioning): Deprecate this once we fix all RawRule types
|
||||
*/
|
||||
export function clearScheduledSnoozesAttributesById(attributes: RawRule, ids: string[]) {
|
||||
export function clearScheduledSnoozesAttributesById(attributes: RuleAttributes, ids: string[]) {
|
||||
return attributes.snoozeSchedule
|
||||
? attributes.snoozeSchedule.filter((s) => s.id && !ids.includes(s.id))
|
||||
: [];
|
||||
|
@ -136,10 +128,7 @@ export function clearScheduledSnoozesById<Params extends RuleParams>(
|
|||
return rule.snoozeSchedule ? rule.snoozeSchedule.filter((s) => s.id && !ids.includes(s.id)) : [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated TODO (http-versioning): Deprecate this once we fix all RawRule types
|
||||
*/
|
||||
export function clearCurrentActiveSnoozeAttributes(attributes: RawRule) {
|
||||
export function clearCurrentActiveSnoozeAttributes(attributes: RuleAttributes) {
|
||||
// First attempt to cancel a simple (unscheduled) snooze
|
||||
const clearedUnscheduledSnoozes = clearUnscheduledSnoozeAttributes(attributes);
|
||||
// Now clear any scheduled snoozes that are currently active and never recur
|
||||
|
@ -193,10 +182,7 @@ export function clearCurrentActiveSnooze<Params extends RuleParams>(rule: RuleDo
|
|||
return clearedSnoozesAndSkippedRecurringSnoozes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated TODO (http-versioning): Deprecate this once we fix all RawRule types
|
||||
*/
|
||||
export function verifySnoozeAttributeScheduleLimit(attributes: Partial<RawRule>) {
|
||||
export function verifySnoozeAttributeScheduleLimit(attributes: Partial<Rule>) {
|
||||
const schedules = attributes.snoozeSchedule?.filter((snooze) => snooze.id);
|
||||
if (schedules && schedules.length > 5) {
|
||||
throw Error(
|
||||
|
|
|
@ -37,6 +37,9 @@ export interface GetAlertFromRawParams {
|
|||
omitGeneratedValues?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated in favor of transformRuleAttributesToRuleDomain
|
||||
*/
|
||||
export function getAlertFromRaw<Params extends RuleTypeParams>(
|
||||
context: RulesClientContext,
|
||||
id: string,
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* 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 { SavedObject } from '@kbn/core/server';
|
||||
import { withSpan } from '@kbn/apm-utils';
|
||||
import { ruleAuditEvent, RuleAuditAction } from '../common/audit_events';
|
||||
import { RulesClientContext } from '../types';
|
||||
import { getRuleSo } from '../../data/rule';
|
||||
import { RuleAttributes } from '../../data/rule/types';
|
||||
|
||||
interface GetRuleSavedObjectParams {
|
||||
ruleId: string;
|
||||
}
|
||||
|
||||
export async function getRuleSavedObject(
|
||||
context: RulesClientContext,
|
||||
params: GetRuleSavedObjectParams
|
||||
): Promise<SavedObject<RuleAttributes>> {
|
||||
const { ruleId } = params;
|
||||
|
||||
context.auditLogger?.log(
|
||||
ruleAuditEvent({
|
||||
action: RuleAuditAction.GET,
|
||||
outcome: 'unknown',
|
||||
savedObject: { type: 'alert', id: ruleId },
|
||||
})
|
||||
);
|
||||
|
||||
return await withSpan({ name: 'unsecuredSavedObjectsClient.get', type: 'rules' }, () =>
|
||||
getRuleSo({
|
||||
id: ruleId,
|
||||
savedObjectsClient: context.unsecuredSavedObjectsClient,
|
||||
})
|
||||
);
|
||||
}
|
|
@ -6,9 +6,13 @@
|
|||
*/
|
||||
|
||||
export { createRuleSavedObject } from './create_rule_saved_object';
|
||||
export { resolveRuleSavedObject } from './resolve_rule_saved_object';
|
||||
export { getRuleSavedObject } from './get_rule_saved_object';
|
||||
|
||||
export { extractReferences } from './extract_references';
|
||||
export { validateActions } from './validate_actions';
|
||||
export { updateMeta } from './update_meta';
|
||||
export { updateMetaAttributes } from './update_meta_attributes';
|
||||
export * from './get_alert_from_raw';
|
||||
export { getAuthorizationFilter } from './get_authorization_filter';
|
||||
export { checkAuthorizationAndGetTotal } from './check_authorization_and_get_total';
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* 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 { SavedObjectsResolveResponse } from '@kbn/core/server';
|
||||
import { withSpan } from '@kbn/apm-utils';
|
||||
import { ruleAuditEvent, RuleAuditAction } from '../common/audit_events';
|
||||
import { RulesClientContext } from '../types';
|
||||
import { resolveRuleSo } from '../../data/rule';
|
||||
import { RuleAttributes } from '../../data/rule/types';
|
||||
|
||||
interface ResolveRuleSavedObjectParams {
|
||||
ruleId: string;
|
||||
}
|
||||
|
||||
export async function resolveRuleSavedObject(
|
||||
context: RulesClientContext,
|
||||
params: ResolveRuleSavedObjectParams
|
||||
): Promise<SavedObjectsResolveResponse<RuleAttributes>> {
|
||||
const { ruleId } = params;
|
||||
|
||||
context.auditLogger?.log(
|
||||
ruleAuditEvent({
|
||||
action: RuleAuditAction.RESOLVE,
|
||||
outcome: 'unknown',
|
||||
savedObject: { type: 'alert', id: ruleId },
|
||||
})
|
||||
);
|
||||
|
||||
return await withSpan({ name: 'unsecuredSavedObjectsClient.resolve', type: 'rules' }, () =>
|
||||
resolveRuleSo({
|
||||
id: ruleId,
|
||||
savedObjectsClient: context.unsecuredSavedObjectsClient,
|
||||
})
|
||||
);
|
||||
}
|
|
@ -8,6 +8,9 @@
|
|||
import { RawRule } from '../../types';
|
||||
import { RulesClientContext } from '../types';
|
||||
|
||||
/**
|
||||
* @deprecated Use updateMetaAttributes instead
|
||||
*/
|
||||
export function updateMeta<T extends Partial<RawRule>>(
|
||||
context: RulesClientContext,
|
||||
alertAttributes: T
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* 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 { RuleAttributes } from '../../data/rule/types';
|
||||
import { RulesClientContext } from '../types';
|
||||
|
||||
export function updateMetaAttributes<T extends Partial<RuleAttributes>>(
|
||||
context: RulesClientContext,
|
||||
alertAttributes: T
|
||||
): T {
|
||||
if (alertAttributes.hasOwnProperty('apiKey') || alertAttributes.hasOwnProperty('apiKeyOwner')) {
|
||||
return {
|
||||
...alertAttributes,
|
||||
meta: {
|
||||
...(alertAttributes.meta ?? {}),
|
||||
versionApiKeyLastmodified: context.kibanaVersion,
|
||||
},
|
||||
};
|
||||
}
|
||||
return alertAttributes;
|
||||
}
|
|
@ -11,8 +11,9 @@ import { retryIfConflicts } from '../../lib/retry_if_conflicts';
|
|||
import { partiallyUpdateAlert } from '../../saved_objects';
|
||||
import { ruleAuditEvent, RuleAuditAction } from '../common/audit_events';
|
||||
import { RulesClientContext } from '../types';
|
||||
import { updateMeta } from '../lib';
|
||||
import { updateMetaAttributes } from '../lib';
|
||||
import { clearUnscheduledSnoozeAttributes } from '../common';
|
||||
import { RuleAttributes } from '../../data/rule/types';
|
||||
|
||||
export async function muteAll(context: RulesClientContext, { id }: { id: string }): Promise<void> {
|
||||
return await retryIfConflicts(
|
||||
|
@ -60,10 +61,10 @@ async function muteAllWithOCC(context: RulesClientContext, { id }: { id: string
|
|||
|
||||
context.ruleTypeRegistry.ensureRuleTypeEnabled(attributes.alertTypeId);
|
||||
|
||||
const updateAttributes = updateMeta(context, {
|
||||
const updateAttributes = updateMetaAttributes(context, {
|
||||
muteAll: true,
|
||||
mutedInstanceIds: [],
|
||||
snoozeSchedule: clearUnscheduledSnoozeAttributes(attributes),
|
||||
snoozeSchedule: clearUnscheduledSnoozeAttributes(attributes as RuleAttributes),
|
||||
updatedBy: await context.getUserName(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
});
|
||||
|
|
|
@ -1,81 +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 { AlertConsumers } from '@kbn/rule-data-utils';
|
||||
|
||||
import { RawRule, RuleTypeParams, ResolvedSanitizedRule } from '../../types';
|
||||
import { ReadOperations, AlertingAuthorizationEntity } from '../../authorization';
|
||||
import { ruleAuditEvent, RuleAuditAction } from '../common/audit_events';
|
||||
import { getAlertFromRaw } from '../lib/get_alert_from_raw';
|
||||
import { RulesClientContext } from '../types';
|
||||
import { formatLegacyActions } from '../lib';
|
||||
|
||||
export interface ResolveParams {
|
||||
id: string;
|
||||
includeLegacyId?: boolean;
|
||||
includeSnoozeData?: boolean;
|
||||
}
|
||||
|
||||
export async function resolve<Params extends RuleTypeParams = never>(
|
||||
context: RulesClientContext,
|
||||
{ id, includeLegacyId, includeSnoozeData = false }: ResolveParams
|
||||
): Promise<ResolvedSanitizedRule<Params>> {
|
||||
const { saved_object: result, ...resolveResponse } =
|
||||
await context.unsecuredSavedObjectsClient.resolve<RawRule>('alert', id);
|
||||
try {
|
||||
await context.authorization.ensureAuthorized({
|
||||
ruleTypeId: result.attributes.alertTypeId,
|
||||
consumer: result.attributes.consumer,
|
||||
operation: ReadOperations.Get,
|
||||
entity: AlertingAuthorizationEntity.Rule,
|
||||
});
|
||||
} catch (error) {
|
||||
context.auditLogger?.log(
|
||||
ruleAuditEvent({
|
||||
action: RuleAuditAction.RESOLVE,
|
||||
savedObject: { type: 'alert', id },
|
||||
error,
|
||||
})
|
||||
);
|
||||
throw error;
|
||||
}
|
||||
context.auditLogger?.log(
|
||||
ruleAuditEvent({
|
||||
action: RuleAuditAction.RESOLVE,
|
||||
savedObject: { type: 'alert', id },
|
||||
})
|
||||
);
|
||||
|
||||
const rule = getAlertFromRaw<Params>(
|
||||
context,
|
||||
result.id,
|
||||
result.attributes.alertTypeId,
|
||||
result.attributes,
|
||||
result.references,
|
||||
includeLegacyId,
|
||||
false,
|
||||
includeSnoozeData
|
||||
);
|
||||
|
||||
// format legacy actions for SIEM rules
|
||||
if (result.attributes.consumer === AlertConsumers.SIEM) {
|
||||
const [migratedRule] = await formatLegacyActions([rule], {
|
||||
savedObjectsClient: context.unsecuredSavedObjectsClient,
|
||||
logger: context.logger,
|
||||
});
|
||||
|
||||
return {
|
||||
...migratedRule,
|
||||
...resolveResponse,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
...rule,
|
||||
...resolveResponse,
|
||||
};
|
||||
}
|
|
@ -11,8 +11,9 @@ import { retryIfConflicts } from '../../lib/retry_if_conflicts';
|
|||
import { partiallyUpdateAlert } from '../../saved_objects';
|
||||
import { ruleAuditEvent, RuleAuditAction } from '../common/audit_events';
|
||||
import { RulesClientContext } from '../types';
|
||||
import { updateMeta } from '../lib';
|
||||
import { updateMetaAttributes } from '../lib';
|
||||
import { clearUnscheduledSnoozeAttributes } from '../common';
|
||||
import { RuleAttributes } from '../../data/rule/types';
|
||||
|
||||
export async function unmuteAll(
|
||||
context: RulesClientContext,
|
||||
|
@ -63,10 +64,10 @@ async function unmuteAllWithOCC(context: RulesClientContext, { id }: { id: strin
|
|||
|
||||
context.ruleTypeRegistry.ensureRuleTypeEnabled(attributes.alertTypeId);
|
||||
|
||||
const updateAttributes = updateMeta(context, {
|
||||
const updateAttributes = updateMetaAttributes(context, {
|
||||
muteAll: false,
|
||||
mutedInstanceIds: [],
|
||||
snoozeSchedule: clearUnscheduledSnoozeAttributes(attributes),
|
||||
snoozeSchedule: clearUnscheduledSnoozeAttributes(attributes as RuleAttributes),
|
||||
updatedBy: await context.getUserName(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
});
|
||||
|
|
|
@ -12,8 +12,10 @@ import { parseDuration } from '../../common/parse_duration';
|
|||
import { RulesClientContext, BulkOptions } from './types';
|
||||
import { clone, CloneArguments } from './methods/clone';
|
||||
import { createRule, CreateRuleParams } from '../application/rule/methods/create';
|
||||
import { snoozeRule, SnoozeRuleOptions } from '../application/rule/methods/snooze';
|
||||
import { unsnoozeRule, UnsnoozeParams } from '../application/rule/methods/unsnooze';
|
||||
import { get, GetParams } from './methods/get';
|
||||
import { resolve, ResolveParams } from './methods/resolve';
|
||||
import { resolveRule, ResolveParams } from '../application/rule/methods/resolve';
|
||||
import { getAlertState, GetAlertStateParams } from './methods/get_alert_state';
|
||||
import { getAlertSummary, GetAlertSummaryParams } from './methods/get_alert_summary';
|
||||
import {
|
||||
|
@ -54,8 +56,6 @@ import { bulkEnableRules } from './methods/bulk_enable';
|
|||
import { updateApiKey } from './methods/update_api_key';
|
||||
import { enable } from './methods/enable';
|
||||
import { disable } from './methods/disable';
|
||||
import { snooze, SnoozeParams } from './methods/snooze';
|
||||
import { unsnooze, UnsnoozeParams } from './methods/unsnooze';
|
||||
import { clearExpiredSnoozes } from './methods/clear_expired_snoozes';
|
||||
import { muteInstance } from '../application/rule/methods/mute_alert/mute_instance';
|
||||
import { muteAll } from './methods/mute_all';
|
||||
|
@ -130,7 +130,7 @@ export class RulesClient {
|
|||
public get = <Params extends RuleTypeParams = never>(params: GetParams) =>
|
||||
get<Params>(this.context, params);
|
||||
public resolve = <Params extends RuleTypeParams = never>(params: ResolveParams) =>
|
||||
resolve<Params>(this.context, params);
|
||||
resolveRule<Params>(this.context, params);
|
||||
public update = <Params extends RuleTypeParams = never>(params: UpdateOptions<Params>) =>
|
||||
update<Params>(this.context, params);
|
||||
|
||||
|
@ -162,8 +162,8 @@ export class RulesClient {
|
|||
public enable = (options: { id: string }) => enable(this.context, options);
|
||||
public disable = (options: { id: string }) => disable(this.context, options);
|
||||
|
||||
public snooze = (options: SnoozeParams) => snooze(this.context, options);
|
||||
public unsnooze = (options: UnsnoozeParams) => unsnooze(this.context, options);
|
||||
public snooze = (options: SnoozeRuleOptions) => snoozeRule(this.context, options);
|
||||
public unsnooze = (options: UnsnoozeParams) => unsnoozeRule(this.context, options);
|
||||
|
||||
public clearExpiredSnoozes = (options: {
|
||||
rule: Pick<SanitizedRule<RuleTypeParams>, 'id' | 'snoozeSchedule'>;
|
||||
|
|
|
@ -96,6 +96,11 @@ describe('resolve()', () => {
|
|||
},
|
||||
],
|
||||
notifyWhen: 'onActiveAlert',
|
||||
executionStatus: {
|
||||
status: 'ok',
|
||||
last_execution_date: new Date().toISOString(),
|
||||
last_duration: 10,
|
||||
},
|
||||
},
|
||||
references: [
|
||||
{
|
||||
|
@ -123,6 +128,10 @@ describe('resolve()', () => {
|
|||
"alertTypeId": "123",
|
||||
"alias_target_id": "2",
|
||||
"createdAt": 2019-02-12T21:01:22.479Z,
|
||||
"executionStatus": Object {
|
||||
"lastExecutionDate": 2019-02-12T21:01:22.479Z,
|
||||
"status": "ok",
|
||||
},
|
||||
"id": "1",
|
||||
"notifyWhen": "onActiveAlert",
|
||||
"outcome": "aliasMatch",
|
||||
|
@ -138,86 +147,12 @@ describe('resolve()', () => {
|
|||
`);
|
||||
expect(unsecuredSavedObjectsClient.resolve).toHaveBeenCalledTimes(1);
|
||||
expect(unsecuredSavedObjectsClient.resolve.mock.calls[0]).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"alert",
|
||||
"1",
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
||||
test('calls saved objects client with id and includeLegacyId params', async () => {
|
||||
const rulesClient = new RulesClient(rulesClientParams);
|
||||
unsecuredSavedObjectsClient.resolve.mockResolvedValueOnce({
|
||||
saved_object: {
|
||||
id: '1',
|
||||
type: 'alert',
|
||||
attributes: {
|
||||
legacyId: 'some-legacy-id',
|
||||
alertTypeId: '123',
|
||||
schedule: { interval: '10s' },
|
||||
params: {
|
||||
bar: true,
|
||||
},
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
actions: [
|
||||
{
|
||||
group: 'default',
|
||||
actionRef: 'action_0',
|
||||
params: {
|
||||
foo: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
notifyWhen: 'onActiveAlert',
|
||||
},
|
||||
references: [
|
||||
{
|
||||
name: 'action_0',
|
||||
type: 'action',
|
||||
id: '1',
|
||||
},
|
||||
],
|
||||
},
|
||||
outcome: 'aliasMatch',
|
||||
alias_target_id: '2',
|
||||
});
|
||||
const result = await rulesClient.resolve({ id: '1', includeLegacyId: true });
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"actions": Array [
|
||||
Object {
|
||||
"group": "default",
|
||||
"id": "1",
|
||||
"params": Object {
|
||||
"foo": true,
|
||||
},
|
||||
},
|
||||
],
|
||||
"alertTypeId": "123",
|
||||
"alias_target_id": "2",
|
||||
"createdAt": 2019-02-12T21:01:22.479Z,
|
||||
"id": "1",
|
||||
"legacyId": "some-legacy-id",
|
||||
"notifyWhen": "onActiveAlert",
|
||||
"outcome": "aliasMatch",
|
||||
"params": Object {
|
||||
"bar": true,
|
||||
},
|
||||
"schedule": Object {
|
||||
"interval": "10s",
|
||||
},
|
||||
"snoozeSchedule": Array [],
|
||||
"updatedAt": 2019-02-12T21:01:22.479Z,
|
||||
}
|
||||
Array [
|
||||
"alert",
|
||||
"1",
|
||||
undefined,
|
||||
]
|
||||
`);
|
||||
expect(unsecuredSavedObjectsClient.resolve).toHaveBeenCalledTimes(1);
|
||||
expect(unsecuredSavedObjectsClient.resolve.mock.calls[0]).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"alert",
|
||||
"1",
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
||||
test('calls saved objects client with id and includeSnoozeData params', async () => {
|
||||
|
@ -256,6 +191,11 @@ describe('resolve()', () => {
|
|||
},
|
||||
],
|
||||
notifyWhen: 'onActiveAlert',
|
||||
executionStatus: {
|
||||
status: 'ok',
|
||||
last_execution_date: new Date().toISOString(),
|
||||
last_duration: 10,
|
||||
},
|
||||
},
|
||||
references: [
|
||||
{
|
||||
|
@ -323,6 +263,11 @@ describe('resolve()', () => {
|
|||
},
|
||||
],
|
||||
notifyWhen: 'onActiveAlert',
|
||||
executionStatus: {
|
||||
status: 'ok',
|
||||
last_execution_date: new Date().toISOString(),
|
||||
last_duration: 10,
|
||||
},
|
||||
},
|
||||
references: [
|
||||
{
|
||||
|
@ -363,6 +308,10 @@ describe('resolve()', () => {
|
|||
"alertTypeId": "123",
|
||||
"alias_target_id": "2",
|
||||
"createdAt": 2019-02-12T21:01:22.479Z,
|
||||
"executionStatus": Object {
|
||||
"lastExecutionDate": 2019-02-12T21:01:22.479Z,
|
||||
"status": "ok",
|
||||
},
|
||||
"id": "1",
|
||||
"notifyWhen": "onActiveAlert",
|
||||
"outcome": "aliasMatch",
|
||||
|
@ -400,6 +349,11 @@ describe('resolve()', () => {
|
|||
},
|
||||
},
|
||||
],
|
||||
executionStatus: {
|
||||
status: 'ok',
|
||||
last_execution_date: new Date().toISOString(),
|
||||
last_duration: 10,
|
||||
},
|
||||
},
|
||||
references: [],
|
||||
},
|
||||
|
@ -505,6 +459,11 @@ describe('resolve()', () => {
|
|||
},
|
||||
},
|
||||
],
|
||||
executionStatus: {
|
||||
status: 'ok',
|
||||
last_execution_date: new Date().toISOString(),
|
||||
last_duration: 10,
|
||||
},
|
||||
},
|
||||
references: [
|
||||
{
|
||||
|
@ -563,6 +522,11 @@ describe('resolve()', () => {
|
|||
bar: true,
|
||||
},
|
||||
actions: [],
|
||||
executionStatus: {
|
||||
status: 'ok',
|
||||
last_execution_date: new Date().toISOString(),
|
||||
last_duration: 10,
|
||||
},
|
||||
},
|
||||
references: [],
|
||||
},
|
||||
|
@ -633,6 +597,11 @@ describe('resolve()', () => {
|
|||
},
|
||||
],
|
||||
notifyWhen: 'onActiveAlert',
|
||||
executionStatus: {
|
||||
status: 'ok',
|
||||
last_execution_date: new Date().toISOString(),
|
||||
last_duration: 10,
|
||||
},
|
||||
},
|
||||
references: [
|
||||
{
|
||||
|
|
|
@ -442,6 +442,9 @@ export interface RawRuleExecutionStatus extends SavedObjectAttributes {
|
|||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated in favor of Rule
|
||||
*/
|
||||
export interface RawRule extends SavedObjectAttributes {
|
||||
enabled: boolean;
|
||||
name: string;
|
||||
|
|
|
@ -59,7 +59,8 @@
|
|||
"@kbn/serverless",
|
||||
"@kbn/core-http-router-server-mocks",
|
||||
"@kbn/core-elasticsearch-server",
|
||||
"@kbn/core-application-common"
|
||||
"@kbn/core-application-common",
|
||||
"@kbn/core-saved-objects-api-server"
|
||||
],
|
||||
"exclude": ["target/**/*"]
|
||||
}
|
||||
|
|
|
@ -199,7 +199,6 @@ export const RulesListNotifyBadge: React.FunctionComponent<RulesListNotifyBadgeP
|
|||
}, [formattedSnoozeText, isLoading, isDisabled, openPopover]);
|
||||
|
||||
const scheduledSnoozeButton = useMemo(() => {
|
||||
// TODO: Implement scheduled snooze button
|
||||
return (
|
||||
<EuiButton
|
||||
size="s"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue