From b20db60a3053bd491c0787c419ad518a60f4a3bb Mon Sep 17 00:00:00 2001 From: Yuliia Naumenko Date: Tue, 8 Dec 2020 12:41:54 -0800 Subject: [PATCH] [Alerts][License] Define minimum license required for each alert type (#84997) * Define minimum license required for each alert type * fixed typechecks * fixed tests * fixed tests * fixed due to comments * fixed due to comments * removed file * removed casting to LicenseType --- .../server/alert_types/always_firing.ts | 1 + .../server/alert_types/astros.ts | 1 + x-pack/plugins/alerts/README.md | 2 + x-pack/plugins/alerts/common/alert_type.ts | 3 + .../plugins/alerts/public/alert_api.test.ts | 4 + .../alert_navigation_registry.test.ts | 1 + .../alerts/server/alert_type_registry.test.ts | 29 +++-- .../alerts/server/alert_type_registry.ts | 2 + .../alerts_client/tests/aggregate.test.ts | 2 + .../server/alerts_client/tests/create.test.ts | 1 + .../server/alerts_client/tests/find.test.ts | 2 + .../alerts/server/alerts_client/tests/lib.ts | 1 + .../tests/list_alert_types.test.ts | 5 + .../server/alerts_client/tests/update.test.ts | 3 + .../alerts_client_conflict_retries.test.ts | 2 + .../alerts_authorization.test.ts | 14 +++ .../alerts_authorization_kuery.test.ts | 5 + .../lib/validate_alert_type_params.test.ts | 3 + x-pack/plugins/alerts/server/plugin.test.ts | 68 +++++++++++- x-pack/plugins/alerts/server/plugin.ts | 34 +++++- .../server/routes/list_alert_types.test.ts | 4 + .../create_execution_handler.test.ts | 1 + .../server/task_runner/task_runner.test.ts | 37 ++++--- .../task_runner/task_runner_factory.test.ts | 4 +- x-pack/plugins/alerts/server/types.ts | 18 +++- x-pack/plugins/apm/common/alert_types.ts | 4 + .../alerts/register_error_count_alert_type.ts | 1 + ...egister_transaction_duration_alert_type.ts | 1 + ...transaction_duration_anomaly_alert_type.ts | 1 + ...ister_transaction_error_rate_alert_type.ts | 1 + ...r_inventory_metric_threshold_alert_type.ts | 4 +- .../register_log_threshold_alert_type.ts | 1 + .../register_metric_threshold_alert_type.ts | 4 +- .../monitoring/server/alerts/base_alert.ts | 1 + .../rules_notification_alert_type.ts | 1 + .../signals/signal_rule_alert_type.ts | 1 + .../alert_types/geo_containment/alert_type.ts | 43 +------- .../alert_types/geo_containment/index.ts | 4 +- .../alert_types/geo_threshold/alert_type.ts | 43 +------- .../alert_types/index_threshold/alert_type.ts | 1 + .../application/lib/action_variables.test.ts | 1 + .../public/application/lib/alert_api.test.ts | 1 + .../components/alert_details.test.tsx | 65 +++++++---- .../components/alert_instances.test.tsx | 1 + .../components/alert_instances_route.test.tsx | 1 + .../sections/alert_form/alert_add.test.tsx | 1 + .../sections/alert_form/alert_form.test.tsx | 3 + .../components/alerts_list.test.tsx | 1 + .../triggers_actions_ui/public/types.ts | 19 ++-- .../server/lib/alerts/duration_anomaly.ts | 1 + .../uptime/server/lib/alerts/status_check.ts | 1 + .../plugins/uptime/server/lib/alerts/tls.ts | 1 + .../plugins/alerts/server/alert_types.ts | 102 ++++++++++-------- .../alerts_restricted/server/alert_types.ts | 2 + .../tests/alerting/list_alert_types.ts | 2 + .../tests/alerting/list_alert_types.ts | 1 + .../fixtures/plugins/alerts/server/plugin.ts | 7 +- 57 files changed, 371 insertions(+), 197 deletions(-) diff --git a/x-pack/examples/alerting_example/server/alert_types/always_firing.ts b/x-pack/examples/alerting_example/server/alert_types/always_firing.ts index 1900f55a51a55..a0abf01e53937 100644 --- a/x-pack/examples/alerting_example/server/alert_types/always_firing.ts +++ b/x-pack/examples/alerting_example/server/alert_types/always_firing.ts @@ -41,6 +41,7 @@ export const alertType: AlertType = { name: 'Always firing', actionGroups: ACTION_GROUPS, defaultActionGroupId: DEFAULT_ACTION_GROUP, + minimumLicenseRequired: 'basic', async executor({ services, params: { instances = DEFAULT_INSTANCES_TO_GENERATE, thresholds }, diff --git a/x-pack/examples/alerting_example/server/alert_types/astros.ts b/x-pack/examples/alerting_example/server/alert_types/astros.ts index f0f47adffa109..27a8bfc7a53a3 100644 --- a/x-pack/examples/alerting_example/server/alert_types/astros.ts +++ b/x-pack/examples/alerting_example/server/alert_types/astros.ts @@ -42,6 +42,7 @@ export const alertType: AlertType = { id: 'example.people-in-space', name: 'People In Space Right Now', actionGroups: [{ id: 'default', name: 'default' }], + minimumLicenseRequired: 'basic', defaultActionGroupId: 'default', recoveryActionGroup: { id: 'hasLandedBackOnEarth', diff --git a/x-pack/plugins/alerts/README.md b/x-pack/plugins/alerts/README.md index 519c50e3f27c0..d5131172bdfa9 100644 --- a/x-pack/plugins/alerts/README.md +++ b/x-pack/plugins/alerts/README.md @@ -172,6 +172,7 @@ server.newPlatform.setup.plugins.alerts.registerType({ { name: 'cpuUsage', description: 'CPU usage' }, ], }, + minimumLicenseRequired: 'basic', async executor({ alertId, startedAt, @@ -239,6 +240,7 @@ server.newPlatform.setup.plugins.alerts.registerType({ }, ], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', actionVariables: { context: [ { name: 'server', description: 'the server' }, diff --git a/x-pack/plugins/alerts/common/alert_type.ts b/x-pack/plugins/alerts/common/alert_type.ts index a06c6d2fd5af2..4ab3ddc7ca810 100644 --- a/x-pack/plugins/alerts/common/alert_type.ts +++ b/x-pack/plugins/alerts/common/alert_type.ts @@ -4,6 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ +import { LicenseType } from '../../licensing/common/types'; + export interface AlertType { id: string; name: string; @@ -12,6 +14,7 @@ export interface AlertType { actionVariables: string[]; defaultActionGroupId: ActionGroup['id']; producer: string; + minimumLicenseRequired: LicenseType; } export interface ActionGroup { diff --git a/x-pack/plugins/alerts/public/alert_api.test.ts b/x-pack/plugins/alerts/public/alert_api.test.ts index 03c55dfdf5b28..bfa7065473dc6 100644 --- a/x-pack/plugins/alerts/public/alert_api.test.ts +++ b/x-pack/plugins/alerts/public/alert_api.test.ts @@ -22,6 +22,7 @@ describe('loadAlertTypes', () => { actionVariables: ['var1'], actionGroups: [{ id: 'default', name: 'Default' }], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', recoveryActionGroup: RecoveredActionGroup, producer: 'alerts', }, @@ -46,6 +47,7 @@ describe('loadAlertType', () => { actionVariables: ['var1'], actionGroups: [{ id: 'default', name: 'Default' }], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', recoveryActionGroup: RecoveredActionGroup, producer: 'alerts', }; @@ -67,6 +69,7 @@ describe('loadAlertType', () => { actionVariables: [], actionGroups: [{ id: 'default', name: 'Default' }], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', recoveryActionGroup: RecoveredActionGroup, producer: 'alerts', }; @@ -83,6 +86,7 @@ describe('loadAlertType', () => { actionVariables: [], actionGroups: [{ id: 'default', name: 'Default' }], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', recoveryActionGroup: RecoveredActionGroup, producer: 'alerts', }, diff --git a/x-pack/plugins/alerts/public/alert_navigation_registry/alert_navigation_registry.test.ts b/x-pack/plugins/alerts/public/alert_navigation_registry/alert_navigation_registry.test.ts index bf005e07f959e..9b40964f71949 100644 --- a/x-pack/plugins/alerts/public/alert_navigation_registry/alert_navigation_registry.test.ts +++ b/x-pack/plugins/alerts/public/alert_navigation_registry/alert_navigation_registry.test.ts @@ -18,6 +18,7 @@ const mockAlertType = (id: string): AlertType => ({ actionVariables: [], defaultActionGroupId: 'default', producer: 'alerts', + minimumLicenseRequired: 'basic', }); describe('AlertNavigationRegistry', () => { diff --git a/x-pack/plugins/alerts/server/alert_type_registry.test.ts b/x-pack/plugins/alerts/server/alert_type_registry.test.ts index e4811daa3611b..ef481788d836f 100644 --- a/x-pack/plugins/alerts/server/alert_type_registry.test.ts +++ b/x-pack/plugins/alerts/server/alert_type_registry.test.ts @@ -35,6 +35,7 @@ describe('has()', () => { }, ], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', executor: jest.fn(), producer: 'alerts', }); @@ -44,7 +45,7 @@ describe('has()', () => { describe('register()', () => { test('throws if AlertType Id contains invalid characters', () => { - const alertType = { + const alertType: AlertType = { id: 'test', name: 'Test', actionGroups: [ @@ -54,6 +55,7 @@ describe('register()', () => { }, ], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', executor: jest.fn(), producer: 'alerts', }; @@ -75,7 +77,7 @@ describe('register()', () => { }); test('throws if AlertType Id isnt a string', () => { - const alertType = { + const alertType: AlertType = { id: (123 as unknown) as string, name: 'Test', actionGroups: [ @@ -85,6 +87,7 @@ describe('register()', () => { }, ], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', executor: jest.fn(), producer: 'alerts', }; @@ -96,7 +99,7 @@ describe('register()', () => { }); test('throws if AlertType action groups contains reserved group id', () => { - const alertType = { + const alertType: AlertType = { id: 'test', name: 'Test', actionGroups: [ @@ -110,6 +113,7 @@ describe('register()', () => { }, ], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', executor: jest.fn(), producer: 'alerts', }; @@ -123,7 +127,7 @@ describe('register()', () => { }); test('allows an AlertType to specify a custom recovery group', () => { - const alertType = { + const alertType: AlertType = { id: 'test', name: 'Test', actionGroups: [ @@ -139,6 +143,7 @@ describe('register()', () => { }, executor: jest.fn(), producer: 'alerts', + minimumLicenseRequired: 'basic', }; const registry = new AlertTypeRegistry(alertTypeRegistryParams); registry.register(alertType); @@ -157,7 +162,7 @@ describe('register()', () => { }); test('throws if the custom recovery group is contained in the AlertType action groups', () => { - const alertType = { + const alertType: AlertType = { id: 'test', name: 'Test', actionGroups: [ @@ -175,6 +180,7 @@ describe('register()', () => { name: 'Back To Awesome', }, defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', executor: jest.fn(), producer: 'alerts', }; @@ -188,7 +194,7 @@ describe('register()', () => { }); test('registers the executor with the task manager', () => { - const alertType = { + const alertType: AlertType = { id: 'test', name: 'Test', actionGroups: [ @@ -198,6 +204,7 @@ describe('register()', () => { }, ], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', executor: jest.fn(), producer: 'alerts', }; @@ -227,6 +234,7 @@ describe('register()', () => { }, ], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', executor: jest.fn(), producer: 'alerts', }; @@ -248,6 +256,7 @@ describe('register()', () => { }, ], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', executor: jest.fn(), producer: 'alerts', }); @@ -262,6 +271,7 @@ describe('register()', () => { }, ], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', executor: jest.fn(), producer: 'alerts', }) @@ -282,6 +292,7 @@ describe('get()', () => { }, ], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', executor: jest.fn(), producer: 'alerts', }); @@ -306,6 +317,7 @@ describe('get()', () => { "defaultActionGroupId": "default", "executor": [MockFunction], "id": "test", + "minimumLicenseRequired": "basic", "name": "Test", "producer": "alerts", "recoveryActionGroup": Object { @@ -343,6 +355,7 @@ describe('list()', () => { }, ], defaultActionGroupId: 'testActionGroup', + minimumLicenseRequired: 'basic', executor: jest.fn(), producer: 'alerts', }); @@ -367,6 +380,7 @@ describe('list()', () => { }, "defaultActionGroupId": "testActionGroup", "id": "test", + "minimumLicenseRequired": "basic", "name": "Test", "producer": "alerts", "recoveryActionGroup": Object { @@ -414,11 +428,12 @@ describe('list()', () => { }); function alertTypeWithVariables(id: string, context: string, state: string): AlertType { - const baseAlert = { + const baseAlert: AlertType = { id, name: `${id}-name`, actionGroups: [], defaultActionGroupId: id, + minimumLicenseRequired: 'basic', async executor() {}, producer: 'alerts', }; diff --git a/x-pack/plugins/alerts/server/alert_type_registry.ts b/x-pack/plugins/alerts/server/alert_type_registry.ts index a3e80fbd6c11a..e7571a71eb321 100644 --- a/x-pack/plugins/alerts/server/alert_type_registry.ts +++ b/x-pack/plugins/alerts/server/alert_type_registry.ts @@ -146,6 +146,7 @@ export class AlertTypeRegistry { defaultActionGroupId, actionVariables, producer, + minimumLicenseRequired, }, ]: [string, NormalizedAlertType]) => ({ id, @@ -155,6 +156,7 @@ export class AlertTypeRegistry { defaultActionGroupId, actionVariables, producer, + minimumLicenseRequired, }) ) ); diff --git a/x-pack/plugins/alerts/server/alerts_client/tests/aggregate.test.ts b/x-pack/plugins/alerts/server/alerts_client/tests/aggregate.test.ts index b21e3dcdf563d..bf796466932d4 100644 --- a/x-pack/plugins/alerts/server/alerts_client/tests/aggregate.test.ts +++ b/x-pack/plugins/alerts/server/alerts_client/tests/aggregate.test.ts @@ -54,6 +54,7 @@ describe('aggregate()', () => { actionGroups: [], actionVariables: undefined, defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', recoveryActionGroup: RecoveredActionGroup, id: 'myType', name: 'myType', @@ -104,6 +105,7 @@ describe('aggregate()', () => { name: 'Test', actionGroups: [{ id: 'default', name: 'Default' }], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', recoveryActionGroup: RecoveredActionGroup, producer: 'alerts', authorizedConsumers: { diff --git a/x-pack/plugins/alerts/server/alerts_client/tests/create.test.ts b/x-pack/plugins/alerts/server/alerts_client/tests/create.test.ts index b943a21ba9bb6..cada7ad7a7132 100644 --- a/x-pack/plugins/alerts/server/alerts_client/tests/create.test.ts +++ b/x-pack/plugins/alerts/server/alerts_client/tests/create.test.ts @@ -759,6 +759,7 @@ describe('create()', () => { threshold: schema.number({ min: 0, max: 1 }), }), }, + minimumLicenseRequired: 'basic', async executor() {}, producer: 'alerts', }); diff --git a/x-pack/plugins/alerts/server/alerts_client/tests/find.test.ts b/x-pack/plugins/alerts/server/alerts_client/tests/find.test.ts index 232d48e258256..9741eca1c3c9c 100644 --- a/x-pack/plugins/alerts/server/alerts_client/tests/find.test.ts +++ b/x-pack/plugins/alerts/server/alerts_client/tests/find.test.ts @@ -59,6 +59,7 @@ describe('find()', () => { recoveryActionGroup: RecoveredActionGroup, actionVariables: undefined, defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', id: 'myType', name: 'myType', producer: 'myApp', @@ -115,6 +116,7 @@ describe('find()', () => { actionGroups: [{ id: 'default', name: 'Default' }], recoveryActionGroup: RecoveredActionGroup, defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', producer: 'alerts', authorizedConsumers: { myApp: { read: true, all: true }, diff --git a/x-pack/plugins/alerts/server/alerts_client/tests/lib.ts b/x-pack/plugins/alerts/server/alerts_client/tests/lib.ts index 8f692cf548a9a..9be1e39fb3e05 100644 --- a/x-pack/plugins/alerts/server/alerts_client/tests/lib.ts +++ b/x-pack/plugins/alerts/server/alerts_client/tests/lib.ts @@ -85,6 +85,7 @@ export function getBeforeSetup( actionGroups: [{ id: 'default', name: 'Default' }], recoveryActionGroup: RecoveredActionGroup, defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', async executor() {}, producer: 'alerts', })); diff --git a/x-pack/plugins/alerts/server/alerts_client/tests/list_alert_types.test.ts b/x-pack/plugins/alerts/server/alerts_client/tests/list_alert_types.test.ts index f3521965d615d..3f7bf57cfc789 100644 --- a/x-pack/plugins/alerts/server/alerts_client/tests/list_alert_types.test.ts +++ b/x-pack/plugins/alerts/server/alerts_client/tests/list_alert_types.test.ts @@ -51,6 +51,7 @@ describe('listAlertTypes', () => { actionGroups: [], actionVariables: undefined, defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', recoveryActionGroup: RecoveredActionGroup, id: 'alertingAlertType', name: 'alertingAlertType', @@ -60,6 +61,7 @@ describe('listAlertTypes', () => { actionGroups: [], actionVariables: undefined, defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', recoveryActionGroup: RecoveredActionGroup, id: 'myAppAlertType', name: 'myAppAlertType', @@ -99,6 +101,7 @@ describe('listAlertTypes', () => { actionGroups: [], actionVariables: undefined, defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', recoveryActionGroup: RecoveredActionGroup, id: 'myType', name: 'myType', @@ -109,6 +112,7 @@ describe('listAlertTypes', () => { name: 'Test', actionGroups: [{ id: 'default', name: 'Default' }], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', recoveryActionGroup: RecoveredActionGroup, producer: 'alerts', }, @@ -124,6 +128,7 @@ describe('listAlertTypes', () => { name: 'Test', actionGroups: [{ id: 'default', name: 'Default' }], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', recoveryActionGroup: RecoveredActionGroup, producer: 'alerts', authorizedConsumers: { diff --git a/x-pack/plugins/alerts/server/alerts_client/tests/update.test.ts b/x-pack/plugins/alerts/server/alerts_client/tests/update.test.ts index 15fb1e2ec0092..b2f41d1dd4c0d 100644 --- a/x-pack/plugins/alerts/server/alerts_client/tests/update.test.ts +++ b/x-pack/plugins/alerts/server/alerts_client/tests/update.test.ts @@ -102,6 +102,7 @@ describe('update()', () => { name: 'Test', actionGroups: [{ id: 'default', name: 'Default' }], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', recoveryActionGroup: RecoveredActionGroup, async executor() {}, producer: 'alerts', @@ -682,6 +683,7 @@ describe('update()', () => { name: 'Test', actionGroups: [{ id: 'default', name: 'Default' }], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', recoveryActionGroup: RecoveredActionGroup, validate: { params: schema.object({ @@ -1028,6 +1030,7 @@ describe('update()', () => { name: 'Test', actionGroups: [{ id: 'default', name: 'Default' }], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', recoveryActionGroup: RecoveredActionGroup, async executor() {}, producer: 'alerts', diff --git a/x-pack/plugins/alerts/server/alerts_client_conflict_retries.test.ts b/x-pack/plugins/alerts/server/alerts_client_conflict_retries.test.ts index 60e733b49b041..6ba8fa40b2874 100644 --- a/x-pack/plugins/alerts/server/alerts_client_conflict_retries.test.ts +++ b/x-pack/plugins/alerts/server/alerts_client_conflict_retries.test.ts @@ -332,6 +332,7 @@ beforeEach(() => { name: 'Test', actionGroups: [{ id: 'default', name: 'Default' }], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', recoveryActionGroup: RecoveredActionGroup, async executor() {}, producer: 'alerts', @@ -342,6 +343,7 @@ beforeEach(() => { name: 'Test', actionGroups: [{ id: 'default', name: 'Default' }], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', recoveryActionGroup: RecoveredActionGroup, async executor() {}, producer: 'alerts', diff --git a/x-pack/plugins/alerts/server/authorization/alerts_authorization.test.ts b/x-pack/plugins/alerts/server/authorization/alerts_authorization.test.ts index ccc325d468c54..1914bbcb0acba 100644 --- a/x-pack/plugins/alerts/server/authorization/alerts_authorization.test.ts +++ b/x-pack/plugins/alerts/server/authorization/alerts_authorization.test.ts @@ -173,6 +173,7 @@ beforeEach(() => { name: 'My Alert Type', actionGroups: [{ id: 'default', name: 'Default' }], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', recoveryActionGroup: RecoveredActionGroup, async executor() {}, producer: 'myApp', @@ -536,6 +537,7 @@ describe('AlertsAuthorization', () => { actionGroups: [], actionVariables: undefined, defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', recoveryActionGroup: RecoveredActionGroup, id: 'myOtherAppAlertType', name: 'myOtherAppAlertType', @@ -545,6 +547,7 @@ describe('AlertsAuthorization', () => { actionGroups: [], actionVariables: undefined, defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', recoveryActionGroup: RecoveredActionGroup, id: 'myAppAlertType', name: 'myAppAlertType', @@ -554,6 +557,7 @@ describe('AlertsAuthorization', () => { actionGroups: [], actionVariables: undefined, defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', recoveryActionGroup: RecoveredActionGroup, id: 'mySecondAppAlertType', name: 'mySecondAppAlertType', @@ -829,6 +833,7 @@ describe('AlertsAuthorization', () => { actionGroups: [], actionVariables: undefined, defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', recoveryActionGroup: RecoveredActionGroup, id: 'myOtherAppAlertType', name: 'myOtherAppAlertType', @@ -838,6 +843,7 @@ describe('AlertsAuthorization', () => { actionGroups: [], actionVariables: undefined, defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', recoveryActionGroup: RecoveredActionGroup, id: 'myAppAlertType', name: 'myAppAlertType', @@ -885,6 +891,7 @@ describe('AlertsAuthorization', () => { }, "defaultActionGroupId": "default", "id": "myAppAlertType", + "minimumLicenseRequired": "basic", "name": "myAppAlertType", "producer": "myApp", "recoveryActionGroup": Object { @@ -915,6 +922,7 @@ describe('AlertsAuthorization', () => { }, "defaultActionGroupId": "default", "id": "myOtherAppAlertType", + "minimumLicenseRequired": "basic", "name": "myOtherAppAlertType", "producer": "myOtherApp", "recoveryActionGroup": Object { @@ -985,6 +993,7 @@ describe('AlertsAuthorization', () => { }, "defaultActionGroupId": "default", "id": "myOtherAppAlertType", + "minimumLicenseRequired": "basic", "name": "myOtherAppAlertType", "producer": "myOtherApp", "recoveryActionGroup": Object { @@ -1011,6 +1020,7 @@ describe('AlertsAuthorization', () => { }, "defaultActionGroupId": "default", "id": "myAppAlertType", + "minimumLicenseRequired": "basic", "name": "myAppAlertType", "producer": "myApp", "recoveryActionGroup": Object { @@ -1076,6 +1086,7 @@ describe('AlertsAuthorization', () => { }, "defaultActionGroupId": "default", "id": "myAppAlertType", + "minimumLicenseRequired": "basic", "name": "myAppAlertType", "producer": "myApp", "recoveryActionGroup": Object { @@ -1170,6 +1181,7 @@ describe('AlertsAuthorization', () => { }, "defaultActionGroupId": "default", "id": "myOtherAppAlertType", + "minimumLicenseRequired": "basic", "name": "myOtherAppAlertType", "producer": "myOtherApp", "recoveryActionGroup": Object { @@ -1196,6 +1208,7 @@ describe('AlertsAuthorization', () => { }, "defaultActionGroupId": "default", "id": "myAppAlertType", + "minimumLicenseRequired": "basic", "name": "myAppAlertType", "producer": "myApp", "recoveryActionGroup": Object { @@ -1274,6 +1287,7 @@ describe('AlertsAuthorization', () => { }, "defaultActionGroupId": "default", "id": "myOtherAppAlertType", + "minimumLicenseRequired": "basic", "name": "myOtherAppAlertType", "producer": "myOtherApp", "recoveryActionGroup": Object { diff --git a/x-pack/plugins/alerts/server/authorization/alerts_authorization_kuery.test.ts b/x-pack/plugins/alerts/server/authorization/alerts_authorization_kuery.test.ts index 4be52f12da9c7..976a9f40f8d66 100644 --- a/x-pack/plugins/alerts/server/authorization/alerts_authorization_kuery.test.ts +++ b/x-pack/plugins/alerts/server/authorization/alerts_authorization_kuery.test.ts @@ -22,6 +22,7 @@ describe('asFiltersByAlertTypeAndConsumer', () => { id: 'myAppAlertType', name: 'myAppAlertType', producer: 'myApp', + minimumLicenseRequired: 'basic', authorizedConsumers: { myApp: { read: true, all: true }, }, @@ -42,6 +43,7 @@ describe('asFiltersByAlertTypeAndConsumer', () => { { actionGroups: [], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', recoveryActionGroup: RecoveredActionGroup, id: 'myAppAlertType', name: 'myAppAlertType', @@ -68,6 +70,7 @@ describe('asFiltersByAlertTypeAndConsumer', () => { { actionGroups: [], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', recoveryActionGroup: RecoveredActionGroup, id: 'myAppAlertType', name: 'myAppAlertType', @@ -82,6 +85,7 @@ describe('asFiltersByAlertTypeAndConsumer', () => { { actionGroups: [], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', recoveryActionGroup: RecoveredActionGroup, id: 'myOtherAppAlertType', name: 'myOtherAppAlertType', @@ -96,6 +100,7 @@ describe('asFiltersByAlertTypeAndConsumer', () => { { actionGroups: [], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', recoveryActionGroup: RecoveredActionGroup, id: 'mySecondAppAlertType', name: 'mySecondAppAlertType', diff --git a/x-pack/plugins/alerts/server/lib/validate_alert_type_params.test.ts b/x-pack/plugins/alerts/server/lib/validate_alert_type_params.test.ts index 1e6c26c02e65b..2814eaef3e02a 100644 --- a/x-pack/plugins/alerts/server/lib/validate_alert_type_params.test.ts +++ b/x-pack/plugins/alerts/server/lib/validate_alert_type_params.test.ts @@ -19,6 +19,7 @@ test('should return passed in params when validation not defined', () => { }, ], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', async executor() {}, producer: 'alerts', }, @@ -41,6 +42,7 @@ test('should validate and apply defaults when params is valid', () => { }, ], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', validate: { params: schema.object({ param1: schema.string(), @@ -71,6 +73,7 @@ test('should validate and throw error when params is invalid', () => { }, ], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', validate: { params: schema.object({ param1: schema.string(), diff --git a/x-pack/plugins/alerts/server/plugin.test.ts b/x-pack/plugins/alerts/server/plugin.test.ts index fee7901c4ea55..b41e70b9d6a5a 100644 --- a/x-pack/plugins/alerts/server/plugin.test.ts +++ b/x-pack/plugins/alerts/server/plugin.test.ts @@ -4,7 +4,12 @@ * you may not use this file except in compliance with the Elastic License. */ -import { AlertingPlugin, AlertingPluginsSetup, AlertingPluginsStart } from './plugin'; +import { + AlertingPlugin, + AlertingPluginsSetup, + AlertingPluginsStart, + PluginSetupContract, +} from './plugin'; import { coreMock, statusServiceMock } from '../../../../src/core/server/mocks'; import { licensingMock } from '../../licensing/server/mocks'; import { encryptedSavedObjectsMock } from '../../encrypted_saved_objects/server/mocks'; @@ -14,9 +19,16 @@ import { KibanaRequest, CoreSetup } from 'kibana/server'; import { featuresPluginMock } from '../../features/server/mocks'; import { KibanaFeature } from '../../features/server'; import { AlertsConfig } from './config'; +import { AlertType } from './types'; +import { eventLogMock } from '../../event_log/server/mocks'; +import { actionsMock } from '../../actions/server/mocks'; describe('Alerting Plugin', () => { describe('setup()', () => { + let plugin: AlertingPlugin; + let coreSetup: ReturnType; + let pluginsSetup: jest.Mocked; + it('should log warning when Encrypted Saved Objects plugin is using an ephemeral encryption key', async () => { const context = coreMock.createPluginInitializerContext({ healthCheck: { @@ -27,9 +39,9 @@ describe('Alerting Plugin', () => { removalDelay: '5m', }, }); - const plugin = new AlertingPlugin(context); + plugin = new AlertingPlugin(context); - const coreSetup = coreMock.createSetup(); + coreSetup = coreMock.createSetup(); const encryptedSavedObjectsSetup = encryptedSavedObjectsMock.createSetup(); const statusMock = statusServiceMock.createSetupContract(); await plugin.setup( @@ -55,6 +67,56 @@ describe('Alerting Plugin', () => { 'APIs are disabled because the Encrypted Saved Objects plugin uses an ephemeral encryption key. Please set xpack.encryptedSavedObjects.encryptionKey in the kibana.yml or use the bin/kibana-encryption-keys command.' ); }); + + describe('registerType()', () => { + let setup: PluginSetupContract; + const sampleAlertType: AlertType = { + id: 'test', + name: 'test', + minimumLicenseRequired: 'basic', + actionGroups: [], + defaultActionGroupId: 'default', + producer: 'test', + async executor() {}, + }; + + beforeEach(async () => { + coreSetup = coreMock.createSetup(); + pluginsSetup = { + taskManager: taskManagerMock.createSetup(), + encryptedSavedObjects: encryptedSavedObjectsMock.createSetup(), + licensing: licensingMock.createSetup(), + eventLog: eventLogMock.createSetup(), + actions: actionsMock.createSetup(), + statusService: statusServiceMock.createSetupContract(), + }; + setup = await plugin.setup(coreSetup, pluginsSetup); + }); + + it('should throw error when license type is invalid', async () => { + expect(() => + setup.registerType({ + ...sampleAlertType, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + minimumLicenseRequired: 'foo' as any, + }) + ).toThrowErrorMatchingInlineSnapshot(`"\\"foo\\" is not a valid license type"`); + }); + + it('should not throw when license type is gold', async () => { + setup.registerType({ + ...sampleAlertType, + minimumLicenseRequired: 'gold', + }); + }); + + it('should not throw when license type is basic', async () => { + setup.registerType({ + ...sampleAlertType, + minimumLicenseRequired: 'basic', + }); + }); + }); }); describe('start()', () => { diff --git a/x-pack/plugins/alerts/server/plugin.ts b/x-pack/plugins/alerts/server/plugin.ts index bafb89c64076b..9122ca405e03e 100644 --- a/x-pack/plugins/alerts/server/plugin.ts +++ b/x-pack/plugins/alerts/server/plugin.ts @@ -54,12 +54,20 @@ import { unmuteAlertInstanceRoute, healthRoute, } from './routes'; -import { LicensingPluginSetup } from '../../licensing/server'; +import { LICENSE_TYPE, LicensingPluginSetup } from '../../licensing/server'; import { PluginSetupContract as ActionsPluginSetupContract, PluginStartContract as ActionsPluginStartContract, } from '../../actions/server'; -import { AlertsHealth, Services } from './types'; +import { + AlertInstanceContext, + AlertInstanceState, + AlertsHealth, + AlertType, + AlertTypeParams, + AlertTypeState, + Services, +} from './types'; import { registerAlertsUsageCollector } from './usage'; import { initializeAlertingTelemetry, scheduleAlertingTelemetry } from './usage/task'; import { IEventLogger, IEventLogService, IEventLogClientService } from '../../event_log/server'; @@ -90,8 +98,16 @@ export const LEGACY_EVENT_LOG_ACTIONS = { }; export interface PluginSetupContract { - registerType: AlertTypeRegistry['register']; + registerType< + Params extends AlertTypeParams = AlertTypeParams, + State extends AlertTypeState = AlertTypeState, + InstanceState extends AlertInstanceState = AlertInstanceState, + InstanceContext extends AlertInstanceContext = AlertInstanceContext + >( + alertType: AlertType + ): void; } + export interface PluginStartContract { listTypes: AlertTypeRegistry['list']; getAlertsClientWithRequest(request: KibanaRequest): PublicMethodsOf; @@ -250,7 +266,17 @@ export class AlertingPlugin { healthRoute(router, this.licenseState, plugins.encryptedSavedObjects); return { - registerType: alertTypeRegistry.register.bind(alertTypeRegistry), + registerType< + Params extends AlertTypeParams = AlertTypeParams, + State extends AlertTypeState = AlertTypeState, + InstanceState extends AlertInstanceState = AlertInstanceState, + InstanceContext extends AlertInstanceContext = AlertInstanceContext + >(alertType: AlertType) { + if (!(alertType.minimumLicenseRequired in LICENSE_TYPE)) { + throw new Error(`"${alertType.minimumLicenseRequired}" is not a valid license type`); + } + alertTypeRegistry.register(alertType); + }, }; } diff --git a/x-pack/plugins/alerts/server/routes/list_alert_types.test.ts b/x-pack/plugins/alerts/server/routes/list_alert_types.test.ts index b18c79fd67484..33c6a1d81139c 100644 --- a/x-pack/plugins/alerts/server/routes/list_alert_types.test.ts +++ b/x-pack/plugins/alerts/server/routes/list_alert_types.test.ts @@ -44,6 +44,7 @@ describe('listAlertTypesRoute', () => { }, ], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', recoveryActionGroup: RecoveredActionGroup, authorizedConsumers: {}, actionVariables: { @@ -74,6 +75,7 @@ describe('listAlertTypesRoute', () => { "authorizedConsumers": Object {}, "defaultActionGroupId": "default", "id": "1", + "minimumLicenseRequired": "basic", "name": "name", "producer": "test", "recoveryActionGroup": Object { @@ -113,6 +115,7 @@ describe('listAlertTypesRoute', () => { }, ], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', recoveryActionGroup: RecoveredActionGroup, authorizedConsumers: {}, actionVariables: { @@ -163,6 +166,7 @@ describe('listAlertTypesRoute', () => { }, ], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', recoveryActionGroup: RecoveredActionGroup, authorizedConsumers: {}, actionVariables: { diff --git a/x-pack/plugins/alerts/server/task_runner/create_execution_handler.test.ts b/x-pack/plugins/alerts/server/task_runner/create_execution_handler.test.ts index 59eca88a9ada3..634dc3c3bd03e 100644 --- a/x-pack/plugins/alerts/server/task_runner/create_execution_handler.test.ts +++ b/x-pack/plugins/alerts/server/task_runner/create_execution_handler.test.ts @@ -20,6 +20,7 @@ const alertType: AlertType = { { id: 'other-group', name: 'Other Group' }, ], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', recoveryActionGroup: { id: 'recovered', name: 'Recovered', diff --git a/x-pack/plugins/alerts/server/task_runner/task_runner.test.ts b/x-pack/plugins/alerts/server/task_runner/task_runner.test.ts index a2b281036d4cc..e1dee712a1985 100644 --- a/x-pack/plugins/alerts/server/task_runner/task_runner.test.ts +++ b/x-pack/plugins/alerts/server/task_runner/task_runner.test.ts @@ -28,15 +28,18 @@ import { IEventLogger } from '../../../event_log/server'; import { SavedObjectsErrorHelpers } from '../../../../../src/core/server'; import { Alert, RecoveredActionGroup } from '../../common'; import { omit } from 'lodash'; +import { NormalizedAlertType } from '../alert_type_registry'; const alertType = { id: 'test', name: 'My test alert', actionGroups: [{ id: 'default', name: 'Default' }, RecoveredActionGroup], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', recoveryActionGroup: RecoveredActionGroup, executor: jest.fn(), producer: 'alerts', }; + let fakeTimer: sinon.SinonFakeTimers; describe('Task Runner', () => { @@ -140,7 +143,7 @@ describe('Task Runner', () => { test('successfully executes the task', async () => { const taskRunner = new TaskRunner( - alertType, + alertType as NormalizedAlertType, { ...mockedTaskInstance, state: { @@ -226,7 +229,7 @@ describe('Task Runner', () => { } ); const taskRunner = new TaskRunner( - alertType, + alertType as NormalizedAlertType, mockedTaskInstance, taskRunnerFactoryInitializerParams ); @@ -361,7 +364,7 @@ describe('Task Runner', () => { } ); const taskRunner = new TaskRunner( - alertType, + alertType as NormalizedAlertType, mockedTaskInstance, taskRunnerFactoryInitializerParams ); @@ -528,7 +531,7 @@ describe('Task Runner', () => { } ); const taskRunner = new TaskRunner( - alertType, + alertType as NormalizedAlertType, { ...mockedTaskInstance, state: { @@ -611,7 +614,7 @@ describe('Task Runner', () => { } ); const taskRunner = new TaskRunner( - alertTypeWithCustomRecovery, + alertTypeWithCustomRecovery as NormalizedAlertType, { ...mockedTaskInstance, state: { @@ -702,7 +705,7 @@ describe('Task Runner', () => { ); const date = new Date().toISOString(); const taskRunner = new TaskRunner( - alertType, + alertType as NormalizedAlertType, { ...mockedTaskInstance, state: { @@ -831,7 +834,7 @@ describe('Task Runner', () => { param1: schema.string(), }), }, - }, + } as NormalizedAlertType, mockedTaskInstance, taskRunnerFactoryInitializerParams ); @@ -859,7 +862,7 @@ describe('Task Runner', () => { test('uses API key when provided', async () => { const taskRunner = new TaskRunner( - alertType, + alertType as NormalizedAlertType, mockedTaskInstance, taskRunnerFactoryInitializerParams ); @@ -892,7 +895,7 @@ describe('Task Runner', () => { test(`doesn't use API key when not provided`, async () => { const taskRunner = new TaskRunner( - alertType, + alertType as NormalizedAlertType, mockedTaskInstance, taskRunnerFactoryInitializerParams ); @@ -922,7 +925,7 @@ describe('Task Runner', () => { test('rescheduled the Alert if the schedule has update during a task run', async () => { const taskRunner = new TaskRunner( - alertType, + alertType as NormalizedAlertType, mockedTaskInstance, taskRunnerFactoryInitializerParams ); @@ -963,7 +966,7 @@ describe('Task Runner', () => { ); const taskRunner = new TaskRunner( - alertType, + alertType as NormalizedAlertType, mockedTaskInstance, taskRunnerFactoryInitializerParams ); @@ -1030,7 +1033,7 @@ describe('Task Runner', () => { }); const taskRunner = new TaskRunner( - alertType, + alertType as NormalizedAlertType, mockedTaskInstance, taskRunnerFactoryInitializerParams ); @@ -1089,7 +1092,7 @@ describe('Task Runner', () => { }); const taskRunner = new TaskRunner( - alertType, + alertType as NormalizedAlertType, mockedTaskInstance, taskRunnerFactoryInitializerParams ); @@ -1156,7 +1159,7 @@ describe('Task Runner', () => { }); const taskRunner = new TaskRunner( - alertType, + alertType as NormalizedAlertType, mockedTaskInstance, taskRunnerFactoryInitializerParams ); @@ -1226,7 +1229,7 @@ describe('Task Runner', () => { const legacyTaskInstance = omit(mockedTaskInstance, 'schedule'); const taskRunner = new TaskRunner( - alertType, + alertType as NormalizedAlertType, legacyTaskInstance, taskRunnerFactoryInitializerParams ); @@ -1264,7 +1267,7 @@ describe('Task Runner', () => { ); const taskRunner = new TaskRunner( - alertType, + alertType as NormalizedAlertType, { ...mockedTaskInstance, state: originalAlertSate, @@ -1295,7 +1298,7 @@ describe('Task Runner', () => { }); const taskRunner = new TaskRunner( - alertType, + alertType as NormalizedAlertType, mockedTaskInstance, taskRunnerFactoryInitializerParams ); diff --git a/x-pack/plugins/alerts/server/task_runner/task_runner_factory.test.ts b/x-pack/plugins/alerts/server/task_runner/task_runner_factory.test.ts index 4c685d2fdec82..f58939440212e 100644 --- a/x-pack/plugins/alerts/server/task_runner/task_runner_factory.test.ts +++ b/x-pack/plugins/alerts/server/task_runner/task_runner_factory.test.ts @@ -16,12 +16,14 @@ import { import { actionsMock } from '../../../actions/server/mocks'; import { alertsMock, alertsClientMock } from '../mocks'; import { eventLoggerMock } from '../../../event_log/server/event_logger.mock'; +import { NormalizedAlertType } from '../alert_type_registry'; -const alertType = { +const alertType: NormalizedAlertType = { id: 'test', name: 'My test alert', actionGroups: [{ id: 'default', name: 'Default' }], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', recoveryActionGroup: { id: 'recovered', name: 'Recovered', diff --git a/x-pack/plugins/alerts/server/types.ts b/x-pack/plugins/alerts/server/types.ts index 7847b6f6249a8..b11352e2e3b7a 100644 --- a/x-pack/plugins/alerts/server/types.ts +++ b/x-pack/plugins/alerts/server/types.ts @@ -29,6 +29,7 @@ import { AlertExecutionStatusErrorReasons, AlertsHealth, } from '../common'; +import { LicenseType } from '../../licensing/server'; export type WithoutQueryAndParams = Pick>; export type GetServicesFunction = (request: KibanaRequest) => Services; @@ -83,6 +84,16 @@ export interface ActionVariable { description: string; } +// signature of the alert type executor function +export type ExecutorType< + Params, + State, + InstanceState extends AlertInstanceState = AlertInstanceState, + InstanceContext extends AlertInstanceContext = AlertInstanceContext +> = ( + options: AlertExecutorOptions +) => Promise; + export interface AlertType< Params extends AlertTypeParams = AlertTypeParams, State extends AlertTypeState = AlertTypeState, @@ -97,17 +108,14 @@ export interface AlertType< actionGroups: ActionGroup[]; defaultActionGroupId: ActionGroup['id']; recoveryActionGroup?: ActionGroup; - executor: ({ - services, - params, - state, - }: AlertExecutorOptions) => Promise; + executor: ExecutorType; producer: string; actionVariables?: { context?: ActionVariable[]; state?: ActionVariable[]; params?: ActionVariable[]; }; + minimumLicenseRequired: LicenseType; } export interface RawAlertAction extends SavedObjectAttributes { diff --git a/x-pack/plugins/apm/common/alert_types.ts b/x-pack/plugins/apm/common/alert_types.ts index a234226d18034..7cc36253ef581 100644 --- a/x-pack/plugins/apm/common/alert_types.ts +++ b/x-pack/plugins/apm/common/alert_types.ts @@ -29,6 +29,7 @@ export const ALERT_TYPES_CONFIG = { }), actionGroups: [THRESHOLD_MET_GROUP], defaultActionGroupId: 'threshold_met', + minimumLicenseRequired: 'basic', producer: 'apm', }, [AlertType.TransactionDuration]: { @@ -37,6 +38,7 @@ export const ALERT_TYPES_CONFIG = { }), actionGroups: [THRESHOLD_MET_GROUP], defaultActionGroupId: 'threshold_met', + minimumLicenseRequired: 'basic', producer: 'apm', }, [AlertType.TransactionDurationAnomaly]: { @@ -45,6 +47,7 @@ export const ALERT_TYPES_CONFIG = { }), actionGroups: [THRESHOLD_MET_GROUP], defaultActionGroupId: 'threshold_met', + minimumLicenseRequired: 'basic', producer: 'apm', }, [AlertType.TransactionErrorRate]: { @@ -53,6 +56,7 @@ export const ALERT_TYPES_CONFIG = { }), actionGroups: [THRESHOLD_MET_GROUP], defaultActionGroupId: 'threshold_met', + minimumLicenseRequired: 'basic', producer: 'apm', }, }; diff --git a/x-pack/plugins/apm/server/lib/alerts/register_error_count_alert_type.ts b/x-pack/plugins/apm/server/lib/alerts/register_error_count_alert_type.ts index 124f61ed031fe..36fdf45d805f1 100644 --- a/x-pack/plugins/apm/server/lib/alerts/register_error_count_alert_type.ts +++ b/x-pack/plugins/apm/server/lib/alerts/register_error_count_alert_type.ts @@ -59,6 +59,7 @@ export function registerErrorCountAlertType({ ], }, producer: 'apm', + minimumLicenseRequired: 'basic', executor: async ({ services, params }) => { const config = await config$.pipe(take(1)).toPromise(); const alertParams = params; diff --git a/x-pack/plugins/apm/server/lib/alerts/register_transaction_duration_alert_type.ts b/x-pack/plugins/apm/server/lib/alerts/register_transaction_duration_alert_type.ts index cad5f5f8b9b56..48fc0899f029c 100644 --- a/x-pack/plugins/apm/server/lib/alerts/register_transaction_duration_alert_type.ts +++ b/x-pack/plugins/apm/server/lib/alerts/register_transaction_duration_alert_type.ts @@ -68,6 +68,7 @@ export function registerTransactionDurationAlertType({ ], }, producer: 'apm', + minimumLicenseRequired: 'basic', executor: async ({ services, params }) => { const config = await config$.pipe(take(1)).toPromise(); const alertParams = params; diff --git a/x-pack/plugins/apm/server/lib/alerts/register_transaction_duration_anomaly_alert_type.ts b/x-pack/plugins/apm/server/lib/alerts/register_transaction_duration_anomaly_alert_type.ts index b9e970ace869d..f3df0092dbbbd 100644 --- a/x-pack/plugins/apm/server/lib/alerts/register_transaction_duration_anomaly_alert_type.ts +++ b/x-pack/plugins/apm/server/lib/alerts/register_transaction_duration_anomaly_alert_type.ts @@ -67,6 +67,7 @@ export function registerTransactionDurationAnomalyAlertType({ ], }, producer: 'apm', + minimumLicenseRequired: 'basic', executor: async ({ services, params, state }) => { if (!ml) { return; diff --git a/x-pack/plugins/apm/server/lib/alerts/register_transaction_error_rate_alert_type.ts b/x-pack/plugins/apm/server/lib/alerts/register_transaction_error_rate_alert_type.ts index 2753b378754f8..766705e2803b1 100644 --- a/x-pack/plugins/apm/server/lib/alerts/register_transaction_error_rate_alert_type.ts +++ b/x-pack/plugins/apm/server/lib/alerts/register_transaction_error_rate_alert_type.ts @@ -65,6 +65,7 @@ export function registerTransactionErrorRateAlertType({ ], }, producer: 'apm', + minimumLicenseRequired: 'basic', executor: async ({ services, params: alertParams }) => { const config = await config$.pipe(take(1)).toPromise(); const indices = await getApmIndices({ diff --git a/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/register_inventory_metric_threshold_alert_type.ts b/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/register_inventory_metric_threshold_alert_type.ts index 14d1acf0e4a9f..6ec6210ecb344 100644 --- a/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/register_inventory_metric_threshold_alert_type.ts +++ b/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/register_inventory_metric_threshold_alert_type.ts @@ -4,6 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ import { schema } from '@kbn/config-schema'; +import { AlertType } from '../../../../../alerts/server'; import { createInventoryMetricThresholdExecutor, FIRED_ACTIONS, @@ -38,7 +39,7 @@ const condition = schema.object({ ), }); -export const registerMetricInventoryThresholdAlertType = (libs: InfraBackendLibs) => ({ +export const registerMetricInventoryThresholdAlertType = (libs: InfraBackendLibs): AlertType => ({ id: METRIC_INVENTORY_THRESHOLD_ALERT_TYPE_ID, name: 'Inventory', validate: { @@ -58,6 +59,7 @@ export const registerMetricInventoryThresholdAlertType = (libs: InfraBackendLibs defaultActionGroupId: FIRED_ACTIONS.id, actionGroups: [FIRED_ACTIONS], producer: 'infrastructure', + minimumLicenseRequired: 'basic', executor: createInventoryMetricThresholdExecutor(libs), actionVariables: { context: [ diff --git a/x-pack/plugins/infra/server/lib/alerting/log_threshold/register_log_threshold_alert_type.ts b/x-pack/plugins/infra/server/lib/alerting/log_threshold/register_log_threshold_alert_type.ts index 34afddc2a4d48..64bfad92a8458 100644 --- a/x-pack/plugins/infra/server/lib/alerting/log_threshold/register_log_threshold_alert_type.ts +++ b/x-pack/plugins/infra/server/lib/alerting/log_threshold/register_log_threshold_alert_type.ts @@ -89,6 +89,7 @@ export async function registerLogThresholdAlertType( }, defaultActionGroupId: FIRED_ACTIONS.id, actionGroups: [FIRED_ACTIONS], + minimumLicenseRequired: 'basic', executor: createLogThresholdExecutor(libs), actionVariables: { context: [ diff --git a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/register_metric_threshold_alert_type.ts b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/register_metric_threshold_alert_type.ts index 45b1df2f03ea1..1a10765eaf734 100644 --- a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/register_metric_threshold_alert_type.ts +++ b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/register_metric_threshold_alert_type.ts @@ -4,6 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ import { schema } from '@kbn/config-schema'; +import { AlertType } from '../../../../../alerts/server'; import { METRIC_EXPLORER_AGGREGATIONS } from '../../../../common/http_api/metrics_explorer'; import { createMetricThresholdExecutor, FIRED_ACTIONS } from './metric_threshold_executor'; import { METRIC_THRESHOLD_ALERT_TYPE_ID, Comparator } from './types'; @@ -19,7 +20,7 @@ import { thresholdActionVariableDescription, } from '../common/messages'; -export function registerMetricThresholdAlertType(libs: InfraBackendLibs) { +export function registerMetricThresholdAlertType(libs: InfraBackendLibs): AlertType { const baseCriterion = { threshold: schema.arrayOf(schema.number()), comparator: oneOfLiterals(Object.values(Comparator)), @@ -60,6 +61,7 @@ export function registerMetricThresholdAlertType(libs: InfraBackendLibs) { }, defaultActionGroupId: FIRED_ACTIONS.id, actionGroups: [FIRED_ACTIONS], + minimumLicenseRequired: 'basic', executor: createMetricThresholdExecutor(libs), actionVariables: { context: [ diff --git a/x-pack/plugins/monitoring/server/alerts/base_alert.ts b/x-pack/plugins/monitoring/server/alerts/base_alert.ts index b345689bdc504..225171e31787f 100644 --- a/x-pack/plugins/monitoring/server/alerts/base_alert.ts +++ b/x-pack/plugins/monitoring/server/alerts/base_alert.ts @@ -106,6 +106,7 @@ export class BaseAlert { }, ], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', executor: (options: AlertExecutorOptions & { state: ExecutedState }): Promise => this.execute(options), producer: 'monitoring', diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/rules_notification_alert_type.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/rules_notification_alert_type.ts index 802b9472a4487..088cc417cf28e 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/rules_notification_alert_type.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/rules_notification_alert_type.ts @@ -31,6 +31,7 @@ export const rulesNotificationAlertType = ({ ruleAlertId: schema.string(), }), }, + minimumLicenseRequired: 'basic', async executor({ startedAt, previousStartedAt, alertId, services, params }) { const ruleAlertSavedObject = await services.savedObjectsClient.get( 'alert', diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/signal_rule_alert_type.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/signal_rule_alert_type.ts index d6bdc14a92b40..91c5a8c3ecf6c 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/signal_rule_alert_type.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/signal_rule_alert_type.ts @@ -90,6 +90,7 @@ export const signalRulesAlertType = ({ params: signalParamsSchema(), }, producer: SERVER_APP_ID, + minimumLicenseRequired: 'basic', async executor({ previousStartedAt, startedAt, diff --git a/x-pack/plugins/stack_alerts/server/alert_types/geo_containment/alert_type.ts b/x-pack/plugins/stack_alerts/server/alert_types/geo_containment/alert_type.ts index a873cab69f23b..164ce993eebac 100644 --- a/x-pack/plugins/stack_alerts/server/alert_types/geo_containment/alert_type.ts +++ b/x-pack/plugins/stack_alerts/server/alert_types/geo_containment/alert_type.ts @@ -9,12 +9,7 @@ import { schema } from '@kbn/config-schema'; import { Logger } from 'src/core/server'; import { STACK_ALERTS_FEATURE_ID } from '../../../common'; import { getGeoContainmentExecutor } from './geo_containment'; -import { - ActionGroup, - AlertServices, - ActionVariable, - AlertTypeState, -} from '../../../../alerts/server'; +import { AlertType } from '../../../../alerts/server'; import { Query } from '../../../../../../src/plugins/data/common/query'; export const GEO_CONTAINMENT_ID = '.geo-containment'; @@ -117,40 +112,7 @@ export interface GeoContainmentParams { boundaryIndexQuery?: Query; } -export function getAlertType( - logger: Logger -): { - defaultActionGroupId: string; - actionGroups: ActionGroup[]; - executor: ({ - previousStartedAt: currIntervalStartTime, - startedAt: currIntervalEndTime, - services, - params, - alertId, - state, - }: { - previousStartedAt: Date | null; - startedAt: Date; - services: AlertServices; - params: GeoContainmentParams; - alertId: string; - state: AlertTypeState; - }) => Promise; - validate?: { - params?: { - validate: (object: unknown) => GeoContainmentParams; - }; - }; - name: string; - producer: string; - id: string; - actionVariables?: { - context?: ActionVariable[]; - state?: ActionVariable[]; - params?: ActionVariable[]; - }; -} { +export function getAlertType(logger: Logger): AlertType { const alertTypeName = i18n.translate('xpack.stackAlerts.geoContainment.alertTypeTitle', { defaultMessage: 'Geo tracking containment', }); @@ -173,5 +135,6 @@ export function getAlertType( params: ParamsSchema, }, actionVariables, + minimumLicenseRequired: 'gold', }; } diff --git a/x-pack/plugins/stack_alerts/server/alert_types/geo_containment/index.ts b/x-pack/plugins/stack_alerts/server/alert_types/geo_containment/index.ts index 2fa2bed9d8419..02116d0701bfa 100644 --- a/x-pack/plugins/stack_alerts/server/alert_types/geo_containment/index.ts +++ b/x-pack/plugins/stack_alerts/server/alert_types/geo_containment/index.ts @@ -6,7 +6,7 @@ import { Logger } from 'src/core/server'; import { AlertingSetup } from '../../types'; -import { getAlertType } from './alert_type'; +import { GeoContainmentParams, getAlertType } from './alert_type'; interface RegisterParams { logger: Logger; @@ -15,5 +15,5 @@ interface RegisterParams { export function register(params: RegisterParams) { const { logger, alerts } = params; - alerts.registerType(getAlertType(logger)); + alerts.registerType(getAlertType(logger)); } diff --git a/x-pack/plugins/stack_alerts/server/alert_types/geo_threshold/alert_type.ts b/x-pack/plugins/stack_alerts/server/alert_types/geo_threshold/alert_type.ts index 0c40f5b5f3866..93a6c0d29cf3c 100644 --- a/x-pack/plugins/stack_alerts/server/alert_types/geo_threshold/alert_type.ts +++ b/x-pack/plugins/stack_alerts/server/alert_types/geo_threshold/alert_type.ts @@ -9,12 +9,7 @@ import { schema } from '@kbn/config-schema'; import { Logger } from 'src/core/server'; import { STACK_ALERTS_FEATURE_ID } from '../../../common'; import { getGeoThresholdExecutor } from './geo_threshold'; -import { - ActionGroup, - AlertServices, - ActionVariable, - AlertTypeState, -} from '../../../../alerts/server'; +import { AlertType } from '../../../../alerts/server'; import { Query } from '../../../../../../src/plugins/data/common/query'; export const GEO_THRESHOLD_ID = '.geo-threshold'; @@ -177,40 +172,7 @@ export interface GeoThresholdParams { boundaryIndexQuery?: Query; } -export function getAlertType( - logger: Logger -): { - defaultActionGroupId: string; - actionGroups: ActionGroup[]; - executor: ({ - previousStartedAt: currIntervalStartTime, - startedAt: currIntervalEndTime, - services, - params, - alertId, - state, - }: { - previousStartedAt: Date | null; - startedAt: Date; - services: AlertServices; - params: GeoThresholdParams; - alertId: string; - state: AlertTypeState; - }) => Promise; - validate?: { - params?: { - validate: (object: unknown) => GeoThresholdParams; - }; - }; - name: string; - producer: string; - id: string; - actionVariables?: { - context?: ActionVariable[]; - state?: ActionVariable[]; - params?: ActionVariable[]; - }; -} { +export function getAlertType(logger: Logger): AlertType { const alertTypeName = i18n.translate('xpack.stackAlerts.geoThreshold.alertTypeTitle', { defaultMessage: 'Geo tracking threshold', }); @@ -233,5 +195,6 @@ export function getAlertType( params: ParamsSchema, }, actionVariables, + minimumLicenseRequired: 'gold', }; } diff --git a/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/alert_type.ts b/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/alert_type.ts index 9de0940771525..9600395c78218 100644 --- a/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/alert_type.ts +++ b/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/alert_type.ts @@ -143,6 +143,7 @@ export function getAlertType( ...alertParamsVariables, ], }, + minimumLicenseRequired: 'basic', executor, producer: STACK_ALERTS_FEATURE_ID, }; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/action_variables.test.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/action_variables.test.ts index daf51dcd43812..474f8655c5150 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/action_variables.test.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/action_variables.test.ts @@ -321,5 +321,6 @@ function getAlertType(actionVariables: ActionVariables): AlertType { recoveryActionGroup: { id: 'recovered', name: 'Recovered' }, authorizedConsumers: {}, producer: ALERTS_FEATURE_ID, + minimumLicenseRequired: 'basic', }; } diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/alert_api.test.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/alert_api.test.ts index e1011e2fe69b9..ed452a77e5ab1 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/alert_api.test.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/alert_api.test.ts @@ -51,6 +51,7 @@ describe('loadAlertTypes', () => { recoveryActionGroup: { id: 'recovered', name: 'Recovered' }, defaultActionGroupId: 'default', authorizedConsumers: {}, + minimumLicenseRequired: 'basic', }, ]; http.get.mockResolvedValueOnce(resolvedValue); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_details/components/alert_details.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_details/components/alert_details.test.tsx index b19b6eb5f7a3e..d2d4efc5973c0 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_details/components/alert_details.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_details/components/alert_details.test.tsx @@ -7,7 +7,7 @@ import * as React from 'react'; import uuid from 'uuid'; import { shallow } from 'enzyme'; import { AlertDetails } from './alert_details'; -import { Alert, ActionType, AlertTypeModel } from '../../../../types'; +import { Alert, ActionType, AlertTypeModel, AlertType } from '../../../../types'; import { EuiTitle, EuiBadge, EuiFlexItem, EuiSwitch, EuiButtonEmpty, EuiText } from '@elastic/eui'; import { ViewInApp } from './view_in_app'; import { @@ -54,13 +54,14 @@ describe('alert_details', () => { it('renders the alert name as a title', () => { const alert = mockAlert(); - const alertType = { + const alertType: AlertType = { id: '.noop', name: 'No Op', actionGroups: [{ id: 'default', name: 'Default' }], recoveryActionGroup, actionVariables: { context: [], state: [], params: [] }, defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', producer: ALERTS_FEATURE_ID, authorizedConsumers, }; @@ -80,13 +81,14 @@ describe('alert_details', () => { it('renders the alert type badge', () => { const alert = mockAlert(); - const alertType = { + const alertType: AlertType = { id: '.noop', name: 'No Op', actionGroups: [{ id: 'default', name: 'Default' }], recoveryActionGroup, actionVariables: { context: [], state: [], params: [] }, defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', producer: ALERTS_FEATURE_ID, authorizedConsumers, }; @@ -109,13 +111,14 @@ describe('alert_details', () => { }, }, }); - const alertType = { + const alertType: AlertType = { id: '.noop', name: 'No Op', actionGroups: [{ id: 'default', name: 'Default' }], recoveryActionGroup, actionVariables: { context: [], state: [], params: [] }, defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', producer: ALERTS_FEATURE_ID, authorizedConsumers, }; @@ -144,13 +147,14 @@ describe('alert_details', () => { ], }); - const alertType = { + const alertType: AlertType = { id: '.noop', name: 'No Op', actionGroups: [{ id: 'default', name: 'Default' }], recoveryActionGroup, actionVariables: { context: [], state: [], params: [] }, defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', producer: ALERTS_FEATURE_ID, authorizedConsumers, }; @@ -199,7 +203,7 @@ describe('alert_details', () => { }, ], }); - const alertType = { + const alertType: AlertType = { id: '.noop', name: 'No Op', actionGroups: [{ id: 'default', name: 'Default' }], @@ -207,6 +211,7 @@ describe('alert_details', () => { actionVariables: { context: [], state: [], params: [] }, defaultActionGroupId: 'default', producer: ALERTS_FEATURE_ID, + minimumLicenseRequired: 'basic', authorizedConsumers, }; const actionTypes: ActionType[] = [ @@ -259,7 +264,7 @@ describe('alert_details', () => { it('links to the app that created the alert', () => { const alert = mockAlert(); - const alertType = { + const alertType: AlertType = { id: '.noop', name: 'No Op', actionGroups: [{ id: 'default', name: 'Default' }], @@ -268,6 +273,7 @@ describe('alert_details', () => { defaultActionGroupId: 'default', producer: ALERTS_FEATURE_ID, authorizedConsumers, + minimumLicenseRequired: 'basic', }; expect( @@ -280,7 +286,7 @@ describe('alert_details', () => { it('links to the Edit flyout', () => { const alert = mockAlert(); - const alertType = { + const alertType: AlertType = { id: '.noop', name: 'No Op', actionGroups: [{ id: 'default', name: 'Default' }], @@ -289,6 +295,7 @@ describe('alert_details', () => { defaultActionGroupId: 'default', producer: ALERTS_FEATURE_ID, authorizedConsumers, + minimumLicenseRequired: 'basic', }; expect( @@ -310,7 +317,7 @@ describe('disable button', () => { enabled: true, }); - const alertType = { + const alertType: AlertType = { id: '.noop', name: 'No Op', actionGroups: [{ id: 'default', name: 'Default' }], @@ -319,6 +326,7 @@ describe('disable button', () => { defaultActionGroupId: 'default', producer: ALERTS_FEATURE_ID, authorizedConsumers, + minimumLicenseRequired: 'basic', }; const enableButton = shallow( @@ -339,7 +347,7 @@ describe('disable button', () => { enabled: false, }); - const alertType = { + const alertType: AlertType = { id: '.noop', name: 'No Op', actionGroups: [{ id: 'default', name: 'Default' }], @@ -348,6 +356,7 @@ describe('disable button', () => { defaultActionGroupId: 'default', producer: ALERTS_FEATURE_ID, authorizedConsumers, + minimumLicenseRequired: 'basic', }; const enableButton = shallow( @@ -368,7 +377,7 @@ describe('disable button', () => { enabled: true, }); - const alertType = { + const alertType: AlertType = { id: '.noop', name: 'No Op', actionGroups: [{ id: 'default', name: 'Default' }], @@ -377,6 +386,7 @@ describe('disable button', () => { defaultActionGroupId: 'default', producer: ALERTS_FEATURE_ID, authorizedConsumers, + minimumLicenseRequired: 'basic', }; const disableAlert = jest.fn(); @@ -406,7 +416,7 @@ describe('disable button', () => { enabled: false, }); - const alertType = { + const alertType: AlertType = { id: '.noop', name: 'No Op', actionGroups: [{ id: 'default', name: 'Default' }], @@ -415,6 +425,7 @@ describe('disable button', () => { defaultActionGroupId: 'default', producer: ALERTS_FEATURE_ID, authorizedConsumers, + minimumLicenseRequired: 'basic', }; const enableAlert = jest.fn(); @@ -447,7 +458,7 @@ describe('mute button', () => { muteAll: false, }); - const alertType = { + const alertType: AlertType = { id: '.noop', name: 'No Op', actionGroups: [{ id: 'default', name: 'Default' }], @@ -456,6 +467,7 @@ describe('mute button', () => { defaultActionGroupId: 'default', producer: ALERTS_FEATURE_ID, authorizedConsumers, + minimumLicenseRequired: 'basic', }; const enableButton = shallow( @@ -477,7 +489,7 @@ describe('mute button', () => { muteAll: true, }); - const alertType = { + const alertType: AlertType = { id: '.noop', name: 'No Op', actionGroups: [{ id: 'default', name: 'Default' }], @@ -486,6 +498,7 @@ describe('mute button', () => { defaultActionGroupId: 'default', producer: ALERTS_FEATURE_ID, authorizedConsumers, + minimumLicenseRequired: 'basic', }; const enableButton = shallow( @@ -507,7 +520,7 @@ describe('mute button', () => { muteAll: false, }); - const alertType = { + const alertType: AlertType = { id: '.noop', name: 'No Op', actionGroups: [{ id: 'default', name: 'Default' }], @@ -516,6 +529,7 @@ describe('mute button', () => { defaultActionGroupId: 'default', producer: ALERTS_FEATURE_ID, authorizedConsumers, + minimumLicenseRequired: 'basic', }; const muteAlert = jest.fn(); @@ -546,7 +560,7 @@ describe('mute button', () => { muteAll: true, }); - const alertType = { + const alertType: AlertType = { id: '.noop', name: 'No Op', actionGroups: [{ id: 'default', name: 'Default' }], @@ -555,6 +569,7 @@ describe('mute button', () => { defaultActionGroupId: 'default', producer: ALERTS_FEATURE_ID, authorizedConsumers, + minimumLicenseRequired: 'basic', }; const unmuteAlert = jest.fn(); @@ -585,7 +600,7 @@ describe('mute button', () => { muteAll: false, }); - const alertType = { + const alertType: AlertType = { id: '.noop', name: 'No Op', actionGroups: [{ id: 'default', name: 'Default' }], @@ -594,6 +609,7 @@ describe('mute button', () => { defaultActionGroupId: 'default', producer: ALERTS_FEATURE_ID, authorizedConsumers, + minimumLicenseRequired: 'basic', }; const enableButton = shallow( @@ -622,7 +638,7 @@ describe('edit button', () => { }, ]; alertTypeRegistry.has.mockReturnValue(true); - const alertTypeR = ({ + const alertTypeR: AlertTypeModel = { id: 'my-alert-type', iconClass: 'test', name: 'test-alert', @@ -631,9 +647,9 @@ describe('edit button', () => { validate: () => { return { errors: {} }; }, - alertParamsExpression: () => {}, + alertParamsExpression: jest.fn(), requiresAppContext: false, - } as unknown) as AlertTypeModel; + }; alertTypeRegistry.get.mockReturnValue(alertTypeR); useKibanaMock().services.alertTypeRegistry = alertTypeRegistry; @@ -651,7 +667,7 @@ describe('edit button', () => { ], }); - const alertType = { + const alertType: AlertType = { id: '.noop', name: 'No Op', actionGroups: [{ id: 'default', name: 'Default' }], @@ -660,6 +676,7 @@ describe('edit button', () => { defaultActionGroupId: 'default', producer: 'alerting', authorizedConsumers, + minimumLicenseRequired: 'basic', }; expect( @@ -694,7 +711,7 @@ describe('edit button', () => { ], }); - const alertType = { + const alertType: AlertType = { id: '.noop', name: 'No Op', actionGroups: [{ id: 'default', name: 'Default' }], @@ -703,6 +720,7 @@ describe('edit button', () => { defaultActionGroupId: 'default', producer: 'alerting', authorizedConsumers, + minimumLicenseRequired: 'basic', }; expect( @@ -730,7 +748,7 @@ describe('edit button', () => { actions: [], }); - const alertType = { + const alertType: AlertType = { id: '.noop', name: 'No Op', actionGroups: [{ id: 'default', name: 'Default' }], @@ -739,6 +757,7 @@ describe('edit button', () => { defaultActionGroupId: 'default', producer: 'alerting', authorizedConsumers, + minimumLicenseRequired: 'basic', }; expect( diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_details/components/alert_instances.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_details/components/alert_instances.test.tsx index f7b00a2ccf0b9..e4708fb82a4b5 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_details/components/alert_instances.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_details/components/alert_instances.test.tsx @@ -310,6 +310,7 @@ function mockAlertType(overloads: Partial = {}): AlertType { recoveryActionGroup: { id: 'recovered', name: 'Recovered' }, authorizedConsumers: {}, producer: 'alerts', + minimumLicenseRequired: 'basic', ...overloads, }; } diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_details/components/alert_instances_route.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_details/components/alert_instances_route.test.tsx index 24e20c5d477f7..42a796a086c6c 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_details/components/alert_instances_route.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_details/components/alert_instances_route.test.tsx @@ -150,6 +150,7 @@ function mockAlertType(overloads: Partial = {}): AlertType { recoveryActionGroup: { id: 'recovered', name: 'Recovered' }, authorizedConsumers: {}, producer: 'alerts', + minimumLicenseRequired: 'basic', ...overloads, }; } diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/alert_add.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/alert_add.test.tsx index 117abddb4d9d7..e068b1274b89a 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/alert_add.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/alert_add.test.tsx @@ -56,6 +56,7 @@ describe('alert_add', () => { }, ], defaultActionGroupId: 'testActionGroup', + minimumLicenseRequired: 'basic', recoveryActionGroup: { id: 'recovered', name: 'Recovered' }, producer: ALERTS_FEATURE_ID, authorizedConsumers: { diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/alert_form.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/alert_form.test.tsx index 785eaeb9059d7..9222130a7fe3e 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/alert_form.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/alert_form.test.tsx @@ -82,6 +82,7 @@ describe('alert_form', () => { }, ], defaultActionGroupId: 'testActionGroup', + minimumLicenseRequired: 'basic', recoveryActionGroup: RecoveredActionGroup, producer: ALERTS_FEATURE_ID, authorizedConsumers: { @@ -204,6 +205,7 @@ describe('alert_form', () => { }, ], defaultActionGroupId: 'testActionGroup', + minimumLicenseRequired: 'basic', recoveryActionGroup: RecoveredActionGroup, producer: ALERTS_FEATURE_ID, authorizedConsumers: { @@ -221,6 +223,7 @@ describe('alert_form', () => { }, ], defaultActionGroupId: 'testActionGroup', + minimumLicenseRequired: 'basic', recoveryActionGroup: RecoveredActionGroup, producer: 'test', authorizedConsumers: { diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_list/components/alerts_list.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_list/components/alerts_list.test.tsx index cb4d6d8097463..a576d811e9f8d 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_list/components/alerts_list.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_list/components/alerts_list.test.tsx @@ -60,6 +60,7 @@ const alertTypeFromApi = { actionVariables: { context: [], state: [] }, defaultActionGroupId: 'default', producer: ALERTS_FEATURE_ID, + minimumLicenseRequired: 'basic', authorizedConsumers: { [ALERTS_FEATURE_ID]: { read: true, all: true }, }, diff --git a/x-pack/plugins/triggers_actions_ui/public/types.ts b/x-pack/plugins/triggers_actions_ui/public/types.ts index acd242eed17fe..4c2de6ca26a4f 100644 --- a/x-pack/plugins/triggers_actions_ui/public/types.ts +++ b/x-pack/plugins/triggers_actions_ui/public/types.ts @@ -11,6 +11,7 @@ import { DataPublicPluginStart } from 'src/plugins/data/public'; import { ActionGroup, AlertActionParam } from '../../alerts/common'; import { ActionType } from '../../actions/common'; import { TypeRegistry } from './application/type_registry'; +import { AlertType as CommonAlertType } from '../../alerts/common'; import { SanitizedAlert as Alert, AlertAction, @@ -138,15 +139,19 @@ export const OPTIONAL_ACTION_VARIABLES = ['context'] as const; export type ActionVariables = AsActionVariables & Partial>; -export interface AlertType { - id: string; - name: string; - actionGroups: ActionGroup[]; - recoveryActionGroup: ActionGroup; +export interface AlertType + extends Pick< + CommonAlertType, + | 'id' + | 'name' + | 'actionGroups' + | 'producer' + | 'minimumLicenseRequired' + | 'recoveryActionGroup' + | 'defaultActionGroupId' + > { actionVariables: ActionVariables; - defaultActionGroupId: ActionGroup['id']; authorizedConsumers: Record; - producer: string; } export type SanitizedAlertType = Omit; diff --git a/x-pack/plugins/uptime/server/lib/alerts/duration_anomaly.ts b/x-pack/plugins/uptime/server/lib/alerts/duration_anomaly.ts index 022ec48bad1d9..f5e79ad43336b 100644 --- a/x-pack/plugins/uptime/server/lib/alerts/duration_anomaly.ts +++ b/x-pack/plugins/uptime/server/lib/alerts/duration_anomaly.ts @@ -82,6 +82,7 @@ export const durationAnomalyAlertFactory: UptimeAlertTypeFactory = (_server, _li context: [], state: [...durationAnomalyTranslations.actionVariables, ...commonStateTranslations], }, + minimumLicenseRequired: 'basic', async executor({ options, uptimeEsClient, savedObjectsClient, dynamicSettings }) { const { services: { alertInstanceFactory }, diff --git a/x-pack/plugins/uptime/server/lib/alerts/status_check.ts b/x-pack/plugins/uptime/server/lib/alerts/status_check.ts index 3e45ce302bf87..56ca7a85784c5 100644 --- a/x-pack/plugins/uptime/server/lib/alerts/status_check.ts +++ b/x-pack/plugins/uptime/server/lib/alerts/status_check.ts @@ -255,6 +255,7 @@ export const statusCheckAlertFactory: UptimeAlertTypeFactory = (_server, libs) = ], state: [...commonMonitorStateI18, ...commonStateTranslations], }, + minimumLicenseRequired: 'basic', async executor({ options: { params: rawParams, diff --git a/x-pack/plugins/uptime/server/lib/alerts/tls.ts b/x-pack/plugins/uptime/server/lib/alerts/tls.ts index 41a5101716122..b6501f7d92059 100644 --- a/x-pack/plugins/uptime/server/lib/alerts/tls.ts +++ b/x-pack/plugins/uptime/server/lib/alerts/tls.ts @@ -100,6 +100,7 @@ export const tlsAlertFactory: UptimeAlertTypeFactory = (_server, libs) => context: [], state: [...tlsTranslations.actionVariables, ...commonStateTranslations], }, + minimumLicenseRequired: 'basic', async executor({ options, dynamicSettings, uptimeEsClient }) { const { services: { alertInstanceFactory }, diff --git a/x-pack/test/alerting_api_integration/common/fixtures/plugins/alerts/server/alert_types.ts b/x-pack/test/alerting_api_integration/common/fixtures/plugins/alerts/server/alert_types.ts index 998ec6ab2ed0e..f4928d5fc60d3 100644 --- a/x-pack/test/alerting_api_integration/common/fixtures/plugins/alerts/server/alert_types.ts +++ b/x-pack/test/alerting_api_integration/common/fixtures/plugins/alerts/server/alert_types.ts @@ -6,7 +6,7 @@ import { CoreSetup } from 'src/core/server'; import { schema, TypeOf } from '@kbn/config-schema'; -import { times } from 'lodash'; +import { curry, times } from 'lodash'; import { ES_TEST_INDEX_NAME } from '../../../../lib'; import { FixtureStartDeps, FixtureSetupDeps } from './plugin'; import { @@ -43,58 +43,61 @@ function getAlwaysFiringAlertType() { }, producer: 'alertsFixture', defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', actionVariables: { state: [{ name: 'instanceStateValue', description: 'the instance state value' }], params: [{ name: 'instanceParamsValue', description: 'the instance params value' }], context: [{ name: 'instanceContextValue', description: 'the instance context value' }], }, - async executor(alertExecutorOptions) { - const { - services, - params, - state, - alertId, - spaceId, - namespace, - name, - tags, - createdBy, - updatedBy, - } = alertExecutorOptions; - let group: string | null = 'default'; - const alertInfo = { alertId, spaceId, namespace, name, tags, createdBy, updatedBy }; + executor: curry(alwaysFiringExecutor)(), + }; + return result; +} - if (params.groupsToScheduleActionsInSeries) { - const index = state.groupInSeriesIndex || 0; - group = params.groupsToScheduleActionsInSeries[index]; - } +async function alwaysFiringExecutor(alertExecutorOptions: any) { + const { + services, + params, + state, + alertId, + spaceId, + namespace, + name, + tags, + createdBy, + updatedBy, + } = alertExecutorOptions; + let group: string | null = 'default'; + const alertInfo = { alertId, spaceId, namespace, name, tags, createdBy, updatedBy }; - if (group) { - services - .alertInstanceFactory('1') - .replaceState({ instanceStateValue: true }) - .scheduleActions(group, { - instanceContextValue: true, - }); - } - await services.scopedClusterClient.index({ - index: params.index, - refresh: 'wait_for', - body: { - state, - params, - reference: params.reference, - source: 'alert:test.always-firing', - alertInfo, - }, + if (params.groupsToScheduleActionsInSeries) { + const index = state.groupInSeriesIndex || 0; + group = params.groupsToScheduleActionsInSeries[index]; + } + + if (group) { + services + .alertInstanceFactory('1') + .replaceState({ instanceStateValue: true }) + .scheduleActions(group, { + instanceContextValue: true, }); - return { - globalStateValue: true, - groupInSeriesIndex: (state.groupInSeriesIndex || 0) + 1, - }; + } + await services.scopedClusterClient.index({ + index: params.index, + refresh: 'wait_for', + body: { + state, + params, + reference: params.reference, + source: 'alert:test.always-firing', + alertInfo, }, + }); + return { + globalStateValue: true, + groupInSeriesIndex: (state.groupInSeriesIndex || 0) + 1, }; - return result; } function getCumulativeFiringAlertType() { @@ -113,6 +116,7 @@ function getCumulativeFiringAlertType() { ], producer: 'alertsFixture', defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', async executor(alertExecutorOptions) { const { services, state } = alertExecutorOptions; const group = 'default'; @@ -131,7 +135,7 @@ function getCumulativeFiringAlertType() { }; }, }; - return result; + return result as AlertType; } function getNeverFiringAlertType() { @@ -157,6 +161,7 @@ function getNeverFiringAlertType() { }, producer: 'alertsFixture', defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', async executor({ services, params, state }) { await services.callCluster('index', { index: params.index, @@ -196,6 +201,7 @@ function getFailingAlertType() { ], producer: 'alertsFixture', defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', async executor({ services, params, state }) { await services.callCluster('index', { index: params.index, @@ -234,6 +240,7 @@ function getAuthorizationAlertType(core: CoreSetup) { ], defaultActionGroupId: 'default', producer: 'alertsFixture', + minimumLicenseRequired: 'basic', validate: { params: paramsSchema, }, @@ -319,6 +326,7 @@ function getValidationAlertType() { }, ], producer: 'alertsFixture', + minimumLicenseRequired: 'basic', defaultActionGroupId: 'default', validate: { params: paramsSchema, @@ -343,6 +351,7 @@ function getPatternFiringAlertType() { actionGroups: [{ id: 'default', name: 'Default' }], producer: 'alertsFixture', defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', async executor(alertExecutorOptions) { const { services, state, params } = alertExecutorOptions; const pattern = params.pattern; @@ -398,6 +407,7 @@ export function defineAlertTypes( actionGroups: [{ id: 'default', name: 'Default' }], producer: 'alertsFixture', defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', async executor() {}, }; const onlyContextVariablesAlertType: AlertType = { @@ -406,6 +416,7 @@ export function defineAlertTypes( actionGroups: [{ id: 'default', name: 'Default' }], producer: 'alertsFixture', defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', actionVariables: { context: [{ name: 'aContextVariable', description: 'this is a context variable' }], }, @@ -420,6 +431,7 @@ export function defineAlertTypes( actionVariables: { state: [{ name: 'aStateVariable', description: 'this is a state variable' }], }, + minimumLicenseRequired: 'basic', async executor() {}, }; const throwAlertType: AlertType = { @@ -433,6 +445,7 @@ export function defineAlertTypes( ], producer: 'alertsFixture', defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', async executor() { throw new Error('this alert is intended to fail'); }, @@ -448,6 +461,7 @@ export function defineAlertTypes( ], producer: 'alertsFixture', defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', async executor() { await new Promise((resolve) => setTimeout(resolve, 5000)); }, diff --git a/x-pack/test/alerting_api_integration/common/fixtures/plugins/alerts_restricted/server/alert_types.ts b/x-pack/test/alerting_api_integration/common/fixtures/plugins/alerts_restricted/server/alert_types.ts index 3e3c44f2c2784..3a81d41a2ca9c 100644 --- a/x-pack/test/alerting_api_integration/common/fixtures/plugins/alerts_restricted/server/alert_types.ts +++ b/x-pack/test/alerting_api_integration/common/fixtures/plugins/alerts_restricted/server/alert_types.ts @@ -18,6 +18,7 @@ export function defineAlertTypes( actionGroups: [{ id: 'default', name: 'Default' }], producer: 'alertsRestrictedFixture', defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', recoveryActionGroup: { id: 'restrictedRecovered', name: 'Restricted Recovery' }, async executor({ services, params, state }: AlertExecutorOptions) {}, }; @@ -27,6 +28,7 @@ export function defineAlertTypes( actionGroups: [{ id: 'default', name: 'Default' }], producer: 'alertsRestrictedFixture', defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', async executor({ services, params, state }: AlertExecutorOptions) {}, }; alerts.registerType(noopRestrictedAlertType); diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/list_alert_types.ts b/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/list_alert_types.ts index 1ce04683f79bf..3ec85d558d4e8 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/list_alert_types.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/list_alert_types.ts @@ -28,6 +28,7 @@ export default function listAlertTypes({ getService }: FtrProviderContext) { params: [], }, producer: 'alertsFixture', + minimumLicenseRequired: 'basic', recoveryActionGroup: { id: 'recovered', name: 'Recovered', @@ -52,6 +53,7 @@ export default function listAlertTypes({ getService }: FtrProviderContext) { params: [], }, producer: 'alertsRestrictedFixture', + minimumLicenseRequired: 'basic', }; describe('list_alert_types', () => { diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/list_alert_types.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/list_alert_types.ts index c76a43b05b172..0b27adf27efdd 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/list_alert_types.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/list_alert_types.ts @@ -40,6 +40,7 @@ export default function listAlertTypes({ getService }: FtrProviderContext) { name: 'Recovered', }, producer: 'alertsFixture', + minimumLicenseRequired: 'basic', }); expect(Object.keys(authorizedConsumers)).to.contain('alertsFixture'); }); diff --git a/x-pack/test/functional_with_es_ssl/fixtures/plugins/alerts/server/plugin.ts b/x-pack/test/functional_with_es_ssl/fixtures/plugins/alerts/server/plugin.ts index 6584c5891a8b9..f6cbc52e7a421 100644 --- a/x-pack/test/functional_with_es_ssl/fixtures/plugins/alerts/server/plugin.ts +++ b/x-pack/test/functional_with_es_ssl/fixtures/plugins/alerts/server/plugin.ts @@ -22,11 +22,12 @@ export const noopAlertType: AlertType = { name: 'Test: Noop', actionGroups: [{ id: 'default', name: 'Default' }], defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', async executor() {}, producer: 'alerts', }; -export const alwaysFiringAlertType: any = { +export const alwaysFiringAlertType: AlertType = { id: 'test.always-firing', name: 'Always Firing', actionGroups: [ @@ -35,6 +36,7 @@ export const alwaysFiringAlertType: any = { ], defaultActionGroupId: 'default', producer: 'alerts', + minimumLicenseRequired: 'basic', async executor(alertExecutorOptions: any) { const { services, state, params } = alertExecutorOptions; @@ -52,7 +54,7 @@ export const alwaysFiringAlertType: any = { }, }; -export const failingAlertType: any = { +export const failingAlertType: AlertType = { id: 'test.failing', name: 'Test: Failing', actionGroups: [ @@ -63,6 +65,7 @@ export const failingAlertType: any = { ], producer: 'alerts', defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', async executor() { throw new Error('Failed to execute alert type'); },