From ed3015e763b00d267ac960fc5cbc76a32cd8112e Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Fri, 17 May 2024 17:48:46 +0300 Subject: [PATCH 001/106] Change the schema of the alerting feature privilege --- .../alerting_example/server/plugin.ts | 80 +++- .../features/src/security/kibana_features.ts | 10 +- .../authorization/alerting_authorization.ts | 5 +- .../common/feature_kibana_privileges.ts | 8 +- .../plugins/features/common/kibana_feature.ts | 2 +- .../plugins/features/server/feature_schema.ts | 31 +- .../plugins/ml/common/types/capabilities.ts | 8 +- x-pack/plugins/ml/server/plugin.ts | 2 +- x-pack/plugins/monitoring/server/plugin.ts | 6 +- .../apm/server/feature.ts | 10 +- .../infra/server/features.ts | 20 +- .../observability/server/plugin.ts | 10 +- .../slo/server/plugin.ts | 10 +- .../synthetics/server/feature.ts | 10 +- .../alerting.test.ts | 431 +++++++++--------- .../feature_privilege_builder/alerting.ts | 22 +- x-pack/plugins/stack_alerts/server/feature.ts | 25 +- 17 files changed, 396 insertions(+), 294 deletions(-) diff --git a/x-pack/examples/alerting_example/server/plugin.ts b/x-pack/examples/alerting_example/server/plugin.ts index 8aee6fb49dbe51..67faaf517274d9 100644 --- a/x-pack/examples/alerting_example/server/plugin.ts +++ b/x-pack/examples/alerting_example/server/plugin.ts @@ -41,15 +41,15 @@ export class AlertingExamplePlugin implements Plugin 0) + ((alerting?.ruleTypeIds?.length ?? 0 > 0) || + (alerting?.consumers?.length ?? 0 > 0)) ) .map((feature) => feature.id) ) @@ -352,7 +353,7 @@ export class AlertingAuthorization { const featureDef = this.features .getKibanaFeatures() .find((kFeature) => kFeature.id === feature); - for (const ruleTypeId of featureDef?.alerting ?? []) { + for (const ruleTypeId of featureDef?.alerting?.ruleTypeIds ?? []) { const ruleTypeAuth = ruleTypesWithAuthorization.find((rtwa) => rtwa.id === ruleTypeId); if (ruleTypeAuth) { if (!ruleTypesAuthorized.has(ruleTypeId)) { diff --git a/x-pack/plugins/features/common/feature_kibana_privileges.ts b/x-pack/plugins/features/common/feature_kibana_privileges.ts index 49c001c890b692..74811f56e85824 100644 --- a/x-pack/plugins/features/common/feature_kibana_privileges.ts +++ b/x-pack/plugins/features/common/feature_kibana_privileges.ts @@ -103,7 +103,7 @@ export interface FeatureKibanaPrivileges { * } * ``` */ - all?: readonly string[]; + all?: { ruleTypeIds?: readonly string[]; consumers?: readonly string[] }; /** * List of rule types which users should have read-only access to when granted this privilege. * @example @@ -113,7 +113,7 @@ export interface FeatureKibanaPrivileges { * } * ``` */ - read?: readonly string[]; + read?: { ruleTypeIds?: readonly string[]; consumers?: readonly string[] }; }; alert?: { /** @@ -125,7 +125,7 @@ export interface FeatureKibanaPrivileges { * } * ``` */ - all?: readonly string[]; + all?: { ruleTypeIds?: readonly string[]; consumers?: readonly string[] }; /** * List of rule types for which users should have read-only access to their alert data when granted this privilege. * @example @@ -135,7 +135,7 @@ export interface FeatureKibanaPrivileges { * } * ``` */ - read?: readonly string[]; + read?: { ruleTypeIds?: readonly string[]; consumers?: readonly string[] }; }; }; diff --git a/x-pack/plugins/features/common/kibana_feature.ts b/x-pack/plugins/features/common/kibana_feature.ts index debcec588dee0d..34d45122dafac8 100644 --- a/x-pack/plugins/features/common/kibana_feature.ts +++ b/x-pack/plugins/features/common/kibana_feature.ts @@ -101,7 +101,7 @@ export interface KibanaFeatureConfig { * Include both Alert Types registered by the feature and external Alert Types such as built-in * Alert Types and Alert Types provided by other features to which you wish to grant access. */ - alerting?: readonly string[]; + alerting?: { ruleTypeIds?: readonly string[]; consumers?: readonly string[] }; /** * If your feature grants access to specific case types, you can specify them here to control visibility based on the current space. diff --git a/x-pack/plugins/features/server/feature_schema.ts b/x-pack/plugins/features/server/feature_schema.ts index b332ea355dcc03..fb26984d439c12 100644 --- a/x-pack/plugins/features/server/feature_schema.ts +++ b/x-pack/plugins/features/server/feature_schema.ts @@ -63,7 +63,10 @@ const managementSchema = schema.recordOf( listOfCapabilitiesSchema ); const catalogueSchema = listOfCapabilitiesSchema; -const alertingSchema = schema.arrayOf(schema.string()); +const alertingSchema = schema.object({ + ruleTypeIds: schema.maybe(schema.arrayOf(schema.string())), + consumers: schema.maybe(schema.arrayOf(schema.string())), +}); const casesSchema = schema.arrayOf(schema.string()); const appCategorySchema = schema.object({ @@ -274,7 +277,13 @@ export function validateKibanaFeature(feature: KibanaFeatureConfig) { kibanaFeatureSchema.validate(feature); // the following validation can't be enforced by the Joi schema, since it'd require us looking "up" the object graph for the list of valid value, which they explicitly forbid. - const { app = [], management = {}, catalogue = [], alerting = [], cases = [] } = feature; + const { + app = [], + management = {}, + catalogue = [], + alerting: { ruleTypeIds = [], consumers = [] } = {}, + cases = [], + } = feature; const unseenApps = new Set(app); @@ -287,7 +296,7 @@ export function validateKibanaFeature(feature: KibanaFeatureConfig) { const unseenCatalogue = new Set(catalogue); - const unseenAlertTypes = new Set(alerting); + const unseenAlertTypes = new Set([...ruleTypeIds, ...consumers]); const unseenCasesTypes = new Set(cases); @@ -318,13 +327,23 @@ export function validateKibanaFeature(feature: KibanaFeatureConfig) { } function validateAlertingEntry(privilegeId: string, entry: FeatureKibanaPrivileges['alerting']) { - const all: string[] = [...(entry?.rule?.all ?? []), ...(entry?.alert?.all ?? [])]; - const read: string[] = [...(entry?.rule?.read ?? []), ...(entry?.alert?.read ?? [])]; + const all: string[] = [ + ...(entry?.rule?.all?.consumers ?? []), + ...(entry?.rule?.all?.ruleTypeIds ?? []), + ...(entry?.alert?.all?.consumers ?? []), + ...(entry?.alert?.all?.ruleTypeIds ?? []), + ]; + const read: string[] = [ + ...(entry?.rule?.read?.consumers ?? []), + ...(entry?.rule?.read?.ruleTypeIds ?? []), + ...(entry?.alert?.read?.consumers ?? []), + ...(entry?.alert?.read?.ruleTypeIds ?? []), + ]; all.forEach((privilegeAlertTypes) => unseenAlertTypes.delete(privilegeAlertTypes)); read.forEach((privilegeAlertTypes) => unseenAlertTypes.delete(privilegeAlertTypes)); - const unknownAlertingEntries = difference([...all, ...read], alerting); + const unknownAlertingEntries = difference([...all, ...read], [...ruleTypeIds, ...consumers]); if (unknownAlertingEntries.length > 0) { throw new Error( `Feature privilege ${ diff --git a/x-pack/plugins/ml/common/types/capabilities.ts b/x-pack/plugins/ml/common/types/capabilities.ts index 7dc841a5cb4d70..c2c25515b105f8 100644 --- a/x-pack/plugins/ml/common/types/capabilities.ts +++ b/x-pack/plugins/ml/common/types/capabilities.ts @@ -149,10 +149,10 @@ export function getPluginPrivileges() { }, alerting: { rule: { - all: Object.values(ML_ALERT_TYPES), + all: { ruleTypeIds: Object.values(ML_ALERT_TYPES), consumers: [PLUGIN_ID] }, }, alert: { - all: Object.values(ML_ALERT_TYPES), + all: { ruleTypeIds: Object.values(ML_ALERT_TYPES), consumers: [PLUGIN_ID] }, }, }, }, @@ -171,10 +171,10 @@ export function getPluginPrivileges() { }, alerting: { rule: { - read: Object.values(ML_ALERT_TYPES), + read: { ruleTypeIds: Object.values(ML_ALERT_TYPES), consumers: [PLUGIN_ID] }, }, alert: { - read: Object.values(ML_ALERT_TYPES), + read: { ruleTypeIds: Object.values(ML_ALERT_TYPES), consumers: [PLUGIN_ID] }, }, }, }, diff --git a/x-pack/plugins/ml/server/plugin.ts b/x-pack/plugins/ml/server/plugin.ts index f8260e22118886..c035ae14d2a021 100644 --- a/x-pack/plugins/ml/server/plugin.ts +++ b/x-pack/plugins/ml/server/plugin.ts @@ -139,7 +139,7 @@ export class MlServerPlugin management: { insightsAndAlerting: ['jobsListLink', 'triggersActions'], }, - alerting: Object.values(ML_ALERT_TYPES), + alerting: { ruleTypeIds: Object.values(ML_ALERT_TYPES), consumers: [PLUGIN_ID] }, privileges: { all: admin, read: user, diff --git a/x-pack/plugins/monitoring/server/plugin.ts b/x-pack/plugins/monitoring/server/plugin.ts index 5219c3441b13e2..a86361467dcd61 100644 --- a/x-pack/plugins/monitoring/server/plugin.ts +++ b/x-pack/plugins/monitoring/server/plugin.ts @@ -275,7 +275,7 @@ export class MonitoringPlugin app: ['monitoring', 'kibana'], catalogue: ['monitoring'], privileges: null, - alerting: RULES, + alerting: { ruleTypeIds: RULES, consumers: ['monitoring'] }, reserved: { description: i18n.translate('xpack.monitoring.feature.reserved.description', { defaultMessage: 'To grant users access, you should also assign the monitoring_user role.', @@ -292,10 +292,10 @@ export class MonitoringPlugin }, alerting: { rule: { - all: RULES, + all: { ruleTypeIds: RULES, consumers: ['monitoring'] }, }, alert: { - all: RULES, + all: { ruleTypeIds: RULES, consumers: ['monitoring'] }, }, }, ui: [], diff --git a/x-pack/plugins/observability_solution/apm/server/feature.ts b/x-pack/plugins/observability_solution/apm/server/feature.ts index 5a0ba552a0c18b..f186ef1e2c03f1 100644 --- a/x-pack/plugins/observability_solution/apm/server/feature.ts +++ b/x-pack/plugins/observability_solution/apm/server/feature.ts @@ -31,7 +31,7 @@ export const APM_FEATURE = { management: { insightsAndAlerting: ['triggersActions'], }, - alerting: ruleTypes, + alerting: { ruleTypeIds: ruleTypes, consumers: [APM_SERVER_FEATURE_ID] }, // see x-pack/plugins/features/common/feature_kibana_privileges.ts privileges: { all: { @@ -44,10 +44,10 @@ export const APM_FEATURE = { }, alerting: { alert: { - all: ruleTypes, + all: { ruleTypeIds: ruleTypes, consumers: [APM_SERVER_FEATURE_ID] }, }, rule: { - all: ruleTypes, + all: { ruleTypeIds: ruleTypes, consumers: [APM_SERVER_FEATURE_ID] }, }, }, management: { @@ -65,10 +65,10 @@ export const APM_FEATURE = { }, alerting: { alert: { - read: ruleTypes, + read: { ruleTypeIds: ruleTypes, consumers: [APM_SERVER_FEATURE_ID] }, }, rule: { - read: ruleTypes, + read: { ruleTypeIds: ruleTypes, consumers: [APM_SERVER_FEATURE_ID] }, }, }, management: { diff --git a/x-pack/plugins/observability_solution/infra/server/features.ts b/x-pack/plugins/observability_solution/infra/server/features.ts index 68fe2503ace143..ff3b1eceaf4c86 100644 --- a/x-pack/plugins/observability_solution/infra/server/features.ts +++ b/x-pack/plugins/observability_solution/infra/server/features.ts @@ -42,7 +42,7 @@ export const METRICS_FEATURE = { management: { insightsAndAlerting: ['triggersActions'], }, - alerting: metricRuleTypes, + alerting: { ruleTypeIds: metricRuleTypes, consumers: [METRICS_FEATURE_ID] }, privileges: { all: { app: ['infra', 'metrics', 'kibana'], @@ -54,10 +54,10 @@ export const METRICS_FEATURE = { }, alerting: { rule: { - all: metricRuleTypes, + all: { ruleTypeIds: metricRuleTypes, consumers: [METRICS_FEATURE_ID] }, }, alert: { - all: metricRuleTypes, + all: { ruleTypeIds: metricRuleTypes, consumers: [METRICS_FEATURE_ID] }, }, }, management: { @@ -75,10 +75,10 @@ export const METRICS_FEATURE = { }, alerting: { rule: { - read: metricRuleTypes, + read: { ruleTypeIds: metricRuleTypes, consumers: [METRICS_FEATURE_ID] }, }, alert: { - read: metricRuleTypes, + read: { ruleTypeIds: metricRuleTypes, consumers: [METRICS_FEATURE_ID] }, }, }, management: { @@ -108,7 +108,7 @@ export const LOGS_FEATURE = { management: { insightsAndAlerting: ['triggersActions'], }, - alerting: logsRuleTypes, + alerting: { ruleTypeIds: logsRuleTypes, consumers: [LOGS_FEATURE_ID] }, privileges: { all: { app: ['infra', 'logs', 'kibana'], @@ -120,10 +120,10 @@ export const LOGS_FEATURE = { }, alerting: { rule: { - all: logsRuleTypes, + all: { ruleTypeIds: logsRuleTypes, consumers: [LOGS_FEATURE_ID] }, }, alert: { - all: logsRuleTypes, + all: { ruleTypeIds: logsRuleTypes, consumers: [LOGS_FEATURE_ID] }, }, }, management: { @@ -137,10 +137,10 @@ export const LOGS_FEATURE = { api: ['infra', 'rac'], alerting: { rule: { - read: logsRuleTypes, + read: { ruleTypeIds: logsRuleTypes, consumers: [LOGS_FEATURE_ID] }, }, alert: { - read: logsRuleTypes, + read: { ruleTypeIds: logsRuleTypes, consumers: [LOGS_FEATURE_ID] }, }, }, management: { diff --git a/x-pack/plugins/observability_solution/observability/server/plugin.ts b/x-pack/plugins/observability_solution/observability/server/plugin.ts index fad3db3f5fd109..73090620c18e1e 100644 --- a/x-pack/plugins/observability_solution/observability/server/plugin.ts +++ b/x-pack/plugins/observability_solution/observability/server/plugin.ts @@ -234,7 +234,7 @@ export class ObservabilityPlugin implements Plugin { category: DEFAULT_APP_CATEGORIES.observability, app: [observabilityFeatureId], catalogue: [observabilityFeatureId], - alerting: o11yRuleTypes, + alerting: { ruleTypeIds: o11yRuleTypes, consumers: [observabilityFeatureId] }, privileges: { all: { app: [observabilityFeatureId], @@ -246,10 +246,10 @@ export class ObservabilityPlugin implements Plugin { }, alerting: { rule: { - all: o11yRuleTypes, + all: { ruleTypeIds: o11yRuleTypes, consumers: [observabilityFeatureId] }, }, alert: { - all: o11yRuleTypes, + all: { ruleTypeIds: o11yRuleTypes, consumers: [observabilityFeatureId] }, }, }, ui: ['read', 'write'], @@ -264,10 +264,10 @@ export class ObservabilityPlugin implements Plugin { }, alerting: { rule: { - read: o11yRuleTypes, + read: { ruleTypeIds: o11yRuleTypes, consumers: [observabilityFeatureId] }, }, alert: { - read: o11yRuleTypes, + read: { ruleTypeIds: o11yRuleTypes, consumers: [observabilityFeatureId] }, }, }, ui: ['read'], diff --git a/x-pack/plugins/observability_solution/slo/server/plugin.ts b/x-pack/plugins/observability_solution/slo/server/plugin.ts index 7c3dd521a5d527..a32f60b42d6652 100644 --- a/x-pack/plugins/observability_solution/slo/server/plugin.ts +++ b/x-pack/plugins/observability_solution/slo/server/plugin.ts @@ -88,7 +88,7 @@ export class SloPlugin implements Plugin { category: DEFAULT_APP_CATEGORIES.observability, app: [sloFeatureId, 'kibana'], catalogue: [sloFeatureId, 'observability'], - alerting: sloRuleTypes, + alerting: { ruleTypeIds: sloRuleTypes, consumers: [sloFeatureId] }, privileges: { all: { app: [sloFeatureId, 'kibana'], @@ -100,10 +100,10 @@ export class SloPlugin implements Plugin { }, alerting: { rule: { - all: sloRuleTypes, + all: { ruleTypeIds: sloRuleTypes, consumers: [sloFeatureId] }, }, alert: { - all: sloRuleTypes, + all: { ruleTypeIds: sloRuleTypes, consumers: [sloFeatureId] }, }, }, ui: ['read', 'write'], @@ -118,10 +118,10 @@ export class SloPlugin implements Plugin { }, alerting: { rule: { - read: sloRuleTypes, + read: { ruleTypeIds: sloRuleTypes, consumers: [sloFeatureId] }, }, alert: { - read: sloRuleTypes, + read: { ruleTypeIds: sloRuleTypes, consumers: [sloFeatureId] }, }, }, ui: ['read'], diff --git a/x-pack/plugins/observability_solution/synthetics/server/feature.ts b/x-pack/plugins/observability_solution/synthetics/server/feature.ts index 951fdaf33c5363..7d69cd4283947f 100644 --- a/x-pack/plugins/observability_solution/synthetics/server/feature.ts +++ b/x-pack/plugins/observability_solution/synthetics/server/feature.ts @@ -55,7 +55,7 @@ export const uptimeFeature = { management: { insightsAndAlerting: ['triggersActions'], }, - alerting: ruleTypes, + alerting: { ruleTypeIds: ruleTypes, consumers: [PLUGIN.ID] }, privileges: { all: { app: ['uptime', 'kibana', 'synthetics'], @@ -73,10 +73,10 @@ export const uptimeFeature = { }, alerting: { rule: { - all: ruleTypes, + all: { ruleTypeIds: ruleTypes, consumers: [PLUGIN.ID] }, }, alert: { - all: ruleTypes, + all: { ruleTypeIds: ruleTypes, consumers: [PLUGIN.ID] }, }, }, management: { @@ -100,10 +100,10 @@ export const uptimeFeature = { }, alerting: { rule: { - read: ruleTypes, + read: { ruleTypeIds: ruleTypes, consumers: [PLUGIN.ID] }, }, alert: { - read: ruleTypes, + read: { ruleTypeIds: ruleTypes, consumers: [PLUGIN.ID] }, }, }, management: { diff --git a/x-pack/plugins/security/server/authorization/privileges/feature_privilege_builder/alerting.test.ts b/x-pack/plugins/security/server/authorization/privileges/feature_privilege_builder/alerting.test.ts index db4aae642a56f8..539f4cd77cc698 100644 --- a/x-pack/plugins/security/server/authorization/privileges/feature_privilege_builder/alerting.test.ts +++ b/x-pack/plugins/security/server/authorization/privileges/feature_privilege_builder/alerting.test.ts @@ -20,15 +20,14 @@ describe(`feature_privilege_builder`, () => { const privilege: FeatureKibanaPrivileges = { alerting: { rule: { - all: [], - read: [], + all: {}, + read: {}, }, alert: { - all: [], - read: [], + all: {}, + read: {}, }, }, - savedObject: { all: [], read: [], @@ -58,11 +57,10 @@ describe(`feature_privilege_builder`, () => { const privilege: FeatureKibanaPrivileges = { alerting: { rule: { - all: [], - read: ['alert-type'], + all: {}, + read: { ruleTypeIds: ['alert-type'], consumers: ['my-consumer'] }, }, }, - savedObject: { all: [], read: [], @@ -83,15 +81,15 @@ describe(`feature_privilege_builder`, () => { expect(alertingFeaturePrivileges.getActions(privilege, feature)).toMatchInlineSnapshot(` Array [ - "alerting:alert-type/my-feature/rule/get", - "alerting:alert-type/my-feature/rule/getRuleState", - "alerting:alert-type/my-feature/rule/getAlertSummary", - "alerting:alert-type/my-feature/rule/getExecutionLog", - "alerting:alert-type/my-feature/rule/getActionErrorLog", - "alerting:alert-type/my-feature/rule/find", - "alerting:alert-type/my-feature/rule/getRuleExecutionKPI", - "alerting:alert-type/my-feature/rule/getBackfill", - "alerting:alert-type/my-feature/rule/findBackfill", + "alerting:alert-type/my-consumer/rule/get", + "alerting:alert-type/my-consumer/rule/getRuleState", + "alerting:alert-type/my-consumer/rule/getAlertSummary", + "alerting:alert-type/my-consumer/rule/getExecutionLog", + "alerting:alert-type/my-consumer/rule/getActionErrorLog", + "alerting:alert-type/my-consumer/rule/find", + "alerting:alert-type/my-consumer/rule/getRuleExecutionKPI", + "alerting:alert-type/my-consumer/rule/getBackfill", + "alerting:alert-type/my-consumer/rule/findBackfill", ] `); }); @@ -103,11 +101,10 @@ describe(`feature_privilege_builder`, () => { const privilege: FeatureKibanaPrivileges = { alerting: { alert: { - all: [], - read: ['alert-type'], + all: {}, + read: { ruleTypeIds: ['alert-type'], consumers: ['my-consumer'] }, }, }, - savedObject: { all: [], read: [], @@ -128,10 +125,10 @@ describe(`feature_privilege_builder`, () => { expect(alertingFeaturePrivileges.getActions(privilege, feature)).toMatchInlineSnapshot(` Array [ - "alerting:alert-type/my-feature/alert/get", - "alerting:alert-type/my-feature/alert/find", - "alerting:alert-type/my-feature/alert/getAuthorizedAlertsIndices", - "alerting:alert-type/my-feature/alert/getAlertSummary", + "alerting:alert-type/my-consumer/alert/get", + "alerting:alert-type/my-consumer/alert/find", + "alerting:alert-type/my-consumer/alert/getAuthorizedAlertsIndices", + "alerting:alert-type/my-consumer/alert/getAlertSummary", ] `); }); @@ -143,15 +140,14 @@ describe(`feature_privilege_builder`, () => { const privilege: FeatureKibanaPrivileges = { alerting: { rule: { - all: [], - read: ['alert-type'], + all: {}, + read: { ruleTypeIds: ['alert-type'], consumers: ['my-consumer'] }, }, alert: { - all: [], - read: ['alert-type'], + all: {}, + read: { ruleTypeIds: ['alert-type'], consumers: ['my-consumer'] }, }, }, - savedObject: { all: [], read: [], @@ -172,19 +168,19 @@ describe(`feature_privilege_builder`, () => { expect(alertingFeaturePrivileges.getActions(privilege, feature)).toMatchInlineSnapshot(` Array [ - "alerting:alert-type/my-feature/rule/get", - "alerting:alert-type/my-feature/rule/getRuleState", - "alerting:alert-type/my-feature/rule/getAlertSummary", - "alerting:alert-type/my-feature/rule/getExecutionLog", - "alerting:alert-type/my-feature/rule/getActionErrorLog", - "alerting:alert-type/my-feature/rule/find", - "alerting:alert-type/my-feature/rule/getRuleExecutionKPI", - "alerting:alert-type/my-feature/rule/getBackfill", - "alerting:alert-type/my-feature/rule/findBackfill", - "alerting:alert-type/my-feature/alert/get", - "alerting:alert-type/my-feature/alert/find", - "alerting:alert-type/my-feature/alert/getAuthorizedAlertsIndices", - "alerting:alert-type/my-feature/alert/getAlertSummary", + "alerting:alert-type/my-consumer/rule/get", + "alerting:alert-type/my-consumer/rule/getRuleState", + "alerting:alert-type/my-consumer/rule/getAlertSummary", + "alerting:alert-type/my-consumer/rule/getExecutionLog", + "alerting:alert-type/my-consumer/rule/getActionErrorLog", + "alerting:alert-type/my-consumer/rule/find", + "alerting:alert-type/my-consumer/rule/getRuleExecutionKPI", + "alerting:alert-type/my-consumer/rule/getBackfill", + "alerting:alert-type/my-consumer/rule/findBackfill", + "alerting:alert-type/my-consumer/alert/get", + "alerting:alert-type/my-consumer/alert/find", + "alerting:alert-type/my-consumer/alert/getAuthorizedAlertsIndices", + "alerting:alert-type/my-consumer/alert/getAlertSummary", ] `); }); @@ -196,8 +192,8 @@ describe(`feature_privilege_builder`, () => { const privilege: FeatureKibanaPrivileges = { alerting: { rule: { - all: ['alert-type'], - read: [], + all: { ruleTypeIds: ['alert-type'], consumers: ['my-consumer'] }, + read: {}, }, }, @@ -221,34 +217,34 @@ describe(`feature_privilege_builder`, () => { expect(alertingFeaturePrivileges.getActions(privilege, feature)).toMatchInlineSnapshot(` Array [ - "alerting:alert-type/my-feature/rule/get", - "alerting:alert-type/my-feature/rule/getRuleState", - "alerting:alert-type/my-feature/rule/getAlertSummary", - "alerting:alert-type/my-feature/rule/getExecutionLog", - "alerting:alert-type/my-feature/rule/getActionErrorLog", - "alerting:alert-type/my-feature/rule/find", - "alerting:alert-type/my-feature/rule/getRuleExecutionKPI", - "alerting:alert-type/my-feature/rule/getBackfill", - "alerting:alert-type/my-feature/rule/findBackfill", - "alerting:alert-type/my-feature/rule/create", - "alerting:alert-type/my-feature/rule/delete", - "alerting:alert-type/my-feature/rule/update", - "alerting:alert-type/my-feature/rule/updateApiKey", - "alerting:alert-type/my-feature/rule/enable", - "alerting:alert-type/my-feature/rule/disable", - "alerting:alert-type/my-feature/rule/muteAll", - "alerting:alert-type/my-feature/rule/unmuteAll", - "alerting:alert-type/my-feature/rule/muteAlert", - "alerting:alert-type/my-feature/rule/unmuteAlert", - "alerting:alert-type/my-feature/rule/snooze", - "alerting:alert-type/my-feature/rule/bulkEdit", - "alerting:alert-type/my-feature/rule/bulkDelete", - "alerting:alert-type/my-feature/rule/bulkEnable", - "alerting:alert-type/my-feature/rule/bulkDisable", - "alerting:alert-type/my-feature/rule/unsnooze", - "alerting:alert-type/my-feature/rule/runSoon", - "alerting:alert-type/my-feature/rule/scheduleBackfill", - "alerting:alert-type/my-feature/rule/deleteBackfill", + "alerting:alert-type/my-consumer/rule/get", + "alerting:alert-type/my-consumer/rule/getRuleState", + "alerting:alert-type/my-consumer/rule/getAlertSummary", + "alerting:alert-type/my-consumer/rule/getExecutionLog", + "alerting:alert-type/my-consumer/rule/getActionErrorLog", + "alerting:alert-type/my-consumer/rule/find", + "alerting:alert-type/my-consumer/rule/getRuleExecutionKPI", + "alerting:alert-type/my-consumer/rule/getBackfill", + "alerting:alert-type/my-consumer/rule/findBackfill", + "alerting:alert-type/my-consumer/rule/create", + "alerting:alert-type/my-consumer/rule/delete", + "alerting:alert-type/my-consumer/rule/update", + "alerting:alert-type/my-consumer/rule/updateApiKey", + "alerting:alert-type/my-consumer/rule/enable", + "alerting:alert-type/my-consumer/rule/disable", + "alerting:alert-type/my-consumer/rule/muteAll", + "alerting:alert-type/my-consumer/rule/unmuteAll", + "alerting:alert-type/my-consumer/rule/muteAlert", + "alerting:alert-type/my-consumer/rule/unmuteAlert", + "alerting:alert-type/my-consumer/rule/snooze", + "alerting:alert-type/my-consumer/rule/bulkEdit", + "alerting:alert-type/my-consumer/rule/bulkDelete", + "alerting:alert-type/my-consumer/rule/bulkEnable", + "alerting:alert-type/my-consumer/rule/bulkDisable", + "alerting:alert-type/my-consumer/rule/unsnooze", + "alerting:alert-type/my-consumer/rule/runSoon", + "alerting:alert-type/my-consumer/rule/scheduleBackfill", + "alerting:alert-type/my-consumer/rule/deleteBackfill", ] `); }); @@ -260,11 +256,10 @@ describe(`feature_privilege_builder`, () => { const privilege: FeatureKibanaPrivileges = { alerting: { alert: { - all: ['alert-type'], - read: [], + all: { ruleTypeIds: ['alert-type'], consumers: ['my-consumer'] }, + read: {}, }, }, - savedObject: { all: [], read: [], @@ -285,11 +280,11 @@ describe(`feature_privilege_builder`, () => { expect(alertingFeaturePrivileges.getActions(privilege, feature)).toMatchInlineSnapshot(` Array [ - "alerting:alert-type/my-feature/alert/get", - "alerting:alert-type/my-feature/alert/find", - "alerting:alert-type/my-feature/alert/getAuthorizedAlertsIndices", - "alerting:alert-type/my-feature/alert/getAlertSummary", - "alerting:alert-type/my-feature/alert/update", + "alerting:alert-type/my-consumer/alert/get", + "alerting:alert-type/my-consumer/alert/find", + "alerting:alert-type/my-consumer/alert/getAuthorizedAlertsIndices", + "alerting:alert-type/my-consumer/alert/getAlertSummary", + "alerting:alert-type/my-consumer/alert/update", ] `); }); @@ -301,15 +296,14 @@ describe(`feature_privilege_builder`, () => { const privilege: FeatureKibanaPrivileges = { alerting: { rule: { - all: ['alert-type'], - read: [], + all: { ruleTypeIds: ['alert-type'], consumers: ['my-consumer'] }, + read: {}, }, alert: { - all: ['alert-type'], - read: [], + all: { ruleTypeIds: ['alert-type'], consumers: ['my-consumer'] }, + read: {}, }, }, - savedObject: { all: [], read: [], @@ -330,39 +324,39 @@ describe(`feature_privilege_builder`, () => { expect(alertingFeaturePrivileges.getActions(privilege, feature)).toMatchInlineSnapshot(` Array [ - "alerting:alert-type/my-feature/rule/get", - "alerting:alert-type/my-feature/rule/getRuleState", - "alerting:alert-type/my-feature/rule/getAlertSummary", - "alerting:alert-type/my-feature/rule/getExecutionLog", - "alerting:alert-type/my-feature/rule/getActionErrorLog", - "alerting:alert-type/my-feature/rule/find", - "alerting:alert-type/my-feature/rule/getRuleExecutionKPI", - "alerting:alert-type/my-feature/rule/getBackfill", - "alerting:alert-type/my-feature/rule/findBackfill", - "alerting:alert-type/my-feature/rule/create", - "alerting:alert-type/my-feature/rule/delete", - "alerting:alert-type/my-feature/rule/update", - "alerting:alert-type/my-feature/rule/updateApiKey", - "alerting:alert-type/my-feature/rule/enable", - "alerting:alert-type/my-feature/rule/disable", - "alerting:alert-type/my-feature/rule/muteAll", - "alerting:alert-type/my-feature/rule/unmuteAll", - "alerting:alert-type/my-feature/rule/muteAlert", - "alerting:alert-type/my-feature/rule/unmuteAlert", - "alerting:alert-type/my-feature/rule/snooze", - "alerting:alert-type/my-feature/rule/bulkEdit", - "alerting:alert-type/my-feature/rule/bulkDelete", - "alerting:alert-type/my-feature/rule/bulkEnable", - "alerting:alert-type/my-feature/rule/bulkDisable", - "alerting:alert-type/my-feature/rule/unsnooze", - "alerting:alert-type/my-feature/rule/runSoon", - "alerting:alert-type/my-feature/rule/scheduleBackfill", - "alerting:alert-type/my-feature/rule/deleteBackfill", - "alerting:alert-type/my-feature/alert/get", - "alerting:alert-type/my-feature/alert/find", - "alerting:alert-type/my-feature/alert/getAuthorizedAlertsIndices", - "alerting:alert-type/my-feature/alert/getAlertSummary", - "alerting:alert-type/my-feature/alert/update", + "alerting:alert-type/my-consumer/rule/get", + "alerting:alert-type/my-consumer/rule/getRuleState", + "alerting:alert-type/my-consumer/rule/getAlertSummary", + "alerting:alert-type/my-consumer/rule/getExecutionLog", + "alerting:alert-type/my-consumer/rule/getActionErrorLog", + "alerting:alert-type/my-consumer/rule/find", + "alerting:alert-type/my-consumer/rule/getRuleExecutionKPI", + "alerting:alert-type/my-consumer/rule/getBackfill", + "alerting:alert-type/my-consumer/rule/findBackfill", + "alerting:alert-type/my-consumer/rule/create", + "alerting:alert-type/my-consumer/rule/delete", + "alerting:alert-type/my-consumer/rule/update", + "alerting:alert-type/my-consumer/rule/updateApiKey", + "alerting:alert-type/my-consumer/rule/enable", + "alerting:alert-type/my-consumer/rule/disable", + "alerting:alert-type/my-consumer/rule/muteAll", + "alerting:alert-type/my-consumer/rule/unmuteAll", + "alerting:alert-type/my-consumer/rule/muteAlert", + "alerting:alert-type/my-consumer/rule/unmuteAlert", + "alerting:alert-type/my-consumer/rule/snooze", + "alerting:alert-type/my-consumer/rule/bulkEdit", + "alerting:alert-type/my-consumer/rule/bulkDelete", + "alerting:alert-type/my-consumer/rule/bulkEnable", + "alerting:alert-type/my-consumer/rule/bulkDisable", + "alerting:alert-type/my-consumer/rule/unsnooze", + "alerting:alert-type/my-consumer/rule/runSoon", + "alerting:alert-type/my-consumer/rule/scheduleBackfill", + "alerting:alert-type/my-consumer/rule/deleteBackfill", + "alerting:alert-type/my-consumer/alert/get", + "alerting:alert-type/my-consumer/alert/find", + "alerting:alert-type/my-consumer/alert/getAuthorizedAlertsIndices", + "alerting:alert-type/my-consumer/alert/getAlertSummary", + "alerting:alert-type/my-consumer/alert/update", ] `); }); @@ -374,11 +368,10 @@ describe(`feature_privilege_builder`, () => { const privilege: FeatureKibanaPrivileges = { alerting: { rule: { - all: ['alert-type'], - read: ['readonly-alert-type'], + all: { ruleTypeIds: ['alert-type'], consumers: ['my-consumer'] }, + read: { ruleTypeIds: ['readonly-alert-type'], consumers: ['my-consumer'] }, }, }, - savedObject: { all: [], read: [], @@ -399,43 +392,43 @@ describe(`feature_privilege_builder`, () => { expect(alertingFeaturePrivileges.getActions(privilege, feature)).toMatchInlineSnapshot(` Array [ - "alerting:alert-type/my-feature/rule/get", - "alerting:alert-type/my-feature/rule/getRuleState", - "alerting:alert-type/my-feature/rule/getAlertSummary", - "alerting:alert-type/my-feature/rule/getExecutionLog", - "alerting:alert-type/my-feature/rule/getActionErrorLog", - "alerting:alert-type/my-feature/rule/find", - "alerting:alert-type/my-feature/rule/getRuleExecutionKPI", - "alerting:alert-type/my-feature/rule/getBackfill", - "alerting:alert-type/my-feature/rule/findBackfill", - "alerting:alert-type/my-feature/rule/create", - "alerting:alert-type/my-feature/rule/delete", - "alerting:alert-type/my-feature/rule/update", - "alerting:alert-type/my-feature/rule/updateApiKey", - "alerting:alert-type/my-feature/rule/enable", - "alerting:alert-type/my-feature/rule/disable", - "alerting:alert-type/my-feature/rule/muteAll", - "alerting:alert-type/my-feature/rule/unmuteAll", - "alerting:alert-type/my-feature/rule/muteAlert", - "alerting:alert-type/my-feature/rule/unmuteAlert", - "alerting:alert-type/my-feature/rule/snooze", - "alerting:alert-type/my-feature/rule/bulkEdit", - "alerting:alert-type/my-feature/rule/bulkDelete", - "alerting:alert-type/my-feature/rule/bulkEnable", - "alerting:alert-type/my-feature/rule/bulkDisable", - "alerting:alert-type/my-feature/rule/unsnooze", - "alerting:alert-type/my-feature/rule/runSoon", - "alerting:alert-type/my-feature/rule/scheduleBackfill", - "alerting:alert-type/my-feature/rule/deleteBackfill", - "alerting:readonly-alert-type/my-feature/rule/get", - "alerting:readonly-alert-type/my-feature/rule/getRuleState", - "alerting:readonly-alert-type/my-feature/rule/getAlertSummary", - "alerting:readonly-alert-type/my-feature/rule/getExecutionLog", - "alerting:readonly-alert-type/my-feature/rule/getActionErrorLog", - "alerting:readonly-alert-type/my-feature/rule/find", - "alerting:readonly-alert-type/my-feature/rule/getRuleExecutionKPI", - "alerting:readonly-alert-type/my-feature/rule/getBackfill", - "alerting:readonly-alert-type/my-feature/rule/findBackfill", + "alerting:alert-type/my-consumer/rule/get", + "alerting:alert-type/my-consumer/rule/getRuleState", + "alerting:alert-type/my-consumer/rule/getAlertSummary", + "alerting:alert-type/my-consumer/rule/getExecutionLog", + "alerting:alert-type/my-consumer/rule/getActionErrorLog", + "alerting:alert-type/my-consumer/rule/find", + "alerting:alert-type/my-consumer/rule/getRuleExecutionKPI", + "alerting:alert-type/my-consumer/rule/getBackfill", + "alerting:alert-type/my-consumer/rule/findBackfill", + "alerting:alert-type/my-consumer/rule/create", + "alerting:alert-type/my-consumer/rule/delete", + "alerting:alert-type/my-consumer/rule/update", + "alerting:alert-type/my-consumer/rule/updateApiKey", + "alerting:alert-type/my-consumer/rule/enable", + "alerting:alert-type/my-consumer/rule/disable", + "alerting:alert-type/my-consumer/rule/muteAll", + "alerting:alert-type/my-consumer/rule/unmuteAll", + "alerting:alert-type/my-consumer/rule/muteAlert", + "alerting:alert-type/my-consumer/rule/unmuteAlert", + "alerting:alert-type/my-consumer/rule/snooze", + "alerting:alert-type/my-consumer/rule/bulkEdit", + "alerting:alert-type/my-consumer/rule/bulkDelete", + "alerting:alert-type/my-consumer/rule/bulkEnable", + "alerting:alert-type/my-consumer/rule/bulkDisable", + "alerting:alert-type/my-consumer/rule/unsnooze", + "alerting:alert-type/my-consumer/rule/runSoon", + "alerting:alert-type/my-consumer/rule/scheduleBackfill", + "alerting:alert-type/my-consumer/rule/deleteBackfill", + "alerting:readonly-alert-type/my-consumer/rule/get", + "alerting:readonly-alert-type/my-consumer/rule/getRuleState", + "alerting:readonly-alert-type/my-consumer/rule/getAlertSummary", + "alerting:readonly-alert-type/my-consumer/rule/getExecutionLog", + "alerting:readonly-alert-type/my-consumer/rule/getActionErrorLog", + "alerting:readonly-alert-type/my-consumer/rule/find", + "alerting:readonly-alert-type/my-consumer/rule/getRuleExecutionKPI", + "alerting:readonly-alert-type/my-consumer/rule/getBackfill", + "alerting:readonly-alert-type/my-consumer/rule/findBackfill", ] `); }); @@ -447,8 +440,8 @@ describe(`feature_privilege_builder`, () => { const privilege: FeatureKibanaPrivileges = { alerting: { alert: { - all: ['alert-type'], - read: ['readonly-alert-type'], + all: { ruleTypeIds: ['alert-type'], consumers: ['my-consumer'] }, + read: { ruleTypeIds: ['readonly-alert-type'], consumers: ['my-consumer'] }, }, }, @@ -472,15 +465,15 @@ describe(`feature_privilege_builder`, () => { expect(alertingFeaturePrivileges.getActions(privilege, feature)).toMatchInlineSnapshot(` Array [ - "alerting:alert-type/my-feature/alert/get", - "alerting:alert-type/my-feature/alert/find", - "alerting:alert-type/my-feature/alert/getAuthorizedAlertsIndices", - "alerting:alert-type/my-feature/alert/getAlertSummary", - "alerting:alert-type/my-feature/alert/update", - "alerting:readonly-alert-type/my-feature/alert/get", - "alerting:readonly-alert-type/my-feature/alert/find", - "alerting:readonly-alert-type/my-feature/alert/getAuthorizedAlertsIndices", - "alerting:readonly-alert-type/my-feature/alert/getAlertSummary", + "alerting:alert-type/my-consumer/alert/get", + "alerting:alert-type/my-consumer/alert/find", + "alerting:alert-type/my-consumer/alert/getAuthorizedAlertsIndices", + "alerting:alert-type/my-consumer/alert/getAlertSummary", + "alerting:alert-type/my-consumer/alert/update", + "alerting:readonly-alert-type/my-consumer/alert/get", + "alerting:readonly-alert-type/my-consumer/alert/find", + "alerting:readonly-alert-type/my-consumer/alert/getAuthorizedAlertsIndices", + "alerting:readonly-alert-type/my-consumer/alert/getAlertSummary", ] `); }); @@ -492,12 +485,12 @@ describe(`feature_privilege_builder`, () => { const privilege: FeatureKibanaPrivileges = { alerting: { rule: { - all: ['alert-type'], - read: ['readonly-alert-type'], + all: { ruleTypeIds: ['alert-type'], consumers: ['my-consumer'] }, + read: { ruleTypeIds: ['readonly-alert-type'], consumers: ['my-consumer'] }, }, alert: { - all: ['another-alert-type'], - read: ['readonly-alert-type'], + all: { ruleTypeIds: ['another-alert-type'], consumers: ['my-consumer'] }, + read: { ruleTypeIds: ['readonly-alert-type'], consumers: ['my-consumer'] }, }, }, @@ -521,52 +514,52 @@ describe(`feature_privilege_builder`, () => { expect(alertingFeaturePrivileges.getActions(privilege, feature)).toMatchInlineSnapshot(` Array [ - "alerting:alert-type/my-feature/rule/get", - "alerting:alert-type/my-feature/rule/getRuleState", - "alerting:alert-type/my-feature/rule/getAlertSummary", - "alerting:alert-type/my-feature/rule/getExecutionLog", - "alerting:alert-type/my-feature/rule/getActionErrorLog", - "alerting:alert-type/my-feature/rule/find", - "alerting:alert-type/my-feature/rule/getRuleExecutionKPI", - "alerting:alert-type/my-feature/rule/getBackfill", - "alerting:alert-type/my-feature/rule/findBackfill", - "alerting:alert-type/my-feature/rule/create", - "alerting:alert-type/my-feature/rule/delete", - "alerting:alert-type/my-feature/rule/update", - "alerting:alert-type/my-feature/rule/updateApiKey", - "alerting:alert-type/my-feature/rule/enable", - "alerting:alert-type/my-feature/rule/disable", - "alerting:alert-type/my-feature/rule/muteAll", - "alerting:alert-type/my-feature/rule/unmuteAll", - "alerting:alert-type/my-feature/rule/muteAlert", - "alerting:alert-type/my-feature/rule/unmuteAlert", - "alerting:alert-type/my-feature/rule/snooze", - "alerting:alert-type/my-feature/rule/bulkEdit", - "alerting:alert-type/my-feature/rule/bulkDelete", - "alerting:alert-type/my-feature/rule/bulkEnable", - "alerting:alert-type/my-feature/rule/bulkDisable", - "alerting:alert-type/my-feature/rule/unsnooze", - "alerting:alert-type/my-feature/rule/runSoon", - "alerting:alert-type/my-feature/rule/scheduleBackfill", - "alerting:alert-type/my-feature/rule/deleteBackfill", - "alerting:readonly-alert-type/my-feature/rule/get", - "alerting:readonly-alert-type/my-feature/rule/getRuleState", - "alerting:readonly-alert-type/my-feature/rule/getAlertSummary", - "alerting:readonly-alert-type/my-feature/rule/getExecutionLog", - "alerting:readonly-alert-type/my-feature/rule/getActionErrorLog", - "alerting:readonly-alert-type/my-feature/rule/find", - "alerting:readonly-alert-type/my-feature/rule/getRuleExecutionKPI", - "alerting:readonly-alert-type/my-feature/rule/getBackfill", - "alerting:readonly-alert-type/my-feature/rule/findBackfill", - "alerting:another-alert-type/my-feature/alert/get", - "alerting:another-alert-type/my-feature/alert/find", - "alerting:another-alert-type/my-feature/alert/getAuthorizedAlertsIndices", - "alerting:another-alert-type/my-feature/alert/getAlertSummary", - "alerting:another-alert-type/my-feature/alert/update", - "alerting:readonly-alert-type/my-feature/alert/get", - "alerting:readonly-alert-type/my-feature/alert/find", - "alerting:readonly-alert-type/my-feature/alert/getAuthorizedAlertsIndices", - "alerting:readonly-alert-type/my-feature/alert/getAlertSummary", + "alerting:alert-type/my-consumer/rule/get", + "alerting:alert-type/my-consumer/rule/getRuleState", + "alerting:alert-type/my-consumer/rule/getAlertSummary", + "alerting:alert-type/my-consumer/rule/getExecutionLog", + "alerting:alert-type/my-consumer/rule/getActionErrorLog", + "alerting:alert-type/my-consumer/rule/find", + "alerting:alert-type/my-consumer/rule/getRuleExecutionKPI", + "alerting:alert-type/my-consumer/rule/getBackfill", + "alerting:alert-type/my-consumer/rule/findBackfill", + "alerting:alert-type/my-consumer/rule/create", + "alerting:alert-type/my-consumer/rule/delete", + "alerting:alert-type/my-consumer/rule/update", + "alerting:alert-type/my-consumer/rule/updateApiKey", + "alerting:alert-type/my-consumer/rule/enable", + "alerting:alert-type/my-consumer/rule/disable", + "alerting:alert-type/my-consumer/rule/muteAll", + "alerting:alert-type/my-consumer/rule/unmuteAll", + "alerting:alert-type/my-consumer/rule/muteAlert", + "alerting:alert-type/my-consumer/rule/unmuteAlert", + "alerting:alert-type/my-consumer/rule/snooze", + "alerting:alert-type/my-consumer/rule/bulkEdit", + "alerting:alert-type/my-consumer/rule/bulkDelete", + "alerting:alert-type/my-consumer/rule/bulkEnable", + "alerting:alert-type/my-consumer/rule/bulkDisable", + "alerting:alert-type/my-consumer/rule/unsnooze", + "alerting:alert-type/my-consumer/rule/runSoon", + "alerting:alert-type/my-consumer/rule/scheduleBackfill", + "alerting:alert-type/my-consumer/rule/deleteBackfill", + "alerting:readonly-alert-type/my-consumer/rule/get", + "alerting:readonly-alert-type/my-consumer/rule/getRuleState", + "alerting:readonly-alert-type/my-consumer/rule/getAlertSummary", + "alerting:readonly-alert-type/my-consumer/rule/getExecutionLog", + "alerting:readonly-alert-type/my-consumer/rule/getActionErrorLog", + "alerting:readonly-alert-type/my-consumer/rule/find", + "alerting:readonly-alert-type/my-consumer/rule/getRuleExecutionKPI", + "alerting:readonly-alert-type/my-consumer/rule/getBackfill", + "alerting:readonly-alert-type/my-consumer/rule/findBackfill", + "alerting:another-alert-type/my-consumer/alert/get", + "alerting:another-alert-type/my-consumer/alert/find", + "alerting:another-alert-type/my-consumer/alert/getAuthorizedAlertsIndices", + "alerting:another-alert-type/my-consumer/alert/getAlertSummary", + "alerting:another-alert-type/my-consumer/alert/update", + "alerting:readonly-alert-type/my-consumer/alert/get", + "alerting:readonly-alert-type/my-consumer/alert/find", + "alerting:readonly-alert-type/my-consumer/alert/getAuthorizedAlertsIndices", + "alerting:readonly-alert-type/my-consumer/alert/getAlertSummary", ] `); }); diff --git a/x-pack/plugins/security/server/authorization/privileges/feature_privilege_builder/alerting.ts b/x-pack/plugins/security/server/authorization/privileges/feature_privilege_builder/alerting.ts index c0b7fa2ea8ab7b..e40ba7038467a2 100644 --- a/x-pack/plugins/security/server/authorization/privileges/feature_privilege_builder/alerting.ts +++ b/x-pack/plugins/security/server/authorization/privileges/feature_privilege_builder/alerting.ts @@ -67,23 +67,27 @@ export class FeaturePrivilegeAlertingBuilder extends BaseFeaturePrivilegeBuilder ): string[] { const getAlertingPrivilege = ( operations: string[], - privilegedTypes: readonly string[], + ruleTypeIds: readonly string[], alertingEntity: string, - consumer: string + consumers: string[] ) => - privilegedTypes.flatMap((type) => - operations.map((operation) => - this.actions.alerting.get(type, consumer, alertingEntity, operation) + ruleTypeIds.flatMap((ruleTypeId) => + consumers.flatMap((consumer) => + operations.map((operation) => + this.actions.alerting.get(ruleTypeId, consumer, alertingEntity, operation) + ) ) ); const getPrivilegesForEntity = (entity: AlertingEntity) => { - const all = get(privilegeDefinition.alerting, `${entity}.all`) ?? []; - const read = get(privilegeDefinition.alerting, `${entity}.read`) ?? []; + const allRuleTypeIds = get(privilegeDefinition.alerting, `${entity}.all.ruleTypeIds`) ?? []; + const allConsumers = get(privilegeDefinition.alerting, `${entity}.all.consumers`) ?? []; + const readRuleTypeId = get(privilegeDefinition.alerting, `${entity}.read.ruleTypeIds`) ?? []; + const readConsumers = get(privilegeDefinition.alerting, `${entity}.read.consumers`) ?? []; return uniq([ - ...getAlertingPrivilege(allOperations[entity], all, entity, feature.id), - ...getAlertingPrivilege(readOperations[entity], read, entity, feature.id), + ...getAlertingPrivilege(allOperations[entity], allRuleTypeIds, entity, allConsumers), + ...getAlertingPrivilege(readOperations[entity], readRuleTypeId, entity, readConsumers), ]); }; diff --git a/x-pack/plugins/stack_alerts/server/feature.ts b/x-pack/plugins/stack_alerts/server/feature.ts index 1a54134d2cdc13..ef91d5f3b66230 100644 --- a/x-pack/plugins/stack_alerts/server/feature.ts +++ b/x-pack/plugins/stack_alerts/server/feature.ts @@ -26,7 +26,10 @@ export const BUILT_IN_ALERTS_FEATURE: KibanaFeatureConfig = { management: { insightsAndAlerting: ['triggersActions'], }, - alerting: [IndexThreshold, GeoContainment, ElasticsearchQuery, TransformHealth], + alerting: { + ruleTypeIds: [IndexThreshold, GeoContainment, ElasticsearchQuery, TransformHealth], + consumers: [STACK_ALERTS_FEATURE_ID], + }, privileges: { all: { app: [], @@ -36,10 +39,16 @@ export const BUILT_IN_ALERTS_FEATURE: KibanaFeatureConfig = { }, alerting: { rule: { - all: [IndexThreshold, GeoContainment, ElasticsearchQuery, TransformHealth], + all: { + ruleTypeIds: [IndexThreshold, GeoContainment, ElasticsearchQuery, TransformHealth], + consumers: [STACK_ALERTS_FEATURE_ID], + }, }, alert: { - all: [IndexThreshold, GeoContainment, ElasticsearchQuery, TransformHealth], + all: { + ruleTypeIds: [IndexThreshold, GeoContainment, ElasticsearchQuery, TransformHealth], + consumers: [STACK_ALERTS_FEATURE_ID], + }, }, }, savedObject: { @@ -57,10 +66,16 @@ export const BUILT_IN_ALERTS_FEATURE: KibanaFeatureConfig = { }, alerting: { rule: { - read: [IndexThreshold, GeoContainment, ElasticsearchQuery, TransformHealth], + read: { + ruleTypeIds: [IndexThreshold, GeoContainment, ElasticsearchQuery, TransformHealth], + consumers: [STACK_ALERTS_FEATURE_ID], + }, }, alert: { - read: [IndexThreshold, GeoContainment, ElasticsearchQuery, TransformHealth], + read: { + ruleTypeIds: [IndexThreshold, GeoContainment, ElasticsearchQuery, TransformHealth], + consumers: [STACK_ALERTS_FEATURE_ID], + }, }, }, savedObject: { From c8ec120db29a72c960c2640d37b6496af9c93f6d Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Sat, 18 May 2024 19:25:46 +0300 Subject: [PATCH 002/106] Change augmentRuleTypesWithAuthorization to use consumers instead of ruleTypeIds --- .../alerting_example/server/plugin.ts | 23 +-- .../authorization/alerting_authorization.ts | 140 ++++++++++++++---- .../feature_privilege_iterator.ts | 56 +++++-- .../server/alert_data_client/alerts_client.ts | 4 +- 4 files changed, 158 insertions(+), 65 deletions(-) diff --git a/x-pack/examples/alerting_example/server/plugin.ts b/x-pack/examples/alerting_example/server/plugin.ts index 67faaf517274d9..be3d9b50f17228 100644 --- a/x-pack/examples/alerting_example/server/plugin.ts +++ b/x-pack/examples/alerting_example/server/plugin.ts @@ -41,17 +41,8 @@ export class AlertingExamplePlugin implements Plugin>; + private readonly allRuleTypeIds: Promise>; private readonly allPossibleConsumers: Promise; private readonly spaceId: string | undefined; private readonly features: FeaturesPluginStart; @@ -110,33 +111,36 @@ export class AlertingAuthorization { this.features = features; this.spaceId = getSpaceId(request); - this.featuresIds = getSpace(request) + const alertingFeaturesPromise = getSpace(request) .then((maybeSpace) => new Set(maybeSpace?.disabledFeatures ?? [])) - .then( - (disabledFeatures) => - new Set( - features - .getKibanaFeatures() - .filter( - ({ id, alerting }) => - // ignore features which are disabled in the user's space - !disabledFeatures.has(id) && - // ignore features which don't grant privileges to alerting - ((alerting?.ruleTypeIds?.length ?? 0 > 0) || - (alerting?.consumers?.length ?? 0 > 0)) - ) - .map((feature) => feature.id) - ) - ) - .catch(() => { - // failing to fetch the space means the user is likely not privileged in the - // active space at all, which means that their list of features should be empty - return new Set(); - }); + .then((disabledFeatures) => + features.getKibanaFeatures().filter( + ({ id, alerting }) => + // ignore features which are disabled in the user's space + !disabledFeatures.has(id) && + // ignore features which don't grant privileges to alerting + ((alerting?.ruleTypeIds?.length ?? 0 > 0) || (alerting?.consumers?.length ?? 0 > 0)) + ) + ); + + this.allRuleTypeIds = alertingFeaturesPromise.then( + (alertingFeatures) => + new Set( + alertingFeatures.flatMap((alertingFeature) => alertingFeature.alerting?.ruleTypeIds ?? []) + ) + ); + + this.featuresIds = alertingFeaturesPromise.then( + (alertingFeatures) => new Set(alertingFeatures.map((alertingFeature) => alertingFeature.id)) + ); - this.allPossibleConsumers = this.featuresIds.then((featuresIds) => { - return featuresIds.size - ? asAuthorizedConsumers([ALERTING_FEATURE_ID, ...featuresIds], { + this.allPossibleConsumers = alertingFeaturesPromise.then((alertingFeatures) => { + const consumers = alertingFeatures + .flatMap((alertingFeature) => alertingFeature.alerting?.consumers) + .filter(Boolean) as string[]; + + return consumers.length + ? asAuthorizedConsumers([ALERTING_FEATURE_ID, ...consumers], { read: true, all: true, }) @@ -320,6 +324,88 @@ export class AlertingAuthorization { } private async augmentRuleTypesWithAuthorization( + ruleTypes: Set, + operations: Array, + authorizationEntity: AlertingAuthorizationEntity, + consumers?: Set + ): Promise<{ + username?: string; + hasAllRequested: boolean; + authorizedRuleTypes: Set; + }> { + const allPossibleConsumers = await this.allPossibleConsumers; + const consumersToAuthorize = consumers ?? new Set(Object.keys(allPossibleConsumers)); + const requiredPrivileges = new Map< + string, + [RegistryAlertTypeWithAuth, string, HasPrivileges, IsAuthorizedAtProducerLevel] + >(); + const authorizedRuleTypes = new Set(); + + if (this.authorization && this.shouldCheckAuthorization()) { + const checkPrivileges = this.authorization.checkPrivilegesDynamicallyWithRequest( + this.request + ); + + const ruleTypesWithAuthorization = Array.from( + this.augmentWithAuthorizedConsumers(ruleTypes, {}) + ); + + for (const ruleTypeWithAuth of ruleTypesWithAuthorization) { + for (const consumerToAuthorize of consumersToAuthorize) { + for (const operation of operations) { + requiredPrivileges.set( + this.authorization!.actions.alerting.get( + ruleTypeWithAuth.id, + consumerToAuthorize, + authorizationEntity, + operation + ), + [ + ruleTypeWithAuth, + consumerToAuthorize, + hasPrivilegeByOperation(operation), + ruleTypeWithAuth.producer === consumerToAuthorize, + ] + ); + } + } + } + + const { username, hasAllRequested, privileges } = await checkPrivileges({ + kibana: [...requiredPrivileges.keys()], + }); + + for (const { authorized, privilege } of privileges.kibana) { + if (authorized && requiredPrivileges.has(privilege)) { + const [ruleType, consumer, hasPrivileges, isAuthorizedAtProducerLevel] = + requiredPrivileges.get(privilege)!; + + ruleType.authorizedConsumers[consumer] = mergeHasPrivileges( + hasPrivileges, + ruleType.authorizedConsumers[consumer] + ); + + authorizedRuleTypes.add(ruleType); + } + } + + return { + username, + hasAllRequested, + authorizedRuleTypes, + }; + } else { + return { + hasAllRequested: true, + authorizedRuleTypes: this.augmentWithAuthorizedConsumers( + new Set([...ruleTypes]), + allPossibleConsumers + ), + }; + } + } + + private async _augmentRuleTypesWithAuthorization( ruleTypes: Set, operations: Array, authorizationEntity: AlertingAuthorizationEntity, @@ -346,13 +432,17 @@ export class AlertingAuthorization { string, [RegistryAlertTypeWithAuth, string, HasPrivileges, IsAuthorizedAtProducerLevel] >(); + const allPossibleConsumers = await this.allPossibleConsumers; + const addLegacyConsumerPrivileges = (legacyConsumer: string) => legacyConsumer === ALERTING_FEATURE_ID || isEmpty(featuresIds); + for (const feature of fIds) { const featureDef = this.features .getKibanaFeatures() .find((kFeature) => kFeature.id === feature); + for (const ruleTypeId of featureDef?.alerting?.ruleTypeIds ?? []) { const ruleTypeAuth = ruleTypesWithAuthorization.find((rtwa) => rtwa.id === ruleTypeId); if (ruleTypeAuth) { diff --git a/x-pack/plugins/features/server/feature_privilege_iterator/feature_privilege_iterator.ts b/x-pack/plugins/features/server/feature_privilege_iterator/feature_privilege_iterator.ts index 0d1dc8e3ab7886..6f803abd9de37a 100644 --- a/x-pack/plugins/features/server/feature_privilege_iterator/feature_privilege_iterator.ts +++ b/x-pack/plugins/features/server/feature_privilege_iterator/feature_privilege_iterator.ts @@ -110,24 +110,48 @@ function mergeWithSubFeatures( mergedConfig.alerting = { rule: { - all: mergeArrays( - mergedConfig.alerting?.rule?.all ?? [], - subFeaturePrivilege.alerting?.rule?.all ?? [] - ), - read: mergeArrays( - mergedConfig.alerting?.rule?.read ?? [], - subFeaturePrivilege.alerting?.rule?.read ?? [] - ), + all: { + ruleTypeIds: mergeArrays( + mergedConfig.alerting?.rule?.all?.ruleTypeIds ?? [], + subFeaturePrivilege.alerting?.rule?.all?.ruleTypeIds ?? [] + ), + consumers: mergeArrays( + mergedConfig.alerting?.rule?.all?.consumers ?? [], + subFeaturePrivilege.alerting?.rule?.all?.consumers ?? [] + ), + }, + read: { + ruleTypeIds: mergeArrays( + mergedConfig.alerting?.rule?.read?.ruleTypeIds ?? [], + subFeaturePrivilege.alerting?.rule?.read?.ruleTypeIds ?? [] + ), + consumers: mergeArrays( + mergedConfig.alerting?.rule?.read?.consumers ?? [], + subFeaturePrivilege.alerting?.rule?.read?.consumers ?? [] + ), + }, }, alert: { - all: mergeArrays( - mergedConfig.alerting?.alert?.all ?? [], - subFeaturePrivilege.alerting?.alert?.all ?? [] - ), - read: mergeArrays( - mergedConfig.alerting?.alert?.read ?? [], - subFeaturePrivilege.alerting?.alert?.read ?? [] - ), + all: { + ruleTypeIds: mergeArrays( + mergedConfig.alerting?.alert?.all?.ruleTypeIds ?? [], + subFeaturePrivilege.alerting?.alert?.all?.ruleTypeIds ?? [] + ), + consumers: mergeArrays( + mergedConfig.alerting?.alert?.all?.consumers ?? [], + subFeaturePrivilege.alerting?.alert?.all?.consumers ?? [] + ), + }, + read: { + ruleTypeIds: mergeArrays( + mergedConfig.alerting?.alert?.read?.ruleTypeIds ?? [], + subFeaturePrivilege.alerting?.alert?.read?.ruleTypeIds ?? [] + ), + consumers: mergeArrays( + mergedConfig.alerting?.alert?.read?.consumers ?? [], + subFeaturePrivilege.alerting?.alert?.read?.consumers ?? [] + ), + }, }, }; diff --git a/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts b/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts index 0c449d4f4126a8..b7d2e3b2e8b14b 100644 --- a/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts +++ b/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts @@ -1028,11 +1028,11 @@ export class AlertsClient { } } - public async getAuthorizedAlertsIndices(featureIds: string[]): Promise { + public async getAuthorizedAlertsIndices(consumers: string[]): Promise { try { const authorizedRuleTypes = await this.authorization.getAuthorizedRuleTypes( AlertingAuthorizationEntity.Alert, - new Set(featureIds) + new Set(consumers) ); const indices = this.getAlertIndicesAlias( authorizedRuleTypes.map((art: { id: any }) => art.id), From 1a02609de865032fcbda8474b539b0960e028cc0 Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Sat, 18 May 2024 19:30:27 +0300 Subject: [PATCH 003/106] Support legacy consumers --- .../authorization/alerting_authorization.ts | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/x-pack/plugins/alerting/server/authorization/alerting_authorization.ts b/x-pack/plugins/alerting/server/authorization/alerting_authorization.ts index 7e7da0eef0207d..c97d2b3606b429 100644 --- a/x-pack/plugins/alerting/server/authorization/alerting_authorization.ts +++ b/x-pack/plugins/alerting/server/authorization/alerting_authorization.ts @@ -341,6 +341,9 @@ export class AlertingAuthorization { >(); const authorizedRuleTypes = new Set(); + const addLegacyConsumerPrivileges = (legacyConsumer: string) => + legacyConsumer === ALERTING_FEATURE_ID || isEmpty(consumers); + if (this.authorization && this.shouldCheckAuthorization()) { const checkPrivileges = this.authorization.checkPrivilegesDynamicallyWithRequest( this.request @@ -367,6 +370,32 @@ export class AlertingAuthorization { ruleTypeWithAuth.producer === consumerToAuthorize, ] ); + + // FUTURE ENGINEER + // We are just trying to add back the legacy consumers associated + // to the rule type to get back the privileges that was given at one point + if (!isEmpty(ruleTypeWithAuth.validLegacyConsumers)) { + ruleTypeWithAuth.validLegacyConsumers.forEach((legacyConsumer) => { + if (addLegacyConsumerPrivileges(legacyConsumer)) { + if (!allPossibleConsumers[legacyConsumer]) { + allPossibleConsumers[legacyConsumer] = { + read: true, + all: true, + }; + } + + requiredPrivileges.set( + this.authorization!.actions.alerting.get( + ruleTypeWithAuth.id, + legacyConsumer, + authorizationEntity, + operation + ), + [ruleTypeWithAuth, legacyConsumer, hasPrivilegeByOperation(operation), false] + ); + } + }); + } } } } From 55f91fdf9f5c47264b1007255f3c82ee032f9320 Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Mon, 20 May 2024 15:52:27 +0300 Subject: [PATCH 004/106] Fixes in rule filtering --- .../alerting_authorization.test.ts | 108 +++++++++-- .../authorization/alerting_authorization.ts | 183 +++--------------- 2 files changed, 116 insertions(+), 175 deletions(-) diff --git a/x-pack/plugins/alerting/server/authorization/alerting_authorization.test.ts b/x-pack/plugins/alerting/server/authorization/alerting_authorization.test.ts index da2774e263b582..b0b0801f5b0435 100644 --- a/x-pack/plugins/alerting/server/authorization/alerting_authorization.test.ts +++ b/x-pack/plugins/alerting/server/authorization/alerting_authorization.test.ts @@ -34,11 +34,12 @@ const getSpace = jest.fn(); const getSpaceId = () => 'space1'; const mockAuthorizationAction = ( - type: string, - app: string, - alertingType: string, + ruleType: string, + consumer: string, + entity: string, operation: string -) => `${type}/${app}/${alertingType}/${operation}`; +) => `${ruleType}/${consumer}/${entity}/${operation}`; + function mockSecurity() { const security = securityMock.createSetup(); const authorization = security.authz; @@ -61,7 +62,7 @@ function mockFeature(appName: string, typeName?: string | string[]) { category: { id: 'foo', label: 'foo' }, ...(typeNameArray ? { - alerting: typeNameArray, + alerting: { ruleTypeIds: typeNameArray, consumers: [appName] }, } : {}), privileges: { @@ -70,10 +71,10 @@ function mockFeature(appName: string, typeName?: string | string[]) { ? { alerting: { rule: { - all: typeNameArray, + all: { ruleTypeIds: typeNameArray, consumers: [appName] }, }, alert: { - all: typeNameArray, + all: { ruleTypeIds: typeNameArray, consumers: [appName] }, }, }, } @@ -89,10 +90,10 @@ function mockFeature(appName: string, typeName?: string | string[]) { ? { alerting: { rule: { - read: typeNameArray, + read: { ruleTypeIds: typeNameArray, consumers: [appName] }, }, alert: { - read: typeNameArray, + read: { ruleTypeIds: typeNameArray, consumers: [appName] }, }, }, } @@ -115,7 +116,7 @@ function mockFeatureWithSubFeature(appName: string, typeName: string) { category: { id: 'foo', label: 'foo' }, ...(typeName ? { - alerting: [typeName], + alerting: { ruleTypeIds: [typeName], consumers: [appName] }, } : {}), privileges: { @@ -147,7 +148,7 @@ function mockFeatureWithSubFeature(appName: string, typeName: string) { includeIn: 'all', alerting: { rule: { - all: [typeName], + all: { ruleTypeIds: [typeName], consumers: [appName] }, }, }, savedObject: { @@ -162,7 +163,7 @@ function mockFeatureWithSubFeature(appName: string, typeName: string) { includeIn: 'read', alerting: { rule: { - read: [typeName], + read: { ruleTypeIds: [typeName], consumers: [appName] }, }, }, savedObject: { @@ -884,6 +885,7 @@ describe('AlertingAuthorization', () => { ); ensureRuleTypeIsAuthorized('someMadeUpType', 'myApp', 'rule'); }); + test('creates a filter based on the privileged types', async () => { features.getKibanaFeatures.mockReturnValue([ mockFeature('myApp', ['myAppAlertType', 'mySecondAppAlertType']), @@ -899,7 +901,83 @@ describe('AlertingAuthorization', () => { checkPrivileges.mockResolvedValueOnce({ username: 'some-user', hasAllRequested: true, - privileges: { kibana: [] }, + privileges: { + kibana: [ + { + privilege: mockAuthorizationAction('myAppAlertType', 'alerts', 'rule', 'find'), + authorized: true, + }, + { + privilege: mockAuthorizationAction('myAppAlertType', 'myApp', 'rule', 'find'), + authorized: true, + }, + { + privilege: mockAuthorizationAction('myAppAlertType', 'myOtherApp', 'rule', 'find'), + authorized: true, + }, + { + privilege: mockAuthorizationAction( + 'myAppAlertType', + 'myAppWithSubFeature', + 'rule', + 'find' + ), + authorized: true, + }, + { + privilege: mockAuthorizationAction('myOtherAppAlertType', 'alerts', 'rule', 'find'), + authorized: true, + }, + { + privilege: mockAuthorizationAction('myOtherAppAlertType', 'myApp', 'rule', 'find'), + authorized: true, + }, + { + privilege: mockAuthorizationAction( + 'myOtherAppAlertType', + 'myOtherApp', + 'rule', + 'find' + ), + authorized: true, + }, + { + privilege: mockAuthorizationAction( + 'myOtherAppAlertType', + 'myAppWithSubFeature', + 'rule', + 'find' + ), + authorized: true, + }, + { + privilege: mockAuthorizationAction('mySecondAppAlertType', 'alerts', 'rule', 'find'), + authorized: true, + }, + { + privilege: mockAuthorizationAction('mySecondAppAlertType', 'myApp', 'rule', 'find'), + authorized: true, + }, + { + privilege: mockAuthorizationAction( + 'mySecondAppAlertType', + 'myOtherApp', + 'rule', + 'find' + ), + authorized: true, + }, + { + privilege: mockAuthorizationAction( + 'mySecondAppAlertType', + 'myAppWithSubFeature', + 'rule', + 'find' + ), + authorized: true, + }, + ], + }, }); const alertAuthorization = new AlertingAuthorization({ request, @@ -922,7 +1000,7 @@ describe('AlertingAuthorization', () => { ).filter ).toEqual( fromKueryExpression( - `((path.to.rule_type_id:myAppAlertType and consumer-field:(alerts or myApp or myOtherApp or myAppWithSubFeature)) or (path.to.rule_type_id:mySecondAppAlertType and consumer-field:(alerts or myApp or myOtherApp or myAppWithSubFeature)) or (path.to.rule_type_id:myOtherAppAlertType and consumer-field:(alerts or myApp or myOtherApp or myAppWithSubFeature)))` + `((path.to.rule_type_id:myAppAlertType and consumer-field:(alerts or myApp or myOtherApp or myAppWithSubFeature)) or (path.to.rule_type_id:myOtherAppAlertType and consumer-field:(alerts or myApp or myOtherApp or myAppWithSubFeature)) or (path.to.rule_type_id:mySecondAppAlertType and consumer-field:(alerts or myApp or myOtherApp or myAppWithSubFeature)))` ) ); }); @@ -969,6 +1047,7 @@ describe('AlertingAuthorization', () => { `"Unauthorized to find rules for any rule types"` ); }); + test('creates an `ensureRuleTypeIsAuthorized` function which throws if type is unauthorized', async () => { features.getKibanaFeatures.mockReturnValue([ mockFeature('myApp', ['myOtherAppAlertType', 'myAppAlertType']), @@ -2250,6 +2329,7 @@ describe('AlertingAuthorization', () => { expect(ruleTypeRegistry.get).toHaveBeenCalledTimes(1); }); }); + test('creates a filter based on the privileged types', async () => { expect( ( diff --git a/x-pack/plugins/alerting/server/authorization/alerting_authorization.ts b/x-pack/plugins/alerting/server/authorization/alerting_authorization.ts index c97d2b3606b429..b67b986ef7d727 100644 --- a/x-pack/plugins/alerting/server/authorization/alerting_authorization.ts +++ b/x-pack/plugins/alerting/server/authorization/alerting_authorization.ts @@ -92,11 +92,8 @@ export class AlertingAuthorization { private readonly ruleTypeRegistry: RuleTypeRegistry; private readonly request: KibanaRequest; private readonly authorization?: SecurityPluginSetup['authz']; - private readonly featuresIds: Promise>; - private readonly allRuleTypeIds: Promise>; private readonly allPossibleConsumers: Promise; private readonly spaceId: string | undefined; - private readonly features: FeaturesPluginStart; constructor({ ruleTypeRegistry, request, @@ -108,7 +105,6 @@ export class AlertingAuthorization { this.request = request; this.authorization = authorization; this.ruleTypeRegistry = ruleTypeRegistry; - this.features = features; this.spaceId = getSpaceId(request); const alertingFeaturesPromise = getSpace(request) @@ -123,17 +119,6 @@ export class AlertingAuthorization { ) ); - this.allRuleTypeIds = alertingFeaturesPromise.then( - (alertingFeatures) => - new Set( - alertingFeatures.flatMap((alertingFeature) => alertingFeature.alerting?.ruleTypeIds ?? []) - ) - ); - - this.featuresIds = alertingFeaturesPromise.then( - (alertingFeatures) => new Set(alertingFeatures.map((alertingFeature) => alertingFeature.id)) - ); - this.allPossibleConsumers = alertingFeaturesPromise.then((alertingFeatures) => { const consumers = alertingFeatures .flatMap((alertingFeature) => alertingFeature.alerting?.consumers) @@ -409,168 +394,44 @@ export class AlertingAuthorization { const [ruleType, consumer, hasPrivileges, isAuthorizedAtProducerLevel] = requiredPrivileges.get(privilege)!; - ruleType.authorizedConsumers[consumer] = mergeHasPrivileges( - hasPrivileges, - ruleType.authorizedConsumers[consumer] - ); - - authorizedRuleTypes.add(ruleType); - } - } - - return { - username, - hasAllRequested, - authorizedRuleTypes, - }; - } else { - return { - hasAllRequested: true, - authorizedRuleTypes: this.augmentWithAuthorizedConsumers( - new Set([...ruleTypes]), - allPossibleConsumers - ), - }; - } - } - - private async _augmentRuleTypesWithAuthorization( - ruleTypes: Set, - operations: Array, - authorizationEntity: AlertingAuthorizationEntity, - featuresIds?: Set - ): Promise<{ - username?: string; - hasAllRequested: boolean; - authorizedRuleTypes: Set; - }> { - const fIds = featuresIds ?? (await this.featuresIds); - if (this.authorization && this.shouldCheckAuthorization()) { - const checkPrivileges = this.authorization.checkPrivilegesDynamicallyWithRequest( - this.request - ); + if (consumersToAuthorize.has(consumer)) { + ruleType.authorizedConsumers[consumer] = mergeHasPrivileges( + hasPrivileges, + ruleType.authorizedConsumers[consumer] + ); - // add an empty `authorizedConsumers` array on each ruleType - const ruleTypesWithAuthorization = Array.from( - this.augmentWithAuthorizedConsumers(ruleTypes, {}) - ); - const ruleTypesAuthorized: Map = new Map(); - // map from privilege to ruleType which we can refer back to when analyzing the result - // of checkPrivileges - const privilegeToRuleType = new Map< - string, - [RegistryAlertTypeWithAuth, string, HasPrivileges, IsAuthorizedAtProducerLevel] - >(); - - const allPossibleConsumers = await this.allPossibleConsumers; - - const addLegacyConsumerPrivileges = (legacyConsumer: string) => - legacyConsumer === ALERTING_FEATURE_ID || isEmpty(featuresIds); - - for (const feature of fIds) { - const featureDef = this.features - .getKibanaFeatures() - .find((kFeature) => kFeature.id === feature); - - for (const ruleTypeId of featureDef?.alerting?.ruleTypeIds ?? []) { - const ruleTypeAuth = ruleTypesWithAuthorization.find((rtwa) => rtwa.id === ruleTypeId); - if (ruleTypeAuth) { - if (!ruleTypesAuthorized.has(ruleTypeId)) { - ruleTypesAuthorized.set(ruleTypeId, ruleTypeAuth); - } - for (const operation of operations) { - privilegeToRuleType.set( - this.authorization!.actions.alerting.get( - ruleTypeId, - feature, - authorizationEntity, - operation - ), - [ - ruleTypeAuth, - feature, - hasPrivilegeByOperation(operation), - ruleTypeAuth.producer === feature, - ] - ); - // FUTURE ENGINEER - // We are just trying to add back the legacy consumers associated - // to the rule type to get back the privileges that was given at one point - if (!isEmpty(ruleTypeAuth.validLegacyConsumers)) { - ruleTypeAuth.validLegacyConsumers.forEach((legacyConsumer) => { - if (addLegacyConsumerPrivileges(legacyConsumer)) { - if (!allPossibleConsumers[legacyConsumer]) { - allPossibleConsumers[legacyConsumer] = { - read: true, - all: true, - }; - } - - privilegeToRuleType.set( - this.authorization!.actions.alerting.get( - ruleTypeId, - legacyConsumer, - authorizationEntity, - operation - ), - [ruleTypeAuth, legacyConsumer, hasPrivilegeByOperation(operation), false] - ); - } - }); - } + if (isAuthorizedAtProducerLevel) { + // granting privileges under the producer automatically authorized the Rules Management UI as well + ruleType.validLegacyConsumers.forEach((legacyConsumer) => { + if (addLegacyConsumerPrivileges(legacyConsumer)) { + ruleType.authorizedConsumers[legacyConsumer] = mergeHasPrivileges( + hasPrivileges, + ruleType.authorizedConsumers[legacyConsumer] + ); + } + }); } + + authorizedRuleTypes.add(ruleType); } } } - const { username, hasAllRequested, privileges } = await checkPrivileges({ - kibana: [...privilegeToRuleType.keys()], - }); - return { username, hasAllRequested, authorizedRuleTypes: - hasAllRequested && featuresIds === undefined + hasAllRequested && consumers === undefined ? // has access to all features - this.augmentWithAuthorizedConsumers( - new Set(ruleTypesAuthorized.values()), - allPossibleConsumers - ) - : // only has some of the required privileges - privileges.kibana.reduce((authorizedRuleTypes, { authorized, privilege }) => { - if (authorized && privilegeToRuleType.has(privilege)) { - const [ruleType, feature, hasPrivileges, isAuthorizedAtProducerLevel] = - privilegeToRuleType.get(privilege)!; - if (fIds.has(feature)) { - ruleType.authorizedConsumers[feature] = mergeHasPrivileges( - hasPrivileges, - ruleType.authorizedConsumers[feature] - ); - - if (isAuthorizedAtProducerLevel) { - // granting privileges under the producer automatically authorized the Rules Management UI as well - ruleType.validLegacyConsumers.forEach((legacyConsumer) => { - if (addLegacyConsumerPrivileges(legacyConsumer)) { - ruleType.authorizedConsumers[legacyConsumer] = mergeHasPrivileges( - hasPrivileges, - ruleType.authorizedConsumers[legacyConsumer] - ); - } - }); - } - authorizedRuleTypes.add(ruleType); - } - } - return authorizedRuleTypes; - }, new Set()), + this.augmentWithAuthorizedConsumers(authorizedRuleTypes, allPossibleConsumers) + : authorizedRuleTypes, }; } else { return { hasAllRequested: true, authorizedRuleTypes: this.augmentWithAuthorizedConsumers( - new Set([...ruleTypes].filter((ruleType) => fIds.has(ruleType.producer))), - await this.allPossibleConsumers + new Set([...ruleTypes].filter((ruleType) => consumersToAuthorize.has(ruleType.producer))), + allPossibleConsumers ), }; } From 3b7c89fbe90bd894e5c2ad647233d5a1a198f0c9 Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Thu, 23 May 2024 18:24:53 +0300 Subject: [PATCH 005/106] Change new schema --- .../alerting_example/server/plugin.ts | 45 +++++++----- .../features/src/security/kibana_features.ts | 19 ++--- .../authorization/alerting_authorization.ts | 11 ++- .../common/feature_kibana_privileges.ts | 8 +- .../plugins/features/common/kibana_feature.ts | 2 +- .../feature_privilege_iterator.ts | 73 +++++++++---------- .../plugins/features/server/feature_schema.ts | 49 +++++++------ .../plugins/ml/common/types/capabilities.ts | 13 +++- x-pack/plugins/ml/server/plugin.ts | 5 +- x-pack/plugins/monitoring/server/plugin.ts | 11 ++- .../apm/server/feature.ts | 15 ++-- .../infra/server/features.ts | 30 +++++--- .../observability/server/plugin.ts | 15 ++-- .../slo/server/plugin.ts | 15 ++-- .../synthetics/server/feature.ts | 15 ++-- .../alerting.test.ts | 56 +++++++------- .../feature_privilege_builder/alerting.ts | 17 ++--- x-pack/plugins/stack_alerts/server/feature.ts | 32 +++----- 18 files changed, 235 insertions(+), 196 deletions(-) diff --git a/x-pack/examples/alerting_example/server/plugin.ts b/x-pack/examples/alerting_example/server/plugin.ts index be3d9b50f17228..f02580e78f702d 100644 --- a/x-pack/examples/alerting_example/server/plugin.ts +++ b/x-pack/examples/alerting_example/server/plugin.ts @@ -75,24 +75,27 @@ export class AlertingExamplePlugin implements Plugin ({ + ruleTypeId, + consumers: [SERVER_APP_ID], +})); + export const getSecurityBaseKibanaFeature = ({ savedObjects, }: SecurityFeatureParams): BaseKibanaFeatureConfig => ({ @@ -57,7 +62,7 @@ export const getSecurityBaseKibanaFeature = ({ management: { insightsAndAlerting: ['triggersActions'], }, - alerting: { ruleTypeIds: SECURITY_RULE_TYPES, consumers: [SERVER_APP_ID] }, + alerting: alertingFeatures, privileges: { all: { app: [APP_ID, CLOUD_POSTURE_APP_ID, CLOUD_DEFEND_APP_ID, 'kibana'], @@ -78,12 +83,8 @@ export const getSecurityBaseKibanaFeature = ({ read: [], }, alerting: { - rule: { - all: { ruleTypeIds: SECURITY_RULE_TYPES, consumers: [SERVER_APP_ID] }, - }, - alert: { - all: { ruleTypeIds: SECURITY_RULE_TYPES, consumers: [SERVER_APP_ID] }, - }, + rule: { all: alertingFeatures }, + alert: { all: alertingFeatures }, }, management: { insightsAndAlerting: ['triggersActions'], @@ -100,10 +101,10 @@ export const getSecurityBaseKibanaFeature = ({ }, alerting: { rule: { - read: { ruleTypeIds: SECURITY_RULE_TYPES, consumers: [SERVER_APP_ID] }, + read: alertingFeatures, }, alert: { - all: { ruleTypeIds: SECURITY_RULE_TYPES, consumers: [SERVER_APP_ID] }, + all: alertingFeatures, }, }, management: { diff --git a/x-pack/plugins/alerting/server/authorization/alerting_authorization.ts b/x-pack/plugins/alerting/server/authorization/alerting_authorization.ts index b67b986ef7d727..b3761fc63b4454 100644 --- a/x-pack/plugins/alerting/server/authorization/alerting_authorization.ts +++ b/x-pack/plugins/alerting/server/authorization/alerting_authorization.ts @@ -115,14 +115,17 @@ export class AlertingAuthorization { // ignore features which are disabled in the user's space !disabledFeatures.has(id) && // ignore features which don't grant privileges to alerting - ((alerting?.ruleTypeIds?.length ?? 0 > 0) || (alerting?.consumers?.length ?? 0 > 0)) + (alerting?.length ?? 0 > 0) ) ); this.allPossibleConsumers = alertingFeaturesPromise.then((alertingFeatures) => { - const consumers = alertingFeatures - .flatMap((alertingFeature) => alertingFeature.alerting?.consumers) - .filter(Boolean) as string[]; + const consumers = alertingFeatures.flatMap( + (alertingFeature) => + alertingFeature.alerting + ?.flatMap((feature) => feature.consumers ?? []) + .filter(Boolean) as string[] + ); return consumers.length ? asAuthorizedConsumers([ALERTING_FEATURE_ID, ...consumers], { diff --git a/x-pack/plugins/features/common/feature_kibana_privileges.ts b/x-pack/plugins/features/common/feature_kibana_privileges.ts index 74811f56e85824..5083ae7450d748 100644 --- a/x-pack/plugins/features/common/feature_kibana_privileges.ts +++ b/x-pack/plugins/features/common/feature_kibana_privileges.ts @@ -103,7 +103,7 @@ export interface FeatureKibanaPrivileges { * } * ``` */ - all?: { ruleTypeIds?: readonly string[]; consumers?: readonly string[] }; + all?: ReadonlyArray<{ ruleTypeId: string; consumers: readonly string[] }>; /** * List of rule types which users should have read-only access to when granted this privilege. * @example @@ -113,7 +113,7 @@ export interface FeatureKibanaPrivileges { * } * ``` */ - read?: { ruleTypeIds?: readonly string[]; consumers?: readonly string[] }; + read?: ReadonlyArray<{ ruleTypeId: string; consumers: readonly string[] }>; }; alert?: { /** @@ -125,7 +125,7 @@ export interface FeatureKibanaPrivileges { * } * ``` */ - all?: { ruleTypeIds?: readonly string[]; consumers?: readonly string[] }; + all?: ReadonlyArray<{ ruleTypeId: string; consumers: readonly string[] }>; /** * List of rule types for which users should have read-only access to their alert data when granted this privilege. * @example @@ -135,7 +135,7 @@ export interface FeatureKibanaPrivileges { * } * ``` */ - read?: { ruleTypeIds?: readonly string[]; consumers?: readonly string[] }; + read?: ReadonlyArray<{ ruleTypeId: string; consumers: readonly string[] }>; }; }; diff --git a/x-pack/plugins/features/common/kibana_feature.ts b/x-pack/plugins/features/common/kibana_feature.ts index 34d45122dafac8..3d30e7fd06022e 100644 --- a/x-pack/plugins/features/common/kibana_feature.ts +++ b/x-pack/plugins/features/common/kibana_feature.ts @@ -101,7 +101,7 @@ export interface KibanaFeatureConfig { * Include both Alert Types registered by the feature and external Alert Types such as built-in * Alert Types and Alert Types provided by other features to which you wish to grant access. */ - alerting?: { ruleTypeIds?: readonly string[]; consumers?: readonly string[] }; + alerting?: ReadonlyArray<{ ruleTypeId: string; consumers: readonly string[] }>; /** * If your feature grants access to specific case types, you can specify them here to control visibility based on the current space. diff --git a/x-pack/plugins/features/server/feature_privilege_iterator/feature_privilege_iterator.ts b/x-pack/plugins/features/server/feature_privilege_iterator/feature_privilege_iterator.ts index 6f803abd9de37a..19a4cfacb9a81a 100644 --- a/x-pack/plugins/features/server/feature_privilege_iterator/feature_privilege_iterator.ts +++ b/x-pack/plugins/features/server/feature_privilege_iterator/feature_privilege_iterator.ts @@ -108,50 +108,43 @@ function mergeWithSubFeatures( subFeaturePrivilege.savedObject.read ); + const mergeAlertingEntries = ( + entries: ReadonlyArray<{ ruleTypeId: string; consumers: readonly string[] }> + ): ReadonlyArray<{ ruleTypeId: string; consumers: readonly string[] }> => { + const alertingMap = new Map>(); + + for (const entry of entries) { + const consumers = alertingMap.get(entry.ruleTypeId) ?? new Set(); + entry.consumers.forEach((consumer) => consumers.add(consumer)); + alertingMap.set(entry.ruleTypeId, consumers); + } + + return Array.from(alertingMap).map(([ruleTypeId, consumers]) => ({ + ruleTypeId, + consumers: Array.from(consumers), + })); + }; + mergedConfig.alerting = { rule: { - all: { - ruleTypeIds: mergeArrays( - mergedConfig.alerting?.rule?.all?.ruleTypeIds ?? [], - subFeaturePrivilege.alerting?.rule?.all?.ruleTypeIds ?? [] - ), - consumers: mergeArrays( - mergedConfig.alerting?.rule?.all?.consumers ?? [], - subFeaturePrivilege.alerting?.rule?.all?.consumers ?? [] - ), - }, - read: { - ruleTypeIds: mergeArrays( - mergedConfig.alerting?.rule?.read?.ruleTypeIds ?? [], - subFeaturePrivilege.alerting?.rule?.read?.ruleTypeIds ?? [] - ), - consumers: mergeArrays( - mergedConfig.alerting?.rule?.read?.consumers ?? [], - subFeaturePrivilege.alerting?.rule?.read?.consumers ?? [] - ), - }, + all: mergeAlertingEntries([ + ...(mergedConfig.alerting?.rule?.all ?? []), + ...(subFeaturePrivilege.alerting?.rule?.all ?? []), + ]), + read: mergeAlertingEntries([ + ...(mergedConfig.alerting?.rule?.read ?? []), + ...(subFeaturePrivilege.alerting?.rule?.read ?? []), + ]), }, alert: { - all: { - ruleTypeIds: mergeArrays( - mergedConfig.alerting?.alert?.all?.ruleTypeIds ?? [], - subFeaturePrivilege.alerting?.alert?.all?.ruleTypeIds ?? [] - ), - consumers: mergeArrays( - mergedConfig.alerting?.alert?.all?.consumers ?? [], - subFeaturePrivilege.alerting?.alert?.all?.consumers ?? [] - ), - }, - read: { - ruleTypeIds: mergeArrays( - mergedConfig.alerting?.alert?.read?.ruleTypeIds ?? [], - subFeaturePrivilege.alerting?.alert?.read?.ruleTypeIds ?? [] - ), - consumers: mergeArrays( - mergedConfig.alerting?.alert?.read?.consumers ?? [], - subFeaturePrivilege.alerting?.alert?.read?.consumers ?? [] - ), - }, + all: mergeAlertingEntries([ + ...(mergedConfig.alerting?.alert?.all ?? []), + ...(subFeaturePrivilege.alerting?.alert?.all ?? []), + ]), + read: mergeAlertingEntries([ + ...(mergedConfig.alerting?.alert?.read ?? []), + ...(subFeaturePrivilege.alerting?.alert?.read ?? []), + ]), }, }; diff --git a/x-pack/plugins/features/server/feature_schema.ts b/x-pack/plugins/features/server/feature_schema.ts index fb26984d439c12..388f609965596a 100644 --- a/x-pack/plugins/features/server/feature_schema.ts +++ b/x-pack/plugins/features/server/feature_schema.ts @@ -63,10 +63,13 @@ const managementSchema = schema.recordOf( listOfCapabilitiesSchema ); const catalogueSchema = listOfCapabilitiesSchema; -const alertingSchema = schema.object({ - ruleTypeIds: schema.maybe(schema.arrayOf(schema.string())), - consumers: schema.maybe(schema.arrayOf(schema.string())), -}); +const alertingSchema = schema.arrayOf( + schema.object({ + ruleTypeId: schema.string(), + consumers: schema.arrayOf(schema.string()), + }) +); + const casesSchema = schema.arrayOf(schema.string()); const appCategorySchema = schema.object({ @@ -277,13 +280,7 @@ export function validateKibanaFeature(feature: KibanaFeatureConfig) { kibanaFeatureSchema.validate(feature); // the following validation can't be enforced by the Joi schema, since it'd require us looking "up" the object graph for the list of valid value, which they explicitly forbid. - const { - app = [], - management = {}, - catalogue = [], - alerting: { ruleTypeIds = [], consumers = [] } = {}, - cases = [], - } = feature; + const { app = [], management = {}, catalogue = [], alerting = [], cases = [] } = feature; const unseenApps = new Set(app); @@ -296,7 +293,9 @@ export function validateKibanaFeature(feature: KibanaFeatureConfig) { const unseenCatalogue = new Set(catalogue); - const unseenAlertTypes = new Set([...ruleTypeIds, ...consumers]); + const unseenAlertTypes = new Set( + alerting.flatMap(({ ruleTypeId, consumers }) => [ruleTypeId, ...consumers]) + ); const unseenCasesTypes = new Set(cases); @@ -327,23 +326,31 @@ export function validateKibanaFeature(feature: KibanaFeatureConfig) { } function validateAlertingEntry(privilegeId: string, entry: FeatureKibanaPrivileges['alerting']) { + const getRuleTypeIdAndConsumers = ({ + ruleTypeId, + consumers, + }: { + ruleTypeId: string; + consumers: readonly string[]; + }) => [ruleTypeId, ...consumers]; + const all: string[] = [ - ...(entry?.rule?.all?.consumers ?? []), - ...(entry?.rule?.all?.ruleTypeIds ?? []), - ...(entry?.alert?.all?.consumers ?? []), - ...(entry?.alert?.all?.ruleTypeIds ?? []), + ...(entry?.rule?.all?.flatMap(getRuleTypeIdAndConsumers) ?? []), + ...(entry?.alert?.all?.flatMap(getRuleTypeIdAndConsumers) ?? []), ]; const read: string[] = [ - ...(entry?.rule?.read?.consumers ?? []), - ...(entry?.rule?.read?.ruleTypeIds ?? []), - ...(entry?.alert?.read?.consumers ?? []), - ...(entry?.alert?.read?.ruleTypeIds ?? []), + ...(entry?.rule?.read?.flatMap(getRuleTypeIdAndConsumers) ?? []), + ...(entry?.alert?.read?.flatMap(getRuleTypeIdAndConsumers) ?? []), ]; all.forEach((privilegeAlertTypes) => unseenAlertTypes.delete(privilegeAlertTypes)); read.forEach((privilegeAlertTypes) => unseenAlertTypes.delete(privilegeAlertTypes)); - const unknownAlertingEntries = difference([...all, ...read], [...ruleTypeIds, ...consumers]); + const unknownAlertingEntries = difference( + [...all, ...read], + alerting.flatMap(({ ruleTypeId, consumers }) => [ruleTypeId, ...consumers]) + ); + if (unknownAlertingEntries.length > 0) { throw new Error( `Feature privilege ${ diff --git a/x-pack/plugins/ml/common/types/capabilities.ts b/x-pack/plugins/ml/common/types/capabilities.ts index c2c25515b105f8..ff97c4f7159d93 100644 --- a/x-pack/plugins/ml/common/types/capabilities.ts +++ b/x-pack/plugins/ml/common/types/capabilities.ts @@ -108,6 +108,11 @@ export function getDefaultCapabilities(): MlCapabilities { }; } +const alertingFeatures = Object.values(ML_ALERT_TYPES).map((ruleTypeId) => ({ + ruleTypeId, + consumers: [PLUGIN_ID], +})); + export function getPluginPrivileges() { const apmUserMlCapabilitiesKeys = Object.keys(apmUserMlCapabilities); const userMlCapabilitiesKeys = Object.keys(userMlCapabilities); @@ -149,10 +154,10 @@ export function getPluginPrivileges() { }, alerting: { rule: { - all: { ruleTypeIds: Object.values(ML_ALERT_TYPES), consumers: [PLUGIN_ID] }, + all: alertingFeatures, }, alert: { - all: { ruleTypeIds: Object.values(ML_ALERT_TYPES), consumers: [PLUGIN_ID] }, + all: alertingFeatures, }, }, }, @@ -171,10 +176,10 @@ export function getPluginPrivileges() { }, alerting: { rule: { - read: { ruleTypeIds: Object.values(ML_ALERT_TYPES), consumers: [PLUGIN_ID] }, + read: alertingFeatures, }, alert: { - read: { ruleTypeIds: Object.values(ML_ALERT_TYPES), consumers: [PLUGIN_ID] }, + read: alertingFeatures, }, }, }, diff --git a/x-pack/plugins/ml/server/plugin.ts b/x-pack/plugins/ml/server/plugin.ts index c035ae14d2a021..487faffa84515c 100644 --- a/x-pack/plugins/ml/server/plugin.ts +++ b/x-pack/plugins/ml/server/plugin.ts @@ -139,7 +139,10 @@ export class MlServerPlugin management: { insightsAndAlerting: ['jobsListLink', 'triggersActions'], }, - alerting: { ruleTypeIds: Object.values(ML_ALERT_TYPES), consumers: [PLUGIN_ID] }, + alerting: Object.values(ML_ALERT_TYPES).map((ruleTypeId) => ({ + ruleTypeId, + consumers: [PLUGIN_ID], + })), privileges: { all: admin, read: user, diff --git a/x-pack/plugins/monitoring/server/plugin.ts b/x-pack/plugins/monitoring/server/plugin.ts index a86361467dcd61..1e98695be420d9 100644 --- a/x-pack/plugins/monitoring/server/plugin.ts +++ b/x-pack/plugins/monitoring/server/plugin.ts @@ -266,6 +266,11 @@ export class MonitoringPlugin } registerPluginInUI(plugins: PluginsSetup) { + const alertingFeatures = RULES.map((ruleTypeId) => ({ + ruleTypeId, + consumers: ['monitoring'], + })); + plugins.features.registerKibanaFeature({ id: 'monitoring', name: i18n.translate('xpack.monitoring.featureRegistry.monitoringFeatureName', { @@ -275,7 +280,7 @@ export class MonitoringPlugin app: ['monitoring', 'kibana'], catalogue: ['monitoring'], privileges: null, - alerting: { ruleTypeIds: RULES, consumers: ['monitoring'] }, + alerting: alertingFeatures, reserved: { description: i18n.translate('xpack.monitoring.feature.reserved.description', { defaultMessage: 'To grant users access, you should also assign the monitoring_user role.', @@ -292,10 +297,10 @@ export class MonitoringPlugin }, alerting: { rule: { - all: { ruleTypeIds: RULES, consumers: ['monitoring'] }, + all: alertingFeatures, }, alert: { - all: { ruleTypeIds: RULES, consumers: ['monitoring'] }, + all: alertingFeatures, }, }, ui: [], diff --git a/x-pack/plugins/observability_solution/apm/server/feature.ts b/x-pack/plugins/observability_solution/apm/server/feature.ts index f186ef1e2c03f1..57e9b7fc2a3b5d 100644 --- a/x-pack/plugins/observability_solution/apm/server/feature.ts +++ b/x-pack/plugins/observability_solution/apm/server/feature.ts @@ -17,7 +17,10 @@ import { APM_INDEX_SETTINGS_SAVED_OBJECT_TYPE } from '@kbn/apm-data-access-plugi import { ApmRuleType } from '@kbn/rule-data-utils'; import { APM_SERVER_FEATURE_ID } from '../common/rules/apm_rule_types'; -const ruleTypes = Object.values(ApmRuleType); +const alertingFeatures = Object.values(ApmRuleType).map((ruleTypeId) => ({ + ruleTypeId, + consumers: [APM_SERVER_FEATURE_ID], +})); export const APM_FEATURE = { id: APM_SERVER_FEATURE_ID, @@ -31,7 +34,7 @@ export const APM_FEATURE = { management: { insightsAndAlerting: ['triggersActions'], }, - alerting: { ruleTypeIds: ruleTypes, consumers: [APM_SERVER_FEATURE_ID] }, + alerting: alertingFeatures, // see x-pack/plugins/features/common/feature_kibana_privileges.ts privileges: { all: { @@ -44,10 +47,10 @@ export const APM_FEATURE = { }, alerting: { alert: { - all: { ruleTypeIds: ruleTypes, consumers: [APM_SERVER_FEATURE_ID] }, + all: alertingFeatures, }, rule: { - all: { ruleTypeIds: ruleTypes, consumers: [APM_SERVER_FEATURE_ID] }, + all: alertingFeatures, }, }, management: { @@ -65,10 +68,10 @@ export const APM_FEATURE = { }, alerting: { alert: { - read: { ruleTypeIds: ruleTypes, consumers: [APM_SERVER_FEATURE_ID] }, + read: alertingFeatures, }, rule: { - read: { ruleTypeIds: ruleTypes, consumers: [APM_SERVER_FEATURE_ID] }, + read: alertingFeatures, }, }, management: { diff --git a/x-pack/plugins/observability_solution/infra/server/features.ts b/x-pack/plugins/observability_solution/infra/server/features.ts index ff3b1eceaf4c86..ed47de593654e2 100644 --- a/x-pack/plugins/observability_solution/infra/server/features.ts +++ b/x-pack/plugins/observability_solution/infra/server/features.ts @@ -30,6 +30,11 @@ const metricRuleTypes = [ ML_ANOMALY_DETECTION_RULE_TYPE_ID, ]; +const metricAlertingFeatures = metricRuleTypes.map((ruleTypeId) => ({ + ruleTypeId, + consumers: [METRICS_FEATURE_ID], +})); + export const METRICS_FEATURE = { id: METRICS_FEATURE_ID, name: i18n.translate('xpack.infra.featureRegistry.linkInfrastructureTitle', { @@ -42,7 +47,7 @@ export const METRICS_FEATURE = { management: { insightsAndAlerting: ['triggersActions'], }, - alerting: { ruleTypeIds: metricRuleTypes, consumers: [METRICS_FEATURE_ID] }, + alerting: metricAlertingFeatures, privileges: { all: { app: ['infra', 'metrics', 'kibana'], @@ -54,10 +59,10 @@ export const METRICS_FEATURE = { }, alerting: { rule: { - all: { ruleTypeIds: metricRuleTypes, consumers: [METRICS_FEATURE_ID] }, + all: metricAlertingFeatures, }, alert: { - all: { ruleTypeIds: metricRuleTypes, consumers: [METRICS_FEATURE_ID] }, + all: metricAlertingFeatures, }, }, management: { @@ -75,10 +80,10 @@ export const METRICS_FEATURE = { }, alerting: { rule: { - read: { ruleTypeIds: metricRuleTypes, consumers: [METRICS_FEATURE_ID] }, + read: metricAlertingFeatures, }, alert: { - read: { ruleTypeIds: metricRuleTypes, consumers: [METRICS_FEATURE_ID] }, + read: metricAlertingFeatures, }, }, management: { @@ -96,6 +101,11 @@ const logsRuleTypes = [ ML_ANOMALY_DETECTION_RULE_TYPE_ID, ]; +const logsAlertingFeatures = logsRuleTypes.map((ruleTypeId) => ({ + ruleTypeId, + consumers: [LOGS_FEATURE_ID], +})); + export const LOGS_FEATURE = { id: LOGS_FEATURE_ID, name: i18n.translate('xpack.infra.featureRegistry.linkLogsTitle', { @@ -108,7 +118,7 @@ export const LOGS_FEATURE = { management: { insightsAndAlerting: ['triggersActions'], }, - alerting: { ruleTypeIds: logsRuleTypes, consumers: [LOGS_FEATURE_ID] }, + alerting: logsAlertingFeatures, privileges: { all: { app: ['infra', 'logs', 'kibana'], @@ -120,10 +130,10 @@ export const LOGS_FEATURE = { }, alerting: { rule: { - all: { ruleTypeIds: logsRuleTypes, consumers: [LOGS_FEATURE_ID] }, + all: logsAlertingFeatures, }, alert: { - all: { ruleTypeIds: logsRuleTypes, consumers: [LOGS_FEATURE_ID] }, + all: logsAlertingFeatures, }, }, management: { @@ -137,10 +147,10 @@ export const LOGS_FEATURE = { api: ['infra', 'rac'], alerting: { rule: { - read: { ruleTypeIds: logsRuleTypes, consumers: [LOGS_FEATURE_ID] }, + read: logsAlertingFeatures, }, alert: { - read: { ruleTypeIds: logsRuleTypes, consumers: [LOGS_FEATURE_ID] }, + read: logsAlertingFeatures, }, }, management: { diff --git a/x-pack/plugins/observability_solution/observability/server/plugin.ts b/x-pack/plugins/observability_solution/observability/server/plugin.ts index 73090620c18e1e..f796c99b8140b5 100644 --- a/x-pack/plugins/observability_solution/observability/server/plugin.ts +++ b/x-pack/plugins/observability_solution/observability/server/plugin.ts @@ -82,6 +82,11 @@ const o11yRuleTypes = [ ...Object.values(ApmRuleType), ]; +const alertingFeatures = o11yRuleTypes.map((ruleTypeId) => ({ + ruleTypeId, + consumers: [observabilityFeatureId], +})); + export class ObservabilityPlugin implements Plugin { private logger: Logger; @@ -234,7 +239,7 @@ export class ObservabilityPlugin implements Plugin { category: DEFAULT_APP_CATEGORIES.observability, app: [observabilityFeatureId], catalogue: [observabilityFeatureId], - alerting: { ruleTypeIds: o11yRuleTypes, consumers: [observabilityFeatureId] }, + alerting: alertingFeatures, privileges: { all: { app: [observabilityFeatureId], @@ -246,10 +251,10 @@ export class ObservabilityPlugin implements Plugin { }, alerting: { rule: { - all: { ruleTypeIds: o11yRuleTypes, consumers: [observabilityFeatureId] }, + all: alertingFeatures, }, alert: { - all: { ruleTypeIds: o11yRuleTypes, consumers: [observabilityFeatureId] }, + all: alertingFeatures, }, }, ui: ['read', 'write'], @@ -264,10 +269,10 @@ export class ObservabilityPlugin implements Plugin { }, alerting: { rule: { - read: { ruleTypeIds: o11yRuleTypes, consumers: [observabilityFeatureId] }, + read: alertingFeatures, }, alert: { - read: { ruleTypeIds: o11yRuleTypes, consumers: [observabilityFeatureId] }, + read: alertingFeatures, }, }, ui: ['read'], diff --git a/x-pack/plugins/observability_solution/slo/server/plugin.ts b/x-pack/plugins/observability_solution/slo/server/plugin.ts index a32f60b42d6652..83483302c5873c 100644 --- a/x-pack/plugins/observability_solution/slo/server/plugin.ts +++ b/x-pack/plugins/observability_solution/slo/server/plugin.ts @@ -79,6 +79,11 @@ export class SloPlugin implements Plugin { const savedObjectTypes = [SO_SLO_TYPE, SO_SLO_SETTINGS_TYPE]; + const alertingFeatures = sloRuleTypes.map((ruleTypeId) => ({ + ruleTypeId, + consumers: [sloFeatureId], + })); + plugins.features.registerKibanaFeature({ id: sloFeatureId, name: i18n.translate('xpack.slo.featureRegistry.linkSloTitle', { @@ -88,7 +93,7 @@ export class SloPlugin implements Plugin { category: DEFAULT_APP_CATEGORIES.observability, app: [sloFeatureId, 'kibana'], catalogue: [sloFeatureId, 'observability'], - alerting: { ruleTypeIds: sloRuleTypes, consumers: [sloFeatureId] }, + alerting: alertingFeatures, privileges: { all: { app: [sloFeatureId, 'kibana'], @@ -100,10 +105,10 @@ export class SloPlugin implements Plugin { }, alerting: { rule: { - all: { ruleTypeIds: sloRuleTypes, consumers: [sloFeatureId] }, + all: alertingFeatures, }, alert: { - all: { ruleTypeIds: sloRuleTypes, consumers: [sloFeatureId] }, + all: alertingFeatures, }, }, ui: ['read', 'write'], @@ -118,10 +123,10 @@ export class SloPlugin implements Plugin { }, alerting: { rule: { - read: { ruleTypeIds: sloRuleTypes, consumers: [sloFeatureId] }, + read: alertingFeatures, }, alert: { - read: { ruleTypeIds: sloRuleTypes, consumers: [sloFeatureId] }, + read: alertingFeatures, }, }, ui: ['read'], diff --git a/x-pack/plugins/observability_solution/synthetics/server/feature.ts b/x-pack/plugins/observability_solution/synthetics/server/feature.ts index 7d69cd4283947f..2893a39e9c1287 100644 --- a/x-pack/plugins/observability_solution/synthetics/server/feature.ts +++ b/x-pack/plugins/observability_solution/synthetics/server/feature.ts @@ -27,6 +27,11 @@ const UPTIME_RULE_TYPES = [ const ruleTypes = [...UPTIME_RULE_TYPES, ...SYNTHETICS_RULE_TYPES]; +const alertingFeatures = ruleTypes.map((ruleTypeId) => ({ + ruleTypeId, + consumers: [PLUGIN.ID], +})); + const elasticManagedLocationsEnabledPrivilege: SubFeaturePrivilegeGroupConfig = { groupType: 'independent' as SubFeaturePrivilegeGroupType, privileges: [ @@ -55,7 +60,7 @@ export const uptimeFeature = { management: { insightsAndAlerting: ['triggersActions'], }, - alerting: { ruleTypeIds: ruleTypes, consumers: [PLUGIN.ID] }, + alerting: alertingFeatures, privileges: { all: { app: ['uptime', 'kibana', 'synthetics'], @@ -73,10 +78,10 @@ export const uptimeFeature = { }, alerting: { rule: { - all: { ruleTypeIds: ruleTypes, consumers: [PLUGIN.ID] }, + all: alertingFeatures, }, alert: { - all: { ruleTypeIds: ruleTypes, consumers: [PLUGIN.ID] }, + all: alertingFeatures, }, }, management: { @@ -100,10 +105,10 @@ export const uptimeFeature = { }, alerting: { rule: { - read: { ruleTypeIds: ruleTypes, consumers: [PLUGIN.ID] }, + read: alertingFeatures, }, alert: { - read: { ruleTypeIds: ruleTypes, consumers: [PLUGIN.ID] }, + read: alertingFeatures, }, }, management: { diff --git a/x-pack/plugins/security/server/authorization/privileges/feature_privilege_builder/alerting.test.ts b/x-pack/plugins/security/server/authorization/privileges/feature_privilege_builder/alerting.test.ts index 539f4cd77cc698..273c1c91dcc657 100644 --- a/x-pack/plugins/security/server/authorization/privileges/feature_privilege_builder/alerting.test.ts +++ b/x-pack/plugins/security/server/authorization/privileges/feature_privilege_builder/alerting.test.ts @@ -20,12 +20,12 @@ describe(`feature_privilege_builder`, () => { const privilege: FeatureKibanaPrivileges = { alerting: { rule: { - all: {}, - read: {}, + all: [], + read: [], }, alert: { - all: {}, - read: {}, + all: [], + read: [], }, }, savedObject: { @@ -57,8 +57,8 @@ describe(`feature_privilege_builder`, () => { const privilege: FeatureKibanaPrivileges = { alerting: { rule: { - all: {}, - read: { ruleTypeIds: ['alert-type'], consumers: ['my-consumer'] }, + all: [], + read: [{ ruleTypeId: 'alert-type', consumers: ['my-consumer'] }], }, }, savedObject: { @@ -101,8 +101,8 @@ describe(`feature_privilege_builder`, () => { const privilege: FeatureKibanaPrivileges = { alerting: { alert: { - all: {}, - read: { ruleTypeIds: ['alert-type'], consumers: ['my-consumer'] }, + all: [], + read: [{ ruleTypeId: 'alert-type', consumers: ['my-consumer'] }], }, }, savedObject: { @@ -140,12 +140,12 @@ describe(`feature_privilege_builder`, () => { const privilege: FeatureKibanaPrivileges = { alerting: { rule: { - all: {}, - read: { ruleTypeIds: ['alert-type'], consumers: ['my-consumer'] }, + all: [], + read: [{ ruleTypeId: 'alert-type', consumers: ['my-consumer'] }], }, alert: { - all: {}, - read: { ruleTypeIds: ['alert-type'], consumers: ['my-consumer'] }, + all: [], + read: [{ ruleTypeId: 'alert-type', consumers: ['my-consumer'] }], }, }, savedObject: { @@ -192,8 +192,8 @@ describe(`feature_privilege_builder`, () => { const privilege: FeatureKibanaPrivileges = { alerting: { rule: { - all: { ruleTypeIds: ['alert-type'], consumers: ['my-consumer'] }, - read: {}, + all: [{ ruleTypeId: 'alert-type', consumers: ['my-consumer'] }], + read: [], }, }, @@ -256,8 +256,8 @@ describe(`feature_privilege_builder`, () => { const privilege: FeatureKibanaPrivileges = { alerting: { alert: { - all: { ruleTypeIds: ['alert-type'], consumers: ['my-consumer'] }, - read: {}, + all: [{ ruleTypeId: 'alert-type', consumers: ['my-consumer'] }], + read: [], }, }, savedObject: { @@ -296,12 +296,12 @@ describe(`feature_privilege_builder`, () => { const privilege: FeatureKibanaPrivileges = { alerting: { rule: { - all: { ruleTypeIds: ['alert-type'], consumers: ['my-consumer'] }, - read: {}, + all: [{ ruleTypeId: 'alert-type', consumers: ['my-consumer'] }], + read: [], }, alert: { - all: { ruleTypeIds: ['alert-type'], consumers: ['my-consumer'] }, - read: {}, + all: [{ ruleTypeId: 'alert-type', consumers: ['my-consumer'] }], + read: [], }, }, savedObject: { @@ -368,8 +368,8 @@ describe(`feature_privilege_builder`, () => { const privilege: FeatureKibanaPrivileges = { alerting: { rule: { - all: { ruleTypeIds: ['alert-type'], consumers: ['my-consumer'] }, - read: { ruleTypeIds: ['readonly-alert-type'], consumers: ['my-consumer'] }, + all: [{ ruleTypeId: 'alert-type', consumers: ['my-consumer'] }], + read: [{ ruleTypeId: 'readonly-alert-type', consumers: ['my-consumer'] }], }, }, savedObject: { @@ -440,8 +440,8 @@ describe(`feature_privilege_builder`, () => { const privilege: FeatureKibanaPrivileges = { alerting: { alert: { - all: { ruleTypeIds: ['alert-type'], consumers: ['my-consumer'] }, - read: { ruleTypeIds: ['readonly-alert-type'], consumers: ['my-consumer'] }, + all: [{ ruleTypeId: 'alert-type', consumers: ['my-consumer'] }], + read: [{ ruleTypeId: 'readonly-alert-type', consumers: ['my-consumer'] }], }, }, @@ -485,12 +485,12 @@ describe(`feature_privilege_builder`, () => { const privilege: FeatureKibanaPrivileges = { alerting: { rule: { - all: { ruleTypeIds: ['alert-type'], consumers: ['my-consumer'] }, - read: { ruleTypeIds: ['readonly-alert-type'], consumers: ['my-consumer'] }, + all: [{ ruleTypeId: 'alert-type', consumers: ['my-consumer'] }], + read: [{ ruleTypeId: 'readonly-alert-type', consumers: ['my-consumer'] }], }, alert: { - all: { ruleTypeIds: ['another-alert-type'], consumers: ['my-consumer'] }, - read: { ruleTypeIds: ['readonly-alert-type'], consumers: ['my-consumer'] }, + all: [{ ruleTypeId: 'another-alert-type', consumers: ['my-consumer'] }], + read: [{ ruleTypeId: 'readonly-alert-type', consumers: ['my-consumer'] }], }, }, diff --git a/x-pack/plugins/security/server/authorization/privileges/feature_privilege_builder/alerting.ts b/x-pack/plugins/security/server/authorization/privileges/feature_privilege_builder/alerting.ts index e40ba7038467a2..bc6bde317db687 100644 --- a/x-pack/plugins/security/server/authorization/privileges/feature_privilege_builder/alerting.ts +++ b/x-pack/plugins/security/server/authorization/privileges/feature_privilege_builder/alerting.ts @@ -67,11 +67,10 @@ export class FeaturePrivilegeAlertingBuilder extends BaseFeaturePrivilegeBuilder ): string[] { const getAlertingPrivilege = ( operations: string[], - ruleTypeIds: readonly string[], - alertingEntity: string, - consumers: string[] + privileges: Array<{ ruleTypeId: string; consumers: string[] }>, + alertingEntity: string ) => - ruleTypeIds.flatMap((ruleTypeId) => + privileges.flatMap(({ ruleTypeId, consumers }) => consumers.flatMap((consumer) => operations.map((operation) => this.actions.alerting.get(ruleTypeId, consumer, alertingEntity, operation) @@ -80,14 +79,12 @@ export class FeaturePrivilegeAlertingBuilder extends BaseFeaturePrivilegeBuilder ); const getPrivilegesForEntity = (entity: AlertingEntity) => { - const allRuleTypeIds = get(privilegeDefinition.alerting, `${entity}.all.ruleTypeIds`) ?? []; - const allConsumers = get(privilegeDefinition.alerting, `${entity}.all.consumers`) ?? []; - const readRuleTypeId = get(privilegeDefinition.alerting, `${entity}.read.ruleTypeIds`) ?? []; - const readConsumers = get(privilegeDefinition.alerting, `${entity}.read.consumers`) ?? []; + const all = get(privilegeDefinition.alerting, `${entity}.all`) ?? []; + const read = get(privilegeDefinition.alerting, `${entity}.read`) ?? []; return uniq([ - ...getAlertingPrivilege(allOperations[entity], allRuleTypeIds, entity, allConsumers), - ...getAlertingPrivilege(readOperations[entity], readRuleTypeId, entity, readConsumers), + ...getAlertingPrivilege(allOperations[entity], all, entity), + ...getAlertingPrivilege(readOperations[entity], read, entity), ]); }; diff --git a/x-pack/plugins/stack_alerts/server/feature.ts b/x-pack/plugins/stack_alerts/server/feature.ts index ef91d5f3b66230..bacc0d2f3c9518 100644 --- a/x-pack/plugins/stack_alerts/server/feature.ts +++ b/x-pack/plugins/stack_alerts/server/feature.ts @@ -16,6 +16,13 @@ import { GEO_CONTAINMENT_ID as GeoContainment } from './rule_types/geo_containme const TransformHealth = TRANSFORM_RULE_TYPE.TRANSFORM_HEALTH; +const alertingFeatures = [IndexThreshold, GeoContainment, ElasticsearchQuery, TransformHealth].map( + (ruleTypeId) => ({ + ruleTypeId, + consumers: [STACK_ALERTS_FEATURE_ID], + }) +); + export const BUILT_IN_ALERTS_FEATURE: KibanaFeatureConfig = { id: STACK_ALERTS_FEATURE_ID, name: i18n.translate('xpack.stackAlerts.featureRegistry.actionsFeatureName', { @@ -26,10 +33,7 @@ export const BUILT_IN_ALERTS_FEATURE: KibanaFeatureConfig = { management: { insightsAndAlerting: ['triggersActions'], }, - alerting: { - ruleTypeIds: [IndexThreshold, GeoContainment, ElasticsearchQuery, TransformHealth], - consumers: [STACK_ALERTS_FEATURE_ID], - }, + alerting: alertingFeatures, privileges: { all: { app: [], @@ -39,16 +43,10 @@ export const BUILT_IN_ALERTS_FEATURE: KibanaFeatureConfig = { }, alerting: { rule: { - all: { - ruleTypeIds: [IndexThreshold, GeoContainment, ElasticsearchQuery, TransformHealth], - consumers: [STACK_ALERTS_FEATURE_ID], - }, + all: alertingFeatures, }, alert: { - all: { - ruleTypeIds: [IndexThreshold, GeoContainment, ElasticsearchQuery, TransformHealth], - consumers: [STACK_ALERTS_FEATURE_ID], - }, + all: alertingFeatures, }, }, savedObject: { @@ -66,16 +64,10 @@ export const BUILT_IN_ALERTS_FEATURE: KibanaFeatureConfig = { }, alerting: { rule: { - read: { - ruleTypeIds: [IndexThreshold, GeoContainment, ElasticsearchQuery, TransformHealth], - consumers: [STACK_ALERTS_FEATURE_ID], - }, + read: alertingFeatures, }, alert: { - read: { - ruleTypeIds: [IndexThreshold, GeoContainment, ElasticsearchQuery, TransformHealth], - consumers: [STACK_ALERTS_FEATURE_ID], - }, + read: alertingFeatures, }, }, savedObject: { From 8b5fd17f9cd75bf686c23836f2b5f1bf1e1f44a5 Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Fri, 31 May 2024 21:11:33 +0300 Subject: [PATCH 006/106] Filter out rule types with no registered consumers --- .../authorization/alerting_authorization.ts | 40 +++++++++++++++++-- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/alerting/server/authorization/alerting_authorization.ts b/x-pack/plugins/alerting/server/authorization/alerting_authorization.ts index b3761fc63b4454..9af6b9aae29036 100644 --- a/x-pack/plugins/alerting/server/authorization/alerting_authorization.ts +++ b/x-pack/plugins/alerting/server/authorization/alerting_authorization.ts @@ -11,7 +11,10 @@ import { KibanaRequest } from '@kbn/core/server'; import { JsonObject } from '@kbn/utility-types'; import { KueryNode } from '@kbn/es-query'; import { SecurityPluginSetup } from '@kbn/security-plugin/server'; -import { PluginStartContract as FeaturesPluginStart } from '@kbn/features-plugin/server'; +import { + KibanaFeature, + PluginStartContract as FeaturesPluginStart, +} from '@kbn/features-plugin/server'; import { Space } from '@kbn/spaces-plugin/server'; import { RegistryRuleType } from '../rule_type_registry'; import { ALERTING_FEATURE_ID, RuleTypeRegistry } from '../types'; @@ -93,6 +96,8 @@ export class AlertingAuthorization { private readonly request: KibanaRequest; private readonly authorization?: SecurityPluginSetup['authz']; private readonly allPossibleConsumers: Promise; + private readonly ruleTypeConsumersMap: Promise>>; + private readonly features: Promise; private readonly spaceId: string | undefined; constructor({ ruleTypeRegistry, @@ -107,7 +112,7 @@ export class AlertingAuthorization { this.ruleTypeRegistry = ruleTypeRegistry; this.spaceId = getSpaceId(request); - const alertingFeaturesPromise = getSpace(request) + this.features = getSpace(request) .then((maybeSpace) => new Set(maybeSpace?.disabledFeatures ?? [])) .then((disabledFeatures) => features.getKibanaFeatures().filter( @@ -119,7 +124,7 @@ export class AlertingAuthorization { ) ); - this.allPossibleConsumers = alertingFeaturesPromise.then((alertingFeatures) => { + this.allPossibleConsumers = this.features.then((alertingFeatures) => { const consumers = alertingFeatures.flatMap( (alertingFeature) => alertingFeature.alerting @@ -134,6 +139,23 @@ export class AlertingAuthorization { }) : {}; }); + + this.ruleTypeConsumersMap = this.features.then((alertingFeatures) => { + const map = new Map>(); + + for (const feature of alertingFeatures) { + if (feature.alerting) { + for (const entry of feature.alerting) { + const consumers = map.get(entry.ruleTypeId) ?? new Set(); + entry.consumers.forEach((consumer) => consumers.add(consumer)); + + map.set(entry.ruleTypeId, consumers); + } + } + } + + return map; + }); } private shouldCheckAuthorization(): boolean { @@ -321,8 +343,10 @@ export class AlertingAuthorization { hasAllRequested: boolean; authorizedRuleTypes: Set; }> { + const ruleTypeConsumersMap = await this.ruleTypeConsumersMap; const allPossibleConsumers = await this.allPossibleConsumers; const consumersToAuthorize = consumers ?? new Set(Object.keys(allPossibleConsumers)); + const requiredPrivileges = new Map< string, [RegistryAlertTypeWithAuth, string, HasPrivileges, IsAuthorizedAtProducerLevel] @@ -342,7 +366,17 @@ export class AlertingAuthorization { ); for (const ruleTypeWithAuth of ruleTypesWithAuthorization) { + if (!ruleTypeConsumersMap.has(ruleTypeWithAuth.id)) { + continue; + } + for (const consumerToAuthorize of consumersToAuthorize) { + const ruleTypeConsumers = ruleTypeConsumersMap.get(ruleTypeWithAuth.id); + + if (!ruleTypeConsumers?.has(consumerToAuthorize)) { + continue; + } + for (const operation of operations) { requiredPrivileges.set( this.authorization!.actions.alerting.get( From b69bff1878b5a7eb79a56c688710709e8a5382ab Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Fri, 12 Jul 2024 15:04:22 +0300 Subject: [PATCH 007/106] Refactor the way the AlertingAuthorization object is created --- .../alerting_authorization_client_factory.ts | 45 +++-- .../authorization/alerting_authorization.ts | 123 +++++++------ x-pack/plugins/alerting/server/plugin.ts | 5 +- .../feature_privilege_iterator.test.ts | 172 +++++++++--------- .../alerts_client_factory.test.ts | 2 +- .../alerts_client_factory.ts | 9 +- x-pack/plugins/rule_registry/server/plugin.ts | 2 +- 7 files changed, 190 insertions(+), 168 deletions(-) diff --git a/x-pack/plugins/alerting/server/alerting_authorization_client_factory.ts b/x-pack/plugins/alerting/server/alerting_authorization_client_factory.ts index b0830a7127a38a..bba2b490e8485a 100644 --- a/x-pack/plugins/alerting/server/alerting_authorization_client_factory.ts +++ b/x-pack/plugins/alerting/server/alerting_authorization_client_factory.ts @@ -6,7 +6,7 @@ */ import { KibanaRequest } from '@kbn/core/server'; -import { SecurityPluginSetup, SecurityPluginStart } from '@kbn/security-plugin/server'; +import { SecurityPluginStart } from '@kbn/security-plugin/server'; import { PluginStartContract as FeaturesPluginStart } from '@kbn/features-plugin/server'; import { Space } from '@kbn/spaces-plugin/server'; import { AlertingAuthorization } from './authorization/alerting_authorization'; @@ -14,7 +14,6 @@ import { RuleTypeRegistry } from './types'; export interface AlertingAuthorizationClientFactoryOpts { ruleTypeRegistry: RuleTypeRegistry; - securityPluginSetup?: SecurityPluginSetup; securityPluginStart?: SecurityPluginStart; getSpace: (request: KibanaRequest) => Promise; getSpaceId: (request: KibanaRequest) => string; @@ -23,33 +22,39 @@ export interface AlertingAuthorizationClientFactoryOpts { export class AlertingAuthorizationClientFactory { private isInitialized = false; - private ruleTypeRegistry!: RuleTypeRegistry; - private securityPluginStart?: SecurityPluginStart; - private features!: FeaturesPluginStart; - private getSpace!: (request: KibanaRequest) => Promise; - private getSpaceId!: (request: KibanaRequest) => string; + // The reason this is protected is because we'll get type collisions otherwise because we're using a type guard assert + // to ensure the options member is instantiated before using it in various places + // See for more info: https://stackoverflow.com/questions/66206180/typescript-typeguard-attribut-with-method + protected options?: AlertingAuthorizationClientFactoryOpts; public initialize(options: AlertingAuthorizationClientFactoryOpts) { if (this.isInitialized) { throw new Error('AlertingAuthorizationClientFactory already initialized'); } this.isInitialized = true; - this.getSpace = options.getSpace; - this.ruleTypeRegistry = options.ruleTypeRegistry; - this.securityPluginStart = options.securityPluginStart; - this.features = options.features; - this.getSpaceId = options.getSpaceId; + this.options = options; } - public create(request: KibanaRequest): AlertingAuthorization { - const { securityPluginStart, features } = this; - return new AlertingAuthorization({ - authorization: securityPluginStart?.authz, + public async create(request: KibanaRequest): Promise { + this.validateInitialization(); + + return await AlertingAuthorization.create({ + authorization: this.options.securityPluginStart?.authz, request, - getSpace: this.getSpace, - getSpaceId: this.getSpaceId, - ruleTypeRegistry: this.ruleTypeRegistry, - features: features!, + getSpace: this.options.getSpace, + getSpaceId: this.options.getSpaceId, + ruleTypeRegistry: this.options.ruleTypeRegistry, + features: this.options.features, }); } + + private validateInitialization(): asserts this is this & { + options: AlertingAuthorizationClientFactoryOpts; + } { + if (!this.isInitialized || this.options == null) { + throw new Error( + 'AlertingAuthorizationClientFactory must be initialized before calling create' + ); + } + } } diff --git a/x-pack/plugins/alerting/server/authorization/alerting_authorization.ts b/x-pack/plugins/alerting/server/authorization/alerting_authorization.ts index 9af6b9aae29036..2fcabfa510c28d 100644 --- a/x-pack/plugins/alerting/server/authorization/alerting_authorization.ts +++ b/x-pack/plugins/alerting/server/authorization/alerting_authorization.ts @@ -10,11 +10,8 @@ import { has, isEmpty } from 'lodash'; import { KibanaRequest } from '@kbn/core/server'; import { JsonObject } from '@kbn/utility-types'; import { KueryNode } from '@kbn/es-query'; -import { SecurityPluginSetup } from '@kbn/security-plugin/server'; -import { - KibanaFeature, - PluginStartContract as FeaturesPluginStart, -} from '@kbn/features-plugin/server'; +import { SecurityPluginStart } from '@kbn/security-plugin/server'; +import { PluginStartContract as FeaturesPluginStart } from '@kbn/features-plugin/server'; import { Space } from '@kbn/spaces-plugin/server'; import { RegistryRuleType } from '../rule_type_registry'; import { ALERTING_FEATURE_ID, RuleTypeRegistry } from '../types'; @@ -82,80 +79,98 @@ export interface RegistryAlertTypeWithAuth extends RegistryRuleType { } type IsAuthorizedAtProducerLevel = boolean; -export interface ConstructorOptions { + +export interface CreateOptions { ruleTypeRegistry: RuleTypeRegistry; request: KibanaRequest; features: FeaturesPluginStart; getSpace: (request: KibanaRequest) => Promise; getSpaceId: (request: KibanaRequest) => string | undefined; - authorization?: SecurityPluginSetup['authz']; + authorization?: SecurityPluginStart['authz']; } +type ConstructorOptions = Pick< + CreateOptions, + 'ruleTypeRegistry' | 'request' | 'authorization' | 'getSpaceId' +> & { + allRegisteredConsumers: Set; + ruleTypeConsumersMap: Map>; +}; + export class AlertingAuthorization { private readonly ruleTypeRegistry: RuleTypeRegistry; private readonly request: KibanaRequest; - private readonly authorization?: SecurityPluginSetup['authz']; - private readonly allPossibleConsumers: Promise; - private readonly ruleTypeConsumersMap: Promise>>; - private readonly features: Promise; + private readonly authorization?: SecurityPluginStart['authz']; + private readonly allRegisteredConsumers: Set; + private readonly ruleTypeConsumersMap: Map>; private readonly spaceId: string | undefined; + constructor({ ruleTypeRegistry, request, authorization, - features, - getSpace, getSpaceId, + allRegisteredConsumers, + ruleTypeConsumersMap, }: ConstructorOptions) { this.request = request; this.authorization = authorization; this.ruleTypeRegistry = ruleTypeRegistry; + this.allRegisteredConsumers = allRegisteredConsumers; + this.ruleTypeConsumersMap = ruleTypeConsumersMap; this.spaceId = getSpaceId(request); + } - this.features = getSpace(request) - .then((maybeSpace) => new Set(maybeSpace?.disabledFeatures ?? [])) - .then((disabledFeatures) => - features.getKibanaFeatures().filter( - ({ id, alerting }) => - // ignore features which are disabled in the user's space - !disabledFeatures.has(id) && - // ignore features which don't grant privileges to alerting - (alerting?.length ?? 0 > 0) - ) - ); - - this.allPossibleConsumers = this.features.then((alertingFeatures) => { - const consumers = alertingFeatures.flatMap( - (alertingFeature) => - alertingFeature.alerting - ?.flatMap((feature) => feature.consumers ?? []) - .filter(Boolean) as string[] + /** + * Creates an Authorization object. + */ + static async create({ + request, + features, + getSpace, + getSpaceId, + authorization, + ruleTypeRegistry, + }: CreateOptions): Promise { + try { + const maybeSpace = await getSpace(request); + const disabledFeatures = new Set(maybeSpace?.disabledFeatures ?? []); + const featuresWithAlertingConfigured = features.getKibanaFeatures().filter( + ({ id, alerting }) => + // ignore features which are disabled in the user's space + !disabledFeatures.has(id) && + // ignore features which don't grant privileges to alerting + Boolean(alerting?.length) ); - return consumers.length - ? asAuthorizedConsumers([ALERTING_FEATURE_ID, ...consumers], { - read: true, - all: true, - }) - : {}; - }); - - this.ruleTypeConsumersMap = this.features.then((alertingFeatures) => { - const map = new Map>(); + const allRegisteredConsumers = new Set(); + const ruleTypeConsumersMap = new Map>(); - for (const feature of alertingFeatures) { + for (const feature of featuresWithAlertingConfigured) { if (feature.alerting) { for (const entry of feature.alerting) { - const consumers = map.get(entry.ruleTypeId) ?? new Set(); - entry.consumers.forEach((consumer) => consumers.add(consumer)); + const consumers = ruleTypeConsumersMap.get(entry.ruleTypeId) ?? new Set(); - map.set(entry.ruleTypeId, consumers); + entry.consumers.forEach((consumer) => { + consumers.add(consumer); + allRegisteredConsumers.add(consumer); + }); + ruleTypeConsumersMap.set(entry.ruleTypeId, consumers); } } } - return map; - }); + return new AlertingAuthorization({ + request, + authorization, + getSpaceId, + ruleTypeRegistry, + allRegisteredConsumers, + ruleTypeConsumersMap, + }); + } catch (error) { + throw new Error(`Failed to create AlertingAuthorization class: ${error}`); + } } private shouldCheckAuthorization(): boolean { @@ -202,7 +217,7 @@ export class AlertingAuthorization { producer: ruleType.producer, }); - const isAvailableConsumer = has(await this.allPossibleConsumers, consumer); + const isAvailableConsumer = has(await this.allRegisteredConsumers, consumer); if (authorization && this.shouldCheckAuthorization()) { const checkPrivileges = authorization.checkPrivilegesDynamicallyWithRequest(this.request); @@ -344,8 +359,8 @@ export class AlertingAuthorization { authorizedRuleTypes: Set; }> { const ruleTypeConsumersMap = await this.ruleTypeConsumersMap; - const allPossibleConsumers = await this.allPossibleConsumers; - const consumersToAuthorize = consumers ?? new Set(Object.keys(allPossibleConsumers)); + const allRegisteredConsumers = await this.allRegisteredConsumers; + const consumersToAuthorize = consumers ?? new Set(Object.keys(allRegisteredConsumers)); const requiredPrivileges = new Map< string, @@ -399,8 +414,8 @@ export class AlertingAuthorization { if (!isEmpty(ruleTypeWithAuth.validLegacyConsumers)) { ruleTypeWithAuth.validLegacyConsumers.forEach((legacyConsumer) => { if (addLegacyConsumerPrivileges(legacyConsumer)) { - if (!allPossibleConsumers[legacyConsumer]) { - allPossibleConsumers[legacyConsumer] = { + if (!allRegisteredConsumers[legacyConsumer]) { + allRegisteredConsumers[legacyConsumer] = { read: true, all: true, }; @@ -460,7 +475,7 @@ export class AlertingAuthorization { authorizedRuleTypes: hasAllRequested && consumers === undefined ? // has access to all features - this.augmentWithAuthorizedConsumers(authorizedRuleTypes, allPossibleConsumers) + this.augmentWithAuthorizedConsumers(authorizedRuleTypes, allRegisteredConsumers) : authorizedRuleTypes, }; } else { @@ -468,7 +483,7 @@ export class AlertingAuthorization { hasAllRequested: true, authorizedRuleTypes: this.augmentWithAuthorizedConsumers( new Set([...ruleTypes].filter((ruleType) => consumersToAuthorize.has(ruleType.producer))), - allPossibleConsumers + allRegisteredConsumers ), }; } diff --git a/x-pack/plugins/alerting/server/plugin.ts b/x-pack/plugins/alerting/server/plugin.ts index 3c996c532acf24..20d52d4099ad25 100644 --- a/x-pack/plugins/alerting/server/plugin.ts +++ b/x-pack/plugins/alerting/server/plugin.ts @@ -171,7 +171,7 @@ export interface PluginStartContract { getAlertingAuthorizationWithRequest( request: KibanaRequest - ): PublicMethodsOf; + ): Promise>; getFrameworkHealth: () => Promise; } @@ -504,7 +504,6 @@ export class AlertingPlugin { alertingAuthorizationClientFactory.initialize({ ruleTypeRegistry: ruleTypeRegistry!, - securityPluginSetup: security, securityPluginStart: plugins.security, async getSpace(request: KibanaRequest) { return plugins.spaces?.spacesService.getActiveSpace(request); @@ -567,7 +566,7 @@ export class AlertingPlugin { return rulesClientFactory!.create(request, core.savedObjects); }; - const getAlertingAuthorizationWithRequest = (request: KibanaRequest) => { + const getAlertingAuthorizationWithRequest = async (request: KibanaRequest) => { return alertingAuthorizationClientFactory!.create(request); }; diff --git a/x-pack/plugins/features/server/feature_privilege_iterator/feature_privilege_iterator.test.ts b/x-pack/plugins/features/server/feature_privilege_iterator/feature_privilege_iterator.test.ts index 58a39c85bf9e98..3b4ef7c87070bd 100644 --- a/x-pack/plugins/features/server/feature_privilege_iterator/feature_privilege_iterator.test.ts +++ b/x-pack/plugins/features/server/feature_privilege_iterator/feature_privilege_iterator.test.ts @@ -62,11 +62,11 @@ describe('featurePrivilegeIterator', () => { }, alerting: { rule: { - all: ['alerting-all-type'], - read: ['alerting-read-type'], + all: [{ ruleTypeId: 'alerting-all-type', consumers: ['foo'] }], + read: [{ ruleTypeId: 'alerting-read-type', consumers: ['foo'] }], }, alert: { - all: ['alerting-all-type'], + all: [{ ruleTypeId: 'alerting-all-type', consumers: ['foo'] }], read: [], }, }, @@ -94,10 +94,10 @@ describe('featurePrivilegeIterator', () => { }, alerting: { rule: { - read: ['alerting-read-type'], + read: [{ ruleTypeId: 'alerting-read-type', consumers: ['foo'] }], }, alert: { - read: ['alerting-read-type'], + read: [{ ruleTypeId: 'alerting-read-type', consumers: ['foo'] }], }, }, cases: { @@ -132,11 +132,11 @@ describe('featurePrivilegeIterator', () => { }, alerting: { rule: { - all: ['alerting-all-type'], - read: ['alerting-read-type'], + all: [{ ruleTypeId: 'alerting-all-type', consumers: ['foo'] }], + read: [{ ruleTypeId: 'alerting-read-type', consumers: ['foo'] }], }, alert: { - all: ['alerting-all-type'], + all: [{ ruleTypeId: 'alerting-all-type', consumers: ['foo'] }], read: [], }, }, @@ -167,10 +167,10 @@ describe('featurePrivilegeIterator', () => { }, alerting: { rule: { - read: ['alerting-read-type'], + read: [{ ruleTypeId: 'alerting-read-type', consumers: ['foo'] }], }, alert: { - read: ['alerting-read-type'], + read: [{ ruleTypeId: 'alerting-read-type', consumers: ['foo'] }], }, }, cases: { @@ -201,12 +201,12 @@ describe('featurePrivilegeIterator', () => { }, alerting: { rule: { - all: ['alerting-all-type'], - read: ['alerting-read-type'], + all: [{ ruleTypeId: 'alerting-all-type', consumers: ['foo'] }], + read: [{ ruleTypeId: 'alerting-read-type', consumers: ['foo'] }], }, alert: { - all: ['alerting-all-type'], - read: ['alerting-read-type-alerts'], + all: [{ ruleTypeId: 'alerting-all-type', consumers: ['foo'] }], + read: [{ ruleTypeId: 'alerting-read-type-alerts', consumers: ['foo'] }], }, }, cases: { @@ -233,10 +233,10 @@ describe('featurePrivilegeIterator', () => { }, alerting: { rule: { - read: ['alerting-read-type'], + read: [{ ruleTypeId: 'alerting-read-type', consumers: ['foo'] }], }, alert: { - read: ['alerting-read-type'], + read: [{ ruleTypeId: 'alerting-read-type', consumers: ['foo'] }], }, }, cases: { @@ -272,12 +272,12 @@ describe('featurePrivilegeIterator', () => { }, alerting: { rule: { - all: ['alerting-all-type'], - read: ['alerting-read-type'], + all: [{ ruleTypeId: 'alerting-all-type', consumers: ['foo'] }], + read: [{ ruleTypeId: 'alerting-read-type', consumers: ['foo'] }], }, alert: { - all: ['alerting-all-type'], - read: ['alerting-read-type-alerts'], + all: [{ ruleTypeId: 'alerting-all-type', consumers: ['foo'] }], + read: [{ ruleTypeId: 'alerting-read-type-alerts', consumers: ['foo'] }], }, }, cases: { @@ -315,10 +315,10 @@ describe('featurePrivilegeIterator', () => { }, alerting: { rule: { - all: ['alerting-all-type'], + all: [{ ruleTypeId: 'alerting-all-type', consumers: ['foo'] }], }, alert: { - read: ['alerting-another-read-type'], + read: [{ ruleTypeId: 'alerting-another-read-type', consumers: ['foo'] }], }, }, cases: { @@ -345,10 +345,10 @@ describe('featurePrivilegeIterator', () => { }, alerting: { rule: { - read: ['alerting-read-type'], + read: [{ ruleTypeId: 'alerting-read-type', consumers: ['foo'] }], }, alert: { - read: ['alerting-read-type'], + read: [{ ruleTypeId: 'alerting-read-type', consumers: ['foo'] }], }, }, cases: { @@ -380,7 +380,7 @@ describe('featurePrivilegeIterator', () => { }, alerting: { alert: { - all: ['alerting-all-sub-type'], + all: [{ ruleTypeId: 'alerting-all-sub-type', consumers: ['foo'] }], }, }, cases: { @@ -424,10 +424,10 @@ describe('featurePrivilegeIterator', () => { }, alerting: { rule: { - all: ['alerting-all-type'], + all: [{ ruleTypeId: 'alerting-all-type', consumers: ['foo'] }], }, alert: { - read: ['alerting-another-read-type'], + read: [{ ruleTypeId: 'alerting-another-read-type', consumers: ['foo'] }], }, }, cases: { @@ -457,10 +457,10 @@ describe('featurePrivilegeIterator', () => { }, alerting: { rule: { - read: ['alerting-read-type'], + read: [{ ruleTypeId: 'alerting-read-type', consumers: ['foo'] }], }, alert: { - read: ['alerting-read-type'], + read: [{ ruleTypeId: 'alerting-read-type', consumers: ['foo'] }], }, }, cases: { @@ -492,10 +492,10 @@ describe('featurePrivilegeIterator', () => { }, alerting: { rule: { - all: ['alerting-all-type'], + all: [{ ruleTypeId: 'alerting-all-type', consumers: ['foo'] }], }, alert: { - read: ['alerting-another-read-type'], + read: [{ ruleTypeId: 'alerting-another-read-type', consumers: ['foo'] }], }, }, cases: { @@ -522,10 +522,10 @@ describe('featurePrivilegeIterator', () => { }, alerting: { rule: { - read: ['alerting-read-type'], + read: [{ ruleTypeId: 'alerting-read-type', consumers: ['foo'] }], }, alert: { - read: ['alerting-read-type'], + read: [{ ruleTypeId: 'alerting-read-type', consumers: ['foo'] }], }, }, cases: { @@ -557,7 +557,7 @@ describe('featurePrivilegeIterator', () => { }, alerting: { alert: { - all: ['alerting-all-sub-type'], + all: [{ ruleTypeId: 'alerting-all-sub-type', consumers: ['foo'] }], }, }, cases: { @@ -601,10 +601,10 @@ describe('featurePrivilegeIterator', () => { }, alerting: { rule: { - all: ['alerting-all-type'], + all: [{ ruleTypeId: 'alerting-all-type', consumers: ['foo'] }], }, alert: { - read: ['alerting-another-read-type'], + read: [{ ruleTypeId: 'alerting-another-read-type', consumers: ['foo'] }], }, }, cases: { @@ -634,10 +634,10 @@ describe('featurePrivilegeIterator', () => { }, alerting: { rule: { - read: ['alerting-read-type'], + read: [{ ruleTypeId: 'alerting-read-type', consumers: ['foo'] }], }, alert: { - read: ['alerting-read-type'], + read: [{ ruleTypeId: 'alerting-read-type', consumers: ['foo'] }], }, }, cases: { @@ -669,10 +669,10 @@ describe('featurePrivilegeIterator', () => { }, alerting: { rule: { - all: ['alerting-all-type'], + all: [{ ruleTypeId: 'alerting-all-type', consumers: ['foo'] }], }, alert: { - read: ['alerting-another-read-type'], + read: [{ ruleTypeId: 'alerting-another-read-type', consumers: ['foo'] }], }, }, cases: { @@ -699,10 +699,10 @@ describe('featurePrivilegeIterator', () => { }, alerting: { rule: { - read: ['alerting-read-type'], + read: [{ ruleTypeId: 'alerting-read-type', consumers: ['foo'] }], }, alert: { - read: ['alerting-read-type'], + read: [{ ruleTypeId: 'alerting-read-type', consumers: ['foo'] }], }, }, cases: { @@ -735,7 +735,7 @@ describe('featurePrivilegeIterator', () => { }, alerting: { alert: { - all: ['alerting-all-sub-type'], + all: [{ ruleTypeId: 'alerting-all-sub-type', consumers: ['foo'] }], }, }, cases: { @@ -780,12 +780,12 @@ describe('featurePrivilegeIterator', () => { }, alerting: { rule: { - all: ['alerting-all-type'], + all: [{ ruleTypeId: 'alerting-all-type', consumers: ['foo'] }], read: [], }, alert: { - all: ['alerting-all-sub-type'], - read: ['alerting-another-read-type'], + all: [{ ruleTypeId: 'alerting-all-sub-type', consumers: ['foo'] }], + read: [{ ruleTypeId: 'alerting-another-read-type', consumers: ['foo'] }], }, }, cases: { @@ -817,11 +817,11 @@ describe('featurePrivilegeIterator', () => { alerting: { rule: { all: [], - read: ['alerting-read-type'], + read: [{ ruleTypeId: 'alerting-read-type', consumers: ['foo'] }], }, alert: { - all: ['alerting-all-sub-type'], - read: ['alerting-read-type'], + all: [{ ruleTypeId: 'alerting-all-sub-type', consumers: ['foo'] }], + read: [{ ruleTypeId: 'alerting-read-type', consumers: ['foo'] }], }, }, cases: { @@ -859,12 +859,12 @@ describe('featurePrivilegeIterator', () => { }, alerting: { rule: { - all: ['alerting-all-type'], - read: ['alerting-read-type'], + all: [{ ruleTypeId: 'alerting-all-type', consumers: ['foo'] }], + read: [{ ruleTypeId: 'alerting-read-type', consumers: ['foo'] }], }, alert: { all: [], - read: ['alerting-read-type'], + read: [{ ruleTypeId: 'alerting-read-type', consumers: ['foo'] }], }, }, cases: { @@ -891,10 +891,10 @@ describe('featurePrivilegeIterator', () => { }, alerting: { rule: { - read: ['alerting-read-type'], + read: [{ ruleTypeId: 'alerting-read-type', consumers: ['foo'] }], }, alert: { - read: ['alerting-read-type'], + read: [{ ruleTypeId: 'alerting-read-type', consumers: ['foo'] }], }, }, cases: { @@ -926,7 +926,7 @@ describe('featurePrivilegeIterator', () => { }, alerting: { alert: { - all: ['alerting-read-type'], + all: [{ ruleTypeId: 'alerting-read-type', consumers: ['foo'] }], }, }, cases: { @@ -964,12 +964,12 @@ describe('featurePrivilegeIterator', () => { }, alerting: { rule: { - all: ['alerting-all-type'], - read: ['alerting-read-type'], + all: [{ ruleTypeId: 'alerting-all-type', consumers: ['foo'] }], + read: [{ ruleTypeId: 'alerting-read-type', consumers: ['foo'] }], }, alert: { - all: ['alerting-read-type'], - read: ['alerting-read-type'], + all: [{ ruleTypeId: 'alerting-read-type', consumers: ['foo'] }], + read: [{ ruleTypeId: 'alerting-read-type', consumers: ['foo'] }], }, }, cases: { @@ -1000,11 +1000,11 @@ describe('featurePrivilegeIterator', () => { alerting: { rule: { all: [], - read: ['alerting-read-type'], + read: [{ ruleTypeId: 'alerting-read-type', consumers: ['foo'] }], }, alert: { - all: ['alerting-read-type'], - read: ['alerting-read-type'], + all: [{ ruleTypeId: 'alerting-read-type', consumers: ['foo'] }], + read: [{ ruleTypeId: 'alerting-read-type', consumers: ['foo'] }], }, }, cases: { @@ -1042,10 +1042,10 @@ describe('featurePrivilegeIterator', () => { }, alerting: { rule: { - all: ['alerting-all-type'], + all: [{ ruleTypeId: 'alerting-all-type', consumers: ['foo'] }], }, alert: { - read: ['alerting-another-read-type'], + read: [{ ruleTypeId: 'alerting-another-read-type', consumers: ['foo'] }], }, }, cases: { @@ -1072,10 +1072,10 @@ describe('featurePrivilegeIterator', () => { }, alerting: { rule: { - read: ['alerting-read-type'], + read: [{ ruleTypeId: 'alerting-read-type', consumers: ['foo'] }], }, alert: { - read: ['alerting-read-type'], + read: [{ ruleTypeId: 'alerting-read-type', consumers: ['foo'] }], }, }, cases: { @@ -1108,7 +1108,7 @@ describe('featurePrivilegeIterator', () => { }, alerting: { alert: { - all: ['alerting-all-sub-type'], + all: [{ ruleTypeId: 'alerting-all-sub-type', consumers: ['foo'] }], }, }, cases: { @@ -1153,12 +1153,12 @@ describe('featurePrivilegeIterator', () => { }, alerting: { rule: { - all: ['alerting-all-type'], + all: [{ ruleTypeId: 'alerting-all-type', consumers: ['foo'] }], read: [], }, alert: { - all: ['alerting-all-sub-type'], - read: ['alerting-another-read-type'], + all: [{ ruleTypeId: 'alerting-all-sub-type', consumers: ['foo'] }], + read: [{ ruleTypeId: 'alerting-another-read-type', consumers: ['foo'] }], }, }, cases: { @@ -1188,10 +1188,10 @@ describe('featurePrivilegeIterator', () => { }, alerting: { rule: { - read: ['alerting-read-type'], + read: [{ ruleTypeId: 'alerting-read-type', consumers: ['foo'] }], }, alert: { - read: ['alerting-read-type'], + read: [{ ruleTypeId: 'alerting-read-type', consumers: ['foo'] }], }, }, cases: { @@ -1350,8 +1350,8 @@ describe('featurePrivilegeIterator', () => { }, alerting: { rule: { - all: ['alerting-all-sub-type'], - read: ['alerting-read-sub-type'], + all: [{ ruleTypeId: 'alerting-all-sub-type', consumers: ['foo'] }], + read: [{ ruleTypeId: 'alerting-read-sub-type', consumers: ['foo'] }], }, }, cases: { @@ -1396,8 +1396,8 @@ describe('featurePrivilegeIterator', () => { }, alerting: { rule: { - all: ['alerting-all-sub-type'], - read: ['alerting-read-sub-type'], + all: [{ ruleTypeId: 'alerting-all-sub-type', consumers: ['foo'] }], + read: [{ ruleTypeId: 'alerting-read-sub-type', consumers: ['foo'] }], }, alert: { all: [], @@ -1432,8 +1432,8 @@ describe('featurePrivilegeIterator', () => { }, alerting: { rule: { - all: ['alerting-all-sub-type'], - read: ['alerting-read-sub-type'], + all: [{ ruleTypeId: 'alerting-all-sub-type', consumers: ['foo'] }], + read: [{ ruleTypeId: 'alerting-read-sub-type', consumers: ['foo'] }], }, alert: { all: [], @@ -1475,10 +1475,10 @@ describe('featurePrivilegeIterator', () => { }, alerting: { rule: { - all: ['alerting-all-type'], + all: [{ ruleTypeId: 'alerting-all-type', consumers: ['foo'] }], }, alert: { - read: ['alerting-another-read-type'], + read: [{ ruleTypeId: 'alerting-another-read-type', consumers: ['foo'] }], }, }, cases: { @@ -1505,10 +1505,10 @@ describe('featurePrivilegeIterator', () => { }, alerting: { rule: { - read: ['alerting-read-type'], + read: [{ ruleTypeId: 'alerting-read-type', consumers: ['foo'] }], }, alert: { - read: ['alerting-read-type'], + read: [{ ruleTypeId: 'alerting-read-type', consumers: ['foo'] }], }, }, cases: { @@ -1564,12 +1564,12 @@ describe('featurePrivilegeIterator', () => { }, alerting: { rule: { - all: ['alerting-all-type'], + all: [{ ruleTypeId: 'alerting-all-type', consumers: ['foo'] }], read: [], }, alert: { all: [], - read: ['alerting-another-read-type'], + read: [{ ruleTypeId: 'alerting-another-read-type', consumers: ['foo'] }], }, }, cases: { @@ -1600,11 +1600,11 @@ describe('featurePrivilegeIterator', () => { alerting: { rule: { all: [], - read: ['alerting-read-type'], + read: [{ ruleTypeId: 'alerting-read-type', consumers: ['foo'] }], }, alert: { all: [], - read: ['alerting-read-type'], + read: [{ ruleTypeId: 'alerting-read-type', consumers: ['foo'] }], }, }, cases: { diff --git a/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client_factory.test.ts b/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client_factory.test.ts index 367ead5744d55c..8613f6135d30ae 100644 --- a/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client_factory.test.ts +++ b/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client_factory.test.ts @@ -21,7 +21,7 @@ const alertingAuthMock = alertingAuthorizationMock.create(); const alertsClientFactoryParams: AlertsClientFactoryProps = { logger: loggingSystemMock.create().get(), - getAlertingAuthorization: (_: KibanaRequest) => alertingAuthMock, + getAlertingAuthorization: (_: KibanaRequest) => Promise.resolve(alertingAuthMock), securityPluginSetup, esClient: {} as ElasticsearchClient, ruleDataService: ruleDataServiceMock.create(), diff --git a/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client_factory.ts b/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client_factory.ts index 934074cc4a2ed6..b2fe182a0ba0a5 100644 --- a/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client_factory.ts +++ b/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client_factory.ts @@ -19,7 +19,9 @@ import { AlertsClient } from './alerts_client'; export interface AlertsClientFactoryProps { logger: Logger; esClient: ElasticsearchClient; - getAlertingAuthorization: (request: KibanaRequest) => PublicMethodsOf; + getAlertingAuthorization: ( + request: KibanaRequest + ) => Promise>; securityPluginSetup: SecurityPluginSetup | undefined; ruleDataService: IRuleDataService | null; getRuleType: RuleTypeRegistry['get']; @@ -33,7 +35,7 @@ export class AlertsClientFactory { private esClient!: ElasticsearchClient; private getAlertingAuthorization!: ( request: KibanaRequest - ) => PublicMethodsOf; + ) => Promise>; private securityPluginSetup!: SecurityPluginSetup | undefined; private ruleDataService!: IRuleDataService | null; private getRuleType!: RuleTypeRegistry['get']; @@ -61,10 +63,11 @@ export class AlertsClientFactory { public async create(request: KibanaRequest): Promise { const { securityPluginSetup, getAlertingAuthorization, logger } = this; + const authorization = await getAlertingAuthorization(request); return new AlertsClient({ logger, - authorization: getAlertingAuthorization(request), + authorization, auditLogger: securityPluginSetup?.audit.asScoped(request), esClient: this.esClient, ruleDataService: this.ruleDataService!, diff --git a/x-pack/plugins/rule_registry/server/plugin.ts b/x-pack/plugins/rule_registry/server/plugin.ts index 2a430c45b54d88..7f7cbc8959583b 100644 --- a/x-pack/plugins/rule_registry/server/plugin.ts +++ b/x-pack/plugins/rule_registry/server/plugin.ts @@ -188,7 +188,7 @@ export class RuleRegistryPlugin return function alertsRouteHandlerContext(context, request): RacApiRequestHandlerContext { return { getAlertsClient: async () => { - const createdClient = alertsClientFactory.create(request); + const createdClient = await alertsClientFactory.create(request); return createdClient; }, }; From e7363b13538283251cc2cbc89a7c5a6240032823 Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Fri, 12 Jul 2024 15:40:39 +0300 Subject: [PATCH 008/106] Add the alerts consumers to all rule types --- .../alerting_example/server/plugin.ts | 76 ++++++++++--- .../features/src/security/kibana_features.ts | 3 +- .../plugins/ml/common/types/capabilities.ts | 3 +- x-pack/plugins/monitoring/server/plugin.ts | 3 +- .../apm/server/feature.ts | 3 +- .../infra/server/features.ts | 5 +- .../observability/server/plugin.ts | 3 +- .../slo/server/plugin.ts | 3 +- .../synthetics/server/feature.ts | 3 +- x-pack/plugins/stack_alerts/server/feature.ts | 3 +- .../common/plugins/alerts/server/plugin.ts | 102 ++++++------------ 11 files changed, 113 insertions(+), 94 deletions(-) diff --git a/x-pack/examples/alerting_example/server/plugin.ts b/x-pack/examples/alerting_example/server/plugin.ts index f02580e78f702d..28f8978848096c 100644 --- a/x-pack/examples/alerting_example/server/plugin.ts +++ b/x-pack/examples/alerting_example/server/plugin.ts @@ -12,6 +12,7 @@ import { DEFAULT_APP_CATEGORIES } from '@kbn/core-application-common'; import { PluginSetupContract as AlertingSetup } from '@kbn/alerting-plugin/server'; import { PluginSetupContract as FeaturesPluginSetup } from '@kbn/features-plugin/server'; +import { ALERTING_FEATURE_ID } from '@kbn/alerting-plugin/common'; import { ruleType as alwaysFiringRule } from './rule_types/always_firing'; import { ruleType as peopleInSpaceRule } from './rule_types/astros'; import { ruleType as patternRule } from './rule_types/pattern'; @@ -76,25 +77,52 @@ export class AlertingExamplePlugin implements Plugin ({ ruleTypeId, - consumers: [SERVER_APP_ID], + consumers: [SERVER_APP_ID, ALERTING_FEATURE_ID], })); export const getSecurityBaseKibanaFeature = ({ diff --git a/x-pack/plugins/ml/common/types/capabilities.ts b/x-pack/plugins/ml/common/types/capabilities.ts index ff97c4f7159d93..ff5cfe88edf169 100644 --- a/x-pack/plugins/ml/common/types/capabilities.ts +++ b/x-pack/plugins/ml/common/types/capabilities.ts @@ -6,6 +6,7 @@ */ import type { KibanaRequest } from '@kbn/core/server'; +import { ALERTING_FEATURE_ID } from '@kbn/alerting-plugin/common'; import { PLUGIN_ID } from '../constants/app'; import { ML_JOB_SAVED_OBJECT_TYPE, @@ -110,7 +111,7 @@ export function getDefaultCapabilities(): MlCapabilities { const alertingFeatures = Object.values(ML_ALERT_TYPES).map((ruleTypeId) => ({ ruleTypeId, - consumers: [PLUGIN_ID], + consumers: [PLUGIN_ID, ALERTING_FEATURE_ID], })); export function getPluginPrivileges() { diff --git a/x-pack/plugins/monitoring/server/plugin.ts b/x-pack/plugins/monitoring/server/plugin.ts index 1e98695be420d9..777fe157bb841f 100644 --- a/x-pack/plugins/monitoring/server/plugin.ts +++ b/x-pack/plugins/monitoring/server/plugin.ts @@ -23,6 +23,7 @@ import { import { get } from 'lodash'; import { DEFAULT_APP_CATEGORIES } from '@kbn/core/server'; import { RouteMethod } from '@kbn/core/server'; +import { ALERTING_FEATURE_ID } from '@kbn/alerting-plugin/common'; import { KIBANA_MONITORING_LOGGING_TAG, KIBANA_STATS_TYPE_MONITORING, @@ -268,7 +269,7 @@ export class MonitoringPlugin registerPluginInUI(plugins: PluginsSetup) { const alertingFeatures = RULES.map((ruleTypeId) => ({ ruleTypeId, - consumers: ['monitoring'], + consumers: ['monitoring', ALERTING_FEATURE_ID], })); plugins.features.registerKibanaFeature({ diff --git a/x-pack/plugins/observability_solution/apm/server/feature.ts b/x-pack/plugins/observability_solution/apm/server/feature.ts index 57e9b7fc2a3b5d..9c2d5dc5c3c4e5 100644 --- a/x-pack/plugins/observability_solution/apm/server/feature.ts +++ b/x-pack/plugins/observability_solution/apm/server/feature.ts @@ -15,11 +15,12 @@ import { import { APM_INDEX_SETTINGS_SAVED_OBJECT_TYPE } from '@kbn/apm-data-access-plugin/server/saved_objects/apm_indices'; import { ApmRuleType } from '@kbn/rule-data-utils'; +import { ALERTING_FEATURE_ID } from '@kbn/alerting-plugin/common'; import { APM_SERVER_FEATURE_ID } from '../common/rules/apm_rule_types'; const alertingFeatures = Object.values(ApmRuleType).map((ruleTypeId) => ({ ruleTypeId, - consumers: [APM_SERVER_FEATURE_ID], + consumers: [APM_SERVER_FEATURE_ID, ALERTING_FEATURE_ID], })); export const APM_FEATURE = { diff --git a/x-pack/plugins/observability_solution/infra/server/features.ts b/x-pack/plugins/observability_solution/infra/server/features.ts index ed47de593654e2..5a2a694ea050fa 100644 --- a/x-pack/plugins/observability_solution/infra/server/features.ts +++ b/x-pack/plugins/observability_solution/infra/server/features.ts @@ -14,6 +14,7 @@ import { } from '@kbn/rule-data-utils'; import { ES_QUERY_ID } from '@kbn/rule-data-utils'; import { metricsDataSourceSavedObjectName } from '@kbn/metrics-data-access-plugin/server'; +import { ALERTING_FEATURE_ID } from '@kbn/alerting-plugin/common'; import { LOG_DOCUMENT_COUNT_RULE_TYPE_ID } from '../common/alerting/logs/log_threshold/types'; import { METRIC_INVENTORY_THRESHOLD_ALERT_TYPE_ID, @@ -32,7 +33,7 @@ const metricRuleTypes = [ const metricAlertingFeatures = metricRuleTypes.map((ruleTypeId) => ({ ruleTypeId, - consumers: [METRICS_FEATURE_ID], + consumers: [METRICS_FEATURE_ID, ALERTING_FEATURE_ID], })); export const METRICS_FEATURE = { @@ -103,7 +104,7 @@ const logsRuleTypes = [ const logsAlertingFeatures = logsRuleTypes.map((ruleTypeId) => ({ ruleTypeId, - consumers: [LOGS_FEATURE_ID], + consumers: [LOGS_FEATURE_ID, ALERTING_FEATURE_ID], })); export const LOGS_FEATURE = { diff --git a/x-pack/plugins/observability_solution/observability/server/plugin.ts b/x-pack/plugins/observability_solution/observability/server/plugin.ts index d84a3105bfbcf8..eb25c6045c08fe 100644 --- a/x-pack/plugins/observability_solution/observability/server/plugin.ts +++ b/x-pack/plugins/observability_solution/observability/server/plugin.ts @@ -37,6 +37,7 @@ import { SharePluginSetup } from '@kbn/share-plugin/server'; import { SpacesPluginSetup, SpacesPluginStart } from '@kbn/spaces-plugin/server'; import { UsageCollectionSetup } from '@kbn/usage-collection-plugin/server'; import { DataViewsServerPluginStart } from '@kbn/data-views-plugin/server'; +import { ALERTING_FEATURE_ID } from '@kbn/alerting-plugin/common'; import { ObservabilityConfig } from '.'; import { casesFeatureId, observabilityFeatureId } from '../common'; import { @@ -86,7 +87,7 @@ const o11yRuleTypes = [ const alertingFeatures = o11yRuleTypes.map((ruleTypeId) => ({ ruleTypeId, - consumers: [observabilityFeatureId], + consumers: [observabilityFeatureId, ALERTING_FEATURE_ID], })); export class ObservabilityPlugin implements Plugin { diff --git a/x-pack/plugins/observability_solution/slo/server/plugin.ts b/x-pack/plugins/observability_solution/slo/server/plugin.ts index 0c849290f9fd29..16e33aa9d503e2 100644 --- a/x-pack/plugins/observability_solution/slo/server/plugin.ts +++ b/x-pack/plugins/observability_solution/slo/server/plugin.ts @@ -33,6 +33,7 @@ import { SpacesPluginSetup, SpacesPluginStart } from '@kbn/spaces-plugin/server' import { AlertsLocatorDefinition } from '@kbn/observability-plugin/common'; import { SLO_BURN_RATE_RULE_TYPE_ID } from '@kbn/rule-data-utils'; import { sloFeatureId } from '@kbn/observability-plugin/common'; +import { ALERTING_FEATURE_ID } from '@kbn/alerting-plugin/common'; import { registerSloUsageCollector } from './lib/collectors/register'; import { SloOrphanSummaryCleanupTask } from './services/tasks/orphan_summary_cleanup_task'; import { slo, SO_SLO_TYPE } from './saved_objects'; @@ -83,7 +84,7 @@ export class SloPlugin implements Plugin { const alertingFeatures = sloRuleTypes.map((ruleTypeId) => ({ ruleTypeId, - consumers: [sloFeatureId], + consumers: [sloFeatureId, ALERTING_FEATURE_ID], })); plugins.features.registerKibanaFeature({ diff --git a/x-pack/plugins/observability_solution/synthetics/server/feature.ts b/x-pack/plugins/observability_solution/synthetics/server/feature.ts index 03703fde0e956c..3165d68fc4cb6a 100644 --- a/x-pack/plugins/observability_solution/synthetics/server/feature.ts +++ b/x-pack/plugins/observability_solution/synthetics/server/feature.ts @@ -11,6 +11,7 @@ import { SubFeaturePrivilegeGroupConfig, SubFeaturePrivilegeGroupType, } from '@kbn/features-plugin/common'; +import { ALERTING_FEATURE_ID } from '@kbn/alerting-plugin/common'; import { syntheticsMonitorType, syntheticsParamType } from '../common/types/saved_objects'; import { SYNTHETICS_RULE_TYPES } from '../common/constants/synthetics_alerts'; import { privateLocationsSavedObjectName } from '../common/saved_objects/private_locations'; @@ -32,7 +33,7 @@ const ruleTypes = [...UPTIME_RULE_TYPES, ...SYNTHETICS_RULE_TYPES]; const alertingFeatures = ruleTypes.map((ruleTypeId) => ({ ruleTypeId, - consumers: [PLUGIN.ID], + consumers: [PLUGIN.ID, ALERTING_FEATURE_ID], })); const elasticManagedLocationsEnabledPrivilege: SubFeaturePrivilegeGroupConfig = { diff --git a/x-pack/plugins/stack_alerts/server/feature.ts b/x-pack/plugins/stack_alerts/server/feature.ts index bacc0d2f3c9518..6851ba5c112b40 100644 --- a/x-pack/plugins/stack_alerts/server/feature.ts +++ b/x-pack/plugins/stack_alerts/server/feature.ts @@ -11,6 +11,7 @@ import { DEFAULT_APP_CATEGORIES } from '@kbn/core/server'; import { TRANSFORM_RULE_TYPE } from '@kbn/transform-plugin/common'; import { STACK_ALERTS_FEATURE_ID } from '@kbn/rule-data-utils'; import { ES_QUERY_ID as ElasticsearchQuery } from '@kbn/rule-data-utils'; +import { ALERTING_FEATURE_ID } from '@kbn/alerting-plugin/common'; import { ID as IndexThreshold } from './rule_types/index_threshold/rule_type'; import { GEO_CONTAINMENT_ID as GeoContainment } from './rule_types/geo_containment'; @@ -19,7 +20,7 @@ const TransformHealth = TRANSFORM_RULE_TYPE.TRANSFORM_HEALTH; const alertingFeatures = [IndexThreshold, GeoContainment, ElasticsearchQuery, TransformHealth].map( (ruleTypeId) => ({ ruleTypeId, - consumers: [STACK_ALERTS_FEATURE_ID], + consumers: [STACK_ALERTS_FEATURE_ID, ALERTING_FEATURE_ID], }) ); diff --git a/x-pack/test/alerting_api_integration/common/plugins/alerts/server/plugin.ts b/x-pack/test/alerting_api_integration/common/plugins/alerts/server/plugin.ts index 4cafa57d3d480a..ad6b3d945f4725 100644 --- a/x-pack/test/alerting_api_integration/common/plugins/alerts/server/plugin.ts +++ b/x-pack/test/alerting_api_integration/common/plugins/alerts/server/plugin.ts @@ -25,6 +25,7 @@ import { RuleRegistryPluginSetupContract } from '@kbn/rule-registry-plugin/serve import { IEventLogClientService } from '@kbn/event-log-plugin/server'; import { NotificationsPluginStart } from '@kbn/notifications-plugin/server'; import { RULE_SAVED_OBJECT_TYPE } from '@kbn/alerting-plugin/server'; +import { ALERTING_FEATURE_ID } from '@kbn/alerting-plugin/common'; import { defineRoutes } from './routes'; import { defineActionTypes } from './action_types'; import { defineRuleTypes } from './rule_types'; @@ -49,6 +50,35 @@ export interface FixtureStartDeps { notifications: NotificationsPluginStart; } +const testRuleTypes = [ + 'test.always-firing', + 'test.cumulative-firing', + 'test.never-firing', + 'test.failing', + 'test.authorization', + 'test.delayed', + 'test.validation', + 'test.onlyContextVariables', + 'test.onlyStateVariables', + 'test.noop', + 'test.unrestricted-noop', + 'test.patternFiring', + 'test.patternSuccessOrFailure', + 'test.throw', + 'test.longRunning', + 'test.exceedsAlertLimit', + 'test.always-firing-alert-as-data', + 'test.patternFiringAad', + 'test.waitingRule', + 'test.patternFiringAutoRecoverFalse', + 'test.severity', +]; + +const testAlertingFeatures = testRuleTypes.map((ruleTypeId) => ({ + ruleTypeId, + consumers: ['alertsFixture', ALERTING_FEATURE_ID], +})); + export class FixturePlugin implements Plugin { private readonly logger: Logger; @@ -71,29 +101,7 @@ export class FixturePlugin implements Plugin Date: Fri, 12 Jul 2024 16:22:09 +0300 Subject: [PATCH 009/106] Fix async type errors --- ...rting_authorization_client_factory.test.ts | 2 - .../alerting_authorization.test.ts | 237 +++++++++--------- .../authorization/alerting_authorization.ts | 28 +-- x-pack/plugins/alerting/server/index.ts | 2 +- x-pack/plugins/alerting/server/mocks.ts | 6 +- x-pack/plugins/alerting/server/plugin.test.ts | 6 +- x-pack/plugins/alerting/server/plugin.ts | 24 +- .../apis/delete/delete_backfill_route.ts | 3 +- .../backfill/apis/find/find_backfill_route.ts | 3 +- .../backfill/apis/get/get_backfill_route.ts | 3 +- .../apis/schedule/schedule_backfill_route.ts | 3 +- .../alerting/server/routes/disable_rule.ts | 3 +- .../alerting/server/routes/enable_rule.ts | 3 +- .../server/routes/get_action_error_log.ts | 3 +- .../server/routes/get_global_execution_kpi.ts | 3 +- .../routes/get_global_execution_logs.ts | 3 +- .../server/routes/get_rule_alert_summary.ts | 3 +- .../server/routes/get_rule_execution_kpi.ts | 3 +- .../server/routes/get_rule_execution_log.ts | 3 +- .../alerting/server/routes/get_rule_state.ts | 3 +- .../plugins/alerting/server/routes/health.ts | 3 +- .../alerting/server/routes/legacy/create.ts | 4 +- .../alerting/server/routes/legacy/delete.ts | 3 +- .../alerting/server/routes/legacy/disable.ts | 3 +- .../alerting/server/routes/legacy/enable.ts | 3 +- .../alerting/server/routes/legacy/find.ts | 3 +- .../alerting/server/routes/legacy/get.ts | 3 +- .../legacy/get_alert_instance_summary.ts | 3 +- .../server/routes/legacy/get_alert_state.ts | 3 +- .../alerting/server/routes/legacy/health.ts | 3 +- .../server/routes/legacy/list_alert_types.ts | 4 +- .../alerting/server/routes/legacy/mute_all.ts | 3 +- .../server/routes/legacy/mute_instance.ts | 3 +- .../server/routes/legacy/unmute_all.ts | 3 +- .../server/routes/legacy/unmute_instance.ts | 3 +- .../alerting/server/routes/legacy/update.ts | 3 +- .../server/routes/legacy/update_api_key.ts | 3 +- .../alerting/server/routes/mute_all_rule.ts | 3 +- .../apis/aggregate/aggregate_rules_route.ts | 3 +- .../bulk_delete/bulk_delete_rules_route.ts | 3 +- .../bulk_disable/bulk_disable_rules_route.ts | 3 +- .../apis/bulk_edit/bulk_edit_rules_route.ts | 3 +- .../bulk_enable/bulk_enable_rules_route.ts | 3 +- .../bulk_untrack/bulk_untrack_alerts_route.ts | 3 +- .../bulk_untrack_alerts_by_query_route.ts | 3 +- .../rule/apis/clone/clone_rule_route.ts | 3 +- .../rule/apis/create/create_rule_route.ts | 3 +- .../rule/apis/delete/delete_rule_route.ts | 3 +- .../routes/rule/apis/find/find_rules_route.ts | 6 +- .../routes/rule/apis/get/get_rule_route.ts | 3 +- .../get_schedule_frequency_route.ts | 3 +- .../routes/rule/apis/mute_alert/mute_alert.ts | 3 +- .../rule/apis/resolve/resolve_rule_route.ts | 3 +- .../rule/apis/snooze/snooze_rule_route.ts | 3 +- .../routes/rule/apis/tags/get_rule_tags.ts | 3 +- .../rule/apis/unsnooze/unsnooze_rule_route.ts | 3 +- .../rule/apis/update/update_rule_route.ts | 3 +- .../alerting/server/routes/rule_types.ts | 3 +- .../alerting/server/routes/run_soon.ts | 3 +- .../suggestions/values_suggestion_alerts.ts | 3 +- .../suggestions/values_suggestion_rules.ts | 3 +- .../alerting/server/routes/unmute_alert.ts | 3 +- .../alerting/server/routes/unmute_all_rule.ts | 3 +- .../server/routes/update_rule_api_key.ts | 3 +- .../server/rules_client_factory.test.ts | 4 +- .../alerting/server/rules_client_factory.ts | 8 +- .../server/task_runner/rule_loader.test.ts | 17 +- .../server/task_runner/rule_loader.ts | 6 +- .../server/task_runner/task_runner.test.ts | 2 +- .../server/task_runner/task_runner.ts | 2 +- .../task_runner_alerts_client.test.ts | 2 +- .../task_runner/task_runner_cancel.test.ts | 2 +- .../alerting/server/task_runner/types.ts | 2 +- x-pack/plugins/alerting/server/types.ts | 8 +- .../features/server/feature_registry.test.ts | 100 ++++++-- 75 files changed, 375 insertions(+), 259 deletions(-) diff --git a/x-pack/plugins/alerting/server/alerting_authorization_client_factory.test.ts b/x-pack/plugins/alerting/server/alerting_authorization_client_factory.test.ts index dca53bb3188e95..b6dac4e3f52d12 100644 --- a/x-pack/plugins/alerting/server/alerting_authorization_client_factory.test.ts +++ b/x-pack/plugins/alerting/server/alerting_authorization_client_factory.test.ts @@ -17,7 +17,6 @@ jest.mock('./authorization/alerting_authorization'); const features = featuresPluginMock.createStart(); -const securityPluginSetup = securityMock.createSetup(); const securityPluginStart = securityMock.createStart(); const alertingAuthorizationClientFactoryParams: jest.Mocked = @@ -35,7 +34,6 @@ beforeEach(() => { test('creates an alerting authorization client with proper constructor arguments when security is enabled', async () => { const factory = new AlertingAuthorizationClientFactory(); factory.initialize({ - securityPluginSetup, securityPluginStart, ...alertingAuthorizationClientFactoryParams, }); diff --git a/x-pack/plugins/alerting/server/authorization/alerting_authorization.test.ts b/x-pack/plugins/alerting/server/authorization/alerting_authorization.test.ts index b0b0801f5b0435..eb6a7b7a33e96c 100644 --- a/x-pack/plugins/alerting/server/authorization/alerting_authorization.test.ts +++ b/x-pack/plugins/alerting/server/authorization/alerting_authorization.test.ts @@ -29,6 +29,8 @@ import { schema } from '@kbn/config-schema'; const ruleTypeRegistry = ruleTypeRegistryMock.create(); const features: jest.Mocked = featuresPluginMock.createStart(); const request = {} as KibanaRequest; +const allRegisteredConsumers = new Set(); +const ruleTypesConsumersMap = new Map>(); const getSpace = jest.fn(); const getSpaceId = () => 'space1'; @@ -41,7 +43,7 @@ const mockAuthorizationAction = ( ) => `${ruleType}/${consumer}/${entity}/${operation}`; function mockSecurity() { - const security = securityMock.createSetup(); + const security = securityMock.createStart(); const authorization = security.authz; // typescript is having trouble inferring jest's automocking ( @@ -53,28 +55,32 @@ function mockSecurity() { return { authorization }; } -function mockFeature(appName: string, typeName?: string | string[]) { - const typeNameArray = typeName ? (Array.isArray(typeName) ? typeName : [typeName]) : undefined; +function mockFeature(appName: string, typeName?: string[]) { + const alertingFeatures = typeName?.map((ruleTypeId) => ({ + ruleTypeId, + consumers: [appName], + })); + return new KibanaFeature({ id: appName, name: appName, app: [], category: { id: 'foo', label: 'foo' }, - ...(typeNameArray + ...(alertingFeatures ? { - alerting: { ruleTypeIds: typeNameArray, consumers: [appName] }, + alerting: alertingFeatures, } : {}), privileges: { all: { - ...(typeNameArray + ...(alertingFeatures ? { alerting: { rule: { - all: { ruleTypeIds: typeNameArray, consumers: [appName] }, + all: alertingFeatures, }, alert: { - all: { ruleTypeIds: typeNameArray, consumers: [appName] }, + all: alertingFeatures, }, }, } @@ -86,14 +92,14 @@ function mockFeature(appName: string, typeName?: string | string[]) { ui: [], }, read: { - ...(typeNameArray + ...(alertingFeatures ? { alerting: { rule: { - read: { ruleTypeIds: typeNameArray, consumers: [appName] }, + read: alertingFeatures, }, alert: { - read: { ruleTypeIds: typeNameArray, consumers: [appName] }, + read: alertingFeatures, }, }, } @@ -108,15 +114,20 @@ function mockFeature(appName: string, typeName?: string | string[]) { }); } -function mockFeatureWithSubFeature(appName: string, typeName: string) { +function mockFeatureWithSubFeature(appName: string, typeName: string[]) { + const alertingFeatures = typeName?.map((ruleTypeId) => ({ + ruleTypeId, + consumers: [appName], + })); + return new KibanaFeature({ id: appName, name: appName, app: [], category: { id: 'foo', label: 'foo' }, - ...(typeName + ...(alertingFeatures ? { - alerting: { ruleTypeIds: [typeName], consumers: [appName] }, + alerting: alertingFeatures, } : {}), privileges: { @@ -148,7 +159,7 @@ function mockFeatureWithSubFeature(appName: string, typeName: string) { includeIn: 'all', alerting: { rule: { - all: { ruleTypeIds: [typeName], consumers: [appName] }, + all: alertingFeatures, }, }, savedObject: { @@ -163,7 +174,7 @@ function mockFeatureWithSubFeature(appName: string, typeName: string) { includeIn: 'read', alerting: { rule: { - read: { ruleTypeIds: [typeName], consumers: [appName] }, + read: alertingFeatures, }, }, savedObject: { @@ -180,9 +191,9 @@ function mockFeatureWithSubFeature(appName: string, typeName: string) { }); } -const myAppFeature = mockFeature('myApp', 'myType'); -const myOtherAppFeature = mockFeature('myOtherApp', 'myType'); -const myAppWithSubFeature = mockFeatureWithSubFeature('myAppWithSubFeature', 'myType'); +const myAppFeature = mockFeature('myApp', ['myType']); +const myOtherAppFeature = mockFeature('myOtherApp', ['myType']); +const myAppWithSubFeature = mockFeatureWithSubFeature('myAppWithSubFeature', ['myType']); const myFeatureWithoutAlerting = mockFeature('myOtherApp'); beforeEach(() => { @@ -227,9 +238,9 @@ describe('AlertingAuthorization', () => { new AlertingAuthorization({ request, ruleTypeRegistry, - features, - getSpace, getSpaceId, + allRegisteredConsumers, + ruleTypesConsumersMap, }); expect(getSpace).toHaveBeenCalledWith(request); @@ -241,9 +252,9 @@ describe('AlertingAuthorization', () => { const alertAuthorization = new AlertingAuthorization({ request, ruleTypeRegistry, - features, - getSpace, getSpaceId, + allRegisteredConsumers, + ruleTypesConsumersMap, }); await alertAuthorization.ensureAuthorized({ @@ -263,9 +274,9 @@ describe('AlertingAuthorization', () => { request, ruleTypeRegistry, authorization, - features, - getSpace, getSpaceId, + allRegisteredConsumers, + ruleTypesConsumersMap, }); await alertAuthorization.ensureAuthorized({ @@ -286,11 +297,11 @@ describe('AlertingAuthorization', () => { authorization.checkPrivilegesDynamicallyWithRequest.mockReturnValue(checkPrivileges); const alertAuthorization = new AlertingAuthorization({ request, - authorization, ruleTypeRegistry, - features, - getSpace, + authorization, getSpaceId, + allRegisteredConsumers, + ruleTypesConsumersMap, }); checkPrivileges.mockResolvedValueOnce({ @@ -328,11 +339,11 @@ describe('AlertingAuthorization', () => { authorization.checkPrivilegesDynamicallyWithRequest.mockReturnValue(checkPrivileges); const alertAuthorization = new AlertingAuthorization({ request, - authorization, ruleTypeRegistry, - features, - getSpace, + authorization, getSpaceId, + allRegisteredConsumers, + ruleTypesConsumersMap, }); checkPrivileges.mockResolvedValueOnce({ @@ -370,11 +381,11 @@ describe('AlertingAuthorization', () => { authorization.checkPrivilegesDynamicallyWithRequest.mockReturnValue(checkPrivileges); const alertAuthorization = new AlertingAuthorization({ request, - authorization, ruleTypeRegistry, - features, - getSpace, + authorization, getSpaceId, + allRegisteredConsumers, + ruleTypesConsumersMap, }); checkPrivileges.mockResolvedValueOnce({ @@ -412,11 +423,11 @@ describe('AlertingAuthorization', () => { authorization.checkPrivilegesDynamicallyWithRequest.mockReturnValue(checkPrivileges); const alertAuthorization = new AlertingAuthorization({ request, - authorization, ruleTypeRegistry, - features, - getSpace, + authorization, getSpaceId, + allRegisteredConsumers, + ruleTypesConsumersMap, }); checkPrivileges.mockResolvedValueOnce({ @@ -460,11 +471,11 @@ describe('AlertingAuthorization', () => { const alertAuthorization = new AlertingAuthorization({ request, - authorization, ruleTypeRegistry, - features, - getSpace, + authorization, getSpaceId, + allRegisteredConsumers, + ruleTypesConsumersMap, }); await alertAuthorization.ensureAuthorized({ @@ -502,11 +513,11 @@ describe('AlertingAuthorization', () => { const alertAuthorization = new AlertingAuthorization({ request, - authorization, ruleTypeRegistry, - features, - getSpace, + authorization, getSpaceId, + allRegisteredConsumers, + ruleTypesConsumersMap, }); await alertAuthorization.ensureAuthorized({ @@ -544,11 +555,11 @@ describe('AlertingAuthorization', () => { const alertAuthorization = new AlertingAuthorization({ request, - authorization, ruleTypeRegistry, - features, - getSpace, + authorization, getSpaceId, + allRegisteredConsumers, + ruleTypesConsumersMap, }); await alertAuthorization.ensureAuthorized({ @@ -580,11 +591,11 @@ describe('AlertingAuthorization', () => { authorization.checkPrivilegesDynamicallyWithRequest.mockReturnValue(checkPrivileges); const alertAuthorization = new AlertingAuthorization({ request, - authorization, ruleTypeRegistry, - features, - getSpace, + authorization, getSpaceId, + allRegisteredConsumers, + ruleTypesConsumersMap, }); checkPrivileges.mockResolvedValueOnce({ @@ -624,11 +635,11 @@ describe('AlertingAuthorization', () => { authorization.checkPrivilegesDynamicallyWithRequest.mockReturnValue(checkPrivileges); const alertAuthorization = new AlertingAuthorization({ request, - authorization, ruleTypeRegistry, - features, - getSpace, + authorization, getSpaceId, + allRegisteredConsumers, + ruleTypesConsumersMap, }); checkPrivileges.mockResolvedValueOnce({ @@ -672,11 +683,11 @@ describe('AlertingAuthorization', () => { authorization.checkPrivilegesDynamicallyWithRequest.mockReturnValue(checkPrivileges); const alertAuthorization = new AlertingAuthorization({ request, - authorization, ruleTypeRegistry, - features, - getSpace, + authorization, getSpaceId, + allRegisteredConsumers, + ruleTypesConsumersMap, }); checkPrivileges.mockResolvedValueOnce({ @@ -716,11 +727,11 @@ describe('AlertingAuthorization', () => { authorization.checkPrivilegesDynamicallyWithRequest.mockReturnValue(checkPrivileges); const alertAuthorization = new AlertingAuthorization({ request, - authorization, ruleTypeRegistry, - features, - getSpace, + authorization, getSpaceId, + allRegisteredConsumers, + ruleTypesConsumersMap, }); checkPrivileges.mockResolvedValueOnce({ @@ -760,11 +771,11 @@ describe('AlertingAuthorization', () => { authorization.checkPrivilegesDynamicallyWithRequest.mockReturnValue(checkPrivileges); const alertAuthorization = new AlertingAuthorization({ request, - authorization, ruleTypeRegistry, - features, - getSpace, + authorization, getSpaceId, + allRegisteredConsumers, + ruleTypesConsumersMap, }); checkPrivileges.mockResolvedValueOnce({ @@ -850,9 +861,9 @@ describe('AlertingAuthorization', () => { const alertAuthorization = new AlertingAuthorization({ request, ruleTypeRegistry, - features, - getSpace, getSpaceId, + allRegisteredConsumers, + ruleTypesConsumersMap, }); const { filter, ensureRuleTypeIsAuthorized } = await alertAuthorization.getFindAuthorizationFilter(AlertingAuthorizationEntity.Rule, { @@ -869,9 +880,9 @@ describe('AlertingAuthorization', () => { const alertAuthorization = new AlertingAuthorization({ request, ruleTypeRegistry, - features, - getSpace, getSpaceId, + allRegisteredConsumers, + ruleTypesConsumersMap, }); const { ensureRuleTypeIsAuthorized } = await alertAuthorization.getFindAuthorizationFilter( AlertingAuthorizationEntity.Rule, @@ -889,7 +900,7 @@ describe('AlertingAuthorization', () => { test('creates a filter based on the privileged types', async () => { features.getKibanaFeatures.mockReturnValue([ mockFeature('myApp', ['myAppAlertType', 'mySecondAppAlertType']), - mockFeature('alerts', 'myOtherAppAlertType'), + mockFeature('alerts', ['myOtherAppAlertType']), myOtherAppFeature, myAppWithSubFeature, ]); @@ -981,11 +992,11 @@ describe('AlertingAuthorization', () => { }); const alertAuthorization = new AlertingAuthorization({ request, - authorization, ruleTypeRegistry, - features, - getSpace, + authorization, getSpaceId, + allRegisteredConsumers, + ruleTypesConsumersMap, }); ruleTypeRegistry.list.mockReturnValue(setOfAlertTypes); expect( @@ -1028,11 +1039,11 @@ describe('AlertingAuthorization', () => { }); const alertAuthorization = new AlertingAuthorization({ request, - authorization, ruleTypeRegistry, - features, - getSpace, + authorization, getSpaceId, + allRegisteredConsumers, + ruleTypesConsumersMap, }); ruleTypeRegistry.list.mockReturnValue(setOfAlertTypes); await expect( @@ -1089,11 +1100,11 @@ describe('AlertingAuthorization', () => { }); const alertAuthorization = new AlertingAuthorization({ request, - authorization, ruleTypeRegistry, - features, - getSpace, + authorization, getSpaceId, + allRegisteredConsumers, + ruleTypesConsumersMap, }); ruleTypeRegistry.list.mockReturnValue(setOfAlertTypes); const { ensureRuleTypeIsAuthorized } = await alertAuthorization.getFindAuthorizationFilter( @@ -1115,7 +1126,7 @@ describe('AlertingAuthorization', () => { test('creates an `ensureRuleTypeIsAuthorized` function which is no-op if type is authorized', async () => { features.getKibanaFeatures.mockReturnValue([ mockFeature('myApp', ['myOtherAppAlertType', 'myAppAlertType']), - mockFeature('myOtherApp', 'myAppAlertType'), + mockFeature('myOtherApp', ['myAppAlertType']), ]); const { authorization } = mockSecurity(); const checkPrivileges: jest.MockedFunction< @@ -1153,11 +1164,11 @@ describe('AlertingAuthorization', () => { }); const alertAuthorization = new AlertingAuthorization({ request, - authorization, ruleTypeRegistry, - features, - getSpace, + authorization, getSpaceId, + allRegisteredConsumers, + ruleTypesConsumersMap, }); ruleTypeRegistry.list.mockReturnValue(setOfAlertTypes); const { ensureRuleTypeIsAuthorized } = await alertAuthorization.getFindAuthorizationFilter( @@ -1228,11 +1239,11 @@ describe('AlertingAuthorization', () => { }); const alertAuthorization = new AlertingAuthorization({ request, - authorization, ruleTypeRegistry, - features, - getSpace, + authorization, getSpaceId, + allRegisteredConsumers, + ruleTypesConsumersMap, }); ruleTypeRegistry.list.mockReturnValue(setOfAlertTypes); const { ensureRuleTypeIsAuthorized } = await alertAuthorization.getFindAuthorizationFilter( @@ -1259,9 +1270,9 @@ describe('AlertingAuthorization', () => { const alertAuthorization = new AlertingAuthorization({ request, ruleTypeRegistry, - features, - getSpace, getSpaceId, + allRegisteredConsumers, + ruleTypesConsumersMap, }); const { filter } = await alertAuthorization.getFindAuthorizationFilter( AlertingAuthorizationEntity.Alert, @@ -1331,9 +1342,9 @@ describe('AlertingAuthorization', () => { const alertAuthorization = new AlertingAuthorization({ request, ruleTypeRegistry, - features, - getSpace, getSpaceId, + allRegisteredConsumers, + ruleTypesConsumersMap, }); ruleTypeRegistry.list.mockReturnValue(setOfAlertTypes); @@ -1461,11 +1472,11 @@ describe('AlertingAuthorization', () => { const alertAuthorization = new AlertingAuthorization({ request, - authorization, ruleTypeRegistry, - features, - getSpace, + authorization, getSpaceId, + allRegisteredConsumers, + ruleTypesConsumersMap, }); ruleTypeRegistry.list.mockReturnValue(setOfAlertTypes); @@ -1560,11 +1571,11 @@ describe('AlertingAuthorization', () => { const alertAuthorization = new AlertingAuthorization({ request, - authorization, ruleTypeRegistry, - features, - getSpace, + authorization, getSpaceId, + allRegisteredConsumers, + ruleTypesConsumersMap, }); ruleTypeRegistry.list.mockReturnValue(setOfAlertTypes); @@ -1664,11 +1675,11 @@ describe('AlertingAuthorization', () => { const alertAuthorization = new AlertingAuthorization({ request, - authorization, ruleTypeRegistry, - features, - getSpace, + authorization, getSpaceId, + allRegisteredConsumers, + ruleTypesConsumersMap, }); ruleTypeRegistry.list.mockReturnValue(setOfAlertTypes); @@ -1780,11 +1791,11 @@ describe('AlertingAuthorization', () => { const alertAuthorization = new AlertingAuthorization({ request, - authorization, ruleTypeRegistry, - features, - getSpace, + authorization, getSpaceId, + allRegisteredConsumers, + ruleTypesConsumersMap, }); ruleTypeRegistry.list.mockReturnValue(setOfAlertTypes); @@ -1903,11 +1914,11 @@ describe('AlertingAuthorization', () => { }); const alertAuthorization = new AlertingAuthorization({ request, - authorization, ruleTypeRegistry, - features, - getSpace, + authorization, getSpaceId, + allRegisteredConsumers, + ruleTypesConsumersMap, }); ruleTypeRegistry.list.mockReturnValue(setOfAlertTypes); @@ -1980,11 +1991,11 @@ describe('AlertingAuthorization', () => { }); const alertAuthorization = new AlertingAuthorization({ request, - authorization, ruleTypeRegistry, - features, - getSpace, + authorization, getSpaceId, + allRegisteredConsumers, + ruleTypesConsumersMap, }); ruleTypeRegistry.list.mockReturnValue(setOfAlertTypes); @@ -2227,11 +2238,11 @@ describe('AlertingAuthorization', () => { authorization.checkPrivilegesDynamicallyWithRequest.mockReturnValue(checkPrivileges); alertAuthorization = new AlertingAuthorization({ request, - authorization, ruleTypeRegistry, - features, - getSpace, + authorization, getSpaceId, + allRegisteredConsumers, + ruleTypesConsumersMap, }); }); @@ -2378,11 +2389,11 @@ describe('AlertingAuthorization', () => { authorization.checkPrivilegesDynamicallyWithRequest.mockReturnValue(checkPrivileges); alertAuthorization = new AlertingAuthorization({ request, - authorization, ruleTypeRegistry, - features, - getSpace, + authorization, getSpaceId, + allRegisteredConsumers, + ruleTypesConsumersMap, }); }); @@ -2525,11 +2536,11 @@ describe('AlertingAuthorization', () => { authorization.checkPrivilegesDynamicallyWithRequest.mockReturnValue(checkPrivileges); alertAuthorization = new AlertingAuthorization({ request, - authorization, ruleTypeRegistry, - features, - getSpace, + authorization, getSpaceId, + allRegisteredConsumers, + ruleTypesConsumersMap, }); }); diff --git a/x-pack/plugins/alerting/server/authorization/alerting_authorization.ts b/x-pack/plugins/alerting/server/authorization/alerting_authorization.ts index 2fcabfa510c28d..a4fc5d24454140 100644 --- a/x-pack/plugins/alerting/server/authorization/alerting_authorization.ts +++ b/x-pack/plugins/alerting/server/authorization/alerting_authorization.ts @@ -94,7 +94,7 @@ type ConstructorOptions = Pick< 'ruleTypeRegistry' | 'request' | 'authorization' | 'getSpaceId' > & { allRegisteredConsumers: Set; - ruleTypeConsumersMap: Map>; + ruleTypesConsumersMap: Map>; }; export class AlertingAuthorization { @@ -102,7 +102,7 @@ export class AlertingAuthorization { private readonly request: KibanaRequest; private readonly authorization?: SecurityPluginStart['authz']; private readonly allRegisteredConsumers: Set; - private readonly ruleTypeConsumersMap: Map>; + private readonly ruleTypesConsumersMap: Map>; private readonly spaceId: string | undefined; constructor({ @@ -111,18 +111,18 @@ export class AlertingAuthorization { authorization, getSpaceId, allRegisteredConsumers, - ruleTypeConsumersMap, + ruleTypesConsumersMap, }: ConstructorOptions) { this.request = request; this.authorization = authorization; this.ruleTypeRegistry = ruleTypeRegistry; this.allRegisteredConsumers = allRegisteredConsumers; - this.ruleTypeConsumersMap = ruleTypeConsumersMap; + this.ruleTypesConsumersMap = ruleTypesConsumersMap; this.spaceId = getSpaceId(request); } /** - * Creates an Authorization object. + * Creates an AlertingAuthorization object. */ static async create({ request, @@ -144,18 +144,18 @@ export class AlertingAuthorization { ); const allRegisteredConsumers = new Set(); - const ruleTypeConsumersMap = new Map>(); + const ruleTypesConsumersMap = new Map>(); for (const feature of featuresWithAlertingConfigured) { if (feature.alerting) { for (const entry of feature.alerting) { - const consumers = ruleTypeConsumersMap.get(entry.ruleTypeId) ?? new Set(); + const consumers = ruleTypesConsumersMap.get(entry.ruleTypeId) ?? new Set(); entry.consumers.forEach((consumer) => { consumers.add(consumer); allRegisteredConsumers.add(consumer); }); - ruleTypeConsumersMap.set(entry.ruleTypeId, consumers); + ruleTypesConsumersMap.set(entry.ruleTypeId, consumers); } } } @@ -166,7 +166,7 @@ export class AlertingAuthorization { getSpaceId, ruleTypeRegistry, allRegisteredConsumers, - ruleTypeConsumersMap, + ruleTypesConsumersMap, }); } catch (error) { throw new Error(`Failed to create AlertingAuthorization class: ${error}`); @@ -358,10 +358,6 @@ export class AlertingAuthorization { hasAllRequested: boolean; authorizedRuleTypes: Set; }> { - const ruleTypeConsumersMap = await this.ruleTypeConsumersMap; - const allRegisteredConsumers = await this.allRegisteredConsumers; - const consumersToAuthorize = consumers ?? new Set(Object.keys(allRegisteredConsumers)); - const requiredPrivileges = new Map< string, [RegistryAlertTypeWithAuth, string, HasPrivileges, IsAuthorizedAtProducerLevel] @@ -381,12 +377,12 @@ export class AlertingAuthorization { ); for (const ruleTypeWithAuth of ruleTypesWithAuthorization) { - if (!ruleTypeConsumersMap.has(ruleTypeWithAuth.id)) { + if (!this.ruleTypesConsumersMap.has(ruleTypeWithAuth.id)) { continue; } - for (const consumerToAuthorize of consumersToAuthorize) { - const ruleTypeConsumers = ruleTypeConsumersMap.get(ruleTypeWithAuth.id); + for (const consumerToAuthorize of this.allRegisteredConsumers) { + const ruleTypeConsumers = this.ruleTypesConsumersMap.get(ruleTypeWithAuth.id); if (!ruleTypeConsumers?.has(consumerToAuthorize)) { continue; diff --git a/x-pack/plugins/alerting/server/index.ts b/x-pack/plugins/alerting/server/index.ts index 2f5cd3994e436a..78aad949131a60 100644 --- a/x-pack/plugins/alerting/server/index.ts +++ b/x-pack/plugins/alerting/server/index.ts @@ -37,7 +37,7 @@ export { DEFAULT_AAD_CONFIG } from './types'; export { RULE_SAVED_OBJECT_TYPE, API_KEY_PENDING_INVALIDATION_TYPE } from './saved_objects'; export { RuleNotifyWhen } from '../common'; export { DEFAULT_MAX_EPHEMERAL_ACTIONS_PER_ALERT } from './config'; -export type { PluginSetupContract, PluginStartContract } from './plugin'; +export type { AlertingServerSetup, AlertingServerStart } from './plugin'; export type { FindResult, BulkEditOperation, BulkOperationError } from './rules_client'; export type { Rule } from './application/rule/types'; export type { PublicAlert as Alert } from './alert'; diff --git a/x-pack/plugins/alerting/server/mocks.ts b/x-pack/plugins/alerting/server/mocks.ts index 1abd11703dd4f0..8fcb7441140a17 100644 --- a/x-pack/plugins/alerting/server/mocks.ts +++ b/x-pack/plugins/alerting/server/mocks.ts @@ -14,7 +14,7 @@ import { dataViewPluginMocks } from '@kbn/data-views-plugin/public/mocks'; import { searchSourceCommonMock } from '@kbn/data-plugin/common/search/search_source/mocks'; import { SharePluginStart } from '@kbn/share-plugin/server'; import { rulesClientMock } from './rules_client.mock'; -import { PluginSetupContract, PluginStartContract } from './plugin'; +import { AlertingServerSetup, AlertingServerStart } from './plugin'; import { Alert, AlertFactoryDoneUtils } from './alert'; import { AlertInstanceContext, @@ -27,7 +27,7 @@ import { publicAlertsClientMock } from './alerts_client/alerts_client.mock'; export { rulesClientMock }; const createSetupMock = () => { - const mock: jest.Mocked = { + const mock: jest.Mocked = { registerType: jest.fn(), getSecurityHealth: jest.fn(), getConfig: jest.fn(), @@ -57,7 +57,7 @@ const createShareStartMock = () => { }; const createStartMock = () => { - const mock: jest.Mocked = { + const mock: jest.Mocked = { listTypes: jest.fn(), getType: jest.fn(), getAllTypes: jest.fn(), diff --git a/x-pack/plugins/alerting/server/plugin.test.ts b/x-pack/plugins/alerting/server/plugin.test.ts index 37175ac9604129..4d6e5090da6ca9 100644 --- a/x-pack/plugins/alerting/server/plugin.test.ts +++ b/x-pack/plugins/alerting/server/plugin.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { AlertingPlugin, PluginSetupContract } from './plugin'; +import { AlertingPlugin, AlertingServerSetup } from './plugin'; import { createUsageCollectionSetupMock } from '@kbn/usage-collection-plugin/server/mocks'; import { coreMock, statusServiceMock } from '@kbn/core/server/mocks'; import { licensingMock } from '@kbn/licensing-plugin/server/mocks'; @@ -170,7 +170,7 @@ describe('Alerting Plugin', () => { }); describe('registerType()', () => { - let setup: PluginSetupContract; + let setup: AlertingServerSetup; beforeEach(async () => { const context = coreMock.createPluginInitializerContext( generateAlertingConfig() @@ -244,7 +244,7 @@ describe('Alerting Plugin', () => { }); describe('registerConnectorAdapter()', () => { - let setup: PluginSetupContract; + let setup: AlertingServerSetup; beforeEach(async () => { const context = coreMock.createPluginInitializerContext( diff --git a/x-pack/plugins/alerting/server/plugin.ts b/x-pack/plugins/alerting/server/plugin.ts index 20d52d4099ad25..d4f36bce86f315 100644 --- a/x-pack/plugins/alerting/server/plugin.ts +++ b/x-pack/plugins/alerting/server/plugin.ts @@ -125,7 +125,7 @@ export const LEGACY_EVENT_LOG_ACTIONS = { resolvedInstance: 'resolved-instance', }; -export interface PluginSetupContract { +export interface AlertingServerSetup { registerConnectorAdapter< RuleActionParams extends ConnectorAdapterParams = ConnectorAdapterParams, ConnectorParams extends ConnectorAdapterParams = ConnectorAdapterParams @@ -160,19 +160,15 @@ export interface PluginSetupContract { getDataStreamAdapter: () => DataStreamAdapter; } -export interface PluginStartContract { +export interface AlertingServerStart { listTypes: RuleTypeRegistry['list']; - getAllTypes: RuleTypeRegistry['getAllTypes']; getType: RuleTypeRegistry['get']; getAlertIndicesAlias: GetAlertIndicesAlias; - - getRulesClientWithRequest(request: KibanaRequest): RulesClientApi; - + getRulesClientWithRequest(request: KibanaRequest): Promise; getAlertingAuthorizationWithRequest( request: KibanaRequest ): Promise>; - getFrameworkHealth: () => Promise; } @@ -252,7 +248,7 @@ export class AlertingPlugin { public setup( core: CoreSetup, plugins: AlertingPluginsSetup - ): PluginSetupContract { + ): AlertingServerSetup { this.kibanaBaseUrl = core.http.basePath.publicBaseUrl; this.licenseState = new LicenseState(plugins.licensing.license$); this.security = plugins.security; @@ -477,7 +473,7 @@ export class AlertingPlugin { }; } - public start(core: CoreStart, plugins: AlertingPluginsStart): PluginStartContract { + public start(core: CoreStart, plugins: AlertingPluginsStart): AlertingServerStart { const { isESOCanEncrypt, logger, @@ -557,7 +553,7 @@ export class AlertingPlugin { uiSettings: core.uiSettings, }); - const getRulesClientWithRequest = (request: KibanaRequest) => { + const getRulesClientWithRequest = async (request: KibanaRequest) => { if (isESOCanEncrypt !== true) { throw new Error( `Unable to create alerts client because the Encrypted Saved Objects plugin is missing encryption key. Please set xpack.encryptedSavedObjects.encryptionKey in the kibana.yml or use the bin/kibana-encryption-keys command.` @@ -609,11 +605,13 @@ export class AlertingPlugin { }); this.eventLogService!.registerSavedObjectProvider(RULE_SAVED_OBJECT_TYPE, (request) => { - const client = getRulesClientWithRequest(request); - return (objects?: SavedObjectsBulkGetObject[]) => - objects + return async (objects?: SavedObjectsBulkGetObject[]) => { + const client = await getRulesClientWithRequest(request); + + return objects ? Promise.all(objects.map(async (objectItem) => await client.get({ id: objectItem.id }))) : Promise.resolve([]); + }; }); this.eventLogService!.isEsContextReady() diff --git a/x-pack/plugins/alerting/server/routes/backfill/apis/delete/delete_backfill_route.ts b/x-pack/plugins/alerting/server/routes/backfill/apis/delete/delete_backfill_route.ts index 57e0a2ed2af8d9..4a3a5d90ebf727 100644 --- a/x-pack/plugins/alerting/server/routes/backfill/apis/delete/delete_backfill_route.ts +++ b/x-pack/plugins/alerting/server/routes/backfill/apis/delete/delete_backfill_route.ts @@ -26,7 +26,8 @@ export const deleteBackfillRoute = ( }, router.handleLegacyErrors( verifyAccessAndContext(licenseState, async function (context, req, res) { - const rulesClient = (await context.alerting).getRulesClient(); + const alertingContext = await context.alerting; + const rulesClient = await alertingContext.getRulesClient(); const params: DeleteBackfillRequestParamsV1 = req.params; await rulesClient.deleteBackfill(params.id); diff --git a/x-pack/plugins/alerting/server/routes/backfill/apis/find/find_backfill_route.ts b/x-pack/plugins/alerting/server/routes/backfill/apis/find/find_backfill_route.ts index 4a6e5c5ef5e31d..413eab9a561dd5 100644 --- a/x-pack/plugins/alerting/server/routes/backfill/apis/find/find_backfill_route.ts +++ b/x-pack/plugins/alerting/server/routes/backfill/apis/find/find_backfill_route.ts @@ -31,7 +31,8 @@ export const findBackfillRoute = ( }, router.handleLegacyErrors( verifyAccessAndContext(licenseState, async function (context, req, res) { - const rulesClient = (await context.alerting).getRulesClient(); + const alertingContext = await context.alerting; + const rulesClient = await alertingContext.getRulesClient(); const query: FindBackfillRequestQueryV1 = req.query; const result = await rulesClient.findBackfill(transformRequestV1(query)); diff --git a/x-pack/plugins/alerting/server/routes/backfill/apis/get/get_backfill_route.ts b/x-pack/plugins/alerting/server/routes/backfill/apis/get/get_backfill_route.ts index 6d84aee4a5f847..956401895320d4 100644 --- a/x-pack/plugins/alerting/server/routes/backfill/apis/get/get_backfill_route.ts +++ b/x-pack/plugins/alerting/server/routes/backfill/apis/get/get_backfill_route.ts @@ -28,7 +28,8 @@ export const getBackfillRoute = ( }, router.handleLegacyErrors( verifyAccessAndContext(licenseState, async function (context, req, res) { - const rulesClient = (await context.alerting).getRulesClient(); + const alertingContext = await context.alerting; + const rulesClient = await alertingContext.getRulesClient(); const params: GetBackfillRequestParamsV1 = req.params; const result = await rulesClient.getBackfill(params.id); diff --git a/x-pack/plugins/alerting/server/routes/backfill/apis/schedule/schedule_backfill_route.ts b/x-pack/plugins/alerting/server/routes/backfill/apis/schedule/schedule_backfill_route.ts index 5f7e89d38ce339..aa1c080a5718f0 100644 --- a/x-pack/plugins/alerting/server/routes/backfill/apis/schedule/schedule_backfill_route.ts +++ b/x-pack/plugins/alerting/server/routes/backfill/apis/schedule/schedule_backfill_route.ts @@ -28,7 +28,8 @@ export const scheduleBackfillRoute = ( }, router.handleLegacyErrors( verifyAccessAndContext(licenseState, async function (context, req, res) { - const rulesClient = (await context.alerting).getRulesClient(); + const alertingContext = await context.alerting; + const rulesClient = await alertingContext.getRulesClient(); const body: ScheduleBackfillRequestBodyV1 = req.body; const result = await rulesClient.scheduleBackfill(transformRequestV1(body)); diff --git a/x-pack/plugins/alerting/server/routes/disable_rule.ts b/x-pack/plugins/alerting/server/routes/disable_rule.ts index 2b60cdbeedeafb..eff53044e155b4 100644 --- a/x-pack/plugins/alerting/server/routes/disable_rule.ts +++ b/x-pack/plugins/alerting/server/routes/disable_rule.ts @@ -41,7 +41,8 @@ export const disableRuleRoute = ( }, router.handleLegacyErrors( verifyAccessAndContext(licenseState, async function (context, req, res) { - const rulesClient = (await context.alerting).getRulesClient(); + const alertingContext = await context.alerting; + const rulesClient = await alertingContext.getRulesClient(); const { id } = req.params; const { untrack = false } = req.body || {}; try { diff --git a/x-pack/plugins/alerting/server/routes/enable_rule.ts b/x-pack/plugins/alerting/server/routes/enable_rule.ts index a6334a25138dc5..c046b42aa21800 100644 --- a/x-pack/plugins/alerting/server/routes/enable_rule.ts +++ b/x-pack/plugins/alerting/server/routes/enable_rule.ts @@ -32,7 +32,8 @@ export const enableRuleRoute = ( }, router.handleLegacyErrors( verifyAccessAndContext(licenseState, async function (context, req, res) { - const rulesClient = (await context.alerting).getRulesClient(); + const alertingContext = await context.alerting; + const rulesClient = await alertingContext.getRulesClient(); const { id } = req.params; try { await rulesClient.enable({ id }); diff --git a/x-pack/plugins/alerting/server/routes/get_action_error_log.ts b/x-pack/plugins/alerting/server/routes/get_action_error_log.ts index 7e8028cad7f16c..8f983abccbaab6 100644 --- a/x-pack/plugins/alerting/server/routes/get_action_error_log.ts +++ b/x-pack/plugins/alerting/server/routes/get_action_error_log.ts @@ -66,7 +66,8 @@ export const getActionErrorLogRoute = ( }, router.handleLegacyErrors( verifyAccessAndContext(licenseState, async function (context, req, res) { - const rulesClient = (await context.alerting).getRulesClient(); + const alertingContext = await context.alerting; + const rulesClient = await alertingContext.getRulesClient(); const { id } = req.params; const withAuth = req.query.with_auth; const rewrittenReq = rewriteReq({ id, ...req.query }); diff --git a/x-pack/plugins/alerting/server/routes/get_global_execution_kpi.ts b/x-pack/plugins/alerting/server/routes/get_global_execution_kpi.ts index 2aec9d998a9e66..064a6e57a95622 100644 --- a/x-pack/plugins/alerting/server/routes/get_global_execution_kpi.ts +++ b/x-pack/plugins/alerting/server/routes/get_global_execution_kpi.ts @@ -43,7 +43,8 @@ export const getGlobalExecutionKPIRoute = ( }, router.handleLegacyErrors( verifyAccessAndContext(licenseState, async function (context, req, res) { - const rulesClient = (await context.alerting).getRulesClient(); + const alertingContext = await context.alerting; + const rulesClient = await alertingContext.getRulesClient(); return res.ok({ body: await rulesClient.getGlobalExecutionKpiWithAuth(rewriteReq(req.query)), }); diff --git a/x-pack/plugins/alerting/server/routes/get_global_execution_logs.ts b/x-pack/plugins/alerting/server/routes/get_global_execution_logs.ts index e08ec1ac5bcb8c..2efee4cb967160 100644 --- a/x-pack/plugins/alerting/server/routes/get_global_execution_logs.ts +++ b/x-pack/plugins/alerting/server/routes/get_global_execution_logs.ts @@ -68,7 +68,8 @@ export const getGlobalExecutionLogRoute = ( }, router.handleLegacyErrors( verifyAccessAndContext(licenseState, async function (context, req, res) { - const rulesClient = (await context.alerting).getRulesClient(); + const alertingContext = await context.alerting; + const rulesClient = await alertingContext.getRulesClient(); return res.ok({ body: await rulesClient.getGlobalExecutionLogWithAuth(rewriteReq(req.query)), }); diff --git a/x-pack/plugins/alerting/server/routes/get_rule_alert_summary.ts b/x-pack/plugins/alerting/server/routes/get_rule_alert_summary.ts index c0d31d1ccbfac5..8bfc51ba35a0c0 100644 --- a/x-pack/plugins/alerting/server/routes/get_rule_alert_summary.ts +++ b/x-pack/plugins/alerting/server/routes/get_rule_alert_summary.ts @@ -72,7 +72,8 @@ export const getRuleAlertSummaryRoute = ( }, router.handleLegacyErrors( verifyAccessAndContext(licenseState, async function (context, req, res) { - const rulesClient = (await context.alerting).getRulesClient(); + const alertingContext = await context.alerting; + const rulesClient = await alertingContext.getRulesClient(); const { id } = req.params; const summary = await rulesClient.getAlertSummary(rewriteReq({ id, ...req.query })); return res.ok({ body: rewriteBodyRes(summary) }); diff --git a/x-pack/plugins/alerting/server/routes/get_rule_execution_kpi.ts b/x-pack/plugins/alerting/server/routes/get_rule_execution_kpi.ts index 11f7085c532907..c8e086b7bffe2f 100644 --- a/x-pack/plugins/alerting/server/routes/get_rule_execution_kpi.ts +++ b/x-pack/plugins/alerting/server/routes/get_rule_execution_kpi.ts @@ -45,7 +45,8 @@ export const getRuleExecutionKPIRoute = ( }, router.handleLegacyErrors( verifyAccessAndContext(licenseState, async function (context, req, res) { - const rulesClient = (await context.alerting).getRulesClient(); + const alertingContext = await context.alerting; + const rulesClient = await alertingContext.getRulesClient(); const { id } = req.params; return res.ok({ body: await rulesClient.getRuleExecutionKPI(rewriteReq({ id, ...req.query })), diff --git a/x-pack/plugins/alerting/server/routes/get_rule_execution_log.ts b/x-pack/plugins/alerting/server/routes/get_rule_execution_log.ts index 4a8a91089203df..90f9c11c899d71 100644 --- a/x-pack/plugins/alerting/server/routes/get_rule_execution_log.ts +++ b/x-pack/plugins/alerting/server/routes/get_rule_execution_log.ts @@ -70,7 +70,8 @@ export const getRuleExecutionLogRoute = ( }, router.handleLegacyErrors( verifyAccessAndContext(licenseState, async function (context, req, res) { - const rulesClient = (await context.alerting).getRulesClient(); + const alertingContext = await context.alerting; + const rulesClient = await alertingContext.getRulesClient(); const { id } = req.params; return res.ok({ body: await rulesClient.getExecutionLogForRule(rewriteReq({ id, ...req.query })), diff --git a/x-pack/plugins/alerting/server/routes/get_rule_state.ts b/x-pack/plugins/alerting/server/routes/get_rule_state.ts index 50ad1f776110ef..36e43f9bf6d31c 100644 --- a/x-pack/plugins/alerting/server/routes/get_rule_state.ts +++ b/x-pack/plugins/alerting/server/routes/get_rule_state.ts @@ -44,7 +44,8 @@ export const getRuleStateRoute = ( }, router.handleLegacyErrors( verifyAccessAndContext(licenseState, async function (context, req, res) { - const rulesClient = (await context.alerting).getRulesClient(); + const alertingContext = await context.alerting; + const rulesClient = await alertingContext.getRulesClient(); const { id } = req.params; const state = await rulesClient.getAlertState({ id }); return state ? res.ok({ body: rewriteBodyRes(state) }) : res.noContent(); diff --git a/x-pack/plugins/alerting/server/routes/health.ts b/x-pack/plugins/alerting/server/routes/health.ts index 6d178e7bd186ce..1020adb166f620 100644 --- a/x-pack/plugins/alerting/server/routes/health.ts +++ b/x-pack/plugins/alerting/server/routes/health.ts @@ -50,8 +50,9 @@ export const healthRoute = ( verifyAccessAndContext(licenseState, async function (context, req, res) { try { const alertingContext = await context.alerting; + const rulesClient = await alertingContext.getRulesClient(); // Verify that user has access to at least one rule type - const ruleTypes = Array.from(await alertingContext.getRulesClient().listRuleTypes()); + const ruleTypes = Array.from(await rulesClient.listRuleTypes()); if (ruleTypes.length > 0) { const alertingFrameworkHealth = await alertingContext.getFrameworkHealth(); diff --git a/x-pack/plugins/alerting/server/routes/legacy/create.ts b/x-pack/plugins/alerting/server/routes/legacy/create.ts index f586a253696b33..963aae8b63a0fa 100644 --- a/x-pack/plugins/alerting/server/routes/legacy/create.ts +++ b/x-pack/plugins/alerting/server/routes/legacy/create.ts @@ -64,7 +64,9 @@ export const createAlertRoute = ({ router, licenseState, usageCounter }: RouteOp if (!context.alerting) { return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' }); } - const rulesClient = (await context.alerting).getRulesClient(); + + const alertingContext = await context.alerting; + const rulesClient = await alertingContext.getRulesClient(); const alert = req.body; const params = req.params; const notifyWhen = alert?.notifyWhen ? (alert.notifyWhen as RuleNotifyWhenType) : null; diff --git a/x-pack/plugins/alerting/server/routes/legacy/delete.ts b/x-pack/plugins/alerting/server/routes/legacy/delete.ts index 4fcf85678db53f..88cbfa2706b78b 100644 --- a/x-pack/plugins/alerting/server/routes/legacy/delete.ts +++ b/x-pack/plugins/alerting/server/routes/legacy/delete.ts @@ -35,7 +35,8 @@ export const deleteAlertRoute = ( return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' }); } trackLegacyRouteUsage('delete', usageCounter); - const rulesClient = (await context.alerting).getRulesClient(); + const alertingContext = await context.alerting; + const rulesClient = await alertingContext.getRulesClient(); const { id } = req.params; await rulesClient.delete({ id }); return res.noContent(); diff --git a/x-pack/plugins/alerting/server/routes/legacy/disable.ts b/x-pack/plugins/alerting/server/routes/legacy/disable.ts index 5572220eb21711..323aea68769536 100644 --- a/x-pack/plugins/alerting/server/routes/legacy/disable.ts +++ b/x-pack/plugins/alerting/server/routes/legacy/disable.ts @@ -36,7 +36,8 @@ export const disableAlertRoute = ( return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' }); } trackLegacyRouteUsage('disable', usageCounter); - const rulesClient = (await context.alerting).getRulesClient(); + const alertingContext = await context.alerting; + const rulesClient = await alertingContext.getRulesClient(); const { id } = req.params; try { await rulesClient.disable({ id }); diff --git a/x-pack/plugins/alerting/server/routes/legacy/enable.ts b/x-pack/plugins/alerting/server/routes/legacy/enable.ts index eb86b5db65da1c..2de219f0374a18 100644 --- a/x-pack/plugins/alerting/server/routes/legacy/enable.ts +++ b/x-pack/plugins/alerting/server/routes/legacy/enable.ts @@ -38,7 +38,8 @@ export const enableAlertRoute = ( return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' }); } trackLegacyRouteUsage('enable', usageCounter); - const rulesClient = (await context.alerting).getRulesClient(); + const alertingContext = await context.alerting; + const rulesClient = await alertingContext.getRulesClient(); const { id } = req.params; try { await rulesClient.enable({ id }); diff --git a/x-pack/plugins/alerting/server/routes/legacy/find.ts b/x-pack/plugins/alerting/server/routes/legacy/find.ts index dcda2e01271d48..32af209b89ff4f 100644 --- a/x-pack/plugins/alerting/server/routes/legacy/find.ts +++ b/x-pack/plugins/alerting/server/routes/legacy/find.ts @@ -85,7 +85,8 @@ export const findAlertRoute = ( ) as string[], usageCounter ); - const rulesClient = (await context.alerting).getRulesClient(); + const alertingContext = await context.alerting; + const rulesClient = await alertingContext.getRulesClient(); const query = req.query; const renameMap = { diff --git a/x-pack/plugins/alerting/server/routes/legacy/get.ts b/x-pack/plugins/alerting/server/routes/legacy/get.ts index be9550f1f336e7..79a91a6f81e146 100644 --- a/x-pack/plugins/alerting/server/routes/legacy/get.ts +++ b/x-pack/plugins/alerting/server/routes/legacy/get.ts @@ -35,7 +35,8 @@ export const getAlertRoute = ( return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' }); } trackLegacyRouteUsage('get', usageCounter); - const rulesClient = (await context.alerting).getRulesClient(); + const alertingContext = await context.alerting; + const rulesClient = await alertingContext.getRulesClient(); const { id } = req.params; const { systemActions, ...rule } = await rulesClient.get({ id, excludeFromPublicApi: true }); return res.ok({ diff --git a/x-pack/plugins/alerting/server/routes/legacy/get_alert_instance_summary.ts b/x-pack/plugins/alerting/server/routes/legacy/get_alert_instance_summary.ts index c33aea8060d777..11c4a27b65ded6 100644 --- a/x-pack/plugins/alerting/server/routes/legacy/get_alert_instance_summary.ts +++ b/x-pack/plugins/alerting/server/routes/legacy/get_alert_instance_summary.ts @@ -46,7 +46,8 @@ export const getAlertInstanceSummaryRoute = ( return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' }); } trackLegacyRouteUsage('instanceSummary', usageCounter); - const rulesClient = (await context.alerting).getRulesClient(); + const alertingContext = await context.alerting; + const rulesClient = await alertingContext.getRulesClient(); const { id } = req.params; const { dateStart } = req.query; const summary = await rulesClient.getAlertSummary({ id, dateStart }); diff --git a/x-pack/plugins/alerting/server/routes/legacy/get_alert_state.ts b/x-pack/plugins/alerting/server/routes/legacy/get_alert_state.ts index 86a56403b39ae5..d2f149c489948b 100644 --- a/x-pack/plugins/alerting/server/routes/legacy/get_alert_state.ts +++ b/x-pack/plugins/alerting/server/routes/legacy/get_alert_state.ts @@ -35,7 +35,8 @@ export const getAlertStateRoute = ( return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' }); } trackLegacyRouteUsage('state', usageCounter); - const rulesClient = (await context.alerting).getRulesClient(); + const alertingContext = await context.alerting; + const rulesClient = await alertingContext.getRulesClient(); const { id } = req.params; const state = await rulesClient.getAlertState({ id }); return state ? res.ok({ body: state }) : res.noContent(); diff --git a/x-pack/plugins/alerting/server/routes/legacy/health.ts b/x-pack/plugins/alerting/server/routes/legacy/health.ts index ca64143638d089..2e9accef524675 100644 --- a/x-pack/plugins/alerting/server/routes/legacy/health.ts +++ b/x-pack/plugins/alerting/server/routes/legacy/health.ts @@ -33,8 +33,9 @@ export function healthRoute( trackLegacyRouteUsage('health', usageCounter); try { const alertingContext = await context.alerting; + const rulesClient = await alertingContext.getRulesClient(); // Verify that user has access to at least one rule type - const ruleTypes = Array.from(await alertingContext.getRulesClient().listRuleTypes()); + const ruleTypes = Array.from(await rulesClient.listRuleTypes()); if (ruleTypes.length > 0) { const alertingFrameworkHealth = await alertingContext.getFrameworkHealth(); diff --git a/x-pack/plugins/alerting/server/routes/legacy/list_alert_types.ts b/x-pack/plugins/alerting/server/routes/legacy/list_alert_types.ts index ead29203940b6d..72b31cb17339e5 100644 --- a/x-pack/plugins/alerting/server/routes/legacy/list_alert_types.ts +++ b/x-pack/plugins/alerting/server/routes/legacy/list_alert_types.ts @@ -28,8 +28,10 @@ export const listAlertTypesRoute = ( } trackLegacyRouteUsage('listAlertTypes', usageCounter); const alertingContext = await context.alerting; + const rulesClient = await alertingContext.getRulesClient(); + return res.ok({ - body: Array.from(await alertingContext.getRulesClient().listRuleTypes()), + body: Array.from(await rulesClient.listRuleTypes()), }); }) ); diff --git a/x-pack/plugins/alerting/server/routes/legacy/mute_all.ts b/x-pack/plugins/alerting/server/routes/legacy/mute_all.ts index dcbc0c19dbe359..5b14b3704efe69 100644 --- a/x-pack/plugins/alerting/server/routes/legacy/mute_all.ts +++ b/x-pack/plugins/alerting/server/routes/legacy/mute_all.ts @@ -36,7 +36,8 @@ export const muteAllAlertRoute = ( return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' }); } trackLegacyRouteUsage('muteAll', usageCounter); - const rulesClient = (await context.alerting).getRulesClient(); + const alertingContext = await context.alerting; + const rulesClient = await alertingContext.getRulesClient(); const { id } = req.params; try { await rulesClient.muteAll({ id }); diff --git a/x-pack/plugins/alerting/server/routes/legacy/mute_instance.ts b/x-pack/plugins/alerting/server/routes/legacy/mute_instance.ts index f6c6a28ecc8655..f89068abdb367f 100644 --- a/x-pack/plugins/alerting/server/routes/legacy/mute_instance.ts +++ b/x-pack/plugins/alerting/server/routes/legacy/mute_instance.ts @@ -41,7 +41,8 @@ export const muteAlertInstanceRoute = ( trackLegacyRouteUsage('muteInstance', usageCounter); - const rulesClient = (await context.alerting).getRulesClient(); + const alertingContext = await context.alerting; + const rulesClient = await alertingContext.getRulesClient(); const renameMap = { alert_id: 'alertId', diff --git a/x-pack/plugins/alerting/server/routes/legacy/unmute_all.ts b/x-pack/plugins/alerting/server/routes/legacy/unmute_all.ts index 31f82849ea1da4..058769ea659b64 100644 --- a/x-pack/plugins/alerting/server/routes/legacy/unmute_all.ts +++ b/x-pack/plugins/alerting/server/routes/legacy/unmute_all.ts @@ -36,7 +36,8 @@ export const unmuteAllAlertRoute = ( return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' }); } trackLegacyRouteUsage('unmuteAll', usageCounter); - const rulesClient = (await context.alerting).getRulesClient(); + const alertingContext = await context.alerting; + const rulesClient = await alertingContext.getRulesClient(); const { id } = req.params; try { await rulesClient.unmuteAll({ id }); diff --git a/x-pack/plugins/alerting/server/routes/legacy/unmute_instance.ts b/x-pack/plugins/alerting/server/routes/legacy/unmute_instance.ts index 4d5b9b02da5f15..830314a0851b4e 100644 --- a/x-pack/plugins/alerting/server/routes/legacy/unmute_instance.ts +++ b/x-pack/plugins/alerting/server/routes/legacy/unmute_instance.ts @@ -37,7 +37,8 @@ export const unmuteAlertInstanceRoute = ( return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' }); } trackLegacyRouteUsage('unmuteInstance', usageCounter); - const rulesClient = (await context.alerting).getRulesClient(); + const alertingContext = await context.alerting; + const rulesClient = await alertingContext.getRulesClient(); const { alertId, alertInstanceId } = req.params; try { await rulesClient.unmuteInstance({ alertId, alertInstanceId }); diff --git a/x-pack/plugins/alerting/server/routes/legacy/update.ts b/x-pack/plugins/alerting/server/routes/legacy/update.ts index 203352dd01a6bc..3993510a386925 100644 --- a/x-pack/plugins/alerting/server/routes/legacy/update.ts +++ b/x-pack/plugins/alerting/server/routes/legacy/update.ts @@ -64,7 +64,8 @@ export const updateAlertRoute = ( return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' }); } trackLegacyRouteUsage('update', usageCounter); - const rulesClient = (await context.alerting).getRulesClient(); + const alertingContext = await context.alerting; + const rulesClient = await alertingContext.getRulesClient(); const { id } = req.params; const { name, actions, params, schedule, tags, throttle, notifyWhen } = req.body; try { diff --git a/x-pack/plugins/alerting/server/routes/legacy/update_api_key.ts b/x-pack/plugins/alerting/server/routes/legacy/update_api_key.ts index f0f7716b00771e..8292f656e0e85f 100644 --- a/x-pack/plugins/alerting/server/routes/legacy/update_api_key.ts +++ b/x-pack/plugins/alerting/server/routes/legacy/update_api_key.ts @@ -38,7 +38,8 @@ export const updateApiKeyRoute = ( return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' }); } trackLegacyRouteUsage('updateApiKey', usageCounter); - const rulesClient = (await context.alerting).getRulesClient(); + const alertingContext = await context.alerting; + const rulesClient = await alertingContext.getRulesClient(); const { id } = req.params; try { await rulesClient.updateApiKey({ id }); diff --git a/x-pack/plugins/alerting/server/routes/mute_all_rule.ts b/x-pack/plugins/alerting/server/routes/mute_all_rule.ts index 185d44b95a50ed..2a0312f93759ef 100644 --- a/x-pack/plugins/alerting/server/routes/mute_all_rule.ts +++ b/x-pack/plugins/alerting/server/routes/mute_all_rule.ts @@ -35,7 +35,8 @@ export const muteAllRuleRoute = ( }, router.handleLegacyErrors( verifyAccessAndContext(licenseState, async function (context, req, res) { - const rulesClient = (await context.alerting).getRulesClient(); + const alertingContext = await context.alerting; + const rulesClient = await alertingContext.getRulesClient(); const { id } = req.params; trackDeprecatedRouteUsage('muteAll', usageCounter); try { diff --git a/x-pack/plugins/alerting/server/routes/rule/apis/aggregate/aggregate_rules_route.ts b/x-pack/plugins/alerting/server/routes/rule/apis/aggregate/aggregate_rules_route.ts index a8f7a20baa4cbe..ac9ca90330b387 100644 --- a/x-pack/plugins/alerting/server/routes/rule/apis/aggregate/aggregate_rules_route.ts +++ b/x-pack/plugins/alerting/server/routes/rule/apis/aggregate/aggregate_rules_route.ts @@ -36,7 +36,8 @@ export const aggregateRulesRoute = ( }, router.handleLegacyErrors( verifyAccessAndContext(licenseState, async function (context, req, res) { - const rulesClient = (await context.alerting).getRulesClient(); + const alertingContext = await context.alerting; + const rulesClient = await alertingContext.getRulesClient(); const body: AggregateRulesRequestBodyV1 = req.body; const options = transformAggregateQueryRequestV1({ ...body, diff --git a/x-pack/plugins/alerting/server/routes/rule/apis/bulk_delete/bulk_delete_rules_route.ts b/x-pack/plugins/alerting/server/routes/rule/apis/bulk_delete/bulk_delete_rules_route.ts index ad9b77b3aba834..c968f40489b465 100644 --- a/x-pack/plugins/alerting/server/routes/rule/apis/bulk_delete/bulk_delete_rules_route.ts +++ b/x-pack/plugins/alerting/server/routes/rule/apis/bulk_delete/bulk_delete_rules_route.ts @@ -35,7 +35,8 @@ export const bulkDeleteRulesRoute = ({ handleDisabledApiKeysError( router.handleLegacyErrors( verifyAccessAndContext(licenseState, async (context, req, res) => { - const rulesClient = (await context.alerting).getRulesClient(); + const alertingContext = await context.alerting; + const rulesClient = await alertingContext.getRulesClient(); const body: BulkDeleteRulesRequestBodyV1 = req.body; const { filter, ids } = body; diff --git a/x-pack/plugins/alerting/server/routes/rule/apis/bulk_disable/bulk_disable_rules_route.ts b/x-pack/plugins/alerting/server/routes/rule/apis/bulk_disable/bulk_disable_rules_route.ts index 39b81ee74fe91c..efbd79aad830de 100644 --- a/x-pack/plugins/alerting/server/routes/rule/apis/bulk_disable/bulk_disable_rules_route.ts +++ b/x-pack/plugins/alerting/server/routes/rule/apis/bulk_disable/bulk_disable_rules_route.ts @@ -36,7 +36,8 @@ export const bulkDisableRulesRoute = ({ handleDisabledApiKeysError( router.handleLegacyErrors( verifyAccessAndContext(licenseState, async (context, req, res) => { - const rulesClient = (await context.alerting).getRulesClient(); + const alertingContext = await context.alerting; + const rulesClient = await alertingContext.getRulesClient(); const body: BulkDisableRulesRequestBodyV1 = req.body; const { filter, ids, untrack } = body; diff --git a/x-pack/plugins/alerting/server/routes/rule/apis/bulk_edit/bulk_edit_rules_route.ts b/x-pack/plugins/alerting/server/routes/rule/apis/bulk_edit/bulk_edit_rules_route.ts index c863d2aba33c13..20145693f2fd73 100644 --- a/x-pack/plugins/alerting/server/routes/rule/apis/bulk_edit/bulk_edit_rules_route.ts +++ b/x-pack/plugins/alerting/server/routes/rule/apis/bulk_edit/bulk_edit_rules_route.ts @@ -40,7 +40,8 @@ const buildBulkEditRulesRoute = ({ licenseState, path, router }: BuildBulkEditRu handleDisabledApiKeysError( router.handleLegacyErrors( verifyAccessAndContext(licenseState, async function (context, req, res) { - const rulesClient = (await context.alerting).getRulesClient(); + const alertingContext = await context.alerting; + const rulesClient = await alertingContext.getRulesClient(); const actionsClient = (await context.actions).getActionsClient(); const bulkEditData: BulkEditRulesRequestBodyV1 = req.body; diff --git a/x-pack/plugins/alerting/server/routes/rule/apis/bulk_enable/bulk_enable_rules_route.ts b/x-pack/plugins/alerting/server/routes/rule/apis/bulk_enable/bulk_enable_rules_route.ts index 9a8210dc8aed87..551b92253a4472 100644 --- a/x-pack/plugins/alerting/server/routes/rule/apis/bulk_enable/bulk_enable_rules_route.ts +++ b/x-pack/plugins/alerting/server/routes/rule/apis/bulk_enable/bulk_enable_rules_route.ts @@ -34,7 +34,8 @@ export const bulkEnableRulesRoute = ({ handleDisabledApiKeysError( router.handleLegacyErrors( verifyAccessAndContext(licenseState, async (context, req, res) => { - const rulesClient = (await context.alerting).getRulesClient(); + const alertingContext = await context.alerting; + const rulesClient = await alertingContext.getRulesClient(); const body: BulkEnableRulesRequestBodyV1 = req.body; try { diff --git a/x-pack/plugins/alerting/server/routes/rule/apis/bulk_untrack/bulk_untrack_alerts_route.ts b/x-pack/plugins/alerting/server/routes/rule/apis/bulk_untrack/bulk_untrack_alerts_route.ts index 3539db62d06494..9f92eab727e612 100644 --- a/x-pack/plugins/alerting/server/routes/rule/apis/bulk_untrack/bulk_untrack_alerts_route.ts +++ b/x-pack/plugins/alerting/server/routes/rule/apis/bulk_untrack/bulk_untrack_alerts_route.ts @@ -27,7 +27,8 @@ export const bulkUntrackAlertsRoute = ( }, router.handleLegacyErrors( verifyAccessAndContext(licenseState, async function (context, req, res) { - const rulesClient = (await context.alerting).getRulesClient(); + const alertingContext = await context.alerting; + const rulesClient = await alertingContext.getRulesClient(); const body: BulkUntrackRequestBodyV1 = req.body; try { await rulesClient.bulkUntrackAlerts({ diff --git a/x-pack/plugins/alerting/server/routes/rule/apis/bulk_untrack_by_query/bulk_untrack_alerts_by_query_route.ts b/x-pack/plugins/alerting/server/routes/rule/apis/bulk_untrack_by_query/bulk_untrack_alerts_by_query_route.ts index 92b43570772c76..b8b7988ebf5560 100644 --- a/x-pack/plugins/alerting/server/routes/rule/apis/bulk_untrack_by_query/bulk_untrack_alerts_by_query_route.ts +++ b/x-pack/plugins/alerting/server/routes/rule/apis/bulk_untrack_by_query/bulk_untrack_alerts_by_query_route.ts @@ -28,7 +28,8 @@ export const bulkUntrackAlertsByQueryRoute = ( }, router.handleLegacyErrors( verifyAccessAndContext(licenseState, async function (context, req, res) { - const rulesClient = (await context.alerting).getRulesClient(); + const alertingContext = await context.alerting; + const rulesClient = await alertingContext.getRulesClient(); const body: BulkUntrackByQueryRequestBodyV1 = req.body; try { await rulesClient.bulkUntrackAlerts({ diff --git a/x-pack/plugins/alerting/server/routes/rule/apis/clone/clone_rule_route.ts b/x-pack/plugins/alerting/server/routes/rule/apis/clone/clone_rule_route.ts index 91214233b61ea8..8b92bc1ccdb688 100644 --- a/x-pack/plugins/alerting/server/routes/rule/apis/clone/clone_rule_route.ts +++ b/x-pack/plugins/alerting/server/routes/rule/apis/clone/clone_rule_route.ts @@ -32,7 +32,8 @@ export const cloneRuleRoute = ( handleDisabledApiKeysError( router.handleLegacyErrors( verifyAccessAndContext(licenseState, async function (context, req, res) { - const rulesClient = (await context.alerting).getRulesClient(); + const alertingContext = await context.alerting; + const rulesClient = await alertingContext.getRulesClient(); const params: CloneRuleRequestParamsV1 = req.params; try { // TODO (http-versioning): Remove this cast, this enables us to move forward diff --git a/x-pack/plugins/alerting/server/routes/rule/apis/create/create_rule_route.ts b/x-pack/plugins/alerting/server/routes/rule/apis/create/create_rule_route.ts index 5bb1eec92de268..98f6fb403e89aa 100644 --- a/x-pack/plugins/alerting/server/routes/rule/apis/create/create_rule_route.ts +++ b/x-pack/plugins/alerting/server/routes/rule/apis/create/create_rule_route.ts @@ -44,7 +44,8 @@ export const createRuleRoute = ({ router, licenseState, usageCounter }: RouteOpt handleDisabledApiKeysError( router.handleLegacyErrors( verifyAccessAndContext(licenseState, async function (context, req, res) { - const rulesClient = (await context.alerting).getRulesClient(); + const alertingContext = await context.alerting; + const rulesClient = await alertingContext.getRulesClient(); const actionsClient = (await context.actions).getActionsClient(); // Assert versioned inputs diff --git a/x-pack/plugins/alerting/server/routes/rule/apis/delete/delete_rule_route.ts b/x-pack/plugins/alerting/server/routes/rule/apis/delete/delete_rule_route.ts index 3fe896cec9622f..5515e0614086a1 100644 --- a/x-pack/plugins/alerting/server/routes/rule/apis/delete/delete_rule_route.ts +++ b/x-pack/plugins/alerting/server/routes/rule/apis/delete/delete_rule_route.ts @@ -31,7 +31,8 @@ export const deleteRuleRoute = ( }, router.handleLegacyErrors( verifyAccessAndContext(licenseState, async function (context, req, res) { - const rulesClient = (await context.alerting).getRulesClient(); + const alertingContext = await context.alerting; + const rulesClient = await alertingContext.getRulesClient(); const params: DeleteRuleRequestParamsV1 = req.params; diff --git a/x-pack/plugins/alerting/server/routes/rule/apis/find/find_rules_route.ts b/x-pack/plugins/alerting/server/routes/rule/apis/find/find_rules_route.ts index 1cadb35969944f..9c059239f57167 100644 --- a/x-pack/plugins/alerting/server/routes/rule/apis/find/find_rules_route.ts +++ b/x-pack/plugins/alerting/server/routes/rule/apis/find/find_rules_route.ts @@ -51,7 +51,8 @@ const buildFindRulesRoute = ({ }, router.handleLegacyErrors( verifyAccessAndContext(licenseState, async function (context, req, res) { - const rulesClient = (await context.alerting).getRulesClient(); + const alertingContext = await context.alerting; + const rulesClient = await alertingContext.getRulesClient(); const query: FindRulesRequestQueryV1 = req.query; @@ -99,7 +100,8 @@ const buildFindRulesRoute = ({ }, router.handleLegacyErrors( verifyAccessAndContext(licenseState, async function (context, req, res) { - const rulesClient = (await context.alerting).getRulesClient(); + const alertingContext = await context.alerting; + const rulesClient = await alertingContext.getRulesClient(); const body: FindRulesRequestQueryV1 = req.body; diff --git a/x-pack/plugins/alerting/server/routes/rule/apis/get/get_rule_route.ts b/x-pack/plugins/alerting/server/routes/rule/apis/get/get_rule_route.ts index e08c81a1d2e5c3..6332e6ab890eb0 100644 --- a/x-pack/plugins/alerting/server/routes/rule/apis/get/get_rule_route.ts +++ b/x-pack/plugins/alerting/server/routes/rule/apis/get/get_rule_route.ts @@ -47,7 +47,8 @@ const buildGetRuleRoute = ({ }, router.handleLegacyErrors( verifyAccessAndContext(licenseState, async function (context, req, res) { - const rulesClient = (await context.alerting).getRulesClient(); + const alertingContext = await context.alerting; + const rulesClient = await alertingContext.getRulesClient(); const params: GetRuleRequestParamsV1 = req.params; // TODO (http-versioning): Remove this cast, this enables us to move forward diff --git a/x-pack/plugins/alerting/server/routes/rule/apis/get_schedule_frequency/get_schedule_frequency_route.ts b/x-pack/plugins/alerting/server/routes/rule/apis/get_schedule_frequency/get_schedule_frequency_route.ts index 438c2f2b4aa545..71cde695dbcf02 100644 --- a/x-pack/plugins/alerting/server/routes/rule/apis/get_schedule_frequency/get_schedule_frequency_route.ts +++ b/x-pack/plugins/alerting/server/routes/rule/apis/get_schedule_frequency/get_schedule_frequency_route.ts @@ -23,7 +23,8 @@ export const getScheduleFrequencyRoute = ( }, router.handleLegacyErrors( verifyAccessAndContext(licenseState, async (context, req, res) => { - const rulesClient = (await context.alerting).getRulesClient(); + const alertingContext = await context.alerting; + const rulesClient = await alertingContext.getRulesClient(); const scheduleFrequencyResult = await rulesClient.getScheduleFrequency(); diff --git a/x-pack/plugins/alerting/server/routes/rule/apis/mute_alert/mute_alert.ts b/x-pack/plugins/alerting/server/routes/rule/apis/mute_alert/mute_alert.ts index 91a254be09663e..bd3497c74a46be 100644 --- a/x-pack/plugins/alerting/server/routes/rule/apis/mute_alert/mute_alert.ts +++ b/x-pack/plugins/alerting/server/routes/rule/apis/mute_alert/mute_alert.ts @@ -31,7 +31,8 @@ export const muteAlertRoute = ( }, router.handleLegacyErrors( verifyAccessAndContext(licenseState, async function (context, req, res) { - const rulesClient = (await context.alerting).getRulesClient(); + const alertingContext = await context.alerting; + const rulesClient = await alertingContext.getRulesClient(); const params: MuteAlertRequestParamsV1 = req.params; try { await rulesClient.muteInstance(transformRequestParamsToApplicationV1(params)); diff --git a/x-pack/plugins/alerting/server/routes/rule/apis/resolve/resolve_rule_route.ts b/x-pack/plugins/alerting/server/routes/rule/apis/resolve/resolve_rule_route.ts index 2e6f016b5f6ac3..b30c53dc0c1170 100644 --- a/x-pack/plugins/alerting/server/routes/rule/apis/resolve/resolve_rule_route.ts +++ b/x-pack/plugins/alerting/server/routes/rule/apis/resolve/resolve_rule_route.ts @@ -33,7 +33,8 @@ export const resolveRuleRoute = ( }, router.handleLegacyErrors( verifyAccessAndContext(licenseState, async function (context, req, res) { - const rulesClient = (await context.alerting).getRulesClient(); + const alertingContext = await context.alerting; + const rulesClient = await alertingContext.getRulesClient(); const params: ResolveRuleRequestParamsV1 = req.params; const { id } = params; // TODO (http-versioning): Remove this cast, this enables us to move forward diff --git a/x-pack/plugins/alerting/server/routes/rule/apis/snooze/snooze_rule_route.ts b/x-pack/plugins/alerting/server/routes/rule/apis/snooze/snooze_rule_route.ts index 93b619b50d82cc..47847f14a945bc 100644 --- a/x-pack/plugins/alerting/server/routes/rule/apis/snooze/snooze_rule_route.ts +++ b/x-pack/plugins/alerting/server/routes/rule/apis/snooze/snooze_rule_route.ts @@ -32,7 +32,8 @@ export const snoozeRuleRoute = ( }, router.handleLegacyErrors( verifyAccessAndContext(licenseState, async function (context, req, res) { - const rulesClient = (await context.alerting).getRulesClient(); + const alertingContext = await context.alerting; + const rulesClient = await alertingContext.getRulesClient(); const params: SnoozeRuleRequestParamsV1 = req.params; const body = transformSnoozeBodyV1(req.body); try { diff --git a/x-pack/plugins/alerting/server/routes/rule/apis/tags/get_rule_tags.ts b/x-pack/plugins/alerting/server/routes/rule/apis/tags/get_rule_tags.ts index c115ba7fc6c6c2..0b54dd1c11a1e2 100644 --- a/x-pack/plugins/alerting/server/routes/rule/apis/tags/get_rule_tags.ts +++ b/x-pack/plugins/alerting/server/routes/rule/apis/tags/get_rule_tags.ts @@ -28,7 +28,8 @@ export const getRuleTagsRoute = ( }, router.handleLegacyErrors( verifyAccessAndContext(licenseState, async function (context, req, res) { - const rulesClient = (await context.alerting).getRulesClient(); + const alertingContext = await context.alerting; + const rulesClient = await alertingContext.getRulesClient(); const query: RuleTagsRequestQueryV1 = req.query; const options = transformRuleTagsQueryRequestV1(query); diff --git a/x-pack/plugins/alerting/server/routes/rule/apis/unsnooze/unsnooze_rule_route.ts b/x-pack/plugins/alerting/server/routes/rule/apis/unsnooze/unsnooze_rule_route.ts index e37b5c0217f0a5..e7175549d4edd7 100644 --- a/x-pack/plugins/alerting/server/routes/rule/apis/unsnooze/unsnooze_rule_route.ts +++ b/x-pack/plugins/alerting/server/routes/rule/apis/unsnooze/unsnooze_rule_route.ts @@ -32,7 +32,8 @@ export const unsnoozeRuleRoute = ( }, router.handleLegacyErrors( verifyAccessAndContext(licenseState, async function (context, req, res) { - const rulesClient = (await context.alerting).getRulesClient(); + const alertingContext = await context.alerting; + const rulesClient = await alertingContext.getRulesClient(); const params: UnsnoozeRuleRequestParamsV1 = req.params; const body = transformUnsnoozeBodyV1(req.body); try { diff --git a/x-pack/plugins/alerting/server/routes/rule/apis/update/update_rule_route.ts b/x-pack/plugins/alerting/server/routes/rule/apis/update/update_rule_route.ts index f13d3ac9ee31b3..3c5461208eb19d 100644 --- a/x-pack/plugins/alerting/server/routes/rule/apis/update/update_rule_route.ts +++ b/x-pack/plugins/alerting/server/routes/rule/apis/update/update_rule_route.ts @@ -43,7 +43,8 @@ export const updateRuleRoute = ( handleDisabledApiKeysError( router.handleLegacyErrors( verifyAccessAndContext(licenseState, async function (context, req, res) { - const rulesClient = (await context.alerting).getRulesClient(); + const alertingContext = await context.alerting; + const rulesClient = await alertingContext.getRulesClient(); const actionsClient = (await context.actions).getActionsClient(); // Assert versioned inputs diff --git a/x-pack/plugins/alerting/server/routes/rule_types.ts b/x-pack/plugins/alerting/server/routes/rule_types.ts index 1021b4c9a14314..575d923cb816e0 100644 --- a/x-pack/plugins/alerting/server/routes/rule_types.ts +++ b/x-pack/plugins/alerting/server/routes/rule_types.ts @@ -63,7 +63,8 @@ export const ruleTypesRoute = ( }, router.handleLegacyErrors( verifyAccessAndContext(licenseState, async function (context, req, res) { - const rulesClient = (await context.alerting).getRulesClient(); + const alertingContext = await context.alerting; + const rulesClient = await alertingContext.getRulesClient(); const ruleTypes = Array.from(await rulesClient.listRuleTypes()); return res.ok({ body: rewriteBodyRes(ruleTypes), diff --git a/x-pack/plugins/alerting/server/routes/run_soon.ts b/x-pack/plugins/alerting/server/routes/run_soon.ts index f6ee65597d9f28..380c3d2b40511a 100644 --- a/x-pack/plugins/alerting/server/routes/run_soon.ts +++ b/x-pack/plugins/alerting/server/routes/run_soon.ts @@ -28,7 +28,8 @@ export const runSoonRoute = ( }, router.handleLegacyErrors( verifyAccessAndContext(licenseState, async function (context, req, res) { - const rulesClient = (await context.alerting).getRulesClient(); + const alertingContext = await context.alerting; + const rulesClient = await alertingContext.getRulesClient(); const message = await rulesClient.runSoon(req.params); return message ? res.ok({ body: message }) : res.noContent(); }) diff --git a/x-pack/plugins/alerting/server/routes/suggestions/values_suggestion_alerts.ts b/x-pack/plugins/alerting/server/routes/suggestions/values_suggestion_alerts.ts index 47a603014a1195..1c0a0ac9621863 100644 --- a/x-pack/plugins/alerting/server/routes/suggestions/values_suggestion_alerts.ts +++ b/x-pack/plugins/alerting/server/routes/suggestions/values_suggestion_alerts.ts @@ -72,7 +72,8 @@ export function registerAlertsValueSuggestionsRoute( const abortSignal = getRequestAbortedSignal(request.events.aborted$); const { savedObjects, elasticsearch } = await context.core; - const rulesClient = (await context.alerting).getRulesClient(); + const alertingContext = await context.alerting; + const rulesClient = await alertingContext.getRulesClient(); let authorizationTuple; let authorizedRuleType = []; try { diff --git a/x-pack/plugins/alerting/server/routes/suggestions/values_suggestion_rules.ts b/x-pack/plugins/alerting/server/routes/suggestions/values_suggestion_rules.ts index 6c34efb214c34e..c669ee9c0e932b 100644 --- a/x-pack/plugins/alerting/server/routes/suggestions/values_suggestion_rules.ts +++ b/x-pack/plugins/alerting/server/routes/suggestions/values_suggestion_rules.ts @@ -58,7 +58,8 @@ export function registerRulesValueSuggestionsRoute( const abortSignal = getRequestAbortedSignal(request.events.aborted$); const { savedObjects, elasticsearch } = await context.core; - const rulesClient = (await context.alerting).getRulesClient(); + const alertingContext = await context.alerting; + const rulesClient = await alertingContext.getRulesClient(); let authorizationTuple; try { authorizationTuple = await rulesClient diff --git a/x-pack/plugins/alerting/server/routes/unmute_alert.ts b/x-pack/plugins/alerting/server/routes/unmute_alert.ts index b0d124e0d3945a..5bf1702237a221 100644 --- a/x-pack/plugins/alerting/server/routes/unmute_alert.ts +++ b/x-pack/plugins/alerting/server/routes/unmute_alert.ts @@ -42,7 +42,8 @@ export const unmuteAlertRoute = ( }, router.handleLegacyErrors( verifyAccessAndContext(licenseState, async function (context, req, res) { - const rulesClient = (await context.alerting).getRulesClient(); + const alertingContext = await context.alerting; + const rulesClient = await alertingContext.getRulesClient(); const params = rewriteParamsReq(req.params); try { await rulesClient.unmuteInstance(params); diff --git a/x-pack/plugins/alerting/server/routes/unmute_all_rule.ts b/x-pack/plugins/alerting/server/routes/unmute_all_rule.ts index 033f5b276828ab..93ce6a9adc3327 100644 --- a/x-pack/plugins/alerting/server/routes/unmute_all_rule.ts +++ b/x-pack/plugins/alerting/server/routes/unmute_all_rule.ts @@ -32,7 +32,8 @@ export const unmuteAllRuleRoute = ( }, router.handleLegacyErrors( verifyAccessAndContext(licenseState, async function (context, req, res) { - const rulesClient = (await context.alerting).getRulesClient(); + const alertingContext = await context.alerting; + const rulesClient = await alertingContext.getRulesClient(); const { id } = req.params; try { await rulesClient.unmuteAll({ id }); diff --git a/x-pack/plugins/alerting/server/routes/update_rule_api_key.ts b/x-pack/plugins/alerting/server/routes/update_rule_api_key.ts index 8591f273eeeb33..a5682cf0088e8d 100644 --- a/x-pack/plugins/alerting/server/routes/update_rule_api_key.ts +++ b/x-pack/plugins/alerting/server/routes/update_rule_api_key.ts @@ -32,7 +32,8 @@ export const updateRuleApiKeyRoute = ( }, router.handleLegacyErrors( verifyAccessAndContext(licenseState, async function (context, req, res) { - const rulesClient = (await context.alerting).getRulesClient(); + const alertingContext = await context.alerting; + const rulesClient = await alertingContext.getRulesClient(); const { id } = req.params; try { await rulesClient.updateApiKey({ id }); diff --git a/x-pack/plugins/alerting/server/rules_client_factory.test.ts b/x-pack/plugins/alerting/server/rules_client_factory.test.ts index 4cd7ffbcf0c6c0..13354310e68a95 100644 --- a/x-pack/plugins/alerting/server/rules_client_factory.test.ts +++ b/x-pack/plugins/alerting/server/rules_client_factory.test.ts @@ -98,7 +98,7 @@ test('creates a rules client with proper constructor arguments when security is const request = mockRouter.createKibanaRequest(); savedObjectsService.getScopedClient.mockReturnValue(savedObjectsClient); - alertingAuthorizationClientFactory.create.mockReturnValue( + alertingAuthorizationClientFactory.create.mockResolvedValue( alertingAuthorization as unknown as AlertingAuthorization ); @@ -154,7 +154,7 @@ test('creates a rules client with proper constructor arguments', async () => { const request = mockRouter.createKibanaRequest(); savedObjectsService.getScopedClient.mockReturnValue(savedObjectsClient); - alertingAuthorizationClientFactory.create.mockReturnValue( + alertingAuthorizationClientFactory.create.mockResolvedValue( alertingAuthorization as unknown as AlertingAuthorization ); diff --git a/x-pack/plugins/alerting/server/rules_client_factory.ts b/x-pack/plugins/alerting/server/rules_client_factory.ts index f28170b277ac46..6fbaadf246d868 100644 --- a/x-pack/plugins/alerting/server/rules_client_factory.ts +++ b/x-pack/plugins/alerting/server/rules_client_factory.ts @@ -115,9 +115,13 @@ export class RulesClientFactory { this.securityService = options.securityService; } - public create(request: KibanaRequest, savedObjects: SavedObjectsServiceStart): RulesClient { + public async create( + request: KibanaRequest, + savedObjects: SavedObjectsServiceStart + ): Promise { const { securityPluginSetup, securityService, securityPluginStart, actions, eventLog } = this; const spaceId = this.getSpaceId(request); + const authorization = await this.authorization.create(request); if (!this.authorization) { throw new Error('AlertingAuthorizationClientFactory is not defined'); @@ -139,7 +143,7 @@ export class RulesClientFactory { AD_HOC_RUN_SAVED_OBJECT_TYPE, ], }), - authorization: this.authorization.create(request), + authorization, actionsAuthorization: actions.getActionsAuthorizationWithRequest(request), namespace: this.spaceIdToNamespace(spaceId), internalSavedObjectsRepository: this.internalSavedObjectsRepository, diff --git a/x-pack/plugins/alerting/server/task_runner/rule_loader.test.ts b/x-pack/plugins/alerting/server/task_runner/rule_loader.test.ts index 4524c08b56688d..0aa3625b67e2aa 100644 --- a/x-pack/plugins/alerting/server/task_runner/rule_loader.test.ts +++ b/x-pack/plugins/alerting/server/task_runner/rule_loader.test.ts @@ -78,10 +78,10 @@ describe('rule_loader', () => { jest.restoreAllMocks(); }); - describe('validateRuleAndCreateFakeRequest()', () => { + describe('await validateRuleAndCreateFakeRequest()', () => { describe('succeeds', () => { - test('validates and returns the results', () => { - const result = validateRuleAndCreateFakeRequest({ + test('validates and returns the results', async () => { + const result = await validateRuleAndCreateFakeRequest({ ...getDefaultValidateRuleParams(), context, }); @@ -100,7 +100,7 @@ describe('rule_loader', () => { test('throws when rule is not enabled', async () => { let outcome = 'success'; try { - validateRuleAndCreateFakeRequest({ + await validateRuleAndCreateFakeRequest({ ...getDefaultValidateRuleParams(false), context, }); @@ -119,7 +119,7 @@ describe('rule_loader', () => { let outcome = 'success'; try { - validateRuleAndCreateFakeRequest({ + await validateRuleAndCreateFakeRequest({ ...getDefaultValidateRuleParams(), context, }); @@ -137,7 +137,7 @@ describe('rule_loader', () => { context = contextMock as unknown as TaskRunnerContext; let outcome = 'success'; try { - validateRuleAndCreateFakeRequest({ + await validateRuleAndCreateFakeRequest({ ...getDefaultValidateRuleParams(), context, }); @@ -292,7 +292,7 @@ function getTaskRunnerContext(ruleParameters: unknown, historyElements: number) getRulesClientWithRequest, }; - function getRulesClientWithRequest() { + async function getRulesClientWithRequest() { // only need get() mocked rulesClient.getAlertFromRaw.mockReturnValue({ name: ruleName, @@ -304,6 +304,7 @@ function getTaskRunnerContext(ruleParameters: unknown, historyElements: number) }, }, } as Rule); - return rulesClient; + + return Promise.resolve(rulesClient); } } diff --git a/x-pack/plugins/alerting/server/task_runner/rule_loader.ts b/x-pack/plugins/alerting/server/task_runner/rule_loader.ts index ae80b03bd0b4ee..eb0dc5f412b69f 100644 --- a/x-pack/plugins/alerting/server/task_runner/rule_loader.ts +++ b/x-pack/plugins/alerting/server/task_runner/rule_loader.ts @@ -47,9 +47,9 @@ interface ValidateRuleAndCreateFakeRequestParams * - create a fakeRequest object using the rule API key * - get an instance of the RulesClient using the fakeRequest */ -export function validateRuleAndCreateFakeRequest( +export async function validateRuleAndCreateFakeRequest( params: ValidateRuleAndCreateFakeRequestParams -): RunRuleParams { +): Promise> { const { context, paramValidator, @@ -72,7 +72,7 @@ export function validateRuleAndCreateFakeRequest( } const fakeRequest = getFakeKibanaRequest(context, spaceId, apiKey); - const rulesClient = context.getRulesClientWithRequest(fakeRequest); + const rulesClient = await context.getRulesClientWithRequest(fakeRequest); const rule = rulesClient.getAlertFromRaw({ id: ruleId, ruleTypeId, diff --git a/x-pack/plugins/alerting/server/task_runner/task_runner.test.ts b/x-pack/plugins/alerting/server/task_runner/task_runner.test.ts index d6f4e4942da1b1..724491844a7cdf 100644 --- a/x-pack/plugins/alerting/server/task_runner/task_runner.test.ts +++ b/x-pack/plugins/alerting/server/task_runner/task_runner.test.ts @@ -234,7 +234,7 @@ describe('Task Runner', () => { savedObjectsService.getScopedClient.mockReturnValue(services.savedObjectsClient); elasticsearchService.client.asScoped.mockReturnValue(services.scopedClusterClient); maintenanceWindowClient.getActiveMaintenanceWindows.mockResolvedValue([]); - taskRunnerFactoryInitializerParams.getRulesClientWithRequest.mockReturnValue(rulesClient); + taskRunnerFactoryInitializerParams.getRulesClientWithRequest.mockResolvedValue(rulesClient); taskRunnerFactoryInitializerParams.actionsPlugin.getActionsClientWithRequest.mockResolvedValue( actionsClient ); diff --git a/x-pack/plugins/alerting/server/task_runner/task_runner.ts b/x-pack/plugins/alerting/server/task_runner/task_runner.ts index fadd0a944acc8c..947a5427f3aff9 100644 --- a/x-pack/plugins/alerting/server/task_runner/task_runner.ts +++ b/x-pack/plugins/alerting/server/task_runner/task_runner.ts @@ -511,7 +511,7 @@ export class TaskRunner< getDecryptedRule(this.context, ruleId, spaceId) ); - const runRuleParams = validateRuleAndCreateFakeRequest({ + const runRuleParams = await validateRuleAndCreateFakeRequest({ ruleData, paramValidator: this.ruleType.validate.params, ruleId, diff --git a/x-pack/plugins/alerting/server/task_runner/task_runner_alerts_client.test.ts b/x-pack/plugins/alerting/server/task_runner/task_runner_alerts_client.test.ts index 69bc11bc48dc8e..ec31e64b0d5856 100644 --- a/x-pack/plugins/alerting/server/task_runner/task_runner_alerts_client.test.ts +++ b/x-pack/plugins/alerting/server/task_runner/task_runner_alerts_client.test.ts @@ -237,7 +237,7 @@ describe('Task Runner', () => { savedObjectsService.getScopedClient.mockReturnValue(services.savedObjectsClient); elasticsearchService.client.asScoped.mockReturnValue(services.scopedClusterClient); maintenanceWindowClient.getActiveMaintenanceWindows.mockResolvedValue([]); - taskRunnerFactoryInitializerParams.getRulesClientWithRequest.mockReturnValue(rulesClient); + taskRunnerFactoryInitializerParams.getRulesClientWithRequest.mockResolvedValue(rulesClient); taskRunnerFactoryInitializerParams.actionsPlugin.getActionsClientWithRequest.mockResolvedValue( actionsClient ); diff --git a/x-pack/plugins/alerting/server/task_runner/task_runner_cancel.test.ts b/x-pack/plugins/alerting/server/task_runner/task_runner_cancel.test.ts index b41b26bd1ea498..43ba9cb8da6386 100644 --- a/x-pack/plugins/alerting/server/task_runner/task_runner_cancel.test.ts +++ b/x-pack/plugins/alerting/server/task_runner/task_runner_cancel.test.ts @@ -173,7 +173,7 @@ describe('Task Runner Cancel', () => { }); savedObjectsService.getScopedClient.mockReturnValue(services.savedObjectsClient); elasticsearchService.client.asScoped.mockReturnValue(services.scopedClusterClient); - taskRunnerFactoryInitializerParams.getRulesClientWithRequest.mockReturnValue(rulesClient); + taskRunnerFactoryInitializerParams.getRulesClientWithRequest.mockResolvedValue(rulesClient); taskRunnerFactoryInitializerParams.actionsPlugin.getActionsClientWithRequest.mockResolvedValue( actionsClient ); diff --git a/x-pack/plugins/alerting/server/task_runner/types.ts b/x-pack/plugins/alerting/server/task_runner/types.ts index e6701d26277e9d..7532afdf9a7047 100644 --- a/x-pack/plugins/alerting/server/task_runner/types.ts +++ b/x-pack/plugins/alerting/server/task_runner/types.ts @@ -168,7 +168,7 @@ export interface TaskRunnerContext { eventLogger: IEventLogger; executionContext: ExecutionContextStart; getMaintenanceWindowClientWithRequest(request: KibanaRequest): MaintenanceWindowClientApi; - getRulesClientWithRequest(request: KibanaRequest): RulesClientApi; + getRulesClientWithRequest(request: KibanaRequest): Promise; getRulesSettingsClientWithRequest(request: KibanaRequest): RulesSettingsClientApi; kibanaBaseUrl: string | undefined; logger: Logger; diff --git a/x-pack/plugins/alerting/server/types.ts b/x-pack/plugins/alerting/server/types.ts index 342c3070379c57..054d4860741abd 100644 --- a/x-pack/plugins/alerting/server/types.ts +++ b/x-pack/plugins/alerting/server/types.ts @@ -30,7 +30,7 @@ import { Filter } from '@kbn/es-query'; import { ActionsApiRequestHandlerContext } from '@kbn/actions-plugin/server'; import { AlertsHealth } from '@kbn/alerting-types'; import { RuleTypeRegistry as OrigruleTypeRegistry } from './rule_type_registry'; -import { PluginSetupContract, PluginStartContract } from './plugin'; +import { AlertingServerSetup, AlertingServerStart } from './plugin'; import { RulesClient } from './rules_client'; import { RulesSettingsClient, @@ -76,7 +76,7 @@ export type { RuleTypeParams }; * @public */ export interface AlertingApiRequestHandlerContext { - getRulesClient: () => RulesClient; + getRulesClient: () => Promise; getRulesSettingsClient: () => RulesSettingsClient; getMaintenanceWindowClient: () => MaintenanceWindowClient; listTypes: RuleTypeRegistry['list']; @@ -375,8 +375,8 @@ export type PartialRuleWithLegacyId = Pic Partial, 'id'>>; export interface AlertingPlugin { - setup: PluginSetupContract; - start: PluginStartContract; + setup: AlertingServerSetup; + start: AlertingServerStart; } export interface AlertsConfigType { diff --git a/x-pack/plugins/features/server/feature_registry.test.ts b/x-pack/plugins/features/server/feature_registry.test.ts index f27c93ac9129e7..3902bd554716be 100644 --- a/x-pack/plugins/features/server/feature_registry.test.ts +++ b/x-pack/plugins/features/server/feature_registry.test.ts @@ -851,13 +851,16 @@ describe('FeatureRegistry', () => { name: 'Test Feature', app: [], category: { id: 'foo', label: 'foo' }, - alerting: ['bar'], + alerting: [{ ruleTypeId: 'bar', consumers: ['test-feature'] }], privileges: { all: { alerting: { rule: { - all: ['foo', 'bar'], - read: ['baz'], + all: [ + { ruleTypeId: 'foo', consumers: ['test-feature'] }, + { ruleTypeId: 'bar', consumers: ['test-feature'] }, + ], + read: [{ ruleTypeId: 'baz', consumers: ['test-feature'] }], }, }, savedObject: { @@ -870,7 +873,11 @@ describe('FeatureRegistry', () => { read: { alerting: { rule: { - read: ['foo', 'bar', 'baz'], + read: [ + { ruleTypeId: 'foo', consumers: ['test-feature'] }, + { ruleTypeId: 'bar', consumers: ['test-feature'] }, + { ruleTypeId: 'baz', consumers: ['test-feature'] }, + ], }, }, savedObject: { @@ -898,13 +905,16 @@ describe('FeatureRegistry', () => { name: 'Test Feature', app: [], category: { id: 'foo', label: 'foo' }, - alerting: ['bar'], + alerting: [{ ruleTypeId: 'bar', consumers: ['test-feature'] }], privileges: { all: { alerting: { alert: { - all: ['foo', 'bar'], - read: ['baz'], + all: [ + { ruleTypeId: 'foo', consumers: ['test-feature'] }, + { ruleTypeId: 'bar', consumers: ['test-feature'] }, + ], + read: [{ ruleTypeId: 'baz', consumers: ['test-feature'] }], }, }, savedObject: { @@ -917,7 +927,11 @@ describe('FeatureRegistry', () => { read: { alerting: { alert: { - read: ['foo', 'bar', 'baz'], + read: [ + { ruleTypeId: 'foo', consumers: ['test-feature'] }, + { ruleTypeId: 'bar', consumers: ['test-feature'] }, + { ruleTypeId: 'baz', consumers: ['test-feature'] }, + ], }, }, savedObject: { @@ -945,12 +959,16 @@ describe('FeatureRegistry', () => { name: 'Test Feature', app: [], category: { id: 'foo', label: 'foo' }, - alerting: ['foo', 'bar', 'baz'], + alerting: [ + { ruleTypeId: 'foo', consumers: ['test-feature'] }, + { ruleTypeId: 'bar', consumers: ['test-feature'] }, + { ruleTypeId: 'baz', consumers: ['test-feature'] }, + ], privileges: { all: { alerting: { rule: { - all: ['foo'], + all: [{ ruleTypeId: 'foo', consumers: ['test-feature'] }], }, }, savedObject: { @@ -963,7 +981,7 @@ describe('FeatureRegistry', () => { read: { alerting: { rule: { - all: ['foo'], + all: [{ ruleTypeId: 'foo', consumers: ['test-feature'] }], }, }, savedObject: { @@ -992,7 +1010,7 @@ describe('FeatureRegistry', () => { ui: [], alerting: { rule: { - all: ['bar'], + all: [{ ruleTypeId: 'bar', consumers: ['test-feature'] }], }, }, }, @@ -1018,12 +1036,16 @@ describe('FeatureRegistry', () => { name: 'Test Feature', app: [], category: { id: 'foo', label: 'foo' }, - alerting: ['foo', 'bar', 'baz'], + alerting: [ + { ruleTypeId: 'foo', consumers: ['test-feature'] }, + { ruleTypeId: 'bar', consumers: ['test-feature'] }, + { ruleTypeId: 'baz', consumers: ['test-feature'] }, + ], privileges: { all: { alerting: { alert: { - all: ['foo'], + all: [{ ruleTypeId: 'foo', consumers: ['test-feature'] }], }, }, savedObject: { @@ -1036,7 +1058,7 @@ describe('FeatureRegistry', () => { read: { alerting: { alert: { - all: ['foo'], + all: [{ ruleTypeId: 'foo', consumers: ['test-feature'] }], }, }, savedObject: { @@ -1065,7 +1087,7 @@ describe('FeatureRegistry', () => { ui: [], alerting: { alert: { - all: ['bar'], + all: [{ ruleTypeId: 'bar', consumers: ['test-feature'] }], }, }, }, @@ -1091,7 +1113,7 @@ describe('FeatureRegistry', () => { name: 'Test Feature', app: [], category: { id: 'foo', label: 'foo' }, - alerting: ['bar'], + alerting: [{ ruleTypeId: 'bar', consumers: ['test-feature'] }], privileges: null, reserved: { description: 'something', @@ -1101,7 +1123,11 @@ describe('FeatureRegistry', () => { privilege: { alerting: { rule: { - all: ['foo', 'bar', 'baz'], + all: [ + { ruleTypeId: 'foo', consumers: ['test-feature'] }, + { ruleTypeId: 'bar', consumers: ['test-feature'] }, + { ruleTypeId: 'baz', consumers: ['test-feature'] }, + ], }, }, savedObject: { @@ -1131,7 +1157,7 @@ describe('FeatureRegistry', () => { name: 'Test Feature', app: [], category: { id: 'foo', label: 'foo' }, - alerting: ['bar'], + alerting: [{ ruleTypeId: 'bar', consumers: ['test-feature'] }], privileges: null, reserved: { description: 'something', @@ -1141,7 +1167,11 @@ describe('FeatureRegistry', () => { privilege: { alerting: { alert: { - all: ['foo', 'bar', 'baz'], + all: [ + { ruleTypeId: 'foo', consumers: ['test-feature'] }, + { ruleTypeId: 'bar', consumers: ['test-feature'] }, + { ruleTypeId: 'baz', consumers: ['test-feature'] }, + ], }, }, savedObject: { @@ -1171,7 +1201,11 @@ describe('FeatureRegistry', () => { name: 'Test Feature', app: [], category: { id: 'foo', label: 'foo' }, - alerting: ['foo', 'bar', 'baz'], + alerting: [ + { ruleTypeId: 'foo', consumers: ['test-feature'] }, + { ruleTypeId: 'bar', consumers: ['test-feature'] }, + { ruleTypeId: 'baz', consumers: ['test-feature'] }, + ], privileges: null, reserved: { description: 'something', @@ -1181,7 +1215,10 @@ describe('FeatureRegistry', () => { privilege: { alerting: { rule: { - all: ['foo', 'bar'], + all: [ + { ruleTypeId: 'foo', consumers: ['test-feature'] }, + { ruleTypeId: 'bar', consumers: ['test-feature'] }, + ], }, }, savedObject: { @@ -1211,7 +1248,11 @@ describe('FeatureRegistry', () => { name: 'Test Feature', app: [], category: { id: 'foo', label: 'foo' }, - alerting: ['foo', 'bar', 'baz'], + alerting: [ + { ruleTypeId: 'foo', consumers: ['test-feature'] }, + { ruleTypeId: 'bar', consumers: ['test-feature'] }, + { ruleTypeId: 'baz', consumers: ['test-feature'] }, + ], privileges: null, reserved: { description: 'something', @@ -1221,7 +1262,10 @@ describe('FeatureRegistry', () => { privilege: { alerting: { alert: { - all: ['foo', 'bar'], + all: [ + { ruleTypeId: 'foo', consumers: ['test-feature'] }, + { ruleTypeId: 'bar', consumers: ['test-feature'] }, + ], }, }, savedObject: { @@ -2007,11 +2051,15 @@ describe('FeatureRegistry', () => { all: { ui: [], savedObject: { all: [], read: [] }, - alerting: { alert: { all: ['one'] } }, + alerting: { + alert: { + all: [{ ruleTypeId: 'one', consumers: ['featureE'] }], + }, + }, }, read: { ui: [], savedObject: { all: [], read: [] } }, }, - alerting: ['one'], + alerting: [{ ruleTypeId: 'one', consumers: ['featureE'] }], }, ]; features.forEach((f) => registry.registerKibanaFeature(f)); From 41e54918dca30983e15900f3b11e8fb318715c6a Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Fri, 12 Jul 2024 17:13:58 +0300 Subject: [PATCH 010/106] Add test for alerting authorization object creation --- .../alerting_authorization.test.ts | 597 ++++++++++++------ .../authorization/alerting_authorization.ts | 4 +- 2 files changed, 416 insertions(+), 185 deletions(-) diff --git a/x-pack/plugins/alerting/server/authorization/alerting_authorization.test.ts b/x-pack/plugins/alerting/server/authorization/alerting_authorization.test.ts index eb6a7b7a33e96c..c5c543e413b55c 100644 --- a/x-pack/plugins/alerting/server/authorization/alerting_authorization.test.ts +++ b/x-pack/plugins/alerting/server/authorization/alerting_authorization.test.ts @@ -20,17 +20,12 @@ import { ReadOperations, AlertingAuthorizationEntity, } from './alerting_authorization'; -import { v4 as uuidv4 } from 'uuid'; import { RecoveredActionGroup } from '../../common'; import { NormalizedRuleType, RegistryRuleType } from '../rule_type_registry'; import { AlertingAuthorizationFilterType } from './alerting_authorization_kuery'; import { schema } from '@kbn/config-schema'; - -const ruleTypeRegistry = ruleTypeRegistryMock.create(); -const features: jest.Mocked = featuresPluginMock.createStart(); -const request = {} as KibanaRequest; -const allRegisteredConsumers = new Set(); -const ruleTypesConsumersMap = new Map>(); +import { httpServerMock } from '@kbn/core-http-server-mocks'; +import { SecurityPluginStart } from '@kbn/security-plugin-types-server'; const getSpace = jest.fn(); const getSpaceId = () => 'space1'; @@ -55,65 +50,6 @@ function mockSecurity() { return { authorization }; } -function mockFeature(appName: string, typeName?: string[]) { - const alertingFeatures = typeName?.map((ruleTypeId) => ({ - ruleTypeId, - consumers: [appName], - })); - - return new KibanaFeature({ - id: appName, - name: appName, - app: [], - category: { id: 'foo', label: 'foo' }, - ...(alertingFeatures - ? { - alerting: alertingFeatures, - } - : {}), - privileges: { - all: { - ...(alertingFeatures - ? { - alerting: { - rule: { - all: alertingFeatures, - }, - alert: { - all: alertingFeatures, - }, - }, - } - : {}), - savedObject: { - all: [], - read: [], - }, - ui: [], - }, - read: { - ...(alertingFeatures - ? { - alerting: { - rule: { - read: alertingFeatures, - }, - alert: { - read: alertingFeatures, - }, - }, - } - : {}), - savedObject: { - all: [], - read: [], - }, - ui: [], - }, - }, - }); -} - function mockFeatureWithSubFeature(appName: string, typeName: string[]) { const alertingFeatures = typeName?.map((ruleTypeId) => ({ ruleTypeId, @@ -191,64 +127,309 @@ function mockFeatureWithSubFeature(appName: string, typeName: string[]) { }); } -const myAppFeature = mockFeature('myApp', ['myType']); -const myOtherAppFeature = mockFeature('myOtherApp', ['myType']); -const myAppWithSubFeature = mockFeatureWithSubFeature('myAppWithSubFeature', ['myType']); -const myFeatureWithoutAlerting = mockFeature('myOtherApp'); - -beforeEach(() => { - jest.resetAllMocks(); - ruleTypeRegistry.get.mockImplementation((id) => ({ - id, - name: 'My Alert Type', - actionGroups: [{ id: 'default', name: 'Default' }], - defaultActionGroupId: 'default', - minimumLicenseRequired: 'basic', - isExportable: true, - recoveryActionGroup: RecoveredActionGroup, - async executor() { - return { state: {} }; - }, - category: 'test', - producer: 'myApp', - validate: { - params: schema.any(), +function mockFeatureWithConsumers( + appName: string, + alertingFeatures?: ReadonlyArray<{ ruleTypeId: string; consumers: readonly string[] }> +) { + return new KibanaFeature({ + id: appName, + name: appName, + app: [], + category: { id: 'foo', label: 'foo' }, + ...(alertingFeatures + ? { + alerting: alertingFeatures, + } + : {}), + privileges: { + all: { + ...(alertingFeatures + ? { + alerting: { + rule: { + all: alertingFeatures, + }, + alert: { + all: alertingFeatures, + }, + }, + } + : {}), + savedObject: { + all: [], + read: [], + }, + ui: [], + }, + read: { + ...(alertingFeatures + ? { + alerting: { + rule: { + read: alertingFeatures, + }, + alert: { + read: alertingFeatures, + }, + }, + } + : {}), + savedObject: { + all: [], + read: [], + }, + ui: [], + }, }, - validLegacyConsumers: [], - })); - features.getKibanaFeatures.mockReturnValue([ - myAppFeature, - myOtherAppFeature, - myAppWithSubFeature, - myFeatureWithoutAlerting, - ]); - getSpace.mockResolvedValue(undefined); -}); + }); +} + +const myAppFeature = mockFeatureWithConsumers('myApp', [ + { ruleTypeId: 'myType', consumers: ['myApp'] }, +]); + +const myOtherAppFeature = mockFeatureWithConsumers('myOtherApp', [ + { ruleTypeId: 'myType', consumers: ['myOtherApp'] }, +]); + +const myAppWithSubFeature = mockFeatureWithSubFeature('myAppWithSubFeature', ['myType']); +const myFeatureWithoutAlerting = mockFeatureWithConsumers('myOtherApp'); describe('AlertingAuthorization', () => { - describe('constructor', () => { - test(`fetches the user's current space`, async () => { - const space = { - id: uuidv4(), - name: uuidv4(), + const ruleTypeRegistry = ruleTypeRegistryMock.create(); + const features: jest.Mocked = featuresPluginMock.createStart(); + const allRegisteredConsumers = new Set(); + const ruleTypesConsumersMap = new Map>(); + let request: KibanaRequest; + + beforeEach(() => { + jest.clearAllMocks(); + request = httpServerMock.createKibanaRequest(); + + ruleTypeRegistry.get.mockImplementation((id) => ({ + id, + name: 'My Alert Type', + actionGroups: [{ id: 'default', name: 'Default' }], + defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', + isExportable: true, + recoveryActionGroup: RecoveredActionGroup, + async executor() { + return { state: {} }; + }, + category: 'test', + producer: 'myApp', + validate: { + params: schema.any(), + }, + validLegacyConsumers: [], + })); + + features.getKibanaFeatures.mockReturnValue([ + myAppFeature, + myOtherAppFeature, + myAppWithSubFeature, + myFeatureWithoutAlerting, + ]); + getSpace.mockResolvedValue(undefined); + + allRegisteredConsumers.clear(); + ruleTypesConsumersMap.clear(); + }); + + describe('create', () => { + let securityStart: jest.Mocked; + + beforeEach(() => { + jest.clearAllMocks(); + securityStart = securityMock.createStart(); + getSpace.mockReturnValue({ id: 'default', name: 'Default', disabledFeatures: [] }); + }); + + it('creates an AlertingAuthorization object', async () => { + expect.assertions(2); + + const authPromise = AlertingAuthorization.create({ + request, + ruleTypeRegistry, + getSpaceId, + features, + getSpace, + authorization: securityStart.authz, + }); + + await expect(authPromise).resolves.toBeDefined(); + await expect(authPromise).resolves.not.toThrow(); + }); + + it('creates an AlertingAuthorization object without spaces', async () => { + getSpace.mockReturnValue(undefined); + expect.assertions(2); + + const authPromise = AlertingAuthorization.create({ + request, + ruleTypeRegistry, + getSpaceId, + features, + getSpace, + authorization: securityStart.authz, + }); + + await expect(authPromise).resolves.toBeDefined(); + await expect(authPromise).resolves.not.toThrow(); + }); + + it('filters out disabled spaces and features without alerting', async () => { + getSpace.mockReturnValue({ + id: 'default', + name: 'Default', + disabledFeatures: ['my-feature-1'], + }); + + features.getKibanaFeatures.mockReturnValue([ + mockFeatureWithConsumers('my-feature-1', [ + { ruleTypeId: 'rule-type-1', consumers: ['consumer-a', 'consumer-b'] }, + ]), + mockFeatureWithConsumers('my-feature-2', [ + { ruleTypeId: 'rule-type-2', consumers: ['consumer-c', 'consumer-d'] }, + ]), + mockFeatureWithConsumers('my-feature-3'), + mockFeatureWithConsumers('my-feature-4', []), + ]); + + const auth = await AlertingAuthorization.create({ + request, + ruleTypeRegistry, + getSpaceId, + features, + getSpace, + authorization: securityStart.authz, + }); + + // @ts-expect-error: allRegisteredConsumers is a private method of the auth class + expect(auth.allRegisteredConsumers).toMatchInlineSnapshot(` + Set { + "consumer-c", + "consumer-d", + } + `); + // @ts-expect-error: allRegisteredConsumers is a private method of the auth class + expect(auth.ruleTypesConsumersMap).toMatchInlineSnapshot(` + Map { + "rule-type-2" => Set { + "consumer-c", + "consumer-d", + }, + } + `); + }); + + it('removes duplicated consumers', async () => { + getSpace.mockReturnValue({ + id: 'default', + name: 'Default', disabledFeatures: [], - }; - getSpace.mockResolvedValue(space); + }); - new AlertingAuthorization({ + features.getKibanaFeatures.mockReturnValue([ + mockFeatureWithConsumers('my-feature-1', [ + { ruleTypeId: 'rule-type-1', consumers: ['consumer-a', 'consumer-b', 'consumer-a'] }, + { ruleTypeId: 'rule-type-2', consumers: ['consumer-a', 'consumer-b', 'consumer-c'] }, + ]), + mockFeatureWithConsumers('my-feature-2', [ + { ruleTypeId: 'rule-type-2', consumers: ['consumer-a', 'consumer-b', 'consumer-c'] }, + ]), + ]); + + const auth = await AlertingAuthorization.create({ request, ruleTypeRegistry, getSpaceId, - allRegisteredConsumers, - ruleTypesConsumersMap, + features, + getSpace, + authorization: securityStart.authz, }); - expect(getSpace).toHaveBeenCalledWith(request); + // @ts-expect-error: allRegisteredConsumers is a private method of the auth class + expect(auth.allRegisteredConsumers).toMatchInlineSnapshot(` + Set { + "consumer-a", + "consumer-b", + "consumer-c", + } + `); + }); + + it('removes duplicated ruleTypes and consumers', async () => { + getSpace.mockReturnValue({ + id: 'default', + name: 'Default', + disabledFeatures: [], + }); + + features.getKibanaFeatures.mockReturnValue([ + mockFeatureWithConsumers('my-feature-1', [ + { ruleTypeId: 'rule-type-1', consumers: ['consumer-a', 'consumer-b', 'consumer-a'] }, + { ruleTypeId: 'rule-type-2', consumers: ['consumer-a', 'consumer-b', 'consumer-c'] }, + ]), + mockFeatureWithConsumers('my-feature-2', [ + { ruleTypeId: 'rule-type-2', consumers: ['consumer-a', 'consumer-b', 'consumer-e'] }, + { ruleTypeId: 'rule-type-1', consumers: ['consumer-a', 'consumer-b', 'consumer-d'] }, + ]), + ]); + + const auth = await AlertingAuthorization.create({ + request, + ruleTypeRegistry, + getSpaceId, + features, + getSpace, + authorization: securityStart.authz, + }); + + // @ts-expect-error: allRegisteredConsumers is a private method of the auth class + expect(auth.ruleTypesConsumersMap).toMatchInlineSnapshot(` + Map { + "rule-type-1" => Set { + "consumer-a", + "consumer-b", + "consumer-d", + }, + "rule-type-2" => Set { + "consumer-a", + "consumer-b", + "consumer-c", + "consumer-e", + }, + } + `); + }); + + it('throws an error when a failure occurs', async () => { + expect.assertions(1); + + getSpace.mockRejectedValue(new Error('Error')); + + const authPromise = AlertingAuthorization.create({ + request, + ruleTypeRegistry, + getSpaceId, + features, + getSpace, + authorization: securityStart.authz, + }); + + await expect(authPromise).rejects.toThrow(); }); }); describe('ensureAuthorized', () => { - test('is a no-op when there is no authorization api', async () => { + beforeEach(() => { + allRegisteredConsumers.clear(); + allRegisteredConsumers.add('myApp'); + }); + + it('is a no-op when there is no authorization api', async () => { const alertAuthorization = new AlertingAuthorization({ request, ruleTypeRegistry, @@ -267,9 +448,10 @@ describe('AlertingAuthorization', () => { expect(ruleTypeRegistry.get).toHaveBeenCalledTimes(1); }); - test('is a no-op when the security license is disabled', async () => { + it('is a no-op when the security license is disabled', async () => { const { authorization } = mockSecurity(); authorization.mode.useRbacForRequest.mockReturnValue(false); + const alertAuthorization = new AlertingAuthorization({ request, ruleTypeRegistry, @@ -289,7 +471,7 @@ describe('AlertingAuthorization', () => { expect(ruleTypeRegistry.get).toHaveBeenCalledTimes(1); }); - test('ensures the user has privileges to execute rules for the specified rule type and operation without consumer when producer and consumer are the same', async () => { + it('ensures the user has privileges to execute rules for the specified rule type and operation without consumer when producer and consumer are the same', async () => { const { authorization } = mockSecurity(); const checkPrivileges: jest.MockedFunction< ReturnType @@ -331,7 +513,7 @@ describe('AlertingAuthorization', () => { }); }); - test('ensures the user has privileges to execute alerts for the specified rule type and operation without consumer when producer and consumer are the same', async () => { + it('ensures the user has privileges to execute alerts for the specified rule type and operation without consumer when producer and consumer are the same', async () => { const { authorization } = mockSecurity(); const checkPrivileges: jest.MockedFunction< ReturnType @@ -373,7 +555,7 @@ describe('AlertingAuthorization', () => { }); }); - test('ensures the user has privileges to execute rules for the specified rule type and operation without consumer when consumer is alerts', async () => { + it('ensures the user has privileges to execute rules for the specified rule type and operation without consumer when consumer is alerts', async () => { const { authorization } = mockSecurity(); const checkPrivileges: jest.MockedFunction< ReturnType @@ -415,7 +597,7 @@ describe('AlertingAuthorization', () => { }); }); - test('ensures the user has privileges to execute alerts for the specified rule type and operation without consumer when consumer is alerts', async () => { + it('ensures the user has privileges to execute alerts for the specified rule type and operation without consumer when consumer is alerts', async () => { const { authorization } = mockSecurity(); const checkPrivileges: jest.MockedFunction< ReturnType @@ -457,7 +639,7 @@ describe('AlertingAuthorization', () => { }); }); - test('ensures the user has privileges to execute rules for the specified rule type, operation and producer when producer is different from consumer', async () => { + it('ensures the user has privileges to execute rules for the specified rule type, operation and producer when producer is different from consumer', async () => { const { authorization } = mockSecurity(); const checkPrivileges: jest.MockedFunction< ReturnType @@ -468,6 +650,7 @@ describe('AlertingAuthorization', () => { hasAllRequested: true, privileges: { kibana: [] }, }); + allRegisteredConsumers.add('myOtherApp'); const alertAuthorization = new AlertingAuthorization({ request, @@ -499,7 +682,7 @@ describe('AlertingAuthorization', () => { }); }); - test('ensures the user has privileges to execute alerts for the specified rule type, operation and producer when producer is different from consumer', async () => { + it('ensures the user has privileges to execute alerts for the specified rule type, operation and producer when producer is different from consumer', async () => { const { authorization } = mockSecurity(); const checkPrivileges: jest.MockedFunction< ReturnType @@ -510,6 +693,7 @@ describe('AlertingAuthorization', () => { hasAllRequested: true, privileges: { kibana: [] }, }); + allRegisteredConsumers.add('myOtherApp'); const alertAuthorization = new AlertingAuthorization({ request, @@ -541,7 +725,7 @@ describe('AlertingAuthorization', () => { }); }); - test('ensures the producer is used for authorization if the consumer is `alerts`', async () => { + it('ensures the producer is used for authorization if the consumer is `alerts`', async () => { const { authorization } = mockSecurity(); const checkPrivileges: jest.MockedFunction< ReturnType @@ -583,7 +767,7 @@ describe('AlertingAuthorization', () => { }); }); - test('throws if user lacks the required rule privileges for the consumer', async () => { + it('throws if user lacks the required rule privileges for the consumer', async () => { const { authorization } = mockSecurity(); const checkPrivileges: jest.MockedFunction< ReturnType @@ -627,7 +811,7 @@ describe('AlertingAuthorization', () => { ); }); - test('throws if user lacks the required alert privileges for the consumer', async () => { + it('throws if user lacks the required alert privileges for the consumer', async () => { const { authorization } = mockSecurity(); const checkPrivileges: jest.MockedFunction< ReturnType @@ -675,7 +859,7 @@ describe('AlertingAuthorization', () => { ); }); - test('throws if user lacks the required privileges for the producer', async () => { + it('throws if user lacks the required privileges for the producer', async () => { const { authorization } = mockSecurity(); const checkPrivileges: jest.MockedFunction< ReturnType @@ -719,7 +903,7 @@ describe('AlertingAuthorization', () => { ); }); - test('throws if user lacks the required privileges for both consumer and producer', async () => { + it('throws if user lacks the required privileges for both consumer and producer', async () => { const { authorization } = mockSecurity(); const checkPrivileges: jest.MockedFunction< ReturnType @@ -763,7 +947,7 @@ describe('AlertingAuthorization', () => { ); }); - test('checks additional privileges correctly', async () => { + it('checks additional privileges correctly', async () => { const { authorization } = mockSecurity(); const checkPrivileges: jest.MockedFunction< ReturnType @@ -857,7 +1041,7 @@ describe('AlertingAuthorization', () => { validLegacyConsumers: [], }; const setOfAlertTypes = new Set([myAppAlertType, myOtherAppAlertType, mySecondAppAlertType]); - test('omits filter when there is no authorization api', async () => { + it('omits filter when there is no authorization api', async () => { const alertAuthorization = new AlertingAuthorization({ request, ruleTypeRegistry, @@ -876,7 +1060,7 @@ describe('AlertingAuthorization', () => { expect(() => ensureRuleTypeIsAuthorized('someMadeUpType', 'myApp', 'rule')).not.toThrow(); expect(filter).toEqual(undefined); }); - test('ensureRuleTypeIsAuthorized is no-op when there is no authorization api', async () => { + it('ensureRuleTypeIsAuthorized is no-op when there is no authorization api', async () => { const alertAuthorization = new AlertingAuthorization({ request, ruleTypeRegistry, @@ -897,10 +1081,17 @@ describe('AlertingAuthorization', () => { ensureRuleTypeIsAuthorized('someMadeUpType', 'myApp', 'rule'); }); - test('creates a filter based on the privileged types', async () => { + it('creates a filter based on the privileged types', async () => { features.getKibanaFeatures.mockReturnValue([ - mockFeature('myApp', ['myAppAlertType', 'mySecondAppAlertType']), - mockFeature('alerts', ['myOtherAppAlertType']), + mockFeatureWithConsumers('myApp', [ + { ruleTypeId: 'myAppAlertType', consumers: ['myApp'] }, + { ruleTypeId: 'mySecondAppAlertType', consumers: ['myApp'] }, + ]), + + mockFeatureWithConsumers('alerts', [ + { ruleTypeId: 'myOtherAppAlertType', consumers: ['alerts'] }, + ]), + myOtherAppFeature, myAppWithSubFeature, ]); @@ -1015,7 +1206,7 @@ describe('AlertingAuthorization', () => { ) ); }); - test('throws if user has no privileges to any rule type', async () => { + it('throws if user has no privileges to any rule type', async () => { const { authorization } = mockSecurity(); const checkPrivileges: jest.MockedFunction< ReturnType @@ -1059,10 +1250,16 @@ describe('AlertingAuthorization', () => { ); }); - test('creates an `ensureRuleTypeIsAuthorized` function which throws if type is unauthorized', async () => { + it('creates an `ensureRuleTypeIsAuthorized` function which throws if type is unauthorized', async () => { features.getKibanaFeatures.mockReturnValue([ - mockFeature('myApp', ['myOtherAppAlertType', 'myAppAlertType']), - mockFeature('myOtherApp', ['myOtherAppAlertType', 'myAppAlertType']), + mockFeatureWithConsumers('myApp', [ + { ruleTypeId: 'myOtherAppAlertType', consumers: ['myApp'] }, + { ruleTypeId: 'myAppAlertType', consumers: ['myApp'] }, + ]), + mockFeatureWithConsumers('myOtherApp', [ + { ruleTypeId: 'myOtherAppAlertType', consumers: ['myOtherApp'] }, + { ruleTypeId: 'myAppAlertType', consumers: ['myOtherApp'] }, + ]), ]); const { authorization } = mockSecurity(); const checkPrivileges: jest.MockedFunction< @@ -1123,10 +1320,15 @@ describe('AlertingAuthorization', () => { `"Unauthorized by \\"myOtherApp\\" to find \\"myAppAlertType\\" alert"` ); }); - test('creates an `ensureRuleTypeIsAuthorized` function which is no-op if type is authorized', async () => { + it('creates an `ensureRuleTypeIsAuthorized` function which is no-op if type is authorized', async () => { features.getKibanaFeatures.mockReturnValue([ - mockFeature('myApp', ['myOtherAppAlertType', 'myAppAlertType']), - mockFeature('myOtherApp', ['myAppAlertType']), + mockFeatureWithConsumers('myApp', [ + { ruleTypeId: 'myOtherAppAlertType', consumers: ['myApp'] }, + { ruleTypeId: 'myAppAlertType', consumers: ['myApp'] }, + ]), + mockFeatureWithConsumers('myOtherApp', [ + { ruleTypeId: 'myOtherApp', consumers: ['myOtherApp'] }, + ]), ]); const { authorization } = mockSecurity(); const checkPrivileges: jest.MockedFunction< @@ -1185,10 +1387,17 @@ describe('AlertingAuthorization', () => { ensureRuleTypeIsAuthorized('myAppAlertType', 'myOtherApp', 'rule'); }).not.toThrow(); }); - test('creates an `logSuccessfulAuthorization` function which logs every authorized type', async () => { + it('creates an `logSuccessfulAuthorization` function which logs every authorized type', async () => { features.getKibanaFeatures.mockReturnValue([ - mockFeature('myApp', ['myOtherAppAlertType', 'myAppAlertType', 'mySecondAppAlertType']), - mockFeature('myOtherApp', ['mySecondAppAlertType', 'myAppAlertType']), + mockFeatureWithConsumers('myApp', [ + { ruleTypeId: 'myOtherAppAlertType', consumers: ['myApp'] }, + { ruleTypeId: 'myAppAlertType', consumers: ['myApp'] }, + { ruleTypeId: 'mySecondAppAlertType', consumers: ['myApp'] }, + ]), + mockFeatureWithConsumers('myOtherApp', [ + { ruleTypeId: 'mySecondAppAlertType', consumers: ['myOtherApp'] }, + { ruleTypeId: 'myAppAlertType', consumers: ['myOtherApp'] }, + ]), ]); const { authorization } = mockSecurity(); const checkPrivileges: jest.MockedFunction< @@ -1266,7 +1475,7 @@ describe('AlertingAuthorization', () => { // This is a specific use case currently for alerts as data // Space ids are stored in the alerts documents and even if security is disabled // still need to consider the users space privileges - test('creates a spaceId only filter if security is disabled, but require space awareness', async () => { + it('creates a spaceId only filter if security is disabled, but require space awareness', async () => { const alertAuthorization = new AlertingAuthorization({ request, ruleTypeRegistry, @@ -1328,11 +1537,17 @@ describe('AlertingAuthorization', () => { const setOfAlertTypes = new Set([myAppAlertType, myOtherAppAlertType]); beforeEach(() => { features.getKibanaFeatures.mockReturnValue([ - mockFeature('myApp', ['myOtherAppAlertType', 'myAppAlertType']), - mockFeature('myOtherApp', ['myAppAlertType', 'myOtherAppAlertType']), + mockFeatureWithConsumers('myApp', [ + { ruleTypeId: 'myOtherAppAlertType', consumers: ['myApp'] }, + { ruleTypeId: 'myAppAlertType', consumers: ['myApp'] }, + ]), + mockFeatureWithConsumers('myOtherApp', [ + { ruleTypeId: 'myOtherAppAlertType', consumers: ['myApp'] }, + { ruleTypeId: 'myAppAlertType', consumers: ['myApp'] }, + ]), ]); }); - test('augments a list of types with all features when there is no authorization api', async () => { + it('augments a list of types with all features when there is no authorization api', async () => { features.getKibanaFeatures.mockReturnValue([ myAppFeature, myOtherAppFeature, @@ -1434,7 +1649,7 @@ describe('AlertingAuthorization', () => { `); }); - test('augments a list of types with consumers under which the operation is authorized', async () => { + it('augments a list of types with consumers under which the operation is authorized', async () => { const { authorization } = mockSecurity(); const checkPrivileges: jest.MockedFunction< ReturnType @@ -1546,7 +1761,7 @@ describe('AlertingAuthorization', () => { `); }); - test('authorizes user under the `alerts` consumer when they are authorized by the producer', async () => { + it('authorizes user under the `alerts` consumer when they are authorized by the producer', async () => { const { authorization } = mockSecurity(); const checkPrivileges: jest.MockedFunction< ReturnType @@ -1616,7 +1831,7 @@ describe('AlertingAuthorization', () => { `); }); - test('augments a list of types with consumers under which multiple operations are authorized', async () => { + it('augments a list of types with consumers under which multiple operations are authorized', async () => { const { authorization } = mockSecurity(); const checkPrivileges: jest.MockedFunction< ReturnType @@ -1753,7 +1968,7 @@ describe('AlertingAuthorization', () => { `); }); - test('omits types which have no consumers under which the operation is authorized', async () => { + it('omits types which have no consumers under which the operation is authorized', async () => { const { authorization } = mockSecurity(); const checkPrivileges: jest.MockedFunction< ReturnType @@ -1892,9 +2107,13 @@ describe('AlertingAuthorization', () => { }; const setOfAlertTypes = new Set([myAppAlertType, myOtherAppAlertType, mySecondAppAlertType]); beforeEach(() => { - features.getKibanaFeatures.mockReturnValue([mockFeature('myApp', ['myOtherAppAlertType'])]); + features.getKibanaFeatures.mockReturnValue([ + mockFeatureWithConsumers('myOtherApp', [ + { ruleTypeId: 'myOtherAppAlertType', consumers: ['myApp'] }, + ]), + ]); }); - test('it returns authorized rule types given a set of feature ids', async () => { + it('it returns authorized rule types given a set of feature ids', async () => { const { authorization } = mockSecurity(); const checkPrivileges: jest.MockedFunction< ReturnType @@ -1963,7 +2182,7 @@ describe('AlertingAuthorization', () => { `); }); - test('it returns all authorized if user has read, get and update alert privileges', async () => { + it('it returns all authorized if user has read, get and update alert privileges', async () => { const { authorization } = mockSecurity(); const checkPrivileges: jest.MockedFunction< ReturnType @@ -2223,8 +2442,10 @@ describe('AlertingAuthorization', () => { features.getKibanaFeatures.mockReset(); features.getKibanaFeatures.mockReturnValue([ - mockFeature('stackAlerts', ['.esQuery']), - mockFeature('discover', []), + mockFeatureWithConsumers('stackAlerts', [ + { ruleTypeId: '.esQuery', consumers: ['stackAlerts'] }, + ]), + mockFeatureWithConsumers('discover'), ]); checkPrivileges.mockReset(); checkPrivileges.mockResolvedValue({ @@ -2247,7 +2468,7 @@ describe('AlertingAuthorization', () => { }); describe('ensureAuthorized', () => { - test('should allow to create .esquery rule type with stackAlerts consumer', async () => { + it('should allow to create .esquery rule type with stackAlerts consumer', async () => { await expect( alertAuthorization.ensureAuthorized({ ruleTypeId: '.esQuery', @@ -2259,7 +2480,7 @@ describe('AlertingAuthorization', () => { expect(ruleTypeRegistry.get).toHaveBeenCalledTimes(1); }); - test('should allow to create .esquery rule type with discover consumer', async () => { + it('should allow to create .esquery rule type with discover consumer', async () => { await expect( alertAuthorization.ensureAuthorized({ ruleTypeId: '.esQuery', @@ -2271,7 +2492,7 @@ describe('AlertingAuthorization', () => { expect(ruleTypeRegistry.get).toHaveBeenCalledTimes(1); }); - test('should allow to create .esquery rule type with alerts consumer', async () => { + it('should allow to create .esquery rule type with alerts consumer', async () => { await expect( alertAuthorization.ensureAuthorized({ ruleTypeId: '.esQuery', @@ -2283,7 +2504,7 @@ describe('AlertingAuthorization', () => { expect(ruleTypeRegistry.get).toHaveBeenCalledTimes(1); }); - test('should throw an error to create .esquery rule type with logs consumer', async () => { + it('should throw an error to create .esquery rule type with logs consumer', async () => { await expect( alertAuthorization.ensureAuthorized({ ruleTypeId: '.esQuery', @@ -2297,7 +2518,7 @@ describe('AlertingAuthorization', () => { expect(ruleTypeRegistry.get).toHaveBeenCalledTimes(1); }); - test('should throw an error to create .esquery rule type with infrastructure consumer', async () => { + it('should throw an error to create .esquery rule type with infrastructure consumer', async () => { await expect( alertAuthorization.ensureAuthorized({ ruleTypeId: '.esQuery', @@ -2311,7 +2532,7 @@ describe('AlertingAuthorization', () => { expect(ruleTypeRegistry.get).toHaveBeenCalledTimes(1); }); - test('should throw an error to create .threshold-rule-o11y rule type with alerts consumer', async () => { + it('should throw an error to create .threshold-rule-o11y rule type with alerts consumer', async () => { await expect( alertAuthorization.ensureAuthorized({ ruleTypeId: '.threshold-rule-o11y', @@ -2325,7 +2546,7 @@ describe('AlertingAuthorization', () => { expect(ruleTypeRegistry.get).toHaveBeenCalledTimes(1); }); - test('should throw an error to create .logs-threshold-o11y rule type with alerts infrastructure', async () => { + it('should throw an error to create .logs-threshold-o11y rule type with alerts infrastructure', async () => { await expect( alertAuthorization.ensureAuthorized({ ruleTypeId: '.logs-threshold-o11y', @@ -2341,7 +2562,7 @@ describe('AlertingAuthorization', () => { }); }); - test('creates a filter based on the privileged types', async () => { + it('creates a filter based on the privileged types', async () => { expect( ( await alertAuthorization.getFindAuthorizationFilter(AlertingAuthorizationEntity.Rule, { @@ -2370,12 +2591,16 @@ describe('AlertingAuthorization', () => { features.getKibanaFeatures.mockReset(); features.getKibanaFeatures.mockReturnValue([ - mockFeature('infrastructure', [ - '.infrastructure-threshold-o11y', - '.threshold-rule-o11y', - '.esQuery', + mockFeatureWithConsumers('infrastructure', [ + { ruleTypeId: '.infrastructure-threshold-o11y', consumers: ['infrastructure'] }, + { ruleTypeId: '.threshold-rule-o11y', consumers: ['myApp'] }, + { ruleTypeId: '.esQuery', consumers: ['myApp'] }, + ]), + mockFeatureWithConsumers('logs', [ + { ruleTypeId: '.threshold-rule-o11y', consumers: ['logs'] }, + { ruleTypeId: '.esQuery', consumers: ['logs'] }, + { ruleTypeId: '.logs-threshold-o11y', consumers: ['logs'] }, ]), - mockFeature('logs', ['.threshold-rule-o11y', '.esQuery', '.logs-threshold-o11y']), ]); checkPrivileges.mockReset(); checkPrivileges.mockResolvedValue({ @@ -2398,7 +2623,7 @@ describe('AlertingAuthorization', () => { }); describe('ensureAuthorized', () => { - test('should throw an error to create .esquery rule type with stackAlerts consumer', async () => { + it('should throw an error to create .esquery rule type with stackAlerts consumer', async () => { await expect( alertAuthorization.ensureAuthorized({ ruleTypeId: '.esQuery', @@ -2412,7 +2637,7 @@ describe('AlertingAuthorization', () => { expect(ruleTypeRegistry.get).toHaveBeenCalledTimes(1); }); - test('should throw an error to create .esquery rule type with discover consumer', async () => { + it('should throw an error to create .esquery rule type with discover consumer', async () => { await expect( alertAuthorization.ensureAuthorized({ ruleTypeId: '.esQuery', @@ -2426,7 +2651,7 @@ describe('AlertingAuthorization', () => { expect(ruleTypeRegistry.get).toHaveBeenCalledTimes(1); }); - test('should throw an error to create .threshold-rule-o11y rule type with alerts consumer', async () => { + it('should throw an error to create .threshold-rule-o11y rule type with alerts consumer', async () => { await expect( alertAuthorization.ensureAuthorized({ ruleTypeId: '.threshold-rule-o11y', @@ -2440,7 +2665,7 @@ describe('AlertingAuthorization', () => { expect(ruleTypeRegistry.get).toHaveBeenCalledTimes(1); }); - test('should allow to create .esquery rule type with logs consumer', async () => { + it('should allow to create .esquery rule type with logs consumer', async () => { await expect( alertAuthorization.ensureAuthorized({ ruleTypeId: '.esQuery', @@ -2452,7 +2677,7 @@ describe('AlertingAuthorization', () => { expect(ruleTypeRegistry.get).toHaveBeenCalledTimes(1); }); - test('should allow to create .esquery rule type with logs infrastructure', async () => { + it('should allow to create .esquery rule type with logs infrastructure', async () => { await expect( alertAuthorization.ensureAuthorized({ ruleTypeId: '.esQuery', @@ -2464,7 +2689,7 @@ describe('AlertingAuthorization', () => { expect(ruleTypeRegistry.get).toHaveBeenCalledTimes(1); }); - test('should allow to create .logs-threshold-o11y rule type with alerts consumer', async () => { + it('should allow to create .logs-threshold-o11y rule type with alerts consumer', async () => { await expect( alertAuthorization.ensureAuthorized({ ruleTypeId: '.logs-threshold-o11y', @@ -2476,7 +2701,7 @@ describe('AlertingAuthorization', () => { expect(ruleTypeRegistry.get).toHaveBeenCalledTimes(1); }); - test('should throw an error to create .threshold-rule-o11y rule type with logs consumer', async () => { + it('should throw an error to create .threshold-rule-o11y rule type with logs consumer', async () => { await expect( alertAuthorization.ensureAuthorized({ ruleTypeId: '.threshold-rule-o11y', @@ -2489,7 +2714,7 @@ describe('AlertingAuthorization', () => { expect(ruleTypeRegistry.get).toHaveBeenCalledTimes(1); }); }); - test('creates a filter based on the privileged types', async () => { + it('creates a filter based on the privileged types', async () => { expect( ( await alertAuthorization.getFindAuthorizationFilter( @@ -2522,8 +2747,14 @@ describe('AlertingAuthorization', () => { features.getKibanaFeatures.mockClear(); features.getKibanaFeatures.mockReturnValue([ - mockFeature('stackAlerts', ['.esQuery']), - mockFeature('logs', ['.logs-threshold-o11y', '.threshold-rule-o11y', '.esQuery']), + mockFeatureWithConsumers('stackAlerts', [ + { ruleTypeId: '.esQuery', consumers: ['stackAlerts'] }, + ]), + mockFeatureWithConsumers('logs', [ + { ruleTypeId: '.logs-threshold-o11y', consumers: ['logs'] }, + { ruleTypeId: '.threshold-rule-o11y', consumers: ['logs'] }, + { ruleTypeId: '.esQuery', consumers: ['logs'] }, + ]), ]); checkPrivileges.mockClear(); checkPrivileges.mockResolvedValue({ @@ -2545,7 +2776,7 @@ describe('AlertingAuthorization', () => { }); describe('ensureAuthorized', () => { - test('should allow to create .esquery rule type with stackAlerts consumer', async () => { + it('should allow to create .esquery rule type with stackAlerts consumer', async () => { await expect( alertAuthorization.ensureAuthorized({ ruleTypeId: '.esQuery', @@ -2557,7 +2788,7 @@ describe('AlertingAuthorization', () => { expect(ruleTypeRegistry.get).toHaveBeenCalledTimes(1); }); - test('should allow to create .esquery rule type with discover consumer', async () => { + it('should allow to create .esquery rule type with discover consumer', async () => { await expect( alertAuthorization.ensureAuthorized({ ruleTypeId: '.esQuery', @@ -2569,7 +2800,7 @@ describe('AlertingAuthorization', () => { expect(ruleTypeRegistry.get).toHaveBeenCalledTimes(1); }); - test('should allow to create .esquery rule type with logs consumer', async () => { + it('should allow to create .esquery rule type with logs consumer', async () => { await expect( alertAuthorization.ensureAuthorized({ ruleTypeId: '.esQuery', @@ -2581,7 +2812,7 @@ describe('AlertingAuthorization', () => { expect(ruleTypeRegistry.get).toHaveBeenCalledTimes(1); }); - test('should allow to create .logs-threshold-o11y rule type with alerts consumer', async () => { + it('should allow to create .logs-threshold-o11y rule type with alerts consumer', async () => { await expect( alertAuthorization.ensureAuthorized({ ruleTypeId: '.logs-threshold-o11y', @@ -2593,7 +2824,7 @@ describe('AlertingAuthorization', () => { expect(ruleTypeRegistry.get).toHaveBeenCalledTimes(1); }); - test('should throw an error to create .threshold-rule-o11y rule type with logs consumer', async () => { + it('should throw an error to create .threshold-rule-o11y rule type with logs consumer', async () => { await expect( alertAuthorization.ensureAuthorized({ ruleTypeId: '.threshold-rule-o11y', @@ -2605,7 +2836,7 @@ describe('AlertingAuthorization', () => { expect(ruleTypeRegistry.get).toHaveBeenCalledTimes(1); }); - test('should throw an error to create .esquery rule type with logs infrastructure', async () => { + it('should throw an error to create .esquery rule type with logs infrastructure', async () => { await expect( alertAuthorization.ensureAuthorized({ ruleTypeId: '.esQuery', @@ -2619,7 +2850,7 @@ describe('AlertingAuthorization', () => { expect(ruleTypeRegistry.get).toHaveBeenCalledTimes(1); }); - test('should throw an error to create .threshold-rule-o11y rule type with alerts consumer', async () => { + it('should throw an error to create .threshold-rule-o11y rule type with alerts consumer', async () => { await expect( alertAuthorization.ensureAuthorized({ ruleTypeId: '.threshold-rule-o11y', @@ -2633,7 +2864,7 @@ describe('AlertingAuthorization', () => { expect(ruleTypeRegistry.get).toHaveBeenCalledTimes(1); }); - test('should throw an error to create .esquery rule type with infrastructure consumer', async () => { + it('should throw an error to create .esquery rule type with infrastructure consumer', async () => { await expect( alertAuthorization.ensureAuthorized({ ruleTypeId: '.esQuery', @@ -2648,7 +2879,7 @@ describe('AlertingAuthorization', () => { expect(ruleTypeRegistry.get).toHaveBeenCalledTimes(1); }); }); - test('creates a filter based on the privileged types', async () => { + it('creates a filter based on the privileged types', async () => { expect( ( await alertAuthorization.getFindAuthorizationFilter(AlertingAuthorizationEntity.Rule, { diff --git a/x-pack/plugins/alerting/server/authorization/alerting_authorization.ts b/x-pack/plugins/alerting/server/authorization/alerting_authorization.ts index a4fc5d24454140..f992381b88ad14 100644 --- a/x-pack/plugins/alerting/server/authorization/alerting_authorization.ts +++ b/x-pack/plugins/alerting/server/authorization/alerting_authorization.ts @@ -6,7 +6,7 @@ */ import Boom from '@hapi/boom'; -import { has, isEmpty } from 'lodash'; +import { isEmpty } from 'lodash'; import { KibanaRequest } from '@kbn/core/server'; import { JsonObject } from '@kbn/utility-types'; import { KueryNode } from '@kbn/es-query'; @@ -217,7 +217,7 @@ export class AlertingAuthorization { producer: ruleType.producer, }); - const isAvailableConsumer = has(await this.allRegisteredConsumers, consumer); + const isAvailableConsumer = this.allRegisteredConsumers.has(consumer); if (authorization && this.shouldCheckAuthorization()) { const checkPrivileges = authorization.checkPrivilegesDynamicallyWithRequest(this.request); From a2b73f9750c888d8235bcc80a9319bd943d4ee80 Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Sat, 13 Jul 2024 18:10:20 +0300 Subject: [PATCH 011/106] Add tests and support filtering --- .../rule/methods/find/find_rules.ts | 2 +- .../alerting_authorization.test.ts | 3828 +++++++++++------ .../authorization/alerting_authorization.ts | 313 +- .../alerting_authorization_kuery.ts | 57 +- .../alerting/server/authorization/types.ts | 46 + .../lib/get_authorization_filter.ts | 2 +- .../server/search_strategy/search_strategy.ts | 4 +- 7 files changed, 2663 insertions(+), 1589 deletions(-) create mode 100644 x-pack/plugins/alerting/server/authorization/types.ts diff --git a/x-pack/plugins/alerting/server/application/rule/methods/find/find_rules.ts b/x-pack/plugins/alerting/server/application/rule/methods/find/find_rules.ts index 10aef42955e741..efd4c6fe10e74f 100644 --- a/x-pack/plugins/alerting/server/application/rule/methods/find/find_rules.ts +++ b/x-pack/plugins/alerting/server/application/rule/methods/find/find_rules.ts @@ -9,8 +9,8 @@ import Boom from '@hapi/boom'; import { isEmpty, pick } from 'lodash'; import { KueryNode, nodeBuilder } from '@kbn/es-query'; import { AlertConsumers } from '@kbn/rule-data-utils'; +import { AlertingAuthorizationEntity } from '../../../../authorization/types'; import { SanitizedRule, Rule as DeprecatedRule, RawRule } from '../../../../types'; -import { AlertingAuthorizationEntity } from '../../../../authorization'; import { ruleAuditEvent, RuleAuditAction } from '../../../../rules_client/common/audit_events'; import { mapSortField, diff --git a/x-pack/plugins/alerting/server/authorization/alerting_authorization.test.ts b/x-pack/plugins/alerting/server/authorization/alerting_authorization.test.ts index c5c543e413b55c..f44b40f647a6bc 100644 --- a/x-pack/plugins/alerting/server/authorization/alerting_authorization.test.ts +++ b/x-pack/plugins/alerting/server/authorization/alerting_authorization.test.ts @@ -5,27 +5,26 @@ * 2.0. */ -import { fromKueryExpression } from '@kbn/es-query'; +import { fromKueryExpression, KueryNode, toKqlExpression } from '@kbn/es-query'; import { KibanaRequest } from '@kbn/core/server'; import { ruleTypeRegistryMock } from '../rule_type_registry.mock'; import { securityMock } from '@kbn/security-plugin/server/mocks'; -import { - PluginStartContract as FeaturesStartContract, - KibanaFeature, -} from '@kbn/features-plugin/server'; +import { KibanaFeature } from '@kbn/features-plugin/server'; import { featuresPluginMock } from '@kbn/features-plugin/server/mocks'; -import { - AlertingAuthorization, - WriteOperations, - ReadOperations, - AlertingAuthorizationEntity, -} from './alerting_authorization'; +import { AlertingAuthorization } from './alerting_authorization'; import { RecoveredActionGroup } from '../../common'; import { NormalizedRuleType, RegistryRuleType } from '../rule_type_registry'; import { AlertingAuthorizationFilterType } from './alerting_authorization_kuery'; import { schema } from '@kbn/config-schema'; import { httpServerMock } from '@kbn/core-http-server-mocks'; -import { SecurityPluginStart } from '@kbn/security-plugin-types-server'; +import { + CheckPrivilegesDynamically, + CheckPrivilegesResponse, + SecurityPluginStart, +} from '@kbn/security-plugin-types-server'; +import type { PluginStartContract as FeaturesPluginStart } from '@kbn/features-plugin/server'; +import { WriteOperations, AlertingAuthorizationEntity, ReadOperations } from './types'; +import { SubFeature } from '@kbn/features-plugin/common'; const getSpace = jest.fn(); const getSpaceId = () => 'space1'; @@ -50,86 +49,10 @@ function mockSecurity() { return { authorization }; } -function mockFeatureWithSubFeature(appName: string, typeName: string[]) { - const alertingFeatures = typeName?.map((ruleTypeId) => ({ - ruleTypeId, - consumers: [appName], - })); - - return new KibanaFeature({ - id: appName, - name: appName, - app: [], - category: { id: 'foo', label: 'foo' }, - ...(alertingFeatures - ? { - alerting: alertingFeatures, - } - : {}), - privileges: { - all: { - savedObject: { - all: [], - read: [], - }, - ui: [], - }, - read: { - savedObject: { - all: [], - read: [], - }, - ui: [], - }, - }, - subFeatures: [ - { - name: appName, - privilegeGroups: [ - { - groupType: 'independent', - privileges: [ - { - id: 'doSomethingAlertRelated', - name: 'sub feature alert', - includeIn: 'all', - alerting: { - rule: { - all: alertingFeatures, - }, - }, - savedObject: { - all: [], - read: [], - }, - ui: ['doSomethingAlertRelated'], - }, - { - id: 'doSomethingAlertRelated', - name: 'sub feature alert', - includeIn: 'read', - alerting: { - rule: { - read: alertingFeatures, - }, - }, - savedObject: { - all: [], - read: [], - }, - ui: ['doSomethingAlertRelated'], - }, - ], - }, - ], - }, - ], - }); -} - function mockFeatureWithConsumers( appName: string, - alertingFeatures?: ReadonlyArray<{ ruleTypeId: string; consumers: readonly string[] }> + alertingFeatures?: ReadonlyArray<{ ruleTypeId: string; consumers: readonly string[] }>, + subFeature?: boolean ) { return new KibanaFeature({ id: appName, @@ -181,6 +104,52 @@ function mockFeatureWithConsumers( ui: [], }, }, + ...(subFeature + ? { + subFeatures: [ + { + name: appName, + privilegeGroups: [ + { + groupType: 'independent', + privileges: [ + { + id: 'doSomethingAlertRelated', + name: 'sub feature alert', + includeIn: 'all', + alerting: { + rule: { + all: alertingFeatures, + }, + }, + savedObject: { + all: [], + read: [], + }, + ui: ['doSomethingAlertRelated'], + }, + { + id: 'doSomethingAlertRelated', + name: 'sub feature alert', + includeIn: 'read', + alerting: { + rule: { + read: alertingFeatures, + }, + }, + savedObject: { + all: [], + read: [], + }, + ui: ['doSomethingAlertRelated'], + }, + ], + }, + ], + }, + ], + } + : {}), }); } @@ -192,15 +161,19 @@ const myOtherAppFeature = mockFeatureWithConsumers('myOtherApp', [ { ruleTypeId: 'myType', consumers: ['myOtherApp'] }, ]); -const myAppWithSubFeature = mockFeatureWithSubFeature('myAppWithSubFeature', ['myType']); +const myAppWithSubFeature = mockFeatureWithConsumers( + 'myAppWithSubFeature', + [{ ruleTypeId: 'myType', consumers: ['myAppWithSubFeature'] }], + true +); + const myFeatureWithoutAlerting = mockFeatureWithConsumers('myOtherApp'); describe('AlertingAuthorization', () => { - const ruleTypeRegistry = ruleTypeRegistryMock.create(); - const features: jest.Mocked = featuresPluginMock.createStart(); const allRegisteredConsumers = new Set(); const ruleTypesConsumersMap = new Map>(); let request: KibanaRequest; + let ruleTypeRegistry = ruleTypeRegistryMock.create(); beforeEach(() => { jest.clearAllMocks(); @@ -225,12 +198,6 @@ describe('AlertingAuthorization', () => { validLegacyConsumers: [], })); - features.getKibanaFeatures.mockReturnValue([ - myAppFeature, - myOtherAppFeature, - myAppWithSubFeature, - myFeatureWithoutAlerting, - ]); getSpace.mockResolvedValue(undefined); allRegisteredConsumers.clear(); @@ -239,11 +206,15 @@ describe('AlertingAuthorization', () => { describe('create', () => { let securityStart: jest.Mocked; + let features: jest.Mocked; beforeEach(() => { jest.clearAllMocks(); securityStart = securityMock.createStart(); + features = featuresPluginMock.createStart(); + getSpace.mockReturnValue({ id: 'default', name: 'Default', disabledFeatures: [] }); + features.getKibanaFeatures.mockReturnValue([mockFeatureWithConsumers('my-feature-1')]); }); it('creates an AlertingAuthorization object', async () => { @@ -424,9 +395,19 @@ describe('AlertingAuthorization', () => { }); describe('ensureAuthorized', () => { + const checkPrivileges = jest.fn(async () => ({ hasAllRequested: true })); + let securityStart: ReturnType; + beforeEach(() => { + jest.clearAllMocks(); allRegisteredConsumers.clear(); allRegisteredConsumers.add('myApp'); + securityStart = securityMock.createStart(); + securityStart.authz.mode.useRbacForRequest.mockReturnValue(true); + securityStart.authz.checkPrivilegesDynamicallyWithRequest.mockReturnValue(checkPrivileges); + + const alertingGet = securityStart.authz.actions.alerting.get as jest.Mock; + alertingGet.mockImplementation(mockAuthorizationAction); }); it('is a no-op when there is no authorization api', async () => { @@ -445,17 +426,16 @@ describe('AlertingAuthorization', () => { entity: AlertingAuthorizationEntity.Rule, }); - expect(ruleTypeRegistry.get).toHaveBeenCalledTimes(1); + expect(checkPrivileges).not.toHaveBeenCalled(); }); it('is a no-op when the security license is disabled', async () => { - const { authorization } = mockSecurity(); - authorization.mode.useRbacForRequest.mockReturnValue(false); + securityStart.authz.mode.useRbacForRequest.mockReturnValue(false); const alertAuthorization = new AlertingAuthorization({ request, ruleTypeRegistry, - authorization, + authorization: securityStart.authz, getSpaceId, allRegisteredConsumers, ruleTypesConsumersMap, @@ -468,30 +448,19 @@ describe('AlertingAuthorization', () => { entity: AlertingAuthorizationEntity.Rule, }); - expect(ruleTypeRegistry.get).toHaveBeenCalledTimes(1); + expect(checkPrivileges).not.toHaveBeenCalled(); }); - it('ensures the user has privileges to execute rules for the specified rule type and operation without consumer when producer and consumer are the same', async () => { - const { authorization } = mockSecurity(); - const checkPrivileges: jest.MockedFunction< - ReturnType - > = jest.fn(); - authorization.checkPrivilegesDynamicallyWithRequest.mockReturnValue(checkPrivileges); + it('authorized correctly', async () => { const alertAuthorization = new AlertingAuthorization({ request, ruleTypeRegistry, - authorization, + authorization: securityStart.authz, getSpaceId, allRegisteredConsumers, ruleTypesConsumersMap, }); - checkPrivileges.mockResolvedValueOnce({ - username: 'some-user', - hasAllRequested: true, - privileges: { kibana: [] }, - }); - await alertAuthorization.ensureAuthorized({ ruleTypeId: 'myType', consumer: 'myApp', @@ -499,248 +468,179 @@ describe('AlertingAuthorization', () => { entity: AlertingAuthorizationEntity.Rule, }); - expect(ruleTypeRegistry.get).toHaveBeenCalledWith('myType'); + expect(checkPrivileges).toBeCalledTimes(1); + expect(checkPrivileges.mock.calls[0]).toMatchInlineSnapshot(` + Array [ + Object { + "kibana": Array [ + "myType/myApp/rule/create", + ], + }, + ] + `); + }); - expect(authorization.actions.alerting.get).toHaveBeenCalledTimes(1); - expect(authorization.actions.alerting.get).toHaveBeenCalledWith( - 'myType', - 'myApp', - 'rule', - 'create' + it('throws if user lacks the required rule privileges for the consumer', async () => { + securityStart.authz.checkPrivilegesDynamicallyWithRequest.mockReturnValue( + jest.fn(async () => ({ hasAllRequested: false })) ); - expect(checkPrivileges).toHaveBeenCalledWith({ - kibana: [mockAuthorizationAction('myType', 'myApp', 'rule', 'create')], - }); - }); - it('ensures the user has privileges to execute alerts for the specified rule type and operation without consumer when producer and consumer are the same', async () => { - const { authorization } = mockSecurity(); - const checkPrivileges: jest.MockedFunction< - ReturnType - > = jest.fn(); - authorization.checkPrivilegesDynamicallyWithRequest.mockReturnValue(checkPrivileges); const alertAuthorization = new AlertingAuthorization({ request, ruleTypeRegistry, - authorization, + authorization: securityStart.authz, getSpaceId, allRegisteredConsumers, ruleTypesConsumersMap, }); - checkPrivileges.mockResolvedValueOnce({ - username: 'some-user', - hasAllRequested: true, - privileges: { kibana: [] }, - }); - - await alertAuthorization.ensureAuthorized({ - ruleTypeId: 'myType', - consumer: 'myApp', - operation: WriteOperations.Update, - entity: AlertingAuthorizationEntity.Alert, - }); - - expect(ruleTypeRegistry.get).toHaveBeenCalledWith('myType'); - - expect(authorization.actions.alerting.get).toHaveBeenCalledTimes(1); - expect(authorization.actions.alerting.get).toHaveBeenCalledWith( - 'myType', - 'myApp', - 'alert', - 'update' + await expect( + alertAuthorization.ensureAuthorized({ + ruleTypeId: 'myType', + consumer: 'myApp', + operation: WriteOperations.Create, + entity: AlertingAuthorizationEntity.Rule, + }) + ).rejects.toThrowErrorMatchingInlineSnapshot( + `"Unauthorized by \\"myApp\\" to create \\"myType\\" rule"` ); - expect(checkPrivileges).toHaveBeenCalledWith({ - kibana: [mockAuthorizationAction('myType', 'myApp', 'alert', 'update')], - }); }); - it('ensures the user has privileges to execute rules for the specified rule type and operation without consumer when consumer is alerts', async () => { - const { authorization } = mockSecurity(); - const checkPrivileges: jest.MockedFunction< - ReturnType - > = jest.fn(); - authorization.checkPrivilegesDynamicallyWithRequest.mockReturnValue(checkPrivileges); + it('throws if user lacks the required alert privileges for the consumer', async () => { + securityStart.authz.checkPrivilegesDynamicallyWithRequest.mockReturnValue( + jest.fn(async () => ({ hasAllRequested: false })) + ); + const alertAuthorization = new AlertingAuthorization({ request, ruleTypeRegistry, - authorization, + authorization: securityStart.authz, getSpaceId, allRegisteredConsumers, ruleTypesConsumersMap, }); - checkPrivileges.mockResolvedValueOnce({ - username: 'some-user', - hasAllRequested: true, - privileges: { kibana: [] }, - }); - - await alertAuthorization.ensureAuthorized({ - ruleTypeId: 'myType', - consumer: 'alerts', - operation: WriteOperations.Create, - entity: AlertingAuthorizationEntity.Rule, - }); - - expect(ruleTypeRegistry.get).toHaveBeenCalledWith('myType'); - - expect(authorization.actions.alerting.get).toHaveBeenCalledTimes(1); - expect(authorization.actions.alerting.get).toHaveBeenCalledWith( - 'myType', - 'myApp', - 'rule', - 'create' + await expect( + alertAuthorization.ensureAuthorized({ + ruleTypeId: 'myType', + consumer: 'myApp', + operation: WriteOperations.Update, + entity: AlertingAuthorizationEntity.Alert, + }) + ).rejects.toThrowErrorMatchingInlineSnapshot( + `"Unauthorized by \\"myApp\\" to update \\"myType\\" alert"` ); - expect(checkPrivileges).toHaveBeenCalledWith({ - kibana: [mockAuthorizationAction('myType', 'myApp', 'rule', 'create')], - }); }); - it('ensures the user has privileges to execute alerts for the specified rule type and operation without consumer when consumer is alerts', async () => { - const { authorization } = mockSecurity(); - const checkPrivileges: jest.MockedFunction< - ReturnType - > = jest.fn(); - authorization.checkPrivilegesDynamicallyWithRequest.mockReturnValue(checkPrivileges); + it('throws if the user has access but the consumer is not registered', async () => { const alertAuthorization = new AlertingAuthorization({ request, ruleTypeRegistry, - authorization, + authorization: securityStart.authz, getSpaceId, allRegisteredConsumers, ruleTypesConsumersMap, }); - checkPrivileges.mockResolvedValueOnce({ - username: 'some-user', - hasAllRequested: true, - privileges: { kibana: [] }, - }); - - await alertAuthorization.ensureAuthorized({ - ruleTypeId: 'myType', - consumer: 'alerts', - operation: WriteOperations.Update, - entity: AlertingAuthorizationEntity.Alert, - }); - - expect(ruleTypeRegistry.get).toHaveBeenCalledWith('myType'); - - expect(authorization.actions.alerting.get).toHaveBeenCalledTimes(1); - expect(authorization.actions.alerting.get).toHaveBeenCalledWith( - 'myType', - 'myApp', - 'alert', - 'update' + await expect( + alertAuthorization.ensureAuthorized({ + ruleTypeId: 'myType', + consumer: 'not-exist', + operation: WriteOperations.Create, + entity: AlertingAuthorizationEntity.Rule, + }) + ).rejects.toThrowErrorMatchingInlineSnapshot( + `"Unauthorized by \\"not-exist\\" to create \\"myType\\" rule"` ); - expect(checkPrivileges).toHaveBeenCalledWith({ - kibana: [mockAuthorizationAction('myType', 'myApp', 'alert', 'update')], - }); }); - it('ensures the user has privileges to execute rules for the specified rule type, operation and producer when producer is different from consumer', async () => { - const { authorization } = mockSecurity(); - const checkPrivileges: jest.MockedFunction< - ReturnType - > = jest.fn(); - authorization.checkPrivilegesDynamicallyWithRequest.mockReturnValue(checkPrivileges); - checkPrivileges.mockResolvedValueOnce({ - username: 'some-user', - hasAllRequested: true, - privileges: { kibana: [] }, - }); - allRegisteredConsumers.add('myOtherApp'); - + it('throws when there is no authorization api but the consumer is not registered', async () => { const alertAuthorization = new AlertingAuthorization({ request, ruleTypeRegistry, - authorization, getSpaceId, allRegisteredConsumers, ruleTypesConsumersMap, }); - await alertAuthorization.ensureAuthorized({ - ruleTypeId: 'myType', - consumer: 'myOtherApp', - operation: WriteOperations.Create, - entity: AlertingAuthorizationEntity.Rule, - }); - - expect(ruleTypeRegistry.get).toHaveBeenCalledWith('myType'); - - expect(authorization.actions.alerting.get).toHaveBeenCalledTimes(1); - expect(authorization.actions.alerting.get).toHaveBeenCalledWith( - 'myType', - 'myOtherApp', - 'rule', - 'create' + await expect( + alertAuthorization.ensureAuthorized({ + ruleTypeId: 'myType', + consumer: 'not-exist', + operation: WriteOperations.Create, + entity: AlertingAuthorizationEntity.Rule, + }) + ).rejects.toThrowErrorMatchingInlineSnapshot( + `"Unauthorized by \\"not-exist\\" to create \\"myType\\" rule"` ); - expect(checkPrivileges).toHaveBeenCalledWith({ - kibana: [mockAuthorizationAction('myType', 'myOtherApp', 'rule', 'create')], - }); }); - it('ensures the user has privileges to execute alerts for the specified rule type, operation and producer when producer is different from consumer', async () => { - const { authorization } = mockSecurity(); - const checkPrivileges: jest.MockedFunction< - ReturnType - > = jest.fn(); - authorization.checkPrivilegesDynamicallyWithRequest.mockReturnValue(checkPrivileges); - checkPrivileges.mockResolvedValueOnce({ - username: 'some-user', - hasAllRequested: true, - privileges: { kibana: [] }, - }); - allRegisteredConsumers.add('myOtherApp'); + it('throws when the security license is disabled but the consumer is not registered', async () => { + securityStart.authz.mode.useRbacForRequest.mockReturnValue(false); const alertAuthorization = new AlertingAuthorization({ request, ruleTypeRegistry, - authorization, getSpaceId, allRegisteredConsumers, ruleTypesConsumersMap, }); - await alertAuthorization.ensureAuthorized({ - ruleTypeId: 'myType', - consumer: 'myOtherApp', - operation: WriteOperations.Update, - entity: AlertingAuthorizationEntity.Alert, - }); + await expect( + alertAuthorization.ensureAuthorized({ + ruleTypeId: 'myType', + consumer: 'not-exist', + operation: WriteOperations.Create, + entity: AlertingAuthorizationEntity.Rule, + }) + ).rejects.toThrowErrorMatchingInlineSnapshot( + `"Unauthorized by \\"not-exist\\" to create \\"myType\\" rule"` + ); + }); - expect(ruleTypeRegistry.get).toHaveBeenCalledWith('myType'); + it('throws an error when the consumer does not exist because it was from a disabled plugin', async () => { + const features = featuresPluginMock.createStart(); + features.getKibanaFeatures.mockReturnValue([ + mockFeatureWithConsumers('my-feature-1', [ + { ruleTypeId: 'rule-type-1', consumers: ['disabled-feature-consumer'] }, + ]), + mockFeatureWithConsumers('my-feature-2', [ + { ruleTypeId: 'rule-type-2', consumers: ['enabled-feature-consumer'] }, + ]), + ]); - expect(authorization.actions.alerting.get).toHaveBeenCalledTimes(1); - expect(authorization.actions.alerting.get).toHaveBeenCalledWith( - 'myType', - 'myOtherApp', - 'alert', - 'update' - ); - expect(checkPrivileges).toHaveBeenCalledWith({ - kibana: [mockAuthorizationAction('myType', 'myOtherApp', 'alert', 'update')], + getSpace.mockReturnValue({ + id: 'default', + name: 'Default', + disabledFeatures: ['my-feature-1'], }); - }); - it('ensures the producer is used for authorization if the consumer is `alerts`', async () => { - const { authorization } = mockSecurity(); - const checkPrivileges: jest.MockedFunction< - ReturnType - > = jest.fn(); - authorization.checkPrivilegesDynamicallyWithRequest.mockReturnValue(checkPrivileges); - checkPrivileges.mockResolvedValueOnce({ - username: 'some-user', - hasAllRequested: true, - privileges: { kibana: [] }, + const auth = await AlertingAuthorization.create({ + request, + ruleTypeRegistry, + getSpaceId, + features, + getSpace, + authorization: securityStart.authz, }); + await expect( + auth.ensureAuthorized({ + ruleTypeId: 'rule-type-1', + consumer: 'disabled-feature-consumer', + operation: WriteOperations.Create, + entity: AlertingAuthorizationEntity.Rule, + }) + ).rejects.toThrowErrorMatchingInlineSnapshot( + `"Unauthorized by \\"disabled-feature-consumer\\" to create \\"rule-type-1\\" rule"` + ); + }); + + it('checks additional privileges correctly', async () => { const alertAuthorization = new AlertingAuthorization({ request, ruleTypeRegistry, - authorization, + authorization: securityStart.authz, getSpaceId, allRegisteredConsumers, ruleTypesConsumersMap, @@ -748,175 +648,270 @@ describe('AlertingAuthorization', () => { await alertAuthorization.ensureAuthorized({ ruleTypeId: 'myType', - consumer: 'alerts', + consumer: 'myApp', operation: WriteOperations.Create, entity: AlertingAuthorizationEntity.Rule, + additionalPrivileges: ['test/create'], }); - expect(ruleTypeRegistry.get).toHaveBeenCalledWith('myType'); - - expect(authorization.actions.alerting.get).toHaveBeenCalledTimes(1); - expect(authorization.actions.alerting.get).toHaveBeenCalledWith( - 'myType', - 'myApp', - 'rule', - 'create' - ); - expect(checkPrivileges).toHaveBeenCalledWith({ - kibana: [mockAuthorizationAction('myType', 'myApp', 'rule', 'create')], - }); + expect(checkPrivileges).toBeCalledTimes(1); + expect(checkPrivileges.mock.calls[0]).toMatchInlineSnapshot(` + Array [ + Object { + "kibana": Array [ + "myType/myApp/rule/create", + "test/create", + ], + }, + ] + `); }); + }); - it('throws if user lacks the required rule privileges for the consumer', async () => { - const { authorization } = mockSecurity(); - const checkPrivileges: jest.MockedFunction< - ReturnType - > = jest.fn(); - authorization.checkPrivilegesDynamicallyWithRequest.mockReturnValue(checkPrivileges); - const alertAuthorization = new AlertingAuthorization({ - request, - ruleTypeRegistry, - authorization, + describe('getFindAuthorizationFilter', () => { + type CheckPrivilegesResponseWithoutES = Omit & { + privileges: Omit; + }; + + const checkPrivileges = jest.fn, []>(async () => ({ + username: 'elastic', + hasAllRequested: true, + privileges: { kibana: [] }, + })); + + const ruleTypeIds = ['rule-type-id-1', 'rule-type-id-2', 'rule-type-id-3', 'rule-type-id-4']; + + let securityStart: ReturnType; + let features: jest.Mocked; + + beforeEach(() => { + jest.clearAllMocks(); + allRegisteredConsumers.clear(); + securityStart = securityMock.createStart(); + securityStart.authz.mode.useRbacForRequest.mockReturnValue(true); + securityStart.authz.checkPrivilegesDynamicallyWithRequest.mockReturnValue(checkPrivileges); + + features = featuresPluginMock.createStart(); + + const alertingGet = securityStart.authz.actions.alerting.get as jest.Mock; + alertingGet.mockImplementation(mockAuthorizationAction); + + ruleTypeRegistry = ruleTypeRegistryMock.create(); + ruleTypeRegistry.getAllTypes.mockReturnValue(ruleTypeIds); + ruleTypeRegistry.has.mockImplementation((ruleTypeId: string) => + ruleTypeIds.includes(ruleTypeId) + ); + + // @ts-expect-error: only the id is needed for the tests + ruleTypeRegistry.get.mockImplementation((ruleTypeId: string) => ({ id: ruleTypeId })); + }); + + it('omits filter when there is no authorization api', async () => { + const alertAuthorization = new AlertingAuthorization({ + request, + ruleTypeRegistry, getSpaceId, allRegisteredConsumers, ruleTypesConsumersMap, }); - checkPrivileges.mockResolvedValueOnce({ - username: 'some-user', - hasAllRequested: false, - privileges: { - kibana: [ - { - privilege: mockAuthorizationAction('myType', 'myOtherApp', 'rule', 'create'), - authorized: false, - }, - { - privilege: mockAuthorizationAction('myType', 'myApp', 'rule', 'create'), - authorized: true, - }, - ], - }, - }); + const { filter, ensureRuleTypeIsAuthorized } = + await alertAuthorization.getFindAuthorizationFilter(AlertingAuthorizationEntity.Rule, { + type: AlertingAuthorizationFilterType.KQL, + fieldNames: { + ruleTypeId: 'ruleId', + consumer: 'consumer', + }, + }); - await expect( - alertAuthorization.ensureAuthorized({ - ruleTypeId: 'myType', - consumer: 'myOtherApp', - operation: WriteOperations.Create, - entity: AlertingAuthorizationEntity.Rule, - }) - ).rejects.toThrowErrorMatchingInlineSnapshot( - `"Unauthorized by \\"myOtherApp\\" to create \\"myType\\" rule"` - ); + expect(() => ensureRuleTypeIsAuthorized('someMadeUpType', 'myApp', 'rule')).not.toThrow(); + expect(filter).toEqual(undefined); }); - it('throws if user lacks the required alert privileges for the consumer', async () => { - const { authorization } = mockSecurity(); - const checkPrivileges: jest.MockedFunction< - ReturnType - > = jest.fn(); - authorization.checkPrivilegesDynamicallyWithRequest.mockReturnValue(checkPrivileges); + it('ensureRuleTypeIsAuthorized is no-op when there is no authorization api', async () => { const alertAuthorization = new AlertingAuthorization({ request, ruleTypeRegistry, - authorization, getSpaceId, allRegisteredConsumers, ruleTypesConsumersMap, }); + const { ensureRuleTypeIsAuthorized } = await alertAuthorization.getFindAuthorizationFilter( + AlertingAuthorizationEntity.Rule, + { + type: AlertingAuthorizationFilterType.KQL, + fieldNames: { + ruleTypeId: 'ruleId', + consumer: 'consumer', + }, + } + ); + + expect(() => ensureRuleTypeIsAuthorized('someMadeUpType', 'myApp', 'rule')).not.toThrow(); + }); + + it('creates a filter based on the privileged types', async () => { + features.getKibanaFeatures.mockReturnValue([ + mockFeatureWithConsumers('feature-id-1', [ + { + ruleTypeId: 'rule-type-id-1', + consumers: ['alerts', 'consumer-a'], + }, + { ruleTypeId: 'rule-type-id-2', consumers: ['alerts', 'consumer-b'] }, + ]), + mockFeatureWithConsumers('feature-id-2', [ + { + ruleTypeId: 'rule-type-id-1', + consumers: ['alerts', 'consumer-b'], + }, + { + ruleTypeId: 'rule-type-id-3', + consumers: ['alerts', 'consumer-c'], + }, + ]), + mockFeatureWithConsumers('feature-id-3', [ + { + ruleTypeId: 'rule-type-id-4', + consumers: ['consumer-d'], + }, + ]), + ]); + + const auth = await AlertingAuthorization.create({ + request, + ruleTypeRegistry, + getSpaceId, + features, + getSpace, + authorization: securityStart.authz, + }); + checkPrivileges.mockResolvedValueOnce({ username: 'some-user', - hasAllRequested: false, + hasAllRequested: true, privileges: { kibana: [ { - privilege: mockAuthorizationAction('myType', 'myOtherApp', 'alert', 'update'), - authorized: false, + privilege: mockAuthorizationAction('rule-type-id-1', 'alerts', 'rule', 'find'), + authorized: true, + }, + { + privilege: mockAuthorizationAction('rule-type-id-1', 'consumer-a', 'rule', 'find'), + authorized: true, + }, + { + privilege: mockAuthorizationAction('rule-type-id-1', 'consumer-b', 'rule', 'find'), + authorized: true, + }, + { + privilege: mockAuthorizationAction('rule-type-id-2', 'alerts', 'rule', 'find'), + authorized: true, + }, + { + privilege: mockAuthorizationAction('rule-type-id-2', 'consumer-b', 'rule', 'find'), + authorized: true, + }, + { + privilege: mockAuthorizationAction('rule-type-id-3', 'consumer-c', 'rule', 'find'), + authorized: true, }, { - privilege: mockAuthorizationAction('myType', 'myApp', 'alert', 'update'), + privilege: mockAuthorizationAction('rule-type-id-3', 'alerts', 'rule', 'find'), authorized: true, }, { - privilege: mockAuthorizationAction('myType', 'myAppRulesOnly', 'alert', 'update'), + privilege: mockAuthorizationAction('rule-type-id-3', 'consumer-d', 'rule', 'find'), authorized: false, }, ], }, }); - await expect( - alertAuthorization.ensureAuthorized({ - ruleTypeId: 'myType', - consumer: 'myAppRulesOnly', - operation: WriteOperations.Update, - entity: AlertingAuthorizationEntity.Alert, + const filter = ( + await auth.getFindAuthorizationFilter(AlertingAuthorizationEntity.Rule, { + type: AlertingAuthorizationFilterType.KQL, + fieldNames: { + ruleTypeId: 'path.to.rule_type_id', + consumer: 'consumer-field', + }, }) - ).rejects.toThrowErrorMatchingInlineSnapshot( - `"Unauthorized by \\"myAppRulesOnly\\" to update \\"myType\\" alert"` + ).filter; + + expect(checkPrivileges).toBeCalledTimes(1); + expect(checkPrivileges.mock.calls[0]).toMatchInlineSnapshot(` + Array [ + Object { + "kibana": Array [ + "rule-type-id-1/alerts/rule/find", + "rule-type-id-1/consumer-a/rule/find", + "rule-type-id-1/consumer-b/rule/find", + "rule-type-id-2/alerts/rule/find", + "rule-type-id-2/consumer-b/rule/find", + "rule-type-id-3/alerts/rule/find", + "rule-type-id-3/consumer-c/rule/find", + "rule-type-id-4/consumer-d/rule/find", + ], + }, + ] + `); + + expect(toKqlExpression(filter as KueryNode)).toMatchInlineSnapshot( + `"((path.to.rule_type_id: rule-type-id-1 AND (consumer-field: alerts OR consumer-field: consumer-a OR consumer-field: consumer-b)) OR (path.to.rule_type_id: rule-type-id-2 AND (consumer-field: alerts OR consumer-field: consumer-b)) OR (path.to.rule_type_id: rule-type-id-3 AND (consumer-field: consumer-c OR consumer-field: alerts)))"` ); }); - it('throws if user lacks the required privileges for the producer', async () => { - const { authorization } = mockSecurity(); - const checkPrivileges: jest.MockedFunction< - ReturnType - > = jest.fn(); - authorization.checkPrivilegesDynamicallyWithRequest.mockReturnValue(checkPrivileges); - const alertAuthorization = new AlertingAuthorization({ - request, - ruleTypeRegistry, - authorization, - getSpaceId, - allRegisteredConsumers, - ruleTypesConsumersMap, - }); - + it('throws if user has no privileges to any rule type', async () => { checkPrivileges.mockResolvedValueOnce({ username: 'some-user', hasAllRequested: false, privileges: { kibana: [ { - privilege: mockAuthorizationAction('myType', 'myOtherApp', 'alert', 'update'), - authorized: true, + privilege: mockAuthorizationAction('myType', 'myOtherApp', 'rule', 'create'), + authorized: false, }, { - privilege: mockAuthorizationAction('myType', 'myApp', 'alert', 'update'), + privilege: mockAuthorizationAction('myType', 'myApp', 'rule', 'create'), authorized: false, }, ], }, }); + const auth = await AlertingAuthorization.create({ + request, + ruleTypeRegistry, + getSpaceId, + features, + getSpace, + authorization: securityStart.authz, + }); + await expect( - alertAuthorization.ensureAuthorized({ - ruleTypeId: 'myType', - consumer: 'myOtherApp', - operation: WriteOperations.Update, - entity: AlertingAuthorizationEntity.Alert, + auth.getFindAuthorizationFilter(AlertingAuthorizationEntity.Rule, { + type: AlertingAuthorizationFilterType.KQL, + fieldNames: { + ruleTypeId: 'path.to.rule_type_id', + consumer: 'consumer-field', + }, }) ).rejects.toThrowErrorMatchingInlineSnapshot( - `"Unauthorized by \\"myOtherApp\\" to update \\"myType\\" alert"` + `"Unauthorized to find rules for any rule types"` ); }); - it('throws if user lacks the required privileges for both consumer and producer', async () => { - const { authorization } = mockSecurity(); - const checkPrivileges: jest.MockedFunction< - ReturnType - > = jest.fn(); - authorization.checkPrivilegesDynamicallyWithRequest.mockReturnValue(checkPrivileges); - const alertAuthorization = new AlertingAuthorization({ - request, - ruleTypeRegistry, - authorization, - getSpaceId, - allRegisteredConsumers, - ruleTypesConsumersMap, - }); + it('creates an `ensureRuleTypeIsAuthorized` function which throws if type is unauthorized', async () => { + features.getKibanaFeatures.mockReturnValue([ + mockFeatureWithConsumers('myApp', [ + { ruleTypeId: 'myOtherAppAlertType', consumers: ['myApp'] }, + { ruleTypeId: 'myAppAlertType', consumers: ['myApp'] }, + ]), + mockFeatureWithConsumers('myOtherApp', [ + { ruleTypeId: 'myOtherAppAlertType', consumers: ['myOtherApp'] }, + { ruleTypeId: 'myAppAlertType', consumers: ['myOtherApp'] }, + ]), + ]); checkPrivileges.mockResolvedValueOnce({ username: 'some-user', @@ -924,212 +919,73 @@ describe('AlertingAuthorization', () => { privileges: { kibana: [ { - privilege: mockAuthorizationAction('myType', 'myOtherApp', 'alert', 'create'), + privilege: mockAuthorizationAction('myOtherAppAlertType', 'myApp', 'alert', 'find'), + authorized: true, + }, + { + privilege: mockAuthorizationAction( + 'myOtherAppAlertType', + 'myOtherApp', + 'alert', + 'find' + ), authorized: false, }, { - privilege: mockAuthorizationAction('myType', 'myApp', 'alert', 'create'), + privilege: mockAuthorizationAction('myAppAlertType', 'myApp', 'alert', 'find'), + authorized: true, + }, + { + privilege: mockAuthorizationAction('myAppAlertType', 'myOtherApp', 'alert', 'find'), authorized: false, }, ], }, }); - await expect( - alertAuthorization.ensureAuthorized({ - ruleTypeId: 'myType', - consumer: 'myOtherApp', - operation: WriteOperations.Create, - entity: AlertingAuthorizationEntity.Alert, - }) - ).rejects.toThrowErrorMatchingInlineSnapshot( - `"Unauthorized by \\"myOtherApp\\" to create \\"myType\\" alert"` - ); - }); - - it('checks additional privileges correctly', async () => { - const { authorization } = mockSecurity(); - const checkPrivileges: jest.MockedFunction< - ReturnType - > = jest.fn(); - authorization.checkPrivilegesDynamicallyWithRequest.mockReturnValue(checkPrivileges); - const alertAuthorization = new AlertingAuthorization({ + const auth = await AlertingAuthorization.create({ request, ruleTypeRegistry, - authorization, getSpaceId, - allRegisteredConsumers, - ruleTypesConsumersMap, - }); - - checkPrivileges.mockResolvedValueOnce({ - username: 'some-user', - hasAllRequested: true, - privileges: { kibana: [] }, + features, + getSpace, + authorization: securityStart.authz, }); - await alertAuthorization.ensureAuthorized({ - ruleTypeId: 'myType', - consumer: 'myApp', - operation: WriteOperations.Create, - entity: AlertingAuthorizationEntity.Rule, - additionalPrivileges: ['test/create'], - }); + const { ensureRuleTypeIsAuthorized } = await auth.getFindAuthorizationFilter( + AlertingAuthorizationEntity.Alert, + { + type: AlertingAuthorizationFilterType.KQL, + fieldNames: { + ruleTypeId: 'ruleId', + consumer: 'consumer', + }, + } + ); - expect(ruleTypeRegistry.get).toHaveBeenCalledWith('myType'); - - expect(authorization.actions.alerting.get).toHaveBeenCalledTimes(1); - expect(authorization.actions.alerting.get).toHaveBeenCalledWith( - 'myType', - 'myApp', - 'rule', - 'create' - ); - expect(checkPrivileges).toHaveBeenCalledWith({ - kibana: [mockAuthorizationAction('myType', 'myApp', 'rule', 'create'), 'test/create'], - }); - }); - }); - - describe('getFindAuthorizationFilter', () => { - const myOtherAppAlertType: RegistryRuleType = { - actionGroups: [], - actionVariables: undefined, - defaultActionGroupId: 'default', - minimumLicenseRequired: 'basic', - isExportable: true, - recoveryActionGroup: RecoveredActionGroup, - id: 'myOtherAppAlertType', - name: 'myOtherAppAlertType', - category: 'test', - producer: 'alerts', - enabledInLicense: true, - hasAlertsMappings: false, - hasFieldsForAAD: false, - validLegacyConsumers: [], - }; - const myAppAlertType: RegistryRuleType = { - actionGroups: [], - actionVariables: undefined, - defaultActionGroupId: 'default', - minimumLicenseRequired: 'basic', - isExportable: true, - recoveryActionGroup: RecoveredActionGroup, - id: 'myAppAlertType', - name: 'myAppAlertType', - category: 'test', - producer: 'myApp', - enabledInLicense: true, - hasAlertsMappings: false, - hasFieldsForAAD: false, - validLegacyConsumers: [], - }; - const mySecondAppAlertType: RegistryRuleType = { - actionGroups: [], - actionVariables: undefined, - defaultActionGroupId: 'default', - minimumLicenseRequired: 'basic', - isExportable: true, - recoveryActionGroup: RecoveredActionGroup, - id: 'mySecondAppAlertType', - name: 'mySecondAppAlertType', - category: 'test', - producer: 'myApp', - enabledInLicense: true, - hasAlertsMappings: false, - hasFieldsForAAD: false, - validLegacyConsumers: [], - }; - const setOfAlertTypes = new Set([myAppAlertType, myOtherAppAlertType, mySecondAppAlertType]); - it('omits filter when there is no authorization api', async () => { - const alertAuthorization = new AlertingAuthorization({ - request, - ruleTypeRegistry, - getSpaceId, - allRegisteredConsumers, - ruleTypesConsumersMap, - }); - const { filter, ensureRuleTypeIsAuthorized } = - await alertAuthorization.getFindAuthorizationFilter(AlertingAuthorizationEntity.Rule, { - type: AlertingAuthorizationFilterType.KQL, - fieldNames: { - ruleTypeId: 'ruleId', - consumer: 'consumer', - }, - }); - expect(() => ensureRuleTypeIsAuthorized('someMadeUpType', 'myApp', 'rule')).not.toThrow(); - expect(filter).toEqual(undefined); - }); - it('ensureRuleTypeIsAuthorized is no-op when there is no authorization api', async () => { - const alertAuthorization = new AlertingAuthorization({ - request, - ruleTypeRegistry, - getSpaceId, - allRegisteredConsumers, - ruleTypesConsumersMap, - }); - const { ensureRuleTypeIsAuthorized } = await alertAuthorization.getFindAuthorizationFilter( - AlertingAuthorizationEntity.Rule, - { - type: AlertingAuthorizationFilterType.KQL, - fieldNames: { - ruleTypeId: 'ruleId', - consumer: 'consumer', - }, - } + expect(() => { + ensureRuleTypeIsAuthorized('myAppAlertType', 'myOtherApp', 'alert'); + }).toThrowErrorMatchingInlineSnapshot( + `"Unauthorized by \\"myOtherApp\\" to find \\"myAppAlertType\\" alert"` ); - ensureRuleTypeIsAuthorized('someMadeUpType', 'myApp', 'rule'); }); - it('creates a filter based on the privileged types', async () => { + it('creates an `ensureRuleTypeIsAuthorized` function which is no-op if type is authorized', async () => { features.getKibanaFeatures.mockReturnValue([ mockFeatureWithConsumers('myApp', [ + { ruleTypeId: 'myOtherAppAlertType', consumers: ['myApp'] }, { ruleTypeId: 'myAppAlertType', consumers: ['myApp'] }, - { ruleTypeId: 'mySecondAppAlertType', consumers: ['myApp'] }, ]), - - mockFeatureWithConsumers('alerts', [ - { ruleTypeId: 'myOtherAppAlertType', consumers: ['alerts'] }, + mockFeatureWithConsumers('myOtherApp', [ + { ruleTypeId: 'myOtherApp', consumers: ['myOtherApp'] }, ]), - - myOtherAppFeature, - myAppWithSubFeature, ]); - const { authorization } = mockSecurity(); - const checkPrivileges: jest.MockedFunction< - ReturnType - > = jest.fn(); - authorization.checkPrivilegesDynamicallyWithRequest.mockReturnValue(checkPrivileges); + checkPrivileges.mockResolvedValueOnce({ username: 'some-user', - hasAllRequested: true, + hasAllRequested: false, privileges: { kibana: [ - { - privilege: mockAuthorizationAction('myAppAlertType', 'alerts', 'rule', 'find'), - authorized: true, - }, - { - privilege: mockAuthorizationAction('myAppAlertType', 'myApp', 'rule', 'find'), - authorized: true, - }, - { - privilege: mockAuthorizationAction('myAppAlertType', 'myOtherApp', 'rule', 'find'), - authorized: true, - }, - { - privilege: mockAuthorizationAction( - 'myAppAlertType', - 'myAppWithSubFeature', - 'rule', - 'find' - ), - authorized: true, - }, - { - privilege: mockAuthorizationAction('myOtherAppAlertType', 'alerts', 'rule', 'find'), - authorized: true, - }, { privilege: mockAuthorizationAction('myOtherAppAlertType', 'myApp', 'rule', 'find'), authorized: true, @@ -1141,321 +997,111 @@ describe('AlertingAuthorization', () => { 'rule', 'find' ), - authorized: true, - }, - { - privilege: mockAuthorizationAction( - 'myOtherAppAlertType', - 'myAppWithSubFeature', - 'rule', - 'find' - ), - authorized: true, - }, - { - privilege: mockAuthorizationAction('mySecondAppAlertType', 'alerts', 'rule', 'find'), - authorized: true, - }, - { - privilege: mockAuthorizationAction('mySecondAppAlertType', 'myApp', 'rule', 'find'), - authorized: true, + authorized: false, }, { - privilege: mockAuthorizationAction( - 'mySecondAppAlertType', - 'myOtherApp', - 'rule', - 'find' - ), + privilege: mockAuthorizationAction('myAppAlertType', 'myApp', 'rule', 'find'), authorized: true, }, { - privilege: mockAuthorizationAction( - 'mySecondAppAlertType', - 'myAppWithSubFeature', - 'rule', - 'find' - ), + privilege: mockAuthorizationAction('myAppAlertType', 'myOtherApp', 'rule', 'find'), authorized: true, }, ], }, }); - const alertAuthorization = new AlertingAuthorization({ - request, - ruleTypeRegistry, - authorization, - getSpaceId, - allRegisteredConsumers, - ruleTypesConsumersMap, - }); - ruleTypeRegistry.list.mockReturnValue(setOfAlertTypes); - expect( - ( - await alertAuthorization.getFindAuthorizationFilter(AlertingAuthorizationEntity.Rule, { - type: AlertingAuthorizationFilterType.KQL, - fieldNames: { - ruleTypeId: 'path.to.rule_type_id', - consumer: 'consumer-field', - }, - }) - ).filter - ).toEqual( - fromKueryExpression( - `((path.to.rule_type_id:myAppAlertType and consumer-field:(alerts or myApp or myOtherApp or myAppWithSubFeature)) or (path.to.rule_type_id:myOtherAppAlertType and consumer-field:(alerts or myApp or myOtherApp or myAppWithSubFeature)) or (path.to.rule_type_id:mySecondAppAlertType and consumer-field:(alerts or myApp or myOtherApp or myAppWithSubFeature)))` - ) - ); - }); - it('throws if user has no privileges to any rule type', async () => { - const { authorization } = mockSecurity(); - const checkPrivileges: jest.MockedFunction< - ReturnType - > = jest.fn(); - authorization.checkPrivilegesDynamicallyWithRequest.mockReturnValue(checkPrivileges); - checkPrivileges.mockResolvedValueOnce({ - username: 'some-user', - hasAllRequested: false, - privileges: { - kibana: [ - { - privilege: mockAuthorizationAction('myType', 'myOtherApp', 'rule', 'create'), - authorized: false, - }, - { - privilege: mockAuthorizationAction('myType', 'myApp', 'rule', 'create'), - authorized: false, - }, - ], - }, - }); - const alertAuthorization = new AlertingAuthorization({ + + const auth = await AlertingAuthorization.create({ request, ruleTypeRegistry, - authorization, getSpaceId, - allRegisteredConsumers, - ruleTypesConsumersMap, + features, + getSpace, + authorization: securityStart.authz, }); - ruleTypeRegistry.list.mockReturnValue(setOfAlertTypes); - await expect( - alertAuthorization.getFindAuthorizationFilter(AlertingAuthorizationEntity.Rule, { + + const { ensureRuleTypeIsAuthorized } = await auth.getFindAuthorizationFilter( + AlertingAuthorizationEntity.Rule, + { type: AlertingAuthorizationFilterType.KQL, fieldNames: { - ruleTypeId: 'path.to.rule_type_id', - consumer: 'consumer-field', + ruleTypeId: 'ruleId', + consumer: 'consumer', }, - }) - ).rejects.toThrowErrorMatchingInlineSnapshot( - `"Unauthorized to find rules for any rule types"` + } ); + + expect(() => { + ensureRuleTypeIsAuthorized('myAppAlertType', 'myOtherApp', 'rule'); + }).not.toThrow(); }); - it('creates an `ensureRuleTypeIsAuthorized` function which throws if type is unauthorized', async () => { + it('creates an `logSuccessfulAuthorization` function which logs every authorized type', async () => { features.getKibanaFeatures.mockReturnValue([ mockFeatureWithConsumers('myApp', [ { ruleTypeId: 'myOtherAppAlertType', consumers: ['myApp'] }, { ruleTypeId: 'myAppAlertType', consumers: ['myApp'] }, + { ruleTypeId: 'mySecondAppAlertType', consumers: ['myApp'] }, ]), mockFeatureWithConsumers('myOtherApp', [ - { ruleTypeId: 'myOtherAppAlertType', consumers: ['myOtherApp'] }, + { ruleTypeId: 'mySecondAppAlertType', consumers: ['myOtherApp'] }, { ruleTypeId: 'myAppAlertType', consumers: ['myOtherApp'] }, ]), ]); - const { authorization } = mockSecurity(); - const checkPrivileges: jest.MockedFunction< - ReturnType - > = jest.fn(); - authorization.checkPrivilegesDynamicallyWithRequest.mockReturnValue(checkPrivileges); + checkPrivileges.mockResolvedValueOnce({ username: 'some-user', hasAllRequested: false, privileges: { kibana: [ { - privilege: mockAuthorizationAction('myOtherAppAlertType', 'myApp', 'alert', 'find'), + privilege: mockAuthorizationAction('myOtherAppAlertType', 'myApp', 'rule', 'find'), authorized: true, }, { privilege: mockAuthorizationAction( 'myOtherAppAlertType', 'myOtherApp', - 'alert', + 'rule', 'find' ), authorized: false, }, { - privilege: mockAuthorizationAction('myAppAlertType', 'myApp', 'alert', 'find'), + privilege: mockAuthorizationAction('myAppAlertType', 'myApp', 'rule', 'find'), authorized: true, }, { - privilege: mockAuthorizationAction('myAppAlertType', 'myOtherApp', 'alert', 'find'), - authorized: false, + privilege: mockAuthorizationAction('myAppAlertType', 'myOtherApp', 'rule', 'find'), + authorized: true, + }, + { + privilege: mockAuthorizationAction('mySecondAppAlertType', 'myApp', 'rule', 'find'), + authorized: true, + }, + { + privilege: mockAuthorizationAction( + 'mySecondAppAlertType', + 'myOtherApp', + 'rule', + 'find' + ), + authorized: true, }, ], }, }); - const alertAuthorization = new AlertingAuthorization({ - request, - ruleTypeRegistry, - authorization, - getSpaceId, - allRegisteredConsumers, - ruleTypesConsumersMap, - }); - ruleTypeRegistry.list.mockReturnValue(setOfAlertTypes); - const { ensureRuleTypeIsAuthorized } = await alertAuthorization.getFindAuthorizationFilter( - AlertingAuthorizationEntity.Alert, - { - type: AlertingAuthorizationFilterType.KQL, - fieldNames: { - ruleTypeId: 'ruleId', - consumer: 'consumer', - }, - } - ); - expect(() => { - ensureRuleTypeIsAuthorized('myAppAlertType', 'myOtherApp', 'alert'); - }).toThrowErrorMatchingInlineSnapshot( - `"Unauthorized by \\"myOtherApp\\" to find \\"myAppAlertType\\" alert"` - ); - }); - it('creates an `ensureRuleTypeIsAuthorized` function which is no-op if type is authorized', async () => { - features.getKibanaFeatures.mockReturnValue([ - mockFeatureWithConsumers('myApp', [ - { ruleTypeId: 'myOtherAppAlertType', consumers: ['myApp'] }, - { ruleTypeId: 'myAppAlertType', consumers: ['myApp'] }, - ]), - mockFeatureWithConsumers('myOtherApp', [ - { ruleTypeId: 'myOtherApp', consumers: ['myOtherApp'] }, - ]), - ]); - const { authorization } = mockSecurity(); - const checkPrivileges: jest.MockedFunction< - ReturnType - > = jest.fn(); - authorization.checkPrivilegesDynamicallyWithRequest.mockReturnValue(checkPrivileges); - checkPrivileges.mockResolvedValueOnce({ - username: 'some-user', - hasAllRequested: false, - privileges: { - kibana: [ - { - privilege: mockAuthorizationAction('myOtherAppAlertType', 'myApp', 'rule', 'find'), - authorized: true, - }, - { - privilege: mockAuthorizationAction( - 'myOtherAppAlertType', - 'myOtherApp', - 'rule', - 'find' - ), - authorized: false, - }, - { - privilege: mockAuthorizationAction('myAppAlertType', 'myApp', 'rule', 'find'), - authorized: true, - }, - { - privilege: mockAuthorizationAction('myAppAlertType', 'myOtherApp', 'rule', 'find'), - authorized: true, - }, - ], - }, - }); - const alertAuthorization = new AlertingAuthorization({ - request, - ruleTypeRegistry, - authorization, - getSpaceId, - allRegisteredConsumers, - ruleTypesConsumersMap, - }); - ruleTypeRegistry.list.mockReturnValue(setOfAlertTypes); - const { ensureRuleTypeIsAuthorized } = await alertAuthorization.getFindAuthorizationFilter( - AlertingAuthorizationEntity.Rule, - { - type: AlertingAuthorizationFilterType.KQL, - fieldNames: { - ruleTypeId: 'ruleId', - consumer: 'consumer', - }, - } - ); - expect(() => { - ensureRuleTypeIsAuthorized('myAppAlertType', 'myOtherApp', 'rule'); - }).not.toThrow(); - }); - it('creates an `logSuccessfulAuthorization` function which logs every authorized type', async () => { - features.getKibanaFeatures.mockReturnValue([ - mockFeatureWithConsumers('myApp', [ - { ruleTypeId: 'myOtherAppAlertType', consumers: ['myApp'] }, - { ruleTypeId: 'myAppAlertType', consumers: ['myApp'] }, - { ruleTypeId: 'mySecondAppAlertType', consumers: ['myApp'] }, - ]), - mockFeatureWithConsumers('myOtherApp', [ - { ruleTypeId: 'mySecondAppAlertType', consumers: ['myOtherApp'] }, - { ruleTypeId: 'myAppAlertType', consumers: ['myOtherApp'] }, - ]), - ]); - const { authorization } = mockSecurity(); - const checkPrivileges: jest.MockedFunction< - ReturnType - > = jest.fn(); - authorization.checkPrivilegesDynamicallyWithRequest.mockReturnValue(checkPrivileges); - checkPrivileges.mockResolvedValueOnce({ - username: 'some-user', - hasAllRequested: false, - privileges: { - kibana: [ - { - privilege: mockAuthorizationAction('myOtherAppAlertType', 'myApp', 'rule', 'find'), - authorized: true, - }, - { - privilege: mockAuthorizationAction( - 'myOtherAppAlertType', - 'myOtherApp', - 'rule', - 'find' - ), - authorized: false, - }, - { - privilege: mockAuthorizationAction('myAppAlertType', 'myApp', 'rule', 'find'), - authorized: true, - }, - { - privilege: mockAuthorizationAction('myAppAlertType', 'myOtherApp', 'rule', 'find'), - authorized: true, - }, - { - privilege: mockAuthorizationAction('mySecondAppAlertType', 'myApp', 'rule', 'find'), - authorized: true, - }, - { - privilege: mockAuthorizationAction( - 'mySecondAppAlertType', - 'myOtherApp', - 'rule', - 'find' - ), - authorized: true, - }, - ], - }, - }); - const alertAuthorization = new AlertingAuthorization({ + + const auth = await AlertingAuthorization.create({ request, ruleTypeRegistry, - authorization, getSpaceId, - allRegisteredConsumers, - ruleTypesConsumersMap, + features, + getSpace, + authorization: securityStart.authz, }); - ruleTypeRegistry.list.mockReturnValue(setOfAlertTypes); - const { ensureRuleTypeIsAuthorized } = await alertAuthorization.getFindAuthorizationFilter( + + const { ensureRuleTypeIsAuthorized } = await auth.getFindAuthorizationFilter( AlertingAuthorizationEntity.Rule, { type: AlertingAuthorizationFilterType.KQL, @@ -1465,6 +1111,7 @@ describe('AlertingAuthorization', () => { }, } ); + expect(() => { ensureRuleTypeIsAuthorized('myAppAlertType', 'myOtherApp', 'rule'); ensureRuleTypeIsAuthorized('mySecondAppAlertType', 'myOtherApp', 'rule'); @@ -1476,24 +1123,22 @@ describe('AlertingAuthorization', () => { // Space ids are stored in the alerts documents and even if security is disabled // still need to consider the users space privileges it('creates a spaceId only filter if security is disabled, but require space awareness', async () => { - const alertAuthorization = new AlertingAuthorization({ + const auth = await AlertingAuthorization.create({ request, ruleTypeRegistry, getSpaceId, - allRegisteredConsumers, - ruleTypesConsumersMap, + features, + getSpace, + }); + + const { filter } = await auth.getFindAuthorizationFilter(AlertingAuthorizationEntity.Alert, { + type: AlertingAuthorizationFilterType.ESDSL, + fieldNames: { + ruleTypeId: 'ruleId', + consumer: 'consumer', + spaceIds: 'path.to.space.id', + }, }); - const { filter } = await alertAuthorization.getFindAuthorizationFilter( - AlertingAuthorizationEntity.Alert, - { - type: AlertingAuthorizationFilterType.ESDSL, - fieldNames: { - ruleTypeId: 'ruleId', - consumer: 'consumer', - spaceIds: 'path.to.space.id', - }, - } - ); expect(filter).toEqual({ bool: { minimum_should_match: 1, should: [{ match: { 'path.to.space.id': 'space1' } }] }, @@ -1501,71 +1146,479 @@ describe('AlertingAuthorization', () => { }); }); - describe('filterByRuleTypeAuthorization', () => { - const myOtherAppAlertType: RegistryRuleType = { - actionGroups: [], - actionVariables: undefined, - defaultActionGroupId: 'default', - minimumLicenseRequired: 'basic', - isExportable: true, - recoveryActionGroup: RecoveredActionGroup, - id: 'myOtherAppAlertType', - name: 'myOtherAppAlertType', - category: 'test', - producer: 'myOtherApp', - enabledInLicense: true, - hasAlertsMappings: false, - hasFieldsForAAD: false, - validLegacyConsumers: [], - }; - const myAppAlertType: RegistryRuleType = { - actionGroups: [], - actionVariables: undefined, - defaultActionGroupId: 'default', - minimumLicenseRequired: 'basic', - isExportable: true, - recoveryActionGroup: RecoveredActionGroup, - id: 'myAppAlertType', - name: 'myAppAlertType', - category: 'test', - producer: 'myApp', - enabledInLicense: true, - hasAlertsMappings: false, - hasFieldsForAAD: false, - validLegacyConsumers: [], + describe.only('getAuthorizationFilter', () => { + type CheckPrivilegesResponseWithoutES = Omit & { + privileges: Omit; }; - const setOfAlertTypes = new Set([myAppAlertType, myOtherAppAlertType]); + + const checkPrivileges = jest.fn, []>(async () => ({ + username: 'elastic', + hasAllRequested: true, + privileges: { kibana: [] }, + })); + + const ruleTypeIds = ['rule-type-id-1', 'rule-type-id-2', 'rule-type-id-3', 'rule-type-id-4']; + const consumers = ['consumer-a', 'consumer-b', 'consumer-c', 'consumer-d']; + + let securityStart: ReturnType; + let features: jest.Mocked; + beforeEach(() => { + jest.clearAllMocks(); + allRegisteredConsumers.clear(); + securityStart = securityMock.createStart(); + securityStart.authz.mode.useRbacForRequest.mockReturnValue(true); + securityStart.authz.checkPrivilegesDynamicallyWithRequest.mockReturnValue(checkPrivileges); + + features = featuresPluginMock.createStart(); features.getKibanaFeatures.mockReturnValue([ - mockFeatureWithConsumers('myApp', [ - { ruleTypeId: 'myOtherAppAlertType', consumers: ['myApp'] }, - { ruleTypeId: 'myAppAlertType', consumers: ['myApp'] }, + mockFeatureWithConsumers('feature-id-1', [ + { + ruleTypeId: 'rule-type-id-1', + consumers: ['alerts', 'consumer-a'], + }, + { ruleTypeId: 'rule-type-id-2', consumers: ['alerts', 'consumer-b'] }, ]), - mockFeatureWithConsumers('myOtherApp', [ - { ruleTypeId: 'myOtherAppAlertType', consumers: ['myApp'] }, - { ruleTypeId: 'myAppAlertType', consumers: ['myApp'] }, + mockFeatureWithConsumers('feature-id-2', [ + { + ruleTypeId: 'rule-type-id-1', + consumers: ['alerts', 'consumer-b'], + }, + { + ruleTypeId: 'rule-type-id-3', + consumers: ['alerts', 'consumer-c'], + }, + ]), + mockFeatureWithConsumers('feature-id-3', [ + { + ruleTypeId: 'rule-type-id-4', + consumers: ['consumer-d'], + }, ]), ]); + + const alertingGet = securityStart.authz.actions.alerting.get as jest.Mock; + alertingGet.mockImplementation(mockAuthorizationAction); + + ruleTypeRegistry = ruleTypeRegistryMock.create(); + ruleTypeRegistry.getAllTypes.mockReturnValue(ruleTypeIds); + ruleTypeRegistry.has.mockImplementation((ruleTypeId: string) => + ruleTypeIds.includes(ruleTypeId) + ); + + // @ts-expect-error: only the id is needed for the tests + ruleTypeRegistry.get.mockImplementation((ruleTypeId: string) => ({ id: ruleTypeId })); }); - it('augments a list of types with all features when there is no authorization api', async () => { - features.getKibanaFeatures.mockReturnValue([ - myAppFeature, - myOtherAppFeature, - myAppWithSubFeature, - myFeatureWithoutAlerting, - ]); - const alertAuthorization = new AlertingAuthorization({ - request, - ruleTypeRegistry, - getSpaceId, - allRegisteredConsumers, - ruleTypesConsumersMap, - }); - ruleTypeRegistry.list.mockReturnValue(setOfAlertTypes); - await expect( - alertAuthorization.filterByRuleTypeAuthorization( - new Set([myAppAlertType, myOtherAppAlertType]), + describe('filter', () => { + it('gets the filter correctly with no security and no spaceIds in the fields names', async () => { + const auth = await AlertingAuthorization.create({ + request, + ruleTypeRegistry, + getSpaceId, + features, + getSpace, + }); + + const { filter } = await auth.getAuthorizationFilter( + AlertingAuthorizationEntity.Rule, + { + type: AlertingAuthorizationFilterType.KQL, + fieldNames: { + ruleTypeId: 'ruleId', + consumer: 'consumer', + }, + }, + ReadOperations.Get + ); + + expect(filter).toEqual(undefined); + }); + + it('gets the filter correctly with no security and spaceIds in the fields names', async () => { + const auth = await AlertingAuthorization.create({ + request, + ruleTypeRegistry, + getSpaceId, + features, + getSpace, + }); + + const { filter } = await auth.getAuthorizationFilter( + AlertingAuthorizationEntity.Rule, + { + type: AlertingAuthorizationFilterType.KQL, + fieldNames: { + ruleTypeId: 'ruleId', + consumer: 'consumer', + spaceIds: 'space-id', + }, + }, + ReadOperations.Get + ); + + expect(toKqlExpression(filter as KueryNode)).toMatchInlineSnapshot(`"space-id: space1"`); + }); + + it('gets the filter correctly with security disabled', async () => { + securityStart.authz.mode.useRbacForRequest.mockReturnValue(false); + + const auth = await AlertingAuthorization.create({ + request, + ruleTypeRegistry, + getSpaceId, + features, + getSpace, + authorization: securityStart.authz, + }); + + const { filter } = await auth.getAuthorizationFilter( + AlertingAuthorizationEntity.Rule, + { + type: AlertingAuthorizationFilterType.KQL, + fieldNames: { + ruleTypeId: 'ruleId', + consumer: 'consumer', + }, + }, + ReadOperations.Get + ); + + expect(filter).toEqual(undefined); + }); + + it('gets the filter correctly for all rule types and consumers', async () => { + checkPrivileges.mockResolvedValueOnce({ + username: 'some-user', + hasAllRequested: true, + privileges: { + kibana: [ + { + privilege: mockAuthorizationAction('rule-type-id-1', 'consumer-a', 'rule', 'get'), + authorized: true, + }, + { + privilege: mockAuthorizationAction('rule-type-id-1', 'consumer-b', 'rule', 'get'), + authorized: true, + }, + { + privilege: mockAuthorizationAction('rule-type-id-2', 'consumer-b', 'rule', 'get'), + authorized: true, + }, + { + privilege: mockAuthorizationAction('rule-type-id-3', 'consumer-c', 'rule', 'get'), + authorized: true, + }, + { + privilege: mockAuthorizationAction('rule-type-id-4', 'consumer-d', 'rule', 'get'), + authorized: true, + }, + ], + }, + }); + + const auth = await AlertingAuthorization.create({ + request, + ruleTypeRegistry, + getSpaceId, + features, + getSpace, + authorization: securityStart.authz, + }); + + const { filter } = await auth.getAuthorizationFilter( + AlertingAuthorizationEntity.Rule, + { + type: AlertingAuthorizationFilterType.KQL, + fieldNames: { + ruleTypeId: 'ruleId', + consumer: 'consumer', + }, + }, + ReadOperations.Get, + new Set(consumers) + ); + + expect(toKqlExpression(filter as KueryNode)).toMatchInlineSnapshot( + `"((ruleId: rule-type-id-1 AND (consumer: consumer-a OR consumer: consumer-b)) OR (ruleId: rule-type-id-2 AND consumer: consumer-b) OR (ruleId: rule-type-id-3 AND consumer: consumer-c) OR (ruleId: rule-type-id-4 AND consumer: consumer-d))"` + ); + }); + + it('throws when the user is not authorized for any rule type', async () => { + checkPrivileges.mockResolvedValueOnce({ + username: 'some-user', + hasAllRequested: true, + privileges: { + kibana: [], + }, + }); + + const auth = await AlertingAuthorization.create({ + request, + ruleTypeRegistry, + getSpaceId, + features, + getSpace, + authorization: securityStart.authz, + }); + + await expect( + auth.getAuthorizationFilter( + AlertingAuthorizationEntity.Rule, + { + type: AlertingAuthorizationFilterType.KQL, + fieldNames: { + ruleTypeId: 'ruleId', + consumer: 'consumer', + }, + }, + ReadOperations.Get, + new Set(consumers) + ) + ).rejects.toThrowErrorMatchingInlineSnapshot( + `"Unauthorized to get rules for any rule types"` + ); + }); + }); + + describe('ensureRuleTypeIsAuthorized', () => { + it('does not throw if the rule type is authorized', async () => { + checkPrivileges.mockResolvedValueOnce({ + username: 'some-user', + hasAllRequested: true, + privileges: { + kibana: [ + { + privilege: mockAuthorizationAction('rule-type-id-1', 'consumer-a', 'rule', 'get'), + authorized: true, + }, + ], + }, + }); + + const auth = await AlertingAuthorization.create({ + request, + ruleTypeRegistry, + getSpaceId, + features, + getSpace, + authorization: securityStart.authz, + }); + + const { ensureRuleTypeIsAuthorized } = await auth.getAuthorizationFilter( + AlertingAuthorizationEntity.Rule, + { + type: AlertingAuthorizationFilterType.KQL, + fieldNames: { + ruleTypeId: 'ruleId', + consumer: 'consumer', + }, + }, + ReadOperations.Get, + new Set(consumers) + ); + + expect(() => + ensureRuleTypeIsAuthorized('rule-type-id-1', 'consumer-a', 'rule') + ).not.toThrow(); + }); + + it('throws if the rule type is not authorized', async () => { + checkPrivileges.mockResolvedValueOnce({ + username: 'some-user', + hasAllRequested: true, + privileges: { + kibana: [ + { + privilege: mockAuthorizationAction('rule-type-id-1', 'consumer-a', 'rule', 'get'), + authorized: true, + }, + ], + }, + }); + + const auth = await AlertingAuthorization.create({ + request, + ruleTypeRegistry, + getSpaceId, + features, + getSpace, + authorization: securityStart.authz, + }); + + const { ensureRuleTypeIsAuthorized } = await auth.getAuthorizationFilter( + AlertingAuthorizationEntity.Rule, + { + type: AlertingAuthorizationFilterType.KQL, + fieldNames: { + ruleTypeId: 'ruleId', + consumer: 'consumer', + }, + }, + ReadOperations.Get, + new Set(consumers) + ); + + expect(() => + ensureRuleTypeIsAuthorized('rule-type-id-2', 'consumer-a', 'rule') + ).toThrowErrorMatchingInlineSnapshot( + `"Unauthorized by \\"consumer-a\\" to get \\"rule-type-id-2\\" rule"` + ); + }); + + it('throws if the rule type is not authorized for the entity', async () => { + checkPrivileges.mockResolvedValueOnce({ + username: 'some-user', + hasAllRequested: true, + privileges: { + kibana: [ + { + privilege: mockAuthorizationAction('rule-type-id-1', 'consumer-a', 'rule', 'get'), + authorized: true, + }, + ], + }, + }); + + const auth = await AlertingAuthorization.create({ + request, + ruleTypeRegistry, + getSpaceId, + features, + getSpace, + authorization: securityStart.authz, + }); + + const { ensureRuleTypeIsAuthorized } = await auth.getAuthorizationFilter( + AlertingAuthorizationEntity.Rule, + { + type: AlertingAuthorizationFilterType.KQL, + fieldNames: { + ruleTypeId: 'ruleId', + consumer: 'consumer', + }, + }, + ReadOperations.Get, + new Set(consumers) + ); + + expect(() => + ensureRuleTypeIsAuthorized('rule-type-id-1', 'consumer-a', 'alert') + ).toThrowErrorMatchingInlineSnapshot( + `"Unauthorized by \\"consumer-a\\" to get \\"rule-type-id-1\\" alert"` + ); + }); + + it('throws if the rule type is not authorized for the consumer', async () => { + checkPrivileges.mockResolvedValueOnce({ + username: 'some-user', + hasAllRequested: true, + privileges: { + kibana: [ + { + privilege: mockAuthorizationAction('rule-type-id-1', 'consumer-a', 'rule', 'get'), + authorized: true, + }, + ], + }, + }); + + const auth = await AlertingAuthorization.create({ + request, + ruleTypeRegistry, + getSpaceId, + features, + getSpace, + authorization: securityStart.authz, + }); + + const { ensureRuleTypeIsAuthorized } = await auth.getAuthorizationFilter( + AlertingAuthorizationEntity.Rule, + { + type: AlertingAuthorizationFilterType.KQL, + fieldNames: { + ruleTypeId: 'ruleId', + consumer: 'consumer', + }, + }, + ReadOperations.Get, + new Set(consumers) + ); + + expect(() => + ensureRuleTypeIsAuthorized('rule-type-id-1', 'consumer-b', 'rule') + ).toThrowErrorMatchingInlineSnapshot( + `"Unauthorized by \\"consumer-b\\" to get \\"rule-type-id-1\\" rule"` + ); + }); + }); + }); + + describe('filterByRuleTypeAuthorization', () => { + const myOtherAppAlertType: RegistryRuleType = { + actionGroups: [], + actionVariables: undefined, + defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', + isExportable: true, + recoveryActionGroup: RecoveredActionGroup, + id: 'myOtherAppAlertType', + name: 'myOtherAppAlertType', + category: 'test', + producer: 'myOtherApp', + enabledInLicense: true, + hasAlertsMappings: false, + hasFieldsForAAD: false, + validLegacyConsumers: [], + }; + const myAppAlertType: RegistryRuleType = { + actionGroups: [], + actionVariables: undefined, + defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', + isExportable: true, + recoveryActionGroup: RecoveredActionGroup, + id: 'myAppAlertType', + name: 'myAppAlertType', + category: 'test', + producer: 'myApp', + enabledInLicense: true, + hasAlertsMappings: false, + hasFieldsForAAD: false, + validLegacyConsumers: [], + }; + const setOfAlertTypes = new Set([myAppAlertType, myOtherAppAlertType]); + beforeEach(() => { + features.getKibanaFeatures.mockReturnValue([ + mockFeatureWithConsumers('myApp', [ + { ruleTypeId: 'myOtherAppAlertType', consumers: ['myApp'] }, + { ruleTypeId: 'myAppAlertType', consumers: ['myApp'] }, + ]), + mockFeatureWithConsumers('myOtherApp', [ + { ruleTypeId: 'myOtherAppAlertType', consumers: ['myApp'] }, + { ruleTypeId: 'myAppAlertType', consumers: ['myApp'] }, + ]), + ]); + }); + it('augments a list of types with all features when there is no authorization api', async () => { + features.getKibanaFeatures.mockReturnValue([ + myAppFeature, + myOtherAppFeature, + myAppWithSubFeature, + myFeatureWithoutAlerting, + ]); + const alertAuthorization = new AlertingAuthorization({ + request, + ruleTypeRegistry, + getSpaceId, + allRegisteredConsumers, + ruleTypesConsumersMap, + }); + ruleTypeRegistry.list.mockReturnValue(setOfAlertTypes); + + await expect( + alertAuthorization.filterByRuleTypeAuthorization( + new Set([myAppAlertType, myOtherAppAlertType]), [WriteOperations.Create], AlertingAuthorizationEntity.Rule ) @@ -1643,621 +1696,1666 @@ describe('AlertingAuthorization', () => { "id": "recovered", "name": "Recovered", }, - "validLegacyConsumers": Array [], + "validLegacyConsumers": Array [], + }, + } + `); + }); + + it('augments a list of types with consumers under which the operation is authorized', async () => { + const { authorization } = mockSecurity(); + const checkPrivileges: jest.MockedFunction< + ReturnType + > = jest.fn(); + authorization.checkPrivilegesDynamicallyWithRequest.mockReturnValue(checkPrivileges); + checkPrivileges.mockResolvedValueOnce({ + username: 'some-user', + hasAllRequested: false, + privileges: { + kibana: [ + { + privilege: mockAuthorizationAction('myOtherAppAlertType', 'myApp', 'rule', 'create'), + authorized: true, + }, + { + privilege: mockAuthorizationAction( + 'myOtherAppAlertType', + 'myOtherApp', + 'rule', + 'create' + ), + authorized: false, + }, + { + privilege: mockAuthorizationAction('myAppAlertType', 'myApp', 'rule', 'create'), + authorized: true, + }, + { + privilege: mockAuthorizationAction('myAppAlertType', 'myOtherApp', 'rule', 'create'), + authorized: true, + }, + ], + }, + }); + + const alertAuthorization = new AlertingAuthorization({ + request, + ruleTypeRegistry, + authorization: securityStart.authz, + getSpaceId, + allRegisteredConsumers, + ruleTypesConsumersMap, + }); + ruleTypeRegistry.list.mockReturnValue(setOfAlertTypes); + + await expect( + alertAuthorization.filterByRuleTypeAuthorization( + new Set([myAppAlertType, myOtherAppAlertType]), + [WriteOperations.Create], + AlertingAuthorizationEntity.Rule + ) + ).resolves.toMatchInlineSnapshot(` + Set { + Object { + "actionGroups": Array [], + "actionVariables": undefined, + "authorizedConsumers": Object { + "myApp": Object { + "all": true, + "read": true, + }, + }, + "category": "test", + "defaultActionGroupId": "default", + "enabledInLicense": true, + "hasAlertsMappings": false, + "hasFieldsForAAD": false, + "id": "myOtherAppAlertType", + "isExportable": true, + "minimumLicenseRequired": "basic", + "name": "myOtherAppAlertType", + "producer": "myOtherApp", + "recoveryActionGroup": Object { + "id": "recovered", + "name": "Recovered", + }, + "validLegacyConsumers": Array [], + }, + Object { + "actionGroups": Array [], + "actionVariables": undefined, + "authorizedConsumers": Object { + "myApp": Object { + "all": true, + "read": true, + }, + "myOtherApp": Object { + "all": true, + "read": true, + }, + }, + "category": "test", + "defaultActionGroupId": "default", + "enabledInLicense": true, + "hasAlertsMappings": false, + "hasFieldsForAAD": false, + "id": "myAppAlertType", + "isExportable": true, + "minimumLicenseRequired": "basic", + "name": "myAppAlertType", + "producer": "myApp", + "recoveryActionGroup": Object { + "id": "recovered", + "name": "Recovered", + }, + "validLegacyConsumers": Array [], + }, + } + `); + }); + + it('authorizes user under the `alerts` consumer when they are authorized by the producer', async () => { + const { authorization } = mockSecurity(); + const checkPrivileges: jest.MockedFunction< + ReturnType + > = jest.fn(); + authorization.checkPrivilegesDynamicallyWithRequest.mockReturnValue(checkPrivileges); + checkPrivileges.mockResolvedValueOnce({ + username: 'some-user', + hasAllRequested: false, + privileges: { + kibana: [ + { + privilege: mockAuthorizationAction('myAppAlertType', 'myApp', 'alert', 'create'), + authorized: true, + }, + { + privilege: mockAuthorizationAction('myAppAlertType', 'myOtherApp', 'alert', 'create'), + authorized: false, + }, + ], + }, + }); + + const alertAuthorization = new AlertingAuthorization({ + request, + ruleTypeRegistry, + authorization: securityStart.authz, + getSpaceId, + allRegisteredConsumers, + ruleTypesConsumersMap, + }); + ruleTypeRegistry.list.mockReturnValue(setOfAlertTypes); + + await expect( + alertAuthorization.filterByRuleTypeAuthorization( + new Set([myAppAlertType]), + [WriteOperations.Create], + AlertingAuthorizationEntity.Alert + ) + ).resolves.toMatchInlineSnapshot(` + Set { + Object { + "actionGroups": Array [], + "actionVariables": undefined, + "authorizedConsumers": Object { + "myApp": Object { + "all": true, + "read": true, + }, + }, + "category": "test", + "defaultActionGroupId": "default", + "enabledInLicense": true, + "hasAlertsMappings": false, + "hasFieldsForAAD": false, + "id": "myAppAlertType", + "isExportable": true, + "minimumLicenseRequired": "basic", + "name": "myAppAlertType", + "producer": "myApp", + "recoveryActionGroup": Object { + "id": "recovered", + "name": "Recovered", + }, + "validLegacyConsumers": Array [], + }, + } + `); + }); + + it('augments a list of types with consumers under which multiple operations are authorized', async () => { + const { authorization } = mockSecurity(); + const checkPrivileges: jest.MockedFunction< + ReturnType + > = jest.fn(); + authorization.checkPrivilegesDynamicallyWithRequest.mockReturnValue(checkPrivileges); + checkPrivileges.mockResolvedValueOnce({ + username: 'some-user', + hasAllRequested: false, + privileges: { + kibana: [ + { + privilege: mockAuthorizationAction('myOtherAppAlertType', 'myApp', 'alert', 'create'), + authorized: true, + }, + { + privilege: mockAuthorizationAction( + 'myOtherAppAlertType', + 'myOtherApp', + 'alert', + 'create' + ), + authorized: false, + }, + { + privilege: mockAuthorizationAction('myAppAlertType', 'myApp', 'alert', 'create'), + authorized: false, + }, + { + privilege: mockAuthorizationAction('myAppAlertType', 'myOtherApp', 'alert', 'create'), + authorized: false, + }, + { + privilege: mockAuthorizationAction('myOtherAppAlertType', 'myApp', 'alert', 'get'), + authorized: true, + }, + { + privilege: mockAuthorizationAction( + 'myOtherAppAlertType', + 'myOtherApp', + 'alert', + 'get' + ), + authorized: true, + }, + { + privilege: mockAuthorizationAction('myAppAlertType', 'myApp', 'alert', 'get'), + authorized: true, + }, + { + privilege: mockAuthorizationAction('myAppAlertType', 'myOtherApp', 'alert', 'get'), + authorized: true, + }, + ], + }, + }); + + const alertAuthorization = new AlertingAuthorization({ + request, + ruleTypeRegistry, + authorization: securityStart.authz, + getSpaceId, + allRegisteredConsumers, + ruleTypesConsumersMap, + }); + ruleTypeRegistry.list.mockReturnValue(setOfAlertTypes); + + await expect( + alertAuthorization.filterByRuleTypeAuthorization( + new Set([myAppAlertType, myOtherAppAlertType]), + [WriteOperations.Create, ReadOperations.Get], + AlertingAuthorizationEntity.Alert + ) + ).resolves.toMatchInlineSnapshot(` + Set { + Object { + "actionGroups": Array [], + "actionVariables": undefined, + "authorizedConsumers": Object { + "myApp": Object { + "all": true, + "read": true, + }, + "myOtherApp": Object { + "all": false, + "read": true, + }, + }, + "category": "test", + "defaultActionGroupId": "default", + "enabledInLicense": true, + "hasAlertsMappings": false, + "hasFieldsForAAD": false, + "id": "myOtherAppAlertType", + "isExportable": true, + "minimumLicenseRequired": "basic", + "name": "myOtherAppAlertType", + "producer": "myOtherApp", + "recoveryActionGroup": Object { + "id": "recovered", + "name": "Recovered", + }, + "validLegacyConsumers": Array [], + }, + Object { + "actionGroups": Array [], + "actionVariables": undefined, + "authorizedConsumers": Object { + "myApp": Object { + "all": false, + "read": true, + }, + "myOtherApp": Object { + "all": false, + "read": true, + }, + }, + "category": "test", + "defaultActionGroupId": "default", + "enabledInLicense": true, + "hasAlertsMappings": false, + "hasFieldsForAAD": false, + "id": "myAppAlertType", + "isExportable": true, + "minimumLicenseRequired": "basic", + "name": "myAppAlertType", + "producer": "myApp", + "recoveryActionGroup": Object { + "id": "recovered", + "name": "Recovered", + }, + "validLegacyConsumers": Array [], + }, + } + `); + }); + + it('omits types which have no consumers under which the operation is authorized', async () => { + const { authorization } = mockSecurity(); + const checkPrivileges: jest.MockedFunction< + ReturnType + > = jest.fn(); + authorization.checkPrivilegesDynamicallyWithRequest.mockReturnValue(checkPrivileges); + checkPrivileges.mockResolvedValueOnce({ + username: 'some-user', + hasAllRequested: false, + privileges: { + kibana: [ + { + privilege: mockAuthorizationAction('myOtherAppAlertType', 'myApp', 'alert', 'create'), + authorized: true, + }, + { + privilege: mockAuthorizationAction( + 'myOtherAppAlertType', + 'myOtherApp', + 'alert', + 'create' + ), + authorized: true, + }, + { + privilege: mockAuthorizationAction('myAppAlertType', 'myApp', 'alert', 'create'), + authorized: false, + }, + { + privilege: mockAuthorizationAction('myAppAlertType', 'myOtherApp', 'alert', 'create'), + authorized: false, + }, + ], + }, + }); + + const alertAuthorization = new AlertingAuthorization({ + request, + ruleTypeRegistry, + authorization: securityStart.authz, + getSpaceId, + allRegisteredConsumers, + ruleTypesConsumersMap, + }); + ruleTypeRegistry.list.mockReturnValue(setOfAlertTypes); + + await expect( + alertAuthorization.filterByRuleTypeAuthorization( + new Set([myAppAlertType, myOtherAppAlertType]), + [WriteOperations.Create], + AlertingAuthorizationEntity.Alert + ) + ).resolves.toMatchInlineSnapshot(` + Set { + Object { + "actionGroups": Array [], + "actionVariables": undefined, + "authorizedConsumers": Object { + "myApp": Object { + "all": true, + "read": true, + }, + "myOtherApp": Object { + "all": true, + "read": true, + }, + }, + "category": "test", + "defaultActionGroupId": "default", + "enabledInLicense": true, + "hasAlertsMappings": false, + "hasFieldsForAAD": false, + "id": "myOtherAppAlertType", + "isExportable": true, + "minimumLicenseRequired": "basic", + "name": "myOtherAppAlertType", + "producer": "myOtherApp", + "recoveryActionGroup": Object { + "id": "recovered", + "name": "Recovered", + }, + "validLegacyConsumers": Array [], + }, + } + `); + }); + }); + + describe('getAuthorizedRuleTypesWithAuthorizedConsumers', () => { + type CheckPrivilegesResponseWithoutES = Omit & { + privileges: Omit; + }; + + const checkPrivileges = jest.fn, []>(async () => ({ + username: 'elastic', + hasAllRequested: true, + privileges: { kibana: [] }, + })); + + const ruleTypeIds = ['rule-type-id-1', 'rule-type-id-2', 'rule-type-id-3', 'rule-type-id-4']; + const consumers = ['consumer-a', 'consumer-b', 'consumer-c', 'consumer-d']; + + let securityStart: ReturnType; + let features: jest.Mocked; + + beforeEach(() => { + jest.clearAllMocks(); + allRegisteredConsumers.clear(); + securityStart = securityMock.createStart(); + securityStart.authz.mode.useRbacForRequest.mockReturnValue(true); + securityStart.authz.checkPrivilegesDynamicallyWithRequest.mockReturnValue(checkPrivileges); + + features = featuresPluginMock.createStart(); + features.getKibanaFeatures.mockReturnValue([ + mockFeatureWithConsumers('feature-id-1', [ + { + ruleTypeId: 'rule-type-id-1', + consumers: ['alerts', 'consumer-a'], + }, + { ruleTypeId: 'rule-type-id-2', consumers: ['alerts', 'consumer-b'] }, + ]), + mockFeatureWithConsumers('feature-id-2', [ + { + ruleTypeId: 'rule-type-id-1', + consumers: ['alerts', 'consumer-b'], + }, + { + ruleTypeId: 'rule-type-id-3', + consumers: ['alerts', 'consumer-c'], + }, + ]), + mockFeatureWithConsumers('feature-id-3', [ + { + ruleTypeId: 'rule-type-id-4', + consumers: ['consumer-d'], + }, + ]), + ]); + + const alertingGet = securityStart.authz.actions.alerting.get as jest.Mock; + alertingGet.mockImplementation(mockAuthorizationAction); + + ruleTypeRegistry = ruleTypeRegistryMock.create(); + ruleTypeRegistry.getAllTypes.mockReturnValue(ruleTypeIds); + ruleTypeRegistry.has.mockImplementation((ruleTypeId: string) => + ruleTypeIds.includes(ruleTypeId) + ); + + // @ts-expect-error: only the id is needed for the tests + ruleTypeRegistry.get.mockImplementation((ruleTypeId: string) => ({ id: ruleTypeId })); + }); + + it('get authorized rule types with authorized consumers', async () => { + checkPrivileges.mockResolvedValueOnce({ + username: 'some-user', + hasAllRequested: true, + privileges: { + kibana: [ + { + privilege: mockAuthorizationAction('rule-type-id-1', 'consumer-a', 'rule', 'get'), + authorized: true, + }, + { + privilege: mockAuthorizationAction('rule-type-id-1', 'consumer-a', 'rule', 'create'), + authorized: true, + }, + { + privilege: mockAuthorizationAction('rule-type-id-2', 'consumer-b', 'rule', 'get'), + authorized: true, + }, + { + privilege: mockAuthorizationAction('rule-type-id-3', 'consumer-c', 'rule', 'create'), + authorized: false, + }, + ], + }, + }); + + const auth = await AlertingAuthorization.create({ + request, + ruleTypeRegistry, + getSpaceId, + features, + getSpace, + authorization: securityStart.authz, + }); + + expect( + await auth.getAuthorizedRuleTypesWithAuthorizedConsumers( + consumers, + [ReadOperations.Get, WriteOperations.Create], + AlertingAuthorizationEntity.Rule + ) + ).toMatchInlineSnapshot(` + Object { + "authorizedRuleTypes": Map { + "rule-type-id-1" => Object { + "authorizedConsumers": Object { + "consumer-a": Object { + "all": true, + "read": true, + }, + }, + }, + "rule-type-id-2" => Object { + "authorizedConsumers": Object { + "consumer-b": Object { + "all": false, + "read": true, + }, + }, + }, + }, + "hasAllRequested": true, + "username": "some-user", + } + `); + }); + + it('calls checkPrivileges with the correct actions', async () => { + const auth = await AlertingAuthorization.create({ + request, + ruleTypeRegistry, + getSpaceId, + features, + getSpace, + authorization: securityStart.authz, + }); + + await auth.getAuthorizedRuleTypesWithAuthorizedConsumers( + consumers, + [ReadOperations.Get, WriteOperations.Create], + AlertingAuthorizationEntity.Rule + ); + + expect(checkPrivileges).toBeCalledTimes(1); + expect(checkPrivileges.mock.calls[0]).toMatchInlineSnapshot(` + Array [ + Object { + "kibana": Array [ + "rule-type-id-1/consumer-a/rule/get", + "rule-type-id-1/consumer-a/rule/create", + "rule-type-id-1/consumer-b/rule/get", + "rule-type-id-1/consumer-b/rule/create", + "rule-type-id-2/consumer-b/rule/get", + "rule-type-id-2/consumer-b/rule/create", + "rule-type-id-3/consumer-c/rule/get", + "rule-type-id-3/consumer-c/rule/create", + "rule-type-id-4/consumer-d/rule/get", + "rule-type-id-4/consumer-d/rule/create", + ], + }, + ] + `); + }); + }); + + describe('_getAuthorizedRuleTypesWithAuthorizedConsumers', () => { + type CheckPrivilegesResponseWithoutES = Omit & { + privileges: Omit; + }; + + const checkPrivileges = jest.fn, []>(async () => ({ + username: 'elastic', + hasAllRequested: true, + privileges: { kibana: [] }, + })); + + const ruleTypeIds = ['rule-type-id-1', 'rule-type-id-2', 'rule-type-id-3', 'rule-type-id-4']; + const consumers = ['consumer-a', 'consumer-b', 'consumer-c', 'consumer-d']; + + let securityStart: ReturnType; + let features: jest.Mocked; + + beforeEach(() => { + jest.clearAllMocks(); + allRegisteredConsumers.clear(); + securityStart = securityMock.createStart(); + securityStart.authz.mode.useRbacForRequest.mockReturnValue(true); + securityStart.authz.checkPrivilegesDynamicallyWithRequest.mockReturnValue(checkPrivileges); + + features = featuresPluginMock.createStart(); + features.getKibanaFeatures.mockReturnValue([ + mockFeatureWithConsumers('feature-id-1', [ + { + ruleTypeId: 'rule-type-id-1', + consumers: ['alerts', 'consumer-a'], + }, + { ruleTypeId: 'rule-type-id-2', consumers: ['alerts', 'consumer-b'] }, + ]), + mockFeatureWithConsumers('feature-id-2', [ + { + ruleTypeId: 'rule-type-id-1', + consumers: ['alerts', 'consumer-b'], + }, + { + ruleTypeId: 'rule-type-id-3', + consumers: ['alerts', 'consumer-c'], + }, + ]), + mockFeatureWithConsumers('feature-id-3', [ + { + ruleTypeId: 'rule-type-id-4', + consumers: ['consumer-d'], + }, + ]), + ]); + + const alertingGet = securityStart.authz.actions.alerting.get as jest.Mock; + alertingGet.mockImplementation(mockAuthorizationAction); + + ruleTypeRegistry = ruleTypeRegistryMock.create(); + ruleTypeRegistry.getAllTypes.mockReturnValue(ruleTypeIds); + ruleTypeRegistry.has.mockImplementation((ruleTypeId: string) => + ruleTypeIds.includes(ruleTypeId) + ); + + // @ts-expect-error: only the id is needed for the tests + ruleTypeRegistry.get.mockImplementation((ruleTypeId: string) => ({ id: ruleTypeId })); + }); + + it('returns all rule types with all consumers as authorized with no authorization', async () => { + const auth = await AlertingAuthorization.create({ + request, + ruleTypeRegistry, + getSpaceId, + features, + getSpace, + }); + + expect( + // @ts-expect-error: need to test the private method + await auth._getAuthorizedRuleTypesWithAuthorizedConsumers( + new Set(ruleTypeIds), + [ReadOperations.Get, WriteOperations.Create], + AlertingAuthorizationEntity.Rule, + new Set(consumers) + ) + ).toMatchInlineSnapshot(` + Object { + "authorizedRuleTypes": Map { + "rule-type-id-1" => Object { + "authorizedConsumers": Object { + "alerts": Object { + "all": true, + "read": true, + }, + "consumer-a": Object { + "all": true, + "read": true, + }, + "consumer-b": Object { + "all": true, + "read": true, + }, + "consumer-c": Object { + "all": true, + "read": true, + }, + "consumer-d": Object { + "all": true, + "read": true, + }, + }, + }, + "rule-type-id-2" => Object { + "authorizedConsumers": Object { + "alerts": Object { + "all": true, + "read": true, + }, + "consumer-a": Object { + "all": true, + "read": true, + }, + "consumer-b": Object { + "all": true, + "read": true, + }, + "consumer-c": Object { + "all": true, + "read": true, + }, + "consumer-d": Object { + "all": true, + "read": true, + }, + }, + }, + "rule-type-id-3" => Object { + "authorizedConsumers": Object { + "alerts": Object { + "all": true, + "read": true, + }, + "consumer-a": Object { + "all": true, + "read": true, + }, + "consumer-b": Object { + "all": true, + "read": true, + }, + "consumer-c": Object { + "all": true, + "read": true, + }, + "consumer-d": Object { + "all": true, + "read": true, + }, + }, + }, + "rule-type-id-4" => Object { + "authorizedConsumers": Object { + "alerts": Object { + "all": true, + "read": true, + }, + "consumer-a": Object { + "all": true, + "read": true, + }, + "consumer-b": Object { + "all": true, + "read": true, + }, + "consumer-c": Object { + "all": true, + "read": true, + }, + "consumer-d": Object { + "all": true, + "read": true, + }, + }, + }, + }, + "hasAllRequested": true, + } + `); + }); + + it('filters out rule types with no authorization', async () => { + const auth = await AlertingAuthorization.create({ + request, + ruleTypeRegistry, + getSpaceId, + features, + getSpace, + }); + + expect( + // @ts-expect-error: need to test the private method + await auth._getAuthorizedRuleTypesWithAuthorizedConsumers( + new Set([ruleTypeIds[0], ruleTypeIds[1]]), + [ReadOperations.Get, WriteOperations.Create], + AlertingAuthorizationEntity.Rule, + new Set(consumers) + ) + ).toMatchInlineSnapshot(` + Object { + "authorizedRuleTypes": Map { + "rule-type-id-1" => Object { + "authorizedConsumers": Object { + "alerts": Object { + "all": true, + "read": true, + }, + "consumer-a": Object { + "all": true, + "read": true, + }, + "consumer-b": Object { + "all": true, + "read": true, + }, + "consumer-c": Object { + "all": true, + "read": true, + }, + "consumer-d": Object { + "all": true, + "read": true, + }, + }, + }, + "rule-type-id-2" => Object { + "authorizedConsumers": Object { + "alerts": Object { + "all": true, + "read": true, + }, + "consumer-a": Object { + "all": true, + "read": true, + }, + "consumer-b": Object { + "all": true, + "read": true, + }, + "consumer-c": Object { + "all": true, + "read": true, + }, + "consumer-d": Object { + "all": true, + "read": true, + }, + }, + }, + }, + "hasAllRequested": true, + } + `); + }); + + it('returns all rule types with all consumers as authorized with disabled authorization', async () => { + securityStart.authz.mode.useRbacForRequest.mockReturnValue(false); + + const auth = await AlertingAuthorization.create({ + request, + ruleTypeRegistry, + getSpaceId, + features, + getSpace, + authorization: securityStart.authz, + }); + + expect( + // @ts-expect-error: need to test the private method + await auth._getAuthorizedRuleTypesWithAuthorizedConsumers( + new Set(ruleTypeIds), + [ReadOperations.Get, WriteOperations.Create], + AlertingAuthorizationEntity.Rule, + new Set(consumers) + ) + ).toMatchInlineSnapshot(` + Object { + "authorizedRuleTypes": Map { + "rule-type-id-1" => Object { + "authorizedConsumers": Object { + "alerts": Object { + "all": true, + "read": true, + }, + "consumer-a": Object { + "all": true, + "read": true, + }, + "consumer-b": Object { + "all": true, + "read": true, + }, + "consumer-c": Object { + "all": true, + "read": true, + }, + "consumer-d": Object { + "all": true, + "read": true, + }, + }, + }, + "rule-type-id-2" => Object { + "authorizedConsumers": Object { + "alerts": Object { + "all": true, + "read": true, + }, + "consumer-a": Object { + "all": true, + "read": true, + }, + "consumer-b": Object { + "all": true, + "read": true, + }, + "consumer-c": Object { + "all": true, + "read": true, + }, + "consumer-d": Object { + "all": true, + "read": true, + }, + }, + }, + "rule-type-id-3" => Object { + "authorizedConsumers": Object { + "alerts": Object { + "all": true, + "read": true, + }, + "consumer-a": Object { + "all": true, + "read": true, + }, + "consumer-b": Object { + "all": true, + "read": true, + }, + "consumer-c": Object { + "all": true, + "read": true, + }, + "consumer-d": Object { + "all": true, + "read": true, + }, + }, + }, + "rule-type-id-4" => Object { + "authorizedConsumers": Object { + "alerts": Object { + "all": true, + "read": true, + }, + "consumer-a": Object { + "all": true, + "read": true, + }, + "consumer-b": Object { + "all": true, + "read": true, + }, + "consumer-c": Object { + "all": true, + "read": true, + }, + "consumer-d": Object { + "all": true, + "read": true, + }, + }, + }, + }, + "hasAllRequested": true, + } + `); + }); + + it('filters out rule types with disabled authorization', async () => { + securityStart.authz.mode.useRbacForRequest.mockReturnValue(false); + + const auth = await AlertingAuthorization.create({ + request, + ruleTypeRegistry, + getSpaceId, + features, + getSpace, + authorization: securityStart.authz, + }); + + expect( + // @ts-expect-error: need to test the private method + await auth._getAuthorizedRuleTypesWithAuthorizedConsumers( + new Set([ruleTypeIds[0], ruleTypeIds[1]]), + [ReadOperations.Get, WriteOperations.Create], + AlertingAuthorizationEntity.Rule, + new Set(consumers) + ) + ).toMatchInlineSnapshot(` + Object { + "authorizedRuleTypes": Map { + "rule-type-id-1" => Object { + "authorizedConsumers": Object { + "alerts": Object { + "all": true, + "read": true, + }, + "consumer-a": Object { + "all": true, + "read": true, + }, + "consumer-b": Object { + "all": true, + "read": true, + }, + "consumer-c": Object { + "all": true, + "read": true, + }, + "consumer-d": Object { + "all": true, + "read": true, + }, + }, + }, + "rule-type-id-2" => Object { + "authorizedConsumers": Object { + "alerts": Object { + "all": true, + "read": true, + }, + "consumer-a": Object { + "all": true, + "read": true, + }, + "consumer-b": Object { + "all": true, + "read": true, + }, + "consumer-c": Object { + "all": true, + "read": true, + }, + "consumer-d": Object { + "all": true, + "read": true, + }, + }, + }, + }, + "hasAllRequested": true, + } + `); + }); + + it('get authorized rule types with authorized consumers with read access only', async () => { + checkPrivileges.mockResolvedValueOnce({ + username: 'some-user', + hasAllRequested: true, + privileges: { + kibana: [ + { + privilege: mockAuthorizationAction('rule-type-id-1', 'consumer-a', 'rule', 'get'), + authorized: true, + }, + ], + }, + }); + + const auth = await AlertingAuthorization.create({ + request, + ruleTypeRegistry, + getSpaceId, + features, + getSpace, + authorization: securityStart.authz, + }); + + expect( + // @ts-expect-error: need to test the private method + await auth._getAuthorizedRuleTypesWithAuthorizedConsumers( + new Set(ruleTypeIds), + [ReadOperations.Get, WriteOperations.Create], + AlertingAuthorizationEntity.Rule, + new Set(consumers) + ) + ).toMatchInlineSnapshot(` + Object { + "authorizedRuleTypes": Map { + "rule-type-id-1" => Object { + "authorizedConsumers": Object { + "consumer-a": Object { + "all": false, + "read": true, + }, + }, + }, + }, + "hasAllRequested": true, + "username": "some-user", + } + `); + }); + + it('get authorized rule types with authorized consumers with full access', async () => { + checkPrivileges.mockResolvedValueOnce({ + username: 'some-user', + hasAllRequested: true, + privileges: { + kibana: [ + { + privilege: mockAuthorizationAction('rule-type-id-1', 'consumer-a', 'rule', 'get'), + authorized: true, + }, + { + privilege: mockAuthorizationAction('rule-type-id-1', 'consumer-a', 'rule', 'create'), + authorized: true, + }, + ], + }, + }); + + const auth = await AlertingAuthorization.create({ + request, + ruleTypeRegistry, + getSpaceId, + features, + getSpace, + authorization: securityStart.authz, + }); + + expect( + // @ts-expect-error: need to test the private method + await auth._getAuthorizedRuleTypesWithAuthorizedConsumers( + new Set(ruleTypeIds), + [ReadOperations.Get, WriteOperations.Create], + AlertingAuthorizationEntity.Rule, + new Set(consumers) + ) + ).toMatchInlineSnapshot(` + Object { + "authorizedRuleTypes": Map { + "rule-type-id-1" => Object { + "authorizedConsumers": Object { + "consumer-a": Object { + "all": true, + "read": true, + }, + }, + }, + }, + "hasAllRequested": true, + "username": "some-user", + } + `); + }); + + it('filters out not requested consumers', async () => { + checkPrivileges.mockResolvedValueOnce({ + username: 'some-user', + hasAllRequested: true, + privileges: { + kibana: [ + { + privilege: mockAuthorizationAction('rule-type-id-1', 'consumer-a', 'rule', 'get'), + authorized: true, + }, + { + privilege: mockAuthorizationAction('rule-type-id-1', 'consumer-b', 'rule', 'create'), + authorized: true, + }, + ], + }, + }); + + const auth = await AlertingAuthorization.create({ + request, + ruleTypeRegistry, + getSpaceId, + features, + getSpace, + authorization: securityStart.authz, + }); + + expect( + // @ts-expect-error: need to test the private method + await auth._getAuthorizedRuleTypesWithAuthorizedConsumers( + new Set(ruleTypeIds), + [ReadOperations.Get, WriteOperations.Create], + AlertingAuthorizationEntity.Rule, + new Set(['consumer-a']) + ) + ).toMatchInlineSnapshot(` + Object { + "authorizedRuleTypes": Map { + "rule-type-id-1" => Object { + "authorizedConsumers": Object { + "consumer-a": Object { + "all": false, + "read": true, + }, + }, + }, + }, + "hasAllRequested": true, + "username": "some-user", + } + `); + }); + + it('filters out not requested rule types', async () => { + checkPrivileges.mockResolvedValueOnce({ + username: 'some-user', + hasAllRequested: true, + privileges: { + kibana: [ + { + privilege: mockAuthorizationAction('rule-type-id-1', 'consumer-a', 'rule', 'get'), + authorized: true, + }, + { + privilege: mockAuthorizationAction('rule-type-id-1', 'consumer-b', 'rule', 'create'), + authorized: true, + }, + { + privilege: mockAuthorizationAction('rule-type-id-3', 'consumer-c', 'rule', 'create'), + authorized: true, + }, + ], + }, + }); + + const auth = await AlertingAuthorization.create({ + request, + ruleTypeRegistry, + getSpaceId, + features, + getSpace, + authorization: securityStart.authz, + }); + + expect( + // @ts-expect-error: need to test the private method + await auth._getAuthorizedRuleTypesWithAuthorizedConsumers( + new Set([ruleTypeIds[0], ruleTypeIds[1]]), + [ReadOperations.Get, WriteOperations.Create], + AlertingAuthorizationEntity.Rule, + new Set(['consumer-a', 'consumer-b']) + ) + ).toMatchInlineSnapshot(` + Object { + "authorizedRuleTypes": Map { + "rule-type-id-1" => Object { + "authorizedConsumers": Object { + "consumer-a": Object { + "all": false, + "read": true, + }, + "consumer-b": Object { + "all": true, + "read": true, + }, + }, + }, }, + "hasAllRequested": true, + "username": "some-user", } `); }); - it('augments a list of types with consumers under which the operation is authorized', async () => { - const { authorization } = mockSecurity(); - const checkPrivileges: jest.MockedFunction< - ReturnType - > = jest.fn(); - authorization.checkPrivilegesDynamicallyWithRequest.mockReturnValue(checkPrivileges); + it('returns an empty map with no requested consumers', async () => { checkPrivileges.mockResolvedValueOnce({ username: 'some-user', - hasAllRequested: false, + hasAllRequested: true, privileges: { kibana: [ { - privilege: mockAuthorizationAction('myOtherAppAlertType', 'myApp', 'rule', 'create'), - authorized: true, - }, - { - privilege: mockAuthorizationAction( - 'myOtherAppAlertType', - 'myOtherApp', - 'rule', - 'create' - ), - authorized: false, - }, - { - privilege: mockAuthorizationAction('myAppAlertType', 'myApp', 'rule', 'create'), + privilege: mockAuthorizationAction('rule-type-id-1', 'consumer-a', 'rule', 'get'), authorized: true, }, { - privilege: mockAuthorizationAction('myAppAlertType', 'myOtherApp', 'rule', 'create'), + privilege: mockAuthorizationAction('rule-type-id-1', 'consumer-a', 'rule', 'create'), authorized: true, }, ], }, }); - const alertAuthorization = new AlertingAuthorization({ + const auth = await AlertingAuthorization.create({ request, ruleTypeRegistry, - authorization, getSpaceId, - allRegisteredConsumers, - ruleTypesConsumersMap, + features, + getSpace, + authorization: securityStart.authz, }); - ruleTypeRegistry.list.mockReturnValue(setOfAlertTypes); - await expect( - alertAuthorization.filterByRuleTypeAuthorization( - new Set([myAppAlertType, myOtherAppAlertType]), - [WriteOperations.Create], - AlertingAuthorizationEntity.Rule + expect( + // @ts-expect-error: need to test the private method + await auth._getAuthorizedRuleTypesWithAuthorizedConsumers( + new Set(ruleTypeIds), + [ReadOperations.Get, WriteOperations.Create], + AlertingAuthorizationEntity.Rule, + new Set([]) ) - ).resolves.toMatchInlineSnapshot(` - Set { - Object { - "actionGroups": Array [], - "actionVariables": undefined, - "authorizedConsumers": Object { - "myApp": Object { - "all": true, - "read": true, - }, - }, - "category": "test", - "defaultActionGroupId": "default", - "enabledInLicense": true, - "hasAlertsMappings": false, - "hasFieldsForAAD": false, - "id": "myOtherAppAlertType", - "isExportable": true, - "minimumLicenseRequired": "basic", - "name": "myOtherAppAlertType", - "producer": "myOtherApp", - "recoveryActionGroup": Object { - "id": "recovered", - "name": "Recovered", - }, - "validLegacyConsumers": Array [], - }, - Object { - "actionGroups": Array [], - "actionVariables": undefined, - "authorizedConsumers": Object { - "myApp": Object { - "all": true, - "read": true, - }, - "myOtherApp": Object { - "all": true, - "read": true, - }, - }, - "category": "test", - "defaultActionGroupId": "default", - "enabledInLicense": true, - "hasAlertsMappings": false, - "hasFieldsForAAD": false, - "id": "myAppAlertType", - "isExportable": true, - "minimumLicenseRequired": "basic", - "name": "myAppAlertType", - "producer": "myApp", - "recoveryActionGroup": Object { - "id": "recovered", - "name": "Recovered", - }, - "validLegacyConsumers": Array [], - }, + ).toMatchInlineSnapshot(` + Object { + "authorizedRuleTypes": Map {}, + "hasAllRequested": true, + "username": "some-user", } `); }); - it('authorizes user under the `alerts` consumer when they are authorized by the producer', async () => { - const { authorization } = mockSecurity(); - const checkPrivileges: jest.MockedFunction< - ReturnType - > = jest.fn(); - authorization.checkPrivilegesDynamicallyWithRequest.mockReturnValue(checkPrivileges); + it('returns an empty map with no requested rule types', async () => { checkPrivileges.mockResolvedValueOnce({ username: 'some-user', - hasAllRequested: false, + hasAllRequested: true, privileges: { kibana: [ { - privilege: mockAuthorizationAction('myAppAlertType', 'myApp', 'alert', 'create'), + privilege: mockAuthorizationAction('rule-type-id-1', 'consumer-a', 'rule', 'get'), authorized: true, }, { - privilege: mockAuthorizationAction('myAppAlertType', 'myOtherApp', 'alert', 'create'), - authorized: false, + privilege: mockAuthorizationAction('rule-type-id-1', 'consumer-a', 'rule', 'create'), + authorized: true, }, ], }, }); - const alertAuthorization = new AlertingAuthorization({ + const auth = await AlertingAuthorization.create({ request, ruleTypeRegistry, - authorization, getSpaceId, - allRegisteredConsumers, - ruleTypesConsumersMap, + features, + getSpace, + authorization: securityStart.authz, }); - ruleTypeRegistry.list.mockReturnValue(setOfAlertTypes); - await expect( - alertAuthorization.filterByRuleTypeAuthorization( - new Set([myAppAlertType]), - [WriteOperations.Create], - AlertingAuthorizationEntity.Alert + expect( + // @ts-expect-error: need to test the private method + await auth._getAuthorizedRuleTypesWithAuthorizedConsumers( + new Set([]), + [ReadOperations.Get, WriteOperations.Create], + AlertingAuthorizationEntity.Rule, + new Set(consumers) ) - ).resolves.toMatchInlineSnapshot(` - Set { - Object { - "actionGroups": Array [], - "actionVariables": undefined, - "authorizedConsumers": Object { - "myApp": Object { - "all": true, - "read": true, - }, - }, - "category": "test", - "defaultActionGroupId": "default", - "enabledInLicense": true, - "hasAlertsMappings": false, - "hasFieldsForAAD": false, - "id": "myAppAlertType", - "isExportable": true, - "minimumLicenseRequired": "basic", - "name": "myAppAlertType", - "producer": "myApp", - "recoveryActionGroup": Object { - "id": "recovered", - "name": "Recovered", - }, - "validLegacyConsumers": Array [], - }, + ).toMatchInlineSnapshot(` + Object { + "authorizedRuleTypes": Map {}, + "hasAllRequested": true, + "username": "some-user", } `); }); - it('augments a list of types with consumers under which multiple operations are authorized', async () => { - const { authorization } = mockSecurity(); - const checkPrivileges: jest.MockedFunction< - ReturnType - > = jest.fn(); - authorization.checkPrivilegesDynamicallyWithRequest.mockReturnValue(checkPrivileges); + it('get authorized rule types with authorized consumers when some rule types are not authorized', async () => { checkPrivileges.mockResolvedValueOnce({ username: 'some-user', - hasAllRequested: false, + hasAllRequested: true, privileges: { kibana: [ { - privilege: mockAuthorizationAction('myOtherAppAlertType', 'myApp', 'alert', 'create'), - authorized: true, - }, - { - privilege: mockAuthorizationAction( - 'myOtherAppAlertType', - 'myOtherApp', - 'alert', - 'create' - ), - authorized: false, - }, - { - privilege: mockAuthorizationAction('myAppAlertType', 'myApp', 'alert', 'create'), - authorized: false, - }, - { - privilege: mockAuthorizationAction('myAppAlertType', 'myOtherApp', 'alert', 'create'), - authorized: false, - }, - { - privilege: mockAuthorizationAction('myOtherAppAlertType', 'myApp', 'alert', 'get'), + privilege: mockAuthorizationAction('rule-type-id-1', 'consumer-a', 'rule', 'get'), authorized: true, }, { - privilege: mockAuthorizationAction( - 'myOtherAppAlertType', - 'myOtherApp', - 'alert', - 'get' - ), + privilege: mockAuthorizationAction('rule-type-id-1', 'consumer-a', 'rule', 'create'), authorized: true, }, { - privilege: mockAuthorizationAction('myAppAlertType', 'myApp', 'alert', 'get'), - authorized: true, + privilege: mockAuthorizationAction('rule-type-id-2', 'consumer-b', 'rule', 'create'), + authorized: false, }, { - privilege: mockAuthorizationAction('myAppAlertType', 'myOtherApp', 'alert', 'get'), + privilege: mockAuthorizationAction('rule-type-id-3', 'consumer-c', 'rule', 'get'), authorized: true, }, ], }, }); - const alertAuthorization = new AlertingAuthorization({ + const auth = await AlertingAuthorization.create({ request, ruleTypeRegistry, - authorization, getSpaceId, - allRegisteredConsumers, - ruleTypesConsumersMap, + features, + getSpace, + authorization: securityStart.authz, }); - ruleTypeRegistry.list.mockReturnValue(setOfAlertTypes); - await expect( - alertAuthorization.filterByRuleTypeAuthorization( - new Set([myAppAlertType, myOtherAppAlertType]), - [WriteOperations.Create, ReadOperations.Get], - AlertingAuthorizationEntity.Alert + expect( + // @ts-expect-error: need to test the private method + await auth._getAuthorizedRuleTypesWithAuthorizedConsumers( + new Set(ruleTypeIds), + [ReadOperations.Get, WriteOperations.Create], + AlertingAuthorizationEntity.Rule, + new Set(consumers) ) - ).resolves.toMatchInlineSnapshot(` - Set { - Object { - "actionGroups": Array [], - "actionVariables": undefined, - "authorizedConsumers": Object { - "myApp": Object { - "all": true, - "read": true, - }, - "myOtherApp": Object { - "all": false, - "read": true, + ).toMatchInlineSnapshot(` + Object { + "authorizedRuleTypes": Map { + "rule-type-id-1" => Object { + "authorizedConsumers": Object { + "consumer-a": Object { + "all": true, + "read": true, + }, }, }, - "category": "test", - "defaultActionGroupId": "default", - "enabledInLicense": true, - "hasAlertsMappings": false, - "hasFieldsForAAD": false, - "id": "myOtherAppAlertType", - "isExportable": true, - "minimumLicenseRequired": "basic", - "name": "myOtherAppAlertType", - "producer": "myOtherApp", - "recoveryActionGroup": Object { - "id": "recovered", - "name": "Recovered", - }, - "validLegacyConsumers": Array [], - }, - Object { - "actionGroups": Array [], - "actionVariables": undefined, - "authorizedConsumers": Object { - "myApp": Object { - "all": false, - "read": true, - }, - "myOtherApp": Object { - "all": false, - "read": true, + "rule-type-id-3" => Object { + "authorizedConsumers": Object { + "consumer-c": Object { + "all": false, + "read": true, + }, }, }, - "category": "test", - "defaultActionGroupId": "default", - "enabledInLicense": true, - "hasAlertsMappings": false, - "hasFieldsForAAD": false, - "id": "myAppAlertType", - "isExportable": true, - "minimumLicenseRequired": "basic", - "name": "myAppAlertType", - "producer": "myApp", - "recoveryActionGroup": Object { - "id": "recovered", - "name": "Recovered", - }, - "validLegacyConsumers": Array [], }, + "hasAllRequested": true, + "username": "some-user", } `); }); - it('omits types which have no consumers under which the operation is authorized', async () => { - const { authorization } = mockSecurity(); - const checkPrivileges: jest.MockedFunction< - ReturnType - > = jest.fn(); - authorization.checkPrivilegesDynamicallyWithRequest.mockReturnValue(checkPrivileges); + it('get authorized rule types with authorized consumers when consumers are not valid for a rule type', async () => { checkPrivileges.mockResolvedValueOnce({ username: 'some-user', - hasAllRequested: false, + hasAllRequested: true, privileges: { kibana: [ { - privilege: mockAuthorizationAction('myOtherAppAlertType', 'myApp', 'alert', 'create'), + privilege: mockAuthorizationAction('rule-type-id-1', 'consumer-a', 'rule', 'get'), authorized: true, }, { - privilege: mockAuthorizationAction( - 'myOtherAppAlertType', - 'myOtherApp', - 'alert', - 'create' - ), + privilege: mockAuthorizationAction('rule-type-id-1', 'consumer-a', 'rule', 'create'), authorized: true, }, { - privilege: mockAuthorizationAction('myAppAlertType', 'myApp', 'alert', 'create'), + privilege: mockAuthorizationAction('rule-type-id-2', 'consumer-b', 'rule', 'create'), authorized: false, }, { - privilege: mockAuthorizationAction('myAppAlertType', 'myOtherApp', 'alert', 'create'), - authorized: false, + privilege: mockAuthorizationAction('rule-type-id-3', 'consumer-d', 'rule', 'get'), + authorized: true, }, ], }, }); - const alertAuthorization = new AlertingAuthorization({ + const auth = await AlertingAuthorization.create({ request, ruleTypeRegistry, - authorization, getSpaceId, - allRegisteredConsumers, - ruleTypesConsumersMap, + features, + getSpace, + authorization: securityStart.authz, }); - ruleTypeRegistry.list.mockReturnValue(setOfAlertTypes); - await expect( - alertAuthorization.filterByRuleTypeAuthorization( - new Set([myAppAlertType, myOtherAppAlertType]), - [WriteOperations.Create], - AlertingAuthorizationEntity.Alert + expect( + // @ts-expect-error: need to test the private method + await auth._getAuthorizedRuleTypesWithAuthorizedConsumers( + new Set(ruleTypeIds), + [ReadOperations.Get, WriteOperations.Create], + AlertingAuthorizationEntity.Rule, + new Set(consumers) ) - ).resolves.toMatchInlineSnapshot(` - Set { - Object { - "actionGroups": Array [], - "actionVariables": undefined, - "authorizedConsumers": Object { - "myApp": Object { - "all": true, - "read": true, - }, - "myOtherApp": Object { - "all": true, - "read": true, + ).toMatchInlineSnapshot(` + Object { + "authorizedRuleTypes": Map { + "rule-type-id-1" => Object { + "authorizedConsumers": Object { + "consumer-a": Object { + "all": true, + "read": true, + }, }, }, - "category": "test", - "defaultActionGroupId": "default", - "enabledInLicense": true, - "hasAlertsMappings": false, - "hasFieldsForAAD": false, - "id": "myOtherAppAlertType", - "isExportable": true, - "minimumLicenseRequired": "basic", - "name": "myOtherAppAlertType", - "producer": "myOtherApp", - "recoveryActionGroup": Object { - "id": "recovered", - "name": "Recovered", - }, - "validLegacyConsumers": Array [], }, + "hasAllRequested": true, + "username": "some-user", } `); }); - }); - describe('getAugmentedRuleTypesWithAuthorization', () => { - const myOtherAppAlertType: RegistryRuleType = { - actionGroups: [], - actionVariables: undefined, - defaultActionGroupId: 'default', - minimumLicenseRequired: 'basic', - recoveryActionGroup: RecoveredActionGroup, - id: 'myOtherAppAlertType', - name: 'myOtherAppAlertType', - category: 'test', - producer: 'alerts', - enabledInLicense: true, - isExportable: true, - hasAlertsMappings: false, - hasFieldsForAAD: false, - validLegacyConsumers: [], - }; - const myAppAlertType: RegistryRuleType = { - actionGroups: [], - actionVariables: undefined, - defaultActionGroupId: 'default', - minimumLicenseRequired: 'basic', - recoveryActionGroup: RecoveredActionGroup, - id: 'myAppAlertType', - name: 'myAppAlertType', - category: 'test', - producer: 'myApp', - enabledInLicense: true, - isExportable: true, - hasAlertsMappings: true, - hasFieldsForAAD: true, - validLegacyConsumers: [], - }; - const mySecondAppAlertType: RegistryRuleType = { - actionGroups: [], - actionVariables: undefined, - defaultActionGroupId: 'default', - minimumLicenseRequired: 'basic', - recoveryActionGroup: RecoveredActionGroup, - id: 'mySecondAppAlertType', - name: 'mySecondAppAlertType', - category: 'test', - producer: 'myApp', - enabledInLicense: true, - isExportable: true, - hasAlertsMappings: false, - hasFieldsForAAD: false, - validLegacyConsumers: [], - }; - const setOfAlertTypes = new Set([myAppAlertType, myOtherAppAlertType, mySecondAppAlertType]); - beforeEach(() => { - features.getKibanaFeatures.mockReturnValue([ - mockFeatureWithConsumers('myOtherApp', [ - { ruleTypeId: 'myOtherAppAlertType', consumers: ['myApp'] }, - ]), - ]); - }); - it('it returns authorized rule types given a set of feature ids', async () => { - const { authorization } = mockSecurity(); - const checkPrivileges: jest.MockedFunction< - ReturnType - > = jest.fn(); - authorization.checkPrivilegesDynamicallyWithRequest.mockReturnValue(checkPrivileges); + it('filters out rule types that are not in the rule type registry but registered in the feature', async () => { + ruleTypeRegistry.has.mockImplementation((ruleTypeId: string) => false); + checkPrivileges.mockResolvedValueOnce({ username: 'some-user', - hasAllRequested: false, + hasAllRequested: true, privileges: { kibana: [ { - privilege: mockAuthorizationAction('myOtherAppAlertType', 'myApp', 'alert', 'find'), + privilege: mockAuthorizationAction('rule-type-id-1', 'consumer-a', 'rule', 'get'), authorized: true, }, ], }, }); - const alertAuthorization = new AlertingAuthorization({ + + const auth = await AlertingAuthorization.create({ request, ruleTypeRegistry, - authorization, getSpaceId, - allRegisteredConsumers, - ruleTypesConsumersMap, + features, + getSpace, + authorization: securityStart.authz, }); - ruleTypeRegistry.list.mockReturnValue(setOfAlertTypes); - await expect( - alertAuthorization.getAugmentedRuleTypesWithAuthorization( - ['myApp'], - [ReadOperations.Find, ReadOperations.Get, WriteOperations.Update], - AlertingAuthorizationEntity.Alert + expect( + // @ts-expect-error: need to test the private method + await auth._getAuthorizedRuleTypesWithAuthorizedConsumers( + new Set(['rule-type-id-1']), + [ReadOperations.Get, WriteOperations.Create], + AlertingAuthorizationEntity.Rule, + new Set(['consumer-a']) ) - ).resolves.toMatchInlineSnapshot(` + ).toMatchInlineSnapshot(` Object { - "authorizedRuleTypes": Set { - Object { - "actionGroups": Array [], - "actionVariables": undefined, - "authorizedConsumers": Object { - "myApp": Object { - "all": false, - "read": true, - }, - }, - "category": "test", - "defaultActionGroupId": "default", - "enabledInLicense": true, - "hasAlertsMappings": false, - "hasFieldsForAAD": false, - "id": "myOtherAppAlertType", - "isExportable": true, - "minimumLicenseRequired": "basic", - "name": "myOtherAppAlertType", - "producer": "alerts", - "recoveryActionGroup": Object { - "id": "recovered", - "name": "Recovered", - }, - "validLegacyConsumers": Array [], - }, - }, - "hasAllRequested": false, + "authorizedRuleTypes": Map {}, + "hasAllRequested": true, "username": "some-user", } `); }); - it('it returns all authorized if user has read, get and update alert privileges', async () => { - const { authorization } = mockSecurity(); - const checkPrivileges: jest.MockedFunction< - ReturnType - > = jest.fn(); - authorization.checkPrivilegesDynamicallyWithRequest.mockReturnValue(checkPrivileges); + it('filters out rule types that are registered in the rule type registry but not in the feature', async () => { + ruleTypeRegistry.has.mockImplementation((ruleTypeId: string) => true); + checkPrivileges.mockResolvedValueOnce({ username: 'some-user', - hasAllRequested: false, + hasAllRequested: true, privileges: { kibana: [ { - privilege: mockAuthorizationAction('myOtherAppAlertType', 'myApp', 'alert', 'find'), - authorized: true, - }, - { - privilege: mockAuthorizationAction('myOtherAppAlertType', 'myApp', 'alert', 'get'), - authorized: true, - }, - { - privilege: mockAuthorizationAction('myOtherAppAlertType', 'myApp', 'alert', 'update'), + privilege: mockAuthorizationAction('not-exist', 'consumer-a', 'rule', 'get'), authorized: true, }, ], }, }); - const alertAuthorization = new AlertingAuthorization({ + + const auth = await AlertingAuthorization.create({ request, ruleTypeRegistry, - authorization, getSpaceId, - allRegisteredConsumers, - ruleTypesConsumersMap, + features, + getSpace, + authorization: securityStart.authz, }); - ruleTypeRegistry.list.mockReturnValue(setOfAlertTypes); - await expect( - alertAuthorization.getAugmentedRuleTypesWithAuthorization( - ['myApp'], - [ReadOperations.Find, ReadOperations.Get, WriteOperations.Update], - AlertingAuthorizationEntity.Alert + expect( + // @ts-expect-error: need to test the private method + await auth._getAuthorizedRuleTypesWithAuthorizedConsumers( + new Set(['not-exist']), + [ReadOperations.Get, WriteOperations.Create], + AlertingAuthorizationEntity.Rule, + new Set(['consumer-a']) ) - ).resolves.toMatchInlineSnapshot(` + ).toMatchInlineSnapshot(` Object { - "authorizedRuleTypes": Set { - Object { - "actionGroups": Array [], - "actionVariables": undefined, - "authorizedConsumers": Object { - "myApp": Object { - "all": true, - "read": true, - }, - }, - "category": "test", - "defaultActionGroupId": "default", - "enabledInLicense": true, - "hasAlertsMappings": false, - "hasFieldsForAAD": false, - "id": "myOtherAppAlertType", - "isExportable": true, - "minimumLicenseRequired": "basic", - "name": "myOtherAppAlertType", - "producer": "alerts", - "recoveryActionGroup": Object { - "id": "recovered", - "name": "Recovered", - }, - "validLegacyConsumers": Array [], - }, - }, - "hasAllRequested": false, + "authorizedRuleTypes": Map {}, + "hasAllRequested": true, "username": "some-user", } `); }); + + it('call checkPrivileges with the correct actions', async () => { + const auth = await AlertingAuthorization.create({ + request, + ruleTypeRegistry, + getSpaceId, + features, + getSpace, + authorization: securityStart.authz, + }); + + // @ts-expect-error: need to test the private method + await auth._getAuthorizedRuleTypesWithAuthorizedConsumers( + new Set([...ruleTypeIds, 'rule-type-not-exist']), + [ReadOperations.Get, WriteOperations.Create], + AlertingAuthorizationEntity.Rule, + new Set([...consumers, 'consumer-not-exist']) + ); + + expect(checkPrivileges).toBeCalledTimes(1); + expect(checkPrivileges.mock.calls[0]).toMatchInlineSnapshot(` + Array [ + Object { + "kibana": Array [ + "rule-type-id-1/consumer-a/rule/get", + "rule-type-id-1/consumer-a/rule/create", + "rule-type-id-1/consumer-b/rule/get", + "rule-type-id-1/consumer-b/rule/create", + "rule-type-id-2/consumer-b/rule/get", + "rule-type-id-2/consumer-b/rule/create", + "rule-type-id-3/consumer-c/rule/get", + "rule-type-id-3/consumer-c/rule/create", + "rule-type-id-4/consumer-d/rule/get", + "rule-type-id-4/consumer-d/rule/create", + ], + }, + ] + `); + }); + + it('call checkPrivileges with the correct actions when the rule type does not exist in the registry', async () => { + ruleTypeRegistry.has.mockImplementation((ruleTypeId: string) => false); + + const auth = await AlertingAuthorization.create({ + request, + ruleTypeRegistry, + getSpaceId, + features, + getSpace, + authorization: securityStart.authz, + }); + + // @ts-expect-error: need to test the private method + await auth._getAuthorizedRuleTypesWithAuthorizedConsumers( + new Set(['rule-type-id-1']), + [ReadOperations.Get, WriteOperations.Create], + AlertingAuthorizationEntity.Rule, + new Set(['consumer-a']) + ); + + expect(checkPrivileges).toBeCalledTimes(1); + expect(checkPrivileges.mock.calls[0]).toMatchInlineSnapshot(` + Array [ + Object { + "kibana": Array [], + }, + ] + `); + }); + + it('call checkPrivileges with the correct actions when the rule type does not exist in the feature', async () => { + ruleTypeRegistry.has.mockImplementation((ruleTypeId: string) => true); + + const auth = await AlertingAuthorization.create({ + request, + ruleTypeRegistry, + getSpaceId, + features, + getSpace, + authorization: securityStart.authz, + }); + + // @ts-expect-error: need to test the private method + await auth._getAuthorizedRuleTypesWithAuthorizedConsumers( + new Set(['not-exist']), + [ReadOperations.Get, WriteOperations.Create], + AlertingAuthorizationEntity.Rule, + new Set(['consumer-a']) + ); + + expect(checkPrivileges).toBeCalledTimes(1); + expect(checkPrivileges.mock.calls[0]).toMatchInlineSnapshot(` + Array [ + Object { + "kibana": Array [], + }, + ] + `); + }); }); describe('8.11+', () => { @@ -2460,7 +3558,7 @@ describe('AlertingAuthorization', () => { alertAuthorization = new AlertingAuthorization({ request, ruleTypeRegistry, - authorization, + authorization: securityStart.authz, getSpaceId, allRegisteredConsumers, ruleTypesConsumersMap, @@ -2615,7 +3713,7 @@ describe('AlertingAuthorization', () => { alertAuthorization = new AlertingAuthorization({ request, ruleTypeRegistry, - authorization, + authorization: securityStart.authz, getSpaceId, allRegisteredConsumers, ruleTypesConsumersMap, @@ -2768,7 +3866,7 @@ describe('AlertingAuthorization', () => { alertAuthorization = new AlertingAuthorization({ request, ruleTypeRegistry, - authorization, + authorization: securityStart.authz, getSpaceId, allRegisteredConsumers, ruleTypesConsumersMap, diff --git a/x-pack/plugins/alerting/server/authorization/alerting_authorization.ts b/x-pack/plugins/alerting/server/authorization/alerting_authorization.ts index f992381b88ad14..8ad667306a671a 100644 --- a/x-pack/plugins/alerting/server/authorization/alerting_authorization.ts +++ b/x-pack/plugins/alerting/server/authorization/alerting_authorization.ts @@ -6,7 +6,6 @@ */ import Boom from '@hapi/boom'; -import { isEmpty } from 'lodash'; import { KibanaRequest } from '@kbn/core/server'; import { JsonObject } from '@kbn/utility-types'; import { KueryNode } from '@kbn/es-query'; @@ -14,52 +13,13 @@ import { SecurityPluginStart } from '@kbn/security-plugin/server'; import { PluginStartContract as FeaturesPluginStart } from '@kbn/features-plugin/server'; import { Space } from '@kbn/spaces-plugin/server'; import { RegistryRuleType } from '../rule_type_registry'; -import { ALERTING_FEATURE_ID, RuleTypeRegistry } from '../types'; +import { RuleTypeRegistry } from '../types'; import { asFiltersByRuleTypeAndConsumer, asFiltersBySpaceId, AlertingAuthorizationFilterOpts, } from './alerting_authorization_kuery'; - -export enum AlertingAuthorizationEntity { - Rule = 'rule', - Alert = 'alert', -} - -export enum ReadOperations { - Get = 'get', - GetRuleState = 'getRuleState', - GetAlertSummary = 'getAlertSummary', - GetExecutionLog = 'getExecutionLog', - GetActionErrorLog = 'getActionErrorLog', - Find = 'find', - GetAuthorizedAlertsIndices = 'getAuthorizedAlertsIndices', - GetRuleExecutionKPI = 'getRuleExecutionKPI', - GetBackfill = 'getBackfill', - FindBackfill = 'findBackfill', -} - -export enum WriteOperations { - Create = 'create', - Delete = 'delete', - Update = 'update', - UpdateApiKey = 'updateApiKey', - Enable = 'enable', - Disable = 'disable', - MuteAll = 'muteAll', - UnmuteAll = 'unmuteAll', - MuteAlert = 'muteAlert', - UnmuteAlert = 'unmuteAlert', - Snooze = 'snooze', - BulkEdit = 'bulkEdit', - BulkDelete = 'bulkDelete', - BulkEnable = 'bulkEnable', - BulkDisable = 'bulkDisable', - Unsnooze = 'unsnooze', - RunSoon = 'runSoon', - ScheduleBackfill = 'scheduleBackfill', - DeleteBackfill = 'deleteBackfill', -} +import { ReadOperations, WriteOperations, AlertingAuthorizationEntity } from './types'; export interface EnsureAuthorizedOpts { ruleTypeId: string; @@ -73,12 +33,13 @@ interface HasPrivileges { read: boolean; all: boolean; } + type AuthorizedConsumers = Record; export interface RegistryAlertTypeWithAuth extends RegistryRuleType { authorizedConsumers: AuthorizedConsumers; } -type IsAuthorizedAtProducerLevel = boolean; +export type AuthorizedRuleTypes = Map; export interface CreateOptions { ruleTypeRegistry: RuleTypeRegistry; @@ -146,6 +107,24 @@ export class AlertingAuthorization { const allRegisteredConsumers = new Set(); const ruleTypesConsumersMap = new Map>(); + /** + * Each feature configures a set of rule types. Each + * rule type configures its valid consumers. For example, + * + * { id: 'my-feature-id-1', alerting: [{ ruleTypeId: 'my-rule-type', consumers: ['consumer-a', 'consumer-b'] }] } + * { id: 'my-feature-id-2', alerting: [{ ruleTypeId: 'my-rule-type-2', consumers: ['consumer-a', 'consumer-d'] }] } + * + * In this loop we iterate over all features and we construct: + * a) a set that contains all registered consumers and + * b) a map that contains all valid consumers per rule type. + * We remove duplicates in the process. For example, + * + * allRegisteredConsumers: Set(1) { 'consumer-a', 'consumer-b', 'consumer-d' } + * ruleTypesConsumersMap: Map(1) { + * 'my-rule-type' => Set(1) { 'consumer-a', 'consumer-b' } + * 'my-rule-type-2' => Set(1) { 'consumer-a', 'consumer-d' } + * } + */ for (const feature of featuresWithAlertingConfigured) { if (feature.alerting) { for (const entry of feature.alerting) { @@ -182,20 +161,20 @@ export class AlertingAuthorization { } /* - * This method exposes the private 'augmentRuleTypesWithAuthorization' to be + * This method exposes the private '_getAuthorizedRuleTypesWithAuthorizedConsumers' to be * used by the RAC/Alerts client */ - public async getAugmentedRuleTypesWithAuthorization( + public async getAuthorizedRuleTypesWithAuthorizedConsumers( featureIds: readonly string[], operations: Array, authorizationEntity: AlertingAuthorizationEntity ): Promise<{ username?: string; hasAllRequested: boolean; - authorizedRuleTypes: Set; + authorizedRuleTypes: AuthorizedRuleTypes; }> { - return this.augmentRuleTypesWithAuthorization( - this.ruleTypeRegistry.list(), + return this._getAuthorizedRuleTypesWithAuthorizedConsumers( + new Set(this.ruleTypeRegistry.getAllTypes()), operations, authorizationEntity, new Set(featureIds) @@ -204,18 +183,12 @@ export class AlertingAuthorization { public async ensureAuthorized({ ruleTypeId, - consumer: legacyConsumer, + consumer, operation, entity, additionalPrivileges = [], }: EnsureAuthorizedOpts) { const { authorization } = this; - const ruleType = this.ruleTypeRegistry.get(ruleTypeId); - const consumer = getValidConsumer({ - validLegacyConsumers: ruleType.validLegacyConsumers, - legacyConsumer, - producer: ruleType.producer, - }); const isAvailableConsumer = this.allRegisteredConsumers.has(consumer); if (authorization && this.shouldCheckAuthorization()) { @@ -236,7 +209,7 @@ export class AlertingAuthorization { * as Privileged. * This check will ensure we don't accidentally let these through */ - throw Boom.forbidden(getUnauthorizedMessage(ruleTypeId, legacyConsumer, operation, entity)); + throw Boom.forbidden(getUnauthorizedMessage(ruleTypeId, consumer, operation, entity)); } if (!hasAllRequested) { @@ -266,14 +239,15 @@ export class AlertingAuthorization { public async getAuthorizedRuleTypes( authorizationEntity: AlertingAuthorizationEntity, featuresIds?: Set - ): Promise { - const { authorizedRuleTypes } = await this.augmentRuleTypesWithAuthorization( - this.ruleTypeRegistry.list(), + ): Promise { + const { authorizedRuleTypes } = await this._getAuthorizedRuleTypesWithAuthorizedConsumers( + new Set(this.ruleTypeRegistry.getAllTypes()), [ReadOperations.Find], authorizationEntity, featuresIds ); - return Array.from(authorizedRuleTypes); + + return authorizedRuleTypes; } public async getAuthorizationFilter( @@ -286,27 +260,19 @@ export class AlertingAuthorization { ensureRuleTypeIsAuthorized: (ruleTypeId: string, consumer: string, auth: string) => void; }> { if (this.authorization && this.shouldCheckAuthorization()) { - const { authorizedRuleTypes } = await this.augmentRuleTypesWithAuthorization( - this.ruleTypeRegistry.list(), + const { authorizedRuleTypes } = await this._getAuthorizedRuleTypesWithAuthorizedConsumers( + new Set(this.ruleTypeRegistry.getAllTypes()), [operation], authorizationEntity, featuresIds ); if (!authorizedRuleTypes.size) { - throw Boom.forbidden(`Unauthorized to find ${authorizationEntity}s for any rule types`); + throw Boom.forbidden( + `Unauthorized to ${operation} ${authorizationEntity}s for any rule types` + ); } - const authorizedRuleTypeIdsToConsumers = new Set( - [...authorizedRuleTypes].reduce((ruleTypeIdConsumerPairs, ruleType) => { - for (const consumer of Object.keys(ruleType.authorizedConsumers)) { - ruleTypeIdConsumerPairs.push(`${ruleType.id}/${consumer}/${authorizationEntity}`); - } - return ruleTypeIdConsumerPairs; - }, []) - ); - - const authorizedEntries: Map> = new Map(); return { filter: asFiltersByRuleTypeAndConsumer( authorizedRuleTypes, @@ -314,16 +280,17 @@ export class AlertingAuthorization { this.spaceId ) as JsonObject, ensureRuleTypeIsAuthorized: (ruleTypeId: string, consumer: string, authType: string) => { - if (!authorizedRuleTypeIdsToConsumers.has(`${ruleTypeId}/${consumer}/${authType}`)) { + if (!authorizedRuleTypes.has(ruleTypeId) || authType !== authorizationEntity) { + throw Boom.forbidden(getUnauthorizedMessage(ruleTypeId, consumer, operation, authType)); + } + + const authorizedRuleType = authorizedRuleTypes.get(ruleTypeId)!; + const authorizedConsumers = authorizedRuleType.authorizedConsumers; + + if (!authorizedConsumers[consumer]) { throw Boom.forbidden( - getUnauthorizedMessage(ruleTypeId, consumer, 'find', authorizationEntity) + getUnauthorizedMessage(ruleTypeId, consumer, operation, authorizationEntity) ); - } else { - if (authorizedEntries.has(ruleTypeId)) { - authorizedEntries.get(ruleTypeId)!.add(consumer); - } else { - authorizedEntries.set(ruleTypeId, new Set([consumer])); - } } }, }; @@ -336,99 +303,78 @@ export class AlertingAuthorization { } public async filterByRuleTypeAuthorization( - ruleTypes: Set, + ruleTypeIds: Set, operations: Array, authorizationEntity: AlertingAuthorizationEntity - ): Promise> { - const { authorizedRuleTypes } = await this.augmentRuleTypesWithAuthorization( - ruleTypes, + ): Promise { + const { authorizedRuleTypes } = await this._getAuthorizedRuleTypesWithAuthorizedConsumers( + ruleTypeIds, operations, authorizationEntity ); return authorizedRuleTypes; } - private async augmentRuleTypesWithAuthorization( - ruleTypes: Set, + private async _getAuthorizedRuleTypesWithAuthorizedConsumers( + ruleTypeIds: Set, operations: Array, authorizationEntity: AlertingAuthorizationEntity, consumers?: Set ): Promise<{ username?: string; hasAllRequested: boolean; - authorizedRuleTypes: Set; + authorizedRuleTypes: Map; }> { const requiredPrivileges = new Map< string, - [RegistryAlertTypeWithAuth, string, HasPrivileges, IsAuthorizedAtProducerLevel] + { ruleTypeId: string; consumer: string; operation: ReadOperations | WriteOperations } >(); - const authorizedRuleTypes = new Set(); - const addLegacyConsumerPrivileges = (legacyConsumer: string) => - legacyConsumer === ALERTING_FEATURE_ID || isEmpty(consumers); + const consumersToAuthorize: Set = consumers ?? this.allRegisteredConsumers; if (this.authorization && this.shouldCheckAuthorization()) { + const authorizedRuleTypes = new Map(); + const checkPrivileges = this.authorization.checkPrivilegesDynamicallyWithRequest( this.request ); - const ruleTypesWithAuthorization = Array.from( - this.augmentWithAuthorizedConsumers(ruleTypes, {}) - ); - - for (const ruleTypeWithAuth of ruleTypesWithAuthorization) { - if (!this.ruleTypesConsumersMap.has(ruleTypeWithAuth.id)) { + for (const ruleTypeId of ruleTypeIds) { + /** + * Skip if the ruleTypeId is not configured in any feature + * or it is not set int the rule type registry. + */ + if (!this.ruleTypesConsumersMap.has(ruleTypeId) || !this.ruleTypeRegistry.has(ruleTypeId)) { continue; } - for (const consumerToAuthorize of this.allRegisteredConsumers) { - const ruleTypeConsumers = this.ruleTypesConsumersMap.get(ruleTypeWithAuth.id); + const ruleType = this.ruleTypeRegistry.get(ruleTypeId)!; + + for (const consumerToAuthorize of consumersToAuthorize) { + const ruleTypeConsumers = this.ruleTypesConsumersMap.get(ruleTypeId); + /** + * Skip if the consumer is not configured for the + * specific rule type when configuring a feature + */ if (!ruleTypeConsumers?.has(consumerToAuthorize)) { continue; } for (const operation of operations) { requiredPrivileges.set( - this.authorization!.actions.alerting.get( - ruleTypeWithAuth.id, + this.authorization.actions.alerting.get( + ruleTypeId, consumerToAuthorize, authorizationEntity, operation ), - [ - ruleTypeWithAuth, - consumerToAuthorize, - hasPrivilegeByOperation(operation), - ruleTypeWithAuth.producer === consumerToAuthorize, - ] + { + ruleTypeId: ruleType.id, + consumer: consumerToAuthorize, + operation, + } ); - - // FUTURE ENGINEER - // We are just trying to add back the legacy consumers associated - // to the rule type to get back the privileges that was given at one point - if (!isEmpty(ruleTypeWithAuth.validLegacyConsumers)) { - ruleTypeWithAuth.validLegacyConsumers.forEach((legacyConsumer) => { - if (addLegacyConsumerPrivileges(legacyConsumer)) { - if (!allRegisteredConsumers[legacyConsumer]) { - allRegisteredConsumers[legacyConsumer] = { - read: true, - all: true, - }; - } - - requiredPrivileges.set( - this.authorization!.actions.alerting.get( - ruleTypeWithAuth.id, - legacyConsumer, - authorizationEntity, - operation - ), - [ruleTypeWithAuth, legacyConsumer, hasPrivilegeByOperation(operation), false] - ); - } - }); - } } } } @@ -439,62 +385,56 @@ export class AlertingAuthorization { for (const { authorized, privilege } of privileges.kibana) { if (authorized && requiredPrivileges.has(privilege)) { - const [ruleType, consumer, hasPrivileges, isAuthorizedAtProducerLevel] = - requiredPrivileges.get(privilege)!; - - if (consumersToAuthorize.has(consumer)) { - ruleType.authorizedConsumers[consumer] = mergeHasPrivileges( - hasPrivileges, - ruleType.authorizedConsumers[consumer] - ); - - if (isAuthorizedAtProducerLevel) { - // granting privileges under the producer automatically authorized the Rules Management UI as well - ruleType.validLegacyConsumers.forEach((legacyConsumer) => { - if (addLegacyConsumerPrivileges(legacyConsumer)) { - ruleType.authorizedConsumers[legacyConsumer] = mergeHasPrivileges( - hasPrivileges, - ruleType.authorizedConsumers[legacyConsumer] - ); - } - }); - } - - authorizedRuleTypes.add(ruleType); - } + const { ruleTypeId, consumer, operation } = requiredPrivileges.get(privilege)!; + + const authorizedRuleType = authorizedRuleTypes.get(ruleTypeId) ?? { + authorizedConsumers: {}, + }; + + const authorizedConsumers = authorizedRuleType.authorizedConsumers; + const mergedOperations = mergeHasPrivileges( + getPrivilegesFromOperation(operation), + authorizedConsumers[consumer] + ); + + authorizedRuleTypes.set(ruleTypeId, { + authorizedConsumers: { + ...authorizedConsumers, + [consumer]: mergedOperations, + }, + }); } } return { username, hasAllRequested, - authorizedRuleTypes: - hasAllRequested && consumers === undefined - ? // has access to all features - this.augmentWithAuthorizedConsumers(authorizedRuleTypes, allRegisteredConsumers) - : authorizedRuleTypes, + authorizedRuleTypes, }; } else { return { hasAllRequested: true, - authorizedRuleTypes: this.augmentWithAuthorizedConsumers( - new Set([...ruleTypes].filter((ruleType) => consumersToAuthorize.has(ruleType.producer))), - allRegisteredConsumers - ), + authorizedRuleTypes: this.getRegisteredRuleTypesWithAllRegisteredConsumers(ruleTypeIds), }; } } - private augmentWithAuthorizedConsumers( - ruleTypes: Set, - authorizedConsumers: AuthorizedConsumers - ): Set { - return new Set( - Array.from(ruleTypes).map((ruleType) => ({ - ...ruleType, - authorizedConsumers: { ...authorizedConsumers }, - })) - ); + private getRegisteredRuleTypesWithAllRegisteredConsumers(ruleTypeIds: Set) { + const authorizedRuleTypes = new Map(); + const authorizedConsumers = getConsumersWithPrivileges(this.allRegisteredConsumers, { + all: true, + read: true, + }); + + Array.from(this.ruleTypesConsumersMap.keys()) + .filter((ruleTypeId) => ruleTypeIds.has(ruleTypeId)) + .forEach((ruleTypeId) => { + authorizedRuleTypes.set(ruleTypeId, { + authorizedConsumers, + }); + }); + + return authorizedRuleTypes; } } @@ -505,7 +445,7 @@ function mergeHasPrivileges(left: HasPrivileges, right?: HasPrivileges): HasPriv }; } -function hasPrivilegeByOperation(operation: ReadOperations | WriteOperations): HasPrivileges { +function getPrivilegesFromOperation(operation: ReadOperations | WriteOperations): HasPrivileges { const read = Object.values(ReadOperations).includes(operation as unknown as ReadOperations); const all = Object.values(WriteOperations).includes(operation as unknown as WriteOperations); return { @@ -514,11 +454,11 @@ function hasPrivilegeByOperation(operation: ReadOperations | WriteOperations): H }; } -function asAuthorizedConsumers( - consumers: string[], +function getConsumersWithPrivileges( + consumers: Set, hasPrivileges: HasPrivileges ): AuthorizedConsumers { - return consumers.reduce((acc, feature) => { + return Array.from(consumers).reduce((acc, feature) => { acc[feature] = hasPrivileges; return acc; }, {}); @@ -532,16 +472,3 @@ function getUnauthorizedMessage( ): string { return `Unauthorized by "${scope}" to ${operation} "${alertTypeId}" ${entity}`; } - -export const getValidConsumer = ({ - validLegacyConsumers, - legacyConsumer, - producer, -}: { - validLegacyConsumers: string[]; - legacyConsumer: string; - producer: string; -}): string => - legacyConsumer === ALERTING_FEATURE_ID || validLegacyConsumers.includes(legacyConsumer) - ? producer - : legacyConsumer; diff --git a/x-pack/plugins/alerting/server/authorization/alerting_authorization_kuery.ts b/x-pack/plugins/alerting/server/authorization/alerting_authorization_kuery.ts index 01e30dfb38327b..666059c7a7b479 100644 --- a/x-pack/plugins/alerting/server/authorization/alerting_authorization_kuery.ts +++ b/x-pack/plugins/alerting/server/authorization/alerting_authorization_kuery.ts @@ -9,7 +9,7 @@ import { remove } from 'lodash'; import { EsQueryConfig, nodeBuilder, toElasticsearchQuery, KueryNode } from '@kbn/es-query'; import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; -import { RegistryAlertTypeWithAuth } from './alerting_authorization'; +import { AuthorizedRuleTypes } from './alerting_authorization'; export enum AlertingAuthorizationFilterType { KQL = 'kql', @@ -35,36 +35,39 @@ const esQueryConfig: EsQueryConfig = { }; export function asFiltersByRuleTypeAndConsumer( - ruleTypes: Set, + ruleTypes: AuthorizedRuleTypes, opts: AlertingAuthorizationFilterOpts, spaceId: string | undefined ): KueryNode | estypes.QueryDslQueryContainer { const kueryNode = nodeBuilder.or( - Array.from(ruleTypes).reduce((filters, { id, authorizedConsumers }) => { - ensureFieldIsSafeForQuery('ruleTypeId', id); - - const andNodes: KueryNode[] = [nodeBuilder.is(opts.fieldNames.ruleTypeId, id)]; - - const authorizedConsumersKeys = Object.keys(authorizedConsumers); - if (authorizedConsumersKeys.length) { - andNodes.push( - nodeBuilder.or( - authorizedConsumersKeys.map((consumer) => { - ensureFieldIsSafeForQuery('consumer', consumer); - return nodeBuilder.is(opts.fieldNames.consumer, consumer); - }) - ) - ); - } - - if (opts.fieldNames.spaceIds != null && spaceId != null) { - andNodes.push(nodeBuilder.is(opts.fieldNames.spaceIds, spaceId)); - } - - filters.push(nodeBuilder.and(andNodes)); - - return filters; - }, []) + Array.from(ruleTypes.entries()).reduce( + (filters, [id, { authorizedConsumers }]) => { + ensureFieldIsSafeForQuery('ruleTypeId', id); + + const andNodes: KueryNode[] = [nodeBuilder.is(opts.fieldNames.ruleTypeId, id)]; + + const authorizedConsumersKeys = Object.keys(authorizedConsumers); + if (authorizedConsumersKeys.length) { + andNodes.push( + nodeBuilder.or( + authorizedConsumersKeys.map((consumer) => { + ensureFieldIsSafeForQuery('consumer', consumer); + return nodeBuilder.is(opts.fieldNames.consumer, consumer); + }) + ) + ); + } + + if (opts.fieldNames.spaceIds != null && spaceId != null) { + andNodes.push(nodeBuilder.is(opts.fieldNames.spaceIds, spaceId)); + } + + filters.push(nodeBuilder.and(andNodes)); + + return filters; + }, + [] + ) ); if (opts.type === AlertingAuthorizationFilterType.ESDSL) { diff --git a/x-pack/plugins/alerting/server/authorization/types.ts b/x-pack/plugins/alerting/server/authorization/types.ts new file mode 100644 index 00000000000000..77357456c74b60 --- /dev/null +++ b/x-pack/plugins/alerting/server/authorization/types.ts @@ -0,0 +1,46 @@ +/* + * 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 enum AlertingAuthorizationEntity { + Rule = 'rule', + Alert = 'alert', +} + +export enum ReadOperations { + Get = 'get', + GetRuleState = 'getRuleState', + GetAlertSummary = 'getAlertSummary', + GetExecutionLog = 'getExecutionLog', + GetActionErrorLog = 'getActionErrorLog', + Find = 'find', + GetAuthorizedAlertsIndices = 'getAuthorizedAlertsIndices', + GetRuleExecutionKPI = 'getRuleExecutionKPI', + GetBackfill = 'getBackfill', + FindBackfill = 'findBackfill', +} + +export enum WriteOperations { + Create = 'create', + Delete = 'delete', + Update = 'update', + UpdateApiKey = 'updateApiKey', + Enable = 'enable', + Disable = 'disable', + MuteAll = 'muteAll', + UnmuteAll = 'unmuteAll', + MuteAlert = 'muteAlert', + UnmuteAlert = 'unmuteAlert', + Snooze = 'snooze', + BulkEdit = 'bulkEdit', + BulkDelete = 'bulkDelete', + BulkEnable = 'bulkEnable', + BulkDisable = 'bulkDisable', + Unsnooze = 'unsnooze', + RunSoon = 'runSoon', + ScheduleBackfill = 'scheduleBackfill', + DeleteBackfill = 'deleteBackfill', +} diff --git a/x-pack/plugins/alerting/server/rules_client/lib/get_authorization_filter.ts b/x-pack/plugins/alerting/server/rules_client/lib/get_authorization_filter.ts index b9cc41a0fd7c42..591ea70972ed9b 100644 --- a/x-pack/plugins/alerting/server/rules_client/lib/get_authorization_filter.ts +++ b/x-pack/plugins/alerting/server/rules_client/lib/get_authorization_filter.ts @@ -6,11 +6,11 @@ */ import { withSpan } from '@kbn/apm-utils'; -import { AlertingAuthorizationEntity } from '../../authorization'; import { ruleAuditEvent, RuleAuditAction } from '../common/audit_events'; import { RulesClientContext } from '../types'; import { alertingAuthorizationFilterOpts } from '../common/constants'; import { BulkAction } from '../types'; +import { AlertingAuthorizationEntity } from '../../authorization/types'; export const getAuthorizationFilter = async ( context: RulesClientContext, diff --git a/x-pack/plugins/rule_registry/server/search_strategy/search_strategy.ts b/x-pack/plugins/rule_registry/server/search_strategy/search_strategy.ts index 49e7d706b31174..477baa21b230d3 100644 --- a/x-pack/plugins/rule_registry/server/search_strategy/search_strategy.ts +++ b/x-pack/plugins/rule_registry/server/search_strategy/search_strategy.ts @@ -13,7 +13,7 @@ import { ENHANCED_ES_SEARCH_STRATEGY } from '@kbn/data-plugin/common'; import { ISearchStrategy, PluginStart } from '@kbn/data-plugin/server'; import { ReadOperations, - PluginStartContract as AlertingStart, + AlertingServerStart, AlertingAuthorizationEntity, } from '@kbn/alerting-plugin/server'; import { SecurityPluginSetup } from '@kbn/security-plugin/server'; @@ -38,7 +38,7 @@ const EXCLUDED_RULE_TYPE_IDS = ['siem.notifications']; export const ruleRegistrySearchStrategyProvider = ( data: PluginStart, - alerting: AlertingStart, + alerting: AlertingServerStart, logger: Logger, security?: SecurityPluginSetup, spaces?: SpacesPluginStart From 0bb255bfc58e9f6cb2acb0e7cc946b3833d5a3eb Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Tue, 16 Jul 2024 13:21:41 +0300 Subject: [PATCH 012/106] Add more tests --- .../alerting_authorization.test.ts | 389 ++---------------- .../authorization/alerting_authorization.ts | 7 +- 2 files changed, 40 insertions(+), 356 deletions(-) diff --git a/x-pack/plugins/alerting/server/authorization/alerting_authorization.test.ts b/x-pack/plugins/alerting/server/authorization/alerting_authorization.test.ts index f44b40f647a6bc..7993ddc412b23f 100644 --- a/x-pack/plugins/alerting/server/authorization/alerting_authorization.test.ts +++ b/x-pack/plugins/alerting/server/authorization/alerting_authorization.test.ts @@ -692,66 +692,6 @@ describe('AlertingAuthorization', () => { securityStart.authz.checkPrivilegesDynamicallyWithRequest.mockReturnValue(checkPrivileges); features = featuresPluginMock.createStart(); - - const alertingGet = securityStart.authz.actions.alerting.get as jest.Mock; - alertingGet.mockImplementation(mockAuthorizationAction); - - ruleTypeRegistry = ruleTypeRegistryMock.create(); - ruleTypeRegistry.getAllTypes.mockReturnValue(ruleTypeIds); - ruleTypeRegistry.has.mockImplementation((ruleTypeId: string) => - ruleTypeIds.includes(ruleTypeId) - ); - - // @ts-expect-error: only the id is needed for the tests - ruleTypeRegistry.get.mockImplementation((ruleTypeId: string) => ({ id: ruleTypeId })); - }); - - it('omits filter when there is no authorization api', async () => { - const alertAuthorization = new AlertingAuthorization({ - request, - ruleTypeRegistry, - getSpaceId, - allRegisteredConsumers, - ruleTypesConsumersMap, - }); - - const { filter, ensureRuleTypeIsAuthorized } = - await alertAuthorization.getFindAuthorizationFilter(AlertingAuthorizationEntity.Rule, { - type: AlertingAuthorizationFilterType.KQL, - fieldNames: { - ruleTypeId: 'ruleId', - consumer: 'consumer', - }, - }); - - expect(() => ensureRuleTypeIsAuthorized('someMadeUpType', 'myApp', 'rule')).not.toThrow(); - expect(filter).toEqual(undefined); - }); - - it('ensureRuleTypeIsAuthorized is no-op when there is no authorization api', async () => { - const alertAuthorization = new AlertingAuthorization({ - request, - ruleTypeRegistry, - getSpaceId, - allRegisteredConsumers, - ruleTypesConsumersMap, - }); - - const { ensureRuleTypeIsAuthorized } = await alertAuthorization.getFindAuthorizationFilter( - AlertingAuthorizationEntity.Rule, - { - type: AlertingAuthorizationFilterType.KQL, - fieldNames: { - ruleTypeId: 'ruleId', - consumer: 'consumer', - }, - } - ); - - expect(() => ensureRuleTypeIsAuthorized('someMadeUpType', 'myApp', 'rule')).not.toThrow(); - }); - - it('creates a filter based on the privileged types', async () => { features.getKibanaFeatures.mockReturnValue([ mockFeatureWithConsumers('feature-id-1', [ { @@ -778,6 +718,20 @@ describe('AlertingAuthorization', () => { ]), ]); + const alertingGet = securityStart.authz.actions.alerting.get as jest.Mock; + alertingGet.mockImplementation(mockAuthorizationAction); + + ruleTypeRegistry = ruleTypeRegistryMock.create(); + ruleTypeRegistry.getAllTypes.mockReturnValue(ruleTypeIds); + ruleTypeRegistry.has.mockImplementation((ruleTypeId: string) => + ruleTypeIds.includes(ruleTypeId) + ); + + // @ts-expect-error: only the id is needed for the tests + ruleTypeRegistry.get.mockImplementation((ruleTypeId: string) => ({ id: ruleTypeId })); + }); + + it('creates a filter based on the privileged types', async () => { const auth = await AlertingAuthorization.create({ request, ruleTypeRegistry, @@ -860,293 +814,9 @@ describe('AlertingAuthorization', () => { `"((path.to.rule_type_id: rule-type-id-1 AND (consumer-field: alerts OR consumer-field: consumer-a OR consumer-field: consumer-b)) OR (path.to.rule_type_id: rule-type-id-2 AND (consumer-field: alerts OR consumer-field: consumer-b)) OR (path.to.rule_type_id: rule-type-id-3 AND (consumer-field: consumer-c OR consumer-field: alerts)))"` ); }); - - it('throws if user has no privileges to any rule type', async () => { - checkPrivileges.mockResolvedValueOnce({ - username: 'some-user', - hasAllRequested: false, - privileges: { - kibana: [ - { - privilege: mockAuthorizationAction('myType', 'myOtherApp', 'rule', 'create'), - authorized: false, - }, - { - privilege: mockAuthorizationAction('myType', 'myApp', 'rule', 'create'), - authorized: false, - }, - ], - }, - }); - - const auth = await AlertingAuthorization.create({ - request, - ruleTypeRegistry, - getSpaceId, - features, - getSpace, - authorization: securityStart.authz, - }); - - await expect( - auth.getFindAuthorizationFilter(AlertingAuthorizationEntity.Rule, { - type: AlertingAuthorizationFilterType.KQL, - fieldNames: { - ruleTypeId: 'path.to.rule_type_id', - consumer: 'consumer-field', - }, - }) - ).rejects.toThrowErrorMatchingInlineSnapshot( - `"Unauthorized to find rules for any rule types"` - ); - }); - - it('creates an `ensureRuleTypeIsAuthorized` function which throws if type is unauthorized', async () => { - features.getKibanaFeatures.mockReturnValue([ - mockFeatureWithConsumers('myApp', [ - { ruleTypeId: 'myOtherAppAlertType', consumers: ['myApp'] }, - { ruleTypeId: 'myAppAlertType', consumers: ['myApp'] }, - ]), - mockFeatureWithConsumers('myOtherApp', [ - { ruleTypeId: 'myOtherAppAlertType', consumers: ['myOtherApp'] }, - { ruleTypeId: 'myAppAlertType', consumers: ['myOtherApp'] }, - ]), - ]); - - checkPrivileges.mockResolvedValueOnce({ - username: 'some-user', - hasAllRequested: false, - privileges: { - kibana: [ - { - privilege: mockAuthorizationAction('myOtherAppAlertType', 'myApp', 'alert', 'find'), - authorized: true, - }, - { - privilege: mockAuthorizationAction( - 'myOtherAppAlertType', - 'myOtherApp', - 'alert', - 'find' - ), - authorized: false, - }, - { - privilege: mockAuthorizationAction('myAppAlertType', 'myApp', 'alert', 'find'), - authorized: true, - }, - { - privilege: mockAuthorizationAction('myAppAlertType', 'myOtherApp', 'alert', 'find'), - authorized: false, - }, - ], - }, - }); - - const auth = await AlertingAuthorization.create({ - request, - ruleTypeRegistry, - getSpaceId, - features, - getSpace, - authorization: securityStart.authz, - }); - - const { ensureRuleTypeIsAuthorized } = await auth.getFindAuthorizationFilter( - AlertingAuthorizationEntity.Alert, - { - type: AlertingAuthorizationFilterType.KQL, - fieldNames: { - ruleTypeId: 'ruleId', - consumer: 'consumer', - }, - } - ); - - expect(() => { - ensureRuleTypeIsAuthorized('myAppAlertType', 'myOtherApp', 'alert'); - }).toThrowErrorMatchingInlineSnapshot( - `"Unauthorized by \\"myOtherApp\\" to find \\"myAppAlertType\\" alert"` - ); - }); - - it('creates an `ensureRuleTypeIsAuthorized` function which is no-op if type is authorized', async () => { - features.getKibanaFeatures.mockReturnValue([ - mockFeatureWithConsumers('myApp', [ - { ruleTypeId: 'myOtherAppAlertType', consumers: ['myApp'] }, - { ruleTypeId: 'myAppAlertType', consumers: ['myApp'] }, - ]), - mockFeatureWithConsumers('myOtherApp', [ - { ruleTypeId: 'myOtherApp', consumers: ['myOtherApp'] }, - ]), - ]); - - checkPrivileges.mockResolvedValueOnce({ - username: 'some-user', - hasAllRequested: false, - privileges: { - kibana: [ - { - privilege: mockAuthorizationAction('myOtherAppAlertType', 'myApp', 'rule', 'find'), - authorized: true, - }, - { - privilege: mockAuthorizationAction( - 'myOtherAppAlertType', - 'myOtherApp', - 'rule', - 'find' - ), - authorized: false, - }, - { - privilege: mockAuthorizationAction('myAppAlertType', 'myApp', 'rule', 'find'), - authorized: true, - }, - { - privilege: mockAuthorizationAction('myAppAlertType', 'myOtherApp', 'rule', 'find'), - authorized: true, - }, - ], - }, - }); - - const auth = await AlertingAuthorization.create({ - request, - ruleTypeRegistry, - getSpaceId, - features, - getSpace, - authorization: securityStart.authz, - }); - - const { ensureRuleTypeIsAuthorized } = await auth.getFindAuthorizationFilter( - AlertingAuthorizationEntity.Rule, - { - type: AlertingAuthorizationFilterType.KQL, - fieldNames: { - ruleTypeId: 'ruleId', - consumer: 'consumer', - }, - } - ); - - expect(() => { - ensureRuleTypeIsAuthorized('myAppAlertType', 'myOtherApp', 'rule'); - }).not.toThrow(); - }); - - it('creates an `logSuccessfulAuthorization` function which logs every authorized type', async () => { - features.getKibanaFeatures.mockReturnValue([ - mockFeatureWithConsumers('myApp', [ - { ruleTypeId: 'myOtherAppAlertType', consumers: ['myApp'] }, - { ruleTypeId: 'myAppAlertType', consumers: ['myApp'] }, - { ruleTypeId: 'mySecondAppAlertType', consumers: ['myApp'] }, - ]), - mockFeatureWithConsumers('myOtherApp', [ - { ruleTypeId: 'mySecondAppAlertType', consumers: ['myOtherApp'] }, - { ruleTypeId: 'myAppAlertType', consumers: ['myOtherApp'] }, - ]), - ]); - - checkPrivileges.mockResolvedValueOnce({ - username: 'some-user', - hasAllRequested: false, - privileges: { - kibana: [ - { - privilege: mockAuthorizationAction('myOtherAppAlertType', 'myApp', 'rule', 'find'), - authorized: true, - }, - { - privilege: mockAuthorizationAction( - 'myOtherAppAlertType', - 'myOtherApp', - 'rule', - 'find' - ), - authorized: false, - }, - { - privilege: mockAuthorizationAction('myAppAlertType', 'myApp', 'rule', 'find'), - authorized: true, - }, - { - privilege: mockAuthorizationAction('myAppAlertType', 'myOtherApp', 'rule', 'find'), - authorized: true, - }, - { - privilege: mockAuthorizationAction('mySecondAppAlertType', 'myApp', 'rule', 'find'), - authorized: true, - }, - { - privilege: mockAuthorizationAction( - 'mySecondAppAlertType', - 'myOtherApp', - 'rule', - 'find' - ), - authorized: true, - }, - ], - }, - }); - - const auth = await AlertingAuthorization.create({ - request, - ruleTypeRegistry, - getSpaceId, - features, - getSpace, - authorization: securityStart.authz, - }); - - const { ensureRuleTypeIsAuthorized } = await auth.getFindAuthorizationFilter( - AlertingAuthorizationEntity.Rule, - { - type: AlertingAuthorizationFilterType.KQL, - fieldNames: { - ruleTypeId: 'ruleId', - consumer: 'consumer', - }, - } - ); - - expect(() => { - ensureRuleTypeIsAuthorized('myAppAlertType', 'myOtherApp', 'rule'); - ensureRuleTypeIsAuthorized('mySecondAppAlertType', 'myOtherApp', 'rule'); - ensureRuleTypeIsAuthorized('myAppAlertType', 'myOtherApp', 'rule'); - }).not.toThrow(); - }); - - // This is a specific use case currently for alerts as data - // Space ids are stored in the alerts documents and even if security is disabled - // still need to consider the users space privileges - it('creates a spaceId only filter if security is disabled, but require space awareness', async () => { - const auth = await AlertingAuthorization.create({ - request, - ruleTypeRegistry, - getSpaceId, - features, - getSpace, - }); - - const { filter } = await auth.getFindAuthorizationFilter(AlertingAuthorizationEntity.Alert, { - type: AlertingAuthorizationFilterType.ESDSL, - fieldNames: { - ruleTypeId: 'ruleId', - consumer: 'consumer', - spaceIds: 'path.to.space.id', - }, - }); - - expect(filter).toEqual({ - bool: { minimum_should_match: 1, should: [{ match: { 'path.to.space.id': 'space1' } }] }, - }); - }); }); - describe.only('getAuthorizationFilter', () => { + describe('getAuthorizationFilter', () => { type CheckPrivilegesResponseWithoutES = Omit & { privileges: Omit; }; @@ -1235,6 +905,9 @@ describe('AlertingAuthorization', () => { expect(filter).toEqual(undefined); }); + // This is a specific use case currently for alerts as data + // Space ids are stored in the alerts documents and even if security is disabled + // still need to consider the users space privileges it('gets the filter correctly with no security and spaceIds in the fields names', async () => { const auth = await AlertingAuthorization.create({ request, @@ -1251,13 +924,15 @@ describe('AlertingAuthorization', () => { fieldNames: { ruleTypeId: 'ruleId', consumer: 'consumer', - spaceIds: 'space-id', + spaceIds: 'path.to.space.id', }, }, ReadOperations.Get ); - expect(toKqlExpression(filter as KueryNode)).toMatchInlineSnapshot(`"space-id: space1"`); + expect(toKqlExpression(filter as KueryNode)).toMatchInlineSnapshot( + `"path.to.space.id: space1"` + ); }); it('gets the filter correctly with security disabled', async () => { @@ -1392,6 +1067,10 @@ describe('AlertingAuthorization', () => { privilege: mockAuthorizationAction('rule-type-id-1', 'consumer-a', 'rule', 'get'), authorized: true, }, + { + privilege: mockAuthorizationAction('rule-type-id-2', 'consumer-b', 'rule', 'get'), + authorized: true, + }, ], }, }); @@ -1421,6 +1100,10 @@ describe('AlertingAuthorization', () => { expect(() => ensureRuleTypeIsAuthorized('rule-type-id-1', 'consumer-a', 'rule') ).not.toThrow(); + + expect(() => + ensureRuleTypeIsAuthorized('rule-type-id-2', 'consumer-b', 'rule') + ).not.toThrow(); }); it('throws if the rule type is not authorized', async () => { @@ -1554,7 +1237,7 @@ describe('AlertingAuthorization', () => { }); }); - describe('filterByRuleTypeAuthorization', () => { + describe('getAuthorizedRuleTypesForAllConsumers', () => { const myOtherAppAlertType: RegistryRuleType = { actionGroups: [], actionVariables: undefined, @@ -1617,7 +1300,7 @@ describe('AlertingAuthorization', () => { ruleTypeRegistry.list.mockReturnValue(setOfAlertTypes); await expect( - alertAuthorization.filterByRuleTypeAuthorization( + alertAuthorization.getAuthorizedRuleTypesForAllConsumers( new Set([myAppAlertType, myOtherAppAlertType]), [WriteOperations.Create], AlertingAuthorizationEntity.Rule @@ -1749,7 +1432,7 @@ describe('AlertingAuthorization', () => { ruleTypeRegistry.list.mockReturnValue(setOfAlertTypes); await expect( - alertAuthorization.filterByRuleTypeAuthorization( + alertAuthorization.getAuthorizedRuleTypesForAllConsumers( new Set([myAppAlertType, myOtherAppAlertType]), [WriteOperations.Create], AlertingAuthorizationEntity.Rule @@ -1848,7 +1531,7 @@ describe('AlertingAuthorization', () => { ruleTypeRegistry.list.mockReturnValue(setOfAlertTypes); await expect( - alertAuthorization.filterByRuleTypeAuthorization( + alertAuthorization.getAuthorizedRuleTypesForAllConsumers( new Set([myAppAlertType]), [WriteOperations.Create], AlertingAuthorizationEntity.Alert @@ -1952,7 +1635,7 @@ describe('AlertingAuthorization', () => { ruleTypeRegistry.list.mockReturnValue(setOfAlertTypes); await expect( - alertAuthorization.filterByRuleTypeAuthorization( + alertAuthorization.getAuthorizedRuleTypesForAllConsumers( new Set([myAppAlertType, myOtherAppAlertType]), [WriteOperations.Create, ReadOperations.Get], AlertingAuthorizationEntity.Alert @@ -2068,7 +1751,7 @@ describe('AlertingAuthorization', () => { ruleTypeRegistry.list.mockReturnValue(setOfAlertTypes); await expect( - alertAuthorization.filterByRuleTypeAuthorization( + alertAuthorization.getAuthorizedRuleTypesForAllConsumers( new Set([myAppAlertType, myOtherAppAlertType]), [WriteOperations.Create], AlertingAuthorizationEntity.Alert diff --git a/x-pack/plugins/alerting/server/authorization/alerting_authorization.ts b/x-pack/plugins/alerting/server/authorization/alerting_authorization.ts index 8ad667306a671a..d51c01f18efcaa 100644 --- a/x-pack/plugins/alerting/server/authorization/alerting_authorization.ts +++ b/x-pack/plugins/alerting/server/authorization/alerting_authorization.ts @@ -164,7 +164,7 @@ export class AlertingAuthorization { * This method exposes the private '_getAuthorizedRuleTypesWithAuthorizedConsumers' to be * used by the RAC/Alerts client */ - public async getAuthorizedRuleTypesWithAuthorizedConsumers( + public async getAllAuthorizedRuleTypesWithAuthorizedConsumers( featureIds: readonly string[], operations: Array, authorizationEntity: AlertingAuthorizationEntity @@ -236,7 +236,7 @@ export class AlertingAuthorization { ); } - public async getAuthorizedRuleTypes( + public async getAllAuthorizedRuleTypesFindOperation( authorizationEntity: AlertingAuthorizationEntity, featuresIds?: Set ): Promise { @@ -302,7 +302,7 @@ export class AlertingAuthorization { }; } - public async filterByRuleTypeAuthorization( + public async getAuthorizedRuleTypesForAllConsumers( ruleTypeIds: Set, operations: Array, authorizationEntity: AlertingAuthorizationEntity @@ -312,6 +312,7 @@ export class AlertingAuthorization { operations, authorizationEntity ); + return authorizedRuleTypes; } From 736a63eda5bc1b019a52150d1f4848d51d6dba2b Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Tue, 16 Jul 2024 18:31:39 +0300 Subject: [PATCH 013/106] Finalize alerting auth unit tests and functionality --- .../alerting_authorization.test.ts | 1657 ++--------------- .../authorization/alerting_authorization.ts | 4 +- 2 files changed, 169 insertions(+), 1492 deletions(-) diff --git a/x-pack/plugins/alerting/server/authorization/alerting_authorization.test.ts b/x-pack/plugins/alerting/server/authorization/alerting_authorization.test.ts index 7993ddc412b23f..315b892e11712d 100644 --- a/x-pack/plugins/alerting/server/authorization/alerting_authorization.test.ts +++ b/x-pack/plugins/alerting/server/authorization/alerting_authorization.test.ts @@ -5,29 +5,18 @@ * 2.0. */ -import { fromKueryExpression, KueryNode, toKqlExpression } from '@kbn/es-query'; +import { KueryNode, toKqlExpression } from '@kbn/es-query'; import { KibanaRequest } from '@kbn/core/server'; import { ruleTypeRegistryMock } from '../rule_type_registry.mock'; import { securityMock } from '@kbn/security-plugin/server/mocks'; import { KibanaFeature } from '@kbn/features-plugin/server'; import { featuresPluginMock } from '@kbn/features-plugin/server/mocks'; import { AlertingAuthorization } from './alerting_authorization'; -import { RecoveredActionGroup } from '../../common'; -import { NormalizedRuleType, RegistryRuleType } from '../rule_type_registry'; import { AlertingAuthorizationFilterType } from './alerting_authorization_kuery'; -import { schema } from '@kbn/config-schema'; import { httpServerMock } from '@kbn/core-http-server-mocks'; -import { - CheckPrivilegesDynamically, - CheckPrivilegesResponse, - SecurityPluginStart, -} from '@kbn/security-plugin-types-server'; +import { CheckPrivilegesResponse } from '@kbn/security-plugin-types-server'; import type { PluginStartContract as FeaturesPluginStart } from '@kbn/features-plugin/server'; import { WriteOperations, AlertingAuthorizationEntity, ReadOperations } from './types'; -import { SubFeature } from '@kbn/features-plugin/common'; - -const getSpace = jest.fn(); -const getSpaceId = () => 'space1'; const mockAuthorizationAction = ( ruleType: string, @@ -36,19 +25,6 @@ const mockAuthorizationAction = ( operation: string ) => `${ruleType}/${consumer}/${entity}/${operation}`; -function mockSecurity() { - const security = securityMock.createStart(); - const authorization = security.authz; - // typescript is having trouble inferring jest's automocking - ( - authorization.actions.alerting.get as jest.MockedFunction< - typeof authorization.actions.alerting.get - > - ).mockImplementation(mockAuthorizationAction); - authorization.mode.useRbacForRequest.mockReturnValue(true); - return { authorization }; -} - function mockFeatureWithConsumers( appName: string, alertingFeatures?: ReadonlyArray<{ ruleTypeId: string; consumers: readonly string[] }>, @@ -153,61 +129,83 @@ function mockFeatureWithConsumers( }); } -const myAppFeature = mockFeatureWithConsumers('myApp', [ - { ruleTypeId: 'myType', consumers: ['myApp'] }, -]); - -const myOtherAppFeature = mockFeatureWithConsumers('myOtherApp', [ - { ruleTypeId: 'myType', consumers: ['myOtherApp'] }, -]); - -const myAppWithSubFeature = mockFeatureWithConsumers( - 'myAppWithSubFeature', - [{ ruleTypeId: 'myType', consumers: ['myAppWithSubFeature'] }], - true -); - -const myFeatureWithoutAlerting = mockFeatureWithConsumers('myOtherApp'); +type CheckPrivilegesResponseWithoutES = Omit & { + privileges: Omit; +}; describe('AlertingAuthorization', () => { + const getSpace = jest.fn(); + const getSpaceId = () => 'space1'; const allRegisteredConsumers = new Set(); const ruleTypesConsumersMap = new Map>(); + + const checkPrivileges = jest.fn, []>(async () => ({ + username: 'elastic', + hasAllRequested: true, + privileges: { kibana: [] }, + })); + + const ruleTypeIds = ['rule-type-id-1', 'rule-type-id-2', 'rule-type-id-3', 'rule-type-id-4']; + const consumers = ['consumer-a', 'consumer-b', 'consumer-c', 'consumer-d']; + let request: KibanaRequest; let ruleTypeRegistry = ruleTypeRegistryMock.create(); + let securityStart: ReturnType; + let features: jest.Mocked; beforeEach(() => { jest.clearAllMocks(); + allRegisteredConsumers.clear(); + allRegisteredConsumers.clear(); + ruleTypesConsumersMap.clear(); + + securityStart = securityMock.createStart(); + securityStart.authz.mode.useRbacForRequest.mockReturnValue(true); + securityStart.authz.checkPrivilegesDynamicallyWithRequest.mockReturnValue(checkPrivileges); request = httpServerMock.createKibanaRequest(); + getSpace.mockResolvedValue(undefined); - ruleTypeRegistry.get.mockImplementation((id) => ({ - id, - name: 'My Alert Type', - actionGroups: [{ id: 'default', name: 'Default' }], - defaultActionGroupId: 'default', - minimumLicenseRequired: 'basic', - isExportable: true, - recoveryActionGroup: RecoveredActionGroup, - async executor() { - return { state: {} }; - }, - category: 'test', - producer: 'myApp', - validate: { - params: schema.any(), - }, - validLegacyConsumers: [], - })); + features = featuresPluginMock.createStart(); + features.getKibanaFeatures.mockReturnValue([ + mockFeatureWithConsumers('feature-id-1', [ + { + ruleTypeId: 'rule-type-id-1', + consumers: ['alerts', 'consumer-a'], + }, + { ruleTypeId: 'rule-type-id-2', consumers: ['alerts', 'consumer-b'] }, + ]), + mockFeatureWithConsumers('feature-id-2', [ + { + ruleTypeId: 'rule-type-id-1', + consumers: ['alerts', 'consumer-b'], + }, + { + ruleTypeId: 'rule-type-id-3', + consumers: ['alerts', 'consumer-c'], + }, + ]), + mockFeatureWithConsumers('feature-id-3', [ + { + ruleTypeId: 'rule-type-id-4', + consumers: ['consumer-d'], + }, + ]), + ]); - getSpace.mockResolvedValue(undefined); + const alertingGet = securityStart.authz.actions.alerting.get as jest.Mock; + alertingGet.mockImplementation(mockAuthorizationAction); - allRegisteredConsumers.clear(); - ruleTypesConsumersMap.clear(); + ruleTypeRegistry = ruleTypeRegistryMock.create(); + ruleTypeRegistry.getAllTypes.mockReturnValue(ruleTypeIds); + ruleTypeRegistry.has.mockImplementation((ruleTypeId: string) => + ruleTypeIds.includes(ruleTypeId) + ); + + // @ts-expect-error: only the id is needed for the tests + ruleTypeRegistry.get.mockImplementation((ruleTypeId: string) => ({ id: ruleTypeId })); }); describe('create', () => { - let securityStart: jest.Mocked; - let features: jest.Mocked; - beforeEach(() => { jest.clearAllMocks(); securityStart = securityMock.createStart(); @@ -395,19 +393,10 @@ describe('AlertingAuthorization', () => { }); describe('ensureAuthorized', () => { - const checkPrivileges = jest.fn(async () => ({ hasAllRequested: true })); - let securityStart: ReturnType; - beforeEach(() => { jest.clearAllMocks(); allRegisteredConsumers.clear(); allRegisteredConsumers.add('myApp'); - securityStart = securityMock.createStart(); - securityStart.authz.mode.useRbacForRequest.mockReturnValue(true); - securityStart.authz.checkPrivilegesDynamicallyWithRequest.mockReturnValue(checkPrivileges); - - const alertingGet = securityStart.authz.actions.alerting.get as jest.Mock; - alertingGet.mockImplementation(mockAuthorizationAction); }); it('is a no-op when there is no authorization api', async () => { @@ -599,7 +588,6 @@ describe('AlertingAuthorization', () => { }); it('throws an error when the consumer does not exist because it was from a disabled plugin', async () => { - const features = featuresPluginMock.createStart(); features.getKibanaFeatures.mockReturnValue([ mockFeatureWithConsumers('my-feature-1', [ { ruleTypeId: 'rule-type-1', consumers: ['disabled-feature-consumer'] }, @@ -669,68 +657,6 @@ describe('AlertingAuthorization', () => { }); describe('getFindAuthorizationFilter', () => { - type CheckPrivilegesResponseWithoutES = Omit & { - privileges: Omit; - }; - - const checkPrivileges = jest.fn, []>(async () => ({ - username: 'elastic', - hasAllRequested: true, - privileges: { kibana: [] }, - })); - - const ruleTypeIds = ['rule-type-id-1', 'rule-type-id-2', 'rule-type-id-3', 'rule-type-id-4']; - - let securityStart: ReturnType; - let features: jest.Mocked; - - beforeEach(() => { - jest.clearAllMocks(); - allRegisteredConsumers.clear(); - securityStart = securityMock.createStart(); - securityStart.authz.mode.useRbacForRequest.mockReturnValue(true); - securityStart.authz.checkPrivilegesDynamicallyWithRequest.mockReturnValue(checkPrivileges); - - features = featuresPluginMock.createStart(); - features.getKibanaFeatures.mockReturnValue([ - mockFeatureWithConsumers('feature-id-1', [ - { - ruleTypeId: 'rule-type-id-1', - consumers: ['alerts', 'consumer-a'], - }, - { ruleTypeId: 'rule-type-id-2', consumers: ['alerts', 'consumer-b'] }, - ]), - mockFeatureWithConsumers('feature-id-2', [ - { - ruleTypeId: 'rule-type-id-1', - consumers: ['alerts', 'consumer-b'], - }, - { - ruleTypeId: 'rule-type-id-3', - consumers: ['alerts', 'consumer-c'], - }, - ]), - mockFeatureWithConsumers('feature-id-3', [ - { - ruleTypeId: 'rule-type-id-4', - consumers: ['consumer-d'], - }, - ]), - ]); - - const alertingGet = securityStart.authz.actions.alerting.get as jest.Mock; - alertingGet.mockImplementation(mockAuthorizationAction); - - ruleTypeRegistry = ruleTypeRegistryMock.create(); - ruleTypeRegistry.getAllTypes.mockReturnValue(ruleTypeIds); - ruleTypeRegistry.has.mockImplementation((ruleTypeId: string) => - ruleTypeIds.includes(ruleTypeId) - ); - - // @ts-expect-error: only the id is needed for the tests - ruleTypeRegistry.get.mockImplementation((ruleTypeId: string) => ({ id: ruleTypeId })); - }); - it('creates a filter based on the privileged types', async () => { const auth = await AlertingAuthorization.create({ request, @@ -814,72 +740,56 @@ describe('AlertingAuthorization', () => { `"((path.to.rule_type_id: rule-type-id-1 AND (consumer-field: alerts OR consumer-field: consumer-a OR consumer-field: consumer-b)) OR (path.to.rule_type_id: rule-type-id-2 AND (consumer-field: alerts OR consumer-field: consumer-b)) OR (path.to.rule_type_id: rule-type-id-3 AND (consumer-field: consumer-c OR consumer-field: alerts)))"` ); }); - }); - describe('getAuthorizationFilter', () => { - type CheckPrivilegesResponseWithoutES = Omit & { - privileges: Omit; - }; - - const checkPrivileges = jest.fn, []>(async () => ({ - username: 'elastic', - hasAllRequested: true, - privileges: { kibana: [] }, - })); - - const ruleTypeIds = ['rule-type-id-1', 'rule-type-id-2', 'rule-type-id-3', 'rule-type-id-4']; - const consumers = ['consumer-a', 'consumer-b', 'consumer-c', 'consumer-d']; - - let securityStart: ReturnType; - let features: jest.Mocked; + it('does not throw if the rule type is authorized', async () => { + checkPrivileges.mockResolvedValueOnce({ + username: 'some-user', + hasAllRequested: true, + privileges: { + kibana: [ + { + privilege: mockAuthorizationAction('rule-type-id-1', 'consumer-a', 'rule', 'find'), + authorized: true, + }, + { + privilege: mockAuthorizationAction('rule-type-id-2', 'consumer-b', 'rule', 'find'), + authorized: true, + }, + ], + }, + }); - beforeEach(() => { - jest.clearAllMocks(); - allRegisteredConsumers.clear(); - securityStart = securityMock.createStart(); - securityStart.authz.mode.useRbacForRequest.mockReturnValue(true); - securityStart.authz.checkPrivilegesDynamicallyWithRequest.mockReturnValue(checkPrivileges); + const auth = await AlertingAuthorization.create({ + request, + ruleTypeRegistry, + getSpaceId, + features, + getSpace, + authorization: securityStart.authz, + }); - features = featuresPluginMock.createStart(); - features.getKibanaFeatures.mockReturnValue([ - mockFeatureWithConsumers('feature-id-1', [ - { - ruleTypeId: 'rule-type-id-1', - consumers: ['alerts', 'consumer-a'], - }, - { ruleTypeId: 'rule-type-id-2', consumers: ['alerts', 'consumer-b'] }, - ]), - mockFeatureWithConsumers('feature-id-2', [ - { - ruleTypeId: 'rule-type-id-1', - consumers: ['alerts', 'consumer-b'], - }, - { - ruleTypeId: 'rule-type-id-3', - consumers: ['alerts', 'consumer-c'], - }, - ]), - mockFeatureWithConsumers('feature-id-3', [ - { - ruleTypeId: 'rule-type-id-4', - consumers: ['consumer-d'], + const { ensureRuleTypeIsAuthorized } = await auth.getFindAuthorizationFilter( + AlertingAuthorizationEntity.Rule, + { + type: AlertingAuthorizationFilterType.KQL, + fieldNames: { + ruleTypeId: 'path.to.rule_type_id', + consumer: 'consumer-field', }, - ]), - ]); - - const alertingGet = securityStart.authz.actions.alerting.get as jest.Mock; - alertingGet.mockImplementation(mockAuthorizationAction); - - ruleTypeRegistry = ruleTypeRegistryMock.create(); - ruleTypeRegistry.getAllTypes.mockReturnValue(ruleTypeIds); - ruleTypeRegistry.has.mockImplementation((ruleTypeId: string) => - ruleTypeIds.includes(ruleTypeId) + } ); - // @ts-expect-error: only the id is needed for the tests - ruleTypeRegistry.get.mockImplementation((ruleTypeId: string) => ({ id: ruleTypeId })); + expect(() => + ensureRuleTypeIsAuthorized('rule-type-id-1', 'consumer-a', 'rule') + ).not.toThrow(); + + expect(() => + ensureRuleTypeIsAuthorized('rule-type-id-2', 'consumer-b', 'rule') + ).not.toThrow(); }); + }); + describe('getAuthorizationFilter', () => { describe('filter', () => { it('gets the filter correctly with no security and no spaceIds in the fields names', async () => { const auth = await AlertingAuthorization.create({ @@ -1216,646 +1126,115 @@ describe('AlertingAuthorization', () => { }); const { ensureRuleTypeIsAuthorized } = await auth.getAuthorizationFilter( - AlertingAuthorizationEntity.Rule, - { - type: AlertingAuthorizationFilterType.KQL, - fieldNames: { - ruleTypeId: 'ruleId', - consumer: 'consumer', - }, - }, - ReadOperations.Get, - new Set(consumers) - ); - - expect(() => - ensureRuleTypeIsAuthorized('rule-type-id-1', 'consumer-b', 'rule') - ).toThrowErrorMatchingInlineSnapshot( - `"Unauthorized by \\"consumer-b\\" to get \\"rule-type-id-1\\" rule"` - ); - }); - }); - }); - - describe('getAuthorizedRuleTypesForAllConsumers', () => { - const myOtherAppAlertType: RegistryRuleType = { - actionGroups: [], - actionVariables: undefined, - defaultActionGroupId: 'default', - minimumLicenseRequired: 'basic', - isExportable: true, - recoveryActionGroup: RecoveredActionGroup, - id: 'myOtherAppAlertType', - name: 'myOtherAppAlertType', - category: 'test', - producer: 'myOtherApp', - enabledInLicense: true, - hasAlertsMappings: false, - hasFieldsForAAD: false, - validLegacyConsumers: [], - }; - const myAppAlertType: RegistryRuleType = { - actionGroups: [], - actionVariables: undefined, - defaultActionGroupId: 'default', - minimumLicenseRequired: 'basic', - isExportable: true, - recoveryActionGroup: RecoveredActionGroup, - id: 'myAppAlertType', - name: 'myAppAlertType', - category: 'test', - producer: 'myApp', - enabledInLicense: true, - hasAlertsMappings: false, - hasFieldsForAAD: false, - validLegacyConsumers: [], - }; - const setOfAlertTypes = new Set([myAppAlertType, myOtherAppAlertType]); - beforeEach(() => { - features.getKibanaFeatures.mockReturnValue([ - mockFeatureWithConsumers('myApp', [ - { ruleTypeId: 'myOtherAppAlertType', consumers: ['myApp'] }, - { ruleTypeId: 'myAppAlertType', consumers: ['myApp'] }, - ]), - mockFeatureWithConsumers('myOtherApp', [ - { ruleTypeId: 'myOtherAppAlertType', consumers: ['myApp'] }, - { ruleTypeId: 'myAppAlertType', consumers: ['myApp'] }, - ]), - ]); - }); - it('augments a list of types with all features when there is no authorization api', async () => { - features.getKibanaFeatures.mockReturnValue([ - myAppFeature, - myOtherAppFeature, - myAppWithSubFeature, - myFeatureWithoutAlerting, - ]); - const alertAuthorization = new AlertingAuthorization({ - request, - ruleTypeRegistry, - getSpaceId, - allRegisteredConsumers, - ruleTypesConsumersMap, - }); - ruleTypeRegistry.list.mockReturnValue(setOfAlertTypes); - - await expect( - alertAuthorization.getAuthorizedRuleTypesForAllConsumers( - new Set([myAppAlertType, myOtherAppAlertType]), - [WriteOperations.Create], - AlertingAuthorizationEntity.Rule - ) - ).resolves.toMatchInlineSnapshot(` - Set { - Object { - "actionGroups": Array [], - "actionVariables": undefined, - "authorizedConsumers": Object { - "alerts": Object { - "all": true, - "read": true, - }, - "myApp": Object { - "all": true, - "read": true, - }, - "myAppWithSubFeature": Object { - "all": true, - "read": true, - }, - "myOtherApp": Object { - "all": true, - "read": true, - }, - }, - "category": "test", - "defaultActionGroupId": "default", - "enabledInLicense": true, - "hasAlertsMappings": false, - "hasFieldsForAAD": false, - "id": "myAppAlertType", - "isExportable": true, - "minimumLicenseRequired": "basic", - "name": "myAppAlertType", - "producer": "myApp", - "recoveryActionGroup": Object { - "id": "recovered", - "name": "Recovered", - }, - "validLegacyConsumers": Array [], - }, - Object { - "actionGroups": Array [], - "actionVariables": undefined, - "authorizedConsumers": Object { - "alerts": Object { - "all": true, - "read": true, - }, - "myApp": Object { - "all": true, - "read": true, - }, - "myAppWithSubFeature": Object { - "all": true, - "read": true, - }, - "myOtherApp": Object { - "all": true, - "read": true, - }, - }, - "category": "test", - "defaultActionGroupId": "default", - "enabledInLicense": true, - "hasAlertsMappings": false, - "hasFieldsForAAD": false, - "id": "myOtherAppAlertType", - "isExportable": true, - "minimumLicenseRequired": "basic", - "name": "myOtherAppAlertType", - "producer": "myOtherApp", - "recoveryActionGroup": Object { - "id": "recovered", - "name": "Recovered", - }, - "validLegacyConsumers": Array [], - }, - } - `); - }); - - it('augments a list of types with consumers under which the operation is authorized', async () => { - const { authorization } = mockSecurity(); - const checkPrivileges: jest.MockedFunction< - ReturnType - > = jest.fn(); - authorization.checkPrivilegesDynamicallyWithRequest.mockReturnValue(checkPrivileges); - checkPrivileges.mockResolvedValueOnce({ - username: 'some-user', - hasAllRequested: false, - privileges: { - kibana: [ - { - privilege: mockAuthorizationAction('myOtherAppAlertType', 'myApp', 'rule', 'create'), - authorized: true, - }, - { - privilege: mockAuthorizationAction( - 'myOtherAppAlertType', - 'myOtherApp', - 'rule', - 'create' - ), - authorized: false, - }, - { - privilege: mockAuthorizationAction('myAppAlertType', 'myApp', 'rule', 'create'), - authorized: true, - }, - { - privilege: mockAuthorizationAction('myAppAlertType', 'myOtherApp', 'rule', 'create'), - authorized: true, - }, - ], - }, - }); - - const alertAuthorization = new AlertingAuthorization({ - request, - ruleTypeRegistry, - authorization: securityStart.authz, - getSpaceId, - allRegisteredConsumers, - ruleTypesConsumersMap, - }); - ruleTypeRegistry.list.mockReturnValue(setOfAlertTypes); - - await expect( - alertAuthorization.getAuthorizedRuleTypesForAllConsumers( - new Set([myAppAlertType, myOtherAppAlertType]), - [WriteOperations.Create], - AlertingAuthorizationEntity.Rule - ) - ).resolves.toMatchInlineSnapshot(` - Set { - Object { - "actionGroups": Array [], - "actionVariables": undefined, - "authorizedConsumers": Object { - "myApp": Object { - "all": true, - "read": true, - }, - }, - "category": "test", - "defaultActionGroupId": "default", - "enabledInLicense": true, - "hasAlertsMappings": false, - "hasFieldsForAAD": false, - "id": "myOtherAppAlertType", - "isExportable": true, - "minimumLicenseRequired": "basic", - "name": "myOtherAppAlertType", - "producer": "myOtherApp", - "recoveryActionGroup": Object { - "id": "recovered", - "name": "Recovered", - }, - "validLegacyConsumers": Array [], - }, - Object { - "actionGroups": Array [], - "actionVariables": undefined, - "authorizedConsumers": Object { - "myApp": Object { - "all": true, - "read": true, - }, - "myOtherApp": Object { - "all": true, - "read": true, - }, - }, - "category": "test", - "defaultActionGroupId": "default", - "enabledInLicense": true, - "hasAlertsMappings": false, - "hasFieldsForAAD": false, - "id": "myAppAlertType", - "isExportable": true, - "minimumLicenseRequired": "basic", - "name": "myAppAlertType", - "producer": "myApp", - "recoveryActionGroup": Object { - "id": "recovered", - "name": "Recovered", - }, - "validLegacyConsumers": Array [], - }, - } - `); - }); - - it('authorizes user under the `alerts` consumer when they are authorized by the producer', async () => { - const { authorization } = mockSecurity(); - const checkPrivileges: jest.MockedFunction< - ReturnType - > = jest.fn(); - authorization.checkPrivilegesDynamicallyWithRequest.mockReturnValue(checkPrivileges); - checkPrivileges.mockResolvedValueOnce({ - username: 'some-user', - hasAllRequested: false, - privileges: { - kibana: [ - { - privilege: mockAuthorizationAction('myAppAlertType', 'myApp', 'alert', 'create'), - authorized: true, - }, - { - privilege: mockAuthorizationAction('myAppAlertType', 'myOtherApp', 'alert', 'create'), - authorized: false, - }, - ], - }, - }); - - const alertAuthorization = new AlertingAuthorization({ - request, - ruleTypeRegistry, - authorization: securityStart.authz, - getSpaceId, - allRegisteredConsumers, - ruleTypesConsumersMap, - }); - ruleTypeRegistry.list.mockReturnValue(setOfAlertTypes); - - await expect( - alertAuthorization.getAuthorizedRuleTypesForAllConsumers( - new Set([myAppAlertType]), - [WriteOperations.Create], - AlertingAuthorizationEntity.Alert - ) - ).resolves.toMatchInlineSnapshot(` - Set { - Object { - "actionGroups": Array [], - "actionVariables": undefined, - "authorizedConsumers": Object { - "myApp": Object { - "all": true, - "read": true, - }, - }, - "category": "test", - "defaultActionGroupId": "default", - "enabledInLicense": true, - "hasAlertsMappings": false, - "hasFieldsForAAD": false, - "id": "myAppAlertType", - "isExportable": true, - "minimumLicenseRequired": "basic", - "name": "myAppAlertType", - "producer": "myApp", - "recoveryActionGroup": Object { - "id": "recovered", - "name": "Recovered", - }, - "validLegacyConsumers": Array [], - }, - } - `); - }); - - it('augments a list of types with consumers under which multiple operations are authorized', async () => { - const { authorization } = mockSecurity(); - const checkPrivileges: jest.MockedFunction< - ReturnType - > = jest.fn(); - authorization.checkPrivilegesDynamicallyWithRequest.mockReturnValue(checkPrivileges); - checkPrivileges.mockResolvedValueOnce({ - username: 'some-user', - hasAllRequested: false, - privileges: { - kibana: [ - { - privilege: mockAuthorizationAction('myOtherAppAlertType', 'myApp', 'alert', 'create'), - authorized: true, - }, - { - privilege: mockAuthorizationAction( - 'myOtherAppAlertType', - 'myOtherApp', - 'alert', - 'create' - ), - authorized: false, - }, - { - privilege: mockAuthorizationAction('myAppAlertType', 'myApp', 'alert', 'create'), - authorized: false, - }, - { - privilege: mockAuthorizationAction('myAppAlertType', 'myOtherApp', 'alert', 'create'), - authorized: false, - }, - { - privilege: mockAuthorizationAction('myOtherAppAlertType', 'myApp', 'alert', 'get'), - authorized: true, - }, - { - privilege: mockAuthorizationAction( - 'myOtherAppAlertType', - 'myOtherApp', - 'alert', - 'get' - ), - authorized: true, - }, - { - privilege: mockAuthorizationAction('myAppAlertType', 'myApp', 'alert', 'get'), - authorized: true, - }, - { - privilege: mockAuthorizationAction('myAppAlertType', 'myOtherApp', 'alert', 'get'), - authorized: true, + AlertingAuthorizationEntity.Rule, + { + type: AlertingAuthorizationFilterType.KQL, + fieldNames: { + ruleTypeId: 'ruleId', + consumer: 'consumer', }, - ], - }, + }, + ReadOperations.Get, + new Set(consumers) + ); + + expect(() => + ensureRuleTypeIsAuthorized('rule-type-id-1', 'consumer-b', 'rule') + ).toThrowErrorMatchingInlineSnapshot( + `"Unauthorized by \\"consumer-b\\" to get \\"rule-type-id-1\\" rule"` + ); }); + }); + }); - const alertAuthorization = new AlertingAuthorization({ + describe('getAuthorizedRuleTypes', () => { + it('calls checkPrivileges correctly', async () => { + const auth = await AlertingAuthorization.create({ request, ruleTypeRegistry, - authorization: securityStart.authz, getSpaceId, - allRegisteredConsumers, - ruleTypesConsumersMap, + features, + getSpace, + authorization: securityStart.authz, }); - ruleTypeRegistry.list.mockReturnValue(setOfAlertTypes); - await expect( - alertAuthorization.getAuthorizedRuleTypesForAllConsumers( - new Set([myAppAlertType, myOtherAppAlertType]), - [WriteOperations.Create, ReadOperations.Get], - AlertingAuthorizationEntity.Alert - ) - ).resolves.toMatchInlineSnapshot(` - Set { - Object { - "actionGroups": Array [], - "actionVariables": undefined, - "authorizedConsumers": Object { - "myApp": Object { - "all": true, - "read": true, - }, - "myOtherApp": Object { - "all": false, - "read": true, - }, - }, - "category": "test", - "defaultActionGroupId": "default", - "enabledInLicense": true, - "hasAlertsMappings": false, - "hasFieldsForAAD": false, - "id": "myOtherAppAlertType", - "isExportable": true, - "minimumLicenseRequired": "basic", - "name": "myOtherAppAlertType", - "producer": "myOtherApp", - "recoveryActionGroup": Object { - "id": "recovered", - "name": "Recovered", - }, - "validLegacyConsumers": Array [], - }, + await auth.getAuthorizedRuleTypes( + new Set(['rule-type-id-1']), + [WriteOperations.Create], + AlertingAuthorizationEntity.Rule + ); + + expect(checkPrivileges).toBeCalledTimes(1); + expect(checkPrivileges.mock.calls[0]).toMatchInlineSnapshot(` + Array [ Object { - "actionGroups": Array [], - "actionVariables": undefined, - "authorizedConsumers": Object { - "myApp": Object { - "all": false, - "read": true, - }, - "myOtherApp": Object { - "all": false, - "read": true, - }, - }, - "category": "test", - "defaultActionGroupId": "default", - "enabledInLicense": true, - "hasAlertsMappings": false, - "hasFieldsForAAD": false, - "id": "myAppAlertType", - "isExportable": true, - "minimumLicenseRequired": "basic", - "name": "myAppAlertType", - "producer": "myApp", - "recoveryActionGroup": Object { - "id": "recovered", - "name": "Recovered", - }, - "validLegacyConsumers": Array [], + "kibana": Array [ + "rule-type-id-1/alerts/rule/create", + "rule-type-id-1/consumer-a/rule/create", + "rule-type-id-1/consumer-b/rule/create", + ], }, - } + ] `); }); - it('omits types which have no consumers under which the operation is authorized', async () => { - const { authorization } = mockSecurity(); - const checkPrivileges: jest.MockedFunction< - ReturnType - > = jest.fn(); - authorization.checkPrivilegesDynamicallyWithRequest.mockReturnValue(checkPrivileges); + it('returns the authorized rules correctly', async () => { checkPrivileges.mockResolvedValueOnce({ username: 'some-user', - hasAllRequested: false, + hasAllRequested: true, privileges: { kibana: [ { - privilege: mockAuthorizationAction('myOtherAppAlertType', 'myApp', 'alert', 'create'), + privilege: mockAuthorizationAction('rule-type-id-1', 'consumer-a', 'rule', 'get'), authorized: true, }, { - privilege: mockAuthorizationAction( - 'myOtherAppAlertType', - 'myOtherApp', - 'alert', - 'create' - ), + privilege: mockAuthorizationAction('rule-type-id-1', 'consumer-a', 'rule', 'create'), authorized: true, }, { - privilege: mockAuthorizationAction('myAppAlertType', 'myApp', 'alert', 'create'), - authorized: false, + privilege: mockAuthorizationAction('rule-type-id-2', 'consumer-b', 'rule', 'get'), + authorized: true, }, { - privilege: mockAuthorizationAction('myAppAlertType', 'myOtherApp', 'alert', 'create'), - authorized: false, + privilege: mockAuthorizationAction('rule-type-id-3', 'consumer-c', 'rule', 'create'), + authorized: true, }, ], }, }); - const alertAuthorization = new AlertingAuthorization({ + const auth = await AlertingAuthorization.create({ request, ruleTypeRegistry, - authorization: securityStart.authz, getSpaceId, - allRegisteredConsumers, - ruleTypesConsumersMap, + features, + getSpace, + authorization: securityStart.authz, }); - ruleTypeRegistry.list.mockReturnValue(setOfAlertTypes); - await expect( - alertAuthorization.getAuthorizedRuleTypesForAllConsumers( - new Set([myAppAlertType, myOtherAppAlertType]), + expect( + await auth.getAuthorizedRuleTypes( + new Set(['rule-type-id-1']), [WriteOperations.Create], - AlertingAuthorizationEntity.Alert + AlertingAuthorizationEntity.Rule ) - ).resolves.toMatchInlineSnapshot(` - Set { - Object { - "actionGroups": Array [], - "actionVariables": undefined, + ).toMatchInlineSnapshot(` + Map { + "rule-type-id-1" => Object { "authorizedConsumers": Object { - "myApp": Object { - "all": true, - "read": true, - }, - "myOtherApp": Object { + "consumer-a": Object { "all": true, "read": true, }, }, - "category": "test", - "defaultActionGroupId": "default", - "enabledInLicense": true, - "hasAlertsMappings": false, - "hasFieldsForAAD": false, - "id": "myOtherAppAlertType", - "isExportable": true, - "minimumLicenseRequired": "basic", - "name": "myOtherAppAlertType", - "producer": "myOtherApp", - "recoveryActionGroup": Object { - "id": "recovered", - "name": "Recovered", - }, - "validLegacyConsumers": Array [], }, } `); }); }); - describe('getAuthorizedRuleTypesWithAuthorizedConsumers', () => { - type CheckPrivilegesResponseWithoutES = Omit & { - privileges: Omit; - }; - - const checkPrivileges = jest.fn, []>(async () => ({ - username: 'elastic', - hasAllRequested: true, - privileges: { kibana: [] }, - })); - - const ruleTypeIds = ['rule-type-id-1', 'rule-type-id-2', 'rule-type-id-3', 'rule-type-id-4']; - const consumers = ['consumer-a', 'consumer-b', 'consumer-c', 'consumer-d']; - - let securityStart: ReturnType; - let features: jest.Mocked; - - beforeEach(() => { - jest.clearAllMocks(); - allRegisteredConsumers.clear(); - securityStart = securityMock.createStart(); - securityStart.authz.mode.useRbacForRequest.mockReturnValue(true); - securityStart.authz.checkPrivilegesDynamicallyWithRequest.mockReturnValue(checkPrivileges); - - features = featuresPluginMock.createStart(); - features.getKibanaFeatures.mockReturnValue([ - mockFeatureWithConsumers('feature-id-1', [ - { - ruleTypeId: 'rule-type-id-1', - consumers: ['alerts', 'consumer-a'], - }, - { ruleTypeId: 'rule-type-id-2', consumers: ['alerts', 'consumer-b'] }, - ]), - mockFeatureWithConsumers('feature-id-2', [ - { - ruleTypeId: 'rule-type-id-1', - consumers: ['alerts', 'consumer-b'], - }, - { - ruleTypeId: 'rule-type-id-3', - consumers: ['alerts', 'consumer-c'], - }, - ]), - mockFeatureWithConsumers('feature-id-3', [ - { - ruleTypeId: 'rule-type-id-4', - consumers: ['consumer-d'], - }, - ]), - ]); - - const alertingGet = securityStart.authz.actions.alerting.get as jest.Mock; - alertingGet.mockImplementation(mockAuthorizationAction); - - ruleTypeRegistry = ruleTypeRegistryMock.create(); - ruleTypeRegistry.getAllTypes.mockReturnValue(ruleTypeIds); - ruleTypeRegistry.has.mockImplementation((ruleTypeId: string) => - ruleTypeIds.includes(ruleTypeId) - ); - - // @ts-expect-error: only the id is needed for the tests - ruleTypeRegistry.get.mockImplementation((ruleTypeId: string) => ({ id: ruleTypeId })); - }); - + describe('getAllAuthorizedRuleTypes', () => { it('get authorized rule types with authorized consumers', async () => { checkPrivileges.mockResolvedValueOnce({ username: 'some-user', @@ -1892,7 +1271,7 @@ describe('AlertingAuthorization', () => { }); expect( - await auth.getAuthorizedRuleTypesWithAuthorizedConsumers( + await auth.getAllAuthorizedRuleTypes( consumers, [ReadOperations.Get, WriteOperations.Create], AlertingAuthorizationEntity.Rule @@ -1933,7 +1312,7 @@ describe('AlertingAuthorization', () => { authorization: securityStart.authz, }); - await auth.getAuthorizedRuleTypesWithAuthorizedConsumers( + await auth.getAllAuthorizedRuleTypes( consumers, [ReadOperations.Get, WriteOperations.Create], AlertingAuthorizationEntity.Rule @@ -1962,69 +1341,6 @@ describe('AlertingAuthorization', () => { }); describe('_getAuthorizedRuleTypesWithAuthorizedConsumers', () => { - type CheckPrivilegesResponseWithoutES = Omit & { - privileges: Omit; - }; - - const checkPrivileges = jest.fn, []>(async () => ({ - username: 'elastic', - hasAllRequested: true, - privileges: { kibana: [] }, - })); - - const ruleTypeIds = ['rule-type-id-1', 'rule-type-id-2', 'rule-type-id-3', 'rule-type-id-4']; - const consumers = ['consumer-a', 'consumer-b', 'consumer-c', 'consumer-d']; - - let securityStart: ReturnType; - let features: jest.Mocked; - - beforeEach(() => { - jest.clearAllMocks(); - allRegisteredConsumers.clear(); - securityStart = securityMock.createStart(); - securityStart.authz.mode.useRbacForRequest.mockReturnValue(true); - securityStart.authz.checkPrivilegesDynamicallyWithRequest.mockReturnValue(checkPrivileges); - - features = featuresPluginMock.createStart(); - features.getKibanaFeatures.mockReturnValue([ - mockFeatureWithConsumers('feature-id-1', [ - { - ruleTypeId: 'rule-type-id-1', - consumers: ['alerts', 'consumer-a'], - }, - { ruleTypeId: 'rule-type-id-2', consumers: ['alerts', 'consumer-b'] }, - ]), - mockFeatureWithConsumers('feature-id-2', [ - { - ruleTypeId: 'rule-type-id-1', - consumers: ['alerts', 'consumer-b'], - }, - { - ruleTypeId: 'rule-type-id-3', - consumers: ['alerts', 'consumer-c'], - }, - ]), - mockFeatureWithConsumers('feature-id-3', [ - { - ruleTypeId: 'rule-type-id-4', - consumers: ['consumer-d'], - }, - ]), - ]); - - const alertingGet = securityStart.authz.actions.alerting.get as jest.Mock; - alertingGet.mockImplementation(mockAuthorizationAction); - - ruleTypeRegistry = ruleTypeRegistryMock.create(); - ruleTypeRegistry.getAllTypes.mockReturnValue(ruleTypeIds); - ruleTypeRegistry.has.mockImplementation((ruleTypeId: string) => - ruleTypeIds.includes(ruleTypeId) - ); - - // @ts-expect-error: only the id is needed for the tests - ruleTypeRegistry.get.mockImplementation((ruleTypeId: string) => ({ id: ruleTypeId })); - }); - it('returns all rule types with all consumers as authorized with no authorization', async () => { const auth = await AlertingAuthorization.create({ request, @@ -3040,643 +2356,4 @@ describe('AlertingAuthorization', () => { `); }); }); - - describe('8.11+', () => { - let alertAuthorization: AlertingAuthorization; - - const setOfRuleTypes: RegistryRuleType[] = [ - { - actionGroups: [], - actionVariables: undefined, - defaultActionGroupId: 'default', - minimumLicenseRequired: 'basic', - isExportable: true, - recoveryActionGroup: RecoveredActionGroup, - id: '.esQuery', - name: 'ES Query', - category: 'management', - producer: 'stackAlerts', - enabledInLicense: true, - hasAlertsMappings: false, - hasFieldsForAAD: false, - validLegacyConsumers: ['discover', 'alerts'], - }, - { - actionGroups: [], - actionVariables: undefined, - defaultActionGroupId: 'default', - minimumLicenseRequired: 'basic', - isExportable: true, - recoveryActionGroup: RecoveredActionGroup, - id: '.threshold-rule-o11y', - name: 'New threshold 011y', - category: 'observability', - producer: 'observability', - enabledInLicense: true, - hasAlertsMappings: false, - hasFieldsForAAD: false, - validLegacyConsumers: [], - }, - { - actionGroups: [], - actionVariables: undefined, - defaultActionGroupId: 'default', - minimumLicenseRequired: 'basic', - isExportable: true, - recoveryActionGroup: RecoveredActionGroup, - id: '.infrastructure-threshold-o11y', - name: 'Metrics o11y', - category: 'observability', - producer: 'infrastructure', - enabledInLicense: true, - hasAlertsMappings: false, - hasFieldsForAAD: false, - validLegacyConsumers: ['alerts'], - }, - { - actionGroups: [], - actionVariables: undefined, - defaultActionGroupId: 'default', - minimumLicenseRequired: 'basic', - isExportable: true, - recoveryActionGroup: RecoveredActionGroup, - id: '.logs-threshold-o11y', - name: 'Logs o11y', - category: 'observability', - producer: 'logs', - enabledInLicense: true, - hasAlertsMappings: false, - hasFieldsForAAD: false, - validLegacyConsumers: ['alerts'], - }, - ]; - - const onlyStackAlertsKibanaPrivileges = [ - { - privilege: mockAuthorizationAction('.esQuery', 'stackAlerts', 'rule', 'create'), - authorized: true, - }, - { - privilege: mockAuthorizationAction('.esQuery', 'stackAlerts', 'rule', 'find'), - authorized: true, - }, - ]; - const only011yKibanaPrivileges = [ - { - privilege: mockAuthorizationAction( - '.infrastructure-threshold-o11y', - 'infrastructure', - 'rule', - 'create' - ), - authorized: true, - }, - { - privilege: mockAuthorizationAction( - '.infrastructure-threshold-o11y', - 'infrastructure', - 'rule', - 'find' - ), - authorized: true, - }, - { - privilege: mockAuthorizationAction( - '.threshold-rule-o11y', - 'infrastructure', - 'rule', - 'create' - ), - authorized: true, - }, - { - privilege: mockAuthorizationAction( - '.threshold-rule-o11y', - 'infrastructure', - 'rule', - 'find' - ), - authorized: true, - }, - { - privilege: mockAuthorizationAction('.logs-threshold-o11y', 'logs', 'rule', 'create'), - authorized: true, - }, - { - privilege: mockAuthorizationAction('.logs-threshold-o11y', 'logs', 'rule', 'find'), - authorized: true, - }, - { - privilege: mockAuthorizationAction('.threshold-rule-o11y', 'logs', 'rule', 'create'), - authorized: true, - }, - { - privilege: mockAuthorizationAction('.threshold-rule-o11y', 'logs', 'rule', 'find'), - authorized: true, - }, - ]; - const onlyLogsAndStackAlertsKibanaPrivileges = [ - { - privilege: mockAuthorizationAction('.esQuery', 'stackAlerts', 'rule', 'create'), - authorized: true, - }, - { - privilege: mockAuthorizationAction('.esQuery', 'stackAlerts', 'rule', 'find'), - authorized: true, - }, - { - privilege: mockAuthorizationAction('.logs-threshold-o11y', 'logs', 'rule', 'create'), - authorized: true, - }, - { - privilege: mockAuthorizationAction('.logs-threshold-o11y', 'logs', 'rule', 'find'), - authorized: true, - }, - { - privilege: mockAuthorizationAction('.threshold-rule-o11y', 'logs', 'rule', 'create'), - authorized: true, - }, - { - privilege: mockAuthorizationAction('.threshold-rule-o11y', 'logs', 'rule', 'find'), - authorized: true, - }, - ]; - - beforeEach(async () => { - ruleTypeRegistry.list.mockReturnValue(new Set(setOfRuleTypes)); - ruleTypeRegistry.get.mockImplementation((id: string) => { - if (setOfRuleTypes.some((rt) => rt.id === id)) { - const ruleType = setOfRuleTypes.find((rt) => rt.id === id); - return (ruleType ?? {}) as NormalizedRuleType<{}, {}, {}, {}, {}, '', '', {}>; - } - return {} as NormalizedRuleType<{}, {}, {}, {}, {}, '', '', {}>; - }); - }); - - describe('user only access to stack alerts + discover', () => { - beforeEach(() => { - const { authorization } = mockSecurity(); - const checkPrivileges: jest.MockedFunction< - ReturnType - > = jest.fn(); - authorization.mode.useRbacForRequest.mockReturnValue(true); - - features.getKibanaFeatures.mockReset(); - features.getKibanaFeatures.mockReturnValue([ - mockFeatureWithConsumers('stackAlerts', [ - { ruleTypeId: '.esQuery', consumers: ['stackAlerts'] }, - ]), - mockFeatureWithConsumers('discover'), - ]); - checkPrivileges.mockReset(); - checkPrivileges.mockResolvedValue({ - username: 'onlyStack', - hasAllRequested: true, - privileges: { - kibana: onlyStackAlertsKibanaPrivileges, - }, - }); - authorization.checkPrivilegesDynamicallyWithRequest.mockReset(); - authorization.checkPrivilegesDynamicallyWithRequest.mockReturnValue(checkPrivileges); - alertAuthorization = new AlertingAuthorization({ - request, - ruleTypeRegistry, - authorization: securityStart.authz, - getSpaceId, - allRegisteredConsumers, - ruleTypesConsumersMap, - }); - }); - - describe('ensureAuthorized', () => { - it('should allow to create .esquery rule type with stackAlerts consumer', async () => { - await expect( - alertAuthorization.ensureAuthorized({ - ruleTypeId: '.esQuery', - consumer: 'stackAlerts', - operation: WriteOperations.Create, - entity: AlertingAuthorizationEntity.Rule, - }) - ).resolves.toEqual(undefined); - - expect(ruleTypeRegistry.get).toHaveBeenCalledTimes(1); - }); - it('should allow to create .esquery rule type with discover consumer', async () => { - await expect( - alertAuthorization.ensureAuthorized({ - ruleTypeId: '.esQuery', - consumer: 'discover', - operation: WriteOperations.Create, - entity: AlertingAuthorizationEntity.Rule, - }) - ).resolves.toEqual(undefined); - - expect(ruleTypeRegistry.get).toHaveBeenCalledTimes(1); - }); - it('should allow to create .esquery rule type with alerts consumer', async () => { - await expect( - alertAuthorization.ensureAuthorized({ - ruleTypeId: '.esQuery', - consumer: 'alerts', - operation: WriteOperations.Create, - entity: AlertingAuthorizationEntity.Rule, - }) - ).resolves.toEqual(undefined); - - expect(ruleTypeRegistry.get).toHaveBeenCalledTimes(1); - }); - it('should throw an error to create .esquery rule type with logs consumer', async () => { - await expect( - alertAuthorization.ensureAuthorized({ - ruleTypeId: '.esQuery', - consumer: 'logs', - operation: WriteOperations.Create, - entity: AlertingAuthorizationEntity.Rule, - }) - ).rejects.toThrowErrorMatchingInlineSnapshot( - `"Unauthorized by \\"logs\\" to create \\".esQuery\\" rule"` - ); - - expect(ruleTypeRegistry.get).toHaveBeenCalledTimes(1); - }); - it('should throw an error to create .esquery rule type with infrastructure consumer', async () => { - await expect( - alertAuthorization.ensureAuthorized({ - ruleTypeId: '.esQuery', - consumer: 'infrastructure', - operation: WriteOperations.Create, - entity: AlertingAuthorizationEntity.Rule, - }) - ).rejects.toThrowErrorMatchingInlineSnapshot( - `"Unauthorized by \\"infrastructure\\" to create \\".esQuery\\" rule"` - ); - - expect(ruleTypeRegistry.get).toHaveBeenCalledTimes(1); - }); - it('should throw an error to create .threshold-rule-o11y rule type with alerts consumer', async () => { - await expect( - alertAuthorization.ensureAuthorized({ - ruleTypeId: '.threshold-rule-o11y', - consumer: 'alerts', - operation: WriteOperations.Create, - entity: AlertingAuthorizationEntity.Rule, - }) - ).rejects.toThrowErrorMatchingInlineSnapshot( - `"Unauthorized by \\"alerts\\" to create \\".threshold-rule-o11y\\" rule"` - ); - - expect(ruleTypeRegistry.get).toHaveBeenCalledTimes(1); - }); - it('should throw an error to create .logs-threshold-o11y rule type with alerts infrastructure', async () => { - await expect( - alertAuthorization.ensureAuthorized({ - ruleTypeId: '.logs-threshold-o11y', - consumer: 'alerts', - operation: WriteOperations.Create, - entity: AlertingAuthorizationEntity.Rule, - }) - ).rejects.toThrowErrorMatchingInlineSnapshot( - `"Unauthorized by \\"alerts\\" to create \\".logs-threshold-o11y\\" rule"` - ); - - expect(ruleTypeRegistry.get).toHaveBeenCalledTimes(1); - }); - }); - - it('creates a filter based on the privileged types', async () => { - expect( - ( - await alertAuthorization.getFindAuthorizationFilter(AlertingAuthorizationEntity.Rule, { - type: AlertingAuthorizationFilterType.KQL, - fieldNames: { - ruleTypeId: 'path.to.rule_type_id', - consumer: 'consumer-field', - }, - }) - ).filter - ).toEqual( - fromKueryExpression( - `path.to.rule_type_id:.esQuery and consumer-field:(alerts or stackAlerts or discover)` - ) - ); - }); - }); - - describe('user only access to o11y', () => { - beforeEach(() => { - const { authorization } = mockSecurity(); - const checkPrivileges: jest.MockedFunction< - ReturnType - > = jest.fn(); - authorization.mode.useRbacForRequest.mockReturnValue(true); - - features.getKibanaFeatures.mockReset(); - features.getKibanaFeatures.mockReturnValue([ - mockFeatureWithConsumers('infrastructure', [ - { ruleTypeId: '.infrastructure-threshold-o11y', consumers: ['infrastructure'] }, - { ruleTypeId: '.threshold-rule-o11y', consumers: ['myApp'] }, - { ruleTypeId: '.esQuery', consumers: ['myApp'] }, - ]), - mockFeatureWithConsumers('logs', [ - { ruleTypeId: '.threshold-rule-o11y', consumers: ['logs'] }, - { ruleTypeId: '.esQuery', consumers: ['logs'] }, - { ruleTypeId: '.logs-threshold-o11y', consumers: ['logs'] }, - ]), - ]); - checkPrivileges.mockReset(); - checkPrivileges.mockResolvedValue({ - username: 'onlyO11y', - hasAllRequested: true, - privileges: { - kibana: only011yKibanaPrivileges, - }, - }); - authorization.checkPrivilegesDynamicallyWithRequest.mockReset(); - authorization.checkPrivilegesDynamicallyWithRequest.mockReturnValue(checkPrivileges); - alertAuthorization = new AlertingAuthorization({ - request, - ruleTypeRegistry, - authorization: securityStart.authz, - getSpaceId, - allRegisteredConsumers, - ruleTypesConsumersMap, - }); - }); - - describe('ensureAuthorized', () => { - it('should throw an error to create .esquery rule type with stackAlerts consumer', async () => { - await expect( - alertAuthorization.ensureAuthorized({ - ruleTypeId: '.esQuery', - consumer: 'stackAlerts', - operation: WriteOperations.Create, - entity: AlertingAuthorizationEntity.Rule, - }) - ).rejects.toThrowErrorMatchingInlineSnapshot( - `"Unauthorized by \\"stackAlerts\\" to create \\".esQuery\\" rule"` - ); - - expect(ruleTypeRegistry.get).toHaveBeenCalledTimes(1); - }); - it('should throw an error to create .esquery rule type with discover consumer', async () => { - await expect( - alertAuthorization.ensureAuthorized({ - ruleTypeId: '.esQuery', - consumer: 'discover', - operation: WriteOperations.Create, - entity: AlertingAuthorizationEntity.Rule, - }) - ).rejects.toThrowErrorMatchingInlineSnapshot( - `"Unauthorized by \\"discover\\" to create \\".esQuery\\" rule"` - ); - - expect(ruleTypeRegistry.get).toHaveBeenCalledTimes(1); - }); - it('should throw an error to create .threshold-rule-o11y rule type with alerts consumer', async () => { - await expect( - alertAuthorization.ensureAuthorized({ - ruleTypeId: '.threshold-rule-o11y', - consumer: 'alerts', - operation: WriteOperations.Create, - entity: AlertingAuthorizationEntity.Rule, - }) - ).rejects.toThrowErrorMatchingInlineSnapshot( - `"Unauthorized by \\"alerts\\" to create \\".threshold-rule-o11y\\" rule"` - ); - - expect(ruleTypeRegistry.get).toHaveBeenCalledTimes(1); - }); - it('should allow to create .esquery rule type with logs consumer', async () => { - await expect( - alertAuthorization.ensureAuthorized({ - ruleTypeId: '.esQuery', - consumer: 'logs', - operation: WriteOperations.Create, - entity: AlertingAuthorizationEntity.Rule, - }) - ).resolves.toEqual(undefined); - - expect(ruleTypeRegistry.get).toHaveBeenCalledTimes(1); - }); - it('should allow to create .esquery rule type with logs infrastructure', async () => { - await expect( - alertAuthorization.ensureAuthorized({ - ruleTypeId: '.esQuery', - consumer: 'infrastructure', - operation: WriteOperations.Create, - entity: AlertingAuthorizationEntity.Rule, - }) - ).resolves.toEqual(undefined); - - expect(ruleTypeRegistry.get).toHaveBeenCalledTimes(1); - }); - it('should allow to create .logs-threshold-o11y rule type with alerts consumer', async () => { - await expect( - alertAuthorization.ensureAuthorized({ - ruleTypeId: '.logs-threshold-o11y', - consumer: 'alerts', - operation: WriteOperations.Create, - entity: AlertingAuthorizationEntity.Rule, - }) - ).resolves.toEqual(undefined); - - expect(ruleTypeRegistry.get).toHaveBeenCalledTimes(1); - }); - it('should throw an error to create .threshold-rule-o11y rule type with logs consumer', async () => { - await expect( - alertAuthorization.ensureAuthorized({ - ruleTypeId: '.threshold-rule-o11y', - consumer: 'logs', - operation: WriteOperations.Create, - entity: AlertingAuthorizationEntity.Rule, - }) - ).resolves.toEqual(undefined); - - expect(ruleTypeRegistry.get).toHaveBeenCalledTimes(1); - }); - }); - it('creates a filter based on the privileged types', async () => { - expect( - ( - await alertAuthorization.getFindAuthorizationFilter( - AlertingAuthorizationEntity.Rule, - { - type: AlertingAuthorizationFilterType.KQL, - fieldNames: { - ruleTypeId: 'path.to.rule_type_id', - consumer: 'consumer-field', - }, - }, - new Set(['infrastructure', 'logs']) - ) - ).filter - ).toEqual( - fromKueryExpression( - `(path.to.rule_type_id:.infrastructure-threshold-o11y and consumer-field:(infrastructure or alerts)) or (path.to.rule_type_id:.threshold-rule-o11y and consumer-field:(infrastructure or logs)) or (path.to.rule_type_id:.logs-threshold-o11y and consumer-field:(logs or alerts))` - ) - ); - }); - }); - - describe('user only access to logs and stackAlerts', () => { - beforeEach(() => { - const { authorization } = mockSecurity(); - const checkPrivileges: jest.MockedFunction< - ReturnType - > = jest.fn(); - authorization.mode.useRbacForRequest.mockReturnValue(true); - - features.getKibanaFeatures.mockClear(); - features.getKibanaFeatures.mockReturnValue([ - mockFeatureWithConsumers('stackAlerts', [ - { ruleTypeId: '.esQuery', consumers: ['stackAlerts'] }, - ]), - mockFeatureWithConsumers('logs', [ - { ruleTypeId: '.logs-threshold-o11y', consumers: ['logs'] }, - { ruleTypeId: '.threshold-rule-o11y', consumers: ['logs'] }, - { ruleTypeId: '.esQuery', consumers: ['logs'] }, - ]), - ]); - checkPrivileges.mockClear(); - checkPrivileges.mockResolvedValue({ - username: 'stackAndLogs', - hasAllRequested: true, - privileges: { - kibana: onlyLogsAndStackAlertsKibanaPrivileges, - }, - }); - authorization.checkPrivilegesDynamicallyWithRequest.mockReturnValue(checkPrivileges); - alertAuthorization = new AlertingAuthorization({ - request, - ruleTypeRegistry, - authorization: securityStart.authz, - getSpaceId, - allRegisteredConsumers, - ruleTypesConsumersMap, - }); - }); - - describe('ensureAuthorized', () => { - it('should allow to create .esquery rule type with stackAlerts consumer', async () => { - await expect( - alertAuthorization.ensureAuthorized({ - ruleTypeId: '.esQuery', - consumer: 'stackAlerts', - operation: WriteOperations.Create, - entity: AlertingAuthorizationEntity.Rule, - }) - ).resolves.toEqual(undefined); - - expect(ruleTypeRegistry.get).toHaveBeenCalledTimes(1); - }); - it('should allow to create .esquery rule type with discover consumer', async () => { - await expect( - alertAuthorization.ensureAuthorized({ - ruleTypeId: '.esQuery', - consumer: 'discover', - operation: WriteOperations.Create, - entity: AlertingAuthorizationEntity.Rule, - }) - ).resolves.toEqual(undefined); - - expect(ruleTypeRegistry.get).toHaveBeenCalledTimes(1); - }); - it('should allow to create .esquery rule type with logs consumer', async () => { - await expect( - alertAuthorization.ensureAuthorized({ - ruleTypeId: '.esQuery', - consumer: 'logs', - operation: WriteOperations.Create, - entity: AlertingAuthorizationEntity.Rule, - }) - ).resolves.toEqual(undefined); - - expect(ruleTypeRegistry.get).toHaveBeenCalledTimes(1); - }); - it('should allow to create .logs-threshold-o11y rule type with alerts consumer', async () => { - await expect( - alertAuthorization.ensureAuthorized({ - ruleTypeId: '.logs-threshold-o11y', - consumer: 'alerts', - operation: WriteOperations.Create, - entity: AlertingAuthorizationEntity.Rule, - }) - ).resolves.toEqual(undefined); - - expect(ruleTypeRegistry.get).toHaveBeenCalledTimes(1); - }); - it('should throw an error to create .threshold-rule-o11y rule type with logs consumer', async () => { - await expect( - alertAuthorization.ensureAuthorized({ - ruleTypeId: '.threshold-rule-o11y', - consumer: 'logs', - operation: WriteOperations.Create, - entity: AlertingAuthorizationEntity.Rule, - }) - ).resolves.toEqual(undefined); - - expect(ruleTypeRegistry.get).toHaveBeenCalledTimes(1); - }); - it('should throw an error to create .esquery rule type with logs infrastructure', async () => { - await expect( - alertAuthorization.ensureAuthorized({ - ruleTypeId: '.esQuery', - consumer: 'infrastructure', - operation: WriteOperations.Create, - entity: AlertingAuthorizationEntity.Rule, - }) - ).rejects.toThrowErrorMatchingInlineSnapshot( - `"Unauthorized by \\"infrastructure\\" to create \\".esQuery\\" rule"` - ); - - expect(ruleTypeRegistry.get).toHaveBeenCalledTimes(1); - }); - it('should throw an error to create .threshold-rule-o11y rule type with alerts consumer', async () => { - await expect( - alertAuthorization.ensureAuthorized({ - ruleTypeId: '.threshold-rule-o11y', - consumer: 'alerts', - operation: WriteOperations.Create, - entity: AlertingAuthorizationEntity.Rule, - }) - ).rejects.toThrowErrorMatchingInlineSnapshot( - `"Unauthorized by \\"alerts\\" to create \\".threshold-rule-o11y\\" rule"` - ); - - expect(ruleTypeRegistry.get).toHaveBeenCalledTimes(1); - }); - it('should throw an error to create .esquery rule type with infrastructure consumer', async () => { - await expect( - alertAuthorization.ensureAuthorized({ - ruleTypeId: '.esQuery', - consumer: 'infrastructure', - operation: WriteOperations.Create, - entity: AlertingAuthorizationEntity.Rule, - }) - ).rejects.toThrowErrorMatchingInlineSnapshot( - `"Unauthorized by \\"infrastructure\\" to create \\".esQuery\\" rule"` - ); - - expect(ruleTypeRegistry.get).toHaveBeenCalledTimes(1); - }); - }); - it('creates a filter based on the privileged types', async () => { - expect( - ( - await alertAuthorization.getFindAuthorizationFilter(AlertingAuthorizationEntity.Rule, { - type: AlertingAuthorizationFilterType.KQL, - fieldNames: { - ruleTypeId: 'path.to.rule_type_id', - consumer: 'consumer-field', - }, - }) - ).filter - ).toEqual( - fromKueryExpression( - `(path.to.rule_type_id:.esQuery and consumer-field:(alerts or stackAlerts or logs or discover)) or (path.to.rule_type_id:.logs-threshold-o11y and consumer-field:(alerts or stackAlerts or logs or discover)) or (path.to.rule_type_id:.threshold-rule-o11y and consumer-field:(alerts or stackAlerts or logs or discover))` - ) - ); - }); - }); - }); }); diff --git a/x-pack/plugins/alerting/server/authorization/alerting_authorization.ts b/x-pack/plugins/alerting/server/authorization/alerting_authorization.ts index d51c01f18efcaa..4040ee524ab1d8 100644 --- a/x-pack/plugins/alerting/server/authorization/alerting_authorization.ts +++ b/x-pack/plugins/alerting/server/authorization/alerting_authorization.ts @@ -164,7 +164,7 @@ export class AlertingAuthorization { * This method exposes the private '_getAuthorizedRuleTypesWithAuthorizedConsumers' to be * used by the RAC/Alerts client */ - public async getAllAuthorizedRuleTypesWithAuthorizedConsumers( + public async getAllAuthorizedRuleTypes( featureIds: readonly string[], operations: Array, authorizationEntity: AlertingAuthorizationEntity @@ -302,7 +302,7 @@ export class AlertingAuthorization { }; } - public async getAuthorizedRuleTypesForAllConsumers( + public async getAuthorizedRuleTypes( ruleTypeIds: Set, operations: Array, authorizationEntity: AlertingAuthorizationEntity From 0a6261e954780485f4421e76c937b91cf2a0053d Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Wed, 17 Jul 2024 17:33:00 +0300 Subject: [PATCH 014/106] Fix types --- .../lib/set_alerts_to_untracked.test.ts | 12 +- .../lib/set_alerts_to_untracked.ts | 16 +- .../methods/aggregate/aggregate_rules.test.ts | 66 ++- .../bulk_untrack/bulk_untrack_alerts.ts | 5 +- .../rule/methods/find/find_rules.test.ts | 132 +++-- .../rule/methods/tags/get_rule_tags.test.ts | 65 +-- .../alerting_authorization.mock.ts | 6 +- .../alerting_authorization_kuery.test.ts | 507 ++++++------------ .../alerting/server/authorization/index.ts | 1 + x-pack/plugins/alerting/server/index.ts | 3 +- .../alerting/server/routes/health.test.ts | 21 +- .../server/routes/legacy/health.test.ts | 16 +- .../routes/legacy/list_alert_types.test.ts | 13 +- .../alerting/server/routes/rule_types.test.ts | 6 +- .../suggestions/values_suggestion_alerts.ts | 12 +- .../alerting/server/rule_type_registry.ts | 73 +-- .../rules_client/methods/list_rule_types.ts | 24 +- .../tests/list_rule_types.test.ts | 101 ++-- ...er_inventory_metric_threshold_rule_type.ts | 4 +- .../server/types.ts | 9 +- .../server/alert_data_client/alerts_client.ts | 21 +- .../alerts_client_factory.ts | 9 +- x-pack/plugins/rule_registry/server/plugin.ts | 11 +- .../server/search_strategy/search_strategy.ts | 14 +- .../triggers_actions_ui/server/plugin.ts | 9 +- .../server/routes/config.test.ts | 4 +- 26 files changed, 518 insertions(+), 642 deletions(-) diff --git a/x-pack/plugins/alerting/server/alerts_service/lib/set_alerts_to_untracked.test.ts b/x-pack/plugins/alerting/server/alerts_service/lib/set_alerts_to_untracked.test.ts index 49ece72c42f955..b9775ec8d5ceda 100644 --- a/x-pack/plugins/alerting/server/alerts_service/lib/set_alerts_to_untracked.test.ts +++ b/x-pack/plugins/alerting/server/alerts_service/lib/set_alerts_to_untracked.test.ts @@ -15,10 +15,8 @@ import { setAlertsToUntracked } from './set_alerts_to_untracked'; let clusterClient: ElasticsearchClientMock; let logger: ReturnType; -const getAuthorizedRuleTypesMock = jest.fn(); - +const getAllAuthorizedRuleTypesFindOperationMock = jest.fn(); const getAlertIndicesAliasMock = jest.fn(); - const ensureAuthorizedMock = jest.fn(); describe('setAlertsToUntracked()', () => { @@ -362,7 +360,7 @@ describe('setAlertsToUntracked()', () => { }); test('should untrack by query', async () => { - getAuthorizedRuleTypesMock.mockResolvedValue([ + getAllAuthorizedRuleTypesFindOperationMock.mockResolvedValue([ { id: 'test-rule-type', }, @@ -443,7 +441,7 @@ describe('setAlertsToUntracked()', () => { ], featureIds: ['o11y'], spaceId: 'default', - getAuthorizedRuleTypes: getAuthorizedRuleTypesMock, + getAllAuthorizedRuleTypesFindOperation: getAllAuthorizedRuleTypesFindOperationMock, getAlertIndicesAlias: getAlertIndicesAliasMock, ensureAuthorized: ensureAuthorizedMock, logger, @@ -527,7 +525,7 @@ describe('setAlertsToUntracked()', () => { }); test('should return an empty array if the search returns zero results', async () => { - getAuthorizedRuleTypesMock.mockResolvedValue([ + getAllAuthorizedRuleTypesFindOperationMock.mockResolvedValue([ { id: 'test-rule-type', }, @@ -577,7 +575,7 @@ describe('setAlertsToUntracked()', () => { ], featureIds: ['o11y'], spaceId: 'default', - getAuthorizedRuleTypes: getAuthorizedRuleTypesMock, + getAllAuthorizedRuleTypesFindOperation: getAllAuthorizedRuleTypesFindOperationMock, getAlertIndicesAlias: getAlertIndicesAliasMock, ensureAuthorized: ensureAuthorizedMock, logger, diff --git a/x-pack/plugins/alerting/server/alerts_service/lib/set_alerts_to_untracked.ts b/x-pack/plugins/alerting/server/alerts_service/lib/set_alerts_to_untracked.ts index ed0c2cb21e06b8..4f6ef683cfc2d0 100644 --- a/x-pack/plugins/alerting/server/alerts_service/lib/set_alerts_to_untracked.ts +++ b/x-pack/plugins/alerting/server/alerts_service/lib/set_alerts_to_untracked.ts @@ -21,8 +21,8 @@ import { AlertStatus, } from '@kbn/rule-data-utils'; import type { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; -import { AlertingAuthorizationEntity } from '../../authorization/alerting_authorization'; import type { RulesClientContext } from '../../rules_client'; +import { AlertingAuthorizationEntity } from '../../authorization/types'; type EnsureAuthorized = (opts: { ruleTypeId: string; consumer: string }) => Promise; @@ -34,7 +34,7 @@ export interface SetAlertsToUntrackedParams { spaceId?: RulesClientContext['spaceId']; featureIds?: string[]; isUsingQuery?: boolean; - getAuthorizedRuleTypes?: RulesClientContext['authorization']['getAuthorizedRuleTypes']; + getAllAuthorizedRuleTypesFindOperation?: RulesClientContext['authorization']['getAllAuthorizedRuleTypesFindOperation']; getAlertIndicesAlias?: RulesClientContext['getAlertIndicesAlias']; ensureAuthorized?: EnsureAuthorized; } @@ -156,19 +156,23 @@ const ensureAuthorizedToUntrack = async (params: SetAlertsToUntrackedParamsWithD const getAuthorizedAlertsIndices = async ({ featureIds, - getAuthorizedRuleTypes, + getAllAuthorizedRuleTypesFindOperation, getAlertIndicesAlias, spaceId, logger, }: SetAlertsToUntrackedParamsWithDep) => { try { const authorizedRuleTypes = - (await getAuthorizedRuleTypes?.(AlertingAuthorizationEntity.Alert, new Set(featureIds))) || - []; + (await getAllAuthorizedRuleTypesFindOperation?.( + AlertingAuthorizationEntity.Alert, + new Set(featureIds) + )) || new Map(); + const indices = getAlertIndicesAlias?.( - authorizedRuleTypes.map((art: { id: string }) => art.id), + Array.from(authorizedRuleTypes.keys()).map(({ id }) => id), spaceId ); + return indices; } catch (error) { const errMessage = `Failed to get authorized rule types to untrack alerts by query: ${error}`; diff --git a/x-pack/plugins/alerting/server/application/rule/methods/aggregate/aggregate_rules.test.ts b/x-pack/plugins/alerting/server/application/rule/methods/aggregate/aggregate_rules.test.ts index 57fb2bf8f48a4c..25be70e73a0573 100644 --- a/x-pack/plugins/alerting/server/application/rule/methods/aggregate/aggregate_rules.test.ts +++ b/x-pack/plugins/alerting/server/application/rule/methods/aggregate/aggregate_rules.test.ts @@ -78,24 +78,28 @@ beforeEach(() => { setGlobalDate(); describe('aggregate()', () => { - const listedTypes = new Set([ - { - actionGroups: [], - actionVariables: undefined, - defaultActionGroupId: 'default', - minimumLicenseRequired: 'basic', - isExportable: true, - recoveryActionGroup: RecoveredActionGroup, - id: 'myType', - name: 'myType', - category: 'test', - producer: 'myApp', - enabledInLicense: true, - hasAlertsMappings: false, - hasFieldsForAAD: false, - validLegacyConsumers: [], - }, + const listedTypes = new Map([ + [ + 'myType', + { + actionGroups: [], + actionVariables: undefined, + defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', + isExportable: true, + recoveryActionGroup: RecoveredActionGroup, + id: 'myType', + name: 'myType', + category: 'test', + producer: 'myApp', + enabledInLicense: true, + hasAlertsMappings: false, + hasFieldsForAAD: false, + validLegacyConsumers: [], + }, + ], ]); + beforeEach(() => { authorization.getFindAuthorizationFilter.mockResolvedValue({ ensureRuleTypeIsAuthorized() {}, @@ -161,26 +165,16 @@ describe('aggregate()', () => { }); ruleTypeRegistry.list.mockReturnValue(listedTypes); - authorization.filterByRuleTypeAuthorization.mockResolvedValue( - new Set([ - { - id: 'myType', - name: 'Test', - actionGroups: [{ id: 'default', name: 'Default' }], - defaultActionGroupId: 'default', - minimumLicenseRequired: 'basic', - isExportable: true, - recoveryActionGroup: RecoveredActionGroup, - category: 'test', - producer: 'alerts', - authorizedConsumers: { - myApp: { read: true, all: true }, + authorization.getAuthorizedRuleTypes.mockResolvedValue( + new Map([ + [ + 'myType', + { + authorizedConsumers: { + myApp: { read: true, all: true }, + }, }, - enabledInLicense: true, - hasAlertsMappings: false, - hasFieldsForAAD: false, - validLegacyConsumers: [], - }, + ], ]) ); }); diff --git a/x-pack/plugins/alerting/server/application/rule/methods/bulk_untrack/bulk_untrack_alerts.ts b/x-pack/plugins/alerting/server/application/rule/methods/bulk_untrack/bulk_untrack_alerts.ts index 304037782f6d39..35e6e6ea00e03c 100644 --- a/x-pack/plugins/alerting/server/application/rule/methods/bulk_untrack/bulk_untrack_alerts.ts +++ b/x-pack/plugins/alerting/server/application/rule/methods/bulk_untrack/bulk_untrack_alerts.ts @@ -44,9 +44,8 @@ async function bulkUntrackAlertsWithOCC(context: RulesClientContext, params: Bul featureIds: params.featureIds || [], spaceId: context.spaceId, getAlertIndicesAlias: context.getAlertIndicesAlias, - getAuthorizedRuleTypes: context.authorization.getAuthorizedRuleTypes.bind( - context.authorization - ), + getAllAuthorizedRuleTypesFindOperation: + context.authorization.getAllAuthorizedRuleTypesFindOperation.bind(context.authorization), ensureAuthorized: async ({ ruleTypeId, consumer, diff --git a/x-pack/plugins/alerting/server/application/rule/methods/find/find_rules.test.ts b/x-pack/plugins/alerting/server/application/rule/methods/find/find_rules.test.ts index ee8038f2c8b6c7..6a3b22714ef7ba 100644 --- a/x-pack/plugins/alerting/server/application/rule/methods/find/find_rules.test.ts +++ b/x-pack/plugins/alerting/server/application/rule/methods/find/find_rules.test.ts @@ -92,23 +92,26 @@ jest.mock('../../../../rules_client/common/map_sort_field', () => ({ })); describe('find()', () => { - const listedTypes = new Set([ - { - actionGroups: [], - recoveryActionGroup: RecoveredActionGroup, - actionVariables: undefined, - defaultActionGroupId: 'default', - minimumLicenseRequired: 'basic', - isExportable: true, - id: 'myType', - name: 'myType', - category: 'test', - producer: 'myApp', - enabledInLicense: true, - hasAlertsMappings: false, - hasFieldsForAAD: false, - validLegacyConsumers: [], - }, + const listedTypes = new Map([ + [ + 'myType', + { + actionGroups: [], + recoveryActionGroup: RecoveredActionGroup, + actionVariables: undefined, + defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', + isExportable: true, + id: 'myType', + name: 'myType', + category: 'test', + producer: 'myApp', + enabledInLicense: true, + hasAlertsMappings: false, + hasFieldsForAAD: false, + validLegacyConsumers: [], + }, + ], ]); beforeEach(() => { @@ -162,26 +165,16 @@ describe('find()', () => { }); ruleTypeRegistry.list.mockReturnValue(listedTypes); - authorization.filterByRuleTypeAuthorization.mockResolvedValue( - new Set([ - { - id: 'myType', - name: 'Test', - actionGroups: [{ id: 'default', name: 'Default' }], - recoveryActionGroup: RecoveredActionGroup, - defaultActionGroupId: 'default', - minimumLicenseRequired: 'basic', - isExportable: true, - category: 'test', - producer: 'alerts', - authorizedConsumers: { - myApp: { read: true, all: true }, + authorization.getAuthorizedRuleTypes.mockResolvedValue( + new Map([ + [ + 'myType', + { + authorizedConsumers: { + myApp: { read: true, all: true }, + }, }, - enabledInLicense: true, - hasAlertsMappings: false, - hasFieldsForAAD: false, - validLegacyConsumers: [], - }, + ], ]) ); }); @@ -511,13 +504,34 @@ describe('find()', () => { authorization.getFindAuthorizationFilter.mockResolvedValue({ ensureRuleTypeIsAuthorized() {}, }); + const injectReferencesFn = jest.fn().mockReturnValue({ bar: true, parameterThatIsSavedObjectId: '9', }); - ruleTypeRegistry.list.mockReturnValue( - new Set([ - ...listedTypes, + + const ruleTypes = new Map([ + [ + 'myType', + { + actionGroups: [], + recoveryActionGroup: RecoveredActionGroup, + actionVariables: undefined, + defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', + isExportable: true, + id: 'myType', + name: 'myType', + category: 'test', + producer: 'myApp', + enabledInLicense: true, + hasAlertsMappings: false, + hasFieldsForAAD: false, + validLegacyConsumers: [], + }, + ], + [ + '123', { actionGroups: [], recoveryActionGroup: RecoveredActionGroup, @@ -534,8 +548,10 @@ describe('find()', () => { hasFieldsForAAD: false, validLegacyConsumers: [], }, - ]) - ); + ], + ]); + + ruleTypeRegistry.list.mockReturnValue(ruleTypes); ruleTypeRegistry.get.mockImplementationOnce(() => ({ id: 'myType', name: 'myType', @@ -748,12 +764,33 @@ describe('find()', () => { authorization.getFindAuthorizationFilter.mockResolvedValue({ ensureRuleTypeIsAuthorized() {}, }); + const injectReferencesFn = jest.fn().mockImplementation(() => { throw new Error('something went wrong!'); }); - ruleTypeRegistry.list.mockReturnValue( - new Set([ - ...listedTypes, + + const ruleTypes = new Map([ + [ + 'myType', + { + actionGroups: [], + recoveryActionGroup: RecoveredActionGroup, + actionVariables: undefined, + defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', + isExportable: true, + id: 'myType', + name: 'myType', + category: 'test', + producer: 'myApp', + enabledInLicense: true, + hasAlertsMappings: false, + hasFieldsForAAD: false, + validLegacyConsumers: [], + }, + ], + [ + '123', { actionGroups: [], recoveryActionGroup: RecoveredActionGroup, @@ -770,8 +807,10 @@ describe('find()', () => { hasFieldsForAAD: false, validLegacyConsumers: [], }, - ]) - ); + ], + ]); + + ruleTypeRegistry.list.mockReturnValue(ruleTypes); ruleTypeRegistry.get.mockImplementationOnce(() => ({ id: 'myType', name: 'myType', @@ -790,6 +829,7 @@ describe('find()', () => { }, validLegacyConsumers: [], })); + ruleTypeRegistry.get.mockImplementationOnce(() => ({ id: '123', name: 'Test', diff --git a/x-pack/plugins/alerting/server/application/rule/methods/tags/get_rule_tags.test.ts b/x-pack/plugins/alerting/server/application/rule/methods/tags/get_rule_tags.test.ts index de356c3a2e2b9a..2a84becfd83d6c 100644 --- a/x-pack/plugins/alerting/server/application/rule/methods/tags/get_rule_tags.test.ts +++ b/x-pack/plugins/alerting/server/application/rule/methods/tags/get_rule_tags.test.ts @@ -66,23 +66,26 @@ const rulesClientParams: jest.Mocked = { isSystemAction: jest.fn(), }; -const listedTypes = new Set([ - { - actionGroups: [], - actionVariables: undefined, - defaultActionGroupId: 'default', - minimumLicenseRequired: 'basic', - isExportable: true, - recoveryActionGroup: RecoveredActionGroup, - id: 'myType', - name: 'myType', - category: 'test', - producer: 'myApp', - enabledInLicense: true, - hasAlertsMappings: false, - hasFieldsForAAD: false, - validLegacyConsumers: [], - }, +const listedTypes = new Map([ + [ + 'myType', + { + actionGroups: [], + actionVariables: undefined, + defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', + isExportable: true, + recoveryActionGroup: RecoveredActionGroup, + id: 'myType', + name: 'myType', + category: 'test', + producer: 'myApp', + enabledInLicense: true, + hasAlertsMappings: false, + hasFieldsForAAD: false, + validLegacyConsumers: [], + }, + ], ]); beforeEach(() => { @@ -118,26 +121,16 @@ describe('getTags()', () => { unsecuredSavedObjectsClient.find.mockResolvedValue(getMockAggregationResult(['a', 'b', 'c'])); ruleTypeRegistry.list.mockReturnValue(listedTypes); - authorization.filterByRuleTypeAuthorization.mockResolvedValue( - new Set([ - { - id: 'myType', - name: 'Test', - actionGroups: [{ id: 'default', name: 'Default' }], - defaultActionGroupId: 'default', - minimumLicenseRequired: 'basic', - isExportable: true, - recoveryActionGroup: RecoveredActionGroup, - category: 'test', - producer: 'alerts', - authorizedConsumers: { - myApp: { read: true, all: true }, + authorization.getAuthorizedRuleTypes.mockResolvedValue( + new Map([ + [ + 'myType', + { + authorizedConsumers: { + myApp: { read: true, all: true }, + }, }, - enabledInLicense: true, - hasAlertsMappings: false, - hasFieldsForAAD: false, - validLegacyConsumers: [], - }, + ], ]) ); }); diff --git a/x-pack/plugins/alerting/server/authorization/alerting_authorization.mock.ts b/x-pack/plugins/alerting/server/authorization/alerting_authorization.mock.ts index e51a5c9b12c794..5729b160db85a1 100644 --- a/x-pack/plugins/alerting/server/authorization/alerting_authorization.mock.ts +++ b/x-pack/plugins/alerting/server/authorization/alerting_authorization.mock.ts @@ -14,12 +14,12 @@ export type AlertingAuthorizationMock = jest.Mocked; const createAlertingAuthorizationMock = () => { const mocked: AlertingAuthorizationMock = { ensureAuthorized: jest.fn(), - filterByRuleTypeAuthorization: jest.fn(), - getAuthorizationFilter: jest.fn(), getAuthorizedRuleTypes: jest.fn(), getFindAuthorizationFilter: jest.fn(), - getAugmentedRuleTypesWithAuthorization: jest.fn(), getSpaceId: jest.fn(), + getAllAuthorizedRuleTypes: jest.fn(), + getAllAuthorizedRuleTypesFindOperation: jest.fn(), + getAuthorizationFilter: jest.fn(), }; return mocked; }; diff --git a/x-pack/plugins/alerting/server/authorization/alerting_authorization_kuery.test.ts b/x-pack/plugins/alerting/server/authorization/alerting_authorization_kuery.test.ts index b433a95a77734d..4cb575c4b51e64 100644 --- a/x-pack/plugins/alerting/server/authorization/alerting_authorization_kuery.test.ts +++ b/x-pack/plugins/alerting/server/authorization/alerting_authorization_kuery.test.ts @@ -5,7 +5,6 @@ * 2.0. */ -import { RecoveredActionGroup } from '../../common'; import { AlertingAuthorizationFilterType, asFiltersByRuleTypeAndConsumer, @@ -16,28 +15,20 @@ import { fromKueryExpression } from '@kbn/es-query'; describe('asKqlFiltersByRuleTypeAndConsumer', () => { test('constructs KQL filter for single rule type with single authorized consumer', async () => { + const authorizedRuleTypes = new Map([ + [ + 'myAppAlertType', + { + authorizedConsumers: { + myApp: { read: true, all: true }, + }, + }, + ], + ]); + expect( asFiltersByRuleTypeAndConsumer( - new Set([ - { - actionGroups: [], - defaultActionGroupId: 'default', - recoveryActionGroup: RecoveredActionGroup, - id: 'myAppAlertType', - name: 'myAppAlertType', - category: 'test', - producer: 'myApp', - minimumLicenseRequired: 'basic', - isExportable: true, - authorizedConsumers: { - myApp: { read: true, all: true }, - }, - enabledInLicense: true, - hasAlertsMappings: false, - hasFieldsForAAD: false, - validLegacyConsumers: [], - }, - ]), + authorizedRuleTypes, { type: AlertingAuthorizationFilterType.KQL, fieldNames: { @@ -53,30 +44,22 @@ describe('asKqlFiltersByRuleTypeAndConsumer', () => { }); test('constructs KQL filter for single rule type with multiple authorized consumers', async () => { + const authorizedRuleTypes = new Map([ + [ + 'myAppAlertType', + { + authorizedConsumers: { + alerts: { read: true, all: true }, + myApp: { read: true, all: true }, + myOtherApp: { read: true, all: true }, + }, + }, + ], + ]); + expect( asFiltersByRuleTypeAndConsumer( - new Set([ - { - actionGroups: [], - defaultActionGroupId: 'default', - minimumLicenseRequired: 'basic', - isExportable: true, - recoveryActionGroup: RecoveredActionGroup, - id: 'myAppAlertType', - name: 'myAppAlertType', - category: 'test', - producer: 'myApp', - authorizedConsumers: { - alerts: { read: true, all: true }, - myApp: { read: true, all: true }, - myOtherApp: { read: true, all: true }, - }, - enabledInLicense: true, - hasAlertsMappings: false, - hasFieldsForAAD: false, - validLegacyConsumers: [], - }, - ]), + authorizedRuleTypes, { type: AlertingAuthorizationFilterType.KQL, fieldNames: { @@ -94,73 +77,34 @@ describe('asKqlFiltersByRuleTypeAndConsumer', () => { }); test('constructs KQL filter for multiple rule types across authorized consumer', async () => { - expect( - asFiltersByRuleTypeAndConsumer( - new Set([ - { - actionGroups: [], - defaultActionGroupId: 'default', - minimumLicenseRequired: 'basic', - isExportable: true, - recoveryActionGroup: RecoveredActionGroup, - id: 'myAppAlertType', - name: 'myAppAlertType', - category: 'test', - producer: 'myApp', - authorizedConsumers: { - alerts: { read: true, all: true }, - myApp: { read: true, all: true }, - myOtherApp: { read: true, all: true }, - myAppWithSubFeature: { read: true, all: true }, - }, - enabledInLicense: true, - hasAlertsMappings: false, - hasFieldsForAAD: false, - validLegacyConsumers: [], - }, - { - actionGroups: [], - defaultActionGroupId: 'default', - minimumLicenseRequired: 'basic', - isExportable: true, - recoveryActionGroup: RecoveredActionGroup, - id: 'myOtherAppAlertType', - name: 'myOtherAppAlertType', - category: 'test', - producer: 'alerts', - authorizedConsumers: { - alerts: { read: true, all: true }, - myApp: { read: true, all: true }, - myOtherApp: { read: true, all: true }, - myAppWithSubFeature: { read: true, all: true }, - }, - enabledInLicense: true, - hasAlertsMappings: false, - hasFieldsForAAD: false, - validLegacyConsumers: [], + const authorizedRuleTypes = new Map([ + [ + 'myAppAlertType', + { + authorizedConsumers: { + alerts: { read: true, all: true }, + myApp: { read: true, all: true }, + myOtherApp: { read: true, all: true }, + myAppWithSubFeature: { read: true, all: true }, }, - { - actionGroups: [], - defaultActionGroupId: 'default', - minimumLicenseRequired: 'basic', - isExportable: true, - recoveryActionGroup: RecoveredActionGroup, - id: 'mySecondAppAlertType', - name: 'mySecondAppAlertType', - category: 'test', - producer: 'myApp', - authorizedConsumers: { - alerts: { read: true, all: true }, - myApp: { read: true, all: true }, - myOtherApp: { read: true, all: true }, - myAppWithSubFeature: { read: true, all: true }, - }, - enabledInLicense: true, - hasAlertsMappings: false, - hasFieldsForAAD: false, - validLegacyConsumers: [], + }, + ], + [ + 'myOtherAppAlertType', + { + authorizedConsumers: { + alerts: { read: true, all: true }, + myApp: { read: true, all: true }, + myOtherApp: { read: true, all: true }, + myAppWithSubFeature: { read: true, all: true }, }, - ]), + }, + ], + ]); + + expect( + asFiltersByRuleTypeAndConsumer( + authorizedRuleTypes, { type: AlertingAuthorizationFilterType.KQL, fieldNames: { @@ -178,52 +122,34 @@ describe('asKqlFiltersByRuleTypeAndConsumer', () => { }); test('constructs KQL filter with spaceId filter when spaceIds field path exists', async () => { - expect( - asFiltersByRuleTypeAndConsumer( - new Set([ - { - actionGroups: [], - defaultActionGroupId: 'default', - minimumLicenseRequired: 'basic', - isExportable: true, - recoveryActionGroup: RecoveredActionGroup, - id: 'myAppAlertType', - name: 'myAppAlertType', - category: 'test', - producer: 'myApp', - authorizedConsumers: { - alerts: { read: true, all: true }, - myApp: { read: true, all: true }, - myOtherApp: { read: true, all: true }, - myAppWithSubFeature: { read: true, all: true }, - }, - enabledInLicense: true, - hasAlertsMappings: false, - hasFieldsForAAD: false, - validLegacyConsumers: [], + const authorizedRuleTypes = new Map([ + [ + 'myAppAlertType', + { + authorizedConsumers: { + alerts: { read: true, all: true }, + myApp: { read: true, all: true }, + myOtherApp: { read: true, all: true }, + myAppWithSubFeature: { read: true, all: true }, }, - { - actionGroups: [], - defaultActionGroupId: 'default', - minimumLicenseRequired: 'basic', - isExportable: true, - recoveryActionGroup: RecoveredActionGroup, - id: 'myOtherAppAlertType', - name: 'myOtherAppAlertType', - category: 'test', - producer: 'alerts', - authorizedConsumers: { - alerts: { read: true, all: true }, - myApp: { read: true, all: true }, - myOtherApp: { read: true, all: true }, - myAppWithSubFeature: { read: true, all: true }, - }, - enabledInLicense: true, - hasAlertsMappings: false, - hasFieldsForAAD: false, - validLegacyConsumers: [], + }, + ], + [ + 'myOtherAppAlertType', + { + authorizedConsumers: { + alerts: { read: true, all: true }, + myApp: { read: true, all: true }, + myOtherApp: { read: true, all: true }, + myAppWithSubFeature: { read: true, all: true }, }, - ]), + }, + ], + ]); + + expect( + asFiltersByRuleTypeAndConsumer( + authorizedRuleTypes, { type: AlertingAuthorizationFilterType.KQL, fieldNames: { @@ -242,52 +168,34 @@ describe('asKqlFiltersByRuleTypeAndConsumer', () => { }); test('constructs KQL filter without spaceId filter when spaceIds path is specified, but spaceId is undefined', async () => { - expect( - asFiltersByRuleTypeAndConsumer( - new Set([ - { - actionGroups: [], - defaultActionGroupId: 'default', - minimumLicenseRequired: 'basic', - isExportable: true, - recoveryActionGroup: RecoveredActionGroup, - id: 'myAppAlertType', - name: 'myAppAlertType', - category: 'test', - producer: 'myApp', - authorizedConsumers: { - alerts: { read: true, all: true }, - myApp: { read: true, all: true }, - myOtherApp: { read: true, all: true }, - myAppWithSubFeature: { read: true, all: true }, - }, - enabledInLicense: true, - hasAlertsMappings: false, - hasFieldsForAAD: false, - validLegacyConsumers: [], + const authorizedRuleTypes = new Map([ + [ + 'myAppAlertType', + { + authorizedConsumers: { + alerts: { read: true, all: true }, + myApp: { read: true, all: true }, + myOtherApp: { read: true, all: true }, + myAppWithSubFeature: { read: true, all: true }, }, - { - actionGroups: [], - defaultActionGroupId: 'default', - minimumLicenseRequired: 'basic', - isExportable: true, - recoveryActionGroup: RecoveredActionGroup, - id: 'myOtherAppAlertType', - name: 'myOtherAppAlertType', - category: 'test', - producer: 'alerts', - authorizedConsumers: { - alerts: { read: true, all: true }, - myApp: { read: true, all: true }, - myOtherApp: { read: true, all: true }, - myAppWithSubFeature: { read: true, all: true }, - }, - enabledInLicense: true, - hasAlertsMappings: false, - hasFieldsForAAD: false, - validLegacyConsumers: [], + }, + ], + [ + 'myOtherAppAlertType', + { + authorizedConsumers: { + alerts: { read: true, all: true }, + myApp: { read: true, all: true }, + myOtherApp: { read: true, all: true }, + myAppWithSubFeature: { read: true, all: true }, }, - ]), + }, + ], + ]); + + expect( + asFiltersByRuleTypeAndConsumer( + authorizedRuleTypes, { type: AlertingAuthorizationFilterType.KQL, fieldNames: { @@ -306,25 +214,17 @@ describe('asKqlFiltersByRuleTypeAndConsumer', () => { }); test('constructs KQL filter for single rule type with no authorized consumer', async () => { - const result = asFiltersByRuleTypeAndConsumer( - new Set([ + const authorizedRuleTypes = new Map([ + [ + 'myAppAlertType', { - actionGroups: [], - defaultActionGroupId: 'default', - recoveryActionGroup: RecoveredActionGroup, - id: 'myAppAlertType', - name: 'myAppAlertType', - category: 'test', - producer: 'myApp', - minimumLicenseRequired: 'basic', - isExportable: true, authorizedConsumers: {}, - enabledInLicense: true, - hasAlertsMappings: false, - hasFieldsForAAD: false, - validLegacyConsumers: [], }, - ]), + ], + ]); + + const result = asFiltersByRuleTypeAndConsumer( + authorizedRuleTypes, { type: AlertingAuthorizationFilterType.KQL, fieldNames: { @@ -341,28 +241,20 @@ describe('asKqlFiltersByRuleTypeAndConsumer', () => { describe('asEsDslFiltersByRuleTypeAndConsumer', () => { test('constructs ES DSL filter for single rule type with single authorized consumer', async () => { + const authorizedRuleTypes = new Map([ + [ + 'myAppAlertType', + { + authorizedConsumers: { + myApp: { read: true, all: true }, + }, + }, + ], + ]); + expect( asFiltersByRuleTypeAndConsumer( - new Set([ - { - actionGroups: [], - defaultActionGroupId: 'default', - recoveryActionGroup: RecoveredActionGroup, - id: 'myAppAlertType', - name: 'myAppAlertType', - category: 'test', - producer: 'myApp', - minimumLicenseRequired: 'basic', - isExportable: true, - authorizedConsumers: { - myApp: { read: true, all: true }, - }, - enabledInLicense: true, - hasAlertsMappings: false, - hasFieldsForAAD: false, - validLegacyConsumers: [], - }, - ]), + authorizedRuleTypes, { type: AlertingAuthorizationFilterType.ESDSL, fieldNames: { @@ -405,30 +297,22 @@ describe('asEsDslFiltersByRuleTypeAndConsumer', () => { }); test('constructs ES DSL filter for single rule type with multiple authorized consumers', async () => { + const authorizedRuleTypes = new Map([ + [ + 'myAppAlertType', + { + authorizedConsumers: { + alerts: { read: true, all: true }, + myApp: { read: true, all: true }, + myOtherApp: { read: true, all: true }, + }, + }, + ], + ]); + expect( asFiltersByRuleTypeAndConsumer( - new Set([ - { - actionGroups: [], - defaultActionGroupId: 'default', - minimumLicenseRequired: 'basic', - isExportable: true, - recoveryActionGroup: RecoveredActionGroup, - id: 'myAppAlertType', - name: 'myAppAlertType', - category: 'test', - producer: 'myApp', - authorizedConsumers: { - alerts: { read: true, all: true }, - myApp: { read: true, all: true }, - myOtherApp: { read: true, all: true }, - }, - enabledInLicense: true, - hasAlertsMappings: false, - hasFieldsForAAD: false, - validLegacyConsumers: [], - }, - ]), + authorizedRuleTypes, { type: AlertingAuthorizationFilterType.ESDSL, fieldNames: { @@ -478,73 +362,34 @@ describe('asEsDslFiltersByRuleTypeAndConsumer', () => { }); test('constructs ES DSL filter for multiple rule types across authorized consumer', async () => { - expect( - asFiltersByRuleTypeAndConsumer( - new Set([ - { - actionGroups: [], - defaultActionGroupId: 'default', - minimumLicenseRequired: 'basic', - isExportable: true, - recoveryActionGroup: RecoveredActionGroup, - id: 'myAppAlertType', - name: 'myAppAlertType', - category: 'test', - producer: 'myApp', - authorizedConsumers: { - alerts: { read: true, all: true }, - myApp: { read: true, all: true }, - myOtherApp: { read: true, all: true }, - myAppWithSubFeature: { read: true, all: true }, - }, - enabledInLicense: true, - hasAlertsMappings: false, - hasFieldsForAAD: false, - validLegacyConsumers: [], - }, - { - actionGroups: [], - defaultActionGroupId: 'default', - minimumLicenseRequired: 'basic', - isExportable: true, - recoveryActionGroup: RecoveredActionGroup, - id: 'myOtherAppAlertType', - name: 'myOtherAppAlertType', - category: 'test', - producer: 'alerts', - authorizedConsumers: { - alerts: { read: true, all: true }, - myApp: { read: true, all: true }, - myOtherApp: { read: true, all: true }, - myAppWithSubFeature: { read: true, all: true }, - }, - enabledInLicense: true, - hasAlertsMappings: false, - hasFieldsForAAD: false, - validLegacyConsumers: [], + const authorizedRuleTypes = new Map([ + [ + 'myAppAlertType', + { + authorizedConsumers: { + alerts: { read: true, all: true }, + myApp: { read: true, all: true }, + myOtherApp: { read: true, all: true }, + myAppWithSubFeature: { read: true, all: true }, }, - { - actionGroups: [], - defaultActionGroupId: 'default', - minimumLicenseRequired: 'basic', - isExportable: true, - recoveryActionGroup: RecoveredActionGroup, - id: 'mySecondAppAlertType', - name: 'mySecondAppAlertType', - category: 'test', - producer: 'myApp', - authorizedConsumers: { - alerts: { read: true, all: true }, - myApp: { read: true, all: true }, - myOtherApp: { read: true, all: true }, - myAppWithSubFeature: { read: true, all: true }, - }, - enabledInLicense: true, - hasAlertsMappings: false, - hasFieldsForAAD: false, - validLegacyConsumers: [], + }, + ], + [ + 'myOtherAppAlertType', + { + authorizedConsumers: { + alerts: { read: true, all: true }, + myApp: { read: true, all: true }, + myOtherApp: { read: true, all: true }, + myAppWithSubFeature: { read: true, all: true }, }, - ]), + }, + ], + ]); + + expect( + asFiltersByRuleTypeAndConsumer( + authorizedRuleTypes, { type: AlertingAuthorizationFilterType.ESDSL, fieldNames: { @@ -693,25 +538,17 @@ describe('asEsDslFiltersByRuleTypeAndConsumer', () => { }); test('constructs KQL filter for single rule type with no authorized consumer', async () => { - const result = asFiltersByRuleTypeAndConsumer( - new Set([ + const authorizedRuleTypes = new Map([ + [ + 'myAppAlertType', { - actionGroups: [], - defaultActionGroupId: 'default', - recoveryActionGroup: RecoveredActionGroup, - id: 'myAppAlertType', - name: 'myAppAlertType', - category: 'test', - producer: 'myApp', - minimumLicenseRequired: 'basic', - isExportable: true, authorizedConsumers: {}, - enabledInLicense: true, - hasAlertsMappings: false, - hasFieldsForAAD: false, - validLegacyConsumers: [], }, - ]), + ], + ]); + + const result = asFiltersByRuleTypeAndConsumer( + authorizedRuleTypes, { type: AlertingAuthorizationFilterType.ESDSL, fieldNames: { diff --git a/x-pack/plugins/alerting/server/authorization/index.ts b/x-pack/plugins/alerting/server/authorization/index.ts index 17f0f9f22bbe1f..e31dac301cbcbc 100644 --- a/x-pack/plugins/alerting/server/authorization/index.ts +++ b/x-pack/plugins/alerting/server/authorization/index.ts @@ -7,3 +7,4 @@ export * from './alerting_authorization'; export * from './alerting_authorization_kuery'; +export * from './types'; diff --git a/x-pack/plugins/alerting/server/index.ts b/x-pack/plugins/alerting/server/index.ts index 78aad949131a60..a7d5cde2e064c4 100644 --- a/x-pack/plugins/alerting/server/index.ts +++ b/x-pack/plugins/alerting/server/index.ts @@ -45,12 +45,13 @@ export { parseDuration, isRuleSnoozed } from './lib'; export { getEsErrorMessage } from './lib/errors'; export type { AlertingRulesConfig } from './config'; export { - ReadOperations, AlertingAuthorizationFilterType, AlertingAuthorization, + ReadOperations, WriteOperations, AlertingAuthorizationEntity, } from './authorization'; + export { DEFAULT_ALERTS_ILM_POLICY, DEFAULT_ALERTS_ILM_POLICY_NAME, diff --git a/x-pack/plugins/alerting/server/routes/health.test.ts b/x-pack/plugins/alerting/server/routes/health.test.ts index 28117eaeeb55bd..a3befd4e1d45dc 100644 --- a/x-pack/plugins/alerting/server/routes/health.test.ts +++ b/x-pack/plugins/alerting/server/routes/health.test.ts @@ -25,7 +25,7 @@ jest.mock('../lib/license_api_access', () => ({ const alerting = alertsMock.createStart(); const currentDate = new Date().toISOString(); -const ruleTypes = [ +const ruleTypes: RegistryAlertTypeWithAuth[] = [ { id: '1', name: 'name', @@ -48,12 +48,11 @@ const ruleTypes = [ category: 'test', producer: 'test', enabledInLicense: true, - minimumScheduleInterval: '1m', defaultScheduleInterval: '10m', hasAlertsMappings: false, hasFieldsForAAD: false, validLegacyConsumers: [], - } as RegistryAlertTypeWithAuth, + }, ]; beforeEach(() => { @@ -76,7 +75,7 @@ beforeEach(() => { describe('healthRoute', () => { it('registers the route', async () => { - rulesClient.listRuleTypes.mockResolvedValueOnce(new Set(ruleTypes)); + rulesClient.listRuleTypes.mockResolvedValueOnce(ruleTypes); const router = httpServiceMock.createRouter(); const licenseState = licenseStateMock.create(); @@ -89,7 +88,7 @@ describe('healthRoute', () => { }); it('queries the usage api', async () => { - rulesClient.listRuleTypes.mockResolvedValueOnce(new Set(ruleTypes)); + rulesClient.listRuleTypes.mockResolvedValueOnce(ruleTypes); const router = httpServiceMock.createRouter(); const licenseState = licenseStateMock.create(); @@ -113,7 +112,7 @@ describe('healthRoute', () => { }); it('throws error when user does not have any access to any rule types', async () => { - rulesClient.listRuleTypes.mockResolvedValueOnce(new Set()); + rulesClient.listRuleTypes.mockResolvedValueOnce([]); const router = httpServiceMock.createRouter(); const licenseState = licenseStateMock.create(); @@ -139,7 +138,7 @@ describe('healthRoute', () => { }); it('evaluates whether Encrypted Saved Objects is missing encryption key', async () => { - rulesClient.listRuleTypes.mockResolvedValueOnce(new Set(ruleTypes)); + rulesClient.listRuleTypes.mockResolvedValueOnce(ruleTypes); const router = httpServiceMock.createRouter(); const licenseState = licenseStateMock.create(); @@ -180,7 +179,7 @@ describe('healthRoute', () => { }); test('when ES security status cannot be determined from license state, isSufficientlySecure should return false', async () => { - rulesClient.listRuleTypes.mockResolvedValueOnce(new Set(ruleTypes)); + rulesClient.listRuleTypes.mockResolvedValueOnce(ruleTypes); const router = httpServiceMock.createRouter(); const licenseState = licenseStateMock.create(); const encryptedSavedObjects = encryptedSavedObjectsMock.createSetup({ canEncrypt: true }); @@ -222,7 +221,7 @@ describe('healthRoute', () => { }); test('when ES security is disabled, isSufficientlySecure should return true', async () => { - rulesClient.listRuleTypes.mockResolvedValueOnce(new Set(ruleTypes)); + rulesClient.listRuleTypes.mockResolvedValueOnce(ruleTypes); const router = httpServiceMock.createRouter(); const licenseState = licenseStateMock.create(); const encryptedSavedObjects = encryptedSavedObjectsMock.createSetup({ canEncrypt: true }); @@ -264,7 +263,7 @@ describe('healthRoute', () => { }); test('when ES security is enabled but user cannot generate api keys, isSufficientlySecure should return false', async () => { - rulesClient.listRuleTypes.mockResolvedValueOnce(new Set(ruleTypes)); + rulesClient.listRuleTypes.mockResolvedValueOnce(ruleTypes); const router = httpServiceMock.createRouter(); const licenseState = licenseStateMock.create(); const encryptedSavedObjects = encryptedSavedObjectsMock.createSetup({ canEncrypt: true }); @@ -306,7 +305,7 @@ describe('healthRoute', () => { }); test('when ES security is enabled and user can generate api keys, isSufficientlySecure should return true', async () => { - rulesClient.listRuleTypes.mockResolvedValueOnce(new Set(ruleTypes)); + rulesClient.listRuleTypes.mockResolvedValueOnce(ruleTypes); const router = httpServiceMock.createRouter(); const licenseState = licenseStateMock.create(); const encryptedSavedObjects = encryptedSavedObjectsMock.createSetup({ canEncrypt: true }); diff --git a/x-pack/plugins/alerting/server/routes/legacy/health.test.ts b/x-pack/plugins/alerting/server/routes/legacy/health.test.ts index d582a8e0ec480d..8b093aead593b5 100644 --- a/x-pack/plugins/alerting/server/routes/legacy/health.test.ts +++ b/x-pack/plugins/alerting/server/routes/legacy/health.test.ts @@ -81,7 +81,7 @@ beforeEach(() => { describe('healthRoute', () => { it('registers the route', async () => { - rulesClient.listRuleTypes.mockResolvedValueOnce(new Set(ruleTypes)); + rulesClient.listRuleTypes.mockResolvedValueOnce(ruleTypes); const router = httpServiceMock.createRouter(); const licenseState = licenseStateMock.create(); @@ -94,7 +94,7 @@ describe('healthRoute', () => { }); it('throws error when user does not have any access to any rule types', async () => { - rulesClient.listRuleTypes.mockResolvedValueOnce(new Set()); + rulesClient.listRuleTypes.mockResolvedValueOnce([]); const router = httpServiceMock.createRouter(); const licenseState = licenseStateMock.create(); @@ -120,7 +120,7 @@ describe('healthRoute', () => { }); it('evaluates whether Encrypted Saved Objects is missing encryption key', async () => { - rulesClient.listRuleTypes.mockResolvedValueOnce(new Set(ruleTypes)); + rulesClient.listRuleTypes.mockResolvedValueOnce(ruleTypes); const router = httpServiceMock.createRouter(); const licenseState = licenseStateMock.create(); @@ -177,7 +177,7 @@ describe('healthRoute', () => { }); test('when ES security status cannot be determined from license state, isSufficientlySecure should return false', async () => { - rulesClient.listRuleTypes.mockResolvedValueOnce(new Set(ruleTypes)); + rulesClient.listRuleTypes.mockResolvedValueOnce(ruleTypes); const router = httpServiceMock.createRouter(); const licenseState = licenseStateMock.create(); const encryptedSavedObjects = encryptedSavedObjectsMock.createSetup({ canEncrypt: true }); @@ -235,7 +235,7 @@ describe('healthRoute', () => { }); test('when ES security is disabled, isSufficientlySecure should return true', async () => { - rulesClient.listRuleTypes.mockResolvedValueOnce(new Set(ruleTypes)); + rulesClient.listRuleTypes.mockResolvedValueOnce(ruleTypes); const router = httpServiceMock.createRouter(); const licenseState = licenseStateMock.create(); const encryptedSavedObjects = encryptedSavedObjectsMock.createSetup({ canEncrypt: true }); @@ -293,7 +293,7 @@ describe('healthRoute', () => { }); test('when ES security is enabled but user cannot generate api keys, isSufficientlySecure should return false', async () => { - rulesClient.listRuleTypes.mockResolvedValueOnce(new Set(ruleTypes)); + rulesClient.listRuleTypes.mockResolvedValueOnce(ruleTypes); const router = httpServiceMock.createRouter(); const licenseState = licenseStateMock.create(); const encryptedSavedObjects = encryptedSavedObjectsMock.createSetup({ canEncrypt: true }); @@ -351,7 +351,7 @@ describe('healthRoute', () => { }); test('when ES security is enabled and user can generate api keys, isSufficientlySecure should return true', async () => { - rulesClient.listRuleTypes.mockResolvedValueOnce(new Set(ruleTypes)); + rulesClient.listRuleTypes.mockResolvedValueOnce(ruleTypes); const router = httpServiceMock.createRouter(); const licenseState = licenseStateMock.create(); const encryptedSavedObjects = encryptedSavedObjectsMock.createSetup({ canEncrypt: true }); @@ -409,7 +409,7 @@ describe('healthRoute', () => { }); it('should track every call', async () => { - rulesClient.listRuleTypes.mockResolvedValueOnce(new Set(ruleTypes)); + rulesClient.listRuleTypes.mockResolvedValueOnce(ruleTypes); const licenseState = licenseStateMock.create(); const router = httpServiceMock.createRouter(); const encryptedSavedObjects = encryptedSavedObjectsMock.createSetup({ canEncrypt: true }); diff --git a/x-pack/plugins/alerting/server/routes/legacy/list_alert_types.test.ts b/x-pack/plugins/alerting/server/routes/legacy/list_alert_types.test.ts index b9abeafd00eccb..384d8be9276b6c 100644 --- a/x-pack/plugins/alerting/server/routes/legacy/list_alert_types.test.ts +++ b/x-pack/plugins/alerting/server/routes/legacy/list_alert_types.test.ts @@ -41,7 +41,7 @@ describe('listAlertTypesRoute', () => { expect(config.path).toMatchInlineSnapshot(`"/api/alerts/list_alert_types"`); - const listTypes = [ + const listTypes: RegistryAlertTypeWithAuth[] = [ { id: '1', name: 'name', @@ -66,9 +66,10 @@ describe('listAlertTypesRoute', () => { hasAlertsMappings: false, hasFieldsForAAD: false, validLegacyConsumers: [], - } as RegistryAlertTypeWithAuth, + }, ]; - rulesClient.listRuleTypes.mockResolvedValueOnce(new Set(listTypes)); + + rulesClient.listRuleTypes.mockResolvedValueOnce(listTypes); const [context, req, res] = mockHandlerArguments({ rulesClient }, {}, ['ok']); @@ -152,7 +153,7 @@ describe('listAlertTypesRoute', () => { } as RegistryAlertTypeWithAuth, ]; - rulesClient.listRuleTypes.mockResolvedValueOnce(new Set(listTypes)); + rulesClient.listRuleTypes.mockResolvedValueOnce(listTypes); const [context, req, res] = mockHandlerArguments( { rulesClient }, @@ -209,7 +210,7 @@ describe('listAlertTypesRoute', () => { } as RegistryAlertTypeWithAuth, ]; - rulesClient.listRuleTypes.mockResolvedValueOnce(new Set(listTypes)); + rulesClient.listRuleTypes.mockResolvedValueOnce(listTypes); const [context, req, res] = mockHandlerArguments( { rulesClient }, @@ -230,7 +231,7 @@ describe('listAlertTypesRoute', () => { const mockUsageCountersSetup = usageCountersServiceMock.createSetupContract(); const mockUsageCounter = mockUsageCountersSetup.createUsageCounter('test'); - rulesClient.listRuleTypes.mockResolvedValueOnce(new Set([])); + rulesClient.listRuleTypes.mockResolvedValueOnce([]); listAlertTypesRoute(router, licenseState, mockUsageCounter); const [, handler] = router.get.mock.calls[0]; diff --git a/x-pack/plugins/alerting/server/routes/rule_types.test.ts b/x-pack/plugins/alerting/server/routes/rule_types.test.ts index a6483f15f9f1c2..6064fb232ca226 100644 --- a/x-pack/plugins/alerting/server/routes/rule_types.test.ts +++ b/x-pack/plugins/alerting/server/routes/rule_types.test.ts @@ -97,7 +97,7 @@ describe('ruleTypesRoute', () => { has_fields_for_a_a_d: false, }, ]; - rulesClient.listRuleTypes.mockResolvedValueOnce(new Set(listTypes)); + rulesClient.listRuleTypes.mockResolvedValueOnce(listTypes); const [context, req, res] = mockHandlerArguments({ rulesClient }, {}, ['ok']); @@ -183,7 +183,7 @@ describe('ruleTypesRoute', () => { } as RegistryAlertTypeWithAuth, ]; - rulesClient.listRuleTypes.mockResolvedValueOnce(new Set(listTypes)); + rulesClient.listRuleTypes.mockResolvedValueOnce(listTypes); const [context, req, res] = mockHandlerArguments( { rulesClient }, @@ -240,7 +240,7 @@ describe('ruleTypesRoute', () => { } as RegistryAlertTypeWithAuth, ]; - rulesClient.listRuleTypes.mockResolvedValueOnce(new Set(listTypes)); + rulesClient.listRuleTypes.mockResolvedValueOnce(listTypes); const [context, req, res] = mockHandlerArguments( { rulesClient }, diff --git a/x-pack/plugins/alerting/server/routes/suggestions/values_suggestion_alerts.ts b/x-pack/plugins/alerting/server/routes/suggestions/values_suggestion_alerts.ts index 1c0a0ac9621863..12d7860bf7f1fa 100644 --- a/x-pack/plugins/alerting/server/routes/suggestions/values_suggestion_alerts.ts +++ b/x-pack/plugins/alerting/server/routes/suggestions/values_suggestion_alerts.ts @@ -27,6 +27,7 @@ import { AlertingAuthorizationEntity, AlertingAuthorizationFilterOpts, AlertingAuthorizationFilterType, + AuthorizedRuleTypes, } from '../../authorization'; import { AlertingRequestHandlerContext } from '../../types'; import { GetAlertIndicesAlias, ILicenseState } from '../../lib'; @@ -75,14 +76,16 @@ export function registerAlertsValueSuggestionsRoute( const alertingContext = await context.alerting; const rulesClient = await alertingContext.getRulesClient(); let authorizationTuple; - let authorizedRuleType = []; + let authorizedRuleType: AuthorizedRuleTypes = new Map(); + try { const authorization = rulesClient.getAuthorization(); authorizationTuple = await authorization.getFindAuthorizationFilter( AlertingAuthorizationEntity.Alert, alertingAuthorizationFilterOpts ); - authorizedRuleType = await authorization.getAuthorizedRuleTypes( + + authorizedRuleType = await authorization.getAllAuthorizedRuleTypesFindOperation( AlertingAuthorizationEntity.Alert, VALID_FEATURE_IDS ); @@ -93,8 +96,10 @@ export function registerAlertsValueSuggestionsRoute( error, }) ); + throw error; } + const spaceId = rulesClient.getSpaceId(); const { filter: authorizationFilter } = authorizationTuple; const filters = [ @@ -103,9 +108,10 @@ export function registerAlertsValueSuggestionsRoute( ] as estypes.QueryDslQueryContainer[]; const index = getAlertIndicesAlias!( - authorizedRuleType.map((art) => art.id), + Array.from(authorizedRuleType.keys()).map((id) => id), spaceId ).join(','); + try { const body = await termsAggSuggestions( config, diff --git a/x-pack/plugins/alerting/server/rule_type_registry.ts b/x-pack/plugins/alerting/server/rule_type_registry.ts index d1ffe59df3b6fe..5468dea79e525c 100644 --- a/x-pack/plugins/alerting/server/rule_type_registry.ts +++ b/x-pack/plugins/alerting/server/rule_type_registry.ts @@ -374,59 +374,26 @@ export class RuleTypeRegistry { >; } - public list(): Set { - const mapRuleTypes: Array<[string, UntypedNormalizedRuleType]> = Array.from(this.ruleTypes); - const tempRegistryRuleType = mapRuleTypes.map( - ([ - id, - { - name, - actionGroups, - recoveryActionGroup, - defaultActionGroupId, - actionVariables, - category, - producer, - minimumLicenseRequired, - isExportable, - ruleTaskTimeout, - defaultScheduleInterval, - doesSetRecoveryContext, - alerts, - fieldsForAAD, - validLegacyConsumers, - }, - ]) => { - // KEEP the type here to be safe if not the map is ignoring it for some reason - const ruleType: RegistryRuleType = { - id, - name, - actionGroups, - recoveryActionGroup, - defaultActionGroupId, - actionVariables, - category, - producer, - minimumLicenseRequired, - isExportable, - ruleTaskTimeout, - defaultScheduleInterval, - doesSetRecoveryContext, - enabledInLicense: !!this.licenseState.getLicenseCheckForRuleType( - id, - name, - minimumLicenseRequired - ).isValid, - fieldsForAAD, - hasFieldsForAAD: Boolean(fieldsForAAD), - hasAlertsMappings: !!alerts, - validLegacyConsumers, - ...(alerts ? { alerts } : {}), - }; - return ruleType; - } - ); - return new Set(tempRegistryRuleType); + public list(): Map { + const ruleTypesMap = new Map(); + + this.ruleTypes.forEach((_ruleType) => { + const ruleType: RegistryRuleType = { + ..._ruleType, + enabledInLicense: !!this.licenseState.getLicenseCheckForRuleType( + _ruleType.id, + _ruleType.name, + _ruleType.minimumLicenseRequired + ).isValid, + hasFieldsForAAD: Boolean(_ruleType.fieldsForAAD), + hasAlertsMappings: !!_ruleType.alerts, + ...(_ruleType.alerts ? { alerts: _ruleType.alerts } : {}), + }; + + ruleTypesMap.set(ruleType.id, ruleType); + }); + + return ruleTypesMap; } public getAllTypes(): string[] { diff --git a/x-pack/plugins/alerting/server/rules_client/methods/list_rule_types.ts b/x-pack/plugins/alerting/server/rules_client/methods/list_rule_types.ts index 51f5b8f8af7ad7..7fc11e6fb5c8f4 100644 --- a/x-pack/plugins/alerting/server/rules_client/methods/list_rule_types.ts +++ b/x-pack/plugins/alerting/server/rules_client/methods/list_rule_types.ts @@ -5,13 +5,29 @@ * 2.0. */ -import { WriteOperations, ReadOperations, AlertingAuthorizationEntity } from '../../authorization'; +import { + WriteOperations, + ReadOperations, + AlertingAuthorizationEntity, + RegistryAlertTypeWithAuth, +} from '../../authorization'; import { RulesClientContext } from '../types'; -export async function listRuleTypes(context: RulesClientContext) { - return await context.authorization.filterByRuleTypeAuthorization( - context.ruleTypeRegistry.list(), +export async function listRuleTypes( + context: RulesClientContext +): Promise { + const registeredRuleTypes = context.ruleTypeRegistry.list(); + + const authorizedRuleTypes = await context.authorization.getAuthorizedRuleTypes( + new Set(Array.from(registeredRuleTypes.keys()).map((id) => id)), [ReadOperations.Get, WriteOperations.Create], AlertingAuthorizationEntity.Rule ); + + return Array.from(authorizedRuleTypes.entries()) + .filter(([id, _]) => context.ruleTypeRegistry.has(id)) + .map(([id, { authorizedConsumers }]) => ({ + ...registeredRuleTypes.get(id)!, + authorizedConsumers, + })); } diff --git a/x-pack/plugins/alerting/server/rules_client/tests/list_rule_types.test.ts b/x-pack/plugins/alerting/server/rules_client/tests/list_rule_types.test.ts index b096ec1c75f7de..c3e33ec06d68de 100644 --- a/x-pack/plugins/alerting/server/rules_client/tests/list_rule_types.test.ts +++ b/x-pack/plugins/alerting/server/rules_client/tests/list_rule_types.test.ts @@ -88,6 +88,7 @@ describe('listRuleTypes', () => { hasFieldsForAAD: false, validLegacyConsumers: [], }; + const myAppAlertType: RegistryRuleType = { actionGroups: [], actionVariables: undefined, @@ -104,7 +105,11 @@ describe('listRuleTypes', () => { hasFieldsForAAD: false, validLegacyConsumers: [], }; - const setOfAlertTypes = new Set([myAppAlertType, alertingAlertType]); + + const setOfAlertTypes = new Map([ + [myAppAlertType.id, myAppAlertType], + [alertingAlertType.id, alertingAlertType], + ]); const authorizedConsumers = { alerts: { read: true, all: true }, @@ -118,12 +123,13 @@ describe('listRuleTypes', () => { test('should return a list of AlertTypes that exist in the registry', async () => { ruleTypeRegistry.list.mockReturnValue(setOfAlertTypes); - authorization.filterByRuleTypeAuthorization.mockResolvedValue( - new Set([ - { ...myAppAlertType, authorizedConsumers }, - { ...alertingAlertType, authorizedConsumers }, + authorization.getAuthorizedRuleTypes.mockResolvedValue( + new Map([ + [myAppAlertType.id, { authorizedConsumers }], + [alertingAlertType.id, { authorizedConsumers }], ]) ); + expect(await rulesClient.listRuleTypes()).toEqual( new Set([ { ...myAppAlertType, authorizedConsumers }, @@ -133,39 +139,46 @@ describe('listRuleTypes', () => { }); describe('authorization', () => { - const listedTypes = new Set([ - { - actionGroups: [], - actionVariables: undefined, - defaultActionGroupId: 'default', - minimumLicenseRequired: 'basic', - isExportable: true, - recoveryActionGroup: RecoveredActionGroup, - id: 'myType', - name: 'myType', - category: 'test', - producer: 'myApp', - enabledInLicense: true, - hasAlertsMappings: false, - hasFieldsForAAD: false, - validLegacyConsumers: [], - }, - { - id: 'myOtherType', - name: 'Test', - actionGroups: [{ id: 'default', name: 'Default' }], - defaultActionGroupId: 'default', - minimumLicenseRequired: 'basic', - isExportable: true, - recoveryActionGroup: RecoveredActionGroup, - category: 'test', - producer: 'alerts', - enabledInLicense: true, - hasAlertsMappings: false, - hasFieldsForAAD: false, - validLegacyConsumers: [], - }, + const listedTypes = new Map([ + [ + 'myType', + { + actionGroups: [], + actionVariables: undefined, + defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', + isExportable: true, + recoveryActionGroup: RecoveredActionGroup, + id: 'myType', + name: 'myType', + category: 'test', + producer: 'myApp', + enabledInLicense: true, + hasAlertsMappings: false, + hasFieldsForAAD: false, + validLegacyConsumers: [], + }, + ], + [ + 'myOtherType', + { + id: 'myOtherType', + name: 'Test', + actionGroups: [{ id: 'default', name: 'Default' }], + defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', + isExportable: true, + recoveryActionGroup: RecoveredActionGroup, + category: 'test', + producer: 'alerts', + enabledInLicense: true, + hasAlertsMappings: false, + hasFieldsForAAD: false, + validLegacyConsumers: [], + }, + ], ]); + beforeEach(() => { ruleTypeRegistry.list.mockReturnValue(listedTypes); }); @@ -191,7 +204,19 @@ describe('listRuleTypes', () => { validLegacyConsumers: [], }, ]); - authorization.filterByRuleTypeAuthorization.mockResolvedValue(authorizedTypes); + + authorization.getAuthorizedRuleTypes.mockResolvedValue( + new Map([ + [ + 'myType', + { + authorizedConsumers: { + myApp: { read: true, all: true }, + }, + }, + ], + ]) + ); expect(await rulesClient.listRuleTypes()).toEqual(authorizedTypes); }); diff --git a/x-pack/plugins/observability_solution/infra/server/lib/alerting/inventory_metric_threshold/register_inventory_metric_threshold_rule_type.ts b/x-pack/plugins/observability_solution/infra/server/lib/alerting/inventory_metric_threshold/register_inventory_metric_threshold_rule_type.ts index 4f124b8327841f..1a3663515ad18d 100644 --- a/x-pack/plugins/observability_solution/infra/server/lib/alerting/inventory_metric_threshold/register_inventory_metric_threshold_rule_type.ts +++ b/x-pack/plugins/observability_solution/infra/server/lib/alerting/inventory_metric_threshold/register_inventory_metric_threshold_rule_type.ts @@ -8,7 +8,7 @@ import { schema, Type } from '@kbn/config-schema'; import { i18n } from '@kbn/i18n'; import { DEFAULT_APP_CATEGORIES } from '@kbn/core/server'; -import { GetViewInAppRelativeUrlFnOpts, PluginSetupContract } from '@kbn/alerting-plugin/server'; +import { GetViewInAppRelativeUrlFnOpts, AlertingServerSetup } from '@kbn/alerting-plugin/server'; import { observabilityPaths } from '@kbn/observability-plugin/common'; import { TimeUnitChar } from '@kbn/observability-plugin/common/utils/formatters/duration'; import { @@ -81,7 +81,7 @@ const groupActionVariableDescription = i18n.translate( ); export function registerInventoryThresholdRuleType( - alertingPlugin: PluginSetupContract, + alertingPlugin: AlertingServerSetup, libs: InfraBackendLibs, { featureFlags }: InfraConfig ) { diff --git a/x-pack/plugins/observability_solution/observability_ai_assistant/server/types.ts b/x-pack/plugins/observability_solution/observability_ai_assistant/server/types.ts index dc84d58bef9e9b..fcf4a78222a55f 100644 --- a/x-pack/plugins/observability_solution/observability_ai_assistant/server/types.ts +++ b/x-pack/plugins/observability_solution/observability_ai_assistant/server/types.ts @@ -25,10 +25,7 @@ import type { LicensingPluginSetup, LicensingPluginStart } from '@kbn/licensing- import type { CloudSetup, CloudStart } from '@kbn/cloud-plugin/server'; import type { ServerlessPluginSetup, ServerlessPluginStart } from '@kbn/serverless/server'; import type { RuleRegistryPluginStartContract } from '@kbn/rule-registry-plugin/server'; -import type { - PluginSetupContract as AlertingPluginSetup, - PluginStartContract as AlertingPluginStart, -} from '@kbn/alerting-plugin/server'; +import type { AlertingServerSetup, AlertingServerStart } from '@kbn/alerting-plugin/server'; import type { ObservabilityAIAssistantService } from './service'; export interface ObservabilityAIAssistantServerSetup { @@ -54,7 +51,7 @@ export interface ObservabilityAIAssistantPluginSetupDependencies { licensing: LicensingPluginSetup; cloud?: CloudSetup; serverless?: ServerlessPluginSetup; - alerting: AlertingPluginSetup; + alerting: AlertingServerSetup; } export interface ObservabilityAIAssistantPluginStartDependencies { @@ -67,5 +64,5 @@ export interface ObservabilityAIAssistantPluginStartDependencies { ruleRegistry: RuleRegistryPluginStartContract; cloud?: CloudStart; serverless?: ServerlessPluginStart; - alerting: AlertingPluginStart; + alerting: AlertingServerStart; } diff --git a/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts b/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts index ceafd58463d7d8..9ff9aac6ec2b8f 100644 --- a/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts +++ b/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts @@ -32,7 +32,7 @@ import { QueryDslQueryContainer, SortCombinations, } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; -import { RuleTypeParams, PluginStartContract as AlertingStart } from '@kbn/alerting-plugin/server'; +import { RuleTypeParams, AlertingServerStart } from '@kbn/alerting-plugin/server'; import { ReadOperations, AlertingAuthorization, @@ -92,7 +92,7 @@ export interface ConstructorOptions { ruleDataService: IRuleDataService; getRuleType: RuleTypeRegistry['get']; getRuleList: RuleTypeRegistry['list']; - getAlertIndicesAlias: AlertingStart['getAlertIndicesAlias']; + getAlertIndicesAlias: AlertingServerStart['getAlertIndicesAlias']; } export interface UpdateOptions { @@ -167,7 +167,7 @@ export class AlertsClient { private readonly ruleDataService: IRuleDataService; private readonly getRuleType: RuleTypeRegistry['get']; private readonly getRuleList: RuleTypeRegistry['list']; - private getAlertIndicesAlias!: AlertingStart['getAlertIndicesAlias']; + private getAlertIndicesAlias!: AlertingServerStart['getAlertIndicesAlias']; constructor(options: ConstructorOptions) { this.logger = options.logger; @@ -1143,12 +1143,13 @@ export class AlertsClient { public async getAuthorizedAlertsIndices(consumers: string[]): Promise { try { - const authorizedRuleTypes = await this.authorization.getAuthorizedRuleTypes( + const authorizedRuleTypes = await this.authorization.getAllAuthorizedRuleTypesFindOperation( AlertingAuthorizationEntity.Alert, new Set(consumers) ); + const indices = this.getAlertIndicesAlias( - authorizedRuleTypes.map((art: { id: any }) => art.id), + Array.from(authorizedRuleTypes.keys()).map((id) => id), this.spaceId ); @@ -1169,7 +1170,7 @@ export class AlertsClient { if (featureIds.length > 0) { // ATTENTION FUTURE DEVELOPER when you are a super user the augmentedRuleTypes.authorizedRuleTypes will // return all of the features that you can access and does not care about your featureIds - const augmentedRuleTypes = await this.authorization.getAugmentedRuleTypesWithAuthorization( + const augmentedRuleTypes = await this.authorization.getAllAuthorizedRuleTypes( featureIds, [ReadOperations.Find, ReadOperations.Get, WriteOperations.Update], AlertingAuthorizationEntity.Alert @@ -1178,13 +1179,16 @@ export class AlertsClient { // the user should be provided that features' alerts index. // Limiting which alerts that user can read on that index will be done via the findAuthorizationFilter const authorizedFeatures = new Set(); - for (const ruleType of augmentedRuleTypes.authorizedRuleTypes) { + for (const [ruleTypeId] of augmentedRuleTypes.authorizedRuleTypes.entries()) { + const ruleType = this.getRuleType(ruleTypeId); authorizedFeatures.add(ruleType.producer); } + const validAuthorizedFeatures = Array.from(authorizedFeatures).filter( (feature): feature is ValidFeatureId => featureIds.includes(feature) && isValidFeatureId(feature) ); + return validAuthorizedFeatures; } return featureIds; @@ -1209,7 +1213,8 @@ export class AlertsClient { const indexPatternsFetcherAsInternalUser = new IndexPatternsFetcher(this.esClient); const ruleTypeList = this.getRuleList(); const fieldsForAAD = new Set(); - for (const rule of ruleTypeList) { + + for (const rule of ruleTypeList.values()) { if (featureIds.includes(rule.producer) && rule.hasFieldsForAAD) { (rule.fieldsForAAD ?? []).forEach((f) => { fieldsForAAD.add(f); diff --git a/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client_factory.ts b/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client_factory.ts index b2fe182a0ba0a5..91449954db61c1 100644 --- a/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client_factory.ts +++ b/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client_factory.ts @@ -8,10 +8,7 @@ import { PublicMethodsOf } from '@kbn/utility-types'; import { ElasticsearchClient, KibanaRequest, Logger } from '@kbn/core/server'; import type { RuleTypeRegistry } from '@kbn/alerting-plugin/server/types'; -import { - AlertingAuthorization, - PluginStartContract as AlertingStart, -} from '@kbn/alerting-plugin/server'; +import { AlertingAuthorization, AlertingServerStart } from '@kbn/alerting-plugin/server'; import { SecurityPluginSetup } from '@kbn/security-plugin/server'; import { IRuleDataService } from '../rule_data_plugin_service'; import { AlertsClient } from './alerts_client'; @@ -26,7 +23,7 @@ export interface AlertsClientFactoryProps { ruleDataService: IRuleDataService | null; getRuleType: RuleTypeRegistry['get']; getRuleList: RuleTypeRegistry['list']; - getAlertIndicesAlias: AlertingStart['getAlertIndicesAlias']; + getAlertIndicesAlias: AlertingServerStart['getAlertIndicesAlias']; } export class AlertsClientFactory { @@ -40,7 +37,7 @@ export class AlertsClientFactory { private ruleDataService!: IRuleDataService | null; private getRuleType!: RuleTypeRegistry['get']; private getRuleList!: RuleTypeRegistry['list']; - private getAlertIndicesAlias!: AlertingStart['getAlertIndicesAlias']; + private getAlertIndicesAlias!: AlertingServerStart['getAlertIndicesAlias']; public initialize(options: AlertsClientFactoryProps) { /** diff --git a/x-pack/plugins/rule_registry/server/plugin.ts b/x-pack/plugins/rule_registry/server/plugin.ts index 7f7cbc8959583b..b99683aa253151 100644 --- a/x-pack/plugins/rule_registry/server/plugin.ts +++ b/x-pack/plugins/rule_registry/server/plugin.ts @@ -16,10 +16,7 @@ import type { IContextProvider, } from '@kbn/core/server'; -import type { - PluginSetupContract as AlertingSetup, - PluginStartContract as AlertingStart, -} from '@kbn/alerting-plugin/server'; +import type { AlertingServerSetup, AlertingServerStart } from '@kbn/alerting-plugin/server'; import type { SecurityPluginSetup } from '@kbn/security-plugin/server'; import type { SpacesPluginStart } from '@kbn/spaces-plugin/server'; import type { @@ -39,11 +36,11 @@ import { ruleRegistrySearchStrategyProvider, RULE_SEARCH_STRATEGY_NAME } from '. export interface RuleRegistryPluginSetupDependencies { security?: SecurityPluginSetup; data: DataPluginSetup; - alerting: AlertingSetup; + alerting: AlertingServerSetup; } export interface RuleRegistryPluginStartDependencies { - alerting: AlertingStart; + alerting: AlertingServerStart; data: DataPluginStart; spaces?: SpacesPluginStart; } @@ -56,7 +53,7 @@ export interface RuleRegistryPluginSetupContract { export interface RuleRegistryPluginStartContract { getRacClientWithRequest: (req: KibanaRequest) => Promise; - alerting: AlertingStart; + alerting: AlertingServerStart; } export class RuleRegistryPlugin diff --git a/x-pack/plugins/rule_registry/server/search_strategy/search_strategy.ts b/x-pack/plugins/rule_registry/server/search_strategy/search_strategy.ts index 477baa21b230d3..922791b3b44a6a 100644 --- a/x-pack/plugins/rule_registry/server/search_strategy/search_strategy.ts +++ b/x-pack/plugins/rule_registry/server/search_strategy/search_strategy.ts @@ -84,20 +84,22 @@ export const ruleRegistrySearchStrategyProvider = ( )) as estypes.QueryDslQueryContainer; } - const authorizedRuleTypes = - featureIds.length > 0 - ? await authorization.getAuthorizedRuleTypes(AlertingAuthorizationEntity.Alert, fIds) - : []; + const authorizedRuleTypes = await authorization.getAllAuthorizedRuleTypesFindOperation( + AlertingAuthorizationEntity.Alert, + fIds + ); return { space, authzFilter, authorizedRuleTypes }; }; return from(getAsync(request.featureIds)).pipe( mergeMap(({ space, authzFilter, authorizedRuleTypes }) => { - const allRuleTypes = authorizedRuleTypes.map((art: { id: string }) => art.id); - const ruleTypes = (allRuleTypes ?? []).filter( + const authorizedRuleTypesIds = Array.from(authorizedRuleTypes.keys()); + const ruleTypes = (authorizedRuleTypesIds ?? []).filter( (ruleTypeId: string) => !EXCLUDED_RULE_TYPE_IDS.includes(ruleTypeId) ); + const indices = alerting.getAlertIndicesAlias(ruleTypes, space?.id); + if (indices.length === 0) { return of(EMPTY_RESPONSE); } diff --git a/x-pack/plugins/triggers_actions_ui/server/plugin.ts b/x-pack/plugins/triggers_actions_ui/server/plugin.ts index b5cafb0571482a..2263af73dbdc7a 100644 --- a/x-pack/plugins/triggers_actions_ui/server/plugin.ts +++ b/x-pack/plugins/triggers_actions_ui/server/plugin.ts @@ -6,10 +6,7 @@ */ import { Logger, Plugin, CoreSetup, PluginInitializerContext } from '@kbn/core/server'; -import { - PluginSetupContract as AlertingPluginSetup, - PluginStartContract as AlertingPluginStart, -} from '@kbn/alerting-plugin/server'; +import { AlertingServerSetup, AlertingServerStart } from '@kbn/alerting-plugin/server'; import { EncryptedSavedObjectsPluginSetup } from '@kbn/encrypted-saved-objects-plugin/server'; import { getService, register as registerDataService } from './data'; import { createHealthRoute, createConfigRoute } from './routes'; @@ -21,11 +18,11 @@ export interface PluginStartContract { interface PluginsSetup { encryptedSavedObjects?: EncryptedSavedObjectsPluginSetup; - alerting: AlertingPluginSetup; + alerting: AlertingServerSetup; } interface TriggersActionsPluginStart { - alerting: AlertingPluginStart; + alerting: AlertingServerStart; } export class TriggersActionsPlugin implements Plugin { diff --git a/x-pack/plugins/triggers_actions_ui/server/routes/config.test.ts b/x-pack/plugins/triggers_actions_ui/server/routes/config.test.ts index 010a01b46fbdb2..e96d5837b1138c 100644 --- a/x-pack/plugins/triggers_actions_ui/server/routes/config.test.ts +++ b/x-pack/plugins/triggers_actions_ui/server/routes/config.test.ts @@ -45,7 +45,7 @@ describe('createConfigRoute', () => { const logger = loggingSystemMock.create().get(); const mockRulesClient = rulesClientMock.create(); - mockRulesClient.listRuleTypes.mockResolvedValueOnce(new Set(ruleTypes)); + mockRulesClient.listRuleTypes.mockResolvedValueOnce(ruleTypes); createConfigRoute({ logger, router, @@ -80,7 +80,7 @@ describe('createConfigRoute', () => { const logger = loggingSystemMock.create().get(); const mockRulesClient = rulesClientMock.create(); - mockRulesClient.listRuleTypes.mockResolvedValueOnce(new Set()); + mockRulesClient.listRuleTypes.mockResolvedValueOnce([]); createConfigRoute({ logger, router, From c4094d0265b0418a06b9eaf6289ef5ffd95814f7 Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Wed, 17 Jul 2024 19:30:48 +0300 Subject: [PATCH 015/106] Fix tests --- ...rting_authorization_client_factory.test.ts | 102 ++-- .../lib/set_alerts_to_untracked.test.ts | 30 +- .../lib/set_alerts_to_untracked.ts | 21 +- .../alerting_authorization.mock.ts | 18 +- .../alerting_authorization_kuery.test.ts | 439 +++++++++--------- x-pack/plugins/alerting/server/plugin.test.ts | 7 +- .../server/rule_type_registry.test.ts | 6 +- .../alerting/server/rule_type_registry.ts | 16 +- .../alerting/server/rules_client.mock.ts | 8 +- .../tests/list_rule_types.test.ts | 183 ++++++-- .../server/rules_client_factory.test.ts | 18 +- .../alerting/server/rules_client_factory.ts | 1 + 12 files changed, 525 insertions(+), 324 deletions(-) diff --git a/x-pack/plugins/alerting/server/alerting_authorization_client_factory.test.ts b/x-pack/plugins/alerting/server/alerting_authorization_client_factory.test.ts index b6dac4e3f52d12..1f477a840ce4ad 100644 --- a/x-pack/plugins/alerting/server/alerting_authorization_client_factory.test.ts +++ b/x-pack/plugins/alerting/server/alerting_authorization_client_factory.test.ts @@ -15,56 +15,78 @@ import { featuresPluginMock } from '@kbn/features-plugin/server/mocks'; jest.mock('./authorization/alerting_authorization'); -const features = featuresPluginMock.createStart(); +describe('setAlertsToUntracked()', () => { + const features = featuresPluginMock.createStart(); + const securityPluginStart = securityMock.createStart(); + const alertingAuthorizationClientFactoryParams: jest.Mocked = + { + ruleTypeRegistry: ruleTypeRegistryMock.create(), + getSpace: jest.fn(), + getSpaceId: jest.fn(), + features, + }; -const securityPluginStart = securityMock.createStart(); + beforeEach(() => { + jest.clearAllMocks(); + }); -const alertingAuthorizationClientFactoryParams: jest.Mocked = - { - ruleTypeRegistry: ruleTypeRegistryMock.create(), - getSpace: jest.fn(), - getSpaceId: jest.fn(), - features, - }; + it('creates an alerting authorization client with proper constructor arguments when security is enabled', async () => { + const factory = new AlertingAuthorizationClientFactory(); -beforeEach(() => { - jest.resetAllMocks(); -}); + factory.initialize({ + securityPluginStart, + ...alertingAuthorizationClientFactoryParams, + }); + + const request = mockRouter.createKibanaRequest(); + + await factory.create(request); -test('creates an alerting authorization client with proper constructor arguments when security is enabled', async () => { - const factory = new AlertingAuthorizationClientFactory(); - factory.initialize({ - securityPluginStart, - ...alertingAuthorizationClientFactoryParams, + const { AlertingAuthorization } = jest.requireMock('./authorization/alerting_authorization'); + expect(AlertingAuthorization.create).toHaveBeenCalledWith({ + request, + authorization: securityPluginStart.authz, + ruleTypeRegistry: alertingAuthorizationClientFactoryParams.ruleTypeRegistry, + features: alertingAuthorizationClientFactoryParams.features, + getSpace: expect.any(Function), + getSpaceId: expect.any(Function), + }); }); - const request = mockRouter.createKibanaRequest(); - factory.create(request); + it('creates an alerting authorization client with proper constructor arguments', async () => { + const factory = new AlertingAuthorizationClientFactory(); + factory.initialize(alertingAuthorizationClientFactoryParams); + const request = mockRouter.createKibanaRequest(); - const { AlertingAuthorization } = jest.requireMock('./authorization/alerting_authorization'); - expect(AlertingAuthorization).toHaveBeenCalledWith({ - request, - authorization: securityPluginStart.authz, - ruleTypeRegistry: alertingAuthorizationClientFactoryParams.ruleTypeRegistry, - features: alertingAuthorizationClientFactoryParams.features, - getSpace: expect.any(Function), - getSpaceId: expect.any(Function), + await factory.create(request); + + const { AlertingAuthorization } = jest.requireMock('./authorization/alerting_authorization'); + expect(AlertingAuthorization.create).toHaveBeenCalledWith({ + request, + ruleTypeRegistry: alertingAuthorizationClientFactoryParams.ruleTypeRegistry, + features: alertingAuthorizationClientFactoryParams.features, + getSpace: expect.any(Function), + getSpaceId: expect.any(Function), + }); }); -}); -test('creates an alerting authorization client with proper constructor arguments', async () => { - const factory = new AlertingAuthorizationClientFactory(); - factory.initialize(alertingAuthorizationClientFactoryParams); - const request = mockRouter.createKibanaRequest(); + it('throws when trying to initialize again and it is already initialized', async () => { + const factory = new AlertingAuthorizationClientFactory(); + factory.initialize(alertingAuthorizationClientFactoryParams); + + expect(() => + factory.initialize(alertingAuthorizationClientFactoryParams) + ).toThrowErrorMatchingInlineSnapshot( + `"AlertingAuthorizationClientFactory already initialized"` + ); + }); - factory.create(request); + it('throws when trying to create an instance and the factory is not initialized', async () => { + const request = mockRouter.createKibanaRequest(); + const factory = new AlertingAuthorizationClientFactory(); - const { AlertingAuthorization } = jest.requireMock('./authorization/alerting_authorization'); - expect(AlertingAuthorization).toHaveBeenCalledWith({ - request, - ruleTypeRegistry: alertingAuthorizationClientFactoryParams.ruleTypeRegistry, - features: alertingAuthorizationClientFactoryParams.features, - getSpace: expect.any(Function), - getSpaceId: expect.any(Function), + await expect(() => factory.create(request)).rejects.toThrowErrorMatchingInlineSnapshot( + `"AlertingAuthorizationClientFactory must be initialized before calling create"` + ); }); }); diff --git a/x-pack/plugins/alerting/server/alerts_service/lib/set_alerts_to_untracked.test.ts b/x-pack/plugins/alerting/server/alerts_service/lib/set_alerts_to_untracked.test.ts index b9775ec8d5ceda..71992dd0f4025a 100644 --- a/x-pack/plugins/alerting/server/alerts_service/lib/set_alerts_to_untracked.test.ts +++ b/x-pack/plugins/alerting/server/alerts_service/lib/set_alerts_to_untracked.test.ts @@ -360,11 +360,16 @@ describe('setAlertsToUntracked()', () => { }); test('should untrack by query', async () => { - getAllAuthorizedRuleTypesFindOperationMock.mockResolvedValue([ - { - id: 'test-rule-type', - }, - ]); + getAllAuthorizedRuleTypesFindOperationMock.mockResolvedValue( + new Map([ + [ + 'test-rule-type', + { + id: 'test-rule-type', + }, + ], + ]) + ); getAlertIndicesAliasMock.mockResolvedValue(['test-alert-index']); clusterClient.search.mockResponseOnce({ @@ -525,11 +530,16 @@ describe('setAlertsToUntracked()', () => { }); test('should return an empty array if the search returns zero results', async () => { - getAllAuthorizedRuleTypesFindOperationMock.mockResolvedValue([ - { - id: 'test-rule-type', - }, - ]); + getAllAuthorizedRuleTypesFindOperationMock.mockResolvedValue( + new Map([ + [ + 'test-rule-type', + { + id: 'test-rule-type', + }, + ], + ]) + ); getAlertIndicesAliasMock.mockResolvedValue(['test-alert-index']); clusterClient.search.mockResponseOnce({ diff --git a/x-pack/plugins/alerting/server/alerts_service/lib/set_alerts_to_untracked.ts b/x-pack/plugins/alerting/server/alerts_service/lib/set_alerts_to_untracked.ts index 4f6ef683cfc2d0..94394f552191bd 100644 --- a/x-pack/plugins/alerting/server/alerts_service/lib/set_alerts_to_untracked.ts +++ b/x-pack/plugins/alerting/server/alerts_service/lib/set_alerts_to_untracked.ts @@ -162,18 +162,19 @@ const getAuthorizedAlertsIndices = async ({ logger, }: SetAlertsToUntrackedParamsWithDep) => { try { - const authorizedRuleTypes = - (await getAllAuthorizedRuleTypesFindOperation?.( - AlertingAuthorizationEntity.Alert, - new Set(featureIds) - )) || new Map(); - - const indices = getAlertIndicesAlias?.( - Array.from(authorizedRuleTypes.keys()).map(({ id }) => id), - spaceId + const authorizedRuleTypes = await getAllAuthorizedRuleTypesFindOperation?.( + AlertingAuthorizationEntity.Alert, + new Set(featureIds) ); - return indices; + if (authorizedRuleTypes) { + return getAlertIndicesAlias?.( + Array.from(authorizedRuleTypes.keys()).map((id) => id), + spaceId + ); + } + + return []; } catch (error) { const errMessage = `Failed to get authorized rule types to untrack alerts by query: ${error}`; logger.error(errMessage); diff --git a/x-pack/plugins/alerting/server/authorization/alerting_authorization.mock.ts b/x-pack/plugins/alerting/server/authorization/alerting_authorization.mock.ts index 5729b160db85a1..12e360c7cd6442 100644 --- a/x-pack/plugins/alerting/server/authorization/alerting_authorization.mock.ts +++ b/x-pack/plugins/alerting/server/authorization/alerting_authorization.mock.ts @@ -14,12 +14,20 @@ export type AlertingAuthorizationMock = jest.Mocked; const createAlertingAuthorizationMock = () => { const mocked: AlertingAuthorizationMock = { ensureAuthorized: jest.fn(), - getAuthorizedRuleTypes: jest.fn(), - getFindAuthorizationFilter: jest.fn(), + getAuthorizedRuleTypes: jest.fn().mockResolvedValue(new Map()), + getFindAuthorizationFilter: jest.fn().mockResolvedValue({ + filter: undefined, + ensureRuleTypeIsAuthorized: () => {}, + }), getSpaceId: jest.fn(), - getAllAuthorizedRuleTypes: jest.fn(), - getAllAuthorizedRuleTypesFindOperation: jest.fn(), - getAuthorizationFilter: jest.fn(), + getAllAuthorizedRuleTypes: jest + .fn() + .mockResolvedValue({ hasAllRequested: true, authorizedRuleTypes: new Map() }), + getAllAuthorizedRuleTypesFindOperation: jest.fn().mockResolvedValue(new Map()), + getAuthorizationFilter: jest.fn().mockResolvedValue({ + filter: undefined, + ensureRuleTypeIsAuthorized: () => {}, + }), }; return mocked; }; diff --git a/x-pack/plugins/alerting/server/authorization/alerting_authorization_kuery.test.ts b/x-pack/plugins/alerting/server/authorization/alerting_authorization_kuery.test.ts index 4cb575c4b51e64..bcc2b37dca7dd1 100644 --- a/x-pack/plugins/alerting/server/authorization/alerting_authorization_kuery.test.ts +++ b/x-pack/plugins/alerting/server/authorization/alerting_authorization_kuery.test.ts @@ -11,7 +11,7 @@ import { ensureFieldIsSafeForQuery, asFiltersBySpaceId, } from './alerting_authorization_kuery'; -import { fromKueryExpression } from '@kbn/es-query'; +import { KueryNode, toKqlExpression } from '@kbn/es-query'; describe('asKqlFiltersByRuleTypeAndConsumer', () => { test('constructs KQL filter for single rule type with single authorized consumer', async () => { @@ -27,20 +27,20 @@ describe('asKqlFiltersByRuleTypeAndConsumer', () => { ]); expect( - asFiltersByRuleTypeAndConsumer( - authorizedRuleTypes, - { - type: AlertingAuthorizationFilterType.KQL, - fieldNames: { - ruleTypeId: 'path.to.rule_type_id', - consumer: 'consumer-field', + toKqlExpression( + asFiltersByRuleTypeAndConsumer( + authorizedRuleTypes, + { + type: AlertingAuthorizationFilterType.KQL, + fieldNames: { + ruleTypeId: 'path.to.rule_type_id', + consumer: 'consumer-field', + }, }, - }, - 'space1' + 'space1' + ) as KueryNode ) - ).toEqual( - fromKueryExpression(`((path.to.rule_type_id:myAppAlertType and consumer-field:(myApp)))`) - ); + ).toMatchInlineSnapshot(`"(path.to.rule_type_id: myAppAlertType AND consumer-field: myApp)"`); }); test('constructs KQL filter for single rule type with multiple authorized consumers', async () => { @@ -58,21 +58,21 @@ describe('asKqlFiltersByRuleTypeAndConsumer', () => { ]); expect( - asFiltersByRuleTypeAndConsumer( - authorizedRuleTypes, - { - type: AlertingAuthorizationFilterType.KQL, - fieldNames: { - ruleTypeId: 'path.to.rule_type_id', - consumer: 'consumer-field', + toKqlExpression( + asFiltersByRuleTypeAndConsumer( + authorizedRuleTypes, + { + type: AlertingAuthorizationFilterType.KQL, + fieldNames: { + ruleTypeId: 'path.to.rule_type_id', + consumer: 'consumer-field', + }, }, - }, - 'space1' - ) - ).toEqual( - fromKueryExpression( - `((path.to.rule_type_id:myAppAlertType and consumer-field:(alerts or myApp or myOtherApp)))` + 'space1' + ) as KueryNode ) + ).toMatchInlineSnapshot( + `"(path.to.rule_type_id: myAppAlertType AND (consumer-field: alerts OR consumer-field: myApp OR consumer-field: myOtherApp))"` ); }); @@ -103,21 +103,21 @@ describe('asKqlFiltersByRuleTypeAndConsumer', () => { ]); expect( - asFiltersByRuleTypeAndConsumer( - authorizedRuleTypes, - { - type: AlertingAuthorizationFilterType.KQL, - fieldNames: { - ruleTypeId: 'path.to.rule_type_id', - consumer: 'consumer-field', + toKqlExpression( + asFiltersByRuleTypeAndConsumer( + authorizedRuleTypes, + { + type: AlertingAuthorizationFilterType.KQL, + fieldNames: { + ruleTypeId: 'path.to.rule_type_id', + consumer: 'consumer-field', + }, }, - }, - 'space1' - ) - ).toEqual( - fromKueryExpression( - `((path.to.rule_type_id:myAppAlertType and consumer-field:(alerts or myApp or myOtherApp or myAppWithSubFeature)) or (path.to.rule_type_id:myOtherAppAlertType and consumer-field:(alerts or myApp or myOtherApp or myAppWithSubFeature)) or (path.to.rule_type_id:mySecondAppAlertType and consumer-field:(alerts or myApp or myOtherApp or myAppWithSubFeature)))` + 'space1' + ) as KueryNode ) + ).toMatchInlineSnapshot( + `"((path.to.rule_type_id: myAppAlertType AND (consumer-field: alerts OR consumer-field: myApp OR consumer-field: myOtherApp OR consumer-field: myAppWithSubFeature)) OR (path.to.rule_type_id: myOtherAppAlertType AND (consumer-field: alerts OR consumer-field: myApp OR consumer-field: myOtherApp OR consumer-field: myAppWithSubFeature)))"` ); }); @@ -148,22 +148,22 @@ describe('asKqlFiltersByRuleTypeAndConsumer', () => { ]); expect( - asFiltersByRuleTypeAndConsumer( - authorizedRuleTypes, - { - type: AlertingAuthorizationFilterType.KQL, - fieldNames: { - ruleTypeId: 'path.to.rule_type_id', - consumer: 'consumer-field', - spaceIds: 'path.to.spaceIds', + toKqlExpression( + asFiltersByRuleTypeAndConsumer( + authorizedRuleTypes, + { + type: AlertingAuthorizationFilterType.KQL, + fieldNames: { + ruleTypeId: 'path.to.rule_type_id', + consumer: 'consumer-field', + spaceIds: 'path.to.spaceIds', + }, }, - }, - 'space1' - ) - ).toEqual( - fromKueryExpression( - `((path.to.rule_type_id:myAppAlertType and consumer-field:(alerts or myApp or myOtherApp or myAppWithSubFeature) and path.to.spaceIds:space1) or (path.to.rule_type_id:myOtherAppAlertType and consumer-field:(alerts or myApp or myOtherApp or myAppWithSubFeature) and path.to.spaceIds:space1))` + 'space1' + ) as KueryNode ) + ).toMatchInlineSnapshot( + `"((path.to.rule_type_id: myAppAlertType AND (consumer-field: alerts OR consumer-field: myApp OR consumer-field: myOtherApp OR consumer-field: myAppWithSubFeature) AND path.to.spaceIds: space1) OR (path.to.rule_type_id: myOtherAppAlertType AND (consumer-field: alerts OR consumer-field: myApp OR consumer-field: myOtherApp OR consumer-field: myAppWithSubFeature) AND path.to.spaceIds: space1))"` ); }); @@ -194,22 +194,22 @@ describe('asKqlFiltersByRuleTypeAndConsumer', () => { ]); expect( - asFiltersByRuleTypeAndConsumer( - authorizedRuleTypes, - { - type: AlertingAuthorizationFilterType.KQL, - fieldNames: { - ruleTypeId: 'path.to.rule_type_id', - consumer: 'consumer-field', - spaceIds: 'path.to.spaceIds', + toKqlExpression( + asFiltersByRuleTypeAndConsumer( + authorizedRuleTypes, + { + type: AlertingAuthorizationFilterType.KQL, + fieldNames: { + ruleTypeId: 'path.to.rule_type_id', + consumer: 'consumer-field', + spaceIds: 'path.to.spaceIds', + }, }, - }, - undefined - ) - ).toEqual( - fromKueryExpression( - `((path.to.rule_type_id:myAppAlertType and consumer-field:(alerts or myApp or myOtherApp or myAppWithSubFeature)) or (path.to.rule_type_id:myOtherAppAlertType and consumer-field:(alerts or myApp or myOtherApp or myAppWithSubFeature)))` + undefined + ) as KueryNode ) + ).toMatchInlineSnapshot( + `"((path.to.rule_type_id: myAppAlertType AND (consumer-field: alerts OR consumer-field: myApp OR consumer-field: myOtherApp OR consumer-field: myAppWithSubFeature)) OR (path.to.rule_type_id: myOtherAppAlertType AND (consumer-field: alerts OR consumer-field: myApp OR consumer-field: myOtherApp OR consumer-field: myAppWithSubFeature)))"` ); }); @@ -223,19 +223,21 @@ describe('asKqlFiltersByRuleTypeAndConsumer', () => { ], ]); - const result = asFiltersByRuleTypeAndConsumer( - authorizedRuleTypes, - { - type: AlertingAuthorizationFilterType.KQL, - fieldNames: { - ruleTypeId: 'path.to.rule_type_id', - consumer: 'consumer-field', + const result = toKqlExpression( + asFiltersByRuleTypeAndConsumer( + authorizedRuleTypes, + { + type: AlertingAuthorizationFilterType.KQL, + fieldNames: { + ruleTypeId: 'path.to.rule_type_id', + consumer: 'consumer-field', + }, }, - }, - 'space1' + 'space1' + ) as KueryNode ); - expect(result).toEqual(fromKueryExpression(`path.to.rule_type_id:myAppAlertType`)); + expect(result).toMatchInlineSnapshot(`"path.to.rule_type_id: myAppAlertType"`); }); }); @@ -399,142 +401,161 @@ describe('asEsDslFiltersByRuleTypeAndConsumer', () => { }, 'space1' ) - ).toEqual({ - bool: { - should: [ - { - bool: { - filter: [ - { - bool: { - should: [{ match: { 'path.to.rule_type_id': 'myAppAlertType' } }], - minimum_should_match: 1, - }, - }, - { - bool: { - should: [ - { - bool: { - should: [{ match: { 'consumer-field': 'alerts' } }], - minimum_should_match: 1, - }, - }, - { - bool: { - should: [{ match: { 'consumer-field': 'myApp' } }], - minimum_should_match: 1, - }, - }, - { - bool: { - should: [{ match: { 'consumer-field': 'myOtherApp' } }], - minimum_should_match: 1, - }, - }, - { - bool: { - should: [{ match: { 'consumer-field': 'myAppWithSubFeature' } }], - minimum_should_match: 1, + ).toMatchInlineSnapshot(` + Object { + "bool": Object { + "minimum_should_match": 1, + "should": Array [ + Object { + "bool": Object { + "filter": Array [ + Object { + "bool": Object { + "minimum_should_match": 1, + "should": Array [ + Object { + "match": Object { + "path.to.rule_type_id": "myAppAlertType", + }, }, - }, - ], - minimum_should_match: 1, - }, - }, - ], - }, - }, - { - bool: { - filter: [ - { - bool: { - should: [{ match: { 'path.to.rule_type_id': 'myOtherAppAlertType' } }], - minimum_should_match: 1, + ], + }, }, - }, - { - bool: { - should: [ - { - bool: { - should: [{ match: { 'consumer-field': 'alerts' } }], - minimum_should_match: 1, + Object { + "bool": Object { + "minimum_should_match": 1, + "should": Array [ + Object { + "bool": Object { + "minimum_should_match": 1, + "should": Array [ + Object { + "match": Object { + "consumer-field": "alerts", + }, + }, + ], + }, }, - }, - { - bool: { - should: [{ match: { 'consumer-field': 'myApp' } }], - minimum_should_match: 1, + Object { + "bool": Object { + "minimum_should_match": 1, + "should": Array [ + Object { + "match": Object { + "consumer-field": "myApp", + }, + }, + ], + }, }, - }, - { - bool: { - should: [{ match: { 'consumer-field': 'myOtherApp' } }], - minimum_should_match: 1, + Object { + "bool": Object { + "minimum_should_match": 1, + "should": Array [ + Object { + "match": Object { + "consumer-field": "myOtherApp", + }, + }, + ], + }, }, - }, - { - bool: { - should: [{ match: { 'consumer-field': 'myAppWithSubFeature' } }], - minimum_should_match: 1, + Object { + "bool": Object { + "minimum_should_match": 1, + "should": Array [ + Object { + "match": Object { + "consumer-field": "myAppWithSubFeature", + }, + }, + ], + }, }, - }, - ], - minimum_should_match: 1, + ], + }, }, - }, - ], + ], + }, }, - }, - { - bool: { - filter: [ - { - bool: { - should: [{ match: { 'path.to.rule_type_id': 'mySecondAppAlertType' } }], - minimum_should_match: 1, + Object { + "bool": Object { + "filter": Array [ + Object { + "bool": Object { + "minimum_should_match": 1, + "should": Array [ + Object { + "match": Object { + "path.to.rule_type_id": "myOtherAppAlertType", + }, + }, + ], + }, }, - }, - { - bool: { - should: [ - { - bool: { - should: [{ match: { 'consumer-field': 'alerts' } }], - minimum_should_match: 1, + Object { + "bool": Object { + "minimum_should_match": 1, + "should": Array [ + Object { + "bool": Object { + "minimum_should_match": 1, + "should": Array [ + Object { + "match": Object { + "consumer-field": "alerts", + }, + }, + ], + }, }, - }, - { - bool: { - should: [{ match: { 'consumer-field': 'myApp' } }], - minimum_should_match: 1, + Object { + "bool": Object { + "minimum_should_match": 1, + "should": Array [ + Object { + "match": Object { + "consumer-field": "myApp", + }, + }, + ], + }, }, - }, - { - bool: { - should: [{ match: { 'consumer-field': 'myOtherApp' } }], - minimum_should_match: 1, + Object { + "bool": Object { + "minimum_should_match": 1, + "should": Array [ + Object { + "match": Object { + "consumer-field": "myOtherApp", + }, + }, + ], + }, }, - }, - { - bool: { - should: [{ match: { 'consumer-field': 'myAppWithSubFeature' } }], - minimum_should_match: 1, + Object { + "bool": Object { + "minimum_should_match": 1, + "should": Array [ + Object { + "match": Object { + "consumer-field": "myAppWithSubFeature", + }, + }, + ], + }, }, - }, - ], - minimum_should_match: 1, + ], + }, }, - }, - ], + ], + }, }, - }, - ], - minimum_should_match: 1, - }, - }); + ], + }, + } + `); }); test('constructs KQL filter for single rule type with no authorized consumer', async () => { @@ -597,18 +618,20 @@ describe('asFiltersBySpaceId', () => { test('returns KQL filter of spaceId', () => { expect( - asFiltersBySpaceId( - { - type: AlertingAuthorizationFilterType.KQL, - fieldNames: { - ruleTypeId: 'path.to.rule_type_id', - consumer: 'consumer-field', - spaceIds: 'path.to.space.id', + toKqlExpression( + asFiltersBySpaceId( + { + type: AlertingAuthorizationFilterType.KQL, + fieldNames: { + ruleTypeId: 'path.to.rule_type_id', + consumer: 'consumer-field', + spaceIds: 'path.to.space.id', + }, }, - }, - 'space1' + 'space1' + ) as KueryNode ) - ).toEqual(fromKueryExpression('(path.to.space.id: space1)')); + ).toMatchInlineSnapshot(`"path.to.space.id: space1"`); }); test('returns undefined if no path to spaceIds is provided', () => { diff --git a/x-pack/plugins/alerting/server/plugin.test.ts b/x-pack/plugins/alerting/server/plugin.test.ts index 4d6e5090da6ca9..38a4f717be3b0d 100644 --- a/x-pack/plugins/alerting/server/plugin.test.ts +++ b/x-pack/plugins/alerting/server/plugin.test.ts @@ -314,9 +314,9 @@ describe('Alerting Plugin', () => { }); expect(encryptedSavedObjectsSetup.canEncrypt).toEqual(false); - expect(() => + await expect(() => startContract.getRulesClientWithRequest({} as KibanaRequest) - ).toThrowErrorMatchingInlineSnapshot( + ).rejects.toThrowErrorMatchingInlineSnapshot( `"Unable to create alerts client because the Encrypted Saved Objects plugin is missing encryption key. Please set xpack.encryptedSavedObjects.encryptionKey in the kibana.yml or use the bin/kibana-encryption-keys command."` ); }); @@ -380,7 +380,8 @@ describe('Alerting Plugin', () => { }, getSavedObjectsClient: jest.fn(), } as unknown as KibanaRequest; - startContract.getRulesClientWithRequest(fakeRequest); + + await startContract.getRulesClientWithRequest(fakeRequest); }); }); diff --git a/x-pack/plugins/alerting/server/rule_type_registry.test.ts b/x-pack/plugins/alerting/server/rule_type_registry.test.ts index 3ee3551a301d5a..649bc051a64ba8 100644 --- a/x-pack/plugins/alerting/server/rule_type_registry.test.ts +++ b/x-pack/plugins/alerting/server/rule_type_registry.test.ts @@ -823,7 +823,7 @@ describe('Create Lifecycle', () => { test('should return empty when nothing is registered', () => { const registry = new RuleTypeRegistry(ruleTypeRegistryParams); const result = registry.list(); - expect(result).toMatchInlineSnapshot(`Set {}`); + expect(result).toMatchInlineSnapshot(`Map {}`); }); test('should return registered types', () => { @@ -855,8 +855,8 @@ describe('Create Lifecycle', () => { }); const result = registry.list(); expect(result).toMatchInlineSnapshot(` - Set { - Object { + Map { + "test" => Object { "actionGroups": Array [ Object { "id": "testActionGroup", diff --git a/x-pack/plugins/alerting/server/rule_type_registry.ts b/x-pack/plugins/alerting/server/rule_type_registry.ts index 5468dea79e525c..47e555e221d587 100644 --- a/x-pack/plugins/alerting/server/rule_type_registry.ts +++ b/x-pack/plugins/alerting/server/rule_type_registry.ts @@ -379,15 +379,29 @@ export class RuleTypeRegistry { this.ruleTypes.forEach((_ruleType) => { const ruleType: RegistryRuleType = { - ..._ruleType, + id: _ruleType.id, + name: _ruleType.name, + actionGroups: _ruleType.actionGroups, + recoveryActionGroup: _ruleType.recoveryActionGroup, + defaultActionGroupId: _ruleType.defaultActionGroupId, + actionVariables: _ruleType.actionVariables, + category: _ruleType.category, + producer: _ruleType.producer, + minimumLicenseRequired: _ruleType.minimumLicenseRequired, + isExportable: _ruleType.isExportable, + ruleTaskTimeout: _ruleType.ruleTaskTimeout, + defaultScheduleInterval: _ruleType.defaultScheduleInterval, + doesSetRecoveryContext: _ruleType.doesSetRecoveryContext, enabledInLicense: !!this.licenseState.getLicenseCheckForRuleType( _ruleType.id, _ruleType.name, _ruleType.minimumLicenseRequired ).isValid, + fieldsForAAD: _ruleType.fieldsForAAD, hasFieldsForAAD: Boolean(_ruleType.fieldsForAAD), hasAlertsMappings: !!_ruleType.alerts, ...(_ruleType.alerts ? { alerts: _ruleType.alerts } : {}), + validLegacyConsumers: _ruleType.validLegacyConsumers, }; ruleTypesMap.set(ruleType.id, ruleType); diff --git a/x-pack/plugins/alerting/server/rules_client.mock.ts b/x-pack/plugins/alerting/server/rules_client.mock.ts index eedd46eaa71ec0..66add58ce4c507 100644 --- a/x-pack/plugins/alerting/server/rules_client.mock.ts +++ b/x-pack/plugins/alerting/server/rules_client.mock.ts @@ -5,12 +5,15 @@ * 2.0. */ +import { alertingAuthorizationMock } from './authorization/alerting_authorization.mock'; import { RulesClientApi } from './types'; type Schema = RulesClientApi; export type RulesClientMock = jest.Mocked; const createRulesClientMock = () => { + const alertingAuthorization = alertingAuthorizationMock.create(); + const mocked: RulesClientMock = { aggregate: jest.fn().mockReturnValue({ ruleExecutionStatus: {}, ruleLastRunOutcome: {} }), getTags: jest.fn(), @@ -31,10 +34,7 @@ const createRulesClientMock = () => { listRuleTypes: jest.fn(), getAlertSummary: jest.fn(), getAuditLogger: jest.fn(), - getAuthorization: jest.fn().mockImplementation(() => ({ - getFindAuthorizationFilter: jest.fn().mockReturnValue({ filter: null }), - getAuthorizedRuleTypes: jest.fn().mockResolvedValue([]), - })), + getAuthorization: jest.fn().mockReturnValue(alertingAuthorization), getExecutionLogForRule: jest.fn(), getRuleExecutionKPI: jest.fn(), getGlobalExecutionKpiWithAuth: jest.fn(), diff --git a/x-pack/plugins/alerting/server/rules_client/tests/list_rule_types.test.ts b/x-pack/plugins/alerting/server/rules_client/tests/list_rule_types.test.ts index c3e33ec06d68de..7205decb32bb50 100644 --- a/x-pack/plugins/alerting/server/rules_client/tests/list_rule_types.test.ts +++ b/x-pack/plugins/alerting/server/rules_client/tests/list_rule_types.test.ts @@ -17,10 +17,7 @@ import { ruleTypeRegistryMock } from '../../rule_type_registry.mock'; import { alertingAuthorizationMock } from '../../authorization/alerting_authorization.mock'; import { encryptedSavedObjectsMock } from '@kbn/encrypted-saved-objects-plugin/server/mocks'; import { actionsAuthorizationMock } from '@kbn/actions-plugin/server/mocks'; -import { - AlertingAuthorization, - RegistryAlertTypeWithAuth, -} from '../../authorization/alerting_authorization'; +import { AlertingAuthorization } from '../../authorization/alerting_authorization'; import { ActionsAuthorization } from '@kbn/actions-plugin/server'; import { getBeforeSetup } from './lib'; import { RecoveredActionGroup } from '../../../common'; @@ -123,6 +120,8 @@ describe('listRuleTypes', () => { test('should return a list of AlertTypes that exist in the registry', async () => { ruleTypeRegistry.list.mockReturnValue(setOfAlertTypes); + ruleTypeRegistry.has.mockReturnValue(true); + authorization.getAuthorizedRuleTypes.mockResolvedValue( new Map([ [myAppAlertType.id, { authorizedConsumers }], @@ -130,12 +129,126 @@ describe('listRuleTypes', () => { ]) ); - expect(await rulesClient.listRuleTypes()).toEqual( - new Set([ - { ...myAppAlertType, authorizedConsumers }, - { ...alertingAlertType, authorizedConsumers }, + expect(await rulesClient.listRuleTypes()).toMatchInlineSnapshot(` + Array [ + Object { + "actionGroups": Array [], + "actionVariables": undefined, + "authorizedConsumers": Object { + "alerts": Object { + "all": true, + "read": true, + }, + "myApp": Object { + "all": true, + "read": true, + }, + "myOtherApp": Object { + "all": true, + "read": true, + }, + }, + "category": "test", + "defaultActionGroupId": "default", + "enabledInLicense": true, + "hasAlertsMappings": false, + "hasFieldsForAAD": false, + "id": "myAppAlertType", + "isExportable": true, + "minimumLicenseRequired": "basic", + "name": "myAppAlertType", + "producer": "myApp", + "recoveryActionGroup": Object { + "id": "recovered", + "name": "Recovered", + }, + "validLegacyConsumers": Array [], + }, + Object { + "actionGroups": Array [], + "actionVariables": undefined, + "authorizedConsumers": Object { + "alerts": Object { + "all": true, + "read": true, + }, + "myApp": Object { + "all": true, + "read": true, + }, + "myOtherApp": Object { + "all": true, + "read": true, + }, + }, + "category": "test", + "defaultActionGroupId": "default", + "enabledInLicense": true, + "hasAlertsMappings": false, + "hasFieldsForAAD": false, + "id": "alertingAlertType", + "isExportable": true, + "minimumLicenseRequired": "basic", + "name": "alertingAlertType", + "producer": "alerts", + "recoveryActionGroup": Object { + "id": "recovered", + "name": "Recovered", + }, + "validLegacyConsumers": Array [], + }, + ] + `); + }); + + test('should filter out rule types that are not registered in the registry', async () => { + ruleTypeRegistry.list.mockReturnValue(setOfAlertTypes); + ruleTypeRegistry.has.mockImplementation((id: string) => id === myAppAlertType.id); + + authorization.getAuthorizedRuleTypes.mockResolvedValue( + new Map([ + [myAppAlertType.id, { authorizedConsumers }], + [alertingAlertType.id, { authorizedConsumers }], ]) ); + + expect(await rulesClient.listRuleTypes()).toMatchInlineSnapshot(` + Array [ + Object { + "actionGroups": Array [], + "actionVariables": undefined, + "authorizedConsumers": Object { + "alerts": Object { + "all": true, + "read": true, + }, + "myApp": Object { + "all": true, + "read": true, + }, + "myOtherApp": Object { + "all": true, + "read": true, + }, + }, + "category": "test", + "defaultActionGroupId": "default", + "enabledInLicense": true, + "hasAlertsMappings": false, + "hasFieldsForAAD": false, + "id": "myAppAlertType", + "isExportable": true, + "minimumLicenseRequired": "basic", + "name": "myAppAlertType", + "producer": "myApp", + "recoveryActionGroup": Object { + "id": "recovered", + "name": "Recovered", + }, + "validLegacyConsumers": Array [], + }, + ] + `); }); describe('authorization', () => { @@ -181,30 +294,10 @@ describe('listRuleTypes', () => { beforeEach(() => { ruleTypeRegistry.list.mockReturnValue(listedTypes); + ruleTypeRegistry.has.mockReturnValue(true); }); - test('should return a list of AlertTypes that exist in the registry only if the user is authorised to get them', async () => { - const authorizedTypes = new Set([ - { - id: 'myType', - name: 'Test', - actionGroups: [{ id: 'default', name: 'Default' }], - defaultActionGroupId: 'default', - minimumLicenseRequired: 'basic', - isExportable: true, - recoveryActionGroup: RecoveredActionGroup, - category: 'test', - producer: 'alerts', - authorizedConsumers: { - myApp: { read: true, all: true }, - }, - enabledInLicense: true, - hasAlertsMappings: false, - hasFieldsForAAD: false, - validLegacyConsumers: [], - }, - ]); - + test('should return a list of AlertTypes that exist in the registry only if the user is authorized to get them', async () => { authorization.getAuthorizedRuleTypes.mockResolvedValue( new Map([ [ @@ -218,7 +311,35 @@ describe('listRuleTypes', () => { ]) ); - expect(await rulesClient.listRuleTypes()).toEqual(authorizedTypes); + expect(await rulesClient.listRuleTypes()).toMatchInlineSnapshot(` + Array [ + Object { + "actionGroups": Array [], + "actionVariables": undefined, + "authorizedConsumers": Object { + "myApp": Object { + "all": true, + "read": true, + }, + }, + "category": "test", + "defaultActionGroupId": "default", + "enabledInLicense": true, + "hasAlertsMappings": false, + "hasFieldsForAAD": false, + "id": "myType", + "isExportable": true, + "minimumLicenseRequired": "basic", + "name": "myType", + "producer": "myApp", + "recoveryActionGroup": Object { + "id": "recovered", + "name": "Recovered", + }, + "validLegacyConsumers": Array [], + }, + ] + `); }); }); }); diff --git a/x-pack/plugins/alerting/server/rules_client_factory.test.ts b/x-pack/plugins/alerting/server/rules_client_factory.test.ts index 13354310e68a95..9af5962915d729 100644 --- a/x-pack/plugins/alerting/server/rules_client_factory.test.ts +++ b/x-pack/plugins/alerting/server/rules_client_factory.test.ts @@ -102,7 +102,7 @@ test('creates a rules client with proper constructor arguments when security is alertingAuthorization as unknown as AlertingAuthorization ); - factory.create(request, savedObjectsService); + await factory.create(request, savedObjectsService); expect(savedObjectsService.getScopedClient).toHaveBeenCalledWith(request, { excludedExtensions: [SECURITY_EXTENSION_ID], @@ -158,7 +158,7 @@ test('creates a rules client with proper constructor arguments', async () => { alertingAuthorization as unknown as AlertingAuthorization ); - factory.create(request, savedObjectsService); + await factory.create(request, savedObjectsService); expect(savedObjectsService.getScopedClient).toHaveBeenCalledWith(request, { excludedExtensions: [SECURITY_EXTENSION_ID], @@ -203,7 +203,7 @@ test('creates a rules client with proper constructor arguments', async () => { test('getUserName() returns null when security is disabled', async () => { const factory = new RulesClientFactory(); factory.initialize(rulesClientFactoryParams); - factory.create(mockRouter.createKibanaRequest(), savedObjectsService); + await factory.create(mockRouter.createKibanaRequest(), savedObjectsService); const constructorCall = jest.requireMock('./rules_client').RulesClient.mock.calls[0][0]; const userNameResult = await constructorCall.getUserName(); @@ -216,7 +216,7 @@ test('getUserName() returns a name when security is enabled', async () => { ...rulesClientFactoryParams, securityService, }); - factory.create(mockRouter.createKibanaRequest(), savedObjectsService); + await factory.create(mockRouter.createKibanaRequest(), savedObjectsService); const constructorCall = jest.requireMock('./rules_client').RulesClient.mock.calls[0][0]; securityService.authc.getCurrentUser.mockReturnValueOnce({ @@ -229,7 +229,7 @@ test('getUserName() returns a name when security is enabled', async () => { test('getActionsClient() returns ActionsClient', async () => { const factory = new RulesClientFactory(); factory.initialize(rulesClientFactoryParams); - factory.create(mockRouter.createKibanaRequest(), savedObjectsService); + await factory.create(mockRouter.createKibanaRequest(), savedObjectsService); const constructorCall = jest.requireMock('./rules_client').RulesClient.mock.calls[0][0]; const actionsClient = await constructorCall.getActionsClient(); @@ -239,7 +239,7 @@ test('getActionsClient() returns ActionsClient', async () => { test('createAPIKey() returns { apiKeysEnabled: false } when security is disabled', async () => { const factory = new RulesClientFactory(); factory.initialize(rulesClientFactoryParams); - factory.create(mockRouter.createKibanaRequest(), savedObjectsService); + await factory.create(mockRouter.createKibanaRequest(), savedObjectsService); const constructorCall = jest.requireMock('./rules_client').RulesClient.mock.calls[0][0]; const createAPIKeyResult = await constructorCall.createAPIKey(); @@ -249,7 +249,7 @@ test('createAPIKey() returns { apiKeysEnabled: false } when security is disabled test('createAPIKey() returns { apiKeysEnabled: false } when security is enabled but ES security is disabled', async () => { const factory = new RulesClientFactory(); factory.initialize(rulesClientFactoryParams); - factory.create(mockRouter.createKibanaRequest(), savedObjectsService); + await factory.create(mockRouter.createKibanaRequest(), savedObjectsService); const constructorCall = jest.requireMock('./rules_client').RulesClient.mock.calls[0][0]; securityPluginStart.authc.apiKeys.grantAsInternalUser.mockResolvedValueOnce(null); @@ -265,7 +265,7 @@ test('createAPIKey() returns an API key when security is enabled', async () => { securityPluginSetup, securityPluginStart, }); - factory.create(mockRouter.createKibanaRequest(), savedObjectsService); + await factory.create(mockRouter.createKibanaRequest(), savedObjectsService); const constructorCall = jest.requireMock('./rules_client').RulesClient.mock.calls[0][0]; securityPluginStart.authc.apiKeys.grantAsInternalUser.mockResolvedValueOnce({ @@ -296,7 +296,7 @@ test('createAPIKey() throws when security plugin createAPIKey throws an error', securityPluginSetup, securityPluginStart, }); - factory.create(mockRouter.createKibanaRequest(), savedObjectsService); + await factory.create(mockRouter.createKibanaRequest(), savedObjectsService); const constructorCall = jest.requireMock('./rules_client').RulesClient.mock.calls[0][0]; securityPluginStart.authc.apiKeys.grantAsInternalUser.mockRejectedValueOnce( diff --git a/x-pack/plugins/alerting/server/rules_client_factory.ts b/x-pack/plugins/alerting/server/rules_client_factory.ts index 6fbaadf246d868..ea3c575fe1fb9e 100644 --- a/x-pack/plugins/alerting/server/rules_client_factory.ts +++ b/x-pack/plugins/alerting/server/rules_client_factory.ts @@ -173,6 +173,7 @@ export class RulesClientFactory { if (!createAPIKeyResult) { return { apiKeysEnabled: false }; } + return { apiKeysEnabled: true, result: createAPIKeyResult, From 83a8d412bf1b07f695765b4a257872aa8f04c9f9 Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Thu, 18 Jul 2024 10:11:29 +0300 Subject: [PATCH 016/106] Fix ML alerting registration --- x-pack/plugins/ml/kibana.jsonc | 3 ++- x-pack/plugins/ml/server/plugin.ts | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/ml/kibana.jsonc b/x-pack/plugins/ml/kibana.jsonc index 4ec2cf57312a91..21731f2543f557 100644 --- a/x-pack/plugins/ml/kibana.jsonc +++ b/x-pack/plugins/ml/kibana.jsonc @@ -56,7 +56,8 @@ "lens", "maps", "savedObjectsFinder", - "usageCollection" + "usageCollection", + "alerting" ], "extraPublicDirs": ["common"] } diff --git a/x-pack/plugins/ml/server/plugin.ts b/x-pack/plugins/ml/server/plugin.ts index d426de86d71d15..7b9dade728ad46 100644 --- a/x-pack/plugins/ml/server/plugin.ts +++ b/x-pack/plugins/ml/server/plugin.ts @@ -25,6 +25,7 @@ import type { SpacesPluginSetup } from '@kbn/spaces-plugin/server'; import type { FieldFormatsStart } from '@kbn/field-formats-plugin/server'; import type { HomeServerPluginSetup } from '@kbn/home-plugin/server'; import type { CasesServerSetup } from '@kbn/cases-plugin/server'; +import { ALERTING_FEATURE_ID } from '@kbn/alerting-plugin/common'; import type { PluginsSetup, PluginsStart, RouteInitialization } from './types'; import type { MlCapabilities } from '../common/types/capabilities'; import { notificationsRoutes } from './routes/notifications'; @@ -140,7 +141,7 @@ export class MlServerPlugin }, alerting: Object.values(ML_ALERT_TYPES).map((ruleTypeId) => ({ ruleTypeId, - consumers: [PLUGIN_ID], + consumers: [PLUGIN_ID, ALERTING_FEATURE_ID], })), privileges: { all: admin, From 05f858e3df8382a6d3eec68f5413752876bca5e2 Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Thu, 18 Jul 2024 11:16:41 +0300 Subject: [PATCH 017/106] Fix stack alerts tests --- .../stack_alerts/server/feature.test.ts | 35 +++++++++++-------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/x-pack/plugins/stack_alerts/server/feature.test.ts b/x-pack/plugins/stack_alerts/server/feature.test.ts index 8935a8a43c5d24..60a2507808b5e1 100644 --- a/x-pack/plugins/stack_alerts/server/feature.test.ts +++ b/x-pack/plugins/stack_alerts/server/feature.test.ts @@ -27,26 +27,31 @@ describe('Stack Alerts Feature Privileges', () => { const featuresSetup = featuresPluginMock.createSetup(); plugin.setup(coreSetup, { alerting: alertingSetup, features: featuresSetup }); - const typesInFeaturePrivilege = BUILT_IN_ALERTS_FEATURE.alerting ?? []; - const typesInFeaturePrivilegeAll = - BUILT_IN_ALERTS_FEATURE.privileges?.all?.alerting?.rule?.all ?? []; - const typesInFeaturePrivilegeRead = - BUILT_IN_ALERTS_FEATURE.privileges?.read?.alerting?.rule?.read ?? []; - // transform alerting rule is initialized during the transform plugin setup - expect(alertingSetup.registerType.mock.calls.length).toEqual( - typesInFeaturePrivilege.length - 1 + const ruleTypeIdsAlerting = new Set( + BUILT_IN_ALERTS_FEATURE.alerting?.map((feature) => feature.ruleTypeId) ?? [] ); - expect(alertingSetup.registerType.mock.calls.length).toEqual( - typesInFeaturePrivilegeAll.length - 1 + + const ruleTypeIdsAll = new Set( + BUILT_IN_ALERTS_FEATURE.privileges?.all?.alerting?.rule?.all?.map( + (feature) => feature.ruleTypeId + ) ?? [] ); - expect(alertingSetup.registerType.mock.calls.length).toEqual( - typesInFeaturePrivilegeRead.length - 1 + + const ruleTypeIdsRead = new Set( + BUILT_IN_ALERTS_FEATURE.privileges?.read?.alerting?.rule?.read?.map( + (feature) => feature.ruleTypeId + ) ?? [] ); + // transform alerting rule is initialized during the transform plugin setup + expect(alertingSetup.registerType.mock.calls.length).toEqual(ruleTypeIdsAlerting.size - 1); + expect(alertingSetup.registerType.mock.calls.length).toEqual(ruleTypeIdsAll.size - 1); + expect(alertingSetup.registerType.mock.calls.length).toEqual(ruleTypeIdsRead.size - 1); + alertingSetup.registerType.mock.calls.forEach((call) => { - expect(typesInFeaturePrivilege.indexOf(call[0].id)).toBeGreaterThanOrEqual(0); - expect(typesInFeaturePrivilegeAll.indexOf(call[0].id)).toBeGreaterThanOrEqual(0); - expect(typesInFeaturePrivilegeRead.indexOf(call[0].id)).toBeGreaterThanOrEqual(0); + expect(ruleTypeIdsAlerting.has(call[0].id)).toBe(true); + expect(ruleTypeIdsAll.has(call[0].id)).toBe(true); + expect(ruleTypeIdsRead.has(call[0].id)).toBe(true); }); }); }); From 7578b2bf77743cb028bc3a61c96e6b8dea724da0 Mon Sep 17 00:00:00 2001 From: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Date: Thu, 18 Jul 2024 08:18:14 +0000 Subject: [PATCH 018/106] [CI] Auto-commit changed files from 'node scripts/lint_ts_projects --fix' --- x-pack/packages/security-solution/features/tsconfig.json | 1 + x-pack/plugins/alerting/tsconfig.json | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/x-pack/packages/security-solution/features/tsconfig.json b/x-pack/packages/security-solution/features/tsconfig.json index 2c153f831721d7..b37b81f709e9e8 100644 --- a/x-pack/packages/security-solution/features/tsconfig.json +++ b/x-pack/packages/security-solution/features/tsconfig.json @@ -17,6 +17,7 @@ "@kbn/cases-plugin", "@kbn/securitysolution-rules", "@kbn/securitysolution-list-constants", + "@kbn/alerting-plugin", ], "exclude": ["target/**/*"] } diff --git a/x-pack/plugins/alerting/tsconfig.json b/x-pack/plugins/alerting/tsconfig.json index 63d1ea5768c4e7..b5c9cb32cfb66c 100644 --- a/x-pack/plugins/alerting/tsconfig.json +++ b/x-pack/plugins/alerting/tsconfig.json @@ -70,7 +70,8 @@ "@kbn/react-kibana-context-render", "@kbn/search-types", "@kbn/alerting-state-types", - "@kbn/core-security-server" + "@kbn/core-security-server", + "@kbn/security-plugin-types-server" ], "exclude": [ "target/**/*" From c28823b4c4df01e2c4fc9335cebe2a3cf69d1c1d Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Thu, 18 Jul 2024 17:20:25 +0300 Subject: [PATCH 019/106] Fix more types --- .../plugins/cases/server/connectors/index.ts | 4 ++-- x-pack/plugins/cases/server/types.ts | 4 ++-- .../bulk_action/bulk_action.ts | 4 ++-- .../plugins/ml/server/routes/job_service.ts | 20 ++++++++----------- .../endpoint/endpoint_app_context_services.ts | 4 ++-- .../fleet_integration/fleet_integration.ts | 4 ++-- .../handlers/install_prepackaged_rules.ts | 11 ++++------ ...ebuilt_rules_and_timelines_status_route.ts | 2 +- .../get_prebuilt_rules_status_route.ts | 2 +- ...tall_prebuilt_rules_and_timelines_route.ts | 2 +- .../perform_rule_installation_route.ts | 2 +- .../perform_rule_upgrade_route.ts | 2 +- .../review_rule_installation_route.ts | 2 +- .../review_rule_upgrade_route.ts | 2 +- .../routes/__mocks__/request_context.ts | 2 +- .../api/create_legacy_notification/route.ts | 2 +- .../api/create_rule_exceptions/route.ts | 2 +- .../api/find_exception_references/route.ts | 2 +- .../api/rules/bulk_actions/route.ts | 2 +- .../api/rules/bulk_create_rules/route.ts | 2 +- .../api/rules/bulk_delete_rules/route.ts | 2 +- .../api/rules/bulk_patch_rules/route.ts | 2 +- .../api/rules/bulk_update_rules/route.ts | 2 +- .../api/rules/coverage_overview/route.ts | 2 +- .../api/rules/create_rule/route.ts | 2 +- .../api/rules/delete_rule/route.ts | 2 +- .../api/rules/export_rules/route.ts | 2 +- .../api/rules/filters/route.ts | 2 +- .../api/rules/find_rules/route.ts | 2 +- .../api/rules/patch_rule/route.ts | 2 +- .../api/rules/read_rule/route.ts | 2 +- .../api/rules/update_rule/route.ts | 2 +- .../api/tags/read_tags/route.ts | 2 +- .../rule_types/__mocks__/rule_type.ts | 4 ++-- .../utils/search_after_bulk_create.test.ts | 4 ++-- .../rule_types/utils/utils.test.ts | 4 ++-- .../rule_types/utils/utils.ts | 4 ++-- .../server/plugin_contract.ts | 9 +++------ .../server/request_context_factory.ts | 6 ++++-- x-pack/plugins/timelines/server/types.ts | 4 ++-- 40 files changed, 65 insertions(+), 73 deletions(-) diff --git a/x-pack/plugins/cases/server/connectors/index.ts b/x-pack/plugins/cases/server/connectors/index.ts index 2d680163dde28d..cb6fe0cb45689c 100644 --- a/x-pack/plugins/cases/server/connectors/index.ts +++ b/x-pack/plugins/cases/server/connectors/index.ts @@ -9,7 +9,7 @@ import type { PluginSetupContract as ActionsPluginSetupContract } from '@kbn/act import type { KibanaRequest } from '@kbn/core-http-server'; import type { CoreSetup, SavedObjectsClientContract } from '@kbn/core/server'; import { SECURITY_EXTENSION_ID } from '@kbn/core/server'; -import type { PluginSetupContract as AlertingPluginSetup } from '@kbn/alerting-plugin/server'; +import type { AlertingServerSetup } from '@kbn/alerting-plugin/server'; import type { CasesClient } from '../client'; import { getCasesConnectorAdapter, getCasesConnectorType } from './cases'; @@ -24,7 +24,7 @@ export function registerConnectorTypes({ getSpaceId, }: { actions: ActionsPluginSetupContract; - alerting: AlertingPluginSetup; + alerting: AlertingServerSetup; core: CoreSetup; getCasesClient: (request: KibanaRequest) => Promise; getSpaceId: (request?: KibanaRequest) => string; diff --git a/x-pack/plugins/cases/server/types.ts b/x-pack/plugins/cases/server/types.ts index 0153083337cfaa..7b00cd87cf71dc 100644 --- a/x-pack/plugins/cases/server/types.ts +++ b/x-pack/plugins/cases/server/types.ts @@ -29,14 +29,14 @@ import type { UsageCollectionSetup } from '@kbn/usage-collection-plugin/server'; import type { LicensingPluginSetup, LicensingPluginStart } from '@kbn/licensing-plugin/server'; import type { NotificationsPluginStart } from '@kbn/notifications-plugin/server'; import type { RuleRegistryPluginStartContract } from '@kbn/rule-registry-plugin/server'; -import type { PluginSetupContract as AlertingPluginSetup } from '@kbn/alerting-plugin/server'; +import type { AlertingServerSetup } from '@kbn/alerting-plugin/server'; import type { CasesClient } from './client'; import type { AttachmentFramework } from './attachment_framework/types'; import type { ExternalReferenceAttachmentTypeRegistry } from './attachment_framework/external_reference_registry'; import type { PersistableStateAttachmentTypeRegistry } from './attachment_framework/persistable_state_registry'; export interface CasesServerSetupDependencies { - alerting: AlertingPluginSetup; + alerting: AlertingServerSetup; actions: ActionsPluginSetup; lens: LensServerPluginSetup; features: FeaturesPluginSetup; diff --git a/x-pack/plugins/cloud_security_posture/server/routes/benchmark_rules/bulk_action/bulk_action.ts b/x-pack/plugins/cloud_security_posture/server/routes/benchmark_rules/bulk_action/bulk_action.ts index 31b80b880bcc96..8f31f80d422cbf 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/benchmark_rules/bulk_action/bulk_action.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/benchmark_rules/bulk_action/bulk_action.ts @@ -31,7 +31,7 @@ import { bulkActionBenchmarkRulesHandler } from './v1'; // ... (additional benchmark rules) ]; } - + Response: { updated_benchmark_rules: CspBenchmarkRulesStates; Benchmark rules object that were affected @@ -68,7 +68,7 @@ export const defineBulkActionCspBenchmarkRulesRoute = (router: CspRouter) => const benchmarkRulesToUpdate = requestBody.rules; - const detectionRulesClient = (await context.alerting).getRulesClient(); + const detectionRulesClient = await (await context.alerting).getRulesClient(); const handlerResponse = await bulkActionBenchmarkRulesHandler( cspContext.soClient, diff --git a/x-pack/plugins/ml/server/routes/job_service.ts b/x-pack/plugins/ml/server/routes/job_service.ts index 3ddbf8a46cb659..d8c7ca0fd8bc7b 100644 --- a/x-pack/plugins/ml/server/routes/job_service.ts +++ b/x-pack/plugins/ml/server/routes/job_service.ts @@ -143,7 +143,7 @@ export function jobServiceRoutes({ router, routeGuard }: RouteInitialization) { routeGuard.fullLicenseAPIGuard(async ({ client, mlClient, request, response, context }) => { try { const alerting = await context.alerting; - const rulesClient = alerting?.getRulesClient(); + const rulesClient = await alerting?.getRulesClient(); const { deleteJobs } = jobServiceProvider(client, mlClient, rulesClient); const { jobIds, deleteUserAnnotations, deleteAlertingRules } = request.body; @@ -314,7 +314,8 @@ export function jobServiceRoutes({ router, routeGuard }: RouteInitialization) { routeGuard.fullLicenseAPIGuard(async ({ client, mlClient, request, response, context }) => { try { const alerting = await context.alerting; - const { jobsSummary } = jobServiceProvider(client, mlClient, alerting?.getRulesClient()); + const rulesClient = await alerting?.getRulesClient(); + const { jobsSummary } = jobServiceProvider(client, mlClient, rulesClient); const { jobIds } = request.body; const resp = await jobsSummary(jobIds); @@ -352,11 +353,8 @@ export function jobServiceRoutes({ router, routeGuard }: RouteInitialization) { routeGuard.fullLicenseAPIGuard(async ({ client, mlClient, response, context }) => { try { const alerting = await context.alerting; - const { getJobIdsWithGeo } = jobServiceProvider( - client, - mlClient, - alerting?.getRulesClient() - ); + const rulesClient = await alerting?.getRulesClient(); + const { getJobIdsWithGeo } = jobServiceProvider(client, mlClient, rulesClient); const resp = await getJobIdsWithGeo(); @@ -475,11 +473,9 @@ export function jobServiceRoutes({ router, routeGuard }: RouteInitialization) { routeGuard.fullLicenseAPIGuard(async ({ client, mlClient, request, response, context }) => { try { const alerting = await context.alerting; - const { createFullJobsList } = jobServiceProvider( - client, - mlClient, - alerting?.getRulesClient() - ); + const rulesClient = await alerting?.getRulesClient(); + + const { createFullJobsList } = jobServiceProvider(client, mlClient, rulesClient); const { jobIds } = request.body; const resp = await createFullJobsList(jobIds); diff --git a/x-pack/plugins/security_solution/server/endpoint/endpoint_app_context_services.ts b/x-pack/plugins/security_solution/server/endpoint/endpoint_app_context_services.ts index d7181b3ce49c60..08f9aa0533c216 100644 --- a/x-pack/plugins/security_solution/server/endpoint/endpoint_app_context_services.ts +++ b/x-pack/plugins/security_solution/server/endpoint/endpoint_app_context_services.ts @@ -20,7 +20,7 @@ import type { FleetStartContract, MessageSigningServiceInterface, } from '@kbn/fleet-plugin/server'; -import type { PluginStartContract as AlertsPluginStartContract } from '@kbn/alerting-plugin/server'; +import type { AlertingServerStart } from '@kbn/alerting-plugin/server'; import type { CloudSetup } from '@kbn/cloud-plugin/server'; import type { FleetActionsClientInterface } from '@kbn/fleet-plugin/server/services/actions/types'; import type { PluginStartContract as ActionsPluginStartContract } from '@kbn/actions-plugin/server'; @@ -69,7 +69,7 @@ export interface EndpointAppContextServiceStartContract { endpointFleetServicesFactory: EndpointFleetServicesFactoryInterface; manifestManager?: ManifestManager; security: SecurityServiceStart; - alerting: AlertsPluginStartContract; + alerting: AlertingServerStart; config: ConfigType; registerIngestCallback?: FleetStartContract['registerExternalCallback']; registerListsServerExtension?: ListsServerExtensionRegistrar; diff --git a/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.ts b/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.ts index 71c935e7205110..c7a707013d8b1e 100644 --- a/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.ts +++ b/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.ts @@ -7,7 +7,7 @@ import type { Logger, ElasticsearchClient, SavedObjectsClientContract } from '@kbn/core/server'; import type { ExceptionListClient } from '@kbn/lists-plugin/server'; -import type { PluginStartContract as AlertsStartContract } from '@kbn/alerting-plugin/server'; +import type { AlertingServerStart } from '@kbn/alerting-plugin/server'; import type { PostPackagePolicyCreateCallback, PostPackagePolicyPostDeleteCallback, @@ -88,7 +88,7 @@ export const getPackagePolicyCreateCallback = ( logger: Logger, manifestManager: ManifestManager, securitySolutionRequestContextFactory: IRequestContextFactory, - alerts: AlertsStartContract, + alerts: AlertingServerStart, licenseService: LicenseService, exceptionsClient: ExceptionListClient | undefined, cloud: CloudSetup, diff --git a/x-pack/plugins/security_solution/server/fleet_integration/handlers/install_prepackaged_rules.ts b/x-pack/plugins/security_solution/server/fleet_integration/handlers/install_prepackaged_rules.ts index d4a60be85d3eab..891face9f2879f 100644 --- a/x-pack/plugins/security_solution/server/fleet_integration/handlers/install_prepackaged_rules.ts +++ b/x-pack/plugins/security_solution/server/fleet_integration/handlers/install_prepackaged_rules.ts @@ -7,7 +7,7 @@ import type { KibanaRequest, Logger } from '@kbn/core/server'; import type { ExceptionListClient } from '@kbn/lists-plugin/server'; -import type { PluginStartContract as AlertsStartContract } from '@kbn/alerting-plugin/server'; +import type { AlertingServerStart } from '@kbn/alerting-plugin/server'; import { createDetectionIndex } from '../../lib/detection_engine/routes/index/create_index_route'; import { createPrepackagedRules } from '../../lib/detection_engine/prebuilt_rules'; import type { SecuritySolutionApiRequestHandlerContext } from '../../types'; @@ -16,7 +16,7 @@ export interface InstallPrepackagedRulesProps { logger: Logger; context: SecuritySolutionApiRequestHandlerContext; request: KibanaRequest; - alerts: AlertsStartContract; + alerts: AlertingServerStart; exceptionsClient: ExceptionListClient; } @@ -45,11 +45,8 @@ export const installPrepackagedRules = async ({ try { // this checks to make sure index exists first, safe to try in case of failure above // may be able to recover from minor errors - await createPrepackagedRules( - context, - alerts.getRulesClientWithRequest(request), - exceptionsClient - ); + const rulesClient = await alerts.getRulesClientWithRequest(request); + await createPrepackagedRules(context, rulesClient, exceptionsClient); } catch (err) { logger.error( `Unable to create detection rules automatically (${err.statusCode}): ${err.message}` diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/get_prebuilt_rules_and_timelines_status/get_prebuilt_rules_and_timelines_status_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/get_prebuilt_rules_and_timelines_status/get_prebuilt_rules_and_timelines_status_route.ts index 84cb18032f50e2..16bff20288ba47 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/get_prebuilt_rules_and_timelines_status/get_prebuilt_rules_and_timelines_status_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/get_prebuilt_rules_and_timelines_status/get_prebuilt_rules_and_timelines_status_route.ts @@ -44,7 +44,7 @@ export const getPrebuiltRulesAndTimelinesStatusRoute = (router: SecuritySolution const siemResponse = buildSiemResponse(response); const ctx = await context.resolve(['core', 'alerting']); const savedObjectsClient = ctx.core.savedObjects.client; - const rulesClient = ctx.alerting.getRulesClient(); + const rulesClient = await ctx.alerting.getRulesClient(); const ruleAssetsClient = createPrebuiltRuleAssetsClient(savedObjectsClient); try { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/get_prebuilt_rules_status/get_prebuilt_rules_status_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/get_prebuilt_rules_status/get_prebuilt_rules_status_route.ts index a5596ca4c84984..f0c32861d1def6 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/get_prebuilt_rules_status/get_prebuilt_rules_status_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/get_prebuilt_rules_status/get_prebuilt_rules_status_route.ts @@ -35,7 +35,7 @@ export const getPrebuiltRulesStatusRoute = (router: SecuritySolutionPluginRouter try { const ctx = await context.resolve(['core', 'alerting']); const soClient = ctx.core.savedObjects.client; - const rulesClient = ctx.alerting.getRulesClient(); + const rulesClient = await ctx.alerting.getRulesClient(); const ruleAssetsClient = createPrebuiltRuleAssetsClient(soClient); const ruleObjectsClient = createPrebuiltRuleObjectsClient(rulesClient); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/install_prebuilt_rules_and_timelines/install_prebuilt_rules_and_timelines_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/install_prebuilt_rules_and_timelines/install_prebuilt_rules_and_timelines_route.ts index 11e841ed504316..25d1d36b018d5a 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/install_prebuilt_rules_and_timelines/install_prebuilt_rules_and_timelines_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/install_prebuilt_rules_and_timelines/install_prebuilt_rules_and_timelines_route.ts @@ -49,7 +49,7 @@ export const installPrebuiltRulesAndTimelinesRoute = (router: SecuritySolutionPl const siemResponse = buildSiemResponse(response); try { - const rulesClient = (await context.alerting).getRulesClient(); + const rulesClient = await (await context.alerting).getRulesClient(); const validated = await createPrepackagedRules( await context.securitySolution, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_installation/perform_rule_installation_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_installation/perform_rule_installation_route.ts index 8ffec60a26c119..efb21bb5412ff1 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_installation/perform_rule_installation_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_installation/perform_rule_installation_route.ts @@ -57,7 +57,7 @@ export const performRuleInstallationRoute = (router: SecuritySolutionPluginRoute const ctx = await context.resolve(['core', 'alerting', 'securitySolution']); const config = ctx.securitySolution.getConfig(); const soClient = ctx.core.savedObjects.client; - const rulesClient = ctx.alerting.getRulesClient(); + const rulesClient = await ctx.alerting.getRulesClient(); const detectionRulesClient = ctx.securitySolution.getDetectionRulesClient(); const ruleAssetsClient = createPrebuiltRuleAssetsClient(soClient); const ruleObjectsClient = createPrebuiltRuleObjectsClient(rulesClient); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_upgrade/perform_rule_upgrade_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_upgrade/perform_rule_upgrade_route.ts index 0d1693a69806e3..221a5549c4a34e 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_upgrade/perform_rule_upgrade_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_upgrade/perform_rule_upgrade_route.ts @@ -58,7 +58,7 @@ export const performRuleUpgradeRoute = (router: SecuritySolutionPluginRouter) => try { const ctx = await context.resolve(['core', 'alerting', 'securitySolution']); const soClient = ctx.core.savedObjects.client; - const rulesClient = ctx.alerting.getRulesClient(); + const rulesClient = await ctx.alerting.getRulesClient(); const detectionRulesClient = ctx.securitySolution.getDetectionRulesClient(); const ruleAssetsClient = createPrebuiltRuleAssetsClient(soClient); const ruleObjectsClient = createPrebuiltRuleObjectsClient(rulesClient); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/review_rule_installation/review_rule_installation_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/review_rule_installation/review_rule_installation_route.ts index ec3ca342bf8c9a..494bdd33d10e97 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/review_rule_installation/review_rule_installation_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/review_rule_installation/review_rule_installation_route.ts @@ -44,7 +44,7 @@ export const reviewRuleInstallationRoute = (router: SecuritySolutionPluginRouter try { const ctx = await context.resolve(['core', 'alerting']); const soClient = ctx.core.savedObjects.client; - const rulesClient = ctx.alerting.getRulesClient(); + const rulesClient = await ctx.alerting.getRulesClient(); const ruleAssetsClient = createPrebuiltRuleAssetsClient(soClient); const ruleObjectsClient = createPrebuiltRuleObjectsClient(rulesClient); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/review_rule_upgrade/review_rule_upgrade_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/review_rule_upgrade/review_rule_upgrade_route.ts index f38fcc7953641d..c09d16a64a8db6 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/review_rule_upgrade/review_rule_upgrade_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/review_rule_upgrade/review_rule_upgrade_route.ts @@ -53,7 +53,7 @@ export const reviewRuleUpgradeRoute = (router: SecuritySolutionPluginRouter) => try { const ctx = await context.resolve(['core', 'alerting']); const soClient = ctx.core.savedObjects.client; - const rulesClient = ctx.alerting.getRulesClient(); + const rulesClient = await ctx.alerting.getRulesClient(); const ruleAssetsClient = createPrebuiltRuleAssetsClient(soClient); const ruleObjectsClient = createPrebuiltRuleObjectsClient(rulesClient); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/__mocks__/request_context.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/__mocks__/request_context.ts index fa9fcc1fa5e225..a30f52b2bd6f69 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/__mocks__/request_context.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/__mocks__/request_context.ts @@ -92,7 +92,7 @@ const createRequestContextMock = ( getActionsClient: jest.fn(() => clients.actionsClient), } as unknown as jest.Mocked, alerting: { - getRulesClient: jest.fn(() => clients.rulesClient), + getRulesClient: jest.fn().mockResolvedValue(clients.rulesClient), } as unknown as jest.Mocked, licensing: clients.licensing, lists: { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_actions_legacy/api/create_legacy_notification/route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_actions_legacy/api/create_legacy_notification/route.ts index 518ece11dbefef..bcf4f11f558dd4 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_actions_legacy/api/create_legacy_notification/route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_actions_legacy/api/create_legacy_notification/route.ts @@ -62,7 +62,7 @@ export const legacyCreateLegacyNotificationRoute = ( }, }, async (context, request, response) => { - const rulesClient = (await context.alerting).getRulesClient(); + const rulesClient = await (await context.alerting).getRulesClient(); const savedObjectsClient = (await context.core).savedObjects.client; const { alert_id: ruleAlertId } = request.query; const { actions, interval, name } = request.body; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_exceptions/api/create_rule_exceptions/route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_exceptions/api/create_rule_exceptions/route.ts index 22aa94ad80aee4..ef7a18b60474c8 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_exceptions/api/create_rule_exceptions/route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_exceptions/api/create_rule_exceptions/route.ts @@ -61,7 +61,7 @@ export const createRuleExceptionsRoute = (router: SecuritySolutionPluginRouter) 'licensing', 'lists', ]); - const rulesClient = ctx.alerting.getRulesClient(); + const rulesClient = await ctx.alerting.getRulesClient(); const listsClient = ctx.securitySolution.getExceptionListClient(); const detectionRulesClient = ctx.securitySolution.getDetectionRulesClient(); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_exceptions/api/find_exception_references/route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_exceptions/api/find_exception_references/route.ts index f8714c4e260ee4..13c913f3ad30ee 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_exceptions/api/find_exception_references/route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_exceptions/api/find_exception_references/route.ts @@ -52,7 +52,7 @@ export const findRuleExceptionReferencesRoute = (router: SecuritySolutionPluginR const { ids, namespace_types: namespaceTypes, list_ids: listIds } = request.query; const ctx = await context.resolve(['core', 'securitySolution', 'alerting']); - const rulesClient = ctx.alerting.getRulesClient(); + const rulesClient = await ctx.alerting.getRulesClient(); const listsClient = ctx.securitySolution.getExceptionListClient(); if ( diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_actions/route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_actions/route.ts index b2c6ae6e044687..bb3ae49cac239c 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_actions/route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_actions/route.ts @@ -117,7 +117,7 @@ export const performBulkActionRoute = ( 'actions', ]); - const rulesClient = ctx.alerting.getRulesClient(); + const rulesClient = await ctx.alerting.getRulesClient(); const exceptionsClient = ctx.lists?.getExceptionListClient(); const savedObjectsClient = ctx.core.savedObjects.client; const actionsClient = ctx.actions.getActionsClient(); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_create_rules/route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_create_rules/route.ts index 98910ea3376307..bb2d97e005eddd 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_create_rules/route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_create_rules/route.ts @@ -60,7 +60,7 @@ export const bulkCreateRulesRoute = (router: SecuritySolutionPluginRouter, logge try { const ctx = await context.resolve(['core', 'securitySolution', 'licensing', 'alerting']); - const rulesClient = ctx.alerting.getRulesClient(); + const rulesClient = await ctx.alerting.getRulesClient(); const detectionRulesClient = ctx.securitySolution.getDetectionRulesClient(); const ruleDefinitions = request.body; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_delete_rules/route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_delete_rules/route.ts index f582e19d2bcad8..1a73b0802188cd 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_delete_rules/route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_delete_rules/route.ts @@ -59,7 +59,7 @@ export const bulkDeleteRulesRoute = (router: SecuritySolutionPluginRouter, logge try { const ctx = await context.resolve(['core', 'securitySolution', 'alerting']); - const rulesClient = ctx.alerting.getRulesClient(); + const rulesClient = await ctx.alerting.getRulesClient(); const detectionRulesClient = ctx.securitySolution.getDetectionRulesClient(); const rules = await Promise.all( diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_patch_rules/route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_patch_rules/route.ts index da75e4e33362a8..c9429ab179ab4a 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_patch_rules/route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_patch_rules/route.ts @@ -54,7 +54,7 @@ export const bulkPatchRulesRoute = (router: SecuritySolutionPluginRouter, logger try { const ctx = await context.resolve(['core', 'securitySolution', 'alerting', 'licensing']); - const rulesClient = ctx.alerting.getRulesClient(); + const rulesClient = await ctx.alerting.getRulesClient(); const detectionRulesClient = ctx.securitySolution.getDetectionRulesClient(); const rules = await Promise.all( diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_update_rules/route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_update_rules/route.ts index fb95e7e452afd9..481959e0d17eb7 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_update_rules/route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_update_rules/route.ts @@ -58,7 +58,7 @@ export const bulkUpdateRulesRoute = (router: SecuritySolutionPluginRouter, logge try { const ctx = await context.resolve(['core', 'securitySolution', 'alerting', 'licensing']); - const rulesClient = ctx.alerting.getRulesClient(); + const rulesClient = await ctx.alerting.getRulesClient(); const detectionRulesClient = ctx.securitySolution.getDetectionRulesClient(); const rules = await Promise.all( diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/coverage_overview/route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/coverage_overview/route.ts index 0a298008dd3543..39177d7f9c0b9c 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/coverage_overview/route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/coverage_overview/route.ts @@ -43,7 +43,7 @@ export const getCoverageOverviewRoute = (router: SecuritySolutionPluginRouter) = const responseData = await handleCoverageOverviewRequest({ params: request.body, - deps: { rulesClient: ctx.alerting.getRulesClient() }, + deps: { rulesClient: await ctx.alerting.getRulesClient() }, }); return response.ok({ diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/create_rule/route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/create_rule/route.ts index aa6425b2e673ce..e3e5b34da67f51 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/create_rule/route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/create_rule/route.ts @@ -56,7 +56,7 @@ export const createRuleRoute = (router: SecuritySolutionPluginRouter): void => { 'lists', ]); - const rulesClient = ctx.alerting.getRulesClient(); + const rulesClient = await ctx.alerting.getRulesClient(); const detectionRulesClient = ctx.securitySolution.getDetectionRulesClient(); const exceptionsClient = ctx.lists?.getExceptionListClient(); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/delete_rule/route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/delete_rule/route.ts index 42a6a1c47544fe..6452cef470ad3a 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/delete_rule/route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/delete_rule/route.ts @@ -48,7 +48,7 @@ export const deleteRuleRoute = (router: SecuritySolutionPluginRouter) => { const { id, rule_id: ruleId } = request.query; const ctx = await context.resolve(['core', 'securitySolution', 'alerting']); - const rulesClient = ctx.alerting.getRulesClient(); + const rulesClient = await ctx.alerting.getRulesClient(); const detectionRulesClient = ctx.securitySolution.getDetectionRulesClient(); const rule = await readRules({ rulesClient, id, ruleId }); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/export_rules/route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/export_rules/route.ts index 478a0ce02cc968..3ff82ee5678d2b 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/export_rules/route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/export_rules/route.ts @@ -49,7 +49,7 @@ export const exportRulesRoute = ( }, async (context, request, response) => { const siemResponse = buildSiemResponse(response); - const rulesClient = (await context.alerting).getRulesClient(); + const rulesClient = await (await context.alerting).getRulesClient(); const exceptionsClient = (await context.lists)?.getExceptionListClient(); const actionsClient = (await context.actions)?.getActionsClient(); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/filters/route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/filters/route.ts index 183d4f8e2f78d3..09665ecd152be1 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/filters/route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/filters/route.ts @@ -68,7 +68,7 @@ export const getRuleManagementFilters = (router: SecuritySolutionPluginRouter) = async (context, _, response): Promise> => { const siemResponse = buildSiemResponse(response); const ctx = await context.resolve(['alerting']); - const rulesClient = ctx.alerting.getRulesClient(); + const rulesClient = await ctx.alerting.getRulesClient(); try { const [{ prebuilt: prebuiltRulesCount, custom: customRulesCount }, tags] = diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/find_rules/route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/find_rules/route.ts index 02ff637ab6f109..3d11e56142dcb3 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/find_rules/route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/find_rules/route.ts @@ -49,7 +49,7 @@ export const findRulesRoute = (router: SecuritySolutionPluginRouter, logger: Log try { const { query } = request; const ctx = await context.resolve(['core', 'securitySolution', 'alerting']); - const rulesClient = ctx.alerting.getRulesClient(); + const rulesClient = await ctx.alerting.getRulesClient(); const rules = await findRules({ rulesClient, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/patch_rule/route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/patch_rule/route.ts index 3886f63c482b0a..bf49debe89ea4d 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/patch_rule/route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/patch_rule/route.ts @@ -50,7 +50,7 @@ export const patchRuleRoute = (router: SecuritySolutionPluginRouter) => { } try { const params = request.body; - const rulesClient = (await context.alerting).getRulesClient(); + const rulesClient = await (await context.alerting).getRulesClient(); const detectionRulesClient = (await context.securitySolution).getDetectionRulesClient(); const existingRule = await readRules({ diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/read_rule/route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/read_rule/route.ts index a119d1afae912b..174106c81b642c 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/read_rule/route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/read_rule/route.ts @@ -47,7 +47,7 @@ export const readRuleRoute = (router: SecuritySolutionPluginRouter, logger: Logg const { id, rule_id: ruleId } = request.query; try { - const rulesClient = (await context.alerting).getRulesClient(); + const rulesClient = await (await context.alerting).getRulesClient(); // TODO: https://github.com/elastic/kibana/issues/125642 Reuse fetchRuleById const rule = await readRules({ diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/update_rule/route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/update_rule/route.ts index fb7a7a9e3197db..8ec38184f8e2f0 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/update_rule/route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/update_rule/route.ts @@ -48,7 +48,7 @@ export const updateRuleRoute = (router: SecuritySolutionPluginRouter) => { } try { const ctx = await context.resolve(['core', 'securitySolution', 'alerting', 'licensing']); - const rulesClient = ctx.alerting.getRulesClient(); + const rulesClient = await ctx.alerting.getRulesClient(); const detectionRulesClient = ctx.securitySolution.getDetectionRulesClient(); checkDefaultRuleExceptionListReferences({ exceptionLists: request.body.exceptions_list }); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/tags/read_tags/route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/tags/read_tags/route.ts index 5120603f9f674c..f6205883947565 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/tags/read_tags/route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/tags/read_tags/route.ts @@ -30,7 +30,7 @@ export const readTagsRoute = (router: SecuritySolutionPluginRouter) => { async (context, request, response): Promise> => { const siemResponse = buildSiemResponse(response); const ctx = await context.resolve(['alerting']); - const rulesClient = ctx.alerting.getRulesClient(); + const rulesClient = await ctx.alerting.getRulesClient(); try { const tags = await readTags({ diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/__mocks__/rule_type.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/__mocks__/rule_type.ts index 6cf237ca583e2d..d4de9fb079ac3b 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/__mocks__/rule_type.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/__mocks__/rule_type.ts @@ -16,7 +16,7 @@ import type { IRuleDataClient } from '@kbn/rule-registry-plugin/server'; import { ruleRegistryMocks } from '@kbn/rule-registry-plugin/server/mocks'; import { eventLogServiceMock } from '@kbn/event-log-plugin/server/mocks'; import type { PluginSetupContract as ActionsPluginSetupContract } from '@kbn/actions-plugin/server'; -import type { PluginSetupContract as AlertingPluginSetupContract } from '@kbn/alerting-plugin/server'; +import type { AlertingServerSetup } from '@kbn/alerting-plugin/server'; import type { ConfigType } from '../../../../config'; import type { AlertAttributes } from '../types'; import { createRuleMock } from './rule'; @@ -48,7 +48,7 @@ export const createRuleTypeMocks = ( alertExecutor = executor; }, getConfig: () => ({ run: { alerts: { max: DEFAULT_MAX_ALERTS } } }), - } as AlertingPluginSetupContract; + } as AlertingServerSetup; const actions = { registerType: jest.fn(), diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/search_after_bulk_create.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/search_after_bulk_create.test.ts index 4d414d71cfadfd..cabfbaeb930377 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/search_after_bulk_create.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/search_after_bulk_create.test.ts @@ -49,7 +49,7 @@ import { ruleExecutionLogMock } from '../../rule_monitoring/mocks'; import type { BuildReasonMessage } from './reason_formatters'; import type { QueryRuleParams } from '../../rule_schema'; import { SERVER_APP_ID } from '../../../../../common/constants'; -import type { PluginSetupContract } from '@kbn/alerting-plugin/server'; +import type { AlertingServerSetup } from '@kbn/alerting-plugin/server'; describe('searchAfterAndBulkCreate', () => { let mockService: RuleExecutorServicesMock; @@ -59,7 +59,7 @@ describe('searchAfterAndBulkCreate', () => { let wrapHits: WrapHits; let inputIndexPattern: string[] = []; let listClient = listMock.getListClient(); - let alerting: PluginSetupContract; + let alerting: AlertingServerSetup; const ruleExecutionLogger = ruleExecutionLogMock.forExecutors.create(); const someGuids = Array.from({ length: 13 }).map(() => uuidv4()); const sampleParams = getQueryRuleParams(); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/utils.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/utils.test.ts index a7895ba229cc8d..821cbec7927d7c 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/utils.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/utils.test.ts @@ -68,7 +68,7 @@ import type { ShardError } from '../../../types'; import { ruleExecutionLogMock } from '../../rule_monitoring/mocks'; import type { GenericBulkCreateResponse } from '../factories'; import type { BaseFieldsLatest } from '../../../../../common/api/detection_engine/model/alerts'; -import type { PluginSetupContract } from '@kbn/alerting-plugin/server'; +import type { AlertingServerSetup } from '@kbn/alerting-plugin/server'; describe('utils', () => { const anchor = '2020-01-01T06:06:06.666Z'; @@ -446,7 +446,7 @@ describe('utils', () => { }); describe('getRuleRangeTuples', () => { - let alerting: PluginSetupContract; + let alerting: AlertingServerSetup; beforeEach(() => { alerting = alertsMock.createSetup(); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/utils.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/utils.ts index e67659b525342e..ef442bd9f86ca3 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/utils.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/utils.ts @@ -26,7 +26,7 @@ import type { import type { AlertInstanceContext, AlertInstanceState, - PluginSetupContract, + AlertingServerSetup, RuleExecutorServices, } from '@kbn/alerting-plugin/server'; import { parseDuration } from '@kbn/alerting-plugin/server'; @@ -429,7 +429,7 @@ export const getRuleRangeTuples = async ({ interval: string; maxSignals: number; ruleExecutionLogger: IRuleExecutionLogForExecutors; - alerting: PluginSetupContract; + alerting: AlertingServerSetup; }) => { const originalFrom = dateMath.parse(from, { forceNow: startedAt }); const originalTo = dateMath.parse(to, { forceNow: startedAt }); diff --git a/x-pack/plugins/security_solution/server/plugin_contract.ts b/x-pack/plugins/security_solution/server/plugin_contract.ts index 1bae27813f5ad2..d56abebe2caeec 100644 --- a/x-pack/plugins/security_solution/server/plugin_contract.ts +++ b/x-pack/plugins/security_solution/server/plugin_contract.ts @@ -12,10 +12,7 @@ import type { } from '@kbn/data-plugin/server'; import type { PluginStart as DataViewsPluginStart } from '@kbn/data-views-plugin/server'; import type { UsageCollectionSetup as UsageCollectionPluginSetup } from '@kbn/usage-collection-plugin/server'; -import type { - PluginSetupContract as AlertingPluginSetup, - PluginStartContract as AlertingPluginStart, -} from '@kbn/alerting-plugin/server'; +import type { AlertingServerSetup, AlertingServerStart } from '@kbn/alerting-plugin/server'; import type { PluginSetupContract as ActionsPluginSetup, PluginStartContract as ActionsPluginStartContract, @@ -50,7 +47,7 @@ import type { ProductFeaturesService } from './lib/product_features_service/prod import type { ExperimentalFeatures } from '../common'; export interface SecuritySolutionPluginSetupDependencies { - alerting: AlertingPluginSetup; + alerting: AlertingServerSetup; actions: ActionsPluginSetup; cases: CasesServerSetup; cloud: CloudSetup; @@ -73,7 +70,7 @@ export interface SecuritySolutionPluginSetupDependencies { } export interface SecuritySolutionPluginStartDependencies { - alerting: AlertingPluginStart; + alerting: AlertingServerStart; cases?: CasesServerStart; cloud: CloudSetup; cloudExperiments?: CloudExperimentsPluginStart; diff --git a/x-pack/plugins/security_solution/server/request_context_factory.ts b/x-pack/plugins/security_solution/server/request_context_factory.ts index 00db7dcb2c3e83..fe6b98d1d3ee5f 100644 --- a/x-pack/plugins/security_solution/server/request_context_factory.ts +++ b/x-pack/plugins/security_solution/server/request_context_factory.ts @@ -86,6 +86,8 @@ export class RequestContextFactory implements IRequestContextFactory { // time it is requested (see `getEndpointAuthz()` below) let endpointAuthz: Immutable; + const rulesClient = await startPlugins.alerting.getRulesClientWithRequest(request); + return { core: coreContext, @@ -123,7 +125,7 @@ export class RequestContextFactory implements IRequestContextFactory { }); return createDetectionRulesClient({ - rulesClient: startPlugins.alerting.getRulesClientWithRequest(request), + rulesClient, savedObjectsClient: coreContext.savedObjects.client, mlAuthz, }); @@ -131,7 +133,7 @@ export class RequestContextFactory implements IRequestContextFactory { getDetectionEngineHealthClient: memoize(() => ruleMonitoringService.createDetectionEngineHealthClient({ - rulesClient: startPlugins.alerting.getRulesClientWithRequest(request), + rulesClient, eventLogClient: startPlugins.eventLog.getClient(request), currentSpaceId: getSpaceId(), }) diff --git a/x-pack/plugins/timelines/server/types.ts b/x-pack/plugins/timelines/server/types.ts index 311281f67ea2a8..b412b69be97379 100644 --- a/x-pack/plugins/timelines/server/types.ts +++ b/x-pack/plugins/timelines/server/types.ts @@ -6,7 +6,7 @@ */ import type { PluginSetup, PluginStart } from '@kbn/data-plugin/server'; -import { PluginStartContract as AlertingPluginStartContract } from '@kbn/alerting-plugin/server'; +import { AlertingServerStart } from '@kbn/alerting-plugin/server'; import { SecurityPluginSetup } from '@kbn/security-plugin/server'; // eslint-disable-next-line @typescript-eslint/no-empty-interface @@ -21,5 +21,5 @@ export interface SetupPlugins { export interface StartPlugins { data: PluginStart; - alerting: AlertingPluginStartContract; + alerting: AlertingServerStart; } From 9915f67490d4dda83da4757f59ef40bc0f6ef0fc Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Thu, 18 Jul 2024 17:59:30 +0300 Subject: [PATCH 020/106] Show rule types with alerts consumer in o11y --- .../src/alerts_as_data_rbac.ts | 2 ++ .../observability/common/constants.ts | 1 + x-pack/plugins/stack_alerts/server/feature.ts | 23 +++++++++++++------ .../sections/alerts_table/constants.ts | 2 +- 4 files changed, 20 insertions(+), 8 deletions(-) diff --git a/packages/kbn-rule-data-utils/src/alerts_as_data_rbac.ts b/packages/kbn-rule-data-utils/src/alerts_as_data_rbac.ts index 2780c4b72a553c..b38eaa1715c154 100644 --- a/packages/kbn-rule-data-utils/src/alerts_as_data_rbac.ts +++ b/packages/kbn-rule-data-utils/src/alerts_as_data_rbac.ts @@ -27,7 +27,9 @@ export const AlertConsumers = { STACK_ALERTS: 'stackAlerts', EXAMPLE: 'AlertingExample', MONITORING: 'monitoring', + ALERTS: 'alerts', } as const; + export type AlertConsumers = typeof AlertConsumers[keyof typeof AlertConsumers]; export type STATUS_VALUES = 'open' | 'acknowledged' | 'closed' | 'in-progress'; // TODO: remove 'in-progress' after migration to 'acknowledged' diff --git a/x-pack/plugins/observability_solution/observability/common/constants.ts b/x-pack/plugins/observability_solution/observability/common/constants.ts index 0286e4bef08257..a45e421f6a8e4f 100644 --- a/x-pack/plugins/observability_solution/observability/common/constants.ts +++ b/x-pack/plugins/observability_solution/observability/common/constants.ts @@ -20,6 +20,7 @@ export const observabilityAlertFeatureIds: ValidFeatureId[] = [ AlertConsumers.UPTIME, AlertConsumers.SLO, AlertConsumers.OBSERVABILITY, + AlertConsumers.ALERTS, ]; export const observabilityRuleCreationValidConsumers: RuleCreationValidConsumer[] = [ diff --git a/x-pack/plugins/stack_alerts/server/feature.ts b/x-pack/plugins/stack_alerts/server/feature.ts index 6851ba5c112b40..0d432f1414f120 100644 --- a/x-pack/plugins/stack_alerts/server/feature.ts +++ b/x-pack/plugins/stack_alerts/server/feature.ts @@ -9,7 +9,11 @@ import { i18n } from '@kbn/i18n'; import { KibanaFeatureConfig } from '@kbn/features-plugin/common'; import { DEFAULT_APP_CATEGORIES } from '@kbn/core/server'; import { TRANSFORM_RULE_TYPE } from '@kbn/transform-plugin/common'; -import { STACK_ALERTS_FEATURE_ID } from '@kbn/rule-data-utils'; +import { + ML_ANOMALY_DETECTION_RULE_TYPE_ID, + OBSERVABILITY_THRESHOLD_RULE_TYPE_ID, + STACK_ALERTS_FEATURE_ID, +} from '@kbn/rule-data-utils'; import { ES_QUERY_ID as ElasticsearchQuery } from '@kbn/rule-data-utils'; import { ALERTING_FEATURE_ID } from '@kbn/alerting-plugin/common'; import { ID as IndexThreshold } from './rule_types/index_threshold/rule_type'; @@ -17,12 +21,17 @@ import { GEO_CONTAINMENT_ID as GeoContainment } from './rule_types/geo_containme const TransformHealth = TRANSFORM_RULE_TYPE.TRANSFORM_HEALTH; -const alertingFeatures = [IndexThreshold, GeoContainment, ElasticsearchQuery, TransformHealth].map( - (ruleTypeId) => ({ - ruleTypeId, - consumers: [STACK_ALERTS_FEATURE_ID, ALERTING_FEATURE_ID], - }) -); +const alertingFeatures = [ + IndexThreshold, + GeoContainment, + ElasticsearchQuery, + TransformHealth, + ML_ANOMALY_DETECTION_RULE_TYPE_ID, + OBSERVABILITY_THRESHOLD_RULE_TYPE_ID, +].map((ruleTypeId) => ({ + ruleTypeId, + consumers: [STACK_ALERTS_FEATURE_ID, ALERTING_FEATURE_ID], +})); export const BUILT_IN_ALERTS_FEATURE: KibanaFeatureConfig = { id: STACK_ALERTS_FEATURE_ID, diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/constants.ts b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/constants.ts index 9605abb085232e..97b8be342c1ead 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/constants.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/constants.ts @@ -39,7 +39,7 @@ export const stackFeatureIds: AlertConsumers[] = [AlertConsumers.STACK_ALERTS, A export const [_, ...observabilityApps] = observabilityFeatureIds; -export const alertProducersData: Record = { +export const alertProducersData: Record, AlertProducerData> = { [AlertConsumers.OBSERVABILITY]: { displayName: OBSERVABILITY_DISPLAY_NAME, icon: 'logoObservability', From 7a66de3f917fb1d531af75f5f38880fce734f5b8 Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Thu, 18 Jul 2024 18:26:56 +0300 Subject: [PATCH 021/106] Fix session_view tests --- .../server/routes/alert_status_route.test.ts | 3 +- .../server/routes/alerts_client_mock.test.ts | 105 ++++++++---------- .../server/routes/alerts_route.test.ts | 6 +- .../routes/process_events_route.test.ts | 4 +- .../components/stack_alerts_page.tsx | 3 +- .../alerts_table/cells/render_cell_value.tsx | 4 +- .../sections/alerts_table/constants.ts | 4 +- .../sections/alerts_table/types.ts | 2 + 8 files changed, 56 insertions(+), 75 deletions(-) diff --git a/x-pack/plugins/session_view/server/routes/alert_status_route.test.ts b/x-pack/plugins/session_view/server/routes/alert_status_route.test.ts index 646c0cbca96b5e..d38b83747181a7 100644 --- a/x-pack/plugins/session_view/server/routes/alert_status_route.test.ts +++ b/x-pack/plugins/session_view/server/routes/alert_status_route.test.ts @@ -13,7 +13,7 @@ import { import { elasticsearchServiceMock } from '@kbn/core/server/mocks'; import { searchAlertByUuid } from './alert_status_route'; import { mockAlerts } from '../../common/mocks/constants/session_view_process.mock'; -import { getAlertsClientMockInstance, resetAlertingAuthMock } from './alerts_client_mock.test'; +import { getAlertsClientMockInstance } from './alerts_client_mock.test'; const getEmptyResponse = async () => { return { @@ -54,7 +54,6 @@ const getResponse = async () => { describe('alert_status_route.ts', () => { beforeEach(() => { jest.resetAllMocks(); - resetAlertingAuthMock(); }); describe('searchAlertByUuid(client, alertUuid)', () => { diff --git a/x-pack/plugins/session_view/server/routes/alerts_client_mock.test.ts b/x-pack/plugins/session_view/server/routes/alerts_client_mock.test.ts index ff76314776025b..dcc1f06b0f2eb2 100644 --- a/x-pack/plugins/session_view/server/routes/alerts_client_mock.test.ts +++ b/x-pack/plugins/session_view/server/routes/alerts_client_mock.test.ts @@ -13,7 +13,6 @@ import { elasticsearchServiceMock } from '@kbn/core/server/mocks'; import { loggingSystemMock } from '@kbn/core/server/mocks'; import { alertingAuthorizationMock } from '@kbn/alerting-plugin/server/authorization/alerting_authorization.mock'; import { auditLoggerMock } from '@kbn/security-plugin/server/audit/mocks'; -import { AlertingAuthorizationEntity } from '@kbn/alerting-plugin/server'; import { ruleDataServiceMock } from '@kbn/rule-registry-plugin/server/rule_data_plugin_service/rule_data_plugin_service.mock'; import type { ElasticsearchClient } from '@kbn/core/server'; import { @@ -24,11 +23,6 @@ import { } from '@kbn/rule-data-utils'; import { mockAlerts } from '../../common/mocks/constants/session_view_process.mock'; -export const alertingAuthMock = alertingAuthorizationMock.create(); -const auditLogger = auditLoggerMock.create(); - -const DEFAULT_SPACE = 'test_default_space_id'; - const getResponse = async () => { return { hits: { @@ -56,73 +50,62 @@ const getResponse = async () => { }; }; -const esClientMock = elasticsearchServiceMock.createElasticsearchClient(getResponse()); -const getAlertIndicesAliasMock = jest.fn(); -const alertsClientParams: jest.Mocked = { - logger: loggingSystemMock.create().get(), - authorization: alertingAuthMock, - auditLogger, - ruleDataService: ruleDataServiceMock.create(), - esClient: esClientMock, - getRuleType: jest.fn(), - getRuleList: jest.fn(), - getAlertIndicesAlias: getAlertIndicesAliasMock, -}; - -export function getAlertsClientMockInstance(esClient?: ElasticsearchClient) { - esClient = esClient || elasticsearchServiceMock.createElasticsearchClient(getResponse()); - - const alertsClient = new AlertsClient({ ...alertsClientParams, esClient }); - - return alertsClient; -} +const createAlertsClientParams = () => { + const getAlertIndicesAliasMock = jest.fn(); + const alertingAuthMock = alertingAuthorizationMock.create(); -export function resetAlertingAuthMock() { - alertingAuthMock.getSpaceId.mockImplementation(() => DEFAULT_SPACE); - // @ts-expect-error - alertingAuthMock.getAuthorizationFilter.mockImplementation(async () => - Promise.resolve({ filter: [] }) - ); - // @ts-expect-error - alertingAuthMock.getAugmentedRuleTypesWithAuthorization.mockImplementation(async () => { - const authorizedRuleTypes = new Set(); - authorizedRuleTypes.add({ producer: 'apm' }); - return Promise.resolve({ authorizedRuleTypes }); - }); - // @ts-expect-error - alertingAuthMock.getAuthorizedRuleTypes.mockImplementation(async () => { - const authorizedRuleTypes = [ + const authorizedRuleTypes = new Map([ + [ + 'apm.error_rate', { producer: 'apm', id: 'apm.error_rate', alerts: { context: 'observability.apm', }, + authorizedConsumers: {}, }, - ]; - return Promise.resolve(authorizedRuleTypes); + ], + ]); + + alertingAuthMock.getSpaceId.mockImplementation(() => 'test_default_space_id'); + alertingAuthMock.getAllAuthorizedRuleTypes.mockResolvedValue({ + hasAllRequested: true, + authorizedRuleTypes, }); + + alertingAuthMock.getAllAuthorizedRuleTypesFindOperation.mockResolvedValue(authorizedRuleTypes); getAlertIndicesAliasMock.mockReturnValue(['.alerts-observability.apm-default']); - alertingAuthMock.ensureAuthorized.mockImplementation( - // @ts-expect-error - async ({ - ruleTypeId, - consumer, - operation, - entity, - }: { - ruleTypeId: string; - consumer: string; - operation: string; - entity: typeof AlertingAuthorizationEntity.Alert; - }) => { - if (ruleTypeId === 'apm.error_rate' && consumer === 'apm') { - return Promise.resolve(); - } - return Promise.reject(new Error(`Unauthorized for ${ruleTypeId} and ${consumer}`)); + alertingAuthMock.ensureAuthorized.mockImplementation(async ({ ruleTypeId, consumer }) => { + if (ruleTypeId === 'apm.error_rate' && consumer === 'apm') { + return Promise.resolve(); } - ); + return Promise.reject(new Error(`Unauthorized for ${ruleTypeId} and ${consumer}`)); + }); + + const auditLogger = auditLoggerMock.create(); + const esClientMock = elasticsearchServiceMock.createElasticsearchClient(getResponse()); + const alertsClientParams: jest.Mocked = { + logger: loggingSystemMock.create().get(), + authorization: alertingAuthMock, + auditLogger, + ruleDataService: ruleDataServiceMock.create(), + esClient: esClientMock, + getRuleType: jest.fn(), + getRuleList: jest.fn(), + getAlertIndicesAlias: getAlertIndicesAliasMock, + }; + + return alertsClientParams; +}; + +export function getAlertsClientMockInstance(esClient?: ElasticsearchClient) { + esClient = esClient || elasticsearchServiceMock.createElasticsearchClient(getResponse()); + + const alertsClient = new AlertsClient({ ...createAlertsClientParams(), esClient }); + + return alertsClient; } // this is only here because the above imports complain if they aren't declared as part of a test file. diff --git a/x-pack/plugins/session_view/server/routes/alerts_route.test.ts b/x-pack/plugins/session_view/server/routes/alerts_route.test.ts index 12300b8946a78a..b8ba3f5d45a02a 100644 --- a/x-pack/plugins/session_view/server/routes/alerts_route.test.ts +++ b/x-pack/plugins/session_view/server/routes/alerts_route.test.ts @@ -7,7 +7,7 @@ import { elasticsearchServiceMock } from '@kbn/core/server/mocks'; import { searchAlerts } from './alerts_route'; import { mockAlerts } from '../../common/mocks/constants/session_view_process.mock'; -import { getAlertsClientMockInstance, resetAlertingAuthMock } from './alerts_client_mock.test'; +import { getAlertsClientMockInstance } from './alerts_client_mock.test'; const getEmptyResponse = async () => { return { @@ -20,9 +20,7 @@ const getEmptyResponse = async () => { describe('alerts_route.ts', () => { beforeEach(() => { - jest.resetAllMocks(); - - resetAlertingAuthMock(); + jest.clearAllMocks(); }); describe('searchAlerts(client, sessionEntityId)', () => { diff --git a/x-pack/plugins/session_view/server/routes/process_events_route.test.ts b/x-pack/plugins/session_view/server/routes/process_events_route.test.ts index 034cab178af2f6..aaba035c7496ba 100644 --- a/x-pack/plugins/session_view/server/routes/process_events_route.test.ts +++ b/x-pack/plugins/session_view/server/routes/process_events_route.test.ts @@ -12,7 +12,7 @@ import { mockEvents, mockAlerts, } from '../../common/mocks/constants/session_view_process.mock'; -import { getAlertsClientMockInstance, resetAlertingAuthMock } from './alerts_client_mock.test'; +import { getAlertsClientMockInstance } from './alerts_client_mock.test'; import type { ProcessEvent } from '../../common'; const getEmptyResponse = async () => { @@ -38,8 +38,6 @@ const getResponse = async () => { describe('process_events_route.ts', () => { beforeEach(() => { jest.resetAllMocks(); - - resetAlertingAuthMock(); }); describe('fetchEventsAndScopedAlerts(client, entityId, cursor, forward)', () => { diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_page/components/stack_alerts_page.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_page/components/stack_alerts_page.tsx index 1c4c511b2ccca0..2559130ef426fe 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_page/components/stack_alerts_page.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_page/components/stack_alerts_page.tsx @@ -46,6 +46,7 @@ import { useLoadRuleTypesQuery } from '../../../hooks/use_load_rule_types_query' import { nonNullable } from '../../../../../common/utils'; import { useRuleTypeIdsByFeatureId } from '../hooks/use_rule_type_ids_by_feature_id'; import { TECH_PREVIEW_DESCRIPTION, TECH_PREVIEW_LABEL } from '../../translations'; +import { AlertsTableSupportedConsumers } from '../../alerts_table/types'; const AlertsTable = lazy(() => import('../../alerts_table/alerts_table_state')); /** @@ -108,7 +109,7 @@ const PageContent = () => { filters.push( ...Object.entries(ruleTypeIdsByFeatureId) .map(([featureId, ruleTypeIds]) => { - const producerData = alertProducersData[featureId as AlertConsumers]; + const producerData = alertProducersData[featureId as AlertsTableSupportedConsumers]; if (!producerData) { return null; } diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/cells/render_cell_value.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/cells/render_cell_value.tsx index 2d76d4cd19aba8..9a32cc11e5018f 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/cells/render_cell_value.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/cells/render_cell_value.tsx @@ -9,7 +9,6 @@ import { isEmpty } from 'lodash'; import React from 'react'; import { ALERT_DURATION, - AlertConsumers, ALERT_RULE_NAME, ALERT_RULE_UUID, ALERT_START, @@ -25,6 +24,7 @@ import { import { EuiBadge, EuiLink, RenderCellValue } from '@elastic/eui'; import { alertProducersData, observabilityFeatureIds } from '../constants'; import { useKibana } from '../../../../common/lib/kibana'; +import { AlertsTableSupportedConsumers } from '../types'; export const getMappedNonEcsValue = ({ data, @@ -136,7 +136,7 @@ export function getAlertFormatters(fieldFormats: FieldFormatsRegistry) { ); case ALERT_RULE_CONSUMER: const producer = rowData?.find(({ field }) => field === ALERT_RULE_PRODUCER)?.value?.[0]; - const consumer: AlertConsumers = observabilityFeatureIds.includes(producer) + const consumer: AlertsTableSupportedConsumers = observabilityFeatureIds.includes(producer) ? 'observability' : producer && (value === 'alerts' || value === 'stackAlerts') ? producer diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/constants.ts b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/constants.ts index 97b8be342c1ead..70ef244d872baf 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/constants.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/constants.ts @@ -19,6 +19,7 @@ import { STACK_MONITORING_DISPLAY_NAME, UPTIME_DISPLAY_NAME, } from '../translations'; +import { AlertsTableSupportedConsumers } from './types'; interface AlertProducerData { displayName: string; @@ -36,10 +37,9 @@ export const observabilityFeatureIds: AlertConsumers[] = [ ]; export const stackFeatureIds: AlertConsumers[] = [AlertConsumers.STACK_ALERTS, AlertConsumers.ML]; - export const [_, ...observabilityApps] = observabilityFeatureIds; -export const alertProducersData: Record, AlertProducerData> = { +export const alertProducersData: Record = { [AlertConsumers.OBSERVABILITY]: { displayName: OBSERVABILITY_DISPLAY_NAME, icon: 'logoObservability', diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/types.ts b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/types.ts index 819cc42bd90e62..46b349ae9bccef 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/types.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/types.ts @@ -20,6 +20,8 @@ export interface Consumer { name: string; } +export type AlertsTableSupportedConsumers = Exclude; + export type ServerError = IHttpFetchError; export interface CellComponentProps { From 87e0ef2f5dc3cd973bc373fdaefdabb07d65e6d9 Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Thu, 18 Jul 2024 18:35:56 +0300 Subject: [PATCH 022/106] Fix types and linting errors --- .../alerting_example/server/plugin.ts | 4 +-- .../server/plugin.ts | 4 +-- x-pack/plugins/alerting/server/plugin.test.ts | 12 +++++---- .../plugins/alerts/server/plugin.ts | 10 +++---- .../plugins/alerts/server/plugin.ts | 26 ++++++++++++------- 5 files changed, 33 insertions(+), 23 deletions(-) diff --git a/x-pack/examples/alerting_example/server/plugin.ts b/x-pack/examples/alerting_example/server/plugin.ts index 06ac98f6a4e297..fa8310a75b1c57 100644 --- a/x-pack/examples/alerting_example/server/plugin.ts +++ b/x-pack/examples/alerting_example/server/plugin.ts @@ -9,7 +9,7 @@ import { Plugin, CoreSetup } from '@kbn/core/server'; import { i18n } from '@kbn/i18n'; // import directly to support examples functional tests (@kbn-test/src/functional_tests/lib/babel_register_for_test_plugins.js) import { DEFAULT_APP_CATEGORIES } from '@kbn/core-application-common'; -import { PluginSetupContract as AlertingSetup } from '@kbn/alerting-plugin/server'; +import { AlertingServerSetup } from '@kbn/alerting-plugin/server'; import { FeaturesPluginSetup } from '@kbn/features-plugin/server'; import { ALERTING_FEATURE_ID } from '@kbn/alerting-plugin/common'; @@ -22,7 +22,7 @@ import { ALERTING_EXAMPLE_APP_ID } from '../common/constants'; // this plugin's dependencies export interface AlertingExampleDeps { - alerting: AlertingSetup; + alerting: AlertingServerSetup; features: FeaturesPluginSetup; } diff --git a/x-pack/examples/triggers_actions_ui_example/server/plugin.ts b/x-pack/examples/triggers_actions_ui_example/server/plugin.ts index 6d55bbb2cb55d8..6bf6c1fd1442e1 100644 --- a/x-pack/examples/triggers_actions_ui_example/server/plugin.ts +++ b/x-pack/examples/triggers_actions_ui_example/server/plugin.ts @@ -8,7 +8,7 @@ import { Plugin, CoreSetup } from '@kbn/core/server'; import { PluginSetupContract as ActionsSetup } from '@kbn/actions-plugin/server'; -import { PluginSetupContract as AlertingSetup } from '@kbn/alerting-plugin/server'; +import { AlertingServerSetup } from '@kbn/alerting-plugin/server'; import { getConnectorType as getSystemLogExampleConnectorType, @@ -17,7 +17,7 @@ import { // this plugin's dependencies export interface TriggersActionsUiExampleDeps { - alerting: AlertingSetup; + alerting: AlertingServerSetup; actions: ActionsSetup; } export class TriggersActionsUiExamplePlugin diff --git a/x-pack/plugins/alerting/server/plugin.test.ts b/x-pack/plugins/alerting/server/plugin.test.ts index 38a4f717be3b0d..2938daf8b1ec33 100644 --- a/x-pack/plugins/alerting/server/plugin.test.ts +++ b/x-pack/plugins/alerting/server/plugin.test.ts @@ -209,7 +209,8 @@ describe('Alerting Plugin', () => { ...sampleRuleType, minimumLicenseRequired: 'basic', } as RuleType; - await setup.registerType(ruleType); + + setup.registerType(ruleType); expect(ruleType.ruleTaskTimeout).toBe('5m'); }); @@ -219,7 +220,7 @@ describe('Alerting Plugin', () => { minimumLicenseRequired: 'basic', ruleTaskTimeout: '20h', } as RuleType; - await setup.registerType(ruleType); + setup.registerType(ruleType); expect(ruleType.ruleTaskTimeout).toBe('20h'); }); @@ -228,7 +229,7 @@ describe('Alerting Plugin', () => { ...sampleRuleType, minimumLicenseRequired: 'basic', } as RuleType; - await setup.registerType(ruleType); + setup.registerType(ruleType); expect(ruleType.cancelAlertsOnRuleTimeout).toBe(true); }); @@ -238,7 +239,7 @@ describe('Alerting Plugin', () => { minimumLicenseRequired: 'basic', cancelAlertsOnRuleTimeout: false, } as RuleType; - await setup.registerType(ruleType); + setup.registerType(ruleType); expect(ruleType.cancelAlertsOnRuleTimeout).toBe(false); }); }); @@ -444,7 +445,8 @@ describe('Alerting Plugin', () => { }, getSavedObjectsClient: jest.fn(), } as unknown as KibanaRequest; - startContract.getAlertingAuthorizationWithRequest(fakeRequest); + + await startContract.getAlertingAuthorizationWithRequest(fakeRequest); }); }); }); diff --git a/x-pack/test/functional_execution_context/plugins/alerts/server/plugin.ts b/x-pack/test/functional_execution_context/plugins/alerts/server/plugin.ts index 7f78f95913cf79..457cc50de007db 100644 --- a/x-pack/test/functional_execution_context/plugins/alerts/server/plugin.ts +++ b/x-pack/test/functional_execution_context/plugins/alerts/server/plugin.ts @@ -7,7 +7,7 @@ import apmAgent from 'elastic-apm-node'; import type { Plugin, CoreSetup } from '@kbn/core/server'; -import { PluginSetupContract as AlertingPluginSetup } from '@kbn/alerting-plugin/server/plugin'; +import { AlertingServerSetup } from '@kbn/alerting-plugin/server/plugin'; import { EncryptedSavedObjectsPluginStart } from '@kbn/encrypted-saved-objects-plugin/server'; import { FeaturesPluginSetup } from '@kbn/features-plugin/server'; import { SpacesPluginStart } from '@kbn/spaces-plugin/server'; @@ -15,7 +15,7 @@ import { SecurityPluginStart } from '@kbn/security-plugin/server'; export interface FixtureSetupDeps { features: FeaturesPluginSetup; - alerting: AlertingPluginSetup; + alerting: AlertingServerSetup; } export interface FixtureStartDeps { @@ -33,7 +33,7 @@ export class FixturePlugin implements Plugin Date: Thu, 18 Jul 2024 22:29:51 +0300 Subject: [PATCH 023/106] Fix rule_registry tests --- .../server/alert_data_client/alerts_client.ts | 4 +- .../tests/bulk_update.test.ts | 60 ++++++------ .../tests/find_alerts.test.ts | 93 +++++++++---------- .../alert_data_client/tests/get.test.ts | 55 +++++------ .../get_alerts_group_aggregations.test.ts | 53 +++++------ .../alert_data_client/tests/update.test.ts | 54 +++++------ .../search_strategy/search_strategy.test.ts | 5 +- 7 files changed, 153 insertions(+), 171 deletions(-) diff --git a/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts b/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts index 9ff9aac6ec2b8f..5a5c3410720e59 100644 --- a/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts +++ b/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts @@ -367,7 +367,9 @@ export class AlertsClient { return result; } catch (error) { - const errorMessage = `Unable to retrieve alert details for alert with id of "${id}" or with query "${query}" and operation ${operation} \nError: ${error}`; + const errorMessage = `Unable to retrieve alert details for alert with id of "${id}" or with query "${JSON.stringify( + query + )}" and operation ${operation} \nError: ${error}`; this.logger.error(errorMessage); throw Boom.notFound(errorMessage); } diff --git a/x-pack/plugins/rule_registry/server/alert_data_client/tests/bulk_update.test.ts b/x-pack/plugins/rule_registry/server/alert_data_client/tests/bulk_update.test.ts index 28cd76ca6dffe2..8d2e6cffa0cc5c 100644 --- a/x-pack/plugins/rule_registry/server/alert_data_client/tests/bulk_update.test.ts +++ b/x-pack/plugins/rule_registry/server/alert_data_client/tests/bulk_update.test.ts @@ -17,7 +17,6 @@ import { loggingSystemMock } from '@kbn/core/server/mocks'; import { elasticsearchClientMock } from '@kbn/core-elasticsearch-client-server-mocks'; import { alertingAuthorizationMock } from '@kbn/alerting-plugin/server/authorization/alerting_authorization.mock'; import { auditLoggerMock } from '@kbn/security-plugin/server/audit/mocks'; -import { AlertingAuthorizationEntity } from '@kbn/alerting-plugin/server'; import { ruleDataServiceMock } from '../../rule_data_plugin_service/rule_data_plugin_service.mock'; const alertingAuthMock = alertingAuthorizationMock.create(); @@ -36,39 +35,38 @@ const alertsClientParams: jest.Mocked = { }; const DEFAULT_SPACE = 'test_default_space_id'; +const authorizedRuleTypes = new Map([ + [ + 'apm.error_rate', + { + producer: 'apm', + id: 'apm.error_rate', + alerts: { + context: 'observability.apm', + }, + authorizedConsumers: {}, + }, + ], +]); beforeEach(() => { jest.resetAllMocks(); - alertingAuthMock.getSpaceId.mockImplementation(() => 'test_default_space_id'); - // @ts-expect-error - alertingAuthMock.getAuthorizationFilter.mockImplementation(async () => - Promise.resolve({ filter: [] }) - ); - // @ts-expect-error - alertingAuthMock.getAugmentedRuleTypesWithAuthorization.mockImplementation(async () => { - const authorizedRuleTypes = new Set(); - authorizedRuleTypes.add({ producer: 'apm' }); - return Promise.resolve({ authorizedRuleTypes }); + alertingAuthMock.getSpaceId.mockImplementation(() => DEFAULT_SPACE); + alertingAuthMock.getAuthorizationFilter.mockResolvedValue({ + filter: undefined, + ensureRuleTypeIsAuthorized: jest.fn(), }); - alertingAuthMock.ensureAuthorized.mockImplementation( - // @ts-expect-error - async ({ - ruleTypeId, - consumer, - operation, - entity, - }: { - ruleTypeId: string; - consumer: string; - operation: string; - entity: typeof AlertingAuthorizationEntity.Alert; - }) => { - if (ruleTypeId === 'apm.error_rate' && consumer === 'apm') { - return Promise.resolve(); - } - return Promise.reject(new Error(`Unauthorized for ${ruleTypeId} and ${consumer}`)); + alertingAuthMock.getAllAuthorizedRuleTypes.mockResolvedValue({ + hasAllRequested: true, + authorizedRuleTypes, + }); + + alertingAuthMock.ensureAuthorized.mockImplementation(async ({ ruleTypeId, consumer }) => { + if (ruleTypeId === 'apm.error_rate' && consumer === 'apm') { + return Promise.resolve(); } - ); + return Promise.reject(new Error(`Unauthorized for ${ruleTypeId} and ${consumer}`)); + }); }); const fakeAlertId = 'myfakeid1'; @@ -337,7 +335,7 @@ describe('bulkUpdate()', () => { }) ).rejects.toThrowErrorMatchingInlineSnapshot(` "queryAndAuditAllAlerts threw an error: Unable to retrieve alerts with query \\"kibana.alert.status: active\\" and operation update - Error: Unable to retrieve alert details for alert with id of \\"null\\" or with query \\"kibana.alert.status: active\\" and operation update + Error: Unable to retrieve alert details for alert with id of \\"null\\" or with query \\"\\"kibana.alert.status: active\\"\\" and operation update Error: Error: Unauthorized for fake.rule and apm" `); @@ -404,7 +402,7 @@ describe('bulkUpdate()', () => { }) ).rejects.toThrowErrorMatchingInlineSnapshot(` "queryAndAuditAllAlerts threw an error: Unable to retrieve alerts with query \\"kibana.alert.status: active\\" and operation update - Error: Unable to retrieve alert details for alert with id of \\"null\\" or with query \\"kibana.alert.status: active\\" and operation update + Error: Unable to retrieve alert details for alert with id of \\"null\\" or with query \\"\\"kibana.alert.status: active\\"\\" and operation update Error: Error: Unauthorized for fake.rule and apm" `); diff --git a/x-pack/plugins/rule_registry/server/alert_data_client/tests/find_alerts.test.ts b/x-pack/plugins/rule_registry/server/alert_data_client/tests/find_alerts.test.ts index 1aee2885cc3182..b704b390a5872b 100644 --- a/x-pack/plugins/rule_registry/server/alert_data_client/tests/find_alerts.test.ts +++ b/x-pack/plugins/rule_registry/server/alert_data_client/tests/find_alerts.test.ts @@ -16,62 +16,59 @@ import { loggingSystemMock } from '@kbn/core/server/mocks'; import { elasticsearchClientMock } from '@kbn/core-elasticsearch-client-server-mocks'; import { alertingAuthorizationMock } from '@kbn/alerting-plugin/server/authorization/alerting_authorization.mock'; import { auditLoggerMock } from '@kbn/security-plugin/server/audit/mocks'; -import { AlertingAuthorizationEntity } from '@kbn/alerting-plugin/server'; import { ruleDataServiceMock } from '../../rule_data_plugin_service/rule_data_plugin_service.mock'; -const alertingAuthMock = alertingAuthorizationMock.create(); -const esClientMock = elasticsearchClientMock.createElasticsearchClient(); -const auditLogger = auditLoggerMock.create(); +describe('find()', () => { + const alertingAuthMock = alertingAuthorizationMock.create(); + const esClientMock = elasticsearchClientMock.createElasticsearchClient(); + const auditLogger = auditLoggerMock.create(); -const alertsClientParams: jest.Mocked = { - logger: loggingSystemMock.create().get(), - authorization: alertingAuthMock, - esClient: esClientMock, - auditLogger, - ruleDataService: ruleDataServiceMock.create(), - getRuleType: jest.fn(), - getRuleList: jest.fn(), - getAlertIndicesAlias: jest.fn(), -}; + const alertsClientParams: jest.Mocked = { + logger: loggingSystemMock.create().get(), + authorization: alertingAuthMock, + esClient: esClientMock, + auditLogger, + ruleDataService: ruleDataServiceMock.create(), + getRuleType: jest.fn(), + getRuleList: jest.fn(), + getAlertIndicesAlias: jest.fn(), + }; -const DEFAULT_SPACE = 'test_default_space_id'; + const DEFAULT_SPACE = 'test_default_space_id'; + const authorizedRuleTypes = new Map([ + [ + 'apm.error_rate', + { + producer: 'apm', + id: 'apm.error_rate', + alerts: { + context: 'observability.apm', + }, + authorizedConsumers: {}, + }, + ], + ]); -beforeEach(() => { - jest.resetAllMocks(); - alertingAuthMock.getSpaceId.mockImplementation(() => DEFAULT_SPACE); - // @ts-expect-error - alertingAuthMock.getAuthorizationFilter.mockImplementation(async () => - Promise.resolve({ filter: [] }) - ); - // @ts-expect-error - alertingAuthMock.getAugmentedRuleTypesWithAuthorization.mockImplementation(async () => { - const authorizedRuleTypes = new Set(); - authorizedRuleTypes.add({ producer: 'apm' }); - return Promise.resolve({ authorizedRuleTypes }); - }); + beforeEach(() => { + jest.resetAllMocks(); + alertingAuthMock.getSpaceId.mockImplementation(() => DEFAULT_SPACE); + alertingAuthMock.getAuthorizationFilter.mockResolvedValue({ + filter: undefined, + ensureRuleTypeIsAuthorized: jest.fn(), + }); + alertingAuthMock.getAllAuthorizedRuleTypes.mockResolvedValue({ + hasAllRequested: true, + authorizedRuleTypes, + }); - alertingAuthMock.ensureAuthorized.mockImplementation( - // @ts-expect-error - async ({ - ruleTypeId, - consumer, - operation, - entity, - }: { - ruleTypeId: string; - consumer: string; - operation: string; - entity: typeof AlertingAuthorizationEntity.Alert; - }) => { + alertingAuthMock.ensureAuthorized.mockImplementation(async ({ ruleTypeId, consumer }) => { if (ruleTypeId === 'apm.error_rate' && consumer === 'apm') { return Promise.resolve(); } return Promise.reject(new Error(`Unauthorized for ${ruleTypeId} and ${consumer}`)); - } - ); -}); + }); + }); -describe('find()', () => { test('calls ES client with given params', async () => { const alertsClient = new AlertsClient(alertsClientParams); esClientMock.search.mockResponseOnce({ @@ -163,7 +160,6 @@ describe('find()', () => { "query": Object { "bool": Object { "filter": Array [ - Object {}, Object { "term": Object { "kibana.space_ids": "test_default_space_id", @@ -297,7 +293,6 @@ describe('find()', () => { "query": Object { "bool": Object { "filter": Array [ - Object {}, Object { "term": Object { "kibana.space_ids": "test_default_space_id", @@ -424,7 +419,7 @@ describe('find()', () => { index: '.alerts-observability.apm.alerts', }) ).rejects.toThrowErrorMatchingInlineSnapshot(` - "Unable to retrieve alert details for alert with id of \\"undefined\\" or with query \\"[object Object]\\" and operation find + "Unable to retrieve alert details for alert with id of \\"undefined\\" or with query \\"{\\"match\\":{\\"kibana.alert.workflow_status\\":\\"open\\"}}\\" and operation find Error: Error: Unauthorized for fake.rule and apm" `); @@ -454,7 +449,7 @@ describe('find()', () => { index: '.alerts-observability.apm.alerts', }) ).rejects.toThrowErrorMatchingInlineSnapshot(` - "Unable to retrieve alert details for alert with id of \\"undefined\\" or with query \\"[object Object]\\" and operation find + "Unable to retrieve alert details for alert with id of \\"undefined\\" or with query \\"{\\"match\\":{\\"kibana.alert.workflow_status\\":\\"open\\"}}\\" and operation find Error: Error: something went wrong" `); }); diff --git a/x-pack/plugins/rule_registry/server/alert_data_client/tests/get.test.ts b/x-pack/plugins/rule_registry/server/alert_data_client/tests/get.test.ts index b48e68c3bf255a..b0fcb505d95b68 100644 --- a/x-pack/plugins/rule_registry/server/alert_data_client/tests/get.test.ts +++ b/x-pack/plugins/rule_registry/server/alert_data_client/tests/get.test.ts @@ -17,7 +17,6 @@ import { loggingSystemMock } from '@kbn/core/server/mocks'; import { elasticsearchClientMock } from '@kbn/core-elasticsearch-client-server-mocks'; import { alertingAuthorizationMock } from '@kbn/alerting-plugin/server/authorization/alerting_authorization.mock'; import { auditLoggerMock } from '@kbn/security-plugin/server/audit/mocks'; -import { AlertingAuthorizationEntity } from '@kbn/alerting-plugin/server'; import { ruleDataServiceMock } from '../../rule_data_plugin_service/rule_data_plugin_service.mock'; const alertingAuthMock = alertingAuthorizationMock.create(); @@ -36,41 +35,38 @@ const alertsClientParams: jest.Mocked = { }; const DEFAULT_SPACE = 'test_default_space_id'; +const authorizedRuleTypes = new Map([ + [ + 'apm.error_rate', + { + producer: 'apm', + id: 'apm.error_rate', + alerts: { + context: 'observability.apm', + }, + authorizedConsumers: {}, + }, + ], +]); beforeEach(() => { jest.resetAllMocks(); alertingAuthMock.getSpaceId.mockImplementation(() => DEFAULT_SPACE); - // @ts-expect-error - alertingAuthMock.getAuthorizationFilter.mockImplementation(async () => - Promise.resolve({ filter: [] }) - ); - - // @ts-expect-error - alertingAuthMock.getAugmentedRuleTypesWithAuthorization.mockImplementation(async () => { - const authorizedRuleTypes = new Set(); - authorizedRuleTypes.add({ producer: 'apm' }); - return Promise.resolve({ authorizedRuleTypes }); + alertingAuthMock.getAuthorizationFilter.mockResolvedValue({ + filter: undefined, + ensureRuleTypeIsAuthorized: jest.fn(), + }); + alertingAuthMock.getAllAuthorizedRuleTypes.mockResolvedValue({ + hasAllRequested: true, + authorizedRuleTypes, }); - alertingAuthMock.ensureAuthorized.mockImplementation( - // @ts-expect-error - async ({ - ruleTypeId, - consumer, - operation, - entity, - }: { - ruleTypeId: string; - consumer: string; - operation: string; - entity: typeof AlertingAuthorizationEntity.Alert; - }) => { - if (ruleTypeId === 'apm.error_rate' && consumer === 'apm') { - return Promise.resolve(); - } - return Promise.reject(new Error(`Unauthorized for ${ruleTypeId} and ${consumer}`)); + alertingAuthMock.ensureAuthorized.mockImplementation(async ({ ruleTypeId, consumer }) => { + if (ruleTypeId === 'apm.error_rate' && consumer === 'apm') { + return Promise.resolve(); } - ); + return Promise.reject(new Error(`Unauthorized for ${ruleTypeId} and ${consumer}`)); + }); }); describe('get()', () => { @@ -150,7 +146,6 @@ describe('get()', () => { ], }, }, - Object {}, Object { "term": Object { "kibana.space_ids": "test_default_space_id", diff --git a/x-pack/plugins/rule_registry/server/alert_data_client/tests/get_alerts_group_aggregations.test.ts b/x-pack/plugins/rule_registry/server/alert_data_client/tests/get_alerts_group_aggregations.test.ts index 8aedf715ff6687..af80e2c0a8b556 100644 --- a/x-pack/plugins/rule_registry/server/alert_data_client/tests/get_alerts_group_aggregations.test.ts +++ b/x-pack/plugins/rule_registry/server/alert_data_client/tests/get_alerts_group_aggregations.test.ts @@ -11,7 +11,6 @@ import { loggingSystemMock } from '@kbn/core/server/mocks'; import { elasticsearchClientMock } from '@kbn/core-elasticsearch-client-server-mocks'; import { alertingAuthorizationMock } from '@kbn/alerting-plugin/server/authorization/alerting_authorization.mock'; import { auditLoggerMock } from '@kbn/security-plugin/server/audit/mocks'; -import { AlertingAuthorizationEntity } from '@kbn/alerting-plugin/server'; import { ruleDataServiceMock } from '../../rule_data_plugin_service/rule_data_plugin_service.mock'; import { DEFAULT_ALERTS_GROUP_BY_FIELD_SIZE, MAX_ALERTS_GROUPING_QUERY_SIZE } from '../constants'; @@ -33,40 +32,38 @@ const alertsClientParams: jest.Mocked = { }; const DEFAULT_SPACE = 'test_default_space_id'; +const authorizedRuleTypes = new Map([ + [ + 'apm.error_rate', + { + producer: 'apm', + id: 'apm.error_rate', + alerts: { + context: 'observability.apm', + }, + authorizedConsumers: {}, + }, + ], +]); beforeEach(() => { jest.resetAllMocks(); alertingAuthMock.getSpaceId.mockImplementation(() => DEFAULT_SPACE); - // @ts-expect-error - alertingAuthMock.getAuthorizationFilter.mockImplementation(async () => - Promise.resolve({ filter: [] }) - ); - // @ts-expect-error - alertingAuthMock.getAugmentedRuleTypesWithAuthorization.mockImplementation(async () => { - const authorizedRuleTypes = new Set(); - authorizedRuleTypes.add({ producer: 'apm' }); - return Promise.resolve({ authorizedRuleTypes }); + alertingAuthMock.getAuthorizationFilter.mockResolvedValue({ + filter: undefined, + ensureRuleTypeIsAuthorized: jest.fn(), + }); + alertingAuthMock.getAllAuthorizedRuleTypes.mockResolvedValue({ + hasAllRequested: true, + authorizedRuleTypes, }); - alertingAuthMock.ensureAuthorized.mockImplementation( - // @ts-expect-error - async ({ - ruleTypeId, - consumer, - operation, - entity, - }: { - ruleTypeId: string; - consumer: string; - operation: string; - entity: typeof AlertingAuthorizationEntity.Alert; - }) => { - if (ruleTypeId === 'apm.error_rate' && consumer === 'apm') { - return Promise.resolve(); - } - return Promise.reject(new Error(`Unauthorized for ${ruleTypeId} and ${consumer}`)); + alertingAuthMock.ensureAuthorized.mockImplementation(async ({ ruleTypeId, consumer }) => { + if (ruleTypeId === 'apm.error_rate' && consumer === 'apm') { + return Promise.resolve(); } - ); + return Promise.reject(new Error(`Unauthorized for ${ruleTypeId} and ${consumer}`)); + }); }); describe('getGroupAggregations()', () => { diff --git a/x-pack/plugins/rule_registry/server/alert_data_client/tests/update.test.ts b/x-pack/plugins/rule_registry/server/alert_data_client/tests/update.test.ts index bd6a1b2695cd18..4b9587b8e0ca1b 100644 --- a/x-pack/plugins/rule_registry/server/alert_data_client/tests/update.test.ts +++ b/x-pack/plugins/rule_registry/server/alert_data_client/tests/update.test.ts @@ -16,7 +16,6 @@ import { loggingSystemMock } from '@kbn/core/server/mocks'; import { elasticsearchClientMock } from '@kbn/core-elasticsearch-client-server-mocks'; import { alertingAuthorizationMock } from '@kbn/alerting-plugin/server/authorization/alerting_authorization.mock'; import { auditLoggerMock } from '@kbn/security-plugin/server/audit/mocks'; -import { AlertingAuthorizationEntity } from '@kbn/alerting-plugin/server'; import { ruleDataServiceMock } from '../../rule_data_plugin_service/rule_data_plugin_service.mock'; const alertingAuthMock = alertingAuthorizationMock.create(); @@ -35,41 +34,38 @@ const alertsClientParams: jest.Mocked = { }; const DEFAULT_SPACE = 'test_default_space_id'; +const authorizedRuleTypes = new Map([ + [ + 'apm.error_rate', + { + producer: 'apm', + id: 'apm.error_rate', + alerts: { + context: 'observability.apm', + }, + authorizedConsumers: {}, + }, + ], +]); beforeEach(() => { jest.resetAllMocks(); alertingAuthMock.getSpaceId.mockImplementation(() => DEFAULT_SPACE); - // @ts-expect-error - alertingAuthMock.getAuthorizationFilter.mockImplementation(async () => - Promise.resolve({ filter: [] }) - ); - - // @ts-expect-error - alertingAuthMock.getAugmentedRuleTypesWithAuthorization.mockImplementation(async () => { - const authorizedRuleTypes = new Set(); - authorizedRuleTypes.add({ producer: 'apm' }); - return Promise.resolve({ authorizedRuleTypes }); + alertingAuthMock.getAuthorizationFilter.mockResolvedValue({ + filter: undefined, + ensureRuleTypeIsAuthorized: jest.fn(), + }); + alertingAuthMock.getAllAuthorizedRuleTypes.mockResolvedValue({ + hasAllRequested: true, + authorizedRuleTypes, }); - alertingAuthMock.ensureAuthorized.mockImplementation( - // @ts-expect-error - async ({ - ruleTypeId, - consumer, - operation, - entity, - }: { - ruleTypeId: string; - consumer: string; - operation: string; - entity: typeof AlertingAuthorizationEntity.Alert; - }) => { - if (ruleTypeId === 'apm.error_rate' && consumer === 'apm') { - return Promise.resolve(); - } - return Promise.reject(new Error(`Unauthorized for ${ruleTypeId} and ${consumer}`)); + alertingAuthMock.ensureAuthorized.mockImplementation(async ({ ruleTypeId, consumer }) => { + if (ruleTypeId === 'apm.error_rate' && consumer === 'apm') { + return Promise.resolve(); } - ); + return Promise.reject(new Error(`Unauthorized for ${ruleTypeId} and ${consumer}`)); + }); }); describe('update()', () => { diff --git a/x-pack/plugins/rule_registry/server/search_strategy/search_strategy.test.ts b/x-pack/plugins/rule_registry/server/search_strategy/search_strategy.test.ts index b4a3a6aad46408..6fdd640aca5fbc 100644 --- a/x-pack/plugins/rule_registry/server/search_strategy/search_strategy.test.ts +++ b/x-pack/plugins/rule_registry/server/search_strategy/search_strategy.test.ts @@ -18,6 +18,7 @@ import { spacesMock } from '@kbn/spaces-plugin/server/mocks'; import { RuleRegistrySearchRequest } from '../../common/search_strategy'; import * as getAuthzFilterImport from '../lib/get_authz_filter'; import { getIsKibanaRequest } from '../lib/get_is_kibana_request'; +import { alertingAuthorizationMock } from '@kbn/alerting-plugin/server/authorization/alerting_authorization.mock'; jest.mock('../lib/get_is_kibana_request'); @@ -75,9 +76,7 @@ describe('ruleRegistrySearchStrategyProvider()', () => { beforeEach(() => { getAuthorizedRuleTypesMock.mockResolvedValue([]); getAlertIndicesAliasMock.mockReturnValue(['test']); - const authorizationMock = { - getAuthorizedRuleTypes: getAuthorizedRuleTypesMock, - } as never; + const authorizationMock = alertingAuthorizationMock.create(); alerting.getAlertingAuthorizationWithRequest.mockResolvedValue(authorizationMock); alerting.getAlertIndicesAlias = getAlertIndicesAliasMock; From 4ff4c0207b77cd22aec6b625fb9b579909634d1d Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Fri, 19 Jul 2024 10:03:48 +0300 Subject: [PATCH 024/106] Fix stack_alerts tests --- .../stack_alerts/server/feature.test.ts | 172 +++++++++++++++--- 1 file changed, 149 insertions(+), 23 deletions(-) diff --git a/x-pack/plugins/stack_alerts/server/feature.test.ts b/x-pack/plugins/stack_alerts/server/feature.test.ts index 60a2507808b5e1..b6fa8c7f7faaf4 100644 --- a/x-pack/plugins/stack_alerts/server/feature.test.ts +++ b/x-pack/plugins/stack_alerts/server/feature.test.ts @@ -27,31 +27,157 @@ describe('Stack Alerts Feature Privileges', () => { const featuresSetup = featuresPluginMock.createSetup(); plugin.setup(coreSetup, { alerting: alertingSetup, features: featuresSetup }); - const ruleTypeIdsAlerting = new Set( - BUILT_IN_ALERTS_FEATURE.alerting?.map((feature) => feature.ruleTypeId) ?? [] - ); - - const ruleTypeIdsAll = new Set( - BUILT_IN_ALERTS_FEATURE.privileges?.all?.alerting?.rule?.all?.map( - (feature) => feature.ruleTypeId - ) ?? [] - ); - - const ruleTypeIdsRead = new Set( - BUILT_IN_ALERTS_FEATURE.privileges?.read?.alerting?.rule?.read?.map( - (feature) => feature.ruleTypeId - ) ?? [] - ); - - // transform alerting rule is initialized during the transform plugin setup - expect(alertingSetup.registerType.mock.calls.length).toEqual(ruleTypeIdsAlerting.size - 1); - expect(alertingSetup.registerType.mock.calls.length).toEqual(ruleTypeIdsAll.size - 1); - expect(alertingSetup.registerType.mock.calls.length).toEqual(ruleTypeIdsRead.size - 1); + const ruleTypeAlerting = BUILT_IN_ALERTS_FEATURE.alerting ?? []; + const ruleTypeAll = BUILT_IN_ALERTS_FEATURE.privileges?.all?.alerting?.rule?.all ?? []; + const ruleTypeRead = BUILT_IN_ALERTS_FEATURE.privileges?.read?.alerting?.rule?.read ?? []; + + expect(ruleTypeAlerting).toMatchInlineSnapshot(` + Array [ + Object { + "consumers": Array [ + "stackAlerts", + "alerts", + ], + "ruleTypeId": ".index-threshold", + }, + Object { + "consumers": Array [ + "stackAlerts", + "alerts", + ], + "ruleTypeId": ".geo-containment", + }, + Object { + "consumers": Array [ + "stackAlerts", + "alerts", + ], + "ruleTypeId": ".es-query", + }, + Object { + "consumers": Array [ + "stackAlerts", + "alerts", + ], + "ruleTypeId": "transform_health", + }, + Object { + "consumers": Array [ + "stackAlerts", + "alerts", + ], + "ruleTypeId": "xpack.ml.anomaly_detection_alert", + }, + Object { + "consumers": Array [ + "stackAlerts", + "alerts", + ], + "ruleTypeId": "observability.rules.custom_threshold", + }, + ] + `); + + expect(ruleTypeAll).toMatchInlineSnapshot(` + Array [ + Object { + "consumers": Array [ + "stackAlerts", + "alerts", + ], + "ruleTypeId": ".index-threshold", + }, + Object { + "consumers": Array [ + "stackAlerts", + "alerts", + ], + "ruleTypeId": ".geo-containment", + }, + Object { + "consumers": Array [ + "stackAlerts", + "alerts", + ], + "ruleTypeId": ".es-query", + }, + Object { + "consumers": Array [ + "stackAlerts", + "alerts", + ], + "ruleTypeId": "transform_health", + }, + Object { + "consumers": Array [ + "stackAlerts", + "alerts", + ], + "ruleTypeId": "xpack.ml.anomaly_detection_alert", + }, + Object { + "consumers": Array [ + "stackAlerts", + "alerts", + ], + "ruleTypeId": "observability.rules.custom_threshold", + }, + ] + `); + + expect(ruleTypeRead).toMatchInlineSnapshot(` + Array [ + Object { + "consumers": Array [ + "stackAlerts", + "alerts", + ], + "ruleTypeId": ".index-threshold", + }, + Object { + "consumers": Array [ + "stackAlerts", + "alerts", + ], + "ruleTypeId": ".geo-containment", + }, + Object { + "consumers": Array [ + "stackAlerts", + "alerts", + ], + "ruleTypeId": ".es-query", + }, + Object { + "consumers": Array [ + "stackAlerts", + "alerts", + ], + "ruleTypeId": "transform_health", + }, + Object { + "consumers": Array [ + "stackAlerts", + "alerts", + ], + "ruleTypeId": "xpack.ml.anomaly_detection_alert", + }, + Object { + "consumers": Array [ + "stackAlerts", + "alerts", + ], + "ruleTypeId": "observability.rules.custom_threshold", + }, + ] + `); alertingSetup.registerType.mock.calls.forEach((call) => { - expect(ruleTypeIdsAlerting.has(call[0].id)).toBe(true); - expect(ruleTypeIdsAll.has(call[0].id)).toBe(true); - expect(ruleTypeIdsRead.has(call[0].id)).toBe(true); + expect( + ruleTypeAlerting.find((feature) => feature.ruleTypeId === call[0].id) + ).not.toBeUndefined(); + expect(ruleTypeAll.find((feature) => feature.ruleTypeId === call[0].id)).not.toBeUndefined(); + expect(ruleTypeRead.find((feature) => feature.ruleTypeId === call[0].id)).not.toBeUndefined(); }); }); }); From 1bd6287d29ed5c259d2558c50b7549249022122f Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Fri, 19 Jul 2024 10:04:10 +0300 Subject: [PATCH 025/106] Fix functional tests alerting registration --- .../common/plugins/alerts/server/plugin.ts | 15 +++--- .../alerts_restricted/server/plugin.ts | 47 +++++++++++++++++-- 2 files changed, 48 insertions(+), 14 deletions(-) diff --git a/x-pack/test/alerting_api_integration/common/plugins/alerts/server/plugin.ts b/x-pack/test/alerting_api_integration/common/plugins/alerts/server/plugin.ts index d1e3f19d7812a5..4da19bc945f2e9 100644 --- a/x-pack/test/alerting_api_integration/common/plugins/alerts/server/plugin.ts +++ b/x-pack/test/alerting_api_integration/common/plugins/alerts/server/plugin.ts @@ -8,10 +8,7 @@ import { Plugin, CoreSetup, CoreStart, Logger, PluginInitializerContext } from '@kbn/core/server'; import { firstValueFrom, Subject } from 'rxjs'; import { PluginSetupContract as ActionsPluginSetup } from '@kbn/actions-plugin/server/plugin'; -import { - PluginStartContract as AlertingPluginsStart, - PluginSetupContract as AlertingPluginSetup, -} from '@kbn/alerting-plugin/server/plugin'; +import { AlertingServerSetup, AlertingServerStart } from '@kbn/alerting-plugin/server/plugin'; import { TaskManagerSetupContract, TaskManagerStartContract, @@ -34,13 +31,13 @@ import { defineConnectorAdapters } from './connector_adapters'; export interface FixtureSetupDeps { features: FeaturesPluginSetup; actions: ActionsPluginSetup; - alerting: AlertingPluginSetup; + alerting: AlertingServerSetup; taskManager: TaskManagerSetupContract; ruleRegistry: RuleRegistryPluginSetupContract; } export interface FixtureStartDeps { - alerting: AlertingPluginsStart; + alerting: AlertingServerStart; encryptedSavedObjects: EncryptedSavedObjectsPluginStart; security?: SecurityPluginStart; spaces?: SpacesPluginStart; @@ -101,7 +98,7 @@ export class FixturePlugin implements Plugin Date: Fri, 19 Jul 2024 11:52:38 +0300 Subject: [PATCH 026/106] Fix triggers_actions_ui unit tests --- .../hooks/use_fetch_browser_fields_capabilities.test.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_fetch_browser_fields_capabilities.test.ts b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_fetch_browser_fields_capabilities.test.ts index 51e270ed1a6a4d..3a52b622310fcb 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_fetch_browser_fields_capabilities.test.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_fetch_browser_fields_capabilities.test.ts @@ -103,7 +103,7 @@ describe('useFetchBrowserFieldCapabilities', () => { it('should not fetch if the only featureId is not valid', async () => { const { result } = renderHook(() => useFetchBrowserFieldCapabilities({ - featureIds: ['alerts'] as unknown as AlertConsumers[], + featureIds: ['foo'] as unknown as AlertConsumers[], }) ); @@ -114,7 +114,7 @@ describe('useFetchBrowserFieldCapabilities', () => { it('should not fetch if all featureId are not valid', async () => { const { result } = renderHook(() => useFetchBrowserFieldCapabilities({ - featureIds: ['alerts', 'tomato'] as unknown as AlertConsumers[], + featureIds: ['foo', 'bar'] as unknown as AlertConsumers[], }) ); @@ -125,7 +125,7 @@ describe('useFetchBrowserFieldCapabilities', () => { it('should filter out the non valid feature id', async () => { const { waitForNextUpdate } = renderHook(() => useFetchBrowserFieldCapabilities({ - featureIds: ['alerts', 'apm', 'logs'] as unknown as AlertConsumers[], + featureIds: ['foo', 'apm', 'logs'] as unknown as AlertConsumers[], }) ); From df5ed4083e6ce94ab74241d00757339e2a1a89d6 Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Fri, 19 Jul 2024 16:43:49 +0300 Subject: [PATCH 027/106] Improve error handling when constructing the AlertingAuthorization class --- .../alerting_authorization.test.ts | 44 ++++++- .../authorization/alerting_authorization.ts | 119 ++++++++++-------- .../tests/alerting/backfill/schedule.ts | 1 + 3 files changed, 111 insertions(+), 53 deletions(-) diff --git a/x-pack/plugins/alerting/server/authorization/alerting_authorization.test.ts b/x-pack/plugins/alerting/server/authorization/alerting_authorization.test.ts index c3245ce6cb5445..b178d65070478e 100644 --- a/x-pack/plugins/alerting/server/authorization/alerting_authorization.test.ts +++ b/x-pack/plugins/alerting/server/authorization/alerting_authorization.test.ts @@ -5,6 +5,7 @@ * 2.0. */ +import Boom from '@hapi/boom'; import { KueryNode, toKqlExpression } from '@kbn/es-query'; import { KibanaRequest } from '@kbn/core/server'; import { ruleTypeRegistryMock } from '../rule_type_registry.mock'; @@ -356,7 +357,7 @@ describe('AlertingAuthorization', () => { authorization: securityStart.authz, }); - // @ts-expect-error: allRegisteredConsumers is a private method of the auth class + // @ts-expect-error: ruleTypesConsumersMap is a private method of the auth class expect(auth.ruleTypesConsumersMap).toMatchInlineSnapshot(` Map { "rule-type-1" => Set { @@ -374,7 +375,7 @@ describe('AlertingAuthorization', () => { `); }); - it('throws an error when a failure occurs', async () => { + it('throws an error when a generic error occurs', async () => { expect.assertions(1); getSpace.mockRejectedValue(new Error('Error')); @@ -390,6 +391,45 @@ describe('AlertingAuthorization', () => { await expect(authPromise).rejects.toThrow(); }); + + it('construct the AlertingAuthorization with empty features if the error is boom and 403', async () => { + getSpace.mockRejectedValue( + new Boom.Boom('Server error', { statusCode: 403, message: 'my error message' }) + ); + + const auth = await AlertingAuthorization.create({ + request, + ruleTypeRegistry, + getSpaceId, + features, + getSpace, + authorization: securityStart.authz, + }); + + // @ts-expect-error: allRegisteredConsumers is a private method of the auth class + expect(auth.ruleTypesConsumersMap).toMatchInlineSnapshot(`Map {}`); + // @ts-expect-error: allRegisteredConsumers is a private method of the auth class + expect(auth.allRegisteredConsumers).toMatchInlineSnapshot(`Set {}`); + }); + + it('throws an error if the error is boom but not 403', async () => { + expect.assertions(1); + + getSpace.mockRejectedValue( + new Boom.Boom('Server error', { statusCode: 400, message: 'my error message' }) + ); + + const authPromise = AlertingAuthorization.create({ + request, + ruleTypeRegistry, + getSpaceId, + features, + getSpace, + authorization: securityStart.authz, + }); + + await expect(authPromise).rejects.toThrow(); + }); }); describe('ensureAuthorized', () => { diff --git a/x-pack/plugins/alerting/server/authorization/alerting_authorization.ts b/x-pack/plugins/alerting/server/authorization/alerting_authorization.ts index c15583430fe7c6..c7a1de650d04fa 100644 --- a/x-pack/plugins/alerting/server/authorization/alerting_authorization.ts +++ b/x-pack/plugins/alerting/server/authorization/alerting_authorization.ts @@ -93,63 +93,80 @@ export class AlertingAuthorization { authorization, ruleTypeRegistry, }: CreateOptions): Promise { + const allRegisteredConsumers = new Set(); + const ruleTypesConsumersMap = new Map>(); + let maybeSpace; + try { - const maybeSpace = await getSpace(request); - const disabledFeatures = new Set(maybeSpace?.disabledFeatures ?? []); - const featuresWithAlertingConfigured = features.getKibanaFeatures().filter( - ({ id, alerting }) => - // ignore features which are disabled in the user's space - !disabledFeatures.has(id) && - // ignore features which don't grant privileges to alerting - Boolean(alerting?.length) - ); + maybeSpace = await getSpace(request); + } catch (error) { + if (Boom.isBoom(error) && error.output.statusCode === 403) { + return new AlertingAuthorization({ + request, + authorization, + getSpaceId, + ruleTypeRegistry, + allRegisteredConsumers, + ruleTypesConsumersMap, + }); + } - const allRegisteredConsumers = new Set(); - const ruleTypesConsumersMap = new Map>(); - - /** - * Each feature configures a set of rule types. Each - * rule type configures its valid consumers. For example, - * - * { id: 'my-feature-id-1', alerting: [{ ruleTypeId: 'my-rule-type', consumers: ['consumer-a', 'consumer-b'] }] } - * { id: 'my-feature-id-2', alerting: [{ ruleTypeId: 'my-rule-type-2', consumers: ['consumer-a', 'consumer-d'] }] } - * - * In this loop we iterate over all features and we construct: - * a) a set that contains all registered consumers and - * b) a map that contains all valid consumers per rule type. - * We remove duplicates in the process. For example, - * - * allRegisteredConsumers: Set(1) { 'consumer-a', 'consumer-b', 'consumer-d' } - * ruleTypesConsumersMap: Map(1) { - * 'my-rule-type' => Set(1) { 'consumer-a', 'consumer-b' } - * 'my-rule-type-2' => Set(1) { 'consumer-a', 'consumer-d' } - * } - */ - for (const feature of featuresWithAlertingConfigured) { - if (feature.alerting) { - for (const entry of feature.alerting) { - const consumers = ruleTypesConsumersMap.get(entry.ruleTypeId) ?? new Set(); - - entry.consumers.forEach((consumer) => { - consumers.add(consumer); - allRegisteredConsumers.add(consumer); - }); - ruleTypesConsumersMap.set(entry.ruleTypeId, consumers); - } - } + if (Boom.isBoom(error)) { + throw error; } - return new AlertingAuthorization({ - request, - authorization, - getSpaceId, - ruleTypeRegistry, - allRegisteredConsumers, - ruleTypesConsumersMap, - }); - } catch (error) { throw new Error(`Failed to create AlertingAuthorization class: ${error}`); } + + const disabledFeatures = new Set(maybeSpace?.disabledFeatures ?? []); + const featuresWithAlertingConfigured = features.getKibanaFeatures().filter( + ({ id, alerting }) => + // ignore features which are disabled in the user's space + !disabledFeatures.has(id) && + // ignore features which don't grant privileges to alerting + Boolean(alerting?.length) + ); + + /** + * Each feature configures a set of rule types. Each + * rule type configures its valid consumers. For example, + * + * { id: 'my-feature-id-1', alerting: [{ ruleTypeId: 'my-rule-type', consumers: ['consumer-a', 'consumer-b'] }] } + * { id: 'my-feature-id-2', alerting: [{ ruleTypeId: 'my-rule-type-2', consumers: ['consumer-a', 'consumer-d'] }] } + * + * In this loop we iterate over all features and we construct: + * a) a set that contains all registered consumers and + * b) a map that contains all valid consumers per rule type. + * We remove duplicates in the process. For example, + * + * allRegisteredConsumers: Set(1) { 'consumer-a', 'consumer-b', 'consumer-d' } + * ruleTypesConsumersMap: Map(1) { + * 'my-rule-type' => Set(1) { 'consumer-a', 'consumer-b' } + * 'my-rule-type-2' => Set(1) { 'consumer-a', 'consumer-d' } + * } + */ + for (const feature of featuresWithAlertingConfigured) { + if (feature.alerting) { + for (const entry of feature.alerting) { + const consumers = ruleTypesConsumersMap.get(entry.ruleTypeId) ?? new Set(); + + entry.consumers.forEach((consumer) => { + consumers.add(consumer); + allRegisteredConsumers.add(consumer); + }); + ruleTypesConsumersMap.set(entry.ruleTypeId, consumers); + } + } + } + + return new AlertingAuthorization({ + request, + authorization, + getSpaceId, + ruleTypeRegistry, + allRegisteredConsumers, + ruleTypesConsumersMap, + }); } private shouldCheckAuthorization(): boolean { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/backfill/schedule.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/backfill/schedule.ts index edd3d8d2ae0721..07846d0b259841 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/backfill/schedule.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/backfill/schedule.ts @@ -127,6 +127,7 @@ export default function scheduleBackfillTests({ getService }: FtrProviderContext username: user.username, password: user.password, }; + it('should handle scheduling backfill job requests appropriately', async () => { const defaultStart = moment().utc().startOf('day').subtract(7, 'days').toISOString(); const defaultEnd = moment().utc().startOf('day').subtract(1, 'day').toISOString(); From 291b016aa12212c90761efa6adec188393349284 Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Sat, 20 Jul 2024 11:45:32 +0300 Subject: [PATCH 028/106] Fix types with rule client --- .../observability_threshold_schema.ts | 89 + .../rule/methods/create/create_rule.ts | 6 + .../authorization/alerting_authorization.ts | 4 +- .../server/routes/_mock_handler_arguments.ts | 2 +- .../task_runner/ad_hoc_task_runner.test.ts | 2 +- .../server/task_runner/task_runner.test.ts | 2 +- .../task_runner_alerts_client.test.ts | 2 +- .../task_runner/task_runner_cancel.test.ts | 2 +- .../task_runner/task_runner_factory.test.ts | 2 +- .../lib/cluster/get_clusters_from_request.ts | 38 +- x-pack/plugins/monitoring/server/plugin.ts | 2 +- .../server/routes/api/v1/alerts/enable.ts | 4 +- .../server/routes/api/v1/alerts/status.ts | 2 +- x-pack/plugins/monitoring/server/types.ts | 21 +- .../apm/server/routes/typings.ts | 6 +- .../apm/server/types.ts | 6 +- .../observability/server/plugin.ts | 6 +- .../server/routes/register_routes.ts | 2 +- .../server/routes/types.ts | 2 +- .../default_alerts/default_alert_service.ts | 6 +- .../routes/monitors/monitors_details.ts | 2 +- .../register_transform_health_rule_type.ts | 8 +- .../api/transforms_all/route_handler.ts | 5 +- .../group1/tests/alerting/create.ts | 9 +- .../group2/tests/alerting/mute_all.ts | 6 +- .../platform_security/authorization.ts | 5337 +++++++++++++++++ 26 files changed, 5495 insertions(+), 78 deletions(-) create mode 100644 packages/kbn-alerts-as-data-utils/src/schemas/generated/observability_threshold_schema.ts diff --git a/packages/kbn-alerts-as-data-utils/src/schemas/generated/observability_threshold_schema.ts b/packages/kbn-alerts-as-data-utils/src/schemas/generated/observability_threshold_schema.ts new file mode 100644 index 00000000000000..074ec11b45e3af --- /dev/null +++ b/packages/kbn-alerts-as-data-utils/src/schemas/generated/observability_threshold_schema.ts @@ -0,0 +1,89 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ +// ---------------------------------- WARNING ---------------------------------- +// this file was generated, and should not be edited by hand +// ---------------------------------- WARNING ---------------------------------- +import * as rt from 'io-ts'; +import { Either } from 'fp-ts/lib/Either'; +import { AlertSchema } from './alert_schema'; +import { EcsSchema } from './ecs_schema'; +const ISO_DATE_PATTERN = /^d{4}-d{2}-d{2}Td{2}:d{2}:d{2}.d{3}Z$/; +export const IsoDateString = new rt.Type( + 'IsoDateString', + rt.string.is, + (input, context): Either => { + if (typeof input === 'string' && ISO_DATE_PATTERN.test(input)) { + return rt.success(input); + } else { + return rt.failure(input, context); + } + }, + rt.identity +); +export type IsoDateStringC = typeof IsoDateString; +export const schemaUnknown = rt.unknown; +export const schemaUnknownArray = rt.array(rt.unknown); +export const schemaString = rt.string; +export const schemaStringArray = rt.array(schemaString); +export const schemaNumber = rt.number; +export const schemaNumberArray = rt.array(schemaNumber); +export const schemaDate = rt.union([IsoDateString, schemaNumber]); +export const schemaDateArray = rt.array(schemaDate); +export const schemaDateRange = rt.partial({ + gte: schemaDate, + lte: schemaDate, +}); +export const schemaDateRangeArray = rt.array(schemaDateRange); +export const schemaStringOrNumber = rt.union([schemaString, schemaNumber]); +export const schemaStringOrNumberArray = rt.array(schemaStringOrNumber); +export const schemaBoolean = rt.boolean; +export const schemaBooleanArray = rt.array(schemaBoolean); +const schemaGeoPointCoords = rt.type({ + type: schemaString, + coordinates: schemaNumberArray, +}); +const schemaGeoPointString = schemaString; +const schemaGeoPointLatLon = rt.type({ + lat: schemaNumber, + lon: schemaNumber, +}); +const schemaGeoPointLocation = rt.type({ + location: schemaNumberArray, +}); +const schemaGeoPointLocationString = rt.type({ + location: schemaString, +}); +export const schemaGeoPoint = rt.union([ + schemaGeoPointCoords, + schemaGeoPointString, + schemaGeoPointLatLon, + schemaGeoPointLocation, + schemaGeoPointLocationString, +]); +export const schemaGeoPointArray = rt.array(schemaGeoPoint); +// prettier-ignore +const ObservabilityThresholdAlertRequired = rt.type({ +}); +// prettier-ignore +const ObservabilityThresholdAlertOptional = rt.partial({ + 'kibana.alert.context': schemaUnknown, + 'kibana.alert.evaluation.threshold': schemaStringOrNumber, + 'kibana.alert.evaluation.value': schemaStringOrNumber, + 'kibana.alert.evaluation.values': schemaStringOrNumberArray, + 'kibana.alert.group': rt.array( + rt.partial({ + field: schemaStringArray, + value: schemaStringArray, + }) + ), +}); + +// prettier-ignore +export const ObservabilityThresholdAlertSchema = rt.intersection([ObservabilityThresholdAlertRequired, ObservabilityThresholdAlertOptional, AlertSchema, EcsSchema]); +// prettier-ignore +export type ObservabilityThresholdAlert = rt.TypeOf; diff --git a/x-pack/plugins/alerting/server/application/rule/methods/create/create_rule.ts b/x-pack/plugins/alerting/server/application/rule/methods/create/create_rule.ts index d1b41de9219523..11dfbb02828a7c 100644 --- a/x-pack/plugins/alerting/server/application/rule/methods/create/create_rule.ts +++ b/x-pack/plugins/alerting/server/application/rule/methods/create/create_rule.ts @@ -78,6 +78,12 @@ export async function createRule( throw Boom.badRequest(`Error validating create data - ${error.message}`); } + /** + * ruleTypeRegistry.get will throw a 400 (Bad request) + * error if the rule type is not registered. + */ + context.ruleTypeRegistry.get(data.alertTypeId); + let validationPayload: ValidateScheduleLimitResult = null; if (data.enabled) { validationPayload = await validateScheduleLimit({ diff --git a/x-pack/plugins/alerting/server/authorization/alerting_authorization.ts b/x-pack/plugins/alerting/server/authorization/alerting_authorization.ts index c7a1de650d04fa..68e7e9d24c4627 100644 --- a/x-pack/plugins/alerting/server/authorization/alerting_authorization.ts +++ b/x-pack/plugins/alerting/server/authorization/alerting_authorization.ts @@ -483,10 +483,10 @@ function getConsumersWithPrivileges( } function getUnauthorizedMessage( - alertTypeId: string, + ruleTypeId: string, scope: string, operation: string, entity: string ): string { - return `Unauthorized by "${scope}" to ${operation} "${alertTypeId}" ${entity}`; + return `Unauthorized by "${scope}" to ${operation} "${ruleTypeId}" ${entity}`; } diff --git a/x-pack/plugins/alerting/server/routes/_mock_handler_arguments.ts b/x-pack/plugins/alerting/server/routes/_mock_handler_arguments.ts index cab10e242cdad6..f72da4bb04e324 100644 --- a/x-pack/plugins/alerting/server/routes/_mock_handler_arguments.ts +++ b/x-pack/plugins/alerting/server/routes/_mock_handler_arguments.ts @@ -56,7 +56,7 @@ export function mockHandlerArguments( alerting: { listTypes, getRulesClient() { - return rulesClient || rulesClientMock.create(); + return Promise.resolve(rulesClient || rulesClientMock.create()); }, getRulesSettingsClient() { return rulesSettingsClient || rulesSettingsClientMock.create(); diff --git a/x-pack/plugins/alerting/server/task_runner/ad_hoc_task_runner.test.ts b/x-pack/plugins/alerting/server/task_runner/ad_hoc_task_runner.test.ts index 84181bb512a789..0eaaf3229ac60a 100644 --- a/x-pack/plugins/alerting/server/task_runner/ad_hoc_task_runner.test.ts +++ b/x-pack/plugins/alerting/server/task_runner/ad_hoc_task_runner.test.ts @@ -167,7 +167,7 @@ const taskRunnerFactoryInitializerParams: TaskRunnerFactoryInitializerParamsType eventLogger: eventLoggerMock.create(), executionContext: executionContextServiceMock.createInternalStartContract(), getMaintenanceWindowClientWithRequest: jest.fn().mockReturnValue(maintenanceWindowClient), - getRulesClientWithRequest: jest.fn().mockReturnValue(rulesClient), + getRulesClientWithRequest: jest.fn().mockResolvedValue(rulesClient), getRulesSettingsClientWithRequest: jest.fn().mockReturnValue(rulesSettingsClientMock.create()), kibanaBaseUrl: 'https://localhost:5601', logger, diff --git a/x-pack/plugins/alerting/server/task_runner/task_runner.test.ts b/x-pack/plugins/alerting/server/task_runner/task_runner.test.ts index e102bb23c8386f..f265e435208d6e 100644 --- a/x-pack/plugins/alerting/server/task_runner/task_runner.test.ts +++ b/x-pack/plugins/alerting/server/task_runner/task_runner.test.ts @@ -172,7 +172,7 @@ describe('Task Runner', () => { uiSettings: uiSettingsService, elasticsearch: elasticsearchService, actionsPlugin: actionsMock.createStart(), - getRulesClientWithRequest: jest.fn().mockReturnValue(rulesClient), + getRulesClientWithRequest: jest.fn().mockResolvedValue(rulesClient), encryptedSavedObjectsClient, logger, backfillClient, diff --git a/x-pack/plugins/alerting/server/task_runner/task_runner_alerts_client.test.ts b/x-pack/plugins/alerting/server/task_runner/task_runner_alerts_client.test.ts index a36e340a4a2595..c7e22c9db128f4 100644 --- a/x-pack/plugins/alerting/server/task_runner/task_runner_alerts_client.test.ts +++ b/x-pack/plugins/alerting/server/task_runner/task_runner_alerts_client.test.ts @@ -195,7 +195,7 @@ describe('Task Runner', () => { uiSettings: uiSettingsService, elasticsearch: elasticsearchService, actionsPlugin: actionsMock.createStart(), - getRulesClientWithRequest: jest.fn().mockReturnValue(rulesClient), + getRulesClientWithRequest: jest.fn().mockResolvedValue(rulesClient), encryptedSavedObjectsClient, logger, executionContext: executionContextServiceMock.createInternalStartContract(), diff --git a/x-pack/plugins/alerting/server/task_runner/task_runner_cancel.test.ts b/x-pack/plugins/alerting/server/task_runner/task_runner_cancel.test.ts index 000edf54dda3dc..967cd5d11db529 100644 --- a/x-pack/plugins/alerting/server/task_runner/task_runner_cancel.test.ts +++ b/x-pack/plugins/alerting/server/task_runner/task_runner_cancel.test.ts @@ -131,7 +131,7 @@ describe('Task Runner Cancel', () => { uiSettings: uiSettingsService, elasticsearch: elasticsearchService, actionsPlugin: actionsMock.createStart(), - getRulesClientWithRequest: jest.fn().mockReturnValue(rulesClient), + getRulesClientWithRequest: jest.fn().mockResolvedValue(rulesClient), encryptedSavedObjectsClient, logger, executionContext: executionContextServiceMock.createInternalStartContract(), diff --git a/x-pack/plugins/alerting/server/task_runner/task_runner_factory.test.ts b/x-pack/plugins/alerting/server/task_runner/task_runner_factory.test.ts index a29d9f3c0ad916..d864cfd0839f57 100644 --- a/x-pack/plugins/alerting/server/task_runner/task_runner_factory.test.ts +++ b/x-pack/plugins/alerting/server/task_runner/task_runner_factory.test.ts @@ -110,7 +110,7 @@ describe('Task Runner Factory', () => { share: {} as SharePluginStart, uiSettings: uiSettingsService, elasticsearch: elasticsearchService, - getRulesClientWithRequest: jest.fn().mockReturnValue(rulesClient), + getRulesClientWithRequest: jest.fn().mockResolvedValue(rulesClient), actionsPlugin: actionsMock.createStart(), encryptedSavedObjectsClient: encryptedSavedObjectsPlugin.getClient(), logger: loggingSystemMock.create().get(), diff --git a/x-pack/plugins/monitoring/server/lib/cluster/get_clusters_from_request.ts b/x-pack/plugins/monitoring/server/lib/cluster/get_clusters_from_request.ts index 6f082dcdb97ac0..5200d0717c3f26 100644 --- a/x-pack/plugins/monitoring/server/lib/cluster/get_clusters_from_request.ts +++ b/x-pack/plugins/monitoring/server/lib/cluster/get_clusters_from_request.ts @@ -123,25 +123,19 @@ export async function getClustersFromRequest( // update clusters with license check results const getSupportedClusters = flagSupportedClusters(req, CCS_REMOTE_PATTERN); clusters = await getSupportedClusters(clusters); + clusters = initializeClusters(clusters); // add alerts data if (isInCodePath(codePaths, [CODE_PATH_ALERTS])) { - const rulesClient = req.getRulesClient(); - const alertStatus = await fetchStatus( - rulesClient, - undefined, - clusters.map((cluster) => get(cluster, 'elasticsearch.cluster.id', cluster.cluster_uuid)) + const rulesClient = await req.getRulesClient(); + const clustersIds = clusters.map((cluster) => + get(cluster, 'elasticsearch.cluster.id', cluster.cluster_uuid) ); - for (const cluster of clusters) { - if (!rulesClient) { - cluster.alerts = { - list: {}, - alertsMeta: { - enabled: false, - }, - }; - } else { + if (rulesClient) { + const alertStatus = await fetchStatus(rulesClient, undefined, clustersIds); + + for (const cluster of clusters) { try { cluster.alerts = { list: Object.keys(alertStatus).reduce((acc, ruleTypeName) => { @@ -163,12 +157,6 @@ export async function getClustersFromRequest( req.logger.warn( `Unable to fetch alert status because '${err.message}'. Alerts may not properly show up in the UI.` ); - cluster.alerts = { - list: {}, - alertsMeta: { - enabled: true, - }, - }; } } } @@ -284,3 +272,13 @@ export async function getClustersFromRequest( return getClustersSummary(req.server, clusters as EnhancedClusters[], kibanaUuid, isCcrEnabled); } + +const initializeClusters = (clusters: Cluster[]): Cluster[] => { + return clusters.map((cluster) => ({ + ...cluster, + list: {}, + alertsMeta: { + enabled: false, + }, + })); +}; diff --git a/x-pack/plugins/monitoring/server/plugin.ts b/x-pack/plugins/monitoring/server/plugin.ts index 777fe157bb841f..376debd9bb01f2 100644 --- a/x-pack/plugins/monitoring/server/plugin.ts +++ b/x-pack/plugins/monitoring/server/plugin.ts @@ -341,7 +341,7 @@ export class MonitoringPlugin payload: req.body, getKibanaStatsCollector: () => this.legacyShimDependencies.kibanaStatsCollector, getUiSettingsService: () => coreContext.uiSettings.client, - getActionTypeRegistry: () => actionContext?.listTypes(), + getActionTypeRegistry: () => actionContext?.listTypes() ?? [], getRulesClient: () => { try { return plugins.alerting.getRulesClientWithRequest(req); diff --git a/x-pack/plugins/monitoring/server/routes/api/v1/alerts/enable.ts b/x-pack/plugins/monitoring/server/routes/api/v1/alerts/enable.ts index 8b919fd1f86eae..593f3c9b2b4ab8 100644 --- a/x-pack/plugins/monitoring/server/routes/api/v1/alerts/enable.ts +++ b/x-pack/plugins/monitoring/server/routes/api/v1/alerts/enable.ts @@ -30,6 +30,7 @@ export function enableAlertsRoute(server: MonitoringCore, npRoute: RouteDependen const actionContext = await context.actions; const alerts = RulesFactory.getAll(); + if (alerts.length) { const { isSufficientlySecure, hasPermanentEncryptionKey } = npRoute.alerting ?.getSecurityHealth @@ -49,9 +50,10 @@ export function enableAlertsRoute(server: MonitoringCore, npRoute: RouteDependen } } - const rulesClient = alertingContext?.getRulesClient(); + const rulesClient = await alertingContext?.getRulesClient(); const actionsClient = actionContext?.getActionsClient(); const types = actionContext?.listTypes(); + if (!rulesClient || !actionsClient || !types) { return response.ok({ body: undefined }); } diff --git a/x-pack/plugins/monitoring/server/routes/api/v1/alerts/status.ts b/x-pack/plugins/monitoring/server/routes/api/v1/alerts/status.ts index 64a0b7b92d85f0..a6c7d9b833ee12 100644 --- a/x-pack/plugins/monitoring/server/routes/api/v1/alerts/status.ts +++ b/x-pack/plugins/monitoring/server/routes/api/v1/alerts/status.ts @@ -36,7 +36,7 @@ export function alertStatusRoute(npRoute: RouteDependencies) { try { const { clusterUuid } = request.params; const { alertTypeIds, filters } = request.body; - const rulesClient = (await context.alerting)?.getRulesClient(); + const rulesClient = await (await context.alerting)?.getRulesClient(); if (!rulesClient) { return response.ok({ body: undefined }); } diff --git a/x-pack/plugins/monitoring/server/types.ts b/x-pack/plugins/monitoring/server/types.ts index 06c796764b5f76..37e6309d0a80c7 100644 --- a/x-pack/plugins/monitoring/server/types.ts +++ b/x-pack/plugins/monitoring/server/types.ts @@ -24,18 +24,15 @@ import type { } from '@kbn/actions-plugin/server'; import type { AlertingApiRequestHandlerContext } from '@kbn/alerting-plugin/server'; import type { RacApiRequestHandlerContext } from '@kbn/rule-registry-plugin/server'; -import { - PluginStartContract as AlertingPluginStartContract, - PluginSetupContract as AlertingPluginSetupContract, -} from '@kbn/alerting-plugin/server'; +import { AlertingServerSetup, AlertingServerStart } from '@kbn/alerting-plugin/server'; import { InfraPluginSetup, InfraRequestHandlerContext } from '@kbn/infra-plugin/server'; -import { PluginSetupContract as AlertingPluginSetup } from '@kbn/alerting-plugin/server'; import { LicensingPluginStart } from '@kbn/licensing-plugin/server'; import { FeaturesPluginSetup } from '@kbn/features-plugin/server'; import { EncryptedSavedObjectsPluginSetup } from '@kbn/encrypted-saved-objects-plugin/server'; import { CloudSetup } from '@kbn/cloud-plugin/server'; import { RouteConfig, RouteMethod, Headers } from '@kbn/core/server'; import { LogsSharedPluginSetup } from '@kbn/logs-shared-plugin/server'; +import { ActionTypeRegistry } from '@kbn/actions-plugin/server/action_type_registry'; import { ElasticsearchModifiedSource } from '../common/types/es'; import { RulesByType } from '../common/types/alerts'; import { configSchema, MonitoringConfig } from './config'; @@ -54,7 +51,7 @@ export interface PluginsSetup { encryptedSavedObjects?: EncryptedSavedObjectsPluginSetup; usageCollection?: UsageCollectionSetup; features: FeaturesPluginSetup; - alerting?: AlertingPluginSetupContract; + alerting?: AlertingServerSetup; infra: InfraPluginSetup; cloud?: CloudSetup; logsShared: LogsSharedPluginSetup; @@ -68,7 +65,7 @@ export type RequestHandlerContextMonitoringPlugin = CustomRequestHandlerContext< }>; export interface PluginsStart { - alerting: AlertingPluginStartContract; + alerting: AlertingServerStart; actions: ActionsPluginsStartContact; licensing: LicensingPluginStart; } @@ -78,7 +75,7 @@ export interface RouteDependencies { router: IRouter; licenseService: MonitoringLicenseService; encryptedSavedObjects?: EncryptedSavedObjectsPluginSetup; - alerting?: AlertingPluginSetup; + alerting?: AlertingServerSetup; logger: Logger; } @@ -129,9 +126,11 @@ export interface LegacyRequest { headers: Headers; getKibanaStatsCollector: () => any; getUiSettingsService: () => any; - getActionTypeRegistry: () => any; - getRulesClient: () => any; - getActionsClient: () => any; + getActionTypeRegistry: () => ReturnType; + getRulesClient: () => ReturnType | null; + getActionsClient: () => ReturnType< + ActionsPluginsStartContact['getActionsClientWithRequest'] + > | null; server: LegacyServer; } diff --git a/x-pack/plugins/observability_solution/apm/server/routes/typings.ts b/x-pack/plugins/observability_solution/apm/server/routes/typings.ts index 8ee9a3849a6fb0..99ee98122a9d0e 100644 --- a/x-pack/plugins/observability_solution/apm/server/routes/typings.ts +++ b/x-pack/plugins/observability_solution/apm/server/routes/typings.ts @@ -17,14 +17,12 @@ import type { import type { RacApiRequestHandlerContext } from '@kbn/rule-registry-plugin/server'; import type { LicensingApiRequestHandlerContext } from '@kbn/licensing-plugin/server'; import type { UsageCollectionSetup } from '@kbn/usage-collection-plugin/server'; -import type { RulesClientApi } from '@kbn/alerting-plugin/server/types'; +import { RulesClientApi } from '@kbn/alerting-plugin/server/types'; export type ApmPluginRequestHandlerContext = CustomRequestHandlerContext<{ licensing: Pick; alerting: { - // Pick is a superset of this - // and incompatible with the start contract from the alerting plugin - getRulesClient: () => RulesClientApi; + getRulesClient: () => Promise; }; rac: Pick; }>; diff --git a/x-pack/plugins/observability_solution/apm/server/types.ts b/x-pack/plugins/observability_solution/apm/server/types.ts index 84e0d5462c43b6..e99860b9d441f3 100644 --- a/x-pack/plugins/observability_solution/apm/server/types.ts +++ b/x-pack/plugins/observability_solution/apm/server/types.ts @@ -24,7 +24,7 @@ import { SpacesPluginSetup, SpacesPluginStart } from '@kbn/spaces-plugin/server' import { HomeServerPluginSetup, HomeServerPluginStart } from '@kbn/home-plugin/server'; import { UsageCollectionSetup } from '@kbn/usage-collection-plugin/server'; import { ActionsPlugin } from '@kbn/actions-plugin/server'; -import { AlertingPlugin } from '@kbn/alerting-plugin/server'; +import type { AlertingServerSetup, AlertingServerStart } from '@kbn/alerting-plugin/server'; import { CloudSetup } from '@kbn/cloud-plugin/server'; import { FeaturesPluginSetup, FeaturesPluginStart } from '@kbn/features-plugin/server'; import { LicensingPluginSetup, LicensingPluginStart } from '@kbn/licensing-plugin/server'; @@ -78,7 +78,7 @@ export interface APMPluginSetupDependencies { observabilityAIAssistant?: ObservabilityAIAssistantServerSetup; // optional dependencies actions?: ActionsPlugin['setup']; - alerting?: AlertingPlugin['setup']; + alerting?: AlertingServerSetup; cloud?: CloudSetup; fleet?: FleetPluginSetup; home?: HomeServerPluginSetup; @@ -105,7 +105,7 @@ export interface APMPluginStartDependencies { observabilityAIAssistant?: ObservabilityAIAssistantServerStart; // optional dependencies actions?: ActionsPlugin['start']; - alerting?: AlertingPlugin['start']; + alerting?: AlertingServerStart; cloud?: undefined; fleet?: FleetPluginStart; home?: HomeServerPluginStart; diff --git a/x-pack/plugins/observability_solution/observability/server/plugin.ts b/x-pack/plugins/observability_solution/observability/server/plugin.ts index 29397a81f487ca..93b141cc8f209e 100644 --- a/x-pack/plugins/observability_solution/observability/server/plugin.ts +++ b/x-pack/plugins/observability_solution/observability/server/plugin.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { PluginSetupContract, PluginStartContract } from '@kbn/alerting-plugin/server'; +import { AlertingServerSetup, AlertingServerStart } from '@kbn/alerting-plugin/server'; import { createUICapabilities as createCasesUICapabilities, getApiTags as getCasesApiTags, @@ -60,7 +60,7 @@ import { uiSettings } from './ui_settings'; export type ObservabilityPluginSetup = ReturnType; interface PluginSetup { - alerting: PluginSetupContract; + alerting: AlertingServerSetup; features: FeaturesPluginSetup; guidedOnboarding?: GuidedOnboardingPluginSetup; ruleRegistry: RuleRegistryPluginSetupContract; @@ -71,7 +71,7 @@ interface PluginSetup { } interface PluginStart { - alerting: PluginStartContract; + alerting: AlertingServerStart; spaces?: SpacesPluginStart; dataViews: DataViewsServerPluginStart; } diff --git a/x-pack/plugins/observability_solution/observability/server/routes/register_routes.ts b/x-pack/plugins/observability_solution/observability/server/routes/register_routes.ts index f0f41a70bec811..b62dae8465ea9a 100644 --- a/x-pack/plugins/observability_solution/observability/server/routes/register_routes.ts +++ b/x-pack/plugins/observability_solution/observability/server/routes/register_routes.ts @@ -42,7 +42,7 @@ export interface RegisterRoutesDependencies { assistant: { alertDetailsContextualInsightsService: AlertDetailsContextualInsightsService; }; - getRulesClientWithRequest: (request: KibanaRequest) => RulesClientApi; + getRulesClientWithRequest: (request: KibanaRequest) => Promise; } export function registerRoutes({ config, repository, core, logger, dependencies }: RegisterRoutes) { diff --git a/x-pack/plugins/observability_solution/observability_ai_assistant/server/routes/types.ts b/x-pack/plugins/observability_solution/observability_ai_assistant/server/routes/types.ts index c0b37b7142a83a..a2e33a1a81725d 100644 --- a/x-pack/plugins/observability_solution/observability_ai_assistant/server/routes/types.ts +++ b/x-pack/plugins/observability_solution/observability_ai_assistant/server/routes/types.ts @@ -29,7 +29,7 @@ export type ObservabilityAIAssistantRequestHandlerContext = Omit< // these two are here for compatibility with APM functions rac: Pick; alerting: { - getRulesClient: () => RulesClientApi; + getRulesClient: () => Promise; }; }>, 'core' | 'resolve' diff --git a/x-pack/plugins/observability_solution/synthetics/server/routes/default_alerts/default_alert_service.ts b/x-pack/plugins/observability_solution/synthetics/server/routes/default_alerts/default_alert_service.ts index 38606b4d2865f1..f065451da9e9ef 100644 --- a/x-pack/plugins/observability_solution/synthetics/server/routes/default_alerts/default_alert_service.ts +++ b/x-pack/plugins/observability_solution/synthetics/server/routes/default_alerts/default_alert_service.ts @@ -72,7 +72,7 @@ export class DefaultAlertService { } async getExistingAlert(ruleType: DefaultRuleType) { - const rulesClient = (await this.context.alerting)?.getRulesClient(); + const rulesClient = await (await this.context.alerting)?.getRulesClient(); const { data } = await rulesClient.find({ options: { @@ -95,7 +95,7 @@ export class DefaultAlertService { } const actions = await this.getAlertActions(ruleType); - const rulesClient = (await this.context.alerting)?.getRulesClient(); + const rulesClient = await (await this.context.alerting)?.getRulesClient(); const { actions: actionsFromRules = [], systemActions = [], @@ -129,7 +129,7 @@ export class DefaultAlertService { } async updateDefaultAlert(ruleType: DefaultRuleType, name: string, interval: string) { - const rulesClient = (await this.context.alerting)?.getRulesClient(); + const rulesClient = await (await this.context.alerting)?.getRulesClient(); const alert = await this.getExistingAlert(ruleType); if (alert) { diff --git a/x-pack/plugins/observability_solution/uptime/server/legacy_uptime/routes/monitors/monitors_details.ts b/x-pack/plugins/observability_solution/uptime/server/legacy_uptime/routes/monitors/monitors_details.ts index 357d008c4b901d..9cfc38b8730ccd 100644 --- a/x-pack/plugins/observability_solution/uptime/server/legacy_uptime/routes/monitors/monitors_details.ts +++ b/x-pack/plugins/observability_solution/uptime/server/legacy_uptime/routes/monitors/monitors_details.ts @@ -23,7 +23,7 @@ export const createGetMonitorDetailsRoute: UMRestApiRouteFactory = (libs: UMServ handler: async ({ uptimeEsClient, context, request }): Promise => { const { monitorId, dateStart, dateEnd } = request.query; - const rulesClient = (await context.alerting)?.getRulesClient(); + const rulesClient = await (await context.alerting)?.getRulesClient(); return await libs.requests.getMonitorDetails({ uptimeEsClient, diff --git a/x-pack/plugins/transform/server/lib/alerting/transform_health_rule_type/register_transform_health_rule_type.ts b/x-pack/plugins/transform/server/lib/alerting/transform_health_rule_type/register_transform_health_rule_type.ts index ac04ff6a7662e7..1fe9c3cc593367 100644 --- a/x-pack/plugins/transform/server/lib/alerting/transform_health_rule_type/register_transform_health_rule_type.ts +++ b/x-pack/plugins/transform/server/lib/alerting/transform_health_rule_type/register_transform_health_rule_type.ts @@ -16,11 +16,7 @@ import type { RuleTypeState, } from '@kbn/alerting-plugin/common'; import { AlertsClientError } from '@kbn/alerting-plugin/server'; -import type { - PluginSetupContract as AlertingSetup, - IRuleTypeAlerts, - RuleType, -} from '@kbn/alerting-plugin/server'; +import type { AlertingServerSetup, IRuleTypeAlerts, RuleType } from '@kbn/alerting-plugin/server'; import type { FieldFormatsStart } from '@kbn/field-formats-plugin/server'; import type { TransformHealthAlert } from '@kbn/alerts-as-data-utils'; import { ALERT_REASON } from '@kbn/rule-data-utils'; @@ -74,7 +70,7 @@ export const TRANSFORM_ISSUE_DETECTED: ActionGroup = { interface RegisterParams { logger: Logger; - alerting: AlertingSetup; + alerting: AlertingServerSetup; getFieldFormatsStart: () => FieldFormatsStart; } diff --git a/x-pack/plugins/transform/server/routes/api/transforms_all/route_handler.ts b/x-pack/plugins/transform/server/routes/api/transforms_all/route_handler.ts index 8bbedd9faa023e..4bf9a03b64882d 100644 --- a/x-pack/plugins/transform/server/routes/api/transforms_all/route_handler.ts +++ b/x-pack/plugins/transform/server/routes/api/transforms_all/route_handler.ts @@ -28,10 +28,13 @@ export const routeHandler: RequestHandler< }); const alerting = await ctx.alerting; + if (alerting) { + const rulesClient = await alerting.getRulesClient(); + const transformHealthService = transformHealthServiceProvider({ esClient: esClient.asCurrentUser, - rulesClient: alerting.getRulesClient(), + rulesClient, }); // @ts-ignore diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/create.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/create.ts index 10359b53f03556..416d61a10b486f 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/create.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/create.ts @@ -253,18 +253,11 @@ export default function createAlertTests({ getService }: FtrProviderContext) { switch (scenario.id) { case 'no_kibana_privileges at space1': case 'space_1_all at space2': - expect(response.statusCode).to.eql(403); - expect(response.body).to.eql({ - error: 'Forbidden', - message: getUnauthorizedErrorMessage('create', 'test.noop', 'alerts'), - statusCode: 403, - }); - break; case 'global_read at space1': expect(response.statusCode).to.eql(403); expect(response.body).to.eql({ error: 'Forbidden', - message: getUnauthorizedErrorMessage('create', 'test.noop', 'alertsFixture'), + message: getUnauthorizedErrorMessage('create', 'test.noop', 'alerts'), statusCode: 403, }); break; diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/mute_all.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/mute_all.ts index c5be0877c89ff5..a9b6bf42e55a3c 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/mute_all.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/mute_all.ts @@ -252,11 +252,7 @@ export default function createMuteAlertTests({ getService }: FtrProviderContext) expect(response.statusCode).to.eql(403); expect(response.body).to.eql({ error: 'Forbidden', - message: getUnauthorizedErrorMessage( - 'muteAll', - 'test.restricted-noop', - 'alertsRestrictedFixture' - ), + message: getUnauthorizedErrorMessage('muteAll', 'test.restricted-noop', 'alerts'), statusCode: 403, }); break; diff --git a/x-pack/test_serverless/api_integration/test_suites/observability/platform_security/authorization.ts b/x-pack/test_serverless/api_integration/test_suites/observability/platform_security/authorization.ts index 0b1f665fa7f72b..847a08a2c2a060 100644 --- a/x-pack/test_serverless/api_integration/test_suites/observability/platform_security/authorization.ts +++ b/x-pack/test_serverless/api_integration/test_suites/observability/platform_security/authorization.ts @@ -44,6 +44,7 @@ export default function ({ getService }: FtrProviderContext) { const features = Object.fromEntries( Object.entries(body.features).filter(([key]) => compositeFeatureIds.includes(key)) ); + expectSnapshot(features).toMatchInline(` Object { "apm": Object { @@ -124,6 +125,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.error_rate/apm/rule/runSoon", "alerting:apm.error_rate/apm/rule/scheduleBackfill", "alerting:apm.error_rate/apm/rule/deleteBackfill", + "alerting:apm.error_rate/alerts/rule/get", + "alerting:apm.error_rate/alerts/rule/getRuleState", + "alerting:apm.error_rate/alerts/rule/getAlertSummary", + "alerting:apm.error_rate/alerts/rule/getExecutionLog", + "alerting:apm.error_rate/alerts/rule/getActionErrorLog", + "alerting:apm.error_rate/alerts/rule/find", + "alerting:apm.error_rate/alerts/rule/getRuleExecutionKPI", + "alerting:apm.error_rate/alerts/rule/getBackfill", + "alerting:apm.error_rate/alerts/rule/findBackfill", + "alerting:apm.error_rate/alerts/rule/create", + "alerting:apm.error_rate/alerts/rule/delete", + "alerting:apm.error_rate/alerts/rule/update", + "alerting:apm.error_rate/alerts/rule/updateApiKey", + "alerting:apm.error_rate/alerts/rule/enable", + "alerting:apm.error_rate/alerts/rule/disable", + "alerting:apm.error_rate/alerts/rule/muteAll", + "alerting:apm.error_rate/alerts/rule/unmuteAll", + "alerting:apm.error_rate/alerts/rule/muteAlert", + "alerting:apm.error_rate/alerts/rule/unmuteAlert", + "alerting:apm.error_rate/alerts/rule/snooze", + "alerting:apm.error_rate/alerts/rule/bulkEdit", + "alerting:apm.error_rate/alerts/rule/bulkDelete", + "alerting:apm.error_rate/alerts/rule/bulkEnable", + "alerting:apm.error_rate/alerts/rule/bulkDisable", + "alerting:apm.error_rate/alerts/rule/unsnooze", + "alerting:apm.error_rate/alerts/rule/runSoon", + "alerting:apm.error_rate/alerts/rule/scheduleBackfill", + "alerting:apm.error_rate/alerts/rule/deleteBackfill", "alerting:apm.transaction_error_rate/apm/rule/get", "alerting:apm.transaction_error_rate/apm/rule/getRuleState", "alerting:apm.transaction_error_rate/apm/rule/getAlertSummary", @@ -152,6 +181,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.transaction_error_rate/apm/rule/runSoon", "alerting:apm.transaction_error_rate/apm/rule/scheduleBackfill", "alerting:apm.transaction_error_rate/apm/rule/deleteBackfill", + "alerting:apm.transaction_error_rate/alerts/rule/get", + "alerting:apm.transaction_error_rate/alerts/rule/getRuleState", + "alerting:apm.transaction_error_rate/alerts/rule/getAlertSummary", + "alerting:apm.transaction_error_rate/alerts/rule/getExecutionLog", + "alerting:apm.transaction_error_rate/alerts/rule/getActionErrorLog", + "alerting:apm.transaction_error_rate/alerts/rule/find", + "alerting:apm.transaction_error_rate/alerts/rule/getRuleExecutionKPI", + "alerting:apm.transaction_error_rate/alerts/rule/getBackfill", + "alerting:apm.transaction_error_rate/alerts/rule/findBackfill", + "alerting:apm.transaction_error_rate/alerts/rule/create", + "alerting:apm.transaction_error_rate/alerts/rule/delete", + "alerting:apm.transaction_error_rate/alerts/rule/update", + "alerting:apm.transaction_error_rate/alerts/rule/updateApiKey", + "alerting:apm.transaction_error_rate/alerts/rule/enable", + "alerting:apm.transaction_error_rate/alerts/rule/disable", + "alerting:apm.transaction_error_rate/alerts/rule/muteAll", + "alerting:apm.transaction_error_rate/alerts/rule/unmuteAll", + "alerting:apm.transaction_error_rate/alerts/rule/muteAlert", + "alerting:apm.transaction_error_rate/alerts/rule/unmuteAlert", + "alerting:apm.transaction_error_rate/alerts/rule/snooze", + "alerting:apm.transaction_error_rate/alerts/rule/bulkEdit", + "alerting:apm.transaction_error_rate/alerts/rule/bulkDelete", + "alerting:apm.transaction_error_rate/alerts/rule/bulkEnable", + "alerting:apm.transaction_error_rate/alerts/rule/bulkDisable", + "alerting:apm.transaction_error_rate/alerts/rule/unsnooze", + "alerting:apm.transaction_error_rate/alerts/rule/runSoon", + "alerting:apm.transaction_error_rate/alerts/rule/scheduleBackfill", + "alerting:apm.transaction_error_rate/alerts/rule/deleteBackfill", "alerting:apm.transaction_duration/apm/rule/get", "alerting:apm.transaction_duration/apm/rule/getRuleState", "alerting:apm.transaction_duration/apm/rule/getAlertSummary", @@ -180,6 +237,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.transaction_duration/apm/rule/runSoon", "alerting:apm.transaction_duration/apm/rule/scheduleBackfill", "alerting:apm.transaction_duration/apm/rule/deleteBackfill", + "alerting:apm.transaction_duration/alerts/rule/get", + "alerting:apm.transaction_duration/alerts/rule/getRuleState", + "alerting:apm.transaction_duration/alerts/rule/getAlertSummary", + "alerting:apm.transaction_duration/alerts/rule/getExecutionLog", + "alerting:apm.transaction_duration/alerts/rule/getActionErrorLog", + "alerting:apm.transaction_duration/alerts/rule/find", + "alerting:apm.transaction_duration/alerts/rule/getRuleExecutionKPI", + "alerting:apm.transaction_duration/alerts/rule/getBackfill", + "alerting:apm.transaction_duration/alerts/rule/findBackfill", + "alerting:apm.transaction_duration/alerts/rule/create", + "alerting:apm.transaction_duration/alerts/rule/delete", + "alerting:apm.transaction_duration/alerts/rule/update", + "alerting:apm.transaction_duration/alerts/rule/updateApiKey", + "alerting:apm.transaction_duration/alerts/rule/enable", + "alerting:apm.transaction_duration/alerts/rule/disable", + "alerting:apm.transaction_duration/alerts/rule/muteAll", + "alerting:apm.transaction_duration/alerts/rule/unmuteAll", + "alerting:apm.transaction_duration/alerts/rule/muteAlert", + "alerting:apm.transaction_duration/alerts/rule/unmuteAlert", + "alerting:apm.transaction_duration/alerts/rule/snooze", + "alerting:apm.transaction_duration/alerts/rule/bulkEdit", + "alerting:apm.transaction_duration/alerts/rule/bulkDelete", + "alerting:apm.transaction_duration/alerts/rule/bulkEnable", + "alerting:apm.transaction_duration/alerts/rule/bulkDisable", + "alerting:apm.transaction_duration/alerts/rule/unsnooze", + "alerting:apm.transaction_duration/alerts/rule/runSoon", + "alerting:apm.transaction_duration/alerts/rule/scheduleBackfill", + "alerting:apm.transaction_duration/alerts/rule/deleteBackfill", "alerting:apm.anomaly/apm/rule/get", "alerting:apm.anomaly/apm/rule/getRuleState", "alerting:apm.anomaly/apm/rule/getAlertSummary", @@ -208,26 +293,74 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.anomaly/apm/rule/runSoon", "alerting:apm.anomaly/apm/rule/scheduleBackfill", "alerting:apm.anomaly/apm/rule/deleteBackfill", + "alerting:apm.anomaly/alerts/rule/get", + "alerting:apm.anomaly/alerts/rule/getRuleState", + "alerting:apm.anomaly/alerts/rule/getAlertSummary", + "alerting:apm.anomaly/alerts/rule/getExecutionLog", + "alerting:apm.anomaly/alerts/rule/getActionErrorLog", + "alerting:apm.anomaly/alerts/rule/find", + "alerting:apm.anomaly/alerts/rule/getRuleExecutionKPI", + "alerting:apm.anomaly/alerts/rule/getBackfill", + "alerting:apm.anomaly/alerts/rule/findBackfill", + "alerting:apm.anomaly/alerts/rule/create", + "alerting:apm.anomaly/alerts/rule/delete", + "alerting:apm.anomaly/alerts/rule/update", + "alerting:apm.anomaly/alerts/rule/updateApiKey", + "alerting:apm.anomaly/alerts/rule/enable", + "alerting:apm.anomaly/alerts/rule/disable", + "alerting:apm.anomaly/alerts/rule/muteAll", + "alerting:apm.anomaly/alerts/rule/unmuteAll", + "alerting:apm.anomaly/alerts/rule/muteAlert", + "alerting:apm.anomaly/alerts/rule/unmuteAlert", + "alerting:apm.anomaly/alerts/rule/snooze", + "alerting:apm.anomaly/alerts/rule/bulkEdit", + "alerting:apm.anomaly/alerts/rule/bulkDelete", + "alerting:apm.anomaly/alerts/rule/bulkEnable", + "alerting:apm.anomaly/alerts/rule/bulkDisable", + "alerting:apm.anomaly/alerts/rule/unsnooze", + "alerting:apm.anomaly/alerts/rule/runSoon", + "alerting:apm.anomaly/alerts/rule/scheduleBackfill", + "alerting:apm.anomaly/alerts/rule/deleteBackfill", "alerting:apm.error_rate/apm/alert/get", "alerting:apm.error_rate/apm/alert/find", "alerting:apm.error_rate/apm/alert/getAuthorizedAlertsIndices", "alerting:apm.error_rate/apm/alert/getAlertSummary", "alerting:apm.error_rate/apm/alert/update", + "alerting:apm.error_rate/alerts/alert/get", + "alerting:apm.error_rate/alerts/alert/find", + "alerting:apm.error_rate/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.error_rate/alerts/alert/getAlertSummary", + "alerting:apm.error_rate/alerts/alert/update", "alerting:apm.transaction_error_rate/apm/alert/get", "alerting:apm.transaction_error_rate/apm/alert/find", "alerting:apm.transaction_error_rate/apm/alert/getAuthorizedAlertsIndices", "alerting:apm.transaction_error_rate/apm/alert/getAlertSummary", "alerting:apm.transaction_error_rate/apm/alert/update", + "alerting:apm.transaction_error_rate/alerts/alert/get", + "alerting:apm.transaction_error_rate/alerts/alert/find", + "alerting:apm.transaction_error_rate/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.transaction_error_rate/alerts/alert/getAlertSummary", + "alerting:apm.transaction_error_rate/alerts/alert/update", "alerting:apm.transaction_duration/apm/alert/get", "alerting:apm.transaction_duration/apm/alert/find", "alerting:apm.transaction_duration/apm/alert/getAuthorizedAlertsIndices", "alerting:apm.transaction_duration/apm/alert/getAlertSummary", "alerting:apm.transaction_duration/apm/alert/update", + "alerting:apm.transaction_duration/alerts/alert/get", + "alerting:apm.transaction_duration/alerts/alert/find", + "alerting:apm.transaction_duration/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.transaction_duration/alerts/alert/getAlertSummary", + "alerting:apm.transaction_duration/alerts/alert/update", "alerting:apm.anomaly/apm/alert/get", "alerting:apm.anomaly/apm/alert/find", "alerting:apm.anomaly/apm/alert/getAuthorizedAlertsIndices", "alerting:apm.anomaly/apm/alert/getAlertSummary", "alerting:apm.anomaly/apm/alert/update", + "alerting:apm.anomaly/alerts/alert/get", + "alerting:apm.anomaly/alerts/alert/find", + "alerting:apm.anomaly/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.anomaly/alerts/alert/getAlertSummary", + "alerting:apm.anomaly/alerts/alert/update", "api:infra", "app:infra", "app:logs", @@ -290,6 +423,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:logs.alert.document.count/logs/rule/runSoon", "alerting:logs.alert.document.count/logs/rule/scheduleBackfill", "alerting:logs.alert.document.count/logs/rule/deleteBackfill", + "alerting:logs.alert.document.count/alerts/rule/get", + "alerting:logs.alert.document.count/alerts/rule/getRuleState", + "alerting:logs.alert.document.count/alerts/rule/getAlertSummary", + "alerting:logs.alert.document.count/alerts/rule/getExecutionLog", + "alerting:logs.alert.document.count/alerts/rule/getActionErrorLog", + "alerting:logs.alert.document.count/alerts/rule/find", + "alerting:logs.alert.document.count/alerts/rule/getRuleExecutionKPI", + "alerting:logs.alert.document.count/alerts/rule/getBackfill", + "alerting:logs.alert.document.count/alerts/rule/findBackfill", + "alerting:logs.alert.document.count/alerts/rule/create", + "alerting:logs.alert.document.count/alerts/rule/delete", + "alerting:logs.alert.document.count/alerts/rule/update", + "alerting:logs.alert.document.count/alerts/rule/updateApiKey", + "alerting:logs.alert.document.count/alerts/rule/enable", + "alerting:logs.alert.document.count/alerts/rule/disable", + "alerting:logs.alert.document.count/alerts/rule/muteAll", + "alerting:logs.alert.document.count/alerts/rule/unmuteAll", + "alerting:logs.alert.document.count/alerts/rule/muteAlert", + "alerting:logs.alert.document.count/alerts/rule/unmuteAlert", + "alerting:logs.alert.document.count/alerts/rule/snooze", + "alerting:logs.alert.document.count/alerts/rule/bulkEdit", + "alerting:logs.alert.document.count/alerts/rule/bulkDelete", + "alerting:logs.alert.document.count/alerts/rule/bulkEnable", + "alerting:logs.alert.document.count/alerts/rule/bulkDisable", + "alerting:logs.alert.document.count/alerts/rule/unsnooze", + "alerting:logs.alert.document.count/alerts/rule/runSoon", + "alerting:logs.alert.document.count/alerts/rule/scheduleBackfill", + "alerting:logs.alert.document.count/alerts/rule/deleteBackfill", "alerting:.es-query/logs/rule/get", "alerting:.es-query/logs/rule/getRuleState", "alerting:.es-query/logs/rule/getAlertSummary", @@ -318,6 +479,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:.es-query/logs/rule/runSoon", "alerting:.es-query/logs/rule/scheduleBackfill", "alerting:.es-query/logs/rule/deleteBackfill", + "alerting:.es-query/alerts/rule/get", + "alerting:.es-query/alerts/rule/getRuleState", + "alerting:.es-query/alerts/rule/getAlertSummary", + "alerting:.es-query/alerts/rule/getExecutionLog", + "alerting:.es-query/alerts/rule/getActionErrorLog", + "alerting:.es-query/alerts/rule/find", + "alerting:.es-query/alerts/rule/getRuleExecutionKPI", + "alerting:.es-query/alerts/rule/getBackfill", + "alerting:.es-query/alerts/rule/findBackfill", + "alerting:.es-query/alerts/rule/create", + "alerting:.es-query/alerts/rule/delete", + "alerting:.es-query/alerts/rule/update", + "alerting:.es-query/alerts/rule/updateApiKey", + "alerting:.es-query/alerts/rule/enable", + "alerting:.es-query/alerts/rule/disable", + "alerting:.es-query/alerts/rule/muteAll", + "alerting:.es-query/alerts/rule/unmuteAll", + "alerting:.es-query/alerts/rule/muteAlert", + "alerting:.es-query/alerts/rule/unmuteAlert", + "alerting:.es-query/alerts/rule/snooze", + "alerting:.es-query/alerts/rule/bulkEdit", + "alerting:.es-query/alerts/rule/bulkDelete", + "alerting:.es-query/alerts/rule/bulkEnable", + "alerting:.es-query/alerts/rule/bulkDisable", + "alerting:.es-query/alerts/rule/unsnooze", + "alerting:.es-query/alerts/rule/runSoon", + "alerting:.es-query/alerts/rule/scheduleBackfill", + "alerting:.es-query/alerts/rule/deleteBackfill", "alerting:observability.rules.custom_threshold/logs/rule/get", "alerting:observability.rules.custom_threshold/logs/rule/getRuleState", "alerting:observability.rules.custom_threshold/logs/rule/getAlertSummary", @@ -346,6 +535,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:observability.rules.custom_threshold/logs/rule/runSoon", "alerting:observability.rules.custom_threshold/logs/rule/scheduleBackfill", "alerting:observability.rules.custom_threshold/logs/rule/deleteBackfill", + "alerting:observability.rules.custom_threshold/alerts/rule/get", + "alerting:observability.rules.custom_threshold/alerts/rule/getRuleState", + "alerting:observability.rules.custom_threshold/alerts/rule/getAlertSummary", + "alerting:observability.rules.custom_threshold/alerts/rule/getExecutionLog", + "alerting:observability.rules.custom_threshold/alerts/rule/getActionErrorLog", + "alerting:observability.rules.custom_threshold/alerts/rule/find", + "alerting:observability.rules.custom_threshold/alerts/rule/getRuleExecutionKPI", + "alerting:observability.rules.custom_threshold/alerts/rule/getBackfill", + "alerting:observability.rules.custom_threshold/alerts/rule/findBackfill", + "alerting:observability.rules.custom_threshold/alerts/rule/create", + "alerting:observability.rules.custom_threshold/alerts/rule/delete", + "alerting:observability.rules.custom_threshold/alerts/rule/update", + "alerting:observability.rules.custom_threshold/alerts/rule/updateApiKey", + "alerting:observability.rules.custom_threshold/alerts/rule/enable", + "alerting:observability.rules.custom_threshold/alerts/rule/disable", + "alerting:observability.rules.custom_threshold/alerts/rule/muteAll", + "alerting:observability.rules.custom_threshold/alerts/rule/unmuteAll", + "alerting:observability.rules.custom_threshold/alerts/rule/muteAlert", + "alerting:observability.rules.custom_threshold/alerts/rule/unmuteAlert", + "alerting:observability.rules.custom_threshold/alerts/rule/snooze", + "alerting:observability.rules.custom_threshold/alerts/rule/bulkEdit", + "alerting:observability.rules.custom_threshold/alerts/rule/bulkDelete", + "alerting:observability.rules.custom_threshold/alerts/rule/bulkEnable", + "alerting:observability.rules.custom_threshold/alerts/rule/bulkDisable", + "alerting:observability.rules.custom_threshold/alerts/rule/unsnooze", + "alerting:observability.rules.custom_threshold/alerts/rule/runSoon", + "alerting:observability.rules.custom_threshold/alerts/rule/scheduleBackfill", + "alerting:observability.rules.custom_threshold/alerts/rule/deleteBackfill", "alerting:xpack.ml.anomaly_detection_alert/logs/rule/get", "alerting:xpack.ml.anomaly_detection_alert/logs/rule/getRuleState", "alerting:xpack.ml.anomaly_detection_alert/logs/rule/getAlertSummary", @@ -374,26 +591,74 @@ export default function ({ getService }: FtrProviderContext) { "alerting:xpack.ml.anomaly_detection_alert/logs/rule/runSoon", "alerting:xpack.ml.anomaly_detection_alert/logs/rule/scheduleBackfill", "alerting:xpack.ml.anomaly_detection_alert/logs/rule/deleteBackfill", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/get", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getRuleState", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getAlertSummary", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getExecutionLog", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getActionErrorLog", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/find", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getRuleExecutionKPI", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getBackfill", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/findBackfill", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/create", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/delete", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/update", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/updateApiKey", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/enable", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/disable", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/muteAll", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/unmuteAll", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/muteAlert", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/unmuteAlert", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/snooze", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/bulkEdit", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/bulkDelete", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/bulkEnable", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/bulkDisable", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/unsnooze", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/runSoon", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/scheduleBackfill", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/deleteBackfill", "alerting:logs.alert.document.count/logs/alert/get", "alerting:logs.alert.document.count/logs/alert/find", "alerting:logs.alert.document.count/logs/alert/getAuthorizedAlertsIndices", "alerting:logs.alert.document.count/logs/alert/getAlertSummary", "alerting:logs.alert.document.count/logs/alert/update", + "alerting:logs.alert.document.count/alerts/alert/get", + "alerting:logs.alert.document.count/alerts/alert/find", + "alerting:logs.alert.document.count/alerts/alert/getAuthorizedAlertsIndices", + "alerting:logs.alert.document.count/alerts/alert/getAlertSummary", + "alerting:logs.alert.document.count/alerts/alert/update", "alerting:.es-query/logs/alert/get", "alerting:.es-query/logs/alert/find", "alerting:.es-query/logs/alert/getAuthorizedAlertsIndices", "alerting:.es-query/logs/alert/getAlertSummary", "alerting:.es-query/logs/alert/update", + "alerting:.es-query/alerts/alert/get", + "alerting:.es-query/alerts/alert/find", + "alerting:.es-query/alerts/alert/getAuthorizedAlertsIndices", + "alerting:.es-query/alerts/alert/getAlertSummary", + "alerting:.es-query/alerts/alert/update", "alerting:observability.rules.custom_threshold/logs/alert/get", "alerting:observability.rules.custom_threshold/logs/alert/find", "alerting:observability.rules.custom_threshold/logs/alert/getAuthorizedAlertsIndices", "alerting:observability.rules.custom_threshold/logs/alert/getAlertSummary", "alerting:observability.rules.custom_threshold/logs/alert/update", + "alerting:observability.rules.custom_threshold/alerts/alert/get", + "alerting:observability.rules.custom_threshold/alerts/alert/find", + "alerting:observability.rules.custom_threshold/alerts/alert/getAuthorizedAlertsIndices", + "alerting:observability.rules.custom_threshold/alerts/alert/getAlertSummary", + "alerting:observability.rules.custom_threshold/alerts/alert/update", "alerting:xpack.ml.anomaly_detection_alert/logs/alert/get", "alerting:xpack.ml.anomaly_detection_alert/logs/alert/find", "alerting:xpack.ml.anomaly_detection_alert/logs/alert/getAuthorizedAlertsIndices", "alerting:xpack.ml.anomaly_detection_alert/logs/alert/getAlertSummary", "alerting:xpack.ml.anomaly_detection_alert/logs/alert/update", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/get", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/find", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/getAuthorizedAlertsIndices", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/getAlertSummary", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/update", "app:observability", "ui:catalogue/observability", "ui:navLinks/observability", @@ -427,6 +692,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:slo.rules.burnRate/observability/rule/runSoon", "alerting:slo.rules.burnRate/observability/rule/scheduleBackfill", "alerting:slo.rules.burnRate/observability/rule/deleteBackfill", + "alerting:slo.rules.burnRate/alerts/rule/get", + "alerting:slo.rules.burnRate/alerts/rule/getRuleState", + "alerting:slo.rules.burnRate/alerts/rule/getAlertSummary", + "alerting:slo.rules.burnRate/alerts/rule/getExecutionLog", + "alerting:slo.rules.burnRate/alerts/rule/getActionErrorLog", + "alerting:slo.rules.burnRate/alerts/rule/find", + "alerting:slo.rules.burnRate/alerts/rule/getRuleExecutionKPI", + "alerting:slo.rules.burnRate/alerts/rule/getBackfill", + "alerting:slo.rules.burnRate/alerts/rule/findBackfill", + "alerting:slo.rules.burnRate/alerts/rule/create", + "alerting:slo.rules.burnRate/alerts/rule/delete", + "alerting:slo.rules.burnRate/alerts/rule/update", + "alerting:slo.rules.burnRate/alerts/rule/updateApiKey", + "alerting:slo.rules.burnRate/alerts/rule/enable", + "alerting:slo.rules.burnRate/alerts/rule/disable", + "alerting:slo.rules.burnRate/alerts/rule/muteAll", + "alerting:slo.rules.burnRate/alerts/rule/unmuteAll", + "alerting:slo.rules.burnRate/alerts/rule/muteAlert", + "alerting:slo.rules.burnRate/alerts/rule/unmuteAlert", + "alerting:slo.rules.burnRate/alerts/rule/snooze", + "alerting:slo.rules.burnRate/alerts/rule/bulkEdit", + "alerting:slo.rules.burnRate/alerts/rule/bulkDelete", + "alerting:slo.rules.burnRate/alerts/rule/bulkEnable", + "alerting:slo.rules.burnRate/alerts/rule/bulkDisable", + "alerting:slo.rules.burnRate/alerts/rule/unsnooze", + "alerting:slo.rules.burnRate/alerts/rule/runSoon", + "alerting:slo.rules.burnRate/alerts/rule/scheduleBackfill", + "alerting:slo.rules.burnRate/alerts/rule/deleteBackfill", "alerting:observability.rules.custom_threshold/observability/rule/get", "alerting:observability.rules.custom_threshold/observability/rule/getRuleState", "alerting:observability.rules.custom_threshold/observability/rule/getAlertSummary", @@ -539,6 +832,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:metrics.alert.inventory.threshold/observability/rule/runSoon", "alerting:metrics.alert.inventory.threshold/observability/rule/scheduleBackfill", "alerting:metrics.alert.inventory.threshold/observability/rule/deleteBackfill", + "alerting:metrics.alert.inventory.threshold/alerts/rule/get", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getRuleState", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getAlertSummary", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getExecutionLog", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getActionErrorLog", + "alerting:metrics.alert.inventory.threshold/alerts/rule/find", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getRuleExecutionKPI", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getBackfill", + "alerting:metrics.alert.inventory.threshold/alerts/rule/findBackfill", + "alerting:metrics.alert.inventory.threshold/alerts/rule/create", + "alerting:metrics.alert.inventory.threshold/alerts/rule/delete", + "alerting:metrics.alert.inventory.threshold/alerts/rule/update", + "alerting:metrics.alert.inventory.threshold/alerts/rule/updateApiKey", + "alerting:metrics.alert.inventory.threshold/alerts/rule/enable", + "alerting:metrics.alert.inventory.threshold/alerts/rule/disable", + "alerting:metrics.alert.inventory.threshold/alerts/rule/muteAll", + "alerting:metrics.alert.inventory.threshold/alerts/rule/unmuteAll", + "alerting:metrics.alert.inventory.threshold/alerts/rule/muteAlert", + "alerting:metrics.alert.inventory.threshold/alerts/rule/unmuteAlert", + "alerting:metrics.alert.inventory.threshold/alerts/rule/snooze", + "alerting:metrics.alert.inventory.threshold/alerts/rule/bulkEdit", + "alerting:metrics.alert.inventory.threshold/alerts/rule/bulkDelete", + "alerting:metrics.alert.inventory.threshold/alerts/rule/bulkEnable", + "alerting:metrics.alert.inventory.threshold/alerts/rule/bulkDisable", + "alerting:metrics.alert.inventory.threshold/alerts/rule/unsnooze", + "alerting:metrics.alert.inventory.threshold/alerts/rule/runSoon", + "alerting:metrics.alert.inventory.threshold/alerts/rule/scheduleBackfill", + "alerting:metrics.alert.inventory.threshold/alerts/rule/deleteBackfill", "alerting:apm.error_rate/observability/rule/get", "alerting:apm.error_rate/observability/rule/getRuleState", "alerting:apm.error_rate/observability/rule/getAlertSummary", @@ -656,6 +977,11 @@ export default function ({ getService }: FtrProviderContext) { "alerting:slo.rules.burnRate/observability/alert/getAuthorizedAlertsIndices", "alerting:slo.rules.burnRate/observability/alert/getAlertSummary", "alerting:slo.rules.burnRate/observability/alert/update", + "alerting:slo.rules.burnRate/alerts/alert/get", + "alerting:slo.rules.burnRate/alerts/alert/find", + "alerting:slo.rules.burnRate/alerts/alert/getAuthorizedAlertsIndices", + "alerting:slo.rules.burnRate/alerts/alert/getAlertSummary", + "alerting:slo.rules.burnRate/alerts/alert/update", "alerting:observability.rules.custom_threshold/observability/alert/get", "alerting:observability.rules.custom_threshold/observability/alert/find", "alerting:observability.rules.custom_threshold/observability/alert/getAuthorizedAlertsIndices", @@ -676,6 +1002,11 @@ export default function ({ getService }: FtrProviderContext) { "alerting:metrics.alert.inventory.threshold/observability/alert/getAuthorizedAlertsIndices", "alerting:metrics.alert.inventory.threshold/observability/alert/getAlertSummary", "alerting:metrics.alert.inventory.threshold/observability/alert/update", + "alerting:metrics.alert.inventory.threshold/alerts/alert/get", + "alerting:metrics.alert.inventory.threshold/alerts/alert/find", + "alerting:metrics.alert.inventory.threshold/alerts/alert/getAuthorizedAlertsIndices", + "alerting:metrics.alert.inventory.threshold/alerts/alert/getAlertSummary", + "alerting:metrics.alert.inventory.threshold/alerts/alert/update", "alerting:apm.error_rate/observability/alert/get", "alerting:apm.error_rate/observability/alert/find", "alerting:apm.error_rate/observability/alert/getAuthorizedAlertsIndices", @@ -774,6 +1105,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.error_rate/apm/rule/runSoon", "alerting:apm.error_rate/apm/rule/scheduleBackfill", "alerting:apm.error_rate/apm/rule/deleteBackfill", + "alerting:apm.error_rate/alerts/rule/get", + "alerting:apm.error_rate/alerts/rule/getRuleState", + "alerting:apm.error_rate/alerts/rule/getAlertSummary", + "alerting:apm.error_rate/alerts/rule/getExecutionLog", + "alerting:apm.error_rate/alerts/rule/getActionErrorLog", + "alerting:apm.error_rate/alerts/rule/find", + "alerting:apm.error_rate/alerts/rule/getRuleExecutionKPI", + "alerting:apm.error_rate/alerts/rule/getBackfill", + "alerting:apm.error_rate/alerts/rule/findBackfill", + "alerting:apm.error_rate/alerts/rule/create", + "alerting:apm.error_rate/alerts/rule/delete", + "alerting:apm.error_rate/alerts/rule/update", + "alerting:apm.error_rate/alerts/rule/updateApiKey", + "alerting:apm.error_rate/alerts/rule/enable", + "alerting:apm.error_rate/alerts/rule/disable", + "alerting:apm.error_rate/alerts/rule/muteAll", + "alerting:apm.error_rate/alerts/rule/unmuteAll", + "alerting:apm.error_rate/alerts/rule/muteAlert", + "alerting:apm.error_rate/alerts/rule/unmuteAlert", + "alerting:apm.error_rate/alerts/rule/snooze", + "alerting:apm.error_rate/alerts/rule/bulkEdit", + "alerting:apm.error_rate/alerts/rule/bulkDelete", + "alerting:apm.error_rate/alerts/rule/bulkEnable", + "alerting:apm.error_rate/alerts/rule/bulkDisable", + "alerting:apm.error_rate/alerts/rule/unsnooze", + "alerting:apm.error_rate/alerts/rule/runSoon", + "alerting:apm.error_rate/alerts/rule/scheduleBackfill", + "alerting:apm.error_rate/alerts/rule/deleteBackfill", "alerting:apm.transaction_error_rate/apm/rule/get", "alerting:apm.transaction_error_rate/apm/rule/getRuleState", "alerting:apm.transaction_error_rate/apm/rule/getAlertSummary", @@ -802,6 +1161,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.transaction_error_rate/apm/rule/runSoon", "alerting:apm.transaction_error_rate/apm/rule/scheduleBackfill", "alerting:apm.transaction_error_rate/apm/rule/deleteBackfill", + "alerting:apm.transaction_error_rate/alerts/rule/get", + "alerting:apm.transaction_error_rate/alerts/rule/getRuleState", + "alerting:apm.transaction_error_rate/alerts/rule/getAlertSummary", + "alerting:apm.transaction_error_rate/alerts/rule/getExecutionLog", + "alerting:apm.transaction_error_rate/alerts/rule/getActionErrorLog", + "alerting:apm.transaction_error_rate/alerts/rule/find", + "alerting:apm.transaction_error_rate/alerts/rule/getRuleExecutionKPI", + "alerting:apm.transaction_error_rate/alerts/rule/getBackfill", + "alerting:apm.transaction_error_rate/alerts/rule/findBackfill", + "alerting:apm.transaction_error_rate/alerts/rule/create", + "alerting:apm.transaction_error_rate/alerts/rule/delete", + "alerting:apm.transaction_error_rate/alerts/rule/update", + "alerting:apm.transaction_error_rate/alerts/rule/updateApiKey", + "alerting:apm.transaction_error_rate/alerts/rule/enable", + "alerting:apm.transaction_error_rate/alerts/rule/disable", + "alerting:apm.transaction_error_rate/alerts/rule/muteAll", + "alerting:apm.transaction_error_rate/alerts/rule/unmuteAll", + "alerting:apm.transaction_error_rate/alerts/rule/muteAlert", + "alerting:apm.transaction_error_rate/alerts/rule/unmuteAlert", + "alerting:apm.transaction_error_rate/alerts/rule/snooze", + "alerting:apm.transaction_error_rate/alerts/rule/bulkEdit", + "alerting:apm.transaction_error_rate/alerts/rule/bulkDelete", + "alerting:apm.transaction_error_rate/alerts/rule/bulkEnable", + "alerting:apm.transaction_error_rate/alerts/rule/bulkDisable", + "alerting:apm.transaction_error_rate/alerts/rule/unsnooze", + "alerting:apm.transaction_error_rate/alerts/rule/runSoon", + "alerting:apm.transaction_error_rate/alerts/rule/scheduleBackfill", + "alerting:apm.transaction_error_rate/alerts/rule/deleteBackfill", "alerting:apm.transaction_duration/apm/rule/get", "alerting:apm.transaction_duration/apm/rule/getRuleState", "alerting:apm.transaction_duration/apm/rule/getAlertSummary", @@ -830,6 +1217,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.transaction_duration/apm/rule/runSoon", "alerting:apm.transaction_duration/apm/rule/scheduleBackfill", "alerting:apm.transaction_duration/apm/rule/deleteBackfill", + "alerting:apm.transaction_duration/alerts/rule/get", + "alerting:apm.transaction_duration/alerts/rule/getRuleState", + "alerting:apm.transaction_duration/alerts/rule/getAlertSummary", + "alerting:apm.transaction_duration/alerts/rule/getExecutionLog", + "alerting:apm.transaction_duration/alerts/rule/getActionErrorLog", + "alerting:apm.transaction_duration/alerts/rule/find", + "alerting:apm.transaction_duration/alerts/rule/getRuleExecutionKPI", + "alerting:apm.transaction_duration/alerts/rule/getBackfill", + "alerting:apm.transaction_duration/alerts/rule/findBackfill", + "alerting:apm.transaction_duration/alerts/rule/create", + "alerting:apm.transaction_duration/alerts/rule/delete", + "alerting:apm.transaction_duration/alerts/rule/update", + "alerting:apm.transaction_duration/alerts/rule/updateApiKey", + "alerting:apm.transaction_duration/alerts/rule/enable", + "alerting:apm.transaction_duration/alerts/rule/disable", + "alerting:apm.transaction_duration/alerts/rule/muteAll", + "alerting:apm.transaction_duration/alerts/rule/unmuteAll", + "alerting:apm.transaction_duration/alerts/rule/muteAlert", + "alerting:apm.transaction_duration/alerts/rule/unmuteAlert", + "alerting:apm.transaction_duration/alerts/rule/snooze", + "alerting:apm.transaction_duration/alerts/rule/bulkEdit", + "alerting:apm.transaction_duration/alerts/rule/bulkDelete", + "alerting:apm.transaction_duration/alerts/rule/bulkEnable", + "alerting:apm.transaction_duration/alerts/rule/bulkDisable", + "alerting:apm.transaction_duration/alerts/rule/unsnooze", + "alerting:apm.transaction_duration/alerts/rule/runSoon", + "alerting:apm.transaction_duration/alerts/rule/scheduleBackfill", + "alerting:apm.transaction_duration/alerts/rule/deleteBackfill", "alerting:apm.anomaly/apm/rule/get", "alerting:apm.anomaly/apm/rule/getRuleState", "alerting:apm.anomaly/apm/rule/getAlertSummary", @@ -858,26 +1273,74 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.anomaly/apm/rule/runSoon", "alerting:apm.anomaly/apm/rule/scheduleBackfill", "alerting:apm.anomaly/apm/rule/deleteBackfill", + "alerting:apm.anomaly/alerts/rule/get", + "alerting:apm.anomaly/alerts/rule/getRuleState", + "alerting:apm.anomaly/alerts/rule/getAlertSummary", + "alerting:apm.anomaly/alerts/rule/getExecutionLog", + "alerting:apm.anomaly/alerts/rule/getActionErrorLog", + "alerting:apm.anomaly/alerts/rule/find", + "alerting:apm.anomaly/alerts/rule/getRuleExecutionKPI", + "alerting:apm.anomaly/alerts/rule/getBackfill", + "alerting:apm.anomaly/alerts/rule/findBackfill", + "alerting:apm.anomaly/alerts/rule/create", + "alerting:apm.anomaly/alerts/rule/delete", + "alerting:apm.anomaly/alerts/rule/update", + "alerting:apm.anomaly/alerts/rule/updateApiKey", + "alerting:apm.anomaly/alerts/rule/enable", + "alerting:apm.anomaly/alerts/rule/disable", + "alerting:apm.anomaly/alerts/rule/muteAll", + "alerting:apm.anomaly/alerts/rule/unmuteAll", + "alerting:apm.anomaly/alerts/rule/muteAlert", + "alerting:apm.anomaly/alerts/rule/unmuteAlert", + "alerting:apm.anomaly/alerts/rule/snooze", + "alerting:apm.anomaly/alerts/rule/bulkEdit", + "alerting:apm.anomaly/alerts/rule/bulkDelete", + "alerting:apm.anomaly/alerts/rule/bulkEnable", + "alerting:apm.anomaly/alerts/rule/bulkDisable", + "alerting:apm.anomaly/alerts/rule/unsnooze", + "alerting:apm.anomaly/alerts/rule/runSoon", + "alerting:apm.anomaly/alerts/rule/scheduleBackfill", + "alerting:apm.anomaly/alerts/rule/deleteBackfill", "alerting:apm.error_rate/apm/alert/get", "alerting:apm.error_rate/apm/alert/find", "alerting:apm.error_rate/apm/alert/getAuthorizedAlertsIndices", "alerting:apm.error_rate/apm/alert/getAlertSummary", "alerting:apm.error_rate/apm/alert/update", + "alerting:apm.error_rate/alerts/alert/get", + "alerting:apm.error_rate/alerts/alert/find", + "alerting:apm.error_rate/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.error_rate/alerts/alert/getAlertSummary", + "alerting:apm.error_rate/alerts/alert/update", "alerting:apm.transaction_error_rate/apm/alert/get", "alerting:apm.transaction_error_rate/apm/alert/find", "alerting:apm.transaction_error_rate/apm/alert/getAuthorizedAlertsIndices", "alerting:apm.transaction_error_rate/apm/alert/getAlertSummary", "alerting:apm.transaction_error_rate/apm/alert/update", + "alerting:apm.transaction_error_rate/alerts/alert/get", + "alerting:apm.transaction_error_rate/alerts/alert/find", + "alerting:apm.transaction_error_rate/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.transaction_error_rate/alerts/alert/getAlertSummary", + "alerting:apm.transaction_error_rate/alerts/alert/update", "alerting:apm.transaction_duration/apm/alert/get", "alerting:apm.transaction_duration/apm/alert/find", "alerting:apm.transaction_duration/apm/alert/getAuthorizedAlertsIndices", "alerting:apm.transaction_duration/apm/alert/getAlertSummary", "alerting:apm.transaction_duration/apm/alert/update", + "alerting:apm.transaction_duration/alerts/alert/get", + "alerting:apm.transaction_duration/alerts/alert/find", + "alerting:apm.transaction_duration/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.transaction_duration/alerts/alert/getAlertSummary", + "alerting:apm.transaction_duration/alerts/alert/update", "alerting:apm.anomaly/apm/alert/get", "alerting:apm.anomaly/apm/alert/find", "alerting:apm.anomaly/apm/alert/getAuthorizedAlertsIndices", "alerting:apm.anomaly/apm/alert/getAlertSummary", "alerting:apm.anomaly/apm/alert/update", + "alerting:apm.anomaly/alerts/alert/get", + "alerting:apm.anomaly/alerts/alert/find", + "alerting:apm.anomaly/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.anomaly/alerts/alert/getAlertSummary", + "alerting:apm.anomaly/alerts/alert/update", "api:infra", "app:infra", "app:logs", @@ -940,6 +1403,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:logs.alert.document.count/logs/rule/runSoon", "alerting:logs.alert.document.count/logs/rule/scheduleBackfill", "alerting:logs.alert.document.count/logs/rule/deleteBackfill", + "alerting:logs.alert.document.count/alerts/rule/get", + "alerting:logs.alert.document.count/alerts/rule/getRuleState", + "alerting:logs.alert.document.count/alerts/rule/getAlertSummary", + "alerting:logs.alert.document.count/alerts/rule/getExecutionLog", + "alerting:logs.alert.document.count/alerts/rule/getActionErrorLog", + "alerting:logs.alert.document.count/alerts/rule/find", + "alerting:logs.alert.document.count/alerts/rule/getRuleExecutionKPI", + "alerting:logs.alert.document.count/alerts/rule/getBackfill", + "alerting:logs.alert.document.count/alerts/rule/findBackfill", + "alerting:logs.alert.document.count/alerts/rule/create", + "alerting:logs.alert.document.count/alerts/rule/delete", + "alerting:logs.alert.document.count/alerts/rule/update", + "alerting:logs.alert.document.count/alerts/rule/updateApiKey", + "alerting:logs.alert.document.count/alerts/rule/enable", + "alerting:logs.alert.document.count/alerts/rule/disable", + "alerting:logs.alert.document.count/alerts/rule/muteAll", + "alerting:logs.alert.document.count/alerts/rule/unmuteAll", + "alerting:logs.alert.document.count/alerts/rule/muteAlert", + "alerting:logs.alert.document.count/alerts/rule/unmuteAlert", + "alerting:logs.alert.document.count/alerts/rule/snooze", + "alerting:logs.alert.document.count/alerts/rule/bulkEdit", + "alerting:logs.alert.document.count/alerts/rule/bulkDelete", + "alerting:logs.alert.document.count/alerts/rule/bulkEnable", + "alerting:logs.alert.document.count/alerts/rule/bulkDisable", + "alerting:logs.alert.document.count/alerts/rule/unsnooze", + "alerting:logs.alert.document.count/alerts/rule/runSoon", + "alerting:logs.alert.document.count/alerts/rule/scheduleBackfill", + "alerting:logs.alert.document.count/alerts/rule/deleteBackfill", "alerting:.es-query/logs/rule/get", "alerting:.es-query/logs/rule/getRuleState", "alerting:.es-query/logs/rule/getAlertSummary", @@ -968,6 +1459,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:.es-query/logs/rule/runSoon", "alerting:.es-query/logs/rule/scheduleBackfill", "alerting:.es-query/logs/rule/deleteBackfill", + "alerting:.es-query/alerts/rule/get", + "alerting:.es-query/alerts/rule/getRuleState", + "alerting:.es-query/alerts/rule/getAlertSummary", + "alerting:.es-query/alerts/rule/getExecutionLog", + "alerting:.es-query/alerts/rule/getActionErrorLog", + "alerting:.es-query/alerts/rule/find", + "alerting:.es-query/alerts/rule/getRuleExecutionKPI", + "alerting:.es-query/alerts/rule/getBackfill", + "alerting:.es-query/alerts/rule/findBackfill", + "alerting:.es-query/alerts/rule/create", + "alerting:.es-query/alerts/rule/delete", + "alerting:.es-query/alerts/rule/update", + "alerting:.es-query/alerts/rule/updateApiKey", + "alerting:.es-query/alerts/rule/enable", + "alerting:.es-query/alerts/rule/disable", + "alerting:.es-query/alerts/rule/muteAll", + "alerting:.es-query/alerts/rule/unmuteAll", + "alerting:.es-query/alerts/rule/muteAlert", + "alerting:.es-query/alerts/rule/unmuteAlert", + "alerting:.es-query/alerts/rule/snooze", + "alerting:.es-query/alerts/rule/bulkEdit", + "alerting:.es-query/alerts/rule/bulkDelete", + "alerting:.es-query/alerts/rule/bulkEnable", + "alerting:.es-query/alerts/rule/bulkDisable", + "alerting:.es-query/alerts/rule/unsnooze", + "alerting:.es-query/alerts/rule/runSoon", + "alerting:.es-query/alerts/rule/scheduleBackfill", + "alerting:.es-query/alerts/rule/deleteBackfill", "alerting:observability.rules.custom_threshold/logs/rule/get", "alerting:observability.rules.custom_threshold/logs/rule/getRuleState", "alerting:observability.rules.custom_threshold/logs/rule/getAlertSummary", @@ -996,6 +1515,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:observability.rules.custom_threshold/logs/rule/runSoon", "alerting:observability.rules.custom_threshold/logs/rule/scheduleBackfill", "alerting:observability.rules.custom_threshold/logs/rule/deleteBackfill", + "alerting:observability.rules.custom_threshold/alerts/rule/get", + "alerting:observability.rules.custom_threshold/alerts/rule/getRuleState", + "alerting:observability.rules.custom_threshold/alerts/rule/getAlertSummary", + "alerting:observability.rules.custom_threshold/alerts/rule/getExecutionLog", + "alerting:observability.rules.custom_threshold/alerts/rule/getActionErrorLog", + "alerting:observability.rules.custom_threshold/alerts/rule/find", + "alerting:observability.rules.custom_threshold/alerts/rule/getRuleExecutionKPI", + "alerting:observability.rules.custom_threshold/alerts/rule/getBackfill", + "alerting:observability.rules.custom_threshold/alerts/rule/findBackfill", + "alerting:observability.rules.custom_threshold/alerts/rule/create", + "alerting:observability.rules.custom_threshold/alerts/rule/delete", + "alerting:observability.rules.custom_threshold/alerts/rule/update", + "alerting:observability.rules.custom_threshold/alerts/rule/updateApiKey", + "alerting:observability.rules.custom_threshold/alerts/rule/enable", + "alerting:observability.rules.custom_threshold/alerts/rule/disable", + "alerting:observability.rules.custom_threshold/alerts/rule/muteAll", + "alerting:observability.rules.custom_threshold/alerts/rule/unmuteAll", + "alerting:observability.rules.custom_threshold/alerts/rule/muteAlert", + "alerting:observability.rules.custom_threshold/alerts/rule/unmuteAlert", + "alerting:observability.rules.custom_threshold/alerts/rule/snooze", + "alerting:observability.rules.custom_threshold/alerts/rule/bulkEdit", + "alerting:observability.rules.custom_threshold/alerts/rule/bulkDelete", + "alerting:observability.rules.custom_threshold/alerts/rule/bulkEnable", + "alerting:observability.rules.custom_threshold/alerts/rule/bulkDisable", + "alerting:observability.rules.custom_threshold/alerts/rule/unsnooze", + "alerting:observability.rules.custom_threshold/alerts/rule/runSoon", + "alerting:observability.rules.custom_threshold/alerts/rule/scheduleBackfill", + "alerting:observability.rules.custom_threshold/alerts/rule/deleteBackfill", "alerting:xpack.ml.anomaly_detection_alert/logs/rule/get", "alerting:xpack.ml.anomaly_detection_alert/logs/rule/getRuleState", "alerting:xpack.ml.anomaly_detection_alert/logs/rule/getAlertSummary", @@ -1024,26 +1571,74 @@ export default function ({ getService }: FtrProviderContext) { "alerting:xpack.ml.anomaly_detection_alert/logs/rule/runSoon", "alerting:xpack.ml.anomaly_detection_alert/logs/rule/scheduleBackfill", "alerting:xpack.ml.anomaly_detection_alert/logs/rule/deleteBackfill", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/get", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getRuleState", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getAlertSummary", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getExecutionLog", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getActionErrorLog", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/find", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getRuleExecutionKPI", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getBackfill", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/findBackfill", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/create", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/delete", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/update", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/updateApiKey", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/enable", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/disable", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/muteAll", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/unmuteAll", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/muteAlert", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/unmuteAlert", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/snooze", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/bulkEdit", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/bulkDelete", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/bulkEnable", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/bulkDisable", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/unsnooze", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/runSoon", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/scheduleBackfill", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/deleteBackfill", "alerting:logs.alert.document.count/logs/alert/get", "alerting:logs.alert.document.count/logs/alert/find", "alerting:logs.alert.document.count/logs/alert/getAuthorizedAlertsIndices", "alerting:logs.alert.document.count/logs/alert/getAlertSummary", "alerting:logs.alert.document.count/logs/alert/update", + "alerting:logs.alert.document.count/alerts/alert/get", + "alerting:logs.alert.document.count/alerts/alert/find", + "alerting:logs.alert.document.count/alerts/alert/getAuthorizedAlertsIndices", + "alerting:logs.alert.document.count/alerts/alert/getAlertSummary", + "alerting:logs.alert.document.count/alerts/alert/update", "alerting:.es-query/logs/alert/get", "alerting:.es-query/logs/alert/find", "alerting:.es-query/logs/alert/getAuthorizedAlertsIndices", "alerting:.es-query/logs/alert/getAlertSummary", "alerting:.es-query/logs/alert/update", + "alerting:.es-query/alerts/alert/get", + "alerting:.es-query/alerts/alert/find", + "alerting:.es-query/alerts/alert/getAuthorizedAlertsIndices", + "alerting:.es-query/alerts/alert/getAlertSummary", + "alerting:.es-query/alerts/alert/update", "alerting:observability.rules.custom_threshold/logs/alert/get", "alerting:observability.rules.custom_threshold/logs/alert/find", "alerting:observability.rules.custom_threshold/logs/alert/getAuthorizedAlertsIndices", "alerting:observability.rules.custom_threshold/logs/alert/getAlertSummary", "alerting:observability.rules.custom_threshold/logs/alert/update", + "alerting:observability.rules.custom_threshold/alerts/alert/get", + "alerting:observability.rules.custom_threshold/alerts/alert/find", + "alerting:observability.rules.custom_threshold/alerts/alert/getAuthorizedAlertsIndices", + "alerting:observability.rules.custom_threshold/alerts/alert/getAlertSummary", + "alerting:observability.rules.custom_threshold/alerts/alert/update", "alerting:xpack.ml.anomaly_detection_alert/logs/alert/get", "alerting:xpack.ml.anomaly_detection_alert/logs/alert/find", "alerting:xpack.ml.anomaly_detection_alert/logs/alert/getAuthorizedAlertsIndices", "alerting:xpack.ml.anomaly_detection_alert/logs/alert/getAlertSummary", "alerting:xpack.ml.anomaly_detection_alert/logs/alert/update", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/get", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/find", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/getAuthorizedAlertsIndices", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/getAlertSummary", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/update", "app:observability", "ui:catalogue/observability", "ui:navLinks/observability", @@ -1077,6 +1672,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:slo.rules.burnRate/observability/rule/runSoon", "alerting:slo.rules.burnRate/observability/rule/scheduleBackfill", "alerting:slo.rules.burnRate/observability/rule/deleteBackfill", + "alerting:slo.rules.burnRate/alerts/rule/get", + "alerting:slo.rules.burnRate/alerts/rule/getRuleState", + "alerting:slo.rules.burnRate/alerts/rule/getAlertSummary", + "alerting:slo.rules.burnRate/alerts/rule/getExecutionLog", + "alerting:slo.rules.burnRate/alerts/rule/getActionErrorLog", + "alerting:slo.rules.burnRate/alerts/rule/find", + "alerting:slo.rules.burnRate/alerts/rule/getRuleExecutionKPI", + "alerting:slo.rules.burnRate/alerts/rule/getBackfill", + "alerting:slo.rules.burnRate/alerts/rule/findBackfill", + "alerting:slo.rules.burnRate/alerts/rule/create", + "alerting:slo.rules.burnRate/alerts/rule/delete", + "alerting:slo.rules.burnRate/alerts/rule/update", + "alerting:slo.rules.burnRate/alerts/rule/updateApiKey", + "alerting:slo.rules.burnRate/alerts/rule/enable", + "alerting:slo.rules.burnRate/alerts/rule/disable", + "alerting:slo.rules.burnRate/alerts/rule/muteAll", + "alerting:slo.rules.burnRate/alerts/rule/unmuteAll", + "alerting:slo.rules.burnRate/alerts/rule/muteAlert", + "alerting:slo.rules.burnRate/alerts/rule/unmuteAlert", + "alerting:slo.rules.burnRate/alerts/rule/snooze", + "alerting:slo.rules.burnRate/alerts/rule/bulkEdit", + "alerting:slo.rules.burnRate/alerts/rule/bulkDelete", + "alerting:slo.rules.burnRate/alerts/rule/bulkEnable", + "alerting:slo.rules.burnRate/alerts/rule/bulkDisable", + "alerting:slo.rules.burnRate/alerts/rule/unsnooze", + "alerting:slo.rules.burnRate/alerts/rule/runSoon", + "alerting:slo.rules.burnRate/alerts/rule/scheduleBackfill", + "alerting:slo.rules.burnRate/alerts/rule/deleteBackfill", "alerting:observability.rules.custom_threshold/observability/rule/get", "alerting:observability.rules.custom_threshold/observability/rule/getRuleState", "alerting:observability.rules.custom_threshold/observability/rule/getAlertSummary", @@ -1189,6 +1812,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:metrics.alert.inventory.threshold/observability/rule/runSoon", "alerting:metrics.alert.inventory.threshold/observability/rule/scheduleBackfill", "alerting:metrics.alert.inventory.threshold/observability/rule/deleteBackfill", + "alerting:metrics.alert.inventory.threshold/alerts/rule/get", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getRuleState", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getAlertSummary", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getExecutionLog", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getActionErrorLog", + "alerting:metrics.alert.inventory.threshold/alerts/rule/find", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getRuleExecutionKPI", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getBackfill", + "alerting:metrics.alert.inventory.threshold/alerts/rule/findBackfill", + "alerting:metrics.alert.inventory.threshold/alerts/rule/create", + "alerting:metrics.alert.inventory.threshold/alerts/rule/delete", + "alerting:metrics.alert.inventory.threshold/alerts/rule/update", + "alerting:metrics.alert.inventory.threshold/alerts/rule/updateApiKey", + "alerting:metrics.alert.inventory.threshold/alerts/rule/enable", + "alerting:metrics.alert.inventory.threshold/alerts/rule/disable", + "alerting:metrics.alert.inventory.threshold/alerts/rule/muteAll", + "alerting:metrics.alert.inventory.threshold/alerts/rule/unmuteAll", + "alerting:metrics.alert.inventory.threshold/alerts/rule/muteAlert", + "alerting:metrics.alert.inventory.threshold/alerts/rule/unmuteAlert", + "alerting:metrics.alert.inventory.threshold/alerts/rule/snooze", + "alerting:metrics.alert.inventory.threshold/alerts/rule/bulkEdit", + "alerting:metrics.alert.inventory.threshold/alerts/rule/bulkDelete", + "alerting:metrics.alert.inventory.threshold/alerts/rule/bulkEnable", + "alerting:metrics.alert.inventory.threshold/alerts/rule/bulkDisable", + "alerting:metrics.alert.inventory.threshold/alerts/rule/unsnooze", + "alerting:metrics.alert.inventory.threshold/alerts/rule/runSoon", + "alerting:metrics.alert.inventory.threshold/alerts/rule/scheduleBackfill", + "alerting:metrics.alert.inventory.threshold/alerts/rule/deleteBackfill", "alerting:apm.error_rate/observability/rule/get", "alerting:apm.error_rate/observability/rule/getRuleState", "alerting:apm.error_rate/observability/rule/getAlertSummary", @@ -1306,6 +1957,11 @@ export default function ({ getService }: FtrProviderContext) { "alerting:slo.rules.burnRate/observability/alert/getAuthorizedAlertsIndices", "alerting:slo.rules.burnRate/observability/alert/getAlertSummary", "alerting:slo.rules.burnRate/observability/alert/update", + "alerting:slo.rules.burnRate/alerts/alert/get", + "alerting:slo.rules.burnRate/alerts/alert/find", + "alerting:slo.rules.burnRate/alerts/alert/getAuthorizedAlertsIndices", + "alerting:slo.rules.burnRate/alerts/alert/getAlertSummary", + "alerting:slo.rules.burnRate/alerts/alert/update", "alerting:observability.rules.custom_threshold/observability/alert/get", "alerting:observability.rules.custom_threshold/observability/alert/find", "alerting:observability.rules.custom_threshold/observability/alert/getAuthorizedAlertsIndices", @@ -1326,6 +1982,11 @@ export default function ({ getService }: FtrProviderContext) { "alerting:metrics.alert.inventory.threshold/observability/alert/getAuthorizedAlertsIndices", "alerting:metrics.alert.inventory.threshold/observability/alert/getAlertSummary", "alerting:metrics.alert.inventory.threshold/observability/alert/update", + "alerting:metrics.alert.inventory.threshold/alerts/alert/get", + "alerting:metrics.alert.inventory.threshold/alerts/alert/find", + "alerting:metrics.alert.inventory.threshold/alerts/alert/getAuthorizedAlertsIndices", + "alerting:metrics.alert.inventory.threshold/alerts/alert/getAlertSummary", + "alerting:metrics.alert.inventory.threshold/alerts/alert/update", "alerting:apm.error_rate/observability/alert/get", "alerting:apm.error_rate/observability/alert/find", "alerting:apm.error_rate/observability/alert/getAuthorizedAlertsIndices", @@ -1395,6 +2056,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.error_rate/apm/rule/getRuleExecutionKPI", "alerting:apm.error_rate/apm/rule/getBackfill", "alerting:apm.error_rate/apm/rule/findBackfill", + "alerting:apm.error_rate/alerts/rule/get", + "alerting:apm.error_rate/alerts/rule/getRuleState", + "alerting:apm.error_rate/alerts/rule/getAlertSummary", + "alerting:apm.error_rate/alerts/rule/getExecutionLog", + "alerting:apm.error_rate/alerts/rule/getActionErrorLog", + "alerting:apm.error_rate/alerts/rule/find", + "alerting:apm.error_rate/alerts/rule/getRuleExecutionKPI", + "alerting:apm.error_rate/alerts/rule/getBackfill", + "alerting:apm.error_rate/alerts/rule/findBackfill", "alerting:apm.transaction_error_rate/apm/rule/get", "alerting:apm.transaction_error_rate/apm/rule/getRuleState", "alerting:apm.transaction_error_rate/apm/rule/getAlertSummary", @@ -1404,6 +2074,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.transaction_error_rate/apm/rule/getRuleExecutionKPI", "alerting:apm.transaction_error_rate/apm/rule/getBackfill", "alerting:apm.transaction_error_rate/apm/rule/findBackfill", + "alerting:apm.transaction_error_rate/alerts/rule/get", + "alerting:apm.transaction_error_rate/alerts/rule/getRuleState", + "alerting:apm.transaction_error_rate/alerts/rule/getAlertSummary", + "alerting:apm.transaction_error_rate/alerts/rule/getExecutionLog", + "alerting:apm.transaction_error_rate/alerts/rule/getActionErrorLog", + "alerting:apm.transaction_error_rate/alerts/rule/find", + "alerting:apm.transaction_error_rate/alerts/rule/getRuleExecutionKPI", + "alerting:apm.transaction_error_rate/alerts/rule/getBackfill", + "alerting:apm.transaction_error_rate/alerts/rule/findBackfill", "alerting:apm.transaction_duration/apm/rule/get", "alerting:apm.transaction_duration/apm/rule/getRuleState", "alerting:apm.transaction_duration/apm/rule/getAlertSummary", @@ -1413,6 +2092,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.transaction_duration/apm/rule/getRuleExecutionKPI", "alerting:apm.transaction_duration/apm/rule/getBackfill", "alerting:apm.transaction_duration/apm/rule/findBackfill", + "alerting:apm.transaction_duration/alerts/rule/get", + "alerting:apm.transaction_duration/alerts/rule/getRuleState", + "alerting:apm.transaction_duration/alerts/rule/getAlertSummary", + "alerting:apm.transaction_duration/alerts/rule/getExecutionLog", + "alerting:apm.transaction_duration/alerts/rule/getActionErrorLog", + "alerting:apm.transaction_duration/alerts/rule/find", + "alerting:apm.transaction_duration/alerts/rule/getRuleExecutionKPI", + "alerting:apm.transaction_duration/alerts/rule/getBackfill", + "alerting:apm.transaction_duration/alerts/rule/findBackfill", "alerting:apm.anomaly/apm/rule/get", "alerting:apm.anomaly/apm/rule/getRuleState", "alerting:apm.anomaly/apm/rule/getAlertSummary", @@ -1422,22 +2110,47 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.anomaly/apm/rule/getRuleExecutionKPI", "alerting:apm.anomaly/apm/rule/getBackfill", "alerting:apm.anomaly/apm/rule/findBackfill", + "alerting:apm.anomaly/alerts/rule/get", + "alerting:apm.anomaly/alerts/rule/getRuleState", + "alerting:apm.anomaly/alerts/rule/getAlertSummary", + "alerting:apm.anomaly/alerts/rule/getExecutionLog", + "alerting:apm.anomaly/alerts/rule/getActionErrorLog", + "alerting:apm.anomaly/alerts/rule/find", + "alerting:apm.anomaly/alerts/rule/getRuleExecutionKPI", + "alerting:apm.anomaly/alerts/rule/getBackfill", + "alerting:apm.anomaly/alerts/rule/findBackfill", "alerting:apm.error_rate/apm/alert/get", "alerting:apm.error_rate/apm/alert/find", "alerting:apm.error_rate/apm/alert/getAuthorizedAlertsIndices", "alerting:apm.error_rate/apm/alert/getAlertSummary", + "alerting:apm.error_rate/alerts/alert/get", + "alerting:apm.error_rate/alerts/alert/find", + "alerting:apm.error_rate/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.error_rate/alerts/alert/getAlertSummary", "alerting:apm.transaction_error_rate/apm/alert/get", "alerting:apm.transaction_error_rate/apm/alert/find", "alerting:apm.transaction_error_rate/apm/alert/getAuthorizedAlertsIndices", "alerting:apm.transaction_error_rate/apm/alert/getAlertSummary", + "alerting:apm.transaction_error_rate/alerts/alert/get", + "alerting:apm.transaction_error_rate/alerts/alert/find", + "alerting:apm.transaction_error_rate/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.transaction_error_rate/alerts/alert/getAlertSummary", "alerting:apm.transaction_duration/apm/alert/get", "alerting:apm.transaction_duration/apm/alert/find", "alerting:apm.transaction_duration/apm/alert/getAuthorizedAlertsIndices", "alerting:apm.transaction_duration/apm/alert/getAlertSummary", + "alerting:apm.transaction_duration/alerts/alert/get", + "alerting:apm.transaction_duration/alerts/alert/find", + "alerting:apm.transaction_duration/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.transaction_duration/alerts/alert/getAlertSummary", "alerting:apm.anomaly/apm/alert/get", "alerting:apm.anomaly/apm/alert/find", "alerting:apm.anomaly/apm/alert/getAuthorizedAlertsIndices", "alerting:apm.anomaly/apm/alert/getAlertSummary", + "alerting:apm.anomaly/alerts/alert/get", + "alerting:apm.anomaly/alerts/alert/find", + "alerting:apm.anomaly/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.anomaly/alerts/alert/getAlertSummary", "api:infra", "app:infra", "app:logs", @@ -1465,6 +2178,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:logs.alert.document.count/logs/rule/getRuleExecutionKPI", "alerting:logs.alert.document.count/logs/rule/getBackfill", "alerting:logs.alert.document.count/logs/rule/findBackfill", + "alerting:logs.alert.document.count/alerts/rule/get", + "alerting:logs.alert.document.count/alerts/rule/getRuleState", + "alerting:logs.alert.document.count/alerts/rule/getAlertSummary", + "alerting:logs.alert.document.count/alerts/rule/getExecutionLog", + "alerting:logs.alert.document.count/alerts/rule/getActionErrorLog", + "alerting:logs.alert.document.count/alerts/rule/find", + "alerting:logs.alert.document.count/alerts/rule/getRuleExecutionKPI", + "alerting:logs.alert.document.count/alerts/rule/getBackfill", + "alerting:logs.alert.document.count/alerts/rule/findBackfill", "alerting:.es-query/logs/rule/get", "alerting:.es-query/logs/rule/getRuleState", "alerting:.es-query/logs/rule/getAlertSummary", @@ -1474,6 +2196,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:.es-query/logs/rule/getRuleExecutionKPI", "alerting:.es-query/logs/rule/getBackfill", "alerting:.es-query/logs/rule/findBackfill", + "alerting:.es-query/alerts/rule/get", + "alerting:.es-query/alerts/rule/getRuleState", + "alerting:.es-query/alerts/rule/getAlertSummary", + "alerting:.es-query/alerts/rule/getExecutionLog", + "alerting:.es-query/alerts/rule/getActionErrorLog", + "alerting:.es-query/alerts/rule/find", + "alerting:.es-query/alerts/rule/getRuleExecutionKPI", + "alerting:.es-query/alerts/rule/getBackfill", + "alerting:.es-query/alerts/rule/findBackfill", "alerting:observability.rules.custom_threshold/logs/rule/get", "alerting:observability.rules.custom_threshold/logs/rule/getRuleState", "alerting:observability.rules.custom_threshold/logs/rule/getAlertSummary", @@ -1483,6 +2214,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:observability.rules.custom_threshold/logs/rule/getRuleExecutionKPI", "alerting:observability.rules.custom_threshold/logs/rule/getBackfill", "alerting:observability.rules.custom_threshold/logs/rule/findBackfill", + "alerting:observability.rules.custom_threshold/alerts/rule/get", + "alerting:observability.rules.custom_threshold/alerts/rule/getRuleState", + "alerting:observability.rules.custom_threshold/alerts/rule/getAlertSummary", + "alerting:observability.rules.custom_threshold/alerts/rule/getExecutionLog", + "alerting:observability.rules.custom_threshold/alerts/rule/getActionErrorLog", + "alerting:observability.rules.custom_threshold/alerts/rule/find", + "alerting:observability.rules.custom_threshold/alerts/rule/getRuleExecutionKPI", + "alerting:observability.rules.custom_threshold/alerts/rule/getBackfill", + "alerting:observability.rules.custom_threshold/alerts/rule/findBackfill", "alerting:xpack.ml.anomaly_detection_alert/logs/rule/get", "alerting:xpack.ml.anomaly_detection_alert/logs/rule/getRuleState", "alerting:xpack.ml.anomaly_detection_alert/logs/rule/getAlertSummary", @@ -1492,22 +2232,47 @@ export default function ({ getService }: FtrProviderContext) { "alerting:xpack.ml.anomaly_detection_alert/logs/rule/getRuleExecutionKPI", "alerting:xpack.ml.anomaly_detection_alert/logs/rule/getBackfill", "alerting:xpack.ml.anomaly_detection_alert/logs/rule/findBackfill", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/get", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getRuleState", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getAlertSummary", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getExecutionLog", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getActionErrorLog", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/find", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getRuleExecutionKPI", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getBackfill", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/findBackfill", "alerting:logs.alert.document.count/logs/alert/get", "alerting:logs.alert.document.count/logs/alert/find", "alerting:logs.alert.document.count/logs/alert/getAuthorizedAlertsIndices", "alerting:logs.alert.document.count/logs/alert/getAlertSummary", + "alerting:logs.alert.document.count/alerts/alert/get", + "alerting:logs.alert.document.count/alerts/alert/find", + "alerting:logs.alert.document.count/alerts/alert/getAuthorizedAlertsIndices", + "alerting:logs.alert.document.count/alerts/alert/getAlertSummary", "alerting:.es-query/logs/alert/get", "alerting:.es-query/logs/alert/find", "alerting:.es-query/logs/alert/getAuthorizedAlertsIndices", "alerting:.es-query/logs/alert/getAlertSummary", + "alerting:.es-query/alerts/alert/get", + "alerting:.es-query/alerts/alert/find", + "alerting:.es-query/alerts/alert/getAuthorizedAlertsIndices", + "alerting:.es-query/alerts/alert/getAlertSummary", "alerting:observability.rules.custom_threshold/logs/alert/get", "alerting:observability.rules.custom_threshold/logs/alert/find", "alerting:observability.rules.custom_threshold/logs/alert/getAuthorizedAlertsIndices", "alerting:observability.rules.custom_threshold/logs/alert/getAlertSummary", + "alerting:observability.rules.custom_threshold/alerts/alert/get", + "alerting:observability.rules.custom_threshold/alerts/alert/find", + "alerting:observability.rules.custom_threshold/alerts/alert/getAuthorizedAlertsIndices", + "alerting:observability.rules.custom_threshold/alerts/alert/getAlertSummary", "alerting:xpack.ml.anomaly_detection_alert/logs/alert/get", "alerting:xpack.ml.anomaly_detection_alert/logs/alert/find", "alerting:xpack.ml.anomaly_detection_alert/logs/alert/getAuthorizedAlertsIndices", "alerting:xpack.ml.anomaly_detection_alert/logs/alert/getAlertSummary", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/get", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/find", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/getAuthorizedAlertsIndices", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/getAlertSummary", "app:observability", "ui:catalogue/observability", "ui:navLinks/observability", @@ -1521,6 +2286,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:slo.rules.burnRate/observability/rule/getRuleExecutionKPI", "alerting:slo.rules.burnRate/observability/rule/getBackfill", "alerting:slo.rules.burnRate/observability/rule/findBackfill", + "alerting:slo.rules.burnRate/alerts/rule/get", + "alerting:slo.rules.burnRate/alerts/rule/getRuleState", + "alerting:slo.rules.burnRate/alerts/rule/getAlertSummary", + "alerting:slo.rules.burnRate/alerts/rule/getExecutionLog", + "alerting:slo.rules.burnRate/alerts/rule/getActionErrorLog", + "alerting:slo.rules.burnRate/alerts/rule/find", + "alerting:slo.rules.burnRate/alerts/rule/getRuleExecutionKPI", + "alerting:slo.rules.burnRate/alerts/rule/getBackfill", + "alerting:slo.rules.burnRate/alerts/rule/findBackfill", "alerting:observability.rules.custom_threshold/observability/rule/get", "alerting:observability.rules.custom_threshold/observability/rule/getRuleState", "alerting:observability.rules.custom_threshold/observability/rule/getAlertSummary", @@ -1557,6 +2331,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:metrics.alert.inventory.threshold/observability/rule/getRuleExecutionKPI", "alerting:metrics.alert.inventory.threshold/observability/rule/getBackfill", "alerting:metrics.alert.inventory.threshold/observability/rule/findBackfill", + "alerting:metrics.alert.inventory.threshold/alerts/rule/get", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getRuleState", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getAlertSummary", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getExecutionLog", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getActionErrorLog", + "alerting:metrics.alert.inventory.threshold/alerts/rule/find", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getRuleExecutionKPI", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getBackfill", + "alerting:metrics.alert.inventory.threshold/alerts/rule/findBackfill", "alerting:apm.error_rate/observability/rule/get", "alerting:apm.error_rate/observability/rule/getRuleState", "alerting:apm.error_rate/observability/rule/getAlertSummary", @@ -1597,6 +2380,10 @@ export default function ({ getService }: FtrProviderContext) { "alerting:slo.rules.burnRate/observability/alert/find", "alerting:slo.rules.burnRate/observability/alert/getAuthorizedAlertsIndices", "alerting:slo.rules.burnRate/observability/alert/getAlertSummary", + "alerting:slo.rules.burnRate/alerts/alert/get", + "alerting:slo.rules.burnRate/alerts/alert/find", + "alerting:slo.rules.burnRate/alerts/alert/getAuthorizedAlertsIndices", + "alerting:slo.rules.burnRate/alerts/alert/getAlertSummary", "alerting:observability.rules.custom_threshold/observability/alert/get", "alerting:observability.rules.custom_threshold/observability/alert/find", "alerting:observability.rules.custom_threshold/observability/alert/getAuthorizedAlertsIndices", @@ -1613,6 +2400,10 @@ export default function ({ getService }: FtrProviderContext) { "alerting:metrics.alert.inventory.threshold/observability/alert/find", "alerting:metrics.alert.inventory.threshold/observability/alert/getAuthorizedAlertsIndices", "alerting:metrics.alert.inventory.threshold/observability/alert/getAlertSummary", + "alerting:metrics.alert.inventory.threshold/alerts/alert/get", + "alerting:metrics.alert.inventory.threshold/alerts/alert/find", + "alerting:metrics.alert.inventory.threshold/alerts/alert/getAuthorizedAlertsIndices", + "alerting:metrics.alert.inventory.threshold/alerts/alert/getAlertSummary", "alerting:apm.error_rate/observability/alert/get", "alerting:apm.error_rate/observability/alert/find", "alerting:apm.error_rate/observability/alert/getAuthorizedAlertsIndices", @@ -1678,6 +2469,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.error_rate/apm/rule/getRuleExecutionKPI", "alerting:apm.error_rate/apm/rule/getBackfill", "alerting:apm.error_rate/apm/rule/findBackfill", + "alerting:apm.error_rate/alerts/rule/get", + "alerting:apm.error_rate/alerts/rule/getRuleState", + "alerting:apm.error_rate/alerts/rule/getAlertSummary", + "alerting:apm.error_rate/alerts/rule/getExecutionLog", + "alerting:apm.error_rate/alerts/rule/getActionErrorLog", + "alerting:apm.error_rate/alerts/rule/find", + "alerting:apm.error_rate/alerts/rule/getRuleExecutionKPI", + "alerting:apm.error_rate/alerts/rule/getBackfill", + "alerting:apm.error_rate/alerts/rule/findBackfill", "alerting:apm.transaction_error_rate/apm/rule/get", "alerting:apm.transaction_error_rate/apm/rule/getRuleState", "alerting:apm.transaction_error_rate/apm/rule/getAlertSummary", @@ -1687,6 +2487,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.transaction_error_rate/apm/rule/getRuleExecutionKPI", "alerting:apm.transaction_error_rate/apm/rule/getBackfill", "alerting:apm.transaction_error_rate/apm/rule/findBackfill", + "alerting:apm.transaction_error_rate/alerts/rule/get", + "alerting:apm.transaction_error_rate/alerts/rule/getRuleState", + "alerting:apm.transaction_error_rate/alerts/rule/getAlertSummary", + "alerting:apm.transaction_error_rate/alerts/rule/getExecutionLog", + "alerting:apm.transaction_error_rate/alerts/rule/getActionErrorLog", + "alerting:apm.transaction_error_rate/alerts/rule/find", + "alerting:apm.transaction_error_rate/alerts/rule/getRuleExecutionKPI", + "alerting:apm.transaction_error_rate/alerts/rule/getBackfill", + "alerting:apm.transaction_error_rate/alerts/rule/findBackfill", "alerting:apm.transaction_duration/apm/rule/get", "alerting:apm.transaction_duration/apm/rule/getRuleState", "alerting:apm.transaction_duration/apm/rule/getAlertSummary", @@ -1696,6 +2505,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.transaction_duration/apm/rule/getRuleExecutionKPI", "alerting:apm.transaction_duration/apm/rule/getBackfill", "alerting:apm.transaction_duration/apm/rule/findBackfill", + "alerting:apm.transaction_duration/alerts/rule/get", + "alerting:apm.transaction_duration/alerts/rule/getRuleState", + "alerting:apm.transaction_duration/alerts/rule/getAlertSummary", + "alerting:apm.transaction_duration/alerts/rule/getExecutionLog", + "alerting:apm.transaction_duration/alerts/rule/getActionErrorLog", + "alerting:apm.transaction_duration/alerts/rule/find", + "alerting:apm.transaction_duration/alerts/rule/getRuleExecutionKPI", + "alerting:apm.transaction_duration/alerts/rule/getBackfill", + "alerting:apm.transaction_duration/alerts/rule/findBackfill", "alerting:apm.anomaly/apm/rule/get", "alerting:apm.anomaly/apm/rule/getRuleState", "alerting:apm.anomaly/apm/rule/getAlertSummary", @@ -1705,22 +2523,47 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.anomaly/apm/rule/getRuleExecutionKPI", "alerting:apm.anomaly/apm/rule/getBackfill", "alerting:apm.anomaly/apm/rule/findBackfill", + "alerting:apm.anomaly/alerts/rule/get", + "alerting:apm.anomaly/alerts/rule/getRuleState", + "alerting:apm.anomaly/alerts/rule/getAlertSummary", + "alerting:apm.anomaly/alerts/rule/getExecutionLog", + "alerting:apm.anomaly/alerts/rule/getActionErrorLog", + "alerting:apm.anomaly/alerts/rule/find", + "alerting:apm.anomaly/alerts/rule/getRuleExecutionKPI", + "alerting:apm.anomaly/alerts/rule/getBackfill", + "alerting:apm.anomaly/alerts/rule/findBackfill", "alerting:apm.error_rate/apm/alert/get", "alerting:apm.error_rate/apm/alert/find", "alerting:apm.error_rate/apm/alert/getAuthorizedAlertsIndices", "alerting:apm.error_rate/apm/alert/getAlertSummary", + "alerting:apm.error_rate/alerts/alert/get", + "alerting:apm.error_rate/alerts/alert/find", + "alerting:apm.error_rate/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.error_rate/alerts/alert/getAlertSummary", "alerting:apm.transaction_error_rate/apm/alert/get", "alerting:apm.transaction_error_rate/apm/alert/find", "alerting:apm.transaction_error_rate/apm/alert/getAuthorizedAlertsIndices", "alerting:apm.transaction_error_rate/apm/alert/getAlertSummary", + "alerting:apm.transaction_error_rate/alerts/alert/get", + "alerting:apm.transaction_error_rate/alerts/alert/find", + "alerting:apm.transaction_error_rate/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.transaction_error_rate/alerts/alert/getAlertSummary", "alerting:apm.transaction_duration/apm/alert/get", "alerting:apm.transaction_duration/apm/alert/find", "alerting:apm.transaction_duration/apm/alert/getAuthorizedAlertsIndices", "alerting:apm.transaction_duration/apm/alert/getAlertSummary", + "alerting:apm.transaction_duration/alerts/alert/get", + "alerting:apm.transaction_duration/alerts/alert/find", + "alerting:apm.transaction_duration/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.transaction_duration/alerts/alert/getAlertSummary", "alerting:apm.anomaly/apm/alert/get", "alerting:apm.anomaly/apm/alert/find", "alerting:apm.anomaly/apm/alert/getAuthorizedAlertsIndices", "alerting:apm.anomaly/apm/alert/getAlertSummary", + "alerting:apm.anomaly/alerts/alert/get", + "alerting:apm.anomaly/alerts/alert/find", + "alerting:apm.anomaly/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.anomaly/alerts/alert/getAlertSummary", "api:infra", "app:infra", "app:logs", @@ -1748,6 +2591,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:logs.alert.document.count/logs/rule/getRuleExecutionKPI", "alerting:logs.alert.document.count/logs/rule/getBackfill", "alerting:logs.alert.document.count/logs/rule/findBackfill", + "alerting:logs.alert.document.count/alerts/rule/get", + "alerting:logs.alert.document.count/alerts/rule/getRuleState", + "alerting:logs.alert.document.count/alerts/rule/getAlertSummary", + "alerting:logs.alert.document.count/alerts/rule/getExecutionLog", + "alerting:logs.alert.document.count/alerts/rule/getActionErrorLog", + "alerting:logs.alert.document.count/alerts/rule/find", + "alerting:logs.alert.document.count/alerts/rule/getRuleExecutionKPI", + "alerting:logs.alert.document.count/alerts/rule/getBackfill", + "alerting:logs.alert.document.count/alerts/rule/findBackfill", "alerting:.es-query/logs/rule/get", "alerting:.es-query/logs/rule/getRuleState", "alerting:.es-query/logs/rule/getAlertSummary", @@ -1757,6 +2609,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:.es-query/logs/rule/getRuleExecutionKPI", "alerting:.es-query/logs/rule/getBackfill", "alerting:.es-query/logs/rule/findBackfill", + "alerting:.es-query/alerts/rule/get", + "alerting:.es-query/alerts/rule/getRuleState", + "alerting:.es-query/alerts/rule/getAlertSummary", + "alerting:.es-query/alerts/rule/getExecutionLog", + "alerting:.es-query/alerts/rule/getActionErrorLog", + "alerting:.es-query/alerts/rule/find", + "alerting:.es-query/alerts/rule/getRuleExecutionKPI", + "alerting:.es-query/alerts/rule/getBackfill", + "alerting:.es-query/alerts/rule/findBackfill", "alerting:observability.rules.custom_threshold/logs/rule/get", "alerting:observability.rules.custom_threshold/logs/rule/getRuleState", "alerting:observability.rules.custom_threshold/logs/rule/getAlertSummary", @@ -1766,6 +2627,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:observability.rules.custom_threshold/logs/rule/getRuleExecutionKPI", "alerting:observability.rules.custom_threshold/logs/rule/getBackfill", "alerting:observability.rules.custom_threshold/logs/rule/findBackfill", + "alerting:observability.rules.custom_threshold/alerts/rule/get", + "alerting:observability.rules.custom_threshold/alerts/rule/getRuleState", + "alerting:observability.rules.custom_threshold/alerts/rule/getAlertSummary", + "alerting:observability.rules.custom_threshold/alerts/rule/getExecutionLog", + "alerting:observability.rules.custom_threshold/alerts/rule/getActionErrorLog", + "alerting:observability.rules.custom_threshold/alerts/rule/find", + "alerting:observability.rules.custom_threshold/alerts/rule/getRuleExecutionKPI", + "alerting:observability.rules.custom_threshold/alerts/rule/getBackfill", + "alerting:observability.rules.custom_threshold/alerts/rule/findBackfill", "alerting:xpack.ml.anomaly_detection_alert/logs/rule/get", "alerting:xpack.ml.anomaly_detection_alert/logs/rule/getRuleState", "alerting:xpack.ml.anomaly_detection_alert/logs/rule/getAlertSummary", @@ -1775,22 +2645,47 @@ export default function ({ getService }: FtrProviderContext) { "alerting:xpack.ml.anomaly_detection_alert/logs/rule/getRuleExecutionKPI", "alerting:xpack.ml.anomaly_detection_alert/logs/rule/getBackfill", "alerting:xpack.ml.anomaly_detection_alert/logs/rule/findBackfill", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/get", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getRuleState", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getAlertSummary", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getExecutionLog", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getActionErrorLog", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/find", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getRuleExecutionKPI", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getBackfill", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/findBackfill", "alerting:logs.alert.document.count/logs/alert/get", "alerting:logs.alert.document.count/logs/alert/find", "alerting:logs.alert.document.count/logs/alert/getAuthorizedAlertsIndices", "alerting:logs.alert.document.count/logs/alert/getAlertSummary", + "alerting:logs.alert.document.count/alerts/alert/get", + "alerting:logs.alert.document.count/alerts/alert/find", + "alerting:logs.alert.document.count/alerts/alert/getAuthorizedAlertsIndices", + "alerting:logs.alert.document.count/alerts/alert/getAlertSummary", "alerting:.es-query/logs/alert/get", "alerting:.es-query/logs/alert/find", "alerting:.es-query/logs/alert/getAuthorizedAlertsIndices", "alerting:.es-query/logs/alert/getAlertSummary", + "alerting:.es-query/alerts/alert/get", + "alerting:.es-query/alerts/alert/find", + "alerting:.es-query/alerts/alert/getAuthorizedAlertsIndices", + "alerting:.es-query/alerts/alert/getAlertSummary", "alerting:observability.rules.custom_threshold/logs/alert/get", "alerting:observability.rules.custom_threshold/logs/alert/find", "alerting:observability.rules.custom_threshold/logs/alert/getAuthorizedAlertsIndices", "alerting:observability.rules.custom_threshold/logs/alert/getAlertSummary", + "alerting:observability.rules.custom_threshold/alerts/alert/get", + "alerting:observability.rules.custom_threshold/alerts/alert/find", + "alerting:observability.rules.custom_threshold/alerts/alert/getAuthorizedAlertsIndices", + "alerting:observability.rules.custom_threshold/alerts/alert/getAlertSummary", "alerting:xpack.ml.anomaly_detection_alert/logs/alert/get", "alerting:xpack.ml.anomaly_detection_alert/logs/alert/find", "alerting:xpack.ml.anomaly_detection_alert/logs/alert/getAuthorizedAlertsIndices", "alerting:xpack.ml.anomaly_detection_alert/logs/alert/getAlertSummary", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/get", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/find", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/getAuthorizedAlertsIndices", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/getAlertSummary", "app:observability", "ui:catalogue/observability", "ui:navLinks/observability", @@ -1804,6 +2699,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:slo.rules.burnRate/observability/rule/getRuleExecutionKPI", "alerting:slo.rules.burnRate/observability/rule/getBackfill", "alerting:slo.rules.burnRate/observability/rule/findBackfill", + "alerting:slo.rules.burnRate/alerts/rule/get", + "alerting:slo.rules.burnRate/alerts/rule/getRuleState", + "alerting:slo.rules.burnRate/alerts/rule/getAlertSummary", + "alerting:slo.rules.burnRate/alerts/rule/getExecutionLog", + "alerting:slo.rules.burnRate/alerts/rule/getActionErrorLog", + "alerting:slo.rules.burnRate/alerts/rule/find", + "alerting:slo.rules.burnRate/alerts/rule/getRuleExecutionKPI", + "alerting:slo.rules.burnRate/alerts/rule/getBackfill", + "alerting:slo.rules.burnRate/alerts/rule/findBackfill", "alerting:observability.rules.custom_threshold/observability/rule/get", "alerting:observability.rules.custom_threshold/observability/rule/getRuleState", "alerting:observability.rules.custom_threshold/observability/rule/getAlertSummary", @@ -1840,6 +2744,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:metrics.alert.inventory.threshold/observability/rule/getRuleExecutionKPI", "alerting:metrics.alert.inventory.threshold/observability/rule/getBackfill", "alerting:metrics.alert.inventory.threshold/observability/rule/findBackfill", + "alerting:metrics.alert.inventory.threshold/alerts/rule/get", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getRuleState", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getAlertSummary", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getExecutionLog", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getActionErrorLog", + "alerting:metrics.alert.inventory.threshold/alerts/rule/find", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getRuleExecutionKPI", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getBackfill", + "alerting:metrics.alert.inventory.threshold/alerts/rule/findBackfill", "alerting:apm.error_rate/observability/rule/get", "alerting:apm.error_rate/observability/rule/getRuleState", "alerting:apm.error_rate/observability/rule/getAlertSummary", @@ -1880,6 +2793,10 @@ export default function ({ getService }: FtrProviderContext) { "alerting:slo.rules.burnRate/observability/alert/find", "alerting:slo.rules.burnRate/observability/alert/getAuthorizedAlertsIndices", "alerting:slo.rules.burnRate/observability/alert/getAlertSummary", + "alerting:slo.rules.burnRate/alerts/alert/get", + "alerting:slo.rules.burnRate/alerts/alert/find", + "alerting:slo.rules.burnRate/alerts/alert/getAuthorizedAlertsIndices", + "alerting:slo.rules.burnRate/alerts/alert/getAlertSummary", "alerting:observability.rules.custom_threshold/observability/alert/get", "alerting:observability.rules.custom_threshold/observability/alert/find", "alerting:observability.rules.custom_threshold/observability/alert/getAuthorizedAlertsIndices", @@ -1896,6 +2813,10 @@ export default function ({ getService }: FtrProviderContext) { "alerting:metrics.alert.inventory.threshold/observability/alert/find", "alerting:metrics.alert.inventory.threshold/observability/alert/getAuthorizedAlertsIndices", "alerting:metrics.alert.inventory.threshold/observability/alert/getAlertSummary", + "alerting:metrics.alert.inventory.threshold/alerts/alert/get", + "alerting:metrics.alert.inventory.threshold/alerts/alert/find", + "alerting:metrics.alert.inventory.threshold/alerts/alert/getAuthorizedAlertsIndices", + "alerting:metrics.alert.inventory.threshold/alerts/alert/getAlertSummary", "alerting:apm.error_rate/observability/alert/get", "alerting:apm.error_rate/observability/alert/find", "alerting:apm.error_rate/observability/alert/getAuthorizedAlertsIndices", @@ -2608,6 +3529,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:slo.rules.burnRate/observability/rule/runSoon", "alerting:slo.rules.burnRate/observability/rule/scheduleBackfill", "alerting:slo.rules.burnRate/observability/rule/deleteBackfill", + "alerting:slo.rules.burnRate/alerts/rule/get", + "alerting:slo.rules.burnRate/alerts/rule/getRuleState", + "alerting:slo.rules.burnRate/alerts/rule/getAlertSummary", + "alerting:slo.rules.burnRate/alerts/rule/getExecutionLog", + "alerting:slo.rules.burnRate/alerts/rule/getActionErrorLog", + "alerting:slo.rules.burnRate/alerts/rule/find", + "alerting:slo.rules.burnRate/alerts/rule/getRuleExecutionKPI", + "alerting:slo.rules.burnRate/alerts/rule/getBackfill", + "alerting:slo.rules.burnRate/alerts/rule/findBackfill", + "alerting:slo.rules.burnRate/alerts/rule/create", + "alerting:slo.rules.burnRate/alerts/rule/delete", + "alerting:slo.rules.burnRate/alerts/rule/update", + "alerting:slo.rules.burnRate/alerts/rule/updateApiKey", + "alerting:slo.rules.burnRate/alerts/rule/enable", + "alerting:slo.rules.burnRate/alerts/rule/disable", + "alerting:slo.rules.burnRate/alerts/rule/muteAll", + "alerting:slo.rules.burnRate/alerts/rule/unmuteAll", + "alerting:slo.rules.burnRate/alerts/rule/muteAlert", + "alerting:slo.rules.burnRate/alerts/rule/unmuteAlert", + "alerting:slo.rules.burnRate/alerts/rule/snooze", + "alerting:slo.rules.burnRate/alerts/rule/bulkEdit", + "alerting:slo.rules.burnRate/alerts/rule/bulkDelete", + "alerting:slo.rules.burnRate/alerts/rule/bulkEnable", + "alerting:slo.rules.burnRate/alerts/rule/bulkDisable", + "alerting:slo.rules.burnRate/alerts/rule/unsnooze", + "alerting:slo.rules.burnRate/alerts/rule/runSoon", + "alerting:slo.rules.burnRate/alerts/rule/scheduleBackfill", + "alerting:slo.rules.burnRate/alerts/rule/deleteBackfill", "alerting:observability.rules.custom_threshold/observability/rule/get", "alerting:observability.rules.custom_threshold/observability/rule/getRuleState", "alerting:observability.rules.custom_threshold/observability/rule/getAlertSummary", @@ -2636,6 +3585,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:observability.rules.custom_threshold/observability/rule/runSoon", "alerting:observability.rules.custom_threshold/observability/rule/scheduleBackfill", "alerting:observability.rules.custom_threshold/observability/rule/deleteBackfill", + "alerting:observability.rules.custom_threshold/alerts/rule/get", + "alerting:observability.rules.custom_threshold/alerts/rule/getRuleState", + "alerting:observability.rules.custom_threshold/alerts/rule/getAlertSummary", + "alerting:observability.rules.custom_threshold/alerts/rule/getExecutionLog", + "alerting:observability.rules.custom_threshold/alerts/rule/getActionErrorLog", + "alerting:observability.rules.custom_threshold/alerts/rule/find", + "alerting:observability.rules.custom_threshold/alerts/rule/getRuleExecutionKPI", + "alerting:observability.rules.custom_threshold/alerts/rule/getBackfill", + "alerting:observability.rules.custom_threshold/alerts/rule/findBackfill", + "alerting:observability.rules.custom_threshold/alerts/rule/create", + "alerting:observability.rules.custom_threshold/alerts/rule/delete", + "alerting:observability.rules.custom_threshold/alerts/rule/update", + "alerting:observability.rules.custom_threshold/alerts/rule/updateApiKey", + "alerting:observability.rules.custom_threshold/alerts/rule/enable", + "alerting:observability.rules.custom_threshold/alerts/rule/disable", + "alerting:observability.rules.custom_threshold/alerts/rule/muteAll", + "alerting:observability.rules.custom_threshold/alerts/rule/unmuteAll", + "alerting:observability.rules.custom_threshold/alerts/rule/muteAlert", + "alerting:observability.rules.custom_threshold/alerts/rule/unmuteAlert", + "alerting:observability.rules.custom_threshold/alerts/rule/snooze", + "alerting:observability.rules.custom_threshold/alerts/rule/bulkEdit", + "alerting:observability.rules.custom_threshold/alerts/rule/bulkDelete", + "alerting:observability.rules.custom_threshold/alerts/rule/bulkEnable", + "alerting:observability.rules.custom_threshold/alerts/rule/bulkDisable", + "alerting:observability.rules.custom_threshold/alerts/rule/unsnooze", + "alerting:observability.rules.custom_threshold/alerts/rule/runSoon", + "alerting:observability.rules.custom_threshold/alerts/rule/scheduleBackfill", + "alerting:observability.rules.custom_threshold/alerts/rule/deleteBackfill", "alerting:.es-query/observability/rule/get", "alerting:.es-query/observability/rule/getRuleState", "alerting:.es-query/observability/rule/getAlertSummary", @@ -2664,6 +3641,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:.es-query/observability/rule/runSoon", "alerting:.es-query/observability/rule/scheduleBackfill", "alerting:.es-query/observability/rule/deleteBackfill", + "alerting:.es-query/alerts/rule/get", + "alerting:.es-query/alerts/rule/getRuleState", + "alerting:.es-query/alerts/rule/getAlertSummary", + "alerting:.es-query/alerts/rule/getExecutionLog", + "alerting:.es-query/alerts/rule/getActionErrorLog", + "alerting:.es-query/alerts/rule/find", + "alerting:.es-query/alerts/rule/getRuleExecutionKPI", + "alerting:.es-query/alerts/rule/getBackfill", + "alerting:.es-query/alerts/rule/findBackfill", + "alerting:.es-query/alerts/rule/create", + "alerting:.es-query/alerts/rule/delete", + "alerting:.es-query/alerts/rule/update", + "alerting:.es-query/alerts/rule/updateApiKey", + "alerting:.es-query/alerts/rule/enable", + "alerting:.es-query/alerts/rule/disable", + "alerting:.es-query/alerts/rule/muteAll", + "alerting:.es-query/alerts/rule/unmuteAll", + "alerting:.es-query/alerts/rule/muteAlert", + "alerting:.es-query/alerts/rule/unmuteAlert", + "alerting:.es-query/alerts/rule/snooze", + "alerting:.es-query/alerts/rule/bulkEdit", + "alerting:.es-query/alerts/rule/bulkDelete", + "alerting:.es-query/alerts/rule/bulkEnable", + "alerting:.es-query/alerts/rule/bulkDisable", + "alerting:.es-query/alerts/rule/unsnooze", + "alerting:.es-query/alerts/rule/runSoon", + "alerting:.es-query/alerts/rule/scheduleBackfill", + "alerting:.es-query/alerts/rule/deleteBackfill", "alerting:xpack.ml.anomaly_detection_alert/observability/rule/get", "alerting:xpack.ml.anomaly_detection_alert/observability/rule/getRuleState", "alerting:xpack.ml.anomaly_detection_alert/observability/rule/getAlertSummary", @@ -2692,6 +3697,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:xpack.ml.anomaly_detection_alert/observability/rule/runSoon", "alerting:xpack.ml.anomaly_detection_alert/observability/rule/scheduleBackfill", "alerting:xpack.ml.anomaly_detection_alert/observability/rule/deleteBackfill", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/get", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getRuleState", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getAlertSummary", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getExecutionLog", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getActionErrorLog", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/find", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getRuleExecutionKPI", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getBackfill", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/findBackfill", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/create", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/delete", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/update", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/updateApiKey", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/enable", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/disable", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/muteAll", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/unmuteAll", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/muteAlert", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/unmuteAlert", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/snooze", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/bulkEdit", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/bulkDelete", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/bulkEnable", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/bulkDisable", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/unsnooze", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/runSoon", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/scheduleBackfill", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/deleteBackfill", "alerting:metrics.alert.inventory.threshold/observability/rule/get", "alerting:metrics.alert.inventory.threshold/observability/rule/getRuleState", "alerting:metrics.alert.inventory.threshold/observability/rule/getAlertSummary", @@ -2720,6 +3753,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:metrics.alert.inventory.threshold/observability/rule/runSoon", "alerting:metrics.alert.inventory.threshold/observability/rule/scheduleBackfill", "alerting:metrics.alert.inventory.threshold/observability/rule/deleteBackfill", + "alerting:metrics.alert.inventory.threshold/alerts/rule/get", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getRuleState", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getAlertSummary", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getExecutionLog", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getActionErrorLog", + "alerting:metrics.alert.inventory.threshold/alerts/rule/find", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getRuleExecutionKPI", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getBackfill", + "alerting:metrics.alert.inventory.threshold/alerts/rule/findBackfill", + "alerting:metrics.alert.inventory.threshold/alerts/rule/create", + "alerting:metrics.alert.inventory.threshold/alerts/rule/delete", + "alerting:metrics.alert.inventory.threshold/alerts/rule/update", + "alerting:metrics.alert.inventory.threshold/alerts/rule/updateApiKey", + "alerting:metrics.alert.inventory.threshold/alerts/rule/enable", + "alerting:metrics.alert.inventory.threshold/alerts/rule/disable", + "alerting:metrics.alert.inventory.threshold/alerts/rule/muteAll", + "alerting:metrics.alert.inventory.threshold/alerts/rule/unmuteAll", + "alerting:metrics.alert.inventory.threshold/alerts/rule/muteAlert", + "alerting:metrics.alert.inventory.threshold/alerts/rule/unmuteAlert", + "alerting:metrics.alert.inventory.threshold/alerts/rule/snooze", + "alerting:metrics.alert.inventory.threshold/alerts/rule/bulkEdit", + "alerting:metrics.alert.inventory.threshold/alerts/rule/bulkDelete", + "alerting:metrics.alert.inventory.threshold/alerts/rule/bulkEnable", + "alerting:metrics.alert.inventory.threshold/alerts/rule/bulkDisable", + "alerting:metrics.alert.inventory.threshold/alerts/rule/unsnooze", + "alerting:metrics.alert.inventory.threshold/alerts/rule/runSoon", + "alerting:metrics.alert.inventory.threshold/alerts/rule/scheduleBackfill", + "alerting:metrics.alert.inventory.threshold/alerts/rule/deleteBackfill", "alerting:apm.error_rate/observability/rule/get", "alerting:apm.error_rate/observability/rule/getRuleState", "alerting:apm.error_rate/observability/rule/getAlertSummary", @@ -2748,6 +3809,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.error_rate/observability/rule/runSoon", "alerting:apm.error_rate/observability/rule/scheduleBackfill", "alerting:apm.error_rate/observability/rule/deleteBackfill", + "alerting:apm.error_rate/alerts/rule/get", + "alerting:apm.error_rate/alerts/rule/getRuleState", + "alerting:apm.error_rate/alerts/rule/getAlertSummary", + "alerting:apm.error_rate/alerts/rule/getExecutionLog", + "alerting:apm.error_rate/alerts/rule/getActionErrorLog", + "alerting:apm.error_rate/alerts/rule/find", + "alerting:apm.error_rate/alerts/rule/getRuleExecutionKPI", + "alerting:apm.error_rate/alerts/rule/getBackfill", + "alerting:apm.error_rate/alerts/rule/findBackfill", + "alerting:apm.error_rate/alerts/rule/create", + "alerting:apm.error_rate/alerts/rule/delete", + "alerting:apm.error_rate/alerts/rule/update", + "alerting:apm.error_rate/alerts/rule/updateApiKey", + "alerting:apm.error_rate/alerts/rule/enable", + "alerting:apm.error_rate/alerts/rule/disable", + "alerting:apm.error_rate/alerts/rule/muteAll", + "alerting:apm.error_rate/alerts/rule/unmuteAll", + "alerting:apm.error_rate/alerts/rule/muteAlert", + "alerting:apm.error_rate/alerts/rule/unmuteAlert", + "alerting:apm.error_rate/alerts/rule/snooze", + "alerting:apm.error_rate/alerts/rule/bulkEdit", + "alerting:apm.error_rate/alerts/rule/bulkDelete", + "alerting:apm.error_rate/alerts/rule/bulkEnable", + "alerting:apm.error_rate/alerts/rule/bulkDisable", + "alerting:apm.error_rate/alerts/rule/unsnooze", + "alerting:apm.error_rate/alerts/rule/runSoon", + "alerting:apm.error_rate/alerts/rule/scheduleBackfill", + "alerting:apm.error_rate/alerts/rule/deleteBackfill", "alerting:apm.transaction_error_rate/observability/rule/get", "alerting:apm.transaction_error_rate/observability/rule/getRuleState", "alerting:apm.transaction_error_rate/observability/rule/getAlertSummary", @@ -2776,6 +3865,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.transaction_error_rate/observability/rule/runSoon", "alerting:apm.transaction_error_rate/observability/rule/scheduleBackfill", "alerting:apm.transaction_error_rate/observability/rule/deleteBackfill", + "alerting:apm.transaction_error_rate/alerts/rule/get", + "alerting:apm.transaction_error_rate/alerts/rule/getRuleState", + "alerting:apm.transaction_error_rate/alerts/rule/getAlertSummary", + "alerting:apm.transaction_error_rate/alerts/rule/getExecutionLog", + "alerting:apm.transaction_error_rate/alerts/rule/getActionErrorLog", + "alerting:apm.transaction_error_rate/alerts/rule/find", + "alerting:apm.transaction_error_rate/alerts/rule/getRuleExecutionKPI", + "alerting:apm.transaction_error_rate/alerts/rule/getBackfill", + "alerting:apm.transaction_error_rate/alerts/rule/findBackfill", + "alerting:apm.transaction_error_rate/alerts/rule/create", + "alerting:apm.transaction_error_rate/alerts/rule/delete", + "alerting:apm.transaction_error_rate/alerts/rule/update", + "alerting:apm.transaction_error_rate/alerts/rule/updateApiKey", + "alerting:apm.transaction_error_rate/alerts/rule/enable", + "alerting:apm.transaction_error_rate/alerts/rule/disable", + "alerting:apm.transaction_error_rate/alerts/rule/muteAll", + "alerting:apm.transaction_error_rate/alerts/rule/unmuteAll", + "alerting:apm.transaction_error_rate/alerts/rule/muteAlert", + "alerting:apm.transaction_error_rate/alerts/rule/unmuteAlert", + "alerting:apm.transaction_error_rate/alerts/rule/snooze", + "alerting:apm.transaction_error_rate/alerts/rule/bulkEdit", + "alerting:apm.transaction_error_rate/alerts/rule/bulkDelete", + "alerting:apm.transaction_error_rate/alerts/rule/bulkEnable", + "alerting:apm.transaction_error_rate/alerts/rule/bulkDisable", + "alerting:apm.transaction_error_rate/alerts/rule/unsnooze", + "alerting:apm.transaction_error_rate/alerts/rule/runSoon", + "alerting:apm.transaction_error_rate/alerts/rule/scheduleBackfill", + "alerting:apm.transaction_error_rate/alerts/rule/deleteBackfill", "alerting:apm.transaction_duration/observability/rule/get", "alerting:apm.transaction_duration/observability/rule/getRuleState", "alerting:apm.transaction_duration/observability/rule/getAlertSummary", @@ -2804,6 +3921,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.transaction_duration/observability/rule/runSoon", "alerting:apm.transaction_duration/observability/rule/scheduleBackfill", "alerting:apm.transaction_duration/observability/rule/deleteBackfill", + "alerting:apm.transaction_duration/alerts/rule/get", + "alerting:apm.transaction_duration/alerts/rule/getRuleState", + "alerting:apm.transaction_duration/alerts/rule/getAlertSummary", + "alerting:apm.transaction_duration/alerts/rule/getExecutionLog", + "alerting:apm.transaction_duration/alerts/rule/getActionErrorLog", + "alerting:apm.transaction_duration/alerts/rule/find", + "alerting:apm.transaction_duration/alerts/rule/getRuleExecutionKPI", + "alerting:apm.transaction_duration/alerts/rule/getBackfill", + "alerting:apm.transaction_duration/alerts/rule/findBackfill", + "alerting:apm.transaction_duration/alerts/rule/create", + "alerting:apm.transaction_duration/alerts/rule/delete", + "alerting:apm.transaction_duration/alerts/rule/update", + "alerting:apm.transaction_duration/alerts/rule/updateApiKey", + "alerting:apm.transaction_duration/alerts/rule/enable", + "alerting:apm.transaction_duration/alerts/rule/disable", + "alerting:apm.transaction_duration/alerts/rule/muteAll", + "alerting:apm.transaction_duration/alerts/rule/unmuteAll", + "alerting:apm.transaction_duration/alerts/rule/muteAlert", + "alerting:apm.transaction_duration/alerts/rule/unmuteAlert", + "alerting:apm.transaction_duration/alerts/rule/snooze", + "alerting:apm.transaction_duration/alerts/rule/bulkEdit", + "alerting:apm.transaction_duration/alerts/rule/bulkDelete", + "alerting:apm.transaction_duration/alerts/rule/bulkEnable", + "alerting:apm.transaction_duration/alerts/rule/bulkDisable", + "alerting:apm.transaction_duration/alerts/rule/unsnooze", + "alerting:apm.transaction_duration/alerts/rule/runSoon", + "alerting:apm.transaction_duration/alerts/rule/scheduleBackfill", + "alerting:apm.transaction_duration/alerts/rule/deleteBackfill", "alerting:apm.anomaly/observability/rule/get", "alerting:apm.anomaly/observability/rule/getRuleState", "alerting:apm.anomaly/observability/rule/getAlertSummary", @@ -2832,51 +3977,124 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.anomaly/observability/rule/runSoon", "alerting:apm.anomaly/observability/rule/scheduleBackfill", "alerting:apm.anomaly/observability/rule/deleteBackfill", + "alerting:apm.anomaly/alerts/rule/get", + "alerting:apm.anomaly/alerts/rule/getRuleState", + "alerting:apm.anomaly/alerts/rule/getAlertSummary", + "alerting:apm.anomaly/alerts/rule/getExecutionLog", + "alerting:apm.anomaly/alerts/rule/getActionErrorLog", + "alerting:apm.anomaly/alerts/rule/find", + "alerting:apm.anomaly/alerts/rule/getRuleExecutionKPI", + "alerting:apm.anomaly/alerts/rule/getBackfill", + "alerting:apm.anomaly/alerts/rule/findBackfill", + "alerting:apm.anomaly/alerts/rule/create", + "alerting:apm.anomaly/alerts/rule/delete", + "alerting:apm.anomaly/alerts/rule/update", + "alerting:apm.anomaly/alerts/rule/updateApiKey", + "alerting:apm.anomaly/alerts/rule/enable", + "alerting:apm.anomaly/alerts/rule/disable", + "alerting:apm.anomaly/alerts/rule/muteAll", + "alerting:apm.anomaly/alerts/rule/unmuteAll", + "alerting:apm.anomaly/alerts/rule/muteAlert", + "alerting:apm.anomaly/alerts/rule/unmuteAlert", + "alerting:apm.anomaly/alerts/rule/snooze", + "alerting:apm.anomaly/alerts/rule/bulkEdit", + "alerting:apm.anomaly/alerts/rule/bulkDelete", + "alerting:apm.anomaly/alerts/rule/bulkEnable", + "alerting:apm.anomaly/alerts/rule/bulkDisable", + "alerting:apm.anomaly/alerts/rule/unsnooze", + "alerting:apm.anomaly/alerts/rule/runSoon", + "alerting:apm.anomaly/alerts/rule/scheduleBackfill", + "alerting:apm.anomaly/alerts/rule/deleteBackfill", "alerting:slo.rules.burnRate/observability/alert/get", "alerting:slo.rules.burnRate/observability/alert/find", "alerting:slo.rules.burnRate/observability/alert/getAuthorizedAlertsIndices", "alerting:slo.rules.burnRate/observability/alert/getAlertSummary", "alerting:slo.rules.burnRate/observability/alert/update", + "alerting:slo.rules.burnRate/alerts/alert/get", + "alerting:slo.rules.burnRate/alerts/alert/find", + "alerting:slo.rules.burnRate/alerts/alert/getAuthorizedAlertsIndices", + "alerting:slo.rules.burnRate/alerts/alert/getAlertSummary", + "alerting:slo.rules.burnRate/alerts/alert/update", "alerting:observability.rules.custom_threshold/observability/alert/get", "alerting:observability.rules.custom_threshold/observability/alert/find", "alerting:observability.rules.custom_threshold/observability/alert/getAuthorizedAlertsIndices", "alerting:observability.rules.custom_threshold/observability/alert/getAlertSummary", "alerting:observability.rules.custom_threshold/observability/alert/update", + "alerting:observability.rules.custom_threshold/alerts/alert/get", + "alerting:observability.rules.custom_threshold/alerts/alert/find", + "alerting:observability.rules.custom_threshold/alerts/alert/getAuthorizedAlertsIndices", + "alerting:observability.rules.custom_threshold/alerts/alert/getAlertSummary", + "alerting:observability.rules.custom_threshold/alerts/alert/update", "alerting:.es-query/observability/alert/get", "alerting:.es-query/observability/alert/find", "alerting:.es-query/observability/alert/getAuthorizedAlertsIndices", "alerting:.es-query/observability/alert/getAlertSummary", "alerting:.es-query/observability/alert/update", + "alerting:.es-query/alerts/alert/get", + "alerting:.es-query/alerts/alert/find", + "alerting:.es-query/alerts/alert/getAuthorizedAlertsIndices", + "alerting:.es-query/alerts/alert/getAlertSummary", + "alerting:.es-query/alerts/alert/update", "alerting:xpack.ml.anomaly_detection_alert/observability/alert/get", "alerting:xpack.ml.anomaly_detection_alert/observability/alert/find", "alerting:xpack.ml.anomaly_detection_alert/observability/alert/getAuthorizedAlertsIndices", "alerting:xpack.ml.anomaly_detection_alert/observability/alert/getAlertSummary", "alerting:xpack.ml.anomaly_detection_alert/observability/alert/update", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/get", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/find", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/getAuthorizedAlertsIndices", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/getAlertSummary", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/update", "alerting:metrics.alert.inventory.threshold/observability/alert/get", "alerting:metrics.alert.inventory.threshold/observability/alert/find", "alerting:metrics.alert.inventory.threshold/observability/alert/getAuthorizedAlertsIndices", "alerting:metrics.alert.inventory.threshold/observability/alert/getAlertSummary", "alerting:metrics.alert.inventory.threshold/observability/alert/update", + "alerting:metrics.alert.inventory.threshold/alerts/alert/get", + "alerting:metrics.alert.inventory.threshold/alerts/alert/find", + "alerting:metrics.alert.inventory.threshold/alerts/alert/getAuthorizedAlertsIndices", + "alerting:metrics.alert.inventory.threshold/alerts/alert/getAlertSummary", + "alerting:metrics.alert.inventory.threshold/alerts/alert/update", "alerting:apm.error_rate/observability/alert/get", "alerting:apm.error_rate/observability/alert/find", "alerting:apm.error_rate/observability/alert/getAuthorizedAlertsIndices", "alerting:apm.error_rate/observability/alert/getAlertSummary", "alerting:apm.error_rate/observability/alert/update", + "alerting:apm.error_rate/alerts/alert/get", + "alerting:apm.error_rate/alerts/alert/find", + "alerting:apm.error_rate/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.error_rate/alerts/alert/getAlertSummary", + "alerting:apm.error_rate/alerts/alert/update", "alerting:apm.transaction_error_rate/observability/alert/get", "alerting:apm.transaction_error_rate/observability/alert/find", "alerting:apm.transaction_error_rate/observability/alert/getAuthorizedAlertsIndices", "alerting:apm.transaction_error_rate/observability/alert/getAlertSummary", "alerting:apm.transaction_error_rate/observability/alert/update", + "alerting:apm.transaction_error_rate/alerts/alert/get", + "alerting:apm.transaction_error_rate/alerts/alert/find", + "alerting:apm.transaction_error_rate/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.transaction_error_rate/alerts/alert/getAlertSummary", + "alerting:apm.transaction_error_rate/alerts/alert/update", "alerting:apm.transaction_duration/observability/alert/get", "alerting:apm.transaction_duration/observability/alert/find", "alerting:apm.transaction_duration/observability/alert/getAuthorizedAlertsIndices", "alerting:apm.transaction_duration/observability/alert/getAlertSummary", "alerting:apm.transaction_duration/observability/alert/update", + "alerting:apm.transaction_duration/alerts/alert/get", + "alerting:apm.transaction_duration/alerts/alert/find", + "alerting:apm.transaction_duration/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.transaction_duration/alerts/alert/getAlertSummary", + "alerting:apm.transaction_duration/alerts/alert/update", "alerting:apm.anomaly/observability/alert/get", "alerting:apm.anomaly/observability/alert/find", "alerting:apm.anomaly/observability/alert/getAuthorizedAlertsIndices", "alerting:apm.anomaly/observability/alert/getAlertSummary", "alerting:apm.anomaly/observability/alert/update", + "alerting:apm.anomaly/alerts/alert/get", + "alerting:apm.anomaly/alerts/alert/find", + "alerting:apm.anomaly/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.anomaly/alerts/alert/getAlertSummary", + "alerting:apm.anomaly/alerts/alert/update", ], "generate_report": Array [ "login:", @@ -2985,6 +4203,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:slo.rules.burnRate/observability/rule/runSoon", "alerting:slo.rules.burnRate/observability/rule/scheduleBackfill", "alerting:slo.rules.burnRate/observability/rule/deleteBackfill", + "alerting:slo.rules.burnRate/alerts/rule/get", + "alerting:slo.rules.burnRate/alerts/rule/getRuleState", + "alerting:slo.rules.burnRate/alerts/rule/getAlertSummary", + "alerting:slo.rules.burnRate/alerts/rule/getExecutionLog", + "alerting:slo.rules.burnRate/alerts/rule/getActionErrorLog", + "alerting:slo.rules.burnRate/alerts/rule/find", + "alerting:slo.rules.burnRate/alerts/rule/getRuleExecutionKPI", + "alerting:slo.rules.burnRate/alerts/rule/getBackfill", + "alerting:slo.rules.burnRate/alerts/rule/findBackfill", + "alerting:slo.rules.burnRate/alerts/rule/create", + "alerting:slo.rules.burnRate/alerts/rule/delete", + "alerting:slo.rules.burnRate/alerts/rule/update", + "alerting:slo.rules.burnRate/alerts/rule/updateApiKey", + "alerting:slo.rules.burnRate/alerts/rule/enable", + "alerting:slo.rules.burnRate/alerts/rule/disable", + "alerting:slo.rules.burnRate/alerts/rule/muteAll", + "alerting:slo.rules.burnRate/alerts/rule/unmuteAll", + "alerting:slo.rules.burnRate/alerts/rule/muteAlert", + "alerting:slo.rules.burnRate/alerts/rule/unmuteAlert", + "alerting:slo.rules.burnRate/alerts/rule/snooze", + "alerting:slo.rules.burnRate/alerts/rule/bulkEdit", + "alerting:slo.rules.burnRate/alerts/rule/bulkDelete", + "alerting:slo.rules.burnRate/alerts/rule/bulkEnable", + "alerting:slo.rules.burnRate/alerts/rule/bulkDisable", + "alerting:slo.rules.burnRate/alerts/rule/unsnooze", + "alerting:slo.rules.burnRate/alerts/rule/runSoon", + "alerting:slo.rules.burnRate/alerts/rule/scheduleBackfill", + "alerting:slo.rules.burnRate/alerts/rule/deleteBackfill", "alerting:observability.rules.custom_threshold/observability/rule/get", "alerting:observability.rules.custom_threshold/observability/rule/getRuleState", "alerting:observability.rules.custom_threshold/observability/rule/getAlertSummary", @@ -3013,6 +4259,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:observability.rules.custom_threshold/observability/rule/runSoon", "alerting:observability.rules.custom_threshold/observability/rule/scheduleBackfill", "alerting:observability.rules.custom_threshold/observability/rule/deleteBackfill", + "alerting:observability.rules.custom_threshold/alerts/rule/get", + "alerting:observability.rules.custom_threshold/alerts/rule/getRuleState", + "alerting:observability.rules.custom_threshold/alerts/rule/getAlertSummary", + "alerting:observability.rules.custom_threshold/alerts/rule/getExecutionLog", + "alerting:observability.rules.custom_threshold/alerts/rule/getActionErrorLog", + "alerting:observability.rules.custom_threshold/alerts/rule/find", + "alerting:observability.rules.custom_threshold/alerts/rule/getRuleExecutionKPI", + "alerting:observability.rules.custom_threshold/alerts/rule/getBackfill", + "alerting:observability.rules.custom_threshold/alerts/rule/findBackfill", + "alerting:observability.rules.custom_threshold/alerts/rule/create", + "alerting:observability.rules.custom_threshold/alerts/rule/delete", + "alerting:observability.rules.custom_threshold/alerts/rule/update", + "alerting:observability.rules.custom_threshold/alerts/rule/updateApiKey", + "alerting:observability.rules.custom_threshold/alerts/rule/enable", + "alerting:observability.rules.custom_threshold/alerts/rule/disable", + "alerting:observability.rules.custom_threshold/alerts/rule/muteAll", + "alerting:observability.rules.custom_threshold/alerts/rule/unmuteAll", + "alerting:observability.rules.custom_threshold/alerts/rule/muteAlert", + "alerting:observability.rules.custom_threshold/alerts/rule/unmuteAlert", + "alerting:observability.rules.custom_threshold/alerts/rule/snooze", + "alerting:observability.rules.custom_threshold/alerts/rule/bulkEdit", + "alerting:observability.rules.custom_threshold/alerts/rule/bulkDelete", + "alerting:observability.rules.custom_threshold/alerts/rule/bulkEnable", + "alerting:observability.rules.custom_threshold/alerts/rule/bulkDisable", + "alerting:observability.rules.custom_threshold/alerts/rule/unsnooze", + "alerting:observability.rules.custom_threshold/alerts/rule/runSoon", + "alerting:observability.rules.custom_threshold/alerts/rule/scheduleBackfill", + "alerting:observability.rules.custom_threshold/alerts/rule/deleteBackfill", "alerting:.es-query/observability/rule/get", "alerting:.es-query/observability/rule/getRuleState", "alerting:.es-query/observability/rule/getAlertSummary", @@ -3041,6 +4315,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:.es-query/observability/rule/runSoon", "alerting:.es-query/observability/rule/scheduleBackfill", "alerting:.es-query/observability/rule/deleteBackfill", + "alerting:.es-query/alerts/rule/get", + "alerting:.es-query/alerts/rule/getRuleState", + "alerting:.es-query/alerts/rule/getAlertSummary", + "alerting:.es-query/alerts/rule/getExecutionLog", + "alerting:.es-query/alerts/rule/getActionErrorLog", + "alerting:.es-query/alerts/rule/find", + "alerting:.es-query/alerts/rule/getRuleExecutionKPI", + "alerting:.es-query/alerts/rule/getBackfill", + "alerting:.es-query/alerts/rule/findBackfill", + "alerting:.es-query/alerts/rule/create", + "alerting:.es-query/alerts/rule/delete", + "alerting:.es-query/alerts/rule/update", + "alerting:.es-query/alerts/rule/updateApiKey", + "alerting:.es-query/alerts/rule/enable", + "alerting:.es-query/alerts/rule/disable", + "alerting:.es-query/alerts/rule/muteAll", + "alerting:.es-query/alerts/rule/unmuteAll", + "alerting:.es-query/alerts/rule/muteAlert", + "alerting:.es-query/alerts/rule/unmuteAlert", + "alerting:.es-query/alerts/rule/snooze", + "alerting:.es-query/alerts/rule/bulkEdit", + "alerting:.es-query/alerts/rule/bulkDelete", + "alerting:.es-query/alerts/rule/bulkEnable", + "alerting:.es-query/alerts/rule/bulkDisable", + "alerting:.es-query/alerts/rule/unsnooze", + "alerting:.es-query/alerts/rule/runSoon", + "alerting:.es-query/alerts/rule/scheduleBackfill", + "alerting:.es-query/alerts/rule/deleteBackfill", "alerting:xpack.ml.anomaly_detection_alert/observability/rule/get", "alerting:xpack.ml.anomaly_detection_alert/observability/rule/getRuleState", "alerting:xpack.ml.anomaly_detection_alert/observability/rule/getAlertSummary", @@ -3069,6 +4371,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:xpack.ml.anomaly_detection_alert/observability/rule/runSoon", "alerting:xpack.ml.anomaly_detection_alert/observability/rule/scheduleBackfill", "alerting:xpack.ml.anomaly_detection_alert/observability/rule/deleteBackfill", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/get", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getRuleState", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getAlertSummary", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getExecutionLog", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getActionErrorLog", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/find", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getRuleExecutionKPI", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getBackfill", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/findBackfill", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/create", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/delete", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/update", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/updateApiKey", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/enable", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/disable", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/muteAll", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/unmuteAll", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/muteAlert", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/unmuteAlert", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/snooze", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/bulkEdit", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/bulkDelete", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/bulkEnable", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/bulkDisable", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/unsnooze", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/runSoon", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/scheduleBackfill", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/deleteBackfill", "alerting:metrics.alert.inventory.threshold/observability/rule/get", "alerting:metrics.alert.inventory.threshold/observability/rule/getRuleState", "alerting:metrics.alert.inventory.threshold/observability/rule/getAlertSummary", @@ -3097,6 +4427,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:metrics.alert.inventory.threshold/observability/rule/runSoon", "alerting:metrics.alert.inventory.threshold/observability/rule/scheduleBackfill", "alerting:metrics.alert.inventory.threshold/observability/rule/deleteBackfill", + "alerting:metrics.alert.inventory.threshold/alerts/rule/get", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getRuleState", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getAlertSummary", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getExecutionLog", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getActionErrorLog", + "alerting:metrics.alert.inventory.threshold/alerts/rule/find", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getRuleExecutionKPI", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getBackfill", + "alerting:metrics.alert.inventory.threshold/alerts/rule/findBackfill", + "alerting:metrics.alert.inventory.threshold/alerts/rule/create", + "alerting:metrics.alert.inventory.threshold/alerts/rule/delete", + "alerting:metrics.alert.inventory.threshold/alerts/rule/update", + "alerting:metrics.alert.inventory.threshold/alerts/rule/updateApiKey", + "alerting:metrics.alert.inventory.threshold/alerts/rule/enable", + "alerting:metrics.alert.inventory.threshold/alerts/rule/disable", + "alerting:metrics.alert.inventory.threshold/alerts/rule/muteAll", + "alerting:metrics.alert.inventory.threshold/alerts/rule/unmuteAll", + "alerting:metrics.alert.inventory.threshold/alerts/rule/muteAlert", + "alerting:metrics.alert.inventory.threshold/alerts/rule/unmuteAlert", + "alerting:metrics.alert.inventory.threshold/alerts/rule/snooze", + "alerting:metrics.alert.inventory.threshold/alerts/rule/bulkEdit", + "alerting:metrics.alert.inventory.threshold/alerts/rule/bulkDelete", + "alerting:metrics.alert.inventory.threshold/alerts/rule/bulkEnable", + "alerting:metrics.alert.inventory.threshold/alerts/rule/bulkDisable", + "alerting:metrics.alert.inventory.threshold/alerts/rule/unsnooze", + "alerting:metrics.alert.inventory.threshold/alerts/rule/runSoon", + "alerting:metrics.alert.inventory.threshold/alerts/rule/scheduleBackfill", + "alerting:metrics.alert.inventory.threshold/alerts/rule/deleteBackfill", "alerting:apm.error_rate/observability/rule/get", "alerting:apm.error_rate/observability/rule/getRuleState", "alerting:apm.error_rate/observability/rule/getAlertSummary", @@ -3125,6 +4483,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.error_rate/observability/rule/runSoon", "alerting:apm.error_rate/observability/rule/scheduleBackfill", "alerting:apm.error_rate/observability/rule/deleteBackfill", + "alerting:apm.error_rate/alerts/rule/get", + "alerting:apm.error_rate/alerts/rule/getRuleState", + "alerting:apm.error_rate/alerts/rule/getAlertSummary", + "alerting:apm.error_rate/alerts/rule/getExecutionLog", + "alerting:apm.error_rate/alerts/rule/getActionErrorLog", + "alerting:apm.error_rate/alerts/rule/find", + "alerting:apm.error_rate/alerts/rule/getRuleExecutionKPI", + "alerting:apm.error_rate/alerts/rule/getBackfill", + "alerting:apm.error_rate/alerts/rule/findBackfill", + "alerting:apm.error_rate/alerts/rule/create", + "alerting:apm.error_rate/alerts/rule/delete", + "alerting:apm.error_rate/alerts/rule/update", + "alerting:apm.error_rate/alerts/rule/updateApiKey", + "alerting:apm.error_rate/alerts/rule/enable", + "alerting:apm.error_rate/alerts/rule/disable", + "alerting:apm.error_rate/alerts/rule/muteAll", + "alerting:apm.error_rate/alerts/rule/unmuteAll", + "alerting:apm.error_rate/alerts/rule/muteAlert", + "alerting:apm.error_rate/alerts/rule/unmuteAlert", + "alerting:apm.error_rate/alerts/rule/snooze", + "alerting:apm.error_rate/alerts/rule/bulkEdit", + "alerting:apm.error_rate/alerts/rule/bulkDelete", + "alerting:apm.error_rate/alerts/rule/bulkEnable", + "alerting:apm.error_rate/alerts/rule/bulkDisable", + "alerting:apm.error_rate/alerts/rule/unsnooze", + "alerting:apm.error_rate/alerts/rule/runSoon", + "alerting:apm.error_rate/alerts/rule/scheduleBackfill", + "alerting:apm.error_rate/alerts/rule/deleteBackfill", "alerting:apm.transaction_error_rate/observability/rule/get", "alerting:apm.transaction_error_rate/observability/rule/getRuleState", "alerting:apm.transaction_error_rate/observability/rule/getAlertSummary", @@ -3153,6 +4539,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.transaction_error_rate/observability/rule/runSoon", "alerting:apm.transaction_error_rate/observability/rule/scheduleBackfill", "alerting:apm.transaction_error_rate/observability/rule/deleteBackfill", + "alerting:apm.transaction_error_rate/alerts/rule/get", + "alerting:apm.transaction_error_rate/alerts/rule/getRuleState", + "alerting:apm.transaction_error_rate/alerts/rule/getAlertSummary", + "alerting:apm.transaction_error_rate/alerts/rule/getExecutionLog", + "alerting:apm.transaction_error_rate/alerts/rule/getActionErrorLog", + "alerting:apm.transaction_error_rate/alerts/rule/find", + "alerting:apm.transaction_error_rate/alerts/rule/getRuleExecutionKPI", + "alerting:apm.transaction_error_rate/alerts/rule/getBackfill", + "alerting:apm.transaction_error_rate/alerts/rule/findBackfill", + "alerting:apm.transaction_error_rate/alerts/rule/create", + "alerting:apm.transaction_error_rate/alerts/rule/delete", + "alerting:apm.transaction_error_rate/alerts/rule/update", + "alerting:apm.transaction_error_rate/alerts/rule/updateApiKey", + "alerting:apm.transaction_error_rate/alerts/rule/enable", + "alerting:apm.transaction_error_rate/alerts/rule/disable", + "alerting:apm.transaction_error_rate/alerts/rule/muteAll", + "alerting:apm.transaction_error_rate/alerts/rule/unmuteAll", + "alerting:apm.transaction_error_rate/alerts/rule/muteAlert", + "alerting:apm.transaction_error_rate/alerts/rule/unmuteAlert", + "alerting:apm.transaction_error_rate/alerts/rule/snooze", + "alerting:apm.transaction_error_rate/alerts/rule/bulkEdit", + "alerting:apm.transaction_error_rate/alerts/rule/bulkDelete", + "alerting:apm.transaction_error_rate/alerts/rule/bulkEnable", + "alerting:apm.transaction_error_rate/alerts/rule/bulkDisable", + "alerting:apm.transaction_error_rate/alerts/rule/unsnooze", + "alerting:apm.transaction_error_rate/alerts/rule/runSoon", + "alerting:apm.transaction_error_rate/alerts/rule/scheduleBackfill", + "alerting:apm.transaction_error_rate/alerts/rule/deleteBackfill", "alerting:apm.transaction_duration/observability/rule/get", "alerting:apm.transaction_duration/observability/rule/getRuleState", "alerting:apm.transaction_duration/observability/rule/getAlertSummary", @@ -3181,6 +4595,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.transaction_duration/observability/rule/runSoon", "alerting:apm.transaction_duration/observability/rule/scheduleBackfill", "alerting:apm.transaction_duration/observability/rule/deleteBackfill", + "alerting:apm.transaction_duration/alerts/rule/get", + "alerting:apm.transaction_duration/alerts/rule/getRuleState", + "alerting:apm.transaction_duration/alerts/rule/getAlertSummary", + "alerting:apm.transaction_duration/alerts/rule/getExecutionLog", + "alerting:apm.transaction_duration/alerts/rule/getActionErrorLog", + "alerting:apm.transaction_duration/alerts/rule/find", + "alerting:apm.transaction_duration/alerts/rule/getRuleExecutionKPI", + "alerting:apm.transaction_duration/alerts/rule/getBackfill", + "alerting:apm.transaction_duration/alerts/rule/findBackfill", + "alerting:apm.transaction_duration/alerts/rule/create", + "alerting:apm.transaction_duration/alerts/rule/delete", + "alerting:apm.transaction_duration/alerts/rule/update", + "alerting:apm.transaction_duration/alerts/rule/updateApiKey", + "alerting:apm.transaction_duration/alerts/rule/enable", + "alerting:apm.transaction_duration/alerts/rule/disable", + "alerting:apm.transaction_duration/alerts/rule/muteAll", + "alerting:apm.transaction_duration/alerts/rule/unmuteAll", + "alerting:apm.transaction_duration/alerts/rule/muteAlert", + "alerting:apm.transaction_duration/alerts/rule/unmuteAlert", + "alerting:apm.transaction_duration/alerts/rule/snooze", + "alerting:apm.transaction_duration/alerts/rule/bulkEdit", + "alerting:apm.transaction_duration/alerts/rule/bulkDelete", + "alerting:apm.transaction_duration/alerts/rule/bulkEnable", + "alerting:apm.transaction_duration/alerts/rule/bulkDisable", + "alerting:apm.transaction_duration/alerts/rule/unsnooze", + "alerting:apm.transaction_duration/alerts/rule/runSoon", + "alerting:apm.transaction_duration/alerts/rule/scheduleBackfill", + "alerting:apm.transaction_duration/alerts/rule/deleteBackfill", "alerting:apm.anomaly/observability/rule/get", "alerting:apm.anomaly/observability/rule/getRuleState", "alerting:apm.anomaly/observability/rule/getAlertSummary", @@ -3209,51 +4651,124 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.anomaly/observability/rule/runSoon", "alerting:apm.anomaly/observability/rule/scheduleBackfill", "alerting:apm.anomaly/observability/rule/deleteBackfill", + "alerting:apm.anomaly/alerts/rule/get", + "alerting:apm.anomaly/alerts/rule/getRuleState", + "alerting:apm.anomaly/alerts/rule/getAlertSummary", + "alerting:apm.anomaly/alerts/rule/getExecutionLog", + "alerting:apm.anomaly/alerts/rule/getActionErrorLog", + "alerting:apm.anomaly/alerts/rule/find", + "alerting:apm.anomaly/alerts/rule/getRuleExecutionKPI", + "alerting:apm.anomaly/alerts/rule/getBackfill", + "alerting:apm.anomaly/alerts/rule/findBackfill", + "alerting:apm.anomaly/alerts/rule/create", + "alerting:apm.anomaly/alerts/rule/delete", + "alerting:apm.anomaly/alerts/rule/update", + "alerting:apm.anomaly/alerts/rule/updateApiKey", + "alerting:apm.anomaly/alerts/rule/enable", + "alerting:apm.anomaly/alerts/rule/disable", + "alerting:apm.anomaly/alerts/rule/muteAll", + "alerting:apm.anomaly/alerts/rule/unmuteAll", + "alerting:apm.anomaly/alerts/rule/muteAlert", + "alerting:apm.anomaly/alerts/rule/unmuteAlert", + "alerting:apm.anomaly/alerts/rule/snooze", + "alerting:apm.anomaly/alerts/rule/bulkEdit", + "alerting:apm.anomaly/alerts/rule/bulkDelete", + "alerting:apm.anomaly/alerts/rule/bulkEnable", + "alerting:apm.anomaly/alerts/rule/bulkDisable", + "alerting:apm.anomaly/alerts/rule/unsnooze", + "alerting:apm.anomaly/alerts/rule/runSoon", + "alerting:apm.anomaly/alerts/rule/scheduleBackfill", + "alerting:apm.anomaly/alerts/rule/deleteBackfill", "alerting:slo.rules.burnRate/observability/alert/get", "alerting:slo.rules.burnRate/observability/alert/find", "alerting:slo.rules.burnRate/observability/alert/getAuthorizedAlertsIndices", "alerting:slo.rules.burnRate/observability/alert/getAlertSummary", "alerting:slo.rules.burnRate/observability/alert/update", + "alerting:slo.rules.burnRate/alerts/alert/get", + "alerting:slo.rules.burnRate/alerts/alert/find", + "alerting:slo.rules.burnRate/alerts/alert/getAuthorizedAlertsIndices", + "alerting:slo.rules.burnRate/alerts/alert/getAlertSummary", + "alerting:slo.rules.burnRate/alerts/alert/update", "alerting:observability.rules.custom_threshold/observability/alert/get", "alerting:observability.rules.custom_threshold/observability/alert/find", "alerting:observability.rules.custom_threshold/observability/alert/getAuthorizedAlertsIndices", "alerting:observability.rules.custom_threshold/observability/alert/getAlertSummary", "alerting:observability.rules.custom_threshold/observability/alert/update", + "alerting:observability.rules.custom_threshold/alerts/alert/get", + "alerting:observability.rules.custom_threshold/alerts/alert/find", + "alerting:observability.rules.custom_threshold/alerts/alert/getAuthorizedAlertsIndices", + "alerting:observability.rules.custom_threshold/alerts/alert/getAlertSummary", + "alerting:observability.rules.custom_threshold/alerts/alert/update", "alerting:.es-query/observability/alert/get", "alerting:.es-query/observability/alert/find", "alerting:.es-query/observability/alert/getAuthorizedAlertsIndices", "alerting:.es-query/observability/alert/getAlertSummary", "alerting:.es-query/observability/alert/update", + "alerting:.es-query/alerts/alert/get", + "alerting:.es-query/alerts/alert/find", + "alerting:.es-query/alerts/alert/getAuthorizedAlertsIndices", + "alerting:.es-query/alerts/alert/getAlertSummary", + "alerting:.es-query/alerts/alert/update", "alerting:xpack.ml.anomaly_detection_alert/observability/alert/get", "alerting:xpack.ml.anomaly_detection_alert/observability/alert/find", "alerting:xpack.ml.anomaly_detection_alert/observability/alert/getAuthorizedAlertsIndices", "alerting:xpack.ml.anomaly_detection_alert/observability/alert/getAlertSummary", "alerting:xpack.ml.anomaly_detection_alert/observability/alert/update", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/get", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/find", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/getAuthorizedAlertsIndices", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/getAlertSummary", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/update", "alerting:metrics.alert.inventory.threshold/observability/alert/get", "alerting:metrics.alert.inventory.threshold/observability/alert/find", "alerting:metrics.alert.inventory.threshold/observability/alert/getAuthorizedAlertsIndices", "alerting:metrics.alert.inventory.threshold/observability/alert/getAlertSummary", "alerting:metrics.alert.inventory.threshold/observability/alert/update", + "alerting:metrics.alert.inventory.threshold/alerts/alert/get", + "alerting:metrics.alert.inventory.threshold/alerts/alert/find", + "alerting:metrics.alert.inventory.threshold/alerts/alert/getAuthorizedAlertsIndices", + "alerting:metrics.alert.inventory.threshold/alerts/alert/getAlertSummary", + "alerting:metrics.alert.inventory.threshold/alerts/alert/update", "alerting:apm.error_rate/observability/alert/get", "alerting:apm.error_rate/observability/alert/find", "alerting:apm.error_rate/observability/alert/getAuthorizedAlertsIndices", "alerting:apm.error_rate/observability/alert/getAlertSummary", "alerting:apm.error_rate/observability/alert/update", + "alerting:apm.error_rate/alerts/alert/get", + "alerting:apm.error_rate/alerts/alert/find", + "alerting:apm.error_rate/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.error_rate/alerts/alert/getAlertSummary", + "alerting:apm.error_rate/alerts/alert/update", "alerting:apm.transaction_error_rate/observability/alert/get", "alerting:apm.transaction_error_rate/observability/alert/find", "alerting:apm.transaction_error_rate/observability/alert/getAuthorizedAlertsIndices", "alerting:apm.transaction_error_rate/observability/alert/getAlertSummary", "alerting:apm.transaction_error_rate/observability/alert/update", + "alerting:apm.transaction_error_rate/alerts/alert/get", + "alerting:apm.transaction_error_rate/alerts/alert/find", + "alerting:apm.transaction_error_rate/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.transaction_error_rate/alerts/alert/getAlertSummary", + "alerting:apm.transaction_error_rate/alerts/alert/update", "alerting:apm.transaction_duration/observability/alert/get", "alerting:apm.transaction_duration/observability/alert/find", "alerting:apm.transaction_duration/observability/alert/getAuthorizedAlertsIndices", "alerting:apm.transaction_duration/observability/alert/getAlertSummary", "alerting:apm.transaction_duration/observability/alert/update", + "alerting:apm.transaction_duration/alerts/alert/get", + "alerting:apm.transaction_duration/alerts/alert/find", + "alerting:apm.transaction_duration/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.transaction_duration/alerts/alert/getAlertSummary", + "alerting:apm.transaction_duration/alerts/alert/update", "alerting:apm.anomaly/observability/alert/get", "alerting:apm.anomaly/observability/alert/find", "alerting:apm.anomaly/observability/alert/getAuthorizedAlertsIndices", "alerting:apm.anomaly/observability/alert/getAlertSummary", "alerting:apm.anomaly/observability/alert/update", + "alerting:apm.anomaly/alerts/alert/get", + "alerting:apm.anomaly/alerts/alert/find", + "alerting:apm.anomaly/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.anomaly/alerts/alert/getAlertSummary", + "alerting:apm.anomaly/alerts/alert/update", ], "minimal_read": Array [ "login:", @@ -3312,6 +4827,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:slo.rules.burnRate/observability/rule/getRuleExecutionKPI", "alerting:slo.rules.burnRate/observability/rule/getBackfill", "alerting:slo.rules.burnRate/observability/rule/findBackfill", + "alerting:slo.rules.burnRate/alerts/rule/get", + "alerting:slo.rules.burnRate/alerts/rule/getRuleState", + "alerting:slo.rules.burnRate/alerts/rule/getAlertSummary", + "alerting:slo.rules.burnRate/alerts/rule/getExecutionLog", + "alerting:slo.rules.burnRate/alerts/rule/getActionErrorLog", + "alerting:slo.rules.burnRate/alerts/rule/find", + "alerting:slo.rules.burnRate/alerts/rule/getRuleExecutionKPI", + "alerting:slo.rules.burnRate/alerts/rule/getBackfill", + "alerting:slo.rules.burnRate/alerts/rule/findBackfill", "alerting:observability.rules.custom_threshold/observability/rule/get", "alerting:observability.rules.custom_threshold/observability/rule/getRuleState", "alerting:observability.rules.custom_threshold/observability/rule/getAlertSummary", @@ -3321,6 +4845,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:observability.rules.custom_threshold/observability/rule/getRuleExecutionKPI", "alerting:observability.rules.custom_threshold/observability/rule/getBackfill", "alerting:observability.rules.custom_threshold/observability/rule/findBackfill", + "alerting:observability.rules.custom_threshold/alerts/rule/get", + "alerting:observability.rules.custom_threshold/alerts/rule/getRuleState", + "alerting:observability.rules.custom_threshold/alerts/rule/getAlertSummary", + "alerting:observability.rules.custom_threshold/alerts/rule/getExecutionLog", + "alerting:observability.rules.custom_threshold/alerts/rule/getActionErrorLog", + "alerting:observability.rules.custom_threshold/alerts/rule/find", + "alerting:observability.rules.custom_threshold/alerts/rule/getRuleExecutionKPI", + "alerting:observability.rules.custom_threshold/alerts/rule/getBackfill", + "alerting:observability.rules.custom_threshold/alerts/rule/findBackfill", "alerting:.es-query/observability/rule/get", "alerting:.es-query/observability/rule/getRuleState", "alerting:.es-query/observability/rule/getAlertSummary", @@ -3330,6 +4863,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:.es-query/observability/rule/getRuleExecutionKPI", "alerting:.es-query/observability/rule/getBackfill", "alerting:.es-query/observability/rule/findBackfill", + "alerting:.es-query/alerts/rule/get", + "alerting:.es-query/alerts/rule/getRuleState", + "alerting:.es-query/alerts/rule/getAlertSummary", + "alerting:.es-query/alerts/rule/getExecutionLog", + "alerting:.es-query/alerts/rule/getActionErrorLog", + "alerting:.es-query/alerts/rule/find", + "alerting:.es-query/alerts/rule/getRuleExecutionKPI", + "alerting:.es-query/alerts/rule/getBackfill", + "alerting:.es-query/alerts/rule/findBackfill", "alerting:xpack.ml.anomaly_detection_alert/observability/rule/get", "alerting:xpack.ml.anomaly_detection_alert/observability/rule/getRuleState", "alerting:xpack.ml.anomaly_detection_alert/observability/rule/getAlertSummary", @@ -3339,6 +4881,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:xpack.ml.anomaly_detection_alert/observability/rule/getRuleExecutionKPI", "alerting:xpack.ml.anomaly_detection_alert/observability/rule/getBackfill", "alerting:xpack.ml.anomaly_detection_alert/observability/rule/findBackfill", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/get", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getRuleState", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getAlertSummary", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getExecutionLog", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getActionErrorLog", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/find", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getRuleExecutionKPI", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getBackfill", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/findBackfill", "alerting:metrics.alert.inventory.threshold/observability/rule/get", "alerting:metrics.alert.inventory.threshold/observability/rule/getRuleState", "alerting:metrics.alert.inventory.threshold/observability/rule/getAlertSummary", @@ -3348,6 +4899,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:metrics.alert.inventory.threshold/observability/rule/getRuleExecutionKPI", "alerting:metrics.alert.inventory.threshold/observability/rule/getBackfill", "alerting:metrics.alert.inventory.threshold/observability/rule/findBackfill", + "alerting:metrics.alert.inventory.threshold/alerts/rule/get", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getRuleState", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getAlertSummary", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getExecutionLog", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getActionErrorLog", + "alerting:metrics.alert.inventory.threshold/alerts/rule/find", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getRuleExecutionKPI", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getBackfill", + "alerting:metrics.alert.inventory.threshold/alerts/rule/findBackfill", "alerting:apm.error_rate/observability/rule/get", "alerting:apm.error_rate/observability/rule/getRuleState", "alerting:apm.error_rate/observability/rule/getAlertSummary", @@ -3357,6 +4917,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.error_rate/observability/rule/getRuleExecutionKPI", "alerting:apm.error_rate/observability/rule/getBackfill", "alerting:apm.error_rate/observability/rule/findBackfill", + "alerting:apm.error_rate/alerts/rule/get", + "alerting:apm.error_rate/alerts/rule/getRuleState", + "alerting:apm.error_rate/alerts/rule/getAlertSummary", + "alerting:apm.error_rate/alerts/rule/getExecutionLog", + "alerting:apm.error_rate/alerts/rule/getActionErrorLog", + "alerting:apm.error_rate/alerts/rule/find", + "alerting:apm.error_rate/alerts/rule/getRuleExecutionKPI", + "alerting:apm.error_rate/alerts/rule/getBackfill", + "alerting:apm.error_rate/alerts/rule/findBackfill", "alerting:apm.transaction_error_rate/observability/rule/get", "alerting:apm.transaction_error_rate/observability/rule/getRuleState", "alerting:apm.transaction_error_rate/observability/rule/getAlertSummary", @@ -3366,6 +4935,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.transaction_error_rate/observability/rule/getRuleExecutionKPI", "alerting:apm.transaction_error_rate/observability/rule/getBackfill", "alerting:apm.transaction_error_rate/observability/rule/findBackfill", + "alerting:apm.transaction_error_rate/alerts/rule/get", + "alerting:apm.transaction_error_rate/alerts/rule/getRuleState", + "alerting:apm.transaction_error_rate/alerts/rule/getAlertSummary", + "alerting:apm.transaction_error_rate/alerts/rule/getExecutionLog", + "alerting:apm.transaction_error_rate/alerts/rule/getActionErrorLog", + "alerting:apm.transaction_error_rate/alerts/rule/find", + "alerting:apm.transaction_error_rate/alerts/rule/getRuleExecutionKPI", + "alerting:apm.transaction_error_rate/alerts/rule/getBackfill", + "alerting:apm.transaction_error_rate/alerts/rule/findBackfill", "alerting:apm.transaction_duration/observability/rule/get", "alerting:apm.transaction_duration/observability/rule/getRuleState", "alerting:apm.transaction_duration/observability/rule/getAlertSummary", @@ -3375,6 +4953,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.transaction_duration/observability/rule/getRuleExecutionKPI", "alerting:apm.transaction_duration/observability/rule/getBackfill", "alerting:apm.transaction_duration/observability/rule/findBackfill", + "alerting:apm.transaction_duration/alerts/rule/get", + "alerting:apm.transaction_duration/alerts/rule/getRuleState", + "alerting:apm.transaction_duration/alerts/rule/getAlertSummary", + "alerting:apm.transaction_duration/alerts/rule/getExecutionLog", + "alerting:apm.transaction_duration/alerts/rule/getActionErrorLog", + "alerting:apm.transaction_duration/alerts/rule/find", + "alerting:apm.transaction_duration/alerts/rule/getRuleExecutionKPI", + "alerting:apm.transaction_duration/alerts/rule/getBackfill", + "alerting:apm.transaction_duration/alerts/rule/findBackfill", "alerting:apm.anomaly/observability/rule/get", "alerting:apm.anomaly/observability/rule/getRuleState", "alerting:apm.anomaly/observability/rule/getAlertSummary", @@ -3384,42 +4971,87 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.anomaly/observability/rule/getRuleExecutionKPI", "alerting:apm.anomaly/observability/rule/getBackfill", "alerting:apm.anomaly/observability/rule/findBackfill", + "alerting:apm.anomaly/alerts/rule/get", + "alerting:apm.anomaly/alerts/rule/getRuleState", + "alerting:apm.anomaly/alerts/rule/getAlertSummary", + "alerting:apm.anomaly/alerts/rule/getExecutionLog", + "alerting:apm.anomaly/alerts/rule/getActionErrorLog", + "alerting:apm.anomaly/alerts/rule/find", + "alerting:apm.anomaly/alerts/rule/getRuleExecutionKPI", + "alerting:apm.anomaly/alerts/rule/getBackfill", + "alerting:apm.anomaly/alerts/rule/findBackfill", "alerting:slo.rules.burnRate/observability/alert/get", "alerting:slo.rules.burnRate/observability/alert/find", "alerting:slo.rules.burnRate/observability/alert/getAuthorizedAlertsIndices", "alerting:slo.rules.burnRate/observability/alert/getAlertSummary", + "alerting:slo.rules.burnRate/alerts/alert/get", + "alerting:slo.rules.burnRate/alerts/alert/find", + "alerting:slo.rules.burnRate/alerts/alert/getAuthorizedAlertsIndices", + "alerting:slo.rules.burnRate/alerts/alert/getAlertSummary", "alerting:observability.rules.custom_threshold/observability/alert/get", "alerting:observability.rules.custom_threshold/observability/alert/find", "alerting:observability.rules.custom_threshold/observability/alert/getAuthorizedAlertsIndices", "alerting:observability.rules.custom_threshold/observability/alert/getAlertSummary", + "alerting:observability.rules.custom_threshold/alerts/alert/get", + "alerting:observability.rules.custom_threshold/alerts/alert/find", + "alerting:observability.rules.custom_threshold/alerts/alert/getAuthorizedAlertsIndices", + "alerting:observability.rules.custom_threshold/alerts/alert/getAlertSummary", "alerting:.es-query/observability/alert/get", "alerting:.es-query/observability/alert/find", "alerting:.es-query/observability/alert/getAuthorizedAlertsIndices", "alerting:.es-query/observability/alert/getAlertSummary", + "alerting:.es-query/alerts/alert/get", + "alerting:.es-query/alerts/alert/find", + "alerting:.es-query/alerts/alert/getAuthorizedAlertsIndices", + "alerting:.es-query/alerts/alert/getAlertSummary", "alerting:xpack.ml.anomaly_detection_alert/observability/alert/get", "alerting:xpack.ml.anomaly_detection_alert/observability/alert/find", "alerting:xpack.ml.anomaly_detection_alert/observability/alert/getAuthorizedAlertsIndices", "alerting:xpack.ml.anomaly_detection_alert/observability/alert/getAlertSummary", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/get", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/find", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/getAuthorizedAlertsIndices", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/getAlertSummary", "alerting:metrics.alert.inventory.threshold/observability/alert/get", "alerting:metrics.alert.inventory.threshold/observability/alert/find", "alerting:metrics.alert.inventory.threshold/observability/alert/getAuthorizedAlertsIndices", "alerting:metrics.alert.inventory.threshold/observability/alert/getAlertSummary", + "alerting:metrics.alert.inventory.threshold/alerts/alert/get", + "alerting:metrics.alert.inventory.threshold/alerts/alert/find", + "alerting:metrics.alert.inventory.threshold/alerts/alert/getAuthorizedAlertsIndices", + "alerting:metrics.alert.inventory.threshold/alerts/alert/getAlertSummary", "alerting:apm.error_rate/observability/alert/get", "alerting:apm.error_rate/observability/alert/find", "alerting:apm.error_rate/observability/alert/getAuthorizedAlertsIndices", "alerting:apm.error_rate/observability/alert/getAlertSummary", + "alerting:apm.error_rate/alerts/alert/get", + "alerting:apm.error_rate/alerts/alert/find", + "alerting:apm.error_rate/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.error_rate/alerts/alert/getAlertSummary", "alerting:apm.transaction_error_rate/observability/alert/get", "alerting:apm.transaction_error_rate/observability/alert/find", "alerting:apm.transaction_error_rate/observability/alert/getAuthorizedAlertsIndices", "alerting:apm.transaction_error_rate/observability/alert/getAlertSummary", + "alerting:apm.transaction_error_rate/alerts/alert/get", + "alerting:apm.transaction_error_rate/alerts/alert/find", + "alerting:apm.transaction_error_rate/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.transaction_error_rate/alerts/alert/getAlertSummary", "alerting:apm.transaction_duration/observability/alert/get", "alerting:apm.transaction_duration/observability/alert/find", "alerting:apm.transaction_duration/observability/alert/getAuthorizedAlertsIndices", "alerting:apm.transaction_duration/observability/alert/getAlertSummary", + "alerting:apm.transaction_duration/alerts/alert/get", + "alerting:apm.transaction_duration/alerts/alert/find", + "alerting:apm.transaction_duration/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.transaction_duration/alerts/alert/getAlertSummary", "alerting:apm.anomaly/observability/alert/get", "alerting:apm.anomaly/observability/alert/find", "alerting:apm.anomaly/observability/alert/getAuthorizedAlertsIndices", "alerting:apm.anomaly/observability/alert/getAlertSummary", + "alerting:apm.anomaly/alerts/alert/get", + "alerting:apm.anomaly/alerts/alert/find", + "alerting:apm.anomaly/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.anomaly/alerts/alert/getAlertSummary", ], "read": Array [ "login:", @@ -3486,6 +5118,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:slo.rules.burnRate/observability/rule/getRuleExecutionKPI", "alerting:slo.rules.burnRate/observability/rule/getBackfill", "alerting:slo.rules.burnRate/observability/rule/findBackfill", + "alerting:slo.rules.burnRate/alerts/rule/get", + "alerting:slo.rules.burnRate/alerts/rule/getRuleState", + "alerting:slo.rules.burnRate/alerts/rule/getAlertSummary", + "alerting:slo.rules.burnRate/alerts/rule/getExecutionLog", + "alerting:slo.rules.burnRate/alerts/rule/getActionErrorLog", + "alerting:slo.rules.burnRate/alerts/rule/find", + "alerting:slo.rules.burnRate/alerts/rule/getRuleExecutionKPI", + "alerting:slo.rules.burnRate/alerts/rule/getBackfill", + "alerting:slo.rules.burnRate/alerts/rule/findBackfill", "alerting:observability.rules.custom_threshold/observability/rule/get", "alerting:observability.rules.custom_threshold/observability/rule/getRuleState", "alerting:observability.rules.custom_threshold/observability/rule/getAlertSummary", @@ -3495,6 +5136,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:observability.rules.custom_threshold/observability/rule/getRuleExecutionKPI", "alerting:observability.rules.custom_threshold/observability/rule/getBackfill", "alerting:observability.rules.custom_threshold/observability/rule/findBackfill", + "alerting:observability.rules.custom_threshold/alerts/rule/get", + "alerting:observability.rules.custom_threshold/alerts/rule/getRuleState", + "alerting:observability.rules.custom_threshold/alerts/rule/getAlertSummary", + "alerting:observability.rules.custom_threshold/alerts/rule/getExecutionLog", + "alerting:observability.rules.custom_threshold/alerts/rule/getActionErrorLog", + "alerting:observability.rules.custom_threshold/alerts/rule/find", + "alerting:observability.rules.custom_threshold/alerts/rule/getRuleExecutionKPI", + "alerting:observability.rules.custom_threshold/alerts/rule/getBackfill", + "alerting:observability.rules.custom_threshold/alerts/rule/findBackfill", "alerting:.es-query/observability/rule/get", "alerting:.es-query/observability/rule/getRuleState", "alerting:.es-query/observability/rule/getAlertSummary", @@ -3504,6 +5154,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:.es-query/observability/rule/getRuleExecutionKPI", "alerting:.es-query/observability/rule/getBackfill", "alerting:.es-query/observability/rule/findBackfill", + "alerting:.es-query/alerts/rule/get", + "alerting:.es-query/alerts/rule/getRuleState", + "alerting:.es-query/alerts/rule/getAlertSummary", + "alerting:.es-query/alerts/rule/getExecutionLog", + "alerting:.es-query/alerts/rule/getActionErrorLog", + "alerting:.es-query/alerts/rule/find", + "alerting:.es-query/alerts/rule/getRuleExecutionKPI", + "alerting:.es-query/alerts/rule/getBackfill", + "alerting:.es-query/alerts/rule/findBackfill", "alerting:xpack.ml.anomaly_detection_alert/observability/rule/get", "alerting:xpack.ml.anomaly_detection_alert/observability/rule/getRuleState", "alerting:xpack.ml.anomaly_detection_alert/observability/rule/getAlertSummary", @@ -3513,6 +5172,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:xpack.ml.anomaly_detection_alert/observability/rule/getRuleExecutionKPI", "alerting:xpack.ml.anomaly_detection_alert/observability/rule/getBackfill", "alerting:xpack.ml.anomaly_detection_alert/observability/rule/findBackfill", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/get", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getRuleState", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getAlertSummary", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getExecutionLog", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getActionErrorLog", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/find", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getRuleExecutionKPI", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getBackfill", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/findBackfill", "alerting:metrics.alert.inventory.threshold/observability/rule/get", "alerting:metrics.alert.inventory.threshold/observability/rule/getRuleState", "alerting:metrics.alert.inventory.threshold/observability/rule/getAlertSummary", @@ -3522,6 +5190,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:metrics.alert.inventory.threshold/observability/rule/getRuleExecutionKPI", "alerting:metrics.alert.inventory.threshold/observability/rule/getBackfill", "alerting:metrics.alert.inventory.threshold/observability/rule/findBackfill", + "alerting:metrics.alert.inventory.threshold/alerts/rule/get", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getRuleState", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getAlertSummary", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getExecutionLog", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getActionErrorLog", + "alerting:metrics.alert.inventory.threshold/alerts/rule/find", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getRuleExecutionKPI", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getBackfill", + "alerting:metrics.alert.inventory.threshold/alerts/rule/findBackfill", "alerting:apm.error_rate/observability/rule/get", "alerting:apm.error_rate/observability/rule/getRuleState", "alerting:apm.error_rate/observability/rule/getAlertSummary", @@ -3531,6 +5208,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.error_rate/observability/rule/getRuleExecutionKPI", "alerting:apm.error_rate/observability/rule/getBackfill", "alerting:apm.error_rate/observability/rule/findBackfill", + "alerting:apm.error_rate/alerts/rule/get", + "alerting:apm.error_rate/alerts/rule/getRuleState", + "alerting:apm.error_rate/alerts/rule/getAlertSummary", + "alerting:apm.error_rate/alerts/rule/getExecutionLog", + "alerting:apm.error_rate/alerts/rule/getActionErrorLog", + "alerting:apm.error_rate/alerts/rule/find", + "alerting:apm.error_rate/alerts/rule/getRuleExecutionKPI", + "alerting:apm.error_rate/alerts/rule/getBackfill", + "alerting:apm.error_rate/alerts/rule/findBackfill", "alerting:apm.transaction_error_rate/observability/rule/get", "alerting:apm.transaction_error_rate/observability/rule/getRuleState", "alerting:apm.transaction_error_rate/observability/rule/getAlertSummary", @@ -3540,6 +5226,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.transaction_error_rate/observability/rule/getRuleExecutionKPI", "alerting:apm.transaction_error_rate/observability/rule/getBackfill", "alerting:apm.transaction_error_rate/observability/rule/findBackfill", + "alerting:apm.transaction_error_rate/alerts/rule/get", + "alerting:apm.transaction_error_rate/alerts/rule/getRuleState", + "alerting:apm.transaction_error_rate/alerts/rule/getAlertSummary", + "alerting:apm.transaction_error_rate/alerts/rule/getExecutionLog", + "alerting:apm.transaction_error_rate/alerts/rule/getActionErrorLog", + "alerting:apm.transaction_error_rate/alerts/rule/find", + "alerting:apm.transaction_error_rate/alerts/rule/getRuleExecutionKPI", + "alerting:apm.transaction_error_rate/alerts/rule/getBackfill", + "alerting:apm.transaction_error_rate/alerts/rule/findBackfill", "alerting:apm.transaction_duration/observability/rule/get", "alerting:apm.transaction_duration/observability/rule/getRuleState", "alerting:apm.transaction_duration/observability/rule/getAlertSummary", @@ -3549,6 +5244,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.transaction_duration/observability/rule/getRuleExecutionKPI", "alerting:apm.transaction_duration/observability/rule/getBackfill", "alerting:apm.transaction_duration/observability/rule/findBackfill", + "alerting:apm.transaction_duration/alerts/rule/get", + "alerting:apm.transaction_duration/alerts/rule/getRuleState", + "alerting:apm.transaction_duration/alerts/rule/getAlertSummary", + "alerting:apm.transaction_duration/alerts/rule/getExecutionLog", + "alerting:apm.transaction_duration/alerts/rule/getActionErrorLog", + "alerting:apm.transaction_duration/alerts/rule/find", + "alerting:apm.transaction_duration/alerts/rule/getRuleExecutionKPI", + "alerting:apm.transaction_duration/alerts/rule/getBackfill", + "alerting:apm.transaction_duration/alerts/rule/findBackfill", "alerting:apm.anomaly/observability/rule/get", "alerting:apm.anomaly/observability/rule/getRuleState", "alerting:apm.anomaly/observability/rule/getAlertSummary", @@ -3558,42 +5262,87 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.anomaly/observability/rule/getRuleExecutionKPI", "alerting:apm.anomaly/observability/rule/getBackfill", "alerting:apm.anomaly/observability/rule/findBackfill", + "alerting:apm.anomaly/alerts/rule/get", + "alerting:apm.anomaly/alerts/rule/getRuleState", + "alerting:apm.anomaly/alerts/rule/getAlertSummary", + "alerting:apm.anomaly/alerts/rule/getExecutionLog", + "alerting:apm.anomaly/alerts/rule/getActionErrorLog", + "alerting:apm.anomaly/alerts/rule/find", + "alerting:apm.anomaly/alerts/rule/getRuleExecutionKPI", + "alerting:apm.anomaly/alerts/rule/getBackfill", + "alerting:apm.anomaly/alerts/rule/findBackfill", "alerting:slo.rules.burnRate/observability/alert/get", "alerting:slo.rules.burnRate/observability/alert/find", "alerting:slo.rules.burnRate/observability/alert/getAuthorizedAlertsIndices", "alerting:slo.rules.burnRate/observability/alert/getAlertSummary", + "alerting:slo.rules.burnRate/alerts/alert/get", + "alerting:slo.rules.burnRate/alerts/alert/find", + "alerting:slo.rules.burnRate/alerts/alert/getAuthorizedAlertsIndices", + "alerting:slo.rules.burnRate/alerts/alert/getAlertSummary", "alerting:observability.rules.custom_threshold/observability/alert/get", "alerting:observability.rules.custom_threshold/observability/alert/find", "alerting:observability.rules.custom_threshold/observability/alert/getAuthorizedAlertsIndices", "alerting:observability.rules.custom_threshold/observability/alert/getAlertSummary", + "alerting:observability.rules.custom_threshold/alerts/alert/get", + "alerting:observability.rules.custom_threshold/alerts/alert/find", + "alerting:observability.rules.custom_threshold/alerts/alert/getAuthorizedAlertsIndices", + "alerting:observability.rules.custom_threshold/alerts/alert/getAlertSummary", "alerting:.es-query/observability/alert/get", "alerting:.es-query/observability/alert/find", "alerting:.es-query/observability/alert/getAuthorizedAlertsIndices", "alerting:.es-query/observability/alert/getAlertSummary", + "alerting:.es-query/alerts/alert/get", + "alerting:.es-query/alerts/alert/find", + "alerting:.es-query/alerts/alert/getAuthorizedAlertsIndices", + "alerting:.es-query/alerts/alert/getAlertSummary", "alerting:xpack.ml.anomaly_detection_alert/observability/alert/get", "alerting:xpack.ml.anomaly_detection_alert/observability/alert/find", "alerting:xpack.ml.anomaly_detection_alert/observability/alert/getAuthorizedAlertsIndices", "alerting:xpack.ml.anomaly_detection_alert/observability/alert/getAlertSummary", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/get", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/find", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/getAuthorizedAlertsIndices", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/getAlertSummary", "alerting:metrics.alert.inventory.threshold/observability/alert/get", "alerting:metrics.alert.inventory.threshold/observability/alert/find", "alerting:metrics.alert.inventory.threshold/observability/alert/getAuthorizedAlertsIndices", "alerting:metrics.alert.inventory.threshold/observability/alert/getAlertSummary", + "alerting:metrics.alert.inventory.threshold/alerts/alert/get", + "alerting:metrics.alert.inventory.threshold/alerts/alert/find", + "alerting:metrics.alert.inventory.threshold/alerts/alert/getAuthorizedAlertsIndices", + "alerting:metrics.alert.inventory.threshold/alerts/alert/getAlertSummary", "alerting:apm.error_rate/observability/alert/get", "alerting:apm.error_rate/observability/alert/find", "alerting:apm.error_rate/observability/alert/getAuthorizedAlertsIndices", "alerting:apm.error_rate/observability/alert/getAlertSummary", + "alerting:apm.error_rate/alerts/alert/get", + "alerting:apm.error_rate/alerts/alert/find", + "alerting:apm.error_rate/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.error_rate/alerts/alert/getAlertSummary", "alerting:apm.transaction_error_rate/observability/alert/get", "alerting:apm.transaction_error_rate/observability/alert/find", "alerting:apm.transaction_error_rate/observability/alert/getAuthorizedAlertsIndices", "alerting:apm.transaction_error_rate/observability/alert/getAlertSummary", + "alerting:apm.transaction_error_rate/alerts/alert/get", + "alerting:apm.transaction_error_rate/alerts/alert/find", + "alerting:apm.transaction_error_rate/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.transaction_error_rate/alerts/alert/getAlertSummary", "alerting:apm.transaction_duration/observability/alert/get", "alerting:apm.transaction_duration/observability/alert/find", "alerting:apm.transaction_duration/observability/alert/getAuthorizedAlertsIndices", "alerting:apm.transaction_duration/observability/alert/getAlertSummary", + "alerting:apm.transaction_duration/alerts/alert/get", + "alerting:apm.transaction_duration/alerts/alert/find", + "alerting:apm.transaction_duration/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.transaction_duration/alerts/alert/getAlertSummary", "alerting:apm.anomaly/observability/alert/get", "alerting:apm.anomaly/observability/alert/find", "alerting:apm.anomaly/observability/alert/getAuthorizedAlertsIndices", "alerting:apm.anomaly/observability/alert/getAlertSummary", + "alerting:apm.anomaly/alerts/alert/get", + "alerting:apm.anomaly/alerts/alert/find", + "alerting:apm.anomaly/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.anomaly/alerts/alert/getAlertSummary", ], "store_search_session": Array [ "login:", @@ -3853,6 +5602,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:logs.alert.document.count/logs/rule/runSoon", "alerting:logs.alert.document.count/logs/rule/scheduleBackfill", "alerting:logs.alert.document.count/logs/rule/deleteBackfill", + "alerting:logs.alert.document.count/alerts/rule/get", + "alerting:logs.alert.document.count/alerts/rule/getRuleState", + "alerting:logs.alert.document.count/alerts/rule/getAlertSummary", + "alerting:logs.alert.document.count/alerts/rule/getExecutionLog", + "alerting:logs.alert.document.count/alerts/rule/getActionErrorLog", + "alerting:logs.alert.document.count/alerts/rule/find", + "alerting:logs.alert.document.count/alerts/rule/getRuleExecutionKPI", + "alerting:logs.alert.document.count/alerts/rule/getBackfill", + "alerting:logs.alert.document.count/alerts/rule/findBackfill", + "alerting:logs.alert.document.count/alerts/rule/create", + "alerting:logs.alert.document.count/alerts/rule/delete", + "alerting:logs.alert.document.count/alerts/rule/update", + "alerting:logs.alert.document.count/alerts/rule/updateApiKey", + "alerting:logs.alert.document.count/alerts/rule/enable", + "alerting:logs.alert.document.count/alerts/rule/disable", + "alerting:logs.alert.document.count/alerts/rule/muteAll", + "alerting:logs.alert.document.count/alerts/rule/unmuteAll", + "alerting:logs.alert.document.count/alerts/rule/muteAlert", + "alerting:logs.alert.document.count/alerts/rule/unmuteAlert", + "alerting:logs.alert.document.count/alerts/rule/snooze", + "alerting:logs.alert.document.count/alerts/rule/bulkEdit", + "alerting:logs.alert.document.count/alerts/rule/bulkDelete", + "alerting:logs.alert.document.count/alerts/rule/bulkEnable", + "alerting:logs.alert.document.count/alerts/rule/bulkDisable", + "alerting:logs.alert.document.count/alerts/rule/unsnooze", + "alerting:logs.alert.document.count/alerts/rule/runSoon", + "alerting:logs.alert.document.count/alerts/rule/scheduleBackfill", + "alerting:logs.alert.document.count/alerts/rule/deleteBackfill", "alerting:.es-query/logs/rule/get", "alerting:.es-query/logs/rule/getRuleState", "alerting:.es-query/logs/rule/getAlertSummary", @@ -3881,6 +5658,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:.es-query/logs/rule/runSoon", "alerting:.es-query/logs/rule/scheduleBackfill", "alerting:.es-query/logs/rule/deleteBackfill", + "alerting:.es-query/alerts/rule/get", + "alerting:.es-query/alerts/rule/getRuleState", + "alerting:.es-query/alerts/rule/getAlertSummary", + "alerting:.es-query/alerts/rule/getExecutionLog", + "alerting:.es-query/alerts/rule/getActionErrorLog", + "alerting:.es-query/alerts/rule/find", + "alerting:.es-query/alerts/rule/getRuleExecutionKPI", + "alerting:.es-query/alerts/rule/getBackfill", + "alerting:.es-query/alerts/rule/findBackfill", + "alerting:.es-query/alerts/rule/create", + "alerting:.es-query/alerts/rule/delete", + "alerting:.es-query/alerts/rule/update", + "alerting:.es-query/alerts/rule/updateApiKey", + "alerting:.es-query/alerts/rule/enable", + "alerting:.es-query/alerts/rule/disable", + "alerting:.es-query/alerts/rule/muteAll", + "alerting:.es-query/alerts/rule/unmuteAll", + "alerting:.es-query/alerts/rule/muteAlert", + "alerting:.es-query/alerts/rule/unmuteAlert", + "alerting:.es-query/alerts/rule/snooze", + "alerting:.es-query/alerts/rule/bulkEdit", + "alerting:.es-query/alerts/rule/bulkDelete", + "alerting:.es-query/alerts/rule/bulkEnable", + "alerting:.es-query/alerts/rule/bulkDisable", + "alerting:.es-query/alerts/rule/unsnooze", + "alerting:.es-query/alerts/rule/runSoon", + "alerting:.es-query/alerts/rule/scheduleBackfill", + "alerting:.es-query/alerts/rule/deleteBackfill", "alerting:observability.rules.custom_threshold/logs/rule/get", "alerting:observability.rules.custom_threshold/logs/rule/getRuleState", "alerting:observability.rules.custom_threshold/logs/rule/getAlertSummary", @@ -3909,6 +5714,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:observability.rules.custom_threshold/logs/rule/runSoon", "alerting:observability.rules.custom_threshold/logs/rule/scheduleBackfill", "alerting:observability.rules.custom_threshold/logs/rule/deleteBackfill", + "alerting:observability.rules.custom_threshold/alerts/rule/get", + "alerting:observability.rules.custom_threshold/alerts/rule/getRuleState", + "alerting:observability.rules.custom_threshold/alerts/rule/getAlertSummary", + "alerting:observability.rules.custom_threshold/alerts/rule/getExecutionLog", + "alerting:observability.rules.custom_threshold/alerts/rule/getActionErrorLog", + "alerting:observability.rules.custom_threshold/alerts/rule/find", + "alerting:observability.rules.custom_threshold/alerts/rule/getRuleExecutionKPI", + "alerting:observability.rules.custom_threshold/alerts/rule/getBackfill", + "alerting:observability.rules.custom_threshold/alerts/rule/findBackfill", + "alerting:observability.rules.custom_threshold/alerts/rule/create", + "alerting:observability.rules.custom_threshold/alerts/rule/delete", + "alerting:observability.rules.custom_threshold/alerts/rule/update", + "alerting:observability.rules.custom_threshold/alerts/rule/updateApiKey", + "alerting:observability.rules.custom_threshold/alerts/rule/enable", + "alerting:observability.rules.custom_threshold/alerts/rule/disable", + "alerting:observability.rules.custom_threshold/alerts/rule/muteAll", + "alerting:observability.rules.custom_threshold/alerts/rule/unmuteAll", + "alerting:observability.rules.custom_threshold/alerts/rule/muteAlert", + "alerting:observability.rules.custom_threshold/alerts/rule/unmuteAlert", + "alerting:observability.rules.custom_threshold/alerts/rule/snooze", + "alerting:observability.rules.custom_threshold/alerts/rule/bulkEdit", + "alerting:observability.rules.custom_threshold/alerts/rule/bulkDelete", + "alerting:observability.rules.custom_threshold/alerts/rule/bulkEnable", + "alerting:observability.rules.custom_threshold/alerts/rule/bulkDisable", + "alerting:observability.rules.custom_threshold/alerts/rule/unsnooze", + "alerting:observability.rules.custom_threshold/alerts/rule/runSoon", + "alerting:observability.rules.custom_threshold/alerts/rule/scheduleBackfill", + "alerting:observability.rules.custom_threshold/alerts/rule/deleteBackfill", "alerting:xpack.ml.anomaly_detection_alert/logs/rule/get", "alerting:xpack.ml.anomaly_detection_alert/logs/rule/getRuleState", "alerting:xpack.ml.anomaly_detection_alert/logs/rule/getAlertSummary", @@ -3937,26 +5770,74 @@ export default function ({ getService }: FtrProviderContext) { "alerting:xpack.ml.anomaly_detection_alert/logs/rule/runSoon", "alerting:xpack.ml.anomaly_detection_alert/logs/rule/scheduleBackfill", "alerting:xpack.ml.anomaly_detection_alert/logs/rule/deleteBackfill", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/get", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getRuleState", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getAlertSummary", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getExecutionLog", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getActionErrorLog", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/find", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getRuleExecutionKPI", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getBackfill", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/findBackfill", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/create", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/delete", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/update", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/updateApiKey", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/enable", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/disable", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/muteAll", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/unmuteAll", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/muteAlert", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/unmuteAlert", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/snooze", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/bulkEdit", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/bulkDelete", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/bulkEnable", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/bulkDisable", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/unsnooze", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/runSoon", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/scheduleBackfill", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/deleteBackfill", "alerting:logs.alert.document.count/logs/alert/get", "alerting:logs.alert.document.count/logs/alert/find", "alerting:logs.alert.document.count/logs/alert/getAuthorizedAlertsIndices", "alerting:logs.alert.document.count/logs/alert/getAlertSummary", "alerting:logs.alert.document.count/logs/alert/update", + "alerting:logs.alert.document.count/alerts/alert/get", + "alerting:logs.alert.document.count/alerts/alert/find", + "alerting:logs.alert.document.count/alerts/alert/getAuthorizedAlertsIndices", + "alerting:logs.alert.document.count/alerts/alert/getAlertSummary", + "alerting:logs.alert.document.count/alerts/alert/update", "alerting:.es-query/logs/alert/get", "alerting:.es-query/logs/alert/find", "alerting:.es-query/logs/alert/getAuthorizedAlertsIndices", "alerting:.es-query/logs/alert/getAlertSummary", "alerting:.es-query/logs/alert/update", + "alerting:.es-query/alerts/alert/get", + "alerting:.es-query/alerts/alert/find", + "alerting:.es-query/alerts/alert/getAuthorizedAlertsIndices", + "alerting:.es-query/alerts/alert/getAlertSummary", + "alerting:.es-query/alerts/alert/update", "alerting:observability.rules.custom_threshold/logs/alert/get", "alerting:observability.rules.custom_threshold/logs/alert/find", "alerting:observability.rules.custom_threshold/logs/alert/getAuthorizedAlertsIndices", "alerting:observability.rules.custom_threshold/logs/alert/getAlertSummary", "alerting:observability.rules.custom_threshold/logs/alert/update", + "alerting:observability.rules.custom_threshold/alerts/alert/get", + "alerting:observability.rules.custom_threshold/alerts/alert/find", + "alerting:observability.rules.custom_threshold/alerts/alert/getAuthorizedAlertsIndices", + "alerting:observability.rules.custom_threshold/alerts/alert/getAlertSummary", + "alerting:observability.rules.custom_threshold/alerts/alert/update", "alerting:xpack.ml.anomaly_detection_alert/logs/alert/get", "alerting:xpack.ml.anomaly_detection_alert/logs/alert/find", "alerting:xpack.ml.anomaly_detection_alert/logs/alert/getAuthorizedAlertsIndices", "alerting:xpack.ml.anomaly_detection_alert/logs/alert/getAlertSummary", "alerting:xpack.ml.anomaly_detection_alert/logs/alert/update", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/get", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/find", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/getAuthorizedAlertsIndices", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/getAlertSummary", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/update", ], "minimal_all": Array [ "login:", @@ -4180,6 +6061,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:logs.alert.document.count/logs/rule/runSoon", "alerting:logs.alert.document.count/logs/rule/scheduleBackfill", "alerting:logs.alert.document.count/logs/rule/deleteBackfill", + "alerting:logs.alert.document.count/alerts/rule/get", + "alerting:logs.alert.document.count/alerts/rule/getRuleState", + "alerting:logs.alert.document.count/alerts/rule/getAlertSummary", + "alerting:logs.alert.document.count/alerts/rule/getExecutionLog", + "alerting:logs.alert.document.count/alerts/rule/getActionErrorLog", + "alerting:logs.alert.document.count/alerts/rule/find", + "alerting:logs.alert.document.count/alerts/rule/getRuleExecutionKPI", + "alerting:logs.alert.document.count/alerts/rule/getBackfill", + "alerting:logs.alert.document.count/alerts/rule/findBackfill", + "alerting:logs.alert.document.count/alerts/rule/create", + "alerting:logs.alert.document.count/alerts/rule/delete", + "alerting:logs.alert.document.count/alerts/rule/update", + "alerting:logs.alert.document.count/alerts/rule/updateApiKey", + "alerting:logs.alert.document.count/alerts/rule/enable", + "alerting:logs.alert.document.count/alerts/rule/disable", + "alerting:logs.alert.document.count/alerts/rule/muteAll", + "alerting:logs.alert.document.count/alerts/rule/unmuteAll", + "alerting:logs.alert.document.count/alerts/rule/muteAlert", + "alerting:logs.alert.document.count/alerts/rule/unmuteAlert", + "alerting:logs.alert.document.count/alerts/rule/snooze", + "alerting:logs.alert.document.count/alerts/rule/bulkEdit", + "alerting:logs.alert.document.count/alerts/rule/bulkDelete", + "alerting:logs.alert.document.count/alerts/rule/bulkEnable", + "alerting:logs.alert.document.count/alerts/rule/bulkDisable", + "alerting:logs.alert.document.count/alerts/rule/unsnooze", + "alerting:logs.alert.document.count/alerts/rule/runSoon", + "alerting:logs.alert.document.count/alerts/rule/scheduleBackfill", + "alerting:logs.alert.document.count/alerts/rule/deleteBackfill", "alerting:.es-query/logs/rule/get", "alerting:.es-query/logs/rule/getRuleState", "alerting:.es-query/logs/rule/getAlertSummary", @@ -4208,6 +6117,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:.es-query/logs/rule/runSoon", "alerting:.es-query/logs/rule/scheduleBackfill", "alerting:.es-query/logs/rule/deleteBackfill", + "alerting:.es-query/alerts/rule/get", + "alerting:.es-query/alerts/rule/getRuleState", + "alerting:.es-query/alerts/rule/getAlertSummary", + "alerting:.es-query/alerts/rule/getExecutionLog", + "alerting:.es-query/alerts/rule/getActionErrorLog", + "alerting:.es-query/alerts/rule/find", + "alerting:.es-query/alerts/rule/getRuleExecutionKPI", + "alerting:.es-query/alerts/rule/getBackfill", + "alerting:.es-query/alerts/rule/findBackfill", + "alerting:.es-query/alerts/rule/create", + "alerting:.es-query/alerts/rule/delete", + "alerting:.es-query/alerts/rule/update", + "alerting:.es-query/alerts/rule/updateApiKey", + "alerting:.es-query/alerts/rule/enable", + "alerting:.es-query/alerts/rule/disable", + "alerting:.es-query/alerts/rule/muteAll", + "alerting:.es-query/alerts/rule/unmuteAll", + "alerting:.es-query/alerts/rule/muteAlert", + "alerting:.es-query/alerts/rule/unmuteAlert", + "alerting:.es-query/alerts/rule/snooze", + "alerting:.es-query/alerts/rule/bulkEdit", + "alerting:.es-query/alerts/rule/bulkDelete", + "alerting:.es-query/alerts/rule/bulkEnable", + "alerting:.es-query/alerts/rule/bulkDisable", + "alerting:.es-query/alerts/rule/unsnooze", + "alerting:.es-query/alerts/rule/runSoon", + "alerting:.es-query/alerts/rule/scheduleBackfill", + "alerting:.es-query/alerts/rule/deleteBackfill", "alerting:observability.rules.custom_threshold/logs/rule/get", "alerting:observability.rules.custom_threshold/logs/rule/getRuleState", "alerting:observability.rules.custom_threshold/logs/rule/getAlertSummary", @@ -4236,6 +6173,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:observability.rules.custom_threshold/logs/rule/runSoon", "alerting:observability.rules.custom_threshold/logs/rule/scheduleBackfill", "alerting:observability.rules.custom_threshold/logs/rule/deleteBackfill", + "alerting:observability.rules.custom_threshold/alerts/rule/get", + "alerting:observability.rules.custom_threshold/alerts/rule/getRuleState", + "alerting:observability.rules.custom_threshold/alerts/rule/getAlertSummary", + "alerting:observability.rules.custom_threshold/alerts/rule/getExecutionLog", + "alerting:observability.rules.custom_threshold/alerts/rule/getActionErrorLog", + "alerting:observability.rules.custom_threshold/alerts/rule/find", + "alerting:observability.rules.custom_threshold/alerts/rule/getRuleExecutionKPI", + "alerting:observability.rules.custom_threshold/alerts/rule/getBackfill", + "alerting:observability.rules.custom_threshold/alerts/rule/findBackfill", + "alerting:observability.rules.custom_threshold/alerts/rule/create", + "alerting:observability.rules.custom_threshold/alerts/rule/delete", + "alerting:observability.rules.custom_threshold/alerts/rule/update", + "alerting:observability.rules.custom_threshold/alerts/rule/updateApiKey", + "alerting:observability.rules.custom_threshold/alerts/rule/enable", + "alerting:observability.rules.custom_threshold/alerts/rule/disable", + "alerting:observability.rules.custom_threshold/alerts/rule/muteAll", + "alerting:observability.rules.custom_threshold/alerts/rule/unmuteAll", + "alerting:observability.rules.custom_threshold/alerts/rule/muteAlert", + "alerting:observability.rules.custom_threshold/alerts/rule/unmuteAlert", + "alerting:observability.rules.custom_threshold/alerts/rule/snooze", + "alerting:observability.rules.custom_threshold/alerts/rule/bulkEdit", + "alerting:observability.rules.custom_threshold/alerts/rule/bulkDelete", + "alerting:observability.rules.custom_threshold/alerts/rule/bulkEnable", + "alerting:observability.rules.custom_threshold/alerts/rule/bulkDisable", + "alerting:observability.rules.custom_threshold/alerts/rule/unsnooze", + "alerting:observability.rules.custom_threshold/alerts/rule/runSoon", + "alerting:observability.rules.custom_threshold/alerts/rule/scheduleBackfill", + "alerting:observability.rules.custom_threshold/alerts/rule/deleteBackfill", "alerting:xpack.ml.anomaly_detection_alert/logs/rule/get", "alerting:xpack.ml.anomaly_detection_alert/logs/rule/getRuleState", "alerting:xpack.ml.anomaly_detection_alert/logs/rule/getAlertSummary", @@ -4264,26 +6229,74 @@ export default function ({ getService }: FtrProviderContext) { "alerting:xpack.ml.anomaly_detection_alert/logs/rule/runSoon", "alerting:xpack.ml.anomaly_detection_alert/logs/rule/scheduleBackfill", "alerting:xpack.ml.anomaly_detection_alert/logs/rule/deleteBackfill", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/get", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getRuleState", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getAlertSummary", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getExecutionLog", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getActionErrorLog", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/find", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getRuleExecutionKPI", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getBackfill", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/findBackfill", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/create", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/delete", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/update", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/updateApiKey", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/enable", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/disable", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/muteAll", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/unmuteAll", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/muteAlert", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/unmuteAlert", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/snooze", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/bulkEdit", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/bulkDelete", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/bulkEnable", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/bulkDisable", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/unsnooze", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/runSoon", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/scheduleBackfill", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/deleteBackfill", "alerting:logs.alert.document.count/logs/alert/get", "alerting:logs.alert.document.count/logs/alert/find", "alerting:logs.alert.document.count/logs/alert/getAuthorizedAlertsIndices", "alerting:logs.alert.document.count/logs/alert/getAlertSummary", "alerting:logs.alert.document.count/logs/alert/update", + "alerting:logs.alert.document.count/alerts/alert/get", + "alerting:logs.alert.document.count/alerts/alert/find", + "alerting:logs.alert.document.count/alerts/alert/getAuthorizedAlertsIndices", + "alerting:logs.alert.document.count/alerts/alert/getAlertSummary", + "alerting:logs.alert.document.count/alerts/alert/update", "alerting:.es-query/logs/alert/get", "alerting:.es-query/logs/alert/find", "alerting:.es-query/logs/alert/getAuthorizedAlertsIndices", "alerting:.es-query/logs/alert/getAlertSummary", "alerting:.es-query/logs/alert/update", + "alerting:.es-query/alerts/alert/get", + "alerting:.es-query/alerts/alert/find", + "alerting:.es-query/alerts/alert/getAuthorizedAlertsIndices", + "alerting:.es-query/alerts/alert/getAlertSummary", + "alerting:.es-query/alerts/alert/update", "alerting:observability.rules.custom_threshold/logs/alert/get", "alerting:observability.rules.custom_threshold/logs/alert/find", "alerting:observability.rules.custom_threshold/logs/alert/getAuthorizedAlertsIndices", "alerting:observability.rules.custom_threshold/logs/alert/getAlertSummary", "alerting:observability.rules.custom_threshold/logs/alert/update", + "alerting:observability.rules.custom_threshold/alerts/alert/get", + "alerting:observability.rules.custom_threshold/alerts/alert/find", + "alerting:observability.rules.custom_threshold/alerts/alert/getAuthorizedAlertsIndices", + "alerting:observability.rules.custom_threshold/alerts/alert/getAlertSummary", + "alerting:observability.rules.custom_threshold/alerts/alert/update", "alerting:xpack.ml.anomaly_detection_alert/logs/alert/get", "alerting:xpack.ml.anomaly_detection_alert/logs/alert/find", "alerting:xpack.ml.anomaly_detection_alert/logs/alert/getAuthorizedAlertsIndices", "alerting:xpack.ml.anomaly_detection_alert/logs/alert/getAlertSummary", "alerting:xpack.ml.anomaly_detection_alert/logs/alert/update", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/get", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/find", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/getAuthorizedAlertsIndices", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/getAlertSummary", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/update", ], "minimal_read": Array [ "login:", @@ -4393,6 +6406,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:logs.alert.document.count/logs/rule/getRuleExecutionKPI", "alerting:logs.alert.document.count/logs/rule/getBackfill", "alerting:logs.alert.document.count/logs/rule/findBackfill", + "alerting:logs.alert.document.count/alerts/rule/get", + "alerting:logs.alert.document.count/alerts/rule/getRuleState", + "alerting:logs.alert.document.count/alerts/rule/getAlertSummary", + "alerting:logs.alert.document.count/alerts/rule/getExecutionLog", + "alerting:logs.alert.document.count/alerts/rule/getActionErrorLog", + "alerting:logs.alert.document.count/alerts/rule/find", + "alerting:logs.alert.document.count/alerts/rule/getRuleExecutionKPI", + "alerting:logs.alert.document.count/alerts/rule/getBackfill", + "alerting:logs.alert.document.count/alerts/rule/findBackfill", "alerting:.es-query/logs/rule/get", "alerting:.es-query/logs/rule/getRuleState", "alerting:.es-query/logs/rule/getAlertSummary", @@ -4402,6 +6424,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:.es-query/logs/rule/getRuleExecutionKPI", "alerting:.es-query/logs/rule/getBackfill", "alerting:.es-query/logs/rule/findBackfill", + "alerting:.es-query/alerts/rule/get", + "alerting:.es-query/alerts/rule/getRuleState", + "alerting:.es-query/alerts/rule/getAlertSummary", + "alerting:.es-query/alerts/rule/getExecutionLog", + "alerting:.es-query/alerts/rule/getActionErrorLog", + "alerting:.es-query/alerts/rule/find", + "alerting:.es-query/alerts/rule/getRuleExecutionKPI", + "alerting:.es-query/alerts/rule/getBackfill", + "alerting:.es-query/alerts/rule/findBackfill", "alerting:observability.rules.custom_threshold/logs/rule/get", "alerting:observability.rules.custom_threshold/logs/rule/getRuleState", "alerting:observability.rules.custom_threshold/logs/rule/getAlertSummary", @@ -4411,6 +6442,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:observability.rules.custom_threshold/logs/rule/getRuleExecutionKPI", "alerting:observability.rules.custom_threshold/logs/rule/getBackfill", "alerting:observability.rules.custom_threshold/logs/rule/findBackfill", + "alerting:observability.rules.custom_threshold/alerts/rule/get", + "alerting:observability.rules.custom_threshold/alerts/rule/getRuleState", + "alerting:observability.rules.custom_threshold/alerts/rule/getAlertSummary", + "alerting:observability.rules.custom_threshold/alerts/rule/getExecutionLog", + "alerting:observability.rules.custom_threshold/alerts/rule/getActionErrorLog", + "alerting:observability.rules.custom_threshold/alerts/rule/find", + "alerting:observability.rules.custom_threshold/alerts/rule/getRuleExecutionKPI", + "alerting:observability.rules.custom_threshold/alerts/rule/getBackfill", + "alerting:observability.rules.custom_threshold/alerts/rule/findBackfill", "alerting:xpack.ml.anomaly_detection_alert/logs/rule/get", "alerting:xpack.ml.anomaly_detection_alert/logs/rule/getRuleState", "alerting:xpack.ml.anomaly_detection_alert/logs/rule/getAlertSummary", @@ -4420,22 +6460,47 @@ export default function ({ getService }: FtrProviderContext) { "alerting:xpack.ml.anomaly_detection_alert/logs/rule/getRuleExecutionKPI", "alerting:xpack.ml.anomaly_detection_alert/logs/rule/getBackfill", "alerting:xpack.ml.anomaly_detection_alert/logs/rule/findBackfill", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/get", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getRuleState", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getAlertSummary", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getExecutionLog", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getActionErrorLog", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/find", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getRuleExecutionKPI", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getBackfill", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/findBackfill", "alerting:logs.alert.document.count/logs/alert/get", "alerting:logs.alert.document.count/logs/alert/find", "alerting:logs.alert.document.count/logs/alert/getAuthorizedAlertsIndices", "alerting:logs.alert.document.count/logs/alert/getAlertSummary", + "alerting:logs.alert.document.count/alerts/alert/get", + "alerting:logs.alert.document.count/alerts/alert/find", + "alerting:logs.alert.document.count/alerts/alert/getAuthorizedAlertsIndices", + "alerting:logs.alert.document.count/alerts/alert/getAlertSummary", "alerting:.es-query/logs/alert/get", "alerting:.es-query/logs/alert/find", "alerting:.es-query/logs/alert/getAuthorizedAlertsIndices", "alerting:.es-query/logs/alert/getAlertSummary", + "alerting:.es-query/alerts/alert/get", + "alerting:.es-query/alerts/alert/find", + "alerting:.es-query/alerts/alert/getAuthorizedAlertsIndices", + "alerting:.es-query/alerts/alert/getAlertSummary", "alerting:observability.rules.custom_threshold/logs/alert/get", "alerting:observability.rules.custom_threshold/logs/alert/find", "alerting:observability.rules.custom_threshold/logs/alert/getAuthorizedAlertsIndices", "alerting:observability.rules.custom_threshold/logs/alert/getAlertSummary", + "alerting:observability.rules.custom_threshold/alerts/alert/get", + "alerting:observability.rules.custom_threshold/alerts/alert/find", + "alerting:observability.rules.custom_threshold/alerts/alert/getAuthorizedAlertsIndices", + "alerting:observability.rules.custom_threshold/alerts/alert/getAlertSummary", "alerting:xpack.ml.anomaly_detection_alert/logs/alert/get", "alerting:xpack.ml.anomaly_detection_alert/logs/alert/find", "alerting:xpack.ml.anomaly_detection_alert/logs/alert/getAuthorizedAlertsIndices", "alerting:xpack.ml.anomaly_detection_alert/logs/alert/getAlertSummary", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/get", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/find", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/getAuthorizedAlertsIndices", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/getAlertSummary", ], "read": Array [ "login:", @@ -4545,6 +6610,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:logs.alert.document.count/logs/rule/getRuleExecutionKPI", "alerting:logs.alert.document.count/logs/rule/getBackfill", "alerting:logs.alert.document.count/logs/rule/findBackfill", + "alerting:logs.alert.document.count/alerts/rule/get", + "alerting:logs.alert.document.count/alerts/rule/getRuleState", + "alerting:logs.alert.document.count/alerts/rule/getAlertSummary", + "alerting:logs.alert.document.count/alerts/rule/getExecutionLog", + "alerting:logs.alert.document.count/alerts/rule/getActionErrorLog", + "alerting:logs.alert.document.count/alerts/rule/find", + "alerting:logs.alert.document.count/alerts/rule/getRuleExecutionKPI", + "alerting:logs.alert.document.count/alerts/rule/getBackfill", + "alerting:logs.alert.document.count/alerts/rule/findBackfill", "alerting:.es-query/logs/rule/get", "alerting:.es-query/logs/rule/getRuleState", "alerting:.es-query/logs/rule/getAlertSummary", @@ -4554,6 +6628,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:.es-query/logs/rule/getRuleExecutionKPI", "alerting:.es-query/logs/rule/getBackfill", "alerting:.es-query/logs/rule/findBackfill", + "alerting:.es-query/alerts/rule/get", + "alerting:.es-query/alerts/rule/getRuleState", + "alerting:.es-query/alerts/rule/getAlertSummary", + "alerting:.es-query/alerts/rule/getExecutionLog", + "alerting:.es-query/alerts/rule/getActionErrorLog", + "alerting:.es-query/alerts/rule/find", + "alerting:.es-query/alerts/rule/getRuleExecutionKPI", + "alerting:.es-query/alerts/rule/getBackfill", + "alerting:.es-query/alerts/rule/findBackfill", "alerting:observability.rules.custom_threshold/logs/rule/get", "alerting:observability.rules.custom_threshold/logs/rule/getRuleState", "alerting:observability.rules.custom_threshold/logs/rule/getAlertSummary", @@ -4563,6 +6646,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:observability.rules.custom_threshold/logs/rule/getRuleExecutionKPI", "alerting:observability.rules.custom_threshold/logs/rule/getBackfill", "alerting:observability.rules.custom_threshold/logs/rule/findBackfill", + "alerting:observability.rules.custom_threshold/alerts/rule/get", + "alerting:observability.rules.custom_threshold/alerts/rule/getRuleState", + "alerting:observability.rules.custom_threshold/alerts/rule/getAlertSummary", + "alerting:observability.rules.custom_threshold/alerts/rule/getExecutionLog", + "alerting:observability.rules.custom_threshold/alerts/rule/getActionErrorLog", + "alerting:observability.rules.custom_threshold/alerts/rule/find", + "alerting:observability.rules.custom_threshold/alerts/rule/getRuleExecutionKPI", + "alerting:observability.rules.custom_threshold/alerts/rule/getBackfill", + "alerting:observability.rules.custom_threshold/alerts/rule/findBackfill", "alerting:xpack.ml.anomaly_detection_alert/logs/rule/get", "alerting:xpack.ml.anomaly_detection_alert/logs/rule/getRuleState", "alerting:xpack.ml.anomaly_detection_alert/logs/rule/getAlertSummary", @@ -4572,22 +6664,47 @@ export default function ({ getService }: FtrProviderContext) { "alerting:xpack.ml.anomaly_detection_alert/logs/rule/getRuleExecutionKPI", "alerting:xpack.ml.anomaly_detection_alert/logs/rule/getBackfill", "alerting:xpack.ml.anomaly_detection_alert/logs/rule/findBackfill", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/get", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getRuleState", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getAlertSummary", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getExecutionLog", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getActionErrorLog", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/find", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getRuleExecutionKPI", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getBackfill", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/findBackfill", "alerting:logs.alert.document.count/logs/alert/get", "alerting:logs.alert.document.count/logs/alert/find", "alerting:logs.alert.document.count/logs/alert/getAuthorizedAlertsIndices", "alerting:logs.alert.document.count/logs/alert/getAlertSummary", + "alerting:logs.alert.document.count/alerts/alert/get", + "alerting:logs.alert.document.count/alerts/alert/find", + "alerting:logs.alert.document.count/alerts/alert/getAuthorizedAlertsIndices", + "alerting:logs.alert.document.count/alerts/alert/getAlertSummary", "alerting:.es-query/logs/alert/get", "alerting:.es-query/logs/alert/find", "alerting:.es-query/logs/alert/getAuthorizedAlertsIndices", "alerting:.es-query/logs/alert/getAlertSummary", + "alerting:.es-query/alerts/alert/get", + "alerting:.es-query/alerts/alert/find", + "alerting:.es-query/alerts/alert/getAuthorizedAlertsIndices", + "alerting:.es-query/alerts/alert/getAlertSummary", "alerting:observability.rules.custom_threshold/logs/alert/get", "alerting:observability.rules.custom_threshold/logs/alert/find", "alerting:observability.rules.custom_threshold/logs/alert/getAuthorizedAlertsIndices", "alerting:observability.rules.custom_threshold/logs/alert/getAlertSummary", + "alerting:observability.rules.custom_threshold/alerts/alert/get", + "alerting:observability.rules.custom_threshold/alerts/alert/find", + "alerting:observability.rules.custom_threshold/alerts/alert/getAuthorizedAlertsIndices", + "alerting:observability.rules.custom_threshold/alerts/alert/getAlertSummary", "alerting:xpack.ml.anomaly_detection_alert/logs/alert/get", "alerting:xpack.ml.anomaly_detection_alert/logs/alert/find", "alerting:xpack.ml.anomaly_detection_alert/logs/alert/getAuthorizedAlertsIndices", "alerting:xpack.ml.anomaly_detection_alert/logs/alert/getAlertSummary", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/get", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/find", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/getAuthorizedAlertsIndices", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/getAlertSummary", ], }, "infrastructure": Object { @@ -4691,6 +6808,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:metrics.alert.threshold/infrastructure/rule/runSoon", "alerting:metrics.alert.threshold/infrastructure/rule/scheduleBackfill", "alerting:metrics.alert.threshold/infrastructure/rule/deleteBackfill", + "alerting:metrics.alert.threshold/alerts/rule/get", + "alerting:metrics.alert.threshold/alerts/rule/getRuleState", + "alerting:metrics.alert.threshold/alerts/rule/getAlertSummary", + "alerting:metrics.alert.threshold/alerts/rule/getExecutionLog", + "alerting:metrics.alert.threshold/alerts/rule/getActionErrorLog", + "alerting:metrics.alert.threshold/alerts/rule/find", + "alerting:metrics.alert.threshold/alerts/rule/getRuleExecutionKPI", + "alerting:metrics.alert.threshold/alerts/rule/getBackfill", + "alerting:metrics.alert.threshold/alerts/rule/findBackfill", + "alerting:metrics.alert.threshold/alerts/rule/create", + "alerting:metrics.alert.threshold/alerts/rule/delete", + "alerting:metrics.alert.threshold/alerts/rule/update", + "alerting:metrics.alert.threshold/alerts/rule/updateApiKey", + "alerting:metrics.alert.threshold/alerts/rule/enable", + "alerting:metrics.alert.threshold/alerts/rule/disable", + "alerting:metrics.alert.threshold/alerts/rule/muteAll", + "alerting:metrics.alert.threshold/alerts/rule/unmuteAll", + "alerting:metrics.alert.threshold/alerts/rule/muteAlert", + "alerting:metrics.alert.threshold/alerts/rule/unmuteAlert", + "alerting:metrics.alert.threshold/alerts/rule/snooze", + "alerting:metrics.alert.threshold/alerts/rule/bulkEdit", + "alerting:metrics.alert.threshold/alerts/rule/bulkDelete", + "alerting:metrics.alert.threshold/alerts/rule/bulkEnable", + "alerting:metrics.alert.threshold/alerts/rule/bulkDisable", + "alerting:metrics.alert.threshold/alerts/rule/unsnooze", + "alerting:metrics.alert.threshold/alerts/rule/runSoon", + "alerting:metrics.alert.threshold/alerts/rule/scheduleBackfill", + "alerting:metrics.alert.threshold/alerts/rule/deleteBackfill", "alerting:metrics.alert.inventory.threshold/infrastructure/rule/get", "alerting:metrics.alert.inventory.threshold/infrastructure/rule/getRuleState", "alerting:metrics.alert.inventory.threshold/infrastructure/rule/getAlertSummary", @@ -4719,6 +6864,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:metrics.alert.inventory.threshold/infrastructure/rule/runSoon", "alerting:metrics.alert.inventory.threshold/infrastructure/rule/scheduleBackfill", "alerting:metrics.alert.inventory.threshold/infrastructure/rule/deleteBackfill", + "alerting:metrics.alert.inventory.threshold/alerts/rule/get", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getRuleState", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getAlertSummary", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getExecutionLog", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getActionErrorLog", + "alerting:metrics.alert.inventory.threshold/alerts/rule/find", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getRuleExecutionKPI", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getBackfill", + "alerting:metrics.alert.inventory.threshold/alerts/rule/findBackfill", + "alerting:metrics.alert.inventory.threshold/alerts/rule/create", + "alerting:metrics.alert.inventory.threshold/alerts/rule/delete", + "alerting:metrics.alert.inventory.threshold/alerts/rule/update", + "alerting:metrics.alert.inventory.threshold/alerts/rule/updateApiKey", + "alerting:metrics.alert.inventory.threshold/alerts/rule/enable", + "alerting:metrics.alert.inventory.threshold/alerts/rule/disable", + "alerting:metrics.alert.inventory.threshold/alerts/rule/muteAll", + "alerting:metrics.alert.inventory.threshold/alerts/rule/unmuteAll", + "alerting:metrics.alert.inventory.threshold/alerts/rule/muteAlert", + "alerting:metrics.alert.inventory.threshold/alerts/rule/unmuteAlert", + "alerting:metrics.alert.inventory.threshold/alerts/rule/snooze", + "alerting:metrics.alert.inventory.threshold/alerts/rule/bulkEdit", + "alerting:metrics.alert.inventory.threshold/alerts/rule/bulkDelete", + "alerting:metrics.alert.inventory.threshold/alerts/rule/bulkEnable", + "alerting:metrics.alert.inventory.threshold/alerts/rule/bulkDisable", + "alerting:metrics.alert.inventory.threshold/alerts/rule/unsnooze", + "alerting:metrics.alert.inventory.threshold/alerts/rule/runSoon", + "alerting:metrics.alert.inventory.threshold/alerts/rule/scheduleBackfill", + "alerting:metrics.alert.inventory.threshold/alerts/rule/deleteBackfill", "alerting:.es-query/infrastructure/rule/get", "alerting:.es-query/infrastructure/rule/getRuleState", "alerting:.es-query/infrastructure/rule/getAlertSummary", @@ -4747,6 +6920,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:.es-query/infrastructure/rule/runSoon", "alerting:.es-query/infrastructure/rule/scheduleBackfill", "alerting:.es-query/infrastructure/rule/deleteBackfill", + "alerting:.es-query/alerts/rule/get", + "alerting:.es-query/alerts/rule/getRuleState", + "alerting:.es-query/alerts/rule/getAlertSummary", + "alerting:.es-query/alerts/rule/getExecutionLog", + "alerting:.es-query/alerts/rule/getActionErrorLog", + "alerting:.es-query/alerts/rule/find", + "alerting:.es-query/alerts/rule/getRuleExecutionKPI", + "alerting:.es-query/alerts/rule/getBackfill", + "alerting:.es-query/alerts/rule/findBackfill", + "alerting:.es-query/alerts/rule/create", + "alerting:.es-query/alerts/rule/delete", + "alerting:.es-query/alerts/rule/update", + "alerting:.es-query/alerts/rule/updateApiKey", + "alerting:.es-query/alerts/rule/enable", + "alerting:.es-query/alerts/rule/disable", + "alerting:.es-query/alerts/rule/muteAll", + "alerting:.es-query/alerts/rule/unmuteAll", + "alerting:.es-query/alerts/rule/muteAlert", + "alerting:.es-query/alerts/rule/unmuteAlert", + "alerting:.es-query/alerts/rule/snooze", + "alerting:.es-query/alerts/rule/bulkEdit", + "alerting:.es-query/alerts/rule/bulkDelete", + "alerting:.es-query/alerts/rule/bulkEnable", + "alerting:.es-query/alerts/rule/bulkDisable", + "alerting:.es-query/alerts/rule/unsnooze", + "alerting:.es-query/alerts/rule/runSoon", + "alerting:.es-query/alerts/rule/scheduleBackfill", + "alerting:.es-query/alerts/rule/deleteBackfill", "alerting:observability.rules.custom_threshold/infrastructure/rule/get", "alerting:observability.rules.custom_threshold/infrastructure/rule/getRuleState", "alerting:observability.rules.custom_threshold/infrastructure/rule/getAlertSummary", @@ -4775,6 +6976,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:observability.rules.custom_threshold/infrastructure/rule/runSoon", "alerting:observability.rules.custom_threshold/infrastructure/rule/scheduleBackfill", "alerting:observability.rules.custom_threshold/infrastructure/rule/deleteBackfill", + "alerting:observability.rules.custom_threshold/alerts/rule/get", + "alerting:observability.rules.custom_threshold/alerts/rule/getRuleState", + "alerting:observability.rules.custom_threshold/alerts/rule/getAlertSummary", + "alerting:observability.rules.custom_threshold/alerts/rule/getExecutionLog", + "alerting:observability.rules.custom_threshold/alerts/rule/getActionErrorLog", + "alerting:observability.rules.custom_threshold/alerts/rule/find", + "alerting:observability.rules.custom_threshold/alerts/rule/getRuleExecutionKPI", + "alerting:observability.rules.custom_threshold/alerts/rule/getBackfill", + "alerting:observability.rules.custom_threshold/alerts/rule/findBackfill", + "alerting:observability.rules.custom_threshold/alerts/rule/create", + "alerting:observability.rules.custom_threshold/alerts/rule/delete", + "alerting:observability.rules.custom_threshold/alerts/rule/update", + "alerting:observability.rules.custom_threshold/alerts/rule/updateApiKey", + "alerting:observability.rules.custom_threshold/alerts/rule/enable", + "alerting:observability.rules.custom_threshold/alerts/rule/disable", + "alerting:observability.rules.custom_threshold/alerts/rule/muteAll", + "alerting:observability.rules.custom_threshold/alerts/rule/unmuteAll", + "alerting:observability.rules.custom_threshold/alerts/rule/muteAlert", + "alerting:observability.rules.custom_threshold/alerts/rule/unmuteAlert", + "alerting:observability.rules.custom_threshold/alerts/rule/snooze", + "alerting:observability.rules.custom_threshold/alerts/rule/bulkEdit", + "alerting:observability.rules.custom_threshold/alerts/rule/bulkDelete", + "alerting:observability.rules.custom_threshold/alerts/rule/bulkEnable", + "alerting:observability.rules.custom_threshold/alerts/rule/bulkDisable", + "alerting:observability.rules.custom_threshold/alerts/rule/unsnooze", + "alerting:observability.rules.custom_threshold/alerts/rule/runSoon", + "alerting:observability.rules.custom_threshold/alerts/rule/scheduleBackfill", + "alerting:observability.rules.custom_threshold/alerts/rule/deleteBackfill", "alerting:xpack.ml.anomaly_detection_alert/infrastructure/rule/get", "alerting:xpack.ml.anomaly_detection_alert/infrastructure/rule/getRuleState", "alerting:xpack.ml.anomaly_detection_alert/infrastructure/rule/getAlertSummary", @@ -4803,31 +7032,84 @@ export default function ({ getService }: FtrProviderContext) { "alerting:xpack.ml.anomaly_detection_alert/infrastructure/rule/runSoon", "alerting:xpack.ml.anomaly_detection_alert/infrastructure/rule/scheduleBackfill", "alerting:xpack.ml.anomaly_detection_alert/infrastructure/rule/deleteBackfill", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/get", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getRuleState", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getAlertSummary", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getExecutionLog", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getActionErrorLog", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/find", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getRuleExecutionKPI", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getBackfill", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/findBackfill", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/create", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/delete", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/update", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/updateApiKey", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/enable", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/disable", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/muteAll", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/unmuteAll", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/muteAlert", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/unmuteAlert", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/snooze", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/bulkEdit", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/bulkDelete", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/bulkEnable", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/bulkDisable", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/unsnooze", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/runSoon", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/scheduleBackfill", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/deleteBackfill", "alerting:metrics.alert.threshold/infrastructure/alert/get", "alerting:metrics.alert.threshold/infrastructure/alert/find", "alerting:metrics.alert.threshold/infrastructure/alert/getAuthorizedAlertsIndices", "alerting:metrics.alert.threshold/infrastructure/alert/getAlertSummary", "alerting:metrics.alert.threshold/infrastructure/alert/update", + "alerting:metrics.alert.threshold/alerts/alert/get", + "alerting:metrics.alert.threshold/alerts/alert/find", + "alerting:metrics.alert.threshold/alerts/alert/getAuthorizedAlertsIndices", + "alerting:metrics.alert.threshold/alerts/alert/getAlertSummary", + "alerting:metrics.alert.threshold/alerts/alert/update", "alerting:metrics.alert.inventory.threshold/infrastructure/alert/get", "alerting:metrics.alert.inventory.threshold/infrastructure/alert/find", "alerting:metrics.alert.inventory.threshold/infrastructure/alert/getAuthorizedAlertsIndices", "alerting:metrics.alert.inventory.threshold/infrastructure/alert/getAlertSummary", "alerting:metrics.alert.inventory.threshold/infrastructure/alert/update", + "alerting:metrics.alert.inventory.threshold/alerts/alert/get", + "alerting:metrics.alert.inventory.threshold/alerts/alert/find", + "alerting:metrics.alert.inventory.threshold/alerts/alert/getAuthorizedAlertsIndices", + "alerting:metrics.alert.inventory.threshold/alerts/alert/getAlertSummary", + "alerting:metrics.alert.inventory.threshold/alerts/alert/update", "alerting:.es-query/infrastructure/alert/get", "alerting:.es-query/infrastructure/alert/find", "alerting:.es-query/infrastructure/alert/getAuthorizedAlertsIndices", "alerting:.es-query/infrastructure/alert/getAlertSummary", "alerting:.es-query/infrastructure/alert/update", + "alerting:.es-query/alerts/alert/get", + "alerting:.es-query/alerts/alert/find", + "alerting:.es-query/alerts/alert/getAuthorizedAlertsIndices", + "alerting:.es-query/alerts/alert/getAlertSummary", + "alerting:.es-query/alerts/alert/update", "alerting:observability.rules.custom_threshold/infrastructure/alert/get", "alerting:observability.rules.custom_threshold/infrastructure/alert/find", "alerting:observability.rules.custom_threshold/infrastructure/alert/getAuthorizedAlertsIndices", "alerting:observability.rules.custom_threshold/infrastructure/alert/getAlertSummary", "alerting:observability.rules.custom_threshold/infrastructure/alert/update", + "alerting:observability.rules.custom_threshold/alerts/alert/get", + "alerting:observability.rules.custom_threshold/alerts/alert/find", + "alerting:observability.rules.custom_threshold/alerts/alert/getAuthorizedAlertsIndices", + "alerting:observability.rules.custom_threshold/alerts/alert/getAlertSummary", + "alerting:observability.rules.custom_threshold/alerts/alert/update", "alerting:xpack.ml.anomaly_detection_alert/infrastructure/alert/get", "alerting:xpack.ml.anomaly_detection_alert/infrastructure/alert/find", "alerting:xpack.ml.anomaly_detection_alert/infrastructure/alert/getAuthorizedAlertsIndices", "alerting:xpack.ml.anomaly_detection_alert/infrastructure/alert/getAlertSummary", "alerting:xpack.ml.anomaly_detection_alert/infrastructure/alert/update", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/get", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/find", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/getAuthorizedAlertsIndices", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/getAlertSummary", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/update", "app:logs", "ui:catalogue/infralogging", "ui:catalogue/logs", @@ -4875,6 +7157,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:logs.alert.document.count/logs/rule/runSoon", "alerting:logs.alert.document.count/logs/rule/scheduleBackfill", "alerting:logs.alert.document.count/logs/rule/deleteBackfill", + "alerting:logs.alert.document.count/alerts/rule/get", + "alerting:logs.alert.document.count/alerts/rule/getRuleState", + "alerting:logs.alert.document.count/alerts/rule/getAlertSummary", + "alerting:logs.alert.document.count/alerts/rule/getExecutionLog", + "alerting:logs.alert.document.count/alerts/rule/getActionErrorLog", + "alerting:logs.alert.document.count/alerts/rule/find", + "alerting:logs.alert.document.count/alerts/rule/getRuleExecutionKPI", + "alerting:logs.alert.document.count/alerts/rule/getBackfill", + "alerting:logs.alert.document.count/alerts/rule/findBackfill", + "alerting:logs.alert.document.count/alerts/rule/create", + "alerting:logs.alert.document.count/alerts/rule/delete", + "alerting:logs.alert.document.count/alerts/rule/update", + "alerting:logs.alert.document.count/alerts/rule/updateApiKey", + "alerting:logs.alert.document.count/alerts/rule/enable", + "alerting:logs.alert.document.count/alerts/rule/disable", + "alerting:logs.alert.document.count/alerts/rule/muteAll", + "alerting:logs.alert.document.count/alerts/rule/unmuteAll", + "alerting:logs.alert.document.count/alerts/rule/muteAlert", + "alerting:logs.alert.document.count/alerts/rule/unmuteAlert", + "alerting:logs.alert.document.count/alerts/rule/snooze", + "alerting:logs.alert.document.count/alerts/rule/bulkEdit", + "alerting:logs.alert.document.count/alerts/rule/bulkDelete", + "alerting:logs.alert.document.count/alerts/rule/bulkEnable", + "alerting:logs.alert.document.count/alerts/rule/bulkDisable", + "alerting:logs.alert.document.count/alerts/rule/unsnooze", + "alerting:logs.alert.document.count/alerts/rule/runSoon", + "alerting:logs.alert.document.count/alerts/rule/scheduleBackfill", + "alerting:logs.alert.document.count/alerts/rule/deleteBackfill", "alerting:.es-query/logs/rule/get", "alerting:.es-query/logs/rule/getRuleState", "alerting:.es-query/logs/rule/getAlertSummary", @@ -4964,6 +7274,11 @@ export default function ({ getService }: FtrProviderContext) { "alerting:logs.alert.document.count/logs/alert/getAuthorizedAlertsIndices", "alerting:logs.alert.document.count/logs/alert/getAlertSummary", "alerting:logs.alert.document.count/logs/alert/update", + "alerting:logs.alert.document.count/alerts/alert/get", + "alerting:logs.alert.document.count/alerts/alert/find", + "alerting:logs.alert.document.count/alerts/alert/getAuthorizedAlertsIndices", + "alerting:logs.alert.document.count/alerts/alert/getAlertSummary", + "alerting:logs.alert.document.count/alerts/alert/update", "alerting:.es-query/logs/alert/get", "alerting:.es-query/logs/alert/find", "alerting:.es-query/logs/alert/getAuthorizedAlertsIndices", @@ -5012,6 +7327,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:slo.rules.burnRate/observability/rule/runSoon", "alerting:slo.rules.burnRate/observability/rule/scheduleBackfill", "alerting:slo.rules.burnRate/observability/rule/deleteBackfill", + "alerting:slo.rules.burnRate/alerts/rule/get", + "alerting:slo.rules.burnRate/alerts/rule/getRuleState", + "alerting:slo.rules.burnRate/alerts/rule/getAlertSummary", + "alerting:slo.rules.burnRate/alerts/rule/getExecutionLog", + "alerting:slo.rules.burnRate/alerts/rule/getActionErrorLog", + "alerting:slo.rules.burnRate/alerts/rule/find", + "alerting:slo.rules.burnRate/alerts/rule/getRuleExecutionKPI", + "alerting:slo.rules.burnRate/alerts/rule/getBackfill", + "alerting:slo.rules.burnRate/alerts/rule/findBackfill", + "alerting:slo.rules.burnRate/alerts/rule/create", + "alerting:slo.rules.burnRate/alerts/rule/delete", + "alerting:slo.rules.burnRate/alerts/rule/update", + "alerting:slo.rules.burnRate/alerts/rule/updateApiKey", + "alerting:slo.rules.burnRate/alerts/rule/enable", + "alerting:slo.rules.burnRate/alerts/rule/disable", + "alerting:slo.rules.burnRate/alerts/rule/muteAll", + "alerting:slo.rules.burnRate/alerts/rule/unmuteAll", + "alerting:slo.rules.burnRate/alerts/rule/muteAlert", + "alerting:slo.rules.burnRate/alerts/rule/unmuteAlert", + "alerting:slo.rules.burnRate/alerts/rule/snooze", + "alerting:slo.rules.burnRate/alerts/rule/bulkEdit", + "alerting:slo.rules.burnRate/alerts/rule/bulkDelete", + "alerting:slo.rules.burnRate/alerts/rule/bulkEnable", + "alerting:slo.rules.burnRate/alerts/rule/bulkDisable", + "alerting:slo.rules.burnRate/alerts/rule/unsnooze", + "alerting:slo.rules.burnRate/alerts/rule/runSoon", + "alerting:slo.rules.burnRate/alerts/rule/scheduleBackfill", + "alerting:slo.rules.burnRate/alerts/rule/deleteBackfill", "alerting:observability.rules.custom_threshold/observability/rule/get", "alerting:observability.rules.custom_threshold/observability/rule/getRuleState", "alerting:observability.rules.custom_threshold/observability/rule/getAlertSummary", @@ -5152,6 +7495,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.error_rate/observability/rule/runSoon", "alerting:apm.error_rate/observability/rule/scheduleBackfill", "alerting:apm.error_rate/observability/rule/deleteBackfill", + "alerting:apm.error_rate/alerts/rule/get", + "alerting:apm.error_rate/alerts/rule/getRuleState", + "alerting:apm.error_rate/alerts/rule/getAlertSummary", + "alerting:apm.error_rate/alerts/rule/getExecutionLog", + "alerting:apm.error_rate/alerts/rule/getActionErrorLog", + "alerting:apm.error_rate/alerts/rule/find", + "alerting:apm.error_rate/alerts/rule/getRuleExecutionKPI", + "alerting:apm.error_rate/alerts/rule/getBackfill", + "alerting:apm.error_rate/alerts/rule/findBackfill", + "alerting:apm.error_rate/alerts/rule/create", + "alerting:apm.error_rate/alerts/rule/delete", + "alerting:apm.error_rate/alerts/rule/update", + "alerting:apm.error_rate/alerts/rule/updateApiKey", + "alerting:apm.error_rate/alerts/rule/enable", + "alerting:apm.error_rate/alerts/rule/disable", + "alerting:apm.error_rate/alerts/rule/muteAll", + "alerting:apm.error_rate/alerts/rule/unmuteAll", + "alerting:apm.error_rate/alerts/rule/muteAlert", + "alerting:apm.error_rate/alerts/rule/unmuteAlert", + "alerting:apm.error_rate/alerts/rule/snooze", + "alerting:apm.error_rate/alerts/rule/bulkEdit", + "alerting:apm.error_rate/alerts/rule/bulkDelete", + "alerting:apm.error_rate/alerts/rule/bulkEnable", + "alerting:apm.error_rate/alerts/rule/bulkDisable", + "alerting:apm.error_rate/alerts/rule/unsnooze", + "alerting:apm.error_rate/alerts/rule/runSoon", + "alerting:apm.error_rate/alerts/rule/scheduleBackfill", + "alerting:apm.error_rate/alerts/rule/deleteBackfill", "alerting:apm.transaction_error_rate/observability/rule/get", "alerting:apm.transaction_error_rate/observability/rule/getRuleState", "alerting:apm.transaction_error_rate/observability/rule/getAlertSummary", @@ -5180,6 +7551,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.transaction_error_rate/observability/rule/runSoon", "alerting:apm.transaction_error_rate/observability/rule/scheduleBackfill", "alerting:apm.transaction_error_rate/observability/rule/deleteBackfill", + "alerting:apm.transaction_error_rate/alerts/rule/get", + "alerting:apm.transaction_error_rate/alerts/rule/getRuleState", + "alerting:apm.transaction_error_rate/alerts/rule/getAlertSummary", + "alerting:apm.transaction_error_rate/alerts/rule/getExecutionLog", + "alerting:apm.transaction_error_rate/alerts/rule/getActionErrorLog", + "alerting:apm.transaction_error_rate/alerts/rule/find", + "alerting:apm.transaction_error_rate/alerts/rule/getRuleExecutionKPI", + "alerting:apm.transaction_error_rate/alerts/rule/getBackfill", + "alerting:apm.transaction_error_rate/alerts/rule/findBackfill", + "alerting:apm.transaction_error_rate/alerts/rule/create", + "alerting:apm.transaction_error_rate/alerts/rule/delete", + "alerting:apm.transaction_error_rate/alerts/rule/update", + "alerting:apm.transaction_error_rate/alerts/rule/updateApiKey", + "alerting:apm.transaction_error_rate/alerts/rule/enable", + "alerting:apm.transaction_error_rate/alerts/rule/disable", + "alerting:apm.transaction_error_rate/alerts/rule/muteAll", + "alerting:apm.transaction_error_rate/alerts/rule/unmuteAll", + "alerting:apm.transaction_error_rate/alerts/rule/muteAlert", + "alerting:apm.transaction_error_rate/alerts/rule/unmuteAlert", + "alerting:apm.transaction_error_rate/alerts/rule/snooze", + "alerting:apm.transaction_error_rate/alerts/rule/bulkEdit", + "alerting:apm.transaction_error_rate/alerts/rule/bulkDelete", + "alerting:apm.transaction_error_rate/alerts/rule/bulkEnable", + "alerting:apm.transaction_error_rate/alerts/rule/bulkDisable", + "alerting:apm.transaction_error_rate/alerts/rule/unsnooze", + "alerting:apm.transaction_error_rate/alerts/rule/runSoon", + "alerting:apm.transaction_error_rate/alerts/rule/scheduleBackfill", + "alerting:apm.transaction_error_rate/alerts/rule/deleteBackfill", "alerting:apm.transaction_duration/observability/rule/get", "alerting:apm.transaction_duration/observability/rule/getRuleState", "alerting:apm.transaction_duration/observability/rule/getAlertSummary", @@ -5208,6 +7607,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.transaction_duration/observability/rule/runSoon", "alerting:apm.transaction_duration/observability/rule/scheduleBackfill", "alerting:apm.transaction_duration/observability/rule/deleteBackfill", + "alerting:apm.transaction_duration/alerts/rule/get", + "alerting:apm.transaction_duration/alerts/rule/getRuleState", + "alerting:apm.transaction_duration/alerts/rule/getAlertSummary", + "alerting:apm.transaction_duration/alerts/rule/getExecutionLog", + "alerting:apm.transaction_duration/alerts/rule/getActionErrorLog", + "alerting:apm.transaction_duration/alerts/rule/find", + "alerting:apm.transaction_duration/alerts/rule/getRuleExecutionKPI", + "alerting:apm.transaction_duration/alerts/rule/getBackfill", + "alerting:apm.transaction_duration/alerts/rule/findBackfill", + "alerting:apm.transaction_duration/alerts/rule/create", + "alerting:apm.transaction_duration/alerts/rule/delete", + "alerting:apm.transaction_duration/alerts/rule/update", + "alerting:apm.transaction_duration/alerts/rule/updateApiKey", + "alerting:apm.transaction_duration/alerts/rule/enable", + "alerting:apm.transaction_duration/alerts/rule/disable", + "alerting:apm.transaction_duration/alerts/rule/muteAll", + "alerting:apm.transaction_duration/alerts/rule/unmuteAll", + "alerting:apm.transaction_duration/alerts/rule/muteAlert", + "alerting:apm.transaction_duration/alerts/rule/unmuteAlert", + "alerting:apm.transaction_duration/alerts/rule/snooze", + "alerting:apm.transaction_duration/alerts/rule/bulkEdit", + "alerting:apm.transaction_duration/alerts/rule/bulkDelete", + "alerting:apm.transaction_duration/alerts/rule/bulkEnable", + "alerting:apm.transaction_duration/alerts/rule/bulkDisable", + "alerting:apm.transaction_duration/alerts/rule/unsnooze", + "alerting:apm.transaction_duration/alerts/rule/runSoon", + "alerting:apm.transaction_duration/alerts/rule/scheduleBackfill", + "alerting:apm.transaction_duration/alerts/rule/deleteBackfill", "alerting:apm.anomaly/observability/rule/get", "alerting:apm.anomaly/observability/rule/getRuleState", "alerting:apm.anomaly/observability/rule/getAlertSummary", @@ -5236,11 +7663,44 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.anomaly/observability/rule/runSoon", "alerting:apm.anomaly/observability/rule/scheduleBackfill", "alerting:apm.anomaly/observability/rule/deleteBackfill", + "alerting:apm.anomaly/alerts/rule/get", + "alerting:apm.anomaly/alerts/rule/getRuleState", + "alerting:apm.anomaly/alerts/rule/getAlertSummary", + "alerting:apm.anomaly/alerts/rule/getExecutionLog", + "alerting:apm.anomaly/alerts/rule/getActionErrorLog", + "alerting:apm.anomaly/alerts/rule/find", + "alerting:apm.anomaly/alerts/rule/getRuleExecutionKPI", + "alerting:apm.anomaly/alerts/rule/getBackfill", + "alerting:apm.anomaly/alerts/rule/findBackfill", + "alerting:apm.anomaly/alerts/rule/create", + "alerting:apm.anomaly/alerts/rule/delete", + "alerting:apm.anomaly/alerts/rule/update", + "alerting:apm.anomaly/alerts/rule/updateApiKey", + "alerting:apm.anomaly/alerts/rule/enable", + "alerting:apm.anomaly/alerts/rule/disable", + "alerting:apm.anomaly/alerts/rule/muteAll", + "alerting:apm.anomaly/alerts/rule/unmuteAll", + "alerting:apm.anomaly/alerts/rule/muteAlert", + "alerting:apm.anomaly/alerts/rule/unmuteAlert", + "alerting:apm.anomaly/alerts/rule/snooze", + "alerting:apm.anomaly/alerts/rule/bulkEdit", + "alerting:apm.anomaly/alerts/rule/bulkDelete", + "alerting:apm.anomaly/alerts/rule/bulkEnable", + "alerting:apm.anomaly/alerts/rule/bulkDisable", + "alerting:apm.anomaly/alerts/rule/unsnooze", + "alerting:apm.anomaly/alerts/rule/runSoon", + "alerting:apm.anomaly/alerts/rule/scheduleBackfill", + "alerting:apm.anomaly/alerts/rule/deleteBackfill", "alerting:slo.rules.burnRate/observability/alert/get", "alerting:slo.rules.burnRate/observability/alert/find", "alerting:slo.rules.burnRate/observability/alert/getAuthorizedAlertsIndices", "alerting:slo.rules.burnRate/observability/alert/getAlertSummary", "alerting:slo.rules.burnRate/observability/alert/update", + "alerting:slo.rules.burnRate/alerts/alert/get", + "alerting:slo.rules.burnRate/alerts/alert/find", + "alerting:slo.rules.burnRate/alerts/alert/getAuthorizedAlertsIndices", + "alerting:slo.rules.burnRate/alerts/alert/getAlertSummary", + "alerting:slo.rules.burnRate/alerts/alert/update", "alerting:observability.rules.custom_threshold/observability/alert/get", "alerting:observability.rules.custom_threshold/observability/alert/find", "alerting:observability.rules.custom_threshold/observability/alert/getAuthorizedAlertsIndices", @@ -5266,21 +7726,41 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.error_rate/observability/alert/getAuthorizedAlertsIndices", "alerting:apm.error_rate/observability/alert/getAlertSummary", "alerting:apm.error_rate/observability/alert/update", + "alerting:apm.error_rate/alerts/alert/get", + "alerting:apm.error_rate/alerts/alert/find", + "alerting:apm.error_rate/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.error_rate/alerts/alert/getAlertSummary", + "alerting:apm.error_rate/alerts/alert/update", "alerting:apm.transaction_error_rate/observability/alert/get", "alerting:apm.transaction_error_rate/observability/alert/find", "alerting:apm.transaction_error_rate/observability/alert/getAuthorizedAlertsIndices", "alerting:apm.transaction_error_rate/observability/alert/getAlertSummary", "alerting:apm.transaction_error_rate/observability/alert/update", + "alerting:apm.transaction_error_rate/alerts/alert/get", + "alerting:apm.transaction_error_rate/alerts/alert/find", + "alerting:apm.transaction_error_rate/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.transaction_error_rate/alerts/alert/getAlertSummary", + "alerting:apm.transaction_error_rate/alerts/alert/update", "alerting:apm.transaction_duration/observability/alert/get", "alerting:apm.transaction_duration/observability/alert/find", "alerting:apm.transaction_duration/observability/alert/getAuthorizedAlertsIndices", "alerting:apm.transaction_duration/observability/alert/getAlertSummary", "alerting:apm.transaction_duration/observability/alert/update", + "alerting:apm.transaction_duration/alerts/alert/get", + "alerting:apm.transaction_duration/alerts/alert/find", + "alerting:apm.transaction_duration/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.transaction_duration/alerts/alert/getAlertSummary", + "alerting:apm.transaction_duration/alerts/alert/update", "alerting:apm.anomaly/observability/alert/get", "alerting:apm.anomaly/observability/alert/find", "alerting:apm.anomaly/observability/alert/getAuthorizedAlertsIndices", "alerting:apm.anomaly/observability/alert/getAlertSummary", "alerting:apm.anomaly/observability/alert/update", + "alerting:apm.anomaly/alerts/alert/get", + "alerting:apm.anomaly/alerts/alert/find", + "alerting:apm.anomaly/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.anomaly/alerts/alert/getAlertSummary", + "alerting:apm.anomaly/alerts/alert/update", ], "minimal_all": Array [ "login:", @@ -5382,6 +7862,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:metrics.alert.threshold/infrastructure/rule/runSoon", "alerting:metrics.alert.threshold/infrastructure/rule/scheduleBackfill", "alerting:metrics.alert.threshold/infrastructure/rule/deleteBackfill", + "alerting:metrics.alert.threshold/alerts/rule/get", + "alerting:metrics.alert.threshold/alerts/rule/getRuleState", + "alerting:metrics.alert.threshold/alerts/rule/getAlertSummary", + "alerting:metrics.alert.threshold/alerts/rule/getExecutionLog", + "alerting:metrics.alert.threshold/alerts/rule/getActionErrorLog", + "alerting:metrics.alert.threshold/alerts/rule/find", + "alerting:metrics.alert.threshold/alerts/rule/getRuleExecutionKPI", + "alerting:metrics.alert.threshold/alerts/rule/getBackfill", + "alerting:metrics.alert.threshold/alerts/rule/findBackfill", + "alerting:metrics.alert.threshold/alerts/rule/create", + "alerting:metrics.alert.threshold/alerts/rule/delete", + "alerting:metrics.alert.threshold/alerts/rule/update", + "alerting:metrics.alert.threshold/alerts/rule/updateApiKey", + "alerting:metrics.alert.threshold/alerts/rule/enable", + "alerting:metrics.alert.threshold/alerts/rule/disable", + "alerting:metrics.alert.threshold/alerts/rule/muteAll", + "alerting:metrics.alert.threshold/alerts/rule/unmuteAll", + "alerting:metrics.alert.threshold/alerts/rule/muteAlert", + "alerting:metrics.alert.threshold/alerts/rule/unmuteAlert", + "alerting:metrics.alert.threshold/alerts/rule/snooze", + "alerting:metrics.alert.threshold/alerts/rule/bulkEdit", + "alerting:metrics.alert.threshold/alerts/rule/bulkDelete", + "alerting:metrics.alert.threshold/alerts/rule/bulkEnable", + "alerting:metrics.alert.threshold/alerts/rule/bulkDisable", + "alerting:metrics.alert.threshold/alerts/rule/unsnooze", + "alerting:metrics.alert.threshold/alerts/rule/runSoon", + "alerting:metrics.alert.threshold/alerts/rule/scheduleBackfill", + "alerting:metrics.alert.threshold/alerts/rule/deleteBackfill", "alerting:metrics.alert.inventory.threshold/infrastructure/rule/get", "alerting:metrics.alert.inventory.threshold/infrastructure/rule/getRuleState", "alerting:metrics.alert.inventory.threshold/infrastructure/rule/getAlertSummary", @@ -5410,6 +7918,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:metrics.alert.inventory.threshold/infrastructure/rule/runSoon", "alerting:metrics.alert.inventory.threshold/infrastructure/rule/scheduleBackfill", "alerting:metrics.alert.inventory.threshold/infrastructure/rule/deleteBackfill", + "alerting:metrics.alert.inventory.threshold/alerts/rule/get", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getRuleState", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getAlertSummary", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getExecutionLog", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getActionErrorLog", + "alerting:metrics.alert.inventory.threshold/alerts/rule/find", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getRuleExecutionKPI", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getBackfill", + "alerting:metrics.alert.inventory.threshold/alerts/rule/findBackfill", + "alerting:metrics.alert.inventory.threshold/alerts/rule/create", + "alerting:metrics.alert.inventory.threshold/alerts/rule/delete", + "alerting:metrics.alert.inventory.threshold/alerts/rule/update", + "alerting:metrics.alert.inventory.threshold/alerts/rule/updateApiKey", + "alerting:metrics.alert.inventory.threshold/alerts/rule/enable", + "alerting:metrics.alert.inventory.threshold/alerts/rule/disable", + "alerting:metrics.alert.inventory.threshold/alerts/rule/muteAll", + "alerting:metrics.alert.inventory.threshold/alerts/rule/unmuteAll", + "alerting:metrics.alert.inventory.threshold/alerts/rule/muteAlert", + "alerting:metrics.alert.inventory.threshold/alerts/rule/unmuteAlert", + "alerting:metrics.alert.inventory.threshold/alerts/rule/snooze", + "alerting:metrics.alert.inventory.threshold/alerts/rule/bulkEdit", + "alerting:metrics.alert.inventory.threshold/alerts/rule/bulkDelete", + "alerting:metrics.alert.inventory.threshold/alerts/rule/bulkEnable", + "alerting:metrics.alert.inventory.threshold/alerts/rule/bulkDisable", + "alerting:metrics.alert.inventory.threshold/alerts/rule/unsnooze", + "alerting:metrics.alert.inventory.threshold/alerts/rule/runSoon", + "alerting:metrics.alert.inventory.threshold/alerts/rule/scheduleBackfill", + "alerting:metrics.alert.inventory.threshold/alerts/rule/deleteBackfill", "alerting:.es-query/infrastructure/rule/get", "alerting:.es-query/infrastructure/rule/getRuleState", "alerting:.es-query/infrastructure/rule/getAlertSummary", @@ -5438,6 +7974,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:.es-query/infrastructure/rule/runSoon", "alerting:.es-query/infrastructure/rule/scheduleBackfill", "alerting:.es-query/infrastructure/rule/deleteBackfill", + "alerting:.es-query/alerts/rule/get", + "alerting:.es-query/alerts/rule/getRuleState", + "alerting:.es-query/alerts/rule/getAlertSummary", + "alerting:.es-query/alerts/rule/getExecutionLog", + "alerting:.es-query/alerts/rule/getActionErrorLog", + "alerting:.es-query/alerts/rule/find", + "alerting:.es-query/alerts/rule/getRuleExecutionKPI", + "alerting:.es-query/alerts/rule/getBackfill", + "alerting:.es-query/alerts/rule/findBackfill", + "alerting:.es-query/alerts/rule/create", + "alerting:.es-query/alerts/rule/delete", + "alerting:.es-query/alerts/rule/update", + "alerting:.es-query/alerts/rule/updateApiKey", + "alerting:.es-query/alerts/rule/enable", + "alerting:.es-query/alerts/rule/disable", + "alerting:.es-query/alerts/rule/muteAll", + "alerting:.es-query/alerts/rule/unmuteAll", + "alerting:.es-query/alerts/rule/muteAlert", + "alerting:.es-query/alerts/rule/unmuteAlert", + "alerting:.es-query/alerts/rule/snooze", + "alerting:.es-query/alerts/rule/bulkEdit", + "alerting:.es-query/alerts/rule/bulkDelete", + "alerting:.es-query/alerts/rule/bulkEnable", + "alerting:.es-query/alerts/rule/bulkDisable", + "alerting:.es-query/alerts/rule/unsnooze", + "alerting:.es-query/alerts/rule/runSoon", + "alerting:.es-query/alerts/rule/scheduleBackfill", + "alerting:.es-query/alerts/rule/deleteBackfill", "alerting:observability.rules.custom_threshold/infrastructure/rule/get", "alerting:observability.rules.custom_threshold/infrastructure/rule/getRuleState", "alerting:observability.rules.custom_threshold/infrastructure/rule/getAlertSummary", @@ -5466,6 +8030,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:observability.rules.custom_threshold/infrastructure/rule/runSoon", "alerting:observability.rules.custom_threshold/infrastructure/rule/scheduleBackfill", "alerting:observability.rules.custom_threshold/infrastructure/rule/deleteBackfill", + "alerting:observability.rules.custom_threshold/alerts/rule/get", + "alerting:observability.rules.custom_threshold/alerts/rule/getRuleState", + "alerting:observability.rules.custom_threshold/alerts/rule/getAlertSummary", + "alerting:observability.rules.custom_threshold/alerts/rule/getExecutionLog", + "alerting:observability.rules.custom_threshold/alerts/rule/getActionErrorLog", + "alerting:observability.rules.custom_threshold/alerts/rule/find", + "alerting:observability.rules.custom_threshold/alerts/rule/getRuleExecutionKPI", + "alerting:observability.rules.custom_threshold/alerts/rule/getBackfill", + "alerting:observability.rules.custom_threshold/alerts/rule/findBackfill", + "alerting:observability.rules.custom_threshold/alerts/rule/create", + "alerting:observability.rules.custom_threshold/alerts/rule/delete", + "alerting:observability.rules.custom_threshold/alerts/rule/update", + "alerting:observability.rules.custom_threshold/alerts/rule/updateApiKey", + "alerting:observability.rules.custom_threshold/alerts/rule/enable", + "alerting:observability.rules.custom_threshold/alerts/rule/disable", + "alerting:observability.rules.custom_threshold/alerts/rule/muteAll", + "alerting:observability.rules.custom_threshold/alerts/rule/unmuteAll", + "alerting:observability.rules.custom_threshold/alerts/rule/muteAlert", + "alerting:observability.rules.custom_threshold/alerts/rule/unmuteAlert", + "alerting:observability.rules.custom_threshold/alerts/rule/snooze", + "alerting:observability.rules.custom_threshold/alerts/rule/bulkEdit", + "alerting:observability.rules.custom_threshold/alerts/rule/bulkDelete", + "alerting:observability.rules.custom_threshold/alerts/rule/bulkEnable", + "alerting:observability.rules.custom_threshold/alerts/rule/bulkDisable", + "alerting:observability.rules.custom_threshold/alerts/rule/unsnooze", + "alerting:observability.rules.custom_threshold/alerts/rule/runSoon", + "alerting:observability.rules.custom_threshold/alerts/rule/scheduleBackfill", + "alerting:observability.rules.custom_threshold/alerts/rule/deleteBackfill", "alerting:xpack.ml.anomaly_detection_alert/infrastructure/rule/get", "alerting:xpack.ml.anomaly_detection_alert/infrastructure/rule/getRuleState", "alerting:xpack.ml.anomaly_detection_alert/infrastructure/rule/getAlertSummary", @@ -5494,31 +8086,84 @@ export default function ({ getService }: FtrProviderContext) { "alerting:xpack.ml.anomaly_detection_alert/infrastructure/rule/runSoon", "alerting:xpack.ml.anomaly_detection_alert/infrastructure/rule/scheduleBackfill", "alerting:xpack.ml.anomaly_detection_alert/infrastructure/rule/deleteBackfill", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/get", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getRuleState", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getAlertSummary", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getExecutionLog", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getActionErrorLog", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/find", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getRuleExecutionKPI", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getBackfill", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/findBackfill", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/create", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/delete", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/update", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/updateApiKey", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/enable", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/disable", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/muteAll", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/unmuteAll", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/muteAlert", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/unmuteAlert", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/snooze", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/bulkEdit", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/bulkDelete", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/bulkEnable", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/bulkDisable", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/unsnooze", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/runSoon", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/scheduleBackfill", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/deleteBackfill", "alerting:metrics.alert.threshold/infrastructure/alert/get", "alerting:metrics.alert.threshold/infrastructure/alert/find", "alerting:metrics.alert.threshold/infrastructure/alert/getAuthorizedAlertsIndices", "alerting:metrics.alert.threshold/infrastructure/alert/getAlertSummary", "alerting:metrics.alert.threshold/infrastructure/alert/update", + "alerting:metrics.alert.threshold/alerts/alert/get", + "alerting:metrics.alert.threshold/alerts/alert/find", + "alerting:metrics.alert.threshold/alerts/alert/getAuthorizedAlertsIndices", + "alerting:metrics.alert.threshold/alerts/alert/getAlertSummary", + "alerting:metrics.alert.threshold/alerts/alert/update", "alerting:metrics.alert.inventory.threshold/infrastructure/alert/get", "alerting:metrics.alert.inventory.threshold/infrastructure/alert/find", "alerting:metrics.alert.inventory.threshold/infrastructure/alert/getAuthorizedAlertsIndices", "alerting:metrics.alert.inventory.threshold/infrastructure/alert/getAlertSummary", "alerting:metrics.alert.inventory.threshold/infrastructure/alert/update", + "alerting:metrics.alert.inventory.threshold/alerts/alert/get", + "alerting:metrics.alert.inventory.threshold/alerts/alert/find", + "alerting:metrics.alert.inventory.threshold/alerts/alert/getAuthorizedAlertsIndices", + "alerting:metrics.alert.inventory.threshold/alerts/alert/getAlertSummary", + "alerting:metrics.alert.inventory.threshold/alerts/alert/update", "alerting:.es-query/infrastructure/alert/get", "alerting:.es-query/infrastructure/alert/find", "alerting:.es-query/infrastructure/alert/getAuthorizedAlertsIndices", "alerting:.es-query/infrastructure/alert/getAlertSummary", "alerting:.es-query/infrastructure/alert/update", + "alerting:.es-query/alerts/alert/get", + "alerting:.es-query/alerts/alert/find", + "alerting:.es-query/alerts/alert/getAuthorizedAlertsIndices", + "alerting:.es-query/alerts/alert/getAlertSummary", + "alerting:.es-query/alerts/alert/update", "alerting:observability.rules.custom_threshold/infrastructure/alert/get", "alerting:observability.rules.custom_threshold/infrastructure/alert/find", "alerting:observability.rules.custom_threshold/infrastructure/alert/getAuthorizedAlertsIndices", "alerting:observability.rules.custom_threshold/infrastructure/alert/getAlertSummary", "alerting:observability.rules.custom_threshold/infrastructure/alert/update", + "alerting:observability.rules.custom_threshold/alerts/alert/get", + "alerting:observability.rules.custom_threshold/alerts/alert/find", + "alerting:observability.rules.custom_threshold/alerts/alert/getAuthorizedAlertsIndices", + "alerting:observability.rules.custom_threshold/alerts/alert/getAlertSummary", + "alerting:observability.rules.custom_threshold/alerts/alert/update", "alerting:xpack.ml.anomaly_detection_alert/infrastructure/alert/get", "alerting:xpack.ml.anomaly_detection_alert/infrastructure/alert/find", "alerting:xpack.ml.anomaly_detection_alert/infrastructure/alert/getAuthorizedAlertsIndices", "alerting:xpack.ml.anomaly_detection_alert/infrastructure/alert/getAlertSummary", "alerting:xpack.ml.anomaly_detection_alert/infrastructure/alert/update", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/get", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/find", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/getAuthorizedAlertsIndices", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/getAlertSummary", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/update", "app:logs", "ui:catalogue/infralogging", "ui:catalogue/logs", @@ -5566,6 +8211,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:logs.alert.document.count/logs/rule/runSoon", "alerting:logs.alert.document.count/logs/rule/scheduleBackfill", "alerting:logs.alert.document.count/logs/rule/deleteBackfill", + "alerting:logs.alert.document.count/alerts/rule/get", + "alerting:logs.alert.document.count/alerts/rule/getRuleState", + "alerting:logs.alert.document.count/alerts/rule/getAlertSummary", + "alerting:logs.alert.document.count/alerts/rule/getExecutionLog", + "alerting:logs.alert.document.count/alerts/rule/getActionErrorLog", + "alerting:logs.alert.document.count/alerts/rule/find", + "alerting:logs.alert.document.count/alerts/rule/getRuleExecutionKPI", + "alerting:logs.alert.document.count/alerts/rule/getBackfill", + "alerting:logs.alert.document.count/alerts/rule/findBackfill", + "alerting:logs.alert.document.count/alerts/rule/create", + "alerting:logs.alert.document.count/alerts/rule/delete", + "alerting:logs.alert.document.count/alerts/rule/update", + "alerting:logs.alert.document.count/alerts/rule/updateApiKey", + "alerting:logs.alert.document.count/alerts/rule/enable", + "alerting:logs.alert.document.count/alerts/rule/disable", + "alerting:logs.alert.document.count/alerts/rule/muteAll", + "alerting:logs.alert.document.count/alerts/rule/unmuteAll", + "alerting:logs.alert.document.count/alerts/rule/muteAlert", + "alerting:logs.alert.document.count/alerts/rule/unmuteAlert", + "alerting:logs.alert.document.count/alerts/rule/snooze", + "alerting:logs.alert.document.count/alerts/rule/bulkEdit", + "alerting:logs.alert.document.count/alerts/rule/bulkDelete", + "alerting:logs.alert.document.count/alerts/rule/bulkEnable", + "alerting:logs.alert.document.count/alerts/rule/bulkDisable", + "alerting:logs.alert.document.count/alerts/rule/unsnooze", + "alerting:logs.alert.document.count/alerts/rule/runSoon", + "alerting:logs.alert.document.count/alerts/rule/scheduleBackfill", + "alerting:logs.alert.document.count/alerts/rule/deleteBackfill", "alerting:.es-query/logs/rule/get", "alerting:.es-query/logs/rule/getRuleState", "alerting:.es-query/logs/rule/getAlertSummary", @@ -5655,6 +8328,11 @@ export default function ({ getService }: FtrProviderContext) { "alerting:logs.alert.document.count/logs/alert/getAuthorizedAlertsIndices", "alerting:logs.alert.document.count/logs/alert/getAlertSummary", "alerting:logs.alert.document.count/logs/alert/update", + "alerting:logs.alert.document.count/alerts/alert/get", + "alerting:logs.alert.document.count/alerts/alert/find", + "alerting:logs.alert.document.count/alerts/alert/getAuthorizedAlertsIndices", + "alerting:logs.alert.document.count/alerts/alert/getAlertSummary", + "alerting:logs.alert.document.count/alerts/alert/update", "alerting:.es-query/logs/alert/get", "alerting:.es-query/logs/alert/find", "alerting:.es-query/logs/alert/getAuthorizedAlertsIndices", @@ -5703,6 +8381,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:slo.rules.burnRate/observability/rule/runSoon", "alerting:slo.rules.burnRate/observability/rule/scheduleBackfill", "alerting:slo.rules.burnRate/observability/rule/deleteBackfill", + "alerting:slo.rules.burnRate/alerts/rule/get", + "alerting:slo.rules.burnRate/alerts/rule/getRuleState", + "alerting:slo.rules.burnRate/alerts/rule/getAlertSummary", + "alerting:slo.rules.burnRate/alerts/rule/getExecutionLog", + "alerting:slo.rules.burnRate/alerts/rule/getActionErrorLog", + "alerting:slo.rules.burnRate/alerts/rule/find", + "alerting:slo.rules.burnRate/alerts/rule/getRuleExecutionKPI", + "alerting:slo.rules.burnRate/alerts/rule/getBackfill", + "alerting:slo.rules.burnRate/alerts/rule/findBackfill", + "alerting:slo.rules.burnRate/alerts/rule/create", + "alerting:slo.rules.burnRate/alerts/rule/delete", + "alerting:slo.rules.burnRate/alerts/rule/update", + "alerting:slo.rules.burnRate/alerts/rule/updateApiKey", + "alerting:slo.rules.burnRate/alerts/rule/enable", + "alerting:slo.rules.burnRate/alerts/rule/disable", + "alerting:slo.rules.burnRate/alerts/rule/muteAll", + "alerting:slo.rules.burnRate/alerts/rule/unmuteAll", + "alerting:slo.rules.burnRate/alerts/rule/muteAlert", + "alerting:slo.rules.burnRate/alerts/rule/unmuteAlert", + "alerting:slo.rules.burnRate/alerts/rule/snooze", + "alerting:slo.rules.burnRate/alerts/rule/bulkEdit", + "alerting:slo.rules.burnRate/alerts/rule/bulkDelete", + "alerting:slo.rules.burnRate/alerts/rule/bulkEnable", + "alerting:slo.rules.burnRate/alerts/rule/bulkDisable", + "alerting:slo.rules.burnRate/alerts/rule/unsnooze", + "alerting:slo.rules.burnRate/alerts/rule/runSoon", + "alerting:slo.rules.burnRate/alerts/rule/scheduleBackfill", + "alerting:slo.rules.burnRate/alerts/rule/deleteBackfill", "alerting:observability.rules.custom_threshold/observability/rule/get", "alerting:observability.rules.custom_threshold/observability/rule/getRuleState", "alerting:observability.rules.custom_threshold/observability/rule/getAlertSummary", @@ -5843,6 +8549,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.error_rate/observability/rule/runSoon", "alerting:apm.error_rate/observability/rule/scheduleBackfill", "alerting:apm.error_rate/observability/rule/deleteBackfill", + "alerting:apm.error_rate/alerts/rule/get", + "alerting:apm.error_rate/alerts/rule/getRuleState", + "alerting:apm.error_rate/alerts/rule/getAlertSummary", + "alerting:apm.error_rate/alerts/rule/getExecutionLog", + "alerting:apm.error_rate/alerts/rule/getActionErrorLog", + "alerting:apm.error_rate/alerts/rule/find", + "alerting:apm.error_rate/alerts/rule/getRuleExecutionKPI", + "alerting:apm.error_rate/alerts/rule/getBackfill", + "alerting:apm.error_rate/alerts/rule/findBackfill", + "alerting:apm.error_rate/alerts/rule/create", + "alerting:apm.error_rate/alerts/rule/delete", + "alerting:apm.error_rate/alerts/rule/update", + "alerting:apm.error_rate/alerts/rule/updateApiKey", + "alerting:apm.error_rate/alerts/rule/enable", + "alerting:apm.error_rate/alerts/rule/disable", + "alerting:apm.error_rate/alerts/rule/muteAll", + "alerting:apm.error_rate/alerts/rule/unmuteAll", + "alerting:apm.error_rate/alerts/rule/muteAlert", + "alerting:apm.error_rate/alerts/rule/unmuteAlert", + "alerting:apm.error_rate/alerts/rule/snooze", + "alerting:apm.error_rate/alerts/rule/bulkEdit", + "alerting:apm.error_rate/alerts/rule/bulkDelete", + "alerting:apm.error_rate/alerts/rule/bulkEnable", + "alerting:apm.error_rate/alerts/rule/bulkDisable", + "alerting:apm.error_rate/alerts/rule/unsnooze", + "alerting:apm.error_rate/alerts/rule/runSoon", + "alerting:apm.error_rate/alerts/rule/scheduleBackfill", + "alerting:apm.error_rate/alerts/rule/deleteBackfill", "alerting:apm.transaction_error_rate/observability/rule/get", "alerting:apm.transaction_error_rate/observability/rule/getRuleState", "alerting:apm.transaction_error_rate/observability/rule/getAlertSummary", @@ -5871,6 +8605,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.transaction_error_rate/observability/rule/runSoon", "alerting:apm.transaction_error_rate/observability/rule/scheduleBackfill", "alerting:apm.transaction_error_rate/observability/rule/deleteBackfill", + "alerting:apm.transaction_error_rate/alerts/rule/get", + "alerting:apm.transaction_error_rate/alerts/rule/getRuleState", + "alerting:apm.transaction_error_rate/alerts/rule/getAlertSummary", + "alerting:apm.transaction_error_rate/alerts/rule/getExecutionLog", + "alerting:apm.transaction_error_rate/alerts/rule/getActionErrorLog", + "alerting:apm.transaction_error_rate/alerts/rule/find", + "alerting:apm.transaction_error_rate/alerts/rule/getRuleExecutionKPI", + "alerting:apm.transaction_error_rate/alerts/rule/getBackfill", + "alerting:apm.transaction_error_rate/alerts/rule/findBackfill", + "alerting:apm.transaction_error_rate/alerts/rule/create", + "alerting:apm.transaction_error_rate/alerts/rule/delete", + "alerting:apm.transaction_error_rate/alerts/rule/update", + "alerting:apm.transaction_error_rate/alerts/rule/updateApiKey", + "alerting:apm.transaction_error_rate/alerts/rule/enable", + "alerting:apm.transaction_error_rate/alerts/rule/disable", + "alerting:apm.transaction_error_rate/alerts/rule/muteAll", + "alerting:apm.transaction_error_rate/alerts/rule/unmuteAll", + "alerting:apm.transaction_error_rate/alerts/rule/muteAlert", + "alerting:apm.transaction_error_rate/alerts/rule/unmuteAlert", + "alerting:apm.transaction_error_rate/alerts/rule/snooze", + "alerting:apm.transaction_error_rate/alerts/rule/bulkEdit", + "alerting:apm.transaction_error_rate/alerts/rule/bulkDelete", + "alerting:apm.transaction_error_rate/alerts/rule/bulkEnable", + "alerting:apm.transaction_error_rate/alerts/rule/bulkDisable", + "alerting:apm.transaction_error_rate/alerts/rule/unsnooze", + "alerting:apm.transaction_error_rate/alerts/rule/runSoon", + "alerting:apm.transaction_error_rate/alerts/rule/scheduleBackfill", + "alerting:apm.transaction_error_rate/alerts/rule/deleteBackfill", "alerting:apm.transaction_duration/observability/rule/get", "alerting:apm.transaction_duration/observability/rule/getRuleState", "alerting:apm.transaction_duration/observability/rule/getAlertSummary", @@ -5899,6 +8661,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.transaction_duration/observability/rule/runSoon", "alerting:apm.transaction_duration/observability/rule/scheduleBackfill", "alerting:apm.transaction_duration/observability/rule/deleteBackfill", + "alerting:apm.transaction_duration/alerts/rule/get", + "alerting:apm.transaction_duration/alerts/rule/getRuleState", + "alerting:apm.transaction_duration/alerts/rule/getAlertSummary", + "alerting:apm.transaction_duration/alerts/rule/getExecutionLog", + "alerting:apm.transaction_duration/alerts/rule/getActionErrorLog", + "alerting:apm.transaction_duration/alerts/rule/find", + "alerting:apm.transaction_duration/alerts/rule/getRuleExecutionKPI", + "alerting:apm.transaction_duration/alerts/rule/getBackfill", + "alerting:apm.transaction_duration/alerts/rule/findBackfill", + "alerting:apm.transaction_duration/alerts/rule/create", + "alerting:apm.transaction_duration/alerts/rule/delete", + "alerting:apm.transaction_duration/alerts/rule/update", + "alerting:apm.transaction_duration/alerts/rule/updateApiKey", + "alerting:apm.transaction_duration/alerts/rule/enable", + "alerting:apm.transaction_duration/alerts/rule/disable", + "alerting:apm.transaction_duration/alerts/rule/muteAll", + "alerting:apm.transaction_duration/alerts/rule/unmuteAll", + "alerting:apm.transaction_duration/alerts/rule/muteAlert", + "alerting:apm.transaction_duration/alerts/rule/unmuteAlert", + "alerting:apm.transaction_duration/alerts/rule/snooze", + "alerting:apm.transaction_duration/alerts/rule/bulkEdit", + "alerting:apm.transaction_duration/alerts/rule/bulkDelete", + "alerting:apm.transaction_duration/alerts/rule/bulkEnable", + "alerting:apm.transaction_duration/alerts/rule/bulkDisable", + "alerting:apm.transaction_duration/alerts/rule/unsnooze", + "alerting:apm.transaction_duration/alerts/rule/runSoon", + "alerting:apm.transaction_duration/alerts/rule/scheduleBackfill", + "alerting:apm.transaction_duration/alerts/rule/deleteBackfill", "alerting:apm.anomaly/observability/rule/get", "alerting:apm.anomaly/observability/rule/getRuleState", "alerting:apm.anomaly/observability/rule/getAlertSummary", @@ -5927,11 +8717,44 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.anomaly/observability/rule/runSoon", "alerting:apm.anomaly/observability/rule/scheduleBackfill", "alerting:apm.anomaly/observability/rule/deleteBackfill", + "alerting:apm.anomaly/alerts/rule/get", + "alerting:apm.anomaly/alerts/rule/getRuleState", + "alerting:apm.anomaly/alerts/rule/getAlertSummary", + "alerting:apm.anomaly/alerts/rule/getExecutionLog", + "alerting:apm.anomaly/alerts/rule/getActionErrorLog", + "alerting:apm.anomaly/alerts/rule/find", + "alerting:apm.anomaly/alerts/rule/getRuleExecutionKPI", + "alerting:apm.anomaly/alerts/rule/getBackfill", + "alerting:apm.anomaly/alerts/rule/findBackfill", + "alerting:apm.anomaly/alerts/rule/create", + "alerting:apm.anomaly/alerts/rule/delete", + "alerting:apm.anomaly/alerts/rule/update", + "alerting:apm.anomaly/alerts/rule/updateApiKey", + "alerting:apm.anomaly/alerts/rule/enable", + "alerting:apm.anomaly/alerts/rule/disable", + "alerting:apm.anomaly/alerts/rule/muteAll", + "alerting:apm.anomaly/alerts/rule/unmuteAll", + "alerting:apm.anomaly/alerts/rule/muteAlert", + "alerting:apm.anomaly/alerts/rule/unmuteAlert", + "alerting:apm.anomaly/alerts/rule/snooze", + "alerting:apm.anomaly/alerts/rule/bulkEdit", + "alerting:apm.anomaly/alerts/rule/bulkDelete", + "alerting:apm.anomaly/alerts/rule/bulkEnable", + "alerting:apm.anomaly/alerts/rule/bulkDisable", + "alerting:apm.anomaly/alerts/rule/unsnooze", + "alerting:apm.anomaly/alerts/rule/runSoon", + "alerting:apm.anomaly/alerts/rule/scheduleBackfill", + "alerting:apm.anomaly/alerts/rule/deleteBackfill", "alerting:slo.rules.burnRate/observability/alert/get", "alerting:slo.rules.burnRate/observability/alert/find", "alerting:slo.rules.burnRate/observability/alert/getAuthorizedAlertsIndices", "alerting:slo.rules.burnRate/observability/alert/getAlertSummary", "alerting:slo.rules.burnRate/observability/alert/update", + "alerting:slo.rules.burnRate/alerts/alert/get", + "alerting:slo.rules.burnRate/alerts/alert/find", + "alerting:slo.rules.burnRate/alerts/alert/getAuthorizedAlertsIndices", + "alerting:slo.rules.burnRate/alerts/alert/getAlertSummary", + "alerting:slo.rules.burnRate/alerts/alert/update", "alerting:observability.rules.custom_threshold/observability/alert/get", "alerting:observability.rules.custom_threshold/observability/alert/find", "alerting:observability.rules.custom_threshold/observability/alert/getAuthorizedAlertsIndices", @@ -5957,21 +8780,41 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.error_rate/observability/alert/getAuthorizedAlertsIndices", "alerting:apm.error_rate/observability/alert/getAlertSummary", "alerting:apm.error_rate/observability/alert/update", + "alerting:apm.error_rate/alerts/alert/get", + "alerting:apm.error_rate/alerts/alert/find", + "alerting:apm.error_rate/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.error_rate/alerts/alert/getAlertSummary", + "alerting:apm.error_rate/alerts/alert/update", "alerting:apm.transaction_error_rate/observability/alert/get", "alerting:apm.transaction_error_rate/observability/alert/find", "alerting:apm.transaction_error_rate/observability/alert/getAuthorizedAlertsIndices", "alerting:apm.transaction_error_rate/observability/alert/getAlertSummary", "alerting:apm.transaction_error_rate/observability/alert/update", + "alerting:apm.transaction_error_rate/alerts/alert/get", + "alerting:apm.transaction_error_rate/alerts/alert/find", + "alerting:apm.transaction_error_rate/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.transaction_error_rate/alerts/alert/getAlertSummary", + "alerting:apm.transaction_error_rate/alerts/alert/update", "alerting:apm.transaction_duration/observability/alert/get", "alerting:apm.transaction_duration/observability/alert/find", "alerting:apm.transaction_duration/observability/alert/getAuthorizedAlertsIndices", "alerting:apm.transaction_duration/observability/alert/getAlertSummary", "alerting:apm.transaction_duration/observability/alert/update", + "alerting:apm.transaction_duration/alerts/alert/get", + "alerting:apm.transaction_duration/alerts/alert/find", + "alerting:apm.transaction_duration/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.transaction_duration/alerts/alert/getAlertSummary", + "alerting:apm.transaction_duration/alerts/alert/update", "alerting:apm.anomaly/observability/alert/get", "alerting:apm.anomaly/observability/alert/find", "alerting:apm.anomaly/observability/alert/getAuthorizedAlertsIndices", "alerting:apm.anomaly/observability/alert/getAlertSummary", "alerting:apm.anomaly/observability/alert/update", + "alerting:apm.anomaly/alerts/alert/get", + "alerting:apm.anomaly/alerts/alert/find", + "alerting:apm.anomaly/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.anomaly/alerts/alert/getAlertSummary", + "alerting:apm.anomaly/alerts/alert/update", ], "minimal_read": Array [ "login:", @@ -6031,6 +8874,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:metrics.alert.threshold/infrastructure/rule/getRuleExecutionKPI", "alerting:metrics.alert.threshold/infrastructure/rule/getBackfill", "alerting:metrics.alert.threshold/infrastructure/rule/findBackfill", + "alerting:metrics.alert.threshold/alerts/rule/get", + "alerting:metrics.alert.threshold/alerts/rule/getRuleState", + "alerting:metrics.alert.threshold/alerts/rule/getAlertSummary", + "alerting:metrics.alert.threshold/alerts/rule/getExecutionLog", + "alerting:metrics.alert.threshold/alerts/rule/getActionErrorLog", + "alerting:metrics.alert.threshold/alerts/rule/find", + "alerting:metrics.alert.threshold/alerts/rule/getRuleExecutionKPI", + "alerting:metrics.alert.threshold/alerts/rule/getBackfill", + "alerting:metrics.alert.threshold/alerts/rule/findBackfill", "alerting:metrics.alert.inventory.threshold/infrastructure/rule/get", "alerting:metrics.alert.inventory.threshold/infrastructure/rule/getRuleState", "alerting:metrics.alert.inventory.threshold/infrastructure/rule/getAlertSummary", @@ -6040,6 +8892,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:metrics.alert.inventory.threshold/infrastructure/rule/getRuleExecutionKPI", "alerting:metrics.alert.inventory.threshold/infrastructure/rule/getBackfill", "alerting:metrics.alert.inventory.threshold/infrastructure/rule/findBackfill", + "alerting:metrics.alert.inventory.threshold/alerts/rule/get", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getRuleState", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getAlertSummary", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getExecutionLog", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getActionErrorLog", + "alerting:metrics.alert.inventory.threshold/alerts/rule/find", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getRuleExecutionKPI", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getBackfill", + "alerting:metrics.alert.inventory.threshold/alerts/rule/findBackfill", "alerting:.es-query/infrastructure/rule/get", "alerting:.es-query/infrastructure/rule/getRuleState", "alerting:.es-query/infrastructure/rule/getAlertSummary", @@ -6049,6 +8910,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:.es-query/infrastructure/rule/getRuleExecutionKPI", "alerting:.es-query/infrastructure/rule/getBackfill", "alerting:.es-query/infrastructure/rule/findBackfill", + "alerting:.es-query/alerts/rule/get", + "alerting:.es-query/alerts/rule/getRuleState", + "alerting:.es-query/alerts/rule/getAlertSummary", + "alerting:.es-query/alerts/rule/getExecutionLog", + "alerting:.es-query/alerts/rule/getActionErrorLog", + "alerting:.es-query/alerts/rule/find", + "alerting:.es-query/alerts/rule/getRuleExecutionKPI", + "alerting:.es-query/alerts/rule/getBackfill", + "alerting:.es-query/alerts/rule/findBackfill", "alerting:observability.rules.custom_threshold/infrastructure/rule/get", "alerting:observability.rules.custom_threshold/infrastructure/rule/getRuleState", "alerting:observability.rules.custom_threshold/infrastructure/rule/getAlertSummary", @@ -6058,6 +8928,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:observability.rules.custom_threshold/infrastructure/rule/getRuleExecutionKPI", "alerting:observability.rules.custom_threshold/infrastructure/rule/getBackfill", "alerting:observability.rules.custom_threshold/infrastructure/rule/findBackfill", + "alerting:observability.rules.custom_threshold/alerts/rule/get", + "alerting:observability.rules.custom_threshold/alerts/rule/getRuleState", + "alerting:observability.rules.custom_threshold/alerts/rule/getAlertSummary", + "alerting:observability.rules.custom_threshold/alerts/rule/getExecutionLog", + "alerting:observability.rules.custom_threshold/alerts/rule/getActionErrorLog", + "alerting:observability.rules.custom_threshold/alerts/rule/find", + "alerting:observability.rules.custom_threshold/alerts/rule/getRuleExecutionKPI", + "alerting:observability.rules.custom_threshold/alerts/rule/getBackfill", + "alerting:observability.rules.custom_threshold/alerts/rule/findBackfill", "alerting:xpack.ml.anomaly_detection_alert/infrastructure/rule/get", "alerting:xpack.ml.anomaly_detection_alert/infrastructure/rule/getRuleState", "alerting:xpack.ml.anomaly_detection_alert/infrastructure/rule/getAlertSummary", @@ -6067,26 +8946,55 @@ export default function ({ getService }: FtrProviderContext) { "alerting:xpack.ml.anomaly_detection_alert/infrastructure/rule/getRuleExecutionKPI", "alerting:xpack.ml.anomaly_detection_alert/infrastructure/rule/getBackfill", "alerting:xpack.ml.anomaly_detection_alert/infrastructure/rule/findBackfill", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/get", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getRuleState", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getAlertSummary", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getExecutionLog", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getActionErrorLog", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/find", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getRuleExecutionKPI", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getBackfill", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/findBackfill", "alerting:metrics.alert.threshold/infrastructure/alert/get", "alerting:metrics.alert.threshold/infrastructure/alert/find", "alerting:metrics.alert.threshold/infrastructure/alert/getAuthorizedAlertsIndices", "alerting:metrics.alert.threshold/infrastructure/alert/getAlertSummary", + "alerting:metrics.alert.threshold/alerts/alert/get", + "alerting:metrics.alert.threshold/alerts/alert/find", + "alerting:metrics.alert.threshold/alerts/alert/getAuthorizedAlertsIndices", + "alerting:metrics.alert.threshold/alerts/alert/getAlertSummary", "alerting:metrics.alert.inventory.threshold/infrastructure/alert/get", "alerting:metrics.alert.inventory.threshold/infrastructure/alert/find", "alerting:metrics.alert.inventory.threshold/infrastructure/alert/getAuthorizedAlertsIndices", "alerting:metrics.alert.inventory.threshold/infrastructure/alert/getAlertSummary", + "alerting:metrics.alert.inventory.threshold/alerts/alert/get", + "alerting:metrics.alert.inventory.threshold/alerts/alert/find", + "alerting:metrics.alert.inventory.threshold/alerts/alert/getAuthorizedAlertsIndices", + "alerting:metrics.alert.inventory.threshold/alerts/alert/getAlertSummary", "alerting:.es-query/infrastructure/alert/get", "alerting:.es-query/infrastructure/alert/find", "alerting:.es-query/infrastructure/alert/getAuthorizedAlertsIndices", "alerting:.es-query/infrastructure/alert/getAlertSummary", + "alerting:.es-query/alerts/alert/get", + "alerting:.es-query/alerts/alert/find", + "alerting:.es-query/alerts/alert/getAuthorizedAlertsIndices", + "alerting:.es-query/alerts/alert/getAlertSummary", "alerting:observability.rules.custom_threshold/infrastructure/alert/get", "alerting:observability.rules.custom_threshold/infrastructure/alert/find", "alerting:observability.rules.custom_threshold/infrastructure/alert/getAuthorizedAlertsIndices", "alerting:observability.rules.custom_threshold/infrastructure/alert/getAlertSummary", + "alerting:observability.rules.custom_threshold/alerts/alert/get", + "alerting:observability.rules.custom_threshold/alerts/alert/find", + "alerting:observability.rules.custom_threshold/alerts/alert/getAuthorizedAlertsIndices", + "alerting:observability.rules.custom_threshold/alerts/alert/getAlertSummary", "alerting:xpack.ml.anomaly_detection_alert/infrastructure/alert/get", "alerting:xpack.ml.anomaly_detection_alert/infrastructure/alert/find", "alerting:xpack.ml.anomaly_detection_alert/infrastructure/alert/getAuthorizedAlertsIndices", "alerting:xpack.ml.anomaly_detection_alert/infrastructure/alert/getAlertSummary", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/get", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/find", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/getAuthorizedAlertsIndices", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/getAlertSummary", "app:logs", "ui:catalogue/infralogging", "ui:catalogue/logs", @@ -6106,6 +9014,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:logs.alert.document.count/logs/rule/getRuleExecutionKPI", "alerting:logs.alert.document.count/logs/rule/getBackfill", "alerting:logs.alert.document.count/logs/rule/findBackfill", + "alerting:logs.alert.document.count/alerts/rule/get", + "alerting:logs.alert.document.count/alerts/rule/getRuleState", + "alerting:logs.alert.document.count/alerts/rule/getAlertSummary", + "alerting:logs.alert.document.count/alerts/rule/getExecutionLog", + "alerting:logs.alert.document.count/alerts/rule/getActionErrorLog", + "alerting:logs.alert.document.count/alerts/rule/find", + "alerting:logs.alert.document.count/alerts/rule/getRuleExecutionKPI", + "alerting:logs.alert.document.count/alerts/rule/getBackfill", + "alerting:logs.alert.document.count/alerts/rule/findBackfill", "alerting:.es-query/logs/rule/get", "alerting:.es-query/logs/rule/getRuleState", "alerting:.es-query/logs/rule/getAlertSummary", @@ -6137,6 +9054,10 @@ export default function ({ getService }: FtrProviderContext) { "alerting:logs.alert.document.count/logs/alert/find", "alerting:logs.alert.document.count/logs/alert/getAuthorizedAlertsIndices", "alerting:logs.alert.document.count/logs/alert/getAlertSummary", + "alerting:logs.alert.document.count/alerts/alert/get", + "alerting:logs.alert.document.count/alerts/alert/find", + "alerting:logs.alert.document.count/alerts/alert/getAuthorizedAlertsIndices", + "alerting:logs.alert.document.count/alerts/alert/getAlertSummary", "alerting:.es-query/logs/alert/get", "alerting:.es-query/logs/alert/find", "alerting:.es-query/logs/alert/getAuthorizedAlertsIndices", @@ -6162,6 +9083,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:slo.rules.burnRate/observability/rule/getRuleExecutionKPI", "alerting:slo.rules.burnRate/observability/rule/getBackfill", "alerting:slo.rules.burnRate/observability/rule/findBackfill", + "alerting:slo.rules.burnRate/alerts/rule/get", + "alerting:slo.rules.burnRate/alerts/rule/getRuleState", + "alerting:slo.rules.burnRate/alerts/rule/getAlertSummary", + "alerting:slo.rules.burnRate/alerts/rule/getExecutionLog", + "alerting:slo.rules.burnRate/alerts/rule/getActionErrorLog", + "alerting:slo.rules.burnRate/alerts/rule/find", + "alerting:slo.rules.burnRate/alerts/rule/getRuleExecutionKPI", + "alerting:slo.rules.burnRate/alerts/rule/getBackfill", + "alerting:slo.rules.burnRate/alerts/rule/findBackfill", "alerting:observability.rules.custom_threshold/observability/rule/get", "alerting:observability.rules.custom_threshold/observability/rule/getRuleState", "alerting:observability.rules.custom_threshold/observability/rule/getAlertSummary", @@ -6207,6 +9137,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.error_rate/observability/rule/getRuleExecutionKPI", "alerting:apm.error_rate/observability/rule/getBackfill", "alerting:apm.error_rate/observability/rule/findBackfill", + "alerting:apm.error_rate/alerts/rule/get", + "alerting:apm.error_rate/alerts/rule/getRuleState", + "alerting:apm.error_rate/alerts/rule/getAlertSummary", + "alerting:apm.error_rate/alerts/rule/getExecutionLog", + "alerting:apm.error_rate/alerts/rule/getActionErrorLog", + "alerting:apm.error_rate/alerts/rule/find", + "alerting:apm.error_rate/alerts/rule/getRuleExecutionKPI", + "alerting:apm.error_rate/alerts/rule/getBackfill", + "alerting:apm.error_rate/alerts/rule/findBackfill", "alerting:apm.transaction_error_rate/observability/rule/get", "alerting:apm.transaction_error_rate/observability/rule/getRuleState", "alerting:apm.transaction_error_rate/observability/rule/getAlertSummary", @@ -6216,6 +9155,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.transaction_error_rate/observability/rule/getRuleExecutionKPI", "alerting:apm.transaction_error_rate/observability/rule/getBackfill", "alerting:apm.transaction_error_rate/observability/rule/findBackfill", + "alerting:apm.transaction_error_rate/alerts/rule/get", + "alerting:apm.transaction_error_rate/alerts/rule/getRuleState", + "alerting:apm.transaction_error_rate/alerts/rule/getAlertSummary", + "alerting:apm.transaction_error_rate/alerts/rule/getExecutionLog", + "alerting:apm.transaction_error_rate/alerts/rule/getActionErrorLog", + "alerting:apm.transaction_error_rate/alerts/rule/find", + "alerting:apm.transaction_error_rate/alerts/rule/getRuleExecutionKPI", + "alerting:apm.transaction_error_rate/alerts/rule/getBackfill", + "alerting:apm.transaction_error_rate/alerts/rule/findBackfill", "alerting:apm.transaction_duration/observability/rule/get", "alerting:apm.transaction_duration/observability/rule/getRuleState", "alerting:apm.transaction_duration/observability/rule/getAlertSummary", @@ -6225,6 +9173,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.transaction_duration/observability/rule/getRuleExecutionKPI", "alerting:apm.transaction_duration/observability/rule/getBackfill", "alerting:apm.transaction_duration/observability/rule/findBackfill", + "alerting:apm.transaction_duration/alerts/rule/get", + "alerting:apm.transaction_duration/alerts/rule/getRuleState", + "alerting:apm.transaction_duration/alerts/rule/getAlertSummary", + "alerting:apm.transaction_duration/alerts/rule/getExecutionLog", + "alerting:apm.transaction_duration/alerts/rule/getActionErrorLog", + "alerting:apm.transaction_duration/alerts/rule/find", + "alerting:apm.transaction_duration/alerts/rule/getRuleExecutionKPI", + "alerting:apm.transaction_duration/alerts/rule/getBackfill", + "alerting:apm.transaction_duration/alerts/rule/findBackfill", "alerting:apm.anomaly/observability/rule/get", "alerting:apm.anomaly/observability/rule/getRuleState", "alerting:apm.anomaly/observability/rule/getAlertSummary", @@ -6234,10 +9191,23 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.anomaly/observability/rule/getRuleExecutionKPI", "alerting:apm.anomaly/observability/rule/getBackfill", "alerting:apm.anomaly/observability/rule/findBackfill", + "alerting:apm.anomaly/alerts/rule/get", + "alerting:apm.anomaly/alerts/rule/getRuleState", + "alerting:apm.anomaly/alerts/rule/getAlertSummary", + "alerting:apm.anomaly/alerts/rule/getExecutionLog", + "alerting:apm.anomaly/alerts/rule/getActionErrorLog", + "alerting:apm.anomaly/alerts/rule/find", + "alerting:apm.anomaly/alerts/rule/getRuleExecutionKPI", + "alerting:apm.anomaly/alerts/rule/getBackfill", + "alerting:apm.anomaly/alerts/rule/findBackfill", "alerting:slo.rules.burnRate/observability/alert/get", "alerting:slo.rules.burnRate/observability/alert/find", "alerting:slo.rules.burnRate/observability/alert/getAuthorizedAlertsIndices", "alerting:slo.rules.burnRate/observability/alert/getAlertSummary", + "alerting:slo.rules.burnRate/alerts/alert/get", + "alerting:slo.rules.burnRate/alerts/alert/find", + "alerting:slo.rules.burnRate/alerts/alert/getAuthorizedAlertsIndices", + "alerting:slo.rules.burnRate/alerts/alert/getAlertSummary", "alerting:observability.rules.custom_threshold/observability/alert/get", "alerting:observability.rules.custom_threshold/observability/alert/find", "alerting:observability.rules.custom_threshold/observability/alert/getAuthorizedAlertsIndices", @@ -6258,18 +9228,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.error_rate/observability/alert/find", "alerting:apm.error_rate/observability/alert/getAuthorizedAlertsIndices", "alerting:apm.error_rate/observability/alert/getAlertSummary", + "alerting:apm.error_rate/alerts/alert/get", + "alerting:apm.error_rate/alerts/alert/find", + "alerting:apm.error_rate/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.error_rate/alerts/alert/getAlertSummary", "alerting:apm.transaction_error_rate/observability/alert/get", "alerting:apm.transaction_error_rate/observability/alert/find", "alerting:apm.transaction_error_rate/observability/alert/getAuthorizedAlertsIndices", "alerting:apm.transaction_error_rate/observability/alert/getAlertSummary", + "alerting:apm.transaction_error_rate/alerts/alert/get", + "alerting:apm.transaction_error_rate/alerts/alert/find", + "alerting:apm.transaction_error_rate/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.transaction_error_rate/alerts/alert/getAlertSummary", "alerting:apm.transaction_duration/observability/alert/get", "alerting:apm.transaction_duration/observability/alert/find", "alerting:apm.transaction_duration/observability/alert/getAuthorizedAlertsIndices", "alerting:apm.transaction_duration/observability/alert/getAlertSummary", + "alerting:apm.transaction_duration/alerts/alert/get", + "alerting:apm.transaction_duration/alerts/alert/find", + "alerting:apm.transaction_duration/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.transaction_duration/alerts/alert/getAlertSummary", "alerting:apm.anomaly/observability/alert/get", "alerting:apm.anomaly/observability/alert/find", "alerting:apm.anomaly/observability/alert/getAuthorizedAlertsIndices", "alerting:apm.anomaly/observability/alert/getAlertSummary", + "alerting:apm.anomaly/alerts/alert/get", + "alerting:apm.anomaly/alerts/alert/find", + "alerting:apm.anomaly/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.anomaly/alerts/alert/getAlertSummary", ], "read": Array [ "login:", @@ -6329,6 +9315,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:metrics.alert.threshold/infrastructure/rule/getRuleExecutionKPI", "alerting:metrics.alert.threshold/infrastructure/rule/getBackfill", "alerting:metrics.alert.threshold/infrastructure/rule/findBackfill", + "alerting:metrics.alert.threshold/alerts/rule/get", + "alerting:metrics.alert.threshold/alerts/rule/getRuleState", + "alerting:metrics.alert.threshold/alerts/rule/getAlertSummary", + "alerting:metrics.alert.threshold/alerts/rule/getExecutionLog", + "alerting:metrics.alert.threshold/alerts/rule/getActionErrorLog", + "alerting:metrics.alert.threshold/alerts/rule/find", + "alerting:metrics.alert.threshold/alerts/rule/getRuleExecutionKPI", + "alerting:metrics.alert.threshold/alerts/rule/getBackfill", + "alerting:metrics.alert.threshold/alerts/rule/findBackfill", "alerting:metrics.alert.inventory.threshold/infrastructure/rule/get", "alerting:metrics.alert.inventory.threshold/infrastructure/rule/getRuleState", "alerting:metrics.alert.inventory.threshold/infrastructure/rule/getAlertSummary", @@ -6338,6 +9333,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:metrics.alert.inventory.threshold/infrastructure/rule/getRuleExecutionKPI", "alerting:metrics.alert.inventory.threshold/infrastructure/rule/getBackfill", "alerting:metrics.alert.inventory.threshold/infrastructure/rule/findBackfill", + "alerting:metrics.alert.inventory.threshold/alerts/rule/get", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getRuleState", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getAlertSummary", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getExecutionLog", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getActionErrorLog", + "alerting:metrics.alert.inventory.threshold/alerts/rule/find", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getRuleExecutionKPI", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getBackfill", + "alerting:metrics.alert.inventory.threshold/alerts/rule/findBackfill", "alerting:.es-query/infrastructure/rule/get", "alerting:.es-query/infrastructure/rule/getRuleState", "alerting:.es-query/infrastructure/rule/getAlertSummary", @@ -6347,6 +9351,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:.es-query/infrastructure/rule/getRuleExecutionKPI", "alerting:.es-query/infrastructure/rule/getBackfill", "alerting:.es-query/infrastructure/rule/findBackfill", + "alerting:.es-query/alerts/rule/get", + "alerting:.es-query/alerts/rule/getRuleState", + "alerting:.es-query/alerts/rule/getAlertSummary", + "alerting:.es-query/alerts/rule/getExecutionLog", + "alerting:.es-query/alerts/rule/getActionErrorLog", + "alerting:.es-query/alerts/rule/find", + "alerting:.es-query/alerts/rule/getRuleExecutionKPI", + "alerting:.es-query/alerts/rule/getBackfill", + "alerting:.es-query/alerts/rule/findBackfill", "alerting:observability.rules.custom_threshold/infrastructure/rule/get", "alerting:observability.rules.custom_threshold/infrastructure/rule/getRuleState", "alerting:observability.rules.custom_threshold/infrastructure/rule/getAlertSummary", @@ -6356,6 +9369,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:observability.rules.custom_threshold/infrastructure/rule/getRuleExecutionKPI", "alerting:observability.rules.custom_threshold/infrastructure/rule/getBackfill", "alerting:observability.rules.custom_threshold/infrastructure/rule/findBackfill", + "alerting:observability.rules.custom_threshold/alerts/rule/get", + "alerting:observability.rules.custom_threshold/alerts/rule/getRuleState", + "alerting:observability.rules.custom_threshold/alerts/rule/getAlertSummary", + "alerting:observability.rules.custom_threshold/alerts/rule/getExecutionLog", + "alerting:observability.rules.custom_threshold/alerts/rule/getActionErrorLog", + "alerting:observability.rules.custom_threshold/alerts/rule/find", + "alerting:observability.rules.custom_threshold/alerts/rule/getRuleExecutionKPI", + "alerting:observability.rules.custom_threshold/alerts/rule/getBackfill", + "alerting:observability.rules.custom_threshold/alerts/rule/findBackfill", "alerting:xpack.ml.anomaly_detection_alert/infrastructure/rule/get", "alerting:xpack.ml.anomaly_detection_alert/infrastructure/rule/getRuleState", "alerting:xpack.ml.anomaly_detection_alert/infrastructure/rule/getAlertSummary", @@ -6365,26 +9387,55 @@ export default function ({ getService }: FtrProviderContext) { "alerting:xpack.ml.anomaly_detection_alert/infrastructure/rule/getRuleExecutionKPI", "alerting:xpack.ml.anomaly_detection_alert/infrastructure/rule/getBackfill", "alerting:xpack.ml.anomaly_detection_alert/infrastructure/rule/findBackfill", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/get", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getRuleState", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getAlertSummary", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getExecutionLog", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getActionErrorLog", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/find", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getRuleExecutionKPI", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getBackfill", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/findBackfill", "alerting:metrics.alert.threshold/infrastructure/alert/get", "alerting:metrics.alert.threshold/infrastructure/alert/find", "alerting:metrics.alert.threshold/infrastructure/alert/getAuthorizedAlertsIndices", "alerting:metrics.alert.threshold/infrastructure/alert/getAlertSummary", + "alerting:metrics.alert.threshold/alerts/alert/get", + "alerting:metrics.alert.threshold/alerts/alert/find", + "alerting:metrics.alert.threshold/alerts/alert/getAuthorizedAlertsIndices", + "alerting:metrics.alert.threshold/alerts/alert/getAlertSummary", "alerting:metrics.alert.inventory.threshold/infrastructure/alert/get", "alerting:metrics.alert.inventory.threshold/infrastructure/alert/find", "alerting:metrics.alert.inventory.threshold/infrastructure/alert/getAuthorizedAlertsIndices", "alerting:metrics.alert.inventory.threshold/infrastructure/alert/getAlertSummary", + "alerting:metrics.alert.inventory.threshold/alerts/alert/get", + "alerting:metrics.alert.inventory.threshold/alerts/alert/find", + "alerting:metrics.alert.inventory.threshold/alerts/alert/getAuthorizedAlertsIndices", + "alerting:metrics.alert.inventory.threshold/alerts/alert/getAlertSummary", "alerting:.es-query/infrastructure/alert/get", "alerting:.es-query/infrastructure/alert/find", "alerting:.es-query/infrastructure/alert/getAuthorizedAlertsIndices", "alerting:.es-query/infrastructure/alert/getAlertSummary", + "alerting:.es-query/alerts/alert/get", + "alerting:.es-query/alerts/alert/find", + "alerting:.es-query/alerts/alert/getAuthorizedAlertsIndices", + "alerting:.es-query/alerts/alert/getAlertSummary", "alerting:observability.rules.custom_threshold/infrastructure/alert/get", "alerting:observability.rules.custom_threshold/infrastructure/alert/find", "alerting:observability.rules.custom_threshold/infrastructure/alert/getAuthorizedAlertsIndices", "alerting:observability.rules.custom_threshold/infrastructure/alert/getAlertSummary", + "alerting:observability.rules.custom_threshold/alerts/alert/get", + "alerting:observability.rules.custom_threshold/alerts/alert/find", + "alerting:observability.rules.custom_threshold/alerts/alert/getAuthorizedAlertsIndices", + "alerting:observability.rules.custom_threshold/alerts/alert/getAlertSummary", "alerting:xpack.ml.anomaly_detection_alert/infrastructure/alert/get", "alerting:xpack.ml.anomaly_detection_alert/infrastructure/alert/find", "alerting:xpack.ml.anomaly_detection_alert/infrastructure/alert/getAuthorizedAlertsIndices", "alerting:xpack.ml.anomaly_detection_alert/infrastructure/alert/getAlertSummary", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/get", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/find", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/getAuthorizedAlertsIndices", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/getAlertSummary", "app:logs", "ui:catalogue/infralogging", "ui:catalogue/logs", @@ -6404,6 +9455,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:logs.alert.document.count/logs/rule/getRuleExecutionKPI", "alerting:logs.alert.document.count/logs/rule/getBackfill", "alerting:logs.alert.document.count/logs/rule/findBackfill", + "alerting:logs.alert.document.count/alerts/rule/get", + "alerting:logs.alert.document.count/alerts/rule/getRuleState", + "alerting:logs.alert.document.count/alerts/rule/getAlertSummary", + "alerting:logs.alert.document.count/alerts/rule/getExecutionLog", + "alerting:logs.alert.document.count/alerts/rule/getActionErrorLog", + "alerting:logs.alert.document.count/alerts/rule/find", + "alerting:logs.alert.document.count/alerts/rule/getRuleExecutionKPI", + "alerting:logs.alert.document.count/alerts/rule/getBackfill", + "alerting:logs.alert.document.count/alerts/rule/findBackfill", "alerting:.es-query/logs/rule/get", "alerting:.es-query/logs/rule/getRuleState", "alerting:.es-query/logs/rule/getAlertSummary", @@ -6435,6 +9495,10 @@ export default function ({ getService }: FtrProviderContext) { "alerting:logs.alert.document.count/logs/alert/find", "alerting:logs.alert.document.count/logs/alert/getAuthorizedAlertsIndices", "alerting:logs.alert.document.count/logs/alert/getAlertSummary", + "alerting:logs.alert.document.count/alerts/alert/get", + "alerting:logs.alert.document.count/alerts/alert/find", + "alerting:logs.alert.document.count/alerts/alert/getAuthorizedAlertsIndices", + "alerting:logs.alert.document.count/alerts/alert/getAlertSummary", "alerting:.es-query/logs/alert/get", "alerting:.es-query/logs/alert/find", "alerting:.es-query/logs/alert/getAuthorizedAlertsIndices", @@ -6460,6 +9524,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:slo.rules.burnRate/observability/rule/getRuleExecutionKPI", "alerting:slo.rules.burnRate/observability/rule/getBackfill", "alerting:slo.rules.burnRate/observability/rule/findBackfill", + "alerting:slo.rules.burnRate/alerts/rule/get", + "alerting:slo.rules.burnRate/alerts/rule/getRuleState", + "alerting:slo.rules.burnRate/alerts/rule/getAlertSummary", + "alerting:slo.rules.burnRate/alerts/rule/getExecutionLog", + "alerting:slo.rules.burnRate/alerts/rule/getActionErrorLog", + "alerting:slo.rules.burnRate/alerts/rule/find", + "alerting:slo.rules.burnRate/alerts/rule/getRuleExecutionKPI", + "alerting:slo.rules.burnRate/alerts/rule/getBackfill", + "alerting:slo.rules.burnRate/alerts/rule/findBackfill", "alerting:observability.rules.custom_threshold/observability/rule/get", "alerting:observability.rules.custom_threshold/observability/rule/getRuleState", "alerting:observability.rules.custom_threshold/observability/rule/getAlertSummary", @@ -6505,6 +9578,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.error_rate/observability/rule/getRuleExecutionKPI", "alerting:apm.error_rate/observability/rule/getBackfill", "alerting:apm.error_rate/observability/rule/findBackfill", + "alerting:apm.error_rate/alerts/rule/get", + "alerting:apm.error_rate/alerts/rule/getRuleState", + "alerting:apm.error_rate/alerts/rule/getAlertSummary", + "alerting:apm.error_rate/alerts/rule/getExecutionLog", + "alerting:apm.error_rate/alerts/rule/getActionErrorLog", + "alerting:apm.error_rate/alerts/rule/find", + "alerting:apm.error_rate/alerts/rule/getRuleExecutionKPI", + "alerting:apm.error_rate/alerts/rule/getBackfill", + "alerting:apm.error_rate/alerts/rule/findBackfill", "alerting:apm.transaction_error_rate/observability/rule/get", "alerting:apm.transaction_error_rate/observability/rule/getRuleState", "alerting:apm.transaction_error_rate/observability/rule/getAlertSummary", @@ -6514,6 +9596,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.transaction_error_rate/observability/rule/getRuleExecutionKPI", "alerting:apm.transaction_error_rate/observability/rule/getBackfill", "alerting:apm.transaction_error_rate/observability/rule/findBackfill", + "alerting:apm.transaction_error_rate/alerts/rule/get", + "alerting:apm.transaction_error_rate/alerts/rule/getRuleState", + "alerting:apm.transaction_error_rate/alerts/rule/getAlertSummary", + "alerting:apm.transaction_error_rate/alerts/rule/getExecutionLog", + "alerting:apm.transaction_error_rate/alerts/rule/getActionErrorLog", + "alerting:apm.transaction_error_rate/alerts/rule/find", + "alerting:apm.transaction_error_rate/alerts/rule/getRuleExecutionKPI", + "alerting:apm.transaction_error_rate/alerts/rule/getBackfill", + "alerting:apm.transaction_error_rate/alerts/rule/findBackfill", "alerting:apm.transaction_duration/observability/rule/get", "alerting:apm.transaction_duration/observability/rule/getRuleState", "alerting:apm.transaction_duration/observability/rule/getAlertSummary", @@ -6523,6 +9614,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.transaction_duration/observability/rule/getRuleExecutionKPI", "alerting:apm.transaction_duration/observability/rule/getBackfill", "alerting:apm.transaction_duration/observability/rule/findBackfill", + "alerting:apm.transaction_duration/alerts/rule/get", + "alerting:apm.transaction_duration/alerts/rule/getRuleState", + "alerting:apm.transaction_duration/alerts/rule/getAlertSummary", + "alerting:apm.transaction_duration/alerts/rule/getExecutionLog", + "alerting:apm.transaction_duration/alerts/rule/getActionErrorLog", + "alerting:apm.transaction_duration/alerts/rule/find", + "alerting:apm.transaction_duration/alerts/rule/getRuleExecutionKPI", + "alerting:apm.transaction_duration/alerts/rule/getBackfill", + "alerting:apm.transaction_duration/alerts/rule/findBackfill", "alerting:apm.anomaly/observability/rule/get", "alerting:apm.anomaly/observability/rule/getRuleState", "alerting:apm.anomaly/observability/rule/getAlertSummary", @@ -6532,10 +9632,23 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.anomaly/observability/rule/getRuleExecutionKPI", "alerting:apm.anomaly/observability/rule/getBackfill", "alerting:apm.anomaly/observability/rule/findBackfill", + "alerting:apm.anomaly/alerts/rule/get", + "alerting:apm.anomaly/alerts/rule/getRuleState", + "alerting:apm.anomaly/alerts/rule/getAlertSummary", + "alerting:apm.anomaly/alerts/rule/getExecutionLog", + "alerting:apm.anomaly/alerts/rule/getActionErrorLog", + "alerting:apm.anomaly/alerts/rule/find", + "alerting:apm.anomaly/alerts/rule/getRuleExecutionKPI", + "alerting:apm.anomaly/alerts/rule/getBackfill", + "alerting:apm.anomaly/alerts/rule/findBackfill", "alerting:slo.rules.burnRate/observability/alert/get", "alerting:slo.rules.burnRate/observability/alert/find", "alerting:slo.rules.burnRate/observability/alert/getAuthorizedAlertsIndices", "alerting:slo.rules.burnRate/observability/alert/getAlertSummary", + "alerting:slo.rules.burnRate/alerts/alert/get", + "alerting:slo.rules.burnRate/alerts/alert/find", + "alerting:slo.rules.burnRate/alerts/alert/getAuthorizedAlertsIndices", + "alerting:slo.rules.burnRate/alerts/alert/getAlertSummary", "alerting:observability.rules.custom_threshold/observability/alert/get", "alerting:observability.rules.custom_threshold/observability/alert/find", "alerting:observability.rules.custom_threshold/observability/alert/getAuthorizedAlertsIndices", @@ -6556,18 +9669,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.error_rate/observability/alert/find", "alerting:apm.error_rate/observability/alert/getAuthorizedAlertsIndices", "alerting:apm.error_rate/observability/alert/getAlertSummary", + "alerting:apm.error_rate/alerts/alert/get", + "alerting:apm.error_rate/alerts/alert/find", + "alerting:apm.error_rate/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.error_rate/alerts/alert/getAlertSummary", "alerting:apm.transaction_error_rate/observability/alert/get", "alerting:apm.transaction_error_rate/observability/alert/find", "alerting:apm.transaction_error_rate/observability/alert/getAuthorizedAlertsIndices", "alerting:apm.transaction_error_rate/observability/alert/getAlertSummary", + "alerting:apm.transaction_error_rate/alerts/alert/get", + "alerting:apm.transaction_error_rate/alerts/alert/find", + "alerting:apm.transaction_error_rate/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.transaction_error_rate/alerts/alert/getAlertSummary", "alerting:apm.transaction_duration/observability/alert/get", "alerting:apm.transaction_duration/observability/alert/find", "alerting:apm.transaction_duration/observability/alert/getAuthorizedAlertsIndices", "alerting:apm.transaction_duration/observability/alert/getAlertSummary", + "alerting:apm.transaction_duration/alerts/alert/get", + "alerting:apm.transaction_duration/alerts/alert/find", + "alerting:apm.transaction_duration/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.transaction_duration/alerts/alert/getAlertSummary", "alerting:apm.anomaly/observability/alert/get", "alerting:apm.anomaly/observability/alert/find", "alerting:apm.anomaly/observability/alert/getAuthorizedAlertsIndices", "alerting:apm.anomaly/observability/alert/getAlertSummary", + "alerting:apm.anomaly/alerts/alert/get", + "alerting:apm.anomaly/alerts/alert/find", + "alerting:apm.anomaly/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.anomaly/alerts/alert/getAlertSummary", ], }, "reporting": Object { @@ -6781,11 +9910,44 @@ export default function ({ getService }: FtrProviderContext) { "alerting:slo.rules.burnRate/slo/rule/runSoon", "alerting:slo.rules.burnRate/slo/rule/scheduleBackfill", "alerting:slo.rules.burnRate/slo/rule/deleteBackfill", + "alerting:slo.rules.burnRate/alerts/rule/get", + "alerting:slo.rules.burnRate/alerts/rule/getRuleState", + "alerting:slo.rules.burnRate/alerts/rule/getAlertSummary", + "alerting:slo.rules.burnRate/alerts/rule/getExecutionLog", + "alerting:slo.rules.burnRate/alerts/rule/getActionErrorLog", + "alerting:slo.rules.burnRate/alerts/rule/find", + "alerting:slo.rules.burnRate/alerts/rule/getRuleExecutionKPI", + "alerting:slo.rules.burnRate/alerts/rule/getBackfill", + "alerting:slo.rules.burnRate/alerts/rule/findBackfill", + "alerting:slo.rules.burnRate/alerts/rule/create", + "alerting:slo.rules.burnRate/alerts/rule/delete", + "alerting:slo.rules.burnRate/alerts/rule/update", + "alerting:slo.rules.burnRate/alerts/rule/updateApiKey", + "alerting:slo.rules.burnRate/alerts/rule/enable", + "alerting:slo.rules.burnRate/alerts/rule/disable", + "alerting:slo.rules.burnRate/alerts/rule/muteAll", + "alerting:slo.rules.burnRate/alerts/rule/unmuteAll", + "alerting:slo.rules.burnRate/alerts/rule/muteAlert", + "alerting:slo.rules.burnRate/alerts/rule/unmuteAlert", + "alerting:slo.rules.burnRate/alerts/rule/snooze", + "alerting:slo.rules.burnRate/alerts/rule/bulkEdit", + "alerting:slo.rules.burnRate/alerts/rule/bulkDelete", + "alerting:slo.rules.burnRate/alerts/rule/bulkEnable", + "alerting:slo.rules.burnRate/alerts/rule/bulkDisable", + "alerting:slo.rules.burnRate/alerts/rule/unsnooze", + "alerting:slo.rules.burnRate/alerts/rule/runSoon", + "alerting:slo.rules.burnRate/alerts/rule/scheduleBackfill", + "alerting:slo.rules.burnRate/alerts/rule/deleteBackfill", "alerting:slo.rules.burnRate/slo/alert/get", "alerting:slo.rules.burnRate/slo/alert/find", "alerting:slo.rules.burnRate/slo/alert/getAuthorizedAlertsIndices", "alerting:slo.rules.burnRate/slo/alert/getAlertSummary", "alerting:slo.rules.burnRate/slo/alert/update", + "alerting:slo.rules.burnRate/alerts/alert/get", + "alerting:slo.rules.burnRate/alerts/alert/find", + "alerting:slo.rules.burnRate/alerts/alert/getAuthorizedAlertsIndices", + "alerting:slo.rules.burnRate/alerts/alert/getAlertSummary", + "alerting:slo.rules.burnRate/alerts/alert/update", "app:observability", "ui:navLinks/observability", "ui:observability/read", @@ -6846,6 +10008,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:observability.rules.custom_threshold/observability/rule/runSoon", "alerting:observability.rules.custom_threshold/observability/rule/scheduleBackfill", "alerting:observability.rules.custom_threshold/observability/rule/deleteBackfill", + "alerting:observability.rules.custom_threshold/alerts/rule/get", + "alerting:observability.rules.custom_threshold/alerts/rule/getRuleState", + "alerting:observability.rules.custom_threshold/alerts/rule/getAlertSummary", + "alerting:observability.rules.custom_threshold/alerts/rule/getExecutionLog", + "alerting:observability.rules.custom_threshold/alerts/rule/getActionErrorLog", + "alerting:observability.rules.custom_threshold/alerts/rule/find", + "alerting:observability.rules.custom_threshold/alerts/rule/getRuleExecutionKPI", + "alerting:observability.rules.custom_threshold/alerts/rule/getBackfill", + "alerting:observability.rules.custom_threshold/alerts/rule/findBackfill", + "alerting:observability.rules.custom_threshold/alerts/rule/create", + "alerting:observability.rules.custom_threshold/alerts/rule/delete", + "alerting:observability.rules.custom_threshold/alerts/rule/update", + "alerting:observability.rules.custom_threshold/alerts/rule/updateApiKey", + "alerting:observability.rules.custom_threshold/alerts/rule/enable", + "alerting:observability.rules.custom_threshold/alerts/rule/disable", + "alerting:observability.rules.custom_threshold/alerts/rule/muteAll", + "alerting:observability.rules.custom_threshold/alerts/rule/unmuteAll", + "alerting:observability.rules.custom_threshold/alerts/rule/muteAlert", + "alerting:observability.rules.custom_threshold/alerts/rule/unmuteAlert", + "alerting:observability.rules.custom_threshold/alerts/rule/snooze", + "alerting:observability.rules.custom_threshold/alerts/rule/bulkEdit", + "alerting:observability.rules.custom_threshold/alerts/rule/bulkDelete", + "alerting:observability.rules.custom_threshold/alerts/rule/bulkEnable", + "alerting:observability.rules.custom_threshold/alerts/rule/bulkDisable", + "alerting:observability.rules.custom_threshold/alerts/rule/unsnooze", + "alerting:observability.rules.custom_threshold/alerts/rule/runSoon", + "alerting:observability.rules.custom_threshold/alerts/rule/scheduleBackfill", + "alerting:observability.rules.custom_threshold/alerts/rule/deleteBackfill", "alerting:.es-query/observability/rule/get", "alerting:.es-query/observability/rule/getRuleState", "alerting:.es-query/observability/rule/getAlertSummary", @@ -6874,6 +10064,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:.es-query/observability/rule/runSoon", "alerting:.es-query/observability/rule/scheduleBackfill", "alerting:.es-query/observability/rule/deleteBackfill", + "alerting:.es-query/alerts/rule/get", + "alerting:.es-query/alerts/rule/getRuleState", + "alerting:.es-query/alerts/rule/getAlertSummary", + "alerting:.es-query/alerts/rule/getExecutionLog", + "alerting:.es-query/alerts/rule/getActionErrorLog", + "alerting:.es-query/alerts/rule/find", + "alerting:.es-query/alerts/rule/getRuleExecutionKPI", + "alerting:.es-query/alerts/rule/getBackfill", + "alerting:.es-query/alerts/rule/findBackfill", + "alerting:.es-query/alerts/rule/create", + "alerting:.es-query/alerts/rule/delete", + "alerting:.es-query/alerts/rule/update", + "alerting:.es-query/alerts/rule/updateApiKey", + "alerting:.es-query/alerts/rule/enable", + "alerting:.es-query/alerts/rule/disable", + "alerting:.es-query/alerts/rule/muteAll", + "alerting:.es-query/alerts/rule/unmuteAll", + "alerting:.es-query/alerts/rule/muteAlert", + "alerting:.es-query/alerts/rule/unmuteAlert", + "alerting:.es-query/alerts/rule/snooze", + "alerting:.es-query/alerts/rule/bulkEdit", + "alerting:.es-query/alerts/rule/bulkDelete", + "alerting:.es-query/alerts/rule/bulkEnable", + "alerting:.es-query/alerts/rule/bulkDisable", + "alerting:.es-query/alerts/rule/unsnooze", + "alerting:.es-query/alerts/rule/runSoon", + "alerting:.es-query/alerts/rule/scheduleBackfill", + "alerting:.es-query/alerts/rule/deleteBackfill", "alerting:xpack.ml.anomaly_detection_alert/observability/rule/get", "alerting:xpack.ml.anomaly_detection_alert/observability/rule/getRuleState", "alerting:xpack.ml.anomaly_detection_alert/observability/rule/getAlertSummary", @@ -6902,6 +10120,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:xpack.ml.anomaly_detection_alert/observability/rule/runSoon", "alerting:xpack.ml.anomaly_detection_alert/observability/rule/scheduleBackfill", "alerting:xpack.ml.anomaly_detection_alert/observability/rule/deleteBackfill", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/get", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getRuleState", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getAlertSummary", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getExecutionLog", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getActionErrorLog", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/find", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getRuleExecutionKPI", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getBackfill", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/findBackfill", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/create", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/delete", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/update", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/updateApiKey", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/enable", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/disable", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/muteAll", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/unmuteAll", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/muteAlert", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/unmuteAlert", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/snooze", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/bulkEdit", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/bulkDelete", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/bulkEnable", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/bulkDisable", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/unsnooze", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/runSoon", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/scheduleBackfill", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/deleteBackfill", "alerting:metrics.alert.inventory.threshold/observability/rule/get", "alerting:metrics.alert.inventory.threshold/observability/rule/getRuleState", "alerting:metrics.alert.inventory.threshold/observability/rule/getAlertSummary", @@ -6930,6 +10176,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:metrics.alert.inventory.threshold/observability/rule/runSoon", "alerting:metrics.alert.inventory.threshold/observability/rule/scheduleBackfill", "alerting:metrics.alert.inventory.threshold/observability/rule/deleteBackfill", + "alerting:metrics.alert.inventory.threshold/alerts/rule/get", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getRuleState", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getAlertSummary", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getExecutionLog", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getActionErrorLog", + "alerting:metrics.alert.inventory.threshold/alerts/rule/find", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getRuleExecutionKPI", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getBackfill", + "alerting:metrics.alert.inventory.threshold/alerts/rule/findBackfill", + "alerting:metrics.alert.inventory.threshold/alerts/rule/create", + "alerting:metrics.alert.inventory.threshold/alerts/rule/delete", + "alerting:metrics.alert.inventory.threshold/alerts/rule/update", + "alerting:metrics.alert.inventory.threshold/alerts/rule/updateApiKey", + "alerting:metrics.alert.inventory.threshold/alerts/rule/enable", + "alerting:metrics.alert.inventory.threshold/alerts/rule/disable", + "alerting:metrics.alert.inventory.threshold/alerts/rule/muteAll", + "alerting:metrics.alert.inventory.threshold/alerts/rule/unmuteAll", + "alerting:metrics.alert.inventory.threshold/alerts/rule/muteAlert", + "alerting:metrics.alert.inventory.threshold/alerts/rule/unmuteAlert", + "alerting:metrics.alert.inventory.threshold/alerts/rule/snooze", + "alerting:metrics.alert.inventory.threshold/alerts/rule/bulkEdit", + "alerting:metrics.alert.inventory.threshold/alerts/rule/bulkDelete", + "alerting:metrics.alert.inventory.threshold/alerts/rule/bulkEnable", + "alerting:metrics.alert.inventory.threshold/alerts/rule/bulkDisable", + "alerting:metrics.alert.inventory.threshold/alerts/rule/unsnooze", + "alerting:metrics.alert.inventory.threshold/alerts/rule/runSoon", + "alerting:metrics.alert.inventory.threshold/alerts/rule/scheduleBackfill", + "alerting:metrics.alert.inventory.threshold/alerts/rule/deleteBackfill", "alerting:apm.error_rate/observability/rule/get", "alerting:apm.error_rate/observability/rule/getRuleState", "alerting:apm.error_rate/observability/rule/getAlertSummary", @@ -6958,6 +10232,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.error_rate/observability/rule/runSoon", "alerting:apm.error_rate/observability/rule/scheduleBackfill", "alerting:apm.error_rate/observability/rule/deleteBackfill", + "alerting:apm.error_rate/alerts/rule/get", + "alerting:apm.error_rate/alerts/rule/getRuleState", + "alerting:apm.error_rate/alerts/rule/getAlertSummary", + "alerting:apm.error_rate/alerts/rule/getExecutionLog", + "alerting:apm.error_rate/alerts/rule/getActionErrorLog", + "alerting:apm.error_rate/alerts/rule/find", + "alerting:apm.error_rate/alerts/rule/getRuleExecutionKPI", + "alerting:apm.error_rate/alerts/rule/getBackfill", + "alerting:apm.error_rate/alerts/rule/findBackfill", + "alerting:apm.error_rate/alerts/rule/create", + "alerting:apm.error_rate/alerts/rule/delete", + "alerting:apm.error_rate/alerts/rule/update", + "alerting:apm.error_rate/alerts/rule/updateApiKey", + "alerting:apm.error_rate/alerts/rule/enable", + "alerting:apm.error_rate/alerts/rule/disable", + "alerting:apm.error_rate/alerts/rule/muteAll", + "alerting:apm.error_rate/alerts/rule/unmuteAll", + "alerting:apm.error_rate/alerts/rule/muteAlert", + "alerting:apm.error_rate/alerts/rule/unmuteAlert", + "alerting:apm.error_rate/alerts/rule/snooze", + "alerting:apm.error_rate/alerts/rule/bulkEdit", + "alerting:apm.error_rate/alerts/rule/bulkDelete", + "alerting:apm.error_rate/alerts/rule/bulkEnable", + "alerting:apm.error_rate/alerts/rule/bulkDisable", + "alerting:apm.error_rate/alerts/rule/unsnooze", + "alerting:apm.error_rate/alerts/rule/runSoon", + "alerting:apm.error_rate/alerts/rule/scheduleBackfill", + "alerting:apm.error_rate/alerts/rule/deleteBackfill", "alerting:apm.transaction_error_rate/observability/rule/get", "alerting:apm.transaction_error_rate/observability/rule/getRuleState", "alerting:apm.transaction_error_rate/observability/rule/getAlertSummary", @@ -6986,6 +10288,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.transaction_error_rate/observability/rule/runSoon", "alerting:apm.transaction_error_rate/observability/rule/scheduleBackfill", "alerting:apm.transaction_error_rate/observability/rule/deleteBackfill", + "alerting:apm.transaction_error_rate/alerts/rule/get", + "alerting:apm.transaction_error_rate/alerts/rule/getRuleState", + "alerting:apm.transaction_error_rate/alerts/rule/getAlertSummary", + "alerting:apm.transaction_error_rate/alerts/rule/getExecutionLog", + "alerting:apm.transaction_error_rate/alerts/rule/getActionErrorLog", + "alerting:apm.transaction_error_rate/alerts/rule/find", + "alerting:apm.transaction_error_rate/alerts/rule/getRuleExecutionKPI", + "alerting:apm.transaction_error_rate/alerts/rule/getBackfill", + "alerting:apm.transaction_error_rate/alerts/rule/findBackfill", + "alerting:apm.transaction_error_rate/alerts/rule/create", + "alerting:apm.transaction_error_rate/alerts/rule/delete", + "alerting:apm.transaction_error_rate/alerts/rule/update", + "alerting:apm.transaction_error_rate/alerts/rule/updateApiKey", + "alerting:apm.transaction_error_rate/alerts/rule/enable", + "alerting:apm.transaction_error_rate/alerts/rule/disable", + "alerting:apm.transaction_error_rate/alerts/rule/muteAll", + "alerting:apm.transaction_error_rate/alerts/rule/unmuteAll", + "alerting:apm.transaction_error_rate/alerts/rule/muteAlert", + "alerting:apm.transaction_error_rate/alerts/rule/unmuteAlert", + "alerting:apm.transaction_error_rate/alerts/rule/snooze", + "alerting:apm.transaction_error_rate/alerts/rule/bulkEdit", + "alerting:apm.transaction_error_rate/alerts/rule/bulkDelete", + "alerting:apm.transaction_error_rate/alerts/rule/bulkEnable", + "alerting:apm.transaction_error_rate/alerts/rule/bulkDisable", + "alerting:apm.transaction_error_rate/alerts/rule/unsnooze", + "alerting:apm.transaction_error_rate/alerts/rule/runSoon", + "alerting:apm.transaction_error_rate/alerts/rule/scheduleBackfill", + "alerting:apm.transaction_error_rate/alerts/rule/deleteBackfill", "alerting:apm.transaction_duration/observability/rule/get", "alerting:apm.transaction_duration/observability/rule/getRuleState", "alerting:apm.transaction_duration/observability/rule/getAlertSummary", @@ -7014,6 +10344,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.transaction_duration/observability/rule/runSoon", "alerting:apm.transaction_duration/observability/rule/scheduleBackfill", "alerting:apm.transaction_duration/observability/rule/deleteBackfill", + "alerting:apm.transaction_duration/alerts/rule/get", + "alerting:apm.transaction_duration/alerts/rule/getRuleState", + "alerting:apm.transaction_duration/alerts/rule/getAlertSummary", + "alerting:apm.transaction_duration/alerts/rule/getExecutionLog", + "alerting:apm.transaction_duration/alerts/rule/getActionErrorLog", + "alerting:apm.transaction_duration/alerts/rule/find", + "alerting:apm.transaction_duration/alerts/rule/getRuleExecutionKPI", + "alerting:apm.transaction_duration/alerts/rule/getBackfill", + "alerting:apm.transaction_duration/alerts/rule/findBackfill", + "alerting:apm.transaction_duration/alerts/rule/create", + "alerting:apm.transaction_duration/alerts/rule/delete", + "alerting:apm.transaction_duration/alerts/rule/update", + "alerting:apm.transaction_duration/alerts/rule/updateApiKey", + "alerting:apm.transaction_duration/alerts/rule/enable", + "alerting:apm.transaction_duration/alerts/rule/disable", + "alerting:apm.transaction_duration/alerts/rule/muteAll", + "alerting:apm.transaction_duration/alerts/rule/unmuteAll", + "alerting:apm.transaction_duration/alerts/rule/muteAlert", + "alerting:apm.transaction_duration/alerts/rule/unmuteAlert", + "alerting:apm.transaction_duration/alerts/rule/snooze", + "alerting:apm.transaction_duration/alerts/rule/bulkEdit", + "alerting:apm.transaction_duration/alerts/rule/bulkDelete", + "alerting:apm.transaction_duration/alerts/rule/bulkEnable", + "alerting:apm.transaction_duration/alerts/rule/bulkDisable", + "alerting:apm.transaction_duration/alerts/rule/unsnooze", + "alerting:apm.transaction_duration/alerts/rule/runSoon", + "alerting:apm.transaction_duration/alerts/rule/scheduleBackfill", + "alerting:apm.transaction_duration/alerts/rule/deleteBackfill", "alerting:apm.anomaly/observability/rule/get", "alerting:apm.anomaly/observability/rule/getRuleState", "alerting:apm.anomaly/observability/rule/getAlertSummary", @@ -7042,6 +10400,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.anomaly/observability/rule/runSoon", "alerting:apm.anomaly/observability/rule/scheduleBackfill", "alerting:apm.anomaly/observability/rule/deleteBackfill", + "alerting:apm.anomaly/alerts/rule/get", + "alerting:apm.anomaly/alerts/rule/getRuleState", + "alerting:apm.anomaly/alerts/rule/getAlertSummary", + "alerting:apm.anomaly/alerts/rule/getExecutionLog", + "alerting:apm.anomaly/alerts/rule/getActionErrorLog", + "alerting:apm.anomaly/alerts/rule/find", + "alerting:apm.anomaly/alerts/rule/getRuleExecutionKPI", + "alerting:apm.anomaly/alerts/rule/getBackfill", + "alerting:apm.anomaly/alerts/rule/findBackfill", + "alerting:apm.anomaly/alerts/rule/create", + "alerting:apm.anomaly/alerts/rule/delete", + "alerting:apm.anomaly/alerts/rule/update", + "alerting:apm.anomaly/alerts/rule/updateApiKey", + "alerting:apm.anomaly/alerts/rule/enable", + "alerting:apm.anomaly/alerts/rule/disable", + "alerting:apm.anomaly/alerts/rule/muteAll", + "alerting:apm.anomaly/alerts/rule/unmuteAll", + "alerting:apm.anomaly/alerts/rule/muteAlert", + "alerting:apm.anomaly/alerts/rule/unmuteAlert", + "alerting:apm.anomaly/alerts/rule/snooze", + "alerting:apm.anomaly/alerts/rule/bulkEdit", + "alerting:apm.anomaly/alerts/rule/bulkDelete", + "alerting:apm.anomaly/alerts/rule/bulkEnable", + "alerting:apm.anomaly/alerts/rule/bulkDisable", + "alerting:apm.anomaly/alerts/rule/unsnooze", + "alerting:apm.anomaly/alerts/rule/runSoon", + "alerting:apm.anomaly/alerts/rule/scheduleBackfill", + "alerting:apm.anomaly/alerts/rule/deleteBackfill", "alerting:slo.rules.burnRate/observability/alert/get", "alerting:slo.rules.burnRate/observability/alert/find", "alerting:slo.rules.burnRate/observability/alert/getAuthorizedAlertsIndices", @@ -7052,41 +10438,81 @@ export default function ({ getService }: FtrProviderContext) { "alerting:observability.rules.custom_threshold/observability/alert/getAuthorizedAlertsIndices", "alerting:observability.rules.custom_threshold/observability/alert/getAlertSummary", "alerting:observability.rules.custom_threshold/observability/alert/update", + "alerting:observability.rules.custom_threshold/alerts/alert/get", + "alerting:observability.rules.custom_threshold/alerts/alert/find", + "alerting:observability.rules.custom_threshold/alerts/alert/getAuthorizedAlertsIndices", + "alerting:observability.rules.custom_threshold/alerts/alert/getAlertSummary", + "alerting:observability.rules.custom_threshold/alerts/alert/update", "alerting:.es-query/observability/alert/get", "alerting:.es-query/observability/alert/find", "alerting:.es-query/observability/alert/getAuthorizedAlertsIndices", "alerting:.es-query/observability/alert/getAlertSummary", "alerting:.es-query/observability/alert/update", + "alerting:.es-query/alerts/alert/get", + "alerting:.es-query/alerts/alert/find", + "alerting:.es-query/alerts/alert/getAuthorizedAlertsIndices", + "alerting:.es-query/alerts/alert/getAlertSummary", + "alerting:.es-query/alerts/alert/update", "alerting:xpack.ml.anomaly_detection_alert/observability/alert/get", "alerting:xpack.ml.anomaly_detection_alert/observability/alert/find", "alerting:xpack.ml.anomaly_detection_alert/observability/alert/getAuthorizedAlertsIndices", "alerting:xpack.ml.anomaly_detection_alert/observability/alert/getAlertSummary", "alerting:xpack.ml.anomaly_detection_alert/observability/alert/update", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/get", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/find", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/getAuthorizedAlertsIndices", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/getAlertSummary", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/update", "alerting:metrics.alert.inventory.threshold/observability/alert/get", "alerting:metrics.alert.inventory.threshold/observability/alert/find", "alerting:metrics.alert.inventory.threshold/observability/alert/getAuthorizedAlertsIndices", "alerting:metrics.alert.inventory.threshold/observability/alert/getAlertSummary", "alerting:metrics.alert.inventory.threshold/observability/alert/update", + "alerting:metrics.alert.inventory.threshold/alerts/alert/get", + "alerting:metrics.alert.inventory.threshold/alerts/alert/find", + "alerting:metrics.alert.inventory.threshold/alerts/alert/getAuthorizedAlertsIndices", + "alerting:metrics.alert.inventory.threshold/alerts/alert/getAlertSummary", + "alerting:metrics.alert.inventory.threshold/alerts/alert/update", "alerting:apm.error_rate/observability/alert/get", "alerting:apm.error_rate/observability/alert/find", "alerting:apm.error_rate/observability/alert/getAuthorizedAlertsIndices", "alerting:apm.error_rate/observability/alert/getAlertSummary", "alerting:apm.error_rate/observability/alert/update", + "alerting:apm.error_rate/alerts/alert/get", + "alerting:apm.error_rate/alerts/alert/find", + "alerting:apm.error_rate/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.error_rate/alerts/alert/getAlertSummary", + "alerting:apm.error_rate/alerts/alert/update", "alerting:apm.transaction_error_rate/observability/alert/get", "alerting:apm.transaction_error_rate/observability/alert/find", "alerting:apm.transaction_error_rate/observability/alert/getAuthorizedAlertsIndices", "alerting:apm.transaction_error_rate/observability/alert/getAlertSummary", "alerting:apm.transaction_error_rate/observability/alert/update", + "alerting:apm.transaction_error_rate/alerts/alert/get", + "alerting:apm.transaction_error_rate/alerts/alert/find", + "alerting:apm.transaction_error_rate/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.transaction_error_rate/alerts/alert/getAlertSummary", + "alerting:apm.transaction_error_rate/alerts/alert/update", "alerting:apm.transaction_duration/observability/alert/get", "alerting:apm.transaction_duration/observability/alert/find", "alerting:apm.transaction_duration/observability/alert/getAuthorizedAlertsIndices", "alerting:apm.transaction_duration/observability/alert/getAlertSummary", "alerting:apm.transaction_duration/observability/alert/update", + "alerting:apm.transaction_duration/alerts/alert/get", + "alerting:apm.transaction_duration/alerts/alert/find", + "alerting:apm.transaction_duration/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.transaction_duration/alerts/alert/getAlertSummary", + "alerting:apm.transaction_duration/alerts/alert/update", "alerting:apm.anomaly/observability/alert/get", "alerting:apm.anomaly/observability/alert/find", "alerting:apm.anomaly/observability/alert/getAuthorizedAlertsIndices", "alerting:apm.anomaly/observability/alert/getAlertSummary", "alerting:apm.anomaly/observability/alert/update", + "alerting:apm.anomaly/alerts/alert/get", + "alerting:apm.anomaly/alerts/alert/find", + "alerting:apm.anomaly/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.anomaly/alerts/alert/getAlertSummary", + "alerting:apm.anomaly/alerts/alert/update", ], "minimal_all": Array [ "login:", @@ -7180,11 +10606,44 @@ export default function ({ getService }: FtrProviderContext) { "alerting:slo.rules.burnRate/slo/rule/runSoon", "alerting:slo.rules.burnRate/slo/rule/scheduleBackfill", "alerting:slo.rules.burnRate/slo/rule/deleteBackfill", + "alerting:slo.rules.burnRate/alerts/rule/get", + "alerting:slo.rules.burnRate/alerts/rule/getRuleState", + "alerting:slo.rules.burnRate/alerts/rule/getAlertSummary", + "alerting:slo.rules.burnRate/alerts/rule/getExecutionLog", + "alerting:slo.rules.burnRate/alerts/rule/getActionErrorLog", + "alerting:slo.rules.burnRate/alerts/rule/find", + "alerting:slo.rules.burnRate/alerts/rule/getRuleExecutionKPI", + "alerting:slo.rules.burnRate/alerts/rule/getBackfill", + "alerting:slo.rules.burnRate/alerts/rule/findBackfill", + "alerting:slo.rules.burnRate/alerts/rule/create", + "alerting:slo.rules.burnRate/alerts/rule/delete", + "alerting:slo.rules.burnRate/alerts/rule/update", + "alerting:slo.rules.burnRate/alerts/rule/updateApiKey", + "alerting:slo.rules.burnRate/alerts/rule/enable", + "alerting:slo.rules.burnRate/alerts/rule/disable", + "alerting:slo.rules.burnRate/alerts/rule/muteAll", + "alerting:slo.rules.burnRate/alerts/rule/unmuteAll", + "alerting:slo.rules.burnRate/alerts/rule/muteAlert", + "alerting:slo.rules.burnRate/alerts/rule/unmuteAlert", + "alerting:slo.rules.burnRate/alerts/rule/snooze", + "alerting:slo.rules.burnRate/alerts/rule/bulkEdit", + "alerting:slo.rules.burnRate/alerts/rule/bulkDelete", + "alerting:slo.rules.burnRate/alerts/rule/bulkEnable", + "alerting:slo.rules.burnRate/alerts/rule/bulkDisable", + "alerting:slo.rules.burnRate/alerts/rule/unsnooze", + "alerting:slo.rules.burnRate/alerts/rule/runSoon", + "alerting:slo.rules.burnRate/alerts/rule/scheduleBackfill", + "alerting:slo.rules.burnRate/alerts/rule/deleteBackfill", "alerting:slo.rules.burnRate/slo/alert/get", "alerting:slo.rules.burnRate/slo/alert/find", "alerting:slo.rules.burnRate/slo/alert/getAuthorizedAlertsIndices", "alerting:slo.rules.burnRate/slo/alert/getAlertSummary", "alerting:slo.rules.burnRate/slo/alert/update", + "alerting:slo.rules.burnRate/alerts/alert/get", + "alerting:slo.rules.burnRate/alerts/alert/find", + "alerting:slo.rules.burnRate/alerts/alert/getAuthorizedAlertsIndices", + "alerting:slo.rules.burnRate/alerts/alert/getAlertSummary", + "alerting:slo.rules.burnRate/alerts/alert/update", "app:observability", "ui:navLinks/observability", "ui:observability/read", @@ -7245,6 +10704,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:observability.rules.custom_threshold/observability/rule/runSoon", "alerting:observability.rules.custom_threshold/observability/rule/scheduleBackfill", "alerting:observability.rules.custom_threshold/observability/rule/deleteBackfill", + "alerting:observability.rules.custom_threshold/alerts/rule/get", + "alerting:observability.rules.custom_threshold/alerts/rule/getRuleState", + "alerting:observability.rules.custom_threshold/alerts/rule/getAlertSummary", + "alerting:observability.rules.custom_threshold/alerts/rule/getExecutionLog", + "alerting:observability.rules.custom_threshold/alerts/rule/getActionErrorLog", + "alerting:observability.rules.custom_threshold/alerts/rule/find", + "alerting:observability.rules.custom_threshold/alerts/rule/getRuleExecutionKPI", + "alerting:observability.rules.custom_threshold/alerts/rule/getBackfill", + "alerting:observability.rules.custom_threshold/alerts/rule/findBackfill", + "alerting:observability.rules.custom_threshold/alerts/rule/create", + "alerting:observability.rules.custom_threshold/alerts/rule/delete", + "alerting:observability.rules.custom_threshold/alerts/rule/update", + "alerting:observability.rules.custom_threshold/alerts/rule/updateApiKey", + "alerting:observability.rules.custom_threshold/alerts/rule/enable", + "alerting:observability.rules.custom_threshold/alerts/rule/disable", + "alerting:observability.rules.custom_threshold/alerts/rule/muteAll", + "alerting:observability.rules.custom_threshold/alerts/rule/unmuteAll", + "alerting:observability.rules.custom_threshold/alerts/rule/muteAlert", + "alerting:observability.rules.custom_threshold/alerts/rule/unmuteAlert", + "alerting:observability.rules.custom_threshold/alerts/rule/snooze", + "alerting:observability.rules.custom_threshold/alerts/rule/bulkEdit", + "alerting:observability.rules.custom_threshold/alerts/rule/bulkDelete", + "alerting:observability.rules.custom_threshold/alerts/rule/bulkEnable", + "alerting:observability.rules.custom_threshold/alerts/rule/bulkDisable", + "alerting:observability.rules.custom_threshold/alerts/rule/unsnooze", + "alerting:observability.rules.custom_threshold/alerts/rule/runSoon", + "alerting:observability.rules.custom_threshold/alerts/rule/scheduleBackfill", + "alerting:observability.rules.custom_threshold/alerts/rule/deleteBackfill", "alerting:.es-query/observability/rule/get", "alerting:.es-query/observability/rule/getRuleState", "alerting:.es-query/observability/rule/getAlertSummary", @@ -7273,6 +10760,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:.es-query/observability/rule/runSoon", "alerting:.es-query/observability/rule/scheduleBackfill", "alerting:.es-query/observability/rule/deleteBackfill", + "alerting:.es-query/alerts/rule/get", + "alerting:.es-query/alerts/rule/getRuleState", + "alerting:.es-query/alerts/rule/getAlertSummary", + "alerting:.es-query/alerts/rule/getExecutionLog", + "alerting:.es-query/alerts/rule/getActionErrorLog", + "alerting:.es-query/alerts/rule/find", + "alerting:.es-query/alerts/rule/getRuleExecutionKPI", + "alerting:.es-query/alerts/rule/getBackfill", + "alerting:.es-query/alerts/rule/findBackfill", + "alerting:.es-query/alerts/rule/create", + "alerting:.es-query/alerts/rule/delete", + "alerting:.es-query/alerts/rule/update", + "alerting:.es-query/alerts/rule/updateApiKey", + "alerting:.es-query/alerts/rule/enable", + "alerting:.es-query/alerts/rule/disable", + "alerting:.es-query/alerts/rule/muteAll", + "alerting:.es-query/alerts/rule/unmuteAll", + "alerting:.es-query/alerts/rule/muteAlert", + "alerting:.es-query/alerts/rule/unmuteAlert", + "alerting:.es-query/alerts/rule/snooze", + "alerting:.es-query/alerts/rule/bulkEdit", + "alerting:.es-query/alerts/rule/bulkDelete", + "alerting:.es-query/alerts/rule/bulkEnable", + "alerting:.es-query/alerts/rule/bulkDisable", + "alerting:.es-query/alerts/rule/unsnooze", + "alerting:.es-query/alerts/rule/runSoon", + "alerting:.es-query/alerts/rule/scheduleBackfill", + "alerting:.es-query/alerts/rule/deleteBackfill", "alerting:xpack.ml.anomaly_detection_alert/observability/rule/get", "alerting:xpack.ml.anomaly_detection_alert/observability/rule/getRuleState", "alerting:xpack.ml.anomaly_detection_alert/observability/rule/getAlertSummary", @@ -7301,6 +10816,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:xpack.ml.anomaly_detection_alert/observability/rule/runSoon", "alerting:xpack.ml.anomaly_detection_alert/observability/rule/scheduleBackfill", "alerting:xpack.ml.anomaly_detection_alert/observability/rule/deleteBackfill", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/get", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getRuleState", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getAlertSummary", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getExecutionLog", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getActionErrorLog", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/find", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getRuleExecutionKPI", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getBackfill", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/findBackfill", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/create", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/delete", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/update", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/updateApiKey", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/enable", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/disable", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/muteAll", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/unmuteAll", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/muteAlert", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/unmuteAlert", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/snooze", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/bulkEdit", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/bulkDelete", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/bulkEnable", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/bulkDisable", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/unsnooze", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/runSoon", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/scheduleBackfill", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/deleteBackfill", "alerting:metrics.alert.inventory.threshold/observability/rule/get", "alerting:metrics.alert.inventory.threshold/observability/rule/getRuleState", "alerting:metrics.alert.inventory.threshold/observability/rule/getAlertSummary", @@ -7329,6 +10872,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:metrics.alert.inventory.threshold/observability/rule/runSoon", "alerting:metrics.alert.inventory.threshold/observability/rule/scheduleBackfill", "alerting:metrics.alert.inventory.threshold/observability/rule/deleteBackfill", + "alerting:metrics.alert.inventory.threshold/alerts/rule/get", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getRuleState", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getAlertSummary", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getExecutionLog", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getActionErrorLog", + "alerting:metrics.alert.inventory.threshold/alerts/rule/find", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getRuleExecutionKPI", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getBackfill", + "alerting:metrics.alert.inventory.threshold/alerts/rule/findBackfill", + "alerting:metrics.alert.inventory.threshold/alerts/rule/create", + "alerting:metrics.alert.inventory.threshold/alerts/rule/delete", + "alerting:metrics.alert.inventory.threshold/alerts/rule/update", + "alerting:metrics.alert.inventory.threshold/alerts/rule/updateApiKey", + "alerting:metrics.alert.inventory.threshold/alerts/rule/enable", + "alerting:metrics.alert.inventory.threshold/alerts/rule/disable", + "alerting:metrics.alert.inventory.threshold/alerts/rule/muteAll", + "alerting:metrics.alert.inventory.threshold/alerts/rule/unmuteAll", + "alerting:metrics.alert.inventory.threshold/alerts/rule/muteAlert", + "alerting:metrics.alert.inventory.threshold/alerts/rule/unmuteAlert", + "alerting:metrics.alert.inventory.threshold/alerts/rule/snooze", + "alerting:metrics.alert.inventory.threshold/alerts/rule/bulkEdit", + "alerting:metrics.alert.inventory.threshold/alerts/rule/bulkDelete", + "alerting:metrics.alert.inventory.threshold/alerts/rule/bulkEnable", + "alerting:metrics.alert.inventory.threshold/alerts/rule/bulkDisable", + "alerting:metrics.alert.inventory.threshold/alerts/rule/unsnooze", + "alerting:metrics.alert.inventory.threshold/alerts/rule/runSoon", + "alerting:metrics.alert.inventory.threshold/alerts/rule/scheduleBackfill", + "alerting:metrics.alert.inventory.threshold/alerts/rule/deleteBackfill", "alerting:apm.error_rate/observability/rule/get", "alerting:apm.error_rate/observability/rule/getRuleState", "alerting:apm.error_rate/observability/rule/getAlertSummary", @@ -7357,6 +10928,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.error_rate/observability/rule/runSoon", "alerting:apm.error_rate/observability/rule/scheduleBackfill", "alerting:apm.error_rate/observability/rule/deleteBackfill", + "alerting:apm.error_rate/alerts/rule/get", + "alerting:apm.error_rate/alerts/rule/getRuleState", + "alerting:apm.error_rate/alerts/rule/getAlertSummary", + "alerting:apm.error_rate/alerts/rule/getExecutionLog", + "alerting:apm.error_rate/alerts/rule/getActionErrorLog", + "alerting:apm.error_rate/alerts/rule/find", + "alerting:apm.error_rate/alerts/rule/getRuleExecutionKPI", + "alerting:apm.error_rate/alerts/rule/getBackfill", + "alerting:apm.error_rate/alerts/rule/findBackfill", + "alerting:apm.error_rate/alerts/rule/create", + "alerting:apm.error_rate/alerts/rule/delete", + "alerting:apm.error_rate/alerts/rule/update", + "alerting:apm.error_rate/alerts/rule/updateApiKey", + "alerting:apm.error_rate/alerts/rule/enable", + "alerting:apm.error_rate/alerts/rule/disable", + "alerting:apm.error_rate/alerts/rule/muteAll", + "alerting:apm.error_rate/alerts/rule/unmuteAll", + "alerting:apm.error_rate/alerts/rule/muteAlert", + "alerting:apm.error_rate/alerts/rule/unmuteAlert", + "alerting:apm.error_rate/alerts/rule/snooze", + "alerting:apm.error_rate/alerts/rule/bulkEdit", + "alerting:apm.error_rate/alerts/rule/bulkDelete", + "alerting:apm.error_rate/alerts/rule/bulkEnable", + "alerting:apm.error_rate/alerts/rule/bulkDisable", + "alerting:apm.error_rate/alerts/rule/unsnooze", + "alerting:apm.error_rate/alerts/rule/runSoon", + "alerting:apm.error_rate/alerts/rule/scheduleBackfill", + "alerting:apm.error_rate/alerts/rule/deleteBackfill", "alerting:apm.transaction_error_rate/observability/rule/get", "alerting:apm.transaction_error_rate/observability/rule/getRuleState", "alerting:apm.transaction_error_rate/observability/rule/getAlertSummary", @@ -7385,6 +10984,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.transaction_error_rate/observability/rule/runSoon", "alerting:apm.transaction_error_rate/observability/rule/scheduleBackfill", "alerting:apm.transaction_error_rate/observability/rule/deleteBackfill", + "alerting:apm.transaction_error_rate/alerts/rule/get", + "alerting:apm.transaction_error_rate/alerts/rule/getRuleState", + "alerting:apm.transaction_error_rate/alerts/rule/getAlertSummary", + "alerting:apm.transaction_error_rate/alerts/rule/getExecutionLog", + "alerting:apm.transaction_error_rate/alerts/rule/getActionErrorLog", + "alerting:apm.transaction_error_rate/alerts/rule/find", + "alerting:apm.transaction_error_rate/alerts/rule/getRuleExecutionKPI", + "alerting:apm.transaction_error_rate/alerts/rule/getBackfill", + "alerting:apm.transaction_error_rate/alerts/rule/findBackfill", + "alerting:apm.transaction_error_rate/alerts/rule/create", + "alerting:apm.transaction_error_rate/alerts/rule/delete", + "alerting:apm.transaction_error_rate/alerts/rule/update", + "alerting:apm.transaction_error_rate/alerts/rule/updateApiKey", + "alerting:apm.transaction_error_rate/alerts/rule/enable", + "alerting:apm.transaction_error_rate/alerts/rule/disable", + "alerting:apm.transaction_error_rate/alerts/rule/muteAll", + "alerting:apm.transaction_error_rate/alerts/rule/unmuteAll", + "alerting:apm.transaction_error_rate/alerts/rule/muteAlert", + "alerting:apm.transaction_error_rate/alerts/rule/unmuteAlert", + "alerting:apm.transaction_error_rate/alerts/rule/snooze", + "alerting:apm.transaction_error_rate/alerts/rule/bulkEdit", + "alerting:apm.transaction_error_rate/alerts/rule/bulkDelete", + "alerting:apm.transaction_error_rate/alerts/rule/bulkEnable", + "alerting:apm.transaction_error_rate/alerts/rule/bulkDisable", + "alerting:apm.transaction_error_rate/alerts/rule/unsnooze", + "alerting:apm.transaction_error_rate/alerts/rule/runSoon", + "alerting:apm.transaction_error_rate/alerts/rule/scheduleBackfill", + "alerting:apm.transaction_error_rate/alerts/rule/deleteBackfill", "alerting:apm.transaction_duration/observability/rule/get", "alerting:apm.transaction_duration/observability/rule/getRuleState", "alerting:apm.transaction_duration/observability/rule/getAlertSummary", @@ -7413,6 +11040,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.transaction_duration/observability/rule/runSoon", "alerting:apm.transaction_duration/observability/rule/scheduleBackfill", "alerting:apm.transaction_duration/observability/rule/deleteBackfill", + "alerting:apm.transaction_duration/alerts/rule/get", + "alerting:apm.transaction_duration/alerts/rule/getRuleState", + "alerting:apm.transaction_duration/alerts/rule/getAlertSummary", + "alerting:apm.transaction_duration/alerts/rule/getExecutionLog", + "alerting:apm.transaction_duration/alerts/rule/getActionErrorLog", + "alerting:apm.transaction_duration/alerts/rule/find", + "alerting:apm.transaction_duration/alerts/rule/getRuleExecutionKPI", + "alerting:apm.transaction_duration/alerts/rule/getBackfill", + "alerting:apm.transaction_duration/alerts/rule/findBackfill", + "alerting:apm.transaction_duration/alerts/rule/create", + "alerting:apm.transaction_duration/alerts/rule/delete", + "alerting:apm.transaction_duration/alerts/rule/update", + "alerting:apm.transaction_duration/alerts/rule/updateApiKey", + "alerting:apm.transaction_duration/alerts/rule/enable", + "alerting:apm.transaction_duration/alerts/rule/disable", + "alerting:apm.transaction_duration/alerts/rule/muteAll", + "alerting:apm.transaction_duration/alerts/rule/unmuteAll", + "alerting:apm.transaction_duration/alerts/rule/muteAlert", + "alerting:apm.transaction_duration/alerts/rule/unmuteAlert", + "alerting:apm.transaction_duration/alerts/rule/snooze", + "alerting:apm.transaction_duration/alerts/rule/bulkEdit", + "alerting:apm.transaction_duration/alerts/rule/bulkDelete", + "alerting:apm.transaction_duration/alerts/rule/bulkEnable", + "alerting:apm.transaction_duration/alerts/rule/bulkDisable", + "alerting:apm.transaction_duration/alerts/rule/unsnooze", + "alerting:apm.transaction_duration/alerts/rule/runSoon", + "alerting:apm.transaction_duration/alerts/rule/scheduleBackfill", + "alerting:apm.transaction_duration/alerts/rule/deleteBackfill", "alerting:apm.anomaly/observability/rule/get", "alerting:apm.anomaly/observability/rule/getRuleState", "alerting:apm.anomaly/observability/rule/getAlertSummary", @@ -7441,6 +11096,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.anomaly/observability/rule/runSoon", "alerting:apm.anomaly/observability/rule/scheduleBackfill", "alerting:apm.anomaly/observability/rule/deleteBackfill", + "alerting:apm.anomaly/alerts/rule/get", + "alerting:apm.anomaly/alerts/rule/getRuleState", + "alerting:apm.anomaly/alerts/rule/getAlertSummary", + "alerting:apm.anomaly/alerts/rule/getExecutionLog", + "alerting:apm.anomaly/alerts/rule/getActionErrorLog", + "alerting:apm.anomaly/alerts/rule/find", + "alerting:apm.anomaly/alerts/rule/getRuleExecutionKPI", + "alerting:apm.anomaly/alerts/rule/getBackfill", + "alerting:apm.anomaly/alerts/rule/findBackfill", + "alerting:apm.anomaly/alerts/rule/create", + "alerting:apm.anomaly/alerts/rule/delete", + "alerting:apm.anomaly/alerts/rule/update", + "alerting:apm.anomaly/alerts/rule/updateApiKey", + "alerting:apm.anomaly/alerts/rule/enable", + "alerting:apm.anomaly/alerts/rule/disable", + "alerting:apm.anomaly/alerts/rule/muteAll", + "alerting:apm.anomaly/alerts/rule/unmuteAll", + "alerting:apm.anomaly/alerts/rule/muteAlert", + "alerting:apm.anomaly/alerts/rule/unmuteAlert", + "alerting:apm.anomaly/alerts/rule/snooze", + "alerting:apm.anomaly/alerts/rule/bulkEdit", + "alerting:apm.anomaly/alerts/rule/bulkDelete", + "alerting:apm.anomaly/alerts/rule/bulkEnable", + "alerting:apm.anomaly/alerts/rule/bulkDisable", + "alerting:apm.anomaly/alerts/rule/unsnooze", + "alerting:apm.anomaly/alerts/rule/runSoon", + "alerting:apm.anomaly/alerts/rule/scheduleBackfill", + "alerting:apm.anomaly/alerts/rule/deleteBackfill", "alerting:slo.rules.burnRate/observability/alert/get", "alerting:slo.rules.burnRate/observability/alert/find", "alerting:slo.rules.burnRate/observability/alert/getAuthorizedAlertsIndices", @@ -7451,41 +11134,81 @@ export default function ({ getService }: FtrProviderContext) { "alerting:observability.rules.custom_threshold/observability/alert/getAuthorizedAlertsIndices", "alerting:observability.rules.custom_threshold/observability/alert/getAlertSummary", "alerting:observability.rules.custom_threshold/observability/alert/update", + "alerting:observability.rules.custom_threshold/alerts/alert/get", + "alerting:observability.rules.custom_threshold/alerts/alert/find", + "alerting:observability.rules.custom_threshold/alerts/alert/getAuthorizedAlertsIndices", + "alerting:observability.rules.custom_threshold/alerts/alert/getAlertSummary", + "alerting:observability.rules.custom_threshold/alerts/alert/update", "alerting:.es-query/observability/alert/get", "alerting:.es-query/observability/alert/find", "alerting:.es-query/observability/alert/getAuthorizedAlertsIndices", "alerting:.es-query/observability/alert/getAlertSummary", "alerting:.es-query/observability/alert/update", + "alerting:.es-query/alerts/alert/get", + "alerting:.es-query/alerts/alert/find", + "alerting:.es-query/alerts/alert/getAuthorizedAlertsIndices", + "alerting:.es-query/alerts/alert/getAlertSummary", + "alerting:.es-query/alerts/alert/update", "alerting:xpack.ml.anomaly_detection_alert/observability/alert/get", "alerting:xpack.ml.anomaly_detection_alert/observability/alert/find", "alerting:xpack.ml.anomaly_detection_alert/observability/alert/getAuthorizedAlertsIndices", "alerting:xpack.ml.anomaly_detection_alert/observability/alert/getAlertSummary", "alerting:xpack.ml.anomaly_detection_alert/observability/alert/update", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/get", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/find", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/getAuthorizedAlertsIndices", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/getAlertSummary", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/update", "alerting:metrics.alert.inventory.threshold/observability/alert/get", "alerting:metrics.alert.inventory.threshold/observability/alert/find", "alerting:metrics.alert.inventory.threshold/observability/alert/getAuthorizedAlertsIndices", "alerting:metrics.alert.inventory.threshold/observability/alert/getAlertSummary", "alerting:metrics.alert.inventory.threshold/observability/alert/update", + "alerting:metrics.alert.inventory.threshold/alerts/alert/get", + "alerting:metrics.alert.inventory.threshold/alerts/alert/find", + "alerting:metrics.alert.inventory.threshold/alerts/alert/getAuthorizedAlertsIndices", + "alerting:metrics.alert.inventory.threshold/alerts/alert/getAlertSummary", + "alerting:metrics.alert.inventory.threshold/alerts/alert/update", "alerting:apm.error_rate/observability/alert/get", "alerting:apm.error_rate/observability/alert/find", "alerting:apm.error_rate/observability/alert/getAuthorizedAlertsIndices", "alerting:apm.error_rate/observability/alert/getAlertSummary", "alerting:apm.error_rate/observability/alert/update", + "alerting:apm.error_rate/alerts/alert/get", + "alerting:apm.error_rate/alerts/alert/find", + "alerting:apm.error_rate/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.error_rate/alerts/alert/getAlertSummary", + "alerting:apm.error_rate/alerts/alert/update", "alerting:apm.transaction_error_rate/observability/alert/get", "alerting:apm.transaction_error_rate/observability/alert/find", "alerting:apm.transaction_error_rate/observability/alert/getAuthorizedAlertsIndices", "alerting:apm.transaction_error_rate/observability/alert/getAlertSummary", "alerting:apm.transaction_error_rate/observability/alert/update", + "alerting:apm.transaction_error_rate/alerts/alert/get", + "alerting:apm.transaction_error_rate/alerts/alert/find", + "alerting:apm.transaction_error_rate/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.transaction_error_rate/alerts/alert/getAlertSummary", + "alerting:apm.transaction_error_rate/alerts/alert/update", "alerting:apm.transaction_duration/observability/alert/get", "alerting:apm.transaction_duration/observability/alert/find", "alerting:apm.transaction_duration/observability/alert/getAuthorizedAlertsIndices", "alerting:apm.transaction_duration/observability/alert/getAlertSummary", "alerting:apm.transaction_duration/observability/alert/update", + "alerting:apm.transaction_duration/alerts/alert/get", + "alerting:apm.transaction_duration/alerts/alert/find", + "alerting:apm.transaction_duration/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.transaction_duration/alerts/alert/getAlertSummary", + "alerting:apm.transaction_duration/alerts/alert/update", "alerting:apm.anomaly/observability/alert/get", "alerting:apm.anomaly/observability/alert/find", "alerting:apm.anomaly/observability/alert/getAuthorizedAlertsIndices", "alerting:apm.anomaly/observability/alert/getAlertSummary", "alerting:apm.anomaly/observability/alert/update", + "alerting:apm.anomaly/alerts/alert/get", + "alerting:apm.anomaly/alerts/alert/find", + "alerting:apm.anomaly/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.anomaly/alerts/alert/getAlertSummary", + "alerting:apm.anomaly/alerts/alert/update", ], "minimal_read": Array [ "login:", @@ -7537,10 +11260,23 @@ export default function ({ getService }: FtrProviderContext) { "alerting:slo.rules.burnRate/slo/rule/getRuleExecutionKPI", "alerting:slo.rules.burnRate/slo/rule/getBackfill", "alerting:slo.rules.burnRate/slo/rule/findBackfill", + "alerting:slo.rules.burnRate/alerts/rule/get", + "alerting:slo.rules.burnRate/alerts/rule/getRuleState", + "alerting:slo.rules.burnRate/alerts/rule/getAlertSummary", + "alerting:slo.rules.burnRate/alerts/rule/getExecutionLog", + "alerting:slo.rules.burnRate/alerts/rule/getActionErrorLog", + "alerting:slo.rules.burnRate/alerts/rule/find", + "alerting:slo.rules.burnRate/alerts/rule/getRuleExecutionKPI", + "alerting:slo.rules.burnRate/alerts/rule/getBackfill", + "alerting:slo.rules.burnRate/alerts/rule/findBackfill", "alerting:slo.rules.burnRate/slo/alert/get", "alerting:slo.rules.burnRate/slo/alert/find", "alerting:slo.rules.burnRate/slo/alert/getAuthorizedAlertsIndices", "alerting:slo.rules.burnRate/slo/alert/getAlertSummary", + "alerting:slo.rules.burnRate/alerts/alert/get", + "alerting:slo.rules.burnRate/alerts/alert/find", + "alerting:slo.rules.burnRate/alerts/alert/getAuthorizedAlertsIndices", + "alerting:slo.rules.burnRate/alerts/alert/getAlertSummary", "app:observability", "ui:navLinks/observability", "ui:observability/read", @@ -7562,6 +11298,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:observability.rules.custom_threshold/observability/rule/getRuleExecutionKPI", "alerting:observability.rules.custom_threshold/observability/rule/getBackfill", "alerting:observability.rules.custom_threshold/observability/rule/findBackfill", + "alerting:observability.rules.custom_threshold/alerts/rule/get", + "alerting:observability.rules.custom_threshold/alerts/rule/getRuleState", + "alerting:observability.rules.custom_threshold/alerts/rule/getAlertSummary", + "alerting:observability.rules.custom_threshold/alerts/rule/getExecutionLog", + "alerting:observability.rules.custom_threshold/alerts/rule/getActionErrorLog", + "alerting:observability.rules.custom_threshold/alerts/rule/find", + "alerting:observability.rules.custom_threshold/alerts/rule/getRuleExecutionKPI", + "alerting:observability.rules.custom_threshold/alerts/rule/getBackfill", + "alerting:observability.rules.custom_threshold/alerts/rule/findBackfill", "alerting:.es-query/observability/rule/get", "alerting:.es-query/observability/rule/getRuleState", "alerting:.es-query/observability/rule/getAlertSummary", @@ -7571,6 +11316,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:.es-query/observability/rule/getRuleExecutionKPI", "alerting:.es-query/observability/rule/getBackfill", "alerting:.es-query/observability/rule/findBackfill", + "alerting:.es-query/alerts/rule/get", + "alerting:.es-query/alerts/rule/getRuleState", + "alerting:.es-query/alerts/rule/getAlertSummary", + "alerting:.es-query/alerts/rule/getExecutionLog", + "alerting:.es-query/alerts/rule/getActionErrorLog", + "alerting:.es-query/alerts/rule/find", + "alerting:.es-query/alerts/rule/getRuleExecutionKPI", + "alerting:.es-query/alerts/rule/getBackfill", + "alerting:.es-query/alerts/rule/findBackfill", "alerting:xpack.ml.anomaly_detection_alert/observability/rule/get", "alerting:xpack.ml.anomaly_detection_alert/observability/rule/getRuleState", "alerting:xpack.ml.anomaly_detection_alert/observability/rule/getAlertSummary", @@ -7580,6 +11334,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:xpack.ml.anomaly_detection_alert/observability/rule/getRuleExecutionKPI", "alerting:xpack.ml.anomaly_detection_alert/observability/rule/getBackfill", "alerting:xpack.ml.anomaly_detection_alert/observability/rule/findBackfill", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/get", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getRuleState", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getAlertSummary", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getExecutionLog", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getActionErrorLog", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/find", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getRuleExecutionKPI", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getBackfill", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/findBackfill", "alerting:metrics.alert.inventory.threshold/observability/rule/get", "alerting:metrics.alert.inventory.threshold/observability/rule/getRuleState", "alerting:metrics.alert.inventory.threshold/observability/rule/getAlertSummary", @@ -7589,6 +11352,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:metrics.alert.inventory.threshold/observability/rule/getRuleExecutionKPI", "alerting:metrics.alert.inventory.threshold/observability/rule/getBackfill", "alerting:metrics.alert.inventory.threshold/observability/rule/findBackfill", + "alerting:metrics.alert.inventory.threshold/alerts/rule/get", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getRuleState", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getAlertSummary", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getExecutionLog", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getActionErrorLog", + "alerting:metrics.alert.inventory.threshold/alerts/rule/find", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getRuleExecutionKPI", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getBackfill", + "alerting:metrics.alert.inventory.threshold/alerts/rule/findBackfill", "alerting:apm.error_rate/observability/rule/get", "alerting:apm.error_rate/observability/rule/getRuleState", "alerting:apm.error_rate/observability/rule/getAlertSummary", @@ -7598,6 +11370,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.error_rate/observability/rule/getRuleExecutionKPI", "alerting:apm.error_rate/observability/rule/getBackfill", "alerting:apm.error_rate/observability/rule/findBackfill", + "alerting:apm.error_rate/alerts/rule/get", + "alerting:apm.error_rate/alerts/rule/getRuleState", + "alerting:apm.error_rate/alerts/rule/getAlertSummary", + "alerting:apm.error_rate/alerts/rule/getExecutionLog", + "alerting:apm.error_rate/alerts/rule/getActionErrorLog", + "alerting:apm.error_rate/alerts/rule/find", + "alerting:apm.error_rate/alerts/rule/getRuleExecutionKPI", + "alerting:apm.error_rate/alerts/rule/getBackfill", + "alerting:apm.error_rate/alerts/rule/findBackfill", "alerting:apm.transaction_error_rate/observability/rule/get", "alerting:apm.transaction_error_rate/observability/rule/getRuleState", "alerting:apm.transaction_error_rate/observability/rule/getAlertSummary", @@ -7607,6 +11388,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.transaction_error_rate/observability/rule/getRuleExecutionKPI", "alerting:apm.transaction_error_rate/observability/rule/getBackfill", "alerting:apm.transaction_error_rate/observability/rule/findBackfill", + "alerting:apm.transaction_error_rate/alerts/rule/get", + "alerting:apm.transaction_error_rate/alerts/rule/getRuleState", + "alerting:apm.transaction_error_rate/alerts/rule/getAlertSummary", + "alerting:apm.transaction_error_rate/alerts/rule/getExecutionLog", + "alerting:apm.transaction_error_rate/alerts/rule/getActionErrorLog", + "alerting:apm.transaction_error_rate/alerts/rule/find", + "alerting:apm.transaction_error_rate/alerts/rule/getRuleExecutionKPI", + "alerting:apm.transaction_error_rate/alerts/rule/getBackfill", + "alerting:apm.transaction_error_rate/alerts/rule/findBackfill", "alerting:apm.transaction_duration/observability/rule/get", "alerting:apm.transaction_duration/observability/rule/getRuleState", "alerting:apm.transaction_duration/observability/rule/getAlertSummary", @@ -7616,6 +11406,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.transaction_duration/observability/rule/getRuleExecutionKPI", "alerting:apm.transaction_duration/observability/rule/getBackfill", "alerting:apm.transaction_duration/observability/rule/findBackfill", + "alerting:apm.transaction_duration/alerts/rule/get", + "alerting:apm.transaction_duration/alerts/rule/getRuleState", + "alerting:apm.transaction_duration/alerts/rule/getAlertSummary", + "alerting:apm.transaction_duration/alerts/rule/getExecutionLog", + "alerting:apm.transaction_duration/alerts/rule/getActionErrorLog", + "alerting:apm.transaction_duration/alerts/rule/find", + "alerting:apm.transaction_duration/alerts/rule/getRuleExecutionKPI", + "alerting:apm.transaction_duration/alerts/rule/getBackfill", + "alerting:apm.transaction_duration/alerts/rule/findBackfill", "alerting:apm.anomaly/observability/rule/get", "alerting:apm.anomaly/observability/rule/getRuleState", "alerting:apm.anomaly/observability/rule/getAlertSummary", @@ -7625,6 +11424,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.anomaly/observability/rule/getRuleExecutionKPI", "alerting:apm.anomaly/observability/rule/getBackfill", "alerting:apm.anomaly/observability/rule/findBackfill", + "alerting:apm.anomaly/alerts/rule/get", + "alerting:apm.anomaly/alerts/rule/getRuleState", + "alerting:apm.anomaly/alerts/rule/getAlertSummary", + "alerting:apm.anomaly/alerts/rule/getExecutionLog", + "alerting:apm.anomaly/alerts/rule/getActionErrorLog", + "alerting:apm.anomaly/alerts/rule/find", + "alerting:apm.anomaly/alerts/rule/getRuleExecutionKPI", + "alerting:apm.anomaly/alerts/rule/getBackfill", + "alerting:apm.anomaly/alerts/rule/findBackfill", "alerting:slo.rules.burnRate/observability/alert/get", "alerting:slo.rules.burnRate/observability/alert/find", "alerting:slo.rules.burnRate/observability/alert/getAuthorizedAlertsIndices", @@ -7633,34 +11441,66 @@ export default function ({ getService }: FtrProviderContext) { "alerting:observability.rules.custom_threshold/observability/alert/find", "alerting:observability.rules.custom_threshold/observability/alert/getAuthorizedAlertsIndices", "alerting:observability.rules.custom_threshold/observability/alert/getAlertSummary", + "alerting:observability.rules.custom_threshold/alerts/alert/get", + "alerting:observability.rules.custom_threshold/alerts/alert/find", + "alerting:observability.rules.custom_threshold/alerts/alert/getAuthorizedAlertsIndices", + "alerting:observability.rules.custom_threshold/alerts/alert/getAlertSummary", "alerting:.es-query/observability/alert/get", "alerting:.es-query/observability/alert/find", "alerting:.es-query/observability/alert/getAuthorizedAlertsIndices", "alerting:.es-query/observability/alert/getAlertSummary", + "alerting:.es-query/alerts/alert/get", + "alerting:.es-query/alerts/alert/find", + "alerting:.es-query/alerts/alert/getAuthorizedAlertsIndices", + "alerting:.es-query/alerts/alert/getAlertSummary", "alerting:xpack.ml.anomaly_detection_alert/observability/alert/get", "alerting:xpack.ml.anomaly_detection_alert/observability/alert/find", "alerting:xpack.ml.anomaly_detection_alert/observability/alert/getAuthorizedAlertsIndices", "alerting:xpack.ml.anomaly_detection_alert/observability/alert/getAlertSummary", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/get", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/find", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/getAuthorizedAlertsIndices", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/getAlertSummary", "alerting:metrics.alert.inventory.threshold/observability/alert/get", "alerting:metrics.alert.inventory.threshold/observability/alert/find", "alerting:metrics.alert.inventory.threshold/observability/alert/getAuthorizedAlertsIndices", "alerting:metrics.alert.inventory.threshold/observability/alert/getAlertSummary", + "alerting:metrics.alert.inventory.threshold/alerts/alert/get", + "alerting:metrics.alert.inventory.threshold/alerts/alert/find", + "alerting:metrics.alert.inventory.threshold/alerts/alert/getAuthorizedAlertsIndices", + "alerting:metrics.alert.inventory.threshold/alerts/alert/getAlertSummary", "alerting:apm.error_rate/observability/alert/get", "alerting:apm.error_rate/observability/alert/find", "alerting:apm.error_rate/observability/alert/getAuthorizedAlertsIndices", "alerting:apm.error_rate/observability/alert/getAlertSummary", + "alerting:apm.error_rate/alerts/alert/get", + "alerting:apm.error_rate/alerts/alert/find", + "alerting:apm.error_rate/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.error_rate/alerts/alert/getAlertSummary", "alerting:apm.transaction_error_rate/observability/alert/get", "alerting:apm.transaction_error_rate/observability/alert/find", "alerting:apm.transaction_error_rate/observability/alert/getAuthorizedAlertsIndices", "alerting:apm.transaction_error_rate/observability/alert/getAlertSummary", + "alerting:apm.transaction_error_rate/alerts/alert/get", + "alerting:apm.transaction_error_rate/alerts/alert/find", + "alerting:apm.transaction_error_rate/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.transaction_error_rate/alerts/alert/getAlertSummary", "alerting:apm.transaction_duration/observability/alert/get", "alerting:apm.transaction_duration/observability/alert/find", "alerting:apm.transaction_duration/observability/alert/getAuthorizedAlertsIndices", "alerting:apm.transaction_duration/observability/alert/getAlertSummary", + "alerting:apm.transaction_duration/alerts/alert/get", + "alerting:apm.transaction_duration/alerts/alert/find", + "alerting:apm.transaction_duration/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.transaction_duration/alerts/alert/getAlertSummary", "alerting:apm.anomaly/observability/alert/get", "alerting:apm.anomaly/observability/alert/find", "alerting:apm.anomaly/observability/alert/getAuthorizedAlertsIndices", "alerting:apm.anomaly/observability/alert/getAlertSummary", + "alerting:apm.anomaly/alerts/alert/get", + "alerting:apm.anomaly/alerts/alert/find", + "alerting:apm.anomaly/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.anomaly/alerts/alert/getAlertSummary", ], "read": Array [ "login:", @@ -7712,10 +11552,23 @@ export default function ({ getService }: FtrProviderContext) { "alerting:slo.rules.burnRate/slo/rule/getRuleExecutionKPI", "alerting:slo.rules.burnRate/slo/rule/getBackfill", "alerting:slo.rules.burnRate/slo/rule/findBackfill", + "alerting:slo.rules.burnRate/alerts/rule/get", + "alerting:slo.rules.burnRate/alerts/rule/getRuleState", + "alerting:slo.rules.burnRate/alerts/rule/getAlertSummary", + "alerting:slo.rules.burnRate/alerts/rule/getExecutionLog", + "alerting:slo.rules.burnRate/alerts/rule/getActionErrorLog", + "alerting:slo.rules.burnRate/alerts/rule/find", + "alerting:slo.rules.burnRate/alerts/rule/getRuleExecutionKPI", + "alerting:slo.rules.burnRate/alerts/rule/getBackfill", + "alerting:slo.rules.burnRate/alerts/rule/findBackfill", "alerting:slo.rules.burnRate/slo/alert/get", "alerting:slo.rules.burnRate/slo/alert/find", "alerting:slo.rules.burnRate/slo/alert/getAuthorizedAlertsIndices", "alerting:slo.rules.burnRate/slo/alert/getAlertSummary", + "alerting:slo.rules.burnRate/alerts/alert/get", + "alerting:slo.rules.burnRate/alerts/alert/find", + "alerting:slo.rules.burnRate/alerts/alert/getAuthorizedAlertsIndices", + "alerting:slo.rules.burnRate/alerts/alert/getAlertSummary", "app:observability", "ui:navLinks/observability", "ui:observability/read", @@ -7737,6 +11590,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:observability.rules.custom_threshold/observability/rule/getRuleExecutionKPI", "alerting:observability.rules.custom_threshold/observability/rule/getBackfill", "alerting:observability.rules.custom_threshold/observability/rule/findBackfill", + "alerting:observability.rules.custom_threshold/alerts/rule/get", + "alerting:observability.rules.custom_threshold/alerts/rule/getRuleState", + "alerting:observability.rules.custom_threshold/alerts/rule/getAlertSummary", + "alerting:observability.rules.custom_threshold/alerts/rule/getExecutionLog", + "alerting:observability.rules.custom_threshold/alerts/rule/getActionErrorLog", + "alerting:observability.rules.custom_threshold/alerts/rule/find", + "alerting:observability.rules.custom_threshold/alerts/rule/getRuleExecutionKPI", + "alerting:observability.rules.custom_threshold/alerts/rule/getBackfill", + "alerting:observability.rules.custom_threshold/alerts/rule/findBackfill", "alerting:.es-query/observability/rule/get", "alerting:.es-query/observability/rule/getRuleState", "alerting:.es-query/observability/rule/getAlertSummary", @@ -7746,6 +11608,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:.es-query/observability/rule/getRuleExecutionKPI", "alerting:.es-query/observability/rule/getBackfill", "alerting:.es-query/observability/rule/findBackfill", + "alerting:.es-query/alerts/rule/get", + "alerting:.es-query/alerts/rule/getRuleState", + "alerting:.es-query/alerts/rule/getAlertSummary", + "alerting:.es-query/alerts/rule/getExecutionLog", + "alerting:.es-query/alerts/rule/getActionErrorLog", + "alerting:.es-query/alerts/rule/find", + "alerting:.es-query/alerts/rule/getRuleExecutionKPI", + "alerting:.es-query/alerts/rule/getBackfill", + "alerting:.es-query/alerts/rule/findBackfill", "alerting:xpack.ml.anomaly_detection_alert/observability/rule/get", "alerting:xpack.ml.anomaly_detection_alert/observability/rule/getRuleState", "alerting:xpack.ml.anomaly_detection_alert/observability/rule/getAlertSummary", @@ -7755,6 +11626,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:xpack.ml.anomaly_detection_alert/observability/rule/getRuleExecutionKPI", "alerting:xpack.ml.anomaly_detection_alert/observability/rule/getBackfill", "alerting:xpack.ml.anomaly_detection_alert/observability/rule/findBackfill", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/get", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getRuleState", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getAlertSummary", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getExecutionLog", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getActionErrorLog", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/find", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getRuleExecutionKPI", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getBackfill", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/findBackfill", "alerting:metrics.alert.inventory.threshold/observability/rule/get", "alerting:metrics.alert.inventory.threshold/observability/rule/getRuleState", "alerting:metrics.alert.inventory.threshold/observability/rule/getAlertSummary", @@ -7764,6 +11644,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:metrics.alert.inventory.threshold/observability/rule/getRuleExecutionKPI", "alerting:metrics.alert.inventory.threshold/observability/rule/getBackfill", "alerting:metrics.alert.inventory.threshold/observability/rule/findBackfill", + "alerting:metrics.alert.inventory.threshold/alerts/rule/get", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getRuleState", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getAlertSummary", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getExecutionLog", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getActionErrorLog", + "alerting:metrics.alert.inventory.threshold/alerts/rule/find", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getRuleExecutionKPI", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getBackfill", + "alerting:metrics.alert.inventory.threshold/alerts/rule/findBackfill", "alerting:apm.error_rate/observability/rule/get", "alerting:apm.error_rate/observability/rule/getRuleState", "alerting:apm.error_rate/observability/rule/getAlertSummary", @@ -7773,6 +11662,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.error_rate/observability/rule/getRuleExecutionKPI", "alerting:apm.error_rate/observability/rule/getBackfill", "alerting:apm.error_rate/observability/rule/findBackfill", + "alerting:apm.error_rate/alerts/rule/get", + "alerting:apm.error_rate/alerts/rule/getRuleState", + "alerting:apm.error_rate/alerts/rule/getAlertSummary", + "alerting:apm.error_rate/alerts/rule/getExecutionLog", + "alerting:apm.error_rate/alerts/rule/getActionErrorLog", + "alerting:apm.error_rate/alerts/rule/find", + "alerting:apm.error_rate/alerts/rule/getRuleExecutionKPI", + "alerting:apm.error_rate/alerts/rule/getBackfill", + "alerting:apm.error_rate/alerts/rule/findBackfill", "alerting:apm.transaction_error_rate/observability/rule/get", "alerting:apm.transaction_error_rate/observability/rule/getRuleState", "alerting:apm.transaction_error_rate/observability/rule/getAlertSummary", @@ -7782,6 +11680,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.transaction_error_rate/observability/rule/getRuleExecutionKPI", "alerting:apm.transaction_error_rate/observability/rule/getBackfill", "alerting:apm.transaction_error_rate/observability/rule/findBackfill", + "alerting:apm.transaction_error_rate/alerts/rule/get", + "alerting:apm.transaction_error_rate/alerts/rule/getRuleState", + "alerting:apm.transaction_error_rate/alerts/rule/getAlertSummary", + "alerting:apm.transaction_error_rate/alerts/rule/getExecutionLog", + "alerting:apm.transaction_error_rate/alerts/rule/getActionErrorLog", + "alerting:apm.transaction_error_rate/alerts/rule/find", + "alerting:apm.transaction_error_rate/alerts/rule/getRuleExecutionKPI", + "alerting:apm.transaction_error_rate/alerts/rule/getBackfill", + "alerting:apm.transaction_error_rate/alerts/rule/findBackfill", "alerting:apm.transaction_duration/observability/rule/get", "alerting:apm.transaction_duration/observability/rule/getRuleState", "alerting:apm.transaction_duration/observability/rule/getAlertSummary", @@ -7791,6 +11698,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.transaction_duration/observability/rule/getRuleExecutionKPI", "alerting:apm.transaction_duration/observability/rule/getBackfill", "alerting:apm.transaction_duration/observability/rule/findBackfill", + "alerting:apm.transaction_duration/alerts/rule/get", + "alerting:apm.transaction_duration/alerts/rule/getRuleState", + "alerting:apm.transaction_duration/alerts/rule/getAlertSummary", + "alerting:apm.transaction_duration/alerts/rule/getExecutionLog", + "alerting:apm.transaction_duration/alerts/rule/getActionErrorLog", + "alerting:apm.transaction_duration/alerts/rule/find", + "alerting:apm.transaction_duration/alerts/rule/getRuleExecutionKPI", + "alerting:apm.transaction_duration/alerts/rule/getBackfill", + "alerting:apm.transaction_duration/alerts/rule/findBackfill", "alerting:apm.anomaly/observability/rule/get", "alerting:apm.anomaly/observability/rule/getRuleState", "alerting:apm.anomaly/observability/rule/getAlertSummary", @@ -7800,6 +11716,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.anomaly/observability/rule/getRuleExecutionKPI", "alerting:apm.anomaly/observability/rule/getBackfill", "alerting:apm.anomaly/observability/rule/findBackfill", + "alerting:apm.anomaly/alerts/rule/get", + "alerting:apm.anomaly/alerts/rule/getRuleState", + "alerting:apm.anomaly/alerts/rule/getAlertSummary", + "alerting:apm.anomaly/alerts/rule/getExecutionLog", + "alerting:apm.anomaly/alerts/rule/getActionErrorLog", + "alerting:apm.anomaly/alerts/rule/find", + "alerting:apm.anomaly/alerts/rule/getRuleExecutionKPI", + "alerting:apm.anomaly/alerts/rule/getBackfill", + "alerting:apm.anomaly/alerts/rule/findBackfill", "alerting:slo.rules.burnRate/observability/alert/get", "alerting:slo.rules.burnRate/observability/alert/find", "alerting:slo.rules.burnRate/observability/alert/getAuthorizedAlertsIndices", @@ -7808,34 +11733,66 @@ export default function ({ getService }: FtrProviderContext) { "alerting:observability.rules.custom_threshold/observability/alert/find", "alerting:observability.rules.custom_threshold/observability/alert/getAuthorizedAlertsIndices", "alerting:observability.rules.custom_threshold/observability/alert/getAlertSummary", + "alerting:observability.rules.custom_threshold/alerts/alert/get", + "alerting:observability.rules.custom_threshold/alerts/alert/find", + "alerting:observability.rules.custom_threshold/alerts/alert/getAuthorizedAlertsIndices", + "alerting:observability.rules.custom_threshold/alerts/alert/getAlertSummary", "alerting:.es-query/observability/alert/get", "alerting:.es-query/observability/alert/find", "alerting:.es-query/observability/alert/getAuthorizedAlertsIndices", "alerting:.es-query/observability/alert/getAlertSummary", + "alerting:.es-query/alerts/alert/get", + "alerting:.es-query/alerts/alert/find", + "alerting:.es-query/alerts/alert/getAuthorizedAlertsIndices", + "alerting:.es-query/alerts/alert/getAlertSummary", "alerting:xpack.ml.anomaly_detection_alert/observability/alert/get", "alerting:xpack.ml.anomaly_detection_alert/observability/alert/find", "alerting:xpack.ml.anomaly_detection_alert/observability/alert/getAuthorizedAlertsIndices", "alerting:xpack.ml.anomaly_detection_alert/observability/alert/getAlertSummary", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/get", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/find", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/getAuthorizedAlertsIndices", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/getAlertSummary", "alerting:metrics.alert.inventory.threshold/observability/alert/get", "alerting:metrics.alert.inventory.threshold/observability/alert/find", "alerting:metrics.alert.inventory.threshold/observability/alert/getAuthorizedAlertsIndices", "alerting:metrics.alert.inventory.threshold/observability/alert/getAlertSummary", + "alerting:metrics.alert.inventory.threshold/alerts/alert/get", + "alerting:metrics.alert.inventory.threshold/alerts/alert/find", + "alerting:metrics.alert.inventory.threshold/alerts/alert/getAuthorizedAlertsIndices", + "alerting:metrics.alert.inventory.threshold/alerts/alert/getAlertSummary", "alerting:apm.error_rate/observability/alert/get", "alerting:apm.error_rate/observability/alert/find", "alerting:apm.error_rate/observability/alert/getAuthorizedAlertsIndices", "alerting:apm.error_rate/observability/alert/getAlertSummary", + "alerting:apm.error_rate/alerts/alert/get", + "alerting:apm.error_rate/alerts/alert/find", + "alerting:apm.error_rate/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.error_rate/alerts/alert/getAlertSummary", "alerting:apm.transaction_error_rate/observability/alert/get", "alerting:apm.transaction_error_rate/observability/alert/find", "alerting:apm.transaction_error_rate/observability/alert/getAuthorizedAlertsIndices", "alerting:apm.transaction_error_rate/observability/alert/getAlertSummary", + "alerting:apm.transaction_error_rate/alerts/alert/get", + "alerting:apm.transaction_error_rate/alerts/alert/find", + "alerting:apm.transaction_error_rate/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.transaction_error_rate/alerts/alert/getAlertSummary", "alerting:apm.transaction_duration/observability/alert/get", "alerting:apm.transaction_duration/observability/alert/find", "alerting:apm.transaction_duration/observability/alert/getAuthorizedAlertsIndices", "alerting:apm.transaction_duration/observability/alert/getAlertSummary", + "alerting:apm.transaction_duration/alerts/alert/get", + "alerting:apm.transaction_duration/alerts/alert/find", + "alerting:apm.transaction_duration/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.transaction_duration/alerts/alert/getAlertSummary", "alerting:apm.anomaly/observability/alert/get", "alerting:apm.anomaly/observability/alert/find", "alerting:apm.anomaly/observability/alert/getAuthorizedAlertsIndices", "alerting:apm.anomaly/observability/alert/getAlertSummary", + "alerting:apm.anomaly/alerts/alert/get", + "alerting:apm.anomaly/alerts/alert/find", + "alerting:apm.anomaly/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.anomaly/alerts/alert/getAlertSummary", ], }, "uptime": Object { @@ -7985,6 +11942,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:xpack.uptime.alerts.tls/uptime/rule/runSoon", "alerting:xpack.uptime.alerts.tls/uptime/rule/scheduleBackfill", "alerting:xpack.uptime.alerts.tls/uptime/rule/deleteBackfill", + "alerting:xpack.uptime.alerts.tls/alerts/rule/get", + "alerting:xpack.uptime.alerts.tls/alerts/rule/getRuleState", + "alerting:xpack.uptime.alerts.tls/alerts/rule/getAlertSummary", + "alerting:xpack.uptime.alerts.tls/alerts/rule/getExecutionLog", + "alerting:xpack.uptime.alerts.tls/alerts/rule/getActionErrorLog", + "alerting:xpack.uptime.alerts.tls/alerts/rule/find", + "alerting:xpack.uptime.alerts.tls/alerts/rule/getRuleExecutionKPI", + "alerting:xpack.uptime.alerts.tls/alerts/rule/getBackfill", + "alerting:xpack.uptime.alerts.tls/alerts/rule/findBackfill", + "alerting:xpack.uptime.alerts.tls/alerts/rule/create", + "alerting:xpack.uptime.alerts.tls/alerts/rule/delete", + "alerting:xpack.uptime.alerts.tls/alerts/rule/update", + "alerting:xpack.uptime.alerts.tls/alerts/rule/updateApiKey", + "alerting:xpack.uptime.alerts.tls/alerts/rule/enable", + "alerting:xpack.uptime.alerts.tls/alerts/rule/disable", + "alerting:xpack.uptime.alerts.tls/alerts/rule/muteAll", + "alerting:xpack.uptime.alerts.tls/alerts/rule/unmuteAll", + "alerting:xpack.uptime.alerts.tls/alerts/rule/muteAlert", + "alerting:xpack.uptime.alerts.tls/alerts/rule/unmuteAlert", + "alerting:xpack.uptime.alerts.tls/alerts/rule/snooze", + "alerting:xpack.uptime.alerts.tls/alerts/rule/bulkEdit", + "alerting:xpack.uptime.alerts.tls/alerts/rule/bulkDelete", + "alerting:xpack.uptime.alerts.tls/alerts/rule/bulkEnable", + "alerting:xpack.uptime.alerts.tls/alerts/rule/bulkDisable", + "alerting:xpack.uptime.alerts.tls/alerts/rule/unsnooze", + "alerting:xpack.uptime.alerts.tls/alerts/rule/runSoon", + "alerting:xpack.uptime.alerts.tls/alerts/rule/scheduleBackfill", + "alerting:xpack.uptime.alerts.tls/alerts/rule/deleteBackfill", "alerting:xpack.uptime.alerts.tlsCertificate/uptime/rule/get", "alerting:xpack.uptime.alerts.tlsCertificate/uptime/rule/getRuleState", "alerting:xpack.uptime.alerts.tlsCertificate/uptime/rule/getAlertSummary", @@ -8013,6 +11998,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:xpack.uptime.alerts.tlsCertificate/uptime/rule/runSoon", "alerting:xpack.uptime.alerts.tlsCertificate/uptime/rule/scheduleBackfill", "alerting:xpack.uptime.alerts.tlsCertificate/uptime/rule/deleteBackfill", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/rule/get", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/rule/getRuleState", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/rule/getAlertSummary", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/rule/getExecutionLog", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/rule/getActionErrorLog", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/rule/find", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/rule/getRuleExecutionKPI", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/rule/getBackfill", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/rule/findBackfill", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/rule/create", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/rule/delete", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/rule/update", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/rule/updateApiKey", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/rule/enable", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/rule/disable", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/rule/muteAll", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/rule/unmuteAll", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/rule/muteAlert", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/rule/unmuteAlert", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/rule/snooze", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/rule/bulkEdit", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/rule/bulkDelete", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/rule/bulkEnable", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/rule/bulkDisable", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/rule/unsnooze", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/rule/runSoon", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/rule/scheduleBackfill", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/rule/deleteBackfill", "alerting:xpack.uptime.alerts.monitorStatus/uptime/rule/get", "alerting:xpack.uptime.alerts.monitorStatus/uptime/rule/getRuleState", "alerting:xpack.uptime.alerts.monitorStatus/uptime/rule/getAlertSummary", @@ -8041,6 +12054,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:xpack.uptime.alerts.monitorStatus/uptime/rule/runSoon", "alerting:xpack.uptime.alerts.monitorStatus/uptime/rule/scheduleBackfill", "alerting:xpack.uptime.alerts.monitorStatus/uptime/rule/deleteBackfill", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/rule/get", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/rule/getRuleState", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/rule/getAlertSummary", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/rule/getExecutionLog", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/rule/getActionErrorLog", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/rule/find", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/rule/getRuleExecutionKPI", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/rule/getBackfill", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/rule/findBackfill", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/rule/create", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/rule/delete", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/rule/update", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/rule/updateApiKey", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/rule/enable", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/rule/disable", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/rule/muteAll", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/rule/unmuteAll", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/rule/muteAlert", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/rule/unmuteAlert", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/rule/snooze", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/rule/bulkEdit", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/rule/bulkDelete", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/rule/bulkEnable", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/rule/bulkDisable", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/rule/unsnooze", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/rule/runSoon", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/rule/scheduleBackfill", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/rule/deleteBackfill", "alerting:xpack.uptime.alerts.durationAnomaly/uptime/rule/get", "alerting:xpack.uptime.alerts.durationAnomaly/uptime/rule/getRuleState", "alerting:xpack.uptime.alerts.durationAnomaly/uptime/rule/getAlertSummary", @@ -8069,6 +12110,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:xpack.uptime.alerts.durationAnomaly/uptime/rule/runSoon", "alerting:xpack.uptime.alerts.durationAnomaly/uptime/rule/scheduleBackfill", "alerting:xpack.uptime.alerts.durationAnomaly/uptime/rule/deleteBackfill", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/rule/get", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/rule/getRuleState", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/rule/getAlertSummary", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/rule/getExecutionLog", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/rule/getActionErrorLog", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/rule/find", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/rule/getRuleExecutionKPI", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/rule/getBackfill", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/rule/findBackfill", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/rule/create", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/rule/delete", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/rule/update", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/rule/updateApiKey", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/rule/enable", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/rule/disable", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/rule/muteAll", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/rule/unmuteAll", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/rule/muteAlert", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/rule/unmuteAlert", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/rule/snooze", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/rule/bulkEdit", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/rule/bulkDelete", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/rule/bulkEnable", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/rule/bulkDisable", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/rule/unsnooze", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/rule/runSoon", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/rule/scheduleBackfill", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/rule/deleteBackfill", "alerting:xpack.synthetics.alerts.monitorStatus/uptime/rule/get", "alerting:xpack.synthetics.alerts.monitorStatus/uptime/rule/getRuleState", "alerting:xpack.synthetics.alerts.monitorStatus/uptime/rule/getAlertSummary", @@ -8097,6 +12166,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:xpack.synthetics.alerts.monitorStatus/uptime/rule/runSoon", "alerting:xpack.synthetics.alerts.monitorStatus/uptime/rule/scheduleBackfill", "alerting:xpack.synthetics.alerts.monitorStatus/uptime/rule/deleteBackfill", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/rule/get", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/rule/getRuleState", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/rule/getAlertSummary", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/rule/getExecutionLog", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/rule/getActionErrorLog", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/rule/find", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/rule/getRuleExecutionKPI", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/rule/getBackfill", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/rule/findBackfill", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/rule/create", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/rule/delete", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/rule/update", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/rule/updateApiKey", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/rule/enable", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/rule/disable", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/rule/muteAll", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/rule/unmuteAll", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/rule/muteAlert", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/rule/unmuteAlert", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/rule/snooze", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/rule/bulkEdit", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/rule/bulkDelete", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/rule/bulkEnable", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/rule/bulkDisable", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/rule/unsnooze", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/rule/runSoon", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/rule/scheduleBackfill", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/rule/deleteBackfill", "alerting:xpack.synthetics.alerts.tls/uptime/rule/get", "alerting:xpack.synthetics.alerts.tls/uptime/rule/getRuleState", "alerting:xpack.synthetics.alerts.tls/uptime/rule/getAlertSummary", @@ -8125,36 +12222,94 @@ export default function ({ getService }: FtrProviderContext) { "alerting:xpack.synthetics.alerts.tls/uptime/rule/runSoon", "alerting:xpack.synthetics.alerts.tls/uptime/rule/scheduleBackfill", "alerting:xpack.synthetics.alerts.tls/uptime/rule/deleteBackfill", + "alerting:xpack.synthetics.alerts.tls/alerts/rule/get", + "alerting:xpack.synthetics.alerts.tls/alerts/rule/getRuleState", + "alerting:xpack.synthetics.alerts.tls/alerts/rule/getAlertSummary", + "alerting:xpack.synthetics.alerts.tls/alerts/rule/getExecutionLog", + "alerting:xpack.synthetics.alerts.tls/alerts/rule/getActionErrorLog", + "alerting:xpack.synthetics.alerts.tls/alerts/rule/find", + "alerting:xpack.synthetics.alerts.tls/alerts/rule/getRuleExecutionKPI", + "alerting:xpack.synthetics.alerts.tls/alerts/rule/getBackfill", + "alerting:xpack.synthetics.alerts.tls/alerts/rule/findBackfill", + "alerting:xpack.synthetics.alerts.tls/alerts/rule/create", + "alerting:xpack.synthetics.alerts.tls/alerts/rule/delete", + "alerting:xpack.synthetics.alerts.tls/alerts/rule/update", + "alerting:xpack.synthetics.alerts.tls/alerts/rule/updateApiKey", + "alerting:xpack.synthetics.alerts.tls/alerts/rule/enable", + "alerting:xpack.synthetics.alerts.tls/alerts/rule/disable", + "alerting:xpack.synthetics.alerts.tls/alerts/rule/muteAll", + "alerting:xpack.synthetics.alerts.tls/alerts/rule/unmuteAll", + "alerting:xpack.synthetics.alerts.tls/alerts/rule/muteAlert", + "alerting:xpack.synthetics.alerts.tls/alerts/rule/unmuteAlert", + "alerting:xpack.synthetics.alerts.tls/alerts/rule/snooze", + "alerting:xpack.synthetics.alerts.tls/alerts/rule/bulkEdit", + "alerting:xpack.synthetics.alerts.tls/alerts/rule/bulkDelete", + "alerting:xpack.synthetics.alerts.tls/alerts/rule/bulkEnable", + "alerting:xpack.synthetics.alerts.tls/alerts/rule/bulkDisable", + "alerting:xpack.synthetics.alerts.tls/alerts/rule/unsnooze", + "alerting:xpack.synthetics.alerts.tls/alerts/rule/runSoon", + "alerting:xpack.synthetics.alerts.tls/alerts/rule/scheduleBackfill", + "alerting:xpack.synthetics.alerts.tls/alerts/rule/deleteBackfill", "alerting:xpack.uptime.alerts.tls/uptime/alert/get", "alerting:xpack.uptime.alerts.tls/uptime/alert/find", "alerting:xpack.uptime.alerts.tls/uptime/alert/getAuthorizedAlertsIndices", "alerting:xpack.uptime.alerts.tls/uptime/alert/getAlertSummary", "alerting:xpack.uptime.alerts.tls/uptime/alert/update", + "alerting:xpack.uptime.alerts.tls/alerts/alert/get", + "alerting:xpack.uptime.alerts.tls/alerts/alert/find", + "alerting:xpack.uptime.alerts.tls/alerts/alert/getAuthorizedAlertsIndices", + "alerting:xpack.uptime.alerts.tls/alerts/alert/getAlertSummary", + "alerting:xpack.uptime.alerts.tls/alerts/alert/update", "alerting:xpack.uptime.alerts.tlsCertificate/uptime/alert/get", "alerting:xpack.uptime.alerts.tlsCertificate/uptime/alert/find", "alerting:xpack.uptime.alerts.tlsCertificate/uptime/alert/getAuthorizedAlertsIndices", "alerting:xpack.uptime.alerts.tlsCertificate/uptime/alert/getAlertSummary", "alerting:xpack.uptime.alerts.tlsCertificate/uptime/alert/update", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/alert/get", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/alert/find", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/alert/getAuthorizedAlertsIndices", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/alert/getAlertSummary", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/alert/update", "alerting:xpack.uptime.alerts.monitorStatus/uptime/alert/get", "alerting:xpack.uptime.alerts.monitorStatus/uptime/alert/find", "alerting:xpack.uptime.alerts.monitorStatus/uptime/alert/getAuthorizedAlertsIndices", "alerting:xpack.uptime.alerts.monitorStatus/uptime/alert/getAlertSummary", "alerting:xpack.uptime.alerts.monitorStatus/uptime/alert/update", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/alert/get", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/alert/find", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/alert/getAuthorizedAlertsIndices", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/alert/getAlertSummary", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/alert/update", "alerting:xpack.uptime.alerts.durationAnomaly/uptime/alert/get", "alerting:xpack.uptime.alerts.durationAnomaly/uptime/alert/find", "alerting:xpack.uptime.alerts.durationAnomaly/uptime/alert/getAuthorizedAlertsIndices", "alerting:xpack.uptime.alerts.durationAnomaly/uptime/alert/getAlertSummary", "alerting:xpack.uptime.alerts.durationAnomaly/uptime/alert/update", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/alert/get", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/alert/find", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/alert/getAuthorizedAlertsIndices", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/alert/getAlertSummary", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/alert/update", "alerting:xpack.synthetics.alerts.monitorStatus/uptime/alert/get", "alerting:xpack.synthetics.alerts.monitorStatus/uptime/alert/find", "alerting:xpack.synthetics.alerts.monitorStatus/uptime/alert/getAuthorizedAlertsIndices", "alerting:xpack.synthetics.alerts.monitorStatus/uptime/alert/getAlertSummary", "alerting:xpack.synthetics.alerts.monitorStatus/uptime/alert/update", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/alert/get", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/alert/find", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/alert/getAuthorizedAlertsIndices", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/alert/getAlertSummary", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/alert/update", "alerting:xpack.synthetics.alerts.tls/uptime/alert/get", "alerting:xpack.synthetics.alerts.tls/uptime/alert/find", "alerting:xpack.synthetics.alerts.tls/uptime/alert/getAuthorizedAlertsIndices", "alerting:xpack.synthetics.alerts.tls/uptime/alert/getAlertSummary", "alerting:xpack.synthetics.alerts.tls/uptime/alert/update", + "alerting:xpack.synthetics.alerts.tls/alerts/alert/get", + "alerting:xpack.synthetics.alerts.tls/alerts/alert/find", + "alerting:xpack.synthetics.alerts.tls/alerts/alert/getAuthorizedAlertsIndices", + "alerting:xpack.synthetics.alerts.tls/alerts/alert/getAlertSummary", + "alerting:xpack.synthetics.alerts.tls/alerts/alert/update", "app:observability", "ui:catalogue/observability", "ui:navLinks/observability", @@ -8188,6 +12343,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:slo.rules.burnRate/observability/rule/runSoon", "alerting:slo.rules.burnRate/observability/rule/scheduleBackfill", "alerting:slo.rules.burnRate/observability/rule/deleteBackfill", + "alerting:slo.rules.burnRate/alerts/rule/get", + "alerting:slo.rules.burnRate/alerts/rule/getRuleState", + "alerting:slo.rules.burnRate/alerts/rule/getAlertSummary", + "alerting:slo.rules.burnRate/alerts/rule/getExecutionLog", + "alerting:slo.rules.burnRate/alerts/rule/getActionErrorLog", + "alerting:slo.rules.burnRate/alerts/rule/find", + "alerting:slo.rules.burnRate/alerts/rule/getRuleExecutionKPI", + "alerting:slo.rules.burnRate/alerts/rule/getBackfill", + "alerting:slo.rules.burnRate/alerts/rule/findBackfill", + "alerting:slo.rules.burnRate/alerts/rule/create", + "alerting:slo.rules.burnRate/alerts/rule/delete", + "alerting:slo.rules.burnRate/alerts/rule/update", + "alerting:slo.rules.burnRate/alerts/rule/updateApiKey", + "alerting:slo.rules.burnRate/alerts/rule/enable", + "alerting:slo.rules.burnRate/alerts/rule/disable", + "alerting:slo.rules.burnRate/alerts/rule/muteAll", + "alerting:slo.rules.burnRate/alerts/rule/unmuteAll", + "alerting:slo.rules.burnRate/alerts/rule/muteAlert", + "alerting:slo.rules.burnRate/alerts/rule/unmuteAlert", + "alerting:slo.rules.burnRate/alerts/rule/snooze", + "alerting:slo.rules.burnRate/alerts/rule/bulkEdit", + "alerting:slo.rules.burnRate/alerts/rule/bulkDelete", + "alerting:slo.rules.burnRate/alerts/rule/bulkEnable", + "alerting:slo.rules.burnRate/alerts/rule/bulkDisable", + "alerting:slo.rules.burnRate/alerts/rule/unsnooze", + "alerting:slo.rules.burnRate/alerts/rule/runSoon", + "alerting:slo.rules.burnRate/alerts/rule/scheduleBackfill", + "alerting:slo.rules.burnRate/alerts/rule/deleteBackfill", "alerting:observability.rules.custom_threshold/observability/rule/get", "alerting:observability.rules.custom_threshold/observability/rule/getRuleState", "alerting:observability.rules.custom_threshold/observability/rule/getAlertSummary", @@ -8216,6 +12399,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:observability.rules.custom_threshold/observability/rule/runSoon", "alerting:observability.rules.custom_threshold/observability/rule/scheduleBackfill", "alerting:observability.rules.custom_threshold/observability/rule/deleteBackfill", + "alerting:observability.rules.custom_threshold/alerts/rule/get", + "alerting:observability.rules.custom_threshold/alerts/rule/getRuleState", + "alerting:observability.rules.custom_threshold/alerts/rule/getAlertSummary", + "alerting:observability.rules.custom_threshold/alerts/rule/getExecutionLog", + "alerting:observability.rules.custom_threshold/alerts/rule/getActionErrorLog", + "alerting:observability.rules.custom_threshold/alerts/rule/find", + "alerting:observability.rules.custom_threshold/alerts/rule/getRuleExecutionKPI", + "alerting:observability.rules.custom_threshold/alerts/rule/getBackfill", + "alerting:observability.rules.custom_threshold/alerts/rule/findBackfill", + "alerting:observability.rules.custom_threshold/alerts/rule/create", + "alerting:observability.rules.custom_threshold/alerts/rule/delete", + "alerting:observability.rules.custom_threshold/alerts/rule/update", + "alerting:observability.rules.custom_threshold/alerts/rule/updateApiKey", + "alerting:observability.rules.custom_threshold/alerts/rule/enable", + "alerting:observability.rules.custom_threshold/alerts/rule/disable", + "alerting:observability.rules.custom_threshold/alerts/rule/muteAll", + "alerting:observability.rules.custom_threshold/alerts/rule/unmuteAll", + "alerting:observability.rules.custom_threshold/alerts/rule/muteAlert", + "alerting:observability.rules.custom_threshold/alerts/rule/unmuteAlert", + "alerting:observability.rules.custom_threshold/alerts/rule/snooze", + "alerting:observability.rules.custom_threshold/alerts/rule/bulkEdit", + "alerting:observability.rules.custom_threshold/alerts/rule/bulkDelete", + "alerting:observability.rules.custom_threshold/alerts/rule/bulkEnable", + "alerting:observability.rules.custom_threshold/alerts/rule/bulkDisable", + "alerting:observability.rules.custom_threshold/alerts/rule/unsnooze", + "alerting:observability.rules.custom_threshold/alerts/rule/runSoon", + "alerting:observability.rules.custom_threshold/alerts/rule/scheduleBackfill", + "alerting:observability.rules.custom_threshold/alerts/rule/deleteBackfill", "alerting:.es-query/observability/rule/get", "alerting:.es-query/observability/rule/getRuleState", "alerting:.es-query/observability/rule/getAlertSummary", @@ -8244,6 +12455,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:.es-query/observability/rule/runSoon", "alerting:.es-query/observability/rule/scheduleBackfill", "alerting:.es-query/observability/rule/deleteBackfill", + "alerting:.es-query/alerts/rule/get", + "alerting:.es-query/alerts/rule/getRuleState", + "alerting:.es-query/alerts/rule/getAlertSummary", + "alerting:.es-query/alerts/rule/getExecutionLog", + "alerting:.es-query/alerts/rule/getActionErrorLog", + "alerting:.es-query/alerts/rule/find", + "alerting:.es-query/alerts/rule/getRuleExecutionKPI", + "alerting:.es-query/alerts/rule/getBackfill", + "alerting:.es-query/alerts/rule/findBackfill", + "alerting:.es-query/alerts/rule/create", + "alerting:.es-query/alerts/rule/delete", + "alerting:.es-query/alerts/rule/update", + "alerting:.es-query/alerts/rule/updateApiKey", + "alerting:.es-query/alerts/rule/enable", + "alerting:.es-query/alerts/rule/disable", + "alerting:.es-query/alerts/rule/muteAll", + "alerting:.es-query/alerts/rule/unmuteAll", + "alerting:.es-query/alerts/rule/muteAlert", + "alerting:.es-query/alerts/rule/unmuteAlert", + "alerting:.es-query/alerts/rule/snooze", + "alerting:.es-query/alerts/rule/bulkEdit", + "alerting:.es-query/alerts/rule/bulkDelete", + "alerting:.es-query/alerts/rule/bulkEnable", + "alerting:.es-query/alerts/rule/bulkDisable", + "alerting:.es-query/alerts/rule/unsnooze", + "alerting:.es-query/alerts/rule/runSoon", + "alerting:.es-query/alerts/rule/scheduleBackfill", + "alerting:.es-query/alerts/rule/deleteBackfill", "alerting:xpack.ml.anomaly_detection_alert/observability/rule/get", "alerting:xpack.ml.anomaly_detection_alert/observability/rule/getRuleState", "alerting:xpack.ml.anomaly_detection_alert/observability/rule/getAlertSummary", @@ -8272,6 +12511,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:xpack.ml.anomaly_detection_alert/observability/rule/runSoon", "alerting:xpack.ml.anomaly_detection_alert/observability/rule/scheduleBackfill", "alerting:xpack.ml.anomaly_detection_alert/observability/rule/deleteBackfill", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/get", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getRuleState", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getAlertSummary", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getExecutionLog", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getActionErrorLog", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/find", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getRuleExecutionKPI", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getBackfill", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/findBackfill", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/create", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/delete", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/update", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/updateApiKey", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/enable", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/disable", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/muteAll", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/unmuteAll", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/muteAlert", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/unmuteAlert", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/snooze", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/bulkEdit", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/bulkDelete", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/bulkEnable", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/bulkDisable", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/unsnooze", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/runSoon", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/scheduleBackfill", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/deleteBackfill", "alerting:metrics.alert.inventory.threshold/observability/rule/get", "alerting:metrics.alert.inventory.threshold/observability/rule/getRuleState", "alerting:metrics.alert.inventory.threshold/observability/rule/getAlertSummary", @@ -8300,6 +12567,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:metrics.alert.inventory.threshold/observability/rule/runSoon", "alerting:metrics.alert.inventory.threshold/observability/rule/scheduleBackfill", "alerting:metrics.alert.inventory.threshold/observability/rule/deleteBackfill", + "alerting:metrics.alert.inventory.threshold/alerts/rule/get", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getRuleState", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getAlertSummary", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getExecutionLog", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getActionErrorLog", + "alerting:metrics.alert.inventory.threshold/alerts/rule/find", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getRuleExecutionKPI", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getBackfill", + "alerting:metrics.alert.inventory.threshold/alerts/rule/findBackfill", + "alerting:metrics.alert.inventory.threshold/alerts/rule/create", + "alerting:metrics.alert.inventory.threshold/alerts/rule/delete", + "alerting:metrics.alert.inventory.threshold/alerts/rule/update", + "alerting:metrics.alert.inventory.threshold/alerts/rule/updateApiKey", + "alerting:metrics.alert.inventory.threshold/alerts/rule/enable", + "alerting:metrics.alert.inventory.threshold/alerts/rule/disable", + "alerting:metrics.alert.inventory.threshold/alerts/rule/muteAll", + "alerting:metrics.alert.inventory.threshold/alerts/rule/unmuteAll", + "alerting:metrics.alert.inventory.threshold/alerts/rule/muteAlert", + "alerting:metrics.alert.inventory.threshold/alerts/rule/unmuteAlert", + "alerting:metrics.alert.inventory.threshold/alerts/rule/snooze", + "alerting:metrics.alert.inventory.threshold/alerts/rule/bulkEdit", + "alerting:metrics.alert.inventory.threshold/alerts/rule/bulkDelete", + "alerting:metrics.alert.inventory.threshold/alerts/rule/bulkEnable", + "alerting:metrics.alert.inventory.threshold/alerts/rule/bulkDisable", + "alerting:metrics.alert.inventory.threshold/alerts/rule/unsnooze", + "alerting:metrics.alert.inventory.threshold/alerts/rule/runSoon", + "alerting:metrics.alert.inventory.threshold/alerts/rule/scheduleBackfill", + "alerting:metrics.alert.inventory.threshold/alerts/rule/deleteBackfill", "alerting:apm.error_rate/observability/rule/get", "alerting:apm.error_rate/observability/rule/getRuleState", "alerting:apm.error_rate/observability/rule/getAlertSummary", @@ -8328,6 +12623,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.error_rate/observability/rule/runSoon", "alerting:apm.error_rate/observability/rule/scheduleBackfill", "alerting:apm.error_rate/observability/rule/deleteBackfill", + "alerting:apm.error_rate/alerts/rule/get", + "alerting:apm.error_rate/alerts/rule/getRuleState", + "alerting:apm.error_rate/alerts/rule/getAlertSummary", + "alerting:apm.error_rate/alerts/rule/getExecutionLog", + "alerting:apm.error_rate/alerts/rule/getActionErrorLog", + "alerting:apm.error_rate/alerts/rule/find", + "alerting:apm.error_rate/alerts/rule/getRuleExecutionKPI", + "alerting:apm.error_rate/alerts/rule/getBackfill", + "alerting:apm.error_rate/alerts/rule/findBackfill", + "alerting:apm.error_rate/alerts/rule/create", + "alerting:apm.error_rate/alerts/rule/delete", + "alerting:apm.error_rate/alerts/rule/update", + "alerting:apm.error_rate/alerts/rule/updateApiKey", + "alerting:apm.error_rate/alerts/rule/enable", + "alerting:apm.error_rate/alerts/rule/disable", + "alerting:apm.error_rate/alerts/rule/muteAll", + "alerting:apm.error_rate/alerts/rule/unmuteAll", + "alerting:apm.error_rate/alerts/rule/muteAlert", + "alerting:apm.error_rate/alerts/rule/unmuteAlert", + "alerting:apm.error_rate/alerts/rule/snooze", + "alerting:apm.error_rate/alerts/rule/bulkEdit", + "alerting:apm.error_rate/alerts/rule/bulkDelete", + "alerting:apm.error_rate/alerts/rule/bulkEnable", + "alerting:apm.error_rate/alerts/rule/bulkDisable", + "alerting:apm.error_rate/alerts/rule/unsnooze", + "alerting:apm.error_rate/alerts/rule/runSoon", + "alerting:apm.error_rate/alerts/rule/scheduleBackfill", + "alerting:apm.error_rate/alerts/rule/deleteBackfill", "alerting:apm.transaction_error_rate/observability/rule/get", "alerting:apm.transaction_error_rate/observability/rule/getRuleState", "alerting:apm.transaction_error_rate/observability/rule/getAlertSummary", @@ -8356,6 +12679,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.transaction_error_rate/observability/rule/runSoon", "alerting:apm.transaction_error_rate/observability/rule/scheduleBackfill", "alerting:apm.transaction_error_rate/observability/rule/deleteBackfill", + "alerting:apm.transaction_error_rate/alerts/rule/get", + "alerting:apm.transaction_error_rate/alerts/rule/getRuleState", + "alerting:apm.transaction_error_rate/alerts/rule/getAlertSummary", + "alerting:apm.transaction_error_rate/alerts/rule/getExecutionLog", + "alerting:apm.transaction_error_rate/alerts/rule/getActionErrorLog", + "alerting:apm.transaction_error_rate/alerts/rule/find", + "alerting:apm.transaction_error_rate/alerts/rule/getRuleExecutionKPI", + "alerting:apm.transaction_error_rate/alerts/rule/getBackfill", + "alerting:apm.transaction_error_rate/alerts/rule/findBackfill", + "alerting:apm.transaction_error_rate/alerts/rule/create", + "alerting:apm.transaction_error_rate/alerts/rule/delete", + "alerting:apm.transaction_error_rate/alerts/rule/update", + "alerting:apm.transaction_error_rate/alerts/rule/updateApiKey", + "alerting:apm.transaction_error_rate/alerts/rule/enable", + "alerting:apm.transaction_error_rate/alerts/rule/disable", + "alerting:apm.transaction_error_rate/alerts/rule/muteAll", + "alerting:apm.transaction_error_rate/alerts/rule/unmuteAll", + "alerting:apm.transaction_error_rate/alerts/rule/muteAlert", + "alerting:apm.transaction_error_rate/alerts/rule/unmuteAlert", + "alerting:apm.transaction_error_rate/alerts/rule/snooze", + "alerting:apm.transaction_error_rate/alerts/rule/bulkEdit", + "alerting:apm.transaction_error_rate/alerts/rule/bulkDelete", + "alerting:apm.transaction_error_rate/alerts/rule/bulkEnable", + "alerting:apm.transaction_error_rate/alerts/rule/bulkDisable", + "alerting:apm.transaction_error_rate/alerts/rule/unsnooze", + "alerting:apm.transaction_error_rate/alerts/rule/runSoon", + "alerting:apm.transaction_error_rate/alerts/rule/scheduleBackfill", + "alerting:apm.transaction_error_rate/alerts/rule/deleteBackfill", "alerting:apm.transaction_duration/observability/rule/get", "alerting:apm.transaction_duration/observability/rule/getRuleState", "alerting:apm.transaction_duration/observability/rule/getAlertSummary", @@ -8384,6 +12735,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.transaction_duration/observability/rule/runSoon", "alerting:apm.transaction_duration/observability/rule/scheduleBackfill", "alerting:apm.transaction_duration/observability/rule/deleteBackfill", + "alerting:apm.transaction_duration/alerts/rule/get", + "alerting:apm.transaction_duration/alerts/rule/getRuleState", + "alerting:apm.transaction_duration/alerts/rule/getAlertSummary", + "alerting:apm.transaction_duration/alerts/rule/getExecutionLog", + "alerting:apm.transaction_duration/alerts/rule/getActionErrorLog", + "alerting:apm.transaction_duration/alerts/rule/find", + "alerting:apm.transaction_duration/alerts/rule/getRuleExecutionKPI", + "alerting:apm.transaction_duration/alerts/rule/getBackfill", + "alerting:apm.transaction_duration/alerts/rule/findBackfill", + "alerting:apm.transaction_duration/alerts/rule/create", + "alerting:apm.transaction_duration/alerts/rule/delete", + "alerting:apm.transaction_duration/alerts/rule/update", + "alerting:apm.transaction_duration/alerts/rule/updateApiKey", + "alerting:apm.transaction_duration/alerts/rule/enable", + "alerting:apm.transaction_duration/alerts/rule/disable", + "alerting:apm.transaction_duration/alerts/rule/muteAll", + "alerting:apm.transaction_duration/alerts/rule/unmuteAll", + "alerting:apm.transaction_duration/alerts/rule/muteAlert", + "alerting:apm.transaction_duration/alerts/rule/unmuteAlert", + "alerting:apm.transaction_duration/alerts/rule/snooze", + "alerting:apm.transaction_duration/alerts/rule/bulkEdit", + "alerting:apm.transaction_duration/alerts/rule/bulkDelete", + "alerting:apm.transaction_duration/alerts/rule/bulkEnable", + "alerting:apm.transaction_duration/alerts/rule/bulkDisable", + "alerting:apm.transaction_duration/alerts/rule/unsnooze", + "alerting:apm.transaction_duration/alerts/rule/runSoon", + "alerting:apm.transaction_duration/alerts/rule/scheduleBackfill", + "alerting:apm.transaction_duration/alerts/rule/deleteBackfill", "alerting:apm.anomaly/observability/rule/get", "alerting:apm.anomaly/observability/rule/getRuleState", "alerting:apm.anomaly/observability/rule/getAlertSummary", @@ -8412,51 +12791,124 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.anomaly/observability/rule/runSoon", "alerting:apm.anomaly/observability/rule/scheduleBackfill", "alerting:apm.anomaly/observability/rule/deleteBackfill", + "alerting:apm.anomaly/alerts/rule/get", + "alerting:apm.anomaly/alerts/rule/getRuleState", + "alerting:apm.anomaly/alerts/rule/getAlertSummary", + "alerting:apm.anomaly/alerts/rule/getExecutionLog", + "alerting:apm.anomaly/alerts/rule/getActionErrorLog", + "alerting:apm.anomaly/alerts/rule/find", + "alerting:apm.anomaly/alerts/rule/getRuleExecutionKPI", + "alerting:apm.anomaly/alerts/rule/getBackfill", + "alerting:apm.anomaly/alerts/rule/findBackfill", + "alerting:apm.anomaly/alerts/rule/create", + "alerting:apm.anomaly/alerts/rule/delete", + "alerting:apm.anomaly/alerts/rule/update", + "alerting:apm.anomaly/alerts/rule/updateApiKey", + "alerting:apm.anomaly/alerts/rule/enable", + "alerting:apm.anomaly/alerts/rule/disable", + "alerting:apm.anomaly/alerts/rule/muteAll", + "alerting:apm.anomaly/alerts/rule/unmuteAll", + "alerting:apm.anomaly/alerts/rule/muteAlert", + "alerting:apm.anomaly/alerts/rule/unmuteAlert", + "alerting:apm.anomaly/alerts/rule/snooze", + "alerting:apm.anomaly/alerts/rule/bulkEdit", + "alerting:apm.anomaly/alerts/rule/bulkDelete", + "alerting:apm.anomaly/alerts/rule/bulkEnable", + "alerting:apm.anomaly/alerts/rule/bulkDisable", + "alerting:apm.anomaly/alerts/rule/unsnooze", + "alerting:apm.anomaly/alerts/rule/runSoon", + "alerting:apm.anomaly/alerts/rule/scheduleBackfill", + "alerting:apm.anomaly/alerts/rule/deleteBackfill", "alerting:slo.rules.burnRate/observability/alert/get", "alerting:slo.rules.burnRate/observability/alert/find", "alerting:slo.rules.burnRate/observability/alert/getAuthorizedAlertsIndices", "alerting:slo.rules.burnRate/observability/alert/getAlertSummary", "alerting:slo.rules.burnRate/observability/alert/update", + "alerting:slo.rules.burnRate/alerts/alert/get", + "alerting:slo.rules.burnRate/alerts/alert/find", + "alerting:slo.rules.burnRate/alerts/alert/getAuthorizedAlertsIndices", + "alerting:slo.rules.burnRate/alerts/alert/getAlertSummary", + "alerting:slo.rules.burnRate/alerts/alert/update", "alerting:observability.rules.custom_threshold/observability/alert/get", "alerting:observability.rules.custom_threshold/observability/alert/find", "alerting:observability.rules.custom_threshold/observability/alert/getAuthorizedAlertsIndices", "alerting:observability.rules.custom_threshold/observability/alert/getAlertSummary", "alerting:observability.rules.custom_threshold/observability/alert/update", + "alerting:observability.rules.custom_threshold/alerts/alert/get", + "alerting:observability.rules.custom_threshold/alerts/alert/find", + "alerting:observability.rules.custom_threshold/alerts/alert/getAuthorizedAlertsIndices", + "alerting:observability.rules.custom_threshold/alerts/alert/getAlertSummary", + "alerting:observability.rules.custom_threshold/alerts/alert/update", "alerting:.es-query/observability/alert/get", "alerting:.es-query/observability/alert/find", "alerting:.es-query/observability/alert/getAuthorizedAlertsIndices", "alerting:.es-query/observability/alert/getAlertSummary", "alerting:.es-query/observability/alert/update", + "alerting:.es-query/alerts/alert/get", + "alerting:.es-query/alerts/alert/find", + "alerting:.es-query/alerts/alert/getAuthorizedAlertsIndices", + "alerting:.es-query/alerts/alert/getAlertSummary", + "alerting:.es-query/alerts/alert/update", "alerting:xpack.ml.anomaly_detection_alert/observability/alert/get", "alerting:xpack.ml.anomaly_detection_alert/observability/alert/find", "alerting:xpack.ml.anomaly_detection_alert/observability/alert/getAuthorizedAlertsIndices", "alerting:xpack.ml.anomaly_detection_alert/observability/alert/getAlertSummary", "alerting:xpack.ml.anomaly_detection_alert/observability/alert/update", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/get", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/find", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/getAuthorizedAlertsIndices", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/getAlertSummary", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/update", "alerting:metrics.alert.inventory.threshold/observability/alert/get", "alerting:metrics.alert.inventory.threshold/observability/alert/find", "alerting:metrics.alert.inventory.threshold/observability/alert/getAuthorizedAlertsIndices", "alerting:metrics.alert.inventory.threshold/observability/alert/getAlertSummary", "alerting:metrics.alert.inventory.threshold/observability/alert/update", + "alerting:metrics.alert.inventory.threshold/alerts/alert/get", + "alerting:metrics.alert.inventory.threshold/alerts/alert/find", + "alerting:metrics.alert.inventory.threshold/alerts/alert/getAuthorizedAlertsIndices", + "alerting:metrics.alert.inventory.threshold/alerts/alert/getAlertSummary", + "alerting:metrics.alert.inventory.threshold/alerts/alert/update", "alerting:apm.error_rate/observability/alert/get", "alerting:apm.error_rate/observability/alert/find", "alerting:apm.error_rate/observability/alert/getAuthorizedAlertsIndices", "alerting:apm.error_rate/observability/alert/getAlertSummary", "alerting:apm.error_rate/observability/alert/update", + "alerting:apm.error_rate/alerts/alert/get", + "alerting:apm.error_rate/alerts/alert/find", + "alerting:apm.error_rate/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.error_rate/alerts/alert/getAlertSummary", + "alerting:apm.error_rate/alerts/alert/update", "alerting:apm.transaction_error_rate/observability/alert/get", "alerting:apm.transaction_error_rate/observability/alert/find", "alerting:apm.transaction_error_rate/observability/alert/getAuthorizedAlertsIndices", "alerting:apm.transaction_error_rate/observability/alert/getAlertSummary", "alerting:apm.transaction_error_rate/observability/alert/update", + "alerting:apm.transaction_error_rate/alerts/alert/get", + "alerting:apm.transaction_error_rate/alerts/alert/find", + "alerting:apm.transaction_error_rate/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.transaction_error_rate/alerts/alert/getAlertSummary", + "alerting:apm.transaction_error_rate/alerts/alert/update", "alerting:apm.transaction_duration/observability/alert/get", "alerting:apm.transaction_duration/observability/alert/find", "alerting:apm.transaction_duration/observability/alert/getAuthorizedAlertsIndices", "alerting:apm.transaction_duration/observability/alert/getAlertSummary", "alerting:apm.transaction_duration/observability/alert/update", + "alerting:apm.transaction_duration/alerts/alert/get", + "alerting:apm.transaction_duration/alerts/alert/find", + "alerting:apm.transaction_duration/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.transaction_duration/alerts/alert/getAlertSummary", + "alerting:apm.transaction_duration/alerts/alert/update", "alerting:apm.anomaly/observability/alert/get", "alerting:apm.anomaly/observability/alert/find", "alerting:apm.anomaly/observability/alert/getAuthorizedAlertsIndices", "alerting:apm.anomaly/observability/alert/getAlertSummary", "alerting:apm.anomaly/observability/alert/update", + "alerting:apm.anomaly/alerts/alert/get", + "alerting:apm.anomaly/alerts/alert/find", + "alerting:apm.anomaly/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.anomaly/alerts/alert/getAlertSummary", + "alerting:apm.anomaly/alerts/alert/update", ], "elastic_managed_locations_enabled": Array [ "login:", @@ -8607,6 +13059,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:xpack.uptime.alerts.tls/uptime/rule/runSoon", "alerting:xpack.uptime.alerts.tls/uptime/rule/scheduleBackfill", "alerting:xpack.uptime.alerts.tls/uptime/rule/deleteBackfill", + "alerting:xpack.uptime.alerts.tls/alerts/rule/get", + "alerting:xpack.uptime.alerts.tls/alerts/rule/getRuleState", + "alerting:xpack.uptime.alerts.tls/alerts/rule/getAlertSummary", + "alerting:xpack.uptime.alerts.tls/alerts/rule/getExecutionLog", + "alerting:xpack.uptime.alerts.tls/alerts/rule/getActionErrorLog", + "alerting:xpack.uptime.alerts.tls/alerts/rule/find", + "alerting:xpack.uptime.alerts.tls/alerts/rule/getRuleExecutionKPI", + "alerting:xpack.uptime.alerts.tls/alerts/rule/getBackfill", + "alerting:xpack.uptime.alerts.tls/alerts/rule/findBackfill", + "alerting:xpack.uptime.alerts.tls/alerts/rule/create", + "alerting:xpack.uptime.alerts.tls/alerts/rule/delete", + "alerting:xpack.uptime.alerts.tls/alerts/rule/update", + "alerting:xpack.uptime.alerts.tls/alerts/rule/updateApiKey", + "alerting:xpack.uptime.alerts.tls/alerts/rule/enable", + "alerting:xpack.uptime.alerts.tls/alerts/rule/disable", + "alerting:xpack.uptime.alerts.tls/alerts/rule/muteAll", + "alerting:xpack.uptime.alerts.tls/alerts/rule/unmuteAll", + "alerting:xpack.uptime.alerts.tls/alerts/rule/muteAlert", + "alerting:xpack.uptime.alerts.tls/alerts/rule/unmuteAlert", + "alerting:xpack.uptime.alerts.tls/alerts/rule/snooze", + "alerting:xpack.uptime.alerts.tls/alerts/rule/bulkEdit", + "alerting:xpack.uptime.alerts.tls/alerts/rule/bulkDelete", + "alerting:xpack.uptime.alerts.tls/alerts/rule/bulkEnable", + "alerting:xpack.uptime.alerts.tls/alerts/rule/bulkDisable", + "alerting:xpack.uptime.alerts.tls/alerts/rule/unsnooze", + "alerting:xpack.uptime.alerts.tls/alerts/rule/runSoon", + "alerting:xpack.uptime.alerts.tls/alerts/rule/scheduleBackfill", + "alerting:xpack.uptime.alerts.tls/alerts/rule/deleteBackfill", "alerting:xpack.uptime.alerts.tlsCertificate/uptime/rule/get", "alerting:xpack.uptime.alerts.tlsCertificate/uptime/rule/getRuleState", "alerting:xpack.uptime.alerts.tlsCertificate/uptime/rule/getAlertSummary", @@ -8635,6 +13115,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:xpack.uptime.alerts.tlsCertificate/uptime/rule/runSoon", "alerting:xpack.uptime.alerts.tlsCertificate/uptime/rule/scheduleBackfill", "alerting:xpack.uptime.alerts.tlsCertificate/uptime/rule/deleteBackfill", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/rule/get", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/rule/getRuleState", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/rule/getAlertSummary", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/rule/getExecutionLog", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/rule/getActionErrorLog", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/rule/find", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/rule/getRuleExecutionKPI", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/rule/getBackfill", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/rule/findBackfill", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/rule/create", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/rule/delete", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/rule/update", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/rule/updateApiKey", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/rule/enable", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/rule/disable", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/rule/muteAll", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/rule/unmuteAll", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/rule/muteAlert", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/rule/unmuteAlert", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/rule/snooze", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/rule/bulkEdit", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/rule/bulkDelete", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/rule/bulkEnable", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/rule/bulkDisable", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/rule/unsnooze", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/rule/runSoon", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/rule/scheduleBackfill", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/rule/deleteBackfill", "alerting:xpack.uptime.alerts.monitorStatus/uptime/rule/get", "alerting:xpack.uptime.alerts.monitorStatus/uptime/rule/getRuleState", "alerting:xpack.uptime.alerts.monitorStatus/uptime/rule/getAlertSummary", @@ -8663,6 +13171,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:xpack.uptime.alerts.monitorStatus/uptime/rule/runSoon", "alerting:xpack.uptime.alerts.monitorStatus/uptime/rule/scheduleBackfill", "alerting:xpack.uptime.alerts.monitorStatus/uptime/rule/deleteBackfill", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/rule/get", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/rule/getRuleState", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/rule/getAlertSummary", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/rule/getExecutionLog", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/rule/getActionErrorLog", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/rule/find", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/rule/getRuleExecutionKPI", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/rule/getBackfill", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/rule/findBackfill", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/rule/create", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/rule/delete", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/rule/update", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/rule/updateApiKey", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/rule/enable", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/rule/disable", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/rule/muteAll", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/rule/unmuteAll", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/rule/muteAlert", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/rule/unmuteAlert", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/rule/snooze", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/rule/bulkEdit", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/rule/bulkDelete", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/rule/bulkEnable", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/rule/bulkDisable", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/rule/unsnooze", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/rule/runSoon", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/rule/scheduleBackfill", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/rule/deleteBackfill", "alerting:xpack.uptime.alerts.durationAnomaly/uptime/rule/get", "alerting:xpack.uptime.alerts.durationAnomaly/uptime/rule/getRuleState", "alerting:xpack.uptime.alerts.durationAnomaly/uptime/rule/getAlertSummary", @@ -8691,6 +13227,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:xpack.uptime.alerts.durationAnomaly/uptime/rule/runSoon", "alerting:xpack.uptime.alerts.durationAnomaly/uptime/rule/scheduleBackfill", "alerting:xpack.uptime.alerts.durationAnomaly/uptime/rule/deleteBackfill", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/rule/get", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/rule/getRuleState", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/rule/getAlertSummary", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/rule/getExecutionLog", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/rule/getActionErrorLog", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/rule/find", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/rule/getRuleExecutionKPI", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/rule/getBackfill", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/rule/findBackfill", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/rule/create", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/rule/delete", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/rule/update", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/rule/updateApiKey", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/rule/enable", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/rule/disable", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/rule/muteAll", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/rule/unmuteAll", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/rule/muteAlert", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/rule/unmuteAlert", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/rule/snooze", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/rule/bulkEdit", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/rule/bulkDelete", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/rule/bulkEnable", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/rule/bulkDisable", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/rule/unsnooze", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/rule/runSoon", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/rule/scheduleBackfill", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/rule/deleteBackfill", "alerting:xpack.synthetics.alerts.monitorStatus/uptime/rule/get", "alerting:xpack.synthetics.alerts.monitorStatus/uptime/rule/getRuleState", "alerting:xpack.synthetics.alerts.monitorStatus/uptime/rule/getAlertSummary", @@ -8719,6 +13283,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:xpack.synthetics.alerts.monitorStatus/uptime/rule/runSoon", "alerting:xpack.synthetics.alerts.monitorStatus/uptime/rule/scheduleBackfill", "alerting:xpack.synthetics.alerts.monitorStatus/uptime/rule/deleteBackfill", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/rule/get", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/rule/getRuleState", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/rule/getAlertSummary", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/rule/getExecutionLog", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/rule/getActionErrorLog", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/rule/find", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/rule/getRuleExecutionKPI", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/rule/getBackfill", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/rule/findBackfill", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/rule/create", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/rule/delete", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/rule/update", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/rule/updateApiKey", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/rule/enable", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/rule/disable", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/rule/muteAll", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/rule/unmuteAll", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/rule/muteAlert", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/rule/unmuteAlert", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/rule/snooze", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/rule/bulkEdit", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/rule/bulkDelete", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/rule/bulkEnable", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/rule/bulkDisable", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/rule/unsnooze", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/rule/runSoon", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/rule/scheduleBackfill", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/rule/deleteBackfill", "alerting:xpack.synthetics.alerts.tls/uptime/rule/get", "alerting:xpack.synthetics.alerts.tls/uptime/rule/getRuleState", "alerting:xpack.synthetics.alerts.tls/uptime/rule/getAlertSummary", @@ -8747,36 +13339,94 @@ export default function ({ getService }: FtrProviderContext) { "alerting:xpack.synthetics.alerts.tls/uptime/rule/runSoon", "alerting:xpack.synthetics.alerts.tls/uptime/rule/scheduleBackfill", "alerting:xpack.synthetics.alerts.tls/uptime/rule/deleteBackfill", + "alerting:xpack.synthetics.alerts.tls/alerts/rule/get", + "alerting:xpack.synthetics.alerts.tls/alerts/rule/getRuleState", + "alerting:xpack.synthetics.alerts.tls/alerts/rule/getAlertSummary", + "alerting:xpack.synthetics.alerts.tls/alerts/rule/getExecutionLog", + "alerting:xpack.synthetics.alerts.tls/alerts/rule/getActionErrorLog", + "alerting:xpack.synthetics.alerts.tls/alerts/rule/find", + "alerting:xpack.synthetics.alerts.tls/alerts/rule/getRuleExecutionKPI", + "alerting:xpack.synthetics.alerts.tls/alerts/rule/getBackfill", + "alerting:xpack.synthetics.alerts.tls/alerts/rule/findBackfill", + "alerting:xpack.synthetics.alerts.tls/alerts/rule/create", + "alerting:xpack.synthetics.alerts.tls/alerts/rule/delete", + "alerting:xpack.synthetics.alerts.tls/alerts/rule/update", + "alerting:xpack.synthetics.alerts.tls/alerts/rule/updateApiKey", + "alerting:xpack.synthetics.alerts.tls/alerts/rule/enable", + "alerting:xpack.synthetics.alerts.tls/alerts/rule/disable", + "alerting:xpack.synthetics.alerts.tls/alerts/rule/muteAll", + "alerting:xpack.synthetics.alerts.tls/alerts/rule/unmuteAll", + "alerting:xpack.synthetics.alerts.tls/alerts/rule/muteAlert", + "alerting:xpack.synthetics.alerts.tls/alerts/rule/unmuteAlert", + "alerting:xpack.synthetics.alerts.tls/alerts/rule/snooze", + "alerting:xpack.synthetics.alerts.tls/alerts/rule/bulkEdit", + "alerting:xpack.synthetics.alerts.tls/alerts/rule/bulkDelete", + "alerting:xpack.synthetics.alerts.tls/alerts/rule/bulkEnable", + "alerting:xpack.synthetics.alerts.tls/alerts/rule/bulkDisable", + "alerting:xpack.synthetics.alerts.tls/alerts/rule/unsnooze", + "alerting:xpack.synthetics.alerts.tls/alerts/rule/runSoon", + "alerting:xpack.synthetics.alerts.tls/alerts/rule/scheduleBackfill", + "alerting:xpack.synthetics.alerts.tls/alerts/rule/deleteBackfill", "alerting:xpack.uptime.alerts.tls/uptime/alert/get", "alerting:xpack.uptime.alerts.tls/uptime/alert/find", "alerting:xpack.uptime.alerts.tls/uptime/alert/getAuthorizedAlertsIndices", "alerting:xpack.uptime.alerts.tls/uptime/alert/getAlertSummary", "alerting:xpack.uptime.alerts.tls/uptime/alert/update", + "alerting:xpack.uptime.alerts.tls/alerts/alert/get", + "alerting:xpack.uptime.alerts.tls/alerts/alert/find", + "alerting:xpack.uptime.alerts.tls/alerts/alert/getAuthorizedAlertsIndices", + "alerting:xpack.uptime.alerts.tls/alerts/alert/getAlertSummary", + "alerting:xpack.uptime.alerts.tls/alerts/alert/update", "alerting:xpack.uptime.alerts.tlsCertificate/uptime/alert/get", "alerting:xpack.uptime.alerts.tlsCertificate/uptime/alert/find", "alerting:xpack.uptime.alerts.tlsCertificate/uptime/alert/getAuthorizedAlertsIndices", "alerting:xpack.uptime.alerts.tlsCertificate/uptime/alert/getAlertSummary", "alerting:xpack.uptime.alerts.tlsCertificate/uptime/alert/update", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/alert/get", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/alert/find", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/alert/getAuthorizedAlertsIndices", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/alert/getAlertSummary", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/alert/update", "alerting:xpack.uptime.alerts.monitorStatus/uptime/alert/get", "alerting:xpack.uptime.alerts.monitorStatus/uptime/alert/find", "alerting:xpack.uptime.alerts.monitorStatus/uptime/alert/getAuthorizedAlertsIndices", "alerting:xpack.uptime.alerts.monitorStatus/uptime/alert/getAlertSummary", "alerting:xpack.uptime.alerts.monitorStatus/uptime/alert/update", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/alert/get", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/alert/find", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/alert/getAuthorizedAlertsIndices", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/alert/getAlertSummary", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/alert/update", "alerting:xpack.uptime.alerts.durationAnomaly/uptime/alert/get", "alerting:xpack.uptime.alerts.durationAnomaly/uptime/alert/find", "alerting:xpack.uptime.alerts.durationAnomaly/uptime/alert/getAuthorizedAlertsIndices", "alerting:xpack.uptime.alerts.durationAnomaly/uptime/alert/getAlertSummary", "alerting:xpack.uptime.alerts.durationAnomaly/uptime/alert/update", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/alert/get", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/alert/find", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/alert/getAuthorizedAlertsIndices", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/alert/getAlertSummary", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/alert/update", "alerting:xpack.synthetics.alerts.monitorStatus/uptime/alert/get", "alerting:xpack.synthetics.alerts.monitorStatus/uptime/alert/find", "alerting:xpack.synthetics.alerts.monitorStatus/uptime/alert/getAuthorizedAlertsIndices", "alerting:xpack.synthetics.alerts.monitorStatus/uptime/alert/getAlertSummary", "alerting:xpack.synthetics.alerts.monitorStatus/uptime/alert/update", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/alert/get", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/alert/find", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/alert/getAuthorizedAlertsIndices", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/alert/getAlertSummary", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/alert/update", "alerting:xpack.synthetics.alerts.tls/uptime/alert/get", "alerting:xpack.synthetics.alerts.tls/uptime/alert/find", "alerting:xpack.synthetics.alerts.tls/uptime/alert/getAuthorizedAlertsIndices", "alerting:xpack.synthetics.alerts.tls/uptime/alert/getAlertSummary", "alerting:xpack.synthetics.alerts.tls/uptime/alert/update", + "alerting:xpack.synthetics.alerts.tls/alerts/alert/get", + "alerting:xpack.synthetics.alerts.tls/alerts/alert/find", + "alerting:xpack.synthetics.alerts.tls/alerts/alert/getAuthorizedAlertsIndices", + "alerting:xpack.synthetics.alerts.tls/alerts/alert/getAlertSummary", + "alerting:xpack.synthetics.alerts.tls/alerts/alert/update", "app:observability", "ui:catalogue/observability", "ui:navLinks/observability", @@ -8810,6 +13460,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:slo.rules.burnRate/observability/rule/runSoon", "alerting:slo.rules.burnRate/observability/rule/scheduleBackfill", "alerting:slo.rules.burnRate/observability/rule/deleteBackfill", + "alerting:slo.rules.burnRate/alerts/rule/get", + "alerting:slo.rules.burnRate/alerts/rule/getRuleState", + "alerting:slo.rules.burnRate/alerts/rule/getAlertSummary", + "alerting:slo.rules.burnRate/alerts/rule/getExecutionLog", + "alerting:slo.rules.burnRate/alerts/rule/getActionErrorLog", + "alerting:slo.rules.burnRate/alerts/rule/find", + "alerting:slo.rules.burnRate/alerts/rule/getRuleExecutionKPI", + "alerting:slo.rules.burnRate/alerts/rule/getBackfill", + "alerting:slo.rules.burnRate/alerts/rule/findBackfill", + "alerting:slo.rules.burnRate/alerts/rule/create", + "alerting:slo.rules.burnRate/alerts/rule/delete", + "alerting:slo.rules.burnRate/alerts/rule/update", + "alerting:slo.rules.burnRate/alerts/rule/updateApiKey", + "alerting:slo.rules.burnRate/alerts/rule/enable", + "alerting:slo.rules.burnRate/alerts/rule/disable", + "alerting:slo.rules.burnRate/alerts/rule/muteAll", + "alerting:slo.rules.burnRate/alerts/rule/unmuteAll", + "alerting:slo.rules.burnRate/alerts/rule/muteAlert", + "alerting:slo.rules.burnRate/alerts/rule/unmuteAlert", + "alerting:slo.rules.burnRate/alerts/rule/snooze", + "alerting:slo.rules.burnRate/alerts/rule/bulkEdit", + "alerting:slo.rules.burnRate/alerts/rule/bulkDelete", + "alerting:slo.rules.burnRate/alerts/rule/bulkEnable", + "alerting:slo.rules.burnRate/alerts/rule/bulkDisable", + "alerting:slo.rules.burnRate/alerts/rule/unsnooze", + "alerting:slo.rules.burnRate/alerts/rule/runSoon", + "alerting:slo.rules.burnRate/alerts/rule/scheduleBackfill", + "alerting:slo.rules.burnRate/alerts/rule/deleteBackfill", "alerting:observability.rules.custom_threshold/observability/rule/get", "alerting:observability.rules.custom_threshold/observability/rule/getRuleState", "alerting:observability.rules.custom_threshold/observability/rule/getAlertSummary", @@ -8838,6 +13516,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:observability.rules.custom_threshold/observability/rule/runSoon", "alerting:observability.rules.custom_threshold/observability/rule/scheduleBackfill", "alerting:observability.rules.custom_threshold/observability/rule/deleteBackfill", + "alerting:observability.rules.custom_threshold/alerts/rule/get", + "alerting:observability.rules.custom_threshold/alerts/rule/getRuleState", + "alerting:observability.rules.custom_threshold/alerts/rule/getAlertSummary", + "alerting:observability.rules.custom_threshold/alerts/rule/getExecutionLog", + "alerting:observability.rules.custom_threshold/alerts/rule/getActionErrorLog", + "alerting:observability.rules.custom_threshold/alerts/rule/find", + "alerting:observability.rules.custom_threshold/alerts/rule/getRuleExecutionKPI", + "alerting:observability.rules.custom_threshold/alerts/rule/getBackfill", + "alerting:observability.rules.custom_threshold/alerts/rule/findBackfill", + "alerting:observability.rules.custom_threshold/alerts/rule/create", + "alerting:observability.rules.custom_threshold/alerts/rule/delete", + "alerting:observability.rules.custom_threshold/alerts/rule/update", + "alerting:observability.rules.custom_threshold/alerts/rule/updateApiKey", + "alerting:observability.rules.custom_threshold/alerts/rule/enable", + "alerting:observability.rules.custom_threshold/alerts/rule/disable", + "alerting:observability.rules.custom_threshold/alerts/rule/muteAll", + "alerting:observability.rules.custom_threshold/alerts/rule/unmuteAll", + "alerting:observability.rules.custom_threshold/alerts/rule/muteAlert", + "alerting:observability.rules.custom_threshold/alerts/rule/unmuteAlert", + "alerting:observability.rules.custom_threshold/alerts/rule/snooze", + "alerting:observability.rules.custom_threshold/alerts/rule/bulkEdit", + "alerting:observability.rules.custom_threshold/alerts/rule/bulkDelete", + "alerting:observability.rules.custom_threshold/alerts/rule/bulkEnable", + "alerting:observability.rules.custom_threshold/alerts/rule/bulkDisable", + "alerting:observability.rules.custom_threshold/alerts/rule/unsnooze", + "alerting:observability.rules.custom_threshold/alerts/rule/runSoon", + "alerting:observability.rules.custom_threshold/alerts/rule/scheduleBackfill", + "alerting:observability.rules.custom_threshold/alerts/rule/deleteBackfill", "alerting:.es-query/observability/rule/get", "alerting:.es-query/observability/rule/getRuleState", "alerting:.es-query/observability/rule/getAlertSummary", @@ -8866,6 +13572,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:.es-query/observability/rule/runSoon", "alerting:.es-query/observability/rule/scheduleBackfill", "alerting:.es-query/observability/rule/deleteBackfill", + "alerting:.es-query/alerts/rule/get", + "alerting:.es-query/alerts/rule/getRuleState", + "alerting:.es-query/alerts/rule/getAlertSummary", + "alerting:.es-query/alerts/rule/getExecutionLog", + "alerting:.es-query/alerts/rule/getActionErrorLog", + "alerting:.es-query/alerts/rule/find", + "alerting:.es-query/alerts/rule/getRuleExecutionKPI", + "alerting:.es-query/alerts/rule/getBackfill", + "alerting:.es-query/alerts/rule/findBackfill", + "alerting:.es-query/alerts/rule/create", + "alerting:.es-query/alerts/rule/delete", + "alerting:.es-query/alerts/rule/update", + "alerting:.es-query/alerts/rule/updateApiKey", + "alerting:.es-query/alerts/rule/enable", + "alerting:.es-query/alerts/rule/disable", + "alerting:.es-query/alerts/rule/muteAll", + "alerting:.es-query/alerts/rule/unmuteAll", + "alerting:.es-query/alerts/rule/muteAlert", + "alerting:.es-query/alerts/rule/unmuteAlert", + "alerting:.es-query/alerts/rule/snooze", + "alerting:.es-query/alerts/rule/bulkEdit", + "alerting:.es-query/alerts/rule/bulkDelete", + "alerting:.es-query/alerts/rule/bulkEnable", + "alerting:.es-query/alerts/rule/bulkDisable", + "alerting:.es-query/alerts/rule/unsnooze", + "alerting:.es-query/alerts/rule/runSoon", + "alerting:.es-query/alerts/rule/scheduleBackfill", + "alerting:.es-query/alerts/rule/deleteBackfill", "alerting:xpack.ml.anomaly_detection_alert/observability/rule/get", "alerting:xpack.ml.anomaly_detection_alert/observability/rule/getRuleState", "alerting:xpack.ml.anomaly_detection_alert/observability/rule/getAlertSummary", @@ -8894,6 +13628,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:xpack.ml.anomaly_detection_alert/observability/rule/runSoon", "alerting:xpack.ml.anomaly_detection_alert/observability/rule/scheduleBackfill", "alerting:xpack.ml.anomaly_detection_alert/observability/rule/deleteBackfill", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/get", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getRuleState", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getAlertSummary", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getExecutionLog", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getActionErrorLog", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/find", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getRuleExecutionKPI", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getBackfill", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/findBackfill", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/create", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/delete", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/update", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/updateApiKey", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/enable", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/disable", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/muteAll", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/unmuteAll", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/muteAlert", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/unmuteAlert", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/snooze", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/bulkEdit", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/bulkDelete", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/bulkEnable", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/bulkDisable", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/unsnooze", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/runSoon", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/scheduleBackfill", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/deleteBackfill", "alerting:metrics.alert.inventory.threshold/observability/rule/get", "alerting:metrics.alert.inventory.threshold/observability/rule/getRuleState", "alerting:metrics.alert.inventory.threshold/observability/rule/getAlertSummary", @@ -8922,6 +13684,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:metrics.alert.inventory.threshold/observability/rule/runSoon", "alerting:metrics.alert.inventory.threshold/observability/rule/scheduleBackfill", "alerting:metrics.alert.inventory.threshold/observability/rule/deleteBackfill", + "alerting:metrics.alert.inventory.threshold/alerts/rule/get", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getRuleState", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getAlertSummary", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getExecutionLog", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getActionErrorLog", + "alerting:metrics.alert.inventory.threshold/alerts/rule/find", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getRuleExecutionKPI", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getBackfill", + "alerting:metrics.alert.inventory.threshold/alerts/rule/findBackfill", + "alerting:metrics.alert.inventory.threshold/alerts/rule/create", + "alerting:metrics.alert.inventory.threshold/alerts/rule/delete", + "alerting:metrics.alert.inventory.threshold/alerts/rule/update", + "alerting:metrics.alert.inventory.threshold/alerts/rule/updateApiKey", + "alerting:metrics.alert.inventory.threshold/alerts/rule/enable", + "alerting:metrics.alert.inventory.threshold/alerts/rule/disable", + "alerting:metrics.alert.inventory.threshold/alerts/rule/muteAll", + "alerting:metrics.alert.inventory.threshold/alerts/rule/unmuteAll", + "alerting:metrics.alert.inventory.threshold/alerts/rule/muteAlert", + "alerting:metrics.alert.inventory.threshold/alerts/rule/unmuteAlert", + "alerting:metrics.alert.inventory.threshold/alerts/rule/snooze", + "alerting:metrics.alert.inventory.threshold/alerts/rule/bulkEdit", + "alerting:metrics.alert.inventory.threshold/alerts/rule/bulkDelete", + "alerting:metrics.alert.inventory.threshold/alerts/rule/bulkEnable", + "alerting:metrics.alert.inventory.threshold/alerts/rule/bulkDisable", + "alerting:metrics.alert.inventory.threshold/alerts/rule/unsnooze", + "alerting:metrics.alert.inventory.threshold/alerts/rule/runSoon", + "alerting:metrics.alert.inventory.threshold/alerts/rule/scheduleBackfill", + "alerting:metrics.alert.inventory.threshold/alerts/rule/deleteBackfill", "alerting:apm.error_rate/observability/rule/get", "alerting:apm.error_rate/observability/rule/getRuleState", "alerting:apm.error_rate/observability/rule/getAlertSummary", @@ -8950,6 +13740,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.error_rate/observability/rule/runSoon", "alerting:apm.error_rate/observability/rule/scheduleBackfill", "alerting:apm.error_rate/observability/rule/deleteBackfill", + "alerting:apm.error_rate/alerts/rule/get", + "alerting:apm.error_rate/alerts/rule/getRuleState", + "alerting:apm.error_rate/alerts/rule/getAlertSummary", + "alerting:apm.error_rate/alerts/rule/getExecutionLog", + "alerting:apm.error_rate/alerts/rule/getActionErrorLog", + "alerting:apm.error_rate/alerts/rule/find", + "alerting:apm.error_rate/alerts/rule/getRuleExecutionKPI", + "alerting:apm.error_rate/alerts/rule/getBackfill", + "alerting:apm.error_rate/alerts/rule/findBackfill", + "alerting:apm.error_rate/alerts/rule/create", + "alerting:apm.error_rate/alerts/rule/delete", + "alerting:apm.error_rate/alerts/rule/update", + "alerting:apm.error_rate/alerts/rule/updateApiKey", + "alerting:apm.error_rate/alerts/rule/enable", + "alerting:apm.error_rate/alerts/rule/disable", + "alerting:apm.error_rate/alerts/rule/muteAll", + "alerting:apm.error_rate/alerts/rule/unmuteAll", + "alerting:apm.error_rate/alerts/rule/muteAlert", + "alerting:apm.error_rate/alerts/rule/unmuteAlert", + "alerting:apm.error_rate/alerts/rule/snooze", + "alerting:apm.error_rate/alerts/rule/bulkEdit", + "alerting:apm.error_rate/alerts/rule/bulkDelete", + "alerting:apm.error_rate/alerts/rule/bulkEnable", + "alerting:apm.error_rate/alerts/rule/bulkDisable", + "alerting:apm.error_rate/alerts/rule/unsnooze", + "alerting:apm.error_rate/alerts/rule/runSoon", + "alerting:apm.error_rate/alerts/rule/scheduleBackfill", + "alerting:apm.error_rate/alerts/rule/deleteBackfill", "alerting:apm.transaction_error_rate/observability/rule/get", "alerting:apm.transaction_error_rate/observability/rule/getRuleState", "alerting:apm.transaction_error_rate/observability/rule/getAlertSummary", @@ -8978,6 +13796,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.transaction_error_rate/observability/rule/runSoon", "alerting:apm.transaction_error_rate/observability/rule/scheduleBackfill", "alerting:apm.transaction_error_rate/observability/rule/deleteBackfill", + "alerting:apm.transaction_error_rate/alerts/rule/get", + "alerting:apm.transaction_error_rate/alerts/rule/getRuleState", + "alerting:apm.transaction_error_rate/alerts/rule/getAlertSummary", + "alerting:apm.transaction_error_rate/alerts/rule/getExecutionLog", + "alerting:apm.transaction_error_rate/alerts/rule/getActionErrorLog", + "alerting:apm.transaction_error_rate/alerts/rule/find", + "alerting:apm.transaction_error_rate/alerts/rule/getRuleExecutionKPI", + "alerting:apm.transaction_error_rate/alerts/rule/getBackfill", + "alerting:apm.transaction_error_rate/alerts/rule/findBackfill", + "alerting:apm.transaction_error_rate/alerts/rule/create", + "alerting:apm.transaction_error_rate/alerts/rule/delete", + "alerting:apm.transaction_error_rate/alerts/rule/update", + "alerting:apm.transaction_error_rate/alerts/rule/updateApiKey", + "alerting:apm.transaction_error_rate/alerts/rule/enable", + "alerting:apm.transaction_error_rate/alerts/rule/disable", + "alerting:apm.transaction_error_rate/alerts/rule/muteAll", + "alerting:apm.transaction_error_rate/alerts/rule/unmuteAll", + "alerting:apm.transaction_error_rate/alerts/rule/muteAlert", + "alerting:apm.transaction_error_rate/alerts/rule/unmuteAlert", + "alerting:apm.transaction_error_rate/alerts/rule/snooze", + "alerting:apm.transaction_error_rate/alerts/rule/bulkEdit", + "alerting:apm.transaction_error_rate/alerts/rule/bulkDelete", + "alerting:apm.transaction_error_rate/alerts/rule/bulkEnable", + "alerting:apm.transaction_error_rate/alerts/rule/bulkDisable", + "alerting:apm.transaction_error_rate/alerts/rule/unsnooze", + "alerting:apm.transaction_error_rate/alerts/rule/runSoon", + "alerting:apm.transaction_error_rate/alerts/rule/scheduleBackfill", + "alerting:apm.transaction_error_rate/alerts/rule/deleteBackfill", "alerting:apm.transaction_duration/observability/rule/get", "alerting:apm.transaction_duration/observability/rule/getRuleState", "alerting:apm.transaction_duration/observability/rule/getAlertSummary", @@ -9006,6 +13852,34 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.transaction_duration/observability/rule/runSoon", "alerting:apm.transaction_duration/observability/rule/scheduleBackfill", "alerting:apm.transaction_duration/observability/rule/deleteBackfill", + "alerting:apm.transaction_duration/alerts/rule/get", + "alerting:apm.transaction_duration/alerts/rule/getRuleState", + "alerting:apm.transaction_duration/alerts/rule/getAlertSummary", + "alerting:apm.transaction_duration/alerts/rule/getExecutionLog", + "alerting:apm.transaction_duration/alerts/rule/getActionErrorLog", + "alerting:apm.transaction_duration/alerts/rule/find", + "alerting:apm.transaction_duration/alerts/rule/getRuleExecutionKPI", + "alerting:apm.transaction_duration/alerts/rule/getBackfill", + "alerting:apm.transaction_duration/alerts/rule/findBackfill", + "alerting:apm.transaction_duration/alerts/rule/create", + "alerting:apm.transaction_duration/alerts/rule/delete", + "alerting:apm.transaction_duration/alerts/rule/update", + "alerting:apm.transaction_duration/alerts/rule/updateApiKey", + "alerting:apm.transaction_duration/alerts/rule/enable", + "alerting:apm.transaction_duration/alerts/rule/disable", + "alerting:apm.transaction_duration/alerts/rule/muteAll", + "alerting:apm.transaction_duration/alerts/rule/unmuteAll", + "alerting:apm.transaction_duration/alerts/rule/muteAlert", + "alerting:apm.transaction_duration/alerts/rule/unmuteAlert", + "alerting:apm.transaction_duration/alerts/rule/snooze", + "alerting:apm.transaction_duration/alerts/rule/bulkEdit", + "alerting:apm.transaction_duration/alerts/rule/bulkDelete", + "alerting:apm.transaction_duration/alerts/rule/bulkEnable", + "alerting:apm.transaction_duration/alerts/rule/bulkDisable", + "alerting:apm.transaction_duration/alerts/rule/unsnooze", + "alerting:apm.transaction_duration/alerts/rule/runSoon", + "alerting:apm.transaction_duration/alerts/rule/scheduleBackfill", + "alerting:apm.transaction_duration/alerts/rule/deleteBackfill", "alerting:apm.anomaly/observability/rule/get", "alerting:apm.anomaly/observability/rule/getRuleState", "alerting:apm.anomaly/observability/rule/getAlertSummary", @@ -9034,51 +13908,124 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.anomaly/observability/rule/runSoon", "alerting:apm.anomaly/observability/rule/scheduleBackfill", "alerting:apm.anomaly/observability/rule/deleteBackfill", + "alerting:apm.anomaly/alerts/rule/get", + "alerting:apm.anomaly/alerts/rule/getRuleState", + "alerting:apm.anomaly/alerts/rule/getAlertSummary", + "alerting:apm.anomaly/alerts/rule/getExecutionLog", + "alerting:apm.anomaly/alerts/rule/getActionErrorLog", + "alerting:apm.anomaly/alerts/rule/find", + "alerting:apm.anomaly/alerts/rule/getRuleExecutionKPI", + "alerting:apm.anomaly/alerts/rule/getBackfill", + "alerting:apm.anomaly/alerts/rule/findBackfill", + "alerting:apm.anomaly/alerts/rule/create", + "alerting:apm.anomaly/alerts/rule/delete", + "alerting:apm.anomaly/alerts/rule/update", + "alerting:apm.anomaly/alerts/rule/updateApiKey", + "alerting:apm.anomaly/alerts/rule/enable", + "alerting:apm.anomaly/alerts/rule/disable", + "alerting:apm.anomaly/alerts/rule/muteAll", + "alerting:apm.anomaly/alerts/rule/unmuteAll", + "alerting:apm.anomaly/alerts/rule/muteAlert", + "alerting:apm.anomaly/alerts/rule/unmuteAlert", + "alerting:apm.anomaly/alerts/rule/snooze", + "alerting:apm.anomaly/alerts/rule/bulkEdit", + "alerting:apm.anomaly/alerts/rule/bulkDelete", + "alerting:apm.anomaly/alerts/rule/bulkEnable", + "alerting:apm.anomaly/alerts/rule/bulkDisable", + "alerting:apm.anomaly/alerts/rule/unsnooze", + "alerting:apm.anomaly/alerts/rule/runSoon", + "alerting:apm.anomaly/alerts/rule/scheduleBackfill", + "alerting:apm.anomaly/alerts/rule/deleteBackfill", "alerting:slo.rules.burnRate/observability/alert/get", "alerting:slo.rules.burnRate/observability/alert/find", "alerting:slo.rules.burnRate/observability/alert/getAuthorizedAlertsIndices", "alerting:slo.rules.burnRate/observability/alert/getAlertSummary", "alerting:slo.rules.burnRate/observability/alert/update", + "alerting:slo.rules.burnRate/alerts/alert/get", + "alerting:slo.rules.burnRate/alerts/alert/find", + "alerting:slo.rules.burnRate/alerts/alert/getAuthorizedAlertsIndices", + "alerting:slo.rules.burnRate/alerts/alert/getAlertSummary", + "alerting:slo.rules.burnRate/alerts/alert/update", "alerting:observability.rules.custom_threshold/observability/alert/get", "alerting:observability.rules.custom_threshold/observability/alert/find", "alerting:observability.rules.custom_threshold/observability/alert/getAuthorizedAlertsIndices", "alerting:observability.rules.custom_threshold/observability/alert/getAlertSummary", "alerting:observability.rules.custom_threshold/observability/alert/update", + "alerting:observability.rules.custom_threshold/alerts/alert/get", + "alerting:observability.rules.custom_threshold/alerts/alert/find", + "alerting:observability.rules.custom_threshold/alerts/alert/getAuthorizedAlertsIndices", + "alerting:observability.rules.custom_threshold/alerts/alert/getAlertSummary", + "alerting:observability.rules.custom_threshold/alerts/alert/update", "alerting:.es-query/observability/alert/get", "alerting:.es-query/observability/alert/find", "alerting:.es-query/observability/alert/getAuthorizedAlertsIndices", "alerting:.es-query/observability/alert/getAlertSummary", "alerting:.es-query/observability/alert/update", + "alerting:.es-query/alerts/alert/get", + "alerting:.es-query/alerts/alert/find", + "alerting:.es-query/alerts/alert/getAuthorizedAlertsIndices", + "alerting:.es-query/alerts/alert/getAlertSummary", + "alerting:.es-query/alerts/alert/update", "alerting:xpack.ml.anomaly_detection_alert/observability/alert/get", "alerting:xpack.ml.anomaly_detection_alert/observability/alert/find", "alerting:xpack.ml.anomaly_detection_alert/observability/alert/getAuthorizedAlertsIndices", "alerting:xpack.ml.anomaly_detection_alert/observability/alert/getAlertSummary", "alerting:xpack.ml.anomaly_detection_alert/observability/alert/update", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/get", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/find", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/getAuthorizedAlertsIndices", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/getAlertSummary", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/update", "alerting:metrics.alert.inventory.threshold/observability/alert/get", "alerting:metrics.alert.inventory.threshold/observability/alert/find", "alerting:metrics.alert.inventory.threshold/observability/alert/getAuthorizedAlertsIndices", "alerting:metrics.alert.inventory.threshold/observability/alert/getAlertSummary", "alerting:metrics.alert.inventory.threshold/observability/alert/update", + "alerting:metrics.alert.inventory.threshold/alerts/alert/get", + "alerting:metrics.alert.inventory.threshold/alerts/alert/find", + "alerting:metrics.alert.inventory.threshold/alerts/alert/getAuthorizedAlertsIndices", + "alerting:metrics.alert.inventory.threshold/alerts/alert/getAlertSummary", + "alerting:metrics.alert.inventory.threshold/alerts/alert/update", "alerting:apm.error_rate/observability/alert/get", "alerting:apm.error_rate/observability/alert/find", "alerting:apm.error_rate/observability/alert/getAuthorizedAlertsIndices", "alerting:apm.error_rate/observability/alert/getAlertSummary", "alerting:apm.error_rate/observability/alert/update", + "alerting:apm.error_rate/alerts/alert/get", + "alerting:apm.error_rate/alerts/alert/find", + "alerting:apm.error_rate/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.error_rate/alerts/alert/getAlertSummary", + "alerting:apm.error_rate/alerts/alert/update", "alerting:apm.transaction_error_rate/observability/alert/get", "alerting:apm.transaction_error_rate/observability/alert/find", "alerting:apm.transaction_error_rate/observability/alert/getAuthorizedAlertsIndices", "alerting:apm.transaction_error_rate/observability/alert/getAlertSummary", "alerting:apm.transaction_error_rate/observability/alert/update", + "alerting:apm.transaction_error_rate/alerts/alert/get", + "alerting:apm.transaction_error_rate/alerts/alert/find", + "alerting:apm.transaction_error_rate/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.transaction_error_rate/alerts/alert/getAlertSummary", + "alerting:apm.transaction_error_rate/alerts/alert/update", "alerting:apm.transaction_duration/observability/alert/get", "alerting:apm.transaction_duration/observability/alert/find", "alerting:apm.transaction_duration/observability/alert/getAuthorizedAlertsIndices", "alerting:apm.transaction_duration/observability/alert/getAlertSummary", "alerting:apm.transaction_duration/observability/alert/update", + "alerting:apm.transaction_duration/alerts/alert/get", + "alerting:apm.transaction_duration/alerts/alert/find", + "alerting:apm.transaction_duration/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.transaction_duration/alerts/alert/getAlertSummary", + "alerting:apm.transaction_duration/alerts/alert/update", "alerting:apm.anomaly/observability/alert/get", "alerting:apm.anomaly/observability/alert/find", "alerting:apm.anomaly/observability/alert/getAuthorizedAlertsIndices", "alerting:apm.anomaly/observability/alert/getAlertSummary", "alerting:apm.anomaly/observability/alert/update", + "alerting:apm.anomaly/alerts/alert/get", + "alerting:apm.anomaly/alerts/alert/find", + "alerting:apm.anomaly/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.anomaly/alerts/alert/getAlertSummary", + "alerting:apm.anomaly/alerts/alert/update", ], "minimal_read": Array [ "login:", @@ -9154,6 +14101,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:xpack.uptime.alerts.tls/uptime/rule/getRuleExecutionKPI", "alerting:xpack.uptime.alerts.tls/uptime/rule/getBackfill", "alerting:xpack.uptime.alerts.tls/uptime/rule/findBackfill", + "alerting:xpack.uptime.alerts.tls/alerts/rule/get", + "alerting:xpack.uptime.alerts.tls/alerts/rule/getRuleState", + "alerting:xpack.uptime.alerts.tls/alerts/rule/getAlertSummary", + "alerting:xpack.uptime.alerts.tls/alerts/rule/getExecutionLog", + "alerting:xpack.uptime.alerts.tls/alerts/rule/getActionErrorLog", + "alerting:xpack.uptime.alerts.tls/alerts/rule/find", + "alerting:xpack.uptime.alerts.tls/alerts/rule/getRuleExecutionKPI", + "alerting:xpack.uptime.alerts.tls/alerts/rule/getBackfill", + "alerting:xpack.uptime.alerts.tls/alerts/rule/findBackfill", "alerting:xpack.uptime.alerts.tlsCertificate/uptime/rule/get", "alerting:xpack.uptime.alerts.tlsCertificate/uptime/rule/getRuleState", "alerting:xpack.uptime.alerts.tlsCertificate/uptime/rule/getAlertSummary", @@ -9163,6 +14119,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:xpack.uptime.alerts.tlsCertificate/uptime/rule/getRuleExecutionKPI", "alerting:xpack.uptime.alerts.tlsCertificate/uptime/rule/getBackfill", "alerting:xpack.uptime.alerts.tlsCertificate/uptime/rule/findBackfill", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/rule/get", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/rule/getRuleState", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/rule/getAlertSummary", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/rule/getExecutionLog", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/rule/getActionErrorLog", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/rule/find", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/rule/getRuleExecutionKPI", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/rule/getBackfill", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/rule/findBackfill", "alerting:xpack.uptime.alerts.monitorStatus/uptime/rule/get", "alerting:xpack.uptime.alerts.monitorStatus/uptime/rule/getRuleState", "alerting:xpack.uptime.alerts.monitorStatus/uptime/rule/getAlertSummary", @@ -9172,6 +14137,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:xpack.uptime.alerts.monitorStatus/uptime/rule/getRuleExecutionKPI", "alerting:xpack.uptime.alerts.monitorStatus/uptime/rule/getBackfill", "alerting:xpack.uptime.alerts.monitorStatus/uptime/rule/findBackfill", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/rule/get", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/rule/getRuleState", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/rule/getAlertSummary", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/rule/getExecutionLog", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/rule/getActionErrorLog", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/rule/find", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/rule/getRuleExecutionKPI", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/rule/getBackfill", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/rule/findBackfill", "alerting:xpack.uptime.alerts.durationAnomaly/uptime/rule/get", "alerting:xpack.uptime.alerts.durationAnomaly/uptime/rule/getRuleState", "alerting:xpack.uptime.alerts.durationAnomaly/uptime/rule/getAlertSummary", @@ -9181,6 +14155,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:xpack.uptime.alerts.durationAnomaly/uptime/rule/getRuleExecutionKPI", "alerting:xpack.uptime.alerts.durationAnomaly/uptime/rule/getBackfill", "alerting:xpack.uptime.alerts.durationAnomaly/uptime/rule/findBackfill", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/rule/get", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/rule/getRuleState", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/rule/getAlertSummary", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/rule/getExecutionLog", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/rule/getActionErrorLog", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/rule/find", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/rule/getRuleExecutionKPI", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/rule/getBackfill", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/rule/findBackfill", "alerting:xpack.synthetics.alerts.monitorStatus/uptime/rule/get", "alerting:xpack.synthetics.alerts.monitorStatus/uptime/rule/getRuleState", "alerting:xpack.synthetics.alerts.monitorStatus/uptime/rule/getAlertSummary", @@ -9190,6 +14173,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:xpack.synthetics.alerts.monitorStatus/uptime/rule/getRuleExecutionKPI", "alerting:xpack.synthetics.alerts.monitorStatus/uptime/rule/getBackfill", "alerting:xpack.synthetics.alerts.monitorStatus/uptime/rule/findBackfill", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/rule/get", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/rule/getRuleState", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/rule/getAlertSummary", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/rule/getExecutionLog", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/rule/getActionErrorLog", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/rule/find", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/rule/getRuleExecutionKPI", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/rule/getBackfill", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/rule/findBackfill", "alerting:xpack.synthetics.alerts.tls/uptime/rule/get", "alerting:xpack.synthetics.alerts.tls/uptime/rule/getRuleState", "alerting:xpack.synthetics.alerts.tls/uptime/rule/getAlertSummary", @@ -9199,30 +14191,63 @@ export default function ({ getService }: FtrProviderContext) { "alerting:xpack.synthetics.alerts.tls/uptime/rule/getRuleExecutionKPI", "alerting:xpack.synthetics.alerts.tls/uptime/rule/getBackfill", "alerting:xpack.synthetics.alerts.tls/uptime/rule/findBackfill", + "alerting:xpack.synthetics.alerts.tls/alerts/rule/get", + "alerting:xpack.synthetics.alerts.tls/alerts/rule/getRuleState", + "alerting:xpack.synthetics.alerts.tls/alerts/rule/getAlertSummary", + "alerting:xpack.synthetics.alerts.tls/alerts/rule/getExecutionLog", + "alerting:xpack.synthetics.alerts.tls/alerts/rule/getActionErrorLog", + "alerting:xpack.synthetics.alerts.tls/alerts/rule/find", + "alerting:xpack.synthetics.alerts.tls/alerts/rule/getRuleExecutionKPI", + "alerting:xpack.synthetics.alerts.tls/alerts/rule/getBackfill", + "alerting:xpack.synthetics.alerts.tls/alerts/rule/findBackfill", "alerting:xpack.uptime.alerts.tls/uptime/alert/get", "alerting:xpack.uptime.alerts.tls/uptime/alert/find", "alerting:xpack.uptime.alerts.tls/uptime/alert/getAuthorizedAlertsIndices", "alerting:xpack.uptime.alerts.tls/uptime/alert/getAlertSummary", + "alerting:xpack.uptime.alerts.tls/alerts/alert/get", + "alerting:xpack.uptime.alerts.tls/alerts/alert/find", + "alerting:xpack.uptime.alerts.tls/alerts/alert/getAuthorizedAlertsIndices", + "alerting:xpack.uptime.alerts.tls/alerts/alert/getAlertSummary", "alerting:xpack.uptime.alerts.tlsCertificate/uptime/alert/get", "alerting:xpack.uptime.alerts.tlsCertificate/uptime/alert/find", "alerting:xpack.uptime.alerts.tlsCertificate/uptime/alert/getAuthorizedAlertsIndices", "alerting:xpack.uptime.alerts.tlsCertificate/uptime/alert/getAlertSummary", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/alert/get", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/alert/find", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/alert/getAuthorizedAlertsIndices", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/alert/getAlertSummary", "alerting:xpack.uptime.alerts.monitorStatus/uptime/alert/get", "alerting:xpack.uptime.alerts.monitorStatus/uptime/alert/find", "alerting:xpack.uptime.alerts.monitorStatus/uptime/alert/getAuthorizedAlertsIndices", "alerting:xpack.uptime.alerts.monitorStatus/uptime/alert/getAlertSummary", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/alert/get", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/alert/find", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/alert/getAuthorizedAlertsIndices", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/alert/getAlertSummary", "alerting:xpack.uptime.alerts.durationAnomaly/uptime/alert/get", "alerting:xpack.uptime.alerts.durationAnomaly/uptime/alert/find", "alerting:xpack.uptime.alerts.durationAnomaly/uptime/alert/getAuthorizedAlertsIndices", "alerting:xpack.uptime.alerts.durationAnomaly/uptime/alert/getAlertSummary", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/alert/get", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/alert/find", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/alert/getAuthorizedAlertsIndices", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/alert/getAlertSummary", "alerting:xpack.synthetics.alerts.monitorStatus/uptime/alert/get", "alerting:xpack.synthetics.alerts.monitorStatus/uptime/alert/find", "alerting:xpack.synthetics.alerts.monitorStatus/uptime/alert/getAuthorizedAlertsIndices", "alerting:xpack.synthetics.alerts.monitorStatus/uptime/alert/getAlertSummary", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/alert/get", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/alert/find", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/alert/getAuthorizedAlertsIndices", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/alert/getAlertSummary", "alerting:xpack.synthetics.alerts.tls/uptime/alert/get", "alerting:xpack.synthetics.alerts.tls/uptime/alert/find", "alerting:xpack.synthetics.alerts.tls/uptime/alert/getAuthorizedAlertsIndices", "alerting:xpack.synthetics.alerts.tls/uptime/alert/getAlertSummary", + "alerting:xpack.synthetics.alerts.tls/alerts/alert/get", + "alerting:xpack.synthetics.alerts.tls/alerts/alert/find", + "alerting:xpack.synthetics.alerts.tls/alerts/alert/getAuthorizedAlertsIndices", + "alerting:xpack.synthetics.alerts.tls/alerts/alert/getAlertSummary", "app:observability", "ui:catalogue/observability", "ui:navLinks/observability", @@ -9236,6 +14261,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:slo.rules.burnRate/observability/rule/getRuleExecutionKPI", "alerting:slo.rules.burnRate/observability/rule/getBackfill", "alerting:slo.rules.burnRate/observability/rule/findBackfill", + "alerting:slo.rules.burnRate/alerts/rule/get", + "alerting:slo.rules.burnRate/alerts/rule/getRuleState", + "alerting:slo.rules.burnRate/alerts/rule/getAlertSummary", + "alerting:slo.rules.burnRate/alerts/rule/getExecutionLog", + "alerting:slo.rules.burnRate/alerts/rule/getActionErrorLog", + "alerting:slo.rules.burnRate/alerts/rule/find", + "alerting:slo.rules.burnRate/alerts/rule/getRuleExecutionKPI", + "alerting:slo.rules.burnRate/alerts/rule/getBackfill", + "alerting:slo.rules.burnRate/alerts/rule/findBackfill", "alerting:observability.rules.custom_threshold/observability/rule/get", "alerting:observability.rules.custom_threshold/observability/rule/getRuleState", "alerting:observability.rules.custom_threshold/observability/rule/getAlertSummary", @@ -9245,6 +14279,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:observability.rules.custom_threshold/observability/rule/getRuleExecutionKPI", "alerting:observability.rules.custom_threshold/observability/rule/getBackfill", "alerting:observability.rules.custom_threshold/observability/rule/findBackfill", + "alerting:observability.rules.custom_threshold/alerts/rule/get", + "alerting:observability.rules.custom_threshold/alerts/rule/getRuleState", + "alerting:observability.rules.custom_threshold/alerts/rule/getAlertSummary", + "alerting:observability.rules.custom_threshold/alerts/rule/getExecutionLog", + "alerting:observability.rules.custom_threshold/alerts/rule/getActionErrorLog", + "alerting:observability.rules.custom_threshold/alerts/rule/find", + "alerting:observability.rules.custom_threshold/alerts/rule/getRuleExecutionKPI", + "alerting:observability.rules.custom_threshold/alerts/rule/getBackfill", + "alerting:observability.rules.custom_threshold/alerts/rule/findBackfill", "alerting:.es-query/observability/rule/get", "alerting:.es-query/observability/rule/getRuleState", "alerting:.es-query/observability/rule/getAlertSummary", @@ -9254,6 +14297,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:.es-query/observability/rule/getRuleExecutionKPI", "alerting:.es-query/observability/rule/getBackfill", "alerting:.es-query/observability/rule/findBackfill", + "alerting:.es-query/alerts/rule/get", + "alerting:.es-query/alerts/rule/getRuleState", + "alerting:.es-query/alerts/rule/getAlertSummary", + "alerting:.es-query/alerts/rule/getExecutionLog", + "alerting:.es-query/alerts/rule/getActionErrorLog", + "alerting:.es-query/alerts/rule/find", + "alerting:.es-query/alerts/rule/getRuleExecutionKPI", + "alerting:.es-query/alerts/rule/getBackfill", + "alerting:.es-query/alerts/rule/findBackfill", "alerting:xpack.ml.anomaly_detection_alert/observability/rule/get", "alerting:xpack.ml.anomaly_detection_alert/observability/rule/getRuleState", "alerting:xpack.ml.anomaly_detection_alert/observability/rule/getAlertSummary", @@ -9263,6 +14315,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:xpack.ml.anomaly_detection_alert/observability/rule/getRuleExecutionKPI", "alerting:xpack.ml.anomaly_detection_alert/observability/rule/getBackfill", "alerting:xpack.ml.anomaly_detection_alert/observability/rule/findBackfill", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/get", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getRuleState", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getAlertSummary", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getExecutionLog", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getActionErrorLog", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/find", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getRuleExecutionKPI", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getBackfill", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/findBackfill", "alerting:metrics.alert.inventory.threshold/observability/rule/get", "alerting:metrics.alert.inventory.threshold/observability/rule/getRuleState", "alerting:metrics.alert.inventory.threshold/observability/rule/getAlertSummary", @@ -9272,6 +14333,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:metrics.alert.inventory.threshold/observability/rule/getRuleExecutionKPI", "alerting:metrics.alert.inventory.threshold/observability/rule/getBackfill", "alerting:metrics.alert.inventory.threshold/observability/rule/findBackfill", + "alerting:metrics.alert.inventory.threshold/alerts/rule/get", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getRuleState", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getAlertSummary", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getExecutionLog", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getActionErrorLog", + "alerting:metrics.alert.inventory.threshold/alerts/rule/find", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getRuleExecutionKPI", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getBackfill", + "alerting:metrics.alert.inventory.threshold/alerts/rule/findBackfill", "alerting:apm.error_rate/observability/rule/get", "alerting:apm.error_rate/observability/rule/getRuleState", "alerting:apm.error_rate/observability/rule/getAlertSummary", @@ -9281,6 +14351,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.error_rate/observability/rule/getRuleExecutionKPI", "alerting:apm.error_rate/observability/rule/getBackfill", "alerting:apm.error_rate/observability/rule/findBackfill", + "alerting:apm.error_rate/alerts/rule/get", + "alerting:apm.error_rate/alerts/rule/getRuleState", + "alerting:apm.error_rate/alerts/rule/getAlertSummary", + "alerting:apm.error_rate/alerts/rule/getExecutionLog", + "alerting:apm.error_rate/alerts/rule/getActionErrorLog", + "alerting:apm.error_rate/alerts/rule/find", + "alerting:apm.error_rate/alerts/rule/getRuleExecutionKPI", + "alerting:apm.error_rate/alerts/rule/getBackfill", + "alerting:apm.error_rate/alerts/rule/findBackfill", "alerting:apm.transaction_error_rate/observability/rule/get", "alerting:apm.transaction_error_rate/observability/rule/getRuleState", "alerting:apm.transaction_error_rate/observability/rule/getAlertSummary", @@ -9290,6 +14369,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.transaction_error_rate/observability/rule/getRuleExecutionKPI", "alerting:apm.transaction_error_rate/observability/rule/getBackfill", "alerting:apm.transaction_error_rate/observability/rule/findBackfill", + "alerting:apm.transaction_error_rate/alerts/rule/get", + "alerting:apm.transaction_error_rate/alerts/rule/getRuleState", + "alerting:apm.transaction_error_rate/alerts/rule/getAlertSummary", + "alerting:apm.transaction_error_rate/alerts/rule/getExecutionLog", + "alerting:apm.transaction_error_rate/alerts/rule/getActionErrorLog", + "alerting:apm.transaction_error_rate/alerts/rule/find", + "alerting:apm.transaction_error_rate/alerts/rule/getRuleExecutionKPI", + "alerting:apm.transaction_error_rate/alerts/rule/getBackfill", + "alerting:apm.transaction_error_rate/alerts/rule/findBackfill", "alerting:apm.transaction_duration/observability/rule/get", "alerting:apm.transaction_duration/observability/rule/getRuleState", "alerting:apm.transaction_duration/observability/rule/getAlertSummary", @@ -9299,6 +14387,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.transaction_duration/observability/rule/getRuleExecutionKPI", "alerting:apm.transaction_duration/observability/rule/getBackfill", "alerting:apm.transaction_duration/observability/rule/findBackfill", + "alerting:apm.transaction_duration/alerts/rule/get", + "alerting:apm.transaction_duration/alerts/rule/getRuleState", + "alerting:apm.transaction_duration/alerts/rule/getAlertSummary", + "alerting:apm.transaction_duration/alerts/rule/getExecutionLog", + "alerting:apm.transaction_duration/alerts/rule/getActionErrorLog", + "alerting:apm.transaction_duration/alerts/rule/find", + "alerting:apm.transaction_duration/alerts/rule/getRuleExecutionKPI", + "alerting:apm.transaction_duration/alerts/rule/getBackfill", + "alerting:apm.transaction_duration/alerts/rule/findBackfill", "alerting:apm.anomaly/observability/rule/get", "alerting:apm.anomaly/observability/rule/getRuleState", "alerting:apm.anomaly/observability/rule/getAlertSummary", @@ -9308,42 +14405,87 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.anomaly/observability/rule/getRuleExecutionKPI", "alerting:apm.anomaly/observability/rule/getBackfill", "alerting:apm.anomaly/observability/rule/findBackfill", + "alerting:apm.anomaly/alerts/rule/get", + "alerting:apm.anomaly/alerts/rule/getRuleState", + "alerting:apm.anomaly/alerts/rule/getAlertSummary", + "alerting:apm.anomaly/alerts/rule/getExecutionLog", + "alerting:apm.anomaly/alerts/rule/getActionErrorLog", + "alerting:apm.anomaly/alerts/rule/find", + "alerting:apm.anomaly/alerts/rule/getRuleExecutionKPI", + "alerting:apm.anomaly/alerts/rule/getBackfill", + "alerting:apm.anomaly/alerts/rule/findBackfill", "alerting:slo.rules.burnRate/observability/alert/get", "alerting:slo.rules.burnRate/observability/alert/find", "alerting:slo.rules.burnRate/observability/alert/getAuthorizedAlertsIndices", "alerting:slo.rules.burnRate/observability/alert/getAlertSummary", + "alerting:slo.rules.burnRate/alerts/alert/get", + "alerting:slo.rules.burnRate/alerts/alert/find", + "alerting:slo.rules.burnRate/alerts/alert/getAuthorizedAlertsIndices", + "alerting:slo.rules.burnRate/alerts/alert/getAlertSummary", "alerting:observability.rules.custom_threshold/observability/alert/get", "alerting:observability.rules.custom_threshold/observability/alert/find", "alerting:observability.rules.custom_threshold/observability/alert/getAuthorizedAlertsIndices", "alerting:observability.rules.custom_threshold/observability/alert/getAlertSummary", + "alerting:observability.rules.custom_threshold/alerts/alert/get", + "alerting:observability.rules.custom_threshold/alerts/alert/find", + "alerting:observability.rules.custom_threshold/alerts/alert/getAuthorizedAlertsIndices", + "alerting:observability.rules.custom_threshold/alerts/alert/getAlertSummary", "alerting:.es-query/observability/alert/get", "alerting:.es-query/observability/alert/find", "alerting:.es-query/observability/alert/getAuthorizedAlertsIndices", "alerting:.es-query/observability/alert/getAlertSummary", + "alerting:.es-query/alerts/alert/get", + "alerting:.es-query/alerts/alert/find", + "alerting:.es-query/alerts/alert/getAuthorizedAlertsIndices", + "alerting:.es-query/alerts/alert/getAlertSummary", "alerting:xpack.ml.anomaly_detection_alert/observability/alert/get", "alerting:xpack.ml.anomaly_detection_alert/observability/alert/find", "alerting:xpack.ml.anomaly_detection_alert/observability/alert/getAuthorizedAlertsIndices", "alerting:xpack.ml.anomaly_detection_alert/observability/alert/getAlertSummary", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/get", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/find", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/getAuthorizedAlertsIndices", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/getAlertSummary", "alerting:metrics.alert.inventory.threshold/observability/alert/get", "alerting:metrics.alert.inventory.threshold/observability/alert/find", "alerting:metrics.alert.inventory.threshold/observability/alert/getAuthorizedAlertsIndices", "alerting:metrics.alert.inventory.threshold/observability/alert/getAlertSummary", + "alerting:metrics.alert.inventory.threshold/alerts/alert/get", + "alerting:metrics.alert.inventory.threshold/alerts/alert/find", + "alerting:metrics.alert.inventory.threshold/alerts/alert/getAuthorizedAlertsIndices", + "alerting:metrics.alert.inventory.threshold/alerts/alert/getAlertSummary", "alerting:apm.error_rate/observability/alert/get", "alerting:apm.error_rate/observability/alert/find", "alerting:apm.error_rate/observability/alert/getAuthorizedAlertsIndices", "alerting:apm.error_rate/observability/alert/getAlertSummary", + "alerting:apm.error_rate/alerts/alert/get", + "alerting:apm.error_rate/alerts/alert/find", + "alerting:apm.error_rate/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.error_rate/alerts/alert/getAlertSummary", "alerting:apm.transaction_error_rate/observability/alert/get", "alerting:apm.transaction_error_rate/observability/alert/find", "alerting:apm.transaction_error_rate/observability/alert/getAuthorizedAlertsIndices", "alerting:apm.transaction_error_rate/observability/alert/getAlertSummary", + "alerting:apm.transaction_error_rate/alerts/alert/get", + "alerting:apm.transaction_error_rate/alerts/alert/find", + "alerting:apm.transaction_error_rate/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.transaction_error_rate/alerts/alert/getAlertSummary", "alerting:apm.transaction_duration/observability/alert/get", "alerting:apm.transaction_duration/observability/alert/find", "alerting:apm.transaction_duration/observability/alert/getAuthorizedAlertsIndices", "alerting:apm.transaction_duration/observability/alert/getAlertSummary", + "alerting:apm.transaction_duration/alerts/alert/get", + "alerting:apm.transaction_duration/alerts/alert/find", + "alerting:apm.transaction_duration/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.transaction_duration/alerts/alert/getAlertSummary", "alerting:apm.anomaly/observability/alert/get", "alerting:apm.anomaly/observability/alert/find", "alerting:apm.anomaly/observability/alert/getAuthorizedAlertsIndices", "alerting:apm.anomaly/observability/alert/getAlertSummary", + "alerting:apm.anomaly/alerts/alert/get", + "alerting:apm.anomaly/alerts/alert/find", + "alerting:apm.anomaly/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.anomaly/alerts/alert/getAlertSummary", ], "read": Array [ "login:", @@ -9419,6 +14561,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:xpack.uptime.alerts.tls/uptime/rule/getRuleExecutionKPI", "alerting:xpack.uptime.alerts.tls/uptime/rule/getBackfill", "alerting:xpack.uptime.alerts.tls/uptime/rule/findBackfill", + "alerting:xpack.uptime.alerts.tls/alerts/rule/get", + "alerting:xpack.uptime.alerts.tls/alerts/rule/getRuleState", + "alerting:xpack.uptime.alerts.tls/alerts/rule/getAlertSummary", + "alerting:xpack.uptime.alerts.tls/alerts/rule/getExecutionLog", + "alerting:xpack.uptime.alerts.tls/alerts/rule/getActionErrorLog", + "alerting:xpack.uptime.alerts.tls/alerts/rule/find", + "alerting:xpack.uptime.alerts.tls/alerts/rule/getRuleExecutionKPI", + "alerting:xpack.uptime.alerts.tls/alerts/rule/getBackfill", + "alerting:xpack.uptime.alerts.tls/alerts/rule/findBackfill", "alerting:xpack.uptime.alerts.tlsCertificate/uptime/rule/get", "alerting:xpack.uptime.alerts.tlsCertificate/uptime/rule/getRuleState", "alerting:xpack.uptime.alerts.tlsCertificate/uptime/rule/getAlertSummary", @@ -9428,6 +14579,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:xpack.uptime.alerts.tlsCertificate/uptime/rule/getRuleExecutionKPI", "alerting:xpack.uptime.alerts.tlsCertificate/uptime/rule/getBackfill", "alerting:xpack.uptime.alerts.tlsCertificate/uptime/rule/findBackfill", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/rule/get", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/rule/getRuleState", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/rule/getAlertSummary", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/rule/getExecutionLog", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/rule/getActionErrorLog", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/rule/find", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/rule/getRuleExecutionKPI", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/rule/getBackfill", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/rule/findBackfill", "alerting:xpack.uptime.alerts.monitorStatus/uptime/rule/get", "alerting:xpack.uptime.alerts.monitorStatus/uptime/rule/getRuleState", "alerting:xpack.uptime.alerts.monitorStatus/uptime/rule/getAlertSummary", @@ -9437,6 +14597,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:xpack.uptime.alerts.monitorStatus/uptime/rule/getRuleExecutionKPI", "alerting:xpack.uptime.alerts.monitorStatus/uptime/rule/getBackfill", "alerting:xpack.uptime.alerts.monitorStatus/uptime/rule/findBackfill", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/rule/get", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/rule/getRuleState", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/rule/getAlertSummary", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/rule/getExecutionLog", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/rule/getActionErrorLog", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/rule/find", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/rule/getRuleExecutionKPI", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/rule/getBackfill", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/rule/findBackfill", "alerting:xpack.uptime.alerts.durationAnomaly/uptime/rule/get", "alerting:xpack.uptime.alerts.durationAnomaly/uptime/rule/getRuleState", "alerting:xpack.uptime.alerts.durationAnomaly/uptime/rule/getAlertSummary", @@ -9446,6 +14615,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:xpack.uptime.alerts.durationAnomaly/uptime/rule/getRuleExecutionKPI", "alerting:xpack.uptime.alerts.durationAnomaly/uptime/rule/getBackfill", "alerting:xpack.uptime.alerts.durationAnomaly/uptime/rule/findBackfill", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/rule/get", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/rule/getRuleState", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/rule/getAlertSummary", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/rule/getExecutionLog", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/rule/getActionErrorLog", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/rule/find", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/rule/getRuleExecutionKPI", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/rule/getBackfill", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/rule/findBackfill", "alerting:xpack.synthetics.alerts.monitorStatus/uptime/rule/get", "alerting:xpack.synthetics.alerts.monitorStatus/uptime/rule/getRuleState", "alerting:xpack.synthetics.alerts.monitorStatus/uptime/rule/getAlertSummary", @@ -9455,6 +14633,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:xpack.synthetics.alerts.monitorStatus/uptime/rule/getRuleExecutionKPI", "alerting:xpack.synthetics.alerts.monitorStatus/uptime/rule/getBackfill", "alerting:xpack.synthetics.alerts.monitorStatus/uptime/rule/findBackfill", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/rule/get", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/rule/getRuleState", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/rule/getAlertSummary", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/rule/getExecutionLog", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/rule/getActionErrorLog", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/rule/find", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/rule/getRuleExecutionKPI", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/rule/getBackfill", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/rule/findBackfill", "alerting:xpack.synthetics.alerts.tls/uptime/rule/get", "alerting:xpack.synthetics.alerts.tls/uptime/rule/getRuleState", "alerting:xpack.synthetics.alerts.tls/uptime/rule/getAlertSummary", @@ -9464,30 +14651,63 @@ export default function ({ getService }: FtrProviderContext) { "alerting:xpack.synthetics.alerts.tls/uptime/rule/getRuleExecutionKPI", "alerting:xpack.synthetics.alerts.tls/uptime/rule/getBackfill", "alerting:xpack.synthetics.alerts.tls/uptime/rule/findBackfill", + "alerting:xpack.synthetics.alerts.tls/alerts/rule/get", + "alerting:xpack.synthetics.alerts.tls/alerts/rule/getRuleState", + "alerting:xpack.synthetics.alerts.tls/alerts/rule/getAlertSummary", + "alerting:xpack.synthetics.alerts.tls/alerts/rule/getExecutionLog", + "alerting:xpack.synthetics.alerts.tls/alerts/rule/getActionErrorLog", + "alerting:xpack.synthetics.alerts.tls/alerts/rule/find", + "alerting:xpack.synthetics.alerts.tls/alerts/rule/getRuleExecutionKPI", + "alerting:xpack.synthetics.alerts.tls/alerts/rule/getBackfill", + "alerting:xpack.synthetics.alerts.tls/alerts/rule/findBackfill", "alerting:xpack.uptime.alerts.tls/uptime/alert/get", "alerting:xpack.uptime.alerts.tls/uptime/alert/find", "alerting:xpack.uptime.alerts.tls/uptime/alert/getAuthorizedAlertsIndices", "alerting:xpack.uptime.alerts.tls/uptime/alert/getAlertSummary", + "alerting:xpack.uptime.alerts.tls/alerts/alert/get", + "alerting:xpack.uptime.alerts.tls/alerts/alert/find", + "alerting:xpack.uptime.alerts.tls/alerts/alert/getAuthorizedAlertsIndices", + "alerting:xpack.uptime.alerts.tls/alerts/alert/getAlertSummary", "alerting:xpack.uptime.alerts.tlsCertificate/uptime/alert/get", "alerting:xpack.uptime.alerts.tlsCertificate/uptime/alert/find", "alerting:xpack.uptime.alerts.tlsCertificate/uptime/alert/getAuthorizedAlertsIndices", "alerting:xpack.uptime.alerts.tlsCertificate/uptime/alert/getAlertSummary", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/alert/get", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/alert/find", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/alert/getAuthorizedAlertsIndices", + "alerting:xpack.uptime.alerts.tlsCertificate/alerts/alert/getAlertSummary", "alerting:xpack.uptime.alerts.monitorStatus/uptime/alert/get", "alerting:xpack.uptime.alerts.monitorStatus/uptime/alert/find", "alerting:xpack.uptime.alerts.monitorStatus/uptime/alert/getAuthorizedAlertsIndices", "alerting:xpack.uptime.alerts.monitorStatus/uptime/alert/getAlertSummary", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/alert/get", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/alert/find", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/alert/getAuthorizedAlertsIndices", + "alerting:xpack.uptime.alerts.monitorStatus/alerts/alert/getAlertSummary", "alerting:xpack.uptime.alerts.durationAnomaly/uptime/alert/get", "alerting:xpack.uptime.alerts.durationAnomaly/uptime/alert/find", "alerting:xpack.uptime.alerts.durationAnomaly/uptime/alert/getAuthorizedAlertsIndices", "alerting:xpack.uptime.alerts.durationAnomaly/uptime/alert/getAlertSummary", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/alert/get", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/alert/find", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/alert/getAuthorizedAlertsIndices", + "alerting:xpack.uptime.alerts.durationAnomaly/alerts/alert/getAlertSummary", "alerting:xpack.synthetics.alerts.monitorStatus/uptime/alert/get", "alerting:xpack.synthetics.alerts.monitorStatus/uptime/alert/find", "alerting:xpack.synthetics.alerts.monitorStatus/uptime/alert/getAuthorizedAlertsIndices", "alerting:xpack.synthetics.alerts.monitorStatus/uptime/alert/getAlertSummary", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/alert/get", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/alert/find", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/alert/getAuthorizedAlertsIndices", + "alerting:xpack.synthetics.alerts.monitorStatus/alerts/alert/getAlertSummary", "alerting:xpack.synthetics.alerts.tls/uptime/alert/get", "alerting:xpack.synthetics.alerts.tls/uptime/alert/find", "alerting:xpack.synthetics.alerts.tls/uptime/alert/getAuthorizedAlertsIndices", "alerting:xpack.synthetics.alerts.tls/uptime/alert/getAlertSummary", + "alerting:xpack.synthetics.alerts.tls/alerts/alert/get", + "alerting:xpack.synthetics.alerts.tls/alerts/alert/find", + "alerting:xpack.synthetics.alerts.tls/alerts/alert/getAuthorizedAlertsIndices", + "alerting:xpack.synthetics.alerts.tls/alerts/alert/getAlertSummary", "app:observability", "ui:catalogue/observability", "ui:navLinks/observability", @@ -9501,6 +14721,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:slo.rules.burnRate/observability/rule/getRuleExecutionKPI", "alerting:slo.rules.burnRate/observability/rule/getBackfill", "alerting:slo.rules.burnRate/observability/rule/findBackfill", + "alerting:slo.rules.burnRate/alerts/rule/get", + "alerting:slo.rules.burnRate/alerts/rule/getRuleState", + "alerting:slo.rules.burnRate/alerts/rule/getAlertSummary", + "alerting:slo.rules.burnRate/alerts/rule/getExecutionLog", + "alerting:slo.rules.burnRate/alerts/rule/getActionErrorLog", + "alerting:slo.rules.burnRate/alerts/rule/find", + "alerting:slo.rules.burnRate/alerts/rule/getRuleExecutionKPI", + "alerting:slo.rules.burnRate/alerts/rule/getBackfill", + "alerting:slo.rules.burnRate/alerts/rule/findBackfill", "alerting:observability.rules.custom_threshold/observability/rule/get", "alerting:observability.rules.custom_threshold/observability/rule/getRuleState", "alerting:observability.rules.custom_threshold/observability/rule/getAlertSummary", @@ -9510,6 +14739,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:observability.rules.custom_threshold/observability/rule/getRuleExecutionKPI", "alerting:observability.rules.custom_threshold/observability/rule/getBackfill", "alerting:observability.rules.custom_threshold/observability/rule/findBackfill", + "alerting:observability.rules.custom_threshold/alerts/rule/get", + "alerting:observability.rules.custom_threshold/alerts/rule/getRuleState", + "alerting:observability.rules.custom_threshold/alerts/rule/getAlertSummary", + "alerting:observability.rules.custom_threshold/alerts/rule/getExecutionLog", + "alerting:observability.rules.custom_threshold/alerts/rule/getActionErrorLog", + "alerting:observability.rules.custom_threshold/alerts/rule/find", + "alerting:observability.rules.custom_threshold/alerts/rule/getRuleExecutionKPI", + "alerting:observability.rules.custom_threshold/alerts/rule/getBackfill", + "alerting:observability.rules.custom_threshold/alerts/rule/findBackfill", "alerting:.es-query/observability/rule/get", "alerting:.es-query/observability/rule/getRuleState", "alerting:.es-query/observability/rule/getAlertSummary", @@ -9519,6 +14757,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:.es-query/observability/rule/getRuleExecutionKPI", "alerting:.es-query/observability/rule/getBackfill", "alerting:.es-query/observability/rule/findBackfill", + "alerting:.es-query/alerts/rule/get", + "alerting:.es-query/alerts/rule/getRuleState", + "alerting:.es-query/alerts/rule/getAlertSummary", + "alerting:.es-query/alerts/rule/getExecutionLog", + "alerting:.es-query/alerts/rule/getActionErrorLog", + "alerting:.es-query/alerts/rule/find", + "alerting:.es-query/alerts/rule/getRuleExecutionKPI", + "alerting:.es-query/alerts/rule/getBackfill", + "alerting:.es-query/alerts/rule/findBackfill", "alerting:xpack.ml.anomaly_detection_alert/observability/rule/get", "alerting:xpack.ml.anomaly_detection_alert/observability/rule/getRuleState", "alerting:xpack.ml.anomaly_detection_alert/observability/rule/getAlertSummary", @@ -9528,6 +14775,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:xpack.ml.anomaly_detection_alert/observability/rule/getRuleExecutionKPI", "alerting:xpack.ml.anomaly_detection_alert/observability/rule/getBackfill", "alerting:xpack.ml.anomaly_detection_alert/observability/rule/findBackfill", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/get", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getRuleState", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getAlertSummary", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getExecutionLog", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getActionErrorLog", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/find", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getRuleExecutionKPI", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/getBackfill", + "alerting:xpack.ml.anomaly_detection_alert/alerts/rule/findBackfill", "alerting:metrics.alert.inventory.threshold/observability/rule/get", "alerting:metrics.alert.inventory.threshold/observability/rule/getRuleState", "alerting:metrics.alert.inventory.threshold/observability/rule/getAlertSummary", @@ -9537,6 +14793,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:metrics.alert.inventory.threshold/observability/rule/getRuleExecutionKPI", "alerting:metrics.alert.inventory.threshold/observability/rule/getBackfill", "alerting:metrics.alert.inventory.threshold/observability/rule/findBackfill", + "alerting:metrics.alert.inventory.threshold/alerts/rule/get", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getRuleState", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getAlertSummary", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getExecutionLog", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getActionErrorLog", + "alerting:metrics.alert.inventory.threshold/alerts/rule/find", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getRuleExecutionKPI", + "alerting:metrics.alert.inventory.threshold/alerts/rule/getBackfill", + "alerting:metrics.alert.inventory.threshold/alerts/rule/findBackfill", "alerting:apm.error_rate/observability/rule/get", "alerting:apm.error_rate/observability/rule/getRuleState", "alerting:apm.error_rate/observability/rule/getAlertSummary", @@ -9546,6 +14811,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.error_rate/observability/rule/getRuleExecutionKPI", "alerting:apm.error_rate/observability/rule/getBackfill", "alerting:apm.error_rate/observability/rule/findBackfill", + "alerting:apm.error_rate/alerts/rule/get", + "alerting:apm.error_rate/alerts/rule/getRuleState", + "alerting:apm.error_rate/alerts/rule/getAlertSummary", + "alerting:apm.error_rate/alerts/rule/getExecutionLog", + "alerting:apm.error_rate/alerts/rule/getActionErrorLog", + "alerting:apm.error_rate/alerts/rule/find", + "alerting:apm.error_rate/alerts/rule/getRuleExecutionKPI", + "alerting:apm.error_rate/alerts/rule/getBackfill", + "alerting:apm.error_rate/alerts/rule/findBackfill", "alerting:apm.transaction_error_rate/observability/rule/get", "alerting:apm.transaction_error_rate/observability/rule/getRuleState", "alerting:apm.transaction_error_rate/observability/rule/getAlertSummary", @@ -9555,6 +14829,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.transaction_error_rate/observability/rule/getRuleExecutionKPI", "alerting:apm.transaction_error_rate/observability/rule/getBackfill", "alerting:apm.transaction_error_rate/observability/rule/findBackfill", + "alerting:apm.transaction_error_rate/alerts/rule/get", + "alerting:apm.transaction_error_rate/alerts/rule/getRuleState", + "alerting:apm.transaction_error_rate/alerts/rule/getAlertSummary", + "alerting:apm.transaction_error_rate/alerts/rule/getExecutionLog", + "alerting:apm.transaction_error_rate/alerts/rule/getActionErrorLog", + "alerting:apm.transaction_error_rate/alerts/rule/find", + "alerting:apm.transaction_error_rate/alerts/rule/getRuleExecutionKPI", + "alerting:apm.transaction_error_rate/alerts/rule/getBackfill", + "alerting:apm.transaction_error_rate/alerts/rule/findBackfill", "alerting:apm.transaction_duration/observability/rule/get", "alerting:apm.transaction_duration/observability/rule/getRuleState", "alerting:apm.transaction_duration/observability/rule/getAlertSummary", @@ -9564,6 +14847,15 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.transaction_duration/observability/rule/getRuleExecutionKPI", "alerting:apm.transaction_duration/observability/rule/getBackfill", "alerting:apm.transaction_duration/observability/rule/findBackfill", + "alerting:apm.transaction_duration/alerts/rule/get", + "alerting:apm.transaction_duration/alerts/rule/getRuleState", + "alerting:apm.transaction_duration/alerts/rule/getAlertSummary", + "alerting:apm.transaction_duration/alerts/rule/getExecutionLog", + "alerting:apm.transaction_duration/alerts/rule/getActionErrorLog", + "alerting:apm.transaction_duration/alerts/rule/find", + "alerting:apm.transaction_duration/alerts/rule/getRuleExecutionKPI", + "alerting:apm.transaction_duration/alerts/rule/getBackfill", + "alerting:apm.transaction_duration/alerts/rule/findBackfill", "alerting:apm.anomaly/observability/rule/get", "alerting:apm.anomaly/observability/rule/getRuleState", "alerting:apm.anomaly/observability/rule/getAlertSummary", @@ -9573,42 +14865,87 @@ export default function ({ getService }: FtrProviderContext) { "alerting:apm.anomaly/observability/rule/getRuleExecutionKPI", "alerting:apm.anomaly/observability/rule/getBackfill", "alerting:apm.anomaly/observability/rule/findBackfill", + "alerting:apm.anomaly/alerts/rule/get", + "alerting:apm.anomaly/alerts/rule/getRuleState", + "alerting:apm.anomaly/alerts/rule/getAlertSummary", + "alerting:apm.anomaly/alerts/rule/getExecutionLog", + "alerting:apm.anomaly/alerts/rule/getActionErrorLog", + "alerting:apm.anomaly/alerts/rule/find", + "alerting:apm.anomaly/alerts/rule/getRuleExecutionKPI", + "alerting:apm.anomaly/alerts/rule/getBackfill", + "alerting:apm.anomaly/alerts/rule/findBackfill", "alerting:slo.rules.burnRate/observability/alert/get", "alerting:slo.rules.burnRate/observability/alert/find", "alerting:slo.rules.burnRate/observability/alert/getAuthorizedAlertsIndices", "alerting:slo.rules.burnRate/observability/alert/getAlertSummary", + "alerting:slo.rules.burnRate/alerts/alert/get", + "alerting:slo.rules.burnRate/alerts/alert/find", + "alerting:slo.rules.burnRate/alerts/alert/getAuthorizedAlertsIndices", + "alerting:slo.rules.burnRate/alerts/alert/getAlertSummary", "alerting:observability.rules.custom_threshold/observability/alert/get", "alerting:observability.rules.custom_threshold/observability/alert/find", "alerting:observability.rules.custom_threshold/observability/alert/getAuthorizedAlertsIndices", "alerting:observability.rules.custom_threshold/observability/alert/getAlertSummary", + "alerting:observability.rules.custom_threshold/alerts/alert/get", + "alerting:observability.rules.custom_threshold/alerts/alert/find", + "alerting:observability.rules.custom_threshold/alerts/alert/getAuthorizedAlertsIndices", + "alerting:observability.rules.custom_threshold/alerts/alert/getAlertSummary", "alerting:.es-query/observability/alert/get", "alerting:.es-query/observability/alert/find", "alerting:.es-query/observability/alert/getAuthorizedAlertsIndices", "alerting:.es-query/observability/alert/getAlertSummary", + "alerting:.es-query/alerts/alert/get", + "alerting:.es-query/alerts/alert/find", + "alerting:.es-query/alerts/alert/getAuthorizedAlertsIndices", + "alerting:.es-query/alerts/alert/getAlertSummary", "alerting:xpack.ml.anomaly_detection_alert/observability/alert/get", "alerting:xpack.ml.anomaly_detection_alert/observability/alert/find", "alerting:xpack.ml.anomaly_detection_alert/observability/alert/getAuthorizedAlertsIndices", "alerting:xpack.ml.anomaly_detection_alert/observability/alert/getAlertSummary", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/get", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/find", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/getAuthorizedAlertsIndices", + "alerting:xpack.ml.anomaly_detection_alert/alerts/alert/getAlertSummary", "alerting:metrics.alert.inventory.threshold/observability/alert/get", "alerting:metrics.alert.inventory.threshold/observability/alert/find", "alerting:metrics.alert.inventory.threshold/observability/alert/getAuthorizedAlertsIndices", "alerting:metrics.alert.inventory.threshold/observability/alert/getAlertSummary", + "alerting:metrics.alert.inventory.threshold/alerts/alert/get", + "alerting:metrics.alert.inventory.threshold/alerts/alert/find", + "alerting:metrics.alert.inventory.threshold/alerts/alert/getAuthorizedAlertsIndices", + "alerting:metrics.alert.inventory.threshold/alerts/alert/getAlertSummary", "alerting:apm.error_rate/observability/alert/get", "alerting:apm.error_rate/observability/alert/find", "alerting:apm.error_rate/observability/alert/getAuthorizedAlertsIndices", "alerting:apm.error_rate/observability/alert/getAlertSummary", + "alerting:apm.error_rate/alerts/alert/get", + "alerting:apm.error_rate/alerts/alert/find", + "alerting:apm.error_rate/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.error_rate/alerts/alert/getAlertSummary", "alerting:apm.transaction_error_rate/observability/alert/get", "alerting:apm.transaction_error_rate/observability/alert/find", "alerting:apm.transaction_error_rate/observability/alert/getAuthorizedAlertsIndices", "alerting:apm.transaction_error_rate/observability/alert/getAlertSummary", + "alerting:apm.transaction_error_rate/alerts/alert/get", + "alerting:apm.transaction_error_rate/alerts/alert/find", + "alerting:apm.transaction_error_rate/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.transaction_error_rate/alerts/alert/getAlertSummary", "alerting:apm.transaction_duration/observability/alert/get", "alerting:apm.transaction_duration/observability/alert/find", "alerting:apm.transaction_duration/observability/alert/getAuthorizedAlertsIndices", "alerting:apm.transaction_duration/observability/alert/getAlertSummary", + "alerting:apm.transaction_duration/alerts/alert/get", + "alerting:apm.transaction_duration/alerts/alert/find", + "alerting:apm.transaction_duration/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.transaction_duration/alerts/alert/getAlertSummary", "alerting:apm.anomaly/observability/alert/get", "alerting:apm.anomaly/observability/alert/find", "alerting:apm.anomaly/observability/alert/getAuthorizedAlertsIndices", "alerting:apm.anomaly/observability/alert/getAlertSummary", + "alerting:apm.anomaly/alerts/alert/get", + "alerting:apm.anomaly/alerts/alert/find", + "alerting:apm.anomaly/alerts/alert/getAuthorizedAlertsIndices", + "alerting:apm.anomaly/alerts/alert/getAlertSummary", ], }, } From 14cd87916468b6638e5a450e4f0c26843ccff1a5 Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Sat, 20 Jul 2024 21:53:38 +0300 Subject: [PATCH 029/106] Fix more integration tests and types --- x-pack/plugins/stack_alerts/server/types.ts | 4 ++-- .../group2/tests/alerting/mute_instance.ts | 13 +------------ .../group3/tests/alerting/bulk_edit.ts | 6 +----- .../group4/tests/alerting/snooze.ts | 13 +------------ 4 files changed, 5 insertions(+), 31 deletions(-) diff --git a/x-pack/plugins/stack_alerts/server/types.ts b/x-pack/plugins/stack_alerts/server/types.ts index ce148fb8c0434c..0f9b9e4127a7c5 100644 --- a/x-pack/plugins/stack_alerts/server/types.ts +++ b/x-pack/plugins/stack_alerts/server/types.ts @@ -6,7 +6,7 @@ */ import { PluginStartContract as TriggersActionsUiStartContract } from '@kbn/triggers-actions-ui-plugin/server'; -import { PluginSetupContract as AlertingSetup } from '@kbn/alerting-plugin/server'; +import { AlertingServerSetup } from '@kbn/alerting-plugin/server'; export type { PluginSetupContract as AlertingSetup, @@ -19,7 +19,7 @@ import { FeaturesPluginSetup } from '@kbn/features-plugin/server'; // this plugin's dependendencies export interface StackAlertsDeps { - alerting: AlertingSetup; + alerting: AlertingServerSetup; features: FeaturesPluginSetup; } diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/mute_instance.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/mute_instance.ts index b7cdf762836fef..1e3d99f5dd6a80 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/mute_instance.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/mute_instance.ts @@ -239,24 +239,13 @@ export default function createMuteAlertInstanceTests({ getService }: FtrProvider switch (scenario.id) { case 'no_kibana_privileges at space1': case 'space_1_all at space2': - expect(response.statusCode).to.eql(403); - expect(response.body).to.eql({ - error: 'Forbidden', - message: getUnauthorizedErrorMessage('muteAlert', 'test.restricted-noop', 'alerts'), - statusCode: 403, - }); - break; case 'global_read at space1': case 'space_1_all at space1': case 'space_1_all_alerts_none_actions at space1': expect(response.statusCode).to.eql(403); expect(response.body).to.eql({ error: 'Forbidden', - message: getUnauthorizedErrorMessage( - 'muteAlert', - 'test.restricted-noop', - 'alertsRestrictedFixture' - ), + message: getUnauthorizedErrorMessage('muteAlert', 'test.restricted-noop', 'alerts'), statusCode: 403, }); break; diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/alerting/bulk_edit.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/alerting/bulk_edit.ts index 1082a6741ec0dd..c0835b91e209ea 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/alerting/bulk_edit.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/alerting/bulk_edit.ts @@ -388,11 +388,7 @@ export default function createUpdateTests({ getService }: FtrProviderContext) { case 'global_read at space1': expect(response.body).to.eql({ error: 'Forbidden', - message: getUnauthorizedErrorMessage( - 'bulkEdit', - 'test.restricted-noop', - 'alertsRestrictedFixture' - ), + message: getUnauthorizedErrorMessage('bulkEdit', 'test.restricted-noop', 'alerts'), statusCode: 403, }); expect(response.statusCode).to.eql(403); diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group4/tests/alerting/snooze.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group4/tests/alerting/snooze.ts index 8c1fed7978b552..c880b18dd4b46d 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group4/tests/alerting/snooze.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group4/tests/alerting/snooze.ts @@ -269,24 +269,13 @@ export default function createSnoozeRuleTests({ getService }: FtrProviderContext switch (scenario.id) { case 'no_kibana_privileges at space1': case 'space_1_all at space2': - expect(response.statusCode).to.eql(403); - expect(response.body).to.eql({ - error: 'Forbidden', - message: getUnauthorizedErrorMessage('snooze', 'test.restricted-noop', 'alerts'), - statusCode: 403, - }); - break; case 'global_read at space1': case 'space_1_all at space1': case 'space_1_all_alerts_none_actions at space1': expect(response.statusCode).to.eql(403); expect(response.body).to.eql({ error: 'Forbidden', - message: getUnauthorizedErrorMessage( - 'snooze', - 'test.restricted-noop', - 'alertsRestrictedFixture' - ), + message: getUnauthorizedErrorMessage('snooze', 'test.restricted-noop', 'alerts'), statusCode: 403, }); break; From 9a4ddc05e3fe816d1f7dc2a890e82d5ded0d00c6 Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Sun, 21 Jul 2024 19:01:23 +0300 Subject: [PATCH 030/106] Fix alerting integration tests --- .../plugins/stack_alerts/server/rule_types/types.ts | 4 ++-- x-pack/plugins/stack_alerts/server/types.ts | 5 ++--- .../group1/tests/alerting/delete.ts | 2 +- .../group1/tests/alerting/disable.ts | 9 +-------- .../group1/tests/alerting/enable.ts | 9 +-------- .../group1/tests/alerting/get.ts | 13 +------------ .../group2/tests/alerting/unmute_all.ts | 6 +++--- .../group2/tests/alerting/unmute_instance.ts | 13 +------------ .../group2/tests/alerting/update.ts | 13 +------------ .../group2/tests/alerting/update_api_key.ts | 13 +------------ .../group3/tests/alerting/bulk_delete.ts | 2 +- .../group3/tests/alerting/bulk_disable.ts | 2 +- .../group3/tests/alerting/bulk_enable.ts | 2 +- .../group4/tests/alerting/unsnooze.ts | 6 +----- 14 files changed, 18 insertions(+), 81 deletions(-) diff --git a/x-pack/plugins/stack_alerts/server/rule_types/types.ts b/x-pack/plugins/stack_alerts/server/rule_types/types.ts index e06553233e774c..876a3c472e3adc 100644 --- a/x-pack/plugins/stack_alerts/server/rule_types/types.ts +++ b/x-pack/plugins/stack_alerts/server/rule_types/types.ts @@ -7,12 +7,12 @@ import { StackAlert } from '@kbn/alerts-as-data-utils'; import { CoreSetup, Logger } from '@kbn/core/server'; -import { AlertingSetup, StackAlertsStartDeps } from '../types'; +import { AlertingServerSetup, StackAlertsStartDeps } from '../types'; export interface RegisterRuleTypesParams { logger: Logger; data: Promise; - alerting: AlertingSetup; + alerting: AlertingServerSetup; core: CoreSetup; } diff --git a/x-pack/plugins/stack_alerts/server/types.ts b/x-pack/plugins/stack_alerts/server/types.ts index 0f9b9e4127a7c5..1f4d2d29148679 100644 --- a/x-pack/plugins/stack_alerts/server/types.ts +++ b/x-pack/plugins/stack_alerts/server/types.ts @@ -6,16 +6,15 @@ */ import { PluginStartContract as TriggersActionsUiStartContract } from '@kbn/triggers-actions-ui-plugin/server'; -import { AlertingServerSetup } from '@kbn/alerting-plugin/server'; - export type { - PluginSetupContract as AlertingSetup, RuleType, RuleParamsAndRefs, RuleExecutorOptions, RuleTypeParams, + AlertingServerSetup, } from '@kbn/alerting-plugin/server'; import { FeaturesPluginSetup } from '@kbn/features-plugin/server'; +import { AlertingServerSetup } from '@kbn/alerting-plugin/server'; // this plugin's dependendencies export interface StackAlertsDeps { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/delete.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/delete.ts index d6cb57261a5580..6814ed46c42b39 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/delete.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/delete.ts @@ -219,7 +219,7 @@ export default function createDeleteTests({ getService }: FtrProviderContext) { expect(response.statusCode).to.eql(403); expect(response.body).to.eql({ error: 'Forbidden', - message: getUnauthorizedErrorMessage('delete', 'test.noop', 'alertsFixture'), + message: getUnauthorizedErrorMessage('delete', 'test.noop', 'alerts'), statusCode: 403, }); objectRemover.add(space.id, createdAlert.id, 'rule', 'alerting'); diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/disable.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/disable.ts index 264df417440f32..aa43d52d60ad42 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/disable.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/disable.ts @@ -255,18 +255,11 @@ export default function createDisableAlertTests({ getService }: FtrProviderConte switch (scenario.id) { case 'no_kibana_privileges at space1': case 'space_1_all at space2': - expect(response.statusCode).to.eql(403); - expect(response.body).to.eql({ - error: 'Forbidden', - message: getUnauthorizedErrorMessage('disable', 'test.noop', 'alerts'), - statusCode: 403, - }); - break; case 'global_read at space1': expect(response.statusCode).to.eql(403); expect(response.body).to.eql({ error: 'Forbidden', - message: getUnauthorizedErrorMessage('disable', 'test.noop', 'alertsFixture'), + message: getUnauthorizedErrorMessage('disable', 'test.noop', 'alerts'), statusCode: 403, }); break; diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/enable.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/enable.ts index 581f6f13a63b75..eef6ff320a8287 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/enable.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/enable.ts @@ -246,18 +246,11 @@ export default function createEnableAlertTests({ getService }: FtrProviderContex switch (scenario.id) { case 'no_kibana_privileges at space1': case 'space_1_all at space2': - expect(response.statusCode).to.eql(403); - expect(response.body).to.eql({ - error: 'Forbidden', - message: getUnauthorizedErrorMessage('enable', 'test.noop', 'alerts'), - statusCode: 403, - }); - break; case 'global_read at space1': expect(response.statusCode).to.eql(403); expect(response.body).to.eql({ error: 'Forbidden', - message: getUnauthorizedErrorMessage('enable', 'test.noop', 'alertsFixture'), + message: getUnauthorizedErrorMessage('enable', 'test.noop', 'alerts'), statusCode: 403, }); break; diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/get.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/get.ts index fa362249229e34..69357e150d3ce4 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/get.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/get.ts @@ -222,23 +222,12 @@ const getTestUtils = ( switch (scenario.id) { case 'no_kibana_privileges at space1': case 'space_1_all at space2': - expect(response.statusCode).to.eql(403); - expect(response.body).to.eql({ - error: 'Forbidden', - message: getUnauthorizedErrorMessage('get', 'test.restricted-noop', 'alerts'), - statusCode: 403, - }); - break; case 'space_1_all at space1': case 'space_1_all_alerts_none_actions at space1': expect(response.statusCode).to.eql(403); expect(response.body).to.eql({ error: 'Forbidden', - message: getUnauthorizedErrorMessage( - 'get', - 'test.restricted-noop', - 'alertsRestrictedFixture' - ), + message: getUnauthorizedErrorMessage('get', 'test.restricted-noop', 'alerts'), statusCode: 403, }); break; diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/unmute_all.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/unmute_all.ts index d038108d29f67d..6c7f56b75eec62 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/unmute_all.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/unmute_all.ts @@ -259,6 +259,9 @@ export default function createUnmuteAlertTests({ getService }: FtrProviderContex switch (scenario.id) { case 'no_kibana_privileges at space1': case 'space_1_all at space2': + case 'global_read at space1': + case 'space_1_all at space1': + case 'space_1_all_alerts_none_actions at space1': expect(response.statusCode).to.eql(403); expect(response.body).to.eql({ error: 'Forbidden', @@ -266,9 +269,6 @@ export default function createUnmuteAlertTests({ getService }: FtrProviderContex statusCode: 403, }); break; - case 'global_read at space1': - case 'space_1_all at space1': - case 'space_1_all_alerts_none_actions at space1': expect(response.statusCode).to.eql(403); expect(response.body).to.eql({ error: 'Forbidden', diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/unmute_instance.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/unmute_instance.ts index 97add81c6d5b8e..a569b834fb82ad 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/unmute_instance.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/unmute_instance.ts @@ -259,17 +259,6 @@ export default function createMuteAlertInstanceTests({ getService }: FtrProvider switch (scenario.id) { case 'no_kibana_privileges at space1': case 'space_1_all at space2': - expect(response.statusCode).to.eql(403); - expect(response.body).to.eql({ - error: 'Forbidden', - message: getUnauthorizedErrorMessage( - 'unmuteAlert', - 'test.restricted-noop', - 'alerts' - ), - statusCode: 403, - }); - break; case 'global_read at space1': case 'space_1_all at space1': case 'space_1_all_alerts_none_actions at space1': @@ -279,7 +268,7 @@ export default function createMuteAlertInstanceTests({ getService }: FtrProvider message: getUnauthorizedErrorMessage( 'unmuteAlert', 'test.restricted-noop', - 'alertsRestrictedFixture' + 'alerts' ), statusCode: 403, }); diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/update.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/update.ts index 8b9d4929d56659..749e04e2774fde 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/update.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/update.ts @@ -381,24 +381,13 @@ export default function createUpdateTests({ getService }: FtrProviderContext) { switch (scenario.id) { case 'no_kibana_privileges at space1': case 'space_1_all at space2': - expect(response.statusCode).to.eql(403); - expect(response.body).to.eql({ - error: 'Forbidden', - message: getUnauthorizedErrorMessage('update', 'test.restricted-noop', 'alerts'), - statusCode: 403, - }); - break; case 'global_read at space1': case 'space_1_all at space1': case 'space_1_all_alerts_none_actions at space1': expect(response.statusCode).to.eql(403); expect(response.body).to.eql({ error: 'Forbidden', - message: getUnauthorizedErrorMessage( - 'update', - 'test.restricted-noop', - 'alertsRestrictedFixture' - ), + message: getUnauthorizedErrorMessage('update', 'test.restricted-noop', 'alerts'), statusCode: 403, }); break; diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/update_api_key.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/update_api_key.ts index 3df05706501463..b92e423cd6829c 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/update_api_key.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/update_api_key.ts @@ -238,17 +238,6 @@ export default function createUpdateApiKeyTests({ getService }: FtrProviderConte switch (scenario.id) { case 'no_kibana_privileges at space1': case 'space_1_all at space2': - expect(response.statusCode).to.eql(403); - expect(response.body).to.eql({ - error: 'Forbidden', - message: getUnauthorizedErrorMessage( - 'updateApiKey', - 'test.restricted-noop', - 'alerts' - ), - statusCode: 403, - }); - break; case 'global_read at space1': case 'space_1_all at space1': case 'space_1_all_alerts_none_actions at space1': @@ -258,7 +247,7 @@ export default function createUpdateApiKeyTests({ getService }: FtrProviderConte message: getUnauthorizedErrorMessage( 'updateApiKey', 'test.restricted-noop', - 'alertsRestrictedFixture' + 'alerts' ), statusCode: 403, }); diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/alerting/bulk_delete.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/alerting/bulk_delete.ts index fc3526eebc6a44..2306e227e7584f 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/alerting/bulk_delete.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/alerting/bulk_delete.ts @@ -348,7 +348,7 @@ export default ({ getService }: FtrProviderContext) => { case 'global_read at space1': expect(response.body).to.eql({ error: 'Forbidden', - message: getUnauthorizedErrorMessage('bulkDelete', 'test.noop', 'alertsFixture'), + message: getUnauthorizedErrorMessage('bulkDelete', 'test.noop', 'alerts'), statusCode: 403, }); expect(response.statusCode).to.eql(403); diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/alerting/bulk_disable.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/alerting/bulk_disable.ts index d69055a92e1f4f..bd448c06456197 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/alerting/bulk_disable.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/alerting/bulk_disable.ts @@ -277,7 +277,7 @@ export default ({ getService }: FtrProviderContext) => { case 'global_read at space1': expect(response.body).to.eql({ error: 'Forbidden', - message: getUnauthorizedErrorMessage('bulkDisable', 'test.noop', 'alertsFixture'), + message: getUnauthorizedErrorMessage('bulkDisable', 'test.noop', 'alerts'), statusCode: 403, }); expect(response.statusCode).to.eql(403); diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/alerting/bulk_enable.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/alerting/bulk_enable.ts index 4464535dbcd4d1..5229091135ef03 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/alerting/bulk_enable.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/alerting/bulk_enable.ts @@ -266,7 +266,7 @@ export default ({ getService }: FtrProviderContext) => { case 'global_read at space1': expect(response.body).to.eql({ error: 'Forbidden', - message: getUnauthorizedErrorMessage('bulkEnable', 'test.noop', 'alertsFixture'), + message: getUnauthorizedErrorMessage('bulkEnable', 'test.noop', 'alerts'), statusCode: 403, }); expect(response.statusCode).to.eql(403); diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group4/tests/alerting/unsnooze.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group4/tests/alerting/unsnooze.ts index eae8814a514fb5..8f509e6104c3d9 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group4/tests/alerting/unsnooze.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group4/tests/alerting/unsnooze.ts @@ -254,11 +254,7 @@ export default function createUnsnoozeRuleTests({ getService }: FtrProviderConte expect(response.statusCode).to.eql(403); expect(response.body).to.eql({ error: 'Forbidden', - message: getUnauthorizedErrorMessage( - 'unsnooze', - 'test.restricted-noop', - 'alertsRestrictedFixture' - ), + message: getUnauthorizedErrorMessage('unsnooze', 'test.restricted-noop', 'alerts'), statusCode: 403, }); break; From 9c6d2cc899a78c1ff500f47ce85ce3d00911a386 Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Mon, 22 Jul 2024 09:47:03 +0300 Subject: [PATCH 031/106] Fix infra e2e tests --- .../infra/public/components/shared/alerts/constants.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/observability_solution/infra/public/components/shared/alerts/constants.ts b/x-pack/plugins/observability_solution/infra/public/components/shared/alerts/constants.ts index 1719a58af61ef2..21251748ca77ec 100644 --- a/x-pack/plugins/observability_solution/infra/public/components/shared/alerts/constants.ts +++ b/x-pack/plugins/observability_solution/infra/public/components/shared/alerts/constants.ts @@ -89,4 +89,7 @@ export const ALERTS_PER_PAGE = 10; export const ALERTS_TABLE_ID = 'xpack.infra.hosts.alerts.table'; export const INFRA_ALERT_FEATURE_ID = 'infrastructure'; -export const infraAlertFeatureIds: ValidFeatureId[] = [AlertConsumers.INFRASTRUCTURE]; +export const infraAlertFeatureIds: ValidFeatureId[] = [ + AlertConsumers.INFRASTRUCTURE, + AlertConsumers.ALERTS, +]; From 85ccea0e6788e75d572fcb205765a4032f6f65ad Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Mon, 22 Jul 2024 10:11:33 +0300 Subject: [PATCH 032/106] Fix triggers_actions_ui tests --- .../apps/triggers_actions_ui/home_page.ts | 48 ++++++++++++------- .../plugins/alerts/server/plugin.ts | 31 ++++++++---- 2 files changed, 53 insertions(+), 26 deletions(-) diff --git a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/home_page.ts b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/home_page.ts index 77ece6d043a595..7101f67c349105 100644 --- a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/home_page.ts +++ b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/home_page.ts @@ -60,14 +60,42 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { }); it('Loads the Alerts page', async () => { - await log.debug('Checking for section heading to say Rules.'); + log.debug('Checking for section heading to say Rules.'); const headingText = await pageObjects.triggersActionsUI.getSectionHeadingText(); expect(headingText).to.be('Rules'); }); describe('Alerts tab', () => { + let createdRule: { name: string; id: string }; + + before(async () => { + const { body: createdAction } = await supertest + .post(`/api/actions/connector`) + .set('kbn-xsrf', 'foo') + .send(getTestActionData()) + .expect(200); + + objectRemover.add(createdAction.id, 'action', 'actions'); + + const resRule = await supertest + .post(`/api/alerting/rule`) + .set('kbn-xsrf', 'foo') + .send(getTestAlertData()) + .expect(200); + + createdRule = resRule.body; + objectRemover.add(resRule.body.id, 'alert', 'alerts'); + }); + + after(async () => { + await objectRemover.removeAll(); + }); + it('renders the alerts tab', async () => { + // refresh to see alert + await browser.refresh(); + // Navigate to the alerts tab await pageObjects.triggersActionsUI.changeTabs('rulesTab'); @@ -82,20 +110,6 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { }); it('navigates to an alert details page', async () => { - const { body: createdAction } = await supertest - .post(`/api/actions/connector`) - .set('kbn-xsrf', 'foo') - .send(getTestActionData()) - .expect(200); - objectRemover.add(createdAction.id, 'action', 'actions'); - - const { body: createdAlert } = await supertest - .post(`/api/alerting/rule`) - .set('kbn-xsrf', 'foo') - .send(getTestAlertData()) - .expect(200); - objectRemover.add(createdAlert.id, 'alert', 'alerts'); - // refresh to see alert await browser.refresh(); @@ -105,10 +119,10 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await testSubjects.existOrFail('rulesList'); // click on first alert - await pageObjects.triggersActionsUI.clickOnAlertInAlertsList(createdAlert.name); + await pageObjects.triggersActionsUI.clickOnAlertInAlertsList(createdRule.name); // Verify url - expect(await browser.getCurrentUrl()).to.contain(`/rule/${createdAlert.id}`); + expect(await browser.getCurrentUrl()).to.contain(`/rule/${createdRule.id}`); }); }); }); diff --git a/x-pack/test/functional_with_es_ssl/plugins/alerts/server/plugin.ts b/x-pack/test/functional_with_es_ssl/plugins/alerts/server/plugin.ts index 68e5c492cc983d..2de42cc70c1f3f 100644 --- a/x-pack/test/functional_with_es_ssl/plugins/alerts/server/plugin.ts +++ b/x-pack/test/functional_with_es_ssl/plugins/alerts/server/plugin.ts @@ -8,6 +8,7 @@ import { Plugin, CoreSetup } from '@kbn/core/server'; import { AlertingServerSetup, RuleType, RuleTypeParams } from '@kbn/alerting-plugin/server'; import { FeaturesPluginSetup } from '@kbn/features-plugin/server'; +import { ALERTING_FEATURE_ID } from '@kbn/alerting-plugin/common'; // this plugin's dependendencies export interface AlertingExampleDeps { @@ -113,18 +114,24 @@ export class AlertingFixturePlugin implements Plugin Date: Mon, 22 Jul 2024 23:24:01 +0300 Subject: [PATCH 033/106] Fix types --- .../lib/setup/collection/get_collection_status.test.ts | 2 +- .../apm/server/routes/alerts/register_apm_rule_types.ts | 7 ++----- .../apm/server/routes/alerts/test_utils/index.ts | 4 ++-- .../infra/server/lib/adapters/framework/adapter_types.ts | 4 ++-- .../log_threshold/register_log_threshold_rule_type.ts | 7 +++++-- .../register_metric_threshold_rule_type.ts | 7 +++++-- .../infra/server/lib/alerting/register_rule_types.ts | 4 ++-- .../infra/server/services/rules/types.ts | 4 ++-- .../server/lib/adapters/framework/adapter_types.ts | 4 ++-- .../server/lib/rules/register_rule_types.ts | 4 ++-- .../observability_ai_assistant_app/server/types.ts | 9 +++------ .../slo/server/lib/rules/register_burn_rate_rule.ts | 4 ++-- .../plugins/observability_solution/slo/server/plugin.ts | 6 +++--- .../alert_rules/status_rule/monitor_status_rule.ts | 4 ++-- 14 files changed, 35 insertions(+), 35 deletions(-) diff --git a/x-pack/plugins/monitoring/server/lib/setup/collection/get_collection_status.test.ts b/x-pack/plugins/monitoring/server/lib/setup/collection/get_collection_status.test.ts index e7ffe701fbd1ae..356cc84b616cd7 100644 --- a/x-pack/plugins/monitoring/server/lib/setup/collection/get_collection_status.test.ts +++ b/x-pack/plugins/monitoring/server/lib/setup/collection/get_collection_status.test.ts @@ -96,7 +96,7 @@ const mockReq = ( headers: {}, getKibanaStatsCollector: () => null, getUiSettingsService: () => null, - getActionTypeRegistry: () => null, + getActionTypeRegistry: () => [], getRulesClient: () => null, getActionsClient: () => null, }; diff --git a/x-pack/plugins/observability_solution/apm/server/routes/alerts/register_apm_rule_types.ts b/x-pack/plugins/observability_solution/apm/server/routes/alerts/register_apm_rule_types.ts index 4c57ef4a10e1d2..ea653b47145a2a 100644 --- a/x-pack/plugins/observability_solution/apm/server/routes/alerts/register_apm_rule_types.ts +++ b/x-pack/plugins/observability_solution/apm/server/routes/alerts/register_apm_rule_types.ts @@ -8,10 +8,7 @@ import type { AlertsLocatorParams } from '@kbn/observability-plugin/common'; import { LocatorPublic } from '@kbn/share-plugin/common'; import { IBasePath, Logger, SavedObjectsClientContract } from '@kbn/core/server'; -import { - PluginSetupContract as AlertingPluginSetupContract, - type IRuleTypeAlerts, -} from '@kbn/alerting-plugin/server'; +import type { AlertingServerSetup, IRuleTypeAlerts } from '@kbn/alerting-plugin/server'; import { ObservabilityPluginSetup } from '@kbn/observability-plugin/server'; import { IRuleDataClient } from '@kbn/rule-registry-plugin/server'; import { MlPluginSetup } from '@kbn/ml-plugin/server'; @@ -100,7 +97,7 @@ export const ApmRuleTypeAlertDefinition: IRuleTypeAlerts }; export interface RegisterRuleDependencies { - alerting: AlertingPluginSetupContract; + alerting: AlertingServerSetup; basePath: IBasePath; getApmIndices: (soClient: SavedObjectsClientContract) => Promise; apmConfig: APMConfig; diff --git a/x-pack/plugins/observability_solution/apm/server/routes/alerts/test_utils/index.ts b/x-pack/plugins/observability_solution/apm/server/routes/alerts/test_utils/index.ts index 1f8ddeaff4620a..245f30e13d2b2f 100644 --- a/x-pack/plugins/observability_solution/apm/server/routes/alerts/test_utils/index.ts +++ b/x-pack/plugins/observability_solution/apm/server/routes/alerts/test_utils/index.ts @@ -11,7 +11,7 @@ import type { AlertsLocatorParams } from '@kbn/observability-plugin/common'; import { LocatorPublic } from '@kbn/share-plugin/common'; import { IRuleDataClient } from '@kbn/rule-registry-plugin/server'; import { ruleRegistryMocks } from '@kbn/rule-registry-plugin/server/mocks'; -import { PluginSetupContract as AlertingPluginSetupContract } from '@kbn/alerting-plugin/server'; +import { AlertingServerSetup } from '@kbn/alerting-plugin/server'; import { ObservabilityPluginSetup } from '@kbn/observability-plugin/server'; import { DEFAULT_FLAPPING_SETTINGS } from '@kbn/alerting-plugin/common'; import { APMConfig, APM_SERVER_FEATURE_ID } from '../../..'; @@ -30,7 +30,7 @@ export const createRuleTypeMocks = () => { registerType: ({ executor }) => { alertExecutor = executor; }, - } as AlertingPluginSetupContract; + } as AlertingServerSetup; const scheduleActions = jest.fn(); const getUuid = jest.fn(); diff --git a/x-pack/plugins/observability_solution/infra/server/lib/adapters/framework/adapter_types.ts b/x-pack/plugins/observability_solution/infra/server/lib/adapters/framework/adapter_types.ts index 8fe4101d7ebcaf..1879dee4be4e0a 100644 --- a/x-pack/plugins/observability_solution/infra/server/lib/adapters/framework/adapter_types.ts +++ b/x-pack/plugins/observability_solution/infra/server/lib/adapters/framework/adapter_types.ts @@ -20,7 +20,7 @@ import { HomeServerPluginSetup } from '@kbn/home-plugin/server'; import { VisTypeTimeseriesSetup } from '@kbn/vis-type-timeseries-plugin/server'; import { FeaturesPluginSetup } from '@kbn/features-plugin/server'; import { SpacesPluginSetup } from '@kbn/spaces-plugin/server'; -import { PluginSetupContract as AlertingPluginContract } from '@kbn/alerting-plugin/server'; +import type { AlertingServerSetup } from '@kbn/alerting-plugin/server'; import { MlPluginSetup } from '@kbn/ml-plugin/server'; import { RuleRegistryPluginSetupContract, @@ -40,7 +40,7 @@ import { } from '@kbn/apm-data-access-plugin/server'; export interface InfraServerPluginSetupDeps { - alerting: AlertingPluginContract; + alerting: AlertingServerSetup; data: DataPluginSetup; home: HomeServerPluginSetup; features: FeaturesPluginSetup; diff --git a/x-pack/plugins/observability_solution/infra/server/lib/alerting/log_threshold/register_log_threshold_rule_type.ts b/x-pack/plugins/observability_solution/infra/server/lib/alerting/log_threshold/register_log_threshold_rule_type.ts index decac47dbb5f97..d4eb9050499cfa 100644 --- a/x-pack/plugins/observability_solution/infra/server/lib/alerting/log_threshold/register_log_threshold_rule_type.ts +++ b/x-pack/plugins/observability_solution/infra/server/lib/alerting/log_threshold/register_log_threshold_rule_type.ts @@ -7,7 +7,10 @@ import { i18n } from '@kbn/i18n'; import { DEFAULT_APP_CATEGORIES } from '@kbn/core/server'; -import { GetViewInAppRelativeUrlFnOpts, PluginSetupContract } from '@kbn/alerting-plugin/server'; +import type { + GetViewInAppRelativeUrlFnOpts, + AlertingServerSetup, +} from '@kbn/alerting-plugin/server'; import { observabilityPaths } from '@kbn/observability-plugin/common'; import { decodeOrThrow } from '@kbn/io-ts-utils'; import type { InfraConfig } from '../../../../common/plugin_config_types'; @@ -103,7 +106,7 @@ const viewInAppUrlActionVariableDescription = i18n.translate( ); export function registerLogThresholdRuleType( - alertingPlugin: PluginSetupContract, + alertingPlugin: AlertingServerSetup, libs: InfraBackendLibs, { featureFlags }: InfraConfig ) { diff --git a/x-pack/plugins/observability_solution/infra/server/lib/alerting/metric_threshold/register_metric_threshold_rule_type.ts b/x-pack/plugins/observability_solution/infra/server/lib/alerting/metric_threshold/register_metric_threshold_rule_type.ts index 8bd8aafcbf2074..7340d6b4226e70 100644 --- a/x-pack/plugins/observability_solution/infra/server/lib/alerting/metric_threshold/register_metric_threshold_rule_type.ts +++ b/x-pack/plugins/observability_solution/infra/server/lib/alerting/metric_threshold/register_metric_threshold_rule_type.ts @@ -8,7 +8,10 @@ import { DEFAULT_APP_CATEGORIES } from '@kbn/core/server'; import { schema } from '@kbn/config-schema'; import { i18n } from '@kbn/i18n'; -import { GetViewInAppRelativeUrlFnOpts, PluginSetupContract } from '@kbn/alerting-plugin/server'; +import type { + GetViewInAppRelativeUrlFnOpts, + AlertingServerSetup, +} from '@kbn/alerting-plugin/server'; import { observabilityPaths } from '@kbn/observability-plugin/common'; import { COMPARATORS } from '@kbn/alerting-comparators'; import { LEGACY_COMPARATORS } from '@kbn/observability-plugin/common/utils/convert_legacy_outside_comparator'; @@ -46,7 +49,7 @@ import { MetricsRulesTypeAlertDefinition } from '../register_rule_types'; import { O11Y_AAD_FIELDS } from '../../../../common/constants'; export function registerMetricThresholdRuleType( - alertingPlugin: PluginSetupContract, + alertingPlugin: AlertingServerSetup, libs: InfraBackendLibs, { featureFlags }: InfraConfig ) { diff --git a/x-pack/plugins/observability_solution/infra/server/lib/alerting/register_rule_types.ts b/x-pack/plugins/observability_solution/infra/server/lib/alerting/register_rule_types.ts index 61f26348ca53f8..e8f3f2ac3fdf2f 100644 --- a/x-pack/plugins/observability_solution/infra/server/lib/alerting/register_rule_types.ts +++ b/x-pack/plugins/observability_solution/infra/server/lib/alerting/register_rule_types.ts @@ -6,7 +6,7 @@ */ import { legacyExperimentalFieldMap } from '@kbn/alerts-as-data-utils'; -import { type IRuleTypeAlerts, PluginSetupContract } from '@kbn/alerting-plugin/server'; +import { type IRuleTypeAlerts, AlertingServerSetup } from '@kbn/alerting-plugin/server'; import { registerMetricThresholdRuleType } from './metric_threshold/register_metric_threshold_rule_type'; import { registerInventoryThresholdRuleType } from './inventory_metric_threshold/register_inventory_metric_threshold_rule_type'; import { registerLogThresholdRuleType } from './log_threshold/register_log_threshold_rule_type'; @@ -36,7 +36,7 @@ export const MetricsRulesTypeAlertDefinition: IRuleTypeAlerts { diff --git a/x-pack/plugins/observability_solution/infra/server/services/rules/types.ts b/x-pack/plugins/observability_solution/infra/server/services/rules/types.ts index fa14089de2ba5b..befa536837b4f8 100644 --- a/x-pack/plugins/observability_solution/infra/server/services/rules/types.ts +++ b/x-pack/plugins/observability_solution/infra/server/services/rules/types.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { PluginSetupContract as AlertingPluginSetup } from '@kbn/alerting-plugin/server'; +import type { AlertingServerSetup } from '@kbn/alerting-plugin/server'; import { createLifecycleExecutor, IRuleDataClient, @@ -14,7 +14,7 @@ import { type LifecycleRuleExecutorCreator = ReturnType; export interface RulesServiceSetupDeps { - alerting: AlertingPluginSetup; + alerting: AlertingServerSetup; ruleRegistry: RuleRegistryPluginSetupContract; } diff --git a/x-pack/plugins/observability_solution/metrics_data_access/server/lib/adapters/framework/adapter_types.ts b/x-pack/plugins/observability_solution/metrics_data_access/server/lib/adapters/framework/adapter_types.ts index daea1177b19f82..6441fd2fe14541 100644 --- a/x-pack/plugins/observability_solution/metrics_data_access/server/lib/adapters/framework/adapter_types.ts +++ b/x-pack/plugins/observability_solution/metrics_data_access/server/lib/adapters/framework/adapter_types.ts @@ -20,7 +20,7 @@ import { HomeServerPluginSetup } from '@kbn/home-plugin/server'; import { VisTypeTimeseriesSetup } from '@kbn/vis-type-timeseries-plugin/server'; import { FeaturesPluginSetup } from '@kbn/features-plugin/server'; import { SpacesPluginSetup } from '@kbn/spaces-plugin/server'; -import { PluginSetupContract as AlertingPluginContract } from '@kbn/alerting-plugin/server'; +import type { AlertingServerSetup } from '@kbn/alerting-plugin/server'; import { MlPluginSetup } from '@kbn/ml-plugin/server'; import { RuleRegistryPluginSetupContract } from '@kbn/rule-registry-plugin/server'; import { ObservabilityPluginSetup } from '@kbn/observability-plugin/server'; @@ -28,7 +28,7 @@ import { VersionedRouteConfig } from '@kbn/core-http-server'; import { MetricsDataPluginSetup } from '../../../types'; export interface InfraServerPluginSetupDeps { - alerting: AlertingPluginContract; + alerting: AlertingServerSetup; data: DataPluginSetup; home: HomeServerPluginSetup; features: FeaturesPluginSetup; diff --git a/x-pack/plugins/observability_solution/observability/server/lib/rules/register_rule_types.ts b/x-pack/plugins/observability_solution/observability/server/lib/rules/register_rule_types.ts index c214939bdec88f..300dcda5e4f0f4 100644 --- a/x-pack/plugins/observability_solution/observability/server/lib/rules/register_rule_types.ts +++ b/x-pack/plugins/observability_solution/observability/server/lib/rules/register_rule_types.ts @@ -5,14 +5,14 @@ * 2.0. */ -import { PluginSetupContract } from '@kbn/alerting-plugin/server'; +import type { AlertingServerSetup } from '@kbn/alerting-plugin/server'; import { IBasePath, Logger } from '@kbn/core/server'; import { CustomThresholdLocators } from './custom_threshold/custom_threshold_executor'; import { ObservabilityConfig } from '../..'; import { thresholdRuleType } from './custom_threshold/register_custom_threshold_rule_type'; export function registerRuleTypes( - alertingPlugin: PluginSetupContract, + alertingPlugin: AlertingServerSetup, basePath: IBasePath, config: ObservabilityConfig, logger: Logger, diff --git a/x-pack/plugins/observability_solution/observability_ai_assistant_app/server/types.ts b/x-pack/plugins/observability_solution/observability_ai_assistant_app/server/types.ts index 30cce3f0b37b3b..40c708306e369c 100644 --- a/x-pack/plugins/observability_solution/observability_ai_assistant_app/server/types.ts +++ b/x-pack/plugins/observability_solution/observability_ai_assistant_app/server/types.ts @@ -9,10 +9,7 @@ import type { PluginSetupContract as ActionsPluginSetup, PluginStartContract as ActionsPluginStart, } from '@kbn/actions-plugin/server'; -import type { - PluginSetupContract as AlertingPluginSetup, - PluginStartContract as AlertingPluginStart, -} from '@kbn/alerting-plugin/server'; +import type { AlertingServerSetup, AlertingServerStart } from '@kbn/alerting-plugin/server'; import type { DataViewsServerPluginSetup, DataViewsServerPluginStart, @@ -44,7 +41,7 @@ export interface ObservabilityAIAssistantAppServerSetup {} export interface ObservabilityAIAssistantAppPluginStartDependencies { observabilityAIAssistant: ObservabilityAIAssistantServerStart; ruleRegistry: RuleRegistryPluginStartContract; - alerting: AlertingPluginStart; + alerting: AlertingServerStart; licensing: LicensingPluginStart; actions: ActionsPluginStart; security: SecurityPluginStart; @@ -58,7 +55,7 @@ export interface ObservabilityAIAssistantAppPluginStartDependencies { export interface ObservabilityAIAssistantAppPluginSetupDependencies { observabilityAIAssistant: ObservabilityAIAssistantServerSetup; ruleRegistry: RuleRegistryPluginSetupContract; - alerting: AlertingPluginSetup; + alerting: AlertingServerSetup; licensing: LicensingPluginSetup; actions: ActionsPluginSetup; security: SecurityPluginSetup; diff --git a/x-pack/plugins/observability_solution/slo/server/lib/rules/register_burn_rate_rule.ts b/x-pack/plugins/observability_solution/slo/server/lib/rules/register_burn_rate_rule.ts index d432dc5c52d34c..ace1a1318ce295 100644 --- a/x-pack/plugins/observability_solution/slo/server/lib/rules/register_burn_rate_rule.ts +++ b/x-pack/plugins/observability_solution/slo/server/lib/rules/register_burn_rate_rule.ts @@ -5,14 +5,14 @@ * 2.0. */ -import { PluginSetupContract } from '@kbn/alerting-plugin/server'; +import type { AlertingServerSetup } from '@kbn/alerting-plugin/server'; import { IBasePath, Logger } from '@kbn/core/server'; import { IRuleDataService } from '@kbn/rule-registry-plugin/server'; import { CustomThresholdLocators } from '@kbn/observability-plugin/server'; import { sloBurnRateRuleType } from './slo_burn_rate'; export function registerBurnRateRule( - alertingPlugin: PluginSetupContract, + alertingPlugin: AlertingServerSetup, basePath: IBasePath, logger: Logger, ruleDataService: IRuleDataService, diff --git a/x-pack/plugins/observability_solution/slo/server/plugin.ts b/x-pack/plugins/observability_solution/slo/server/plugin.ts index 00959963fbee03..b3521811e0bbe6 100644 --- a/x-pack/plugins/observability_solution/slo/server/plugin.ts +++ b/x-pack/plugins/observability_solution/slo/server/plugin.ts @@ -15,7 +15,7 @@ import { Logger, SavedObjectsClient, } from '@kbn/core/server'; -import { PluginSetupContract, PluginStartContract } from '@kbn/alerting-plugin/server'; +import type { AlertingServerSetup, AlertingServerStart } from '@kbn/alerting-plugin/server'; import { FeaturesPluginSetup } from '@kbn/features-plugin/server'; import { RuleRegistryPluginSetupContract, @@ -47,7 +47,7 @@ import { sloSettings, SO_SLO_SETTINGS_TYPE } from './saved_objects/slo_settings' export type SloPluginSetup = ReturnType; export interface PluginSetup { - alerting: PluginSetupContract; + alerting: AlertingServerSetup; ruleRegistry: RuleRegistryPluginSetupContract; share: SharePluginSetup; features: FeaturesPluginSetup; @@ -58,7 +58,7 @@ export interface PluginSetup { } export interface PluginStart { - alerting: PluginStartContract; + alerting: AlertingServerStart; taskManager: TaskManagerStartContract; spaces?: SpacesPluginStart; ruleRegistry: RuleRegistryPluginStartContract; diff --git a/x-pack/plugins/observability_solution/synthetics/server/alert_rules/status_rule/monitor_status_rule.ts b/x-pack/plugins/observability_solution/synthetics/server/alert_rules/status_rule/monitor_status_rule.ts index d042e8d3233029..a6a1cf34454900 100644 --- a/x-pack/plugins/observability_solution/synthetics/server/alert_rules/status_rule/monitor_status_rule.ts +++ b/x-pack/plugins/observability_solution/synthetics/server/alert_rules/status_rule/monitor_status_rule.ts @@ -8,7 +8,7 @@ import { DEFAULT_APP_CATEGORIES } from '@kbn/core/server'; import { isEmpty } from 'lodash'; import { ActionGroupIdsOf } from '@kbn/alerting-plugin/common'; -import { PluginSetupContract } from '@kbn/alerting-plugin/server'; +import type { AlertingServerSetup } from '@kbn/alerting-plugin/server'; import { GetViewInAppRelativeUrlFnOpts, AlertInstanceContext as AlertContext, @@ -56,7 +56,7 @@ export const registerSyntheticsStatusCheckRule = ( server: SyntheticsServerSetup, plugins: SyntheticsPluginsSetupDependencies, syntheticsMonitorClient: SyntheticsMonitorClient, - alerting: PluginSetupContract + alerting: AlertingServerSetup ) => { if (!alerting) { throw new Error( From 5140a064eb341f2f001875f96f7b446b804c52ac Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Sat, 27 Jul 2024 14:45:30 +0300 Subject: [PATCH 034/106] Switch authorization and search strategy to rule type ids --- .../search_strategy_types.ts | 3 +- .../src/alerts_as_data_rbac.ts | 2 +- .../alerting_authorization.test.ts | 432 +++++++----------- .../authorization/alerting_authorization.ts | 159 ++++--- .../server/lib/get_authz_filter.ts | 12 +- .../search_strategy/search_strategy.test.ts | 32 +- .../server/search_strategy/search_strategy.ts | 61 ++- 7 files changed, 313 insertions(+), 388 deletions(-) diff --git a/packages/kbn-alerting-types/search_strategy_types.ts b/packages/kbn-alerting-types/search_strategy_types.ts index 07025fd4f435f0..586dbc7a761960 100644 --- a/packages/kbn-alerting-types/search_strategy_types.ts +++ b/packages/kbn-alerting-types/search_strategy_types.ts @@ -7,7 +7,6 @@ */ import type { IEsSearchRequest, IEsSearchResponse } from '@kbn/search-types'; -import type { ValidFeatureId } from '@kbn/rule-data-utils'; import type { MappingRuntimeFields, QueryDslFieldAndFormat, @@ -17,7 +16,7 @@ import type { import type { Alert } from './alert_type'; export type RuleRegistrySearchRequest = IEsSearchRequest & { - featureIds: ValidFeatureId[]; + ruleTypeIds: string[]; fields?: QueryDslFieldAndFormat[]; query?: Pick; sort?: SortCombinations[]; diff --git a/packages/kbn-rule-data-utils/src/alerts_as_data_rbac.ts b/packages/kbn-rule-data-utils/src/alerts_as_data_rbac.ts index d736644985a283..e6aedcba096f3d 100644 --- a/packages/kbn-rule-data-utils/src/alerts_as_data_rbac.ts +++ b/packages/kbn-rule-data-utils/src/alerts_as_data_rbac.ts @@ -29,7 +29,7 @@ export const AlertConsumers = { MONITORING: 'monitoring', ALERTS: 'alerts', } as const; -export type AlertConsumers = typeof AlertConsumers[keyof typeof AlertConsumers]; +export type AlertConsumers = (typeof AlertConsumers)[keyof typeof AlertConsumers]; export type STATUS_VALUES = 'open' | 'acknowledged' | 'closed' | 'in-progress'; // TODO: remove 'in-progress' after migration to 'acknowledged' export type ValidFeatureId = AlertConsumers; diff --git a/x-pack/plugins/alerting/server/authorization/alerting_authorization.test.ts b/x-pack/plugins/alerting/server/authorization/alerting_authorization.test.ts index b178d65070478e..296b451990d5d0 100644 --- a/x-pack/plugins/alerting/server/authorization/alerting_authorization.test.ts +++ b/x-pack/plugins/alerting/server/authorization/alerting_authorization.test.ts @@ -147,7 +147,6 @@ describe('AlertingAuthorization', () => { })); const ruleTypeIds = ['rule-type-id-1', 'rule-type-id-2', 'rule-type-id-3', 'rule-type-id-4']; - const consumers = ['consumer-a', 'consumer-b', 'consumer-c', 'consumer-d']; let request: KibanaRequest; let ruleTypeRegistry = ruleTypeRegistryMock.create(); @@ -749,11 +748,14 @@ describe('AlertingAuthorization', () => { }); const filter = ( - await auth.getFindAuthorizationFilter(AlertingAuthorizationEntity.Rule, { - type: AlertingAuthorizationFilterType.KQL, - fieldNames: { - ruleTypeId: 'path.to.rule_type_id', - consumer: 'consumer-field', + await auth.getFindAuthorizationFilter({ + authorizationEntity: AlertingAuthorizationEntity.Rule, + filterOpts: { + type: AlertingAuthorizationFilterType.KQL, + fieldNames: { + ruleTypeId: 'path.to.rule_type_id', + consumer: 'consumer-field', + }, }, }) ).filter; @@ -808,16 +810,16 @@ describe('AlertingAuthorization', () => { authorization: securityStart.authz, }); - const { ensureRuleTypeIsAuthorized } = await auth.getFindAuthorizationFilter( - AlertingAuthorizationEntity.Rule, - { + const { ensureRuleTypeIsAuthorized } = await auth.getFindAuthorizationFilter({ + authorizationEntity: AlertingAuthorizationEntity.Rule, + filterOpts: { type: AlertingAuthorizationFilterType.KQL, fieldNames: { ruleTypeId: 'path.to.rule_type_id', consumer: 'consumer-field', }, - } - ); + }, + }); expect(() => ensureRuleTypeIsAuthorized('rule-type-id-1', 'consumer-a', 'rule') @@ -840,17 +842,17 @@ describe('AlertingAuthorization', () => { getSpace, }); - const { filter } = await auth.getAuthorizationFilter( - AlertingAuthorizationEntity.Rule, - { + const { filter } = await auth.getAuthorizationFilter({ + authorizationEntity: AlertingAuthorizationEntity.Rule, + filterOpts: { type: AlertingAuthorizationFilterType.KQL, fieldNames: { ruleTypeId: 'ruleId', consumer: 'consumer', }, }, - ReadOperations.Get - ); + operation: ReadOperations.Get, + }); expect(filter).toEqual(undefined); }); @@ -867,9 +869,9 @@ describe('AlertingAuthorization', () => { getSpace, }); - const { filter } = await auth.getAuthorizationFilter( - AlertingAuthorizationEntity.Rule, - { + const { filter } = await auth.getAuthorizationFilter({ + authorizationEntity: AlertingAuthorizationEntity.Rule, + filterOpts: { type: AlertingAuthorizationFilterType.KQL, fieldNames: { ruleTypeId: 'ruleId', @@ -877,8 +879,8 @@ describe('AlertingAuthorization', () => { spaceIds: 'path.to.space.id', }, }, - ReadOperations.Get - ); + operation: ReadOperations.Get, + }); expect(toKqlExpression(filter as KueryNode)).toMatchInlineSnapshot( `"path.to.space.id: space1"` @@ -897,17 +899,17 @@ describe('AlertingAuthorization', () => { authorization: securityStart.authz, }); - const { filter } = await auth.getAuthorizationFilter( - AlertingAuthorizationEntity.Rule, - { + const { filter } = await auth.getAuthorizationFilter({ + authorizationEntity: AlertingAuthorizationEntity.Rule, + filterOpts: { type: AlertingAuthorizationFilterType.KQL, fieldNames: { ruleTypeId: 'ruleId', consumer: 'consumer', }, }, - ReadOperations.Get - ); + operation: ReadOperations.Get, + }); expect(filter).toEqual(undefined); }); @@ -951,18 +953,17 @@ describe('AlertingAuthorization', () => { authorization: securityStart.authz, }); - const { filter } = await auth.getAuthorizationFilter( - AlertingAuthorizationEntity.Rule, - { + const { filter } = await auth.getAuthorizationFilter({ + authorizationEntity: AlertingAuthorizationEntity.Rule, + filterOpts: { type: AlertingAuthorizationFilterType.KQL, fieldNames: { ruleTypeId: 'ruleId', consumer: 'consumer', }, }, - ReadOperations.Get, - new Set(consumers) - ); + operation: ReadOperations.Get, + }); expect(toKqlExpression(filter as KueryNode)).toMatchInlineSnapshot( `"((ruleId: rule-type-id-1 AND (consumer: consumer-a OR consumer: consumer-b)) OR (ruleId: rule-type-id-2 AND consumer: consumer-b) OR (ruleId: rule-type-id-3 AND consumer: consumer-c) OR (ruleId: rule-type-id-4 AND consumer: consumer-d))"` @@ -988,18 +989,17 @@ describe('AlertingAuthorization', () => { }); await expect( - auth.getAuthorizationFilter( - AlertingAuthorizationEntity.Rule, - { + auth.getAuthorizationFilter({ + authorizationEntity: AlertingAuthorizationEntity.Rule, + filterOpts: { type: AlertingAuthorizationFilterType.KQL, fieldNames: { ruleTypeId: 'ruleId', consumer: 'consumer', }, }, - ReadOperations.Get, - new Set(consumers) - ) + operation: ReadOperations.Get, + }) ).rejects.toThrowErrorMatchingInlineSnapshot( `"Unauthorized to get rules for any rule types"` ); @@ -1034,18 +1034,17 @@ describe('AlertingAuthorization', () => { authorization: securityStart.authz, }); - const { ensureRuleTypeIsAuthorized } = await auth.getAuthorizationFilter( - AlertingAuthorizationEntity.Rule, - { + const { ensureRuleTypeIsAuthorized } = await auth.getAuthorizationFilter({ + authorizationEntity: AlertingAuthorizationEntity.Rule, + filterOpts: { type: AlertingAuthorizationFilterType.KQL, fieldNames: { ruleTypeId: 'ruleId', consumer: 'consumer', }, }, - ReadOperations.Get, - new Set(consumers) - ); + operation: ReadOperations.Get, + }); expect(() => ensureRuleTypeIsAuthorized('rule-type-id-1', 'consumer-a', 'rule') @@ -1079,18 +1078,17 @@ describe('AlertingAuthorization', () => { authorization: securityStart.authz, }); - const { ensureRuleTypeIsAuthorized } = await auth.getAuthorizationFilter( - AlertingAuthorizationEntity.Rule, - { + const { ensureRuleTypeIsAuthorized } = await auth.getAuthorizationFilter({ + authorizationEntity: AlertingAuthorizationEntity.Rule, + filterOpts: { type: AlertingAuthorizationFilterType.KQL, fieldNames: { ruleTypeId: 'ruleId', consumer: 'consumer', }, }, - ReadOperations.Get, - new Set(consumers) - ); + operation: ReadOperations.Get, + }); expect(() => ensureRuleTypeIsAuthorized('rule-type-id-2', 'consumer-a', 'rule') @@ -1122,18 +1120,17 @@ describe('AlertingAuthorization', () => { authorization: securityStart.authz, }); - const { ensureRuleTypeIsAuthorized } = await auth.getAuthorizationFilter( - AlertingAuthorizationEntity.Rule, - { + const { ensureRuleTypeIsAuthorized } = await auth.getAuthorizationFilter({ + authorizationEntity: AlertingAuthorizationEntity.Rule, + filterOpts: { type: AlertingAuthorizationFilterType.KQL, fieldNames: { ruleTypeId: 'ruleId', consumer: 'consumer', }, }, - ReadOperations.Get, - new Set(consumers) - ); + operation: ReadOperations.Get, + }); expect(() => ensureRuleTypeIsAuthorized('rule-type-id-1', 'consumer-a', 'alert') @@ -1165,18 +1162,17 @@ describe('AlertingAuthorization', () => { authorization: securityStart.authz, }); - const { ensureRuleTypeIsAuthorized } = await auth.getAuthorizationFilter( - AlertingAuthorizationEntity.Rule, - { + const { ensureRuleTypeIsAuthorized } = await auth.getAuthorizationFilter({ + authorizationEntity: AlertingAuthorizationEntity.Rule, + filterOpts: { type: AlertingAuthorizationFilterType.KQL, fieldNames: { ruleTypeId: 'ruleId', consumer: 'consumer', }, }, - ReadOperations.Get, - new Set(consumers) - ); + operation: ReadOperations.Get, + }); expect(() => ensureRuleTypeIsAuthorized('rule-type-id-1', 'consumer-b', 'rule') @@ -1198,11 +1194,11 @@ describe('AlertingAuthorization', () => { authorization: securityStart.authz, }); - await auth.getAuthorizedRuleTypes( - new Set(['rule-type-id-1']), - [WriteOperations.Create], - AlertingAuthorizationEntity.Rule - ); + await auth.getAuthorizedRuleTypes({ + ruleTypeIds: ['rule-type-id-1'], + operations: [WriteOperations.Create], + authorizationEntity: AlertingAuthorizationEntity.Rule, + }); expect(checkPrivileges).toBeCalledTimes(1); expect(checkPrivileges.mock.calls[0]).toMatchInlineSnapshot(` @@ -1254,11 +1250,11 @@ describe('AlertingAuthorization', () => { }); expect( - await auth.getAuthorizedRuleTypes( - new Set(['rule-type-id-1']), - [WriteOperations.Create], - AlertingAuthorizationEntity.Rule - ) + await auth.getAuthorizedRuleTypes({ + ruleTypeIds: ['rule-type-id-1'], + operations: [WriteOperations.Create], + authorizationEntity: AlertingAuthorizationEntity.Rule, + }) ).toMatchInlineSnapshot(` Map { "rule-type-id-1" => Object { @@ -1311,11 +1307,10 @@ describe('AlertingAuthorization', () => { }); expect( - await auth.getAllAuthorizedRuleTypes( - consumers, - [ReadOperations.Get, WriteOperations.Create], - AlertingAuthorizationEntity.Rule - ) + await auth.getAllAuthorizedRuleTypes({ + operations: [ReadOperations.Get, WriteOperations.Create], + authorizationEntity: AlertingAuthorizationEntity.Rule, + }) ).toMatchInlineSnapshot(` Object { "authorizedRuleTypes": Map { @@ -1352,23 +1347,28 @@ describe('AlertingAuthorization', () => { authorization: securityStart.authz, }); - await auth.getAllAuthorizedRuleTypes( - consumers, - [ReadOperations.Get, WriteOperations.Create], - AlertingAuthorizationEntity.Rule - ); + await auth.getAllAuthorizedRuleTypes({ + operations: [ReadOperations.Get, WriteOperations.Create], + authorizationEntity: AlertingAuthorizationEntity.Rule, + }); expect(checkPrivileges).toBeCalledTimes(1); expect(checkPrivileges.mock.calls[0]).toMatchInlineSnapshot(` Array [ Object { "kibana": Array [ + "rule-type-id-1/alerts/rule/get", + "rule-type-id-1/alerts/rule/create", "rule-type-id-1/consumer-a/rule/get", "rule-type-id-1/consumer-a/rule/create", "rule-type-id-1/consumer-b/rule/get", "rule-type-id-1/consumer-b/rule/create", + "rule-type-id-2/alerts/rule/get", + "rule-type-id-2/alerts/rule/create", "rule-type-id-2/consumer-b/rule/get", "rule-type-id-2/consumer-b/rule/create", + "rule-type-id-3/alerts/rule/get", + "rule-type-id-3/alerts/rule/create", "rule-type-id-3/consumer-c/rule/get", "rule-type-id-3/consumer-c/rule/create", "rule-type-id-4/consumer-d/rule/get", @@ -1392,12 +1392,11 @@ describe('AlertingAuthorization', () => { expect( // @ts-expect-error: need to test the private method - await auth._getAuthorizedRuleTypesWithAuthorizedConsumers( - new Set(ruleTypeIds), - [ReadOperations.Get, WriteOperations.Create], - AlertingAuthorizationEntity.Rule, - new Set(consumers) - ) + await auth._getAuthorizedRuleTypesWithAuthorizedConsumers({ + ruleTypeIds, + operations: [ReadOperations.Get, WriteOperations.Create], + authorizationEntity: AlertingAuthorizationEntity.Rule, + }) ).toMatchInlineSnapshot(` Object { "authorizedRuleTypes": Map { @@ -1514,12 +1513,11 @@ describe('AlertingAuthorization', () => { expect( // @ts-expect-error: need to test the private method - await auth._getAuthorizedRuleTypesWithAuthorizedConsumers( - new Set([ruleTypeIds[0], ruleTypeIds[1]]), - [ReadOperations.Get, WriteOperations.Create], - AlertingAuthorizationEntity.Rule, - new Set(consumers) - ) + await auth._getAuthorizedRuleTypesWithAuthorizedConsumers({ + ruleTypeIds: [ruleTypeIds[0], ruleTypeIds[1]], + operations: [ReadOperations.Get, WriteOperations.Create], + authorizationEntity: AlertingAuthorizationEntity.Rule, + }) ).toMatchInlineSnapshot(` Object { "authorizedRuleTypes": Map { @@ -1591,12 +1589,11 @@ describe('AlertingAuthorization', () => { expect( // @ts-expect-error: need to test the private method - await auth._getAuthorizedRuleTypesWithAuthorizedConsumers( - new Set(ruleTypeIds), - [ReadOperations.Get, WriteOperations.Create], - AlertingAuthorizationEntity.Rule, - new Set(consumers) - ) + await auth._getAuthorizedRuleTypesWithAuthorizedConsumers({ + ruleTypeIds, + operations: [ReadOperations.Get, WriteOperations.Create], + authorizationEntity: AlertingAuthorizationEntity.Rule, + }) ).toMatchInlineSnapshot(` Object { "authorizedRuleTypes": Map { @@ -1716,12 +1713,11 @@ describe('AlertingAuthorization', () => { expect( // @ts-expect-error: need to test the private method - await auth._getAuthorizedRuleTypesWithAuthorizedConsumers( - new Set([ruleTypeIds[0], ruleTypeIds[1]]), - [ReadOperations.Get, WriteOperations.Create], - AlertingAuthorizationEntity.Rule, - new Set(consumers) - ) + await auth._getAuthorizedRuleTypesWithAuthorizedConsumers({ + ruleTypeIds: [ruleTypeIds[0], ruleTypeIds[1]], + operations: [ReadOperations.Get, WriteOperations.Create], + authorizationEntity: AlertingAuthorizationEntity.Rule, + }) ).toMatchInlineSnapshot(` Object { "authorizedRuleTypes": Map { @@ -1804,12 +1800,11 @@ describe('AlertingAuthorization', () => { expect( // @ts-expect-error: need to test the private method - await auth._getAuthorizedRuleTypesWithAuthorizedConsumers( - new Set(ruleTypeIds), - [ReadOperations.Get, WriteOperations.Create], - AlertingAuthorizationEntity.Rule, - new Set(consumers) - ) + await auth._getAuthorizedRuleTypesWithAuthorizedConsumers({ + ruleTypeIds, + operations: [ReadOperations.Get, WriteOperations.Create], + authorizationEntity: AlertingAuthorizationEntity.Rule, + }) ).toMatchInlineSnapshot(` Object { "authorizedRuleTypes": Map { @@ -1857,12 +1852,11 @@ describe('AlertingAuthorization', () => { expect( // @ts-expect-error: need to test the private method - await auth._getAuthorizedRuleTypesWithAuthorizedConsumers( - new Set(ruleTypeIds), - [ReadOperations.Get, WriteOperations.Create], - AlertingAuthorizationEntity.Rule, - new Set(consumers) - ) + await auth._getAuthorizedRuleTypesWithAuthorizedConsumers({ + ruleTypeIds, + operations: [ReadOperations.Get, WriteOperations.Create], + authorizationEntity: AlertingAuthorizationEntity.Rule, + }) ).toMatchInlineSnapshot(` Object { "authorizedRuleTypes": Map { @@ -1881,59 +1875,6 @@ describe('AlertingAuthorization', () => { `); }); - it('filters out not requested consumers', async () => { - checkPrivileges.mockResolvedValueOnce({ - username: 'some-user', - hasAllRequested: true, - privileges: { - kibana: [ - { - privilege: mockAuthorizationAction('rule-type-id-1', 'consumer-a', 'rule', 'get'), - authorized: true, - }, - { - privilege: mockAuthorizationAction('rule-type-id-1', 'consumer-b', 'rule', 'create'), - authorized: true, - }, - ], - }, - }); - - const auth = await AlertingAuthorization.create({ - request, - ruleTypeRegistry, - getSpaceId, - features, - getSpace, - authorization: securityStart.authz, - }); - - expect( - // @ts-expect-error: need to test the private method - await auth._getAuthorizedRuleTypesWithAuthorizedConsumers( - new Set(ruleTypeIds), - [ReadOperations.Get, WriteOperations.Create], - AlertingAuthorizationEntity.Rule, - new Set(['consumer-a']) - ) - ).toMatchInlineSnapshot(` - Object { - "authorizedRuleTypes": Map { - "rule-type-id-1" => Object { - "authorizedConsumers": Object { - "consumer-a": Object { - "all": false, - "read": true, - }, - }, - }, - }, - "hasAllRequested": true, - "username": "some-user", - } - `); - }); - it('filters out not requested rule types', async () => { checkPrivileges.mockResolvedValueOnce({ username: 'some-user', @@ -1967,12 +1908,11 @@ describe('AlertingAuthorization', () => { expect( // @ts-expect-error: need to test the private method - await auth._getAuthorizedRuleTypesWithAuthorizedConsumers( - new Set([ruleTypeIds[0], ruleTypeIds[1]]), - [ReadOperations.Get, WriteOperations.Create], - AlertingAuthorizationEntity.Rule, - new Set(['consumer-a', 'consumer-b']) - ) + await auth._getAuthorizedRuleTypesWithAuthorizedConsumers({ + ruleTypeIds: [ruleTypeIds[0], ruleTypeIds[1]], + operations: [ReadOperations.Get, WriteOperations.Create], + authorizationEntity: AlertingAuthorizationEntity.Rule, + }) ).toMatchInlineSnapshot(` Object { "authorizedRuleTypes": Map { @@ -1995,50 +1935,6 @@ describe('AlertingAuthorization', () => { `); }); - it('returns an empty map with no requested consumers', async () => { - checkPrivileges.mockResolvedValueOnce({ - username: 'some-user', - hasAllRequested: true, - privileges: { - kibana: [ - { - privilege: mockAuthorizationAction('rule-type-id-1', 'consumer-a', 'rule', 'get'), - authorized: true, - }, - { - privilege: mockAuthorizationAction('rule-type-id-1', 'consumer-a', 'rule', 'create'), - authorized: true, - }, - ], - }, - }); - - const auth = await AlertingAuthorization.create({ - request, - ruleTypeRegistry, - getSpaceId, - features, - getSpace, - authorization: securityStart.authz, - }); - - expect( - // @ts-expect-error: need to test the private method - await auth._getAuthorizedRuleTypesWithAuthorizedConsumers( - new Set(ruleTypeIds), - [ReadOperations.Get, WriteOperations.Create], - AlertingAuthorizationEntity.Rule, - new Set([]) - ) - ).toMatchInlineSnapshot(` - Object { - "authorizedRuleTypes": Map {}, - "hasAllRequested": true, - "username": "some-user", - } - `); - }); - it('returns an empty map with no requested rule types', async () => { checkPrivileges.mockResolvedValueOnce({ username: 'some-user', @@ -2068,12 +1964,11 @@ describe('AlertingAuthorization', () => { expect( // @ts-expect-error: need to test the private method - await auth._getAuthorizedRuleTypesWithAuthorizedConsumers( - new Set([]), - [ReadOperations.Get, WriteOperations.Create], - AlertingAuthorizationEntity.Rule, - new Set(consumers) - ) + await auth._getAuthorizedRuleTypesWithAuthorizedConsumers({ + ruleTypeIds: [], + operations: [ReadOperations.Get, WriteOperations.Create], + authorizationEntity: AlertingAuthorizationEntity.Rule, + }) ).toMatchInlineSnapshot(` Object { "authorizedRuleTypes": Map {}, @@ -2120,12 +2015,11 @@ describe('AlertingAuthorization', () => { expect( // @ts-expect-error: need to test the private method - await auth._getAuthorizedRuleTypesWithAuthorizedConsumers( - new Set(ruleTypeIds), - [ReadOperations.Get, WriteOperations.Create], - AlertingAuthorizationEntity.Rule, - new Set(consumers) - ) + await auth._getAuthorizedRuleTypesWithAuthorizedConsumers({ + ruleTypeIds, + operations: [ReadOperations.Get, WriteOperations.Create], + authorizationEntity: AlertingAuthorizationEntity.Rule, + }) ).toMatchInlineSnapshot(` Object { "authorizedRuleTypes": Map { @@ -2189,12 +2083,11 @@ describe('AlertingAuthorization', () => { expect( // @ts-expect-error: need to test the private method - await auth._getAuthorizedRuleTypesWithAuthorizedConsumers( - new Set(ruleTypeIds), - [ReadOperations.Get, WriteOperations.Create], - AlertingAuthorizationEntity.Rule, - new Set(consumers) - ) + await auth._getAuthorizedRuleTypesWithAuthorizedConsumers({ + ruleTypeIds, + operations: [ReadOperations.Get, WriteOperations.Create], + authorizationEntity: AlertingAuthorizationEntity.Rule, + }) ).toMatchInlineSnapshot(` Object { "authorizedRuleTypes": Map { @@ -2240,12 +2133,11 @@ describe('AlertingAuthorization', () => { expect( // @ts-expect-error: need to test the private method - await auth._getAuthorizedRuleTypesWithAuthorizedConsumers( - new Set(['rule-type-id-1']), - [ReadOperations.Get, WriteOperations.Create], - AlertingAuthorizationEntity.Rule, - new Set(['consumer-a']) - ) + await auth._getAuthorizedRuleTypesWithAuthorizedConsumers({ + ruleTypeIds: ['rule-type-id-1'], + operations: [ReadOperations.Get, WriteOperations.Create], + authorizationEntity: AlertingAuthorizationEntity.Rule, + }) ).toMatchInlineSnapshot(` Object { "authorizedRuleTypes": Map {}, @@ -2282,12 +2174,11 @@ describe('AlertingAuthorization', () => { expect( // @ts-expect-error: need to test the private method - await auth._getAuthorizedRuleTypesWithAuthorizedConsumers( - new Set(['not-exist']), - [ReadOperations.Get, WriteOperations.Create], - AlertingAuthorizationEntity.Rule, - new Set(['consumer-a']) - ) + await auth._getAuthorizedRuleTypesWithAuthorizedConsumers({ + ruleTypeIds: ['not-exist'], + operations: [ReadOperations.Get, WriteOperations.Create], + authorizationEntity: AlertingAuthorizationEntity.Rule, + }) ).toMatchInlineSnapshot(` Object { "authorizedRuleTypes": Map {}, @@ -2308,24 +2199,29 @@ describe('AlertingAuthorization', () => { }); // @ts-expect-error: need to test the private method - await auth._getAuthorizedRuleTypesWithAuthorizedConsumers( - new Set([...ruleTypeIds, 'rule-type-not-exist']), - [ReadOperations.Get, WriteOperations.Create], - AlertingAuthorizationEntity.Rule, - new Set([...consumers, 'consumer-not-exist']) - ); + await auth._getAuthorizedRuleTypesWithAuthorizedConsumers({ + ruleTypeIds: [...ruleTypeIds, 'rule-type-not-exist'], + operations: [ReadOperations.Get, WriteOperations.Create], + authorizationEntity: AlertingAuthorizationEntity.Rule, + }); expect(checkPrivileges).toBeCalledTimes(1); expect(checkPrivileges.mock.calls[0]).toMatchInlineSnapshot(` Array [ Object { "kibana": Array [ + "rule-type-id-1/alerts/rule/get", + "rule-type-id-1/alerts/rule/create", "rule-type-id-1/consumer-a/rule/get", "rule-type-id-1/consumer-a/rule/create", "rule-type-id-1/consumer-b/rule/get", "rule-type-id-1/consumer-b/rule/create", + "rule-type-id-2/alerts/rule/get", + "rule-type-id-2/alerts/rule/create", "rule-type-id-2/consumer-b/rule/get", "rule-type-id-2/consumer-b/rule/create", + "rule-type-id-3/alerts/rule/get", + "rule-type-id-3/alerts/rule/create", "rule-type-id-3/consumer-c/rule/get", "rule-type-id-3/consumer-c/rule/create", "rule-type-id-4/consumer-d/rule/get", @@ -2349,12 +2245,11 @@ describe('AlertingAuthorization', () => { }); // @ts-expect-error: need to test the private method - await auth._getAuthorizedRuleTypesWithAuthorizedConsumers( - new Set(['rule-type-id-1']), - [ReadOperations.Get, WriteOperations.Create], - AlertingAuthorizationEntity.Rule, - new Set(['consumer-a']) - ); + await auth._getAuthorizedRuleTypesWithAuthorizedConsumers({ + ruleTypeIds: ['rule-type-id-1'], + operations: [ReadOperations.Get, WriteOperations.Create], + authorizationEntity: AlertingAuthorizationEntity.Rule, + }); expect(checkPrivileges).toBeCalledTimes(1); expect(checkPrivileges.mock.calls[0]).toMatchInlineSnapshot(` @@ -2379,12 +2274,11 @@ describe('AlertingAuthorization', () => { }); // @ts-expect-error: need to test the private method - await auth._getAuthorizedRuleTypesWithAuthorizedConsumers( - new Set(['not-exist']), - [ReadOperations.Get, WriteOperations.Create], - AlertingAuthorizationEntity.Rule, - new Set(['consumer-a']) - ); + await auth._getAuthorizedRuleTypesWithAuthorizedConsumers({ + ruleTypeIds: ['not-exist'], + operations: [ReadOperations.Get, WriteOperations.Create], + authorizationEntity: AlertingAuthorizationEntity.Rule, + }); expect(checkPrivileges).toBeCalledTimes(1); expect(checkPrivileges.mock.calls[0]).toMatchInlineSnapshot(` diff --git a/x-pack/plugins/alerting/server/authorization/alerting_authorization.ts b/x-pack/plugins/alerting/server/authorization/alerting_authorization.ts index 68e7e9d24c4627..91484caa8912c6 100644 --- a/x-pack/plugins/alerting/server/authorization/alerting_authorization.ts +++ b/x-pack/plugins/alerting/server/authorization/alerting_authorization.ts @@ -58,6 +58,41 @@ type ConstructorOptions = Pick< ruleTypesConsumersMap: Map>; }; +interface GetAuthorizationFilterParams { + authorizationEntity: AlertingAuthorizationEntity; + filterOpts: AlertingAuthorizationFilterOpts; + operation: WriteOperations | ReadOperations; + ruleTypeIds?: string[]; +} + +interface GetAuthorizedRuleTypesWithAuthorizedConsumersParams { + ruleTypeIds?: string[]; + operations: Array; + authorizationEntity: AlertingAuthorizationEntity; +} + +interface GetAllAuthorizedRuleTypesFindOperationParams { + authorizationEntity: AlertingAuthorizationEntity; + ruleTypeIds?: string[]; +} + +interface GetFindAuthorizationFilterParams { + authorizationEntity: AlertingAuthorizationEntity; + filterOpts: AlertingAuthorizationFilterOpts; + ruleTypeIds?: string[]; +} + +interface GetAuthorizedRuleTypesParams { + ruleTypeIds?: string[]; + operations: Array; + authorizationEntity: AlertingAuthorizationEntity; +} + +interface GetAllAuthorizedRuleTypes { + operations: Array; + authorizationEntity: AlertingAuthorizationEntity; +} + export class AlertingAuthorization { private readonly ruleTypeRegistry: RuleTypeRegistry; private readonly request: KibanaRequest; @@ -181,21 +216,15 @@ export class AlertingAuthorization { * This method exposes the private '_getAuthorizedRuleTypesWithAuthorizedConsumers' to be * used by the RAC/Alerts client */ - public async getAllAuthorizedRuleTypes( - featureIds: readonly string[], - operations: Array, - authorizationEntity: AlertingAuthorizationEntity - ): Promise<{ + public async getAllAuthorizedRuleTypes(params: GetAllAuthorizedRuleTypes): Promise<{ username?: string; hasAllRequested: boolean; authorizedRuleTypes: AuthorizedRuleTypes; }> { - return this._getAuthorizedRuleTypesWithAuthorizedConsumers( - new Set(this.ruleTypeRegistry.getAllTypes()), - operations, - authorizationEntity, - new Set(featureIds) - ); + return this._getAuthorizedRuleTypesWithAuthorizedConsumers({ + operations: params.operations, + authorizationEntity: params.authorizationEntity, + }); } public async ensureAuthorized({ @@ -237,68 +266,58 @@ export class AlertingAuthorization { } } - public async getFindAuthorizationFilter( - authorizationEntity: AlertingAuthorizationEntity, - filterOpts: AlertingAuthorizationFilterOpts, - featuresIds?: Set - ): Promise<{ + public async getFindAuthorizationFilter(params: GetFindAuthorizationFilterParams): Promise<{ filter?: KueryNode | JsonObject; ensureRuleTypeIsAuthorized: (ruleTypeId: string, consumer: string, auth: string) => void; }> { - return this.getAuthorizationFilter( - authorizationEntity, - filterOpts, - ReadOperations.Find, - featuresIds - ); + return this.getAuthorizationFilter({ + ruleTypeIds: params.ruleTypeIds, + operation: ReadOperations.Find, + authorizationEntity: params.authorizationEntity, + filterOpts: params.filterOpts, + }); } public async getAllAuthorizedRuleTypesFindOperation( - authorizationEntity: AlertingAuthorizationEntity, - featuresIds?: Set + params: GetAllAuthorizedRuleTypesFindOperationParams ): Promise { - const { authorizedRuleTypes } = await this._getAuthorizedRuleTypesWithAuthorizedConsumers( - new Set(this.ruleTypeRegistry.getAllTypes()), - [ReadOperations.Find], - authorizationEntity, - featuresIds - ); + const { authorizedRuleTypes } = await this._getAuthorizedRuleTypesWithAuthorizedConsumers({ + ruleTypeIds: params.ruleTypeIds, + operations: [ReadOperations.Find], + authorizationEntity: params.authorizationEntity, + }); return authorizedRuleTypes; } - public async getAuthorizationFilter( - authorizationEntity: AlertingAuthorizationEntity, - filterOpts: AlertingAuthorizationFilterOpts, - operation: WriteOperations | ReadOperations, - featuresIds?: Set - ): Promise<{ + public async getAuthorizationFilter(params: GetAuthorizationFilterParams): Promise<{ filter?: KueryNode | JsonObject; ensureRuleTypeIsAuthorized: (ruleTypeId: string, consumer: string, auth: string) => void; }> { if (this.authorization && this.shouldCheckAuthorization()) { - const { authorizedRuleTypes } = await this._getAuthorizedRuleTypesWithAuthorizedConsumers( - new Set(this.ruleTypeRegistry.getAllTypes()), - [operation], - authorizationEntity, - featuresIds - ); + const { authorizedRuleTypes } = await this._getAuthorizedRuleTypesWithAuthorizedConsumers({ + ruleTypeIds: params.ruleTypeIds, + operations: [params.operation], + authorizationEntity: params.authorizationEntity, + }); if (!authorizedRuleTypes.size) { throw Boom.forbidden( - `Unauthorized to ${operation} ${authorizationEntity}s for any rule types` + `Unauthorized to ${params.operation} ${params.authorizationEntity}s for any rule types` ); } return { filter: asFiltersByRuleTypeAndConsumer( authorizedRuleTypes, - filterOpts, + params.filterOpts, this.spaceId ) as JsonObject, ensureRuleTypeIsAuthorized: (ruleTypeId: string, consumer: string, authType: string) => { - if (!authorizedRuleTypes.has(ruleTypeId) || authType !== authorizationEntity) { - throw Boom.forbidden(getUnauthorizedMessage(ruleTypeId, consumer, operation, authType)); + if (!authorizedRuleTypes.has(ruleTypeId) || authType !== params.authorizationEntity) { + throw Boom.forbidden( + getUnauthorizedMessage(ruleTypeId, consumer, params.operation, authType) + ); } const authorizedRuleType = authorizedRuleTypes.get(ruleTypeId)!; @@ -306,7 +325,12 @@ export class AlertingAuthorization { if (!authorizedConsumers[consumer]) { throw Boom.forbidden( - getUnauthorizedMessage(ruleTypeId, consumer, operation, authorizationEntity) + getUnauthorizedMessage( + ruleTypeId, + consumer, + params.operation, + params.authorizationEntity + ) ); } }, @@ -314,42 +338,40 @@ export class AlertingAuthorization { } return { - filter: asFiltersBySpaceId(filterOpts, this.spaceId) as JsonObject, + filter: asFiltersBySpaceId(params.filterOpts, this.spaceId) as JsonObject, ensureRuleTypeIsAuthorized: (ruleTypeId: string, consumer: string, authType: string) => {}, }; } public async getAuthorizedRuleTypes( - ruleTypeIds: Set, - operations: Array, - authorizationEntity: AlertingAuthorizationEntity + params: GetAuthorizedRuleTypesParams ): Promise { - const { authorizedRuleTypes } = await this._getAuthorizedRuleTypesWithAuthorizedConsumers( - ruleTypeIds, - operations, - authorizationEntity - ); + const { authorizedRuleTypes } = await this._getAuthorizedRuleTypesWithAuthorizedConsumers({ + ruleTypeIds: params.ruleTypeIds, + operations: params.operations, + authorizationEntity: params.authorizationEntity, + }); return authorizedRuleTypes; } private async _getAuthorizedRuleTypesWithAuthorizedConsumers( - ruleTypeIds: Set, - operations: Array, - authorizationEntity: AlertingAuthorizationEntity, - consumers?: Set + params: GetAuthorizedRuleTypesWithAuthorizedConsumersParams ): Promise<{ username?: string; hasAllRequested: boolean; authorizedRuleTypes: Map; }> { + const { operations, authorizationEntity } = params; + const ruleTypeIds = params.ruleTypeIds + ? new Set(params.ruleTypeIds) + : new Set(this.ruleTypeRegistry.getAllTypes()); + const requiredPrivileges = new Map< string, { ruleTypeId: string; consumer: string; operation: ReadOperations | WriteOperations } >(); - const consumersToAuthorize: Set = consumers ?? this.allRegisteredConsumers; - if (this.authorization && this.shouldCheckAuthorization()) { const authorizedRuleTypes = new Map(); @@ -367,18 +389,9 @@ export class AlertingAuthorization { } const ruleType = this.ruleTypeRegistry.get(ruleTypeId)!; + const ruleTypeConsumers = this.ruleTypesConsumersMap.get(ruleTypeId) ?? new Set(); - for (const consumerToAuthorize of consumersToAuthorize) { - const ruleTypeConsumers = this.ruleTypesConsumersMap.get(ruleTypeId); - - /** - * Skip if the consumer is not configured for the - * specific rule type when configuring a feature - */ - if (!ruleTypeConsumers?.has(consumerToAuthorize)) { - continue; - } - + for (const consumerToAuthorize of ruleTypeConsumers) { for (const operation of operations) { requiredPrivileges.set( this.authorization.actions.alerting.get( diff --git a/x-pack/plugins/rule_registry/server/lib/get_authz_filter.ts b/x-pack/plugins/rule_registry/server/lib/get_authz_filter.ts index e1524b99f88d98..0a768446b59204 100644 --- a/x-pack/plugins/rule_registry/server/lib/get_authz_filter.ts +++ b/x-pack/plugins/rule_registry/server/lib/get_authz_filter.ts @@ -20,16 +20,16 @@ import { export async function getAuthzFilter( authorization: PublicMethodsOf, operation: WriteOperations.Update | ReadOperations.Get | ReadOperations.Find, - featuresIds?: Set + ruleTypeIds?: string[] ) { - const { filter } = await authorization.getAuthorizationFilter( - AlertingAuthorizationEntity.Alert, - { + const { filter } = await authorization.getAuthorizationFilter({ + authorizationEntity: AlertingAuthorizationEntity.Alert, + filterOpts: { type: AlertingAuthorizationFilterType.ESDSL, fieldNames: { consumer: ALERT_RULE_CONSUMER, ruleTypeId: ALERT_RULE_TYPE_ID }, }, operation, - featuresIds - ); + ruleTypeIds, + }); return filter; } diff --git a/x-pack/plugins/rule_registry/server/search_strategy/search_strategy.test.ts b/x-pack/plugins/rule_registry/server/search_strategy/search_strategy.test.ts index 23061ba1e64509..27a58d63f056af 100644 --- a/x-pack/plugins/rule_registry/server/search_strategy/search_strategy.test.ts +++ b/x-pack/plugins/rule_registry/server/search_strategy/search_strategy.test.ts @@ -7,7 +7,6 @@ import { of } from 'rxjs'; import { merge } from 'lodash'; import { loggerMock } from '@kbn/logging-mocks'; -import { AlertConsumers } from '@kbn/rule-data-utils'; import { ALERT_EVENTS_FIELDS } from '@kbn/alerts-as-data-utils'; import { ruleRegistrySearchStrategyProvider, EMPTY_RESPONSE } from './search_strategy'; import { dataPluginMock } from '@kbn/data-plugin/server/mocks'; @@ -79,6 +78,13 @@ describe('ruleRegistrySearchStrategyProvider()', () => { const authorizationMock = alertingAuthorizationMock.create(); alerting.getAlertingAuthorizationWithRequest.mockResolvedValue(authorizationMock); alerting.getAlertIndicesAlias = getAlertIndicesAliasMock; + alerting.listTypes.mockReturnValue( + // @ts-expect-error: rule type properties are not needed for the test + new Map([ + ['.es-query', {}], + ['siem.esqlRule', {}], + ]) + ); data.search.getSearchStrategy.mockImplementation(() => { return { @@ -114,7 +120,7 @@ describe('ruleRegistrySearchStrategyProvider()', () => { getAuthorizedRuleTypesMock.mockResolvedValue([]); getAlertIndicesAliasMock.mockReturnValue(['observability-logs']); const request: RuleRegistrySearchRequest = { - featureIds: [AlertConsumers.LOGS], + ruleTypeIds: ['.es-query'], }; const options = {}; const deps = { @@ -132,7 +138,7 @@ describe('ruleRegistrySearchStrategyProvider()', () => { it('should return an empty response if no valid indices are found', async () => { const request: RuleRegistrySearchRequest = { - featureIds: [AlertConsumers.LOGS], + ruleTypeIds: ['.es-query'], }; const options = {}; const deps = { @@ -150,9 +156,9 @@ describe('ruleRegistrySearchStrategyProvider()', () => { expect(result).toBe(EMPTY_RESPONSE); }); - it('should not apply rbac filters for siem', async () => { + it('should not apply rbac filters for siem rule types', async () => { const request: RuleRegistrySearchRequest = { - featureIds: [AlertConsumers.SIEM], + ruleTypeIds: ['siem.esqlRule'], }; const options = {}; const deps = { @@ -170,9 +176,9 @@ describe('ruleRegistrySearchStrategyProvider()', () => { expect(getAuthzFilterSpy).not.toHaveBeenCalled(); }); - it('should throw an error if requesting multiple featureIds and one is SIEM', async () => { + it('should throw an error if requesting multiple rule types and one is for siem', async () => { const request: RuleRegistrySearchRequest = { - featureIds: [AlertConsumers.SIEM, AlertConsumers.LOGS], + ruleTypeIds: ['.es-query', 'siem.esqlRule'], }; const options = {}; const deps = { @@ -197,7 +203,7 @@ describe('ruleRegistrySearchStrategyProvider()', () => { it('should use internal user when requesting o11y alerts as RBAC is applied', async () => { const request: RuleRegistrySearchRequest = { - featureIds: [AlertConsumers.LOGS], + ruleTypeIds: ['.es-query'], }; const options = {}; const deps = { @@ -217,7 +223,7 @@ describe('ruleRegistrySearchStrategyProvider()', () => { it('should use scoped user when requesting siem alerts as RBAC is not applied', async () => { const request: RuleRegistrySearchRequest = { - featureIds: [AlertConsumers.SIEM], + ruleTypeIds: ['siem.esqlRule'], }; const options = {}; const deps = { @@ -238,7 +244,7 @@ describe('ruleRegistrySearchStrategyProvider()', () => { it('should support pagination', async () => { const request: RuleRegistrySearchRequest = { - featureIds: [AlertConsumers.LOGS], + ruleTypeIds: ['.es-query'], pagination: { pageSize: 10, pageIndex: 0, @@ -267,7 +273,7 @@ describe('ruleRegistrySearchStrategyProvider()', () => { it('should support sorting', async () => { const request: RuleRegistrySearchRequest = { - featureIds: [AlertConsumers.LOGS], + ruleTypeIds: ['.es-query'], sort: [ { test: { @@ -296,7 +302,7 @@ describe('ruleRegistrySearchStrategyProvider()', () => { it('passes the query ids if provided', async () => { const request: RuleRegistrySearchRequest = { - featureIds: [AlertConsumers.SIEM], + ruleTypeIds: ['siem.esqlRule'], query: { ids: { values: ['test-id'] }, }, @@ -356,7 +362,7 @@ describe('ruleRegistrySearchStrategyProvider()', () => { it('passes the fields if provided', async () => { const request: RuleRegistrySearchRequest = { - featureIds: [AlertConsumers.SIEM], + ruleTypeIds: ['siem.esqlRule'], query: { ids: { values: ['test-id'] }, }, diff --git a/x-pack/plugins/rule_registry/server/search_strategy/search_strategy.ts b/x-pack/plugins/rule_registry/server/search_strategy/search_strategy.ts index 382648f517bd3e..65545c47e1f08b 100644 --- a/x-pack/plugins/rule_registry/server/search_strategy/search_strategy.ts +++ b/x-pack/plugins/rule_registry/server/search_strategy/search_strategy.ts @@ -8,7 +8,6 @@ import { map, mergeMap, catchError } from 'rxjs'; import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { Logger } from '@kbn/core/server'; import { from, of } from 'rxjs'; -import { isValidFeatureId, AlertConsumers } from '@kbn/rule-data-utils'; import { ENHANCED_ES_SEARCH_STRATEGY } from '@kbn/data-plugin/common'; import { ISearchStrategy, PluginStart } from '@kbn/data-plugin/server'; import { @@ -19,6 +18,7 @@ import { import { SecurityPluginSetup } from '@kbn/security-plugin/server'; import { SpacesPluginStart } from '@kbn/spaces-plugin/server'; import { buildAlertFieldsRequest } from '@kbn/alerts-as-data-utils'; +import { partition } from 'lodash'; import type { RuleRegistrySearchRequest, RuleRegistrySearchResponse } from '../../common'; import { MAX_ALERT_SEARCH_SIZE } from '../../common/constants'; import { AlertAuditAction, alertAuditEvent } from '..'; @@ -44,51 +44,64 @@ export const ruleRegistrySearchStrategyProvider = ( const requestUserEs = data.search.getSearchStrategy(ENHANCED_ES_SEARCH_STRATEGY); return { search: (request, options, deps) => { + let params = {}; + // SIEM uses RBAC fields in their alerts but also utilizes ES DLS which // is different than every other solution so we need to special case // those requests. - let siemRequest = false; - let params = {}; - if (request.featureIds.length === 1 && request.featureIds[0] === AlertConsumers.SIEM) { - siemRequest = true; - } else if (request.featureIds.includes(AlertConsumers.SIEM)) { + const isAnyRuleTypeESAuthorized = request.ruleTypeIds.some((ruleTypeId) => + ruleTypeId.startsWith('siem.') + ); + + const isEachRuleTypeESAuthorized = request.ruleTypeIds.every((ruleTypeId) => + ruleTypeId.startsWith('siem.') + ); + + const registeredRuleTypes = alerting.listTypes(); + + const [validRuleTypeIds, invalidRuleTypeIds] = partition(request.ruleTypeIds, (ruleTypeId) => + registeredRuleTypes.has(ruleTypeId) + ); + + if (isAnyRuleTypeESAuthorized && !isEachRuleTypeESAuthorized) { throw new Error( - `The ${RULE_SEARCH_STRATEGY_NAME} search strategy is unable to accommodate requests containing multiple feature IDs and one of those IDs is SIEM.` + `The ${RULE_SEARCH_STRATEGY_NAME} search strategy is unable to accommodate requests containing multiple rule types with mixed authorization.` ); } - request.featureIds.forEach((featureId) => { - if (!isValidFeatureId(featureId)) { - logger.warn( - `Found invalid feature '${featureId}' while using ${RULE_SEARCH_STRATEGY_NAME} search strategy. No alert data from this feature will be searched.` - ); - } + + invalidRuleTypeIds.forEach((ruleTypeId) => { + logger.warn( + `Found invalid rule type '${ruleTypeId}' while using ${RULE_SEARCH_STRATEGY_NAME} search strategy. No alert data from this rule type will be searched.` + ); }); const securityAuditLogger = security?.audit.asScoped(deps.request); const getActiveSpace = async () => spaces?.spacesService.getActiveSpace(deps.request); - const getAsync = async (featureIds: string[]) => { + + const getAsync = async (ruleTypeIds: string[]) => { const [space, authorization] = await Promise.all([ getActiveSpace(), alerting.getAlertingAuthorizationWithRequest(deps.request), ]); + let authzFilter; - const fIds = new Set(featureIds); - if (!siemRequest && featureIds.length > 0) { + + if (!isAnyRuleTypeESAuthorized && ruleTypeIds.length > 0) { authzFilter = (await getAuthzFilter( authorization, ReadOperations.Find, - fIds + ruleTypeIds )) as estypes.QueryDslQueryContainer; } - const authorizedRuleTypes = await authorization.getAllAuthorizedRuleTypesFindOperation( - AlertingAuthorizationEntity.Alert, - fIds - ); + const authorizedRuleTypes = await authorization.getAllAuthorizedRuleTypesFindOperation({ + authorizationEntity: AlertingAuthorizationEntity.Alert, + ruleTypeIds, + }); return { space, authzFilter, authorizedRuleTypes }; }; - return from(getAsync(request.featureIds)).pipe( + return from(getAsync(validRuleTypeIds)).pipe( mergeMap(({ space, authzFilter, authorizedRuleTypes }) => { const authorizedRuleTypesIds = Array.from(authorizedRuleTypes.keys()); const ruleTypes = (authorizedRuleTypesIds ?? []).filter( @@ -128,7 +141,7 @@ export const ruleRegistrySearchStrategyProvider = ( let fields = request?.fields ?? []; fields.push({ field: 'kibana.alert.*', include_unmapped: false }); - if (siemRequest) { + if (isAnyRuleTypeESAuthorized) { fields.push({ field: 'signal.*', include_unmapped: false }); fields = fields.concat(buildAlertFieldsRequest([], false)); } else { @@ -151,7 +164,7 @@ export const ruleRegistrySearchStrategyProvider = ( ...(request.runtimeMappings ? { runtime_mappings: request.runtimeMappings } : {}), }, }; - return (siemRequest ? requestUserEs : internalUserEs).search( + return (isAnyRuleTypeESAuthorized ? requestUserEs : internalUserEs).search( { id: request.id, params }, options, deps From c2371d03ff34a02a0a335051c2c07c7ae4788c52 Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Sun, 28 Jul 2024 10:20:01 +0300 Subject: [PATCH 035/106] Fix usage of alerting authorization methods --- .../lib/set_alerts_to_untracked.ts | 12 ++-- .../backfill/methods/find/find_backfill.ts | 10 +-- .../methods/schedule/schedule_backfill.ts | 8 +-- .../rule/methods/aggregate/aggregate_rules.ts | 13 ++-- .../rule/methods/aggregate/types/index.ts | 2 +- .../rule/methods/bulk_edit/bulk_edit_rules.ts | 8 +-- .../rule/methods/find/find_rules.ts | 14 ++-- .../find/schemas/find_rules_schemas.ts | 4 +- .../rule/methods/tags/get_rule_tags.ts | 8 +-- .../suggestions/values_suggestion_alerts.ts | 8 +-- .../suggestions/values_suggestion_rules.ts | 10 ++- .../lib/get_authorization_filter.ts | 8 +-- .../methods/get_action_error_log.ts | 10 +-- .../rules_client/methods/get_execution_kpi.ts | 10 +-- .../rules_client/methods/get_execution_log.ts | 10 +-- .../rules_client/methods/list_rule_types.ts | 10 +-- .../server/alert_data_client/alerts_client.ts | 65 +++++++++---------- 17 files changed, 103 insertions(+), 107 deletions(-) diff --git a/x-pack/plugins/alerting/server/alerts_service/lib/set_alerts_to_untracked.ts b/x-pack/plugins/alerting/server/alerts_service/lib/set_alerts_to_untracked.ts index 94394f552191bd..89c8d671de6a08 100644 --- a/x-pack/plugins/alerting/server/alerts_service/lib/set_alerts_to_untracked.ts +++ b/x-pack/plugins/alerting/server/alerts_service/lib/set_alerts_to_untracked.ts @@ -32,7 +32,7 @@ export interface SetAlertsToUntrackedParams { alertUuids?: string[]; query?: QueryDslQueryContainer[]; spaceId?: RulesClientContext['spaceId']; - featureIds?: string[]; + ruleTypeIds?: string[]; isUsingQuery?: boolean; getAllAuthorizedRuleTypesFindOperation?: RulesClientContext['authorization']['getAllAuthorizedRuleTypesFindOperation']; getAlertIndicesAlias?: RulesClientContext['getAlertIndicesAlias']; @@ -155,17 +155,17 @@ const ensureAuthorizedToUntrack = async (params: SetAlertsToUntrackedParamsWithD }; const getAuthorizedAlertsIndices = async ({ - featureIds, + ruleTypeIds, getAllAuthorizedRuleTypesFindOperation, getAlertIndicesAlias, spaceId, logger, }: SetAlertsToUntrackedParamsWithDep) => { try { - const authorizedRuleTypes = await getAllAuthorizedRuleTypesFindOperation?.( - AlertingAuthorizationEntity.Alert, - new Set(featureIds) - ); + const authorizedRuleTypes = await getAllAuthorizedRuleTypesFindOperation?.({ + authorizationEntity: AlertingAuthorizationEntity.Alert, + ruleTypeIds, + }); if (authorizedRuleTypes) { return getAlertIndicesAlias?.( diff --git a/x-pack/plugins/alerting/server/application/backfill/methods/find/find_backfill.ts b/x-pack/plugins/alerting/server/application/backfill/methods/find/find_backfill.ts index 522128d0385f89..3482d854bda1f6 100644 --- a/x-pack/plugins/alerting/server/application/backfill/methods/find/find_backfill.ts +++ b/x-pack/plugins/alerting/server/application/backfill/methods/find/find_backfill.ts @@ -40,16 +40,16 @@ export async function findBackfill( let authorizationTuple; try { - authorizationTuple = await context.authorization.getFindAuthorizationFilter( - AlertingAuthorizationEntity.Rule, - { + authorizationTuple = await context.authorization.getFindAuthorizationFilter({ + authorizationEntity: AlertingAuthorizationEntity.Rule, + filterOpts: { type: AlertingAuthorizationFilterType.KQL, fieldNames: { ruleTypeId: 'ad_hoc_run_params.attributes.rule.alertTypeId', consumer: 'ad_hoc_run_params.attributes.rule.consumer', }, - } - ); + }, + }); } catch (error) { context.auditLogger?.log( adHocRunAuditEvent({ diff --git a/x-pack/plugins/alerting/server/application/backfill/methods/schedule/schedule_backfill.ts b/x-pack/plugins/alerting/server/application/backfill/methods/schedule/schedule_backfill.ts index 9ff777f0108c66..60b98b407a49d0 100644 --- a/x-pack/plugins/alerting/server/application/backfill/methods/schedule/schedule_backfill.ts +++ b/x-pack/plugins/alerting/server/application/backfill/methods/schedule/schedule_backfill.ts @@ -46,10 +46,10 @@ export async function scheduleBackfill( let authorizationTuple; try { - authorizationTuple = await context.authorization.getFindAuthorizationFilter( - AlertingAuthorizationEntity.Rule, - alertingAuthorizationFilterOpts - ); + authorizationTuple = await context.authorization.getFindAuthorizationFilter({ + authorizationEntity: AlertingAuthorizationEntity.Rule, + filterOpts: alertingAuthorizationFilterOpts, + }); } catch (error) { context.auditLogger?.log( ruleAuditEvent({ diff --git a/x-pack/plugins/alerting/server/application/rule/methods/aggregate/aggregate_rules.ts b/x-pack/plugins/alerting/server/application/rule/methods/aggregate/aggregate_rules.ts index 9011b971e629a5..4418e8ccf8c74a 100644 --- a/x-pack/plugins/alerting/server/application/rule/methods/aggregate/aggregate_rules.ts +++ b/x-pack/plugins/alerting/server/application/rule/methods/aggregate/aggregate_rules.ts @@ -6,7 +6,6 @@ */ import { KueryNode, nodeBuilder } from '@kbn/es-query'; -import { isEmpty } from 'lodash'; import { findRulesSo } from '../../../../data/rule'; import { AlertingAuthorizationEntity } from '../../../../authorization'; import { ruleAuditEvent, RuleAuditAction } from '../../../../rules_client/common/audit_events'; @@ -22,15 +21,15 @@ export async function aggregateRules>( params: AggregateParams ): Promise { const { options = {}, aggs } = params; - const { filter, page = 1, perPage = 0, filterConsumers, ...restOptions } = options; + const { filter, page = 1, perPage = 0, ruleTypeIds, ...restOptions } = options; let authorizationTuple; try { - authorizationTuple = await context.authorization.getFindAuthorizationFilter( - AlertingAuthorizationEntity.Rule, - alertingAuthorizationFilterOpts, - isEmpty(filterConsumers) ? undefined : new Set(filterConsumers) - ); + authorizationTuple = await context.authorization.getFindAuthorizationFilter({ + authorizationEntity: AlertingAuthorizationEntity.Rule, + filterOpts: alertingAuthorizationFilterOpts, + ruleTypeIds, + }); validateRuleAggregationFields(aggs); aggregateOptionsSchema.validate(options); } catch (error) { diff --git a/x-pack/plugins/alerting/server/application/rule/methods/aggregate/types/index.ts b/x-pack/plugins/alerting/server/application/rule/methods/aggregate/types/index.ts index 2156fb91e87786..47e76dc7500e6d 100644 --- a/x-pack/plugins/alerting/server/application/rule/methods/aggregate/types/index.ts +++ b/x-pack/plugins/alerting/server/application/rule/methods/aggregate/types/index.ts @@ -19,7 +19,7 @@ export type AggregateOptions = TypeOf & { filter?: string | KueryNode; page?: AggregateOptionsSchemaTypes['page']; perPage?: AggregateOptionsSchemaTypes['perPage']; - filterConsumers?: string[]; + ruleTypeIds?: string[]; }; export interface AggregateParams { diff --git a/x-pack/plugins/alerting/server/application/rule/methods/bulk_edit/bulk_edit_rules.ts b/x-pack/plugins/alerting/server/application/rule/methods/bulk_edit/bulk_edit_rules.ts index 8bd10fe722c1df..179383044b99b2 100644 --- a/x-pack/plugins/alerting/server/application/rule/methods/bulk_edit/bulk_edit_rules.ts +++ b/x-pack/plugins/alerting/server/application/rule/methods/bulk_edit/bulk_edit_rules.ts @@ -133,10 +133,10 @@ export async function bulkEditRules( const qNodeFilter = ids ? convertRuleIdsToKueryNode(ids) : qNodeQueryFilter; let authorizationTuple; try { - authorizationTuple = await context.authorization.getFindAuthorizationFilter( - AlertingAuthorizationEntity.Rule, - alertingAuthorizationFilterOpts - ); + authorizationTuple = await context.authorization.getFindAuthorizationFilter({ + authorizationEntity: AlertingAuthorizationEntity.Rule, + filterOpts: alertingAuthorizationFilterOpts, + }); } catch (error) { context.auditLogger?.log( ruleAuditEvent({ diff --git a/x-pack/plugins/alerting/server/application/rule/methods/find/find_rules.ts b/x-pack/plugins/alerting/server/application/rule/methods/find/find_rules.ts index efd4c6fe10e74f..e3ad28f35c6867 100644 --- a/x-pack/plugins/alerting/server/application/rule/methods/find/find_rules.ts +++ b/x-pack/plugins/alerting/server/application/rule/methods/find/find_rules.ts @@ -6,7 +6,7 @@ */ import Boom from '@hapi/boom'; -import { isEmpty, pick } from 'lodash'; +import { pick } from 'lodash'; import { KueryNode, nodeBuilder } from '@kbn/es-query'; import { AlertConsumers } from '@kbn/rule-data-utils'; import { AlertingAuthorizationEntity } from '../../../../authorization/types'; @@ -46,7 +46,7 @@ export async function findRules( ): Promise> { const { options, excludeFromPublicApi = false, includeSnoozeData = false } = params || {}; - const { fields, filterConsumers, ...restOptions } = options || {}; + const { fields, filterRuleTypeIds, ...restOptions } = options || {}; try { if (params) { @@ -58,11 +58,11 @@ export async function findRules( let authorizationTuple; try { - authorizationTuple = await context.authorization.getFindAuthorizationFilter( - AlertingAuthorizationEntity.Rule, - alertingAuthorizationFilterOpts, - isEmpty(filterConsumers) ? undefined : new Set(filterConsumers) - ); + authorizationTuple = await context.authorization.getFindAuthorizationFilter({ + authorizationEntity: AlertingAuthorizationEntity.Rule, + filterOpts: alertingAuthorizationFilterOpts, + ruleTypeIds: filterRuleTypeIds, + }); } catch (error) { context.auditLogger?.log( ruleAuditEvent({ diff --git a/x-pack/plugins/alerting/server/application/rule/methods/find/schemas/find_rules_schemas.ts b/x-pack/plugins/alerting/server/application/rule/methods/find/schemas/find_rules_schemas.ts index b766ffc283bb24..31d6cadaebff0b 100644 --- a/x-pack/plugins/alerting/server/application/rule/methods/find/schemas/find_rules_schemas.ts +++ b/x-pack/plugins/alerting/server/application/rule/methods/find/schemas/find_rules_schemas.ts @@ -28,7 +28,7 @@ export const findRulesOptionsSchema = schema.object( filter: schema.maybe( schema.oneOf([schema.string(), schema.recordOf(schema.string(), schema.any())]) ), - filterConsumers: schema.maybe(schema.arrayOf(schema.string())), + filterRuleTypeIds: schema.maybe(schema.arrayOf(schema.string())), }, { unknowns: 'allow' } ); @@ -37,5 +37,5 @@ export const findRulesParamsSchema = schema.object({ options: schema.maybe(findRulesOptionsSchema), excludeFromPublicApi: schema.maybe(schema.boolean()), includeSnoozeData: schema.maybe(schema.boolean()), - featureIds: schema.maybe(schema.arrayOf(schema.string())), + ruleTypeIds: schema.maybe(schema.arrayOf(schema.string())), }); diff --git a/x-pack/plugins/alerting/server/application/rule/methods/tags/get_rule_tags.ts b/x-pack/plugins/alerting/server/application/rule/methods/tags/get_rule_tags.ts index c26fae42ce324e..84a05ac67057aa 100644 --- a/x-pack/plugins/alerting/server/application/rule/methods/tags/get_rule_tags.ts +++ b/x-pack/plugins/alerting/server/application/rule/methods/tags/get_rule_tags.ts @@ -33,10 +33,10 @@ export async function getRuleTags( let authorizationTuple; try { - authorizationTuple = await context.authorization.getFindAuthorizationFilter( - AlertingAuthorizationEntity.Rule, - alertingAuthorizationFilterOpts - ); + authorizationTuple = await context.authorization.getFindAuthorizationFilter({ + authorizationEntity: AlertingAuthorizationEntity.Rule, + filterOpts: alertingAuthorizationFilterOpts, + }); } catch (error) { context.auditLogger?.log( ruleAuditEvent({ diff --git a/x-pack/plugins/alerting/server/routes/suggestions/values_suggestion_alerts.ts b/x-pack/plugins/alerting/server/routes/suggestions/values_suggestion_alerts.ts index 12d7860bf7f1fa..e3cc1deb7dd652 100644 --- a/x-pack/plugins/alerting/server/routes/suggestions/values_suggestion_alerts.ts +++ b/x-pack/plugins/alerting/server/routes/suggestions/values_suggestion_alerts.ts @@ -80,10 +80,10 @@ export function registerAlertsValueSuggestionsRoute( try { const authorization = rulesClient.getAuthorization(); - authorizationTuple = await authorization.getFindAuthorizationFilter( - AlertingAuthorizationEntity.Alert, - alertingAuthorizationFilterOpts - ); + authorizationTuple = await authorization.getFindAuthorizationFilter({ + authorizationEntity: AlertingAuthorizationEntity.Alert, + filterOpts: alertingAuthorizationFilterOpts, + }); authorizedRuleType = await authorization.getAllAuthorizedRuleTypesFindOperation( AlertingAuthorizationEntity.Alert, diff --git a/x-pack/plugins/alerting/server/routes/suggestions/values_suggestion_rules.ts b/x-pack/plugins/alerting/server/routes/suggestions/values_suggestion_rules.ts index c669ee9c0e932b..4b9db8928c804c 100644 --- a/x-pack/plugins/alerting/server/routes/suggestions/values_suggestion_rules.ts +++ b/x-pack/plugins/alerting/server/routes/suggestions/values_suggestion_rules.ts @@ -62,12 +62,10 @@ export function registerRulesValueSuggestionsRoute( const rulesClient = await alertingContext.getRulesClient(); let authorizationTuple; try { - authorizationTuple = await rulesClient - .getAuthorization() - .getFindAuthorizationFilter( - AlertingAuthorizationEntity.Rule, - alertingAuthorizationFilterOpts - ); + authorizationTuple = await rulesClient.getAuthorization().getFindAuthorizationFilter({ + authorizationEntity: AlertingAuthorizationEntity.Rule, + filterOpts: alertingAuthorizationFilterOpts, + }); } catch (error) { rulesClient.getAuditLogger()?.log( ruleAuditEvent({ diff --git a/x-pack/plugins/alerting/server/rules_client/lib/get_authorization_filter.ts b/x-pack/plugins/alerting/server/rules_client/lib/get_authorization_filter.ts index 591ea70972ed9b..591602effc474c 100644 --- a/x-pack/plugins/alerting/server/rules_client/lib/get_authorization_filter.ts +++ b/x-pack/plugins/alerting/server/rules_client/lib/get_authorization_filter.ts @@ -20,10 +20,10 @@ export const getAuthorizationFilter = async ( const authorizationTuple = await withSpan( { name: 'authorization.getFindAuthorizationFilter', type: 'rules' }, () => - context.authorization.getFindAuthorizationFilter( - AlertingAuthorizationEntity.Rule, - alertingAuthorizationFilterOpts - ) + context.authorization.getFindAuthorizationFilter({ + authorizationEntity: AlertingAuthorizationEntity.Rule, + filterOpts: alertingAuthorizationFilterOpts, + }) ); return authorizationTuple.filter; } catch (error) { diff --git a/x-pack/plugins/alerting/server/rules_client/methods/get_action_error_log.ts b/x-pack/plugins/alerting/server/rules_client/methods/get_action_error_log.ts index 3640dbcf62c407..847ba60c32b9af 100644 --- a/x-pack/plugins/alerting/server/rules_client/methods/get_action_error_log.ts +++ b/x-pack/plugins/alerting/server/rules_client/methods/get_action_error_log.ts @@ -108,16 +108,16 @@ export async function getActionErrorLogWithAuth( let authorizationTuple; try { - authorizationTuple = await context.authorization.getFindAuthorizationFilter( - AlertingAuthorizationEntity.Alert, - { + authorizationTuple = await context.authorization.getFindAuthorizationFilter({ + authorizationEntity: AlertingAuthorizationEntity.Alert, + filterOpts: { type: AlertingAuthorizationFilterType.KQL, fieldNames: { ruleTypeId: 'kibana.alert.rule.rule_type_id', consumer: 'kibana.alert.rule.consumer', }, - } - ); + }, + }); } catch (error) { context.auditLogger?.log( ruleAuditEvent({ diff --git a/x-pack/plugins/alerting/server/rules_client/methods/get_execution_kpi.ts b/x-pack/plugins/alerting/server/rules_client/methods/get_execution_kpi.ts index 082071ead79e5a..fa793ae892214c 100644 --- a/x-pack/plugins/alerting/server/rules_client/methods/get_execution_kpi.ts +++ b/x-pack/plugins/alerting/server/rules_client/methods/get_execution_kpi.ts @@ -105,16 +105,16 @@ export async function getGlobalExecutionKpiWithAuth( let authorizationTuple; try { - authorizationTuple = await context.authorization.getFindAuthorizationFilter( - AlertingAuthorizationEntity.Alert, - { + authorizationTuple = await context.authorization.getFindAuthorizationFilter({ + authorizationEntity: AlertingAuthorizationEntity.Alert, + filterOpts: { type: AlertingAuthorizationFilterType.KQL, fieldNames: { ruleTypeId: 'kibana.alert.rule.rule_type_id', consumer: 'kibana.alert.rule.consumer', }, - } - ); + }, + }); } catch (error) { context.auditLogger?.log( ruleAuditEvent({ diff --git a/x-pack/plugins/alerting/server/rules_client/methods/get_execution_log.ts b/x-pack/plugins/alerting/server/rules_client/methods/get_execution_log.ts index f154a8e840be2e..4c346c59a8cacd 100644 --- a/x-pack/plugins/alerting/server/rules_client/methods/get_execution_log.ts +++ b/x-pack/plugins/alerting/server/rules_client/methods/get_execution_log.ts @@ -118,16 +118,16 @@ export async function getGlobalExecutionLogWithAuth( let authorizationTuple; try { - authorizationTuple = await context.authorization.getFindAuthorizationFilter( - AlertingAuthorizationEntity.Alert, - { + authorizationTuple = await context.authorization.getFindAuthorizationFilter({ + authorizationEntity: AlertingAuthorizationEntity.Alert, + filterOpts: { type: AlertingAuthorizationFilterType.KQL, fieldNames: { ruleTypeId: 'kibana.alert.rule.rule_type_id', consumer: 'kibana.alert.rule.consumer', }, - } - ); + }, + }); } catch (error) { context.auditLogger?.log( ruleAuditEvent({ diff --git a/x-pack/plugins/alerting/server/rules_client/methods/list_rule_types.ts b/x-pack/plugins/alerting/server/rules_client/methods/list_rule_types.ts index 7fc11e6fb5c8f4..d1da16c3ae0f7a 100644 --- a/x-pack/plugins/alerting/server/rules_client/methods/list_rule_types.ts +++ b/x-pack/plugins/alerting/server/rules_client/methods/list_rule_types.ts @@ -18,11 +18,11 @@ export async function listRuleTypes( ): Promise { const registeredRuleTypes = context.ruleTypeRegistry.list(); - const authorizedRuleTypes = await context.authorization.getAuthorizedRuleTypes( - new Set(Array.from(registeredRuleTypes.keys()).map((id) => id)), - [ReadOperations.Get, WriteOperations.Create], - AlertingAuthorizationEntity.Rule - ); + const authorizedRuleTypes = await context.authorization.getAuthorizedRuleTypes({ + authorizationEntity: AlertingAuthorizationEntity.Rule, + operations: [ReadOperations.Get, WriteOperations.Create], + ruleTypeIds: Array.from(registeredRuleTypes.keys()).map((id) => id), + }); return Array.from(authorizedRuleTypes.entries()) .filter(([id, _]) => context.ruleTypeRegistry.has(id)) diff --git a/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts b/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts index 5a5c3410720e59..d715e123ef4ee7 100644 --- a/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts +++ b/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts @@ -133,7 +133,7 @@ interface GetAlertSummaryParams { id?: string; gte: string; lte: string; - featureIds: string[]; + ruleTypeIds: string[]; filter?: estypes.QueryDslQueryContainer[]; fixedInterval?: string; } @@ -149,7 +149,7 @@ interface SearchAlertsParams { operation: WriteOperations.Update | ReadOperations.Find | ReadOperations.Get; sort?: estypes.SortOptions[]; lastSortIds?: Array; - featureIds?: string[]; + ruleTypeIds?: string[]; runtimeMappings?: MappingRuntimeFields; } @@ -290,7 +290,7 @@ export class AlertsClient { operation, sort, lastSortIds = [], - featureIds, + ruleTypeIds, runtimeMappings, }: SearchAlertsParams) { try { @@ -311,7 +311,7 @@ export class AlertsClient { alertSpaceId, operation, config, - featureIds ? new Set(featureIds) : undefined + ruleTypeIds ), aggs, _source, @@ -454,13 +454,13 @@ export class AlertsClient { alertSpaceId: string, operation: WriteOperations.Update | ReadOperations.Get | ReadOperations.Find, config: EsQueryConfig, - featuresIds?: Set + ruleTypeIds?: string[] ) { try { const authzFilter = (await getAuthzFilter( this.authorization, operation, - featuresIds + ruleTypeIds )) as Filter; const spacesFilter = getSpacesFilter(alertSpaceId) as unknown as Filter; let esQuery; @@ -636,15 +636,15 @@ export class AlertsClient { public async getAlertSummary({ gte, lte, - featureIds, + ruleTypeIds, filter, fixedInterval = '1m', }: GetAlertSummaryParams) { try { - const indexToUse = await this.getAuthorizedAlertsIndices(featureIds); + const indexToUse = await this.getAuthorizedAlertsIndices(ruleTypeIds); if (isEmpty(indexToUse)) { - throw Boom.badRequest('no featureIds were provided for getting alert summary'); + throw Boom.badRequest('no ruleTypeIds were provided for getting alert summary'); } // first search for the alert by id, then use the alert info to check if user has access to it @@ -707,7 +707,7 @@ export class AlertsClient { }, }, size: 0, - featureIds, + ruleTypeIds, }); let activeAlertCount = 0; @@ -979,7 +979,7 @@ export class AlertsClient { public async find({ aggs, - featureIds, + ruleTypeIds, index, query, search_after: searchAfter, @@ -990,7 +990,7 @@ export class AlertsClient { runtimeMappings, }: { aggs?: object; - featureIds?: string[]; + ruleTypeIds?: string[]; index?: string; query?: object; search_after?: Array; @@ -1002,8 +1002,8 @@ export class AlertsClient { }) { try { let indexToUse = index; - if (featureIds && !isEmpty(featureIds)) { - const tempIndexToUse = await this.getAuthorizedAlertsIndices(featureIds); + if (ruleTypeIds && !isEmpty(ruleTypeIds)) { + const tempIndexToUse = await this.getAuthorizedAlertsIndices(ruleTypeIds); if (!isEmpty(tempIndexToUse)) { indexToUse = (tempIndexToUse ?? []).join(); } @@ -1039,7 +1039,7 @@ export class AlertsClient { * Performs a `find` query to extract aggregations on alert groups */ public getGroupAggregations({ - featureIds, + ruleTypeIds, groupByField, aggregations, filters, @@ -1048,9 +1048,9 @@ export class AlertsClient { sort = [{ unitsCount: { order: 'desc' } }], }: { /** - * The feature ids the alerts belong to, used for authorization + * The rule type IDs the alerts belong to, used for authorization */ - featureIds: string[]; + ruleTypeIds: string[]; /** * The field to group by * @example "kibana.alert.rule.name" @@ -1089,7 +1089,7 @@ export class AlertsClient { ); } return this.find({ - featureIds, + ruleTypeIds, aggs: { groupByFields: { terms: { @@ -1143,12 +1143,12 @@ export class AlertsClient { }); } - public async getAuthorizedAlertsIndices(consumers: string[]): Promise { + public async getAuthorizedAlertsIndices(ruleTypeIds: string[]): Promise { try { - const authorizedRuleTypes = await this.authorization.getAllAuthorizedRuleTypesFindOperation( - AlertingAuthorizationEntity.Alert, - new Set(consumers) - ); + const authorizedRuleTypes = await this.authorization.getAllAuthorizedRuleTypesFindOperation({ + authorizationEntity: AlertingAuthorizationEntity.Alert, + ruleTypeIds, + }); const indices = this.getAlertIndicesAlias( Array.from(authorizedRuleTypes.keys()).map((id) => id), @@ -1169,14 +1169,13 @@ export class AlertsClient { try { const featureIds = this.ruleDataService.findFeatureIdsByRegistrationContexts(RegistrationContexts); + if (featureIds.length > 0) { - // ATTENTION FUTURE DEVELOPER when you are a super user the augmentedRuleTypes.authorizedRuleTypes will - // return all of the features that you can access and does not care about your featureIds - const augmentedRuleTypes = await this.authorization.getAllAuthorizedRuleTypes( - featureIds, - [ReadOperations.Find, ReadOperations.Get, WriteOperations.Update], - AlertingAuthorizationEntity.Alert - ); + const augmentedRuleTypes = await this.authorization.getAllAuthorizedRuleTypes({ + operations: [ReadOperations.Find, ReadOperations.Get, WriteOperations.Update], + authorizationEntity: AlertingAuthorizationEntity.Alert, + }); + // As long as the user can read a minimum of one type of rule type produced by the provided feature, // the user should be provided that features' alerts index. // Limiting which alerts that user can read on that index will be done via the findAuthorizationFilter @@ -1202,12 +1201,12 @@ export class AlertsClient { } public async getBrowserFields({ - featureIds, + ruleTypeIds, indices, metaFields, allowNoIndex, }: { - featureIds: string[]; + ruleTypeIds: string[]; indices: string[]; metaFields: string[]; allowNoIndex: boolean; @@ -1217,7 +1216,7 @@ export class AlertsClient { const fieldsForAAD = new Set(); for (const rule of ruleTypeList.values()) { - if (featureIds.includes(rule.producer) && rule.hasFieldsForAAD) { + if (ruleTypeIds.includes(rule.id) && rule.hasFieldsForAAD) { (rule.fieldsForAAD ?? []).forEach((f) => { fieldsForAAD.add(f); }); From 3d89a36bf626fb30e4ec22b6a9b69460465435b7 Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Sun, 28 Jul 2024 10:30:02 +0300 Subject: [PATCH 036/106] Delete _feature_ids route --- .../server/alert_data_client/alerts_client.ts | 39 --------- .../routes/__mocks__/request_responses.ts | 7 -- ...ature_ids_by_registration_contexts.test.ts | 78 ------------------ ...et_feature_ids_by_registration_contexts.ts | 66 ---------------- ...et_feature_ids_by_registration_contexts.ts | 79 ------------------- .../security_and_spaces/tests/basic/index.ts | 1 - 6 files changed, 270 deletions(-) delete mode 100644 x-pack/plugins/rule_registry/server/routes/get_feature_ids_by_registration_contexts.test.ts delete mode 100644 x-pack/plugins/rule_registry/server/routes/get_feature_ids_by_registration_contexts.ts delete mode 100644 x-pack/test/rule_registry/security_and_spaces/tests/basic/get_feature_ids_by_registration_contexts.ts diff --git a/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts b/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts index d715e123ef4ee7..eacc2bb8329178 100644 --- a/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts +++ b/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts @@ -15,9 +15,7 @@ import { ALERT_STATUS, getEsQueryConfig, getSafeSortIds, - isValidFeatureId, STATUS_VALUES, - ValidFeatureId, ALERT_STATUS_RECOVERED, ALERT_END, ALERT_STATUS_ACTIVE, @@ -1163,43 +1161,6 @@ export class AlertsClient { } } - public async getFeatureIdsByRegistrationContexts( - RegistrationContexts: string[] - ): Promise { - try { - const featureIds = - this.ruleDataService.findFeatureIdsByRegistrationContexts(RegistrationContexts); - - if (featureIds.length > 0) { - const augmentedRuleTypes = await this.authorization.getAllAuthorizedRuleTypes({ - operations: [ReadOperations.Find, ReadOperations.Get, WriteOperations.Update], - authorizationEntity: AlertingAuthorizationEntity.Alert, - }); - - // As long as the user can read a minimum of one type of rule type produced by the provided feature, - // the user should be provided that features' alerts index. - // Limiting which alerts that user can read on that index will be done via the findAuthorizationFilter - const authorizedFeatures = new Set(); - for (const [ruleTypeId] of augmentedRuleTypes.authorizedRuleTypes.entries()) { - const ruleType = this.getRuleType(ruleTypeId); - authorizedFeatures.add(ruleType.producer); - } - - const validAuthorizedFeatures = Array.from(authorizedFeatures).filter( - (feature): feature is ValidFeatureId => - featureIds.includes(feature) && isValidFeatureId(feature) - ); - - return validAuthorizedFeatures; - } - return featureIds; - } catch (exc) { - const errMessage = `getFeatureIdsByRegistrationContexts failed to get feature ids: ${exc}`; - this.logger.error(errMessage); - throw Boom.failedDependency(errMessage); - } - } - public async getBrowserFields({ ruleTypeIds, indices, diff --git a/x-pack/plugins/rule_registry/server/routes/__mocks__/request_responses.ts b/x-pack/plugins/rule_registry/server/routes/__mocks__/request_responses.ts index d3857c4c49f179..18099d01a4ed24 100644 --- a/x-pack/plugins/rule_registry/server/routes/__mocks__/request_responses.ts +++ b/x-pack/plugins/rule_registry/server/routes/__mocks__/request_responses.ts @@ -33,13 +33,6 @@ export const getUpdateRequest = () => }, }); -export const getReadFeatureIdsRequest = () => - requestMock.create({ - method: 'get', - path: `${BASE_RAC_ALERTS_API_PATH}/_feature_ids`, - query: { registrationContext: ['security'] }, - }); - export const getO11yBrowserFields = () => requestMock.create({ method: 'get', diff --git a/x-pack/plugins/rule_registry/server/routes/get_feature_ids_by_registration_contexts.test.ts b/x-pack/plugins/rule_registry/server/routes/get_feature_ids_by_registration_contexts.test.ts deleted file mode 100644 index 80f2b4e6026d0d..00000000000000 --- a/x-pack/plugins/rule_registry/server/routes/get_feature_ids_by_registration_contexts.test.ts +++ /dev/null @@ -1,78 +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 { BASE_RAC_ALERTS_API_PATH } from '../../common/constants'; -import { getFeatureIdsByRegistrationContexts } from './get_feature_ids_by_registration_contexts'; -import { requestContextMock } from './__mocks__/request_context'; -import { getReadFeatureIdsRequest } from './__mocks__/request_responses'; -import { requestMock, serverMock } from './__mocks__/server'; - -describe('getFeatureIdsByRegistrationContexts', () => { - let server: ReturnType; - let { clients, context } = requestContextMock.createTools(); - - beforeEach(async () => { - server = serverMock.create(); - ({ clients, context } = requestContextMock.createTools()); - - clients.rac.getFeatureIdsByRegistrationContexts.mockResolvedValue(['siem']); - - getFeatureIdsByRegistrationContexts(server.router); - }); - - test('returns 200 when querying for features ids', async () => { - const response = await server.inject(getReadFeatureIdsRequest(), context); - - expect(response.status).toEqual(200); - expect(response.body).toEqual(['siem']); - }); - - describe('request validation', () => { - test('rejects invalid query params', async () => { - await expect( - server.inject( - requestMock.create({ - method: 'get', - path: `${BASE_RAC_ALERTS_API_PATH}/_feature_ids`, - query: { registrationContext: 4 }, - }), - context - ) - ).rejects.toThrowErrorMatchingInlineSnapshot( - `"Request was rejected with message: 'Invalid value \\"4\\" supplied to \\"registrationContext\\"'"` - ); - }); - - test('rejects unknown query params', async () => { - await expect( - server.inject( - requestMock.create({ - method: 'get', - path: `${BASE_RAC_ALERTS_API_PATH}/_feature_ids`, - query: { boop: 'siem' }, - }), - context - ) - ).rejects.toThrowErrorMatchingInlineSnapshot( - `"Request was rejected with message: 'invalid keys \\"boop\\"'"` - ); - }); - }); - - test('returns error status if rac client "getFeatureIdsByRegistrationContexts" fails', async () => { - clients.rac.getFeatureIdsByRegistrationContexts.mockRejectedValue( - new Error('Unable to get feature ids') - ); - const response = await server.inject(getReadFeatureIdsRequest(), context); - - expect(response.status).toEqual(500); - expect(response.body).toEqual({ - attributes: { success: false }, - message: 'Unable to get feature ids', - }); - }); -}); diff --git a/x-pack/plugins/rule_registry/server/routes/get_feature_ids_by_registration_contexts.ts b/x-pack/plugins/rule_registry/server/routes/get_feature_ids_by_registration_contexts.ts deleted file mode 100644 index 28e0aa59407092..00000000000000 --- a/x-pack/plugins/rule_registry/server/routes/get_feature_ids_by_registration_contexts.ts +++ /dev/null @@ -1,66 +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 { IRouter } from '@kbn/core/server'; -import * as t from 'io-ts'; -import { transformError } from '@kbn/securitysolution-es-utils'; - -import { RacRequestHandlerContext } from '../types'; -import { BASE_RAC_ALERTS_API_PATH } from '../../common/constants'; -import { buildRouteValidation } from './utils/route_validation'; - -export const getFeatureIdsByRegistrationContexts = (router: IRouter) => { - router.get( - { - path: `${BASE_RAC_ALERTS_API_PATH}/_feature_ids`, - validate: { - query: buildRouteValidation( - t.exact( - t.partial({ - registrationContext: t.union([t.string, t.array(t.string)]), - }) - ) - ), - }, - options: { - tags: ['access:rac'], - }, - }, - async (context, request, response) => { - try { - const racContext = await context.rac; - const alertsClient = await racContext.getAlertsClient(); - const { registrationContext = [] } = request.query; - const featureIds = await alertsClient.getFeatureIdsByRegistrationContexts( - Array.isArray(registrationContext) ? registrationContext : [registrationContext] - ); - return response.ok({ - body: featureIds, - }); - } catch (exc) { - const err = transformError(exc); - const contentType = { - 'content-type': 'application/json', - }; - const defaultedHeaders = { - ...contentType, - }; - - return response.customError({ - headers: defaultedHeaders, - statusCode: err.statusCode, - body: { - message: err.message, - attributes: { - success: false, - }, - }, - }); - } - } - ); -}; diff --git a/x-pack/test/rule_registry/security_and_spaces/tests/basic/get_feature_ids_by_registration_contexts.ts b/x-pack/test/rule_registry/security_and_spaces/tests/basic/get_feature_ids_by_registration_contexts.ts deleted file mode 100644 index 5b4063cfe52859..00000000000000 --- a/x-pack/test/rule_registry/security_and_spaces/tests/basic/get_feature_ids_by_registration_contexts.ts +++ /dev/null @@ -1,79 +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 expect from '@kbn/expect'; - -import { superUser, obsOnlySpacesAll, secOnlyRead } from '../../../common/lib/authentication/users'; -import type { User } from '../../../common/lib/authentication/types'; -import { FtrProviderContext } from '../../../common/ftr_provider_context'; -import { getSpaceUrlPrefix } from '../../../common/lib/authentication/spaces'; - -// eslint-disable-next-line import/no-default-export -export default ({ getService }: FtrProviderContext) => { - const supertestWithoutAuth = getService('supertestWithoutAuth'); - const esArchiver = getService('esArchiver'); - - const TEST_URL = '/internal/rac/alerts'; - const ALERTS_FEATURE_IDS_URL = `${TEST_URL}/_feature_ids`; - const SPACE1 = 'space1'; - - const getApmFeatureIdByRegistrationContexts = async ( - user: User, - space: string, - expectedStatusCode: number = 200 - ) => { - const resp = await supertestWithoutAuth - .get( - `${getSpaceUrlPrefix(space)}${ALERTS_FEATURE_IDS_URL}?registrationContext=observability.apm` - ) - .auth(user.username, user.password) - .set('kbn-xsrf', 'true') - .expect(expectedStatusCode); - return resp.body as string[]; - }; - - const getSecurityFeatureIdByRegistrationContexts = async ( - user: User, - space: string, - expectedStatusCode: number = 200 - ) => { - const resp = await supertestWithoutAuth - .get(`${getSpaceUrlPrefix(space)}${ALERTS_FEATURE_IDS_URL}?registrationContext=security`) - .auth(user.username, user.password) - .set('kbn-xsrf', 'true') - .expect(expectedStatusCode); - - return resp.body as string[]; - }; - - describe('Alert - Get feature ids by registration context', () => { - before(async () => { - await esArchiver.load('x-pack/test/functional/es_archives/rule_registry/alerts'); - }); - describe('Users:', () => { - it(`${obsOnlySpacesAll.username} should be able to get feature id for registration context 'observability.apm' in ${SPACE1}`, async () => { - const featureIds = await getApmFeatureIdByRegistrationContexts(obsOnlySpacesAll, SPACE1); - expect(featureIds).to.eql(['apm']); - }); - - it(`${superUser.username} should be able to get feature id for registration context 'observability.apm' in ${SPACE1}`, async () => { - const featureIds = await getApmFeatureIdByRegistrationContexts(superUser, SPACE1); - expect(featureIds).to.eql(['apm']); - }); - - it(`${secOnlyRead.username} should NOT be able to get feature id for registration context 'observability.apm' in ${SPACE1}`, async () => { - const featureIds = await getApmFeatureIdByRegistrationContexts(secOnlyRead, SPACE1); - expect(featureIds).to.eql([]); - }); - - it(`${secOnlyRead.username} should be able to get feature id for registration context 'security' in ${SPACE1}`, async () => { - const featureIds = await getSecurityFeatureIdByRegistrationContexts(secOnlyRead, SPACE1); - expect(featureIds).to.eql(['siem']); - }); - }); - }); -}; diff --git a/x-pack/test/rule_registry/security_and_spaces/tests/basic/index.ts b/x-pack/test/rule_registry/security_and_spaces/tests/basic/index.ts index 5237cd02c0c892..3cf7e28357ed8d 100644 --- a/x-pack/test/rule_registry/security_and_spaces/tests/basic/index.ts +++ b/x-pack/test/rule_registry/security_and_spaces/tests/basic/index.ts @@ -25,7 +25,6 @@ export default ({ loadTestFile, getService }: FtrProviderContext): void => { // loadTestFile(require.resolve('./update_alert')); // loadTestFile(require.resolve('./bulk_update_alerts')); - loadTestFile(require.resolve('./get_feature_ids_by_registration_contexts')); loadTestFile(require.resolve('./get_alerts_index')); loadTestFile(require.resolve('./find_alerts')); loadTestFile(require.resolve('./search_strategy')); From cca69667b8d5bc137a684e13f0ac9e0945577b3a Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Sun, 28 Jul 2024 11:29:58 +0300 Subject: [PATCH 037/106] Switch rule registry routes to use ruleTypeIds instead of featureIds --- .../src/common/apis/fetch_alert_fields.ts | 7 ++--- .../common/apis/fetch_alert_index_names.ts | 6 ++-- .../apis/search_alerts/search_alerts.test.tsx | 4 +-- .../apis/search_alerts/search_alerts.ts | 9 +++--- .../src/common/hooks/use_alert_data_view.ts | 30 +++++++++---------- ...t_alerts_group_aggregations_query.test.tsx | 3 +- ...use_get_alerts_group_aggregations_query.ts | 3 +- .../hooks/use_search_alerts_query.test.tsx | 6 ++-- .../common/hooks/use_search_alerts_query.ts | 6 ++-- .../system_actions/hooks/alert_fields.ts | 7 ++--- .../server/alert_data_client/alerts_client.ts | 2 +- .../routes/__mocks__/request_responses.ts | 10 +++++-- .../server/routes/get_alert_index.ts | 9 ++---- .../server/routes/get_alert_summary.ts | 6 ++-- .../get_alerts_group_aggregations.test.ts | 26 +++++++++++++--- .../routes/get_alerts_group_aggregations.ts | 6 ++-- .../get_browser_fields_by_feature_id.test.ts | 2 +- .../get_browser_fields_by_feature_id.ts | 20 ++++++++----- .../application/hooks/use_alert_data_view.ts | 28 ++++++++--------- .../hooks/use_load_alert_summary.ts | 17 +++++------ .../application/lib/rule_api/alert_fields.ts | 7 ++--- .../application/lib/rule_api/alert_index.ts | 6 ++-- .../alerts_table/alerts_table_state.tsx | 19 ++++++------ .../hooks/use_columns/use_columns.ts | 7 ++--- 24 files changed, 129 insertions(+), 117 deletions(-) diff --git a/packages/kbn-alerts-ui-shared/src/common/apis/fetch_alert_fields.ts b/packages/kbn-alerts-ui-shared/src/common/apis/fetch_alert_fields.ts index 2c41e8adc7875f..30df86178411d0 100644 --- a/packages/kbn-alerts-ui-shared/src/common/apis/fetch_alert_fields.ts +++ b/packages/kbn-alerts-ui-shared/src/common/apis/fetch_alert_fields.ts @@ -6,22 +6,21 @@ * Side Public License, v 1. */ -import { ValidFeatureId } from '@kbn/rule-data-utils'; import { HttpSetup } from '@kbn/core/public'; import { FieldSpec } from '@kbn/data-views-plugin/common'; import { BASE_RAC_ALERTS_API_PATH } from '../constants'; export async function fetchAlertFields({ http, - featureIds, + ruleTypeIds, }: { http: HttpSetup; - featureIds: ValidFeatureId[]; + ruleTypeIds: string[]; }): Promise { const { fields: alertFields = [] } = await http.get<{ fields: FieldSpec[] }>( `${BASE_RAC_ALERTS_API_PATH}/browser_fields`, { - query: { featureIds }, + query: { ruleTypeIds }, } ); return alertFields; diff --git a/packages/kbn-alerts-ui-shared/src/common/apis/fetch_alert_index_names.ts b/packages/kbn-alerts-ui-shared/src/common/apis/fetch_alert_index_names.ts index 9cf7fe1d3ebc84..f14f575e49f01e 100644 --- a/packages/kbn-alerts-ui-shared/src/common/apis/fetch_alert_index_names.ts +++ b/packages/kbn-alerts-ui-shared/src/common/apis/fetch_alert_index_names.ts @@ -11,15 +11,15 @@ import { BASE_RAC_ALERTS_API_PATH } from '../constants'; export async function fetchAlertIndexNames({ http, - features, + ruleTypeIds, }: { http: HttpSetup; - features: string; + ruleTypeIds: string; }): Promise { const { index_name: indexNamesStr = [] } = await http.get<{ index_name: string[] }>( `${BASE_RAC_ALERTS_API_PATH}/index`, { - query: { features }, + query: { ruleTypeIds }, } ); return indexNamesStr; diff --git a/packages/kbn-alerts-ui-shared/src/common/apis/search_alerts/search_alerts.test.tsx b/packages/kbn-alerts-ui-shared/src/common/apis/search_alerts/search_alerts.test.tsx index 9c3a20811c5376..a205bafbf53047 100644 --- a/packages/kbn-alerts-ui-shared/src/common/apis/search_alerts/search_alerts.test.tsx +++ b/packages/kbn-alerts-ui-shared/src/common/apis/search_alerts/search_alerts.test.tsx @@ -203,7 +203,7 @@ describe('searchAlerts', () => { const params: SearchAlertsParams = { data: mockDataPlugin as unknown as DataPublicPluginStart, - featureIds: ['siem'], + ruleTypeIds: ['siem.esqlRule'], fields: [ { field: 'kibana.rule.type.id', include_unmapped: true }, { field: '*', include_unmapped: true }, @@ -236,7 +236,7 @@ describe('searchAlerts', () => { expect(mockDataPlugin.search.search).toHaveBeenCalledTimes(1); expect(mockDataPlugin.search.search).toHaveBeenCalledWith( { - featureIds: params.featureIds, + ruleTypeIds: params.ruleTypeIds, fields: [...params.fields!], pagination: { pageIndex: params.pageIndex, diff --git a/packages/kbn-alerts-ui-shared/src/common/apis/search_alerts/search_alerts.ts b/packages/kbn-alerts-ui-shared/src/common/apis/search_alerts/search_alerts.ts index ae678b9d25bfad..a0898cdfcdf75a 100644 --- a/packages/kbn-alerts-ui-shared/src/common/apis/search_alerts/search_alerts.ts +++ b/packages/kbn-alerts-ui-shared/src/common/apis/search_alerts/search_alerts.ts @@ -14,7 +14,6 @@ import type { } from '@kbn/alerting-types'; import { set } from '@kbn/safer-lodash-set'; import type { DataPublicPluginStart } from '@kbn/data-plugin/public'; -import type { ValidFeatureId } from '@kbn/rule-data-utils'; import type { MappingRuntimeFields, QueryDslFieldAndFormat, @@ -36,9 +35,9 @@ export interface SearchAlertsParams { // Parameters /** - * Array of feature ids used for authorization and area-based filtering + * Array of rule type ids used for authorization and area-based filtering */ - featureIds: ValidFeatureId[]; + ruleTypeIds: string[]; /** * ES query to perform on the affected alert indices */ @@ -79,7 +78,7 @@ export interface SearchAlertsResult { export const searchAlerts = ({ data, signal, - featureIds, + ruleTypeIds, fields, query, sort, @@ -91,7 +90,7 @@ export const searchAlerts = ({ data.search .search( { - featureIds, + ruleTypeIds, fields, query, pagination: { pageIndex, pageSize }, diff --git a/packages/kbn-alerts-ui-shared/src/common/hooks/use_alert_data_view.ts b/packages/kbn-alerts-ui-shared/src/common/hooks/use_alert_data_view.ts index 8c76671819b25c..c876c0e6cd104b 100644 --- a/packages/kbn-alerts-ui-shared/src/common/hooks/use_alert_data_view.ts +++ b/packages/kbn-alerts-ui-shared/src/common/hooks/use_alert_data_view.ts @@ -9,7 +9,6 @@ import { useEffect, useMemo, useState } from 'react'; import { i18n } from '@kbn/i18n'; import type { DataView, DataViewsContract } from '@kbn/data-views-plugin/common'; -import { AlertConsumers, ValidFeatureId } from '@kbn/rule-data-utils'; import type { ToastsStart, HttpStart } from '@kbn/core/public'; import { useQuery } from '@tanstack/react-query'; @@ -22,31 +21,30 @@ export interface UseAlertDataViewResult { } export interface UseAlertDataViewProps { - featureIds: ValidFeatureId[]; + ruleTypeIds: string[]; http: HttpStart; dataViewsService: DataViewsContract; toasts: ToastsStart; } export function useAlertDataView(props: UseAlertDataViewProps): UseAlertDataViewResult { - const { http, dataViewsService, toasts, featureIds } = props; + const { http, dataViewsService, toasts, ruleTypeIds } = props; const [dataViews, setDataViews] = useState([]); - const features = featureIds.sort().join(','); - const isOnlySecurity = featureIds.length === 1 && featureIds.includes(AlertConsumers.SIEM); - - const hasSecurityAndO11yFeatureIds = - featureIds.length > 1 && featureIds.includes(AlertConsumers.SIEM); + const ruleTypes = ruleTypeIds.sort().join(','); + const hasSecurity = ruleTypeIds.some((ruleTypeId) => ruleTypeId.startsWith('siem.')); + const isOnlySecurity = ruleTypeIds.length === 1 && hasSecurity; + const hasSecurityAndO11yFeatureIds = ruleTypeIds.length > 1 && hasSecurity; const hasNoSecuritySolution = - featureIds.length > 0 && !isOnlySecurity && !hasSecurityAndO11yFeatureIds; + ruleTypeIds.length > 0 && !isOnlySecurity && !hasSecurityAndO11yFeatureIds; const queryIndexNameFn = () => { - return fetchAlertIndexNames({ http, features }); + return fetchAlertIndexNames({ http, ruleTypeIds: ruleTypes }); }; const queryAlertFieldsFn = () => { - return fetchAlertFields({ http, featureIds }); + return fetchAlertFields({ http, ruleTypeIds }); }; const onErrorFn = () => { @@ -63,12 +61,12 @@ export function useAlertDataView(props: UseAlertDataViewProps): UseAlertDataView isInitialLoading: isIndexNameInitialLoading, isLoading: isIndexNameLoading, } = useQuery({ - queryKey: ['loadAlertIndexNames', features], + queryKey: ['loadAlertIndexNames', ruleTypeIds], queryFn: queryIndexNameFn, onError: onErrorFn, refetchOnWindowFocus: false, staleTime: 60 * 1000, // To prevent duplicated requests - enabled: featureIds.length > 0 && !hasSecurityAndO11yFeatureIds, + enabled: ruleTypeIds.length > 0 && !hasSecurityAndO11yFeatureIds, }); const { @@ -77,7 +75,7 @@ export function useAlertDataView(props: UseAlertDataViewProps): UseAlertDataView isInitialLoading: isAlertFieldsInitialLoading, isLoading: isAlertFieldsLoading, } = useQuery({ - queryKey: ['loadAlertFields', features], + queryKey: ['loadAlertFields', ruleTypeIds], queryFn: queryAlertFieldsFn, onError: onErrorFn, refetchOnWindowFocus: false, @@ -146,7 +144,7 @@ export function useAlertDataView(props: UseAlertDataViewProps): UseAlertDataView () => ({ dataViews, loading: - featureIds.length === 0 || hasSecurityAndO11yFeatureIds + ruleTypeIds.length === 0 || hasSecurityAndO11yFeatureIds ? false : isOnlySecurity ? isIndexNameInitialLoading || isIndexNameLoading || dataViews.length === 0 @@ -157,7 +155,7 @@ export function useAlertDataView(props: UseAlertDataViewProps): UseAlertDataView }), [ dataViews, - featureIds.length, + ruleTypeIds.length, hasSecurityAndO11yFeatureIds, isOnlySecurity, isIndexNameInitialLoading, diff --git a/packages/kbn-alerts-ui-shared/src/common/hooks/use_get_alerts_group_aggregations_query.test.tsx b/packages/kbn-alerts-ui-shared/src/common/hooks/use_get_alerts_group_aggregations_query.test.tsx index f4566ffed2e456..72092a229baa71 100644 --- a/packages/kbn-alerts-ui-shared/src/common/hooks/use_get_alerts_group_aggregations_query.test.tsx +++ b/packages/kbn-alerts-ui-shared/src/common/hooks/use_get_alerts_group_aggregations_query.test.tsx @@ -11,7 +11,6 @@ import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { renderHook } from '@testing-library/react-hooks/dom'; import type { HttpStart } from '@kbn/core-http-browser'; import { ToastsStart } from '@kbn/core-notifications-browser'; -import { AlertConsumers } from '@kbn/rule-data-utils'; import { useGetAlertsGroupAggregationsQuery } from './use_get_alerts_group_aggregations_query'; import { waitFor } from '@testing-library/react'; @@ -40,7 +39,7 @@ const mockToasts = { const toasts = mockToasts as unknown as ToastsStart; const params = { - featureIds: [AlertConsumers.STACK_ALERTS], + ruleTypeIds: ['.es-query'], groupByField: 'kibana.alert.rule.name', }; diff --git a/packages/kbn-alerts-ui-shared/src/common/hooks/use_get_alerts_group_aggregations_query.ts b/packages/kbn-alerts-ui-shared/src/common/hooks/use_get_alerts_group_aggregations_query.ts index eab5b9ac510fac..2e93ade47b3f8f 100644 --- a/packages/kbn-alerts-ui-shared/src/common/hooks/use_get_alerts_group_aggregations_query.ts +++ b/packages/kbn-alerts-ui-shared/src/common/hooks/use_get_alerts_group_aggregations_query.ts @@ -11,7 +11,6 @@ import { useQuery } from '@tanstack/react-query'; import type { HttpStart } from '@kbn/core-http-browser'; import type { ToastsStart } from '@kbn/core-notifications-browser'; import { SearchResponseBody } from '@elastic/elasticsearch/lib/api/types'; -import { AlertConsumers } from '@kbn/rule-data-utils'; import type { AggregationsAggregationContainer, QueryDslQueryContainer, @@ -24,7 +23,7 @@ export interface UseGetAlertsGroupAggregationsQueryProps { toasts: ToastsStart; enabled?: boolean; params: { - featureIds: AlertConsumers[]; + ruleTypeIds: string[]; groupByField: string; aggregations?: Record; filters?: QueryDslQueryContainer[]; diff --git a/packages/kbn-alerts-ui-shared/src/common/hooks/use_search_alerts_query.test.tsx b/packages/kbn-alerts-ui-shared/src/common/hooks/use_search_alerts_query.test.tsx index 30624b22772cb4..71bdeadef6a492 100644 --- a/packages/kbn-alerts-ui-shared/src/common/hooks/use_search_alerts_query.test.tsx +++ b/packages/kbn-alerts-ui-shared/src/common/hooks/use_search_alerts_query.test.tsx @@ -104,7 +104,7 @@ describe('useSearchAlertsQuery', () => { const params: UseSearchAlertsQueryParams = { data: mockDataPlugin as unknown as DataPublicPluginStart, - featureIds: ['siem'], + ruleTypeIds: ['siem.esqlRule'], fields: [ { field: 'kibana.rule.type.id', include_unmapped: true }, { field: '*', include_unmapped: true }, @@ -267,8 +267,8 @@ describe('useSearchAlertsQuery', () => { }); }); - it('does not fetch with no feature ids', () => { - const { result } = renderHook(() => useSearchAlertsQuery({ ...params, featureIds: [] }), { + it('does not fetch with no rule type ids', () => { + const { result } = renderHook(() => useSearchAlertsQuery({ ...params, ruleTypeIds: [] }), { wrapper, }); diff --git a/packages/kbn-alerts-ui-shared/src/common/hooks/use_search_alerts_query.ts b/packages/kbn-alerts-ui-shared/src/common/hooks/use_search_alerts_query.ts index 562da6b45a0bb5..f54ebec0e01d10 100644 --- a/packages/kbn-alerts-ui-shared/src/common/hooks/use_search_alerts_query.ts +++ b/packages/kbn-alerts-ui-shared/src/common/hooks/use_search_alerts_query.ts @@ -28,7 +28,7 @@ export const queryKeyPrefix = ['alerts', searchAlerts.name]; */ export const useSearchAlertsQuery = ({ data, ...params }: UseSearchAlertsQueryParams) => { const { - featureIds, + ruleTypeIds, fields, query = { bool: {}, @@ -48,7 +48,7 @@ export const useSearchAlertsQuery = ({ data, ...params }: UseSearchAlertsQueryPa searchAlerts({ data, signal, - featureIds, + ruleTypeIds, fields, query, sort, @@ -58,7 +58,7 @@ export const useSearchAlertsQuery = ({ data, ...params }: UseSearchAlertsQueryPa }), refetchOnWindowFocus: false, context: AlertsQueryContext, - enabled: featureIds.length > 0, + enabled: ruleTypeIds.length > 0, // To avoid flash of empty state with pagination, see https://tanstack.com/query/latest/docs/framework/react/guides/paginated-queries#better-paginated-queries-with-placeholderdata keepPreviousData: true, placeholderData: { diff --git a/x-pack/plugins/cases/public/components/system_actions/hooks/alert_fields.ts b/x-pack/plugins/cases/public/components/system_actions/hooks/alert_fields.ts index 8a73674a5e2641..e4a18bc1dc9e25 100644 --- a/x-pack/plugins/cases/public/components/system_actions/hooks/alert_fields.ts +++ b/x-pack/plugins/cases/public/components/system_actions/hooks/alert_fields.ts @@ -5,22 +5,21 @@ * 2.0. */ -import type { ValidFeatureId } from '@kbn/rule-data-utils'; import type { HttpSetup } from '@kbn/core/public'; import type { FieldSpec } from '@kbn/data-views-plugin/common'; import { BASE_RAC_ALERTS_API_PATH } from '@kbn/rule-registry-plugin/common'; export async function fetchAlertFields({ http, - featureIds, + ruleTypeIds, }: { http: HttpSetup; - featureIds: ValidFeatureId[]; + ruleTypeIds: string[]; }): Promise { const { fields: alertFields = [] } = await http.get<{ fields: FieldSpec[] }>( `${BASE_RAC_ALERTS_API_PATH}/browser_fields`, { - query: { featureIds }, + query: { ruleTypeIds }, } ); return alertFields; diff --git a/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts b/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts index eacc2bb8329178..8882d7ce4a14de 100644 --- a/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts +++ b/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts @@ -1141,7 +1141,7 @@ export class AlertsClient { }); } - public async getAuthorizedAlertsIndices(ruleTypeIds: string[]): Promise { + public async getAuthorizedAlertsIndices(ruleTypeIds?: string[]): Promise { try { const authorizedRuleTypes = await this.authorization.getAllAuthorizedRuleTypesFindOperation({ authorizationEntity: AlertingAuthorizationEntity.Alert, diff --git a/x-pack/plugins/rule_registry/server/routes/__mocks__/request_responses.ts b/x-pack/plugins/rule_registry/server/routes/__mocks__/request_responses.ts index 18099d01a4ed24..2f7ae082181d20 100644 --- a/x-pack/plugins/rule_registry/server/routes/__mocks__/request_responses.ts +++ b/x-pack/plugins/rule_registry/server/routes/__mocks__/request_responses.ts @@ -37,7 +37,7 @@ export const getO11yBrowserFields = () => requestMock.create({ method: 'get', path: `${BASE_RAC_ALERTS_API_PATH}/browser_fields`, - query: { featureIds: ['apm', 'logs'] }, + query: { ruleTypeIds: ['apm.anomaly', 'logs.alert.document.count'] }, }); export const getMetricThresholdAADFields = () => @@ -52,7 +52,13 @@ export const getAlertsGroupAggregationsRequest = () => method: 'post', path: `${BASE_RAC_ALERTS_API_PATH}/_group_aggregations`, body: { - featureIds: ['apm', 'infrastructure', 'logs', 'observability', 'slo', 'uptime'], + ruleTypeIds: [ + 'apm.anomaly', + 'logs.alert.document.count', + 'metrics.alert.threshold', + 'slo.rules.burnRate', + 'xpack.uptime.alerts.durationAnomaly', + ], groupByField: 'kibana.alert.rule.name', aggregations: { unitsCount: { diff --git a/x-pack/plugins/rule_registry/server/routes/get_alert_index.ts b/x-pack/plugins/rule_registry/server/routes/get_alert_index.ts index 8140f413c96f9f..39a4149d860b67 100644 --- a/x-pack/plugins/rule_registry/server/routes/get_alert_index.ts +++ b/x-pack/plugins/rule_registry/server/routes/get_alert_index.ts @@ -8,7 +8,6 @@ import { IRouter } from '@kbn/core/server'; import * as t from 'io-ts'; import { transformError } from '@kbn/securitysolution-es-utils'; -import { validFeatureIds } from '@kbn/rule-data-utils'; import { buildRouteValidation } from './utils/route_validation'; import { RacRequestHandlerContext } from '../types'; @@ -22,7 +21,7 @@ export const getAlertsIndexRoute = (router: IRouter) = query: buildRouteValidation( t.exact( t.partial({ - features: t.string, + ruleTypeIds: t.string, }) ) ), @@ -35,10 +34,8 @@ export const getAlertsIndexRoute = (router: IRouter) = try { const racContext = await context.rac; const alertsClient = await racContext.getAlertsClient(); - const { features } = request.query; - const indexName = await alertsClient.getAuthorizedAlertsIndices( - features?.split(',') ?? validFeatureIds - ); + const { ruleTypeIds } = request.query; + const indexName = await alertsClient.getAuthorizedAlertsIndices(ruleTypeIds?.split(',')); return response.ok({ body: { index_name: indexName }, }); diff --git a/x-pack/plugins/rule_registry/server/routes/get_alert_summary.ts b/x-pack/plugins/rule_registry/server/routes/get_alert_summary.ts index 838bf06e7e7684..d98a90b53af58c 100644 --- a/x-pack/plugins/rule_registry/server/routes/get_alert_summary.ts +++ b/x-pack/plugins/rule_registry/server/routes/get_alert_summary.ts @@ -27,7 +27,7 @@ export const getAlertSummaryRoute = (router: IRouter) t.type({ gte: t.string, lte: t.string, - featureIds: t.array(t.string), + ruleTypeIds: t.array(t.string), }) ), t.exact( @@ -47,7 +47,7 @@ export const getAlertSummaryRoute = (router: IRouter) try { const racContext = await context.rac; const alertsClient = await racContext.getAlertsClient(); - const { gte, lte, featureIds, filter, fixed_interval: fixedInterval } = request.body; + const { gte, lte, ruleTypeIds, filter, fixed_interval: fixedInterval } = request.body; if ( !( moment(gte, 'YYYY-MM-DDTHH:mm:ss.SSSZ', true).isValid() && @@ -66,7 +66,7 @@ export const getAlertSummaryRoute = (router: IRouter) const aggs = await alertsClient.getAlertSummary({ gte, lte, - featureIds, + ruleTypeIds, filter: filter as estypes.QueryDslQueryContainer[], fixedInterval, }); diff --git a/x-pack/plugins/rule_registry/server/routes/get_alerts_group_aggregations.test.ts b/x-pack/plugins/rule_registry/server/routes/get_alerts_group_aggregations.test.ts index 1ce32adc37e625..888a8686c02981 100644 --- a/x-pack/plugins/rule_registry/server/routes/get_alerts_group_aggregations.test.ts +++ b/x-pack/plugins/rule_registry/server/routes/get_alerts_group_aggregations.test.ts @@ -200,7 +200,7 @@ describe('getAlertsGroupAggregations', () => { context ) ).rejects.toThrowErrorMatchingInlineSnapshot( - `"Request was rejected with message: 'Invalid value \\"undefined\\" supplied to \\"featureIds\\"'"` + `"Request was rejected with message: 'Invalid value \\"undefined\\" supplied to \\"ruleTypeIds\\"'"` ); }); @@ -211,7 +211,13 @@ describe('getAlertsGroupAggregations', () => { method: 'post', path: `${BASE_RAC_ALERTS_API_PATH}/_group_aggregations`, body: { - featureIds: ['apm', 'infrastructure', 'logs', 'observability', 'slo', 'uptime'], + ruleTypeIds: [ + 'apm.anomaly', + 'logs.alert.document.count', + 'metrics.alert.threshold', + 'slo.rules.burnRate', + 'xpack.uptime.alerts.durationAnomaly', + ], groupByField: 'kibana.alert.rule.name', aggregations: { scriptedAggregation: { @@ -231,7 +237,13 @@ describe('getAlertsGroupAggregations', () => { method: 'post', path: `${BASE_RAC_ALERTS_API_PATH}/_group_aggregations`, body: { - featureIds: ['apm', 'infrastructure', 'logs', 'observability', 'slo', 'uptime'], + ruleTypeIds: [ + 'apm.anomaly', + 'logs.alert.document.count', + 'metrics.alert.threshold', + 'slo.rules.burnRate', + 'xpack.uptime.alerts.durationAnomaly', + ], groupByField: 'kibana.alert.rule.name', filters: [ { @@ -256,7 +268,13 @@ describe('getAlertsGroupAggregations', () => { method: 'post', path: `${BASE_RAC_ALERTS_API_PATH}/_group_aggregations`, body: { - featureIds: ['apm', 'infrastructure', 'logs', 'observability', 'slo', 'uptime'], + ruleTypeIds: [ + 'apm.anomaly', + 'logs.alert.document.count', + 'metrics.alert.threshold', + 'slo.rules.burnRate', + 'xpack.uptime.alerts.durationAnomaly', + ], groupByField: 'kibana.alert.rule.name', aggregations: {}, runtimeMappings: {}, diff --git a/x-pack/plugins/rule_registry/server/routes/get_alerts_group_aggregations.ts b/x-pack/plugins/rule_registry/server/routes/get_alerts_group_aggregations.ts index bd589fcda71a18..e5fb59c96f994f 100644 --- a/x-pack/plugins/rule_registry/server/routes/get_alerts_group_aggregations.ts +++ b/x-pack/plugins/rule_registry/server/routes/get_alerts_group_aggregations.ts @@ -24,7 +24,7 @@ export const getAlertsGroupAggregations = (router: IRouter { const { - featureIds, + ruleTypeIds, groupByField, aggregations, filters, @@ -53,7 +53,7 @@ export const getAlertsGroupAggregations = (router: IRouter { requestMock.create({ method: 'get', path, - query: { featureIds: undefined }, + query: { ruleTypeIds: undefined }, }), context ) diff --git a/x-pack/plugins/rule_registry/server/routes/get_browser_fields_by_feature_id.ts b/x-pack/plugins/rule_registry/server/routes/get_browser_fields_by_feature_id.ts index 995f992e0b8007..4376faff4bc210 100644 --- a/x-pack/plugins/rule_registry/server/routes/get_browser_fields_by_feature_id.ts +++ b/x-pack/plugins/rule_registry/server/routes/get_browser_fields_by_feature_id.ts @@ -21,7 +21,7 @@ export const getBrowserFieldsByFeatureId = (router: IRouter fId !== 'siem' + const { ruleTypeIds = [] } = request.query; + + const onlyO11yRuleTypeIds = ruleTypeIds.filter( + (ruleTypeId) => !ruleTypeId.startsWith('siem.') ); + const o11yIndices = - (onlyO11yFeatureIds - ? await alertsClient.getAuthorizedAlertsIndices(onlyO11yFeatureIds) + (onlyO11yRuleTypeIds + ? await alertsClient.getAuthorizedAlertsIndices(onlyO11yRuleTypeIds) : []) ?? []; + if (o11yIndices.length === 0) { return response.notFound({ body: { - message: `No alerts-observability indices found for featureIds [${featureIds}]`, + message: `No alerts-observability indices found for rule type ids [${onlyO11yRuleTypeIds}]`, attributes: { success: false }, }, }); @@ -53,10 +56,11 @@ export const getBrowserFieldsByFeatureId = (router: IRouter().services; const [dataViews, setDataViews] = useState(undefined); - const features = featureIds.sort().join(','); - const isOnlySecurity = featureIds.length === 1 && featureIds.includes(AlertConsumers.SIEM); - - const hasSecurityAndO11yFeatureIds = - featureIds.length > 1 && featureIds.includes(AlertConsumers.SIEM); + const ruleTypes = ruleTypeIds.sort().join(','); + const hasSecurity = ruleTypeIds.some((ruleTypeId) => ruleTypeId.startsWith('siem.')); + const isOnlySecurity = ruleTypeIds.length === 1 && hasSecurity; + const hasSecurityAndO11yFeatureIds = ruleTypeIds.length > 1 && hasSecurity; const hasNoSecuritySolution = - featureIds.length > 0 && !isOnlySecurity && !hasSecurityAndO11yFeatureIds; + ruleTypeIds.length > 0 && !isOnlySecurity && !hasSecurityAndO11yFeatureIds; const queryIndexNameFn = () => { - return fetchAlertIndexNames({ http, features }); + return fetchAlertIndexNames({ http, ruleTypeIds: ruleTypes }); }; const queryAlertFieldsFn = () => { - return fetchAlertFields({ http, featureIds }); + return fetchAlertFields({ http, ruleTypeIds }); }; const onErrorFn = () => { @@ -58,11 +56,11 @@ export function useAlertDataViews(featureIds: ValidFeatureId[]): UserAlertDataVi isInitialLoading: isIndexNameInitialLoading, isLoading: isIndexNameLoading, } = useQuery({ - queryKey: ['loadAlertIndexNames', features], + queryKey: ['loadAlertIndexNames', ruleTypeIds], queryFn: queryIndexNameFn, onError: onErrorFn, refetchOnWindowFocus: false, - enabled: featureIds.length > 0 && !hasSecurityAndO11yFeatureIds, + enabled: ruleTypeIds.length > 0 && !hasSecurityAndO11yFeatureIds, }); const { @@ -71,7 +69,7 @@ export function useAlertDataViews(featureIds: ValidFeatureId[]): UserAlertDataVi isInitialLoading: isAlertFieldsInitialLoading, isLoading: isAlertFieldsLoading, } = useQuery({ - queryKey: ['loadAlertFields', features], + queryKey: ['loadAlertFields', ruleTypeIds], queryFn: queryAlertFieldsFn, onError: onErrorFn, refetchOnWindowFocus: false, @@ -139,7 +137,7 @@ export function useAlertDataViews(featureIds: ValidFeatureId[]): UserAlertDataVi () => ({ dataViews, loading: - featureIds.length === 0 || hasSecurityAndO11yFeatureIds + ruleTypeIds.length === 0 || hasSecurityAndO11yFeatureIds ? false : isOnlySecurity ? isIndexNameInitialLoading || isIndexNameLoading @@ -150,7 +148,7 @@ export function useAlertDataViews(featureIds: ValidFeatureId[]): UserAlertDataVi }), [ dataViews, - featureIds.length, + ruleTypeIds.length, hasSecurityAndO11yFeatureIds, isOnlySecurity, isIndexNameInitialLoading, diff --git a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_alert_summary.ts b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_alert_summary.ts index 50fcc6025938ad..bb6b7b26f22a20 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_alert_summary.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_alert_summary.ts @@ -6,7 +6,6 @@ */ import { useEffect, useState, useCallback, useRef } from 'react'; -import type { ValidFeatureId } from '@kbn/rule-data-utils'; import { estypes } from '@elastic/elasticsearch'; import { AsApiContract } from '@kbn/actions-plugin/common'; import { HttpSetup } from '@kbn/core/public'; @@ -15,7 +14,7 @@ import { useKibana } from '../../common/lib/kibana'; import { Alert, AlertSummaryTimeRange } from '../sections/alert_summary_widget/types'; interface UseLoadAlertSummaryProps { - featureIds?: ValidFeatureId[]; + ruleTypeIds?: string[]; timeRange: AlertSummaryTimeRange; filter?: estypes.QueryDslQueryContainer; } @@ -32,7 +31,7 @@ interface LoadAlertSummaryResponse { error?: string; } -export function useLoadAlertSummary({ featureIds, timeRange, filter }: UseLoadAlertSummaryProps) { +export function useLoadAlertSummary({ ruleTypeIds, timeRange, filter }: UseLoadAlertSummaryProps) { const { http } = useKibana().services; const [alertSummary, setAlertSummary] = useState({ isLoading: true, @@ -45,14 +44,14 @@ export function useLoadAlertSummary({ featureIds, timeRange, filter }: UseLoadAl const isCancelledRef = useRef(false); const abortCtrlRef = useRef(new AbortController()); const loadAlertSummary = useCallback(async () => { - if (!featureIds) return; + if (!ruleTypeIds) return; isCancelledRef.current = false; abortCtrlRef.current.abort(); abortCtrlRef.current = new AbortController(); try { const { activeAlertCount, activeAlerts, recoveredAlertCount } = await fetchAlertSummary({ - featureIds, + ruleTypeIds, filter, http, signal: abortCtrlRef.current.signal, @@ -80,7 +79,7 @@ export function useLoadAlertSummary({ featureIds, timeRange, filter }: UseLoadAl } } } - }, [featureIds, filter, http, timeRange]); + }, [ruleTypeIds, filter, http, timeRange]); useEffect(() => { loadAlertSummary(); @@ -90,14 +89,14 @@ export function useLoadAlertSummary({ featureIds, timeRange, filter }: UseLoadAl } async function fetchAlertSummary({ - featureIds, + ruleTypeIds, filter, http, signal, timeRange: { utcFrom, utcTo, fixedInterval }, }: { http: HttpSetup; - featureIds: ValidFeatureId[]; + ruleTypeIds: string[]; signal: AbortSignal; timeRange: AlertSummaryTimeRange; filter?: estypes.QueryDslQueryContainer; @@ -108,7 +107,7 @@ async function fetchAlertSummary({ fixed_interval: fixedInterval, gte: utcFrom, lte: utcTo, - featureIds, + ruleTypeIds, filter: [filter], }), }); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/alert_fields.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/alert_fields.ts index 7be5b3eec0e692..1628a142466134 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/alert_fields.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/alert_fields.ts @@ -5,22 +5,21 @@ * 2.0. */ -import { ValidFeatureId } from '@kbn/rule-data-utils'; import { HttpSetup } from '@kbn/core/public'; import { FieldSpec } from '@kbn/data-views-plugin/common'; import { BASE_RAC_ALERTS_API_PATH } from '@kbn/rule-registry-plugin/common'; export async function fetchAlertFields({ http, - featureIds, + ruleTypeIds, }: { http: HttpSetup; - featureIds: ValidFeatureId[]; + ruleTypeIds: string[]; }): Promise { const { fields: alertFields = [] } = await http.get<{ fields: FieldSpec[] }>( `${BASE_RAC_ALERTS_API_PATH}/browser_fields`, { - query: { featureIds }, + query: { ruleTypeIds }, } ); return alertFields; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/alert_index.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/alert_index.ts index 8ac678664168b6..dd8eb336289b20 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/alert_index.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/alert_index.ts @@ -10,15 +10,15 @@ import { HttpSetup } from '@kbn/core/public'; export async function fetchAlertIndexNames({ http, - features, + ruleTypeIds, }: { http: HttpSetup; - features: string; + ruleTypeIds: string; }): Promise { const { index_name: indexNamesStr = [] } = await http.get<{ index_name: string[] }>( `${BASE_RAC_ALERTS_API_PATH}/index`, { - query: { features }, + query: { ruleTypeIds }, } ); return indexNamesStr; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/alerts_table_state.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/alerts_table_state.tsx index edd18905b1cec0..d936212412b386 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/alerts_table_state.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/alerts_table_state.tsx @@ -21,7 +21,6 @@ import { } from '@elastic/eui'; import type { MappingRuntimeFields } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { ALERT_CASE_IDS, ALERT_MAINTENANCE_WINDOW_IDS } from '@kbn/rule-data-utils'; -import type { ValidFeatureId } from '@kbn/rule-data-utils'; import type { BrowserFields, RuleRegistrySearchRequestPagination, @@ -70,7 +69,7 @@ export type AlertsTableStateProps = { alertsTableConfigurationRegistry: AlertsTableConfigurationRegistryContract; configurationId: string; id: string; - featureIds: ValidFeatureId[]; + ruleTypeIds: string[]; query: Pick; initialPageSize?: number; browserFields?: BrowserFields; @@ -194,7 +193,7 @@ const AlertsTableStateWithQueryProvider = memo( alertsTableConfigurationRegistry, configurationId, id, - featureIds, + ruleTypeIds, query, initialPageSize = DEFAULT_ALERTS_PAGE_SIZE, leadingControlColumns = DEFAULT_LEADING_CONTROL_COLUMNS, @@ -293,7 +292,7 @@ const AlertsTableStateWithQueryProvider = memo( onColumnResize, fields, } = useColumns({ - featureIds, + ruleTypeIds, storageAlertsTable, storage, id, @@ -302,7 +301,7 @@ const AlertsTableStateWithQueryProvider = memo( }); const [queryParams, setQueryParams] = useState({ - featureIds, + ruleTypeIds, fields, query, sort, @@ -313,14 +312,14 @@ const AlertsTableStateWithQueryProvider = memo( useEffect(() => { setQueryParams(({ pageIndex: oldPageIndex, pageSize: oldPageSize, ...prevQueryParams }) => ({ - featureIds, + ruleTypeIds, fields, query, sort, runtimeMappings, // Go back to the first page if the query changes pageIndex: !deepEqual(prevQueryParams, { - featureIds, + ruleTypeIds, fields, query, sort, @@ -330,7 +329,7 @@ const AlertsTableStateWithQueryProvider = memo( : oldPageIndex, pageSize: oldPageSize, })); - }, [featureIds, fields, query, runtimeMappings, sort]); + }, [ruleTypeIds, fields, query, runtimeMappings, sort]); const { data: alertsData, @@ -501,7 +500,7 @@ const AlertsTableStateWithQueryProvider = memo( toolbarVisibility, shouldHighlightRow, dynamicRowHeight, - featureIds, + ruleTypeIds, querySnapshot, pageIndex: queryParams.pageIndex, pageSize: queryParams.pageSize, @@ -540,7 +539,7 @@ const AlertsTableStateWithQueryProvider = memo( toolbarVisibility, shouldHighlightRow, dynamicRowHeight, - featureIds, + ruleTypeIds, querySnapshot, queryParams.pageIndex, queryParams.pageSize, diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_columns/use_columns.ts b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_columns/use_columns.ts index b3ff16cfd89ef3..5ccff31a2310ea 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_columns/use_columns.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_columns/use_columns.ts @@ -9,14 +9,13 @@ import { EuiDataGridColumn, EuiDataGridOnColumnResizeData } from '@elastic/eui'; import { IStorageWrapper } from '@kbn/kibana-utils-plugin/public'; import { BrowserField, BrowserFields } from '@kbn/rule-registry-plugin/common'; import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; -import { AlertConsumers } from '@kbn/rule-data-utils'; import { isEmpty } from 'lodash'; import { AlertsTableStorage } from '../../alerts_table_state'; import { toggleColumn } from './toggle_column'; import { useFetchBrowserFieldCapabilities } from '../use_fetch_browser_fields_capabilities'; export interface UseColumnsArgs { - featureIds: AlertConsumers[]; + ruleTypeIds: string[]; storageAlertsTable: React.MutableRefObject; storage: React.MutableRefObject; id: string; @@ -149,7 +148,7 @@ const persist = ({ }; export const useColumns = ({ - featureIds, + ruleTypeIds, storageAlertsTable, storage, id, @@ -157,7 +156,7 @@ export const useColumns = ({ initialBrowserFields, }: UseColumnsArgs): UseColumnsResp => { const [isBrowserFieldDataLoading, browserFields] = useFetchBrowserFieldCapabilities({ - featureIds, + ruleTypeIds, initialBrowserFields, }); From 52b472bf45027411bd6a7c94cff6d028dac33969 Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Sun, 28 Jul 2024 13:01:32 +0300 Subject: [PATCH 038/106] Change UI to use rule type IDs --- .../src/components/alerts_grouping.test.tsx | 4 +- .../src/components/alerts_grouping.tsx | 6 +- .../src/components/alerts_grouping_level.tsx | 6 +- .../src/mocks/grouping_props.mock.tsx | 4 +- .../src/mocks/grouping_query.mock.ts | 6 +- packages/kbn-alerts-grouping/src/types.ts | 5 +- .../alert_filter_controls.tsx | 15 ++- .../filter_group.test.tsx | 7 +- .../alert_filter_controls/filter_group.tsx | 6 +- .../src/alert_filter_controls/types.ts | 3 +- .../src/alerts_search_bar/index.tsx | 6 +- .../src/alerts_search_bar/types.ts | 3 +- .../src/common/hooks/use_find_alerts_query.ts | 2 +- ...use_get_alerts_group_aggregations_query.ts | 4 +- .../src/rule_types/o11y_rules.ts | 2 + .../src/rule_type_constants.ts | 11 ++ .../src/hooks/use_alerts_history.test.tsx | 11 +- .../src/hooks/use_alerts_history.ts | 13 +-- .../apis/bulk_untrack_by_query/schemas/v1.ts | 2 +- .../create_maintenance_windows_form.tsx | 11 +- .../maintenance_window_scoped_query.test.tsx | 7 +- .../maintenance_window_scoped_query.tsx | 7 +- .../lib/set_alerts_to_untracked.test.ts | 4 +- .../bulk_untrack/bulk_untrack_alerts.ts | 2 +- .../schemas/bulk_untrack_body_schema.ts | 2 +- ...bulk_untrack_alerts_by_query_route.test.ts | 4 +- .../v1.ts | 4 +- .../suggestions/values_suggestion_alerts.ts | 26 +---- .../components/case_view_alerts.test.tsx | 4 +- .../case_view/components/case_view_alerts.tsx | 3 +- x-pack/plugins/ml/common/constants/alerts.ts | 2 + x-pack/plugins/ml/common/index.ts | 2 +- .../explorer/alerts/alerts_panel.tsx | 9 +- .../anomaly_detection_alerts_state_service.ts | 4 +- .../components/app/alerts_overview/index.tsx | 4 +- .../infra/common/alerting/metrics/types.ts | 2 + .../shared/alerts/alerts_overview.tsx | 9 +- .../public/hooks/use_alerts_count.test.ts | 12 +- .../infra/public/hooks/use_alerts_count.ts | 16 +-- .../tabs/alerts/alerts_tab_content.tsx | 6 +- .../components/tabs/alerts_tab_badge.tsx | 4 +- .../observability/common/constants.ts | 19 ++- .../alert_search_bar.test.tsx | 4 +- .../alert_search_bar/alert_search_bar.tsx | 4 +- .../components/alert_history.tsx | 22 +--- .../public/pages/alerts/alerts.tsx | 9 +- .../public/pages/overview/overview.tsx | 6 +- .../components/rule_details_tabs.tsx | 9 +- .../pages/rule_details/rule_details.tsx | 17 +-- .../server/functions/alerts.ts | 14 +-- .../alerts/components/slo_alerts_summary.tsx | 4 +- .../alerts/components/slo_alerts_table.tsx | 4 +- .../components/slo_detail_alerts.tsx | 4 +- .../slo/server/services/get_slos_overview.ts | 4 +- .../synthetics/server/feature.ts | 8 +- .../uptime/common/constants/uptime_alerts.ts | 36 ------ .../alert_data_client/alerts_client.mock.ts | 1 - .../server/alert_data_client/alerts_client.ts | 7 +- .../get_alerts_group_aggregations.test.ts | 12 +- .../rule_registry/server/routes/find.ts | 6 +- .../server/routes/get_alert_summary.test.ts | 8 +- .../get_browser_fields_by_feature_id.test.ts | 2 +- .../rule_registry/server/routes/index.ts | 2 - .../rule_data_plugin_service.mock.ts | 1 - .../rule_data_plugin_service.ts | 17 --- .../tabs/alerts_tab/index.tsx | 7 +- .../components/alerts_table/index.tsx | 3 +- .../detection_engine_filters.tsx | 4 +- .../hooks/use_alert_data_view.test.tsx | 30 ++--- .../hooks/use_load_alert_summary.test.ts | 11 +- .../public/application/lib/search_filters.ts | 109 +++++++++--------- .../action_alerts_filter_query.tsx | 7 +- .../alert_summary_widget.test.tsx | 2 +- .../alert_summary_widget.tsx | 4 +- .../sections/alert_summary_widget/types.ts | 4 +- .../components/stack_alerts_page.tsx | 25 ++-- .../alerts_search_bar/alerts_search_bar.tsx | 6 +- .../sections/alerts_search_bar/types.ts | 3 +- .../url_synced_alerts_search_bar.tsx | 13 +-- .../sections/alerts_table/alerts_table.tsx | 6 +- .../alerts_table/alerts_table_state.test.tsx | 9 +- .../hooks/use_bulk_actions.test.tsx | 12 +- .../alerts_table/hooks/use_bulk_actions.ts | 24 ++-- .../use_bulk_untrack_alerts_by_query.tsx | 7 +- .../hooks/use_columns/use_columns.test.ts | 23 ++-- .../sections/rule_details/components/rule.tsx | 13 +-- .../triggers_actions_ui/public/types.ts | 4 +- 87 files changed, 353 insertions(+), 453 deletions(-) diff --git a/packages/kbn-alerts-grouping/src/components/alerts_grouping.test.tsx b/packages/kbn-alerts-grouping/src/components/alerts_grouping.test.tsx index c60ef03ca35e57..e21d47157aaa19 100644 --- a/packages/kbn-alerts-grouping/src/components/alerts_grouping.test.tsx +++ b/packages/kbn-alerts-grouping/src/components/alerts_grouping.test.tsx @@ -22,7 +22,7 @@ import { groupingSearchResponse } from '../mocks/grouping_query.mock'; import { useAlertsGroupingState } from '../contexts/alerts_grouping_context'; import { I18nProvider } from '@kbn/i18n-react'; import { - mockFeatureIds, + mockRuleTypeIds, mockDate, mockGroupingProps, mockGroupingId, @@ -145,7 +145,7 @@ describe('AlertsGrouping', () => { expect.objectContaining({ params: { aggregations: {}, - featureIds: mockFeatureIds, + ruleTypeIds: mockRuleTypeIds, groupByField: 'kibana.alert.rule.name', filters: [ { diff --git a/packages/kbn-alerts-grouping/src/components/alerts_grouping.tsx b/packages/kbn-alerts-grouping/src/components/alerts_grouping.tsx index 130997dd393ce6..7e80038e22b765 100644 --- a/packages/kbn-alerts-grouping/src/components/alerts_grouping.tsx +++ b/packages/kbn-alerts-grouping/src/components/alerts_grouping.tsx @@ -60,7 +60,7 @@ const AlertsGroupingInternal = (props: AlertsGroupingProps) => { const { groupingId, services, - featureIds, + ruleTypeIds, defaultGroupingOptions, defaultFilters, globalFilters, @@ -73,7 +73,7 @@ const AlertsGroupingInternal = (props: AlertsGroupingProps) => { const { grouping, updateGrouping } = useAlertsGroupingState(groupingId); const { dataViews: alertDataViews } = useAlertDataView({ - featureIds, + ruleTypeIds, dataViewsService: dataViews, http, toasts: notifications.toasts, @@ -245,7 +245,7 @@ const AlertsGroupingInternal = (props: AlertsGroupingProps) => { * * return ( * = {}>({ - featureIds, + ruleTypeIds, defaultFilters = DEFAULT_FILTERS, from, getGrouping, @@ -82,7 +82,7 @@ export const AlertsGroupingLevel = memo( const aggregationsQuery = useMemo(() => { return { - featureIds, + ruleTypeIds, groupByField: selectedGroup, aggregations: getAggregationsByGroupingField(selectedGroup)?.reduce( (acc, val) => Object.assign(acc, val), @@ -103,12 +103,12 @@ export const AlertsGroupingLevel = memo( pageSize, }; }, [ - featureIds, filters, from, getAggregationsByGroupingField, pageIndex, pageSize, + ruleTypeIds, selectedGroup, to, ]); diff --git a/packages/kbn-alerts-grouping/src/mocks/grouping_props.mock.tsx b/packages/kbn-alerts-grouping/src/mocks/grouping_props.mock.tsx index ac8e55bfb02225..94467d7b5f19e5 100644 --- a/packages/kbn-alerts-grouping/src/mocks/grouping_props.mock.tsx +++ b/packages/kbn-alerts-grouping/src/mocks/grouping_props.mock.tsx @@ -12,7 +12,7 @@ import { AlertsGroupingProps } from '../types'; export const mockGroupingId = 'test'; -export const mockFeatureIds = [AlertConsumers.STACK_ALERTS]; +export const mockRuleTypeIds = [AlertConsumers.STACK_ALERTS]; export const mockDate = { from: '2020-07-07T08:20:18.966Z', @@ -29,7 +29,7 @@ export const mockOptions = [ export const mockGroupingProps: Omit = { ...mockDate, groupingId: mockGroupingId, - featureIds: mockFeatureIds, + ruleTypeIds: mockRuleTypeIds, defaultGroupingOptions: mockOptions, getAggregationsByGroupingField: () => [], getGroupStats: () => [{ title: 'Stat', component: }], diff --git a/packages/kbn-alerts-grouping/src/mocks/grouping_query.mock.ts b/packages/kbn-alerts-grouping/src/mocks/grouping_query.mock.ts index 3cdf07ec8c31f7..8cccca04a7d6c7 100644 --- a/packages/kbn-alerts-grouping/src/mocks/grouping_query.mock.ts +++ b/packages/kbn-alerts-grouping/src/mocks/grouping_query.mock.ts @@ -10,12 +10,12 @@ export const getQuery = ({ selectedGroup, uniqueValue, timeRange, - featureIds, + ruleTypeIds, }: { selectedGroup: string; uniqueValue: string; timeRange: { from: string; to: string }; - featureIds: string[]; + ruleTypeIds: string[]; }) => ({ _source: false, aggs: { @@ -51,7 +51,7 @@ export const getQuery = ({ }, }, }, - feature_ids: featureIds, + feature_ids: ruleTypeIds, query: { bool: { filter: [ diff --git a/packages/kbn-alerts-grouping/src/types.ts b/packages/kbn-alerts-grouping/src/types.ts index 8d226bb74e71f1..ab63b3135df697 100644 --- a/packages/kbn-alerts-grouping/src/types.ts +++ b/packages/kbn-alerts-grouping/src/types.ts @@ -7,7 +7,6 @@ */ import type { Filter, Query } from '@kbn/es-query'; -import { ValidFeatureId } from '@kbn/rule-data-utils'; import type { NotificationsStart } from '@kbn/core-notifications-browser'; import type { DataViewsServicePublic } from '@kbn/data-views-plugin/public/types'; import type { HttpSetup } from '@kbn/core-http-browser'; @@ -60,9 +59,9 @@ export interface AlertsGroupingProps = {}> { */ defaultGroupingOptions: GroupOption[]; /** - * The alerting feature ids this grouping covers + * The alerting rule type ids this grouping covers */ - featureIds: ValidFeatureId[]; + ruleTypeIds: string[]; /** * Time filter start */ diff --git a/packages/kbn-alerts-ui-shared/src/alert_filter_controls/alert_filter_controls.tsx b/packages/kbn-alerts-ui-shared/src/alert_filter_controls/alert_filter_controls.tsx index fc2b9fbbc207fd..46f6c794d5fe4f 100644 --- a/packages/kbn-alerts-ui-shared/src/alert_filter_controls/alert_filter_controls.tsx +++ b/packages/kbn-alerts-ui-shared/src/alert_filter_controls/alert_filter_controls.tsx @@ -11,7 +11,6 @@ import React, { useCallback, useEffect, useState } from 'react'; import type { Filter } from '@kbn/es-query'; import { EuiFlexItem } from '@elastic/eui'; import type { DataViewSpec, DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public'; -import { AlertConsumers } from '@kbn/rule-data-utils'; import { HttpStart } from '@kbn/core-http-browser'; import { NotificationsStart } from '@kbn/core-notifications-browser'; import type { Storage } from '@kbn/kibana-utils-plugin/public'; @@ -23,12 +22,12 @@ import { FilterControlConfig } from './types'; export type AlertFilterControlsProps = Omit< ComponentProps, - 'dataViewId' | 'defaultControls' | 'featureIds' | 'Storage' + 'dataViewId' | 'defaultControls' | 'ruleTypeIds' | 'Storage' > & { /** - * The feature ids used to get the correct alert data view(s) + * The rule type ids used to get the correct alert data view(s) */ - featureIds?: AlertConsumers[]; + ruleTypeIds?: string[]; /** * An array of default control configurations */ @@ -56,7 +55,7 @@ export type AlertFilterControlsProps = Omit< * * { const { - featureIds = [AlertConsumers.STACK_ALERTS], + ruleTypeIds = [], defaultControls = DEFAULT_CONTROLS, dataViewSpec, onFiltersChange, @@ -95,7 +94,7 @@ export const AlertFilterControls = (props: AlertFilterControlsProps) => { } = props; const [loadingPageFilters, setLoadingPageFilters] = useState(true); const { dataViews: alertDataViews, loading: loadingDataViews } = useAlertDataView({ - featureIds, + ruleTypeIds, dataViewsService: dataViews, http, toasts, @@ -155,7 +154,7 @@ export const AlertFilterControls = (props: AlertFilterControlsProps) => { > = (props) => { ) => { maxControls = Infinity, ControlGroupRenderer, Storage, - featureIds, + ruleTypeIds, } = props; const filterChangedSubscription = useRef(); @@ -82,8 +82,8 @@ export const FilterGroup = (props: PropsWithChildren) => { const [controlGroup, setControlGroup] = useState(); const localStoragePageFilterKey = useMemo( - () => `${featureIds.join(',')}.${spaceId}.${URL_PARAM_KEY}`, - [featureIds, spaceId] + () => `${ruleTypeIds.join(',')}.${spaceId}.${URL_PARAM_KEY}`, + [ruleTypeIds, spaceId] ); const currentFiltersRef = useRef(); diff --git a/packages/kbn-alerts-ui-shared/src/alert_filter_controls/types.ts b/packages/kbn-alerts-ui-shared/src/alert_filter_controls/types.ts index 75dcad2acb5c2b..6b27ab3acc29fd 100644 --- a/packages/kbn-alerts-ui-shared/src/alert_filter_controls/types.ts +++ b/packages/kbn-alerts-ui-shared/src/alert_filter_controls/types.ts @@ -14,7 +14,6 @@ import type { import type { Filter } from '@kbn/es-query'; import type { ControlGroupRenderer } from '@kbn/controls-plugin/public'; import type { Storage } from '@kbn/kibana-utils-plugin/public'; -import { AlertConsumers } from '@kbn/rule-data-utils'; export type FilterUrlFormat = Record< string, @@ -42,7 +41,7 @@ export interface FilterGroupProps extends Pick { spaceId?: string; dataViewId: string | null; - featureIds: AlertConsumers[]; + ruleTypeIds: string[]; /** * Filters changed callback */ diff --git a/packages/kbn-alerts-ui-shared/src/alerts_search_bar/index.tsx b/packages/kbn-alerts-ui-shared/src/alerts_search_bar/index.tsx index 9a095200a85062..4915799ac7aa14 100644 --- a/packages/kbn-alerts-ui-shared/src/alerts_search_bar/index.tsx +++ b/packages/kbn-alerts-ui-shared/src/alerts_search_bar/index.tsx @@ -20,7 +20,7 @@ const SA_ALERTS = { type: 'alerts', fields: {} } as SuggestionsAbstraction; export const AlertsSearchBar = ({ appName, disableQueryLanguageSwitcher = false, - featureIds, + ruleTypeIds, ruleTypeId, query, filters, @@ -41,7 +41,7 @@ export const AlertsSearchBar = ({ }: AlertsSearchBarProps) => { const [queryLanguage, setQueryLanguage] = useState('kuery'); const { dataViews, loading } = useAlertDataView({ - featureIds: featureIds ?? [], + ruleTypeIds, http, toasts, dataViewsService, @@ -63,7 +63,7 @@ export const AlertsSearchBar = ({ }); const isSecurity = - (featureIds && featureIds.length === 1 && featureIds.includes(AlertConsumers.SIEM)) || + (ruleTypeIds && ruleTypeIds.length === 1 && ruleTypeIds[0].startsWith('siem.')) || (ruleType && ruleTypeId && ruleType.ruleTypesState.data.get(ruleTypeId)?.producer === AlertConsumers.SIEM); diff --git a/packages/kbn-alerts-ui-shared/src/alerts_search_bar/types.ts b/packages/kbn-alerts-ui-shared/src/alerts_search_bar/types.ts index 06ed60f1eab921..d0d728ae3f607a 100644 --- a/packages/kbn-alerts-ui-shared/src/alerts_search_bar/types.ts +++ b/packages/kbn-alerts-ui-shared/src/alerts_search_bar/types.ts @@ -7,7 +7,6 @@ */ import type { Filter } from '@kbn/es-query'; -import type { ValidFeatureId } from '@kbn/rule-data-utils'; import type { ToastsStart, HttpStart } from '@kbn/core/public'; import type { UnifiedSearchPublicPluginStart } from '@kbn/unified-search-plugin/public'; import type { DataViewsContract } from '@kbn/data-views-plugin/common'; @@ -17,7 +16,7 @@ export type QueryLanguageType = 'lucene' | 'kuery'; export interface AlertsSearchBarProps { appName: string; disableQueryLanguageSwitcher?: boolean; - featureIds: ValidFeatureId[]; + ruleTypeIds: string[]; rangeFrom?: string; rangeTo?: string; query?: string; diff --git a/packages/kbn-alerts-ui-shared/src/common/hooks/use_find_alerts_query.ts b/packages/kbn-alerts-ui-shared/src/common/hooks/use_find_alerts_query.ts index a0d1b68458e042..abec0f2f427bc4 100644 --- a/packages/kbn-alerts-ui-shared/src/common/hooks/use_find_alerts_query.ts +++ b/packages/kbn-alerts-ui-shared/src/common/hooks/use_find_alerts_query.ts @@ -18,7 +18,7 @@ export interface UseFindAlertsQueryProps { http: HttpStart; toasts: ToastsStart; enabled?: boolean; - params: ISearchRequestParams & { feature_ids?: string[] }; + params: ISearchRequestParams & { rule_type_ids?: string[] }; } /** diff --git a/packages/kbn-alerts-ui-shared/src/common/hooks/use_get_alerts_group_aggregations_query.ts b/packages/kbn-alerts-ui-shared/src/common/hooks/use_get_alerts_group_aggregations_query.ts index 2e93ade47b3f8f..e80f5b91c21d51 100644 --- a/packages/kbn-alerts-ui-shared/src/common/hooks/use_get_alerts_group_aggregations_query.ts +++ b/packages/kbn-alerts-ui-shared/src/common/hooks/use_get_alerts_group_aggregations_query.ts @@ -45,7 +45,7 @@ export interface UseGetAlertsGroupAggregationsQueryProps { * The provided `aggregations` are applied within `groupByFields`. Here the `groupByField` runtime * field can be used to perform grouping-based aggregations. * - * Applies alerting RBAC through featureIds. + * Applies alerting RBAC through ruleTypeIds. */ export const useGetAlertsGroupAggregationsQuery = ({ http, @@ -57,7 +57,7 @@ export const useGetAlertsGroupAggregationsQuery = ({ if (error) { toasts.addDanger( i18n.translate( - 'alertsUIShared.hooks.useFindAlertsQuery.unableToFetchAlertsGroupingAggregations', + 'alertsUIShared.hooks.useGetAlertsGroupAggregationsQuery.unableToFetchAlertsGroupingAggregations', { defaultMessage: 'Unable to fetch alerts grouping aggregations', } diff --git a/packages/kbn-rule-data-utils/src/rule_types/o11y_rules.ts b/packages/kbn-rule-data-utils/src/rule_types/o11y_rules.ts index dd2b3af12cc4bd..1376379c8e3464 100644 --- a/packages/kbn-rule-data-utils/src/rule_types/o11y_rules.ts +++ b/packages/kbn-rule-data-utils/src/rule_types/o11y_rules.ts @@ -19,3 +19,5 @@ export enum ApmRuleType { TransactionDuration = 'apm.transaction_duration', Anomaly = 'apm.anomaly', } + +export const APM_RULE_TYPE_IDS = Object.values(ApmRuleType); diff --git a/packages/kbn-securitysolution-rules/src/rule_type_constants.ts b/packages/kbn-securitysolution-rules/src/rule_type_constants.ts index 136c8353a5091f..28836498c13607 100644 --- a/packages/kbn-securitysolution-rules/src/rule_type_constants.ts +++ b/packages/kbn-securitysolution-rules/src/rule_type_constants.ts @@ -23,3 +23,14 @@ export const QUERY_RULE_TYPE_ID = `${RULE_TYPE_PREFIX}.queryRule` as const; export const SAVED_QUERY_RULE_TYPE_ID = `${RULE_TYPE_PREFIX}.savedQueryRule` as const; export const THRESHOLD_RULE_TYPE_ID = `${RULE_TYPE_PREFIX}.thresholdRule` as const; export const NEW_TERMS_RULE_TYPE_ID = `${RULE_TYPE_PREFIX}.newTermsRule` as const; + +export const SECURITY_SOLUTION_RULE_TYPE_IDS = [ + EQL_RULE_TYPE_ID, + ESQL_RULE_TYPE_ID, + INDICATOR_RULE_TYPE_ID, + ML_RULE_TYPE_ID, + QUERY_RULE_TYPE_ID, + SAVED_QUERY_RULE_TYPE_ID, + THRESHOLD_RULE_TYPE_ID, + NEW_TERMS_RULE_TYPE_ID, +]; diff --git a/x-pack/packages/observability/alert_details/src/hooks/use_alerts_history.test.tsx b/x-pack/packages/observability/alert_details/src/hooks/use_alerts_history.test.tsx index 82ced89354006d..9081b497736b9b 100644 --- a/x-pack/packages/observability/alert_details/src/hooks/use_alerts_history.test.tsx +++ b/x-pack/packages/observability/alert_details/src/hooks/use_alerts_history.test.tsx @@ -6,7 +6,6 @@ */ import React from 'react'; import { HttpSetup } from '@kbn/core-http-browser'; -import { AlertConsumers } from '@kbn/rule-data-utils'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { act, renderHook } from '@testing-library/react-hooks'; import { @@ -44,7 +43,7 @@ describe('useAlertsHistory', () => { () => useAlertsHistory({ http, - featureIds: [AlertConsumers.APM], + ruleTypeIds: ['apm'], ruleId, dateRange: { from: start, to: end }, }), @@ -70,7 +69,7 @@ describe('useAlertsHistory', () => { () => useAlertsHistory({ http, - featureIds: [AlertConsumers.APM], + ruleTypeIds: ['apm'], ruleId, dateRange: { from: start, to: end }, }), @@ -134,7 +133,7 @@ describe('useAlertsHistory', () => { () => useAlertsHistory({ http, - featureIds: [AlertConsumers.APM], + ruleTypeIds: ['apm'], ruleId, dateRange: { from: start, to: end }, }), @@ -174,7 +173,7 @@ describe('useAlertsHistory', () => { () => useAlertsHistory({ http, - featureIds: [AlertConsumers.APM], + ruleTypeIds: ['apm'], ruleId, dateRange: { from: start, to: end }, instanceId: 'instance-1', @@ -223,7 +222,7 @@ describe('useAlertsHistory', () => { () => useAlertsHistory({ http, - featureIds: [AlertConsumers.APM], + ruleTypeIds: ['apm'], ruleId, dateRange: { from: start, to: end }, instanceId: '*', diff --git a/x-pack/packages/observability/alert_details/src/hooks/use_alerts_history.ts b/x-pack/packages/observability/alert_details/src/hooks/use_alerts_history.ts index 7519fea5f99f8d..51e316313b24f4 100644 --- a/x-pack/packages/observability/alert_details/src/hooks/use_alerts_history.ts +++ b/x-pack/packages/observability/alert_details/src/hooks/use_alerts_history.ts @@ -14,14 +14,13 @@ import { ALERT_START, ALERT_STATUS, ALERT_TIME_RANGE, - ValidFeatureId, } from '@kbn/rule-data-utils'; import { BASE_RAC_ALERTS_API_PATH } from '@kbn/rule-registry-plugin/common'; import { useQuery } from '@tanstack/react-query'; export interface Props { http: HttpSetup | undefined; - featureIds: ValidFeatureId[]; + ruleTypeIds: string[]; ruleId: string; dateRange: { from: string; @@ -49,7 +48,7 @@ export const EMPTY_ALERTS_HISTORY = { }; export function useAlertsHistory({ - featureIds, + ruleTypeIds, ruleId, dateRange, http, @@ -62,7 +61,7 @@ export function useAlertsHistory({ throw new Error('Http client is missing'); } return fetchTriggeredAlertsHistory({ - featureIds, + ruleTypeIds, http, ruleId, dateRange, @@ -99,14 +98,14 @@ interface AggsESResponse { } export async function fetchTriggeredAlertsHistory({ - featureIds, + ruleTypeIds, http, ruleId, dateRange, signal, instanceId, }: { - featureIds: ValidFeatureId[]; + ruleTypeIds: string[]; http: HttpSetup; ruleId: string; dateRange: { @@ -121,7 +120,7 @@ export async function fetchTriggeredAlertsHistory({ signal, body: JSON.stringify({ size: 0, - feature_ids: featureIds, + rule_type_ids: ruleTypeIds, query: { bool: { must: [ diff --git a/x-pack/plugins/alerting/common/routes/rule/apis/bulk_untrack_by_query/schemas/v1.ts b/x-pack/plugins/alerting/common/routes/rule/apis/bulk_untrack_by_query/schemas/v1.ts index 62cc67360b162f..26e5283cede138 100644 --- a/x-pack/plugins/alerting/common/routes/rule/apis/bulk_untrack_by_query/schemas/v1.ts +++ b/x-pack/plugins/alerting/common/routes/rule/apis/bulk_untrack_by_query/schemas/v1.ts @@ -9,5 +9,5 @@ import { schema } from '@kbn/config-schema'; export const bulkUntrackByQueryBodySchema = schema.object({ query: schema.arrayOf(schema.any()), - feature_ids: schema.arrayOf(schema.string()), + rule_type_ids: schema.arrayOf(schema.string()), }); diff --git a/x-pack/plugins/alerting/public/pages/maintenance_windows/components/create_maintenance_windows_form.tsx b/x-pack/plugins/alerting/public/pages/maintenance_windows/components/create_maintenance_windows_form.tsx index cd69f972c675aa..2f38e08f7af328 100644 --- a/x-pack/plugins/alerting/public/pages/maintenance_windows/components/create_maintenance_windows_form.tsx +++ b/x-pack/plugins/alerting/public/pages/maintenance_windows/components/create_maintenance_windows_form.tsx @@ -30,7 +30,6 @@ import { } from '@elastic/eui'; import { TIMEZONE_OPTIONS as UI_TIMEZONE_OPTIONS } from '@kbn/core-ui-settings-common'; import { DEFAULT_APP_CATEGORIES } from '@kbn/core-application-common'; -import type { ValidFeatureId } from '@kbn/rule-data-utils'; import type { Filter } from '@kbn/es-query'; import type { IHttpFetchError } from '@kbn/core-http-browser'; import type { KibanaServerError } from '@kbn/kibana-utils-plugin/public'; @@ -213,20 +212,20 @@ export const CreateMaintenanceWindowForm = React.memo ruleType.category))]; }, [validRuleTypes]); - const featureIds = useMemo(() => { + const ruleTypeIds = useMemo(() => { if (!Array.isArray(validRuleTypes) || !Array.isArray(categoryIds) || !mounted) { return []; } - const featureIdsSet = new Set(); + const uniqueRuleTypeIds = new Set(); validRuleTypes.forEach((ruleType) => { if (categoryIds.includes(ruleType.category)) { - featureIdsSet.add(ruleType.producer as ValidFeatureId); + uniqueRuleTypeIds.add(ruleType.id); } }); - return [...featureIdsSet]; + return [...uniqueRuleTypeIds]; }, [validRuleTypes, categoryIds, mounted]); const onCategoryIdsChange = useCallback( @@ -466,7 +465,7 @@ export const CreateMaintenanceWindowForm = React.memo {() => ( { it('renders correctly', () => { appMockRenderer.render( { it('should hide the search bar if isEnabled is false', () => { appMockRenderer.render( { it('should render loading if isLoading is true', () => { appMockRenderer.render( { const { - featureIds, + ruleTypeIds, query, filters, errors = [], @@ -76,7 +75,7 @@ export const MaintenanceWindowScopedQuery = React.memo( { }, }, ], - featureIds: ['o11y'], + ruleTypeIds: ['my-rule-type-id'], spaceId: 'default', getAllAuthorizedRuleTypesFindOperation: getAllAuthorizedRuleTypesFindOperationMock, getAlertIndicesAlias: getAlertIndicesAliasMock, @@ -583,7 +583,7 @@ describe('setAlertsToUntracked()', () => { }, }, ], - featureIds: ['o11y'], + ruleTypeIds: ['my-rule-type-id'], spaceId: 'default', getAllAuthorizedRuleTypesFindOperation: getAllAuthorizedRuleTypesFindOperationMock, getAlertIndicesAlias: getAlertIndicesAliasMock, diff --git a/x-pack/plugins/alerting/server/application/rule/methods/bulk_untrack/bulk_untrack_alerts.ts b/x-pack/plugins/alerting/server/application/rule/methods/bulk_untrack/bulk_untrack_alerts.ts index 35e6e6ea00e03c..e93f82da28cbec 100644 --- a/x-pack/plugins/alerting/server/application/rule/methods/bulk_untrack/bulk_untrack_alerts.ts +++ b/x-pack/plugins/alerting/server/application/rule/methods/bulk_untrack/bulk_untrack_alerts.ts @@ -41,7 +41,7 @@ async function bulkUntrackAlertsWithOCC(context: RulesClientContext, params: Bul if (!context.alertsService) throw new Error('unable to access alertsService'); const result = await context.alertsService.setAlertsToUntracked({ ...params, - featureIds: params.featureIds || [], + ruleTypeIds: params.ruleTypeIds || [], spaceId: context.spaceId, getAlertIndicesAlias: context.getAlertIndicesAlias, getAllAuthorizedRuleTypesFindOperation: diff --git a/x-pack/plugins/alerting/server/application/rule/methods/bulk_untrack/schemas/bulk_untrack_body_schema.ts b/x-pack/plugins/alerting/server/application/rule/methods/bulk_untrack/schemas/bulk_untrack_body_schema.ts index f597d9f5b6fa46..8a4affbc83c3f3 100644 --- a/x-pack/plugins/alerting/server/application/rule/methods/bulk_untrack/schemas/bulk_untrack_body_schema.ts +++ b/x-pack/plugins/alerting/server/application/rule/methods/bulk_untrack/schemas/bulk_untrack_body_schema.ts @@ -11,5 +11,5 @@ export const bulkUntrackBodySchema = schema.object({ indices: schema.maybe(schema.arrayOf(schema.string())), alertUuids: schema.maybe(schema.arrayOf(schema.string())), query: schema.maybe(schema.arrayOf(schema.any())), - featureIds: schema.maybe(schema.arrayOf(schema.string())), + ruleTypeIds: schema.maybe(schema.arrayOf(schema.string())), }); diff --git a/x-pack/plugins/alerting/server/routes/rule/apis/bulk_untrack_by_query/bulk_untrack_alerts_by_query_route.test.ts b/x-pack/plugins/alerting/server/routes/rule/apis/bulk_untrack_by_query/bulk_untrack_alerts_by_query_route.test.ts index 3486005d3b588e..ebaab0cb98402d 100644 --- a/x-pack/plugins/alerting/server/routes/rule/apis/bulk_untrack_by_query/bulk_untrack_alerts_by_query_route.test.ts +++ b/x-pack/plugins/alerting/server/routes/rule/apis/bulk_untrack_by_query/bulk_untrack_alerts_by_query_route.test.ts @@ -45,7 +45,7 @@ describe('bulkUntrackAlertsByQueryRoute', () => { }, }, ], - feature_ids: ['o11y'], + rule_type_ids: ['o11y'], }; const [context, req, res] = mockHandlerArguments( @@ -62,7 +62,7 @@ describe('bulkUntrackAlertsByQueryRoute', () => { expect(rulesClient.bulkUntrackAlerts.mock.calls[0]).toEqual([ { query: requestBody.query, - featureIds: requestBody.feature_ids, + ruleTypeIds: requestBody.rule_type_ids, isUsingQuery: true, }, ]); diff --git a/x-pack/plugins/alerting/server/routes/rule/apis/bulk_untrack_by_query/transforms/transform_bulk_untrack_alerts_by_query_body/v1.ts b/x-pack/plugins/alerting/server/routes/rule/apis/bulk_untrack_by_query/transforms/transform_bulk_untrack_alerts_by_query_body/v1.ts index 87c58c48c4c6d8..dd346f8cc818ec 100644 --- a/x-pack/plugins/alerting/server/routes/rule/apis/bulk_untrack_by_query/transforms/transform_bulk_untrack_alerts_by_query_body/v1.ts +++ b/x-pack/plugins/alerting/server/routes/rule/apis/bulk_untrack_by_query/transforms/transform_bulk_untrack_alerts_by_query_body/v1.ts @@ -9,8 +9,8 @@ import type { BulkUntrackByQueryRequestBodyV1 } from '../../../../../../../commo export const transformBulkUntrackAlertsByQueryBody = ({ query, - feature_ids: featureIds, + rule_type_ids: ruleTypeIds, }: BulkUntrackByQueryRequestBodyV1) => ({ query, - featureIds, + ruleTypeIds, }); diff --git a/x-pack/plugins/alerting/server/routes/suggestions/values_suggestion_alerts.ts b/x-pack/plugins/alerting/server/routes/suggestions/values_suggestion_alerts.ts index e3cc1deb7dd652..e7be7b1ad8a453 100644 --- a/x-pack/plugins/alerting/server/routes/suggestions/values_suggestion_alerts.ts +++ b/x-pack/plugins/alerting/server/routes/suggestions/values_suggestion_alerts.ts @@ -11,15 +11,9 @@ import { firstValueFrom, Observable } from 'rxjs'; import { getRequestAbortedSignal } from '@kbn/data-plugin/server'; import { termsAggSuggestions } from '@kbn/unified-search-plugin/server/autocomplete/terms_agg'; import type { ConfigSchema } from '@kbn/unified-search-plugin/config'; -import { UsageCounter } from '@kbn/usage-collection-plugin/server'; import { getKbnServerError, reportServerError } from '@kbn/kibana-utils-plugin/server'; import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; -import { - AlertConsumers, - ALERT_RULE_CONSUMER, - ALERT_RULE_TYPE_ID, - SPACE_IDS, -} from '@kbn/rule-data-utils'; +import { ALERT_RULE_CONSUMER, ALERT_RULE_TYPE_ID, SPACE_IDS } from '@kbn/rule-data-utils'; import { verifyAccessAndContext } from '../lib'; import { RuleAuditAction, ruleAuditEvent } from '../../rules_client/common/audit_events'; @@ -46,20 +40,11 @@ export const AlertsSuggestionsSchema = { }), }; -const VALID_FEATURE_IDS = new Set([ - AlertConsumers.APM, - AlertConsumers.INFRASTRUCTURE, - AlertConsumers.LOGS, - AlertConsumers.SLO, - AlertConsumers.UPTIME, -]); - export function registerAlertsValueSuggestionsRoute( router: IRouter, licenseState: ILicenseState, config$: Observable, - getAlertIndicesAlias?: GetAlertIndicesAlias, - usageCounter?: UsageCounter + getAlertIndicesAlias?: GetAlertIndicesAlias ) { router.post( { @@ -85,10 +70,9 @@ export function registerAlertsValueSuggestionsRoute( filterOpts: alertingAuthorizationFilterOpts, }); - authorizedRuleType = await authorization.getAllAuthorizedRuleTypesFindOperation( - AlertingAuthorizationEntity.Alert, - VALID_FEATURE_IDS - ); + authorizedRuleType = await authorization.getAllAuthorizedRuleTypesFindOperation({ + authorizationEntity: AlertingAuthorizationEntity.Alert, + }); } catch (error) { rulesClient.getAuditLogger()?.log( ruleAuditEvent({ diff --git a/x-pack/plugins/cases/public/components/case_view/components/case_view_alerts.test.tsx b/x-pack/plugins/cases/public/components/case_view/components/case_view_alerts.test.tsx index fe2deb74dfa102..a4cc4c751eba69 100644 --- a/x-pack/plugins/cases/public/components/case_view/components/case_view_alerts.test.tsx +++ b/x-pack/plugins/cases/public/components/case_view/components/case_view_alerts.test.tsx @@ -54,7 +54,7 @@ describe('CaseUI View Page activity tab', () => { expect(getAlertsStateTableMock).toHaveBeenCalledWith({ alertsTableConfigurationRegistry: expect.anything(), configurationId: 'securitySolution-case', - featureIds: ['siem'], + ruleTypeIds: ['siem'], id: 'case-details-alerts-securitySolution', query: { ids: { @@ -88,7 +88,7 @@ describe('CaseUI View Page activity tab', () => { expect(getAlertsStateTableMock).toHaveBeenCalledWith({ alertsTableConfigurationRegistry: expect.anything(), configurationId: 'case-details-alerts-observability', - featureIds: ['observability'], + ruleTypeIds: ['observability'], id: 'case-details-alerts-observability', query: { ids: { diff --git a/x-pack/plugins/cases/public/components/case_view/components/case_view_alerts.tsx b/x-pack/plugins/cases/public/components/case_view/components/case_view_alerts.tsx index 9570bee46b3fe3..7d98973a29f562 100644 --- a/x-pack/plugins/cases/public/components/case_view/components/case_view_alerts.tsx +++ b/x-pack/plugins/cases/public/components/case_view/components/case_view_alerts.tsx @@ -10,6 +10,7 @@ import React, { useMemo } from 'react'; import { EuiFlexItem, EuiFlexGroup, EuiProgress } from '@elastic/eui'; import type { ValidFeatureId } from '@kbn/rule-registry-plugin/common/technical_rule_data_field_names'; import { AlertConsumers } from '@kbn/rule-registry-plugin/common/technical_rule_data_field_names'; +import type { AlertsTableStateProps } from '@kbn/triggers-actions-ui-plugin/public/application/sections/alerts_table/alerts_table_state'; import { SECURITY_SOLUTION_OWNER } from '../../../../common/constants'; import type { CaseUI } from '../../../../common'; import { useKibana } from '../../../common/lib/kibana'; @@ -49,7 +50,7 @@ export const CaseViewAlerts = ({ caseData, onAlertsTableLoaded }: CaseViewAlerts ) : ''; - const alertStateProps = useMemo( + const alertStateProps: AlertsTableStateProps = useMemo( () => ({ alertsTableConfigurationRegistry: triggersActionsUi.alertsTableConfigurationRegistry, configurationId: configId, diff --git a/x-pack/plugins/ml/common/constants/alerts.ts b/x-pack/plugins/ml/common/constants/alerts.ts index 009345d23542d6..1128a217d11fe2 100644 --- a/x-pack/plugins/ml/common/constants/alerts.ts +++ b/x-pack/plugins/ml/common/constants/alerts.ts @@ -21,6 +21,8 @@ export const ML_ALERT_TYPES = { AD_JOBS_HEALTH: 'xpack.ml.anomaly_detection_jobs_health', } as const; +export const ML_RULE_TYPE_IDS = Object.values(ML_ALERT_TYPES); + export type MlAlertType = (typeof ML_ALERT_TYPES)[keyof typeof ML_ALERT_TYPES]; export const ALERT_PREVIEW_SAMPLE_SIZE = 5; diff --git a/x-pack/plugins/ml/common/index.ts b/x-pack/plugins/ml/common/index.ts index ac0da68923e52d..c714173a933ae9 100644 --- a/x-pack/plugins/ml/common/index.ts +++ b/x-pack/plugins/ml/common/index.ts @@ -9,5 +9,5 @@ export { composeValidators, patternValidator } from './util/validators'; export { getDefaultCapabilities as getDefaultMlCapabilities } from './types/capabilities'; export { DATAFEED_STATE, JOB_STATE } from './constants/states'; export type { MlSummaryJob, SummaryJobState } from './types/anomaly_detection_jobs'; -export { ML_ALERT_TYPES } from './constants/alerts'; +export { ML_ALERT_TYPES, ML_RULE_TYPE_IDS } from './constants/alerts'; export type { Job, Datafeed } from './types/anomaly_detection_jobs'; diff --git a/x-pack/plugins/ml/public/application/explorer/alerts/alerts_panel.tsx b/x-pack/plugins/ml/public/application/explorer/alerts/alerts_panel.tsx index 4c76ebe628f4f9..baca3c542b2f74 100644 --- a/x-pack/plugins/ml/public/application/explorer/alerts/alerts_panel.tsx +++ b/x-pack/plugins/ml/public/application/explorer/alerts/alerts_panel.tsx @@ -15,9 +15,11 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; -import { ALERT_STATUS_ACTIVE, AlertConsumers, type AlertStatus } from '@kbn/rule-data-utils'; +import { ALERT_STATUS_ACTIVE, type AlertStatus } from '@kbn/rule-data-utils'; +import type { AlertsTableStateProps } from '@kbn/triggers-actions-ui-plugin/public/application/sections/alerts_table/alerts_table_state'; import React, { type FC, useState } from 'react'; import useObservable from 'react-use/lib/useObservable'; +import { ML_RULE_TYPE_IDS } from '../../../../common'; import { ML_ALERTS_CONFIG_ID } from '../../../alerting/anomaly_detection_alerts_table/register_alerts_table_configuration'; import { CollapsiblePanel } from '../../components/collapsible_panel'; import { useMlKibana } from '../../contexts/kibana'; @@ -42,13 +44,12 @@ export const AlertsPanel: FC = () => { const alertsQuery = useObservable(anomalyDetectionAlertsStateService.alertsQuery$, {}); const isLoading = useObservable(anomalyDetectionAlertsStateService.isLoading$, true); - const alertStateProps = { + const alertStateProps: AlertsTableStateProps = { alertsTableConfigurationRegistry: triggersActionsUi!.alertsTableConfigurationRegistry, configurationId: ML_ALERTS_CONFIG_ID, id: `ml-details-alerts`, - featureIds: [AlertConsumers.ML], + ruleTypeIds: ML_RULE_TYPE_IDS, query: alertsQuery, - showExpandToDetails: true, showAlertStatusWithFlapping: true, cellContext: { fieldFormats, diff --git a/x-pack/plugins/ml/public/application/explorer/alerts/anomaly_detection_alerts_state_service.ts b/x-pack/plugins/ml/public/application/explorer/alerts/anomaly_detection_alerts_state_service.ts index d02e9baf91c955..d5d4f710a34c96 100644 --- a/x-pack/plugins/ml/public/application/explorer/alerts/anomaly_detection_alerts_state_service.ts +++ b/x-pack/plugins/ml/public/application/explorer/alerts/anomaly_detection_alerts_state_service.ts @@ -21,7 +21,6 @@ import { ALERT_START, ALERT_STATUS, ALERT_UUID, - AlertConsumers, } from '@kbn/rule-data-utils'; import { isDefined } from '@kbn/ml-is-defined'; import { getSeverityColor } from '@kbn/ml-anomaly-utils'; @@ -30,6 +29,7 @@ import { ALERT_ANOMALY_SCORE, ALERT_ANOMALY_TIMESTAMP, ML_ALERT_TYPES, + ML_RULE_TYPE_IDS, } from '../../../../common/constants/alerts'; import { StateService } from '../../services/state_service'; import type { AnomalyTimelineStateService } from '../anomaly_timeline_state_service'; @@ -175,7 +175,7 @@ export class AnomalyDetectionAlertsStateService extends StateService { return this.data.search .search( { - featureIds: [AlertConsumers.ML], + ruleTypeIds: ML_RULE_TYPE_IDS, query, }, { strategy: 'privateRuleRegistryAlertsSearchStrategy' } diff --git a/x-pack/plugins/observability_solution/apm/public/components/app/alerts_overview/index.tsx b/x-pack/plugins/observability_solution/apm/public/components/app/alerts_overview/index.tsx index e606c5c2e16328..9e870223fa8236 100644 --- a/x-pack/plugins/observability_solution/apm/public/components/app/alerts_overview/index.tsx +++ b/x-pack/plugins/observability_solution/apm/public/components/app/alerts_overview/index.tsx @@ -11,7 +11,7 @@ import { ObservabilityAlertSearchBar } from '@kbn/observability-plugin/public'; import { AlertStatus } from '@kbn/observability-plugin/common/typings'; import { EuiPanel, EuiFlexItem, EuiFlexGroup } from '@elastic/eui'; import { BoolQuery } from '@kbn/es-query'; -import { AlertConsumers } from '@kbn/rule-data-utils'; +import { AlertConsumers, APM_RULE_TYPE_IDS } from '@kbn/rule-data-utils'; import { useKibana } from '@kbn/kibana-react-plugin/public'; import { ApmPluginStartDeps } from '../../../plugin'; import { useAnyOfApmParams } from '../../../hooks/use_apm_params'; @@ -107,7 +107,7 @@ export function AlertsOverview() { alertsTableConfigurationRegistry={alertsTableConfigurationRegistry} id={'service-overview-alerts'} configurationId={AlertConsumers.OBSERVABILITY} - featureIds={[AlertConsumers.APM, AlertConsumers.OBSERVABILITY]} + ruleTypeIds={APM_RULE_TYPE_IDS} query={esQuery} showAlertStatusWithFlapping cellContext={{ observabilityRuleTypeRegistry }} diff --git a/x-pack/plugins/observability_solution/infra/common/alerting/metrics/types.ts b/x-pack/plugins/observability_solution/infra/common/alerting/metrics/types.ts index b5a3c084c47cb8..2a304ea1c40f5f 100644 --- a/x-pack/plugins/observability_solution/infra/common/alerting/metrics/types.ts +++ b/x-pack/plugins/observability_solution/infra/common/alerting/metrics/types.ts @@ -18,6 +18,8 @@ export enum InfraRuleType { InventoryThreshold = 'metrics.alert.inventory.threshold', } +export const INFRA_RULE_TYPE_IDS = Object.values(InfraRuleType); + export enum Aggregators { COUNT = 'count', AVERAGE = 'avg', diff --git a/x-pack/plugins/observability_solution/infra/public/components/shared/alerts/alerts_overview.tsx b/x-pack/plugins/observability_solution/infra/public/components/shared/alerts/alerts_overview.tsx index 2cdc0ee81d7fe6..654b87ab2e48ee 100644 --- a/x-pack/plugins/observability_solution/infra/public/components/shared/alerts/alerts_overview.tsx +++ b/x-pack/plugins/observability_solution/infra/public/components/shared/alerts/alerts_overview.tsx @@ -12,10 +12,11 @@ import { AlertConsumers } from '@kbn/rule-data-utils'; import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import { BrushEndListener, XYBrushEvent } from '@elastic/charts'; import type { InventoryItemType } from '@kbn/metrics-data-access-plugin/common'; +import { INFRA_RULE_TYPE_IDS } from '../../../../common/alerting/metrics/types'; import { AlertsCount } from '../../../hooks/use_alerts_count'; import { useKibanaContextForPlugin } from '../../../hooks/use_kibana'; import { createAlertsEsQuery } from '../../../utils/filters/create_alerts_es_query'; -import { ALERT_STATUS_ALL, infraAlertFeatureIds } from './constants'; +import { ALERT_STATUS_ALL } from './constants'; import { HostsStateUpdater } from '../../../pages/metrics/hosts/hooks/use_unified_search_url_state'; import AlertsStatusFilter from './alerts_status_filter'; import { useAssetDetailsUrlState } from '../../asset_details/hooks/use_asset_details_url_state'; @@ -28,8 +29,6 @@ interface AlertsOverviewProps { assetType?: InventoryItemType; } -const alertFeatureIds = [...infraAlertFeatureIds, AlertConsumers.OBSERVABILITY]; - export const AlertsOverview = ({ assetId, dateRange, @@ -115,7 +114,7 @@ export const AlertsOverview = ({ { }; describe('useAlertsCount', () => { - const featureIds: ValidFeatureId[] = ['infrastructure']; + const ruleTypeIds: string[] = ['infrastructure']; beforeAll(() => { mockUseKibana(); @@ -66,7 +66,7 @@ describe('useAlertsCount', () => { it('should return the mocked data from API', async () => { mockedPostAPI.mockResolvedValue(mockedAlertsCountResponse); - const { result, waitForNextUpdate } = renderHook(() => useAlertsCount({ featureIds })); + const { result, waitForNextUpdate } = renderHook(() => useAlertsCount({ ruleTypeIds })); expect(result.current.loading).toBe(true); expect(result.current.alertsCount).toEqual(undefined); @@ -90,7 +90,7 @@ describe('useAlertsCount', () => { const { waitForNextUpdate } = renderHook(() => useAlertsCount({ - featureIds, + ruleTypeIds, query, }) ); @@ -103,7 +103,7 @@ describe('useAlertsCount', () => { terms: { field: ALERT_STATUS }, }, }, - feature_ids: featureIds, + feature_ids: ruleTypeIds, query, size: 0, }); @@ -118,7 +118,7 @@ describe('useAlertsCount', () => { const error = new Error('Fetch Alerts Count Failed'); mockedPostAPI.mockRejectedValueOnce(error); - const { result, waitForNextUpdate } = renderHook(() => useAlertsCount({ featureIds })); + const { result, waitForNextUpdate } = renderHook(() => useAlertsCount({ ruleTypeIds })); await waitForNextUpdate(); diff --git a/x-pack/plugins/observability_solution/infra/public/hooks/use_alerts_count.ts b/x-pack/plugins/observability_solution/infra/public/hooks/use_alerts_count.ts index 5c602d09b7d232..b0a28219b9a1fb 100644 --- a/x-pack/plugins/observability_solution/infra/public/hooks/use_alerts_count.ts +++ b/x-pack/plugins/observability_solution/infra/public/hooks/use_alerts_count.ts @@ -12,17 +12,17 @@ import { BASE_RAC_ALERTS_API_PATH } from '@kbn/rule-registry-plugin/common/const import { estypes } from '@elastic/elasticsearch'; import { useKibana } from '@kbn/kibana-react-plugin/public'; import type { HttpSetup } from '@kbn/core/public'; -import { ALERT_STATUS_ACTIVE, ALERT_STATUS_RECOVERED, ValidFeatureId } from '@kbn/rule-data-utils'; +import { ALERT_STATUS_ACTIVE, ALERT_STATUS_RECOVERED } from '@kbn/rule-data-utils'; import { InfraClientCoreStart } from '../types'; interface UseAlertsCountProps { - featureIds: ValidFeatureId[]; + ruleTypeIds: string[]; query?: estypes.QueryDslQueryContainer; } interface FetchAlertsCountParams { - featureIds: ValidFeatureId[]; + ruleTypeIds: string[]; query?: estypes.QueryDslQueryContainer; http: HttpSetup; signal: AbortSignal; @@ -35,7 +35,7 @@ export interface AlertsCount { const ALERT_STATUS = 'kibana.alert.status'; -export function useAlertsCount({ featureIds, query }: UseAlertsCountProps) { +export function useAlertsCount({ ruleTypeIds, query }: UseAlertsCountProps) { const { http } = useKibana().services; const abortCtrlRef = useRef(new AbortController()); @@ -45,13 +45,13 @@ export function useAlertsCount({ featureIds, query }: UseAlertsCountProps) { abortCtrlRef.current.abort(); abortCtrlRef.current = new AbortController(); return fetchAlertsCount({ - featureIds, + ruleTypeIds, query, http, signal: abortCtrlRef.current.signal, }); }, - [featureIds, query, http], + [ruleTypeIds, query, http], { loading: true } ); @@ -70,7 +70,7 @@ export function useAlertsCount({ featureIds, query }: UseAlertsCountProps) { } async function fetchAlertsCount({ - featureIds, + ruleTypeIds, http, query, signal, @@ -84,7 +84,7 @@ async function fetchAlertsCount({ terms: { field: ALERT_STATUS }, }, }, - feature_ids: featureIds, + rule_type_ids: ruleTypeIds, query, size: 0, }), diff --git a/x-pack/plugins/observability_solution/infra/public/pages/metrics/hosts/components/tabs/alerts/alerts_tab_content.tsx b/x-pack/plugins/observability_solution/infra/public/pages/metrics/hosts/components/tabs/alerts/alerts_tab_content.tsx index 6350cab5e3ff6b..d30a709d08edff 100644 --- a/x-pack/plugins/observability_solution/infra/public/pages/metrics/hosts/components/tabs/alerts/alerts_tab_content.tsx +++ b/x-pack/plugins/observability_solution/infra/public/pages/metrics/hosts/components/tabs/alerts/alerts_tab_content.tsx @@ -10,6 +10,7 @@ import { AlertConsumers, ALERT_RULE_PRODUCER } from '@kbn/rule-data-utils'; import { BrushEndListener, type XYBrushEvent } from '@elastic/charts'; import { useSummaryTimeRange } from '@kbn/observability-plugin/public'; import { useBoolean } from '@kbn/react-hooks'; +import { INFRA_RULE_TYPE_IDS } from '../../../../../../../common/alerting/metrics/types'; import { useKibanaContextForPlugin } from '../../../../../../hooks/use_kibana'; import { HeightRetainer } from '../../../../../../components/height_retainer'; import { useUnifiedSearchContext } from '../../../hooks/use_unified_search'; @@ -19,7 +20,6 @@ import { AlertsEsQuery } from '../../../../../../utils/filters/create_alerts_es_ import { ALERTS_PER_PAGE, ALERTS_TABLE_ID, - infraAlertFeatureIds, } from '../../../../../../components/shared/alerts/constants'; import AlertsStatusFilter from '../../../../../../components/shared/alerts/alerts_status_filter'; import { CreateAlertRuleButton } from '../../../../../../components/shared/alerts/links/create_alert_rule_button'; @@ -79,7 +79,7 @@ export const AlertsTabContent = () => { { const { alertsEsQuery } = useAlertsQuery(); const { alertsCount, loading, error } = useAlertsCount({ - featureIds: infraAlertFeatureIds, + ruleTypeIds: INFRA_RULE_TYPE_IDS, query: alertsEsQuery, }); diff --git a/x-pack/plugins/observability_solution/observability/common/constants.ts b/x-pack/plugins/observability_solution/observability/common/constants.ts index a45e421f6a8e4f..193dc0a8c70766 100644 --- a/x-pack/plugins/observability_solution/observability/common/constants.ts +++ b/x-pack/plugins/observability_solution/observability/common/constants.ts @@ -5,9 +5,17 @@ * 2.0. */ -import { AlertConsumers } from '@kbn/rule-data-utils'; +import { + AlertConsumers, + APM_RULE_TYPE_IDS, + SLO_BURN_RATE_RULE_TYPE_ID, +} from '@kbn/rule-data-utils'; import type { ValidFeatureId } from '@kbn/rule-data-utils'; import type { RuleCreationValidConsumer } from '@kbn/triggers-actions-ui-plugin/public'; +import { SYNTHETICS_RULE_TYPES } from '@kbn/synthetics-plugin/common/constants/synthetics_alerts'; +import { UPTIME_RULE_TYPES } from '@kbn/uptime-plugin/common/constants/uptime_alerts'; +import { INFRA_RULE_TYPE_IDS } from '@kbn/infra-plugin/common/alerting/metrics/types'; +import { LOG_DOCUMENT_COUNT_RULE_TYPE_ID } from '@kbn/infra-plugin/common/alerting/logs/log_threshold/types'; export const INVALID_EQUATION_REGEX = /[^A-Z|+|\-|\s|\d+|\.|\(|\)|\/|\*|>|<|=|\?|\:|&|\!|\|]+/g; export const ALERT_STATUS_ALL = 'all'; @@ -30,3 +38,12 @@ export const observabilityRuleCreationValidConsumers: RuleCreationValidConsumer[ ]; export const EventsAsUnit = 'events'; + +export const OBSERVABILITY_RULE_TYPE_IDS = [ + ...APM_RULE_TYPE_IDS, + ...SYNTHETICS_RULE_TYPES, + ...INFRA_RULE_TYPE_IDS, + ...UPTIME_RULE_TYPES, + LOG_DOCUMENT_COUNT_RULE_TYPE_ID, + SLO_BURN_RATE_RULE_TYPE_ID, +]; diff --git a/x-pack/plugins/observability_solution/observability/public/components/alert_search_bar/alert_search_bar.test.tsx b/x-pack/plugins/observability_solution/observability/public/components/alert_search_bar/alert_search_bar.test.tsx index b7da84869679a0..fb951db83e039a 100644 --- a/x-pack/plugins/observability_solution/observability/public/components/alert_search_bar/alert_search_bar.test.tsx +++ b/x-pack/plugins/observability_solution/observability/public/components/alert_search_bar/alert_search_bar.test.tsx @@ -12,7 +12,7 @@ import { uiSettingsServiceMock } from '@kbn/core-ui-settings-browser-mocks'; import { ObservabilityAlertSearchBarProps, Services } from './types'; import { ObservabilityAlertSearchBar } from './alert_search_bar'; -import { observabilityAlertFeatureIds } from '../../../common/constants'; +import { OBSERVABILITY_RULE_TYPE_IDS } from '../../../common/constants'; import { render } from '../../utils/test_helper'; const getAlertsSearchBarMock = jest.fn(); @@ -69,7 +69,7 @@ describe('ObservabilityAlertSearchBar', () => { expect(getAlertsSearchBarMock).toHaveBeenCalledWith( expect.objectContaining({ appName: 'testAppName', - featureIds: observabilityAlertFeatureIds, + ruleTypeIds: OBSERVABILITY_RULE_TYPE_IDS, rangeFrom: 'now-15m', rangeTo: 'now', query: '', diff --git a/x-pack/plugins/observability_solution/observability/public/components/alert_search_bar/alert_search_bar.tsx b/x-pack/plugins/observability_solution/observability/public/components/alert_search_bar/alert_search_bar.tsx index 863855bbbb3b85..e9f889655aa293 100644 --- a/x-pack/plugins/observability_solution/observability/public/components/alert_search_bar/alert_search_bar.tsx +++ b/x-pack/plugins/observability_solution/observability/public/components/alert_search_bar/alert_search_bar.tsx @@ -12,7 +12,7 @@ import { i18n } from '@kbn/i18n'; import { Filter, Query } from '@kbn/es-query'; import { getEsQueryConfig } from '@kbn/data-plugin/common'; import { AlertsStatusFilter } from './components'; -import { observabilityAlertFeatureIds } from '../../../common/constants'; +import { OBSERVABILITY_RULE_TYPE_IDS } from '../../../common/constants'; import { ALERT_STATUS_QUERY, DEFAULT_QUERIES, DEFAULT_QUERY_STRING } from './constants'; import { ObservabilityAlertSearchBarProps } from './types'; import { buildEsQuery } from '../../utils/build_es_query'; @@ -161,7 +161,7 @@ export function ObservabilityAlertSearchBar({ type.id === rule?.ruleTypeId); - const featureIds = - rule?.consumer === ALERTING_FEATURE_ID && ruleType?.producer - ? [ruleType.producer as AlertConsumers] - : rule - ? [rule.consumer as AlertConsumers] - : []; const ruleId = alert.fields[ALERT_RULE_UUID]; const { @@ -63,7 +51,7 @@ export function AlertHistoryChart({ rule, alert }: Props) { isError, } = useAlertsHistory({ http, - featureIds, + ruleTypeIds: OBSERVABILITY_RULE_TYPE_IDS, ruleId: rule.id, dateRange, instanceId, @@ -162,7 +150,7 @@ export function AlertHistoryChart({ rule, alert }: Props) { ; ruleId: string; ruleType: any; @@ -49,7 +48,7 @@ interface Props { export function RuleDetailsTabs({ activeTabId, esQuery, - featureIds, + ruleTypeIds, rule, ruleId, ruleType, @@ -90,12 +89,12 @@ export function RuleDetailsTabs({ - {esQuery && featureIds && ( + {esQuery && ruleTypeIds && ( type.id === rule?.ruleTypeId); - const isEditable = isRuleEditable({ capabilities, rule, ruleType, ruleTypeRegistry }); - const featureIds = - rule?.consumer === ALERTING_FEATURE_ID && ruleType?.producer - ? [ruleType.producer as AlertConsumers] - : rule - ? [rule.consumer as AlertConsumers] - : []; - const ruleStatusMessage = rule?.executionStatus.error?.reason === RuleExecutionStatusErrorReasons.License ? rulesStatusesTranslationsMapping.noLicense @@ -226,7 +217,7 @@ export function RuleDetailsPage() { ({ diff --git a/x-pack/plugins/observability_solution/uptime/common/constants/uptime_alerts.ts b/x-pack/plugins/observability_solution/uptime/common/constants/uptime_alerts.ts index 71f6bd1b183fb1..11c93d646eb16a 100644 --- a/x-pack/plugins/observability_solution/uptime/common/constants/uptime_alerts.ts +++ b/x-pack/plugins/observability_solution/uptime/common/constants/uptime_alerts.ts @@ -5,42 +5,6 @@ * 2.0. */ -import { ActionGroup } from '@kbn/alerting-plugin/common'; - -export type MonitorStatusActionGroup = - ActionGroup<'xpack.uptime.alerts.actionGroups.monitorStatus'>; -export type TLSLegacyActionGroup = ActionGroup<'xpack.uptime.alerts.actionGroups.tls'>; -export type TLSActionGroup = ActionGroup<'xpack.uptime.alerts.actionGroups.tlsCertificate'>; -export type DurationAnomalyActionGroup = - ActionGroup<'xpack.uptime.alerts.actionGroups.durationAnomaly'>; - -export const MONITOR_STATUS: MonitorStatusActionGroup = { - id: 'xpack.uptime.alerts.actionGroups.monitorStatus', - name: 'Uptime Down Monitor', -}; - -export const TLS_LEGACY: TLSLegacyActionGroup = { - id: 'xpack.uptime.alerts.actionGroups.tls', - name: 'Uptime TLS Alert (Legacy)', -}; - -export const TLS: TLSActionGroup = { - id: 'xpack.uptime.alerts.actionGroups.tlsCertificate', - name: 'Uptime TLS Alert', -}; - -export const DURATION_ANOMALY: DurationAnomalyActionGroup = { - id: 'xpack.uptime.alerts.actionGroups.durationAnomaly', - name: 'Uptime Duration Anomaly', -}; - -export const CLIENT_ALERT_TYPES = { - MONITOR_STATUS: 'xpack.uptime.alerts.monitorStatus', - TLS_LEGACY: 'xpack.uptime.alerts.tls', - TLS: 'xpack.uptime.alerts.tlsCertificate', - DURATION_ANOMALY: 'xpack.uptime.alerts.durationAnomaly', -}; - export const UPTIME_RULE_TYPES = [ 'xpack.uptime.alerts.tls', 'xpack.uptime.alerts.tlsCertificate', diff --git a/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.mock.ts b/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.mock.ts index 66ef6a73013f41..d58d5398f907c4 100644 --- a/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.mock.ts +++ b/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.mock.ts @@ -20,7 +20,6 @@ const createAlertsClientMock = () => { bulkUpdateCases: jest.fn(), find: jest.fn(), getGroupAggregations: jest.fn(), - getFeatureIdsByRegistrationContexts: jest.fn(), getBrowserFields: jest.fn(), getAlertSummary: jest.fn(), ensureAllAlertsAuthorizedRead: jest.fn(), diff --git a/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts b/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts index 8882d7ce4a14de..1b1d5cb9cd6173 100644 --- a/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts +++ b/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts @@ -21,7 +21,6 @@ import { ALERT_STATUS_ACTIVE, ALERT_CASE_IDS, MAX_CASES_PER_ALERT, - AlertConsumers, } from '@kbn/rule-data-utils'; import { @@ -1197,11 +1196,11 @@ export class AlertsClient { } public async getAADFields({ ruleTypeId }: { ruleTypeId: string }) { - const { producer, fieldsForAAD = [] } = this.getRuleType(ruleTypeId); - if (producer === AlertConsumers.SIEM) { + const { fieldsForAAD = [] } = this.getRuleType(ruleTypeId); + if (ruleTypeId.startsWith('siem.')) { throw Boom.badRequest(`Security solution rule type is not supported`); } - const indices = await this.getAuthorizedAlertsIndices([producer]); + const indices = await this.getAuthorizedAlertsIndices([ruleTypeId]); const indexPatternsFetcherAsInternalUser = new IndexPatternsFetcher(this.esClient); const { fields = [] } = await indexPatternsFetcherAsInternalUser.getFieldsForWildcard({ pattern: indices ?? [], diff --git a/x-pack/plugins/rule_registry/server/alert_data_client/tests/get_alerts_group_aggregations.test.ts b/x-pack/plugins/rule_registry/server/alert_data_client/tests/get_alerts_group_aggregations.test.ts index af80e2c0a8b556..5b24e98aa48daf 100644 --- a/x-pack/plugins/rule_registry/server/alert_data_client/tests/get_alerts_group_aggregations.test.ts +++ b/x-pack/plugins/rule_registry/server/alert_data_client/tests/get_alerts_group_aggregations.test.ts @@ -5,7 +5,6 @@ * 2.0. */ -import { AlertConsumers } from '@kbn/rule-data-utils'; import { AlertsClient, ConstructorOptions } from '../alerts_client'; import { loggingSystemMock } from '@kbn/core/server/mocks'; import { elasticsearchClientMock } from '@kbn/core-elasticsearch-client-server-mocks'; @@ -71,7 +70,8 @@ describe('getGroupAggregations()', () => { const alertsClient = new AlertsClient(alertsClientParams); alertsClient.find = jest.fn(); - const featureIds = [AlertConsumers.STACK_ALERTS]; + const ruleTypeIds = ['.es-query']; + const groupByField = 'kibana.alert.rule.name'; const aggregations = { usersCount: { @@ -83,7 +83,7 @@ describe('getGroupAggregations()', () => { const filters = [{ range: { '@timestamp': { gte: 'now-1d/d', lte: 'now/d' } } }]; await alertsClient.getGroupAggregations({ - featureIds, + ruleTypeIds, groupByField, aggregations, filters, @@ -92,7 +92,7 @@ describe('getGroupAggregations()', () => { }); expect(alertsClient.find).toHaveBeenCalledWith({ - featureIds, + ruleTypeIds, aggs: { groupByFields: { terms: { @@ -143,7 +143,7 @@ describe('getGroupAggregations()', () => { expect(() => alertsClient.getGroupAggregations({ - featureIds: ['apm', 'infrastructure', 'logs', 'observability', 'slo', 'uptime'], + ruleTypeIds: ['apm', 'infrastructure', 'logs', 'observability', 'slo', 'uptime'], groupByField: 'kibana.alert.rule.name', pageIndex: 101, pageSize: 50, @@ -153,7 +153,7 @@ describe('getGroupAggregations()', () => { ); expect(() => alertsClient.getGroupAggregations({ - featureIds: ['apm', 'infrastructure', 'logs', 'observability', 'slo', 'uptime'], + ruleTypeIds: ['apm', 'infrastructure', 'logs', 'observability', 'slo', 'uptime'], groupByField: 'kibana.alert.rule.name', pageIndex: 10, pageSize: 5000, diff --git a/x-pack/plugins/rule_registry/server/routes/find.ts b/x-pack/plugins/rule_registry/server/routes/find.ts index 5075525a9dbd81..4c79c1f4ea2528 100644 --- a/x-pack/plugins/rule_registry/server/routes/find.ts +++ b/x-pack/plugins/rule_registry/server/routes/find.ts @@ -25,7 +25,7 @@ export const findAlertsByQueryRoute = (router: IRouter t.exact( t.partial({ aggs: t.record(t.string, t.intersection([metricsAggsSchemas, bucketAggsSchemas])), - feature_ids: t.union([t.array(t.string), t.undefined]), + rule_type_ids: t.union([t.array(t.string), t.undefined]), index: t.string, query: t.object, search_after: t.union([t.array(t.number), t.array(t.string), t.undefined]), @@ -45,7 +45,7 @@ export const findAlertsByQueryRoute = (router: IRouter try { const { aggs, - feature_ids: featureIds, + rule_type_ids: ruleTypeIds, index, query, // eslint-disable-next-line @typescript-eslint/naming-convention @@ -60,7 +60,7 @@ export const findAlertsByQueryRoute = (router: IRouter const alertsClient = await racContext.getAlertsClient(); const alerts = await alertsClient.find({ aggs, - featureIds, + ruleTypeIds, index, query, search_after, diff --git a/x-pack/plugins/rule_registry/server/routes/get_alert_summary.test.ts b/x-pack/plugins/rule_registry/server/routes/get_alert_summary.test.ts index e15f2d40dc826d..7a1ec09b9dba5e 100644 --- a/x-pack/plugins/rule_registry/server/routes/get_alert_summary.test.ts +++ b/x-pack/plugins/rule_registry/server/routes/get_alert_summary.test.ts @@ -35,7 +35,7 @@ describe('getAlertSummaryRoute', () => { requestMock.create({ method: 'post', path: `${BASE_RAC_ALERTS_API_PATH}/_alert_summary`, - body: { gte: 4, lte: 3, featureIds: ['logs'] }, + body: { gte: 4, lte: 3, ruleTypeIds: ['logs'] }, }), context ) @@ -52,7 +52,7 @@ describe('getAlertSummaryRoute', () => { body: { gte: '2020-12-16T15:00:00.000Z', lte: '2020-12-16', - featureIds: ['logs'], + ruleTypeIds: ['logs'], }, }), context @@ -76,7 +76,7 @@ describe('getAlertSummaryRoute', () => { body: { gte: '2020-12-16T15:00:00.000Z', lte: '2020-12-16T16:00:00.000Z', - featureIds: ['logs'], + ruleTypeIds: ['logs'], fixed_interval: 'xx', }, }), @@ -102,7 +102,7 @@ describe('getAlertSummaryRoute', () => { body: { gte: '2020-12-16T15:00:00.000Z', lte: '2020-12-16T16:00:00.000Z', - featureIds: ['logs'], + ruleTypeIds: ['logs'], boop: 'unknown', }, }), diff --git a/x-pack/plugins/rule_registry/server/routes/get_browser_fields_by_feature_id.test.ts b/x-pack/plugins/rule_registry/server/routes/get_browser_fields_by_feature_id.test.ts index e77fa3a1ba66d1..b37ee0e18afae5 100644 --- a/x-pack/plugins/rule_registry/server/routes/get_browser_fields_by_feature_id.test.ts +++ b/x-pack/plugins/rule_registry/server/routes/get_browser_fields_by_feature_id.test.ts @@ -47,7 +47,7 @@ describe('getBrowserFieldsByFeatureId', () => { context ) ).rejects.toThrowErrorMatchingInlineSnapshot( - `"Request was rejected with message: 'Invalid value \\"undefined\\" supplied to \\"featureIds\\"'"` + `"Request was rejected with message: 'Invalid value \\"undefined\\" supplied to \\"ruleTypeIds\\"'"` ); }); diff --git a/x-pack/plugins/rule_registry/server/routes/index.ts b/x-pack/plugins/rule_registry/server/routes/index.ts index ae9f113ee0ac12..9169ded668cb32 100644 --- a/x-pack/plugins/rule_registry/server/routes/index.ts +++ b/x-pack/plugins/rule_registry/server/routes/index.ts @@ -13,7 +13,6 @@ import { updateAlertByIdRoute } from './update_alert_by_id'; import { getAlertsIndexRoute } from './get_alert_index'; import { bulkUpdateAlertsRoute } from './bulk_update_alerts'; import { findAlertsByQueryRoute } from './find'; -import { getFeatureIdsByRegistrationContexts } from './get_feature_ids_by_registration_contexts'; import { getBrowserFieldsByFeatureId } from './get_browser_fields_by_feature_id'; import { getAlertSummaryRoute } from './get_alert_summary'; import { getAADFieldsByRuleType } from './get_aad_fields_by_rule_type'; @@ -25,7 +24,6 @@ export function defineRoutes(router: IRouter) { bulkUpdateAlertsRoute(router); findAlertsByQueryRoute(router); getAlertsGroupAggregations(router); - getFeatureIdsByRegistrationContexts(router); getBrowserFieldsByFeatureId(router); getAlertSummaryRoute(router); getAADFieldsByRuleType(router); diff --git a/x-pack/plugins/rule_registry/server/rule_data_plugin_service/rule_data_plugin_service.mock.ts b/x-pack/plugins/rule_registry/server/rule_data_plugin_service/rule_data_plugin_service.mock.ts index 9b279a541b3e9c..cfbfafd0092bfc 100644 --- a/x-pack/plugins/rule_registry/server/rule_data_plugin_service/rule_data_plugin_service.mock.ts +++ b/x-pack/plugins/rule_registry/server/rule_data_plugin_service/rule_data_plugin_service.mock.ts @@ -17,7 +17,6 @@ export const ruleDataServiceMock = { initializeIndex: jest.fn(), findIndexByName: jest.fn(), findIndexByFeature: jest.fn(), - findFeatureIdsByRegistrationContexts: jest.fn(), }), }; diff --git a/x-pack/plugins/rule_registry/server/rule_data_plugin_service/rule_data_plugin_service.ts b/x-pack/plugins/rule_registry/server/rule_data_plugin_service/rule_data_plugin_service.ts index a5f160f05c5378..71652467b7e1c5 100644 --- a/x-pack/plugins/rule_registry/server/rule_data_plugin_service/rule_data_plugin_service.ts +++ b/x-pack/plugins/rule_registry/server/rule_data_plugin_service/rule_data_plugin_service.ts @@ -78,12 +78,6 @@ export interface IRuleDataService { * Note: features are used in RBAC. */ findIndexByFeature(featureId: ValidFeatureId, dataset: Dataset): IndexInfo | null; - - /** - * Looks up Kibana "feature" associated with the given registration context. - * Note: features are used in RBAC. - */ - findFeatureIdsByRegistrationContexts(registrationContexts: string[]): string[]; } // TODO: This is a leftover. Remove its usage from the "observability" plugin and delete it. @@ -246,17 +240,6 @@ export class RuleDataService implements IRuleDataService { return this.indicesByBaseName.get(baseName) ?? null; } - public findFeatureIdsByRegistrationContexts(registrationContexts: string[]): string[] { - const featureIds: string[] = []; - registrationContexts.forEach((rc) => { - const featureId = this.registrationContextByFeatureId.get(rc); - if (featureId) { - featureIds.push(featureId); - } - }); - return featureIds; - } - public findIndexByFeature(featureId: ValidFeatureId, dataset: Dataset): IndexInfo | null { const foundIndices = this.indicesByFeatureId.get(featureId) ?? []; if (dataset && foundIndices.length > 0) { diff --git a/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/tabs/alerts_tab/index.tsx b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/tabs/alerts_tab/index.tsx index fc1838dad055d4..33c0893e7a5949 100644 --- a/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/tabs/alerts_tab/index.tsx +++ b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/tabs/alerts_tab/index.tsx @@ -6,7 +6,8 @@ */ import type { AttackDiscovery, Replacements } from '@kbn/elastic-assistant-common'; -import { AlertConsumers } from '@kbn/rule-registry-plugin/common/technical_rule_data_field_names'; +import { SECURITY_SOLUTION_RULE_TYPE_IDS } from '@kbn/securitysolution-rules'; +import type { AlertsTableStateProps } from '@kbn/triggers-actions-ui-plugin/public/application/sections/alerts_table/alerts_table_state'; import React, { useMemo } from 'react'; import { ALERTS_TABLE_REGISTRY_CONFIG_IDS } from '../../../../../common/constants'; @@ -39,12 +40,12 @@ const AlertsTabComponent: React.FC = ({ attackDiscovery, replacements }) const configId = ALERTS_TABLE_REGISTRY_CONFIG_IDS.CASE; // show the same row-actions as in the case view - const alertStateProps = useMemo( + const alertStateProps: AlertsTableStateProps = useMemo( () => ({ alertsTableConfigurationRegistry: triggersActionsUi.alertsTableConfigurationRegistry, configurationId: configId, id: `attack-discovery-alerts-${attackDiscovery.id}`, - featureIds: [AlertConsumers.SIEM], + ruleTypeIds: SECURITY_SOLUTION_RULE_TYPE_IDS, query: alertIdsQuery, showAlertStatusWithFlapping: false, }), diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_table/index.tsx b/x-pack/plugins/security_solution/public/detections/components/alerts_table/index.tsx index b556f81523fc5a..ca9a46a3d64f57 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_table/index.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_table/index.tsx @@ -22,6 +22,7 @@ import { tableDefaults, TableId, } from '@kbn/securitysolution-data-table'; +import { SECURITY_SOLUTION_RULE_TYPE_IDS } from '@kbn/securitysolution-rules'; import { useGlobalTime } from '../../../common/containers/use_global_time'; import { useLicense } from '../../../common/hooks/use_license'; import { VIEW_SELECTION } from '../../../../common/constants'; @@ -274,7 +275,7 @@ export const AlertsTableComponent: FC = ({ configurationId: configId, // stores separate configuration based on the view of the table id: `detection-engine-alert-table-${configId}-${tableView}`, - featureIds: ['siem'], + ruleTypeIds: SECURITY_SOLUTION_RULE_TYPE_IDS, query: finalBoolQuery, gridStyle, shouldHighlightRow, diff --git a/x-pack/plugins/security_solution/public/detections/components/detection_engine_filters/detection_engine_filters.tsx b/x-pack/plugins/security_solution/public/detections/components/detection_engine_filters/detection_engine_filters.tsx index 126c86055aa4cc..5e5f3418b3e2b9 100644 --- a/x-pack/plugins/security_solution/public/detections/components/detection_engine_filters/detection_engine_filters.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/detection_engine_filters/detection_engine_filters.tsx @@ -7,12 +7,12 @@ import React, { useCallback, useMemo } from 'react'; import type { FilterControlConfig } from '@kbn/alerts-ui-shared'; -import { AlertConsumers } from '@kbn/rule-data-utils'; import { createKbnUrlStateStorage, Storage } from '@kbn/kibana-utils-plugin/public'; import { ControlGroupRenderer } from '@kbn/controls-plugin/public'; import type { AlertFilterControlsProps } from '@kbn/alerts-ui-shared/src/alert_filter_controls'; import { AlertFilterControls } from '@kbn/alerts-ui-shared/src/alert_filter_controls'; import { useHistory } from 'react-router-dom'; +import { SECURITY_SOLUTION_RULE_TYPE_IDS } from '@kbn/securitysolution-rules'; import { useKibana } from '../../../common/lib/kibana'; import { DEFAULT_DETECTION_PAGE_FILTERS } from '../../../../common/constants'; import { URL_PARAM_KEY } from '../../../common/hooks/use_url_state'; @@ -75,7 +75,7 @@ export const DetectionEngineFilters = ({ indexPattern, ...props }: DetectionEngi controlsUrlState={filterControlsUrlState} setControlsUrlState={setFilterControlsUrlState} spaceId={spaceId} - featureIds={[AlertConsumers.SIEM]} + ruleTypeIds={SECURITY_SOLUTION_RULE_TYPE_IDS} chainingSystem="HIERARCHICAL" defaultControls={DEFAULT_DETECTION_PAGE_FILTERS} dataViewSpec={dataViewSpec} diff --git a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_alert_data_view.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_alert_data_view.test.tsx index b12d0454b997c6..3b06e48a65d101 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_alert_data_view.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_alert_data_view.test.tsx @@ -5,9 +5,7 @@ * 2.0. */ -import { AlertConsumers } from '@kbn/rule-data-utils'; import { createStartServicesMock } from '../../common/lib/kibana/kibana_react.mock'; -import type { ValidFeatureId } from '@kbn/rule-data-utils'; import { renderHook } from '@testing-library/react-hooks/dom'; import { useAlertDataViews } from './use_alert_data_view'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; @@ -47,12 +45,7 @@ const wrapper = ({ children }: { children: Node }) => ( ); describe('useAlertDataView', () => { - const observabilityAlertFeatureIds: ValidFeatureId[] = [ - AlertConsumers.APM, - AlertConsumers.INFRASTRUCTURE, - AlertConsumers.LOGS, - AlertConsumers.UPTIME, - ]; + const ruleTypeIds = ['.es-query']; beforeEach(() => { fetchAlertIndexNames.mockResolvedValue([ @@ -75,15 +68,15 @@ describe('useAlertDataView', () => { dataview: undefined, }; - const { result } = renderHook(() => useAlertDataViews(observabilityAlertFeatureIds), { + const { result } = renderHook(() => useAlertDataViews(ruleTypeIds), { wrapper, }); await waitFor(() => expect(result.current).toEqual(mockedAsyncDataView)); }); - it('fetch index names + fields for the provided o11y featureIds', async () => { - renderHook(() => useAlertDataViews(observabilityAlertFeatureIds), { + it('fetch index names + fields for the provided o11y ruleTypeIds', async () => { + renderHook(() => useAlertDataViews(ruleTypeIds), { wrapper, }); @@ -92,7 +85,7 @@ describe('useAlertDataView', () => { }); it('only fetch index names for security featureId', async () => { - renderHook(() => useAlertDataViews([AlertConsumers.SIEM]), { + renderHook(() => useAlertDataViews(['siem.esqlRule']), { wrapper, }); @@ -100,13 +93,10 @@ describe('useAlertDataView', () => { expect(fetchAlertFields).toHaveBeenCalledTimes(0); }); - it('Do not fetch anything if security and o11y featureIds are mixed together', async () => { - const { result } = renderHook( - () => useAlertDataViews([AlertConsumers.SIEM, AlertConsumers.LOGS]), - { - wrapper, - } - ); + it('Do not fetch anything if security and o11y ruleTypeIds are mixed together', async () => { + const { result } = renderHook(() => useAlertDataViews(['siem.esqlRule', 'logs']), { + wrapper, + }); await waitFor(() => expect(result.current).toEqual({ @@ -121,7 +111,7 @@ describe('useAlertDataView', () => { it('if fetch throws error return no data', async () => { fetchAlertIndexNames.mockRejectedValue('error'); - const { result } = renderHook(() => useAlertDataViews(observabilityAlertFeatureIds), { + const { result } = renderHook(() => useAlertDataViews(ruleTypeIds), { wrapper, }); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_alert_summary.test.ts b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_alert_summary.test.ts index e56c8aa1348b98..06bf7ccf49d77b 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_alert_summary.test.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_alert_summary.test.ts @@ -6,7 +6,6 @@ */ import { renderHook } from '@testing-library/react-hooks'; -import { ValidFeatureId } from '@kbn/rule-data-utils'; import { useKibana } from '../../common/lib/kibana'; import { mockedAlertSummaryResponse, @@ -18,7 +17,7 @@ jest.mock('../../common/lib/kibana'); const useKibanaMock = useKibana as jest.Mocked; describe('useLoadAlertSummary', () => { - const featureIds: ValidFeatureId[] = ['apm']; + const ruleTypeIds: string[] = ['apm']; const mockedPostAPI = jest.fn(); beforeAll(() => { @@ -36,7 +35,7 @@ describe('useLoadAlertSummary', () => { const { result, waitForNextUpdate } = renderHook(() => useLoadAlertSummary({ - featureIds, + ruleTypeIds, timeRange: mockedAlertSummaryTimeRange, }) ); @@ -72,7 +71,7 @@ describe('useLoadAlertSummary', () => { const { waitForNextUpdate } = renderHook(() => useLoadAlertSummary({ - featureIds, + ruleTypeIds, timeRange: mockedAlertSummaryTimeRange, filter, }) @@ -84,7 +83,7 @@ describe('useLoadAlertSummary', () => { fixed_interval: fixedInterval, gte: utcFrom, lte: utcTo, - featureIds, + ruleTypeIds, filter: [filter], }); expect(mockedPostAPI).toHaveBeenCalledWith( @@ -101,7 +100,7 @@ describe('useLoadAlertSummary', () => { const { result, waitForNextUpdate } = renderHook(() => useLoadAlertSummary({ - featureIds, + ruleTypeIds, timeRange: mockedAlertSummaryTimeRange, }) ); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/search_filters.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/search_filters.ts index 3ae6a01633e400..669fddd976d842 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/search_filters.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/search_filters.ts @@ -11,72 +11,75 @@ import { AlertConsumers, DefaultAlertFieldName, } from '@kbn/rule-data-utils'; -import { FILTERS, FilterStateStore, PhraseFilter, PhrasesFilter } from '@kbn/es-query'; +import { FILTERS, FilterStateStore, PhrasesFilter } from '@kbn/es-query'; const $state = { store: FilterStateStore.APP_STATE, }; export type AlertsFeatureIdsFilter = PhrasesFilter & { - meta: Pick & { alertsFeatureIds: AlertConsumers[] }; + meta: PhrasesFilter['meta'] & { ruleTypeIds: string[] }; }; /** * Creates a match_phrase filter without an index pattern */ -export const createMatchPhraseFilter = (field: DefaultAlertFieldName, value: unknown) => - ({ - meta: { - field, - type: FILTERS.PHRASE, - key: field, - alias: null, - disabled: false, - index: undefined, - negate: false, - params: { query: value }, - value: undefined, - }, - $state, - query: { - match_phrase: { - [field]: value, - }, +export const createMatchPhraseFilter = ( + field: DefaultAlertFieldName, + value: string +): AlertsFeatureIdsFilter => ({ + meta: { + field, + type: FILTERS.PHRASE, + key: field, + alias: null, + disabled: false, + index: undefined, + negate: false, + params: { query: value }, + value: undefined, + ruleTypeIds: [], + }, + $state, + query: { + match_phrase: { + [field]: value, }, - } as PhraseFilter); + }, +}); /** * Creates a match_phrases filter without an index pattern */ export const createMatchPhrasesFilter = ( field: DefaultAlertFieldName, - values: unknown[], + values: string[], alias: string | null = null -) => - ({ - meta: { - field, - type: FILTERS.PHRASES, - key: field, - alias, - disabled: false, - index: undefined, - negate: false, - params: values, - value: undefined, - }, - $state, - query: { - bool: { - minimum_should_match: 1, - should: values.map((v) => ({ - match_phrase: { - [field]: v, - }, - })), - }, +): AlertsFeatureIdsFilter => ({ + meta: { + field, + type: FILTERS.PHRASES, + key: field, + alias, + disabled: false, + index: undefined, + negate: false, + params: values, + value: undefined, + ruleTypeIds: [], + }, + $state, + query: { + bool: { + minimum_should_match: 1, + should: values.map((v) => ({ + match_phrase: { + [field]: v, + }, + })), }, - } as PhrasesFilter); + }, +}); /** * Creates a match_phrase filter targeted to filtering alerts by producer @@ -87,16 +90,8 @@ export const createRuleProducerFilter = (producer: AlertConsumers) => /** * Creates a match_phrase filter targeted to filtering alerts by rule type ids */ -export const createRuleTypesFilter = ( - featureIds: AlertConsumers[], - alias: string, - ruleTypeIds: string[] -) => { - const filter = createMatchPhrasesFilter( - ALERT_RULE_TYPE_ID, - ruleTypeIds, - alias - ) as AlertsFeatureIdsFilter; - filter.meta.alertsFeatureIds = featureIds; +export const createRuleTypesFilter = (ruleTypeIds: string[], alias: string) => { + const filter = createMatchPhrasesFilter(ALERT_RULE_TYPE_ID, ruleTypeIds, alias); + filter.meta.ruleTypeIds = ruleTypeIds; return filter; }; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_alerts_filter_query.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_alerts_filter_query.tsx index bbaf737101910e..e844744c20af42 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_alerts_filter_query.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_alerts_filter_query.tsx @@ -6,7 +6,6 @@ */ import React, { useState, useCallback, useMemo, useEffect } from 'react'; -import { ValidFeatureId } from '@kbn/rule-data-utils'; import { Filter } from '@kbn/es-query'; import { i18n } from '@kbn/i18n'; import { EuiSwitch, EuiSpacer } from '@elastic/eui'; @@ -18,7 +17,7 @@ interface ActionAlertsFilterQueryProps { state?: AlertsFilter['query']; onChange: (update?: AlertsFilter['query']) => void; appName: string; - featureIds: ValidFeatureId[]; + ruleTypeIds: string[]; ruleTypeId?: string; } @@ -26,7 +25,7 @@ export const ActionAlertsFilterQuery: React.FC = ( state, onChange, appName, - featureIds, + ruleTypeIds, ruleTypeId, }) => { const [query, setQuery] = useState(state ?? { kql: '', filters: [] }); @@ -80,7 +79,7 @@ export const ActionAlertsFilterQuery: React.FC = ( { {}, @@ -34,7 +34,7 @@ export const AlertSummaryWidget = ({ isLoading, error, } = useLoadAlertSummary({ - featureIds, + ruleTypeIds, filter, timeRange, }); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_summary_widget/types.ts b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_summary_widget/types.ts index 2393ff9c16a648..c696c8e3f8d0fa 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_summary_widget/types.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_summary_widget/types.ts @@ -8,7 +8,7 @@ import type { BrushEndListener, PartialTheme, SettingsProps, Theme } from '@elastic/charts'; import { estypes } from '@elastic/elasticsearch'; import { IUiSettingsClient } from '@kbn/core-ui-settings-browser'; -import { AlertStatus, ValidFeatureId } from '@kbn/rule-data-utils'; +import { AlertStatus } from '@kbn/rule-data-utils'; import { ChartsPluginStart } from '@kbn/charts-plugin/public'; export interface Alert { @@ -48,7 +48,7 @@ export interface DependencyProps { } export interface AlertSummaryWidgetProps { - featureIds?: ValidFeatureId[]; + ruleTypeIds?: string[]; filter?: estypes.QueryDslQueryContainer; fullSize?: boolean; onClick?: (status?: AlertStatus) => void; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_page/components/stack_alerts_page.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_page/components/stack_alerts_page.tsx index 6d4657fee7eed3..0e9fa7d27fadc1 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_page/components/stack_alerts_page.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_page/components/stack_alerts_page.tsx @@ -77,7 +77,7 @@ const PageContent = () => { alertsTableConfigurationRegistry, } = useKibana().services; const [esQuery, setEsQuery] = useState({ bool: {} } as { bool: BoolQuery }); - const [activeFeatureFilters, setActiveFeatureFilters] = useState([]); + const [activeRuleTypeFilters, setActiveRuleTypeFilters] = useState([]); const ruleStats = useRuleStats(); const { @@ -87,22 +87,25 @@ const PageContent = () => { const ruleTypeIdsByFeatureId = useRuleTypeIdsByFeatureId(ruleTypesIndex); const browsingSiem = useMemo( - () => activeFeatureFilters.length === 1 && activeFeatureFilters[0] === AlertConsumers.SIEM, - [activeFeatureFilters] + () => activeRuleTypeFilters.length === 1 && activeRuleTypeFilters[0] === AlertConsumers.SIEM, + [activeRuleTypeFilters] ); + const filteringBySolution = useMemo( - () => activeFeatureFilters.length > 0, - [activeFeatureFilters.length] + () => activeRuleTypeFilters.length > 0, + [activeRuleTypeFilters.length] ); + const featureIds = useMemo( () => filteringBySolution ? browsingSiem ? [AlertConsumers.SIEM] - : activeFeatureFilters + : activeRuleTypeFilters : NON_SIEM_FEATURE_IDS, - [activeFeatureFilters, browsingSiem, filteringBySolution] + [activeRuleTypeFilters, browsingSiem, filteringBySolution] ); + const quickFilters = useMemo(() => { const filters: QuickFiltersMenuItem[] = []; if (Object.values(ruleTypeIdsByFeatureId).length > 0) { @@ -184,22 +187,22 @@ const PageContent = () => { }> ().services; const [queryLanguage, setQueryLanguage] = useState('kuery'); - const { dataViews, loading } = useAlertDataViews(featureIds ?? []); + const { dataViews, loading } = useAlertDataViews(ruleTypeIds ?? []); const { aadFields, loading: fieldsLoading } = useRuleAADFields(ruleTypeId); const indexPatterns = @@ -64,7 +64,7 @@ export function AlertsSearchBar({ }); const isSecurity = - (featureIds && featureIds.length === 1 && featureIds.includes(AlertConsumers.SIEM)) || + (ruleTypeIds && ruleTypeIds.length === 1 && ruleTypeIds[0].startsWith('siem.')) || (ruleType && ruleTypeId && ruleType.ruleTypesState.data.get(ruleTypeId)?.producer === AlertConsumers.SIEM); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_search_bar/types.ts b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_search_bar/types.ts index b1af2746d6cac9..b16d2df899cb33 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_search_bar/types.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_search_bar/types.ts @@ -6,7 +6,6 @@ */ import { Filter } from '@kbn/es-query'; -import { ValidFeatureId } from '@kbn/rule-data-utils'; import { SearchBarProps } from '@kbn/unified-search-plugin/public/search_bar/search_bar'; import { QuickFiltersMenuItem } from './quick_filters'; @@ -16,7 +15,7 @@ export interface AlertsSearchBarProps extends Omit, 'query' | 'onQueryChange' | 'onQuerySubmit'> { appName: string; disableQueryLanguageSwitcher?: boolean; - featureIds: ValidFeatureId[]; + ruleTypeIds: string[]; rangeFrom?: string; rangeTo?: string; query?: string; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_search_bar/url_synced_alerts_search_bar.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_search_bar/url_synced_alerts_search_bar.tsx index 71594e3206ffd5..1d5c59af201ef7 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_search_bar/url_synced_alerts_search_bar.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_search_bar/url_synced_alerts_search_bar.tsx @@ -7,7 +7,6 @@ import React, { useCallback, useEffect, useState } from 'react'; import { BoolQuery } from '@kbn/es-query'; -import { AlertConsumers } from '@kbn/rule-data-utils'; import { i18n } from '@kbn/i18n'; import { AlertFilterControls } from '@kbn/alerts-ui-shared/src/alert_filter_controls'; import { ControlGroupRenderer } from '@kbn/controls-plugin/public'; @@ -35,7 +34,7 @@ export interface UrlSyncedAlertsSearchBarProps > { showFilterControls?: boolean; onEsQueryChange: (esQuery: { bool: BoolQuery }) => void; - onActiveFeatureFiltersChange?: (value: AlertConsumers[]) => void; + onActiveRuleTypeFiltersChange?: (value: string[]) => void; } /** @@ -44,7 +43,7 @@ export interface UrlSyncedAlertsSearchBarProps export const UrlSyncedAlertsSearchBar = ({ showFilterControls = false, onEsQueryChange, - onActiveFeatureFiltersChange, + onActiveRuleTypeFiltersChange, ...rest }: UrlSyncedAlertsSearchBarProps) => { const { @@ -85,11 +84,9 @@ export const UrlSyncedAlertsSearchBar = ({ useEffect(() => { try { - onActiveFeatureFiltersChange?.([ + onActiveRuleTypeFiltersChange?.([ ...new Set( - filters - .flatMap((f) => (f as AlertsFeatureIdsFilter).meta.alertsFeatureIds) - .filter(nonNullable) + filters.flatMap((f) => (f as AlertsFeatureIdsFilter).meta.ruleTypeIds).filter(nonNullable) ), ]); onEsQueryChange( @@ -112,7 +109,7 @@ export const UrlSyncedAlertsSearchBar = ({ controlFilters, filters, kuery, - onActiveFeatureFiltersChange, + onActiveRuleTypeFiltersChange, onEsQueryChange, onKueryChange, rangeFrom, diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/alerts_table.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/alerts_table.tsx index 76bc9b1ff7f4ab..19f8bdc4e76bc3 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/alerts_table.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/alerts_table.tsx @@ -309,7 +309,7 @@ const AlertsTable: React.FunctionComponent = memo((props: Aler dynamicRowHeight, query, querySnapshot, - featureIds, + ruleTypeIds, cases: { data: cases, isLoading: isLoadingCases }, maintenanceWindows: { data: maintenanceWindows, isLoading: isLoadingMaintenanceWindows }, controls, @@ -344,7 +344,7 @@ const AlertsTable: React.FunctionComponent = memo((props: Aler query, useBulkActionsConfig: alertsTableConfiguration.useBulkActions, refresh: refetchAlerts, - featureIds, + ruleTypeIds, hideBulkActions: Boolean(alertsTableConfiguration.hideBulkActions), }; }, [ @@ -354,7 +354,7 @@ const AlertsTable: React.FunctionComponent = memo((props: Aler alertsTableConfiguration.hideBulkActions, query, refetchAlerts, - featureIds, + ruleTypeIds, ]); const { diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/alerts_table_state.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/alerts_table_state.test.tsx index 0028af392455dd..ce619108f002a5 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/alerts_table_state.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/alerts_table_state.test.tsx @@ -9,12 +9,7 @@ import { BehaviorSubject } from 'rxjs'; import userEvent from '@testing-library/user-event'; import { get } from 'lodash'; import { fireEvent, render, waitFor, screen, act } from '@testing-library/react'; -import { - AlertConsumers, - ALERT_CASE_IDS, - ALERT_MAINTENANCE_WINDOW_IDS, - ALERT_UUID, -} from '@kbn/rule-data-utils'; +import { ALERT_CASE_IDS, ALERT_MAINTENANCE_WINDOW_IDS, ALERT_UUID } from '@kbn/rule-data-utils'; import { Storage } from '@kbn/kibana-utils-plugin/public'; import { @@ -340,7 +335,7 @@ describe('AlertsTableState', () => { alertsTableConfigurationRegistry: alertsTableConfigurationRegistryMock, configurationId: PLUGIN_ID, id: PLUGIN_ID, - featureIds: [AlertConsumers.LOGS], + ruleTypeIds: ['logs'], query: {}, columns, pagination: { diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_bulk_actions.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_bulk_actions.test.tsx index d84909e746f27f..e03dd9aaffe6f5 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_bulk_actions.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_bulk_actions.test.tsx @@ -392,7 +392,13 @@ describe('bulk action hooks', () => { it('appends only the case bulk actions for SIEM', async () => { const { result } = renderHook( () => - useBulkActions({ alertsCount: 0, query: {}, casesConfig, refresh, featureIds: ['siem'] }), + useBulkActions({ + alertsCount: 0, + query: {}, + casesConfig, + refresh, + ruleTypeIds: ['siem'], + }), { wrapper: appMockRender.AppWrapper, } @@ -476,7 +482,7 @@ describe('bulk action hooks', () => { query: {}, casesConfig, refresh, - featureIds: ['observability'], + ruleTypeIds: ['observability'], }), { wrapper: appMockRender.AppWrapper, @@ -492,7 +498,7 @@ describe('bulk action hooks', () => { query: {}, casesConfig, refresh, - featureIds: ['observability'], + ruleTypeIds: ['observability'], hideBulkActions: true, }), { diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_bulk_actions.ts b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_bulk_actions.ts index 727ff4f93ebd8c..74da460fca6662 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_bulk_actions.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_bulk_actions.ts @@ -7,7 +7,7 @@ import { useCallback, useContext, useEffect, useMemo } from 'react'; import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { useKibana } from '@kbn/kibana-react-plugin/public'; -import { ALERT_CASE_IDS, ValidFeatureId } from '@kbn/rule-data-utils'; +import { ALERT_CASE_IDS } from '@kbn/rule-data-utils'; import { AlertsTableContext } from '../contexts/alerts_table_context'; import { AlertsTableConfigurationRegistry, @@ -40,7 +40,7 @@ interface BulkActionsProps { casesConfig?: AlertsTableConfigurationRegistry['cases']; useBulkActionsConfig?: UseBulkActionsRegistry; refresh: () => void; - featureIds?: ValidFeatureId[]; + ruleTypeIds?: string[]; hideBulkActions?: boolean; } @@ -57,7 +57,7 @@ export interface UseBulkActions { type UseBulkAddToCaseActionsProps = Pick & Pick; -type UseBulkUntrackActionsProps = Pick & +type UseBulkUntrackActionsProps = Pick & Pick & { isAllSelected: boolean; }; @@ -191,7 +191,7 @@ export const useBulkUntrackActions = ({ refresh, clearSelection, query, - featureIds = [], + ruleTypeIds = [], isAllSelected, }: UseBulkUntrackActionsProps) => { const onSuccess = useCallback(() => { @@ -217,7 +217,7 @@ export const useBulkUntrackActions = ({ try { setIsBulkActionsLoading(true); if (isAllSelected) { - await untrackAlertsByQuery({ query, featureIds }); + await untrackAlertsByQuery({ query, ruleTypeIds }); } else { await untrackAlerts({ indices, alertUuids }); } @@ -228,7 +228,7 @@ export const useBulkUntrackActions = ({ }, [ query, - featureIds, + ruleTypeIds, isAllSelected, onSuccess, setIsBulkActionsLoading, @@ -277,7 +277,7 @@ export function useBulkActions({ query, refresh, useBulkActionsConfig = () => [], - featureIds, + ruleTypeIds, hideBulkActions, }: BulkActionsProps): UseBulkActions { const { @@ -300,13 +300,17 @@ export function useBulkActions({ refresh, clearSelection, query, - featureIds, + ruleTypeIds, isAllSelected: bulkActionsState.isAllSelected, }); const initialItems = useMemo(() => { - return [...caseBulkActions, ...(featureIds?.includes('siem') ? [] : untrackBulkActions)]; - }, [caseBulkActions, featureIds, untrackBulkActions]); + return [ + ...caseBulkActions, + ...(ruleTypeIds?.some((ruleTypeId) => ruleTypeId.includes('siem')) ? [] : untrackBulkActions), + ]; + }, [caseBulkActions, ruleTypeIds, untrackBulkActions]); + const bulkActions = useMemo(() => { if (hideBulkActions) { return []; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_bulk_untrack_alerts_by_query.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_bulk_untrack_alerts_by_query.tsx index 321d861e03615c..88c878aa47a664 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_bulk_untrack_alerts_by_query.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_bulk_untrack_alerts_by_query.tsx @@ -9,7 +9,6 @@ import { i18n } from '@kbn/i18n'; import { useMutation } from '@tanstack/react-query'; import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { INTERNAL_BASE_ALERTING_API_PATH } from '@kbn/alerting-plugin/common'; -import { ValidFeatureId } from '@kbn/rule-data-utils'; import { AlertsQueryContext } from '@kbn/alerts-ui-shared/src/common/contexts/alerts_query_context'; import { useKibana } from '../../../../common'; @@ -22,14 +21,14 @@ export const useBulkUntrackAlertsByQuery = () => { const untrackAlertsByQuery = useMutation< string, string, - { query: Pick; featureIds: ValidFeatureId[] } + { query: Pick; ruleTypeIds: string[] } >( ['untrackAlerts'], - ({ query, featureIds }) => { + ({ query, ruleTypeIds }) => { try { const body = JSON.stringify({ query: Array.isArray(query) ? query : [query], - feature_ids: featureIds, + rule_type_ids: ruleTypeIds, }); return http.post(`${INTERNAL_BASE_ALERTING_API_PATH}/alerts/_bulk_untrack_by_query`, { body, diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_columns/use_columns.test.ts b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_columns/use_columns.test.ts index 237fad28e30272..7934d8fe8ad2c3 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_columns/use_columns.test.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_columns/use_columns.test.ts @@ -6,7 +6,6 @@ */ import { EuiDataGridColumn } from '@elastic/eui'; -import { AlertConsumers } from '@kbn/rule-data-utils'; import { Storage } from '@kbn/kibana-utils-plugin/public'; import { act, renderHook } from '@testing-library/react-hooks'; @@ -35,7 +34,7 @@ const mockStorage = { describe('useColumn', () => { const id = 'useColumnTest'; - const featureIds: AlertConsumers[] = [AlertConsumers.LOGS, AlertConsumers.APM]; + const ruleTypeIds: string[] = ['apm', 'logs']; let storage = { current: new Storage(mockStorage) }; const getStorageAlertsTableByDefaultColumns = (defaultColumns: EuiDataGridColumn[]) => { @@ -116,7 +115,7 @@ describe('useColumn', () => { const { result } = renderHook(() => useColumns({ defaultColumns, - featureIds, + ruleTypeIds, id, storageAlertsTable: localStorageAlertsTable, storage, @@ -145,7 +144,7 @@ describe('useColumn', () => { const { result } = renderHook(() => useColumns({ defaultColumns, - featureIds, + ruleTypeIds, id, storageAlertsTable: localStorageAlertsTable, storage, @@ -165,7 +164,7 @@ describe('useColumn', () => { const { result } = renderHook(() => useColumns({ defaultColumns, - featureIds, + ruleTypeIds, id, storageAlertsTable: localStorageAlertsTable, storage, @@ -192,7 +191,7 @@ describe('useColumn', () => { const { result } = renderHook(() => useColumns({ defaultColumns, - featureIds, + ruleTypeIds, id, storageAlertsTable: localStorageAlertsTable, storage, @@ -208,7 +207,7 @@ describe('useColumn', () => { const { result, rerender } = renderHook(() => useColumns({ defaultColumns: localDefaultColumns, - featureIds, + ruleTypeIds, id, storageAlertsTable: localStorageAlertsTable, storage, @@ -243,7 +242,7 @@ describe('useColumn', () => { const { result, waitFor } = renderHook(() => useColumns({ defaultColumns, - featureIds, + ruleTypeIds, id, storageAlertsTable: localStorageAlertsTable, storage, @@ -260,7 +259,7 @@ describe('useColumn', () => { const { result } = renderHook(() => useColumns({ defaultColumns, - featureIds, + ruleTypeIds, id, storageAlertsTable: localStorageAlertsTable, storage, @@ -279,7 +278,7 @@ describe('useColumn', () => { const { result } = renderHook(() => useColumns({ defaultColumns, - featureIds, + ruleTypeIds, id, storageAlertsTable: localStorageAlertsTable, storage, @@ -306,7 +305,7 @@ describe('useColumn', () => { const { result } = renderHook(() => useColumns({ defaultColumns, - featureIds, + ruleTypeIds, id, storageAlertsTable: localStorageAlertsTable, storage, @@ -337,7 +336,7 @@ describe('useColumn', () => { const { result } = renderHook(() => useColumns({ defaultColumns, - featureIds, + ruleTypeIds, id, storageAlertsTable: localStorageAlertsTable, storage, diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule.tsx index c6598becec313f..108f1bce4d5ddb 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule.tsx @@ -8,8 +8,8 @@ import React, { lazy, useCallback } from 'react'; import { i18n } from '@kbn/i18n'; import { EuiSpacer, EuiFlexGroup, EuiFlexItem, EuiTabbedContent } from '@elastic/eui'; -import { AlertStatusValues, ALERTING_FEATURE_ID } from '@kbn/alerting-plugin/common'; -import { ALERT_RULE_UUID, AlertConsumers } from '@kbn/rule-data-utils'; +import { AlertStatusValues } from '@kbn/alerting-plugin/common'; +import { ALERT_RULE_UUID } from '@kbn/rule-data-utils'; import { ALERT_TABLE_GENERIC_CONFIG_ID } from '../../../constants'; import { AlertTableConfigRegistry } from '../../../alert_table_config_registry'; import { useKibana } from '../../../../common/lib/kibana'; @@ -103,11 +103,7 @@ export function RuleComponent({ alertsTableConfigurationRegistry={ alertsTableConfigurationRegistry as AlertTableConfigRegistry } - featureIds={ - (rule.consumer === ALERTING_FEATURE_ID - ? [ruleType.producer] - : [rule.consumer]) as AlertConsumers[] - } + ruleTypeIds={[ruleType.id]} query={{ bool: { filter: { term: { [ALERT_RULE_UUID]: rule.id } } } }} showAlertStatusWithFlapping /> @@ -126,11 +122,10 @@ export function RuleComponent({ alertsTableConfigurationRegistry, onMuteAction, readOnly, - rule.consumer, rule.id, ruleType.hasAlertsMappings, ruleType.hasFieldsForAAD, - ruleType.producer, + ruleType.id, ]); const tabs = [ diff --git a/x-pack/plugins/triggers_actions_ui/public/types.ts b/x-pack/plugins/triggers_actions_ui/public/types.ts index 415541b26b3785..2acc21b5ac617f 100644 --- a/x-pack/plugins/triggers_actions_ui/public/types.ts +++ b/x-pack/plugins/triggers_actions_ui/public/types.ts @@ -26,7 +26,7 @@ import type { RenderCellValue, EuiDataGridCellPopoverElementProps, } from '@elastic/eui'; -import type { RuleCreationValidConsumer, ValidFeatureId } from '@kbn/rule-data-utils'; +import type { RuleCreationValidConsumer } from '@kbn/rule-data-utils'; import { EuiDataGridColumn, EuiDataGridControlColumn, EuiDataGridSorting } from '@elastic/eui'; import { HttpSetup } from '@kbn/core/public'; import { KueryNode } from '@kbn/es-query'; @@ -489,7 +489,7 @@ export type AlertsTableProps = { * Enable when rows may have variable heights (disables virtualization) */ dynamicRowHeight?: boolean; - featureIds?: ValidFeatureId[]; + ruleTypeIds?: string[]; pageIndex: number; pageSize: number; sort: SortCombinations[]; From 42c734ac9d5a418ea36cf009a04c242a66ac6acf Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Tue, 30 Jul 2024 10:24:51 +0300 Subject: [PATCH 039/106] Move rule types to a package --- .../src/rule_types/o11y_rules.ts | 70 +++++++++++++++++-- .../alerting/logs/log_threshold/types.ts | 2 - .../infra/common/alerting/metrics/types.ts | 7 -- .../observability/common/constants.ts | 19 +---- .../common/constants/synthetics_alerts.ts | 10 --- .../lib/alert_types/monitor_status.tsx | 3 +- .../uptime/common/constants/uptime_alerts.ts | 13 ---- .../action_type_form.tsx | 2 +- 8 files changed, 69 insertions(+), 57 deletions(-) delete mode 100644 x-pack/plugins/observability_solution/uptime/common/constants/uptime_alerts.ts diff --git a/packages/kbn-rule-data-utils/src/rule_types/o11y_rules.ts b/packages/kbn-rule-data-utils/src/rule_types/o11y_rules.ts index 1376379c8e3464..9637562c43a702 100644 --- a/packages/kbn-rule-data-utils/src/rule_types/o11y_rules.ts +++ b/packages/kbn-rule-data-utils/src/rule_types/o11y_rules.ts @@ -7,11 +7,10 @@ */ export const OBSERVABILITY_THRESHOLD_RULE_TYPE_ID = 'observability.rules.custom_threshold'; -export const SLO_BURN_RATE_RULE_TYPE_ID = 'slo.rules.burnRate'; -export const METRIC_INVENTORY_THRESHOLD_ALERT_TYPE_ID = 'metrics.alert.inventory.threshold'; -export const METRIC_THRESHOLD_ALERT_TYPE_ID = 'metrics.alert.threshold'; -export const LOG_THRESHOLD_ALERT_TYPE_ID = 'logs.alert.document.count'; +/** + * APM rule types + */ export enum ApmRuleType { ErrorCount = 'apm.error_rate', // ErrorRate was renamed to ErrorCount but the key is kept as `error_rate` for backwards-compat. @@ -21,3 +20,66 @@ export enum ApmRuleType { } export const APM_RULE_TYPE_IDS = Object.values(ApmRuleType); + +/** + * Synthetics ryle types + */ + +export const SYNTHETICS_STATUS_RULE = 'xpack.synthetics.alerts.monitorStatus'; +export const SYNTHETICS_TLS_RULE = 'xpack.synthetics.alerts.tls'; + +export const SYNTHETICS_ALERT_RULE_TYPES = { + MONITOR_STATUS: SYNTHETICS_STATUS_RULE, + TLS: SYNTHETICS_TLS_RULE, +}; + +export const SYNTHETICS_RULE_TYPE_IDS = [SYNTHETICS_STATUS_RULE, SYNTHETICS_TLS_RULE]; + +/** + * SLO rule types + */ +export const SLO_BURN_RATE_RULE_TYPE_ID = 'slo.rules.burnRate'; +export const SLO_RULE_TYPE_IDS = [SLO_BURN_RATE_RULE_TYPE_ID]; + +/** + * Metrics rule types + */ +export const METRIC_INVENTORY_THRESHOLD_ALERT_TYPE_ID = 'metrics.alert.inventory.threshold'; +export const METRIC_THRESHOLD_ALERT_TYPE_ID = 'metrics.alert.threshold'; + +/** + * Logs rule types + */ +export const LOG_THRESHOLD_ALERT_TYPE_ID = 'logs.alert.document.count'; +export const LOG_RULE_TYPE_IDS = [LOG_THRESHOLD_ALERT_TYPE_ID]; + +/** + * Uptime rule types + */ + +export const UPTIME_RULE_TYPE_IDS = [ + 'xpack.uptime.alerts.tls', + 'xpack.uptime.alerts.tlsCertificate', + 'xpack.uptime.alerts.monitorStatus', + 'xpack.uptime.alerts.durationAnomaly', +]; + +/** + * Infra rule types + */ + +export enum InfraRuleType { + MetricThreshold = 'metrics.alert.threshold', + InventoryThreshold = 'metrics.alert.inventory.threshold', +} + +export const INFRA_RULE_TYPE_IDS = Object.values(InfraRuleType); + +export const OBSERVABILITY_RULE_TYPE_IDS = [ + ...APM_RULE_TYPE_IDS, + ...SYNTHETICS_RULE_TYPE_IDS, + ...INFRA_RULE_TYPE_IDS, + ...UPTIME_RULE_TYPE_IDS, + ...LOG_RULE_TYPE_IDS, + ...SLO_RULE_TYPE_IDS, +]; diff --git a/x-pack/plugins/observability_solution/infra/common/alerting/logs/log_threshold/types.ts b/x-pack/plugins/observability_solution/infra/common/alerting/logs/log_threshold/types.ts index 4f5b977dd3b827..1fcd1b2316e522 100644 --- a/x-pack/plugins/observability_solution/infra/common/alerting/logs/log_threshold/types.ts +++ b/x-pack/plugins/observability_solution/infra/common/alerting/logs/log_threshold/types.ts @@ -10,8 +10,6 @@ import * as rt from 'io-ts'; import { persistedLogViewReferenceRT } from '@kbn/logs-shared-plugin/common'; import { commonSearchSuccessResponseFieldsRT } from '../../../utils/elasticsearch_runtime_types'; -export const LOG_DOCUMENT_COUNT_RULE_TYPE_ID = 'logs.alert.document.count'; - const ThresholdTypeRT = rt.keyof({ count: null, ratio: null, diff --git a/x-pack/plugins/observability_solution/infra/common/alerting/metrics/types.ts b/x-pack/plugins/observability_solution/infra/common/alerting/metrics/types.ts index 2a304ea1c40f5f..bd5d6f25ac72dd 100644 --- a/x-pack/plugins/observability_solution/infra/common/alerting/metrics/types.ts +++ b/x-pack/plugins/observability_solution/infra/common/alerting/metrics/types.ts @@ -13,13 +13,6 @@ import { SnapshotCustomMetricInput } from '../../http_api'; export const METRIC_THRESHOLD_ALERT_TYPE_ID = 'metrics.alert.threshold'; export const METRIC_INVENTORY_THRESHOLD_ALERT_TYPE_ID = 'metrics.alert.inventory.threshold'; -export enum InfraRuleType { - MetricThreshold = 'metrics.alert.threshold', - InventoryThreshold = 'metrics.alert.inventory.threshold', -} - -export const INFRA_RULE_TYPE_IDS = Object.values(InfraRuleType); - export enum Aggregators { COUNT = 'count', AVERAGE = 'avg', diff --git a/x-pack/plugins/observability_solution/observability/common/constants.ts b/x-pack/plugins/observability_solution/observability/common/constants.ts index 193dc0a8c70766..a45e421f6a8e4f 100644 --- a/x-pack/plugins/observability_solution/observability/common/constants.ts +++ b/x-pack/plugins/observability_solution/observability/common/constants.ts @@ -5,17 +5,9 @@ * 2.0. */ -import { - AlertConsumers, - APM_RULE_TYPE_IDS, - SLO_BURN_RATE_RULE_TYPE_ID, -} from '@kbn/rule-data-utils'; +import { AlertConsumers } from '@kbn/rule-data-utils'; import type { ValidFeatureId } from '@kbn/rule-data-utils'; import type { RuleCreationValidConsumer } from '@kbn/triggers-actions-ui-plugin/public'; -import { SYNTHETICS_RULE_TYPES } from '@kbn/synthetics-plugin/common/constants/synthetics_alerts'; -import { UPTIME_RULE_TYPES } from '@kbn/uptime-plugin/common/constants/uptime_alerts'; -import { INFRA_RULE_TYPE_IDS } from '@kbn/infra-plugin/common/alerting/metrics/types'; -import { LOG_DOCUMENT_COUNT_RULE_TYPE_ID } from '@kbn/infra-plugin/common/alerting/logs/log_threshold/types'; export const INVALID_EQUATION_REGEX = /[^A-Z|+|\-|\s|\d+|\.|\(|\)|\/|\*|>|<|=|\?|\:|&|\!|\|]+/g; export const ALERT_STATUS_ALL = 'all'; @@ -38,12 +30,3 @@ export const observabilityRuleCreationValidConsumers: RuleCreationValidConsumer[ ]; export const EventsAsUnit = 'events'; - -export const OBSERVABILITY_RULE_TYPE_IDS = [ - ...APM_RULE_TYPE_IDS, - ...SYNTHETICS_RULE_TYPES, - ...INFRA_RULE_TYPE_IDS, - ...UPTIME_RULE_TYPES, - LOG_DOCUMENT_COUNT_RULE_TYPE_ID, - SLO_BURN_RATE_RULE_TYPE_ID, -]; diff --git a/x-pack/plugins/observability_solution/synthetics/common/constants/synthetics_alerts.ts b/x-pack/plugins/observability_solution/synthetics/common/constants/synthetics_alerts.ts index 620c5c88033a75..cb9fa42479d5e4 100644 --- a/x-pack/plugins/observability_solution/synthetics/common/constants/synthetics_alerts.ts +++ b/x-pack/plugins/observability_solution/synthetics/common/constants/synthetics_alerts.ts @@ -34,14 +34,4 @@ export const ACTION_GROUP_DEFINITIONS: { TLS_CERTIFICATE, }; -export const SYNTHETICS_STATUS_RULE = 'xpack.synthetics.alerts.monitorStatus'; -export const SYNTHETICS_TLS_RULE = 'xpack.synthetics.alerts.tls'; - -export const SYNTHETICS_ALERT_RULE_TYPES = { - MONITOR_STATUS: SYNTHETICS_STATUS_RULE, - TLS: SYNTHETICS_TLS_RULE, -}; - -export const SYNTHETICS_RULE_TYPES = [SYNTHETICS_STATUS_RULE, SYNTHETICS_TLS_RULE]; - export const SYNTHETICS_RULE_TYPES_ALERT_CONTEXT = 'observability.uptime'; diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/lib/alert_types/monitor_status.tsx b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/lib/alert_types/monitor_status.tsx index ba864078594087..e7f4d4f1323899 100644 --- a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/lib/alert_types/monitor_status.tsx +++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/lib/alert_types/monitor_status.tsx @@ -7,7 +7,7 @@ import React from 'react'; -import { ALERT_REASON } from '@kbn/rule-data-utils'; +import { ALERT_REASON, SYNTHETICS_ALERT_RULE_TYPES } from '@kbn/rule-data-utils'; import type { ObservabilityRuleTypeModel } from '@kbn/observability-plugin/public'; import type { RuleTypeParamsExpressionProps } from '@kbn/triggers-actions-ui-plugin/public'; @@ -15,7 +15,6 @@ import { getSyntheticsErrorRouteFromMonitorId } from '../../../../../common/util import { STATE_ID } from '../../../../../common/field_names'; import { SyntheticsMonitorStatusTranslations } from '../../../../../common/rules/synthetics/translations'; import type { StatusRuleParams } from '../../../../../common/rules/status_rule'; -import { SYNTHETICS_ALERT_RULE_TYPES } from '../../../../../common/constants/synthetics_alerts'; import type { AlertTypeInitializer } from '.'; const { defaultActionMessage, defaultRecoveryMessage, description } = SyntheticsMonitorStatusTranslations; diff --git a/x-pack/plugins/observability_solution/uptime/common/constants/uptime_alerts.ts b/x-pack/plugins/observability_solution/uptime/common/constants/uptime_alerts.ts deleted file mode 100644 index 11c93d646eb16a..00000000000000 --- a/x-pack/plugins/observability_solution/uptime/common/constants/uptime_alerts.ts +++ /dev/null @@ -1,13 +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. - */ - -export const UPTIME_RULE_TYPES = [ - 'xpack.uptime.alerts.tls', - 'xpack.uptime.alerts.tlsCertificate', - 'xpack.uptime.alerts.monitorStatus', - 'xpack.uptime.alerts.durationAnomaly', -]; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_type_form.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_type_form.tsx index d59ef1e6d2d0df..b067799c041682 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_type_form.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_type_form.tsx @@ -518,7 +518,7 @@ export const ActionTypeForm = ({ setActionAlertsFilterProperty('query', query, index)} - ruleTypeIds={[ruleTypeId]} + ruleTypeIds={ruleTypeId ? [ruleTypeId] : []} appName={featureId!} ruleTypeId={ruleTypeId} /> From e19424df45c64a09da945ff31ade6982d17ad894 Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Wed, 31 Jul 2024 13:00:13 +0300 Subject: [PATCH 040/106] Fix types after merge --- .../src/common/apis/fetch_alerts_fields/types.ts | 5 ++--- .../hooks/use_fetch_alerts_fields_query.ts | 16 ++++++---------- .../src/alerts_as_data_rbac.ts | 2 ++ 3 files changed, 10 insertions(+), 13 deletions(-) diff --git a/packages/kbn-alerts-ui-shared/src/common/apis/fetch_alerts_fields/types.ts b/packages/kbn-alerts-ui-shared/src/common/apis/fetch_alerts_fields/types.ts index d60663236ac766..85c5922a590f09 100644 --- a/packages/kbn-alerts-ui-shared/src/common/apis/fetch_alerts_fields/types.ts +++ b/packages/kbn-alerts-ui-shared/src/common/apis/fetch_alerts_fields/types.ts @@ -7,7 +7,6 @@ */ import { HttpSetup } from '@kbn/core-http-browser'; -import { ValidFeatureId } from '@kbn/rule-data-utils'; export interface FetchAlertsFieldsParams { // Dependencies @@ -15,7 +14,7 @@ export interface FetchAlertsFieldsParams { // Params /** - * Array of feature ids used for authorization and area-based filtering + * Array of rule type ids used for authorization and area-based filtering */ - featureIds: ValidFeatureId[]; + ruleTypeIds: string[]; } diff --git a/packages/kbn-alerts-ui-shared/src/common/hooks/use_fetch_alerts_fields_query.ts b/packages/kbn-alerts-ui-shared/src/common/hooks/use_fetch_alerts_fields_query.ts index 5d0f785335b228..07b5cf24e991f2 100644 --- a/packages/kbn-alerts-ui-shared/src/common/hooks/use_fetch_alerts_fields_query.ts +++ b/packages/kbn-alerts-ui-shared/src/common/hooks/use_fetch_alerts_fields_query.ts @@ -6,15 +6,13 @@ * Side Public License, v 1. */ -import { AlertConsumers, isValidFeatureId } from '@kbn/rule-data-utils'; +import { isSiemRuleType } from '@kbn/rule-data-utils'; import { useQuery } from '@tanstack/react-query'; import type { QueryOptionsOverrides } from '../types/tanstack_query_utility_types'; import { fetchAlertsFields, FetchAlertsFieldsParams } from '../apis/fetch_alerts_fields'; export type UseFetchAlertsFieldsQueryParams = FetchAlertsFieldsParams; -const UNSUPPORTED_FEATURE_ID = AlertConsumers.SIEM; - export const queryKeyPrefix = ['alerts', fetchAlertsFields.name]; /** @@ -30,16 +28,14 @@ export const useFetchAlertsFieldsQuery = ( 'context' | 'onError' | 'refetchOnWindowFocus' | 'staleTime' | 'enabled' > ) => { - const { featureIds } = params; + const { ruleTypeIds } = params; - const validFeatureIds = featureIds.filter( - (fid) => isValidFeatureId(fid) && fid !== UNSUPPORTED_FEATURE_ID - ); + const validRuleTypeIds = ruleTypeIds.filter(isSiemRuleType); return useQuery({ - queryKey: queryKeyPrefix.concat(JSON.stringify(featureIds)), - queryFn: () => fetchAlertsFields({ http, featureIds: validFeatureIds }), - enabled: validFeatureIds.length > 0, + queryKey: queryKeyPrefix.concat(JSON.stringify(ruleTypeIds)), + queryFn: () => fetchAlertsFields({ http, ruleTypeIds: validRuleTypeIds }), + enabled: validRuleTypeIds.length > 0, initialData: { browserFields: {}, fields: [] }, ...options, }); diff --git a/packages/kbn-rule-data-utils/src/alerts_as_data_rbac.ts b/packages/kbn-rule-data-utils/src/alerts_as_data_rbac.ts index e6aedcba096f3d..79a90b331b5fcb 100644 --- a/packages/kbn-rule-data-utils/src/alerts_as_data_rbac.ts +++ b/packages/kbn-rule-data-utils/src/alerts_as_data_rbac.ts @@ -91,3 +91,5 @@ export const getEsQueryConfig = (params?: GetEsQueryConfigParamType): EsQueryCon }, {} as EsQueryConfig); return paramKeysWithValues; }; + +export const isSiemRuleType = (ruleTypeId: string) => ruleTypeId.startsWith('siem.'); From cc944b05f5d40ab0f48c008a0393f12a9b3b9fdc Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Wed, 31 Jul 2024 13:16:25 +0300 Subject: [PATCH 041/106] Use the new isSiemRuleType util --- .../kbn-alerts-ui-shared/src/alerts_search_bar/index.tsx | 4 ++-- .../src/common/hooks/use_alert_data_view.ts | 3 ++- packages/kbn-rule-data-utils/src/alerts_as_data_rbac.ts | 3 +++ .../server/alert_data_client/alerts_client.ts | 3 ++- .../server/routes/get_browser_fields_by_feature_id.ts | 5 ++--- .../server/search_strategy/search_strategy.ts | 9 +++------ .../public/application/hooks/use_alert_data_view.ts | 3 ++- .../sections/alerts_search_bar/alerts_search_bar.tsx | 4 ++-- 8 files changed, 18 insertions(+), 16 deletions(-) diff --git a/packages/kbn-alerts-ui-shared/src/alerts_search_bar/index.tsx b/packages/kbn-alerts-ui-shared/src/alerts_search_bar/index.tsx index 4915799ac7aa14..b06a76a55f4013 100644 --- a/packages/kbn-alerts-ui-shared/src/alerts_search_bar/index.tsx +++ b/packages/kbn-alerts-ui-shared/src/alerts_search_bar/index.tsx @@ -9,7 +9,7 @@ import { useCallback, useState } from 'react'; import type { Query, TimeRange } from '@kbn/es-query'; import type { SuggestionsAbstraction } from '@kbn/unified-search-plugin/public/typeahead/suggestions_component'; -import { AlertConsumers } from '@kbn/rule-data-utils'; +import { AlertConsumers, isSiemRuleType } from '@kbn/rule-data-utils'; import { NO_INDEX_PATTERNS } from './constants'; import { SEARCH_BAR_PLACEHOLDER } from './translations'; import type { AlertsSearchBarProps, QueryLanguageType } from './types'; @@ -63,7 +63,7 @@ export const AlertsSearchBar = ({ }); const isSecurity = - (ruleTypeIds && ruleTypeIds.length === 1 && ruleTypeIds[0].startsWith('siem.')) || + (ruleTypeIds && ruleTypeIds.length === 1 && isSiemRuleType(ruleTypeIds[0])) || (ruleType && ruleTypeId && ruleType.ruleTypesState.data.get(ruleTypeId)?.producer === AlertConsumers.SIEM); diff --git a/packages/kbn-alerts-ui-shared/src/common/hooks/use_alert_data_view.ts b/packages/kbn-alerts-ui-shared/src/common/hooks/use_alert_data_view.ts index f0220ca42769ff..2e1a17865596e6 100644 --- a/packages/kbn-alerts-ui-shared/src/common/hooks/use_alert_data_view.ts +++ b/packages/kbn-alerts-ui-shared/src/common/hooks/use_alert_data_view.ts @@ -12,6 +12,7 @@ import type { DataView, DataViewsContract } from '@kbn/data-views-plugin/common' import type { ToastsStart, HttpStart } from '@kbn/core/public'; import { useQuery } from '@tanstack/react-query'; +import { isSiemRuleType } from '@kbn/rule-data-utils'; import { useFetchAlertsFieldsQuery } from './use_fetch_alerts_fields_query'; import { fetchAlertIndexNames } from '../apis/fetch_alert_index_names'; @@ -32,7 +33,7 @@ export function useAlertDataView(props: UseAlertDataViewProps): UseAlertDataView const [dataViews, setDataViews] = useState([]); const ruleTypes = ruleTypeIds.sort().join(','); - const hasSecurity = ruleTypeIds.some((ruleTypeId) => ruleTypeId.startsWith('siem.')); + const hasSecurity = ruleTypeIds.some(isSiemRuleType); const isOnlySecurity = ruleTypeIds.length === 1 && hasSecurity; const hasSecurityAndO11yFeatureIds = ruleTypeIds.length > 1 && hasSecurity; diff --git a/packages/kbn-rule-data-utils/src/alerts_as_data_rbac.ts b/packages/kbn-rule-data-utils/src/alerts_as_data_rbac.ts index 79a90b331b5fcb..8b0343cebd97a2 100644 --- a/packages/kbn-rule-data-utils/src/alerts_as_data_rbac.ts +++ b/packages/kbn-rule-data-utils/src/alerts_as_data_rbac.ts @@ -92,4 +92,7 @@ export const getEsQueryConfig = (params?: GetEsQueryConfigParamType): EsQueryCon return paramKeysWithValues; }; +/** + * TODO: Abstract it and remove it + */ export const isSiemRuleType = (ruleTypeId: string) => ruleTypeId.startsWith('siem.'); diff --git a/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts b/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts index 1b1d5cb9cd6173..4803b6952b9e1e 100644 --- a/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts +++ b/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts @@ -21,6 +21,7 @@ import { ALERT_STATUS_ACTIVE, ALERT_CASE_IDS, MAX_CASES_PER_ALERT, + isSiemRuleType, } from '@kbn/rule-data-utils'; import { @@ -1197,7 +1198,7 @@ export class AlertsClient { public async getAADFields({ ruleTypeId }: { ruleTypeId: string }) { const { fieldsForAAD = [] } = this.getRuleType(ruleTypeId); - if (ruleTypeId.startsWith('siem.')) { + if (isSiemRuleType(ruleTypeId)) { throw Boom.badRequest(`Security solution rule type is not supported`); } const indices = await this.getAuthorizedAlertsIndices([ruleTypeId]); diff --git a/x-pack/plugins/rule_registry/server/routes/get_browser_fields_by_feature_id.ts b/x-pack/plugins/rule_registry/server/routes/get_browser_fields_by_feature_id.ts index 4376faff4bc210..e6b39529d359ab 100644 --- a/x-pack/plugins/rule_registry/server/routes/get_browser_fields_by_feature_id.ts +++ b/x-pack/plugins/rule_registry/server/routes/get_browser_fields_by_feature_id.ts @@ -9,6 +9,7 @@ import { IRouter } from '@kbn/core/server'; import { transformError } from '@kbn/securitysolution-es-utils'; import * as t from 'io-ts'; +import { isSiemRuleType } from '@kbn/rule-data-utils'; import { RacRequestHandlerContext } from '../types'; import { BASE_RAC_ALERTS_API_PATH } from '../../common/constants'; import { buildRouteValidation } from './utils/route_validation'; @@ -36,9 +37,7 @@ export const getBrowserFieldsByFeatureId = (router: IRouter !ruleTypeId.startsWith('siem.') - ); + const onlyO11yRuleTypeIds = ruleTypeIds.filter((ruleTypeId) => !isSiemRuleType(ruleTypeId)); const o11yIndices = (onlyO11yRuleTypeIds diff --git a/x-pack/plugins/rule_registry/server/search_strategy/search_strategy.ts b/x-pack/plugins/rule_registry/server/search_strategy/search_strategy.ts index 65545c47e1f08b..2f49a5a0440ef1 100644 --- a/x-pack/plugins/rule_registry/server/search_strategy/search_strategy.ts +++ b/x-pack/plugins/rule_registry/server/search_strategy/search_strategy.ts @@ -19,6 +19,7 @@ import { SecurityPluginSetup } from '@kbn/security-plugin/server'; import { SpacesPluginStart } from '@kbn/spaces-plugin/server'; import { buildAlertFieldsRequest } from '@kbn/alerts-as-data-utils'; import { partition } from 'lodash'; +import { isSiemRuleType } from '@kbn/rule-data-utils'; import type { RuleRegistrySearchRequest, RuleRegistrySearchResponse } from '../../common'; import { MAX_ALERT_SEARCH_SIZE } from '../../common/constants'; import { AlertAuditAction, alertAuditEvent } from '..'; @@ -49,13 +50,9 @@ export const ruleRegistrySearchStrategyProvider = ( // SIEM uses RBAC fields in their alerts but also utilizes ES DLS which // is different than every other solution so we need to special case // those requests. - const isAnyRuleTypeESAuthorized = request.ruleTypeIds.some((ruleTypeId) => - ruleTypeId.startsWith('siem.') - ); + const isAnyRuleTypeESAuthorized = request.ruleTypeIds.some(isSiemRuleType); - const isEachRuleTypeESAuthorized = request.ruleTypeIds.every((ruleTypeId) => - ruleTypeId.startsWith('siem.') - ); + const isEachRuleTypeESAuthorized = request.ruleTypeIds.every(isSiemRuleType); const registeredRuleTypes = alerting.listTypes(); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_alert_data_view.ts b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_alert_data_view.ts index f5ee0e777d4c90..d21045090242fa 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_alert_data_view.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_alert_data_view.ts @@ -10,6 +10,7 @@ import { DataView } from '@kbn/data-views-plugin/common'; import { useKibana } from '@kbn/kibana-react-plugin/public'; import { useEffect, useMemo, useState } from 'react'; import { useQuery } from '@tanstack/react-query'; +import { isSiemRuleType } from '@kbn/rule-data-utils'; import { TriggersAndActionsUiServices } from '../..'; import { fetchAlertIndexNames } from '../lib/rule_api/alert_index'; import { fetchAlertFields } from '../lib/rule_api/alert_fields'; @@ -27,7 +28,7 @@ export function useAlertDataViews(ruleTypeIds: string[]): UserAlertDataViews { } = useKibana().services; const [dataViews, setDataViews] = useState(undefined); const ruleTypes = ruleTypeIds.sort().join(','); - const hasSecurity = ruleTypeIds.some((ruleTypeId) => ruleTypeId.startsWith('siem.')); + const hasSecurity = ruleTypeIds.some(isSiemRuleType); const isOnlySecurity = ruleTypeIds.length === 1 && hasSecurity; const hasSecurityAndO11yFeatureIds = ruleTypeIds.length > 1 && hasSecurity; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_search_bar/alerts_search_bar.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_search_bar/alerts_search_bar.tsx index 990746aa0b5248..daa6876c80e23e 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_search_bar/alerts_search_bar.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_search_bar/alerts_search_bar.tsx @@ -9,7 +9,7 @@ import React, { useCallback, useMemo, useState } from 'react'; import { useKibana } from '@kbn/kibana-react-plugin/public'; import { compareFilters, Query, TimeRange } from '@kbn/es-query'; import { SuggestionsAbstraction } from '@kbn/unified-search-plugin/public/typeahead/suggestions_component'; -import { AlertConsumers } from '@kbn/rule-data-utils'; +import { AlertConsumers, isSiemRuleType } from '@kbn/rule-data-utils'; import { EuiContextMenuPanelDescriptor, EuiContextMenuPanelItemDescriptor } from '@elastic/eui'; import { isQuickFiltersGroup, QuickFiltersMenuItem } from './quick_filters'; import { NO_INDEX_PATTERNS } from './constants'; @@ -64,7 +64,7 @@ export function AlertsSearchBar({ }); const isSecurity = - (ruleTypeIds && ruleTypeIds.length === 1 && ruleTypeIds[0].startsWith('siem.')) || + (ruleTypeIds && ruleTypeIds.length === 1 && isSiemRuleType(ruleTypeIds[0])) || (ruleType && ruleTypeId && ruleType.ruleTypesState.data.get(ruleTypeId)?.producer === AlertConsumers.SIEM); From c8fcf38fb668341133566ba2c778fad0639d40ee Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Wed, 31 Jul 2024 13:17:29 +0300 Subject: [PATCH 042/106] Use fetchAlertsFields to use rule type IDs --- .../fetch_alerts_fields.test.ts | 8 ++--- .../fetch_alerts_fields.ts | 4 +-- .../use_fetch_alerts_fields_query.test.tsx | 31 +++++-------------- 3 files changed, 13 insertions(+), 30 deletions(-) diff --git a/packages/kbn-alerts-ui-shared/src/common/apis/fetch_alerts_fields/fetch_alerts_fields.test.ts b/packages/kbn-alerts-ui-shared/src/common/apis/fetch_alerts_fields/fetch_alerts_fields.test.ts index 9149c68e2f522a..27176c8cb0392b 100644 --- a/packages/kbn-alerts-ui-shared/src/common/apis/fetch_alerts_fields/fetch_alerts_fields.test.ts +++ b/packages/kbn-alerts-ui-shared/src/common/apis/fetch_alerts_fields/fetch_alerts_fields.test.ts @@ -8,12 +8,12 @@ import { httpServiceMock } from '@kbn/core/public/mocks'; import { fetchAlertsFields } from '.'; -import { AlertConsumers } from '@kbn/rule-data-utils'; describe('fetchAlertsFields', () => { const http = httpServiceMock.createStartContract(); test('should call the browser_fields API with the correct parameters', async () => { - const featureIds = [AlertConsumers.STACK_ALERTS]; + const ruleTypeIds = ['.es-query']; + http.get.mockResolvedValueOnce({ browserFields: { fakeCategory: {} }, fields: [ @@ -22,7 +22,7 @@ describe('fetchAlertsFields', () => { }, ], }); - const result = await fetchAlertsFields({ http, featureIds }); + const result = await fetchAlertsFields({ http, ruleTypeIds }); expect(result).toEqual({ browserFields: { fakeCategory: {} }, fields: [ @@ -32,7 +32,7 @@ describe('fetchAlertsFields', () => { ], }); expect(http.get).toHaveBeenLastCalledWith('/internal/rac/alerts/browser_fields', { - query: { featureIds }, + query: { ruleTypeIds }, }); }); }); diff --git a/packages/kbn-alerts-ui-shared/src/common/apis/fetch_alerts_fields/fetch_alerts_fields.ts b/packages/kbn-alerts-ui-shared/src/common/apis/fetch_alerts_fields/fetch_alerts_fields.ts index 3deafc37e8ce42..ae0fb1ef7f81f5 100644 --- a/packages/kbn-alerts-ui-shared/src/common/apis/fetch_alerts_fields/fetch_alerts_fields.ts +++ b/packages/kbn-alerts-ui-shared/src/common/apis/fetch_alerts_fields/fetch_alerts_fields.ts @@ -11,10 +11,10 @@ import type { BrowserFields } from '@kbn/alerting-types'; import type { FetchAlertsFieldsParams } from './types'; import { BASE_RAC_ALERTS_API_PATH } from '../../constants'; -export const fetchAlertsFields = ({ http, featureIds }: FetchAlertsFieldsParams) => +export const fetchAlertsFields = ({ http, ruleTypeIds }: FetchAlertsFieldsParams) => http.get<{ browserFields: BrowserFields; fields: FieldDescriptor[] }>( `${BASE_RAC_ALERTS_API_PATH}/browser_fields`, { - query: { featureIds }, + query: { ruleTypeIds }, } ); diff --git a/packages/kbn-alerts-ui-shared/src/common/hooks/use_fetch_alerts_fields_query.test.tsx b/packages/kbn-alerts-ui-shared/src/common/hooks/use_fetch_alerts_fields_query.test.tsx index adcf3b37e38cb0..4c65ecab32c614 100644 --- a/packages/kbn-alerts-ui-shared/src/common/hooks/use_fetch_alerts_fields_query.test.tsx +++ b/packages/kbn-alerts-ui-shared/src/common/hooks/use_fetch_alerts_fields_query.test.tsx @@ -8,7 +8,6 @@ import React, { FunctionComponent } from 'react'; import type { HttpSetup } from '@kbn/core-http-browser'; -import { AlertConsumers } from '@kbn/rule-data-utils'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { renderHook } from '@testing-library/react-hooks'; import { testQueryClientConfig } from '../test_utils/test_query_client_config'; @@ -45,9 +44,9 @@ describe('useFetchAlertsFieldsQuery', () => { queryClient.clear(); }); - it('should not fetch for siem', () => { + it('should not fetch for siem rule types', () => { const { result } = renderHook( - () => useFetchAlertsFieldsQuery({ http: mockHttpClient, featureIds: ['siem'] }), + () => useFetchAlertsFieldsQuery({ http: mockHttpClient, ruleTypeIds: ['siem.esqlRule'] }), { wrapper, } @@ -59,7 +58,7 @@ describe('useFetchAlertsFieldsQuery', () => { it('should call the api only once', async () => { const { result, rerender, waitForValueToChange } = renderHook( - () => useFetchAlertsFieldsQuery({ http: mockHttpClient, featureIds: ['apm'] }), + () => useFetchAlertsFieldsQuery({ http: mockHttpClient, ruleTypeIds: ['apm'] }), { wrapper, } @@ -90,28 +89,12 @@ describe('useFetchAlertsFieldsQuery', () => { }); }); - it('should not fetch if the only featureId is not valid', async () => { + it('should not fetch if all rule types are siem', async () => { const { result } = renderHook( () => useFetchAlertsFieldsQuery({ http: mockHttpClient, - featureIds: ['alerts'] as unknown as AlertConsumers[], - }), - { - wrapper, - } - ); - - expect(mockHttpGet).toHaveBeenCalledTimes(0); - expect(result.current.data).toEqual(emptyData); - }); - - it('should not fetch if all featureId are not valid', async () => { - const { result } = renderHook( - () => - useFetchAlertsFieldsQuery({ - http: mockHttpClient, - featureIds: ['alerts', 'tomato'] as unknown as AlertConsumers[], + ruleTypeIds: ['siem.esqlRule', 'siem.eqlRule'], }), { wrapper, @@ -127,7 +110,7 @@ describe('useFetchAlertsFieldsQuery', () => { () => useFetchAlertsFieldsQuery({ http: mockHttpClient, - featureIds: ['alerts', 'apm', 'logs'] as AlertConsumers[], + ruleTypeIds: ['siem.esqlRule', 'apm', 'logs'], }), { wrapper, @@ -136,7 +119,7 @@ describe('useFetchAlertsFieldsQuery', () => { expect(mockHttpGet).toHaveBeenCalledTimes(1); expect(mockHttpGet).toHaveBeenCalledWith('/internal/rac/alerts/browser_fields', { - query: { featureIds: ['apm', 'logs'] }, + query: { ruleTypeIds: ['apm', 'logs'] }, }); }); }); From 50c28120972a50e3f0bcec91412f4210c8e99c0c Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Wed, 31 Jul 2024 14:05:34 +0300 Subject: [PATCH 043/106] Fix stack management types --- .../public/application/lib/search_filters.ts | 1 + .../components/stack_alerts_page.tsx | 50 +++++++------------ .../hooks/use_rule_type_ids_by_feature_id.ts | 14 +++--- .../url_synced_alerts_search_bar.tsx | 37 +++++++------- 4 files changed, 43 insertions(+), 59 deletions(-) diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/search_filters.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/search_filters.ts index 669fddd976d842..31f7175904526d 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/search_filters.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/search_filters.ts @@ -36,6 +36,7 @@ export const createMatchPhraseFilter = ( disabled: false, index: undefined, negate: false, + // @ts-expect-error params: { query: value }, value: undefined, ruleTypeIds: [], diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_page/components/stack_alerts_page.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_page/components/stack_alerts_page.tsx index 0e9fa7d27fadc1..5ae519ba6f4406 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_page/components/stack_alerts_page.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_page/components/stack_alerts_page.tsx @@ -21,6 +21,7 @@ import { ALERT_STATUS_RECOVERED, ALERT_STATUS_UNTRACKED, AlertConsumers, + isSiemRuleType, } from '@kbn/rule-data-utils'; import { QueryClientProvider } from '@tanstack/react-query'; import { BoolQuery } from '@kbn/es-query'; @@ -31,7 +32,6 @@ import { NoPermissionPrompt } from '../../../components/prompts/no_permission_pr import { ALERT_TABLE_GLOBAL_CONFIG_ID } from '../../../constants'; import { useRuleStats } from '../hooks/use_rule_stats'; import { getAlertingSectionBreadcrumb } from '../../../lib/breadcrumb'; -import { NON_SIEM_FEATURE_IDS } from '../../alerts_search_bar/constants'; import { alertProducersData } from '../../alerts_table/constants'; import { UrlSyncedAlertsSearchBar } from '../../alerts_search_bar/url_synced_alerts_search_bar'; import { useKibana } from '../../../../common/lib/kibana'; @@ -77,64 +77,47 @@ const PageContent = () => { alertsTableConfigurationRegistry, } = useKibana().services; const [esQuery, setEsQuery] = useState({ bool: {} } as { bool: BoolQuery }); - const [activeRuleTypeFilters, setActiveRuleTypeFilters] = useState([]); - + const [ruleTypeIds, setRuleTypeIds] = useState([]); const ruleStats = useRuleStats(); + const { ruleTypesState: { data: ruleTypesIndex, initialLoad: isInitialLoadingRuleTypes }, authorizedToReadAnyRules, } = useLoadRuleTypesQuery({ filteredRuleTypes: [] }); - const ruleTypeIdsByFeatureId = useRuleTypeIdsByFeatureId(ruleTypesIndex); - - const browsingSiem = useMemo( - () => activeRuleTypeFilters.length === 1 && activeRuleTypeFilters[0] === AlertConsumers.SIEM, - [activeRuleTypeFilters] - ); - - const filteringBySolution = useMemo( - () => activeRuleTypeFilters.length > 0, - [activeRuleTypeFilters.length] - ); - const featureIds = useMemo( - () => - filteringBySolution - ? browsingSiem - ? [AlertConsumers.SIEM] - : activeRuleTypeFilters - : NON_SIEM_FEATURE_IDS, - [activeRuleTypeFilters, browsingSiem, filteringBySolution] - ); + const ruleTypeIdsByFeatureId = useRuleTypeIdsByFeatureId(ruleTypesIndex); + const browsingSiem = ruleTypeIds.length === 1 && isSiemRuleType(ruleTypeIds[0]); + const filteringBySolution = ruleTypeIds.length > 0; + const ruleTypeIdsByFeatureIdEntries = Object.entries(ruleTypeIdsByFeatureId); const quickFilters = useMemo(() => { const filters: QuickFiltersMenuItem[] = []; - if (Object.values(ruleTypeIdsByFeatureId).length > 0) { + if (ruleTypeIdsByFeatureIdEntries.length > 0) { filters.push( - ...Object.entries(ruleTypeIdsByFeatureId) - .map(([featureId, ruleTypeIds]) => { + ...ruleTypeIdsByFeatureIdEntries + .map(([featureId, _ruleTypeIds]) => { const producerData = alertProducersData[featureId as AlertsTableSupportedConsumers]; if (!producerData) { return null; } + const filterLabel = getFeatureFilterLabel(producerData.displayName); const disabled = filteringBySolution && featureId === AlertConsumers.SIEM ? !browsingSiem : browsingSiem; + return { name: filterLabel, icon: producerData.icon, - filter: createRuleTypesFilter( - producerData.subFeatureIds ?? [featureId as AlertConsumers], - filterLabel, - ruleTypeIds - ), + filter: createRuleTypesFilter(_ruleTypeIds, filterLabel), disabled, }; }) .filter(nonNullable) ); } + filters.push({ title: i18n.translate('xpack.triggersActionsUI.sections.globalAlerts.quickFilters.status', { defaultMessage: 'Status', @@ -146,7 +129,8 @@ const PageContent = () => { })), }); return filters; - }, [browsingSiem, filteringBySolution, ruleTypeIdsByFeatureId]); + }, [browsingSiem, filteringBySolution, ruleTypeIdsByFeatureIdEntries]); + const tableConfigurationId = useMemo( // TODO in preparation for using solution-specific configurations () => ALERT_TABLE_GLOBAL_CONFIG_ID, @@ -191,7 +175,7 @@ const PageContent = () => { showFilterControls showFilterBar quickFilters={quickFilters} - onActiveRuleTypeFiltersChange={setActiveRuleTypeFilters} + onRuleTypesChanged={setRuleTypeIds} onEsQueryChange={setEsQuery} /> }> diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_page/hooks/use_rule_type_ids_by_feature_id.ts b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_page/hooks/use_rule_type_ids_by_feature_id.ts index c8c5eedc3054f0..cc80d73b1fcbc0 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_page/hooks/use_rule_type_ids_by_feature_id.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_page/hooks/use_rule_type_ids_by_feature_id.ts @@ -30,9 +30,10 @@ export const useRuleTypeIdsByFeatureId = (ruleTypesIndex: RuleTypeIndex) => if (!ruleTypesIndex?.size) { return {}; } + const map = Array.from(ruleTypesIndex.entries()).reduce>>( - (types, [key, value]) => { - let producer = value.producer as keyof RuleTypeIdsByFeatureId; + (types, [ruleTypeId, ruleType]) => { + let producer = ruleType.producer as keyof RuleTypeIdsByFeatureId; // Some o11y apps are listed under 'observability' to create a grouped filter if (observabilityFeatureIds.includes(producer)) { producer = AlertConsumers.OBSERVABILITY; @@ -41,14 +42,15 @@ export const useRuleTypeIdsByFeatureId = (ruleTypesIndex: RuleTypeIndex) => if (stackFeatureIds.includes(producer)) { producer = AlertConsumers.STACK_ALERTS; } + // Multi consumer rule type ids should be listed both in Observability and Stack alerts - if (MULTI_CONSUMER_RULE_TYPE_IDS.includes(value.id)) { + if (MULTI_CONSUMER_RULE_TYPE_IDS.includes(ruleType.id)) { (types[AlertConsumers.OBSERVABILITY] = - types[AlertConsumers.OBSERVABILITY] || new Set()).add(key); + types[AlertConsumers.OBSERVABILITY] || new Set()).add(ruleTypeId); (types[AlertConsumers.STACK_ALERTS] = - types[AlertConsumers.STACK_ALERTS] || new Set()).add(key); + types[AlertConsumers.STACK_ALERTS] || new Set()).add(ruleTypeId); } else { - (types[producer] = types[producer] || new Set()).add(key); + (types[producer] = types[producer] || new Set()).add(ruleTypeId); } return types; }, diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_search_bar/url_synced_alerts_search_bar.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_search_bar/url_synced_alerts_search_bar.tsx index 1d5c59af201ef7..b7458688b7a8c6 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_search_bar/url_synced_alerts_search_bar.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_search_bar/url_synced_alerts_search_bar.tsx @@ -6,7 +6,7 @@ */ import React, { useCallback, useEffect, useState } from 'react'; -import { BoolQuery } from '@kbn/es-query'; +import { BoolQuery, Filter } from '@kbn/es-query'; import { i18n } from '@kbn/i18n'; import { AlertFilterControls } from '@kbn/alerts-ui-shared/src/alert_filter_controls'; import { ControlGroupRenderer } from '@kbn/controls-plugin/public'; @@ -34,7 +34,7 @@ export interface UrlSyncedAlertsSearchBarProps > { showFilterControls?: boolean; onEsQueryChange: (esQuery: { bool: BoolQuery }) => void; - onActiveRuleTypeFiltersChange?: (value: string[]) => void; + onRuleTypesChanged?: (ruleTypeIds: string[]) => void; } /** @@ -43,7 +43,7 @@ export interface UrlSyncedAlertsSearchBarProps export const UrlSyncedAlertsSearchBar = ({ showFilterControls = false, onEsQueryChange, - onActiveRuleTypeFiltersChange, + onRuleTypesChanged, ...rest }: UrlSyncedAlertsSearchBarProps) => { const { @@ -84,11 +84,6 @@ export const UrlSyncedAlertsSearchBar = ({ useEffect(() => { try { - onActiveRuleTypeFiltersChange?.([ - ...new Set( - filters.flatMap((f) => (f as AlertsFeatureIdsFilter).meta.ruleTypeIds).filter(nonNullable) - ), - ]); onEsQueryChange( buildEsQuery({ timeRange: { @@ -105,17 +100,7 @@ export const UrlSyncedAlertsSearchBar = ({ }); onKueryChange(''); } - }, [ - controlFilters, - filters, - kuery, - onActiveRuleTypeFiltersChange, - onEsQueryChange, - onKueryChange, - rangeFrom, - rangeTo, - toasts, - ]); + }, [controlFilters, filters, kuery, onEsQueryChange, onKueryChange, rangeFrom, rangeTo, toasts]); const onQueryChange = useCallback>( ({ query, dateRange }) => { @@ -128,6 +113,18 @@ export const UrlSyncedAlertsSearchBar = ({ [onKueryChange, onRangeFromChange, onRangeToChange, setSavedQuery, timeFilterService] ); + const onFiltersUpdated = (updatedFilters: Filter[]) => { + onRuleTypesChanged?.([ + ...new Set( + updatedFilters + .flatMap((ruleTypeId) => (ruleTypeId as AlertsFeatureIdsFilter).meta.ruleTypeIds) + .filter(nonNullable) + ), + ]); + + onFiltersChange(updatedFilters); + }; + return ( <> Date: Wed, 31 Jul 2024 14:12:30 +0300 Subject: [PATCH 044/106] Revert uptime file --- .../uptime/common/constants/uptime_alerts.ts | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 x-pack/plugins/observability_solution/uptime/common/constants/uptime_alerts.ts diff --git a/x-pack/plugins/observability_solution/uptime/common/constants/uptime_alerts.ts b/x-pack/plugins/observability_solution/uptime/common/constants/uptime_alerts.ts new file mode 100644 index 00000000000000..71f6bd1b183fb1 --- /dev/null +++ b/x-pack/plugins/observability_solution/uptime/common/constants/uptime_alerts.ts @@ -0,0 +1,49 @@ +/* + * 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 { ActionGroup } from '@kbn/alerting-plugin/common'; + +export type MonitorStatusActionGroup = + ActionGroup<'xpack.uptime.alerts.actionGroups.monitorStatus'>; +export type TLSLegacyActionGroup = ActionGroup<'xpack.uptime.alerts.actionGroups.tls'>; +export type TLSActionGroup = ActionGroup<'xpack.uptime.alerts.actionGroups.tlsCertificate'>; +export type DurationAnomalyActionGroup = + ActionGroup<'xpack.uptime.alerts.actionGroups.durationAnomaly'>; + +export const MONITOR_STATUS: MonitorStatusActionGroup = { + id: 'xpack.uptime.alerts.actionGroups.monitorStatus', + name: 'Uptime Down Monitor', +}; + +export const TLS_LEGACY: TLSLegacyActionGroup = { + id: 'xpack.uptime.alerts.actionGroups.tls', + name: 'Uptime TLS Alert (Legacy)', +}; + +export const TLS: TLSActionGroup = { + id: 'xpack.uptime.alerts.actionGroups.tlsCertificate', + name: 'Uptime TLS Alert', +}; + +export const DURATION_ANOMALY: DurationAnomalyActionGroup = { + id: 'xpack.uptime.alerts.actionGroups.durationAnomaly', + name: 'Uptime Duration Anomaly', +}; + +export const CLIENT_ALERT_TYPES = { + MONITOR_STATUS: 'xpack.uptime.alerts.monitorStatus', + TLS_LEGACY: 'xpack.uptime.alerts.tls', + TLS: 'xpack.uptime.alerts.tlsCertificate', + DURATION_ANOMALY: 'xpack.uptime.alerts.durationAnomaly', +}; + +export const UPTIME_RULE_TYPES = [ + 'xpack.uptime.alerts.tls', + 'xpack.uptime.alerts.tlsCertificate', + 'xpack.uptime.alerts.monitorStatus', + 'xpack.uptime.alerts.durationAnomaly', +]; From e40682c698a41fd5d239d5866d33a9bc4dbaacd9 Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Wed, 31 Jul 2024 15:11:43 +0300 Subject: [PATCH 045/106] Fix types to start --- .../infra/common/alerting/logs/log_threshold/types.ts | 2 ++ .../components/alert_search_bar/alert_search_bar.test.tsx | 2 +- .../components/alert_search_bar/alert_search_bar.tsx | 2 +- .../pages/alert_details/components/alert_history.tsx | 7 +++++-- .../observability/public/pages/alerts/alerts.tsx | 7 ++----- .../observability/public/pages/overview/overview.tsx | 3 +-- .../public/pages/rule_details/rule_details.tsx | 3 ++- .../server/functions/alerts.ts | 2 +- .../slo/alerts/components/slo_alerts_summary.tsx | 2 +- .../slo/server/services/get_slos_overview.ts | 2 +- .../synthetics/common/constants/synthetics_alerts.ts | 2 ++ .../public/apps/synthetics/lib/alert_types/tls.tsx | 3 +-- .../server/alert_rules/status_rule/monitor_status_rule.ts | 6 ++---- .../synthetics/server/alert_rules/tls_rule/tls_rule.ts | 7 ++----- .../uptime/common/constants/synthetics_alerts.ts | 2 -- 15 files changed, 24 insertions(+), 28 deletions(-) diff --git a/x-pack/plugins/observability_solution/infra/common/alerting/logs/log_threshold/types.ts b/x-pack/plugins/observability_solution/infra/common/alerting/logs/log_threshold/types.ts index 1fcd1b2316e522..50ed3ac2542aac 100644 --- a/x-pack/plugins/observability_solution/infra/common/alerting/logs/log_threshold/types.ts +++ b/x-pack/plugins/observability_solution/infra/common/alerting/logs/log_threshold/types.ts @@ -10,6 +10,8 @@ import * as rt from 'io-ts'; import { persistedLogViewReferenceRT } from '@kbn/logs-shared-plugin/common'; import { commonSearchSuccessResponseFieldsRT } from '../../../utils/elasticsearch_runtime_types'; +export { LOG_THRESHOLD_ALERT_TYPE_ID as LOG_DOCUMENT_COUNT_RULE_TYPE_ID } from '@kbn/rule-data-utils'; + const ThresholdTypeRT = rt.keyof({ count: null, ratio: null, diff --git a/x-pack/plugins/observability_solution/observability/public/components/alert_search_bar/alert_search_bar.test.tsx b/x-pack/plugins/observability_solution/observability/public/components/alert_search_bar/alert_search_bar.test.tsx index fb951db83e039a..c1a38f22f16025 100644 --- a/x-pack/plugins/observability_solution/observability/public/components/alert_search_bar/alert_search_bar.test.tsx +++ b/x-pack/plugins/observability_solution/observability/public/components/alert_search_bar/alert_search_bar.test.tsx @@ -12,8 +12,8 @@ import { uiSettingsServiceMock } from '@kbn/core-ui-settings-browser-mocks'; import { ObservabilityAlertSearchBarProps, Services } from './types'; import { ObservabilityAlertSearchBar } from './alert_search_bar'; -import { OBSERVABILITY_RULE_TYPE_IDS } from '../../../common/constants'; import { render } from '../../utils/test_helper'; +import { OBSERVABILITY_RULE_TYPE_IDS } from '@kbn/rule-data-utils'; const getAlertsSearchBarMock = jest.fn(); const ALERT_SEARCH_BAR_DATA_TEST_SUBJ = 'alerts-search-bar'; diff --git a/x-pack/plugins/observability_solution/observability/public/components/alert_search_bar/alert_search_bar.tsx b/x-pack/plugins/observability_solution/observability/public/components/alert_search_bar/alert_search_bar.tsx index e9f889655aa293..98ec9093923e05 100644 --- a/x-pack/plugins/observability_solution/observability/public/components/alert_search_bar/alert_search_bar.tsx +++ b/x-pack/plugins/observability_solution/observability/public/components/alert_search_bar/alert_search_bar.tsx @@ -11,8 +11,8 @@ import React, { useCallback, useEffect } from 'react'; import { i18n } from '@kbn/i18n'; import { Filter, Query } from '@kbn/es-query'; import { getEsQueryConfig } from '@kbn/data-plugin/common'; +import { OBSERVABILITY_RULE_TYPE_IDS } from '@kbn/rule-data-utils'; import { AlertsStatusFilter } from './components'; -import { OBSERVABILITY_RULE_TYPE_IDS } from '../../../common/constants'; import { ALERT_STATUS_QUERY, DEFAULT_QUERIES, DEFAULT_QUERY_STRING } from './constants'; import { ObservabilityAlertSearchBarProps } from './types'; import { buildEsQuery } from '../../utils/build_es_query'; diff --git a/x-pack/plugins/observability_solution/observability/public/pages/alert_details/components/alert_history.tsx b/x-pack/plugins/observability_solution/observability/public/pages/alert_details/components/alert_history.tsx index 8c967a265e3f13..cb8250898d30ba 100644 --- a/x-pack/plugins/observability_solution/observability/public/pages/alert_details/components/alert_history.tsx +++ b/x-pack/plugins/observability_solution/observability/public/pages/alert_details/components/alert_history.tsx @@ -16,10 +16,13 @@ import { EuiLoadingSpinner, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { ALERT_INSTANCE_ID, ALERT_RULE_UUID } from '@kbn/rule-data-utils'; +import { + ALERT_INSTANCE_ID, + ALERT_RULE_UUID, + OBSERVABILITY_RULE_TYPE_IDS, +} from '@kbn/rule-data-utils'; import { useAlertsHistory } from '@kbn/observability-alert-details'; import type { Rule } from '@kbn/triggers-actions-ui-plugin/public'; -import { OBSERVABILITY_RULE_TYPE_IDS } from '../../../../common/constants'; import { convertTo } from '../../../../common/utils/formatters'; import { useKibana } from '../../../utils/kibana_react'; import { TopAlert } from '../../..'; diff --git a/x-pack/plugins/observability_solution/observability/public/pages/alerts/alerts.tsx b/x-pack/plugins/observability_solution/observability/public/pages/alerts/alerts.tsx index cc8ae4d935873b..4dba6200604f67 100644 --- a/x-pack/plugins/observability_solution/observability/public/pages/alerts/alerts.tsx +++ b/x-pack/plugins/observability_solution/observability/public/pages/alerts/alerts.tsx @@ -11,7 +11,7 @@ import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import { BoolQuery } from '@kbn/es-query'; import { i18n } from '@kbn/i18n'; import { loadRuleAggregations } from '@kbn/triggers-actions-ui-plugin/public'; -import { AlertConsumers } from '@kbn/rule-data-utils'; +import { AlertConsumers, OBSERVABILITY_RULE_TYPE_IDS } from '@kbn/rule-data-utils'; import { useBreadcrumbs } from '@kbn/observability-shared-plugin/public'; import { MaintenanceWindowCallout } from '@kbn/alerts-ui-shared'; import { DEFAULT_APP_CATEGORIES } from '@kbn/core-application-common'; @@ -32,10 +32,7 @@ import { } from '../../components/alert_search_bar/containers'; import { calculateTimeRangeBucketSize } from '../overview/helpers/calculate_bucket_size'; import { getAlertSummaryTimeRange } from '../../utils/alert_summary_widget'; -import { - observabilityAlertFeatureIds, - OBSERVABILITY_RULE_TYPE_IDS, -} from '../../../common/constants'; +import { observabilityAlertFeatureIds } from '../../../common/constants'; import { ALERTS_URL_STORAGE_KEY } from '../../../common/constants'; import { HeaderMenu } from '../overview/components/header_menu/header_menu'; import { useGetAvailableRulesWithDescriptions } from '../../hooks/use_get_available_rules_with_descriptions'; diff --git a/x-pack/plugins/observability_solution/observability/public/pages/overview/overview.tsx b/x-pack/plugins/observability_solution/observability/public/pages/overview/overview.tsx index f9257476f0eb56..48774299d6dd4b 100644 --- a/x-pack/plugins/observability_solution/observability/public/pages/overview/overview.tsx +++ b/x-pack/plugins/observability_solution/observability/public/pages/overview/overview.tsx @@ -9,9 +9,8 @@ import { EuiFlexGroup, EuiFlexItem, EuiHorizontalRule, EuiSpacer } from '@elasti import { BoolQuery } from '@kbn/es-query'; import { i18n } from '@kbn/i18n'; import { useBreadcrumbs, useFetcher } from '@kbn/observability-shared-plugin/public'; -import { AlertConsumers } from '@kbn/rule-data-utils'; +import { AlertConsumers, OBSERVABILITY_RULE_TYPE_IDS } from '@kbn/rule-data-utils'; import React, { useCallback, useEffect, useMemo, useState } from 'react'; -import { OBSERVABILITY_RULE_TYPE_IDS } from '../../../common/constants'; import { paths } from '../../../common/locators/paths'; import { LoadingObservability } from '../../components/loading_observability'; import { DEFAULT_DATE_FORMAT, DEFAULT_INTERVAL } from '../../constants'; diff --git a/x-pack/plugins/observability_solution/observability/public/pages/rule_details/rule_details.tsx b/x-pack/plugins/observability_solution/observability/public/pages/rule_details/rule_details.tsx index eef39db96b86cd..9c137e4a8228ef 100644 --- a/x-pack/plugins/observability_solution/observability/public/pages/rule_details/rule_details.tsx +++ b/x-pack/plugins/observability_solution/observability/public/pages/rule_details/rule_details.tsx @@ -12,6 +12,7 @@ import { i18n } from '@kbn/i18n'; import { RuleExecutionStatusErrorReasons } from '@kbn/alerting-plugin/common'; import type { BoolQuery } from '@kbn/es-query'; import { useBreadcrumbs } from '@kbn/observability-shared-plugin/public'; +import { OBSERVABILITY_RULE_TYPE_IDS } from '@kbn/rule-data-utils'; import { useKibana } from '../../utils/kibana_react'; import { usePluginContext } from '../../hooks/use_plugin_context'; import { useFetchRule } from '../../hooks/use_fetch_rule'; @@ -26,7 +27,7 @@ import { RuleDetailsTabs } from './components/rule_details_tabs'; import { getHealthColor } from './helpers/get_health_color'; import { isRuleEditable } from './helpers/is_rule_editable'; import { ruleDetailsLocatorID } from '../../../common'; -import { ALERT_STATUS_ALL, OBSERVABILITY_RULE_TYPE_IDS } from '../../../common/constants'; +import { ALERT_STATUS_ALL } from '../../../common/constants'; import { RULE_DETAILS_EXECUTION_TAB, RULE_DETAILS_ALERTS_TAB, diff --git a/x-pack/plugins/observability_solution/observability_ai_assistant_app/server/functions/alerts.ts b/x-pack/plugins/observability_solution/observability_ai_assistant_app/server/functions/alerts.ts index adb74f845029bc..f91731962cf86b 100644 --- a/x-pack/plugins/observability_solution/observability_ai_assistant_app/server/functions/alerts.ts +++ b/x-pack/plugins/observability_solution/observability_ai_assistant_app/server/functions/alerts.ts @@ -10,8 +10,8 @@ import { KibanaRequest } from '@kbn/core/server'; import { fromKueryExpression, toElasticsearchQuery } from '@kbn/es-query'; import { FunctionVisibility } from '@kbn/observability-ai-assistant-plugin/common'; import { getRelevantFieldNames } from '@kbn/observability-ai-assistant-plugin/server/functions/get_dataset_info/get_relevant_field_names'; -import { OBSERVABILITY_RULE_TYPE_IDS } from '@kbn/observability-plugin/common/constants'; import { ParsedTechnicalFields } from '@kbn/rule-registry-plugin/common'; +import { OBSERVABILITY_RULE_TYPE_IDS } from '@kbn/rule-data-utils'; import { ALERT_STATUS, ALERT_STATUS_ACTIVE, diff --git a/x-pack/plugins/observability_solution/slo/public/embeddable/slo/alerts/components/slo_alerts_summary.tsx b/x-pack/plugins/observability_solution/slo/public/embeddable/slo/alerts/components/slo_alerts_summary.tsx index 2e74d3bef58866..ec4e5dc8b497bc 100644 --- a/x-pack/plugins/observability_solution/slo/public/embeddable/slo/alerts/components/slo_alerts_summary.tsx +++ b/x-pack/plugins/observability_solution/slo/public/embeddable/slo/alerts/components/slo_alerts_summary.tsx @@ -9,7 +9,7 @@ import type { TimeRange } from '@kbn/es-query'; import { useTimeBuckets } from '@kbn/observability-plugin/public'; import { getAlertSummaryTimeRange } from '@kbn/observability-plugin/public'; import { calculateTimeRangeBucketSize } from '@kbn/observability-plugin/public'; -import { OBSERVABILITY_RULE_TYPE_IDS } from '@kbn/observability-plugin/common/constants'; +import { OBSERVABILITY_RULE_TYPE_IDS } from '@kbn/rule-data-utils'; import { useSloAlertsQuery } from './slo_alerts_table'; import { SloEmbeddableDeps } from '../types'; diff --git a/x-pack/plugins/observability_solution/slo/server/services/get_slos_overview.ts b/x-pack/plugins/observability_solution/slo/server/services/get_slos_overview.ts index e57cac0b8d96e0..05426d509ddf5c 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/get_slos_overview.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/get_slos_overview.ts @@ -15,7 +15,7 @@ import { import { RulesClientApi } from '@kbn/alerting-plugin/server/types'; import { AlertsClient } from '@kbn/rule-registry-plugin/server'; import moment from 'moment'; -import { OBSERVABILITY_RULE_TYPE_IDS } from '@kbn/observability-plugin/common/constants'; +import { OBSERVABILITY_RULE_TYPE_IDS } from '@kbn/rule-data-utils'; import { typedSearch } from '../utils/queries'; import { getElasticsearchQueryOrThrow, parseStringFilters } from './transform_generators'; import { getListOfSummaryIndices, getSloSettings } from './slo_settings'; diff --git a/x-pack/plugins/observability_solution/synthetics/common/constants/synthetics_alerts.ts b/x-pack/plugins/observability_solution/synthetics/common/constants/synthetics_alerts.ts index cb9fa42479d5e4..472de463897277 100644 --- a/x-pack/plugins/observability_solution/synthetics/common/constants/synthetics_alerts.ts +++ b/x-pack/plugins/observability_solution/synthetics/common/constants/synthetics_alerts.ts @@ -35,3 +35,5 @@ export const ACTION_GROUP_DEFINITIONS: { }; export const SYNTHETICS_RULE_TYPES_ALERT_CONTEXT = 'observability.uptime'; + +export { SYNTHETICS_RULE_TYPE_IDS as SYNTHETICS_RULE_TYPES } from '@kbn/rule-data-utils'; diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/lib/alert_types/tls.tsx b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/lib/alert_types/tls.tsx index 15c0fa90ec605a..00ae18ab6a4334 100644 --- a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/lib/alert_types/tls.tsx +++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/lib/alert_types/tls.tsx @@ -6,13 +6,12 @@ */ import React from 'react'; -import { ALERT_REASON } from '@kbn/rule-data-utils'; +import { ALERT_REASON, SYNTHETICS_ALERT_RULE_TYPES } from '@kbn/rule-data-utils'; import { ObservabilityRuleTypeModel } from '@kbn/observability-plugin/public'; import type { RuleTypeParamsExpressionProps } from '@kbn/triggers-actions-ui-plugin/public'; import { ValidationResult } from '@kbn/triggers-actions-ui-plugin/public'; import { TlsTranslations } from '../../../../../common/rules/synthetics/translations'; import { CERTIFICATES_ROUTE } from '../../../../../common/constants/ui'; -import { SYNTHETICS_ALERT_RULE_TYPES } from '../../../../../common/constants/synthetics_alerts'; import type { TLSParams } from '../../../../../common/runtime_types/alerts/tls'; import { AlertTypeInitializer } from '.'; diff --git a/x-pack/plugins/observability_solution/synthetics/server/alert_rules/status_rule/monitor_status_rule.ts b/x-pack/plugins/observability_solution/synthetics/server/alert_rules/status_rule/monitor_status_rule.ts index a6a1cf34454900..d4d456538e2c0a 100644 --- a/x-pack/plugins/observability_solution/synthetics/server/alert_rules/status_rule/monitor_status_rule.ts +++ b/x-pack/plugins/observability_solution/synthetics/server/alert_rules/status_rule/monitor_status_rule.ts @@ -18,6 +18,7 @@ import { } from '@kbn/alerting-plugin/server'; import { observabilityPaths } from '@kbn/observability-plugin/common'; import { ObservabilityUptimeAlert } from '@kbn/alerts-as-data-utils'; +import { SYNTHETICS_ALERT_RULE_TYPES } from '@kbn/rule-data-utils'; import { syntheticsRuleFieldMap } from '../../../common/rules/synthetics_rule_field_map'; import { SyntheticsPluginsSetupDependencies, SyntheticsServerSetup } from '../../types'; import { DOWN_LABEL, getMonitorAlertDocument, getMonitorSummary } from './message_utils'; @@ -28,10 +29,7 @@ import { import { OverviewStatus } from '../../../common/runtime_types'; import { StatusRuleExecutor } from './status_rule_executor'; import { StatusRulePramsSchema, StatusRuleParams } from '../../../common/rules/status_rule'; -import { - MONITOR_STATUS, - SYNTHETICS_ALERT_RULE_TYPES, -} from '../../../common/constants/synthetics_alerts'; +import { MONITOR_STATUS } from '../../../common/constants/synthetics_alerts'; import { setRecoveredAlertsContext, updateState, diff --git a/x-pack/plugins/observability_solution/synthetics/server/alert_rules/tls_rule/tls_rule.ts b/x-pack/plugins/observability_solution/synthetics/server/alert_rules/tls_rule/tls_rule.ts index b251e950a5d4a8..68082854b9f7bb 100644 --- a/x-pack/plugins/observability_solution/synthetics/server/alert_rules/tls_rule/tls_rule.ts +++ b/x-pack/plugins/observability_solution/synthetics/server/alert_rules/tls_rule/tls_rule.ts @@ -10,7 +10,7 @@ import { ActionGroupIdsOf } from '@kbn/alerting-plugin/common'; import { GetViewInAppRelativeUrlFnOpts } from '@kbn/alerting-plugin/server'; import { createLifecycleRuleTypeFactory, IRuleDataClient } from '@kbn/rule-registry-plugin/server'; import { asyncForEach } from '@kbn/std'; -import { ALERT_REASON, ALERT_UUID } from '@kbn/rule-data-utils'; +import { ALERT_REASON, ALERT_UUID, SYNTHETICS_ALERT_RULE_TYPES } from '@kbn/rule-data-utils'; import { alertsLocatorID, AlertsLocatorParams, @@ -32,10 +32,7 @@ import { import { getCertSummary, setTLSRecoveredAlertsContext } from './message_utils'; import { SyntheticsCommonState } from '../../../common/runtime_types/alert_rules/common'; import { TLSRuleExecutor } from './tls_rule_executor'; -import { - SYNTHETICS_ALERT_RULE_TYPES, - TLS_CERTIFICATE, -} from '../../../common/constants/synthetics_alerts'; +import { TLS_CERTIFICATE } from '../../../common/constants/synthetics_alerts'; import { generateAlertMessage, SyntheticsRuleTypeAlertDefinition, updateState } from '../common'; import { ALERT_DETAILS_URL, getActionVariables } from '../action_variables'; import { SyntheticsMonitorClient } from '../../synthetics_service/synthetics_monitor/synthetics_monitor_client'; diff --git a/x-pack/plugins/observability_solution/uptime/common/constants/synthetics_alerts.ts b/x-pack/plugins/observability_solution/uptime/common/constants/synthetics_alerts.ts index 223b8909de96e8..5de01b708ea2cd 100644 --- a/x-pack/plugins/observability_solution/uptime/common/constants/synthetics_alerts.ts +++ b/x-pack/plugins/observability_solution/uptime/common/constants/synthetics_alerts.ts @@ -42,6 +42,4 @@ export const SYNTHETICS_ALERT_RULE_TYPES = { TLS: SYNTHETICS_TLS_RULE, }; -export const SYNTHETICS_RULE_TYPES = [SYNTHETICS_STATUS_RULE, SYNTHETICS_TLS_RULE]; - export const SYNTHETICS_RULE_TYPES_ALERT_CONTEXT = 'observability.uptime'; From 90a225ab87c29717645b081feb0e6ed5cbcb52a1 Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Wed, 31 Jul 2024 17:41:35 +0300 Subject: [PATCH 046/106] Fix cases --- .../case_view/components/case_view_alerts.tsx | 12 ++++---- .../system_actions/hooks/alert_index.ts | 6 ++-- .../hooks/use_alert_data_view.ts | 29 +++++++++---------- .../components/shared/alerts/constants.ts | 5 +--- .../observability/common/constants.ts | 1 - 5 files changed, 24 insertions(+), 29 deletions(-) diff --git a/x-pack/plugins/cases/public/components/case_view/components/case_view_alerts.tsx b/x-pack/plugins/cases/public/components/case_view/components/case_view_alerts.tsx index 7d98973a29f562..f44a56b609b4c6 100644 --- a/x-pack/plugins/cases/public/components/case_view/components/case_view_alerts.tsx +++ b/x-pack/plugins/cases/public/components/case_view/components/case_view_alerts.tsx @@ -8,9 +8,8 @@ import React, { useMemo } from 'react'; import { EuiFlexItem, EuiFlexGroup, EuiProgress } from '@elastic/eui'; -import type { ValidFeatureId } from '@kbn/rule-registry-plugin/common/technical_rule_data_field_names'; -import { AlertConsumers } from '@kbn/rule-registry-plugin/common/technical_rule_data_field_names'; import type { AlertsTableStateProps } from '@kbn/triggers-actions-ui-plugin/public/application/sections/alerts_table/alerts_table_state'; +import { SECURITY_SOLUTION_RULE_TYPE_IDS } from '@kbn/securitysolution-rules'; import { SECURITY_SOLUTION_OWNER } from '../../../../common/constants'; import type { CaseUI } from '../../../../common'; import { useKibana } from '../../../common/lib/kibana'; @@ -55,9 +54,10 @@ export const CaseViewAlerts = ({ caseData, onAlertsTableLoaded }: CaseViewAlerts alertsTableConfigurationRegistry: triggersActionsUi.alertsTableConfigurationRegistry, configurationId: configId, id: `case-details-alerts-${caseData.owner}`, - featureIds: (caseData.owner === SECURITY_SOLUTION_OWNER - ? [AlertConsumers.SIEM] - : alertData?.featureIds ?? []) as ValidFeatureId[], + ruleTypeIds: + caseData.owner === SECURITY_SOLUTION_OWNER + ? SECURITY_SOLUTION_RULE_TYPE_IDS + : alertData?.ruleTypeIds ?? [], query: alertIdsQuery, showAlertStatusWithFlapping: caseData.owner !== SECURITY_SOLUTION_OWNER, onLoaded: onAlertsTableLoaded, @@ -66,7 +66,7 @@ export const CaseViewAlerts = ({ caseData, onAlertsTableLoaded }: CaseViewAlerts triggersActionsUi.alertsTableConfigurationRegistry, configId, caseData.owner, - alertData?.featureIds, + alertData?.ruleTypeIds, alertIdsQuery, onAlertsTableLoaded, ] diff --git a/x-pack/plugins/cases/public/components/system_actions/hooks/alert_index.ts b/x-pack/plugins/cases/public/components/system_actions/hooks/alert_index.ts index 4b5a496f226bbc..d2319a43c78b31 100644 --- a/x-pack/plugins/cases/public/components/system_actions/hooks/alert_index.ts +++ b/x-pack/plugins/cases/public/components/system_actions/hooks/alert_index.ts @@ -10,15 +10,15 @@ import type { HttpSetup } from '@kbn/core/public'; export async function fetchAlertIndexNames({ http, - features, + ruleTypeIds, }: { http: HttpSetup; - features: string; + ruleTypeIds: string; }): Promise { const { index_name: indexNamesStr = [] } = await http.get<{ index_name: string[] }>( `${BASE_RAC_ALERTS_API_PATH}/index`, { - query: { features }, + query: { ruleTypeIds }, } ); return indexNamesStr; diff --git a/x-pack/plugins/cases/public/components/system_actions/hooks/use_alert_data_view.ts b/x-pack/plugins/cases/public/components/system_actions/hooks/use_alert_data_view.ts index 863b07949af9db..a396c023617add 100644 --- a/x-pack/plugins/cases/public/components/system_actions/hooks/use_alert_data_view.ts +++ b/x-pack/plugins/cases/public/components/system_actions/hooks/use_alert_data_view.ts @@ -9,7 +9,7 @@ import { i18n } from '@kbn/i18n'; import type { DataView } from '@kbn/data-views-plugin/common'; import { useKibana } from '@kbn/kibana-react-plugin/public'; import type { ValidFeatureId } from '@kbn/rule-data-utils'; -import { AlertConsumers } from '@kbn/rule-data-utils'; +import { isSiemRuleType } from '@kbn/rule-data-utils'; import { useEffect, useMemo, useState } from 'react'; import { useQuery } from '@tanstack/react-query'; import type { TriggersAndActionsUiServices } from '@kbn/triggers-actions-ui-plugin/public'; @@ -21,28 +21,27 @@ export interface UserAlertDataViews { loading: boolean; } -export function useAlertDataViews(featureIds: ValidFeatureId[]): UserAlertDataViews { +export function useAlertDataViews(ruleTypeIds: ValidFeatureId[]): UserAlertDataViews { const { http, data: dataService, notifications: { toasts }, } = useKibana().services; const [dataViews, setDataViews] = useState(undefined); - const features = featureIds.sort().join(','); - const isOnlySecurity = featureIds.length === 1 && featureIds.includes(AlertConsumers.SIEM); - - const hasSecurityAndO11yFeatureIds = - featureIds.length > 1 && featureIds.includes(AlertConsumers.SIEM); + const ruleTypes = ruleTypeIds.sort().join(','); + const hasSecurity = ruleTypeIds.some(isSiemRuleType); + const isOnlySecurity = ruleTypeIds.length === 1 && hasSecurity; + const hasSecurityAndO11yFeatureIds = ruleTypeIds.length > 1 && hasSecurity; const hasNoSecuritySolution = - featureIds.length > 0 && !isOnlySecurity && !hasSecurityAndO11yFeatureIds; + ruleTypeIds.length > 0 && !isOnlySecurity && !hasSecurityAndO11yFeatureIds; const queryIndexNameFn = () => { - return fetchAlertIndexNames({ http, features }); + return fetchAlertIndexNames({ http, ruleTypeIds: ruleTypes }); }; const queryAlertFieldsFn = () => { - return fetchAlertFields({ http, featureIds }); + return fetchAlertFields({ http, ruleTypeIds }); }; const onErrorFn = () => { @@ -59,11 +58,11 @@ export function useAlertDataViews(featureIds: ValidFeatureId[]): UserAlertDataVi isInitialLoading: isIndexNameInitialLoading, isLoading: isIndexNameLoading, } = useQuery({ - queryKey: ['loadAlertIndexNames', features], + queryKey: ['loadAlertIndexNames', ruleTypeIds], queryFn: queryIndexNameFn, onError: onErrorFn, refetchOnWindowFocus: false, - enabled: featureIds.length > 0 && !hasSecurityAndO11yFeatureIds, + enabled: ruleTypeIds.length > 0 && !hasSecurityAndO11yFeatureIds, }); const { @@ -72,7 +71,7 @@ export function useAlertDataViews(featureIds: ValidFeatureId[]): UserAlertDataVi isInitialLoading: isAlertFieldsInitialLoading, isLoading: isAlertFieldsLoading, } = useQuery({ - queryKey: ['loadAlertFields', features], + queryKey: ['loadAlertFields', ruleTypeIds], queryFn: queryAlertFieldsFn, onError: onErrorFn, refetchOnWindowFocus: false, @@ -138,7 +137,7 @@ export function useAlertDataViews(featureIds: ValidFeatureId[]): UserAlertDataVi () => ({ dataViews, loading: - featureIds.length === 0 || hasSecurityAndO11yFeatureIds + ruleTypeIds.length === 0 || hasSecurityAndO11yFeatureIds ? false : isOnlySecurity ? isIndexNameInitialLoading || isIndexNameLoading @@ -149,7 +148,7 @@ export function useAlertDataViews(featureIds: ValidFeatureId[]): UserAlertDataVi }), [ dataViews, - featureIds.length, + ruleTypeIds.length, hasSecurityAndO11yFeatureIds, isOnlySecurity, isIndexNameInitialLoading, diff --git a/x-pack/plugins/observability_solution/infra/public/components/shared/alerts/constants.ts b/x-pack/plugins/observability_solution/infra/public/components/shared/alerts/constants.ts index 21251748ca77ec..1719a58af61ef2 100644 --- a/x-pack/plugins/observability_solution/infra/public/components/shared/alerts/constants.ts +++ b/x-pack/plugins/observability_solution/infra/public/components/shared/alerts/constants.ts @@ -89,7 +89,4 @@ export const ALERTS_PER_PAGE = 10; export const ALERTS_TABLE_ID = 'xpack.infra.hosts.alerts.table'; export const INFRA_ALERT_FEATURE_ID = 'infrastructure'; -export const infraAlertFeatureIds: ValidFeatureId[] = [ - AlertConsumers.INFRASTRUCTURE, - AlertConsumers.ALERTS, -]; +export const infraAlertFeatureIds: ValidFeatureId[] = [AlertConsumers.INFRASTRUCTURE]; diff --git a/x-pack/plugins/observability_solution/observability/common/constants.ts b/x-pack/plugins/observability_solution/observability/common/constants.ts index a45e421f6a8e4f..0286e4bef08257 100644 --- a/x-pack/plugins/observability_solution/observability/common/constants.ts +++ b/x-pack/plugins/observability_solution/observability/common/constants.ts @@ -20,7 +20,6 @@ export const observabilityAlertFeatureIds: ValidFeatureId[] = [ AlertConsumers.UPTIME, AlertConsumers.SLO, AlertConsumers.OBSERVABILITY, - AlertConsumers.ALERTS, ]; export const observabilityRuleCreationValidConsumers: RuleCreationValidConsumer[] = [ From 4efcced7bec0a8f0e941c3a8fdee13a82d16f33c Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Thu, 1 Aug 2024 12:43:18 +0300 Subject: [PATCH 047/106] Fix types and tests --- .../hooks/use_fetch_alerts_fields_query.ts | 2 +- .../methods/find/find_backfill.test.ts | 91 ++++++++++++------- .../schedule/schedule_backfill.test.ts | 13 ++- .../infra/common/alerting/metrics/types.ts | 1 + .../common/constants/synthetics_alerts.ts | 2 + .../synthetics/server/feature.ts | 5 +- .../server/alert_data_client/alerts_client.ts | 1 + .../tests/get_aad_fields.test.ts | 4 +- .../routes/__mocks__/request_responses.ts | 2 +- .../server/routes/get_alert_index.test.ts | 4 +- .../alerts_table/alerts_table_state.test.tsx | 34 ++++--- 11 files changed, 96 insertions(+), 63 deletions(-) diff --git a/packages/kbn-alerts-ui-shared/src/common/hooks/use_fetch_alerts_fields_query.ts b/packages/kbn-alerts-ui-shared/src/common/hooks/use_fetch_alerts_fields_query.ts index 07b5cf24e991f2..14c7281511d411 100644 --- a/packages/kbn-alerts-ui-shared/src/common/hooks/use_fetch_alerts_fields_query.ts +++ b/packages/kbn-alerts-ui-shared/src/common/hooks/use_fetch_alerts_fields_query.ts @@ -30,7 +30,7 @@ export const useFetchAlertsFieldsQuery = ( ) => { const { ruleTypeIds } = params; - const validRuleTypeIds = ruleTypeIds.filter(isSiemRuleType); + const validRuleTypeIds = ruleTypeIds.filter((ruleTypeId) => !isSiemRuleType(ruleTypeId)); return useQuery({ queryKey: queryKeyPrefix.concat(JSON.stringify(ruleTypeIds)), diff --git a/x-pack/plugins/alerting/server/application/backfill/methods/find/find_backfill.test.ts b/x-pack/plugins/alerting/server/application/backfill/methods/find/find_backfill.test.ts index e7d4ab36449100..0fe6b50bcd23e7 100644 --- a/x-pack/plugins/alerting/server/application/backfill/methods/find/find_backfill.test.ts +++ b/x-pack/plugins/alerting/server/application/backfill/methods/find/find_backfill.test.ts @@ -239,12 +239,15 @@ describe('findBackfill()', () => { test('should successfully find backfill with no filter', async () => { const result = await rulesClient.findBackfill({ page: 1, perPage: 10 }); - expect(authorization.getFindAuthorizationFilter).toHaveBeenCalledWith('rule', { - fieldNames: { - consumer: 'ad_hoc_run_params.attributes.rule.consumer', - ruleTypeId: 'ad_hoc_run_params.attributes.rule.alertTypeId', + expect(authorization.getFindAuthorizationFilter).toHaveBeenCalledWith({ + authorizationEntity: 'rule', + filterOpts: { + fieldNames: { + consumer: 'ad_hoc_run_params.attributes.rule.consumer', + ruleTypeId: 'ad_hoc_run_params.attributes.rule.alertTypeId', + }, + type: 'kql', }, - type: 'kql', }); expect(unsecuredSavedObjectsClient.find).toHaveBeenCalledWith({ @@ -283,12 +286,15 @@ describe('findBackfill()', () => { test('should successfully find backfill with rule id', async () => { const result = await rulesClient.findBackfill({ page: 1, perPage: 10, ruleIds: 'abc' }); - expect(authorization.getFindAuthorizationFilter).toHaveBeenCalledWith('rule', { - fieldNames: { - consumer: 'ad_hoc_run_params.attributes.rule.consumer', - ruleTypeId: 'ad_hoc_run_params.attributes.rule.alertTypeId', + expect(authorization.getFindAuthorizationFilter).toHaveBeenCalledWith({ + authorizationEntity: 'rule', + filterOpts: { + fieldNames: { + consumer: 'ad_hoc_run_params.attributes.rule.consumer', + ruleTypeId: 'ad_hoc_run_params.attributes.rule.alertTypeId', + }, + type: 'kql', }, - type: 'kql', }); expect(unsecuredSavedObjectsClient.find).toHaveBeenCalledWith({ @@ -332,12 +338,15 @@ describe('findBackfill()', () => { start: '2024-03-29T02:07:55Z', }); - expect(authorization.getFindAuthorizationFilter).toHaveBeenCalledWith('rule', { - fieldNames: { - consumer: 'ad_hoc_run_params.attributes.rule.consumer', - ruleTypeId: 'ad_hoc_run_params.attributes.rule.alertTypeId', + expect(authorization.getFindAuthorizationFilter).toHaveBeenCalledWith({ + authorizationEntity: 'rule', + filterOpts: { + fieldNames: { + consumer: 'ad_hoc_run_params.attributes.rule.consumer', + ruleTypeId: 'ad_hoc_run_params.attributes.rule.alertTypeId', + }, + type: 'kql', }, - type: 'kql', }); expect(unsecuredSavedObjectsClient.find).toHaveBeenCalledWith({ @@ -395,12 +404,15 @@ describe('findBackfill()', () => { end: '2024-03-29T02:07:55Z', }); - expect(authorization.getFindAuthorizationFilter).toHaveBeenCalledWith('rule', { - fieldNames: { - consumer: 'ad_hoc_run_params.attributes.rule.consumer', - ruleTypeId: 'ad_hoc_run_params.attributes.rule.alertTypeId', + expect(authorization.getFindAuthorizationFilter).toHaveBeenCalledWith({ + authorizationEntity: 'rule', + filterOpts: { + fieldNames: { + consumer: 'ad_hoc_run_params.attributes.rule.consumer', + ruleTypeId: 'ad_hoc_run_params.attributes.rule.alertTypeId', + }, + type: 'kql', }, - type: 'kql', }); expect(unsecuredSavedObjectsClient.find).toHaveBeenCalledWith({ @@ -459,12 +471,15 @@ describe('findBackfill()', () => { end: '2024-03-29T02:07:55Z', }); - expect(authorization.getFindAuthorizationFilter).toHaveBeenCalledWith('rule', { - fieldNames: { - consumer: 'ad_hoc_run_params.attributes.rule.consumer', - ruleTypeId: 'ad_hoc_run_params.attributes.rule.alertTypeId', + expect(authorization.getFindAuthorizationFilter).toHaveBeenCalledWith({ + authorizationEntity: 'rule', + filterOpts: { + fieldNames: { + consumer: 'ad_hoc_run_params.attributes.rule.consumer', + ruleTypeId: 'ad_hoc_run_params.attributes.rule.alertTypeId', + }, + type: 'kql', }, - type: 'kql', }); expect(unsecuredSavedObjectsClient.find).toHaveBeenCalledWith({ @@ -539,12 +554,15 @@ describe('findBackfill()', () => { ruleIds: 'abc', }); - expect(authorization.getFindAuthorizationFilter).toHaveBeenCalledWith('rule', { - fieldNames: { - consumer: 'ad_hoc_run_params.attributes.rule.consumer', - ruleTypeId: 'ad_hoc_run_params.attributes.rule.alertTypeId', + expect(authorization.getFindAuthorizationFilter).toHaveBeenCalledWith({ + authorizationEntity: 'rule', + filterOpts: { + fieldNames: { + consumer: 'ad_hoc_run_params.attributes.rule.consumer', + ruleTypeId: 'ad_hoc_run_params.attributes.rule.alertTypeId', + }, + type: 'kql', }, - type: 'kql', }); expect(unsecuredSavedObjectsClient.find).toHaveBeenCalledWith({ @@ -619,12 +637,15 @@ describe('findBackfill()', () => { sortOrder: 'asc', }); - expect(authorization.getFindAuthorizationFilter).toHaveBeenCalledWith('rule', { - fieldNames: { - consumer: 'ad_hoc_run_params.attributes.rule.consumer', - ruleTypeId: 'ad_hoc_run_params.attributes.rule.alertTypeId', + expect(authorization.getFindAuthorizationFilter).toHaveBeenCalledWith({ + authorizationEntity: 'rule', + filterOpts: { + fieldNames: { + consumer: 'ad_hoc_run_params.attributes.rule.consumer', + ruleTypeId: 'ad_hoc_run_params.attributes.rule.alertTypeId', + }, + type: 'kql', }, - type: 'kql', }); expect(unsecuredSavedObjectsClient.find).toHaveBeenCalledWith({ diff --git a/x-pack/plugins/alerting/server/application/backfill/methods/schedule/schedule_backfill.test.ts b/x-pack/plugins/alerting/server/application/backfill/methods/schedule/schedule_backfill.test.ts index 7edcb26b9718e7..88f6dc8338987b 100644 --- a/x-pack/plugins/alerting/server/application/backfill/methods/schedule/schedule_backfill.test.ts +++ b/x-pack/plugins/alerting/server/application/backfill/methods/schedule/schedule_backfill.test.ts @@ -249,12 +249,15 @@ describe('scheduleBackfill()', () => { const mockData = [getMockData(), getMockData({ ruleId: '2', end: '2023-11-17T08:00:00.000Z' })]; const result = await rulesClient.scheduleBackfill(mockData); - expect(authorization.getFindAuthorizationFilter).toHaveBeenCalledWith('rule', { - fieldNames: { - consumer: 'alert.attributes.consumer', - ruleTypeId: 'alert.attributes.alertTypeId', + expect(authorization.getFindAuthorizationFilter).toHaveBeenCalledWith({ + authorizationEntity: 'rule', + filterOpts: { + fieldNames: { + consumer: 'alert.attributes.consumer', + ruleTypeId: 'alert.attributes.alertTypeId', + }, + type: 'kql', }, - type: 'kql', }); expect(unsecuredSavedObjectsClient.find).toHaveBeenCalledWith({ diff --git a/x-pack/plugins/observability_solution/infra/common/alerting/metrics/types.ts b/x-pack/plugins/observability_solution/infra/common/alerting/metrics/types.ts index bd5d6f25ac72dd..d1adb75d511346 100644 --- a/x-pack/plugins/observability_solution/infra/common/alerting/metrics/types.ts +++ b/x-pack/plugins/observability_solution/infra/common/alerting/metrics/types.ts @@ -8,6 +8,7 @@ import { TimeUnitChar } from '@kbn/observability-plugin/common/utils/formatters/ import { InventoryItemType, SnapshotMetricType } from '@kbn/metrics-data-access-plugin/common'; import { COMPARATORS } from '@kbn/alerting-comparators'; import { LEGACY_COMPARATORS } from '@kbn/observability-plugin/common/utils/convert_legacy_outside_comparator'; +export { INFRA_RULE_TYPE_IDS } from '@kbn/rule-data-utils'; import { SnapshotCustomMetricInput } from '../../http_api'; export const METRIC_THRESHOLD_ALERT_TYPE_ID = 'metrics.alert.threshold'; diff --git a/x-pack/plugins/observability_solution/synthetics/common/constants/synthetics_alerts.ts b/x-pack/plugins/observability_solution/synthetics/common/constants/synthetics_alerts.ts index 472de463897277..adb37c3fdc3ce9 100644 --- a/x-pack/plugins/observability_solution/synthetics/common/constants/synthetics_alerts.ts +++ b/x-pack/plugins/observability_solution/synthetics/common/constants/synthetics_alerts.ts @@ -8,6 +8,8 @@ import { ActionGroup } from '@kbn/alerting-plugin/common'; import { i18n } from '@kbn/i18n'; +export { SYNTHETICS_STATUS_RULE, SYNTHETICS_TLS_RULE } from '@kbn/rule-data-utils'; + export type MonitorStatusActionGroup = | ActionGroup<'xpack.synthetics.alerts.actionGroups.monitorStatus'> | ActionGroup<'xpack.synthetics.alerts.actionGroups.tls'>; diff --git a/x-pack/plugins/observability_solution/synthetics/server/feature.ts b/x-pack/plugins/observability_solution/synthetics/server/feature.ts index bc58440b5743a7..9aee9791a2fd5e 100644 --- a/x-pack/plugins/observability_solution/synthetics/server/feature.ts +++ b/x-pack/plugins/observability_solution/synthetics/server/feature.ts @@ -12,9 +12,8 @@ import { SubFeaturePrivilegeGroupType, } from '@kbn/features-plugin/common'; import { ALERTING_FEATURE_ID } from '@kbn/alerting-plugin/common'; -import { UPTIME_RULE_TYPES } from '@kbn/uptime-plugin/common/constants/uptime_alerts'; +import { UPTIME_RULE_TYPE_IDS, SYNTHETICS_RULE_TYPE_IDS } from '@kbn/rule-data-utils'; import { syntheticsMonitorType, syntheticsParamType } from '../common/types/saved_objects'; -import { SYNTHETICS_RULE_TYPES } from '../common/constants/synthetics_alerts'; import { privateLocationsSavedObjectName } from '../common/saved_objects/private_locations'; import { PLUGIN } from '../common/constants/plugin'; import { @@ -23,7 +22,7 @@ import { } from './saved_objects/synthetics_settings'; import { syntheticsApiKeyObjectType } from './saved_objects/service_api_key'; -const ruleTypes = [...UPTIME_RULE_TYPES, ...SYNTHETICS_RULE_TYPES]; +const ruleTypes = [...UPTIME_RULE_TYPE_IDS, ...SYNTHETICS_RULE_TYPE_IDS]; const alertingFeatures = ruleTypes.map((ruleTypeId) => ({ ruleTypeId, diff --git a/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts b/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts index 4803b6952b9e1e..1ae937925d875a 100644 --- a/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts +++ b/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts @@ -1201,6 +1201,7 @@ export class AlertsClient { if (isSiemRuleType(ruleTypeId)) { throw Boom.badRequest(`Security solution rule type is not supported`); } + const indices = await this.getAuthorizedAlertsIndices([ruleTypeId]); const indexPatternsFetcherAsInternalUser = new IndexPatternsFetcher(this.esClient); const { fields = [] } = await indexPatternsFetcherAsInternalUser.getFieldsForWildcard({ diff --git a/x-pack/plugins/rule_registry/server/alert_data_client/tests/get_aad_fields.test.ts b/x-pack/plugins/rule_registry/server/alert_data_client/tests/get_aad_fields.test.ts index 777b3d3e26742a..0a7b11e2be9b00 100644 --- a/x-pack/plugins/rule_registry/server/alert_data_client/tests/get_aad_fields.test.ts +++ b/x-pack/plugins/rule_registry/server/alert_data_client/tests/get_aad_fields.test.ts @@ -5,7 +5,6 @@ * 2.0. */ -import { AlertConsumers } from '@kbn/rule-data-utils'; import { AlertsClient, ConstructorOptions } from '../alerts_client'; import { loggingSystemMock } from '@kbn/core/server/mocks'; import { elasticsearchClientMock } from '@kbn/core-elasticsearch-client-server-mocks'; @@ -38,13 +37,12 @@ beforeEach(() => { describe('getAADFields()', () => { test('should throw an error when a rule type belong to security solution', async () => { getRuleTypeMock.mockImplementation(() => ({ - producer: AlertConsumers.SIEM, fieldsForAAD: [], })); const alertsClient = new AlertsClient(alertsClientParams); await expect( - alertsClient.getAADFields({ ruleTypeId: 'security-type' }) + alertsClient.getAADFields({ ruleTypeId: 'siem.esqlRule' }) ).rejects.toThrowErrorMatchingInlineSnapshot(`"Security solution rule type is not supported"`); }); }); diff --git a/x-pack/plugins/rule_registry/server/routes/__mocks__/request_responses.ts b/x-pack/plugins/rule_registry/server/routes/__mocks__/request_responses.ts index 2f7ae082181d20..e884b8f842000a 100644 --- a/x-pack/plugins/rule_registry/server/routes/__mocks__/request_responses.ts +++ b/x-pack/plugins/rule_registry/server/routes/__mocks__/request_responses.ts @@ -12,7 +12,7 @@ export const getReadIndexRequest = () => requestMock.create({ method: 'get', path: `${BASE_RAC_ALERTS_API_PATH}/index`, - query: { features: 'siem' }, + query: { ruleTypeIds: 'siem' }, }); export const getReadRequest = () => diff --git a/x-pack/plugins/rule_registry/server/routes/get_alert_index.test.ts b/x-pack/plugins/rule_registry/server/routes/get_alert_index.test.ts index b8ef01847d8eac..fd1b3afbb0d5e1 100644 --- a/x-pack/plugins/rule_registry/server/routes/get_alert_index.test.ts +++ b/x-pack/plugins/rule_registry/server/routes/get_alert_index.test.ts @@ -38,12 +38,12 @@ describe('getAlertsIndexRoute', () => { requestMock.create({ method: 'get', path: `${BASE_RAC_ALERTS_API_PATH}/index`, - query: { features: 4 }, + query: { ruleTypeIds: 4 }, }), context ) ).rejects.toThrowErrorMatchingInlineSnapshot( - `"Request was rejected with message: 'Invalid value \\"4\\" supplied to \\"features\\"'"` + `"Request was rejected with message: 'Invalid value \\"4\\" supplied to \\"ruleTypeIds\\"'"` ); }); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/alerts_table_state.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/alerts_table_state.test.tsx index 2857b54f057537..b381461b7467e0 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/alerts_table_state.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/alerts_table_state.test.tsx @@ -339,7 +339,7 @@ const browserFields: BrowserFields = { }, }; -jest.mocked(fetchAlertsFields).mockResolvedValue({ browserFields, fields: [] }); +const fetchAlertsFieldsMock = fetchAlertsFields as jest.Mock; const queryClient = new QueryClient({ defaultOptions: { @@ -414,6 +414,8 @@ describe('AlertsTableState', () => { data: maintenanceWindowsMap, isFetching: false, }); + + fetchAlertsFieldsMock.mockResolvedValue({ browserFields, fields: [] }); }); describe('Cases', () => { @@ -832,6 +834,8 @@ describe('AlertsTableState', () => { data: new Map(), isFetching: false, }); + + fetchAlertsFieldsMock.mockResolvedValue({ browserFields, fields: [] }); }); it('should show field browser', async () => { @@ -840,13 +844,13 @@ describe('AlertsTableState', () => { }); it('should remove an already existing element when selected', async () => { - const { getByTestId, queryByTestId } = render(); + const { findByTestId, queryByTestId } = render(); expect(queryByTestId(`dataGridHeaderCell-${AlertsField.name}`)).not.toBe(null); - fireEvent.click(getByTestId('show-field-browser')); - const fieldCheckbox = getByTestId(`field-${AlertsField.name}-checkbox`); + fireEvent.click(await findByTestId('show-field-browser')); + const fieldCheckbox = await findByTestId(`field-${AlertsField.name}-checkbox`); fireEvent.click(fieldCheckbox); - fireEvent.click(getByTestId('close')); + fireEvent.click(await findByTestId('close')); await waitFor(() => { expect(queryByTestId(`dataGridHeaderCell-${AlertsField.name}`)).toBe(null); @@ -872,13 +876,15 @@ describe('AlertsTableState', () => { set: jest.fn(), })); - const { getByTestId, queryByTestId } = render(); + const { getByTestId, findByTestId, queryByTestId } = render( + + ); expect(queryByTestId(`dataGridHeaderCell-${AlertsField.name}`)).toBe(null); - fireEvent.click(getByTestId('show-field-browser')); - const fieldCheckbox = getByTestId(`field-${AlertsField.name}-checkbox`); + fireEvent.click(await findByTestId('show-field-browser')); + const fieldCheckbox = await findByTestId(`field-${AlertsField.name}-checkbox`); fireEvent.click(fieldCheckbox); - fireEvent.click(getByTestId('close')); + fireEvent.click(await findByTestId('close')); await waitFor(() => { expect(queryByTestId(`dataGridHeaderCell-${AlertsField.name}`)).not.toBe(null); @@ -891,13 +897,15 @@ describe('AlertsTableState', () => { }); it('should insert a new field as column when its not a default one', async () => { - const { getByTestId, queryByTestId } = render(); + const { getByTestId, findByTestId, queryByTestId } = render( + + ); expect(queryByTestId(`dataGridHeaderCell-${AlertsField.uuid}`)).toBe(null); - fireEvent.click(getByTestId('show-field-browser')); - const fieldCheckbox = getByTestId(`field-${AlertsField.uuid}-checkbox`); + fireEvent.click(await findByTestId('show-field-browser')); + const fieldCheckbox = await findByTestId(`field-${AlertsField.uuid}-checkbox`); fireEvent.click(fieldCheckbox); - fireEvent.click(getByTestId('close')); + fireEvent.click(await findByTestId('close')); await waitFor(() => { expect(queryByTestId(`dataGridHeaderCell-${AlertsField.uuid}`)).not.toBe(null); From 11d50be32ee5f8e3c260d6ef23bcbe1734e0cd6e Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Thu, 1 Aug 2024 15:15:59 +0300 Subject: [PATCH 048/106] Fix rule registry integration tests --- ...t_browser_fields_by_rule_type_ids.test.ts} | 2 +- ...=> get_browser_fields_by_rule_type_ids.ts} | 6 +- .../rule_registry/server/routes/index.ts | 2 +- .../observability/alerts/data.json | 1520 +++ .../security_solution/alerts/8.1.0/data.json | 8186 +++++++++++++++++ .../tests/basic/find_alerts.ts | 14 +- .../tests/basic/get_alert_summary.ts | 6 +- .../tests/basic/get_alerts_index.ts | 9 +- ...=> get_browser_fields_by_rule_type_ids.ts} | 52 +- .../security_and_spaces/tests/basic/index.ts | 2 +- .../tests/basic/search_strategy.ts | 101 +- .../tests/trial/get_alerts.ts | 5 + 12 files changed, 9830 insertions(+), 75 deletions(-) rename x-pack/plugins/rule_registry/server/routes/{get_browser_fields_by_feature_id.test.ts => get_browser_fields_by_rule_type_ids.test.ts} (99%) rename x-pack/plugins/rule_registry/server/routes/{get_browser_fields_by_feature_id.ts => get_browser_fields_by_rule_type_ids.ts} (91%) create mode 100644 x-pack/test/functional/es_archives/observability/alerts/data.json create mode 100644 x-pack/test/functional/es_archives/security_solution/alerts/8.1.0/data.json rename x-pack/test/rule_registry/security_and_spaces/tests/basic/{get_browser_fields_by_feature_id.ts => get_browser_fields_by_rule_type_ids.ts} (73%) diff --git a/x-pack/plugins/rule_registry/server/routes/get_browser_fields_by_feature_id.test.ts b/x-pack/plugins/rule_registry/server/routes/get_browser_fields_by_rule_type_ids.test.ts similarity index 99% rename from x-pack/plugins/rule_registry/server/routes/get_browser_fields_by_feature_id.test.ts rename to x-pack/plugins/rule_registry/server/routes/get_browser_fields_by_rule_type_ids.test.ts index b37ee0e18afae5..06bc7ee9967153 100644 --- a/x-pack/plugins/rule_registry/server/routes/get_browser_fields_by_feature_id.test.ts +++ b/x-pack/plugins/rule_registry/server/routes/get_browser_fields_by_rule_type_ids.test.ts @@ -6,7 +6,7 @@ */ import { BASE_RAC_ALERTS_API_PATH } from '../../common/constants'; -import { getBrowserFieldsByFeatureId } from './get_browser_fields_by_feature_id'; +import { getBrowserFieldsByFeatureId } from './get_browser_fields_by_rule_type_ids'; import { requestContextMock } from './__mocks__/request_context'; import { getO11yBrowserFields } from './__mocks__/request_responses'; import { requestMock, serverMock } from './__mocks__/server'; diff --git a/x-pack/plugins/rule_registry/server/routes/get_browser_fields_by_feature_id.ts b/x-pack/plugins/rule_registry/server/routes/get_browser_fields_by_rule_type_ids.ts similarity index 91% rename from x-pack/plugins/rule_registry/server/routes/get_browser_fields_by_feature_id.ts rename to x-pack/plugins/rule_registry/server/routes/get_browser_fields_by_rule_type_ids.ts index e6b39529d359ab..3347d7d0c39f5d 100644 --- a/x-pack/plugins/rule_registry/server/routes/get_browser_fields_by_feature_id.ts +++ b/x-pack/plugins/rule_registry/server/routes/get_browser_fields_by_rule_type_ids.ts @@ -22,7 +22,7 @@ export const getBrowserFieldsByFeatureId = (router: IRouter !isSiemRuleType(ruleTypeId)); + const onlyO11yRuleTypeIds = ( + Array.isArray(ruleTypeIds) ? ruleTypeIds : [ruleTypeIds] + ).filter((ruleTypeId) => !isSiemRuleType(ruleTypeId)); const o11yIndices = (onlyO11yRuleTypeIds diff --git a/x-pack/plugins/rule_registry/server/routes/index.ts b/x-pack/plugins/rule_registry/server/routes/index.ts index 9169ded668cb32..72ecfc4c9b8ef6 100644 --- a/x-pack/plugins/rule_registry/server/routes/index.ts +++ b/x-pack/plugins/rule_registry/server/routes/index.ts @@ -13,7 +13,7 @@ import { updateAlertByIdRoute } from './update_alert_by_id'; import { getAlertsIndexRoute } from './get_alert_index'; import { bulkUpdateAlertsRoute } from './bulk_update_alerts'; import { findAlertsByQueryRoute } from './find'; -import { getBrowserFieldsByFeatureId } from './get_browser_fields_by_feature_id'; +import { getBrowserFieldsByFeatureId } from './get_browser_fields_by_rule_type_ids'; import { getAlertSummaryRoute } from './get_alert_summary'; import { getAADFieldsByRuleType } from './get_aad_fields_by_rule_type'; diff --git a/x-pack/test/functional/es_archives/observability/alerts/data.json b/x-pack/test/functional/es_archives/observability/alerts/data.json new file mode 100644 index 00000000000000..b2df5530b21a4f --- /dev/null +++ b/x-pack/test/functional/es_archives/observability/alerts/data.json @@ -0,0 +1,1520 @@ +{ + "type": "doc", + "value": { + "id": "8b75bfe9-c2f5-47e9-bac6-b082dd9c9e93", + "index": ".internal.alerts-observability.apm.alerts-default-000001", + "source": { + "@timestamp": "2021-10-19T15:20:38.749Z", + "event.action": "active", + "event.kind": "signal", + "kibana.alert.duration.us": 1197194000, + "kibana.alert.evaluation.threshold": 5, + "kibana.alert.evaluation.value": 30.727896995708154, + "kibana.alert.instance.id": "apm.transaction_error_rate_elastic-co-frontend_http-request_https://www.elastic.co", + "kibana.alert.reason": "Failed transactions rate is greater than 5.0% (current value is 31%) for elastic-co-frontend", + "kibana.alert.rule.category": "Failed transaction rate threshold", + "kibana.alert.rule.consumer": "alerts", + "kibana.alert.rule.name": "APM Failed Transaction Rate (one)", + "kibana.alert.rule.producer": "apm", + "kibana.alert.rule.rule_type_id": "apm.transaction_error_rate", + "kibana.alert.rule.uuid": "521bd1a0-30ed-11ec-9819-c5cd0facebad", + "kibana.alert.start": "2021-10-19T15:00:41.555Z", + "kibana.alert.status": "active", + "kibana.alert.time_range": { + "gte": "2021-10-19T15:00:41.555Z" + }, + "kibana.alert.uuid": "8b75bfe9-c2f5-47e9-bac6-b082dd9c9e93", + "kibana.alert.workflow_status": "open", + "kibana.space_ids": [ + "default" + ], + "kibana.version": "8.0.0", + "processor.event": "transaction", + "service.environment": "https://www.elastic.co", + "service.name": "elastic-co-frontend", + "tags": [], + "transaction.type": "http-request" + } + } +} + +{ + "type": "doc", + "value": { + "id": "4c87bd11-ff31-4a05-8a04-833e2da94858", + "index": ".internal.alerts-observability.apm.alerts-default-000001", + "source": { + "@timestamp": "2021-10-19T15:20:38.749Z", + "event.action": "active", + "event.kind": "signal", + "kibana.alert.duration.us": 1197194000, + "kibana.alert.evaluation.threshold": 5, + "kibana.alert.evaluation.value": 34.902337495997436, + "kibana.alert.instance.id": "apm.transaction_error_rate_opbeans-python_celery_production", + "kibana.alert.reason": "Failed transactions rate is greater than 5.0% (current value is 35%) for opbeans-python", + "kibana.alert.rule.category": "Failed transaction rate threshold", + "kibana.alert.rule.consumer": "alerts", + "kibana.alert.rule.name": "APM Failed Transaction Rate (one)", + "kibana.alert.rule.producer": "apm", + "kibana.alert.rule.rule_type_id": "apm.transaction_error_rate", + "kibana.alert.rule.uuid": "521bd1a0-30ed-11ec-9819-c5cd0facebad", + "kibana.alert.start": "2021-10-19T15:00:41.555Z", + "kibana.alert.status": "active", + "kibana.alert.time_range": { + "gte": "2021-10-19T15:00:41.555Z" + }, + "kibana.alert.uuid": "4c87bd11-ff31-4a05-8a04-833e2da94858", + "kibana.alert.workflow_status": "acknowledged", + "kibana.space_ids": [ + "default" + ], + "kibana.version": "8.0.0", + "processor.event": "transaction", + "service.environment": "production", + "service.name": "opbeans-python", + "tags": [], + "transaction.type": "celery" + } + } +} + +{ + "type": "doc", + "value": { + "id": "6a348681-d354-454f-a5dd-ddfff406c982", + "index": ".internal.alerts-observability.apm.alerts-default-000001", + "source": { + "@timestamp": "2021-10-19T15:20:38.749Z", + "event.action": "active", + "event.kind": "signal", + "kibana.alert.duration.us": 1197194000, + "kibana.alert.evaluation.threshold": 5, + "kibana.alert.evaluation.value": 10, + "kibana.alert.instance.id": "apm.transaction_error_rate_opbeans-java_request_production", + "kibana.alert.reason": "Failed transactions rate is greater than 5.0% (current value is 10%) for opbeans-java", + "kibana.alert.rule.category": "Failed transaction rate threshold", + "kibana.alert.rule.consumer": "alerts", + "kibana.alert.rule.name": "APM Failed Transaction Rate (one)", + "kibana.alert.rule.producer": "apm", + "kibana.alert.rule.rule_type_id": "apm.transaction_error_rate", + "kibana.alert.rule.uuid": "521bd1a0-30ed-11ec-9819-c5cd0facebad", + "kibana.alert.start": "2021-10-19T15:00:41.555Z", + "kibana.alert.status": "active", + "kibana.alert.time_range": { + "gte": "2021-10-19T15:00:41.555Z" + }, + "kibana.alert.uuid": "6a348681-d354-454f-a5dd-ddfff406c982", + "kibana.alert.workflow_status": "open", + "kibana.space_ids": [ + "default" + ], + "kibana.version": "8.0.0", + "processor.event": "transaction", + "service.environment": "production", + "service.name": "opbeans-java", + "tags": [], + "transaction.type": "request" + } + } +} + +{ + "type": "doc", + "value": { + "id": "32c8f6b9-bddf-4922-875e-ddd374a94676", + "index": ".internal.alerts-observability.apm.alerts-default-000001", + "source": { + "@timestamp": "2021-10-19T15:20:38.749Z", + "event.action": "active", + "event.kind": "signal", + "kibana.alert.duration.us": 1197194000, + "kibana.alert.evaluation.threshold": 5, + "kibana.alert.evaluation.value": 100, + "kibana.alert.instance.id": "apm.transaction_error_rate_elastic-co-frontend_http-request_http://archivebox.veda.dragonsden.jpalcala.com", + "kibana.alert.reason": "Failed transactions rate is greater than 5.0% (current value is 100%) for elastic-co-frontend", + "kibana.alert.rule.category": "Failed transaction rate threshold", + "kibana.alert.rule.consumer": "alerts", + "kibana.alert.rule.name": "APM Failed Transaction Rate (one)", + "kibana.alert.rule.producer": "apm", + "kibana.alert.rule.rule_type_id": "apm.transaction_error_rate", + "kibana.alert.rule.uuid": "521bd1a0-30ed-11ec-9819-c5cd0facebad", + "kibana.alert.start": "2021-10-19T15:00:41.555Z", + "kibana.alert.status": "active", + "kibana.alert.time_range": { + "gte": "2021-10-19T15:00:41.555Z" + }, + "kibana.alert.uuid": "32c8f6b9-bddf-4922-875e-ddd374a94676", + "kibana.alert.workflow_status": "open", + "kibana.space_ids": [ + "default" + ], + "kibana.version": "8.0.0", + "processor.event": "transaction", + "service.environment": "http://archivebox.veda.dragonsden.jpalcala.com", + "service.name": "elastic-co-frontend", + "tags": [], + "transaction.type": "http-request" + } + } +} + +{ + "type": "doc", + "value": { + "id": "c2e7e50e-e421-4a75-a22d-193e1dce87fa", + "index": ".internal.alerts-observability.apm.alerts-default-000001", + "source": { + "@timestamp": "2021-10-19T15:20:38.749Z", + "event.action": "active", + "event.kind": "signal", + "kibana.alert.duration.us": 1197194000, + "kibana.alert.evaluation.threshold": 5, + "kibana.alert.evaluation.value": 42.5531914893617, + "kibana.alert.instance.id": "apm.transaction_error_rate_elastic-co-frontend_http-request_http://localhost:3100", + "kibana.alert.reason": "Failed transactions rate is greater than 5.0% (current value is 43%) for elastic-co-frontend", + "kibana.alert.rule.category": "Failed transaction rate threshold", + "kibana.alert.rule.consumer": "alerts", + "kibana.alert.rule.name": "APM Failed Transaction Rate (one)", + "kibana.alert.rule.producer": "apm", + "kibana.alert.rule.rule_type_id": "apm.transaction_error_rate", + "kibana.alert.rule.uuid": "521bd1a0-30ed-11ec-9819-c5cd0facebad", + "kibana.alert.start": "2021-10-19T15:00:41.555Z", + "kibana.alert.status": "active", + "kibana.alert.time_range": { + "gte": "2021-10-19T15:00:41.555Z" + }, + "kibana.alert.uuid": "c2e7e50e-e421-4a75-a22d-193e1dce87fa", + "kibana.alert.workflow_status": "open", + "kibana.space_ids": [ + "default" + ], + "kibana.version": "8.0.0", + "processor.event": "transaction", + "service.environment": "http://localhost:3100", + "service.name": "elastic-co-frontend", + "tags": [], + "transaction.type": "http-request" + } + } +} + +{ + "type": "doc", + "value": { + "id": "d8c4832a-369b-439d-abe0-c1243ef89368", + "index": ".internal.alerts-observability.apm.alerts-default-000001", + "source": { + "@timestamp": "2021-10-19T15:20:38.749Z", + "event.action": "active", + "event.kind": "signal", + "kibana.alert.duration.us": 1197194000, + "kibana.alert.evaluation.threshold": 5, + "kibana.alert.evaluation.value": 16, + "kibana.alert.instance.id": "apm.transaction_error_rate_elastic-co-frontend_http-request_http://192.168.1.217:3100", + "kibana.alert.reason": "Failed transactions rate is greater than 5.0% (current value is 16%) for elastic-co-frontend", + "kibana.alert.rule.category": "Failed transaction rate threshold", + "kibana.alert.rule.consumer": "alerts", + "kibana.alert.rule.name": "APM Failed Transaction Rate (one)", + "kibana.alert.rule.producer": "apm", + "kibana.alert.rule.rule_type_id": "apm.transaction_error_rate", + "kibana.alert.rule.uuid": "521bd1a0-30ed-11ec-9819-c5cd0facebad", + "kibana.alert.start": "2021-10-19T15:00:41.555Z", + "kibana.alert.status": "active", + "kibana.alert.time_range": { + "gte": "2021-10-19T15:00:41.555Z" + }, + "kibana.alert.uuid": "d8c4832a-369b-439d-abe0-c1243ef89368", + "kibana.alert.workflow_status": "open", + "kibana.space_ids": [ + "default" + ], + "kibana.version": "8.0.0", + "processor.event": "transaction", + "service.environment": "http://192.168.1.217:3100", + "service.name": "elastic-co-frontend", + "tags": [], + "transaction.type": "http-request" + } + } +} + +{ + "type": "doc", + "value": { + "id": "2fbe40e9-511a-40b1-ac59-f6c4d3d1ce23", + "index": ".internal.alerts-observability.apm.alerts-default-000001", + "source": { + "@timestamp": "2021-10-19T15:18:05.741Z", + "event.action": "close", + "event.kind": "signal", + "kibana.alert.duration.us": 315091000, + "kibana.alert.end": "2021-10-19T15:18:05.741Z", + "kibana.alert.evaluation.threshold": 25, + "kibana.alert.evaluation.value": 41, + "kibana.alert.instance.id": "apm.error_rate_elastic-co-frontend_https://www.elastic.co", + "kibana.alert.reason": "Error count is greater than 25 (current value is 41) for elastic-co-frontend", + "kibana.alert.rule.category": "Error count threshold", + "kibana.alert.rule.consumer": "alerts", + "kibana.alert.rule.name": "APM Error Count (one)", + "kibana.alert.rule.producer": "apm", + "kibana.alert.rule.rule_type_id": "apm.error_rate", + "kibana.alert.rule.uuid": "d20dfd30-30ec-11ec-9819-c5cd0facebad", + "kibana.alert.start": "2021-10-19T15:12:50.650Z", + "kibana.alert.status": "recovered", + "kibana.alert.time_range": { + "gte": "2021-10-19T15:12:50.650Z", + "lte": "2021-10-19T15:18:05.741Z" + }, + "kibana.alert.uuid": "2fbe40e9-511a-40b1-ac59-f6c4d3d1ce23", + "kibana.alert.workflow_status": "open", + "kibana.space_ids": [ + "default" + ], + "kibana.version": "8.0.0", + "processor.event": [ + "error" + ], + "service.environment": [ + "https://www.elastic.co" + ], + "service.name": [ + "elastic-co-frontend" + ], + "tags": [] + } + } +} + +{ + "type": "doc", + "value": { + "id": "be33de56-3d36-420c-af95-4e88b02fcc69", + "index": ".internal.alerts-observability.apm.alerts-default-000001", + "source": { + "@timestamp": "2021-10-19T15:08:38.581Z", + "event.action": "close", + "event.kind": "signal", + "kibana.alert.duration.us": 378012000, + "kibana.alert.end": "2021-10-19T15:08:38.581Z", + "kibana.alert.evaluation.threshold": 25, + "kibana.alert.evaluation.value": 27, + "kibana.alert.instance.id": "apm.error_rate_elastic-co-frontend_https://www.elastic.co", + "kibana.alert.reason": "Error count is greater than 25 (current value is 27) for elastic-co-frontend", + "kibana.alert.rule.category": "Error count threshold", + "kibana.alert.rule.consumer": "alerts", + "kibana.alert.rule.name": "APM Error Count (one)", + "kibana.alert.rule.producer": "apm", + "kibana.alert.rule.rule_type_id": "apm.error_rate", + "kibana.alert.rule.uuid": "d20dfd30-30ec-11ec-9819-c5cd0facebad", + "kibana.alert.start": "2021-10-19T15:02:20.569Z", + "kibana.alert.status": "recovered", + "kibana.alert.time_range": { + "gte": "2021-10-19T15:02:20.569Z", + "lte": "2021-10-19T15:08:38.581Z" + }, + "kibana.alert.uuid": "be33de56-3d36-420c-af95-4e88b02fcc69", + "kibana.alert.workflow_status": "open", + "kibana.space_ids": [ + "default" + ], + "kibana.version": "8.0.0", + "processor.event": [ + "error" + ], + "service.environment": [ + "https://www.elastic.co" + ], + "service.name": [ + "elastic-co-frontend" + ], + "tags": [] + } + } +} + +{ + "type": "doc", + "value": { + "id": "779d10e6-d858-434a-be7a-067a6ab1e5e3", + "index": ".internal.alerts-observability.apm.alerts-default-000001", + "source": { + "@timestamp": "2021-10-19T15:00:14.550Z", + "event.action": "close", + "event.kind": "signal", + "kibana.alert.duration.us": 126011000, + "kibana.alert.end": "2021-10-19T15:00:14.550Z", + "kibana.alert.evaluation.threshold": 25, + "kibana.alert.evaluation.value": 26, + "kibana.alert.instance.id": "apm.error_rate_elastic-co-frontend_https://www.elastic.co", + "kibana.alert.reason": "Error count is greater than 25 (current value is 26) for elastic-co-frontend", + "kibana.alert.rule.category": "Error count threshold", + "kibana.alert.rule.consumer": "alerts", + "kibana.alert.rule.name": "APM Error Count (one)", + "kibana.alert.rule.producer": "apm", + "kibana.alert.rule.rule_type_id": "apm.error_rate", + "kibana.alert.rule.uuid": "d20dfd30-30ec-11ec-9819-c5cd0facebad", + "kibana.alert.start": "2021-10-19T14:58:08.539Z", + "kibana.alert.status": "recovered", + "kibana.alert.time_range": { + "gte": "2021-10-19T14:58:08.539Z", + "lte": "2021-10-19T15:00:14.550Z" + }, + "kibana.alert.uuid": "779d10e6-d858-434a-be7a-067a6ab1e5e3", + "kibana.alert.workflow_status": "acknowledged", + "kibana.space_ids": [ + "default" + ], + "kibana.version": "8.0.0", + "processor.event": [ + "error" + ], + "service.environment": [ + "https://www.elastic.co" + ], + "service.name": [ + "elastic-co-frontend" + ], + "tags": [] + } + } +} + +{ + "type": "doc", + "value": { + "id": "2ea488b6-24ce-4270-96d3-e9ddad876f38", + "index": ".internal.alerts-observability.logs.alerts-default-000001", + "source": { + "@timestamp": "2021-10-19T00:41:42.013Z", + "event.action": "close", + "event.kind": "signal", + "kibana.alert.duration.us": 33812471000, + "kibana.alert.end": "2021-10-19T00:41:42.013Z", + "kibana.alert.evaluation.threshold": 75, + "kibana.alert.evaluation.value": 84, + "kibana.alert.instance.id": "*", + "kibana.alert.reason": "84 log entries (more than 75) match the conditions.", + "kibana.alert.rule.category": "Log threshold", + "kibana.alert.rule.consumer": "alerts", + "kibana.alert.rule.name": "test", + "kibana.alert.rule.producer": "logs", + "kibana.alert.rule.rule_type_id": "logs.alert.document.count", + "kibana.alert.rule.uuid": "98d37c50-3026-11ec-80fd-1d41e589486f", + "kibana.alert.start": "2021-10-18T15:18:09.542Z", + "kibana.alert.status": "recovered", + "kibana.alert.time_range": { + "gte": "2021-10-18T15:18:09.542Z", + "lte": "2021-10-19T00:41:42.013Z" + }, + "kibana.alert.uuid": "2ea488b6-24ce-4270-96d3-e9ddad876f38", + "kibana.alert.workflow_status": "open", + "kibana.space_ids": [ + "default" + ], + "kibana.version": "8.0.0", + "tags": [] + } + } +} + +{ + "type": "doc", + "value": { + "id": "c848950d-6ce6-4d37-9948-102f77ddd719", + "index": ".internal.alerts-observability.logs.alerts-default-000001", + "source": { + "@timestamp": "2021-10-19T15:20:05.795Z", + "event.action": "active", + "event.kind": "signal", + "kibana.alert.duration.us": 126100000, + "kibana.alert.evaluation.threshold": 75, + "kibana.alert.evaluation.value": 449, + "kibana.alert.instance.id": "filebeat-gr8g6", + "kibana.alert.reason": "449 log entries (more than 75) match the conditions for filebeat-gr8g6.", + "kibana.alert.rule.category": "Log threshold", + "kibana.alert.rule.consumer": "logs", + "kibana.alert.rule.name": "Log threshold group by (one)", + "kibana.alert.rule.producer": "logs", + "kibana.alert.rule.rule_type_id": "logs.alert.document.count", + "kibana.alert.rule.uuid": "bc9c9c60-30ef-11ec-9819-c5cd0facebad", + "kibana.alert.start": "2021-10-19T15:17:59.695Z", + "kibana.alert.status": "active", + "kibana.alert.time_range": { + "gte": "2021-10-19T15:17:59.695Z" + }, + "kibana.alert.uuid": "c848950d-6ce6-4d37-9948-102f77ddd719", + "kibana.alert.workflow_status": "open", + "kibana.space_ids": [ + "default" + ], + "kibana.version": "8.0.0", + "tags": [] + } + } +} + +{ + "type": "doc", + "value": { + "id": "54040429-66f5-478a-bb30-73986bca1994", + "index": ".internal.alerts-observability.logs.alerts-default-000001", + "source": { + "@timestamp": "2021-10-19T15:20:05.795Z", + "event.action": "active", + "event.kind": "signal", + "kibana.alert.duration.us": 1953316000, + "kibana.alert.evaluation.threshold": 75, + "kibana.alert.evaluation.value": 4069, + "kibana.alert.instance.id": "*", + "kibana.alert.reason": "4069 log entries (more than 75) match the conditions.", + "kibana.alert.rule.category": "Log threshold", + "kibana.alert.rule.consumer": "alerts", + "kibana.alert.rule.name": "Log threshold (two)", + "kibana.alert.rule.producer": "logs", + "kibana.alert.rule.rule_type_id": "logs.alert.document.count", + "kibana.alert.rule.uuid": "7b664330-30eb-11ec-9819-c5cd0facebad", + "kibana.alert.start": "2021-10-19T14:47:32.479Z", + "kibana.alert.status": "active", + "kibana.alert.time_range": { + "gte": "2021-10-19T14:47:32.479Z" + }, + "kibana.alert.uuid": "54040429-66f5-478a-bb30-73986bca1994", + "kibana.alert.workflow_status": "open", + "kibana.space_ids": [ + "default" + ], + "kibana.version": "8.0.0", + "tags": [] + } + } +} + +{ + "type": "doc", + "value": { + "id": "30db6bb6-61cb-4cdd-b3bc-4fb4091d6990", + "index": ".internal.alerts-observability.logs.alerts-default-000001", + "source": { + "@timestamp": "2021-10-19T15:20:38.749Z", + "event.action": "active", + "event.kind": "signal", + "kibana.alert.duration.us": 2079287000, + "kibana.alert.evaluation.threshold": 5, + "kibana.alert.evaluation.value": 199, + "kibana.alert.instance.id": "*", + "kibana.alert.reason": "199 log entries (more than 5) match the conditions.", + "kibana.alert.rule.category": "Log threshold", + "kibana.alert.rule.consumer": "alerts", + "kibana.alert.rule.name": "Log threshold (one)", + "kibana.alert.rule.producer": "logs", + "kibana.alert.rule.rule_type_id": "logs.alert.document.count", + "kibana.alert.rule.uuid": "43a9ebe0-30eb-11ec-9819-c5cd0facebad", + "kibana.alert.start": "2021-10-19T14:45:59.462Z", + "kibana.alert.status": "active", + "kibana.alert.time_range": { + "gte": "2021-10-19T14:45:59.462Z" + }, + "kibana.alert.uuid": "30db6bb6-61cb-4cdd-b3bc-4fb4091d6990", + "kibana.alert.workflow_status": "open", + "kibana.space_ids": [ + "default" + ], + "kibana.version": "8.0.0", + "tags": [] + } + } +} + +{ + "type": "doc", + "value": { + "id": "f995b07f-6112-49da-9984-c9703447ba8c", + "index": ".internal.alerts-observability.logs.alerts-default-000001", + "source": { + "@timestamp": "2021-10-19T14:55:35.560Z", + "event.action": "active", + "event.kind": "signal", + "kibana.alert.duration.us": 6048820000, + "kibana.alert.evaluation.threshold": 75, + "kibana.alert.evaluation.value": 393, + "kibana.alert.instance.id": "*", + "kibana.alert.reason": "393 log entries (more than 75) match the conditions.", + "kibana.alert.rule.category": "Log threshold", + "kibana.alert.rule.consumer": "alerts", + "kibana.alert.rule.name": "test", + "kibana.alert.rule.producer": "logs", + "kibana.alert.rule.rule_type_id": "logs.alert.document.count", + "kibana.alert.rule.uuid": "98d37c50-3026-11ec-80fd-1d41e589486f", + "kibana.alert.start": "2021-10-19T13:14:46.740Z", + "kibana.alert.status": "active", + "kibana.alert.time_range": { + "gte": "2021-10-19T13:14:46.740Z" + }, + "kibana.alert.uuid": "f995b07f-6112-49da-9984-c9703447ba8c", + "kibana.alert.workflow_status": "open", + "kibana.space_ids": [ + "default" + ], + "kibana.version": "8.0.0", + "tags": [] + } + } +} + +{ + "type": "doc", + "value": { + "id": "47368c89-3ee0-4057-853f-cda404024bff", + "index": ".internal.alerts-observability.metrics.alerts-default-000001", + "source": { + "@timestamp": "2021-10-19T15:20:26.974Z", + "event.action": "active", + "event.kind": "signal", + "kibana.alert.duration.us": 63291000, + "kibana.alert.end": "2021-10-19T15:20:26.974Z", + "kibana.alert.instance.id": "gke-edge-oblt-default-pool-350b44de-3v4p", + "kibana.alert.reason": "CPU usage is greater than a threshold of 40 (current value is 40.8%) for gke-edge-oblt-default-pool-350b44de-3v4p", + "kibana.alert.rule.category": "Inventory", + "kibana.alert.rule.consumer": "alerts", + "kibana.alert.rule.name": "Metrics inventory (one)", + "kibana.alert.rule.params": "{\"nodeType\":\"host\",\"criteria\":[{\"metric\":\"cpu\",\"comparator\":\">\",\"threshold\":[40],\"timeSize\":1,\"timeUnit\":\"m\",\"customMetric\":{\"type\":\"custom\",\"id\":\"alert-custom-metric\",\"field\":\"\",\"aggregation\":\"avg\"}}],\"sourceId\":\"default\"}", + "kibana.alert.rule.producer": "infrastructure", + "kibana.alert.rule.rule_type_id": "metrics.alert.inventory.threshold", + "kibana.alert.rule.uuid": "f95ef340-30eb-11ec-9819-c5cd0facebad", + "kibana.alert.start": "2021-10-19T15:19:23.683Z", + "kibana.alert.status": "recovered", + "kibana.alert.time_range": { + "gte": "2021-10-19T15:19:23.683Z", + "lte": "2021-10-19T15:20:26.974Z" + }, + "kibana.alert.uuid": "47368c89-3ee0-4057-853f-cda404024bff", + "kibana.alert.workflow_status": "open", + "kibana.space_ids": [ + "default" + ], + "kibana.version": "8.0.0", + "tags": [] + } + } +} + +{ + "type": "doc", + "value": { + "id": "ebecfc9d-0022-4f01-9a82-5cf9a722a29f", + "index": ".internal.alerts-observability.metrics.alerts-default-000001", + "source": { + "@timestamp": "2021-10-19T15:20:26.974Z", + "event.action": "active", + "event.kind": "signal", + "kibana.alert.duration.us": 63291000, + "kibana.alert.end": "2021-10-19T15:20:26.974Z", + "kibana.alert.instance.id": "gke-edge-oblt-default-pool-350b44de-v7vb", + "kibana.alert.reason": "CPU usage is greater than a threshold of 40 (current value is 53.4%) for gke-edge-oblt-default-pool-350b44de-v7vb", + "kibana.alert.rule.category": "Inventory", + "kibana.alert.rule.consumer": "alerts", + "kibana.alert.rule.name": "Metrics inventory (one)", + "kibana.alert.rule.params": "{\"nodeType\":\"host\",\"criteria\":[{\"metric\":\"cpu\",\"comparator\":\">\",\"threshold\":[40],\"timeSize\":1,\"timeUnit\":\"m\",\"customMetric\":{\"type\":\"custom\",\"id\":\"alert-custom-metric\",\"field\":\"\",\"aggregation\":\"avg\"}}],\"sourceId\":\"default\"}", + "kibana.alert.rule.producer": "infrastructure", + "kibana.alert.rule.rule_type_id": "metrics.alert.inventory.threshold", + "kibana.alert.rule.uuid": "f95ef340-30eb-11ec-9819-c5cd0facebad", + "kibana.alert.start": "2021-10-19T15:19:23.683Z", + "kibana.alert.status": "recovered", + "kibana.alert.time_range": { + "gte": "2021-10-19T15:19:23.683Z", + "lte": "2021-10-19T15:20:26.974Z" + }, + "kibana.alert.uuid": "ebecfc9d-0022-4f01-9a82-5cf9a722a29f", + "kibana.alert.workflow_status": "open", + "kibana.space_ids": [ + "default" + ], + "kibana.version": "8.0.0", + "tags": [] + } + } +} + +{ + "type": "doc", + "value": { + "id": "a43f0d7b-58e8-4abe-a880-28c50c327380", + "index": ".internal.alerts-observability.metrics.alerts-default-000001", + "source": { + "@timestamp": "2021-10-19T15:20:26.974Z", + "event.action": "open", + "event.kind": "signal", + "kibana.alert.duration.us": 0, + "kibana.alert.end": "2021-10-19T15:20:26.974Z", + "kibana.alert.instance.id": "gke-edge-oblt-default-pool-350b44de-c3dd", + "kibana.alert.reason": "CPU usage is greater than a threshold of 40 (current value is 45.2%) for gke-edge-oblt-default-pool-350b44de-c3dd", + "kibana.alert.rule.category": "Inventory", + "kibana.alert.rule.consumer": "alerts", + "kibana.alert.rule.name": "Metrics inventory (one)", + "kibana.alert.rule.params": "{\"nodeType\":\"host\",\"criteria\":[{\"metric\":\"cpu\",\"comparator\":\">\",\"threshold\":[40],\"timeSize\":1,\"timeUnit\":\"m\",\"customMetric\":{\"type\":\"custom\",\"id\":\"alert-custom-metric\",\"field\":\"\",\"aggregation\":\"avg\"}}],\"sourceId\":\"default\"}", + "kibana.alert.rule.producer": "infrastructure", + "kibana.alert.rule.rule_type_id": "metrics.alert.inventory.threshold", + "kibana.alert.rule.uuid": "f95ef340-30eb-11ec-9819-c5cd0facebad", + "kibana.alert.start": "2021-10-19T15:20:26.974Z", + "kibana.alert.status": "recovered", + "kibana.alert.time_range": { + "gte": "2021-10-19T15:20:26.974Z", + "lte": "2021-10-19T15:20:26.974Z" + }, + "kibana.alert.uuid": "a43f0d7b-58e8-4abe-a880-28c50c327380", + "kibana.alert.workflow_status": "open", + "kibana.space_ids": [ + "default" + ], + "kibana.version": "8.0.0", + "tags": [] + } + } +} + +{ + "type": "doc", + "value": { + "id": "204eceda-6c5e-40ff-acc1-c4d4cdab890b", + "index": ".internal.alerts-observability.metrics.alerts-default-000001", + "source": { + "@timestamp": "2021-10-19T15:19:59.804Z", + "event.action": "active", + "event.kind": "signal", + "kibana.alert.duration.us": 441160000, + "kibana.alert.end": "2021-10-19T15:19:59.804Z", + "kibana.alert.instance.id": "*", + "kibana.alert.reason": "system.cpu.user.pct is greater than a threshold of 115% (current value is 142.4%) for *", + "kibana.alert.rule.category": "Metric threshold", + "kibana.alert.rule.consumer": "alerts", + "kibana.alert.rule.name": "Metrics threshold (one)", + "kibana.alert.rule.producer": "infrastructure", + "kibana.alert.rule.rule_type_id": "metrics.alert.threshold", + "kibana.alert.rule.uuid": "a57eabc0-30ec-11ec-9819-c5cd0facebad", + "kibana.alert.start": "2021-10-19T15:12:38.644Z", + "kibana.alert.status": "recovered", + "kibana.alert.time_range": { + "gte": "2021-10-19T15:12:38.644Z", + "lte": "2021-10-19T15:19:59.804Z" + }, + "kibana.alert.uuid": "204eceda-6c5e-40ff-acc1-c4d4cdab890b", + "kibana.alert.workflow_status": "open", + "kibana.space_ids": [ + "default" + ], + "kibana.version": "8.0.0", + "tags": [] + } + } +} + +{ + "type": "doc", + "value": { + "id": "220eb1e7-8a0a-41eb-b6d8-579337a3cdd9", + "index": ".internal.alerts-observability.metrics.alerts-default-000001", + "source": { + "@timestamp": "2021-10-19T15:19:23.683Z", + "event.action": "close", + "event.kind": "signal", + "kibana.alert.duration.us": 125946000, + "kibana.alert.end": "2021-10-19T15:19:23.683Z", + "kibana.alert.instance.id": "gke-edge-oblt-default-pool-350b44de-c3dd", + "kibana.alert.reason": "CPU usage is greater than a threshold of 40 (current value is 66.8%) for gke-edge-oblt-default-pool-350b44de-c3dd", + "kibana.alert.rule.category": "Inventory", + "kibana.alert.rule.consumer": "alerts", + "kibana.alert.rule.name": "Metrics inventory (one)", + "kibana.alert.rule.params": "{\"nodeType\":\"host\",\"criteria\":[{\"metric\":\"cpu\",\"comparator\":\">\",\"threshold\":[40],\"timeSize\":1,\"timeUnit\":\"m\",\"customMetric\":{\"type\":\"custom\",\"id\":\"alert-custom-metric\",\"field\":\"\",\"aggregation\":\"avg\"}}],\"sourceId\":\"default\"}", + "kibana.alert.rule.producer": "infrastructure", + "kibana.alert.rule.rule_type_id": "metrics.alert.inventory.threshold", + "kibana.alert.rule.uuid": "f95ef340-30eb-11ec-9819-c5cd0facebad", + "kibana.alert.start": "2021-10-19T15:17:17.737Z", + "kibana.alert.status": "recovered", + "kibana.alert.time_range": { + "gte": "2021-10-19T15:17:17.737Z", + "lte": "2021-10-19T15:19:23.683Z" + }, + "kibana.alert.uuid": "220eb1e7-8a0a-41eb-b6d8-579337a3cdd9", + "kibana.alert.workflow_status": "open", + "kibana.space_ids": [ + "default" + ], + "kibana.version": "8.0.0", + "tags": [] + } + } +} + +{ + "type": "doc", + "value": { + "id": "5058e22c-abc2-4c2f-a276-682ad5a2498e", + "index": ".internal.alerts-observability.metrics.alerts-default-000001", + "source": { + "@timestamp": "2021-10-19T14:52:05.509Z", + "event.action": "close", + "event.kind": "signal", + "kibana.alert.duration.us": 63008000, + "kibana.alert.end": "2021-10-19T14:52:05.509Z", + "kibana.alert.instance.id": "gke-edge-oblt-default-pool-350b44de-3v4p", + "kibana.alert.reason": "CPU usage is greater than a threshold of 40 (current value is 42.6%) for gke-edge-oblt-default-pool-350b44de-3v4p", + "kibana.alert.rule.category": "Inventory", + "kibana.alert.rule.consumer": "alerts", + "kibana.alert.rule.name": "Metrics inventory (one)", + "kibana.alert.rule.params": "{\"nodeType\":\"host\",\"criteria\":[{\"metric\":\"cpu\",\"comparator\":\">\",\"threshold\":[40],\"timeSize\":1,\"timeUnit\":\"m\",\"customMetric\":{\"type\":\"custom\",\"id\":\"alert-custom-metric\",\"field\":\"\",\"aggregation\":\"avg\"}}],\"sourceId\":\"default\"}", + "kibana.alert.rule.producer": "infrastructure", + "kibana.alert.rule.rule_type_id": "metrics.alert.inventory.threshold", + "kibana.alert.rule.uuid": "f95ef340-30eb-11ec-9819-c5cd0facebad", + "kibana.alert.start": "2021-10-19T14:51:02.501Z", + "kibana.alert.status": "recovered", + "kibana.alert.time_range": { + "gte": "2021-10-19T14:51:02.501Z", + "lte": "2021-10-19T14:52:05.509Z" + }, + "kibana.alert.uuid": "5058e22c-abc2-4c2f-a276-682ad5a2498e", + "kibana.alert.workflow_status": "open", + "kibana.space_ids": [ + "default" + ], + "kibana.version": "8.0.0", + "tags": [] + } + } +} + +{ + "type": "doc", + "value": { + "id": "f94c7e72-d380-4e69-8b3e-3bb145789b42", + "index": ".internal.alerts-observability.metrics.alerts-default-000001", + "source": { + "@timestamp": "2021-10-19T14:53:08.491Z", + "event.action": "close", + "event.kind": "signal", + "kibana.alert.duration.us": 125990000, + "kibana.alert.end": "2021-10-19T14:53:08.491Z", + "kibana.alert.instance.id": "gke-edge-oblt-default-pool-350b44de-v7vb", + "kibana.alert.reason": "CPU usage is greater than a threshold of 40 (current value is 45.6%) for gke-edge-oblt-default-pool-350b44de-v7vb", + "kibana.alert.rule.category": "Inventory", + "kibana.alert.rule.consumer": "alerts", + "kibana.alert.rule.name": "Metrics inventory (one)", + "kibana.alert.rule.params": "{\"nodeType\":\"host\",\"criteria\":[{\"metric\":\"cpu\",\"comparator\":\">\",\"threshold\":[40],\"timeSize\":1,\"timeUnit\":\"m\",\"customMetric\":{\"type\":\"custom\",\"id\":\"alert-custom-metric\",\"field\":\"\",\"aggregation\":\"avg\"}}],\"sourceId\":\"default\"}", + "kibana.alert.rule.producer": "infrastructure", + "kibana.alert.rule.rule_type_id": "metrics.alert.inventory.threshold", + "kibana.alert.rule.uuid": "f95ef340-30eb-11ec-9819-c5cd0facebad", + "kibana.alert.start": "2021-10-19T14:51:02.501Z", + "kibana.alert.status": "recovered", + "kibana.alert.time_range": { + "gte": "2021-10-19T14:51:02.501Z", + "lte": "2021-10-19T14:53:08.491Z" + }, + "kibana.alert.uuid": "f94c7e72-d380-4e69-8b3e-3bb145789b42", + "kibana.alert.workflow_status": "open", + "kibana.space_ids": [ + "default" + ], + "kibana.version": "8.0.0", + "tags": [] + } + } +} + +{ + "type": "doc", + "value": { + "id": "21263f25-0013-4e8d-836d-857d27e7781f", + "index": ".internal.alerts-observability.metrics.alerts-default-000001", + "source": { + "@timestamp": "2021-10-19T14:56:17.533Z", + "event.action": "close", + "event.kind": "signal", + "kibana.alert.duration.us": 125991000, + "kibana.alert.end": "2021-10-19T14:56:17.533Z", + "kibana.alert.instance.id": "gke-edge-oblt-default-pool-350b44de-3v4p", + "kibana.alert.reason": "CPU usage is greater than a threshold of 40 (current value is 44.3%) for gke-edge-oblt-default-pool-350b44de-3v4p", + "kibana.alert.rule.category": "Inventory", + "kibana.alert.rule.consumer": "alerts", + "kibana.alert.rule.name": "Metrics inventory (one)", + "kibana.alert.rule.params": "{\"nodeType\":\"host\",\"criteria\":[{\"metric\":\"cpu\",\"comparator\":\">\",\"threshold\":[40],\"timeSize\":1,\"timeUnit\":\"m\",\"customMetric\":{\"type\":\"custom\",\"id\":\"alert-custom-metric\",\"field\":\"\",\"aggregation\":\"avg\"}}],\"sourceId\":\"default\"}", + "kibana.alert.rule.producer": "infrastructure", + "kibana.alert.rule.rule_type_id": "metrics.alert.inventory.threshold", + "kibana.alert.rule.uuid": "f95ef340-30eb-11ec-9819-c5cd0facebad", + "kibana.alert.start": "2021-10-19T14:54:11.542Z", + "kibana.alert.status": "recovered", + "kibana.alert.time_range": { + "gte": "2021-10-19T14:54:11.542Z", + "lte": "2021-10-19T14:56:17.533Z" + }, + "kibana.alert.uuid": "21263f25-0013-4e8d-836d-857d27e7781f", + "kibana.alert.workflow_status": "open", + "kibana.space_ids": [ + "default" + ], + "kibana.version": "8.0.0", + "tags": [] + } + } +} + +{ + "type": "doc", + "value": { + "id": "c29936fc-3be7-4193-ba3d-4198ec3dbd78", + "index": ".internal.alerts-observability.metrics.alerts-default-000001", + "source": { + "@timestamp": "2021-10-19T14:57:20.528Z", + "event.action": "close", + "event.kind": "signal", + "kibana.alert.duration.us": 126025000, + "kibana.alert.end": "2021-10-19T14:57:20.528Z", + "kibana.alert.instance.id": "gke-edge-oblt-default-pool-350b44de-v7vb", + "kibana.alert.reason": "CPU usage is greater than a threshold of 40 (current value is 50.2%) for gke-edge-oblt-default-pool-350b44de-v7vb", + "kibana.alert.rule.category": "Inventory", + "kibana.alert.rule.consumer": "alerts", + "kibana.alert.rule.name": "Metrics inventory (one)", + "kibana.alert.rule.params": "{\"nodeType\":\"host\",\"criteria\":[{\"metric\":\"cpu\",\"comparator\":\">\",\"threshold\":[40],\"timeSize\":1,\"timeUnit\":\"m\",\"customMetric\":{\"type\":\"custom\",\"id\":\"alert-custom-metric\",\"field\":\"\",\"aggregation\":\"avg\"}}],\"sourceId\":\"default\"}", + "kibana.alert.rule.producer": "infrastructure", + "kibana.alert.rule.rule_type_id": "metrics.alert.inventory.threshold", + "kibana.alert.rule.uuid": "f95ef340-30eb-11ec-9819-c5cd0facebad", + "kibana.alert.start": "2021-10-19T14:55:14.503Z", + "kibana.alert.status": "recovered", + "kibana.alert.time_range": { + "gte": "2021-10-19T14:55:14.503Z", + "lte": "2021-10-19T14:57:20.528Z" + }, + "kibana.alert.uuid": "c29936fc-3be7-4193-ba3d-4198ec3dbd78", + "kibana.alert.workflow_status": "open", + "kibana.space_ids": [ + "default" + ], + "kibana.version": "8.0.0", + "tags": [] + } + } +} + +{ + "type": "doc", + "value": { + "id": "f3f896ab-111c-4b84-a9d9-dca4ffdea492", + "index": ".internal.alerts-observability.metrics.alerts-default-000001", + "source": { + "@timestamp": "2021-10-19T15:04:41.569Z", + "event.action": "close", + "event.kind": "signal", + "kibana.alert.duration.us": 189017000, + "kibana.alert.end": "2021-10-19T15:04:41.569Z", + "kibana.alert.instance.id": "gke-edge-oblt-default-pool-350b44de-c3dd", + "kibana.alert.reason": "CPU usage is greater than a threshold of 40 (current value is 50.7%) for gke-edge-oblt-default-pool-350b44de-c3dd", + "kibana.alert.rule.category": "Inventory", + "kibana.alert.rule.consumer": "alerts", + "kibana.alert.rule.name": "Metrics inventory (one)", + "kibana.alert.rule.params": "{\"nodeType\":\"host\",\"criteria\":[{\"metric\":\"cpu\",\"comparator\":\">\",\"threshold\":[40],\"timeSize\":1,\"timeUnit\":\"m\",\"customMetric\":{\"type\":\"custom\",\"id\":\"alert-custom-metric\",\"field\":\"\",\"aggregation\":\"avg\"}}],\"sourceId\":\"default\"}", + "kibana.alert.rule.producer": "infrastructure", + "kibana.alert.rule.rule_type_id": "metrics.alert.inventory.threshold", + "kibana.alert.rule.uuid": "f95ef340-30eb-11ec-9819-c5cd0facebad", + "kibana.alert.start": "2021-10-19T15:01:32.552Z", + "kibana.alert.status": "recovered", + "kibana.alert.time_range": { + "gte": "2021-10-19T15:01:32.552Z", + "lte": "2021-10-19T15:04:41.569Z" + }, + "kibana.alert.uuid": "f3f896ab-111c-4b84-a9d9-dca4ffdea492", + "kibana.alert.workflow_status": "open", + "kibana.space_ids": [ + "default" + ], + "kibana.version": "8.0.0", + "tags": [] + } + } +} + +{ + "type": "doc", + "value": { + "id": "c26ca019-da1e-427b-bd59-a3802116e8f3", + "index": ".internal.alerts-observability.metrics.alerts-default-000001", + "source": { + "@timestamp": "2021-10-19T15:04:41.569Z", + "event.action": "close", + "event.kind": "signal", + "kibana.alert.duration.us": 63005000, + "kibana.alert.end": "2021-10-19T15:04:41.569Z", + "kibana.alert.instance.id": "gke-edge-oblt-default-pool-350b44de-v7vb", + "kibana.alert.reason": "CPU usage is greater than a threshold of 40 (current value is 43.1%) for gke-edge-oblt-default-pool-350b44de-v7vb", + "kibana.alert.rule.category": "Inventory", + "kibana.alert.rule.consumer": "alerts", + "kibana.alert.rule.name": "Metrics inventory (one)", + "kibana.alert.rule.params": "{\"nodeType\":\"host\",\"criteria\":[{\"metric\":\"cpu\",\"comparator\":\">\",\"threshold\":[40],\"timeSize\":1,\"timeUnit\":\"m\",\"customMetric\":{\"type\":\"custom\",\"id\":\"alert-custom-metric\",\"field\":\"\",\"aggregation\":\"avg\"}}],\"sourceId\":\"default\"}", + "kibana.alert.rule.producer": "infrastructure", + "kibana.alert.rule.rule_type_id": "metrics.alert.inventory.threshold", + "kibana.alert.rule.uuid": "f95ef340-30eb-11ec-9819-c5cd0facebad", + "kibana.alert.start": "2021-10-19T15:03:38.564Z", + "kibana.alert.status": "recovered", + "kibana.alert.time_range": { + "gte": "2021-10-19T15:03:38.564Z", + "lte": "2021-10-19T15:04:41.569Z" + }, + "kibana.alert.uuid": "c26ca019-da1e-427b-bd59-a3802116e8f3", + "kibana.alert.workflow_status": "open", + "kibana.space_ids": [ + "default" + ], + "kibana.version": "8.0.0", + "tags": [] + } + } +} + +{ + "type": "doc", + "value": { + "id": "b1c9fff7-59e3-417d-8707-76d709f64591", + "index": ".internal.alerts-observability.metrics.alerts-default-000001", + "source": { + "@timestamp": "2021-10-19T15:07:50.615Z", + "event.action": "close", + "event.kind": "signal", + "kibana.alert.duration.us": 126038000, + "kibana.alert.end": "2021-10-19T15:07:50.615Z", + "kibana.alert.instance.id": "gke-edge-oblt-default-pool-350b44de-c3dd", + "kibana.alert.reason": "CPU usage is greater than a threshold of 40 (current value is 52.3%) for gke-edge-oblt-default-pool-350b44de-c3dd", + "kibana.alert.rule.category": "Inventory", + "kibana.alert.rule.consumer": "alerts", + "kibana.alert.rule.name": "Metrics inventory (one)", + "kibana.alert.rule.params": "{\"nodeType\":\"host\",\"criteria\":[{\"metric\":\"cpu\",\"comparator\":\">\",\"threshold\":[40],\"timeSize\":1,\"timeUnit\":\"m\",\"customMetric\":{\"type\":\"custom\",\"id\":\"alert-custom-metric\",\"field\":\"\",\"aggregation\":\"avg\"}}],\"sourceId\":\"default\"}", + "kibana.alert.rule.producer": "infrastructure", + "kibana.alert.rule.rule_type_id": "metrics.alert.inventory.threshold", + "kibana.alert.rule.uuid": "f95ef340-30eb-11ec-9819-c5cd0facebad", + "kibana.alert.start": "2021-10-19T15:05:44.577Z", + "kibana.alert.status": "recovered", + "kibana.alert.time_range": { + "gte": "2021-10-19T15:05:44.577Z", + "lte": "2021-10-19T15:07:50.615Z" + }, + "kibana.alert.uuid": "b1c9fff7-59e3-417d-8707-76d709f64591", + "kibana.alert.workflow_status": "open", + "kibana.space_ids": [ + "default" + ], + "kibana.version": "8.0.0", + "tags": [] + } + } +} + +{ + "type": "doc", + "value": { + "id": "bc84ea52-3450-44aa-9fb9-af00a208d609", + "index": ".internal.alerts-observability.metrics.alerts-default-000001", + "source": { + "@timestamp": "2021-10-19T15:17:17.737Z", + "event.action": "close", + "event.kind": "signal", + "kibana.alert.duration.us": 126037000, + "kibana.alert.end": "2021-10-19T15:17:17.737Z", + "kibana.alert.instance.id": "gke-edge-oblt-default-pool-350b44de-3v4p", + "kibana.alert.reason": "CPU usage is greater than a threshold of 40 (current value is 40.5%) for gke-edge-oblt-default-pool-350b44de-3v4p", + "kibana.alert.rule.category": "Inventory", + "kibana.alert.rule.consumer": "alerts", + "kibana.alert.rule.name": "Metrics inventory (one)", + "kibana.alert.rule.params": "{\"nodeType\":\"host\",\"criteria\":[{\"metric\":\"cpu\",\"comparator\":\">\",\"threshold\":[40],\"timeSize\":1,\"timeUnit\":\"m\",\"customMetric\":{\"type\":\"custom\",\"id\":\"alert-custom-metric\",\"field\":\"\",\"aggregation\":\"avg\"}}],\"sourceId\":\"default\"}", + "kibana.alert.rule.producer": "infrastructure", + "kibana.alert.rule.rule_type_id": "metrics.alert.inventory.threshold", + "kibana.alert.rule.uuid": "f95ef340-30eb-11ec-9819-c5cd0facebad", + "kibana.alert.start": "2021-10-19T15:15:11.700Z", + "kibana.alert.status": "recovered", + "kibana.alert.time_range": { + "gte": "2021-10-19T15:15:11.700Z", + "lte": "2021-10-19T15:17:17.737Z" + }, + "kibana.alert.uuid": "bc84ea52-3450-44aa-9fb9-af00a208d609", + "kibana.alert.workflow_status": "open", + "kibana.space_ids": [ + "default" + ], + "kibana.version": "8.0.0", + "tags": [] + } + } +} + +{ + "type": "doc", + "value": { + "id": "e8be7281-0a76-43ce-9e9a-d5661ec396bb", + "index": ".internal.alerts-observability.metrics.alerts-default-000001", + "source": { + "@timestamp": "2021-10-19T15:01:32.552Z", + "event.action": "close", + "event.kind": "signal", + "kibana.alert.duration.us": 126002000, + "kibana.alert.end": "2021-10-19T15:01:32.552Z", + "kibana.alert.instance.id": "gke-edge-oblt-default-pool-350b44de-v7vb", + "kibana.alert.reason": "CPU usage is greater than a threshold of 40 (current value is 44.2%) for gke-edge-oblt-default-pool-350b44de-v7vb", + "kibana.alert.rule.category": "Inventory", + "kibana.alert.rule.consumer": "alerts", + "kibana.alert.rule.name": "Metrics inventory (one)", + "kibana.alert.rule.params": "{\"nodeType\":\"host\",\"criteria\":[{\"metric\":\"cpu\",\"comparator\":\">\",\"threshold\":[40],\"timeSize\":1,\"timeUnit\":\"m\",\"customMetric\":{\"type\":\"custom\",\"id\":\"alert-custom-metric\",\"field\":\"\",\"aggregation\":\"avg\"}}],\"sourceId\":\"default\"}", + "kibana.alert.rule.producer": "infrastructure", + "kibana.alert.rule.rule_type_id": "metrics.alert.inventory.threshold", + "kibana.alert.rule.uuid": "f95ef340-30eb-11ec-9819-c5cd0facebad", + "kibana.alert.start": "2021-10-19T14:59:26.550Z", + "kibana.alert.status": "recovered", + "kibana.alert.time_range": { + "gte": "2021-10-19T14:59:26.550Z", + "lte": "2021-10-19T15:01:32.552Z" + }, + "kibana.alert.uuid": "e8be7281-0a76-43ce-9e9a-d5661ec396bb", + "kibana.alert.workflow_status": "acknowledged", + "kibana.space_ids": [ + "default" + ], + "kibana.version": "8.0.0", + "tags": [] + } + } +} + +{ + "type": "doc", + "value": { + "id": "2a9f3df9-9c5f-4713-81c3-340bf7f58e04", + "index": ".internal.alerts-observability.metrics.alerts-default-000001", + "source": { + "@timestamp": "2021-10-19T15:12:02.607Z", + "event.action": "close", + "event.kind": "signal", + "kibana.alert.duration.us": 188989000, + "kibana.alert.end": "2021-10-19T15:12:02.607Z", + "kibana.alert.instance.id": "gke-edge-oblt-default-pool-350b44de-c3dd", + "kibana.alert.reason": "CPU usage is greater than a threshold of 40 (current value is 50.4%) for gke-edge-oblt-default-pool-350b44de-c3dd", + "kibana.alert.rule.category": "Inventory", + "kibana.alert.rule.consumer": "alerts", + "kibana.alert.rule.name": "Metrics inventory (one)", + "kibana.alert.rule.params": "{\"nodeType\":\"host\",\"criteria\":[{\"metric\":\"cpu\",\"comparator\":\">\",\"threshold\":[40],\"timeSize\":1,\"timeUnit\":\"m\",\"customMetric\":{\"type\":\"custom\",\"id\":\"alert-custom-metric\",\"field\":\"\",\"aggregation\":\"avg\"}}],\"sourceId\":\"default\"}", + "kibana.alert.rule.producer": "infrastructure", + "kibana.alert.rule.rule_type_id": "metrics.alert.inventory.threshold", + "kibana.alert.rule.uuid": "f95ef340-30eb-11ec-9819-c5cd0facebad", + "kibana.alert.start": "2021-10-19T15:08:53.618Z", + "kibana.alert.status": "recovered", + "kibana.alert.time_range": { + "gte": "2021-10-19T15:08:53.618Z", + "lte": "2021-10-19T15:12:02.607Z" + }, + "kibana.alert.uuid": "2a9f3df9-9c5f-4713-81c3-340bf7f58e04", + "kibana.alert.workflow_status": "closed", + "kibana.space_ids": [ + "default" + ], + "kibana.version": "8.0.0", + "tags": [] + } + } +} + +{ + "type": "doc", + "value": { + "id": "c3102af5-c6ce-4f90-b970-6d696e0f7115", + "index": ".internal.alerts-observability.metrics.alerts-default-000001", + "source": { + "@timestamp": "2021-10-19T15:17:17.737Z", + "event.action": "close", + "event.kind": "signal", + "kibana.alert.duration.us": 126037000, + "kibana.alert.end": "2021-10-19T15:17:17.737Z", + "kibana.alert.instance.id": "gke-edge-oblt-default-pool-350b44de-v7vb", + "kibana.alert.reason": "CPU usage is greater than a threshold of 40 (current value is 50.6%) for gke-edge-oblt-default-pool-350b44de-v7vb", + "kibana.alert.rule.category": "Inventory", + "kibana.alert.rule.consumer": "alerts", + "kibana.alert.rule.name": "Metrics inventory (one)", + "kibana.alert.rule.params": "{\"nodeType\":\"host\",\"criteria\":[{\"metric\":\"cpu\",\"comparator\":\">\",\"threshold\":[40],\"timeSize\":1,\"timeUnit\":\"m\",\"customMetric\":{\"type\":\"custom\",\"id\":\"alert-custom-metric\",\"field\":\"\",\"aggregation\":\"avg\"}}],\"sourceId\":\"default\"}", + "kibana.alert.rule.producer": "infrastructure", + "kibana.alert.rule.rule_type_id": "metrics.alert.inventory.threshold", + "kibana.alert.rule.uuid": "f95ef340-30eb-11ec-9819-c5cd0facebad", + "kibana.alert.start": "2021-10-19T15:15:11.700Z", + "kibana.alert.status": "recovered", + "kibana.alert.time_range": { + "gte": "2021-10-19T15:15:11.700Z", + "lte": "2021-10-19T15:17:17.737Z" + }, + "kibana.alert.uuid": "c3102af5-c6ce-4f90-b970-6d696e0f7115", + "kibana.alert.workflow_status": "acknowledged", + "kibana.space_ids": [ + "default" + ], + "kibana.version": "8.0.0", + "tags": [] + } + } +} + +{ + "type": "doc", + "value": { + "id": "5b406ccc-20e9-4d5b-aa47-5d898fd5ed0f", + "index": ".internal.alerts-observability.metrics.alerts-default-000001", + "source": { + "@timestamp": "2021-10-19T15:15:11.700Z", + "event.action": "close", + "event.kind": "signal", + "kibana.alert.duration.us": 125995000, + "kibana.alert.end": "2021-10-19T15:15:11.700Z", + "kibana.alert.instance.id": "gke-edge-oblt-default-pool-350b44de-c3dd", + "kibana.alert.reason": "CPU usage is greater than a threshold of 40 (current value is 68.7%) for gke-edge-oblt-default-pool-350b44de-c3dd", + "kibana.alert.rule.category": "Inventory", + "kibana.alert.rule.consumer": "alerts", + "kibana.alert.rule.name": "Metrics inventory (one)", + "kibana.alert.rule.params": "{\"nodeType\":\"host\",\"criteria\":[{\"metric\":\"cpu\",\"comparator\":\">\",\"threshold\":[40],\"timeSize\":1,\"timeUnit\":\"m\",\"customMetric\":{\"type\":\"custom\",\"id\":\"alert-custom-metric\",\"field\":\"\",\"aggregation\":\"avg\"}}],\"sourceId\":\"default\"}", + "kibana.alert.rule.producer": "infrastructure", + "kibana.alert.rule.rule_type_id": "metrics.alert.inventory.threshold", + "kibana.alert.rule.uuid": "f95ef340-30eb-11ec-9819-c5cd0facebad", + "kibana.alert.start": "2021-10-19T15:13:05.705Z", + "kibana.alert.status": "recovered", + "kibana.alert.time_range": { + "gte": "2021-10-19T15:13:05.705Z", + "lte": "2021-10-19T15:15:11.700Z" + }, + "kibana.alert.uuid": "5b406ccc-20e9-4d5b-aa47-5d898fd5ed0f", + "kibana.alert.workflow_status": "acknowledged", + "kibana.space_ids": [ + "default" + ], + "kibana.version": "8.0.0", + "tags": [] + } + } +} + +{ + "type": "doc", + "value": { + "id": "1ac9eaa5-7275-46be-80a8-23625a4fb35b", + "index": ".internal.alerts-observability.metrics.alerts-default-000001", + "source": { + "@timestamp": "2021-10-19T14:55:14.503Z", + "event.action": "close", + "event.kind": "signal", + "kibana.alert.duration.us": 252002000, + "kibana.alert.end": "2021-10-19T14:55:14.503Z", + "kibana.alert.instance.id": "gke-edge-oblt-default-pool-350b44de-c3dd", + "kibana.alert.reason": "CPU usage is greater than a threshold of 40 (current value is 56.7%) for gke-edge-oblt-default-pool-350b44de-c3dd", + "kibana.alert.rule.category": "Inventory", + "kibana.alert.rule.consumer": "alerts", + "kibana.alert.rule.name": "Metrics inventory (one)", + "kibana.alert.rule.params": "{\"nodeType\":\"host\",\"criteria\":[{\"metric\":\"cpu\",\"comparator\":\">\",\"threshold\":[40],\"timeSize\":1,\"timeUnit\":\"m\",\"customMetric\":{\"type\":\"custom\",\"id\":\"alert-custom-metric\",\"field\":\"\",\"aggregation\":\"avg\"}}],\"sourceId\":\"default\"}", + "kibana.alert.rule.producer": "infrastructure", + "kibana.alert.rule.rule_type_id": "metrics.alert.inventory.threshold", + "kibana.alert.rule.uuid": "f95ef340-30eb-11ec-9819-c5cd0facebad", + "kibana.alert.start": "2021-10-19T14:51:02.501Z", + "kibana.alert.status": "recovered", + "kibana.alert.time_range": { + "gte": "2021-10-19T14:51:02.501Z", + "lte": "2021-10-19T14:55:14.503Z" + }, + "kibana.alert.uuid": "1ac9eaa5-7275-46be-80a8-23625a4fb35b", + "kibana.alert.workflow_status": "open", + "kibana.space_ids": [ + "default" + ], + "kibana.version": "8.0.0", + "tags": [] + } + } +} + +{ + "type": "doc", + "value": { + "id": "565e1700-1ccd-4e5e-a43d-481b9e4c1d09", + "index": ".internal.alerts-observability.metrics.alerts-default-000001", + "source": { + "@timestamp": "2021-10-19T14:59:26.550Z", + "event.action": "close", + "event.kind": "signal", + "kibana.alert.duration.us": 126022000, + "kibana.alert.end": "2021-10-19T14:59:26.550Z", + "kibana.alert.instance.id": "gke-edge-oblt-default-pool-350b44de-c3dd", + "kibana.alert.reason": "CPU usage is greater than a threshold of 40 (current value is 62.4%) for gke-edge-oblt-default-pool-350b44de-c3dd", + "kibana.alert.rule.category": "Inventory", + "kibana.alert.rule.consumer": "alerts", + "kibana.alert.rule.name": "Metrics inventory (one)", + "kibana.alert.rule.params": "{\"nodeType\":\"host\",\"criteria\":[{\"metric\":\"cpu\",\"comparator\":\">\",\"threshold\":[40],\"timeSize\":1,\"timeUnit\":\"m\",\"customMetric\":{\"type\":\"custom\",\"id\":\"alert-custom-metric\",\"field\":\"\",\"aggregation\":\"avg\"}}],\"sourceId\":\"default\"}", + "kibana.alert.rule.producer": "infrastructure", + "kibana.alert.rule.rule_type_id": "metrics.alert.inventory.threshold", + "kibana.alert.rule.uuid": "f95ef340-30eb-11ec-9819-c5cd0facebad", + "kibana.alert.start": "2021-10-19T14:57:20.528Z", + "kibana.alert.status": "recovered", + "kibana.alert.time_range": { + "gte": "2021-10-19T14:57:20.528Z", + "lte": "2021-10-19T14:59:26.550Z" + }, + "kibana.alert.uuid": "565e1700-1ccd-4e5e-a43d-481b9e4c1d09", + "kibana.alert.workflow_status": "open", + "kibana.space_ids": [ + "default" + ], + "kibana.version": "8.0.0", + "tags": [] + } + } +} + +{ + "type": "doc", + "value": { + "id": "88290eb9-d46d-4bca-a08f-ab08bdc2b7b2", + "index": ".internal.alerts-observability.metrics.alerts-default-000001", + "source": { + "@timestamp": "2021-10-19T15:00:29.541Z", + "event.action": "close", + "event.kind": "signal", + "kibana.alert.duration.us": 62991000, + "kibana.alert.end": "2021-10-19T15:00:29.541Z", + "kibana.alert.instance.id": "gke-edge-oblt-default-pool-350b44de-3v4p", + "kibana.alert.reason": "CPU usage is greater than a threshold of 40 (current value is 43.4%) for gke-edge-oblt-default-pool-350b44de-3v4p", + "kibana.alert.rule.category": "Inventory", + "kibana.alert.rule.consumer": "alerts", + "kibana.alert.rule.name": "Metrics inventory (one)", + "kibana.alert.rule.params": "{\"nodeType\":\"host\",\"criteria\":[{\"metric\":\"cpu\",\"comparator\":\">\",\"threshold\":[40],\"timeSize\":1,\"timeUnit\":\"m\",\"customMetric\":{\"type\":\"custom\",\"id\":\"alert-custom-metric\",\"field\":\"\",\"aggregation\":\"avg\"}}],\"sourceId\":\"default\"}", + "kibana.alert.rule.producer": "infrastructure", + "kibana.alert.rule.rule_type_id": "metrics.alert.inventory.threshold", + "kibana.alert.rule.uuid": "f95ef340-30eb-11ec-9819-c5cd0facebad", + "kibana.alert.start": "2021-10-19T14:59:26.550Z", + "kibana.alert.status": "recovered", + "kibana.alert.time_range": { + "gte": "2021-10-19T14:59:26.550Z", + "lte": "2021-10-19T15:00:29.541Z" + }, + "kibana.alert.uuid": "88290eb9-d46d-4bca-a08f-ab08bdc2b7b2", + "kibana.alert.workflow_status": "open", + "kibana.space_ids": [ + "default" + ], + "kibana.version": "8.0.0", + "tags": [] + } + } +} + +{ + "type": "doc", + "value": { + "id": "65b14fd0-5fc5-4382-8b0a-6ad3cb24d2e8", + "index": ".internal.alerts-observability.metrics.alerts-default-000001", + "source": { + "@timestamp": "2021-10-19T15:02:08.556Z", + "event.action": "close", + "event.kind": "signal", + "kibana.alert.duration.us": 378056000, + "kibana.alert.end": "2021-10-19T15:02:08.556Z", + "kibana.alert.instance.id": "*", + "kibana.alert.reason": "system.cpu.user.pct is greater than a threshold of 115% (current value is 131.6%) for *", + "kibana.alert.rule.category": "Metric threshold", + "kibana.alert.rule.consumer": "alerts", + "kibana.alert.rule.name": "Metrics threshold (one)", + "kibana.alert.rule.producer": "infrastructure", + "kibana.alert.rule.rule_type_id": "metrics.alert.threshold", + "kibana.alert.rule.uuid": "a57eabc0-30ec-11ec-9819-c5cd0facebad", + "kibana.alert.start": "2021-10-19T14:55:50.500Z", + "kibana.alert.status": "recovered", + "kibana.alert.time_range": { + "gte": "2021-10-19T14:55:50.500Z", + "lte": "2021-10-19T15:02:08.556Z" + }, + "kibana.alert.uuid": "65b14fd0-5fc5-4382-8b0a-6ad3cb24d2e8", + "kibana.alert.workflow_status": "open", + "kibana.space_ids": [ + "default" + ], + "kibana.version": "8.0.0", + "tags": [] + } + } +} + +{ + "type": "doc", + "value": { + "id": "53bc595c-d8de-4b1a-962a-ea7f679ed6b0", + "index": ".internal.alerts-observability.metrics.alerts-default-000001", + "source": { + "@timestamp": "2021-10-19T15:09:56.608Z", + "event.action": "close", + "event.kind": "signal", + "kibana.alert.duration.us": 315039000, + "kibana.alert.end": "2021-10-19T15:09:56.608Z", + "kibana.alert.instance.id": "gke-edge-oblt-default-pool-350b44de-3v4p", + "kibana.alert.reason": "CPU usage is greater than a threshold of 40 (current value is 40.3%) for gke-edge-oblt-default-pool-350b44de-3v4p", + "kibana.alert.rule.category": "Inventory", + "kibana.alert.rule.consumer": "alerts", + "kibana.alert.rule.name": "Metrics inventory (one)", + "kibana.alert.rule.params": "{\"nodeType\":\"host\",\"criteria\":[{\"metric\":\"cpu\",\"comparator\":\">\",\"threshold\":[40],\"timeSize\":1,\"timeUnit\":\"m\",\"customMetric\":{\"type\":\"custom\",\"id\":\"alert-custom-metric\",\"field\":\"\",\"aggregation\":\"avg\"}}],\"sourceId\":\"default\"}", + "kibana.alert.rule.producer": "infrastructure", + "kibana.alert.rule.rule_type_id": "metrics.alert.inventory.threshold", + "kibana.alert.rule.uuid": "f95ef340-30eb-11ec-9819-c5cd0facebad", + "kibana.alert.start": "2021-10-19T15:04:41.569Z", + "kibana.alert.status": "recovered", + "kibana.alert.time_range": { + "gte": "2021-10-19T15:04:41.569Z", + "lte": "2021-10-19T15:09:56.608Z" + }, + "kibana.alert.uuid": "53bc595c-d8de-4b1a-962a-ea7f679ed6b0", + "kibana.alert.workflow_status": "open", + "kibana.space_ids": [ + "default" + ], + "kibana.version": "8.0.0", + "tags": [] + } + } +} + +{ + "type": "doc", + "value": { + "id": "c511bdea-2eba-441a-8d77-b0ea83e16b6f", + "index": ".internal.alerts-observability.metrics.alerts-default-000001", + "source": { + "@timestamp": "2021-10-19T15:12:02.607Z", + "event.action": "close", + "event.kind": "signal", + "kibana.alert.duration.us": 62967000, + "kibana.alert.end": "2021-10-19T15:12:02.607Z", + "kibana.alert.instance.id": "gke-edge-oblt-default-pool-350b44de-3v4p", + "kibana.alert.reason": "CPU usage is greater than a threshold of 40 (current value is 42.4%) for gke-edge-oblt-default-pool-350b44de-3v4p", + "kibana.alert.rule.category": "Inventory", + "kibana.alert.rule.consumer": "alerts", + "kibana.alert.rule.name": "Metrics inventory (one)", + "kibana.alert.rule.params": "{\"nodeType\":\"host\",\"criteria\":[{\"metric\":\"cpu\",\"comparator\":\">\",\"threshold\":[40],\"timeSize\":1,\"timeUnit\":\"m\",\"customMetric\":{\"type\":\"custom\",\"id\":\"alert-custom-metric\",\"field\":\"\",\"aggregation\":\"avg\"}}],\"sourceId\":\"default\"}", + "kibana.alert.rule.producer": "infrastructure", + "kibana.alert.rule.rule_type_id": "metrics.alert.inventory.threshold", + "kibana.alert.rule.uuid": "f95ef340-30eb-11ec-9819-c5cd0facebad", + "kibana.alert.start": "2021-10-19T15:10:59.640Z", + "kibana.alert.status": "recovered", + "kibana.alert.time_range": { + "gte": "2021-10-19T15:10:59.640Z", + "lte": "2021-10-19T15:12:02.607Z" + }, + "kibana.alert.uuid": "c511bdea-2eba-441a-8d77-b0ea83e16b6f", + "kibana.alert.workflow_status": "open", + "kibana.space_ids": [ + "default" + ], + "kibana.version": "8.0.0", + "tags": [] + } + } +} + +{ + "type": "doc", + "value": { + "id": "73e818c0-2a52-4805-88bc-2236be4f0f78", + "index": ".internal.alerts-observability.metrics.alerts-default-000001", + "source": { + "@timestamp": "2021-10-19T15:12:02.607Z", + "event.action": "close", + "event.kind": "signal", + "kibana.alert.duration.us": 62967000, + "kibana.alert.end": "2021-10-19T15:12:02.607Z", + "kibana.alert.instance.id": "gke-edge-oblt-default-pool-350b44de-v7vb", + "kibana.alert.reason": "CPU usage is greater than a threshold of 40 (current value is 40.1%) for gke-edge-oblt-default-pool-350b44de-v7vb", + "kibana.alert.rule.category": "Inventory", + "kibana.alert.rule.consumer": "alerts", + "kibana.alert.rule.name": "Metrics inventory (one)", + "kibana.alert.rule.params": "{\"nodeType\":\"host\",\"criteria\":[{\"metric\":\"cpu\",\"comparator\":\">\",\"threshold\":[40],\"timeSize\":1,\"timeUnit\":\"m\",\"customMetric\":{\"type\":\"custom\",\"id\":\"alert-custom-metric\",\"field\":\"\",\"aggregation\":\"avg\"}}],\"sourceId\":\"default\"}", + "kibana.alert.rule.producer": "infrastructure", + "kibana.alert.rule.rule_type_id": "metrics.alert.inventory.threshold", + "kibana.alert.rule.uuid": "f95ef340-30eb-11ec-9819-c5cd0facebad", + "kibana.alert.start": "2021-10-19T15:10:59.640Z", + "kibana.alert.status": "recovered", + "kibana.alert.time_range": { + "gte": "2021-10-19T15:10:59.640Z", + "lte": "2021-10-19T15:12:02.607Z" + }, + "kibana.alert.uuid": "73e818c0-2a52-4805-88bc-2236be4f0f78", + "kibana.alert.workflow_status": "open", + "kibana.space_ids": [ + "default" + ], + "kibana.version": "8.0.0", + "tags": [] + } + } +} + +{ + "type": "doc", + "value": { + "id": "295b2add-c83b-426c-94e9-8356b5526c99", + "index": ".internal.alerts-observability.metrics.alerts-default-000001", + "source": { + "@timestamp": "2021-10-19T15:11:35.649Z", + "event.action": "close", + "event.kind": "signal", + "kibana.alert.duration.us": 189075000, + "kibana.alert.end": "2021-10-19T15:11:35.649Z", + "kibana.alert.instance.id": "*", + "kibana.alert.reason": "system.cpu.user.pct is greater than a threshold of 115% (current value is 123%) for *", + "kibana.alert.rule.category": "Metric threshold", + "kibana.alert.rule.consumer": "alerts", + "kibana.alert.rule.name": "Metrics threshold (one)", + "kibana.alert.rule.producer": "infrastructure", + "kibana.alert.rule.rule_type_id": "metrics.alert.threshold", + "kibana.alert.rule.uuid": "a57eabc0-30ec-11ec-9819-c5cd0facebad", + "kibana.alert.start": "2021-10-19T15:08:26.574Z", + "kibana.alert.status": "recovered", + "kibana.alert.time_range": { + "gte": "2021-10-19T15:08:26.574Z", + "lte": "2021-10-19T15:11:35.649Z" + }, + "kibana.alert.uuid": "295b2add-c83b-426c-94e9-8356b5526c99", + "kibana.alert.workflow_status": "open", + "kibana.space_ids": [ + "default" + ], + "kibana.version": "8.0.0", + "tags": [] + } + } +} + +{ + "type": "doc", + "value": { + "id": "0a36921f-45e9-40f6-b066-f4358bbb95c2", + "index": ".internal.alerts-observability.metrics.alerts-default-000001", + "source": { + "@timestamp": "2021-10-19T15:05:17.646Z", + "event.action": "close", + "event.kind": "signal", + "kibana.alert.duration.us": 63080000, + "kibana.alert.end": "2021-10-19T15:05:17.646Z", + "kibana.alert.instance.id": "*", + "kibana.alert.reason": "system.cpu.user.pct is greater than a threshold of 115% (current value is 121.7%) for *", + "kibana.alert.rule.category": "Metric threshold", + "kibana.alert.rule.consumer": "alerts", + "kibana.alert.rule.name": "Metrics threshold (one)", + "kibana.alert.rule.producer": "infrastructure", + "kibana.alert.rule.rule_type_id": "metrics.alert.threshold", + "kibana.alert.rule.uuid": "a57eabc0-30ec-11ec-9819-c5cd0facebad", + "kibana.alert.start": "2021-10-19T15:04:14.566Z", + "kibana.alert.status": "recovered", + "kibana.alert.time_range": { + "gte": "2021-10-19T15:04:14.566Z", + "lte": "2021-10-19T15:05:17.646Z" + }, + "kibana.alert.uuid": "0a36921f-45e9-40f6-b066-f4358bbb95c2", + "kibana.alert.workflow_status": "closed", + "kibana.space_ids": [ + "default" + ], + "kibana.version": "8.0.0", + "tags": [] + } + } +} diff --git a/x-pack/test/functional/es_archives/security_solution/alerts/8.1.0/data.json b/x-pack/test/functional/es_archives/security_solution/alerts/8.1.0/data.json new file mode 100644 index 00000000000000..3fe96e71928579 --- /dev/null +++ b/x-pack/test/functional/es_archives/security_solution/alerts/8.1.0/data.json @@ -0,0 +1,8186 @@ +{ + "type": "doc", + "value": { + "index": ".internal.alerts-security.alerts-default-000001", + "id": "30a75fe46d3dbdfab55982036f77a8d60e2d1112e96f277c3b8c22f9bb57817a", + "_score": 1, + "source": { + "kibana.version": "8.1.0", + "kibana.alert.rule.category": "Indicator Match Rule", + "kibana.alert.rule.consumer": "siem", + "kibana.alert.rule.execution.uuid": "63219e9b-045c-4e91-9e9d-3584663bc0be", + "kibana.alert.rule.name": "threat-match-rule", + "kibana.alert.rule.producer": "siem", + "kibana.alert.rule.rule_type_id": "siem.indicatorRule", + "kibana.alert.rule.uuid": "031d5c00-a72f-11ec-a8a3-7b1c8077fc3e", + "kibana.space_ids": [ + "default" + ], + "kibana.alert.rule.tags": [], + "@timestamp": "2022-03-19T02:48:12.634Z", + "agent": { + "name": "security-linux-1.example.dev", + "id": "d8f66724-3cf2-437c-b124-6ac9fb0e2311", + "type": "filebeat", + "version": "8.1.0" + }, + "log": { + "file": { + "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" + }, + "offset": 148938 + }, + "cloud": { + "availability_zone": "us-central1-c", + "instance": { + "name": "security-linux-1", + "id": "8995531128842994872" + }, + "provider": "gcp", + "service": { + "name": "GCE" + }, + "machine": { + "type": "g1-small" + }, + "project": { + "id": "elastic-siem" + }, + "account": { + "id": "elastic-siem" + } + }, + "ecs": { + "version": "8.1.0" + }, + "host": { + "hostname": "security-linux-1", + "os": { + "kernel": "4.19.0-18-cloud-amd64", + "codename": "buster", + "name": "Debian GNU/Linux", + "type": "linux", + "family": "debian", + "version": "10 (buster)", + "platform": "debian" + }, + "containerized": false, + "ip": "11.200.0.194", + "name": "security-linux-1", + "architecture": "x86_64" + }, + "service.name": "filebeat", + "message": "Status message.", + "data_stream": { + "namespace": "default", + "type": "logs", + "dataset": "elastic_agent.filebeat" + }, + "threat": { + "enrichments": [ + { + "indicator": {}, + "feed": {}, + "matched": { + "atomic": "security-linux-1", + "field": "host.name", + "id": "XhEToH8BK09aFtXZBFPs", + "index": "threat-index-000001", + "type": "indicator_match_rule" + } + } + ] + }, + "event.agent_id_status": "verified", + "event.ingested": "2022-03-19T02:47:57.376Z", + "event.dataset": "elastic_agent.filebeat", + "kibana.alert.ancestors": [ + { + "id": "ahEToH8BK09aFtXZFVMq", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "kibana.alert.status": "active", + "kibana.alert.workflow_status": "open", + "kibana.alert.depth": 1, + "kibana.alert.reason": "event on security-linux-1 created low alert threat-match-rule.", + "kibana.alert.severity": "low", + "kibana.alert.risk_score": 21, + "kibana.alert.rule.parameters": { + "description": "a simple threat match rule", + "risk_score": 21, + "severity": "low", + "license": "", + "author": [], + "false_positives": [], + "from": "now-36000s", + "rule_id": "53000028-120c-4e55-a8c0-db092e05aef4", + "max_signals": 100, + "risk_score_mapping": [], + "severity_mapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptions_list": [], + "immutable": false, + "type": "threat_match", + "language": "kuery", + "index": [ + "events-index-*" + ], + "query": "*", + "filters": [], + "threat_query": "*", + "threat_mapping": [ + { + "entries": [ + { + "field": "host.name", + "type": "mapping", + "value": "host.name" + } + ] + } + ], + "threat_language": "kuery", + "threat_index": [ + "threat-index-*" + ], + "threat_indicator_path": "threat.indicator" + }, + "kibana.alert.rule.actions": [], + "kibana.alert.rule.created_at": "2022-03-19T02:48:10.218Z", + "kibana.alert.rule.created_by": "elastic", + "kibana.alert.rule.enabled": true, + "kibana.alert.rule.interval": "1m", + "kibana.alert.rule.updated_at": "2022-03-19T02:48:10.218Z", + "kibana.alert.rule.updated_by": "elastic", + "kibana.alert.rule.type": "threat_match", + "kibana.alert.rule.description": "a simple threat match rule", + "kibana.alert.rule.risk_score": 21, + "kibana.alert.rule.severity": "low", + "kibana.alert.rule.license": "", + "kibana.alert.rule.author": [], + "kibana.alert.rule.false_positives": [], + "kibana.alert.rule.from": "now-36000s", + "kibana.alert.rule.rule_id": "53000028-120c-4e55-a8c0-db092e05aef4", + "kibana.alert.rule.max_signals": 100, + "kibana.alert.rule.risk_score_mapping": [], + "kibana.alert.rule.severity_mapping": [], + "kibana.alert.rule.threat": [], + "kibana.alert.rule.to": "now", + "kibana.alert.rule.references": [], + "kibana.alert.rule.version": 1, + "kibana.alert.rule.exceptions_list": [], + "kibana.alert.rule.immutable": false, + "kibana.alert.original_time": "2022-03-19T02:47:57.376Z", + "kibana.alert.original_event.agent_id_status": "verified", + "kibana.alert.original_event.ingested": "2022-03-19T02:47:57.376Z", + "kibana.alert.original_event.dataset": "elastic_agent.filebeat", + "event.kind": "signal", + "kibana.alert.uuid": "30a75fe46d3dbdfab55982036f77a8d60e2d1112e96f277c3b8c22f9bb57817a" + } + } +} + +{ + "type": "doc", + "value": { + "index": ".internal.alerts-security.alerts-default-000001", + "id": "500b032158474ac14dc532b49cccbf1be50f2e31cecc5504ed8d01722943aa3e", + "_score": 1, + "source": { + "kibana.version": "8.1.0", + "kibana.alert.rule.category": "Indicator Match Rule", + "kibana.alert.rule.consumer": "siem", + "kibana.alert.rule.execution.uuid": "63219e9b-045c-4e91-9e9d-3584663bc0be", + "kibana.alert.rule.name": "threat-match-rule", + "kibana.alert.rule.producer": "siem", + "kibana.alert.rule.rule_type_id": "siem.indicatorRule", + "kibana.alert.rule.uuid": "031d5c00-a72f-11ec-a8a3-7b1c8077fc3e", + "kibana.space_ids": [ + "default" + ], + "kibana.alert.rule.tags": [], + "@timestamp": "2022-03-19T02:48:12.637Z", + "agent": { + "name": "security-linux-3.example.dev", + "id": "06851da1-73e7-41e3-97d6-ff1d62c98dc5", + "type": "filebeat", + "version": "8.1.0" + }, + "log": { + "file": { + "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" + }, + "offset": 148938 + }, + "cloud": { + "availability_zone": "us-central1-c", + "instance": { + "name": "security-linux-1", + "id": "8995531128842994872" + }, + "provider": "gcp", + "service": { + "name": "GCE" + }, + "machine": { + "type": "g1-small" + }, + "project": { + "id": "elastic-siem" + }, + "account": { + "id": "elastic-siem" + } + }, + "ecs": { + "version": "8.1.0" + }, + "host": { + "hostname": "security-linux-3", + "os": { + "kernel": "4.19.0-18-cloud-amd64", + "codename": "buster", + "name": "Debian GNU/Linux", + "type": "linux", + "family": "debian", + "version": "10 (buster)", + "platform": "debian" + }, + "containerized": false, + "ip": "11.200.0.196", + "name": "security-linux-3", + "architecture": "x86_64" + }, + "service.name": "filebeat", + "message": "Status message.", + "data_stream": { + "namespace": "default", + "type": "logs", + "dataset": "elastic_agent.filebeat" + }, + "threat": { + "enrichments": [ + { + "indicator": {}, + "feed": {}, + "matched": { + "atomic": "security-linux-3", + "field": "host.name", + "id": "YBEToH8BK09aFtXZCFNr", + "index": "threat-index-000001", + "type": "indicator_match_rule" + } + } + ] + }, + "event.agent_id_status": "verified", + "event.ingested": "2022-03-19T02:47:57.047Z", + "event.dataset": "elastic_agent.filebeat", + "kibana.alert.ancestors": [ + { + "id": "aREToH8BK09aFtXZE1Pf", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "kibana.alert.status": "active", + "kibana.alert.workflow_status": "open", + "kibana.alert.depth": 1, + "kibana.alert.reason": "event on security-linux-3 created low alert threat-match-rule.", + "kibana.alert.severity": "low", + "kibana.alert.risk_score": 21, + "kibana.alert.rule.parameters": { + "description": "a simple threat match rule", + "risk_score": 21, + "severity": "low", + "license": "", + "author": [], + "false_positives": [], + "from": "now-36000s", + "rule_id": "53000028-120c-4e55-a8c0-db092e05aef4", + "max_signals": 100, + "risk_score_mapping": [], + "severity_mapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptions_list": [], + "immutable": false, + "type": "threat_match", + "language": "kuery", + "index": [ + "events-index-*" + ], + "query": "*", + "filters": [], + "threat_query": "*", + "threat_mapping": [ + { + "entries": [ + { + "field": "host.name", + "type": "mapping", + "value": "host.name" + } + ] + } + ], + "threat_language": "kuery", + "threat_index": [ + "threat-index-*" + ], + "threat_indicator_path": "threat.indicator" + }, + "kibana.alert.rule.actions": [], + "kibana.alert.rule.created_at": "2022-03-19T02:48:10.218Z", + "kibana.alert.rule.created_by": "elastic", + "kibana.alert.rule.enabled": true, + "kibana.alert.rule.interval": "1m", + "kibana.alert.rule.updated_at": "2022-03-19T02:48:10.218Z", + "kibana.alert.rule.updated_by": "elastic", + "kibana.alert.rule.type": "threat_match", + "kibana.alert.rule.description": "a simple threat match rule", + "kibana.alert.rule.risk_score": 21, + "kibana.alert.rule.severity": "low", + "kibana.alert.rule.license": "", + "kibana.alert.rule.author": [], + "kibana.alert.rule.false_positives": [], + "kibana.alert.rule.from": "now-36000s", + "kibana.alert.rule.rule_id": "53000028-120c-4e55-a8c0-db092e05aef4", + "kibana.alert.rule.max_signals": 100, + "kibana.alert.rule.risk_score_mapping": [], + "kibana.alert.rule.severity_mapping": [], + "kibana.alert.rule.threat": [], + "kibana.alert.rule.to": "now", + "kibana.alert.rule.references": [], + "kibana.alert.rule.version": 1, + "kibana.alert.rule.exceptions_list": [], + "kibana.alert.rule.immutable": false, + "kibana.alert.original_time": "2022-03-19T02:47:57.047Z", + "kibana.alert.original_event.agent_id_status": "verified", + "kibana.alert.original_event.ingested": "2022-03-19T02:47:57.047Z", + "kibana.alert.original_event.dataset": "elastic_agent.filebeat", + "event.kind": "signal", + "kibana.alert.uuid": "500b032158474ac14dc532b49cccbf1be50f2e31cecc5504ed8d01722943aa3e" + } + } +} + +{ + "type": "doc", + "value": { + "index": ".internal.alerts-security.alerts-default-000001", + "id": "b8232f895189bcecf3c87550c54c9f24dd8c3606c3bfc3f74373f3eb017597df", + "_score": 1, + "source": { + "kibana.version": "8.1.0", + "kibana.alert.rule.category": "Indicator Match Rule", + "kibana.alert.rule.consumer": "siem", + "kibana.alert.rule.execution.uuid": "63219e9b-045c-4e91-9e9d-3584663bc0be", + "kibana.alert.rule.name": "threat-match-rule", + "kibana.alert.rule.producer": "siem", + "kibana.alert.rule.rule_type_id": "siem.indicatorRule", + "kibana.alert.rule.uuid": "031d5c00-a72f-11ec-a8a3-7b1c8077fc3e", + "kibana.space_ids": [ + "default" + ], + "kibana.alert.rule.tags": [], + "@timestamp": "2022-03-19T02:48:12.643Z", + "agent": { + "name": "security-linux-2.example.dev", + "id": "87c417dd-08d6-4e24-ad69-285cb8de84e9", + "type": "filebeat", + "version": "8.1.0" + }, + "log": { + "file": { + "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" + }, + "offset": 148938 + }, + "cloud": { + "availability_zone": "us-central1-c", + "instance": { + "name": "security-linux-1", + "id": "8995531128842994872" + }, + "provider": "gcp", + "service": { + "name": "GCE" + }, + "machine": { + "type": "g1-small" + }, + "project": { + "id": "elastic-siem" + }, + "account": { + "id": "elastic-siem" + } + }, + "ecs": { + "version": "8.1.0" + }, + "host": { + "hostname": "security-linux-2", + "os": { + "kernel": "4.19.0-18-cloud-amd64", + "codename": "buster", + "name": "Debian GNU/Linux", + "type": "linux", + "family": "debian", + "version": "10 (buster)", + "platform": "debian" + }, + "containerized": false, + "ip": "11.200.0.195", + "name": "security-linux-2", + "architecture": "x86_64" + }, + "service.name": "filebeat", + "message": "Status message.", + "data_stream": { + "namespace": "default", + "type": "logs", + "dataset": "elastic_agent.filebeat" + }, + "threat": { + "enrichments": [ + { + "indicator": {}, + "feed": {}, + "matched": { + "atomic": "security-linux-2", + "field": "host.name", + "id": "XxEToH8BK09aFtXZB1Mn", + "index": "threat-index-000001", + "type": "indicator_match_rule" + } + } + ] + }, + "event.agent_id_status": "verified", + "event.ingested": "2022-03-19T02:47:56.723Z", + "event.dataset": "elastic_agent.filebeat", + "kibana.alert.ancestors": [ + { + "id": "aBEToH8BK09aFtXZElOb", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "kibana.alert.status": "active", + "kibana.alert.workflow_status": "open", + "kibana.alert.depth": 1, + "kibana.alert.reason": "event on security-linux-2 created low alert threat-match-rule.", + "kibana.alert.severity": "low", + "kibana.alert.risk_score": 21, + "kibana.alert.rule.parameters": { + "description": "a simple threat match rule", + "risk_score": 21, + "severity": "low", + "license": "", + "author": [], + "false_positives": [], + "from": "now-36000s", + "rule_id": "53000028-120c-4e55-a8c0-db092e05aef4", + "max_signals": 100, + "risk_score_mapping": [], + "severity_mapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptions_list": [], + "immutable": false, + "type": "threat_match", + "language": "kuery", + "index": [ + "events-index-*" + ], + "query": "*", + "filters": [], + "threat_query": "*", + "threat_mapping": [ + { + "entries": [ + { + "field": "host.name", + "type": "mapping", + "value": "host.name" + } + ] + } + ], + "threat_language": "kuery", + "threat_index": [ + "threat-index-*" + ], + "threat_indicator_path": "threat.indicator" + }, + "kibana.alert.rule.actions": [], + "kibana.alert.rule.created_at": "2022-03-19T02:48:10.218Z", + "kibana.alert.rule.created_by": "elastic", + "kibana.alert.rule.enabled": true, + "kibana.alert.rule.interval": "1m", + "kibana.alert.rule.updated_at": "2022-03-19T02:48:10.218Z", + "kibana.alert.rule.updated_by": "elastic", + "kibana.alert.rule.type": "threat_match", + "kibana.alert.rule.description": "a simple threat match rule", + "kibana.alert.rule.risk_score": 21, + "kibana.alert.rule.severity": "low", + "kibana.alert.rule.license": "", + "kibana.alert.rule.author": [], + "kibana.alert.rule.false_positives": [], + "kibana.alert.rule.from": "now-36000s", + "kibana.alert.rule.rule_id": "53000028-120c-4e55-a8c0-db092e05aef4", + "kibana.alert.rule.max_signals": 100, + "kibana.alert.rule.risk_score_mapping": [], + "kibana.alert.rule.severity_mapping": [], + "kibana.alert.rule.threat": [], + "kibana.alert.rule.to": "now", + "kibana.alert.rule.references": [], + "kibana.alert.rule.version": 1, + "kibana.alert.rule.exceptions_list": [], + "kibana.alert.rule.immutable": false, + "kibana.alert.original_time": "2022-03-19T02:47:56.723Z", + "kibana.alert.original_event.agent_id_status": "verified", + "kibana.alert.original_event.ingested": "2022-03-19T02:47:56.723Z", + "kibana.alert.original_event.dataset": "elastic_agent.filebeat", + "event.kind": "signal", + "kibana.alert.uuid": "b8232f895189bcecf3c87550c54c9f24dd8c3606c3bfc3f74373f3eb017597df" + } + } +} + +{ + "type": "doc", + "value": { + "index": ".internal.alerts-security.alerts-default-000001", + "id": "f3bbdf17847c703e37dca942dc6c1db69eb8af18a74c1f52b6d0bd76c6b3b135", + "_score": 1, + "source": { + "kibana.version": "8.1.0", + "kibana.alert.rule.category": "Indicator Match Rule", + "kibana.alert.rule.consumer": "siem", + "kibana.alert.rule.execution.uuid": "63219e9b-045c-4e91-9e9d-3584663bc0be", + "kibana.alert.rule.name": "threat-match-rule", + "kibana.alert.rule.producer": "siem", + "kibana.alert.rule.rule_type_id": "siem.indicatorRule", + "kibana.alert.rule.uuid": "031d5c00-a72f-11ec-a8a3-7b1c8077fc3e", + "kibana.space_ids": [ + "default" + ], + "kibana.alert.rule.tags": [], + "@timestamp": "2022-03-19T02:48:12.646Z", + "agent": { + "name": "security-linux-1.example.dev", + "id": "d8f66724-3cf2-437c-b124-6ac9fb0e2311", + "type": "filebeat", + "version": "8.1.0" + }, + "log": { + "file": { + "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" + }, + "offset": 148938 + }, + "cloud": { + "availability_zone": "us-central1-c", + "instance": { + "name": "security-linux-1", + "id": "8995531128842994872" + }, + "provider": "gcp", + "service": { + "name": "GCE" + }, + "machine": { + "type": "g1-small" + }, + "project": { + "id": "elastic-siem" + }, + "account": { + "id": "elastic-siem" + } + }, + "ecs": { + "version": "8.1.0" + }, + "host": { + "hostname": "security-linux-1", + "os": { + "kernel": "4.19.0-18-cloud-amd64", + "codename": "buster", + "name": "Debian GNU/Linux", + "type": "linux", + "family": "debian", + "version": "10 (buster)", + "platform": "debian" + }, + "containerized": false, + "ip": "11.200.0.194", + "name": "security-linux-1", + "architecture": "x86_64" + }, + "service.name": "filebeat", + "message": "Status message.", + "data_stream": { + "namespace": "default", + "type": "logs", + "dataset": "elastic_agent.filebeat" + }, + "threat": { + "enrichments": [ + { + "indicator": {}, + "feed": {}, + "matched": { + "atomic": "security-linux-1", + "field": "host.name", + "id": "XhEToH8BK09aFtXZBFPs", + "index": "threat-index-000001", + "type": "indicator_match_rule" + } + } + ] + }, + "event.agent_id_status": "verified", + "event.ingested": "2022-03-19T02:47:56.372Z", + "event.dataset": "elastic_agent.filebeat", + "kibana.alert.ancestors": [ + { + "id": "ZxEToH8BK09aFtXZEVNR", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "kibana.alert.status": "active", + "kibana.alert.workflow_status": "open", + "kibana.alert.depth": 1, + "kibana.alert.reason": "event on security-linux-1 created low alert threat-match-rule.", + "kibana.alert.severity": "low", + "kibana.alert.risk_score": 21, + "kibana.alert.rule.parameters": { + "description": "a simple threat match rule", + "risk_score": 21, + "severity": "low", + "license": "", + "author": [], + "false_positives": [], + "from": "now-36000s", + "rule_id": "53000028-120c-4e55-a8c0-db092e05aef4", + "max_signals": 100, + "risk_score_mapping": [], + "severity_mapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptions_list": [], + "immutable": false, + "type": "threat_match", + "language": "kuery", + "index": [ + "events-index-*" + ], + "query": "*", + "filters": [], + "threat_query": "*", + "threat_mapping": [ + { + "entries": [ + { + "field": "host.name", + "type": "mapping", + "value": "host.name" + } + ] + } + ], + "threat_language": "kuery", + "threat_index": [ + "threat-index-*" + ], + "threat_indicator_path": "threat.indicator" + }, + "kibana.alert.rule.actions": [], + "kibana.alert.rule.created_at": "2022-03-19T02:48:10.218Z", + "kibana.alert.rule.created_by": "elastic", + "kibana.alert.rule.enabled": true, + "kibana.alert.rule.interval": "1m", + "kibana.alert.rule.updated_at": "2022-03-19T02:48:10.218Z", + "kibana.alert.rule.updated_by": "elastic", + "kibana.alert.rule.type": "threat_match", + "kibana.alert.rule.description": "a simple threat match rule", + "kibana.alert.rule.risk_score": 21, + "kibana.alert.rule.severity": "low", + "kibana.alert.rule.license": "", + "kibana.alert.rule.author": [], + "kibana.alert.rule.false_positives": [], + "kibana.alert.rule.from": "now-36000s", + "kibana.alert.rule.rule_id": "53000028-120c-4e55-a8c0-db092e05aef4", + "kibana.alert.rule.max_signals": 100, + "kibana.alert.rule.risk_score_mapping": [], + "kibana.alert.rule.severity_mapping": [], + "kibana.alert.rule.threat": [], + "kibana.alert.rule.to": "now", + "kibana.alert.rule.references": [], + "kibana.alert.rule.version": 1, + "kibana.alert.rule.exceptions_list": [], + "kibana.alert.rule.immutable": false, + "kibana.alert.original_time": "2022-03-19T02:47:56.372Z", + "kibana.alert.original_event.agent_id_status": "verified", + "kibana.alert.original_event.ingested": "2022-03-19T02:47:56.372Z", + "kibana.alert.original_event.dataset": "elastic_agent.filebeat", + "event.kind": "signal", + "kibana.alert.uuid": "f3bbdf17847c703e37dca942dc6c1db69eb8af18a74c1f52b6d0bd76c6b3b135" + } + } +} + +{ + "type": "doc", + "value": { + "index": ".internal.alerts-security.alerts-default-000001", + "id": "170865e675eda76202f0095b23869d8d0726df4c91a343876df38b566bf1e57d", + "_score": 1, + "source": { + "kibana.version": "8.1.0", + "kibana.alert.rule.category": "Indicator Match Rule", + "kibana.alert.rule.consumer": "siem", + "kibana.alert.rule.execution.uuid": "63219e9b-045c-4e91-9e9d-3584663bc0be", + "kibana.alert.rule.name": "threat-match-rule", + "kibana.alert.rule.producer": "siem", + "kibana.alert.rule.rule_type_id": "siem.indicatorRule", + "kibana.alert.rule.uuid": "031d5c00-a72f-11ec-a8a3-7b1c8077fc3e", + "kibana.space_ids": [ + "default" + ], + "kibana.alert.rule.tags": [], + "@timestamp": "2022-03-19T02:48:12.650Z", + "agent": { + "name": "security-linux-3.example.dev", + "id": "06851da1-73e7-41e3-97d6-ff1d62c98dc5", + "type": "filebeat", + "version": "8.1.0" + }, + "log": { + "file": { + "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" + }, + "offset": 148938 + }, + "cloud": { + "availability_zone": "us-central1-c", + "instance": { + "name": "security-linux-1", + "id": "8995531128842994872" + }, + "provider": "gcp", + "service": { + "name": "GCE" + }, + "machine": { + "type": "g1-small" + }, + "project": { + "id": "elastic-siem" + }, + "account": { + "id": "elastic-siem" + } + }, + "ecs": { + "version": "8.1.0" + }, + "host": { + "hostname": "security-linux-3", + "os": { + "kernel": "4.19.0-18-cloud-amd64", + "codename": "buster", + "name": "Debian GNU/Linux", + "type": "linux", + "family": "debian", + "version": "10 (buster)", + "platform": "debian" + }, + "containerized": false, + "ip": "11.200.0.196", + "name": "security-linux-3", + "architecture": "x86_64" + }, + "service.name": "filebeat", + "message": "Status message.", + "data_stream": { + "namespace": "default", + "type": "logs", + "dataset": "elastic_agent.filebeat" + }, + "threat": { + "enrichments": [ + { + "indicator": {}, + "feed": {}, + "matched": { + "atomic": "security-linux-3", + "field": "host.name", + "id": "YBEToH8BK09aFtXZCFNr", + "index": "threat-index-000001", + "type": "indicator_match_rule" + } + } + ] + }, + "event.agent_id_status": "verified", + "event.ingested": "2022-03-19T02:47:56.044Z", + "event.dataset": "elastic_agent.filebeat", + "kibana.alert.ancestors": [ + { + "id": "ZhEToH8BK09aFtXZD1P3", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "kibana.alert.status": "active", + "kibana.alert.workflow_status": "open", + "kibana.alert.depth": 1, + "kibana.alert.reason": "event on security-linux-3 created low alert threat-match-rule.", + "kibana.alert.severity": "low", + "kibana.alert.risk_score": 21, + "kibana.alert.rule.parameters": { + "description": "a simple threat match rule", + "risk_score": 21, + "severity": "low", + "license": "", + "author": [], + "false_positives": [], + "from": "now-36000s", + "rule_id": "53000028-120c-4e55-a8c0-db092e05aef4", + "max_signals": 100, + "risk_score_mapping": [], + "severity_mapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptions_list": [], + "immutable": false, + "type": "threat_match", + "language": "kuery", + "index": [ + "events-index-*" + ], + "query": "*", + "filters": [], + "threat_query": "*", + "threat_mapping": [ + { + "entries": [ + { + "field": "host.name", + "type": "mapping", + "value": "host.name" + } + ] + } + ], + "threat_language": "kuery", + "threat_index": [ + "threat-index-*" + ], + "threat_indicator_path": "threat.indicator" + }, + "kibana.alert.rule.actions": [], + "kibana.alert.rule.created_at": "2022-03-19T02:48:10.218Z", + "kibana.alert.rule.created_by": "elastic", + "kibana.alert.rule.enabled": true, + "kibana.alert.rule.interval": "1m", + "kibana.alert.rule.updated_at": "2022-03-19T02:48:10.218Z", + "kibana.alert.rule.updated_by": "elastic", + "kibana.alert.rule.type": "threat_match", + "kibana.alert.rule.description": "a simple threat match rule", + "kibana.alert.rule.risk_score": 21, + "kibana.alert.rule.severity": "low", + "kibana.alert.rule.license": "", + "kibana.alert.rule.author": [], + "kibana.alert.rule.false_positives": [], + "kibana.alert.rule.from": "now-36000s", + "kibana.alert.rule.rule_id": "53000028-120c-4e55-a8c0-db092e05aef4", + "kibana.alert.rule.max_signals": 100, + "kibana.alert.rule.risk_score_mapping": [], + "kibana.alert.rule.severity_mapping": [], + "kibana.alert.rule.threat": [], + "kibana.alert.rule.to": "now", + "kibana.alert.rule.references": [], + "kibana.alert.rule.version": 1, + "kibana.alert.rule.exceptions_list": [], + "kibana.alert.rule.immutable": false, + "kibana.alert.original_time": "2022-03-19T02:47:56.044Z", + "kibana.alert.original_event.agent_id_status": "verified", + "kibana.alert.original_event.ingested": "2022-03-19T02:47:56.044Z", + "kibana.alert.original_event.dataset": "elastic_agent.filebeat", + "event.kind": "signal", + "kibana.alert.uuid": "170865e675eda76202f0095b23869d8d0726df4c91a343876df38b566bf1e57d" + } + } +} + +{ + "type": "doc", + "value": { + "index": ".internal.alerts-security.alerts-default-000001", + "id": "9d94a2a27250e17a68201dbb87848da654faffc0b3e152318b7b987123c169d7", + "_score": 1, + "source": { + "kibana.version": "8.1.0", + "kibana.alert.rule.category": "Indicator Match Rule", + "kibana.alert.rule.consumer": "siem", + "kibana.alert.rule.execution.uuid": "63219e9b-045c-4e91-9e9d-3584663bc0be", + "kibana.alert.rule.name": "threat-match-rule", + "kibana.alert.rule.producer": "siem", + "kibana.alert.rule.rule_type_id": "siem.indicatorRule", + "kibana.alert.rule.uuid": "031d5c00-a72f-11ec-a8a3-7b1c8077fc3e", + "kibana.space_ids": [ + "default" + ], + "kibana.alert.rule.tags": [], + "@timestamp": "2022-03-19T02:48:12.652Z", + "agent": { + "name": "security-linux-2.example.dev", + "id": "87c417dd-08d6-4e24-ad69-285cb8de84e9", + "type": "filebeat", + "version": "8.1.0" + }, + "log": { + "file": { + "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" + }, + "offset": 148938 + }, + "cloud": { + "availability_zone": "us-central1-c", + "instance": { + "name": "security-linux-1", + "id": "8995531128842994872" + }, + "provider": "gcp", + "service": { + "name": "GCE" + }, + "machine": { + "type": "g1-small" + }, + "project": { + "id": "elastic-siem" + }, + "account": { + "id": "elastic-siem" + } + }, + "ecs": { + "version": "8.1.0" + }, + "host": { + "hostname": "security-linux-2", + "os": { + "kernel": "4.19.0-18-cloud-amd64", + "codename": "buster", + "name": "Debian GNU/Linux", + "type": "linux", + "family": "debian", + "version": "10 (buster)", + "platform": "debian" + }, + "containerized": false, + "ip": "11.200.0.195", + "name": "security-linux-2", + "architecture": "x86_64" + }, + "service.name": "filebeat", + "message": "Status message.", + "data_stream": { + "namespace": "default", + "type": "logs", + "dataset": "elastic_agent.filebeat" + }, + "threat": { + "enrichments": [ + { + "indicator": {}, + "feed": {}, + "matched": { + "atomic": "security-linux-2", + "field": "host.name", + "id": "XxEToH8BK09aFtXZB1Mn", + "index": "threat-index-000001", + "type": "indicator_match_rule" + } + } + ] + }, + "event.agent_id_status": "verified", + "event.ingested": "2022-03-19T02:47:55.722Z", + "event.dataset": "elastic_agent.filebeat", + "kibana.alert.ancestors": [ + { + "id": "ZREToH8BK09aFtXZDlOv", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "kibana.alert.status": "active", + "kibana.alert.workflow_status": "open", + "kibana.alert.depth": 1, + "kibana.alert.reason": "event on security-linux-2 created low alert threat-match-rule.", + "kibana.alert.severity": "low", + "kibana.alert.risk_score": 21, + "kibana.alert.rule.parameters": { + "description": "a simple threat match rule", + "risk_score": 21, + "severity": "low", + "license": "", + "author": [], + "false_positives": [], + "from": "now-36000s", + "rule_id": "53000028-120c-4e55-a8c0-db092e05aef4", + "max_signals": 100, + "risk_score_mapping": [], + "severity_mapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptions_list": [], + "immutable": false, + "type": "threat_match", + "language": "kuery", + "index": [ + "events-index-*" + ], + "query": "*", + "filters": [], + "threat_query": "*", + "threat_mapping": [ + { + "entries": [ + { + "field": "host.name", + "type": "mapping", + "value": "host.name" + } + ] + } + ], + "threat_language": "kuery", + "threat_index": [ + "threat-index-*" + ], + "threat_indicator_path": "threat.indicator" + }, + "kibana.alert.rule.actions": [], + "kibana.alert.rule.created_at": "2022-03-19T02:48:10.218Z", + "kibana.alert.rule.created_by": "elastic", + "kibana.alert.rule.enabled": true, + "kibana.alert.rule.interval": "1m", + "kibana.alert.rule.updated_at": "2022-03-19T02:48:10.218Z", + "kibana.alert.rule.updated_by": "elastic", + "kibana.alert.rule.type": "threat_match", + "kibana.alert.rule.description": "a simple threat match rule", + "kibana.alert.rule.risk_score": 21, + "kibana.alert.rule.severity": "low", + "kibana.alert.rule.license": "", + "kibana.alert.rule.author": [], + "kibana.alert.rule.false_positives": [], + "kibana.alert.rule.from": "now-36000s", + "kibana.alert.rule.rule_id": "53000028-120c-4e55-a8c0-db092e05aef4", + "kibana.alert.rule.max_signals": 100, + "kibana.alert.rule.risk_score_mapping": [], + "kibana.alert.rule.severity_mapping": [], + "kibana.alert.rule.threat": [], + "kibana.alert.rule.to": "now", + "kibana.alert.rule.references": [], + "kibana.alert.rule.version": 1, + "kibana.alert.rule.exceptions_list": [], + "kibana.alert.rule.immutable": false, + "kibana.alert.original_time": "2022-03-19T02:47:55.722Z", + "kibana.alert.original_event.agent_id_status": "verified", + "kibana.alert.original_event.ingested": "2022-03-19T02:47:55.722Z", + "kibana.alert.original_event.dataset": "elastic_agent.filebeat", + "event.kind": "signal", + "kibana.alert.uuid": "9d94a2a27250e17a68201dbb87848da654faffc0b3e152318b7b987123c169d7" + } + } +} + +{ + "type": "doc", + "value": { + "index": ".internal.alerts-security.alerts-default-000001", + "id": "e6e5910a36f102033c316f083b93859ab1c793f7619f2edc946b8d9f016fd8bc", + "_score": 1, + "source": { + "kibana.version": "8.1.0", + "kibana.alert.rule.category": "Indicator Match Rule", + "kibana.alert.rule.consumer": "siem", + "kibana.alert.rule.execution.uuid": "63219e9b-045c-4e91-9e9d-3584663bc0be", + "kibana.alert.rule.name": "threat-match-rule", + "kibana.alert.rule.producer": "siem", + "kibana.alert.rule.rule_type_id": "siem.indicatorRule", + "kibana.alert.rule.uuid": "031d5c00-a72f-11ec-a8a3-7b1c8077fc3e", + "kibana.space_ids": [ + "default" + ], + "kibana.alert.rule.tags": [], + "@timestamp": "2022-03-19T02:48:12.655Z", + "agent": { + "name": "security-linux-1.example.dev", + "id": "d8f66724-3cf2-437c-b124-6ac9fb0e2311", + "type": "filebeat", + "version": "8.1.0" + }, + "log": { + "file": { + "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" + }, + "offset": 148938 + }, + "cloud": { + "availability_zone": "us-central1-c", + "instance": { + "name": "security-linux-1", + "id": "8995531128842994872" + }, + "provider": "gcp", + "service": { + "name": "GCE" + }, + "machine": { + "type": "g1-small" + }, + "project": { + "id": "elastic-siem" + }, + "account": { + "id": "elastic-siem" + } + }, + "ecs": { + "version": "8.1.0" + }, + "host": { + "hostname": "security-linux-1", + "os": { + "kernel": "4.19.0-18-cloud-amd64", + "codename": "buster", + "name": "Debian GNU/Linux", + "type": "linux", + "family": "debian", + "version": "10 (buster)", + "platform": "debian" + }, + "containerized": false, + "ip": "11.200.0.194", + "name": "security-linux-1", + "architecture": "x86_64" + }, + "service.name": "filebeat", + "message": "Status message.", + "data_stream": { + "namespace": "default", + "type": "logs", + "dataset": "elastic_agent.filebeat" + }, + "threat": { + "enrichments": [ + { + "indicator": {}, + "feed": {}, + "matched": { + "atomic": "security-linux-1", + "field": "host.name", + "id": "XhEToH8BK09aFtXZBFPs", + "index": "threat-index-000001", + "type": "indicator_match_rule" + } + } + ] + }, + "event.agent_id_status": "verified", + "event.ingested": "2022-03-19T02:47:55.468Z", + "event.dataset": "elastic_agent.filebeat", + "kibana.alert.ancestors": [ + { + "id": "ZBEToH8BK09aFtXZDVNr", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "kibana.alert.status": "active", + "kibana.alert.workflow_status": "open", + "kibana.alert.depth": 1, + "kibana.alert.reason": "event on security-linux-1 created low alert threat-match-rule.", + "kibana.alert.severity": "low", + "kibana.alert.risk_score": 21, + "kibana.alert.rule.parameters": { + "description": "a simple threat match rule", + "risk_score": 21, + "severity": "low", + "license": "", + "author": [], + "false_positives": [], + "from": "now-36000s", + "rule_id": "53000028-120c-4e55-a8c0-db092e05aef4", + "max_signals": 100, + "risk_score_mapping": [], + "severity_mapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptions_list": [], + "immutable": false, + "type": "threat_match", + "language": "kuery", + "index": [ + "events-index-*" + ], + "query": "*", + "filters": [], + "threat_query": "*", + "threat_mapping": [ + { + "entries": [ + { + "field": "host.name", + "type": "mapping", + "value": "host.name" + } + ] + } + ], + "threat_language": "kuery", + "threat_index": [ + "threat-index-*" + ], + "threat_indicator_path": "threat.indicator" + }, + "kibana.alert.rule.actions": [], + "kibana.alert.rule.created_at": "2022-03-19T02:48:10.218Z", + "kibana.alert.rule.created_by": "elastic", + "kibana.alert.rule.enabled": true, + "kibana.alert.rule.interval": "1m", + "kibana.alert.rule.updated_at": "2022-03-19T02:48:10.218Z", + "kibana.alert.rule.updated_by": "elastic", + "kibana.alert.rule.type": "threat_match", + "kibana.alert.rule.description": "a simple threat match rule", + "kibana.alert.rule.risk_score": 21, + "kibana.alert.rule.severity": "low", + "kibana.alert.rule.license": "", + "kibana.alert.rule.author": [], + "kibana.alert.rule.false_positives": [], + "kibana.alert.rule.from": "now-36000s", + "kibana.alert.rule.rule_id": "53000028-120c-4e55-a8c0-db092e05aef4", + "kibana.alert.rule.max_signals": 100, + "kibana.alert.rule.risk_score_mapping": [], + "kibana.alert.rule.severity_mapping": [], + "kibana.alert.rule.threat": [], + "kibana.alert.rule.to": "now", + "kibana.alert.rule.references": [], + "kibana.alert.rule.version": 1, + "kibana.alert.rule.exceptions_list": [], + "kibana.alert.rule.immutable": false, + "kibana.alert.original_time": "2022-03-19T02:47:55.468Z", + "kibana.alert.original_event.agent_id_status": "verified", + "kibana.alert.original_event.ingested": "2022-03-19T02:47:55.468Z", + "kibana.alert.original_event.dataset": "elastic_agent.filebeat", + "event.kind": "signal", + "kibana.alert.uuid": "e6e5910a36f102033c316f083b93859ab1c793f7619f2edc946b8d9f016fd8bc" + } + } +} + +{ + "type": "doc", + "value": { + "index": ".internal.alerts-security.alerts-default-000001", + "id": "e888b3a14f852c5e81dcc5d5f67a3731862c1eda7ffae502407b8dd8c251c7ba", + "_score": 1, + "source": { + "kibana.version": "8.1.0", + "kibana.alert.rule.category": "Indicator Match Rule", + "kibana.alert.rule.consumer": "siem", + "kibana.alert.rule.execution.uuid": "63219e9b-045c-4e91-9e9d-3584663bc0be", + "kibana.alert.rule.name": "threat-match-rule", + "kibana.alert.rule.producer": "siem", + "kibana.alert.rule.rule_type_id": "siem.indicatorRule", + "kibana.alert.rule.uuid": "031d5c00-a72f-11ec-a8a3-7b1c8077fc3e", + "kibana.space_ids": [ + "default" + ], + "kibana.alert.rule.tags": [], + "@timestamp": "2022-03-19T02:48:12.658Z", + "agent": { + "name": "security-linux-3.example.dev", + "id": "06851da1-73e7-41e3-97d6-ff1d62c98dc5", + "type": "filebeat", + "version": "8.1.0" + }, + "log": { + "file": { + "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" + }, + "offset": 148938 + }, + "cloud": { + "availability_zone": "us-central1-c", + "instance": { + "name": "security-linux-1", + "id": "8995531128842994872" + }, + "provider": "gcp", + "service": { + "name": "GCE" + }, + "machine": { + "type": "g1-small" + }, + "project": { + "id": "elastic-siem" + }, + "account": { + "id": "elastic-siem" + } + }, + "ecs": { + "version": "8.1.0" + }, + "host": { + "hostname": "security-linux-3", + "os": { + "kernel": "4.19.0-18-cloud-amd64", + "codename": "buster", + "name": "Debian GNU/Linux", + "type": "linux", + "family": "debian", + "version": "10 (buster)", + "platform": "debian" + }, + "containerized": false, + "ip": "11.200.0.196", + "name": "security-linux-3", + "architecture": "x86_64" + }, + "service.name": "filebeat", + "message": "Status message.", + "data_stream": { + "namespace": "default", + "type": "logs", + "dataset": "elastic_agent.filebeat" + }, + "threat": { + "enrichments": [ + { + "indicator": {}, + "feed": {}, + "matched": { + "atomic": "security-linux-3", + "field": "host.name", + "id": "YBEToH8BK09aFtXZCFNr", + "index": "threat-index-000001", + "type": "indicator_match_rule" + } + } + ] + }, + "event.agent_id_status": "verified", + "event.ingested": "2022-03-19T02:47:55.150Z", + "event.dataset": "elastic_agent.filebeat", + "kibana.alert.ancestors": [ + { + "id": "YxEToH8BK09aFtXZDFNv", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "kibana.alert.status": "active", + "kibana.alert.workflow_status": "open", + "kibana.alert.depth": 1, + "kibana.alert.reason": "event on security-linux-3 created low alert threat-match-rule.", + "kibana.alert.severity": "low", + "kibana.alert.risk_score": 21, + "kibana.alert.rule.parameters": { + "description": "a simple threat match rule", + "risk_score": 21, + "severity": "low", + "license": "", + "author": [], + "false_positives": [], + "from": "now-36000s", + "rule_id": "53000028-120c-4e55-a8c0-db092e05aef4", + "max_signals": 100, + "risk_score_mapping": [], + "severity_mapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptions_list": [], + "immutable": false, + "type": "threat_match", + "language": "kuery", + "index": [ + "events-index-*" + ], + "query": "*", + "filters": [], + "threat_query": "*", + "threat_mapping": [ + { + "entries": [ + { + "field": "host.name", + "type": "mapping", + "value": "host.name" + } + ] + } + ], + "threat_language": "kuery", + "threat_index": [ + "threat-index-*" + ], + "threat_indicator_path": "threat.indicator" + }, + "kibana.alert.rule.actions": [], + "kibana.alert.rule.created_at": "2022-03-19T02:48:10.218Z", + "kibana.alert.rule.created_by": "elastic", + "kibana.alert.rule.enabled": true, + "kibana.alert.rule.interval": "1m", + "kibana.alert.rule.updated_at": "2022-03-19T02:48:10.218Z", + "kibana.alert.rule.updated_by": "elastic", + "kibana.alert.rule.type": "threat_match", + "kibana.alert.rule.description": "a simple threat match rule", + "kibana.alert.rule.risk_score": 21, + "kibana.alert.rule.severity": "low", + "kibana.alert.rule.license": "", + "kibana.alert.rule.author": [], + "kibana.alert.rule.false_positives": [], + "kibana.alert.rule.from": "now-36000s", + "kibana.alert.rule.rule_id": "53000028-120c-4e55-a8c0-db092e05aef4", + "kibana.alert.rule.max_signals": 100, + "kibana.alert.rule.risk_score_mapping": [], + "kibana.alert.rule.severity_mapping": [], + "kibana.alert.rule.threat": [], + "kibana.alert.rule.to": "now", + "kibana.alert.rule.references": [], + "kibana.alert.rule.version": 1, + "kibana.alert.rule.exceptions_list": [], + "kibana.alert.rule.immutable": false, + "kibana.alert.original_time": "2022-03-19T02:47:55.150Z", + "kibana.alert.original_event.agent_id_status": "verified", + "kibana.alert.original_event.ingested": "2022-03-19T02:47:55.150Z", + "kibana.alert.original_event.dataset": "elastic_agent.filebeat", + "event.kind": "signal", + "kibana.alert.uuid": "e888b3a14f852c5e81dcc5d5f67a3731862c1eda7ffae502407b8dd8c251c7ba" + } + } +} + +{ + "type": "doc", + "value": { + "index": ".internal.alerts-security.alerts-default-000001", + "id": "0e951426cfad980caabb41fee7a1eeae6a0ad18d1391ade9ef112fdab377999c", + "_score": 1, + "source": { + "kibana.version": "8.1.0", + "kibana.alert.rule.category": "Indicator Match Rule", + "kibana.alert.rule.consumer": "siem", + "kibana.alert.rule.execution.uuid": "63219e9b-045c-4e91-9e9d-3584663bc0be", + "kibana.alert.rule.name": "threat-match-rule", + "kibana.alert.rule.producer": "siem", + "kibana.alert.rule.rule_type_id": "siem.indicatorRule", + "kibana.alert.rule.uuid": "031d5c00-a72f-11ec-a8a3-7b1c8077fc3e", + "kibana.space_ids": [ + "default" + ], + "kibana.alert.rule.tags": [], + "@timestamp": "2022-03-19T02:48:12.661Z", + "agent": { + "name": "security-linux-2.example.dev", + "id": "87c417dd-08d6-4e24-ad69-285cb8de84e9", + "type": "filebeat", + "version": "8.1.0" + }, + "log": { + "file": { + "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" + }, + "offset": 148938 + }, + "cloud": { + "availability_zone": "us-central1-c", + "instance": { + "name": "security-linux-1", + "id": "8995531128842994872" + }, + "provider": "gcp", + "service": { + "name": "GCE" + }, + "machine": { + "type": "g1-small" + }, + "project": { + "id": "elastic-siem" + }, + "account": { + "id": "elastic-siem" + } + }, + "ecs": { + "version": "8.1.0" + }, + "host": { + "hostname": "security-linux-2", + "os": { + "kernel": "4.19.0-18-cloud-amd64", + "codename": "buster", + "name": "Debian GNU/Linux", + "type": "linux", + "family": "debian", + "version": "10 (buster)", + "platform": "debian" + }, + "containerized": false, + "ip": "11.200.0.195", + "name": "security-linux-2", + "architecture": "x86_64" + }, + "service.name": "filebeat", + "message": "Status message.", + "data_stream": { + "namespace": "default", + "type": "logs", + "dataset": "elastic_agent.filebeat" + }, + "threat": { + "enrichments": [ + { + "indicator": {}, + "feed": {}, + "matched": { + "atomic": "security-linux-2", + "field": "host.name", + "id": "XxEToH8BK09aFtXZB1Mn", + "index": "threat-index-000001", + "type": "indicator_match_rule" + } + } + ] + }, + "event.agent_id_status": "verified", + "event.ingested": "2022-03-19T02:47:54.820Z", + "event.dataset": "elastic_agent.filebeat", + "kibana.alert.ancestors": [ + { + "id": "YhEToH8BK09aFtXZC1Mt", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "kibana.alert.status": "active", + "kibana.alert.workflow_status": "open", + "kibana.alert.depth": 1, + "kibana.alert.reason": "event on security-linux-2 created low alert threat-match-rule.", + "kibana.alert.severity": "low", + "kibana.alert.risk_score": 21, + "kibana.alert.rule.parameters": { + "description": "a simple threat match rule", + "risk_score": 21, + "severity": "low", + "license": "", + "author": [], + "false_positives": [], + "from": "now-36000s", + "rule_id": "53000028-120c-4e55-a8c0-db092e05aef4", + "max_signals": 100, + "risk_score_mapping": [], + "severity_mapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptions_list": [], + "immutable": false, + "type": "threat_match", + "language": "kuery", + "index": [ + "events-index-*" + ], + "query": "*", + "filters": [], + "threat_query": "*", + "threat_mapping": [ + { + "entries": [ + { + "field": "host.name", + "type": "mapping", + "value": "host.name" + } + ] + } + ], + "threat_language": "kuery", + "threat_index": [ + "threat-index-*" + ], + "threat_indicator_path": "threat.indicator" + }, + "kibana.alert.rule.actions": [], + "kibana.alert.rule.created_at": "2022-03-19T02:48:10.218Z", + "kibana.alert.rule.created_by": "elastic", + "kibana.alert.rule.enabled": true, + "kibana.alert.rule.interval": "1m", + "kibana.alert.rule.updated_at": "2022-03-19T02:48:10.218Z", + "kibana.alert.rule.updated_by": "elastic", + "kibana.alert.rule.type": "threat_match", + "kibana.alert.rule.description": "a simple threat match rule", + "kibana.alert.rule.risk_score": 21, + "kibana.alert.rule.severity": "low", + "kibana.alert.rule.license": "", + "kibana.alert.rule.author": [], + "kibana.alert.rule.false_positives": [], + "kibana.alert.rule.from": "now-36000s", + "kibana.alert.rule.rule_id": "53000028-120c-4e55-a8c0-db092e05aef4", + "kibana.alert.rule.max_signals": 100, + "kibana.alert.rule.risk_score_mapping": [], + "kibana.alert.rule.severity_mapping": [], + "kibana.alert.rule.threat": [], + "kibana.alert.rule.to": "now", + "kibana.alert.rule.references": [], + "kibana.alert.rule.version": 1, + "kibana.alert.rule.exceptions_list": [], + "kibana.alert.rule.immutable": false, + "kibana.alert.original_time": "2022-03-19T02:47:54.820Z", + "kibana.alert.original_event.agent_id_status": "verified", + "kibana.alert.original_event.ingested": "2022-03-19T02:47:54.820Z", + "kibana.alert.original_event.dataset": "elastic_agent.filebeat", + "event.kind": "signal", + "kibana.alert.uuid": "0e951426cfad980caabb41fee7a1eeae6a0ad18d1391ade9ef112fdab377999c" + } + } +} + +{ + "type": "doc", + "value": { + "index": ".internal.alerts-security.alerts-default-000001", + "id": "3fd3725809525f84c67d68e086c889f7046893c2b8ea2dc905af0844a086da51", + "_score": 1, + "source": { + "kibana.version": "8.1.0", + "kibana.alert.rule.category": "Indicator Match Rule", + "kibana.alert.rule.consumer": "siem", + "kibana.alert.rule.execution.uuid": "63219e9b-045c-4e91-9e9d-3584663bc0be", + "kibana.alert.rule.name": "threat-match-rule", + "kibana.alert.rule.producer": "siem", + "kibana.alert.rule.rule_type_id": "siem.indicatorRule", + "kibana.alert.rule.uuid": "031d5c00-a72f-11ec-a8a3-7b1c8077fc3e", + "kibana.space_ids": [ + "default" + ], + "kibana.alert.rule.tags": [], + "@timestamp": "2022-03-19T02:48:12.663Z", + "agent": { + "name": "security-linux-1.example.dev", + "id": "d8f66724-3cf2-437c-b124-6ac9fb0e2311", + "type": "filebeat", + "version": "8.1.0" + }, + "log": { + "file": { + "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" + }, + "offset": 148938 + }, + "cloud": { + "availability_zone": "us-central1-c", + "instance": { + "name": "security-linux-1", + "id": "8995531128842994872" + }, + "provider": "gcp", + "service": { + "name": "GCE" + }, + "machine": { + "type": "g1-small" + }, + "project": { + "id": "elastic-siem" + }, + "account": { + "id": "elastic-siem" + } + }, + "ecs": { + "version": "8.1.0" + }, + "host": { + "hostname": "security-linux-1", + "os": { + "kernel": "4.19.0-18-cloud-amd64", + "codename": "buster", + "name": "Debian GNU/Linux", + "type": "linux", + "family": "debian", + "version": "10 (buster)", + "platform": "debian" + }, + "containerized": false, + "ip": "11.200.0.194", + "name": "security-linux-1", + "architecture": "x86_64" + }, + "service.name": "filebeat", + "message": "Status message.", + "data_stream": { + "namespace": "default", + "type": "logs", + "dataset": "elastic_agent.filebeat" + }, + "threat": { + "enrichments": [ + { + "indicator": {}, + "feed": {}, + "matched": { + "atomic": "security-linux-1", + "field": "host.name", + "id": "XhEToH8BK09aFtXZBFPs", + "index": "threat-index-000001", + "type": "indicator_match_rule" + } + } + ] + }, + "event.agent_id_status": "verified", + "event.ingested": "2022-03-19T02:47:54.442Z", + "event.dataset": "elastic_agent.filebeat", + "kibana.alert.ancestors": [ + { + "id": "YREToH8BK09aFtXZCVO3", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "kibana.alert.status": "active", + "kibana.alert.workflow_status": "open", + "kibana.alert.depth": 1, + "kibana.alert.reason": "event on security-linux-1 created low alert threat-match-rule.", + "kibana.alert.severity": "low", + "kibana.alert.risk_score": 21, + "kibana.alert.rule.parameters": { + "description": "a simple threat match rule", + "risk_score": 21, + "severity": "low", + "license": "", + "author": [], + "false_positives": [], + "from": "now-36000s", + "rule_id": "53000028-120c-4e55-a8c0-db092e05aef4", + "max_signals": 100, + "risk_score_mapping": [], + "severity_mapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptions_list": [], + "immutable": false, + "type": "threat_match", + "language": "kuery", + "index": [ + "events-index-*" + ], + "query": "*", + "filters": [], + "threat_query": "*", + "threat_mapping": [ + { + "entries": [ + { + "field": "host.name", + "type": "mapping", + "value": "host.name" + } + ] + } + ], + "threat_language": "kuery", + "threat_index": [ + "threat-index-*" + ], + "threat_indicator_path": "threat.indicator" + }, + "kibana.alert.rule.actions": [], + "kibana.alert.rule.created_at": "2022-03-19T02:48:10.218Z", + "kibana.alert.rule.created_by": "elastic", + "kibana.alert.rule.enabled": true, + "kibana.alert.rule.interval": "1m", + "kibana.alert.rule.updated_at": "2022-03-19T02:48:10.218Z", + "kibana.alert.rule.updated_by": "elastic", + "kibana.alert.rule.type": "threat_match", + "kibana.alert.rule.description": "a simple threat match rule", + "kibana.alert.rule.risk_score": 21, + "kibana.alert.rule.severity": "low", + "kibana.alert.rule.license": "", + "kibana.alert.rule.author": [], + "kibana.alert.rule.false_positives": [], + "kibana.alert.rule.from": "now-36000s", + "kibana.alert.rule.rule_id": "53000028-120c-4e55-a8c0-db092e05aef4", + "kibana.alert.rule.max_signals": 100, + "kibana.alert.rule.risk_score_mapping": [], + "kibana.alert.rule.severity_mapping": [], + "kibana.alert.rule.threat": [], + "kibana.alert.rule.to": "now", + "kibana.alert.rule.references": [], + "kibana.alert.rule.version": 1, + "kibana.alert.rule.exceptions_list": [], + "kibana.alert.rule.immutable": false, + "kibana.alert.original_time": "2022-03-19T02:47:54.442Z", + "kibana.alert.original_event.agent_id_status": "verified", + "kibana.alert.original_event.ingested": "2022-03-19T02:47:54.442Z", + "kibana.alert.original_event.dataset": "elastic_agent.filebeat", + "event.kind": "signal", + "kibana.alert.uuid": "3fd3725809525f84c67d68e086c889f7046893c2b8ea2dc905af0844a086da51" + } + } +} + +{ + "type": "doc", + "value": { + "index": ".internal.alerts-security.alerts-default-000001", + "id": "b1527c2efcd223c32e446308266072b196af4b40fd7b52f4f48651e07288c106", + "_score": 1, + "source": { + "kibana.version": "8.1.0", + "kibana.alert.rule.category": "Threshold Rule", + "kibana.alert.rule.consumer": "siem", + "kibana.alert.rule.execution.uuid": "42543ad3-fc35-490f-b908-0904009de6b2", + "kibana.alert.rule.name": "threshold-rule", + "kibana.alert.rule.producer": "siem", + "kibana.alert.rule.rule_type_id": "siem.thresholdRule", + "kibana.alert.rule.uuid": "0171a7d0-a72f-11ec-bc9e-ed906a2c068e", + "kibana.space_ids": [ + "default" + ], + "kibana.alert.rule.tags": [], + "@timestamp": "2022-03-19T02:48:09.570Z", + "host.name": "security-linux-1", + "kibana.alert.ancestors": [ + { + "id": "5094535b-4092-5043-a842-ea63799e386b", + "type": "event", + "index": "events-index-*", + "depth": 0 + } + ], + "kibana.alert.status": "active", + "kibana.alert.workflow_status": "open", + "kibana.alert.depth": 1, + "kibana.alert.reason": "event created low alert threshold-rule.", + "kibana.alert.severity": "low", + "kibana.alert.risk_score": 21, + "kibana.alert.rule.parameters": { + "description": "a simple threshold rule", + "risk_score": 21, + "severity": "low", + "license": "", + "author": [], + "false_positives": [], + "from": "now-36000s", + "rule_id": "5e39f5f3-b561-4f4d-9493-7c37d2070f15", + "max_signals": 100, + "risk_score_mapping": [], + "severity_mapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptions_list": [], + "immutable": false, + "type": "threshold", + "language": "kuery", + "index": [ + "events-index-*" + ], + "query": "*", + "filters": [], + "threshold": { + "field": [ + "host.name" + ], + "value": 1 + } + }, + "kibana.alert.rule.actions": [], + "kibana.alert.rule.created_at": "2022-03-19T02:48:07.210Z", + "kibana.alert.rule.created_by": "elastic", + "kibana.alert.rule.enabled": true, + "kibana.alert.rule.interval": "1m", + "kibana.alert.rule.updated_at": "2022-03-19T02:48:08.514Z", + "kibana.alert.rule.updated_by": "elastic", + "kibana.alert.rule.type": "threshold", + "kibana.alert.rule.description": "a simple threshold rule", + "kibana.alert.rule.risk_score": 21, + "kibana.alert.rule.severity": "low", + "kibana.alert.rule.license": "", + "kibana.alert.rule.author": [], + "kibana.alert.rule.false_positives": [], + "kibana.alert.rule.from": "now-36000s", + "kibana.alert.rule.rule_id": "5e39f5f3-b561-4f4d-9493-7c37d2070f15", + "kibana.alert.rule.max_signals": 100, + "kibana.alert.rule.risk_score_mapping": [], + "kibana.alert.rule.severity_mapping": [], + "kibana.alert.rule.threat": [], + "kibana.alert.rule.to": "now", + "kibana.alert.rule.references": [], + "kibana.alert.rule.version": 1, + "kibana.alert.rule.exceptions_list": [], + "kibana.alert.rule.immutable": false, + "kibana.alert.original_time": "2022-03-19T02:47:57.376Z", + "kibana.alert.threshold_result": { + "terms": [ + { + "field": "host.name", + "value": "security-linux-1" + } + ], + "count": 4, + "from": "2022-03-19T02:47:54.442Z" + }, + "event.kind": "signal", + "kibana.alert.uuid": "b1527c2efcd223c32e446308266072b196af4b40fd7b52f4f48651e07288c106" + } + } +} + +{ + "type": "doc", + "value": { + "index": ".internal.alerts-security.alerts-default-000001", + "id": "e8030bc1d3f772588fd553b12015b98bb989536569ce3462170d3640c41a413b", + "_score": 1, + "source": { + "kibana.version": "8.1.0", + "kibana.alert.rule.category": "Threshold Rule", + "kibana.alert.rule.consumer": "siem", + "kibana.alert.rule.execution.uuid": "42543ad3-fc35-490f-b908-0904009de6b2", + "kibana.alert.rule.name": "threshold-rule", + "kibana.alert.rule.producer": "siem", + "kibana.alert.rule.rule_type_id": "siem.thresholdRule", + "kibana.alert.rule.uuid": "0171a7d0-a72f-11ec-bc9e-ed906a2c068e", + "kibana.space_ids": [ + "default" + ], + "kibana.alert.rule.tags": [], + "@timestamp": "2022-03-19T02:48:09.571Z", + "host.name": "security-linux-2", + "kibana.alert.ancestors": [ + { + "id": "c7779a8c-3f89-578e-a66d-4b164f2c40f5", + "type": "event", + "index": "events-index-*", + "depth": 0 + } + ], + "kibana.alert.status": "active", + "kibana.alert.workflow_status": "open", + "kibana.alert.depth": 1, + "kibana.alert.reason": "event created low alert threshold-rule.", + "kibana.alert.severity": "low", + "kibana.alert.risk_score": 21, + "kibana.alert.rule.parameters": { + "description": "a simple threshold rule", + "risk_score": 21, + "severity": "low", + "license": "", + "author": [], + "false_positives": [], + "from": "now-36000s", + "rule_id": "5e39f5f3-b561-4f4d-9493-7c37d2070f15", + "max_signals": 100, + "risk_score_mapping": [], + "severity_mapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptions_list": [], + "immutable": false, + "type": "threshold", + "language": "kuery", + "index": [ + "events-index-*" + ], + "query": "*", + "filters": [], + "threshold": { + "field": [ + "host.name" + ], + "value": 1 + } + }, + "kibana.alert.rule.actions": [], + "kibana.alert.rule.created_at": "2022-03-19T02:48:07.210Z", + "kibana.alert.rule.created_by": "elastic", + "kibana.alert.rule.enabled": true, + "kibana.alert.rule.interval": "1m", + "kibana.alert.rule.updated_at": "2022-03-19T02:48:08.514Z", + "kibana.alert.rule.updated_by": "elastic", + "kibana.alert.rule.type": "threshold", + "kibana.alert.rule.description": "a simple threshold rule", + "kibana.alert.rule.risk_score": 21, + "kibana.alert.rule.severity": "low", + "kibana.alert.rule.license": "", + "kibana.alert.rule.author": [], + "kibana.alert.rule.false_positives": [], + "kibana.alert.rule.from": "now-36000s", + "kibana.alert.rule.rule_id": "5e39f5f3-b561-4f4d-9493-7c37d2070f15", + "kibana.alert.rule.max_signals": 100, + "kibana.alert.rule.risk_score_mapping": [], + "kibana.alert.rule.severity_mapping": [], + "kibana.alert.rule.threat": [], + "kibana.alert.rule.to": "now", + "kibana.alert.rule.references": [], + "kibana.alert.rule.version": 1, + "kibana.alert.rule.exceptions_list": [], + "kibana.alert.rule.immutable": false, + "kibana.alert.original_time": "2022-03-19T02:47:56.723Z", + "kibana.alert.threshold_result": { + "terms": [ + { + "field": "host.name", + "value": "security-linux-2" + } + ], + "count": 3, + "from": "2022-03-19T02:47:54.820Z" + }, + "event.kind": "signal", + "kibana.alert.uuid": "e8030bc1d3f772588fd553b12015b98bb989536569ce3462170d3640c41a413b" + } + } +} + +{ + "type": "doc", + "value": { + "index": ".internal.alerts-security.alerts-default-000001", + "id": "ec81cb5b5bc3cb2fe0a68995827680290072224d48b25e1c50a8bdf0c2319240", + "_score": 1, + "source": { + "kibana.version": "8.1.0", + "kibana.alert.rule.category": "Threshold Rule", + "kibana.alert.rule.consumer": "siem", + "kibana.alert.rule.execution.uuid": "42543ad3-fc35-490f-b908-0904009de6b2", + "kibana.alert.rule.name": "threshold-rule", + "kibana.alert.rule.producer": "siem", + "kibana.alert.rule.rule_type_id": "siem.thresholdRule", + "kibana.alert.rule.uuid": "0171a7d0-a72f-11ec-bc9e-ed906a2c068e", + "kibana.space_ids": [ + "default" + ], + "kibana.alert.rule.tags": [], + "@timestamp": "2022-03-19T02:48:09.573Z", + "host.name": "security-linux-3", + "kibana.alert.ancestors": [ + { + "id": "be16bed6-44b8-5b24-b36b-4852b3c9dd01", + "type": "event", + "index": "events-index-*", + "depth": 0 + } + ], + "kibana.alert.status": "active", + "kibana.alert.workflow_status": "open", + "kibana.alert.depth": 1, + "kibana.alert.reason": "event created low alert threshold-rule.", + "kibana.alert.severity": "low", + "kibana.alert.risk_score": 21, + "kibana.alert.rule.parameters": { + "description": "a simple threshold rule", + "risk_score": 21, + "severity": "low", + "license": "", + "author": [], + "false_positives": [], + "from": "now-36000s", + "rule_id": "5e39f5f3-b561-4f4d-9493-7c37d2070f15", + "max_signals": 100, + "risk_score_mapping": [], + "severity_mapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptions_list": [], + "immutable": false, + "type": "threshold", + "language": "kuery", + "index": [ + "events-index-*" + ], + "query": "*", + "filters": [], + "threshold": { + "field": [ + "host.name" + ], + "value": 1 + } + }, + "kibana.alert.rule.actions": [], + "kibana.alert.rule.created_at": "2022-03-19T02:48:07.210Z", + "kibana.alert.rule.created_by": "elastic", + "kibana.alert.rule.enabled": true, + "kibana.alert.rule.interval": "1m", + "kibana.alert.rule.updated_at": "2022-03-19T02:48:08.514Z", + "kibana.alert.rule.updated_by": "elastic", + "kibana.alert.rule.type": "threshold", + "kibana.alert.rule.description": "a simple threshold rule", + "kibana.alert.rule.risk_score": 21, + "kibana.alert.rule.severity": "low", + "kibana.alert.rule.license": "", + "kibana.alert.rule.author": [], + "kibana.alert.rule.false_positives": [], + "kibana.alert.rule.from": "now-36000s", + "kibana.alert.rule.rule_id": "5e39f5f3-b561-4f4d-9493-7c37d2070f15", + "kibana.alert.rule.max_signals": 100, + "kibana.alert.rule.risk_score_mapping": [], + "kibana.alert.rule.severity_mapping": [], + "kibana.alert.rule.threat": [], + "kibana.alert.rule.to": "now", + "kibana.alert.rule.references": [], + "kibana.alert.rule.version": 1, + "kibana.alert.rule.exceptions_list": [], + "kibana.alert.rule.immutable": false, + "kibana.alert.original_time": "2022-03-19T02:47:57.047Z", + "kibana.alert.threshold_result": { + "terms": [ + { + "field": "host.name", + "value": "security-linux-3" + } + ], + "count": 3, + "from": "2022-03-19T02:47:55.150Z" + }, + "event.kind": "signal", + "kibana.alert.uuid": "ec81cb5b5bc3cb2fe0a68995827680290072224d48b25e1c50a8bdf0c2319240" + } + } +} + +{ + "type": "doc", + "value": { + "index": ".internal.alerts-security.alerts-default-000001", + "id": "c2212cd742aff3560682e4e84c24cc3f7bb5dec5d7e41040065b150225d29712", + "_score": 1, + "source": { + "kibana.version": "8.1.0", + "kibana.alert.rule.category": "Event Correlation Rule", + "kibana.alert.rule.consumer": "siem", + "kibana.alert.rule.execution.uuid": "51d785a9-7d7c-4688-9e64-f7901eef88bb", + "kibana.alert.rule.name": "eql-rule", + "kibana.alert.rule.producer": "siem", + "kibana.alert.rule.rule_type_id": "siem.eqlRule", + "kibana.alert.rule.uuid": "ff7a1d90-a72e-11ec-bc9e-ed906a2c068e", + "kibana.space_ids": [ + "default" + ], + "kibana.alert.rule.tags": [], + "@timestamp": "2022-03-19T02:48:06.802Z", + "agent": { + "name": "security-linux-1.example.dev", + "id": "d8f66724-3cf2-437c-b124-6ac9fb0e2311", + "type": "filebeat", + "version": "8.1.0" + }, + "log": { + "file": { + "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" + }, + "offset": 148938 + }, + "cloud": { + "availability_zone": "us-central1-c", + "instance": { + "name": "security-linux-1", + "id": "8995531128842994872" + }, + "provider": "gcp", + "service": { + "name": "GCE" + }, + "machine": { + "type": "g1-small" + }, + "project": { + "id": "elastic-siem" + }, + "account": { + "id": "elastic-siem" + } + }, + "ecs": { + "version": "8.1.0" + }, + "host": { + "hostname": "security-linux-1", + "os": { + "kernel": "4.19.0-18-cloud-amd64", + "codename": "buster", + "name": "Debian GNU/Linux", + "type": "linux", + "family": "debian", + "version": "10 (buster)", + "platform": "debian" + }, + "containerized": false, + "ip": "11.200.0.194", + "name": "security-linux-1", + "architecture": "x86_64" + }, + "service.name": "filebeat", + "message": "Status message.", + "data_stream": { + "namespace": "default", + "type": "logs", + "dataset": "elastic_agent.filebeat" + }, + "event.agent_id_status": "verified", + "event.ingested": "2022-03-19T02:47:54.442Z", + "event.dataset": "elastic_agent.filebeat", + "kibana.alert.ancestors": [ + { + "id": "YREToH8BK09aFtXZCVO3", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "kibana.alert.status": "active", + "kibana.alert.workflow_status": "open", + "kibana.alert.depth": 1, + "kibana.alert.reason": "event on security-linux-1 created low alert eql-rule.", + "kibana.alert.building_block_type": "default", + "kibana.alert.severity": "low", + "kibana.alert.risk_score": 21, + "kibana.alert.rule.parameters": { + "description": "a simple eql rule", + "risk_score": 21, + "severity": "low", + "license": "", + "author": [], + "false_positives": [], + "from": "now-36000s", + "rule_id": "4dd16f77-5dd2-46c8-a1d9-f1d2ffb56456", + "max_signals": 100, + "risk_score_mapping": [], + "severity_mapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptions_list": [], + "immutable": false, + "type": "eql", + "language": "eql", + "index": [ + "events-index-*" + ], + "query": "sequence [any where true] [any where true]", + "filters": [] + }, + "kibana.alert.rule.actions": [], + "kibana.alert.rule.created_at": "2022-03-19T02:48:04.202Z", + "kibana.alert.rule.created_by": "elastic", + "kibana.alert.rule.enabled": true, + "kibana.alert.rule.interval": "1m", + "kibana.alert.rule.updated_at": "2022-03-19T02:48:05.465Z", + "kibana.alert.rule.updated_by": "elastic", + "kibana.alert.rule.type": "eql", + "kibana.alert.rule.description": "a simple eql rule", + "kibana.alert.rule.risk_score": 21, + "kibana.alert.rule.severity": "low", + "kibana.alert.rule.license": "", + "kibana.alert.rule.author": [], + "kibana.alert.rule.false_positives": [], + "kibana.alert.rule.from": "now-36000s", + "kibana.alert.rule.rule_id": "4dd16f77-5dd2-46c8-a1d9-f1d2ffb56456", + "kibana.alert.rule.max_signals": 100, + "kibana.alert.rule.risk_score_mapping": [], + "kibana.alert.rule.severity_mapping": [], + "kibana.alert.rule.threat": [], + "kibana.alert.rule.to": "now", + "kibana.alert.rule.references": [], + "kibana.alert.rule.version": 1, + "kibana.alert.rule.exceptions_list": [], + "kibana.alert.rule.immutable": false, + "kibana.alert.original_time": "2022-03-19T02:47:54.442Z", + "kibana.alert.original_event.agent_id_status": "verified", + "kibana.alert.original_event.ingested": "2022-03-19T02:47:54.442Z", + "kibana.alert.original_event.dataset": "elastic_agent.filebeat", + "event.kind": "signal", + "kibana.alert.uuid": "c2212cd742aff3560682e4e84c24cc3f7bb5dec5d7e41040065b150225d29712", + "kibana.alert.group.id": "3166e88dc22be20867cf2841d1954fba65bd9969fa24d2bc228db18ff22d460a", + "kibana.alert.group.index": 0 + } + } +} + +{ + "type": "doc", + "value": { + "index": ".internal.alerts-security.alerts-default-000001", + "id": "73293504399a0c0297290010a6da0fc90b424c8b5b4a39c8e2d9b8e30535db6c", + "_score": 1, + "source": { + "kibana.version": "8.1.0", + "kibana.alert.rule.category": "Event Correlation Rule", + "kibana.alert.rule.consumer": "siem", + "kibana.alert.rule.execution.uuid": "51d785a9-7d7c-4688-9e64-f7901eef88bb", + "kibana.alert.rule.name": "eql-rule", + "kibana.alert.rule.producer": "siem", + "kibana.alert.rule.rule_type_id": "siem.eqlRule", + "kibana.alert.rule.uuid": "ff7a1d90-a72e-11ec-bc9e-ed906a2c068e", + "kibana.space_ids": [ + "default" + ], + "kibana.alert.rule.tags": [], + "@timestamp": "2022-03-19T02:48:06.805Z", + "agent": { + "name": "security-linux-2.example.dev", + "id": "87c417dd-08d6-4e24-ad69-285cb8de84e9", + "type": "filebeat", + "version": "8.1.0" + }, + "log": { + "file": { + "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" + }, + "offset": 148938 + }, + "cloud": { + "availability_zone": "us-central1-c", + "instance": { + "name": "security-linux-1", + "id": "8995531128842994872" + }, + "provider": "gcp", + "service": { + "name": "GCE" + }, + "machine": { + "type": "g1-small" + }, + "project": { + "id": "elastic-siem" + }, + "account": { + "id": "elastic-siem" + } + }, + "ecs": { + "version": "8.1.0" + }, + "host": { + "hostname": "security-linux-2", + "os": { + "kernel": "4.19.0-18-cloud-amd64", + "codename": "buster", + "name": "Debian GNU/Linux", + "type": "linux", + "family": "debian", + "version": "10 (buster)", + "platform": "debian" + }, + "containerized": false, + "ip": "11.200.0.195", + "name": "security-linux-2", + "architecture": "x86_64" + }, + "service.name": "filebeat", + "message": "Status message.", + "data_stream": { + "namespace": "default", + "type": "logs", + "dataset": "elastic_agent.filebeat" + }, + "event.agent_id_status": "verified", + "event.ingested": "2022-03-19T02:47:54.820Z", + "event.dataset": "elastic_agent.filebeat", + "kibana.alert.ancestors": [ + { + "id": "YhEToH8BK09aFtXZC1Mt", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "kibana.alert.status": "active", + "kibana.alert.workflow_status": "open", + "kibana.alert.depth": 1, + "kibana.alert.reason": "event on security-linux-2 created low alert eql-rule.", + "kibana.alert.building_block_type": "default", + "kibana.alert.severity": "low", + "kibana.alert.risk_score": 21, + "kibana.alert.rule.parameters": { + "description": "a simple eql rule", + "risk_score": 21, + "severity": "low", + "license": "", + "author": [], + "false_positives": [], + "from": "now-36000s", + "rule_id": "4dd16f77-5dd2-46c8-a1d9-f1d2ffb56456", + "max_signals": 100, + "risk_score_mapping": [], + "severity_mapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptions_list": [], + "immutable": false, + "type": "eql", + "language": "eql", + "index": [ + "events-index-*" + ], + "query": "sequence [any where true] [any where true]", + "filters": [] + }, + "kibana.alert.rule.actions": [], + "kibana.alert.rule.created_at": "2022-03-19T02:48:04.202Z", + "kibana.alert.rule.created_by": "elastic", + "kibana.alert.rule.enabled": true, + "kibana.alert.rule.interval": "1m", + "kibana.alert.rule.updated_at": "2022-03-19T02:48:05.465Z", + "kibana.alert.rule.updated_by": "elastic", + "kibana.alert.rule.type": "eql", + "kibana.alert.rule.description": "a simple eql rule", + "kibana.alert.rule.risk_score": 21, + "kibana.alert.rule.severity": "low", + "kibana.alert.rule.license": "", + "kibana.alert.rule.author": [], + "kibana.alert.rule.false_positives": [], + "kibana.alert.rule.from": "now-36000s", + "kibana.alert.rule.rule_id": "4dd16f77-5dd2-46c8-a1d9-f1d2ffb56456", + "kibana.alert.rule.max_signals": 100, + "kibana.alert.rule.risk_score_mapping": [], + "kibana.alert.rule.severity_mapping": [], + "kibana.alert.rule.threat": [], + "kibana.alert.rule.to": "now", + "kibana.alert.rule.references": [], + "kibana.alert.rule.version": 1, + "kibana.alert.rule.exceptions_list": [], + "kibana.alert.rule.immutable": false, + "kibana.alert.original_time": "2022-03-19T02:47:54.820Z", + "kibana.alert.original_event.agent_id_status": "verified", + "kibana.alert.original_event.ingested": "2022-03-19T02:47:54.820Z", + "kibana.alert.original_event.dataset": "elastic_agent.filebeat", + "event.kind": "signal", + "kibana.alert.uuid": "73293504399a0c0297290010a6da0fc90b424c8b5b4a39c8e2d9b8e30535db6c", + "kibana.alert.group.id": "3166e88dc22be20867cf2841d1954fba65bd9969fa24d2bc228db18ff22d460a", + "kibana.alert.group.index": 1 + } + } +} + +{ + "type": "doc", + "value": { + "index": ".internal.alerts-security.alerts-default-000001", + "id": "3166e88dc22be20867cf2841d1954fba65bd9969fa24d2bc228db18ff22d460a", + "_score": 1, + "source": { + "kibana.version": "8.1.0", + "kibana.alert.rule.category": "Event Correlation Rule", + "kibana.alert.rule.consumer": "siem", + "kibana.alert.rule.execution.uuid": "51d785a9-7d7c-4688-9e64-f7901eef88bb", + "kibana.alert.rule.name": "eql-rule", + "kibana.alert.rule.producer": "siem", + "kibana.alert.rule.rule_type_id": "siem.eqlRule", + "kibana.alert.rule.uuid": "ff7a1d90-a72e-11ec-bc9e-ed906a2c068e", + "kibana.space_ids": [ + "default" + ], + "kibana.alert.rule.tags": [], + "@timestamp": "2022-03-19T02:48:06.806Z", + "agent": { + "type": "filebeat", + "version": "8.1.0" + }, + "log": { + "file": { + "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" + }, + "offset": 148938 + }, + "cloud": { + "availability_zone": "us-central1-c", + "instance": { + "name": "security-linux-1", + "id": "8995531128842994872" + }, + "provider": "gcp", + "service": { + "name": "GCE" + }, + "machine": { + "type": "g1-small" + }, + "project": { + "id": "elastic-siem" + }, + "account": { + "id": "elastic-siem" + } + }, + "ecs": { + "version": "8.1.0" + }, + "host": { + "os": { + "kernel": "4.19.0-18-cloud-amd64", + "codename": "buster", + "name": "Debian GNU/Linux", + "type": "linux", + "family": "debian", + "version": "10 (buster)", + "platform": "debian" + }, + "containerized": false, + "architecture": "x86_64" + }, + "service.name": "filebeat", + "message": "Status message.", + "data_stream": { + "namespace": "default", + "type": "logs", + "dataset": "elastic_agent.filebeat" + }, + "event.agent_id_status": "verified", + "event.dataset": "elastic_agent.filebeat", + "kibana.alert.status": "active", + "kibana.alert.workflow_status": "open", + "kibana.alert.depth": 2, + "kibana.alert.severity": "low", + "kibana.alert.risk_score": 21, + "kibana.alert.rule.parameters": { + "description": "a simple eql rule", + "risk_score": 21, + "severity": "low", + "license": "", + "author": [], + "false_positives": [], + "from": "now-36000s", + "rule_id": "4dd16f77-5dd2-46c8-a1d9-f1d2ffb56456", + "max_signals": 100, + "risk_score_mapping": [], + "severity_mapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptions_list": [], + "immutable": false, + "type": "eql", + "language": "eql", + "index": [ + "events-index-*" + ], + "query": "sequence [any where true] [any where true]", + "filters": [] + }, + "kibana.alert.rule.created_at": "2022-03-19T02:48:04.202Z", + "kibana.alert.rule.created_by": "elastic", + "kibana.alert.rule.enabled": true, + "kibana.alert.rule.interval": "1m", + "kibana.alert.rule.updated_at": "2022-03-19T02:48:05.465Z", + "kibana.alert.rule.updated_by": "elastic", + "kibana.alert.rule.type": "eql", + "kibana.alert.rule.description": "a simple eql rule", + "kibana.alert.rule.risk_score": 21, + "kibana.alert.rule.severity": "low", + "kibana.alert.rule.license": "", + "kibana.alert.rule.author": [], + "kibana.alert.rule.false_positives": [], + "kibana.alert.rule.from": "now-36000s", + "kibana.alert.rule.rule_id": "4dd16f77-5dd2-46c8-a1d9-f1d2ffb56456", + "kibana.alert.rule.max_signals": 100, + "kibana.alert.rule.risk_score_mapping": [], + "kibana.alert.rule.severity_mapping": [], + "kibana.alert.rule.threat": [], + "kibana.alert.rule.to": "now", + "kibana.alert.rule.references": [], + "kibana.alert.rule.version": 1, + "kibana.alert.rule.exceptions_list": [], + "kibana.alert.rule.immutable": false, + "kibana.alert.original_event.agent_id_status": "verified", + "kibana.alert.original_event.dataset": "elastic_agent.filebeat", + "event.kind": "signal", + "event": { + "kind": "signal" + }, + "kibana.alert.ancestors": [ + { + "id": "YREToH8BK09aFtXZCVO3", + "type": "event", + "index": "events-index-000001", + "depth": 0 + }, + { + "id": "c2212cd742aff3560682e4e84c24cc3f7bb5dec5d7e41040065b150225d29712", + "type": "signal", + "index": "", + "depth": 1, + "rule": "ff7a1d90-a72e-11ec-bc9e-ed906a2c068e" + }, + { + "id": "YhEToH8BK09aFtXZC1Mt", + "type": "event", + "index": "events-index-000001", + "depth": 0 + }, + { + "id": "73293504399a0c0297290010a6da0fc90b424c8b5b4a39c8e2d9b8e30535db6c", + "type": "signal", + "index": "", + "depth": 1, + "rule": "ff7a1d90-a72e-11ec-bc9e-ed906a2c068e" + } + ], + "kibana.alert.reason": "event created low alert eql-rule.", + "kibana.alert.rule.actions": [], + "kibana.alert.original_time": "2022-03-19T02:47:54.442Z", + "kibana.alert.group.id": "3166e88dc22be20867cf2841d1954fba65bd9969fa24d2bc228db18ff22d460a", + "kibana.alert.uuid": "3166e88dc22be20867cf2841d1954fba65bd9969fa24d2bc228db18ff22d460a" + } + } +} + +{ + "type": "doc", + "value": { + "index": ".internal.alerts-security.alerts-default-000001", + "id": "deb4ff08d8ee46741e3552694de1405d9c8dc94f3ddf7c2b12386a33f4c43ac8", + "_score": 1, + "source": { + "kibana.version": "8.1.0", + "kibana.alert.rule.category": "Event Correlation Rule", + "kibana.alert.rule.consumer": "siem", + "kibana.alert.rule.execution.uuid": "51d785a9-7d7c-4688-9e64-f7901eef88bb", + "kibana.alert.rule.name": "eql-rule", + "kibana.alert.rule.producer": "siem", + "kibana.alert.rule.rule_type_id": "siem.eqlRule", + "kibana.alert.rule.uuid": "ff7a1d90-a72e-11ec-bc9e-ed906a2c068e", + "kibana.space_ids": [ + "default" + ], + "kibana.alert.rule.tags": [], + "@timestamp": "2022-03-19T02:48:06.810Z", + "agent": { + "name": "security-linux-2.example.dev", + "id": "87c417dd-08d6-4e24-ad69-285cb8de84e9", + "type": "filebeat", + "version": "8.1.0" + }, + "log": { + "file": { + "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" + }, + "offset": 148938 + }, + "cloud": { + "availability_zone": "us-central1-c", + "instance": { + "name": "security-linux-1", + "id": "8995531128842994872" + }, + "provider": "gcp", + "service": { + "name": "GCE" + }, + "machine": { + "type": "g1-small" + }, + "project": { + "id": "elastic-siem" + }, + "account": { + "id": "elastic-siem" + } + }, + "ecs": { + "version": "8.1.0" + }, + "host": { + "hostname": "security-linux-2", + "os": { + "kernel": "4.19.0-18-cloud-amd64", + "codename": "buster", + "name": "Debian GNU/Linux", + "type": "linux", + "family": "debian", + "version": "10 (buster)", + "platform": "debian" + }, + "containerized": false, + "ip": "11.200.0.195", + "name": "security-linux-2", + "architecture": "x86_64" + }, + "service.name": "filebeat", + "message": "Status message.", + "data_stream": { + "namespace": "default", + "type": "logs", + "dataset": "elastic_agent.filebeat" + }, + "event.agent_id_status": "verified", + "event.ingested": "2022-03-19T02:47:54.820Z", + "event.dataset": "elastic_agent.filebeat", + "kibana.alert.ancestors": [ + { + "id": "YhEToH8BK09aFtXZC1Mt", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "kibana.alert.status": "active", + "kibana.alert.workflow_status": "open", + "kibana.alert.depth": 1, + "kibana.alert.reason": "event on security-linux-2 created low alert eql-rule.", + "kibana.alert.building_block_type": "default", + "kibana.alert.severity": "low", + "kibana.alert.risk_score": 21, + "kibana.alert.rule.parameters": { + "description": "a simple eql rule", + "risk_score": 21, + "severity": "low", + "license": "", + "author": [], + "false_positives": [], + "from": "now-36000s", + "rule_id": "4dd16f77-5dd2-46c8-a1d9-f1d2ffb56456", + "max_signals": 100, + "risk_score_mapping": [], + "severity_mapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptions_list": [], + "immutable": false, + "type": "eql", + "language": "eql", + "index": [ + "events-index-*" + ], + "query": "sequence [any where true] [any where true]", + "filters": [] + }, + "kibana.alert.rule.actions": [], + "kibana.alert.rule.created_at": "2022-03-19T02:48:04.202Z", + "kibana.alert.rule.created_by": "elastic", + "kibana.alert.rule.enabled": true, + "kibana.alert.rule.interval": "1m", + "kibana.alert.rule.updated_at": "2022-03-19T02:48:05.465Z", + "kibana.alert.rule.updated_by": "elastic", + "kibana.alert.rule.type": "eql", + "kibana.alert.rule.description": "a simple eql rule", + "kibana.alert.rule.risk_score": 21, + "kibana.alert.rule.severity": "low", + "kibana.alert.rule.license": "", + "kibana.alert.rule.author": [], + "kibana.alert.rule.false_positives": [], + "kibana.alert.rule.from": "now-36000s", + "kibana.alert.rule.rule_id": "4dd16f77-5dd2-46c8-a1d9-f1d2ffb56456", + "kibana.alert.rule.max_signals": 100, + "kibana.alert.rule.risk_score_mapping": [], + "kibana.alert.rule.severity_mapping": [], + "kibana.alert.rule.threat": [], + "kibana.alert.rule.to": "now", + "kibana.alert.rule.references": [], + "kibana.alert.rule.version": 1, + "kibana.alert.rule.exceptions_list": [], + "kibana.alert.rule.immutable": false, + "kibana.alert.original_time": "2022-03-19T02:47:54.820Z", + "kibana.alert.original_event.agent_id_status": "verified", + "kibana.alert.original_event.ingested": "2022-03-19T02:47:54.820Z", + "kibana.alert.original_event.dataset": "elastic_agent.filebeat", + "event.kind": "signal", + "kibana.alert.uuid": "deb4ff08d8ee46741e3552694de1405d9c8dc94f3ddf7c2b12386a33f4c43ac8", + "kibana.alert.group.id": "99ecd61224453120ab8ac69a68a8c198143ea3920273941a6b85b4609ab86e1a", + "kibana.alert.group.index": 0 + } + } +} + +{ + "type": "doc", + "value": { + "index": ".internal.alerts-security.alerts-default-000001", + "id": "70ac61a6a0bb630da02e4a2737958b814536a8016d88eddb4e6d5b193fabcbcb", + "_score": 1, + "source": { + "kibana.version": "8.1.0", + "kibana.alert.rule.category": "Event Correlation Rule", + "kibana.alert.rule.consumer": "siem", + "kibana.alert.rule.execution.uuid": "51d785a9-7d7c-4688-9e64-f7901eef88bb", + "kibana.alert.rule.name": "eql-rule", + "kibana.alert.rule.producer": "siem", + "kibana.alert.rule.rule_type_id": "siem.eqlRule", + "kibana.alert.rule.uuid": "ff7a1d90-a72e-11ec-bc9e-ed906a2c068e", + "kibana.space_ids": [ + "default" + ], + "kibana.alert.rule.tags": [], + "@timestamp": "2022-03-19T02:48:06.812Z", + "agent": { + "name": "security-linux-3.example.dev", + "id": "06851da1-73e7-41e3-97d6-ff1d62c98dc5", + "type": "filebeat", + "version": "8.1.0" + }, + "log": { + "file": { + "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" + }, + "offset": 148938 + }, + "cloud": { + "availability_zone": "us-central1-c", + "instance": { + "name": "security-linux-1", + "id": "8995531128842994872" + }, + "provider": "gcp", + "service": { + "name": "GCE" + }, + "machine": { + "type": "g1-small" + }, + "project": { + "id": "elastic-siem" + }, + "account": { + "id": "elastic-siem" + } + }, + "ecs": { + "version": "8.1.0" + }, + "host": { + "hostname": "security-linux-3", + "os": { + "kernel": "4.19.0-18-cloud-amd64", + "codename": "buster", + "name": "Debian GNU/Linux", + "type": "linux", + "family": "debian", + "version": "10 (buster)", + "platform": "debian" + }, + "containerized": false, + "ip": "11.200.0.196", + "name": "security-linux-3", + "architecture": "x86_64" + }, + "service.name": "filebeat", + "message": "Status message.", + "data_stream": { + "namespace": "default", + "type": "logs", + "dataset": "elastic_agent.filebeat" + }, + "event.agent_id_status": "verified", + "event.ingested": "2022-03-19T02:47:55.150Z", + "event.dataset": "elastic_agent.filebeat", + "kibana.alert.ancestors": [ + { + "id": "YxEToH8BK09aFtXZDFNv", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "kibana.alert.status": "active", + "kibana.alert.workflow_status": "open", + "kibana.alert.depth": 1, + "kibana.alert.reason": "event on security-linux-3 created low alert eql-rule.", + "kibana.alert.building_block_type": "default", + "kibana.alert.severity": "low", + "kibana.alert.risk_score": 21, + "kibana.alert.rule.parameters": { + "description": "a simple eql rule", + "risk_score": 21, + "severity": "low", + "license": "", + "author": [], + "false_positives": [], + "from": "now-36000s", + "rule_id": "4dd16f77-5dd2-46c8-a1d9-f1d2ffb56456", + "max_signals": 100, + "risk_score_mapping": [], + "severity_mapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptions_list": [], + "immutable": false, + "type": "eql", + "language": "eql", + "index": [ + "events-index-*" + ], + "query": "sequence [any where true] [any where true]", + "filters": [] + }, + "kibana.alert.rule.actions": [], + "kibana.alert.rule.created_at": "2022-03-19T02:48:04.202Z", + "kibana.alert.rule.created_by": "elastic", + "kibana.alert.rule.enabled": true, + "kibana.alert.rule.interval": "1m", + "kibana.alert.rule.updated_at": "2022-03-19T02:48:05.465Z", + "kibana.alert.rule.updated_by": "elastic", + "kibana.alert.rule.type": "eql", + "kibana.alert.rule.description": "a simple eql rule", + "kibana.alert.rule.risk_score": 21, + "kibana.alert.rule.severity": "low", + "kibana.alert.rule.license": "", + "kibana.alert.rule.author": [], + "kibana.alert.rule.false_positives": [], + "kibana.alert.rule.from": "now-36000s", + "kibana.alert.rule.rule_id": "4dd16f77-5dd2-46c8-a1d9-f1d2ffb56456", + "kibana.alert.rule.max_signals": 100, + "kibana.alert.rule.risk_score_mapping": [], + "kibana.alert.rule.severity_mapping": [], + "kibana.alert.rule.threat": [], + "kibana.alert.rule.to": "now", + "kibana.alert.rule.references": [], + "kibana.alert.rule.version": 1, + "kibana.alert.rule.exceptions_list": [], + "kibana.alert.rule.immutable": false, + "kibana.alert.original_time": "2022-03-19T02:47:55.150Z", + "kibana.alert.original_event.agent_id_status": "verified", + "kibana.alert.original_event.ingested": "2022-03-19T02:47:55.150Z", + "kibana.alert.original_event.dataset": "elastic_agent.filebeat", + "event.kind": "signal", + "kibana.alert.uuid": "70ac61a6a0bb630da02e4a2737958b814536a8016d88eddb4e6d5b193fabcbcb", + "kibana.alert.group.id": "99ecd61224453120ab8ac69a68a8c198143ea3920273941a6b85b4609ab86e1a", + "kibana.alert.group.index": 1 + } + } +} + +{ + "type": "doc", + "value": { + "index": ".internal.alerts-security.alerts-default-000001", + "id": "99ecd61224453120ab8ac69a68a8c198143ea3920273941a6b85b4609ab86e1a", + "_score": 1, + "source": { + "kibana.version": "8.1.0", + "kibana.alert.rule.category": "Event Correlation Rule", + "kibana.alert.rule.consumer": "siem", + "kibana.alert.rule.execution.uuid": "51d785a9-7d7c-4688-9e64-f7901eef88bb", + "kibana.alert.rule.name": "eql-rule", + "kibana.alert.rule.producer": "siem", + "kibana.alert.rule.rule_type_id": "siem.eqlRule", + "kibana.alert.rule.uuid": "ff7a1d90-a72e-11ec-bc9e-ed906a2c068e", + "kibana.space_ids": [ + "default" + ], + "kibana.alert.rule.tags": [], + "@timestamp": "2022-03-19T02:48:06.813Z", + "agent": { + "type": "filebeat", + "version": "8.1.0" + }, + "log": { + "file": { + "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" + }, + "offset": 148938 + }, + "cloud": { + "availability_zone": "us-central1-c", + "instance": { + "name": "security-linux-1", + "id": "8995531128842994872" + }, + "provider": "gcp", + "service": { + "name": "GCE" + }, + "machine": { + "type": "g1-small" + }, + "project": { + "id": "elastic-siem" + }, + "account": { + "id": "elastic-siem" + } + }, + "ecs": { + "version": "8.1.0" + }, + "host": { + "os": { + "kernel": "4.19.0-18-cloud-amd64", + "codename": "buster", + "name": "Debian GNU/Linux", + "type": "linux", + "family": "debian", + "version": "10 (buster)", + "platform": "debian" + }, + "containerized": false, + "architecture": "x86_64" + }, + "service.name": "filebeat", + "message": "Status message.", + "data_stream": { + "namespace": "default", + "type": "logs", + "dataset": "elastic_agent.filebeat" + }, + "event.agent_id_status": "verified", + "event.dataset": "elastic_agent.filebeat", + "kibana.alert.status": "active", + "kibana.alert.workflow_status": "open", + "kibana.alert.depth": 2, + "kibana.alert.severity": "low", + "kibana.alert.risk_score": 21, + "kibana.alert.rule.parameters": { + "description": "a simple eql rule", + "risk_score": 21, + "severity": "low", + "license": "", + "author": [], + "false_positives": [], + "from": "now-36000s", + "rule_id": "4dd16f77-5dd2-46c8-a1d9-f1d2ffb56456", + "max_signals": 100, + "risk_score_mapping": [], + "severity_mapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptions_list": [], + "immutable": false, + "type": "eql", + "language": "eql", + "index": [ + "events-index-*" + ], + "query": "sequence [any where true] [any where true]", + "filters": [] + }, + "kibana.alert.rule.created_at": "2022-03-19T02:48:04.202Z", + "kibana.alert.rule.created_by": "elastic", + "kibana.alert.rule.enabled": true, + "kibana.alert.rule.interval": "1m", + "kibana.alert.rule.updated_at": "2022-03-19T02:48:05.465Z", + "kibana.alert.rule.updated_by": "elastic", + "kibana.alert.rule.type": "eql", + "kibana.alert.rule.description": "a simple eql rule", + "kibana.alert.rule.risk_score": 21, + "kibana.alert.rule.severity": "low", + "kibana.alert.rule.license": "", + "kibana.alert.rule.author": [], + "kibana.alert.rule.false_positives": [], + "kibana.alert.rule.from": "now-36000s", + "kibana.alert.rule.rule_id": "4dd16f77-5dd2-46c8-a1d9-f1d2ffb56456", + "kibana.alert.rule.max_signals": 100, + "kibana.alert.rule.risk_score_mapping": [], + "kibana.alert.rule.severity_mapping": [], + "kibana.alert.rule.threat": [], + "kibana.alert.rule.to": "now", + "kibana.alert.rule.references": [], + "kibana.alert.rule.version": 1, + "kibana.alert.rule.exceptions_list": [], + "kibana.alert.rule.immutable": false, + "kibana.alert.original_event.agent_id_status": "verified", + "kibana.alert.original_event.dataset": "elastic_agent.filebeat", + "event.kind": "signal", + "event": { + "kind": "signal" + }, + "kibana.alert.ancestors": [ + { + "id": "YhEToH8BK09aFtXZC1Mt", + "type": "event", + "index": "events-index-000001", + "depth": 0 + }, + { + "id": "deb4ff08d8ee46741e3552694de1405d9c8dc94f3ddf7c2b12386a33f4c43ac8", + "type": "signal", + "index": "", + "depth": 1, + "rule": "ff7a1d90-a72e-11ec-bc9e-ed906a2c068e" + }, + { + "id": "YxEToH8BK09aFtXZDFNv", + "type": "event", + "index": "events-index-000001", + "depth": 0 + }, + { + "id": "70ac61a6a0bb630da02e4a2737958b814536a8016d88eddb4e6d5b193fabcbcb", + "type": "signal", + "index": "", + "depth": 1, + "rule": "ff7a1d90-a72e-11ec-bc9e-ed906a2c068e" + } + ], + "kibana.alert.reason": "event created low alert eql-rule.", + "kibana.alert.rule.actions": [], + "kibana.alert.original_time": "2022-03-19T02:47:54.820Z", + "kibana.alert.group.id": "99ecd61224453120ab8ac69a68a8c198143ea3920273941a6b85b4609ab86e1a", + "kibana.alert.uuid": "99ecd61224453120ab8ac69a68a8c198143ea3920273941a6b85b4609ab86e1a" + } + } +} + +{ + "type": "doc", + "value": { + "index": ".internal.alerts-security.alerts-default-000001", + "id": "82ad71870bb9ce4c6570f5060feb5d6f2ca38806c67cca2cdda19384dc4b8a79", + "_score": 1, + "source": { + "kibana.version": "8.1.0", + "kibana.alert.rule.category": "Event Correlation Rule", + "kibana.alert.rule.consumer": "siem", + "kibana.alert.rule.execution.uuid": "51d785a9-7d7c-4688-9e64-f7901eef88bb", + "kibana.alert.rule.name": "eql-rule", + "kibana.alert.rule.producer": "siem", + "kibana.alert.rule.rule_type_id": "siem.eqlRule", + "kibana.alert.rule.uuid": "ff7a1d90-a72e-11ec-bc9e-ed906a2c068e", + "kibana.space_ids": [ + "default" + ], + "kibana.alert.rule.tags": [], + "@timestamp": "2022-03-19T02:48:06.816Z", + "agent": { + "name": "security-linux-3.example.dev", + "id": "06851da1-73e7-41e3-97d6-ff1d62c98dc5", + "type": "filebeat", + "version": "8.1.0" + }, + "log": { + "file": { + "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" + }, + "offset": 148938 + }, + "cloud": { + "availability_zone": "us-central1-c", + "instance": { + "name": "security-linux-1", + "id": "8995531128842994872" + }, + "provider": "gcp", + "service": { + "name": "GCE" + }, + "machine": { + "type": "g1-small" + }, + "project": { + "id": "elastic-siem" + }, + "account": { + "id": "elastic-siem" + } + }, + "ecs": { + "version": "8.1.0" + }, + "host": { + "hostname": "security-linux-3", + "os": { + "kernel": "4.19.0-18-cloud-amd64", + "codename": "buster", + "name": "Debian GNU/Linux", + "type": "linux", + "family": "debian", + "version": "10 (buster)", + "platform": "debian" + }, + "containerized": false, + "ip": "11.200.0.196", + "name": "security-linux-3", + "architecture": "x86_64" + }, + "service.name": "filebeat", + "message": "Status message.", + "data_stream": { + "namespace": "default", + "type": "logs", + "dataset": "elastic_agent.filebeat" + }, + "event.agent_id_status": "verified", + "event.ingested": "2022-03-19T02:47:55.150Z", + "event.dataset": "elastic_agent.filebeat", + "kibana.alert.ancestors": [ + { + "id": "YxEToH8BK09aFtXZDFNv", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "kibana.alert.status": "active", + "kibana.alert.workflow_status": "open", + "kibana.alert.depth": 1, + "kibana.alert.reason": "event on security-linux-3 created low alert eql-rule.", + "kibana.alert.building_block_type": "default", + "kibana.alert.severity": "low", + "kibana.alert.risk_score": 21, + "kibana.alert.rule.parameters": { + "description": "a simple eql rule", + "risk_score": 21, + "severity": "low", + "license": "", + "author": [], + "false_positives": [], + "from": "now-36000s", + "rule_id": "4dd16f77-5dd2-46c8-a1d9-f1d2ffb56456", + "max_signals": 100, + "risk_score_mapping": [], + "severity_mapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptions_list": [], + "immutable": false, + "type": "eql", + "language": "eql", + "index": [ + "events-index-*" + ], + "query": "sequence [any where true] [any where true]", + "filters": [] + }, + "kibana.alert.rule.actions": [], + "kibana.alert.rule.created_at": "2022-03-19T02:48:04.202Z", + "kibana.alert.rule.created_by": "elastic", + "kibana.alert.rule.enabled": true, + "kibana.alert.rule.interval": "1m", + "kibana.alert.rule.updated_at": "2022-03-19T02:48:05.465Z", + "kibana.alert.rule.updated_by": "elastic", + "kibana.alert.rule.type": "eql", + "kibana.alert.rule.description": "a simple eql rule", + "kibana.alert.rule.risk_score": 21, + "kibana.alert.rule.severity": "low", + "kibana.alert.rule.license": "", + "kibana.alert.rule.author": [], + "kibana.alert.rule.false_positives": [], + "kibana.alert.rule.from": "now-36000s", + "kibana.alert.rule.rule_id": "4dd16f77-5dd2-46c8-a1d9-f1d2ffb56456", + "kibana.alert.rule.max_signals": 100, + "kibana.alert.rule.risk_score_mapping": [], + "kibana.alert.rule.severity_mapping": [], + "kibana.alert.rule.threat": [], + "kibana.alert.rule.to": "now", + "kibana.alert.rule.references": [], + "kibana.alert.rule.version": 1, + "kibana.alert.rule.exceptions_list": [], + "kibana.alert.rule.immutable": false, + "kibana.alert.original_time": "2022-03-19T02:47:55.150Z", + "kibana.alert.original_event.agent_id_status": "verified", + "kibana.alert.original_event.ingested": "2022-03-19T02:47:55.150Z", + "kibana.alert.original_event.dataset": "elastic_agent.filebeat", + "event.kind": "signal", + "kibana.alert.uuid": "82ad71870bb9ce4c6570f5060feb5d6f2ca38806c67cca2cdda19384dc4b8a79", + "kibana.alert.group.id": "86fbd0f02916608f9a6078ee5db3635e58b6138aae232d85006f27a05ee5ff30", + "kibana.alert.group.index": 0 + } + } +} + +{ + "type": "doc", + "value": { + "index": ".internal.alerts-security.alerts-default-000001", + "id": "50a224a9b65c5cdfcaee60d0f5fec7c98901161779138d686cff39277034f9fd", + "_score": 1, + "source": { + "kibana.version": "8.1.0", + "kibana.alert.rule.category": "Event Correlation Rule", + "kibana.alert.rule.consumer": "siem", + "kibana.alert.rule.execution.uuid": "51d785a9-7d7c-4688-9e64-f7901eef88bb", + "kibana.alert.rule.name": "eql-rule", + "kibana.alert.rule.producer": "siem", + "kibana.alert.rule.rule_type_id": "siem.eqlRule", + "kibana.alert.rule.uuid": "ff7a1d90-a72e-11ec-bc9e-ed906a2c068e", + "kibana.space_ids": [ + "default" + ], + "kibana.alert.rule.tags": [], + "@timestamp": "2022-03-19T02:48:06.818Z", + "agent": { + "name": "security-linux-1.example.dev", + "id": "d8f66724-3cf2-437c-b124-6ac9fb0e2311", + "type": "filebeat", + "version": "8.1.0" + }, + "log": { + "file": { + "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" + }, + "offset": 148938 + }, + "cloud": { + "availability_zone": "us-central1-c", + "instance": { + "name": "security-linux-1", + "id": "8995531128842994872" + }, + "provider": "gcp", + "service": { + "name": "GCE" + }, + "machine": { + "type": "g1-small" + }, + "project": { + "id": "elastic-siem" + }, + "account": { + "id": "elastic-siem" + } + }, + "ecs": { + "version": "8.1.0" + }, + "host": { + "hostname": "security-linux-1", + "os": { + "kernel": "4.19.0-18-cloud-amd64", + "codename": "buster", + "name": "Debian GNU/Linux", + "type": "linux", + "family": "debian", + "version": "10 (buster)", + "platform": "debian" + }, + "containerized": false, + "ip": "11.200.0.194", + "name": "security-linux-1", + "architecture": "x86_64" + }, + "service.name": "filebeat", + "message": "Status message.", + "data_stream": { + "namespace": "default", + "type": "logs", + "dataset": "elastic_agent.filebeat" + }, + "event.agent_id_status": "verified", + "event.ingested": "2022-03-19T02:47:55.468Z", + "event.dataset": "elastic_agent.filebeat", + "kibana.alert.ancestors": [ + { + "id": "ZBEToH8BK09aFtXZDVNr", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "kibana.alert.status": "active", + "kibana.alert.workflow_status": "open", + "kibana.alert.depth": 1, + "kibana.alert.reason": "event on security-linux-1 created low alert eql-rule.", + "kibana.alert.building_block_type": "default", + "kibana.alert.severity": "low", + "kibana.alert.risk_score": 21, + "kibana.alert.rule.parameters": { + "description": "a simple eql rule", + "risk_score": 21, + "severity": "low", + "license": "", + "author": [], + "false_positives": [], + "from": "now-36000s", + "rule_id": "4dd16f77-5dd2-46c8-a1d9-f1d2ffb56456", + "max_signals": 100, + "risk_score_mapping": [], + "severity_mapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptions_list": [], + "immutable": false, + "type": "eql", + "language": "eql", + "index": [ + "events-index-*" + ], + "query": "sequence [any where true] [any where true]", + "filters": [] + }, + "kibana.alert.rule.actions": [], + "kibana.alert.rule.created_at": "2022-03-19T02:48:04.202Z", + "kibana.alert.rule.created_by": "elastic", + "kibana.alert.rule.enabled": true, + "kibana.alert.rule.interval": "1m", + "kibana.alert.rule.updated_at": "2022-03-19T02:48:05.465Z", + "kibana.alert.rule.updated_by": "elastic", + "kibana.alert.rule.type": "eql", + "kibana.alert.rule.description": "a simple eql rule", + "kibana.alert.rule.risk_score": 21, + "kibana.alert.rule.severity": "low", + "kibana.alert.rule.license": "", + "kibana.alert.rule.author": [], + "kibana.alert.rule.false_positives": [], + "kibana.alert.rule.from": "now-36000s", + "kibana.alert.rule.rule_id": "4dd16f77-5dd2-46c8-a1d9-f1d2ffb56456", + "kibana.alert.rule.max_signals": 100, + "kibana.alert.rule.risk_score_mapping": [], + "kibana.alert.rule.severity_mapping": [], + "kibana.alert.rule.threat": [], + "kibana.alert.rule.to": "now", + "kibana.alert.rule.references": [], + "kibana.alert.rule.version": 1, + "kibana.alert.rule.exceptions_list": [], + "kibana.alert.rule.immutable": false, + "kibana.alert.original_time": "2022-03-19T02:47:55.468Z", + "kibana.alert.original_event.agent_id_status": "verified", + "kibana.alert.original_event.ingested": "2022-03-19T02:47:55.468Z", + "kibana.alert.original_event.dataset": "elastic_agent.filebeat", + "event.kind": "signal", + "kibana.alert.uuid": "50a224a9b65c5cdfcaee60d0f5fec7c98901161779138d686cff39277034f9fd", + "kibana.alert.group.id": "86fbd0f02916608f9a6078ee5db3635e58b6138aae232d85006f27a05ee5ff30", + "kibana.alert.group.index": 1 + } + } +} + +{ + "type": "doc", + "value": { + "index": ".internal.alerts-security.alerts-default-000001", + "id": "86fbd0f02916608f9a6078ee5db3635e58b6138aae232d85006f27a05ee5ff30", + "_score": 1, + "source": { + "kibana.version": "8.1.0", + "kibana.alert.rule.category": "Event Correlation Rule", + "kibana.alert.rule.consumer": "siem", + "kibana.alert.rule.execution.uuid": "51d785a9-7d7c-4688-9e64-f7901eef88bb", + "kibana.alert.rule.name": "eql-rule", + "kibana.alert.rule.producer": "siem", + "kibana.alert.rule.rule_type_id": "siem.eqlRule", + "kibana.alert.rule.uuid": "ff7a1d90-a72e-11ec-bc9e-ed906a2c068e", + "kibana.space_ids": [ + "default" + ], + "kibana.alert.rule.tags": [], + "@timestamp": "2022-03-19T02:48:06.819Z", + "agent": { + "type": "filebeat", + "version": "8.1.0" + }, + "log": { + "file": { + "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" + }, + "offset": 148938 + }, + "cloud": { + "availability_zone": "us-central1-c", + "instance": { + "name": "security-linux-1", + "id": "8995531128842994872" + }, + "provider": "gcp", + "service": { + "name": "GCE" + }, + "machine": { + "type": "g1-small" + }, + "project": { + "id": "elastic-siem" + }, + "account": { + "id": "elastic-siem" + } + }, + "ecs": { + "version": "8.1.0" + }, + "host": { + "os": { + "kernel": "4.19.0-18-cloud-amd64", + "codename": "buster", + "name": "Debian GNU/Linux", + "type": "linux", + "family": "debian", + "version": "10 (buster)", + "platform": "debian" + }, + "containerized": false, + "architecture": "x86_64" + }, + "service.name": "filebeat", + "message": "Status message.", + "data_stream": { + "namespace": "default", + "type": "logs", + "dataset": "elastic_agent.filebeat" + }, + "event.agent_id_status": "verified", + "event.dataset": "elastic_agent.filebeat", + "kibana.alert.status": "active", + "kibana.alert.workflow_status": "open", + "kibana.alert.depth": 2, + "kibana.alert.severity": "low", + "kibana.alert.risk_score": 21, + "kibana.alert.rule.parameters": { + "description": "a simple eql rule", + "risk_score": 21, + "severity": "low", + "license": "", + "author": [], + "false_positives": [], + "from": "now-36000s", + "rule_id": "4dd16f77-5dd2-46c8-a1d9-f1d2ffb56456", + "max_signals": 100, + "risk_score_mapping": [], + "severity_mapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptions_list": [], + "immutable": false, + "type": "eql", + "language": "eql", + "index": [ + "events-index-*" + ], + "query": "sequence [any where true] [any where true]", + "filters": [] + }, + "kibana.alert.rule.created_at": "2022-03-19T02:48:04.202Z", + "kibana.alert.rule.created_by": "elastic", + "kibana.alert.rule.enabled": true, + "kibana.alert.rule.interval": "1m", + "kibana.alert.rule.updated_at": "2022-03-19T02:48:05.465Z", + "kibana.alert.rule.updated_by": "elastic", + "kibana.alert.rule.type": "eql", + "kibana.alert.rule.description": "a simple eql rule", + "kibana.alert.rule.risk_score": 21, + "kibana.alert.rule.severity": "low", + "kibana.alert.rule.license": "", + "kibana.alert.rule.author": [], + "kibana.alert.rule.false_positives": [], + "kibana.alert.rule.from": "now-36000s", + "kibana.alert.rule.rule_id": "4dd16f77-5dd2-46c8-a1d9-f1d2ffb56456", + "kibana.alert.rule.max_signals": 100, + "kibana.alert.rule.risk_score_mapping": [], + "kibana.alert.rule.severity_mapping": [], + "kibana.alert.rule.threat": [], + "kibana.alert.rule.to": "now", + "kibana.alert.rule.references": [], + "kibana.alert.rule.version": 1, + "kibana.alert.rule.exceptions_list": [], + "kibana.alert.rule.immutable": false, + "kibana.alert.original_event.agent_id_status": "verified", + "kibana.alert.original_event.dataset": "elastic_agent.filebeat", + "event.kind": "signal", + "event": { + "kind": "signal" + }, + "kibana.alert.ancestors": [ + { + "id": "YxEToH8BK09aFtXZDFNv", + "type": "event", + "index": "events-index-000001", + "depth": 0 + }, + { + "id": "82ad71870bb9ce4c6570f5060feb5d6f2ca38806c67cca2cdda19384dc4b8a79", + "type": "signal", + "index": "", + "depth": 1, + "rule": "ff7a1d90-a72e-11ec-bc9e-ed906a2c068e" + }, + { + "id": "ZBEToH8BK09aFtXZDVNr", + "type": "event", + "index": "events-index-000001", + "depth": 0 + }, + { + "id": "50a224a9b65c5cdfcaee60d0f5fec7c98901161779138d686cff39277034f9fd", + "type": "signal", + "index": "", + "depth": 1, + "rule": "ff7a1d90-a72e-11ec-bc9e-ed906a2c068e" + } + ], + "kibana.alert.reason": "event created low alert eql-rule.", + "kibana.alert.rule.actions": [], + "kibana.alert.original_time": "2022-03-19T02:47:55.150Z", + "kibana.alert.group.id": "86fbd0f02916608f9a6078ee5db3635e58b6138aae232d85006f27a05ee5ff30", + "kibana.alert.uuid": "86fbd0f02916608f9a6078ee5db3635e58b6138aae232d85006f27a05ee5ff30" + } + } +} + +{ + "type": "doc", + "value": { + "index": ".internal.alerts-security.alerts-default-000001", + "id": "9148662e17d39a5b384c8429ca7736ea540b13ffc881ae6d4079678ea405f3f0", + "_score": 1, + "source": { + "kibana.version": "8.1.0", + "kibana.alert.rule.category": "Event Correlation Rule", + "kibana.alert.rule.consumer": "siem", + "kibana.alert.rule.execution.uuid": "51d785a9-7d7c-4688-9e64-f7901eef88bb", + "kibana.alert.rule.name": "eql-rule", + "kibana.alert.rule.producer": "siem", + "kibana.alert.rule.rule_type_id": "siem.eqlRule", + "kibana.alert.rule.uuid": "ff7a1d90-a72e-11ec-bc9e-ed906a2c068e", + "kibana.space_ids": [ + "default" + ], + "kibana.alert.rule.tags": [], + "@timestamp": "2022-03-19T02:48:06.823Z", + "agent": { + "name": "security-linux-1.example.dev", + "id": "d8f66724-3cf2-437c-b124-6ac9fb0e2311", + "type": "filebeat", + "version": "8.1.0" + }, + "log": { + "file": { + "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" + }, + "offset": 148938 + }, + "cloud": { + "availability_zone": "us-central1-c", + "instance": { + "name": "security-linux-1", + "id": "8995531128842994872" + }, + "provider": "gcp", + "service": { + "name": "GCE" + }, + "machine": { + "type": "g1-small" + }, + "project": { + "id": "elastic-siem" + }, + "account": { + "id": "elastic-siem" + } + }, + "ecs": { + "version": "8.1.0" + }, + "host": { + "hostname": "security-linux-1", + "os": { + "kernel": "4.19.0-18-cloud-amd64", + "codename": "buster", + "name": "Debian GNU/Linux", + "type": "linux", + "family": "debian", + "version": "10 (buster)", + "platform": "debian" + }, + "containerized": false, + "ip": "11.200.0.194", + "name": "security-linux-1", + "architecture": "x86_64" + }, + "service.name": "filebeat", + "message": "Status message.", + "data_stream": { + "namespace": "default", + "type": "logs", + "dataset": "elastic_agent.filebeat" + }, + "event.agent_id_status": "verified", + "event.ingested": "2022-03-19T02:47:55.468Z", + "event.dataset": "elastic_agent.filebeat", + "kibana.alert.ancestors": [ + { + "id": "ZBEToH8BK09aFtXZDVNr", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "kibana.alert.status": "active", + "kibana.alert.workflow_status": "open", + "kibana.alert.depth": 1, + "kibana.alert.reason": "event on security-linux-1 created low alert eql-rule.", + "kibana.alert.building_block_type": "default", + "kibana.alert.severity": "low", + "kibana.alert.risk_score": 21, + "kibana.alert.rule.parameters": { + "description": "a simple eql rule", + "risk_score": 21, + "severity": "low", + "license": "", + "author": [], + "false_positives": [], + "from": "now-36000s", + "rule_id": "4dd16f77-5dd2-46c8-a1d9-f1d2ffb56456", + "max_signals": 100, + "risk_score_mapping": [], + "severity_mapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptions_list": [], + "immutable": false, + "type": "eql", + "language": "eql", + "index": [ + "events-index-*" + ], + "query": "sequence [any where true] [any where true]", + "filters": [] + }, + "kibana.alert.rule.actions": [], + "kibana.alert.rule.created_at": "2022-03-19T02:48:04.202Z", + "kibana.alert.rule.created_by": "elastic", + "kibana.alert.rule.enabled": true, + "kibana.alert.rule.interval": "1m", + "kibana.alert.rule.updated_at": "2022-03-19T02:48:05.465Z", + "kibana.alert.rule.updated_by": "elastic", + "kibana.alert.rule.type": "eql", + "kibana.alert.rule.description": "a simple eql rule", + "kibana.alert.rule.risk_score": 21, + "kibana.alert.rule.severity": "low", + "kibana.alert.rule.license": "", + "kibana.alert.rule.author": [], + "kibana.alert.rule.false_positives": [], + "kibana.alert.rule.from": "now-36000s", + "kibana.alert.rule.rule_id": "4dd16f77-5dd2-46c8-a1d9-f1d2ffb56456", + "kibana.alert.rule.max_signals": 100, + "kibana.alert.rule.risk_score_mapping": [], + "kibana.alert.rule.severity_mapping": [], + "kibana.alert.rule.threat": [], + "kibana.alert.rule.to": "now", + "kibana.alert.rule.references": [], + "kibana.alert.rule.version": 1, + "kibana.alert.rule.exceptions_list": [], + "kibana.alert.rule.immutable": false, + "kibana.alert.original_time": "2022-03-19T02:47:55.468Z", + "kibana.alert.original_event.agent_id_status": "verified", + "kibana.alert.original_event.ingested": "2022-03-19T02:47:55.468Z", + "kibana.alert.original_event.dataset": "elastic_agent.filebeat", + "event.kind": "signal", + "kibana.alert.uuid": "9148662e17d39a5b384c8429ca7736ea540b13ffc881ae6d4079678ea405f3f0", + "kibana.alert.group.id": "6f6f4de344632bf418be705ea307e502295a64c2e5c8db5496a701a195ca8ba9", + "kibana.alert.group.index": 0 + } + } +} + +{ + "type": "doc", + "value": { + "index": ".internal.alerts-security.alerts-default-000001", + "id": "8497c7aeea8bc5c5faa870fd0f3e934e50047b54171b917c8255f0485a8c86bb", + "_score": 1, + "source": { + "kibana.version": "8.1.0", + "kibana.alert.rule.category": "Event Correlation Rule", + "kibana.alert.rule.consumer": "siem", + "kibana.alert.rule.execution.uuid": "51d785a9-7d7c-4688-9e64-f7901eef88bb", + "kibana.alert.rule.name": "eql-rule", + "kibana.alert.rule.producer": "siem", + "kibana.alert.rule.rule_type_id": "siem.eqlRule", + "kibana.alert.rule.uuid": "ff7a1d90-a72e-11ec-bc9e-ed906a2c068e", + "kibana.space_ids": [ + "default" + ], + "kibana.alert.rule.tags": [], + "@timestamp": "2022-03-19T02:48:06.825Z", + "agent": { + "name": "security-linux-2.example.dev", + "id": "87c417dd-08d6-4e24-ad69-285cb8de84e9", + "type": "filebeat", + "version": "8.1.0" + }, + "log": { + "file": { + "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" + }, + "offset": 148938 + }, + "cloud": { + "availability_zone": "us-central1-c", + "instance": { + "name": "security-linux-1", + "id": "8995531128842994872" + }, + "provider": "gcp", + "service": { + "name": "GCE" + }, + "machine": { + "type": "g1-small" + }, + "project": { + "id": "elastic-siem" + }, + "account": { + "id": "elastic-siem" + } + }, + "ecs": { + "version": "8.1.0" + }, + "host": { + "hostname": "security-linux-2", + "os": { + "kernel": "4.19.0-18-cloud-amd64", + "codename": "buster", + "name": "Debian GNU/Linux", + "type": "linux", + "family": "debian", + "version": "10 (buster)", + "platform": "debian" + }, + "containerized": false, + "ip": "11.200.0.195", + "name": "security-linux-2", + "architecture": "x86_64" + }, + "service.name": "filebeat", + "message": "Status message.", + "data_stream": { + "namespace": "default", + "type": "logs", + "dataset": "elastic_agent.filebeat" + }, + "event.agent_id_status": "verified", + "event.ingested": "2022-03-19T02:47:55.722Z", + "event.dataset": "elastic_agent.filebeat", + "kibana.alert.ancestors": [ + { + "id": "ZREToH8BK09aFtXZDlOv", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "kibana.alert.status": "active", + "kibana.alert.workflow_status": "open", + "kibana.alert.depth": 1, + "kibana.alert.reason": "event on security-linux-2 created low alert eql-rule.", + "kibana.alert.building_block_type": "default", + "kibana.alert.severity": "low", + "kibana.alert.risk_score": 21, + "kibana.alert.rule.parameters": { + "description": "a simple eql rule", + "risk_score": 21, + "severity": "low", + "license": "", + "author": [], + "false_positives": [], + "from": "now-36000s", + "rule_id": "4dd16f77-5dd2-46c8-a1d9-f1d2ffb56456", + "max_signals": 100, + "risk_score_mapping": [], + "severity_mapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptions_list": [], + "immutable": false, + "type": "eql", + "language": "eql", + "index": [ + "events-index-*" + ], + "query": "sequence [any where true] [any where true]", + "filters": [] + }, + "kibana.alert.rule.actions": [], + "kibana.alert.rule.created_at": "2022-03-19T02:48:04.202Z", + "kibana.alert.rule.created_by": "elastic", + "kibana.alert.rule.enabled": true, + "kibana.alert.rule.interval": "1m", + "kibana.alert.rule.updated_at": "2022-03-19T02:48:05.465Z", + "kibana.alert.rule.updated_by": "elastic", + "kibana.alert.rule.type": "eql", + "kibana.alert.rule.description": "a simple eql rule", + "kibana.alert.rule.risk_score": 21, + "kibana.alert.rule.severity": "low", + "kibana.alert.rule.license": "", + "kibana.alert.rule.author": [], + "kibana.alert.rule.false_positives": [], + "kibana.alert.rule.from": "now-36000s", + "kibana.alert.rule.rule_id": "4dd16f77-5dd2-46c8-a1d9-f1d2ffb56456", + "kibana.alert.rule.max_signals": 100, + "kibana.alert.rule.risk_score_mapping": [], + "kibana.alert.rule.severity_mapping": [], + "kibana.alert.rule.threat": [], + "kibana.alert.rule.to": "now", + "kibana.alert.rule.references": [], + "kibana.alert.rule.version": 1, + "kibana.alert.rule.exceptions_list": [], + "kibana.alert.rule.immutable": false, + "kibana.alert.original_time": "2022-03-19T02:47:55.722Z", + "kibana.alert.original_event.agent_id_status": "verified", + "kibana.alert.original_event.ingested": "2022-03-19T02:47:55.722Z", + "kibana.alert.original_event.dataset": "elastic_agent.filebeat", + "event.kind": "signal", + "kibana.alert.uuid": "8497c7aeea8bc5c5faa870fd0f3e934e50047b54171b917c8255f0485a8c86bb", + "kibana.alert.group.id": "6f6f4de344632bf418be705ea307e502295a64c2e5c8db5496a701a195ca8ba9", + "kibana.alert.group.index": 1 + } + } +} + +{ + "type": "doc", + "value": { + "index": ".internal.alerts-security.alerts-default-000001", + "id": "6f6f4de344632bf418be705ea307e502295a64c2e5c8db5496a701a195ca8ba9", + "_score": 1, + "source": { + "kibana.version": "8.1.0", + "kibana.alert.rule.category": "Event Correlation Rule", + "kibana.alert.rule.consumer": "siem", + "kibana.alert.rule.execution.uuid": "51d785a9-7d7c-4688-9e64-f7901eef88bb", + "kibana.alert.rule.name": "eql-rule", + "kibana.alert.rule.producer": "siem", + "kibana.alert.rule.rule_type_id": "siem.eqlRule", + "kibana.alert.rule.uuid": "ff7a1d90-a72e-11ec-bc9e-ed906a2c068e", + "kibana.space_ids": [ + "default" + ], + "kibana.alert.rule.tags": [], + "@timestamp": "2022-03-19T02:48:06.826Z", + "agent": { + "type": "filebeat", + "version": "8.1.0" + }, + "log": { + "file": { + "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" + }, + "offset": 148938 + }, + "cloud": { + "availability_zone": "us-central1-c", + "instance": { + "name": "security-linux-1", + "id": "8995531128842994872" + }, + "provider": "gcp", + "service": { + "name": "GCE" + }, + "machine": { + "type": "g1-small" + }, + "project": { + "id": "elastic-siem" + }, + "account": { + "id": "elastic-siem" + } + }, + "ecs": { + "version": "8.1.0" + }, + "host": { + "os": { + "kernel": "4.19.0-18-cloud-amd64", + "codename": "buster", + "name": "Debian GNU/Linux", + "type": "linux", + "family": "debian", + "version": "10 (buster)", + "platform": "debian" + }, + "containerized": false, + "architecture": "x86_64" + }, + "service.name": "filebeat", + "message": "Status message.", + "data_stream": { + "namespace": "default", + "type": "logs", + "dataset": "elastic_agent.filebeat" + }, + "event.agent_id_status": "verified", + "event.dataset": "elastic_agent.filebeat", + "kibana.alert.status": "active", + "kibana.alert.workflow_status": "open", + "kibana.alert.depth": 2, + "kibana.alert.severity": "low", + "kibana.alert.risk_score": 21, + "kibana.alert.rule.parameters": { + "description": "a simple eql rule", + "risk_score": 21, + "severity": "low", + "license": "", + "author": [], + "false_positives": [], + "from": "now-36000s", + "rule_id": "4dd16f77-5dd2-46c8-a1d9-f1d2ffb56456", + "max_signals": 100, + "risk_score_mapping": [], + "severity_mapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptions_list": [], + "immutable": false, + "type": "eql", + "language": "eql", + "index": [ + "events-index-*" + ], + "query": "sequence [any where true] [any where true]", + "filters": [] + }, + "kibana.alert.rule.created_at": "2022-03-19T02:48:04.202Z", + "kibana.alert.rule.created_by": "elastic", + "kibana.alert.rule.enabled": true, + "kibana.alert.rule.interval": "1m", + "kibana.alert.rule.updated_at": "2022-03-19T02:48:05.465Z", + "kibana.alert.rule.updated_by": "elastic", + "kibana.alert.rule.type": "eql", + "kibana.alert.rule.description": "a simple eql rule", + "kibana.alert.rule.risk_score": 21, + "kibana.alert.rule.severity": "low", + "kibana.alert.rule.license": "", + "kibana.alert.rule.author": [], + "kibana.alert.rule.false_positives": [], + "kibana.alert.rule.from": "now-36000s", + "kibana.alert.rule.rule_id": "4dd16f77-5dd2-46c8-a1d9-f1d2ffb56456", + "kibana.alert.rule.max_signals": 100, + "kibana.alert.rule.risk_score_mapping": [], + "kibana.alert.rule.severity_mapping": [], + "kibana.alert.rule.threat": [], + "kibana.alert.rule.to": "now", + "kibana.alert.rule.references": [], + "kibana.alert.rule.version": 1, + "kibana.alert.rule.exceptions_list": [], + "kibana.alert.rule.immutable": false, + "kibana.alert.original_event.agent_id_status": "verified", + "kibana.alert.original_event.dataset": "elastic_agent.filebeat", + "event.kind": "signal", + "event": { + "kind": "signal" + }, + "kibana.alert.ancestors": [ + { + "id": "ZBEToH8BK09aFtXZDVNr", + "type": "event", + "index": "events-index-000001", + "depth": 0 + }, + { + "id": "9148662e17d39a5b384c8429ca7736ea540b13ffc881ae6d4079678ea405f3f0", + "type": "signal", + "index": "", + "depth": 1, + "rule": "ff7a1d90-a72e-11ec-bc9e-ed906a2c068e" + }, + { + "id": "ZREToH8BK09aFtXZDlOv", + "type": "event", + "index": "events-index-000001", + "depth": 0 + }, + { + "id": "8497c7aeea8bc5c5faa870fd0f3e934e50047b54171b917c8255f0485a8c86bb", + "type": "signal", + "index": "", + "depth": 1, + "rule": "ff7a1d90-a72e-11ec-bc9e-ed906a2c068e" + } + ], + "kibana.alert.reason": "event created low alert eql-rule.", + "kibana.alert.rule.actions": [], + "kibana.alert.original_time": "2022-03-19T02:47:55.468Z", + "kibana.alert.group.id": "6f6f4de344632bf418be705ea307e502295a64c2e5c8db5496a701a195ca8ba9", + "kibana.alert.uuid": "6f6f4de344632bf418be705ea307e502295a64c2e5c8db5496a701a195ca8ba9" + } + } +} + +{ + "type": "doc", + "value": { + "index": ".internal.alerts-security.alerts-default-000001", + "id": "11941a5508aa59bdfa43d8b5c660b26e9aa0eeb67a741ec93c5b61e7670fba7e", + "_score": 1, + "source": { + "kibana.version": "8.1.0", + "kibana.alert.rule.category": "Event Correlation Rule", + "kibana.alert.rule.consumer": "siem", + "kibana.alert.rule.execution.uuid": "51d785a9-7d7c-4688-9e64-f7901eef88bb", + "kibana.alert.rule.name": "eql-rule", + "kibana.alert.rule.producer": "siem", + "kibana.alert.rule.rule_type_id": "siem.eqlRule", + "kibana.alert.rule.uuid": "ff7a1d90-a72e-11ec-bc9e-ed906a2c068e", + "kibana.space_ids": [ + "default" + ], + "kibana.alert.rule.tags": [], + "@timestamp": "2022-03-19T02:48:06.829Z", + "agent": { + "name": "security-linux-2.example.dev", + "id": "87c417dd-08d6-4e24-ad69-285cb8de84e9", + "type": "filebeat", + "version": "8.1.0" + }, + "log": { + "file": { + "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" + }, + "offset": 148938 + }, + "cloud": { + "availability_zone": "us-central1-c", + "instance": { + "name": "security-linux-1", + "id": "8995531128842994872" + }, + "provider": "gcp", + "service": { + "name": "GCE" + }, + "machine": { + "type": "g1-small" + }, + "project": { + "id": "elastic-siem" + }, + "account": { + "id": "elastic-siem" + } + }, + "ecs": { + "version": "8.1.0" + }, + "host": { + "hostname": "security-linux-2", + "os": { + "kernel": "4.19.0-18-cloud-amd64", + "codename": "buster", + "name": "Debian GNU/Linux", + "type": "linux", + "family": "debian", + "version": "10 (buster)", + "platform": "debian" + }, + "containerized": false, + "ip": "11.200.0.195", + "name": "security-linux-2", + "architecture": "x86_64" + }, + "service.name": "filebeat", + "message": "Status message.", + "data_stream": { + "namespace": "default", + "type": "logs", + "dataset": "elastic_agent.filebeat" + }, + "event.agent_id_status": "verified", + "event.ingested": "2022-03-19T02:47:55.722Z", + "event.dataset": "elastic_agent.filebeat", + "kibana.alert.ancestors": [ + { + "id": "ZREToH8BK09aFtXZDlOv", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "kibana.alert.status": "active", + "kibana.alert.workflow_status": "open", + "kibana.alert.depth": 1, + "kibana.alert.reason": "event on security-linux-2 created low alert eql-rule.", + "kibana.alert.building_block_type": "default", + "kibana.alert.severity": "low", + "kibana.alert.risk_score": 21, + "kibana.alert.rule.parameters": { + "description": "a simple eql rule", + "risk_score": 21, + "severity": "low", + "license": "", + "author": [], + "false_positives": [], + "from": "now-36000s", + "rule_id": "4dd16f77-5dd2-46c8-a1d9-f1d2ffb56456", + "max_signals": 100, + "risk_score_mapping": [], + "severity_mapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptions_list": [], + "immutable": false, + "type": "eql", + "language": "eql", + "index": [ + "events-index-*" + ], + "query": "sequence [any where true] [any where true]", + "filters": [] + }, + "kibana.alert.rule.actions": [], + "kibana.alert.rule.created_at": "2022-03-19T02:48:04.202Z", + "kibana.alert.rule.created_by": "elastic", + "kibana.alert.rule.enabled": true, + "kibana.alert.rule.interval": "1m", + "kibana.alert.rule.updated_at": "2022-03-19T02:48:05.465Z", + "kibana.alert.rule.updated_by": "elastic", + "kibana.alert.rule.type": "eql", + "kibana.alert.rule.description": "a simple eql rule", + "kibana.alert.rule.risk_score": 21, + "kibana.alert.rule.severity": "low", + "kibana.alert.rule.license": "", + "kibana.alert.rule.author": [], + "kibana.alert.rule.false_positives": [], + "kibana.alert.rule.from": "now-36000s", + "kibana.alert.rule.rule_id": "4dd16f77-5dd2-46c8-a1d9-f1d2ffb56456", + "kibana.alert.rule.max_signals": 100, + "kibana.alert.rule.risk_score_mapping": [], + "kibana.alert.rule.severity_mapping": [], + "kibana.alert.rule.threat": [], + "kibana.alert.rule.to": "now", + "kibana.alert.rule.references": [], + "kibana.alert.rule.version": 1, + "kibana.alert.rule.exceptions_list": [], + "kibana.alert.rule.immutable": false, + "kibana.alert.original_time": "2022-03-19T02:47:55.722Z", + "kibana.alert.original_event.agent_id_status": "verified", + "kibana.alert.original_event.ingested": "2022-03-19T02:47:55.722Z", + "kibana.alert.original_event.dataset": "elastic_agent.filebeat", + "event.kind": "signal", + "kibana.alert.uuid": "11941a5508aa59bdfa43d8b5c660b26e9aa0eeb67a741ec93c5b61e7670fba7e", + "kibana.alert.group.id": "89565a00d1db6d634d655e9b3e44e399f83c9305d4aafbd96bd476b570d0ef59", + "kibana.alert.group.index": 0 + } + } +} + +{ + "type": "doc", + "value": { + "index": ".internal.alerts-security.alerts-default-000001", + "id": "3c6a7eaf77af1d891cf57c7f8c1296907a2593b90b1fbe0fdcb31d7edc4c1e5f", + "_score": 1, + "source": { + "kibana.version": "8.1.0", + "kibana.alert.rule.category": "Event Correlation Rule", + "kibana.alert.rule.consumer": "siem", + "kibana.alert.rule.execution.uuid": "51d785a9-7d7c-4688-9e64-f7901eef88bb", + "kibana.alert.rule.name": "eql-rule", + "kibana.alert.rule.producer": "siem", + "kibana.alert.rule.rule_type_id": "siem.eqlRule", + "kibana.alert.rule.uuid": "ff7a1d90-a72e-11ec-bc9e-ed906a2c068e", + "kibana.space_ids": [ + "default" + ], + "kibana.alert.rule.tags": [], + "@timestamp": "2022-03-19T02:48:06.832Z", + "agent": { + "name": "security-linux-3.example.dev", + "id": "06851da1-73e7-41e3-97d6-ff1d62c98dc5", + "type": "filebeat", + "version": "8.1.0" + }, + "log": { + "file": { + "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" + }, + "offset": 148938 + }, + "cloud": { + "availability_zone": "us-central1-c", + "instance": { + "name": "security-linux-1", + "id": "8995531128842994872" + }, + "provider": "gcp", + "service": { + "name": "GCE" + }, + "machine": { + "type": "g1-small" + }, + "project": { + "id": "elastic-siem" + }, + "account": { + "id": "elastic-siem" + } + }, + "ecs": { + "version": "8.1.0" + }, + "host": { + "hostname": "security-linux-3", + "os": { + "kernel": "4.19.0-18-cloud-amd64", + "codename": "buster", + "name": "Debian GNU/Linux", + "type": "linux", + "family": "debian", + "version": "10 (buster)", + "platform": "debian" + }, + "containerized": false, + "ip": "11.200.0.196", + "name": "security-linux-3", + "architecture": "x86_64" + }, + "service.name": "filebeat", + "message": "Status message.", + "data_stream": { + "namespace": "default", + "type": "logs", + "dataset": "elastic_agent.filebeat" + }, + "event.agent_id_status": "verified", + "event.ingested": "2022-03-19T02:47:56.044Z", + "event.dataset": "elastic_agent.filebeat", + "kibana.alert.ancestors": [ + { + "id": "ZhEToH8BK09aFtXZD1P3", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "kibana.alert.status": "active", + "kibana.alert.workflow_status": "open", + "kibana.alert.depth": 1, + "kibana.alert.reason": "event on security-linux-3 created low alert eql-rule.", + "kibana.alert.building_block_type": "default", + "kibana.alert.severity": "low", + "kibana.alert.risk_score": 21, + "kibana.alert.rule.parameters": { + "description": "a simple eql rule", + "risk_score": 21, + "severity": "low", + "license": "", + "author": [], + "false_positives": [], + "from": "now-36000s", + "rule_id": "4dd16f77-5dd2-46c8-a1d9-f1d2ffb56456", + "max_signals": 100, + "risk_score_mapping": [], + "severity_mapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptions_list": [], + "immutable": false, + "type": "eql", + "language": "eql", + "index": [ + "events-index-*" + ], + "query": "sequence [any where true] [any where true]", + "filters": [] + }, + "kibana.alert.rule.actions": [], + "kibana.alert.rule.created_at": "2022-03-19T02:48:04.202Z", + "kibana.alert.rule.created_by": "elastic", + "kibana.alert.rule.enabled": true, + "kibana.alert.rule.interval": "1m", + "kibana.alert.rule.updated_at": "2022-03-19T02:48:05.465Z", + "kibana.alert.rule.updated_by": "elastic", + "kibana.alert.rule.type": "eql", + "kibana.alert.rule.description": "a simple eql rule", + "kibana.alert.rule.risk_score": 21, + "kibana.alert.rule.severity": "low", + "kibana.alert.rule.license": "", + "kibana.alert.rule.author": [], + "kibana.alert.rule.false_positives": [], + "kibana.alert.rule.from": "now-36000s", + "kibana.alert.rule.rule_id": "4dd16f77-5dd2-46c8-a1d9-f1d2ffb56456", + "kibana.alert.rule.max_signals": 100, + "kibana.alert.rule.risk_score_mapping": [], + "kibana.alert.rule.severity_mapping": [], + "kibana.alert.rule.threat": [], + "kibana.alert.rule.to": "now", + "kibana.alert.rule.references": [], + "kibana.alert.rule.version": 1, + "kibana.alert.rule.exceptions_list": [], + "kibana.alert.rule.immutable": false, + "kibana.alert.original_time": "2022-03-19T02:47:56.044Z", + "kibana.alert.original_event.agent_id_status": "verified", + "kibana.alert.original_event.ingested": "2022-03-19T02:47:56.044Z", + "kibana.alert.original_event.dataset": "elastic_agent.filebeat", + "event.kind": "signal", + "kibana.alert.uuid": "3c6a7eaf77af1d891cf57c7f8c1296907a2593b90b1fbe0fdcb31d7edc4c1e5f", + "kibana.alert.group.id": "89565a00d1db6d634d655e9b3e44e399f83c9305d4aafbd96bd476b570d0ef59", + "kibana.alert.group.index": 1 + } + } +} + +{ + "type": "doc", + "value": { + "index": ".internal.alerts-security.alerts-default-000001", + "id": "89565a00d1db6d634d655e9b3e44e399f83c9305d4aafbd96bd476b570d0ef59", + "_score": 1, + "source": { + "kibana.version": "8.1.0", + "kibana.alert.rule.category": "Event Correlation Rule", + "kibana.alert.rule.consumer": "siem", + "kibana.alert.rule.execution.uuid": "51d785a9-7d7c-4688-9e64-f7901eef88bb", + "kibana.alert.rule.name": "eql-rule", + "kibana.alert.rule.producer": "siem", + "kibana.alert.rule.rule_type_id": "siem.eqlRule", + "kibana.alert.rule.uuid": "ff7a1d90-a72e-11ec-bc9e-ed906a2c068e", + "kibana.space_ids": [ + "default" + ], + "kibana.alert.rule.tags": [], + "@timestamp": "2022-03-19T02:48:06.833Z", + "agent": { + "type": "filebeat", + "version": "8.1.0" + }, + "log": { + "file": { + "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" + }, + "offset": 148938 + }, + "cloud": { + "availability_zone": "us-central1-c", + "instance": { + "name": "security-linux-1", + "id": "8995531128842994872" + }, + "provider": "gcp", + "service": { + "name": "GCE" + }, + "machine": { + "type": "g1-small" + }, + "project": { + "id": "elastic-siem" + }, + "account": { + "id": "elastic-siem" + } + }, + "ecs": { + "version": "8.1.0" + }, + "host": { + "os": { + "kernel": "4.19.0-18-cloud-amd64", + "codename": "buster", + "name": "Debian GNU/Linux", + "type": "linux", + "family": "debian", + "version": "10 (buster)", + "platform": "debian" + }, + "containerized": false, + "architecture": "x86_64" + }, + "service.name": "filebeat", + "message": "Status message.", + "data_stream": { + "namespace": "default", + "type": "logs", + "dataset": "elastic_agent.filebeat" + }, + "event.agent_id_status": "verified", + "event.dataset": "elastic_agent.filebeat", + "kibana.alert.status": "active", + "kibana.alert.workflow_status": "open", + "kibana.alert.depth": 2, + "kibana.alert.severity": "low", + "kibana.alert.risk_score": 21, + "kibana.alert.rule.parameters": { + "description": "a simple eql rule", + "risk_score": 21, + "severity": "low", + "license": "", + "author": [], + "false_positives": [], + "from": "now-36000s", + "rule_id": "4dd16f77-5dd2-46c8-a1d9-f1d2ffb56456", + "max_signals": 100, + "risk_score_mapping": [], + "severity_mapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptions_list": [], + "immutable": false, + "type": "eql", + "language": "eql", + "index": [ + "events-index-*" + ], + "query": "sequence [any where true] [any where true]", + "filters": [] + }, + "kibana.alert.rule.created_at": "2022-03-19T02:48:04.202Z", + "kibana.alert.rule.created_by": "elastic", + "kibana.alert.rule.enabled": true, + "kibana.alert.rule.interval": "1m", + "kibana.alert.rule.updated_at": "2022-03-19T02:48:05.465Z", + "kibana.alert.rule.updated_by": "elastic", + "kibana.alert.rule.type": "eql", + "kibana.alert.rule.description": "a simple eql rule", + "kibana.alert.rule.risk_score": 21, + "kibana.alert.rule.severity": "low", + "kibana.alert.rule.license": "", + "kibana.alert.rule.author": [], + "kibana.alert.rule.false_positives": [], + "kibana.alert.rule.from": "now-36000s", + "kibana.alert.rule.rule_id": "4dd16f77-5dd2-46c8-a1d9-f1d2ffb56456", + "kibana.alert.rule.max_signals": 100, + "kibana.alert.rule.risk_score_mapping": [], + "kibana.alert.rule.severity_mapping": [], + "kibana.alert.rule.threat": [], + "kibana.alert.rule.to": "now", + "kibana.alert.rule.references": [], + "kibana.alert.rule.version": 1, + "kibana.alert.rule.exceptions_list": [], + "kibana.alert.rule.immutable": false, + "kibana.alert.original_event.agent_id_status": "verified", + "kibana.alert.original_event.dataset": "elastic_agent.filebeat", + "event.kind": "signal", + "event": { + "kind": "signal" + }, + "kibana.alert.ancestors": [ + { + "id": "ZREToH8BK09aFtXZDlOv", + "type": "event", + "index": "events-index-000001", + "depth": 0 + }, + { + "id": "11941a5508aa59bdfa43d8b5c660b26e9aa0eeb67a741ec93c5b61e7670fba7e", + "type": "signal", + "index": "", + "depth": 1, + "rule": "ff7a1d90-a72e-11ec-bc9e-ed906a2c068e" + }, + { + "id": "ZhEToH8BK09aFtXZD1P3", + "type": "event", + "index": "events-index-000001", + "depth": 0 + }, + { + "id": "3c6a7eaf77af1d891cf57c7f8c1296907a2593b90b1fbe0fdcb31d7edc4c1e5f", + "type": "signal", + "index": "", + "depth": 1, + "rule": "ff7a1d90-a72e-11ec-bc9e-ed906a2c068e" + } + ], + "kibana.alert.reason": "event created low alert eql-rule.", + "kibana.alert.rule.actions": [], + "kibana.alert.original_time": "2022-03-19T02:47:55.722Z", + "kibana.alert.group.id": "89565a00d1db6d634d655e9b3e44e399f83c9305d4aafbd96bd476b570d0ef59", + "kibana.alert.uuid": "89565a00d1db6d634d655e9b3e44e399f83c9305d4aafbd96bd476b570d0ef59" + } + } +} + +{ + "type": "doc", + "value": { + "index": ".internal.alerts-security.alerts-default-000001", + "id": "e2c0a0d7bdb23e8cf9cb37da28fe0eb9ee890e164b8adcb9a774b21d21d4191c", + "_score": 1, + "source": { + "kibana.version": "8.1.0", + "kibana.alert.rule.category": "Event Correlation Rule", + "kibana.alert.rule.consumer": "siem", + "kibana.alert.rule.execution.uuid": "51d785a9-7d7c-4688-9e64-f7901eef88bb", + "kibana.alert.rule.name": "eql-rule", + "kibana.alert.rule.producer": "siem", + "kibana.alert.rule.rule_type_id": "siem.eqlRule", + "kibana.alert.rule.uuid": "ff7a1d90-a72e-11ec-bc9e-ed906a2c068e", + "kibana.space_ids": [ + "default" + ], + "kibana.alert.rule.tags": [], + "@timestamp": "2022-03-19T02:48:06.836Z", + "agent": { + "name": "security-linux-3.example.dev", + "id": "06851da1-73e7-41e3-97d6-ff1d62c98dc5", + "type": "filebeat", + "version": "8.1.0" + }, + "log": { + "file": { + "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" + }, + "offset": 148938 + }, + "cloud": { + "availability_zone": "us-central1-c", + "instance": { + "name": "security-linux-1", + "id": "8995531128842994872" + }, + "provider": "gcp", + "service": { + "name": "GCE" + }, + "machine": { + "type": "g1-small" + }, + "project": { + "id": "elastic-siem" + }, + "account": { + "id": "elastic-siem" + } + }, + "ecs": { + "version": "8.1.0" + }, + "host": { + "hostname": "security-linux-3", + "os": { + "kernel": "4.19.0-18-cloud-amd64", + "codename": "buster", + "name": "Debian GNU/Linux", + "type": "linux", + "family": "debian", + "version": "10 (buster)", + "platform": "debian" + }, + "containerized": false, + "ip": "11.200.0.196", + "name": "security-linux-3", + "architecture": "x86_64" + }, + "service.name": "filebeat", + "message": "Status message.", + "data_stream": { + "namespace": "default", + "type": "logs", + "dataset": "elastic_agent.filebeat" + }, + "event.agent_id_status": "verified", + "event.ingested": "2022-03-19T02:47:56.044Z", + "event.dataset": "elastic_agent.filebeat", + "kibana.alert.ancestors": [ + { + "id": "ZhEToH8BK09aFtXZD1P3", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "kibana.alert.status": "active", + "kibana.alert.workflow_status": "open", + "kibana.alert.depth": 1, + "kibana.alert.reason": "event on security-linux-3 created low alert eql-rule.", + "kibana.alert.building_block_type": "default", + "kibana.alert.severity": "low", + "kibana.alert.risk_score": 21, + "kibana.alert.rule.parameters": { + "description": "a simple eql rule", + "risk_score": 21, + "severity": "low", + "license": "", + "author": [], + "false_positives": [], + "from": "now-36000s", + "rule_id": "4dd16f77-5dd2-46c8-a1d9-f1d2ffb56456", + "max_signals": 100, + "risk_score_mapping": [], + "severity_mapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptions_list": [], + "immutable": false, + "type": "eql", + "language": "eql", + "index": [ + "events-index-*" + ], + "query": "sequence [any where true] [any where true]", + "filters": [] + }, + "kibana.alert.rule.actions": [], + "kibana.alert.rule.created_at": "2022-03-19T02:48:04.202Z", + "kibana.alert.rule.created_by": "elastic", + "kibana.alert.rule.enabled": true, + "kibana.alert.rule.interval": "1m", + "kibana.alert.rule.updated_at": "2022-03-19T02:48:05.465Z", + "kibana.alert.rule.updated_by": "elastic", + "kibana.alert.rule.type": "eql", + "kibana.alert.rule.description": "a simple eql rule", + "kibana.alert.rule.risk_score": 21, + "kibana.alert.rule.severity": "low", + "kibana.alert.rule.license": "", + "kibana.alert.rule.author": [], + "kibana.alert.rule.false_positives": [], + "kibana.alert.rule.from": "now-36000s", + "kibana.alert.rule.rule_id": "4dd16f77-5dd2-46c8-a1d9-f1d2ffb56456", + "kibana.alert.rule.max_signals": 100, + "kibana.alert.rule.risk_score_mapping": [], + "kibana.alert.rule.severity_mapping": [], + "kibana.alert.rule.threat": [], + "kibana.alert.rule.to": "now", + "kibana.alert.rule.references": [], + "kibana.alert.rule.version": 1, + "kibana.alert.rule.exceptions_list": [], + "kibana.alert.rule.immutable": false, + "kibana.alert.original_time": "2022-03-19T02:47:56.044Z", + "kibana.alert.original_event.agent_id_status": "verified", + "kibana.alert.original_event.ingested": "2022-03-19T02:47:56.044Z", + "kibana.alert.original_event.dataset": "elastic_agent.filebeat", + "event.kind": "signal", + "kibana.alert.uuid": "e2c0a0d7bdb23e8cf9cb37da28fe0eb9ee890e164b8adcb9a774b21d21d4191c", + "kibana.alert.group.id": "34c97599a4f1a2d0a9c03934bf7e00b3894e5188f478db436aa23af09feb5344", + "kibana.alert.group.index": 0 + } + } +} + +{ + "type": "doc", + "value": { + "index": ".internal.alerts-security.alerts-default-000001", + "id": "b437e07a5f89d081884ce89a546c7d1857c481389b3b2acc8792805d180a6cd4", + "_score": 1, + "source": { + "kibana.version": "8.1.0", + "kibana.alert.rule.category": "Event Correlation Rule", + "kibana.alert.rule.consumer": "siem", + "kibana.alert.rule.execution.uuid": "51d785a9-7d7c-4688-9e64-f7901eef88bb", + "kibana.alert.rule.name": "eql-rule", + "kibana.alert.rule.producer": "siem", + "kibana.alert.rule.rule_type_id": "siem.eqlRule", + "kibana.alert.rule.uuid": "ff7a1d90-a72e-11ec-bc9e-ed906a2c068e", + "kibana.space_ids": [ + "default" + ], + "kibana.alert.rule.tags": [], + "@timestamp": "2022-03-19T02:48:06.838Z", + "agent": { + "name": "security-linux-1.example.dev", + "id": "d8f66724-3cf2-437c-b124-6ac9fb0e2311", + "type": "filebeat", + "version": "8.1.0" + }, + "log": { + "file": { + "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" + }, + "offset": 148938 + }, + "cloud": { + "availability_zone": "us-central1-c", + "instance": { + "name": "security-linux-1", + "id": "8995531128842994872" + }, + "provider": "gcp", + "service": { + "name": "GCE" + }, + "machine": { + "type": "g1-small" + }, + "project": { + "id": "elastic-siem" + }, + "account": { + "id": "elastic-siem" + } + }, + "ecs": { + "version": "8.1.0" + }, + "host": { + "hostname": "security-linux-1", + "os": { + "kernel": "4.19.0-18-cloud-amd64", + "codename": "buster", + "name": "Debian GNU/Linux", + "type": "linux", + "family": "debian", + "version": "10 (buster)", + "platform": "debian" + }, + "containerized": false, + "ip": "11.200.0.194", + "name": "security-linux-1", + "architecture": "x86_64" + }, + "service.name": "filebeat", + "message": "Status message.", + "data_stream": { + "namespace": "default", + "type": "logs", + "dataset": "elastic_agent.filebeat" + }, + "event.agent_id_status": "verified", + "event.ingested": "2022-03-19T02:47:56.372Z", + "event.dataset": "elastic_agent.filebeat", + "kibana.alert.ancestors": [ + { + "id": "ZxEToH8BK09aFtXZEVNR", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "kibana.alert.status": "active", + "kibana.alert.workflow_status": "open", + "kibana.alert.depth": 1, + "kibana.alert.reason": "event on security-linux-1 created low alert eql-rule.", + "kibana.alert.building_block_type": "default", + "kibana.alert.severity": "low", + "kibana.alert.risk_score": 21, + "kibana.alert.rule.parameters": { + "description": "a simple eql rule", + "risk_score": 21, + "severity": "low", + "license": "", + "author": [], + "false_positives": [], + "from": "now-36000s", + "rule_id": "4dd16f77-5dd2-46c8-a1d9-f1d2ffb56456", + "max_signals": 100, + "risk_score_mapping": [], + "severity_mapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptions_list": [], + "immutable": false, + "type": "eql", + "language": "eql", + "index": [ + "events-index-*" + ], + "query": "sequence [any where true] [any where true]", + "filters": [] + }, + "kibana.alert.rule.actions": [], + "kibana.alert.rule.created_at": "2022-03-19T02:48:04.202Z", + "kibana.alert.rule.created_by": "elastic", + "kibana.alert.rule.enabled": true, + "kibana.alert.rule.interval": "1m", + "kibana.alert.rule.updated_at": "2022-03-19T02:48:05.465Z", + "kibana.alert.rule.updated_by": "elastic", + "kibana.alert.rule.type": "eql", + "kibana.alert.rule.description": "a simple eql rule", + "kibana.alert.rule.risk_score": 21, + "kibana.alert.rule.severity": "low", + "kibana.alert.rule.license": "", + "kibana.alert.rule.author": [], + "kibana.alert.rule.false_positives": [], + "kibana.alert.rule.from": "now-36000s", + "kibana.alert.rule.rule_id": "4dd16f77-5dd2-46c8-a1d9-f1d2ffb56456", + "kibana.alert.rule.max_signals": 100, + "kibana.alert.rule.risk_score_mapping": [], + "kibana.alert.rule.severity_mapping": [], + "kibana.alert.rule.threat": [], + "kibana.alert.rule.to": "now", + "kibana.alert.rule.references": [], + "kibana.alert.rule.version": 1, + "kibana.alert.rule.exceptions_list": [], + "kibana.alert.rule.immutable": false, + "kibana.alert.original_time": "2022-03-19T02:47:56.372Z", + "kibana.alert.original_event.agent_id_status": "verified", + "kibana.alert.original_event.ingested": "2022-03-19T02:47:56.372Z", + "kibana.alert.original_event.dataset": "elastic_agent.filebeat", + "event.kind": "signal", + "kibana.alert.uuid": "b437e07a5f89d081884ce89a546c7d1857c481389b3b2acc8792805d180a6cd4", + "kibana.alert.group.id": "34c97599a4f1a2d0a9c03934bf7e00b3894e5188f478db436aa23af09feb5344", + "kibana.alert.group.index": 1 + } + } +} + +{ + "type": "doc", + "value": { + "index": ".internal.alerts-security.alerts-default-000001", + "id": "34c97599a4f1a2d0a9c03934bf7e00b3894e5188f478db436aa23af09feb5344", + "_score": 1, + "source": { + "kibana.version": "8.1.0", + "kibana.alert.rule.category": "Event Correlation Rule", + "kibana.alert.rule.consumer": "siem", + "kibana.alert.rule.execution.uuid": "51d785a9-7d7c-4688-9e64-f7901eef88bb", + "kibana.alert.rule.name": "eql-rule", + "kibana.alert.rule.producer": "siem", + "kibana.alert.rule.rule_type_id": "siem.eqlRule", + "kibana.alert.rule.uuid": "ff7a1d90-a72e-11ec-bc9e-ed906a2c068e", + "kibana.space_ids": [ + "default" + ], + "kibana.alert.rule.tags": [], + "@timestamp": "2022-03-19T02:48:06.838Z", + "agent": { + "type": "filebeat", + "version": "8.1.0" + }, + "log": { + "file": { + "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" + }, + "offset": 148938 + }, + "cloud": { + "availability_zone": "us-central1-c", + "instance": { + "name": "security-linux-1", + "id": "8995531128842994872" + }, + "provider": "gcp", + "service": { + "name": "GCE" + }, + "machine": { + "type": "g1-small" + }, + "project": { + "id": "elastic-siem" + }, + "account": { + "id": "elastic-siem" + } + }, + "ecs": { + "version": "8.1.0" + }, + "host": { + "os": { + "kernel": "4.19.0-18-cloud-amd64", + "codename": "buster", + "name": "Debian GNU/Linux", + "type": "linux", + "family": "debian", + "version": "10 (buster)", + "platform": "debian" + }, + "containerized": false, + "architecture": "x86_64" + }, + "service.name": "filebeat", + "message": "Status message.", + "data_stream": { + "namespace": "default", + "type": "logs", + "dataset": "elastic_agent.filebeat" + }, + "event.agent_id_status": "verified", + "event.dataset": "elastic_agent.filebeat", + "kibana.alert.status": "active", + "kibana.alert.workflow_status": "open", + "kibana.alert.depth": 2, + "kibana.alert.severity": "low", + "kibana.alert.risk_score": 21, + "kibana.alert.rule.parameters": { + "description": "a simple eql rule", + "risk_score": 21, + "severity": "low", + "license": "", + "author": [], + "false_positives": [], + "from": "now-36000s", + "rule_id": "4dd16f77-5dd2-46c8-a1d9-f1d2ffb56456", + "max_signals": 100, + "risk_score_mapping": [], + "severity_mapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptions_list": [], + "immutable": false, + "type": "eql", + "language": "eql", + "index": [ + "events-index-*" + ], + "query": "sequence [any where true] [any where true]", + "filters": [] + }, + "kibana.alert.rule.created_at": "2022-03-19T02:48:04.202Z", + "kibana.alert.rule.created_by": "elastic", + "kibana.alert.rule.enabled": true, + "kibana.alert.rule.interval": "1m", + "kibana.alert.rule.updated_at": "2022-03-19T02:48:05.465Z", + "kibana.alert.rule.updated_by": "elastic", + "kibana.alert.rule.type": "eql", + "kibana.alert.rule.description": "a simple eql rule", + "kibana.alert.rule.risk_score": 21, + "kibana.alert.rule.severity": "low", + "kibana.alert.rule.license": "", + "kibana.alert.rule.author": [], + "kibana.alert.rule.false_positives": [], + "kibana.alert.rule.from": "now-36000s", + "kibana.alert.rule.rule_id": "4dd16f77-5dd2-46c8-a1d9-f1d2ffb56456", + "kibana.alert.rule.max_signals": 100, + "kibana.alert.rule.risk_score_mapping": [], + "kibana.alert.rule.severity_mapping": [], + "kibana.alert.rule.threat": [], + "kibana.alert.rule.to": "now", + "kibana.alert.rule.references": [], + "kibana.alert.rule.version": 1, + "kibana.alert.rule.exceptions_list": [], + "kibana.alert.rule.immutable": false, + "kibana.alert.original_event.agent_id_status": "verified", + "kibana.alert.original_event.dataset": "elastic_agent.filebeat", + "event.kind": "signal", + "event": { + "kind": "signal" + }, + "kibana.alert.ancestors": [ + { + "id": "ZhEToH8BK09aFtXZD1P3", + "type": "event", + "index": "events-index-000001", + "depth": 0 + }, + { + "id": "e2c0a0d7bdb23e8cf9cb37da28fe0eb9ee890e164b8adcb9a774b21d21d4191c", + "type": "signal", + "index": "", + "depth": 1, + "rule": "ff7a1d90-a72e-11ec-bc9e-ed906a2c068e" + }, + { + "id": "ZxEToH8BK09aFtXZEVNR", + "type": "event", + "index": "events-index-000001", + "depth": 0 + }, + { + "id": "b437e07a5f89d081884ce89a546c7d1857c481389b3b2acc8792805d180a6cd4", + "type": "signal", + "index": "", + "depth": 1, + "rule": "ff7a1d90-a72e-11ec-bc9e-ed906a2c068e" + } + ], + "kibana.alert.reason": "event created low alert eql-rule.", + "kibana.alert.rule.actions": [], + "kibana.alert.original_time": "2022-03-19T02:47:56.044Z", + "kibana.alert.group.id": "34c97599a4f1a2d0a9c03934bf7e00b3894e5188f478db436aa23af09feb5344", + "kibana.alert.uuid": "34c97599a4f1a2d0a9c03934bf7e00b3894e5188f478db436aa23af09feb5344" + } + } +} + +{ + "type": "doc", + "value": { + "index": ".internal.alerts-security.alerts-default-000001", + "id": "29f746ebfaf25e59068d3bd11849f531c76c05619c0e5d560501bad163912bc7", + "_score": 1, + "source": { + "kibana.version": "8.1.0", + "kibana.alert.rule.category": "Event Correlation Rule", + "kibana.alert.rule.consumer": "siem", + "kibana.alert.rule.execution.uuid": "51d785a9-7d7c-4688-9e64-f7901eef88bb", + "kibana.alert.rule.name": "eql-rule", + "kibana.alert.rule.producer": "siem", + "kibana.alert.rule.rule_type_id": "siem.eqlRule", + "kibana.alert.rule.uuid": "ff7a1d90-a72e-11ec-bc9e-ed906a2c068e", + "kibana.space_ids": [ + "default" + ], + "kibana.alert.rule.tags": [], + "@timestamp": "2022-03-19T02:48:06.842Z", + "agent": { + "name": "security-linux-1.example.dev", + "id": "d8f66724-3cf2-437c-b124-6ac9fb0e2311", + "type": "filebeat", + "version": "8.1.0" + }, + "log": { + "file": { + "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" + }, + "offset": 148938 + }, + "cloud": { + "availability_zone": "us-central1-c", + "instance": { + "name": "security-linux-1", + "id": "8995531128842994872" + }, + "provider": "gcp", + "service": { + "name": "GCE" + }, + "machine": { + "type": "g1-small" + }, + "project": { + "id": "elastic-siem" + }, + "account": { + "id": "elastic-siem" + } + }, + "ecs": { + "version": "8.1.0" + }, + "host": { + "hostname": "security-linux-1", + "os": { + "kernel": "4.19.0-18-cloud-amd64", + "codename": "buster", + "name": "Debian GNU/Linux", + "type": "linux", + "family": "debian", + "version": "10 (buster)", + "platform": "debian" + }, + "containerized": false, + "ip": "11.200.0.194", + "name": "security-linux-1", + "architecture": "x86_64" + }, + "service.name": "filebeat", + "message": "Status message.", + "data_stream": { + "namespace": "default", + "type": "logs", + "dataset": "elastic_agent.filebeat" + }, + "event.agent_id_status": "verified", + "event.ingested": "2022-03-19T02:47:56.372Z", + "event.dataset": "elastic_agent.filebeat", + "kibana.alert.ancestors": [ + { + "id": "ZxEToH8BK09aFtXZEVNR", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "kibana.alert.status": "active", + "kibana.alert.workflow_status": "open", + "kibana.alert.depth": 1, + "kibana.alert.reason": "event on security-linux-1 created low alert eql-rule.", + "kibana.alert.building_block_type": "default", + "kibana.alert.severity": "low", + "kibana.alert.risk_score": 21, + "kibana.alert.rule.parameters": { + "description": "a simple eql rule", + "risk_score": 21, + "severity": "low", + "license": "", + "author": [], + "false_positives": [], + "from": "now-36000s", + "rule_id": "4dd16f77-5dd2-46c8-a1d9-f1d2ffb56456", + "max_signals": 100, + "risk_score_mapping": [], + "severity_mapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptions_list": [], + "immutable": false, + "type": "eql", + "language": "eql", + "index": [ + "events-index-*" + ], + "query": "sequence [any where true] [any where true]", + "filters": [] + }, + "kibana.alert.rule.actions": [], + "kibana.alert.rule.created_at": "2022-03-19T02:48:04.202Z", + "kibana.alert.rule.created_by": "elastic", + "kibana.alert.rule.enabled": true, + "kibana.alert.rule.interval": "1m", + "kibana.alert.rule.updated_at": "2022-03-19T02:48:05.465Z", + "kibana.alert.rule.updated_by": "elastic", + "kibana.alert.rule.type": "eql", + "kibana.alert.rule.description": "a simple eql rule", + "kibana.alert.rule.risk_score": 21, + "kibana.alert.rule.severity": "low", + "kibana.alert.rule.license": "", + "kibana.alert.rule.author": [], + "kibana.alert.rule.false_positives": [], + "kibana.alert.rule.from": "now-36000s", + "kibana.alert.rule.rule_id": "4dd16f77-5dd2-46c8-a1d9-f1d2ffb56456", + "kibana.alert.rule.max_signals": 100, + "kibana.alert.rule.risk_score_mapping": [], + "kibana.alert.rule.severity_mapping": [], + "kibana.alert.rule.threat": [], + "kibana.alert.rule.to": "now", + "kibana.alert.rule.references": [], + "kibana.alert.rule.version": 1, + "kibana.alert.rule.exceptions_list": [], + "kibana.alert.rule.immutable": false, + "kibana.alert.original_time": "2022-03-19T02:47:56.372Z", + "kibana.alert.original_event.agent_id_status": "verified", + "kibana.alert.original_event.ingested": "2022-03-19T02:47:56.372Z", + "kibana.alert.original_event.dataset": "elastic_agent.filebeat", + "event.kind": "signal", + "kibana.alert.uuid": "29f746ebfaf25e59068d3bd11849f531c76c05619c0e5d560501bad163912bc7", + "kibana.alert.group.id": "a0a0cf2900db9a5ad2376e7af94a730fa30e385d04f320c576db3a178559ecfa", + "kibana.alert.group.index": 0 + } + } +} + +{ + "type": "doc", + "value": { + "index": ".internal.alerts-security.alerts-default-000001", + "id": "d677e68795e482d683406cc274621e3908ce80bf47df8505410029ec1aa7e344", + "_score": 1, + "source": { + "kibana.version": "8.1.0", + "kibana.alert.rule.category": "Event Correlation Rule", + "kibana.alert.rule.consumer": "siem", + "kibana.alert.rule.execution.uuid": "51d785a9-7d7c-4688-9e64-f7901eef88bb", + "kibana.alert.rule.name": "eql-rule", + "kibana.alert.rule.producer": "siem", + "kibana.alert.rule.rule_type_id": "siem.eqlRule", + "kibana.alert.rule.uuid": "ff7a1d90-a72e-11ec-bc9e-ed906a2c068e", + "kibana.space_ids": [ + "default" + ], + "kibana.alert.rule.tags": [], + "@timestamp": "2022-03-19T02:48:06.844Z", + "agent": { + "name": "security-linux-2.example.dev", + "id": "87c417dd-08d6-4e24-ad69-285cb8de84e9", + "type": "filebeat", + "version": "8.1.0" + }, + "log": { + "file": { + "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" + }, + "offset": 148938 + }, + "cloud": { + "availability_zone": "us-central1-c", + "instance": { + "name": "security-linux-1", + "id": "8995531128842994872" + }, + "provider": "gcp", + "service": { + "name": "GCE" + }, + "machine": { + "type": "g1-small" + }, + "project": { + "id": "elastic-siem" + }, + "account": { + "id": "elastic-siem" + } + }, + "ecs": { + "version": "8.1.0" + }, + "host": { + "hostname": "security-linux-2", + "os": { + "kernel": "4.19.0-18-cloud-amd64", + "codename": "buster", + "name": "Debian GNU/Linux", + "type": "linux", + "family": "debian", + "version": "10 (buster)", + "platform": "debian" + }, + "containerized": false, + "ip": "11.200.0.195", + "name": "security-linux-2", + "architecture": "x86_64" + }, + "service.name": "filebeat", + "message": "Status message.", + "data_stream": { + "namespace": "default", + "type": "logs", + "dataset": "elastic_agent.filebeat" + }, + "event.agent_id_status": "verified", + "event.ingested": "2022-03-19T02:47:56.723Z", + "event.dataset": "elastic_agent.filebeat", + "kibana.alert.ancestors": [ + { + "id": "aBEToH8BK09aFtXZElOb", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "kibana.alert.status": "active", + "kibana.alert.workflow_status": "open", + "kibana.alert.depth": 1, + "kibana.alert.reason": "event on security-linux-2 created low alert eql-rule.", + "kibana.alert.building_block_type": "default", + "kibana.alert.severity": "low", + "kibana.alert.risk_score": 21, + "kibana.alert.rule.parameters": { + "description": "a simple eql rule", + "risk_score": 21, + "severity": "low", + "license": "", + "author": [], + "false_positives": [], + "from": "now-36000s", + "rule_id": "4dd16f77-5dd2-46c8-a1d9-f1d2ffb56456", + "max_signals": 100, + "risk_score_mapping": [], + "severity_mapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptions_list": [], + "immutable": false, + "type": "eql", + "language": "eql", + "index": [ + "events-index-*" + ], + "query": "sequence [any where true] [any where true]", + "filters": [] + }, + "kibana.alert.rule.actions": [], + "kibana.alert.rule.created_at": "2022-03-19T02:48:04.202Z", + "kibana.alert.rule.created_by": "elastic", + "kibana.alert.rule.enabled": true, + "kibana.alert.rule.interval": "1m", + "kibana.alert.rule.updated_at": "2022-03-19T02:48:05.465Z", + "kibana.alert.rule.updated_by": "elastic", + "kibana.alert.rule.type": "eql", + "kibana.alert.rule.description": "a simple eql rule", + "kibana.alert.rule.risk_score": 21, + "kibana.alert.rule.severity": "low", + "kibana.alert.rule.license": "", + "kibana.alert.rule.author": [], + "kibana.alert.rule.false_positives": [], + "kibana.alert.rule.from": "now-36000s", + "kibana.alert.rule.rule_id": "4dd16f77-5dd2-46c8-a1d9-f1d2ffb56456", + "kibana.alert.rule.max_signals": 100, + "kibana.alert.rule.risk_score_mapping": [], + "kibana.alert.rule.severity_mapping": [], + "kibana.alert.rule.threat": [], + "kibana.alert.rule.to": "now", + "kibana.alert.rule.references": [], + "kibana.alert.rule.version": 1, + "kibana.alert.rule.exceptions_list": [], + "kibana.alert.rule.immutable": false, + "kibana.alert.original_time": "2022-03-19T02:47:56.723Z", + "kibana.alert.original_event.agent_id_status": "verified", + "kibana.alert.original_event.ingested": "2022-03-19T02:47:56.723Z", + "kibana.alert.original_event.dataset": "elastic_agent.filebeat", + "event.kind": "signal", + "kibana.alert.uuid": "d677e68795e482d683406cc274621e3908ce80bf47df8505410029ec1aa7e344", + "kibana.alert.group.id": "a0a0cf2900db9a5ad2376e7af94a730fa30e385d04f320c576db3a178559ecfa", + "kibana.alert.group.index": 1 + } + } +} + +{ + "type": "doc", + "value": { + "index": ".internal.alerts-security.alerts-default-000001", + "id": "a0a0cf2900db9a5ad2376e7af94a730fa30e385d04f320c576db3a178559ecfa", + "_score": 1, + "source": { + "kibana.version": "8.1.0", + "kibana.alert.rule.category": "Event Correlation Rule", + "kibana.alert.rule.consumer": "siem", + "kibana.alert.rule.execution.uuid": "51d785a9-7d7c-4688-9e64-f7901eef88bb", + "kibana.alert.rule.name": "eql-rule", + "kibana.alert.rule.producer": "siem", + "kibana.alert.rule.rule_type_id": "siem.eqlRule", + "kibana.alert.rule.uuid": "ff7a1d90-a72e-11ec-bc9e-ed906a2c068e", + "kibana.space_ids": [ + "default" + ], + "kibana.alert.rule.tags": [], + "@timestamp": "2022-03-19T02:48:06.844Z", + "agent": { + "type": "filebeat", + "version": "8.1.0" + }, + "log": { + "file": { + "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" + }, + "offset": 148938 + }, + "cloud": { + "availability_zone": "us-central1-c", + "instance": { + "name": "security-linux-1", + "id": "8995531128842994872" + }, + "provider": "gcp", + "service": { + "name": "GCE" + }, + "machine": { + "type": "g1-small" + }, + "project": { + "id": "elastic-siem" + }, + "account": { + "id": "elastic-siem" + } + }, + "ecs": { + "version": "8.1.0" + }, + "host": { + "os": { + "kernel": "4.19.0-18-cloud-amd64", + "codename": "buster", + "name": "Debian GNU/Linux", + "type": "linux", + "family": "debian", + "version": "10 (buster)", + "platform": "debian" + }, + "containerized": false, + "architecture": "x86_64" + }, + "service.name": "filebeat", + "message": "Status message.", + "data_stream": { + "namespace": "default", + "type": "logs", + "dataset": "elastic_agent.filebeat" + }, + "event.agent_id_status": "verified", + "event.dataset": "elastic_agent.filebeat", + "kibana.alert.status": "active", + "kibana.alert.workflow_status": "open", + "kibana.alert.depth": 2, + "kibana.alert.severity": "low", + "kibana.alert.risk_score": 21, + "kibana.alert.rule.parameters": { + "description": "a simple eql rule", + "risk_score": 21, + "severity": "low", + "license": "", + "author": [], + "false_positives": [], + "from": "now-36000s", + "rule_id": "4dd16f77-5dd2-46c8-a1d9-f1d2ffb56456", + "max_signals": 100, + "risk_score_mapping": [], + "severity_mapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptions_list": [], + "immutable": false, + "type": "eql", + "language": "eql", + "index": [ + "events-index-*" + ], + "query": "sequence [any where true] [any where true]", + "filters": [] + }, + "kibana.alert.rule.created_at": "2022-03-19T02:48:04.202Z", + "kibana.alert.rule.created_by": "elastic", + "kibana.alert.rule.enabled": true, + "kibana.alert.rule.interval": "1m", + "kibana.alert.rule.updated_at": "2022-03-19T02:48:05.465Z", + "kibana.alert.rule.updated_by": "elastic", + "kibana.alert.rule.type": "eql", + "kibana.alert.rule.description": "a simple eql rule", + "kibana.alert.rule.risk_score": 21, + "kibana.alert.rule.severity": "low", + "kibana.alert.rule.license": "", + "kibana.alert.rule.author": [], + "kibana.alert.rule.false_positives": [], + "kibana.alert.rule.from": "now-36000s", + "kibana.alert.rule.rule_id": "4dd16f77-5dd2-46c8-a1d9-f1d2ffb56456", + "kibana.alert.rule.max_signals": 100, + "kibana.alert.rule.risk_score_mapping": [], + "kibana.alert.rule.severity_mapping": [], + "kibana.alert.rule.threat": [], + "kibana.alert.rule.to": "now", + "kibana.alert.rule.references": [], + "kibana.alert.rule.version": 1, + "kibana.alert.rule.exceptions_list": [], + "kibana.alert.rule.immutable": false, + "kibana.alert.original_event.agent_id_status": "verified", + "kibana.alert.original_event.dataset": "elastic_agent.filebeat", + "event.kind": "signal", + "event": { + "kind": "signal" + }, + "kibana.alert.ancestors": [ + { + "id": "ZxEToH8BK09aFtXZEVNR", + "type": "event", + "index": "events-index-000001", + "depth": 0 + }, + { + "id": "29f746ebfaf25e59068d3bd11849f531c76c05619c0e5d560501bad163912bc7", + "type": "signal", + "index": "", + "depth": 1, + "rule": "ff7a1d90-a72e-11ec-bc9e-ed906a2c068e" + }, + { + "id": "aBEToH8BK09aFtXZElOb", + "type": "event", + "index": "events-index-000001", + "depth": 0 + }, + { + "id": "d677e68795e482d683406cc274621e3908ce80bf47df8505410029ec1aa7e344", + "type": "signal", + "index": "", + "depth": 1, + "rule": "ff7a1d90-a72e-11ec-bc9e-ed906a2c068e" + } + ], + "kibana.alert.reason": "event created low alert eql-rule.", + "kibana.alert.rule.actions": [], + "kibana.alert.original_time": "2022-03-19T02:47:56.372Z", + "kibana.alert.group.id": "a0a0cf2900db9a5ad2376e7af94a730fa30e385d04f320c576db3a178559ecfa", + "kibana.alert.uuid": "a0a0cf2900db9a5ad2376e7af94a730fa30e385d04f320c576db3a178559ecfa" + } + } +} + +{ + "type": "doc", + "value": { + "index": ".internal.alerts-security.alerts-default-000001", + "id": "efd22ae93ac2d5fc7f91f1d9e52deb1b994263e6b16cf52711cc96df2919fef1", + "_score": 1, + "source": { + "kibana.version": "8.1.0", + "kibana.alert.rule.category": "Event Correlation Rule", + "kibana.alert.rule.consumer": "siem", + "kibana.alert.rule.execution.uuid": "51d785a9-7d7c-4688-9e64-f7901eef88bb", + "kibana.alert.rule.name": "eql-rule", + "kibana.alert.rule.producer": "siem", + "kibana.alert.rule.rule_type_id": "siem.eqlRule", + "kibana.alert.rule.uuid": "ff7a1d90-a72e-11ec-bc9e-ed906a2c068e", + "kibana.space_ids": [ + "default" + ], + "kibana.alert.rule.tags": [], + "@timestamp": "2022-03-19T02:48:06.847Z", + "agent": { + "name": "security-linux-2.example.dev", + "id": "87c417dd-08d6-4e24-ad69-285cb8de84e9", + "type": "filebeat", + "version": "8.1.0" + }, + "log": { + "file": { + "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" + }, + "offset": 148938 + }, + "cloud": { + "availability_zone": "us-central1-c", + "instance": { + "name": "security-linux-1", + "id": "8995531128842994872" + }, + "provider": "gcp", + "service": { + "name": "GCE" + }, + "machine": { + "type": "g1-small" + }, + "project": { + "id": "elastic-siem" + }, + "account": { + "id": "elastic-siem" + } + }, + "ecs": { + "version": "8.1.0" + }, + "host": { + "hostname": "security-linux-2", + "os": { + "kernel": "4.19.0-18-cloud-amd64", + "codename": "buster", + "name": "Debian GNU/Linux", + "type": "linux", + "family": "debian", + "version": "10 (buster)", + "platform": "debian" + }, + "containerized": false, + "ip": "11.200.0.195", + "name": "security-linux-2", + "architecture": "x86_64" + }, + "service.name": "filebeat", + "message": "Status message.", + "data_stream": { + "namespace": "default", + "type": "logs", + "dataset": "elastic_agent.filebeat" + }, + "event.agent_id_status": "verified", + "event.ingested": "2022-03-19T02:47:56.723Z", + "event.dataset": "elastic_agent.filebeat", + "kibana.alert.ancestors": [ + { + "id": "aBEToH8BK09aFtXZElOb", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "kibana.alert.status": "active", + "kibana.alert.workflow_status": "open", + "kibana.alert.depth": 1, + "kibana.alert.reason": "event on security-linux-2 created low alert eql-rule.", + "kibana.alert.building_block_type": "default", + "kibana.alert.severity": "low", + "kibana.alert.risk_score": 21, + "kibana.alert.rule.parameters": { + "description": "a simple eql rule", + "risk_score": 21, + "severity": "low", + "license": "", + "author": [], + "false_positives": [], + "from": "now-36000s", + "rule_id": "4dd16f77-5dd2-46c8-a1d9-f1d2ffb56456", + "max_signals": 100, + "risk_score_mapping": [], + "severity_mapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptions_list": [], + "immutable": false, + "type": "eql", + "language": "eql", + "index": [ + "events-index-*" + ], + "query": "sequence [any where true] [any where true]", + "filters": [] + }, + "kibana.alert.rule.actions": [], + "kibana.alert.rule.created_at": "2022-03-19T02:48:04.202Z", + "kibana.alert.rule.created_by": "elastic", + "kibana.alert.rule.enabled": true, + "kibana.alert.rule.interval": "1m", + "kibana.alert.rule.updated_at": "2022-03-19T02:48:05.465Z", + "kibana.alert.rule.updated_by": "elastic", + "kibana.alert.rule.type": "eql", + "kibana.alert.rule.description": "a simple eql rule", + "kibana.alert.rule.risk_score": 21, + "kibana.alert.rule.severity": "low", + "kibana.alert.rule.license": "", + "kibana.alert.rule.author": [], + "kibana.alert.rule.false_positives": [], + "kibana.alert.rule.from": "now-36000s", + "kibana.alert.rule.rule_id": "4dd16f77-5dd2-46c8-a1d9-f1d2ffb56456", + "kibana.alert.rule.max_signals": 100, + "kibana.alert.rule.risk_score_mapping": [], + "kibana.alert.rule.severity_mapping": [], + "kibana.alert.rule.threat": [], + "kibana.alert.rule.to": "now", + "kibana.alert.rule.references": [], + "kibana.alert.rule.version": 1, + "kibana.alert.rule.exceptions_list": [], + "kibana.alert.rule.immutable": false, + "kibana.alert.original_time": "2022-03-19T02:47:56.723Z", + "kibana.alert.original_event.agent_id_status": "verified", + "kibana.alert.original_event.ingested": "2022-03-19T02:47:56.723Z", + "kibana.alert.original_event.dataset": "elastic_agent.filebeat", + "event.kind": "signal", + "kibana.alert.uuid": "efd22ae93ac2d5fc7f91f1d9e52deb1b994263e6b16cf52711cc96df2919fef1", + "kibana.alert.group.id": "0485ecbf90fd3541db66415655bc13843543fa9c9803501228bf4e9e7a806985", + "kibana.alert.group.index": 0 + } + } +} + +{ + "type": "doc", + "value": { + "index": ".internal.alerts-security.alerts-default-000001", + "id": "3b67e7cba17e54aef89d70346bd47ae5ab73c5e11d0a5cda33b985c3e0c4f373", + "_score": 1, + "source": { + "kibana.version": "8.1.0", + "kibana.alert.rule.category": "Event Correlation Rule", + "kibana.alert.rule.consumer": "siem", + "kibana.alert.rule.execution.uuid": "51d785a9-7d7c-4688-9e64-f7901eef88bb", + "kibana.alert.rule.name": "eql-rule", + "kibana.alert.rule.producer": "siem", + "kibana.alert.rule.rule_type_id": "siem.eqlRule", + "kibana.alert.rule.uuid": "ff7a1d90-a72e-11ec-bc9e-ed906a2c068e", + "kibana.space_ids": [ + "default" + ], + "kibana.alert.rule.tags": [], + "@timestamp": "2022-03-19T02:48:06.850Z", + "agent": { + "name": "security-linux-3.example.dev", + "id": "06851da1-73e7-41e3-97d6-ff1d62c98dc5", + "type": "filebeat", + "version": "8.1.0" + }, + "log": { + "file": { + "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" + }, + "offset": 148938 + }, + "cloud": { + "availability_zone": "us-central1-c", + "instance": { + "name": "security-linux-1", + "id": "8995531128842994872" + }, + "provider": "gcp", + "service": { + "name": "GCE" + }, + "machine": { + "type": "g1-small" + }, + "project": { + "id": "elastic-siem" + }, + "account": { + "id": "elastic-siem" + } + }, + "ecs": { + "version": "8.1.0" + }, + "host": { + "hostname": "security-linux-3", + "os": { + "kernel": "4.19.0-18-cloud-amd64", + "codename": "buster", + "name": "Debian GNU/Linux", + "type": "linux", + "family": "debian", + "version": "10 (buster)", + "platform": "debian" + }, + "containerized": false, + "ip": "11.200.0.196", + "name": "security-linux-3", + "architecture": "x86_64" + }, + "service.name": "filebeat", + "message": "Status message.", + "data_stream": { + "namespace": "default", + "type": "logs", + "dataset": "elastic_agent.filebeat" + }, + "event.agent_id_status": "verified", + "event.ingested": "2022-03-19T02:47:57.047Z", + "event.dataset": "elastic_agent.filebeat", + "kibana.alert.ancestors": [ + { + "id": "aREToH8BK09aFtXZE1Pf", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "kibana.alert.status": "active", + "kibana.alert.workflow_status": "open", + "kibana.alert.depth": 1, + "kibana.alert.reason": "event on security-linux-3 created low alert eql-rule.", + "kibana.alert.building_block_type": "default", + "kibana.alert.severity": "low", + "kibana.alert.risk_score": 21, + "kibana.alert.rule.parameters": { + "description": "a simple eql rule", + "risk_score": 21, + "severity": "low", + "license": "", + "author": [], + "false_positives": [], + "from": "now-36000s", + "rule_id": "4dd16f77-5dd2-46c8-a1d9-f1d2ffb56456", + "max_signals": 100, + "risk_score_mapping": [], + "severity_mapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptions_list": [], + "immutable": false, + "type": "eql", + "language": "eql", + "index": [ + "events-index-*" + ], + "query": "sequence [any where true] [any where true]", + "filters": [] + }, + "kibana.alert.rule.actions": [], + "kibana.alert.rule.created_at": "2022-03-19T02:48:04.202Z", + "kibana.alert.rule.created_by": "elastic", + "kibana.alert.rule.enabled": true, + "kibana.alert.rule.interval": "1m", + "kibana.alert.rule.updated_at": "2022-03-19T02:48:05.465Z", + "kibana.alert.rule.updated_by": "elastic", + "kibana.alert.rule.type": "eql", + "kibana.alert.rule.description": "a simple eql rule", + "kibana.alert.rule.risk_score": 21, + "kibana.alert.rule.severity": "low", + "kibana.alert.rule.license": "", + "kibana.alert.rule.author": [], + "kibana.alert.rule.false_positives": [], + "kibana.alert.rule.from": "now-36000s", + "kibana.alert.rule.rule_id": "4dd16f77-5dd2-46c8-a1d9-f1d2ffb56456", + "kibana.alert.rule.max_signals": 100, + "kibana.alert.rule.risk_score_mapping": [], + "kibana.alert.rule.severity_mapping": [], + "kibana.alert.rule.threat": [], + "kibana.alert.rule.to": "now", + "kibana.alert.rule.references": [], + "kibana.alert.rule.version": 1, + "kibana.alert.rule.exceptions_list": [], + "kibana.alert.rule.immutable": false, + "kibana.alert.original_time": "2022-03-19T02:47:57.047Z", + "kibana.alert.original_event.agent_id_status": "verified", + "kibana.alert.original_event.ingested": "2022-03-19T02:47:57.047Z", + "kibana.alert.original_event.dataset": "elastic_agent.filebeat", + "event.kind": "signal", + "kibana.alert.uuid": "3b67e7cba17e54aef89d70346bd47ae5ab73c5e11d0a5cda33b985c3e0c4f373", + "kibana.alert.group.id": "0485ecbf90fd3541db66415655bc13843543fa9c9803501228bf4e9e7a806985", + "kibana.alert.group.index": 1 + } + } +} + +{ + "type": "doc", + "value": { + "index": ".internal.alerts-security.alerts-default-000001", + "id": "0485ecbf90fd3541db66415655bc13843543fa9c9803501228bf4e9e7a806985", + "_score": 1, + "source": { + "kibana.version": "8.1.0", + "kibana.alert.rule.category": "Event Correlation Rule", + "kibana.alert.rule.consumer": "siem", + "kibana.alert.rule.execution.uuid": "51d785a9-7d7c-4688-9e64-f7901eef88bb", + "kibana.alert.rule.name": "eql-rule", + "kibana.alert.rule.producer": "siem", + "kibana.alert.rule.rule_type_id": "siem.eqlRule", + "kibana.alert.rule.uuid": "ff7a1d90-a72e-11ec-bc9e-ed906a2c068e", + "kibana.space_ids": [ + "default" + ], + "kibana.alert.rule.tags": [], + "@timestamp": "2022-03-19T02:48:06.851Z", + "agent": { + "type": "filebeat", + "version": "8.1.0" + }, + "log": { + "file": { + "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" + }, + "offset": 148938 + }, + "cloud": { + "availability_zone": "us-central1-c", + "instance": { + "name": "security-linux-1", + "id": "8995531128842994872" + }, + "provider": "gcp", + "service": { + "name": "GCE" + }, + "machine": { + "type": "g1-small" + }, + "project": { + "id": "elastic-siem" + }, + "account": { + "id": "elastic-siem" + } + }, + "ecs": { + "version": "8.1.0" + }, + "host": { + "os": { + "kernel": "4.19.0-18-cloud-amd64", + "codename": "buster", + "name": "Debian GNU/Linux", + "type": "linux", + "family": "debian", + "version": "10 (buster)", + "platform": "debian" + }, + "containerized": false, + "architecture": "x86_64" + }, + "service.name": "filebeat", + "message": "Status message.", + "data_stream": { + "namespace": "default", + "type": "logs", + "dataset": "elastic_agent.filebeat" + }, + "event.agent_id_status": "verified", + "event.dataset": "elastic_agent.filebeat", + "kibana.alert.status": "active", + "kibana.alert.workflow_status": "open", + "kibana.alert.depth": 2, + "kibana.alert.severity": "low", + "kibana.alert.risk_score": 21, + "kibana.alert.rule.parameters": { + "description": "a simple eql rule", + "risk_score": 21, + "severity": "low", + "license": "", + "author": [], + "false_positives": [], + "from": "now-36000s", + "rule_id": "4dd16f77-5dd2-46c8-a1d9-f1d2ffb56456", + "max_signals": 100, + "risk_score_mapping": [], + "severity_mapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptions_list": [], + "immutable": false, + "type": "eql", + "language": "eql", + "index": [ + "events-index-*" + ], + "query": "sequence [any where true] [any where true]", + "filters": [] + }, + "kibana.alert.rule.created_at": "2022-03-19T02:48:04.202Z", + "kibana.alert.rule.created_by": "elastic", + "kibana.alert.rule.enabled": true, + "kibana.alert.rule.interval": "1m", + "kibana.alert.rule.updated_at": "2022-03-19T02:48:05.465Z", + "kibana.alert.rule.updated_by": "elastic", + "kibana.alert.rule.type": "eql", + "kibana.alert.rule.description": "a simple eql rule", + "kibana.alert.rule.risk_score": 21, + "kibana.alert.rule.severity": "low", + "kibana.alert.rule.license": "", + "kibana.alert.rule.author": [], + "kibana.alert.rule.false_positives": [], + "kibana.alert.rule.from": "now-36000s", + "kibana.alert.rule.rule_id": "4dd16f77-5dd2-46c8-a1d9-f1d2ffb56456", + "kibana.alert.rule.max_signals": 100, + "kibana.alert.rule.risk_score_mapping": [], + "kibana.alert.rule.severity_mapping": [], + "kibana.alert.rule.threat": [], + "kibana.alert.rule.to": "now", + "kibana.alert.rule.references": [], + "kibana.alert.rule.version": 1, + "kibana.alert.rule.exceptions_list": [], + "kibana.alert.rule.immutable": false, + "kibana.alert.original_event.agent_id_status": "verified", + "kibana.alert.original_event.dataset": "elastic_agent.filebeat", + "event.kind": "signal", + "event": { + "kind": "signal" + }, + "kibana.alert.ancestors": [ + { + "id": "aBEToH8BK09aFtXZElOb", + "type": "event", + "index": "events-index-000001", + "depth": 0 + }, + { + "id": "efd22ae93ac2d5fc7f91f1d9e52deb1b994263e6b16cf52711cc96df2919fef1", + "type": "signal", + "index": "", + "depth": 1, + "rule": "ff7a1d90-a72e-11ec-bc9e-ed906a2c068e" + }, + { + "id": "aREToH8BK09aFtXZE1Pf", + "type": "event", + "index": "events-index-000001", + "depth": 0 + }, + { + "id": "3b67e7cba17e54aef89d70346bd47ae5ab73c5e11d0a5cda33b985c3e0c4f373", + "type": "signal", + "index": "", + "depth": 1, + "rule": "ff7a1d90-a72e-11ec-bc9e-ed906a2c068e" + } + ], + "kibana.alert.reason": "event created low alert eql-rule.", + "kibana.alert.rule.actions": [], + "kibana.alert.original_time": "2022-03-19T02:47:56.723Z", + "kibana.alert.group.id": "0485ecbf90fd3541db66415655bc13843543fa9c9803501228bf4e9e7a806985", + "kibana.alert.uuid": "0485ecbf90fd3541db66415655bc13843543fa9c9803501228bf4e9e7a806985" + } + } +} + +{ + "type": "doc", + "value": { + "index": ".internal.alerts-security.alerts-default-000001", + "id": "80be2d338842cc01c46455a140db8dcb142a937eb67cf3ee9c70a34242863781", + "_score": 1, + "source": { + "kibana.version": "8.1.0", + "kibana.alert.rule.category": "Event Correlation Rule", + "kibana.alert.rule.consumer": "siem", + "kibana.alert.rule.execution.uuid": "51d785a9-7d7c-4688-9e64-f7901eef88bb", + "kibana.alert.rule.name": "eql-rule", + "kibana.alert.rule.producer": "siem", + "kibana.alert.rule.rule_type_id": "siem.eqlRule", + "kibana.alert.rule.uuid": "ff7a1d90-a72e-11ec-bc9e-ed906a2c068e", + "kibana.space_ids": [ + "default" + ], + "kibana.alert.rule.tags": [], + "@timestamp": "2022-03-19T02:48:06.861Z", + "agent": { + "name": "security-linux-3.example.dev", + "id": "06851da1-73e7-41e3-97d6-ff1d62c98dc5", + "type": "filebeat", + "version": "8.1.0" + }, + "log": { + "file": { + "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" + }, + "offset": 148938 + }, + "cloud": { + "availability_zone": "us-central1-c", + "instance": { + "name": "security-linux-1", + "id": "8995531128842994872" + }, + "provider": "gcp", + "service": { + "name": "GCE" + }, + "machine": { + "type": "g1-small" + }, + "project": { + "id": "elastic-siem" + }, + "account": { + "id": "elastic-siem" + } + }, + "ecs": { + "version": "8.1.0" + }, + "host": { + "hostname": "security-linux-3", + "os": { + "kernel": "4.19.0-18-cloud-amd64", + "codename": "buster", + "name": "Debian GNU/Linux", + "type": "linux", + "family": "debian", + "version": "10 (buster)", + "platform": "debian" + }, + "containerized": false, + "ip": "11.200.0.196", + "name": "security-linux-3", + "architecture": "x86_64" + }, + "service.name": "filebeat", + "message": "Status message.", + "data_stream": { + "namespace": "default", + "type": "logs", + "dataset": "elastic_agent.filebeat" + }, + "event.agent_id_status": "verified", + "event.ingested": "2022-03-19T02:47:57.047Z", + "event.dataset": "elastic_agent.filebeat", + "kibana.alert.ancestors": [ + { + "id": "aREToH8BK09aFtXZE1Pf", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "kibana.alert.status": "active", + "kibana.alert.workflow_status": "open", + "kibana.alert.depth": 1, + "kibana.alert.reason": "event on security-linux-3 created low alert eql-rule.", + "kibana.alert.building_block_type": "default", + "kibana.alert.severity": "low", + "kibana.alert.risk_score": 21, + "kibana.alert.rule.parameters": { + "description": "a simple eql rule", + "risk_score": 21, + "severity": "low", + "license": "", + "author": [], + "false_positives": [], + "from": "now-36000s", + "rule_id": "4dd16f77-5dd2-46c8-a1d9-f1d2ffb56456", + "max_signals": 100, + "risk_score_mapping": [], + "severity_mapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptions_list": [], + "immutable": false, + "type": "eql", + "language": "eql", + "index": [ + "events-index-*" + ], + "query": "sequence [any where true] [any where true]", + "filters": [] + }, + "kibana.alert.rule.actions": [], + "kibana.alert.rule.created_at": "2022-03-19T02:48:04.202Z", + "kibana.alert.rule.created_by": "elastic", + "kibana.alert.rule.enabled": true, + "kibana.alert.rule.interval": "1m", + "kibana.alert.rule.updated_at": "2022-03-19T02:48:05.465Z", + "kibana.alert.rule.updated_by": "elastic", + "kibana.alert.rule.type": "eql", + "kibana.alert.rule.description": "a simple eql rule", + "kibana.alert.rule.risk_score": 21, + "kibana.alert.rule.severity": "low", + "kibana.alert.rule.license": "", + "kibana.alert.rule.author": [], + "kibana.alert.rule.false_positives": [], + "kibana.alert.rule.from": "now-36000s", + "kibana.alert.rule.rule_id": "4dd16f77-5dd2-46c8-a1d9-f1d2ffb56456", + "kibana.alert.rule.max_signals": 100, + "kibana.alert.rule.risk_score_mapping": [], + "kibana.alert.rule.severity_mapping": [], + "kibana.alert.rule.threat": [], + "kibana.alert.rule.to": "now", + "kibana.alert.rule.references": [], + "kibana.alert.rule.version": 1, + "kibana.alert.rule.exceptions_list": [], + "kibana.alert.rule.immutable": false, + "kibana.alert.original_time": "2022-03-19T02:47:57.047Z", + "kibana.alert.original_event.agent_id_status": "verified", + "kibana.alert.original_event.ingested": "2022-03-19T02:47:57.047Z", + "kibana.alert.original_event.dataset": "elastic_agent.filebeat", + "event.kind": "signal", + "kibana.alert.uuid": "80be2d338842cc01c46455a140db8dcb142a937eb67cf3ee9c70a34242863781", + "kibana.alert.group.id": "912d955d2286325b67c10968faa11d706e9d9a3bc2360ec27083039f9b6b41d1", + "kibana.alert.group.index": 0 + } + } +} + +{ + "type": "doc", + "value": { + "index": ".internal.alerts-security.alerts-default-000001", + "id": "a960b4ce4e3135a66a79bf4bd78910e470330a9470c86cd8b682515975662c6c", + "_score": 1, + "source": { + "kibana.version": "8.1.0", + "kibana.alert.rule.category": "Event Correlation Rule", + "kibana.alert.rule.consumer": "siem", + "kibana.alert.rule.execution.uuid": "51d785a9-7d7c-4688-9e64-f7901eef88bb", + "kibana.alert.rule.name": "eql-rule", + "kibana.alert.rule.producer": "siem", + "kibana.alert.rule.rule_type_id": "siem.eqlRule", + "kibana.alert.rule.uuid": "ff7a1d90-a72e-11ec-bc9e-ed906a2c068e", + "kibana.space_ids": [ + "default" + ], + "kibana.alert.rule.tags": [], + "@timestamp": "2022-03-19T02:48:06.863Z", + "agent": { + "name": "security-linux-1.example.dev", + "id": "d8f66724-3cf2-437c-b124-6ac9fb0e2311", + "type": "filebeat", + "version": "8.1.0" + }, + "log": { + "file": { + "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" + }, + "offset": 148938 + }, + "cloud": { + "availability_zone": "us-central1-c", + "instance": { + "name": "security-linux-1", + "id": "8995531128842994872" + }, + "provider": "gcp", + "service": { + "name": "GCE" + }, + "machine": { + "type": "g1-small" + }, + "project": { + "id": "elastic-siem" + }, + "account": { + "id": "elastic-siem" + } + }, + "ecs": { + "version": "8.1.0" + }, + "host": { + "hostname": "security-linux-1", + "os": { + "kernel": "4.19.0-18-cloud-amd64", + "codename": "buster", + "name": "Debian GNU/Linux", + "type": "linux", + "family": "debian", + "version": "10 (buster)", + "platform": "debian" + }, + "containerized": false, + "ip": "11.200.0.194", + "name": "security-linux-1", + "architecture": "x86_64" + }, + "service.name": "filebeat", + "message": "Status message.", + "data_stream": { + "namespace": "default", + "type": "logs", + "dataset": "elastic_agent.filebeat" + }, + "event.agent_id_status": "verified", + "event.ingested": "2022-03-19T02:47:57.376Z", + "event.dataset": "elastic_agent.filebeat", + "kibana.alert.ancestors": [ + { + "id": "ahEToH8BK09aFtXZFVMq", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "kibana.alert.status": "active", + "kibana.alert.workflow_status": "open", + "kibana.alert.depth": 1, + "kibana.alert.reason": "event on security-linux-1 created low alert eql-rule.", + "kibana.alert.building_block_type": "default", + "kibana.alert.severity": "low", + "kibana.alert.risk_score": 21, + "kibana.alert.rule.parameters": { + "description": "a simple eql rule", + "risk_score": 21, + "severity": "low", + "license": "", + "author": [], + "false_positives": [], + "from": "now-36000s", + "rule_id": "4dd16f77-5dd2-46c8-a1d9-f1d2ffb56456", + "max_signals": 100, + "risk_score_mapping": [], + "severity_mapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptions_list": [], + "immutable": false, + "type": "eql", + "language": "eql", + "index": [ + "events-index-*" + ], + "query": "sequence [any where true] [any where true]", + "filters": [] + }, + "kibana.alert.rule.actions": [], + "kibana.alert.rule.created_at": "2022-03-19T02:48:04.202Z", + "kibana.alert.rule.created_by": "elastic", + "kibana.alert.rule.enabled": true, + "kibana.alert.rule.interval": "1m", + "kibana.alert.rule.updated_at": "2022-03-19T02:48:05.465Z", + "kibana.alert.rule.updated_by": "elastic", + "kibana.alert.rule.type": "eql", + "kibana.alert.rule.description": "a simple eql rule", + "kibana.alert.rule.risk_score": 21, + "kibana.alert.rule.severity": "low", + "kibana.alert.rule.license": "", + "kibana.alert.rule.author": [], + "kibana.alert.rule.false_positives": [], + "kibana.alert.rule.from": "now-36000s", + "kibana.alert.rule.rule_id": "4dd16f77-5dd2-46c8-a1d9-f1d2ffb56456", + "kibana.alert.rule.max_signals": 100, + "kibana.alert.rule.risk_score_mapping": [], + "kibana.alert.rule.severity_mapping": [], + "kibana.alert.rule.threat": [], + "kibana.alert.rule.to": "now", + "kibana.alert.rule.references": [], + "kibana.alert.rule.version": 1, + "kibana.alert.rule.exceptions_list": [], + "kibana.alert.rule.immutable": false, + "kibana.alert.original_time": "2022-03-19T02:47:57.376Z", + "kibana.alert.original_event.agent_id_status": "verified", + "kibana.alert.original_event.ingested": "2022-03-19T02:47:57.376Z", + "kibana.alert.original_event.dataset": "elastic_agent.filebeat", + "event.kind": "signal", + "kibana.alert.uuid": "a960b4ce4e3135a66a79bf4bd78910e470330a9470c86cd8b682515975662c6c", + "kibana.alert.group.id": "912d955d2286325b67c10968faa11d706e9d9a3bc2360ec27083039f9b6b41d1", + "kibana.alert.group.index": 1 + } + } +} + +{ + "type": "doc", + "value": { + "index": ".internal.alerts-security.alerts-default-000001", + "id": "912d955d2286325b67c10968faa11d706e9d9a3bc2360ec27083039f9b6b41d1", + "_score": 1, + "source": { + "kibana.version": "8.1.0", + "kibana.alert.rule.category": "Event Correlation Rule", + "kibana.alert.rule.consumer": "siem", + "kibana.alert.rule.execution.uuid": "51d785a9-7d7c-4688-9e64-f7901eef88bb", + "kibana.alert.rule.name": "eql-rule", + "kibana.alert.rule.producer": "siem", + "kibana.alert.rule.rule_type_id": "siem.eqlRule", + "kibana.alert.rule.uuid": "ff7a1d90-a72e-11ec-bc9e-ed906a2c068e", + "kibana.space_ids": [ + "default" + ], + "kibana.alert.rule.tags": [], + "@timestamp": "2022-03-19T02:48:06.865Z", + "agent": { + "type": "filebeat", + "version": "8.1.0" + }, + "log": { + "file": { + "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" + }, + "offset": 148938 + }, + "cloud": { + "availability_zone": "us-central1-c", + "instance": { + "name": "security-linux-1", + "id": "8995531128842994872" + }, + "provider": "gcp", + "service": { + "name": "GCE" + }, + "machine": { + "type": "g1-small" + }, + "project": { + "id": "elastic-siem" + }, + "account": { + "id": "elastic-siem" + } + }, + "ecs": { + "version": "8.1.0" + }, + "host": { + "os": { + "kernel": "4.19.0-18-cloud-amd64", + "codename": "buster", + "name": "Debian GNU/Linux", + "type": "linux", + "family": "debian", + "version": "10 (buster)", + "platform": "debian" + }, + "containerized": false, + "architecture": "x86_64" + }, + "service.name": "filebeat", + "message": "Status message.", + "data_stream": { + "namespace": "default", + "type": "logs", + "dataset": "elastic_agent.filebeat" + }, + "event.agent_id_status": "verified", + "event.dataset": "elastic_agent.filebeat", + "kibana.alert.status": "active", + "kibana.alert.workflow_status": "open", + "kibana.alert.depth": 2, + "kibana.alert.severity": "low", + "kibana.alert.risk_score": 21, + "kibana.alert.rule.parameters": { + "description": "a simple eql rule", + "risk_score": 21, + "severity": "low", + "license": "", + "author": [], + "false_positives": [], + "from": "now-36000s", + "rule_id": "4dd16f77-5dd2-46c8-a1d9-f1d2ffb56456", + "max_signals": 100, + "risk_score_mapping": [], + "severity_mapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptions_list": [], + "immutable": false, + "type": "eql", + "language": "eql", + "index": [ + "events-index-*" + ], + "query": "sequence [any where true] [any where true]", + "filters": [] + }, + "kibana.alert.rule.created_at": "2022-03-19T02:48:04.202Z", + "kibana.alert.rule.created_by": "elastic", + "kibana.alert.rule.enabled": true, + "kibana.alert.rule.interval": "1m", + "kibana.alert.rule.updated_at": "2022-03-19T02:48:05.465Z", + "kibana.alert.rule.updated_by": "elastic", + "kibana.alert.rule.type": "eql", + "kibana.alert.rule.description": "a simple eql rule", + "kibana.alert.rule.risk_score": 21, + "kibana.alert.rule.severity": "low", + "kibana.alert.rule.license": "", + "kibana.alert.rule.author": [], + "kibana.alert.rule.false_positives": [], + "kibana.alert.rule.from": "now-36000s", + "kibana.alert.rule.rule_id": "4dd16f77-5dd2-46c8-a1d9-f1d2ffb56456", + "kibana.alert.rule.max_signals": 100, + "kibana.alert.rule.risk_score_mapping": [], + "kibana.alert.rule.severity_mapping": [], + "kibana.alert.rule.threat": [], + "kibana.alert.rule.to": "now", + "kibana.alert.rule.references": [], + "kibana.alert.rule.version": 1, + "kibana.alert.rule.exceptions_list": [], + "kibana.alert.rule.immutable": false, + "kibana.alert.original_event.agent_id_status": "verified", + "kibana.alert.original_event.dataset": "elastic_agent.filebeat", + "event.kind": "signal", + "event": { + "kind": "signal" + }, + "kibana.alert.ancestors": [ + { + "id": "aREToH8BK09aFtXZE1Pf", + "type": "event", + "index": "events-index-000001", + "depth": 0 + }, + { + "id": "80be2d338842cc01c46455a140db8dcb142a937eb67cf3ee9c70a34242863781", + "type": "signal", + "index": "", + "depth": 1, + "rule": "ff7a1d90-a72e-11ec-bc9e-ed906a2c068e" + }, + { + "id": "ahEToH8BK09aFtXZFVMq", + "type": "event", + "index": "events-index-000001", + "depth": 0 + }, + { + "id": "a960b4ce4e3135a66a79bf4bd78910e470330a9470c86cd8b682515975662c6c", + "type": "signal", + "index": "", + "depth": 1, + "rule": "ff7a1d90-a72e-11ec-bc9e-ed906a2c068e" + } + ], + "kibana.alert.reason": "event created low alert eql-rule.", + "kibana.alert.rule.actions": [], + "kibana.alert.original_time": "2022-03-19T02:47:57.047Z", + "kibana.alert.group.id": "912d955d2286325b67c10968faa11d706e9d9a3bc2360ec27083039f9b6b41d1", + "kibana.alert.uuid": "912d955d2286325b67c10968faa11d706e9d9a3bc2360ec27083039f9b6b41d1" + } + } +} + +{ + "type": "doc", + "value": { + "index": ".internal.alerts-security.alerts-default-000001", + "id": "f0aa867f7a29bb6d655207d9b3db9b4186000bdc816b52f96955b9d0f1778c33", + "_score": 1, + "source": { + "kibana.version": "8.1.0", + "kibana.alert.rule.category": "Custom Query Rule", + "kibana.alert.rule.consumer": "siem", + "kibana.alert.rule.execution.uuid": "f378da0e-6f34-4d37-97eb-a3871b6c4509", + "kibana.alert.rule.name": "query-rule", + "kibana.alert.rule.producer": "siem", + "kibana.alert.rule.rule_type_id": "siem.queryRule", + "kibana.alert.rule.uuid": "fd531ee0-a72e-11ec-bc9e-ed906a2c068e", + "kibana.space_ids": [ + "default" + ], + "kibana.alert.rule.tags": [], + "@timestamp": "2022-03-19T02:48:03.524Z", + "agent": { + "name": "security-linux-1.example.dev", + "id": "d8f66724-3cf2-437c-b124-6ac9fb0e2311", + "type": "filebeat", + "version": "8.1.0" + }, + "log": { + "file": { + "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" + }, + "offset": 148938 + }, + "cloud": { + "availability_zone": "us-central1-c", + "instance": { + "name": "security-linux-1", + "id": "8995531128842994872" + }, + "provider": "gcp", + "service": { + "name": "GCE" + }, + "machine": { + "type": "g1-small" + }, + "project": { + "id": "elastic-siem" + }, + "account": { + "id": "elastic-siem" + } + }, + "ecs": { + "version": "8.1.0" + }, + "host": { + "hostname": "security-linux-1", + "os": { + "kernel": "4.19.0-18-cloud-amd64", + "codename": "buster", + "name": "Debian GNU/Linux", + "type": "linux", + "family": "debian", + "version": "10 (buster)", + "platform": "debian" + }, + "containerized": false, + "ip": "11.200.0.194", + "name": "security-linux-1", + "architecture": "x86_64" + }, + "service.name": "filebeat", + "message": "Status message.", + "data_stream": { + "namespace": "default", + "type": "logs", + "dataset": "elastic_agent.filebeat" + }, + "event.agent_id_status": "verified", + "event.ingested": "2022-03-19T02:47:54.442Z", + "event.dataset": "elastic_agent.filebeat", + "kibana.alert.ancestors": [ + { + "id": "YREToH8BK09aFtXZCVO3", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "kibana.alert.status": "active", + "kibana.alert.workflow_status": "open", + "kibana.alert.depth": 1, + "kibana.alert.reason": "event on security-linux-1 created low alert query-rule.", + "kibana.alert.severity": "low", + "kibana.alert.risk_score": 21, + "kibana.alert.rule.parameters": { + "description": "a simple query rule", + "risk_score": 21, + "severity": "low", + "license": "", + "author": [], + "false_positives": [], + "from": "now-36000s", + "rule_id": "83fef54f-2751-419a-844e-ce3e9605000c", + "max_signals": 100, + "risk_score_mapping": [], + "severity_mapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptions_list": [], + "immutable": false, + "type": "query", + "language": "kuery", + "index": [ + "events-index-*" + ], + "query": "*", + "filters": [] + }, + "kibana.alert.rule.actions": [], + "kibana.alert.rule.created_at": "2022-03-19T02:48:01.193Z", + "kibana.alert.rule.created_by": "elastic", + "kibana.alert.rule.enabled": true, + "kibana.alert.rule.interval": "1m", + "kibana.alert.rule.updated_at": "2022-03-19T02:48:02.426Z", + "kibana.alert.rule.updated_by": "elastic", + "kibana.alert.rule.type": "query", + "kibana.alert.rule.description": "a simple query rule", + "kibana.alert.rule.risk_score": 21, + "kibana.alert.rule.severity": "low", + "kibana.alert.rule.license": "", + "kibana.alert.rule.author": [], + "kibana.alert.rule.false_positives": [], + "kibana.alert.rule.from": "now-36000s", + "kibana.alert.rule.rule_id": "83fef54f-2751-419a-844e-ce3e9605000c", + "kibana.alert.rule.max_signals": 100, + "kibana.alert.rule.risk_score_mapping": [], + "kibana.alert.rule.severity_mapping": [], + "kibana.alert.rule.threat": [], + "kibana.alert.rule.to": "now", + "kibana.alert.rule.references": [], + "kibana.alert.rule.version": 1, + "kibana.alert.rule.exceptions_list": [], + "kibana.alert.rule.immutable": false, + "kibana.alert.original_time": "2022-03-19T02:47:54.442Z", + "kibana.alert.original_event.agent_id_status": "verified", + "kibana.alert.original_event.ingested": "2022-03-19T02:47:54.442Z", + "kibana.alert.original_event.dataset": "elastic_agent.filebeat", + "event.kind": "signal", + "kibana.alert.uuid": "f0aa867f7a29bb6d655207d9b3db9b4186000bdc816b52f96955b9d0f1778c33" + } + } +} + +{ + "type": "doc", + "value": { + "index": ".internal.alerts-security.alerts-default-000001", + "id": "5b2dab231cc2ca89a72119919012c131c86f931682081c79c0a9c496264e6628", + "_score": 1, + "source": { + "kibana.version": "8.1.0", + "kibana.alert.rule.category": "Custom Query Rule", + "kibana.alert.rule.consumer": "siem", + "kibana.alert.rule.execution.uuid": "f378da0e-6f34-4d37-97eb-a3871b6c4509", + "kibana.alert.rule.name": "query-rule", + "kibana.alert.rule.producer": "siem", + "kibana.alert.rule.rule_type_id": "siem.queryRule", + "kibana.alert.rule.uuid": "fd531ee0-a72e-11ec-bc9e-ed906a2c068e", + "kibana.space_ids": [ + "default" + ], + "kibana.alert.rule.tags": [], + "@timestamp": "2022-03-19T02:48:03.528Z", + "agent": { + "name": "security-linux-2.example.dev", + "id": "87c417dd-08d6-4e24-ad69-285cb8de84e9", + "type": "filebeat", + "version": "8.1.0" + }, + "log": { + "file": { + "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" + }, + "offset": 148938 + }, + "cloud": { + "availability_zone": "us-central1-c", + "instance": { + "name": "security-linux-1", + "id": "8995531128842994872" + }, + "provider": "gcp", + "service": { + "name": "GCE" + }, + "machine": { + "type": "g1-small" + }, + "project": { + "id": "elastic-siem" + }, + "account": { + "id": "elastic-siem" + } + }, + "ecs": { + "version": "8.1.0" + }, + "host": { + "hostname": "security-linux-2", + "os": { + "kernel": "4.19.0-18-cloud-amd64", + "codename": "buster", + "name": "Debian GNU/Linux", + "type": "linux", + "family": "debian", + "version": "10 (buster)", + "platform": "debian" + }, + "containerized": false, + "ip": "11.200.0.195", + "name": "security-linux-2", + "architecture": "x86_64" + }, + "service.name": "filebeat", + "message": "Status message.", + "data_stream": { + "namespace": "default", + "type": "logs", + "dataset": "elastic_agent.filebeat" + }, + "event.agent_id_status": "verified", + "event.ingested": "2022-03-19T02:47:54.820Z", + "event.dataset": "elastic_agent.filebeat", + "kibana.alert.ancestors": [ + { + "id": "YhEToH8BK09aFtXZC1Mt", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "kibana.alert.status": "active", + "kibana.alert.workflow_status": "open", + "kibana.alert.depth": 1, + "kibana.alert.reason": "event on security-linux-2 created low alert query-rule.", + "kibana.alert.severity": "low", + "kibana.alert.risk_score": 21, + "kibana.alert.rule.parameters": { + "description": "a simple query rule", + "risk_score": 21, + "severity": "low", + "license": "", + "author": [], + "false_positives": [], + "from": "now-36000s", + "rule_id": "83fef54f-2751-419a-844e-ce3e9605000c", + "max_signals": 100, + "risk_score_mapping": [], + "severity_mapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptions_list": [], + "immutable": false, + "type": "query", + "language": "kuery", + "index": [ + "events-index-*" + ], + "query": "*", + "filters": [] + }, + "kibana.alert.rule.actions": [], + "kibana.alert.rule.created_at": "2022-03-19T02:48:01.193Z", + "kibana.alert.rule.created_by": "elastic", + "kibana.alert.rule.enabled": true, + "kibana.alert.rule.interval": "1m", + "kibana.alert.rule.updated_at": "2022-03-19T02:48:02.426Z", + "kibana.alert.rule.updated_by": "elastic", + "kibana.alert.rule.type": "query", + "kibana.alert.rule.description": "a simple query rule", + "kibana.alert.rule.risk_score": 21, + "kibana.alert.rule.severity": "low", + "kibana.alert.rule.license": "", + "kibana.alert.rule.author": [], + "kibana.alert.rule.false_positives": [], + "kibana.alert.rule.from": "now-36000s", + "kibana.alert.rule.rule_id": "83fef54f-2751-419a-844e-ce3e9605000c", + "kibana.alert.rule.max_signals": 100, + "kibana.alert.rule.risk_score_mapping": [], + "kibana.alert.rule.severity_mapping": [], + "kibana.alert.rule.threat": [], + "kibana.alert.rule.to": "now", + "kibana.alert.rule.references": [], + "kibana.alert.rule.version": 1, + "kibana.alert.rule.exceptions_list": [], + "kibana.alert.rule.immutable": false, + "kibana.alert.original_time": "2022-03-19T02:47:54.820Z", + "kibana.alert.original_event.agent_id_status": "verified", + "kibana.alert.original_event.ingested": "2022-03-19T02:47:54.820Z", + "kibana.alert.original_event.dataset": "elastic_agent.filebeat", + "event.kind": "signal", + "kibana.alert.uuid": "5b2dab231cc2ca89a72119919012c131c86f931682081c79c0a9c496264e6628" + } + } +} + +{ + "type": "doc", + "value": { + "index": ".internal.alerts-security.alerts-default-000001", + "id": "33c030b049a1341e8f20e470adcecc30eb73f30457a5e356c9ab4f22e60b7006", + "_score": 1, + "source": { + "kibana.version": "8.1.0", + "kibana.alert.rule.category": "Custom Query Rule", + "kibana.alert.rule.consumer": "siem", + "kibana.alert.rule.execution.uuid": "f378da0e-6f34-4d37-97eb-a3871b6c4509", + "kibana.alert.rule.name": "query-rule", + "kibana.alert.rule.producer": "siem", + "kibana.alert.rule.rule_type_id": "siem.queryRule", + "kibana.alert.rule.uuid": "fd531ee0-a72e-11ec-bc9e-ed906a2c068e", + "kibana.space_ids": [ + "default" + ], + "kibana.alert.rule.tags": [], + "@timestamp": "2022-03-19T02:48:03.543Z", + "agent": { + "name": "security-linux-3.example.dev", + "id": "06851da1-73e7-41e3-97d6-ff1d62c98dc5", + "type": "filebeat", + "version": "8.1.0" + }, + "log": { + "file": { + "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" + }, + "offset": 148938 + }, + "cloud": { + "availability_zone": "us-central1-c", + "instance": { + "name": "security-linux-1", + "id": "8995531128842994872" + }, + "provider": "gcp", + "service": { + "name": "GCE" + }, + "machine": { + "type": "g1-small" + }, + "project": { + "id": "elastic-siem" + }, + "account": { + "id": "elastic-siem" + } + }, + "ecs": { + "version": "8.1.0" + }, + "host": { + "hostname": "security-linux-3", + "os": { + "kernel": "4.19.0-18-cloud-amd64", + "codename": "buster", + "name": "Debian GNU/Linux", + "type": "linux", + "family": "debian", + "version": "10 (buster)", + "platform": "debian" + }, + "containerized": false, + "ip": "11.200.0.196", + "name": "security-linux-3", + "architecture": "x86_64" + }, + "service.name": "filebeat", + "message": "Status message.", + "data_stream": { + "namespace": "default", + "type": "logs", + "dataset": "elastic_agent.filebeat" + }, + "event.agent_id_status": "verified", + "event.ingested": "2022-03-19T02:47:55.150Z", + "event.dataset": "elastic_agent.filebeat", + "kibana.alert.ancestors": [ + { + "id": "YxEToH8BK09aFtXZDFNv", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "kibana.alert.status": "active", + "kibana.alert.workflow_status": "open", + "kibana.alert.depth": 1, + "kibana.alert.reason": "event on security-linux-3 created low alert query-rule.", + "kibana.alert.severity": "low", + "kibana.alert.risk_score": 21, + "kibana.alert.rule.parameters": { + "description": "a simple query rule", + "risk_score": 21, + "severity": "low", + "license": "", + "author": [], + "false_positives": [], + "from": "now-36000s", + "rule_id": "83fef54f-2751-419a-844e-ce3e9605000c", + "max_signals": 100, + "risk_score_mapping": [], + "severity_mapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptions_list": [], + "immutable": false, + "type": "query", + "language": "kuery", + "index": [ + "events-index-*" + ], + "query": "*", + "filters": [] + }, + "kibana.alert.rule.actions": [], + "kibana.alert.rule.created_at": "2022-03-19T02:48:01.193Z", + "kibana.alert.rule.created_by": "elastic", + "kibana.alert.rule.enabled": true, + "kibana.alert.rule.interval": "1m", + "kibana.alert.rule.updated_at": "2022-03-19T02:48:02.426Z", + "kibana.alert.rule.updated_by": "elastic", + "kibana.alert.rule.type": "query", + "kibana.alert.rule.description": "a simple query rule", + "kibana.alert.rule.risk_score": 21, + "kibana.alert.rule.severity": "low", + "kibana.alert.rule.license": "", + "kibana.alert.rule.author": [], + "kibana.alert.rule.false_positives": [], + "kibana.alert.rule.from": "now-36000s", + "kibana.alert.rule.rule_id": "83fef54f-2751-419a-844e-ce3e9605000c", + "kibana.alert.rule.max_signals": 100, + "kibana.alert.rule.risk_score_mapping": [], + "kibana.alert.rule.severity_mapping": [], + "kibana.alert.rule.threat": [], + "kibana.alert.rule.to": "now", + "kibana.alert.rule.references": [], + "kibana.alert.rule.version": 1, + "kibana.alert.rule.exceptions_list": [], + "kibana.alert.rule.immutable": false, + "kibana.alert.original_time": "2022-03-19T02:47:55.150Z", + "kibana.alert.original_event.agent_id_status": "verified", + "kibana.alert.original_event.ingested": "2022-03-19T02:47:55.150Z", + "kibana.alert.original_event.dataset": "elastic_agent.filebeat", + "event.kind": "signal", + "kibana.alert.uuid": "33c030b049a1341e8f20e470adcecc30eb73f30457a5e356c9ab4f22e60b7006" + } + } +} + +{ + "type": "doc", + "value": { + "index": ".internal.alerts-security.alerts-default-000001", + "id": "ba93188e82eb3017b92269696dda8fafcc8fc463b07f7cb4ac162a39840520eb", + "_score": 1, + "source": { + "kibana.version": "8.1.0", + "kibana.alert.rule.category": "Custom Query Rule", + "kibana.alert.rule.consumer": "siem", + "kibana.alert.rule.execution.uuid": "f378da0e-6f34-4d37-97eb-a3871b6c4509", + "kibana.alert.rule.name": "query-rule", + "kibana.alert.rule.producer": "siem", + "kibana.alert.rule.rule_type_id": "siem.queryRule", + "kibana.alert.rule.uuid": "fd531ee0-a72e-11ec-bc9e-ed906a2c068e", + "kibana.space_ids": [ + "default" + ], + "kibana.alert.rule.tags": [], + "@timestamp": "2022-03-19T02:48:03.546Z", + "agent": { + "name": "security-linux-1.example.dev", + "id": "d8f66724-3cf2-437c-b124-6ac9fb0e2311", + "type": "filebeat", + "version": "8.1.0" + }, + "log": { + "file": { + "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" + }, + "offset": 148938 + }, + "cloud": { + "availability_zone": "us-central1-c", + "instance": { + "name": "security-linux-1", + "id": "8995531128842994872" + }, + "provider": "gcp", + "service": { + "name": "GCE" + }, + "machine": { + "type": "g1-small" + }, + "project": { + "id": "elastic-siem" + }, + "account": { + "id": "elastic-siem" + } + }, + "ecs": { + "version": "8.1.0" + }, + "host": { + "hostname": "security-linux-1", + "os": { + "kernel": "4.19.0-18-cloud-amd64", + "codename": "buster", + "name": "Debian GNU/Linux", + "type": "linux", + "family": "debian", + "version": "10 (buster)", + "platform": "debian" + }, + "containerized": false, + "ip": "11.200.0.194", + "name": "security-linux-1", + "architecture": "x86_64" + }, + "service.name": "filebeat", + "message": "Status message.", + "data_stream": { + "namespace": "default", + "type": "logs", + "dataset": "elastic_agent.filebeat" + }, + "event.agent_id_status": "verified", + "event.ingested": "2022-03-19T02:47:55.468Z", + "event.dataset": "elastic_agent.filebeat", + "kibana.alert.ancestors": [ + { + "id": "ZBEToH8BK09aFtXZDVNr", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "kibana.alert.status": "active", + "kibana.alert.workflow_status": "open", + "kibana.alert.depth": 1, + "kibana.alert.reason": "event on security-linux-1 created low alert query-rule.", + "kibana.alert.severity": "low", + "kibana.alert.risk_score": 21, + "kibana.alert.rule.parameters": { + "description": "a simple query rule", + "risk_score": 21, + "severity": "low", + "license": "", + "author": [], + "false_positives": [], + "from": "now-36000s", + "rule_id": "83fef54f-2751-419a-844e-ce3e9605000c", + "max_signals": 100, + "risk_score_mapping": [], + "severity_mapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptions_list": [], + "immutable": false, + "type": "query", + "language": "kuery", + "index": [ + "events-index-*" + ], + "query": "*", + "filters": [] + }, + "kibana.alert.rule.actions": [], + "kibana.alert.rule.created_at": "2022-03-19T02:48:01.193Z", + "kibana.alert.rule.created_by": "elastic", + "kibana.alert.rule.enabled": true, + "kibana.alert.rule.interval": "1m", + "kibana.alert.rule.updated_at": "2022-03-19T02:48:02.426Z", + "kibana.alert.rule.updated_by": "elastic", + "kibana.alert.rule.type": "query", + "kibana.alert.rule.description": "a simple query rule", + "kibana.alert.rule.risk_score": 21, + "kibana.alert.rule.severity": "low", + "kibana.alert.rule.license": "", + "kibana.alert.rule.author": [], + "kibana.alert.rule.false_positives": [], + "kibana.alert.rule.from": "now-36000s", + "kibana.alert.rule.rule_id": "83fef54f-2751-419a-844e-ce3e9605000c", + "kibana.alert.rule.max_signals": 100, + "kibana.alert.rule.risk_score_mapping": [], + "kibana.alert.rule.severity_mapping": [], + "kibana.alert.rule.threat": [], + "kibana.alert.rule.to": "now", + "kibana.alert.rule.references": [], + "kibana.alert.rule.version": 1, + "kibana.alert.rule.exceptions_list": [], + "kibana.alert.rule.immutable": false, + "kibana.alert.original_time": "2022-03-19T02:47:55.468Z", + "kibana.alert.original_event.agent_id_status": "verified", + "kibana.alert.original_event.ingested": "2022-03-19T02:47:55.468Z", + "kibana.alert.original_event.dataset": "elastic_agent.filebeat", + "event.kind": "signal", + "kibana.alert.uuid": "ba93188e82eb3017b92269696dda8fafcc8fc463b07f7cb4ac162a39840520eb" + } + } +} + +{ + "type": "doc", + "value": { + "index": ".internal.alerts-security.alerts-default-000001", + "id": "6fbd3dab836cacbaae940d4670fbf6ed7368a78948ae37b8c499d5ecc2c60028", + "_score": 1, + "source": { + "kibana.version": "8.1.0", + "kibana.alert.rule.category": "Custom Query Rule", + "kibana.alert.rule.consumer": "siem", + "kibana.alert.rule.execution.uuid": "f378da0e-6f34-4d37-97eb-a3871b6c4509", + "kibana.alert.rule.name": "query-rule", + "kibana.alert.rule.producer": "siem", + "kibana.alert.rule.rule_type_id": "siem.queryRule", + "kibana.alert.rule.uuid": "fd531ee0-a72e-11ec-bc9e-ed906a2c068e", + "kibana.space_ids": [ + "default" + ], + "kibana.alert.rule.tags": [], + "@timestamp": "2022-03-19T02:48:03.549Z", + "agent": { + "name": "security-linux-2.example.dev", + "id": "87c417dd-08d6-4e24-ad69-285cb8de84e9", + "type": "filebeat", + "version": "8.1.0" + }, + "log": { + "file": { + "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" + }, + "offset": 148938 + }, + "cloud": { + "availability_zone": "us-central1-c", + "instance": { + "name": "security-linux-1", + "id": "8995531128842994872" + }, + "provider": "gcp", + "service": { + "name": "GCE" + }, + "machine": { + "type": "g1-small" + }, + "project": { + "id": "elastic-siem" + }, + "account": { + "id": "elastic-siem" + } + }, + "ecs": { + "version": "8.1.0" + }, + "host": { + "hostname": "security-linux-2", + "os": { + "kernel": "4.19.0-18-cloud-amd64", + "codename": "buster", + "name": "Debian GNU/Linux", + "type": "linux", + "family": "debian", + "version": "10 (buster)", + "platform": "debian" + }, + "containerized": false, + "ip": "11.200.0.195", + "name": "security-linux-2", + "architecture": "x86_64" + }, + "service.name": "filebeat", + "message": "Status message.", + "data_stream": { + "namespace": "default", + "type": "logs", + "dataset": "elastic_agent.filebeat" + }, + "event.agent_id_status": "verified", + "event.ingested": "2022-03-19T02:47:55.722Z", + "event.dataset": "elastic_agent.filebeat", + "kibana.alert.ancestors": [ + { + "id": "ZREToH8BK09aFtXZDlOv", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "kibana.alert.status": "active", + "kibana.alert.workflow_status": "open", + "kibana.alert.depth": 1, + "kibana.alert.reason": "event on security-linux-2 created low alert query-rule.", + "kibana.alert.severity": "low", + "kibana.alert.risk_score": 21, + "kibana.alert.rule.parameters": { + "description": "a simple query rule", + "risk_score": 21, + "severity": "low", + "license": "", + "author": [], + "false_positives": [], + "from": "now-36000s", + "rule_id": "83fef54f-2751-419a-844e-ce3e9605000c", + "max_signals": 100, + "risk_score_mapping": [], + "severity_mapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptions_list": [], + "immutable": false, + "type": "query", + "language": "kuery", + "index": [ + "events-index-*" + ], + "query": "*", + "filters": [] + }, + "kibana.alert.rule.actions": [], + "kibana.alert.rule.created_at": "2022-03-19T02:48:01.193Z", + "kibana.alert.rule.created_by": "elastic", + "kibana.alert.rule.enabled": true, + "kibana.alert.rule.interval": "1m", + "kibana.alert.rule.updated_at": "2022-03-19T02:48:02.426Z", + "kibana.alert.rule.updated_by": "elastic", + "kibana.alert.rule.type": "query", + "kibana.alert.rule.description": "a simple query rule", + "kibana.alert.rule.risk_score": 21, + "kibana.alert.rule.severity": "low", + "kibana.alert.rule.license": "", + "kibana.alert.rule.author": [], + "kibana.alert.rule.false_positives": [], + "kibana.alert.rule.from": "now-36000s", + "kibana.alert.rule.rule_id": "83fef54f-2751-419a-844e-ce3e9605000c", + "kibana.alert.rule.max_signals": 100, + "kibana.alert.rule.risk_score_mapping": [], + "kibana.alert.rule.severity_mapping": [], + "kibana.alert.rule.threat": [], + "kibana.alert.rule.to": "now", + "kibana.alert.rule.references": [], + "kibana.alert.rule.version": 1, + "kibana.alert.rule.exceptions_list": [], + "kibana.alert.rule.immutable": false, + "kibana.alert.original_time": "2022-03-19T02:47:55.722Z", + "kibana.alert.original_event.agent_id_status": "verified", + "kibana.alert.original_event.ingested": "2022-03-19T02:47:55.722Z", + "kibana.alert.original_event.dataset": "elastic_agent.filebeat", + "event.kind": "signal", + "kibana.alert.uuid": "6fbd3dab836cacbaae940d4670fbf6ed7368a78948ae37b8c499d5ecc2c60028" + } + } +} + +{ + "type": "doc", + "value": { + "index": ".internal.alerts-security.alerts-default-000001", + "id": "b3524204722372966876fd8639b1afbde984db8df3b57c8f6a3ff0858e436a89", + "_score": 1, + "source": { + "kibana.version": "8.1.0", + "kibana.alert.rule.category": "Custom Query Rule", + "kibana.alert.rule.consumer": "siem", + "kibana.alert.rule.execution.uuid": "f378da0e-6f34-4d37-97eb-a3871b6c4509", + "kibana.alert.rule.name": "query-rule", + "kibana.alert.rule.producer": "siem", + "kibana.alert.rule.rule_type_id": "siem.queryRule", + "kibana.alert.rule.uuid": "fd531ee0-a72e-11ec-bc9e-ed906a2c068e", + "kibana.space_ids": [ + "default" + ], + "kibana.alert.rule.tags": [], + "@timestamp": "2022-03-19T02:48:03.552Z", + "agent": { + "name": "security-linux-3.example.dev", + "id": "06851da1-73e7-41e3-97d6-ff1d62c98dc5", + "type": "filebeat", + "version": "8.1.0" + }, + "log": { + "file": { + "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" + }, + "offset": 148938 + }, + "cloud": { + "availability_zone": "us-central1-c", + "instance": { + "name": "security-linux-1", + "id": "8995531128842994872" + }, + "provider": "gcp", + "service": { + "name": "GCE" + }, + "machine": { + "type": "g1-small" + }, + "project": { + "id": "elastic-siem" + }, + "account": { + "id": "elastic-siem" + } + }, + "ecs": { + "version": "8.1.0" + }, + "host": { + "hostname": "security-linux-3", + "os": { + "kernel": "4.19.0-18-cloud-amd64", + "codename": "buster", + "name": "Debian GNU/Linux", + "type": "linux", + "family": "debian", + "version": "10 (buster)", + "platform": "debian" + }, + "containerized": false, + "ip": "11.200.0.196", + "name": "security-linux-3", + "architecture": "x86_64" + }, + "service.name": "filebeat", + "message": "Status message.", + "data_stream": { + "namespace": "default", + "type": "logs", + "dataset": "elastic_agent.filebeat" + }, + "event.agent_id_status": "verified", + "event.ingested": "2022-03-19T02:47:56.044Z", + "event.dataset": "elastic_agent.filebeat", + "kibana.alert.ancestors": [ + { + "id": "ZhEToH8BK09aFtXZD1P3", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "kibana.alert.status": "active", + "kibana.alert.workflow_status": "open", + "kibana.alert.depth": 1, + "kibana.alert.reason": "event on security-linux-3 created low alert query-rule.", + "kibana.alert.severity": "low", + "kibana.alert.risk_score": 21, + "kibana.alert.rule.parameters": { + "description": "a simple query rule", + "risk_score": 21, + "severity": "low", + "license": "", + "author": [], + "false_positives": [], + "from": "now-36000s", + "rule_id": "83fef54f-2751-419a-844e-ce3e9605000c", + "max_signals": 100, + "risk_score_mapping": [], + "severity_mapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptions_list": [], + "immutable": false, + "type": "query", + "language": "kuery", + "index": [ + "events-index-*" + ], + "query": "*", + "filters": [] + }, + "kibana.alert.rule.actions": [], + "kibana.alert.rule.created_at": "2022-03-19T02:48:01.193Z", + "kibana.alert.rule.created_by": "elastic", + "kibana.alert.rule.enabled": true, + "kibana.alert.rule.interval": "1m", + "kibana.alert.rule.updated_at": "2022-03-19T02:48:02.426Z", + "kibana.alert.rule.updated_by": "elastic", + "kibana.alert.rule.type": "query", + "kibana.alert.rule.description": "a simple query rule", + "kibana.alert.rule.risk_score": 21, + "kibana.alert.rule.severity": "low", + "kibana.alert.rule.license": "", + "kibana.alert.rule.author": [], + "kibana.alert.rule.false_positives": [], + "kibana.alert.rule.from": "now-36000s", + "kibana.alert.rule.rule_id": "83fef54f-2751-419a-844e-ce3e9605000c", + "kibana.alert.rule.max_signals": 100, + "kibana.alert.rule.risk_score_mapping": [], + "kibana.alert.rule.severity_mapping": [], + "kibana.alert.rule.threat": [], + "kibana.alert.rule.to": "now", + "kibana.alert.rule.references": [], + "kibana.alert.rule.version": 1, + "kibana.alert.rule.exceptions_list": [], + "kibana.alert.rule.immutable": false, + "kibana.alert.original_time": "2022-03-19T02:47:56.044Z", + "kibana.alert.original_event.agent_id_status": "verified", + "kibana.alert.original_event.ingested": "2022-03-19T02:47:56.044Z", + "kibana.alert.original_event.dataset": "elastic_agent.filebeat", + "event.kind": "signal", + "kibana.alert.uuid": "b3524204722372966876fd8639b1afbde984db8df3b57c8f6a3ff0858e436a89" + } + } +} + +{ + "type": "doc", + "value": { + "index": ".internal.alerts-security.alerts-default-000001", + "id": "13fc52cad9931eade0fb41b0396c66b7ab23e5d270c6c0691d41154d2070cde5", + "_score": 1, + "source": { + "kibana.version": "8.1.0", + "kibana.alert.rule.category": "Custom Query Rule", + "kibana.alert.rule.consumer": "siem", + "kibana.alert.rule.execution.uuid": "f378da0e-6f34-4d37-97eb-a3871b6c4509", + "kibana.alert.rule.name": "query-rule", + "kibana.alert.rule.producer": "siem", + "kibana.alert.rule.rule_type_id": "siem.queryRule", + "kibana.alert.rule.uuid": "fd531ee0-a72e-11ec-bc9e-ed906a2c068e", + "kibana.space_ids": [ + "default" + ], + "kibana.alert.rule.tags": [], + "@timestamp": "2022-03-19T02:48:03.555Z", + "agent": { + "name": "security-linux-1.example.dev", + "id": "d8f66724-3cf2-437c-b124-6ac9fb0e2311", + "type": "filebeat", + "version": "8.1.0" + }, + "log": { + "file": { + "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" + }, + "offset": 148938 + }, + "cloud": { + "availability_zone": "us-central1-c", + "instance": { + "name": "security-linux-1", + "id": "8995531128842994872" + }, + "provider": "gcp", + "service": { + "name": "GCE" + }, + "machine": { + "type": "g1-small" + }, + "project": { + "id": "elastic-siem" + }, + "account": { + "id": "elastic-siem" + } + }, + "ecs": { + "version": "8.1.0" + }, + "host": { + "hostname": "security-linux-1", + "os": { + "kernel": "4.19.0-18-cloud-amd64", + "codename": "buster", + "name": "Debian GNU/Linux", + "type": "linux", + "family": "debian", + "version": "10 (buster)", + "platform": "debian" + }, + "containerized": false, + "ip": "11.200.0.194", + "name": "security-linux-1", + "architecture": "x86_64" + }, + "service.name": "filebeat", + "message": "Status message.", + "data_stream": { + "namespace": "default", + "type": "logs", + "dataset": "elastic_agent.filebeat" + }, + "event.agent_id_status": "verified", + "event.ingested": "2022-03-19T02:47:56.372Z", + "event.dataset": "elastic_agent.filebeat", + "kibana.alert.ancestors": [ + { + "id": "ZxEToH8BK09aFtXZEVNR", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "kibana.alert.status": "active", + "kibana.alert.workflow_status": "open", + "kibana.alert.depth": 1, + "kibana.alert.reason": "event on security-linux-1 created low alert query-rule.", + "kibana.alert.severity": "low", + "kibana.alert.risk_score": 21, + "kibana.alert.rule.parameters": { + "description": "a simple query rule", + "risk_score": 21, + "severity": "low", + "license": "", + "author": [], + "false_positives": [], + "from": "now-36000s", + "rule_id": "83fef54f-2751-419a-844e-ce3e9605000c", + "max_signals": 100, + "risk_score_mapping": [], + "severity_mapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptions_list": [], + "immutable": false, + "type": "query", + "language": "kuery", + "index": [ + "events-index-*" + ], + "query": "*", + "filters": [] + }, + "kibana.alert.rule.actions": [], + "kibana.alert.rule.created_at": "2022-03-19T02:48:01.193Z", + "kibana.alert.rule.created_by": "elastic", + "kibana.alert.rule.enabled": true, + "kibana.alert.rule.interval": "1m", + "kibana.alert.rule.updated_at": "2022-03-19T02:48:02.426Z", + "kibana.alert.rule.updated_by": "elastic", + "kibana.alert.rule.type": "query", + "kibana.alert.rule.description": "a simple query rule", + "kibana.alert.rule.risk_score": 21, + "kibana.alert.rule.severity": "low", + "kibana.alert.rule.license": "", + "kibana.alert.rule.author": [], + "kibana.alert.rule.false_positives": [], + "kibana.alert.rule.from": "now-36000s", + "kibana.alert.rule.rule_id": "83fef54f-2751-419a-844e-ce3e9605000c", + "kibana.alert.rule.max_signals": 100, + "kibana.alert.rule.risk_score_mapping": [], + "kibana.alert.rule.severity_mapping": [], + "kibana.alert.rule.threat": [], + "kibana.alert.rule.to": "now", + "kibana.alert.rule.references": [], + "kibana.alert.rule.version": 1, + "kibana.alert.rule.exceptions_list": [], + "kibana.alert.rule.immutable": false, + "kibana.alert.original_time": "2022-03-19T02:47:56.372Z", + "kibana.alert.original_event.agent_id_status": "verified", + "kibana.alert.original_event.ingested": "2022-03-19T02:47:56.372Z", + "kibana.alert.original_event.dataset": "elastic_agent.filebeat", + "event.kind": "signal", + "kibana.alert.uuid": "13fc52cad9931eade0fb41b0396c66b7ab23e5d270c6c0691d41154d2070cde5" + } + } +} + +{ + "type": "doc", + "value": { + "index": ".internal.alerts-security.alerts-default-000001", + "id": "7e3f263e2ed4da3d88381cbe5460680b84e25973a584f17b76adfe2bb2aa703a", + "_score": 1, + "source": { + "kibana.version": "8.1.0", + "kibana.alert.rule.category": "Custom Query Rule", + "kibana.alert.rule.consumer": "siem", + "kibana.alert.rule.execution.uuid": "f378da0e-6f34-4d37-97eb-a3871b6c4509", + "kibana.alert.rule.name": "query-rule", + "kibana.alert.rule.producer": "siem", + "kibana.alert.rule.rule_type_id": "siem.queryRule", + "kibana.alert.rule.uuid": "fd531ee0-a72e-11ec-bc9e-ed906a2c068e", + "kibana.space_ids": [ + "default" + ], + "kibana.alert.rule.tags": [], + "@timestamp": "2022-03-19T02:48:03.558Z", + "agent": { + "name": "security-linux-2.example.dev", + "id": "87c417dd-08d6-4e24-ad69-285cb8de84e9", + "type": "filebeat", + "version": "8.1.0" + }, + "log": { + "file": { + "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" + }, + "offset": 148938 + }, + "cloud": { + "availability_zone": "us-central1-c", + "instance": { + "name": "security-linux-1", + "id": "8995531128842994872" + }, + "provider": "gcp", + "service": { + "name": "GCE" + }, + "machine": { + "type": "g1-small" + }, + "project": { + "id": "elastic-siem" + }, + "account": { + "id": "elastic-siem" + } + }, + "ecs": { + "version": "8.1.0" + }, + "host": { + "hostname": "security-linux-2", + "os": { + "kernel": "4.19.0-18-cloud-amd64", + "codename": "buster", + "name": "Debian GNU/Linux", + "type": "linux", + "family": "debian", + "version": "10 (buster)", + "platform": "debian" + }, + "containerized": false, + "ip": "11.200.0.195", + "name": "security-linux-2", + "architecture": "x86_64" + }, + "service.name": "filebeat", + "message": "Status message.", + "data_stream": { + "namespace": "default", + "type": "logs", + "dataset": "elastic_agent.filebeat" + }, + "event.agent_id_status": "verified", + "event.ingested": "2022-03-19T02:47:56.723Z", + "event.dataset": "elastic_agent.filebeat", + "kibana.alert.ancestors": [ + { + "id": "aBEToH8BK09aFtXZElOb", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "kibana.alert.status": "active", + "kibana.alert.workflow_status": "open", + "kibana.alert.depth": 1, + "kibana.alert.reason": "event on security-linux-2 created low alert query-rule.", + "kibana.alert.severity": "low", + "kibana.alert.risk_score": 21, + "kibana.alert.rule.parameters": { + "description": "a simple query rule", + "risk_score": 21, + "severity": "low", + "license": "", + "author": [], + "false_positives": [], + "from": "now-36000s", + "rule_id": "83fef54f-2751-419a-844e-ce3e9605000c", + "max_signals": 100, + "risk_score_mapping": [], + "severity_mapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptions_list": [], + "immutable": false, + "type": "query", + "language": "kuery", + "index": [ + "events-index-*" + ], + "query": "*", + "filters": [] + }, + "kibana.alert.rule.actions": [], + "kibana.alert.rule.created_at": "2022-03-19T02:48:01.193Z", + "kibana.alert.rule.created_by": "elastic", + "kibana.alert.rule.enabled": true, + "kibana.alert.rule.interval": "1m", + "kibana.alert.rule.updated_at": "2022-03-19T02:48:02.426Z", + "kibana.alert.rule.updated_by": "elastic", + "kibana.alert.rule.type": "query", + "kibana.alert.rule.description": "a simple query rule", + "kibana.alert.rule.risk_score": 21, + "kibana.alert.rule.severity": "low", + "kibana.alert.rule.license": "", + "kibana.alert.rule.author": [], + "kibana.alert.rule.false_positives": [], + "kibana.alert.rule.from": "now-36000s", + "kibana.alert.rule.rule_id": "83fef54f-2751-419a-844e-ce3e9605000c", + "kibana.alert.rule.max_signals": 100, + "kibana.alert.rule.risk_score_mapping": [], + "kibana.alert.rule.severity_mapping": [], + "kibana.alert.rule.threat": [], + "kibana.alert.rule.to": "now", + "kibana.alert.rule.references": [], + "kibana.alert.rule.version": 1, + "kibana.alert.rule.exceptions_list": [], + "kibana.alert.rule.immutable": false, + "kibana.alert.original_time": "2022-03-19T02:47:56.723Z", + "kibana.alert.original_event.agent_id_status": "verified", + "kibana.alert.original_event.ingested": "2022-03-19T02:47:56.723Z", + "kibana.alert.original_event.dataset": "elastic_agent.filebeat", + "event.kind": "signal", + "kibana.alert.uuid": "7e3f263e2ed4da3d88381cbe5460680b84e25973a584f17b76adfe2bb2aa703a" + } + } +} + +{ + "type": "doc", + "value": { + "index": ".internal.alerts-security.alerts-default-000001", + "id": "146eff6de5bfb6c98e9ffec98e05589c4efe29ce55245f0b2136ba0a699233e7", + "_score": 1, + "source": { + "kibana.version": "8.1.0", + "kibana.alert.rule.category": "Custom Query Rule", + "kibana.alert.rule.consumer": "siem", + "kibana.alert.rule.execution.uuid": "f378da0e-6f34-4d37-97eb-a3871b6c4509", + "kibana.alert.rule.name": "query-rule", + "kibana.alert.rule.producer": "siem", + "kibana.alert.rule.rule_type_id": "siem.queryRule", + "kibana.alert.rule.uuid": "fd531ee0-a72e-11ec-bc9e-ed906a2c068e", + "kibana.space_ids": [ + "default" + ], + "kibana.alert.rule.tags": [], + "@timestamp": "2022-03-19T02:48:03.561Z", + "agent": { + "name": "security-linux-3.example.dev", + "id": "06851da1-73e7-41e3-97d6-ff1d62c98dc5", + "type": "filebeat", + "version": "8.1.0" + }, + "log": { + "file": { + "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" + }, + "offset": 148938 + }, + "cloud": { + "availability_zone": "us-central1-c", + "instance": { + "name": "security-linux-1", + "id": "8995531128842994872" + }, + "provider": "gcp", + "service": { + "name": "GCE" + }, + "machine": { + "type": "g1-small" + }, + "project": { + "id": "elastic-siem" + }, + "account": { + "id": "elastic-siem" + } + }, + "ecs": { + "version": "8.1.0" + }, + "host": { + "hostname": "security-linux-3", + "os": { + "kernel": "4.19.0-18-cloud-amd64", + "codename": "buster", + "name": "Debian GNU/Linux", + "type": "linux", + "family": "debian", + "version": "10 (buster)", + "platform": "debian" + }, + "containerized": false, + "ip": "11.200.0.196", + "name": "security-linux-3", + "architecture": "x86_64" + }, + "service.name": "filebeat", + "message": "Status message.", + "data_stream": { + "namespace": "default", + "type": "logs", + "dataset": "elastic_agent.filebeat" + }, + "event.agent_id_status": "verified", + "event.ingested": "2022-03-19T02:47:57.047Z", + "event.dataset": "elastic_agent.filebeat", + "kibana.alert.ancestors": [ + { + "id": "aREToH8BK09aFtXZE1Pf", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "kibana.alert.status": "active", + "kibana.alert.workflow_status": "open", + "kibana.alert.depth": 1, + "kibana.alert.reason": "event on security-linux-3 created low alert query-rule.", + "kibana.alert.severity": "low", + "kibana.alert.risk_score": 21, + "kibana.alert.rule.parameters": { + "description": "a simple query rule", + "risk_score": 21, + "severity": "low", + "license": "", + "author": [], + "false_positives": [], + "from": "now-36000s", + "rule_id": "83fef54f-2751-419a-844e-ce3e9605000c", + "max_signals": 100, + "risk_score_mapping": [], + "severity_mapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptions_list": [], + "immutable": false, + "type": "query", + "language": "kuery", + "index": [ + "events-index-*" + ], + "query": "*", + "filters": [] + }, + "kibana.alert.rule.actions": [], + "kibana.alert.rule.created_at": "2022-03-19T02:48:01.193Z", + "kibana.alert.rule.created_by": "elastic", + "kibana.alert.rule.enabled": true, + "kibana.alert.rule.interval": "1m", + "kibana.alert.rule.updated_at": "2022-03-19T02:48:02.426Z", + "kibana.alert.rule.updated_by": "elastic", + "kibana.alert.rule.type": "query", + "kibana.alert.rule.description": "a simple query rule", + "kibana.alert.rule.risk_score": 21, + "kibana.alert.rule.severity": "low", + "kibana.alert.rule.license": "", + "kibana.alert.rule.author": [], + "kibana.alert.rule.false_positives": [], + "kibana.alert.rule.from": "now-36000s", + "kibana.alert.rule.rule_id": "83fef54f-2751-419a-844e-ce3e9605000c", + "kibana.alert.rule.max_signals": 100, + "kibana.alert.rule.risk_score_mapping": [], + "kibana.alert.rule.severity_mapping": [], + "kibana.alert.rule.threat": [], + "kibana.alert.rule.to": "now", + "kibana.alert.rule.references": [], + "kibana.alert.rule.version": 1, + "kibana.alert.rule.exceptions_list": [], + "kibana.alert.rule.immutable": false, + "kibana.alert.original_time": "2022-03-19T02:47:57.047Z", + "kibana.alert.original_event.agent_id_status": "verified", + "kibana.alert.original_event.ingested": "2022-03-19T02:47:57.047Z", + "kibana.alert.original_event.dataset": "elastic_agent.filebeat", + "event.kind": "signal", + "kibana.alert.uuid": "146eff6de5bfb6c98e9ffec98e05589c4efe29ce55245f0b2136ba0a699233e7" + } + } +} + +{ + "type": "doc", + "value": { + "index": ".internal.alerts-security.alerts-default-000001", + "id": "d7c0195e787bbafe32ae0389b26e1ac73d599f004ba3347bf1f2d76bdcc688a8", + "_score": 1, + "source": { + "kibana.version": "8.1.0", + "kibana.alert.rule.category": "Custom Query Rule", + "kibana.alert.rule.consumer": "siem", + "kibana.alert.rule.execution.uuid": "f378da0e-6f34-4d37-97eb-a3871b6c4509", + "kibana.alert.rule.name": "query-rule", + "kibana.alert.rule.producer": "siem", + "kibana.alert.rule.rule_type_id": "siem.queryRule", + "kibana.alert.rule.uuid": "fd531ee0-a72e-11ec-bc9e-ed906a2c068e", + "kibana.space_ids": [ + "default" + ], + "kibana.alert.rule.tags": [], + "@timestamp": "2022-03-19T02:48:03.563Z", + "agent": { + "name": "security-linux-1.example.dev", + "id": "d8f66724-3cf2-437c-b124-6ac9fb0e2311", + "type": "filebeat", + "version": "8.1.0" + }, + "log": { + "file": { + "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" + }, + "offset": 148938 + }, + "cloud": { + "availability_zone": "us-central1-c", + "instance": { + "name": "security-linux-1", + "id": "8995531128842994872" + }, + "provider": "gcp", + "service": { + "name": "GCE" + }, + "machine": { + "type": "g1-small" + }, + "project": { + "id": "elastic-siem" + }, + "account": { + "id": "elastic-siem" + } + }, + "ecs": { + "version": "8.1.0" + }, + "host": { + "hostname": "security-linux-1", + "os": { + "kernel": "4.19.0-18-cloud-amd64", + "codename": "buster", + "name": "Debian GNU/Linux", + "type": "linux", + "family": "debian", + "version": "10 (buster)", + "platform": "debian" + }, + "containerized": false, + "ip": "11.200.0.194", + "name": "security-linux-1", + "architecture": "x86_64" + }, + "service.name": "filebeat", + "message": "Status message.", + "data_stream": { + "namespace": "default", + "type": "logs", + "dataset": "elastic_agent.filebeat" + }, + "event.agent_id_status": "verified", + "event.ingested": "2022-03-19T02:47:57.376Z", + "event.dataset": "elastic_agent.filebeat", + "kibana.alert.ancestors": [ + { + "id": "ahEToH8BK09aFtXZFVMq", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "kibana.alert.status": "active", + "kibana.alert.workflow_status": "open", + "kibana.alert.depth": 1, + "kibana.alert.reason": "event on security-linux-1 created low alert query-rule.", + "kibana.alert.severity": "low", + "kibana.alert.risk_score": 21, + "kibana.alert.rule.parameters": { + "description": "a simple query rule", + "risk_score": 21, + "severity": "low", + "license": "", + "author": [], + "false_positives": [], + "from": "now-36000s", + "rule_id": "83fef54f-2751-419a-844e-ce3e9605000c", + "max_signals": 100, + "risk_score_mapping": [], + "severity_mapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptions_list": [], + "immutable": false, + "type": "query", + "language": "kuery", + "index": [ + "events-index-*" + ], + "query": "*", + "filters": [] + }, + "kibana.alert.rule.actions": [], + "kibana.alert.rule.created_at": "2022-03-19T02:48:01.193Z", + "kibana.alert.rule.created_by": "elastic", + "kibana.alert.rule.enabled": true, + "kibana.alert.rule.interval": "1m", + "kibana.alert.rule.updated_at": "2022-03-19T02:48:02.426Z", + "kibana.alert.rule.updated_by": "elastic", + "kibana.alert.rule.type": "query", + "kibana.alert.rule.description": "a simple query rule", + "kibana.alert.rule.risk_score": 21, + "kibana.alert.rule.severity": "low", + "kibana.alert.rule.license": "", + "kibana.alert.rule.author": [], + "kibana.alert.rule.false_positives": [], + "kibana.alert.rule.from": "now-36000s", + "kibana.alert.rule.rule_id": "83fef54f-2751-419a-844e-ce3e9605000c", + "kibana.alert.rule.max_signals": 100, + "kibana.alert.rule.risk_score_mapping": [], + "kibana.alert.rule.severity_mapping": [], + "kibana.alert.rule.threat": [], + "kibana.alert.rule.to": "now", + "kibana.alert.rule.references": [], + "kibana.alert.rule.version": 1, + "kibana.alert.rule.exceptions_list": [], + "kibana.alert.rule.immutable": false, + "kibana.alert.original_time": "2022-03-19T02:47:57.376Z", + "kibana.alert.original_event.agent_id_status": "verified", + "kibana.alert.original_event.ingested": "2022-03-19T02:47:57.376Z", + "kibana.alert.original_event.dataset": "elastic_agent.filebeat", + "event.kind": "signal", + "kibana.alert.uuid": "d7c0195e787bbafe32ae0389b26e1ac73d599f004ba3347bf1f2d76bdcc688a8" + } + } +} + diff --git a/x-pack/test/rule_registry/security_and_spaces/tests/basic/find_alerts.ts b/x-pack/test/rule_registry/security_and_spaces/tests/basic/find_alerts.ts index 694c27060f1911..404250a169e0a2 100644 --- a/x-pack/test/rule_registry/security_and_spaces/tests/basic/find_alerts.ts +++ b/x-pack/test/rule_registry/security_and_spaces/tests/basic/find_alerts.ts @@ -7,7 +7,7 @@ import expect from '@kbn/expect'; import { - ALERT_RULE_CONSUMER, + ALERT_RULE_TYPE_ID, ALERT_WORKFLOW_STATUS, } from '@kbn/rule-registry-plugin/common/technical_rule_data_field_names'; import { @@ -268,30 +268,30 @@ export default ({ getService }: FtrProviderContext) => { expect(found.body.aggregations.nbr_consumer.value).to.be.equal(2); }); - it(`${superUser.username} should handle 'siem' featureIds`, async () => { + it(`${superUser.username} should handle 'siem' rule type IDs`, async () => { const found = await supertestWithoutAuth .post(`${getSpaceUrlPrefix(SPACE1)}${TEST_URL}/find`) .auth(superUser.username, superUser.password) .set('kbn-xsrf', 'true') .send({ - feature_ids: ['siem'], + rule_type_ids: ['siem.queryRule'], }); - expect(found.body.hits.hits.every((hit: any) => hit[ALERT_RULE_CONSUMER] === 'siem')).equal( + expect(found.body.hits.hits.every((hit: any) => hit[ALERT_RULE_TYPE_ID] === 'siem')).equal( true ); }); - it(`${superUser.username} should handle 'apm' featureIds`, async () => { + it(`${superUser.username} should handle 'apm' rule type IDs`, async () => { const found = await supertestWithoutAuth .post(`${getSpaceUrlPrefix(SPACE1)}${TEST_URL}/find`) .auth(superUser.username, superUser.password) .set('kbn-xsrf', 'true') .send({ - feature_ids: ['apm'], + rule_type_ids: ['apm.error_rate'], }); - expect(found.body.hits.hits.every((hit: any) => hit[ALERT_RULE_CONSUMER] === 'apm')).equal( + expect(found.body.hits.hits.every((hit: any) => hit[ALERT_RULE_TYPE_ID] === 'apm')).equal( true ); }); diff --git a/x-pack/test/rule_registry/security_and_spaces/tests/basic/get_alert_summary.ts b/x-pack/test/rule_registry/security_and_spaces/tests/basic/get_alert_summary.ts index 5da72c7f6a76ab..abfc4c9d5aa792 100644 --- a/x-pack/test/rule_registry/security_and_spaces/tests/basic/get_alert_summary.ts +++ b/x-pack/test/rule_registry/security_and_spaces/tests/basic/get_alert_summary.ts @@ -39,7 +39,7 @@ export default ({ getService }: FtrProviderContext) => { .send({ gte: '2020-12-16T15:00:00.000Z', lte: '2020-12-16T16:00:00.000Z', - featureIds: ['logs'], + ruleTypeIds: ['logs.alert.document.count'], fixed_interval: '10m', }) .expect(200); @@ -83,7 +83,7 @@ export default ({ getService }: FtrProviderContext) => { }, }, ], - featureIds: ['logs'], + ruleTypeIds: ['logs.alert.document.count'], fixed_interval: '10m', }) .expect(200); @@ -127,7 +127,7 @@ export default ({ getService }: FtrProviderContext) => { }, }, ], - featureIds: ['logs'], + ruleTypeIds: ['logs.alert.document.count'], fixed_interval: '10m', }) .expect(200); diff --git a/x-pack/test/rule_registry/security_and_spaces/tests/basic/get_alerts_index.ts b/x-pack/test/rule_registry/security_and_spaces/tests/basic/get_alerts_index.ts index 1146fa925908c1..3f802dcea61734 100644 --- a/x-pack/test/rule_registry/security_and_spaces/tests/basic/get_alerts_index.ts +++ b/x-pack/test/rule_registry/security_and_spaces/tests/basic/get_alerts_index.ts @@ -25,7 +25,7 @@ export default ({ getService }: FtrProviderContext) => { const getAPMIndexName = async (user: User, space: string, expectedStatusCode: number = 200) => { const resp = await supertestWithoutAuth - .get(`${getSpaceUrlPrefix(space)}${ALERTS_INDEX_URL}?features=apm`) + .get(`${getSpaceUrlPrefix(space)}${ALERTS_INDEX_URL}?ruleTypeIds=apm.error_rate`) .auth(user.username, user.password) .set('kbn-xsrf', 'true') .expect(expectedStatusCode); @@ -38,7 +38,7 @@ export default ({ getService }: FtrProviderContext) => { expectedStatusCode: number = 200 ) => { const resp = await supertestWithoutAuth - .get(`${getSpaceUrlPrefix(space)}${ALERTS_INDEX_URL}?features=siem`) + .get(`${getSpaceUrlPrefix(space)}${ALERTS_INDEX_URL}?ruleTypeIds=siem.queryRule`) .auth(user.username, user.password) .set('kbn-xsrf', 'true') .expect(expectedStatusCode); @@ -50,6 +50,11 @@ export default ({ getService }: FtrProviderContext) => { before(async () => { await esArchiver.load('x-pack/test/functional/es_archives/rule_registry/alerts'); }); + + before(async () => { + await esArchiver.unload('x-pack/test/functional/es_archives/rule_registry/alerts'); + }); + describe('Users:', () => { it(`${obsOnlySpacesAll.username} should be able to access the APM alert in ${SPACE1}`, async () => { const indexNames = await getAPMIndexName(obsOnlySpacesAll, SPACE1); diff --git a/x-pack/test/rule_registry/security_and_spaces/tests/basic/get_browser_fields_by_feature_id.ts b/x-pack/test/rule_registry/security_and_spaces/tests/basic/get_browser_fields_by_rule_type_ids.ts similarity index 73% rename from x-pack/test/rule_registry/security_and_spaces/tests/basic/get_browser_fields_by_feature_id.ts rename to x-pack/test/rule_registry/security_and_spaces/tests/basic/get_browser_fields_by_rule_type_ids.ts index f922371edc4926..bf5339606914b0 100644 --- a/x-pack/test/rule_registry/security_and_spaces/tests/basic/get_browser_fields_by_feature_id.ts +++ b/x-pack/test/rule_registry/security_and_spaces/tests/basic/get_browser_fields_by_rule_type_ids.ts @@ -6,6 +6,12 @@ */ import expect from 'expect'; +import { + APM_RULE_TYPE_IDS, + UPTIME_RULE_TYPE_IDS, + INFRA_RULE_TYPE_IDS, + LOG_RULE_TYPE_IDS, +} from '@kbn/rule-data-utils'; import { superUser, obsOnlySpacesAll, secOnlyRead } from '../../../common/lib/authentication/users'; import type { User } from '../../../common/lib/authentication/types'; import { FtrProviderContext } from '../../../common/ftr_provider_context'; @@ -20,31 +26,39 @@ export default ({ getService }: FtrProviderContext) => { const getBrowserFieldsByFeatureId = async ( user: User, - featureIds: string[], + ruleTypeIds: string[], expectedStatusCode: number = 200 ) => { const resp = await supertestWithoutAuth .get(`${getSpaceUrlPrefix(SPACE1)}${TEST_URL}`) - .query({ featureIds }) + .query({ ruleTypeIds }) .auth(user.username, user.password) .set('kbn-xsrf', 'true') .expect(expectedStatusCode); + return resp.body; }; - describe('Alert - Get browser fields by featureId', () => { + describe('Alert - Get browser fields by rule type IDs', () => { + const ruleTypeIds = [ + ...APM_RULE_TYPE_IDS, + ...UPTIME_RULE_TYPE_IDS, + ...INFRA_RULE_TYPE_IDS, + ...LOG_RULE_TYPE_IDS, + ]; + before(async () => { await esArchiver.load('x-pack/test/functional/es_archives/rule_registry/alerts'); }); + after(async () => { + await esArchiver.unload('x-pack/test/functional/es_archives/rule_registry/alerts'); + }); + describe('Users:', () => { - it(`${obsOnlySpacesAll.username} should be able to get browser fields for o11y featureIds`, async () => { - const resp = await getBrowserFieldsByFeatureId(obsOnlySpacesAll, [ - 'apm', - 'infrastructure', - 'logs', - 'uptime', - ]); + it(`${obsOnlySpacesAll.username} should be able to get browser fields for o11y ruleTypeIds`, async () => { + const resp = await getBrowserFieldsByFeatureId(obsOnlySpacesAll, ruleTypeIds); + expect(Object.keys(resp.browserFields)).toEqual([ 'base', 'agent', @@ -60,13 +74,9 @@ export default ({ getService }: FtrProviderContext) => { ]); }); - it(`${superUser.username} should be able to get browser fields for o11y featureIds`, async () => { - const resp = await getBrowserFieldsByFeatureId(superUser, [ - 'apm', - 'infrastructure', - 'logs', - 'uptime', - ]); + it(`${superUser.username} should be able to get browser fields for o11y ruleTypeIds`, async () => { + const resp = await getBrowserFieldsByFeatureId(superUser, ruleTypeIds); + expect(Object.keys(resp.browserFields)).toEqual([ 'base', 'agent', @@ -85,12 +95,12 @@ export default ({ getService }: FtrProviderContext) => { ]); }); - it(`${superUser.username} should NOT be able to get browser fields for siem featureId`, async () => { - await getBrowserFieldsByFeatureId(superUser, ['siem'], 404); + it(`${superUser.username} should NOT be able to get browser fields for siem rule types`, async () => { + await getBrowserFieldsByFeatureId(superUser, ['siem.queryRule'], 404); }); - it(`${secOnlyRead.username} should NOT be able to get browser fields for siem featureId`, async () => { - await getBrowserFieldsByFeatureId(secOnlyRead, ['siem'], 404); + it(`${secOnlyRead.username} should NOT be able to get browser fields for siem rule types`, async () => { + await getBrowserFieldsByFeatureId(secOnlyRead, ['siem.queryRule'], 404); }); }); }); diff --git a/x-pack/test/rule_registry/security_and_spaces/tests/basic/index.ts b/x-pack/test/rule_registry/security_and_spaces/tests/basic/index.ts index 3cf7e28357ed8d..e7593121bc2d06 100644 --- a/x-pack/test/rule_registry/security_and_spaces/tests/basic/index.ts +++ b/x-pack/test/rule_registry/security_and_spaces/tests/basic/index.ts @@ -28,7 +28,7 @@ export default ({ loadTestFile, getService }: FtrProviderContext): void => { loadTestFile(require.resolve('./get_alerts_index')); loadTestFile(require.resolve('./find_alerts')); loadTestFile(require.resolve('./search_strategy')); - loadTestFile(require.resolve('./get_browser_fields_by_feature_id')); + loadTestFile(require.resolve('./get_browser_fields_by_rule_type_ids')); loadTestFile(require.resolve('./get_alert_summary')); loadTestFile(require.resolve('./get_aad_fields_by_rule_type')); }); diff --git a/x-pack/test/rule_registry/security_and_spaces/tests/basic/search_strategy.ts b/x-pack/test/rule_registry/security_and_spaces/tests/basic/search_strategy.ts index cbdd9d2301294d..7e8c5b312e6f42 100644 --- a/x-pack/test/rule_registry/security_and_spaces/tests/basic/search_strategy.ts +++ b/x-pack/test/rule_registry/security_and_spaces/tests/basic/search_strategy.ts @@ -5,7 +5,6 @@ * 2.0. */ import expect from '@kbn/expect'; -import { AlertConsumers } from '@kbn/rule-data-utils'; import type { RuleRegistrySearchResponse } from '@kbn/rule-registry-plugin/common'; import type { FtrProviderContext } from '../../../common/ftr_provider_context'; @@ -37,6 +36,7 @@ export default ({ getService }: FtrProviderContext) => { before(async () => { await esArchiver.load('x-pack/test/functional/es_archives/observability/alerts'); }); + after(async () => { await esArchiver.unload('x-pack/test/functional/es_archives/observability/alerts'); }); @@ -52,15 +52,14 @@ export default ({ getService }: FtrProviderContext) => { kibanaVersion, internalOrigin: 'Kibana', options: { - featureIds: [AlertConsumers.LOGS], + ruleTypeIds: ['logs.alert.document.count'], }, strategy: 'privateRuleRegistryAlertsSearchStrategy', }); + expect(result.rawResponse.hits.total).to.eql(5); - const consumers = result.rawResponse.hits.hits.map((hit) => { - return hit.fields?.['kibana.alert.rule.consumer']; - }); - expect(consumers.every((consumer) => consumer === AlertConsumers.LOGS)); + + validateRuleTypeIds(result, ['logs.alert.document.count']); }); it('should support pagination and sorting', async () => { @@ -74,7 +73,7 @@ export default ({ getService }: FtrProviderContext) => { kibanaVersion, internalOrigin: 'Kibana', options: { - featureIds: [AlertConsumers.LOGS], + ruleTypeIds: ['logs.alert.document.count'], pagination: { pageSize: 2, pageIndex: 1, @@ -89,15 +88,25 @@ export default ({ getService }: FtrProviderContext) => { }, strategy: 'privateRuleRegistryAlertsSearchStrategy', }); + expect(result.rawResponse.hits.total).to.eql(5); expect(result.rawResponse.hits.hits.length).to.eql(2); + const first = result.rawResponse.hits.hits[0].fields?.['kibana.alert.evaluation.value']; const second = result.rawResponse.hits.hits[1].fields?.['kibana.alert.evaluation.value']; + expect(first > second).to.be(true); }); }); describe('siem', () => { + const siemRuleTypeIds = [ + 'siem.indicatorRule', + 'siem.thresholdRule', + 'siem.eqlRule', + 'siem.queryRule', + ]; + before(async () => { await esArchiver.load('x-pack/test/functional/es_archives/observability/alerts'); await esArchiver.load('x-pack/test/functional/es_archives/security_solution/alerts/8.1.0'); @@ -121,15 +130,14 @@ export default ({ getService }: FtrProviderContext) => { kibanaVersion, internalOrigin: 'Kibana', options: { - featureIds: [AlertConsumers.SIEM], + ruleTypeIds: siemRuleTypeIds, }, strategy: 'privateRuleRegistryAlertsSearchStrategy', }); + expect(result.rawResponse.hits.total).to.eql(50); - const consumers = result.rawResponse.hits.hits.map( - (hit) => hit.fields?.['kibana.alert.rule.consumer'] - ); - expect(consumers.every((consumer) => consumer === AlertConsumers.SIEM)); + + validateRuleTypeIds(result, siemRuleTypeIds); }); it('should throw an error when trying to to search for more than just siem', async () => { @@ -143,13 +151,14 @@ export default ({ getService }: FtrProviderContext) => { kibanaVersion, internalOrigin: 'Kibana', options: { - featureIds: [AlertConsumers.SIEM, AlertConsumers.LOGS], + ruleTypeIds: ['siem.indicatorRule', 'logs.alert.document.count'], }, strategy: 'privateRuleRegistryAlertsSearchStrategy', }); + expect(result.statusCode).to.be(500); expect(result.message).to.be( - `The privateRuleRegistryAlertsSearchStrategy search strategy is unable to accommodate requests containing multiple feature IDs and one of those IDs is SIEM.` + 'The privateRuleRegistryAlertsSearchStrategy search strategy is unable to accommodate requests containing multiple rule types with mixed authorization.' ); }); @@ -166,7 +175,7 @@ export default ({ getService }: FtrProviderContext) => { kibanaVersion, internalOrigin: 'Kibana', options: { - featureIds: [AlertConsumers.SIEM], + ruleTypeIds: siemRuleTypeIds, runtimeMappings: { [runtimeFieldKey]: { type: 'keyword', @@ -178,18 +187,24 @@ export default ({ getService }: FtrProviderContext) => { }, strategy: 'privateRuleRegistryAlertsSearchStrategy', }); + expect(result.rawResponse.hits.total).to.eql(50); + const runtimeFields = result.rawResponse.hits.hits.map( (hit) => hit.fields?.[runtimeFieldKey] ); + expect(runtimeFields.every((field) => field === runtimeFieldValue)); }); }); describe('apm', () => { + const apmRuleTypeIds = ['apm.transaction_error_rate', 'apm.error_rate']; + before(async () => { await esArchiver.load('x-pack/test/functional/es_archives/observability/alerts'); }); + after(async () => { await esArchiver.unload('x-pack/test/functional/es_archives/observability/alerts'); }); @@ -205,16 +220,15 @@ export default ({ getService }: FtrProviderContext) => { kibanaVersion, internalOrigin: 'Kibana', options: { - featureIds: [AlertConsumers.APM], + ruleTypeIds: apmRuleTypeIds, }, strategy: 'privateRuleRegistryAlertsSearchStrategy', space: 'default', }); + expect(result.rawResponse.hits.total).to.eql(9); - const consumers = result.rawResponse.hits.hits.map( - (hit) => hit.fields?.['kibana.alert.rule.consumer'] - ); - expect(consumers.every((consumer) => consumer === AlertConsumers.APM)); + + validateRuleTypeIds(result, apmRuleTypeIds); }); it('should not by pass our RBAC authz filter with a should filter', async () => { @@ -228,7 +242,7 @@ export default ({ getService }: FtrProviderContext) => { kibanaVersion, internalOrigin: 'Kibana', options: { - featureIds: [AlertConsumers.APM], + ruleTypeIds: apmRuleTypeIds, query: { bool: { filter: [], @@ -238,7 +252,7 @@ export default ({ getService }: FtrProviderContext) => { should: [ { match: { - 'kibana.alert.rule.consumer': 'logs', + 'kibana.alert.rule.rule_type_id': 'logs.alert.document.count', }, }, ], @@ -254,11 +268,10 @@ export default ({ getService }: FtrProviderContext) => { strategy: 'privateRuleRegistryAlertsSearchStrategy', space: 'default', }); + expect(result.rawResponse.hits.total).to.eql(9); - const consumers = result.rawResponse.hits.hits.map( - (hit) => hit.fields?.['kibana.alert.rule.consumer'] - ); - expect(consumers.every((consumer) => consumer === AlertConsumers.APM)); + + validateRuleTypeIds(result, apmRuleTypeIds); }); it('should return an empty response with must filter and our RBAC authz filter', async () => { @@ -272,7 +285,7 @@ export default ({ getService }: FtrProviderContext) => { kibanaVersion, internalOrigin: 'Kibana', options: { - featureIds: [AlertConsumers.APM], + ruleTypeIds: apmRuleTypeIds, query: { bool: { filter: [], @@ -282,7 +295,7 @@ export default ({ getService }: FtrProviderContext) => { should: [ { match: { - 'kibana.alert.rule.consumer': 'logs', + 'kibana.alert.rule.rule_type_id': 'logs.alert.document.count', }, }, ], @@ -298,6 +311,7 @@ export default ({ getService }: FtrProviderContext) => { strategy: 'privateRuleRegistryAlertsSearchStrategy', space: 'default', }); + expect(result.rawResponse.hits.total).to.eql(0); }); @@ -312,7 +326,7 @@ export default ({ getService }: FtrProviderContext) => { kibanaVersion, internalOrigin: 'Kibana', options: { - featureIds: [AlertConsumers.APM], + ruleTypeIds: apmRuleTypeIds, query: { bool: { filter: [], @@ -321,11 +335,11 @@ export default ({ getService }: FtrProviderContext) => { { bool: { should: [ - { + ...apmRuleTypeIds.map((apmRuleTypeId) => ({ match: { - 'kibana.alert.rule.consumer': 'apm', + 'kibana.alert.rule.rule_type_id': apmRuleTypeId, }, - }, + })), ], minimum_should_match: 1, }, @@ -338,11 +352,10 @@ export default ({ getService }: FtrProviderContext) => { strategy: 'privateRuleRegistryAlertsSearchStrategy', space: 'default', }); + expect(result.rawResponse.hits.total).to.eql(9); - const consumers = result.rawResponse.hits.hits.map( - (hit) => hit.fields?.['kibana.alert.rule.consumer'] - ); - expect(consumers.every((consumer) => consumer === AlertConsumers.APM)); + + validateRuleTypeIds(result, apmRuleTypeIds); }); }); @@ -358,7 +371,7 @@ export default ({ getService }: FtrProviderContext) => { kibanaVersion, internalOrigin: 'Kibana', options: { - featureIds: [], + ruleTypeIds: [], }, strategy: 'privateRuleRegistryAlertsSearchStrategy', }); @@ -367,3 +380,17 @@ export default ({ getService }: FtrProviderContext) => { }); }); }; + +const validateRuleTypeIds = (result: RuleRegistrySearchResponse, ruleTypeIdsToVerify: string[]) => { + const ruleTypeIds = result.rawResponse.hits.hits + .map((hit) => { + return hit.fields?.['kibana.alert.rule.rule_type_id']; + }) + .flat(); + + expect( + ruleTypeIds.every((ruleTypeId) => + ruleTypeIdsToVerify.some((ruleTypeIdToVerify) => ruleTypeIdToVerify === ruleTypeId) + ) + ).to.eql(true); +}; diff --git a/x-pack/test/rule_registry/security_and_spaces/tests/trial/get_alerts.ts b/x-pack/test/rule_registry/security_and_spaces/tests/trial/get_alerts.ts index f4aa5c503bc197..f3c4a4e6146a27 100644 --- a/x-pack/test/rule_registry/security_and_spaces/tests/trial/get_alerts.ts +++ b/x-pack/test/rule_registry/security_and_spaces/tests/trial/get_alerts.ts @@ -47,6 +47,11 @@ export default ({ getService }: FtrProviderContext) => { before(async () => { await esArchiver.load('x-pack/test/functional/es_archives/rule_registry/alerts'); }); + + after(async () => { + await esArchiver.unload('x-pack/test/functional/es_archives/rule_registry/alerts'); + }); + describe('Users:', () => { // user with minimal_read and alerts_read privileges should be able to access apm alert it(`${obsMinReadAlertsRead.username} should be able to access the APM alert in ${SPACE1}`, async () => { From 22cbb1e8f506a47fbaab11cdf20b14c87b67f07c Mon Sep 17 00:00:00 2001 From: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Date: Sat, 3 Aug 2024 12:22:44 +0000 Subject: [PATCH 049/106] [CI] Auto-commit changed files from 'node scripts/lint_ts_projects --fix' --- x-pack/examples/triggers_actions_ui_example/tsconfig.json | 1 - x-pack/plugins/cases/tsconfig.json | 1 + .../observability_ai_assistant_app/tsconfig.json | 3 ++- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/x-pack/examples/triggers_actions_ui_example/tsconfig.json b/x-pack/examples/triggers_actions_ui_example/tsconfig.json index 601f23edd2647b..458a4a99d589b2 100644 --- a/x-pack/examples/triggers_actions_ui_example/tsconfig.json +++ b/x-pack/examples/triggers_actions_ui_example/tsconfig.json @@ -19,7 +19,6 @@ "@kbn/alerting-plugin", "@kbn/triggers-actions-ui-plugin", "@kbn/developer-examples-plugin", - "@kbn/rule-data-utils", "@kbn/data-plugin", "@kbn/i18n-react", "@kbn/shared-ux-router", diff --git a/x-pack/plugins/cases/tsconfig.json b/x-pack/plugins/cases/tsconfig.json index 6bbc5cfd4e421a..125beece46b099 100644 --- a/x-pack/plugins/cases/tsconfig.json +++ b/x-pack/plugins/cases/tsconfig.json @@ -76,6 +76,7 @@ "@kbn/data-views-plugin", "@kbn/core-http-router-server-internal", "@kbn/presentation-publishing", + "@kbn/securitysolution-rules", ], "exclude": [ "target/**/*", diff --git a/x-pack/plugins/observability_solution/observability_ai_assistant_app/tsconfig.json b/x-pack/plugins/observability_solution/observability_ai_assistant_app/tsconfig.json index 282363e50ec3fd..4de6693168db62 100644 --- a/x-pack/plugins/observability_solution/observability_ai_assistant_app/tsconfig.json +++ b/x-pack/plugins/observability_solution/observability_ai_assistant_app/tsconfig.json @@ -70,7 +70,8 @@ "@kbn/cloud-plugin", "@kbn/observability-plugin", "@kbn/esql-datagrid", - "@kbn/alerting-comparators" + "@kbn/alerting-comparators", + "@kbn/rule-data-utils" ], "exclude": ["target/**/*"] } From d37760b429afa8c9f64b89f067e926e4f7693b44 Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Sun, 4 Aug 2024 14:04:38 +0300 Subject: [PATCH 050/106] Improve search strategy alert handling --- .../search_strategy/search_strategy.test.ts | 165 ++++++++++--- .../server/search_strategy/search_strategy.ts | 20 +- x-pack/test/common/services/bsearch_secure.ts | 6 +- .../tests/basic/search_strategy.ts | 220 +++++++++++++++++- 4 files changed, 370 insertions(+), 41 deletions(-) diff --git a/x-pack/plugins/rule_registry/server/search_strategy/search_strategy.test.ts b/x-pack/plugins/rule_registry/server/search_strategy/search_strategy.test.ts index 27a58d63f056af..b6706485a08d5d 100644 --- a/x-pack/plugins/rule_registry/server/search_strategy/search_strategy.test.ts +++ b/x-pack/plugins/rule_registry/server/search_strategy/search_strategy.test.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { of } from 'rxjs'; +import { lastValueFrom, of } from 'rxjs'; import { merge } from 'lodash'; import { loggerMock } from '@kbn/logging-mocks'; import { ALERT_EVENTS_FIELDS } from '@kbn/alerts-as-data-utils'; @@ -18,6 +18,8 @@ import type { RuleRegistrySearchRequest } from '../../common'; import * as getAuthzFilterImport from '../lib/get_authz_filter'; import { getIsKibanaRequest } from '../lib/get_is_kibana_request'; import { alertingAuthorizationMock } from '@kbn/alerting-plugin/server/authorization/alerting_authorization.mock'; +import { Boom } from '@hapi/boom'; +import { KbnSearchError } from '@kbn/data-plugin/server/search/report_search_error'; jest.mock('../lib/get_is_kibana_request'); @@ -129,9 +131,9 @@ describe('ruleRegistrySearchStrategyProvider()', () => { const strategy = ruleRegistrySearchStrategyProvider(data, alerting, logger, security, spaces); - const result = await strategy - .search(request, options, deps as unknown as SearchStrategyDependencies) - .toPromise(); + const result = await lastValueFrom( + strategy.search(request, options, deps as unknown as SearchStrategyDependencies) + ); expect(result).toEqual(response); }); @@ -150,9 +152,10 @@ describe('ruleRegistrySearchStrategyProvider()', () => { const strategy = ruleRegistrySearchStrategyProvider(data, alerting, logger, security, spaces); - const result = await strategy - .search(request, options, deps as unknown as SearchStrategyDependencies) - .toPromise(); + const result = await lastValueFrom( + strategy.search(request, options, deps as unknown as SearchStrategyDependencies) + ); + expect(result).toBe(EMPTY_RESPONSE); }); @@ -170,9 +173,10 @@ describe('ruleRegistrySearchStrategyProvider()', () => { const strategy = ruleRegistrySearchStrategyProvider(data, alerting, logger, security, spaces); - await strategy - .search(request, options, deps as unknown as SearchStrategyDependencies) - .toPromise(); + await lastValueFrom( + strategy.search(request, options, deps as unknown as SearchStrategyDependencies) + ); + expect(getAuthzFilterSpy).not.toHaveBeenCalled(); }); @@ -191,14 +195,19 @@ describe('ruleRegistrySearchStrategyProvider()', () => { const strategy = ruleRegistrySearchStrategyProvider(data, alerting, logger, security, spaces); let err; + try { - await strategy - .search(request, options, deps as unknown as SearchStrategyDependencies) - .toPromise(); + await lastValueFrom( + strategy.search(request, options, deps as unknown as SearchStrategyDependencies) + ); } catch (e) { err = e; } - expect(err).toBeDefined(); + + expect(err.statusCode).toBe(400); + expect(err.message).toBe( + 'The privateRuleRegistryAlertsSearchStrategy search strategy is unable to accommodate requests containing multiple rule types with mixed authorization.' + ); }); it('should use internal user when requesting o11y alerts as RBAC is applied', async () => { @@ -214,9 +223,10 @@ describe('ruleRegistrySearchStrategyProvider()', () => { const strategy = ruleRegistrySearchStrategyProvider(data, alerting, logger, security, spaces); - await strategy - .search(request, options, deps as unknown as SearchStrategyDependencies) - .toPromise(); + await lastValueFrom( + strategy.search(request, options, deps as unknown as SearchStrategyDependencies) + ); + expect(data.search.searchAsInternalUser.search).toHaveBeenCalled(); expect(searchStrategySearch).not.toHaveBeenCalled(); }); @@ -235,9 +245,10 @@ describe('ruleRegistrySearchStrategyProvider()', () => { const strategy = ruleRegistrySearchStrategyProvider(data, alerting, logger, security, spaces); - await strategy - .search(request, options, deps as unknown as SearchStrategyDependencies) - .toPromise(); + await lastValueFrom( + strategy.search(request, options, deps as unknown as SearchStrategyDependencies) + ); + expect(data.search.searchAsInternalUser.search as jest.Mock).not.toHaveBeenCalled(); expect(searchStrategySearch).toHaveBeenCalled(); }); @@ -259,9 +270,10 @@ describe('ruleRegistrySearchStrategyProvider()', () => { const strategy = ruleRegistrySearchStrategyProvider(data, alerting, logger, security, spaces); - await strategy - .search(request, options, deps as unknown as SearchStrategyDependencies) - .toPromise(); + await lastValueFrom( + strategy.search(request, options, deps as unknown as SearchStrategyDependencies) + ); + expect((data.search.searchAsInternalUser.search as jest.Mock).mock.calls.length).toBe(1); expect( (data.search.searchAsInternalUser.search as jest.Mock).mock.calls[0][0].params.body.size @@ -291,9 +303,10 @@ describe('ruleRegistrySearchStrategyProvider()', () => { const strategy = ruleRegistrySearchStrategyProvider(data, alerting, logger, security, spaces); - await strategy - .search(request, options, deps as unknown as SearchStrategyDependencies) - .toPromise(); + await lastValueFrom( + strategy.search(request, options, deps as unknown as SearchStrategyDependencies) + ); + expect((data.search.searchAsInternalUser.search as jest.Mock).mock.calls.length).toBe(1); expect( (data.search.searchAsInternalUser.search as jest.Mock).mock.calls[0][0].params.body.sort @@ -316,21 +329,24 @@ describe('ruleRegistrySearchStrategyProvider()', () => { const strategy = ruleRegistrySearchStrategyProvider(data, alerting, logger, security, spaces); - await strategy - .search(request, options, deps as unknown as SearchStrategyDependencies) - .toPromise(); + await lastValueFrom( + strategy.search(request, options, deps as unknown as SearchStrategyDependencies) + ); + const arg0 = searchStrategySearch.mock.calls[0][0]; expect(arg0.params.body.fields.length).toEqual( // +2 because of fields.push({ field: 'kibana.alert.*', include_unmapped: false }); and // fields.push({ field: 'signal.*', include_unmapped: false }); ALERT_EVENTS_FIELDS.length + 2 ); + expect.arrayContaining([ expect.objectContaining({ x: 2, y: 3, }), ]); + expect(arg0).toEqual( expect.objectContaining({ id: undefined, @@ -377,9 +393,9 @@ describe('ruleRegistrySearchStrategyProvider()', () => { const strategy = ruleRegistrySearchStrategyProvider(data, alerting, logger, security, spaces); - await strategy - .search(request, options, deps as unknown as SearchStrategyDependencies) - .toPromise(); + await lastValueFrom( + strategy.search(request, options, deps as unknown as SearchStrategyDependencies) + ); const arg0 = searchStrategySearch.mock.calls[0][0]; expect(arg0.params.body.fields.length).toEqual( @@ -387,6 +403,7 @@ describe('ruleRegistrySearchStrategyProvider()', () => { // fields.push({ field: 'signal.*', include_unmapped: false }); + my-super-field ALERT_EVENTS_FIELDS.length + 3 ); + expect(arg0).toEqual( expect.objectContaining({ id: undefined, @@ -415,4 +432,88 @@ describe('ruleRegistrySearchStrategyProvider()', () => { }) ); }); + + it('should handle Boom errors correctly', async () => { + getAuthzFilterSpy.mockRejectedValue(new Boom('boom error message', { statusCode: 400 })); + + const request: RuleRegistrySearchRequest = { + ruleTypeIds: ['.es-query'], + }; + + const options = {}; + const deps = { + request: {}, + }; + + const strategy = ruleRegistrySearchStrategyProvider(data, alerting, logger, security, spaces); + + let err; + + try { + await lastValueFrom( + strategy.search(request, options, deps as unknown as SearchStrategyDependencies) + ); + } catch (e) { + err = e; + } + + expect(err.statusCode).toBe(400); + expect(err.message).toBe('boom error message'); + }); + + it('should handle KbnSearchError errors correctly', async () => { + getAuthzFilterSpy.mockRejectedValue(new KbnSearchError('kbn search error message', 403)); + + const request: RuleRegistrySearchRequest = { + ruleTypeIds: ['.es-query'], + }; + + const options = {}; + const deps = { + request: {}, + }; + + const strategy = ruleRegistrySearchStrategyProvider(data, alerting, logger, security, spaces); + + let err; + + try { + await lastValueFrom( + strategy.search(request, options, deps as unknown as SearchStrategyDependencies) + ); + } catch (e) { + err = e; + } + + expect(err.statusCode).toBe(403); + expect(err.message).toBe('kbn search error message'); + }); + + it('should convert errors to KbnSearchError errors correctly', async () => { + getAuthzFilterSpy.mockRejectedValue(new Error('plain error message')); + + const request: RuleRegistrySearchRequest = { + ruleTypeIds: ['.es-query'], + }; + + const options = {}; + const deps = { + request: {}, + }; + + const strategy = ruleRegistrySearchStrategyProvider(data, alerting, logger, security, spaces); + + let err; + + try { + await lastValueFrom( + strategy.search(request, options, deps as unknown as SearchStrategyDependencies) + ); + } catch (e) { + err = e; + } + + expect(err.statusCode).toBe(500); + expect(err.message).toBe('plain error message'); + }); }); diff --git a/x-pack/plugins/rule_registry/server/search_strategy/search_strategy.ts b/x-pack/plugins/rule_registry/server/search_strategy/search_strategy.ts index 2f49a5a0440ef1..40bd1bbf82dcf0 100644 --- a/x-pack/plugins/rule_registry/server/search_strategy/search_strategy.ts +++ b/x-pack/plugins/rule_registry/server/search_strategy/search_strategy.ts @@ -4,6 +4,8 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ + +import Boom from '@hapi/boom'; import { map, mergeMap, catchError } from 'rxjs'; import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { Logger } from '@kbn/core/server'; @@ -20,6 +22,7 @@ import { SpacesPluginStart } from '@kbn/spaces-plugin/server'; import { buildAlertFieldsRequest } from '@kbn/alerts-as-data-utils'; import { partition } from 'lodash'; import { isSiemRuleType } from '@kbn/rule-data-utils'; +import { KbnSearchError } from '@kbn/data-plugin/server/search/report_search_error'; import type { RuleRegistrySearchRequest, RuleRegistrySearchResponse } from '../../common'; import { MAX_ALERT_SEARCH_SIZE } from '../../common/constants'; import { AlertAuditAction, alertAuditEvent } from '..'; @@ -61,8 +64,9 @@ export const ruleRegistrySearchStrategyProvider = ( ); if (isAnyRuleTypeESAuthorized && !isEachRuleTypeESAuthorized) { - throw new Error( - `The ${RULE_SEARCH_STRATEGY_NAME} search strategy is unable to accommodate requests containing multiple rule types with mixed authorization.` + throw new KbnSearchError( + `The ${RULE_SEARCH_STRATEGY_NAME} search strategy is unable to accommodate requests containing multiple rule types with mixed authorization.`, + 400 ); } @@ -135,6 +139,7 @@ export const ruleRegistrySearchStrategyProvider = ( }, }), }; + let fields = request?.fields ?? []; fields.push({ field: 'kibana.alert.*', include_unmapped: false }); @@ -192,7 +197,6 @@ export const ruleRegistrySearchStrategyProvider = ( return response; }), catchError((err) => { - // check if auth error, if yes, write to ecs logger if (securityAuditLogger != null && err?.output?.statusCode === 403) { securityAuditLogger.log( alertAuditEvent({ @@ -203,7 +207,15 @@ export const ruleRegistrySearchStrategyProvider = ( ); } - throw err; + if (Boom.isBoom(err)) { + throw new KbnSearchError(err.output.payload.message, err.output.statusCode); + } + + if (err instanceof KbnSearchError) { + throw err; + } + + throw new KbnSearchError(err.message, 500); }) ); }, diff --git a/x-pack/test/common/services/bsearch_secure.ts b/x-pack/test/common/services/bsearch_secure.ts index 01050d1bb60c02..90a39201e276ff 100644 --- a/x-pack/test/common/services/bsearch_secure.ts +++ b/x-pack/test/common/services/bsearch_secure.ts @@ -52,10 +52,12 @@ export class BsearchSecureService extends FtrService { space, }: SendOptions) { const spaceUrl = getSpaceUrlPrefix(space); + const statusesWithoutRetry = [200, 400, 403, 500]; const { body } = await this.retry.try(async () => { let result; const url = `${spaceUrl}/internal/search/${strategy}`; + if (referer && kibanaVersion) { result = await supertestWithoutAuth .post(url) @@ -97,9 +99,11 @@ export class BsearchSecureService extends FtrService { .set('kbn-xsrf', 'true') .send(options); } - if ((result.status === 500 || result.status === 200) && result.body) { + + if (statusesWithoutRetry.includes(result.status) && result.body) { return result; } + throw new Error('try again'); }); diff --git a/x-pack/test/rule_registry/security_and_spaces/tests/basic/search_strategy.ts b/x-pack/test/rule_registry/security_and_spaces/tests/basic/search_strategy.ts index 7e8c5b312e6f42..b88e34e5455e48 100644 --- a/x-pack/test/rule_registry/security_and_spaces/tests/basic/search_strategy.ts +++ b/x-pack/test/rule_registry/security_and_spaces/tests/basic/search_strategy.ts @@ -156,7 +156,7 @@ export default ({ getService }: FtrProviderContext) => { strategy: 'privateRuleRegistryAlertsSearchStrategy', }); - expect(result.statusCode).to.be(500); + expect(result.statusCode).to.be(400); expect(result.message).to.be( 'The privateRuleRegistryAlertsSearchStrategy search strategy is unable to accommodate requests containing multiple rule types with mixed authorization.' ); @@ -231,7 +231,7 @@ export default ({ getService }: FtrProviderContext) => { validateRuleTypeIds(result, apmRuleTypeIds); }); - it('should not by pass our RBAC authz filter with a should filter', async () => { + it('should not by pass our RBAC authz filter with a should filter for rule type ids', async () => { const result = await secureBsearch.send({ supertestWithoutAuth, auth: { @@ -274,7 +274,50 @@ export default ({ getService }: FtrProviderContext) => { validateRuleTypeIds(result, apmRuleTypeIds); }); - it('should return an empty response with must filter and our RBAC authz filter', async () => { + it('should not by pass our RBAC authz filter with a should filter for consumers', async () => { + const result = await secureBsearch.send({ + supertestWithoutAuth, + auth: { + username: obsOnlySpacesAll.username, + password: obsOnlySpacesAll.password, + }, + referer: 'test', + kibanaVersion, + internalOrigin: 'Kibana', + options: { + ruleTypeIds: apmRuleTypeIds, + query: { + bool: { + filter: [], + should: [ + { + bool: { + should: [ + { + match: { + 'kibana.alert.rule.consumer': 'logs', + }, + }, + ], + minimum_should_match: 1, + }, + }, + ], + must: [], + must_not: [], + }, + }, + }, + strategy: 'privateRuleRegistryAlertsSearchStrategy', + space: 'default', + }); + + expect(result.rawResponse.hits.total).to.eql(9); + + validateRuleTypeIds(result, apmRuleTypeIds); + }); + + it('should return an empty response with must filter and our RBAC authz filter for rule type ids', async () => { const result = await secureBsearch.send({ supertestWithoutAuth, auth: { @@ -315,7 +358,48 @@ export default ({ getService }: FtrProviderContext) => { expect(result.rawResponse.hits.total).to.eql(0); }); - it('should not by pass our RBAC authz filter with must_not filter', async () => { + it('should return an empty response with must filter and our RBAC authz filter for consumers', async () => { + const result = await secureBsearch.send({ + supertestWithoutAuth, + auth: { + username: obsOnlySpacesAll.username, + password: obsOnlySpacesAll.password, + }, + referer: 'test', + kibanaVersion, + internalOrigin: 'Kibana', + options: { + ruleTypeIds: apmRuleTypeIds, + query: { + bool: { + filter: [], + must: [ + { + bool: { + should: [ + { + match: { + 'kibana.alert.rule.consumer': 'logs', + }, + }, + ], + minimum_should_match: 1, + }, + }, + ], + should: [], + must_not: [], + }, + }, + }, + strategy: 'privateRuleRegistryAlertsSearchStrategy', + space: 'default', + }); + + expect(result.rawResponse.hits.total).to.eql(0); + }); + + it('should not by pass our RBAC authz filter with must_not filter for rule type ids', async () => { const result = await secureBsearch.send({ supertestWithoutAuth, auth: { @@ -341,6 +425,49 @@ export default ({ getService }: FtrProviderContext) => { }, })), ], + minimum_should_match: apmRuleTypeIds.length, + }, + }, + ], + should: [], + }, + }, + }, + strategy: 'privateRuleRegistryAlertsSearchStrategy', + space: 'default', + }); + + expect(result.rawResponse.hits.total).to.eql(9); + + validateRuleTypeIds(result, apmRuleTypeIds); + }); + + it('should not by pass our RBAC authz filter with must_not filter for consumers', async () => { + const result = await secureBsearch.send({ + supertestWithoutAuth, + auth: { + username: obsOnlySpacesAll.username, + password: obsOnlySpacesAll.password, + }, + referer: 'test', + kibanaVersion, + internalOrigin: 'Kibana', + options: { + ruleTypeIds: apmRuleTypeIds, + query: { + bool: { + filter: [], + must: [], + must_not: [ + { + bool: { + should: [ + { + match: { + 'kibana.alert.rule.consumer': 'apm', + }, + }, + ], minimum_should_match: 1, }, }, @@ -357,6 +484,91 @@ export default ({ getService }: FtrProviderContext) => { validateRuleTypeIds(result, apmRuleTypeIds); }); + + it('should return 403 if the user does not have access to any alerts', async () => { + const result = await secureBsearch.send({ + supertestWithoutAuth, + auth: { + username: obsOnlySpacesAll.username, + password: obsOnlySpacesAll.password, + }, + referer: 'test', + kibanaVersion, + internalOrigin: 'Kibana', + options: { + ruleTypeIds: ['metrics.alert.threshold', 'metrics.alert.inventory.threshold'], + }, + strategy: 'privateRuleRegistryAlertsSearchStrategy', + space: 'default', + }); + + expect(result.statusCode).to.eql(403); + expect(result.message).to.eql('Unauthorized to find alerts for any rule types'); + }); + + it('should not return alerts that the user does not have access to', async () => { + const result = await secureBsearch.send({ + supertestWithoutAuth, + auth: { + username: obsOnlySpacesAll.username, + password: obsOnlySpacesAll.password, + }, + referer: 'test', + kibanaVersion, + internalOrigin: 'Kibana', + options: { + ruleTypeIds: ['metrics.alert.threshold', 'logs.alert.document.count'], + }, + strategy: 'privateRuleRegistryAlertsSearchStrategy', + space: 'default', + }); + + expect(result.rawResponse.hits.total).to.eql(5); + validateRuleTypeIds(result, ['logs.alert.document.count']); + }); + + it('should not return alerts if the user does not have access to using a filter', async () => { + const result = await secureBsearch.send({ + supertestWithoutAuth, + auth: { + username: obsOnlySpacesAll.username, + password: obsOnlySpacesAll.password, + }, + referer: 'test', + kibanaVersion, + internalOrigin: 'Kibana', + options: { + ruleTypeIds: apmRuleTypeIds, + query: { + bool: { + filter: [], + should: [ + { + bool: { + should: [ + { + match: { + 'kibana.alert.rule.rule_type_id': 'metrics.alert.inventory.threshold', + }, + }, + ], + minimum_should_match: 1, + }, + }, + ], + must: [], + must_not: [], + }, + }, + }, + strategy: 'privateRuleRegistryAlertsSearchStrategy', + space: 'default', + }); + + expect(result.rawResponse.hits.total).to.eql(9); + + validateRuleTypeIds(result, apmRuleTypeIds); + }); }); describe('empty response', () => { From 885d1584378b0ac7637ec921100d7f216d517f33 Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Sun, 4 Aug 2024 15:10:31 +0300 Subject: [PATCH 051/106] Fix search strategy integration tests --- .../src/rule_types/o11y_rules.ts | 1 + .../server/alert_data_client/alerts_client.ts | 1 + .../tests/basic/bulk_update_alerts.ts | 3 --- .../basic/get_aad_fields_by_rule_type.ts | 4 ++++ .../get_browser_fields_by_rule_type_ids.ts | 19 +++++++------------ .../tests/basic/search_strategy.ts | 2 +- .../tests/basic/update_alert.ts | 1 - .../tests/trial/update_alert.ts | 2 ++ .../spaces_only/tests/trial/update_alert.ts | 1 - 9 files changed, 16 insertions(+), 18 deletions(-) diff --git a/packages/kbn-rule-data-utils/src/rule_types/o11y_rules.ts b/packages/kbn-rule-data-utils/src/rule_types/o11y_rules.ts index 9637562c43a702..c0a4209ab64bc9 100644 --- a/packages/kbn-rule-data-utils/src/rule_types/o11y_rules.ts +++ b/packages/kbn-rule-data-utils/src/rule_types/o11y_rules.ts @@ -82,4 +82,5 @@ export const OBSERVABILITY_RULE_TYPE_IDS = [ ...UPTIME_RULE_TYPE_IDS, ...LOG_RULE_TYPE_IDS, ...SLO_RULE_TYPE_IDS, + OBSERVABILITY_THRESHOLD_RULE_TYPE_ID, ]; diff --git a/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts b/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts index 1ae937925d875a..412047ee1dfbb8 100644 --- a/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts +++ b/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts @@ -1183,6 +1183,7 @@ export class AlertsClient { }); } } + const { fields } = await indexPatternsFetcherAsInternalUser.getFieldsForWildcard({ pattern: indices, metaFields, diff --git a/x-pack/test/rule_registry/security_and_spaces/tests/basic/bulk_update_alerts.ts b/x-pack/test/rule_registry/security_and_spaces/tests/basic/bulk_update_alerts.ts index 68feb371373976..e54af674f6572e 100644 --- a/x-pack/test/rule_registry/security_and_spaces/tests/basic/bulk_update_alerts.ts +++ b/x-pack/test/rule_registry/security_and_spaces/tests/basic/bulk_update_alerts.ts @@ -102,7 +102,6 @@ export default ({ getService }: FtrProviderContext) => { function addTests({ space, authorizedUsers, unauthorizedUsers, alertId, index }: TestCase) { authorizedUsers.forEach(({ username, password }) => { it(`${username} should bulk update alert with given id ${alertId} in ${space}/${index}`, async () => { - await esArchiver.load('x-pack/test/functional/es_archives/rule_registry/alerts'); // since this is a success case, reload the test data immediately beforehand const { body: updated } = await supertestWithoutAuth .post(`${getSpaceUrlPrefix(space)}${TEST_URL}/bulk_update`) .auth(username, password) @@ -119,7 +118,6 @@ export default ({ getService }: FtrProviderContext) => { }); it(`${username} should bulk update alerts which match KQL query string in ${space}/${index}`, async () => { - await esArchiver.load('x-pack/test/functional/es_archives/rule_registry/alerts'); // since this is a success case, reload the test data immediately beforehand const { body: updated } = await supertestWithoutAuth .post(`${getSpaceUrlPrefix(space)}${TEST_URL}/bulk_update`) .auth(username, password) @@ -134,7 +132,6 @@ export default ({ getService }: FtrProviderContext) => { }); it(`${username} should bulk update alerts which match query in DSL in ${space}/${index}`, async () => { - await esArchiver.load('x-pack/test/functional/es_archives/rule_registry/alerts'); // since this is a success case, reload the test data immediately beforehand const { body: updated } = await supertestWithoutAuth .post(`${getSpaceUrlPrefix(space)}${TEST_URL}/bulk_update`) .auth(username, password) diff --git a/x-pack/test/rule_registry/security_and_spaces/tests/basic/get_aad_fields_by_rule_type.ts b/x-pack/test/rule_registry/security_and_spaces/tests/basic/get_aad_fields_by_rule_type.ts index 4d8fed02a7c71c..776400a988a054 100644 --- a/x-pack/test/rule_registry/security_and_spaces/tests/basic/get_aad_fields_by_rule_type.ts +++ b/x-pack/test/rule_registry/security_and_spaces/tests/basic/get_aad_fields_by_rule_type.ts @@ -38,6 +38,10 @@ export default ({ getService }: FtrProviderContext) => { await esArchiver.load('x-pack/test/functional/es_archives/rule_registry/alerts'); }); + after(async () => { + await esArchiver.unload('x-pack/test/functional/es_archives/rule_registry/alerts'); + }); + describe('Users:', () => { it(`${obsOnlySpacesAll.username} should be able to get browser fields for o11y featureIds`, async () => { await retry.try(async () => { diff --git a/x-pack/test/rule_registry/security_and_spaces/tests/basic/get_browser_fields_by_rule_type_ids.ts b/x-pack/test/rule_registry/security_and_spaces/tests/basic/get_browser_fields_by_rule_type_ids.ts index bf5339606914b0..85609f562ff79a 100644 --- a/x-pack/test/rule_registry/security_and_spaces/tests/basic/get_browser_fields_by_rule_type_ids.ts +++ b/x-pack/test/rule_registry/security_and_spaces/tests/basic/get_browser_fields_by_rule_type_ids.ts @@ -6,12 +6,7 @@ */ import expect from 'expect'; -import { - APM_RULE_TYPE_IDS, - UPTIME_RULE_TYPE_IDS, - INFRA_RULE_TYPE_IDS, - LOG_RULE_TYPE_IDS, -} from '@kbn/rule-data-utils'; +import { OBSERVABILITY_RULE_TYPE_IDS } from '@kbn/rule-data-utils'; import { superUser, obsOnlySpacesAll, secOnlyRead } from '../../../common/lib/authentication/users'; import type { User } from '../../../common/lib/authentication/types'; import { FtrProviderContext } from '../../../common/ftr_provider_context'; @@ -41,10 +36,9 @@ export default ({ getService }: FtrProviderContext) => { describe('Alert - Get browser fields by rule type IDs', () => { const ruleTypeIds = [ - ...APM_RULE_TYPE_IDS, - ...UPTIME_RULE_TYPE_IDS, - ...INFRA_RULE_TYPE_IDS, - ...LOG_RULE_TYPE_IDS, + ...OBSERVABILITY_RULE_TYPE_IDS, + '.es-query', + 'xpack.ml.anomaly_detection_alert', ]; before(async () => { @@ -56,7 +50,7 @@ export default ({ getService }: FtrProviderContext) => { }); describe('Users:', () => { - it(`${obsOnlySpacesAll.username} should be able to get browser fields for o11y ruleTypeIds`, async () => { + it(`${obsOnlySpacesAll.username} should be able to get browser fields for o11y ruleTypeIds that has access to`, async () => { const resp = await getBrowserFieldsByFeatureId(obsOnlySpacesAll, ruleTypeIds); expect(Object.keys(resp.browserFields)).toEqual([ @@ -74,7 +68,7 @@ export default ({ getService }: FtrProviderContext) => { ]); }); - it(`${superUser.username} should be able to get browser fields for o11y ruleTypeIds`, async () => { + it(`${superUser.username} should be able to get browser fields for all o11y ruleTypeIds`, async () => { const resp = await getBrowserFieldsByFeatureId(superUser, ruleTypeIds); expect(Object.keys(resp.browserFields)).toEqual([ @@ -90,6 +84,7 @@ export default ({ getService }: FtrProviderContext) => { 'monitor', 'observer', 'orchestrator', + 'slo', 'tls', 'url', ]); diff --git a/x-pack/test/rule_registry/security_and_spaces/tests/basic/search_strategy.ts b/x-pack/test/rule_registry/security_and_spaces/tests/basic/search_strategy.ts index b88e34e5455e48..9eb190325bc441 100644 --- a/x-pack/test/rule_registry/security_and_spaces/tests/basic/search_strategy.ts +++ b/x-pack/test/rule_registry/security_and_spaces/tests/basic/search_strategy.ts @@ -113,10 +113,10 @@ export default ({ getService }: FtrProviderContext) => { }); after(async () => { + await esArchiver.unload('x-pack/test/functional/es_archives/observability/alerts'); await esArchiver.unload( 'x-pack/test/functional/es_archives/security_solution/alerts/8.1.0' ); - await esArchiver.unload('x-pack/test/functional/es_archives/observability/alerts'); }); it('should return alerts from siem rules', async () => { diff --git a/x-pack/test/rule_registry/security_and_spaces/tests/basic/update_alert.ts b/x-pack/test/rule_registry/security_and_spaces/tests/basic/update_alert.ts index 4d7607442fbcb4..237f492ebf3638 100644 --- a/x-pack/test/rule_registry/security_and_spaces/tests/basic/update_alert.ts +++ b/x-pack/test/rule_registry/security_and_spaces/tests/basic/update_alert.ts @@ -101,7 +101,6 @@ export default ({ getService }: FtrProviderContext) => { function addTests({ space, authorizedUsers, unauthorizedUsers, alertId, index }: TestCase) { authorizedUsers.forEach(({ username, password }) => { it(`${username} should be able to update alert ${alertId} in ${space}/${index}`, async () => { - await esArchiver.load('x-pack/test/functional/es_archives/rule_registry/alerts'); // since this is a success case, reload the test data immediately beforehand await supertestWithoutAuth .post(`${getSpaceUrlPrefix(space)}${TEST_URL}`) .auth(username, password) diff --git a/x-pack/test/rule_registry/security_and_spaces/tests/trial/update_alert.ts b/x-pack/test/rule_registry/security_and_spaces/tests/trial/update_alert.ts index 9b4e4b70d59c82..0de2adbf0f57f2 100644 --- a/x-pack/test/rule_registry/security_and_spaces/tests/trial/update_alert.ts +++ b/x-pack/test/rule_registry/security_and_spaces/tests/trial/update_alert.ts @@ -46,9 +46,11 @@ export default ({ getService }: FtrProviderContext) => { beforeEach(async () => { await esArchiver.load('x-pack/test/functional/es_archives/rule_registry/alerts'); }); + afterEach(async () => { await esArchiver.unload('x-pack/test/functional/es_archives/rule_registry/alerts'); }); + it(`${superUser.username} should be able to update the APM alert in ${SPACE1}`, async () => { const apmIndex = await getAPMIndexName(superUser); await supertestWithoutAuth diff --git a/x-pack/test/rule_registry/spaces_only/tests/trial/update_alert.ts b/x-pack/test/rule_registry/spaces_only/tests/trial/update_alert.ts index 31c3cfdecb9eea..2fe7ff9dac0c43 100644 --- a/x-pack/test/rule_registry/spaces_only/tests/trial/update_alert.ts +++ b/x-pack/test/rule_registry/spaces_only/tests/trial/update_alert.ts @@ -90,7 +90,6 @@ export default ({ getService }: FtrProviderContext) => { }); it(`${superUser.username} should be able to update alert ${APM_ALERT_ID} in ${SPACE2}/${APM_ALERT_INDEX}`, async () => { - await esArchiver.load('x-pack/test/functional/es_archives/rule_registry/alerts'); // since this is a success case, reload the test data immediately beforehand await supertestWithoutAuth .post(`${getSpaceUrlPrefix(SPACE2)}${TEST_URL}`) .set('kbn-xsrf', 'true') From 01fa579a98fc92702969473b3e27902afd1de1e4 Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Tue, 17 Sep 2024 15:57:03 +0300 Subject: [PATCH 052/106] Fix tests and types --- .../alert_filter_controls.test.tsx | 3 +-- .../fetch_alerts_index_names.test.ts | 7 +++---- .../hooks/use_alerts_data_view.test.tsx | 20 ++++++------------- ...se_fetch_alerts_index_names_query.test.tsx | 15 ++++++++------ .../src/hooks/use_alerts_history.test.tsx | 4 ++-- .../components/case_view_alerts.test.tsx | 5 +++-- .../tests/find_alerts.test.ts | 6 +++--- .../get_alerts_group_aggregations.test.ts | 2 +- 8 files changed, 28 insertions(+), 34 deletions(-) diff --git a/packages/kbn-alerts-ui-shared/src/alert_filter_controls/alert_filter_controls.test.tsx b/packages/kbn-alerts-ui-shared/src/alert_filter_controls/alert_filter_controls.test.tsx index 3c314c62fc28cb..6c35234b54006c 100644 --- a/packages/kbn-alerts-ui-shared/src/alert_filter_controls/alert_filter_controls.test.tsx +++ b/packages/kbn-alerts-ui-shared/src/alert_filter_controls/alert_filter_controls.test.tsx @@ -10,7 +10,6 @@ import React from 'react'; import { render, screen } from '@testing-library/react'; import { AlertFilterControls, AlertFilterControlsProps } from './alert_filter_controls'; -import { AlertConsumers } from '@kbn/rule-data-utils'; import { DEFAULT_CONTROLS } from './constants'; import { useAlertsDataView } from '../common/hooks/use_alerts_data_view'; import { FilterGroup } from './filter_group'; @@ -56,7 +55,7 @@ const ControlGroupRenderer = (() => ( describe('AlertFilterControls', () => { const props: AlertFilterControlsProps = { - featureIds: [AlertConsumers.STACK_ALERTS], + ruleTypeIds: ['.es-query'], defaultControls: DEFAULT_CONTROLS, dataViewSpec: { id: 'alerts-filters-dv', diff --git a/packages/kbn-alerts-ui-shared/src/common/apis/fetch_alerts_index_names/fetch_alerts_index_names.test.ts b/packages/kbn-alerts-ui-shared/src/common/apis/fetch_alerts_index_names/fetch_alerts_index_names.test.ts index 7ba85e4978e73e..17af39ff50ad10 100644 --- a/packages/kbn-alerts-ui-shared/src/common/apis/fetch_alerts_index_names/fetch_alerts_index_names.test.ts +++ b/packages/kbn-alerts-ui-shared/src/common/apis/fetch_alerts_index_names/fetch_alerts_index_names.test.ts @@ -9,22 +9,21 @@ import { httpServiceMock } from '@kbn/core/public/mocks'; import { fetchAlertsIndexNames } from '.'; -import { AlertConsumers } from '@kbn/rule-data-utils'; import { BASE_RAC_ALERTS_API_PATH } from '../../constants'; describe('fetchAlertsIndexNames', () => { const http = httpServiceMock.createStartContract(); it('calls the alerts/index API with the correct parameters', async () => { - const featureIds = [AlertConsumers.STACK_ALERTS, AlertConsumers.APM]; + const ruleTypeIds = ['.es-query']; const indexNames = ['test-index']; http.get.mockResolvedValueOnce({ index_name: indexNames, }); - const result = await fetchAlertsIndexNames({ http, featureIds }); + const result = await fetchAlertsIndexNames({ http, ruleTypeIds }); expect(result).toEqual(indexNames); expect(http.get).toHaveBeenLastCalledWith(`${BASE_RAC_ALERTS_API_PATH}/index`, { - query: { features: featureIds.join(',') }, + query: { ruleTypeIds }, }); }); }); diff --git a/packages/kbn-alerts-ui-shared/src/common/hooks/use_alerts_data_view.test.tsx b/packages/kbn-alerts-ui-shared/src/common/hooks/use_alerts_data_view.test.tsx index 2f4e8598a4cf60..458a17d2eeb83d 100644 --- a/packages/kbn-alerts-ui-shared/src/common/hooks/use_alerts_data_view.test.tsx +++ b/packages/kbn-alerts-ui-shared/src/common/hooks/use_alerts_data_view.test.tsx @@ -8,7 +8,6 @@ */ import React from 'react'; -import { AlertConsumers } from '@kbn/rule-data-utils'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { renderHook } from '@testing-library/react-hooks/dom'; import { DataView } from '@kbn/data-views-plugin/common'; @@ -51,13 +50,6 @@ const wrapper: React.FC> = ({ children }) => ( ); describe('useAlertsDataView', () => { - const observabilityFeatureIds = [ - AlertConsumers.APM, - AlertConsumers.INFRASTRUCTURE, - AlertConsumers.LOGS, - AlertConsumers.UPTIME, - ]; - beforeEach(() => { jest.clearAllMocks(); queryClient.clear(); @@ -73,7 +65,7 @@ describe('useAlertsDataView', () => { () => useAlertsDataView({ ...mockServices, - featureIds: observabilityFeatureIds, + ruleTypeIds: ['apm'], }), { wrapper, @@ -88,7 +80,7 @@ describe('useAlertsDataView', () => { () => useAlertsDataView({ ...mockServices, - featureIds: observabilityFeatureIds, + ruleTypeIds: ['apm, .es-query'], }), { wrapper, @@ -104,7 +96,7 @@ describe('useAlertsDataView', () => { it('only fetches index names for the siem feature id, returning a DataView', async () => { const { result, waitFor } = renderHook( - () => useAlertsDataView({ ...mockServices, featureIds: [AlertConsumers.SIEM] }), + () => useAlertsDataView({ ...mockServices, ruleTypeIds: ['siem.esqlRule', 'siem.eqlRule'] }), { wrapper, } @@ -121,7 +113,7 @@ describe('useAlertsDataView', () => { () => useAlertsDataView({ ...mockServices, - featureIds: [AlertConsumers.SIEM, AlertConsumers.LOGS], + ruleTypeIds: ['siem.esqlRule', 'apm', 'logs'], }), { wrapper, @@ -142,7 +134,7 @@ describe('useAlertsDataView', () => { mockFetchAlertsIndexNames.mockRejectedValue('error'); const { result, waitFor } = renderHook( - () => useAlertsDataView({ ...mockServices, featureIds: observabilityFeatureIds }), + () => useAlertsDataView({ ...mockServices, ruleTypeIds: ['.es-query'] }), { wrapper, } @@ -160,7 +152,7 @@ describe('useAlertsDataView', () => { mockFetchAlertsIndexNames.mockRejectedValue('error'); const { waitFor } = renderHook( - () => useAlertsDataView({ ...mockServices, featureIds: observabilityFeatureIds }), + () => useAlertsDataView({ ...mockServices, ruleTypeIds: ['.es-query'] }), { wrapper, } diff --git a/packages/kbn-alerts-ui-shared/src/common/hooks/use_fetch_alerts_index_names_query.test.tsx b/packages/kbn-alerts-ui-shared/src/common/hooks/use_fetch_alerts_index_names_query.test.tsx index ab702a2ea09ec2..810a1653d88acb 100644 --- a/packages/kbn-alerts-ui-shared/src/common/hooks/use_fetch_alerts_index_names_query.test.tsx +++ b/packages/kbn-alerts-ui-shared/src/common/hooks/use_fetch_alerts_index_names_query.test.tsx @@ -37,7 +37,7 @@ describe('useFetchAlertsIndexNamesQuery', () => { }); it('does not fetch if featureIds is empty', () => { - renderHook(() => useFetchAlertsIndexNamesQuery({ http: mockHttpClient, featureIds: [] }), { + renderHook(() => useFetchAlertsIndexNamesQuery({ http: mockHttpClient, ruleTypeIds: [] }), { wrapper, }); @@ -45,19 +45,22 @@ describe('useFetchAlertsIndexNamesQuery', () => { }); it('calls fetchAlertsIndexNames with the correct parameters', () => { - renderHook(() => useFetchAlertsIndexNamesQuery({ http: mockHttpClient, featureIds: ['apm'] }), { - wrapper, - }); + renderHook( + () => useFetchAlertsIndexNamesQuery({ http: mockHttpClient, ruleTypeIds: ['apm'] }), + { + wrapper, + } + ); expect(mockFetchAlertsIndexNames).toHaveBeenCalledWith({ http: mockHttpClient, - featureIds: ['apm'], + ruleTypeIds: ['apm'], }); }); it('correctly caches the index names', async () => { const { result, rerender, waitForValueToChange } = renderHook( - () => useFetchAlertsIndexNamesQuery({ http: mockHttpClient, featureIds: ['apm'] }), + () => useFetchAlertsIndexNamesQuery({ http: mockHttpClient, ruleTypeIds: ['apm'] }), { wrapper, } diff --git a/x-pack/packages/observability/alert_details/src/hooks/use_alerts_history.test.tsx b/x-pack/packages/observability/alert_details/src/hooks/use_alerts_history.test.tsx index 9081b497736b9b..12b398c9321b2b 100644 --- a/x-pack/packages/observability/alert_details/src/hooks/use_alerts_history.test.tsx +++ b/x-pack/packages/observability/alert_details/src/hooks/use_alerts_history.test.tsx @@ -188,7 +188,7 @@ describe('useAlertsHistory', () => { }); expect(mockedHttpPost).toBeCalledWith('/internal/rac/alerts/find', { body: - '{"size":0,"feature_ids":["apm"],"query":{"bool":{"must":[' + + '{"size":0,"rule_type_ids":["apm"],"query":{"bool":{"must":[' + '{"term":{"kibana.alert.rule.uuid":"cfd36e60-ef22-11ed-91eb-b7893acacfe2"}},' + '{"term":{"kibana.alert.instance.id":"instance-1"}},' + '{"range":{"kibana.alert.time_range":{"from":"2023-04-10T00:00:00.000Z","to":"2023-05-10T00:00:00.000Z"}}}]}},' + @@ -237,7 +237,7 @@ describe('useAlertsHistory', () => { }); expect(mockedHttpPost).toBeCalledWith('/internal/rac/alerts/find', { body: - '{"size":0,"feature_ids":["apm"],"query":{"bool":{"must":[' + + '{"size":0,"rule_type_ids":["apm"],"query":{"bool":{"must":[' + '{"term":{"kibana.alert.rule.uuid":"cfd36e60-ef22-11ed-91eb-b7893acacfe2"}},' + '{"range":{"kibana.alert.time_range":{"from":"2023-04-10T00:00:00.000Z","to":"2023-05-10T00:00:00.000Z"}}}]}},' + '"aggs":{"histogramTriggeredAlerts":{"date_histogram":{"field":"kibana.alert.start","fixed_interval":"1d",' + diff --git a/x-pack/plugins/cases/public/components/case_view/components/case_view_alerts.test.tsx b/x-pack/plugins/cases/public/components/case_view/components/case_view_alerts.test.tsx index a4cc4c751eba69..c6bad3b2bf7357 100644 --- a/x-pack/plugins/cases/public/components/case_view/components/case_view_alerts.test.tsx +++ b/x-pack/plugins/cases/public/components/case_view/components/case_view_alerts.test.tsx @@ -15,6 +15,7 @@ import type { CaseUI } from '../../../../common'; import { CaseViewAlerts } from './case_view_alerts'; import * as api from '../../../containers/api'; import type { FeatureIdsResponse } from '../../../containers/types'; +import { SECURITY_SOLUTION_RULE_TYPE_IDS } from '@kbn/securitysolution-rules'; jest.mock('../../../containers/api'); @@ -54,7 +55,7 @@ describe('CaseUI View Page activity tab', () => { expect(getAlertsStateTableMock).toHaveBeenCalledWith({ alertsTableConfigurationRegistry: expect.anything(), configurationId: 'securitySolution-case', - ruleTypeIds: ['siem'], + ruleTypeIds: SECURITY_SOLUTION_RULE_TYPE_IDS, id: 'case-details-alerts-securitySolution', query: { ids: { @@ -88,7 +89,7 @@ describe('CaseUI View Page activity tab', () => { expect(getAlertsStateTableMock).toHaveBeenCalledWith({ alertsTableConfigurationRegistry: expect.anything(), configurationId: 'case-details-alerts-observability', - ruleTypeIds: ['observability'], + ruleTypeIds: ['log-threshold'], id: 'case-details-alerts-observability', query: { ids: { diff --git a/x-pack/plugins/rule_registry/server/alert_data_client/tests/find_alerts.test.ts b/x-pack/plugins/rule_registry/server/alert_data_client/tests/find_alerts.test.ts index a13b7ee8e3da74..08fd08716a22f2 100644 --- a/x-pack/plugins/rule_registry/server/alert_data_client/tests/find_alerts.test.ts +++ b/x-pack/plugins/rule_registry/server/alert_data_client/tests/find_alerts.test.ts @@ -108,17 +108,17 @@ describe('find()', () => { }); const query = { match: { [ALERT_WORKFLOW_STATUS]: 'open' } }; const index = '.alerts-observability.apm.alerts'; - const featureIds = ['siem']; + const ruleTypeIds = ['siem.esqlRule', 'siem.eqlRule']; const result = await alertsClient.find({ query, index, - featureIds, + ruleTypeIds, }); expect(searchAlertsSpy).toHaveBeenCalledWith( expect.objectContaining({ query, index, - featureIds, + ruleTypeIds, }) ); expect(result).toMatchInlineSnapshot(` diff --git a/x-pack/plugins/rule_registry/server/alert_data_client/tests/get_alerts_group_aggregations.test.ts b/x-pack/plugins/rule_registry/server/alert_data_client/tests/get_alerts_group_aggregations.test.ts index ba0c602cbfc255..fb539ed7cee49d 100644 --- a/x-pack/plugins/rule_registry/server/alert_data_client/tests/get_alerts_group_aggregations.test.ts +++ b/x-pack/plugins/rule_registry/server/alert_data_client/tests/get_alerts_group_aggregations.test.ts @@ -154,7 +154,7 @@ describe('getGroupAggregations()', () => { }); const result = await alertsClient.getGroupAggregations({ - featureIds: [AlertConsumers.STACK_ALERTS], + ruleTypeIds: ['.es-query'], groupByField: 'kibana.alert.rule.name', aggregations: {}, filters: [], From 9389991ee749a15792409b0bd4ce76daa957bf7b Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Wed, 18 Sep 2024 17:41:34 +0300 Subject: [PATCH 053/106] Fix types and unit tests --- .../src/mocks/grouping_props.mock.tsx | 3 +-- .../src/mocks/grouping_query.mock.ts | 2 +- .../src/common/hooks/use_alerts_data_view.test.tsx | 1 + .../src/common/hooks/use_alerts_data_view.ts | 3 ++- .../kbn-rule-data-utils/src/alerts_as_data_rbac.ts | 1 + src/plugins/data_views/public/mocks.ts | 1 + .../maintenance_window_scoped_query.test.tsx | 6 +++--- x-pack/plugins/cases/common/constants/owners.ts | 8 +++++++- .../components/system_actions/cases/cases_params.tsx | 7 ++----- .../alerts/get_alerts_page_table_configuration.tsx | 10 +++------- .../alerts_table/alerts/get_persistent_controls.ts | 7 +++---- .../observability/public/pages/alerts/alerts.tsx | 4 ++-- .../monitor_alerts/monitor_detail_alerts.tsx | 9 +++++++-- .../routes/default_alerts/default_alert_service.ts | 4 ++-- .../observability_solution/synthetics/server/types.ts | 11 ++++------- .../application/sections/alerts_table/constants.ts | 5 +++++ .../hooks/use_columns/use_columns.test.tsx | 4 ++-- .../group1/tests/alerting/bulk_untrack_by_query.ts | 2 +- 18 files changed, 48 insertions(+), 40 deletions(-) diff --git a/packages/kbn-alerts-grouping/src/mocks/grouping_props.mock.tsx b/packages/kbn-alerts-grouping/src/mocks/grouping_props.mock.tsx index d41eea48dd139f..f891e2e10c1a78 100644 --- a/packages/kbn-alerts-grouping/src/mocks/grouping_props.mock.tsx +++ b/packages/kbn-alerts-grouping/src/mocks/grouping_props.mock.tsx @@ -8,12 +8,11 @@ */ import React from 'react'; -import { AlertConsumers } from '@kbn/rule-data-utils'; import { AlertsGroupingProps } from '../types'; export const mockGroupingId = 'test'; -export const mockRuleTypeIds = [AlertConsumers.STACK_ALERTS]; +export const mockRuleTypeIds = ['.es-query']; export const mockDate = { from: '2020-07-07T08:20:18.966Z', diff --git a/packages/kbn-alerts-grouping/src/mocks/grouping_query.mock.ts b/packages/kbn-alerts-grouping/src/mocks/grouping_query.mock.ts index da923f538ebb13..486771e70a140c 100644 --- a/packages/kbn-alerts-grouping/src/mocks/grouping_query.mock.ts +++ b/packages/kbn-alerts-grouping/src/mocks/grouping_query.mock.ts @@ -52,7 +52,7 @@ export const getQuery = ({ }, }, }, - feature_ids: ruleTypeIds, + rule_type_ids: ruleTypeIds, query: { bool: { filter: [ diff --git a/packages/kbn-alerts-ui-shared/src/common/hooks/use_alerts_data_view.test.tsx b/packages/kbn-alerts-ui-shared/src/common/hooks/use_alerts_data_view.test.tsx index 458a17d2eeb83d..c1c45cfb838fea 100644 --- a/packages/kbn-alerts-ui-shared/src/common/hooks/use_alerts_data_view.test.tsx +++ b/packages/kbn-alerts-ui-shared/src/common/hooks/use_alerts_data_view.test.tsx @@ -41,6 +41,7 @@ const mockServices = { toasts: notificationServiceMock.createStartContract().toasts, dataViewsService: dataViewPluginMocks.createStartContract(), }; + mockServices.dataViewsService.create.mockResolvedValue(mockDataView); const queryClient = new QueryClient(testQueryClientConfig); diff --git a/packages/kbn-alerts-ui-shared/src/common/hooks/use_alerts_data_view.ts b/packages/kbn-alerts-ui-shared/src/common/hooks/use_alerts_data_view.ts index ad09e77442992c..bcd821b76608eb 100644 --- a/packages/kbn-alerts-ui-shared/src/common/hooks/use_alerts_data_view.ts +++ b/packages/kbn-alerts-ui-shared/src/common/hooks/use_alerts_data_view.ts @@ -97,7 +97,7 @@ export const useAlertsDataView = ({ }: UseAlertsDataViewParams): UseAlertsDataViewResult => { const includesSecurity = ruleTypeIds.some(isSiemRuleType); const isOnlySecurity = ruleTypeIds.every(isSiemRuleType); - const hasMixedFeatureIds = !isOnlySecurity; + const hasMixedFeatureIds = !isOnlySecurity && includesSecurity; const { data: indexNames, @@ -180,6 +180,7 @@ export const useAlertsDataView = ({ isLoadingFields; } } + return { dataView, isLoading, diff --git a/packages/kbn-rule-data-utils/src/alerts_as_data_rbac.ts b/packages/kbn-rule-data-utils/src/alerts_as_data_rbac.ts index 97154b43d32f18..a1dc1459cc4e0d 100644 --- a/packages/kbn-rule-data-utils/src/alerts_as_data_rbac.ts +++ b/packages/kbn-rule-data-utils/src/alerts_as_data_rbac.ts @@ -29,6 +29,7 @@ export const AlertConsumers = { EXAMPLE: 'AlertingExample', MONITORING: 'monitoring', ALERTS: 'alerts', + DISCOVER: 'discover', } as const; export type AlertConsumers = (typeof AlertConsumers)[keyof typeof AlertConsumers]; export type STATUS_VALUES = 'open' | 'acknowledged' | 'closed' | 'in-progress'; // TODO: remove 'in-progress' after migration to 'acknowledged' diff --git a/src/plugins/data_views/public/mocks.ts b/src/plugins/data_views/public/mocks.ts index 0ca7ad592e4f27..3ce7f87ae70cbc 100644 --- a/src/plugins/data_views/public/mocks.ts +++ b/src/plugins/data_views/public/mocks.ts @@ -43,6 +43,7 @@ const createStartContract = (): Start => { create: jest.fn().mockReturnValue(Promise.resolve({})), toDataView: jest.fn().mockReturnValue(Promise.resolve({})), toDataViewLazy: jest.fn().mockReturnValue(Promise.resolve({})), + clearInstanceCache: jest.fn(), } as unknown as jest.Mocked; }; diff --git a/x-pack/plugins/alerting/public/pages/maintenance_windows/components/maintenance_window_scoped_query.test.tsx b/x-pack/plugins/alerting/public/pages/maintenance_windows/components/maintenance_window_scoped_query.test.tsx index 4c6e2f46c86e3e..3474805485ac07 100644 --- a/x-pack/plugins/alerting/public/pages/maintenance_windows/components/maintenance_window_scoped_query.test.tsx +++ b/x-pack/plugins/alerting/public/pages/maintenance_windows/components/maintenance_window_scoped_query.test.tsx @@ -46,7 +46,7 @@ describe('MaintenanceWindowScopedQuery', () => { it('renders correctly', () => { appMockRenderer.render( { it('should hide the search bar if isEnabled is false', () => { appMockRenderer.render( { it('should render loading if isLoading is true', () => { appMockRenderer.render( = { label: 'Management', iconType: 'managementApp', appRoute: '/app/management/insightsAndAlerting', - validRuleConsumers: [AlertConsumers.ML, AlertConsumers.STACK_ALERTS, AlertConsumers.EXAMPLE], + validRuleConsumers: [ + AlertConsumers.ML, + AlertConsumers.STACK_ALERTS, + AlertConsumers.EXAMPLE, + AlertConsumers.DISCOVER, + AlertConsumers.ALERTS, + ], }, } as const; diff --git a/x-pack/plugins/cases/public/components/system_actions/cases/cases_params.tsx b/x-pack/plugins/cases/public/components/system_actions/cases/cases_params.tsx index 6b6f85e53045f4..2ba54790b1dc6c 100644 --- a/x-pack/plugins/cases/public/components/system_actions/cases/cases_params.tsx +++ b/x-pack/plugins/cases/public/components/system_actions/cases/cases_params.tsx @@ -8,7 +8,6 @@ import React, { memo, useCallback, useEffect, useMemo } from 'react'; import type { ActionParamsProps } from '@kbn/triggers-actions-ui-plugin/public/types'; -import type { AlertConsumers, ValidFeatureId } from '@kbn/rule-data-utils'; import type { EuiComboBoxOptionOption } from '@elastic/eui'; import { EuiCheckbox, @@ -37,7 +36,7 @@ const DEFAULT_EMPTY_TEMPLATE_KEY = 'defaultEmptyTemplateKey'; export const CasesParamsFieldsComponent: React.FunctionComponent< ActionParamsProps -> = ({ actionParams, editAction, errors, index, producerId, featureId }) => { +> = ({ actionParams, editAction, errors, index, producerId, featureId, ruleTypeId }) => { const { http, notifications: { toasts }, @@ -49,9 +48,7 @@ export const CasesParamsFieldsComponent: React.FunctionComponent< http, toasts, dataViewsService, - featureIds: producerId - ? [producerId as Exclude] - : [], + ruleTypeIds: ruleTypeId ? [ruleTypeId] : [], }); const { data: configurations, isLoading: isLoadingCaseConfiguration } = diff --git a/x-pack/plugins/observability_solution/observability/public/components/alerts_table/alerts/get_alerts_page_table_configuration.tsx b/x-pack/plugins/observability_solution/observability/public/components/alerts_table/alerts/get_alerts_page_table_configuration.tsx index 30c912b5107436..9b7eb10c29aa86 100644 --- a/x-pack/plugins/observability_solution/observability/public/components/alerts_table/alerts/get_alerts_page_table_configuration.tsx +++ b/x-pack/plugins/observability_solution/observability/public/components/alerts_table/alerts/get_alerts_page_table_configuration.tsx @@ -7,7 +7,7 @@ import React from 'react'; import { SortOrder } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; -import { ALERT_START } from '@kbn/rule-data-utils'; +import { ALERT_START, OBSERVABILITY_RULE_TYPE_IDS } from '@kbn/rule-data-utils'; import { AlertsTableConfigurationRegistry, RenderCustomActionsRowArgs, @@ -15,11 +15,7 @@ import { import { DataViewsServicePublic } from '@kbn/data-views-plugin/public/types'; import { HttpSetup } from '@kbn/core-http-browser'; import { NotificationsStart } from '@kbn/core-notifications-browser'; -import { - casesFeatureId, - observabilityAlertFeatureIds, - observabilityFeatureId, -} from '../../../../common'; +import { casesFeatureId, observabilityFeatureId } from '../../../../common'; import { AlertActions } from '../../../pages/alerts/components/alert_actions'; import { useGetAlertFlyoutComponents } from '../../alerts_flyout/use_get_alert_flyout_components'; import type { ObservabilityRuleTypeRegistry } from '../../../rules/create_observability_rule_type_registry'; @@ -67,7 +63,7 @@ export const getAlertsPageTableConfiguration = ( ruleTypeIds: observabilityRuleTypeRegistry.list(), usePersistentControls: getPersistentControlsHook({ groupingId: ALERTS_PAGE_ALERTS_TABLE_CONFIG_ID, - featureIds: observabilityAlertFeatureIds, + ruleTypeIds: OBSERVABILITY_RULE_TYPE_IDS, services: { dataViews, http, diff --git a/x-pack/plugins/observability_solution/observability/public/components/alerts_table/alerts/get_persistent_controls.ts b/x-pack/plugins/observability_solution/observability/public/components/alerts_table/alerts/get_persistent_controls.ts index 2141e0fb68d66b..6e0f697e831a98 100644 --- a/x-pack/plugins/observability_solution/observability/public/components/alerts_table/alerts/get_persistent_controls.ts +++ b/x-pack/plugins/observability_solution/observability/public/components/alerts_table/alerts/get_persistent_controls.ts @@ -9,12 +9,11 @@ import { useMemo, useCallback } from 'react'; import { type AlertsGroupingProps, useAlertsGroupingState } from '@kbn/alerts-grouping'; import { useAlertsDataView } from '@kbn/alerts-ui-shared/src/common/hooks/use_alerts_data_view'; import { useGetGroupSelectorStateless } from '@kbn/grouping/src/hooks/use_get_group_selector'; -import { AlertConsumers } from '@kbn/rule-data-utils'; import { AlertsByGroupingAgg } from '../types'; interface GetPersistentControlsParams { groupingId: string; - featureIds: AlertConsumers[]; + ruleTypeIds: string[]; maxGroupingLevels?: number; services: Pick< AlertsGroupingProps['services'], @@ -25,7 +24,7 @@ interface GetPersistentControlsParams { export const getPersistentControlsHook = ({ groupingId, - featureIds, + ruleTypeIds, maxGroupingLevels = 3, services: { dataViews, http, notifications }, }: GetPersistentControlsParams) => @@ -43,7 +42,7 @@ export const getPersistentControlsHook = ); const { dataView } = useAlertsDataView({ - featureIds, + ruleTypeIds, dataViewsService: dataViews, http, toasts: notifications.toasts, diff --git a/x-pack/plugins/observability_solution/observability/public/pages/alerts/alerts.tsx b/x-pack/plugins/observability_solution/observability/public/pages/alerts/alerts.tsx index da966afaffbb7a..31752ca66dc5e9 100644 --- a/x-pack/plugins/observability_solution/observability/public/pages/alerts/alerts.tsx +++ b/x-pack/plugins/observability_solution/observability/public/pages/alerts/alerts.tsx @@ -16,6 +16,7 @@ import { MaintenanceWindowCallout } from '@kbn/alerts-ui-shared'; import { DEFAULT_APP_CATEGORIES } from '@kbn/core-application-common'; import { AlertsGrouping } from '@kbn/alerts-grouping'; +import { OBSERVABILITY_RULE_TYPE_IDS } from '@kbn/rule-data-utils'; import { renderGroupPanel } from './grouping/render_group_panel'; import { rulesLocatorID } from '../../../common'; import { ALERT_STATUS_FILTER } from '../../components/alert_search_bar/constants'; @@ -45,7 +46,6 @@ import { getGroupStats } from './grouping/get_group_stats'; import { getAggregationsByGroupingField } from './grouping/get_aggregations_by_grouping_field'; import { DEFAULT_GROUPING_OPTIONS } from './grouping/constants'; import { mergeBoolQueries } from './helpers/merge_bool_queries'; -import { OBSERVABILITY_RULE_TYPE_IDS } from '@kbn/rule-data-utils'; const ALERTS_SEARCH_BAR_ID = 'alerts-search-bar-o11y'; const ALERTS_PER_PAGE = 50; @@ -279,7 +279,7 @@ function InternalAlertsPage() { return ( { () => useColumns({ defaultColumns, - featureIds, + ruleTypeIds, id, storageAlertsTable: localStorageAlertsTable, storage, @@ -215,7 +215,7 @@ describe('useColumns', () => { useColumns({ alertsFields, defaultColumns, - featureIds, + ruleTypeIds, id, storageAlertsTable: localStorageAlertsTable, storage, diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/bulk_untrack_by_query.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/bulk_untrack_by_query.ts index c7062bd4789116..571731fec26c78 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/bulk_untrack_by_query.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/bulk_untrack_by_query.ts @@ -129,7 +129,7 @@ export default function bulkUntrackByQueryTests({ getService }: FtrProviderConte }, }, ], - feature_ids: ['alertsFixture'], + rule_type_ids: ['test.always-firing-alert-as-data'], }); switch (scenario.id) { From 218eb3ede2d11b530c5a24b9f5eac7e667cde9cb Mon Sep 17 00:00:00 2001 From: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Date: Wed, 18 Sep 2024 18:07:33 +0000 Subject: [PATCH 054/106] [CI] Auto-commit changed files from 'node scripts/eslint --no-cache --fix' --- .../generated/observability_threshold_schema.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/kbn-alerts-as-data-utils/src/schemas/generated/observability_threshold_schema.ts b/packages/kbn-alerts-as-data-utils/src/schemas/generated/observability_threshold_schema.ts index 074ec11b45e3af..06163a4c558357 100644 --- a/packages/kbn-alerts-as-data-utils/src/schemas/generated/observability_threshold_schema.ts +++ b/packages/kbn-alerts-as-data-utils/src/schemas/generated/observability_threshold_schema.ts @@ -1,10 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". */ + // ---------------------------------- WARNING ---------------------------------- // this file was generated, and should not be edited by hand // ---------------------------------- WARNING ---------------------------------- From fcc6a480fa87e3c118419710f275b6f5d43cbf3b Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Fri, 20 Sep 2024 18:13:10 +0300 Subject: [PATCH 055/106] Fix arguments of getAuthorizedAlertsIndices --- .../lib/helpers/get_apm_alerts_client.ts | 3 ++- .../public/hooks/use_alerts_count.test.ts | 4 ++-- .../lib/helpers/get_infra_alerts_client.ts | 3 ++- .../server/services/get_alerts_client.ts | 18 ++++++++++++------ .../server/routes/alert_status_route.ts | 7 ++++--- 5 files changed, 22 insertions(+), 13 deletions(-) diff --git a/x-pack/plugins/observability_solution/apm/server/lib/helpers/get_apm_alerts_client.ts b/x-pack/plugins/observability_solution/apm/server/lib/helpers/get_apm_alerts_client.ts index 3c885eef658d5b..a795476ded74fc 100644 --- a/x-pack/plugins/observability_solution/apm/server/lib/helpers/get_apm_alerts_client.ts +++ b/x-pack/plugins/observability_solution/apm/server/lib/helpers/get_apm_alerts_client.ts @@ -8,6 +8,7 @@ import { isEmpty } from 'lodash'; import { ESSearchRequest, InferSearchResponseOf } from '@kbn/es-types'; import { ParsedTechnicalFields } from '@kbn/rule-registry-plugin/common'; +import { APM_RULE_TYPE_IDS } from '@kbn/rule-data-utils'; import type { MinimalAPMRouteHandlerResources } from '../../routes/apm_routes/register_apm_server_routes'; export type ApmAlertsClient = Awaited>; @@ -18,7 +19,7 @@ export async function getApmAlertsClient({ }: Pick) { const ruleRegistryPluginStart = await plugins.ruleRegistry.start(); const alertsClient = await ruleRegistryPluginStart.getRacClientWithRequest(request); - const apmAlertsIndices = await alertsClient.getAuthorizedAlertsIndices(['apm']); + const apmAlertsIndices = await alertsClient.getAuthorizedAlertsIndices(APM_RULE_TYPE_IDS); if (!apmAlertsIndices || isEmpty(apmAlertsIndices)) { throw Error('No alert indices exist for "apm"'); diff --git a/x-pack/plugins/observability_solution/infra/public/hooks/use_alerts_count.test.ts b/x-pack/plugins/observability_solution/infra/public/hooks/use_alerts_count.test.ts index 5f6ed6d57d3117..771cdd37275a8b 100644 --- a/x-pack/plugins/observability_solution/infra/public/hooks/use_alerts_count.test.ts +++ b/x-pack/plugins/observability_solution/infra/public/hooks/use_alerts_count.test.ts @@ -53,7 +53,7 @@ const mockUseKibana = () => { }; describe('useAlertsCount', () => { - const ruleTypeIds: string[] = ['infrastructure']; + const ruleTypeIds: string[] = ['metrics.alert.inventory.threshold']; beforeAll(() => { mockUseKibana(); @@ -103,7 +103,7 @@ describe('useAlertsCount', () => { terms: { field: ALERT_STATUS }, }, }, - feature_ids: ruleTypeIds, + rule_type_ids: ruleTypeIds, query, size: 0, }); diff --git a/x-pack/plugins/observability_solution/infra/server/lib/helpers/get_infra_alerts_client.ts b/x-pack/plugins/observability_solution/infra/server/lib/helpers/get_infra_alerts_client.ts index 58dfdde223ebd9..e4df794e7f4c83 100644 --- a/x-pack/plugins/observability_solution/infra/server/lib/helpers/get_infra_alerts_client.ts +++ b/x-pack/plugins/observability_solution/infra/server/lib/helpers/get_infra_alerts_client.ts @@ -8,6 +8,7 @@ import { isEmpty } from 'lodash'; import type { ESSearchRequest, InferSearchResponseOf } from '@kbn/es-types'; import { ParsedTechnicalFields } from '@kbn/rule-registry-plugin/common'; import type { KibanaRequest } from '@kbn/core/server'; +import { INFRA_RULE_TYPE_IDS } from '@kbn/rule-data-utils'; import type { InfraBackendLibs } from '../infra_types'; type RequiredParams = ESSearchRequest & { @@ -26,7 +27,7 @@ export async function getInfraAlertsClient({ }) { const [, { ruleRegistry }] = await libs.getStartServices(); const alertsClient = await ruleRegistry.getRacClientWithRequest(request); - const infraAlertsIndices = await alertsClient.getAuthorizedAlertsIndices(['infrastructure']); + const infraAlertsIndices = await alertsClient.getAuthorizedAlertsIndices(INFRA_RULE_TYPE_IDS); if (!infraAlertsIndices || isEmpty(infraAlertsIndices)) { throw Error('No alert indices exist for "infrastructure"'); diff --git a/x-pack/plugins/observability_solution/investigate_app/server/services/get_alerts_client.ts b/x-pack/plugins/observability_solution/investigate_app/server/services/get_alerts_client.ts index bf1070307742ad..81bbbeb7d448bf 100644 --- a/x-pack/plugins/observability_solution/investigate_app/server/services/get_alerts_client.ts +++ b/x-pack/plugins/observability_solution/investigate_app/server/services/get_alerts_client.ts @@ -8,6 +8,13 @@ import { isEmpty } from 'lodash'; import { ESSearchRequest, InferSearchResponseOf } from '@kbn/es-types'; import { ParsedTechnicalFields } from '@kbn/rule-registry-plugin/common'; +import { + APM_RULE_TYPE_IDS, + INFRA_RULE_TYPE_IDS, + LOG_RULE_TYPE_IDS, + SLO_RULE_TYPE_IDS, + UPTIME_RULE_TYPE_IDS, +} from '@kbn/rule-data-utils'; import { InvestigateAppRouteHandlerResources } from '../routes/types'; export type AlertsClient = Awaited>; @@ -19,12 +26,11 @@ export async function getAlertsClient({ const ruleRegistryPluginStart = await plugins.ruleRegistry.start(); const alertsClient = await ruleRegistryPluginStart.getRacClientWithRequest(request); const alertsIndices = await alertsClient.getAuthorizedAlertsIndices([ - 'logs', - 'infrastructure', - 'apm', - 'slo', - 'uptime', - 'observability', + ...LOG_RULE_TYPE_IDS, + ...INFRA_RULE_TYPE_IDS, + ...APM_RULE_TYPE_IDS, + ...SLO_RULE_TYPE_IDS, + ...UPTIME_RULE_TYPE_IDS, ]); if (!alertsIndices || isEmpty(alertsIndices)) { diff --git a/x-pack/plugins/session_view/server/routes/alert_status_route.ts b/x-pack/plugins/session_view/server/routes/alert_status_route.ts index e0b95f9705e9df..43989625ea87db 100644 --- a/x-pack/plugins/session_view/server/routes/alert_status_route.ts +++ b/x-pack/plugins/session_view/server/routes/alert_status_route.ts @@ -11,6 +11,7 @@ import type { AlertsClient, RuleRegistryPluginStartContract, } from '@kbn/rule-registry-plugin/server'; +import { SECURITY_SOLUTION_RULE_TYPE_IDS } from '@kbn/securitysolution-rules'; import { ALERT_STATUS_ROUTE, ALERT_UUID_PROPERTY, @@ -60,9 +61,9 @@ export const registerAlertStatusRoute = ( }; export const searchAlertByUuid = async (client: AlertsClient, alertUuid: string) => { - const indices = (await client.getAuthorizedAlertsIndices(['siem']))?.filter( - (index) => index !== PREVIEW_ALERTS_INDEX - ); + const indices = ( + await client.getAuthorizedAlertsIndices(SECURITY_SOLUTION_RULE_TYPE_IDS) + )?.filter((index) => index !== PREVIEW_ALERTS_INDEX); if (!indices) { return { events: [] }; From f18ed298106826475c252ac49bd91db916b89eb2 Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Fri, 20 Sep 2024 18:13:30 +0300 Subject: [PATCH 056/106] Fix alerting integration tests --- .../authorization/alerting_authorization.ts | 2 +- .../group3/tests/alerting/bulk_delete.ts | 65 ------------------- .../group3/tests/alerting/bulk_enable.ts | 48 -------------- .../basic/get_aad_fields_by_rule_type.ts | 2 +- 4 files changed, 2 insertions(+), 115 deletions(-) diff --git a/x-pack/plugins/alerting/server/authorization/alerting_authorization.ts b/x-pack/plugins/alerting/server/authorization/alerting_authorization.ts index 91484caa8912c6..19c2222c931e98 100644 --- a/x-pack/plugins/alerting/server/authorization/alerting_authorization.ts +++ b/x-pack/plugins/alerting/server/authorization/alerting_authorization.ts @@ -382,7 +382,7 @@ export class AlertingAuthorization { for (const ruleTypeId of ruleTypeIds) { /** * Skip if the ruleTypeId is not configured in any feature - * or it is not set int the rule type registry. + * or it is not set in the rule type registry. */ if (!this.ruleTypesConsumersMap.has(ruleTypeId) || !this.ruleTypeRegistry.has(ruleTypeId)) { continue; diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/alerting/bulk_delete.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/alerting/bulk_delete.ts index 2306e227e7584f..acc0321adfa5bf 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/alerting/bulk_delete.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/alerting/bulk_delete.ts @@ -249,71 +249,6 @@ export default ({ getService }: FtrProviderContext) => { } }); - it('should handle delete alert request appropriately when consumer is not the producer', async () => { - const { body: createdRule1 } = await supertest - .post(`${getUrlPrefix(space.id)}/api/alerting/rule`) - .set('kbn-xsrf', 'foo') - .send( - getTestRuleData({ - rule_type_id: 'test.restricted-noop', - consumer: 'alertsFixture', - }) - ) - .expect(200); - - const response = await supertestWithoutAuth - .patch(`${getUrlPrefix(space.id)}/internal/alerting/rules/_bulk_delete`) - .set('kbn-xsrf', 'foo') - .send({ ids: [createdRule1.id] }) - .auth(user.username, user.password); - - switch (scenario.id) { - case 'no_kibana_privileges at space1': - case 'space_1_all at space2': - expect(response.body).to.eql({ - error: 'Forbidden', - message: 'Unauthorized to find rules for any rule types', - statusCode: 403, - }); - expect(response.statusCode).to.eql(403); - objectRemover.add(space.id, createdRule1.id, 'rule', 'alerting'); - // Ensure task still exists - await getScheduledTask(createdRule1.scheduled_task_id); - break; - case 'space_1_all at space1': - case 'space_1_all_alerts_none_actions at space1': - case 'space_1_all_with_restricted_fixture at space1': - case 'global_read at space1': - expect(response.body).to.eql({ - statusCode: 400, - error: 'Bad Request', - message: 'No rules found for bulk delete', - }); - expect(response.statusCode).to.eql(400); - objectRemover.add(space.id, createdRule1.id, 'rule', 'alerting'); - // Ensure task still exists - await getScheduledTask(createdRule1.scheduled_task_id); - break; - case 'superuser at space1': - expect(response.body).to.eql({ - rules: [{ ...getDefaultRules(response), rule_type_id: 'test.restricted-noop' }], - errors: [], - total: 1, - taskIdsFailedToBeDeleted: [], - }); - expect(response.statusCode).to.eql(200); - try { - await getScheduledTask(createdRule1.scheduled_task_id); - throw new Error('Should have removed scheduled task'); - } catch (e) { - expect(e.meta.statusCode).to.eql(404); - } - break; - default: - throw new Error(`Scenario untested: ${JSON.stringify(scenario)}`); - } - }); - it('should handle delete alert request appropriately when consumer is "alerts"', async () => { const { body: createdRule1 } = await supertest .post(`${getUrlPrefix(space.id)}/api/alerting/rule`) diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/alerting/bulk_enable.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/alerting/bulk_enable.ts index d004078ac9c402..c829e130f246d1 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/alerting/bulk_enable.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/alerting/bulk_enable.ts @@ -228,54 +228,6 @@ export default ({ getService }: FtrProviderContext) => { } }); - it('should handle enable alert request appropriately when consumer is not the producer', async () => { - const { body: createdRule } = await supertest - .post(`${getUrlPrefix(space.id)}/api/alerting/rule`) - .set('kbn-xsrf', 'foo') - .send( - getTestRuleData({ - rule_type_id: 'test.restricted-noop', - consumer: 'alertsFixture', - }) - ) - .expect(200); - objectRemover.add(space.id, createdRule.id, 'rule', 'alerting'); - - const response = await supertestWithoutAuth - .patch(`${getUrlPrefix(space.id)}/internal/alerting/rules/_bulk_enable`) - .set('kbn-xsrf', 'foo') - .send({ ids: [createdRule.id] }) - .auth(user.username, user.password); - - switch (scenario.id) { - case 'no_kibana_privileges at space1': - case 'space_1_all at space2': - expect(response.body).to.eql({ - error: 'Forbidden', - message: 'Unauthorized to find rules for any rule types', - statusCode: 403, - }); - expect(response.statusCode).to.eql(403); - break; - case 'space_1_all at space1': - case 'space_1_all_alerts_none_actions at space1': - case 'space_1_all_with_restricted_fixture at space1': - case 'global_read at space1': - expect(response.body).to.eql({ - statusCode: 400, - error: 'Bad Request', - message: 'No rules found for bulk enable', - }); - expect(response.statusCode).to.eql(400); - break; - case 'superuser at space1': - expect(response.statusCode).to.eql(200); - break; - default: - throw new Error(`Scenario untested: ${JSON.stringify(scenario)}`); - } - }); - it('should handle enable alert request appropriately when consumer is "alerts"', async () => { const { body: createdRule } = await supertest .post(`${getUrlPrefix(space.id)}/api/alerting/rule`) diff --git a/x-pack/test/rule_registry/security_and_spaces/tests/basic/get_aad_fields_by_rule_type.ts b/x-pack/test/rule_registry/security_and_spaces/tests/basic/get_aad_fields_by_rule_type.ts index 776400a988a054..1e7759b06c30dd 100644 --- a/x-pack/test/rule_registry/security_and_spaces/tests/basic/get_aad_fields_by_rule_type.ts +++ b/x-pack/test/rule_registry/security_and_spaces/tests/basic/get_aad_fields_by_rule_type.ts @@ -43,7 +43,7 @@ export default ({ getService }: FtrProviderContext) => { }); describe('Users:', () => { - it(`${obsOnlySpacesAll.username} should be able to get browser fields for o11y featureIds`, async () => { + it(`${obsOnlySpacesAll.username} should be able to get browser fields for o11y rule type ids`, async () => { await retry.try(async () => { const aadFields = await getAADFieldsByRuleType( obsOnlySpacesAll, From 3f1fc6801c60353cca26109bc96d3c6d98de23ac Mon Sep 17 00:00:00 2001 From: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Date: Fri, 20 Sep 2024 15:27:08 +0000 Subject: [PATCH 057/106] [CI] Auto-commit changed files from 'node scripts/lint_ts_projects --fix' --- x-pack/plugins/session_view/tsconfig.json | 1 + 1 file changed, 1 insertion(+) diff --git a/x-pack/plugins/session_view/tsconfig.json b/x-pack/plugins/session_view/tsconfig.json index 20a1f5234d9fff..412de8355943cb 100644 --- a/x-pack/plugins/session_view/tsconfig.json +++ b/x-pack/plugins/session_view/tsconfig.json @@ -38,6 +38,7 @@ "@kbn/shared-ux-router", "@kbn/usage-collection-plugin", "@kbn/analytics", + "@kbn/securitysolution-rules", ], "exclude": [ "target/**/*", From 1c19bedccf0bdaf33080ce84e90e2a7cad73be43 Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Sat, 21 Sep 2024 15:15:55 +0300 Subject: [PATCH 058/106] Remove alerts consumer for security rule types --- .../security-solution/features/src/security/kibana_features.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/x-pack/packages/security-solution/features/src/security/kibana_features.ts b/x-pack/packages/security-solution/features/src/security/kibana_features.ts index cb458f20a136bb..458b8f6fd1f1ff 100644 --- a/x-pack/packages/security-solution/features/src/security/kibana_features.ts +++ b/x-pack/packages/security-solution/features/src/security/kibana_features.ts @@ -19,7 +19,6 @@ import { SAVED_QUERY_RULE_TYPE_ID, THRESHOLD_RULE_TYPE_ID, } from '@kbn/securitysolution-rules'; -import { ALERTING_FEATURE_ID } from '@kbn/alerting-plugin/common'; import type { BaseKibanaFeatureConfig } from '../types'; import { APP_ID, @@ -44,7 +43,7 @@ const SECURITY_RULE_TYPES = [ const alertingFeatures = SECURITY_RULE_TYPES.map((ruleTypeId) => ({ ruleTypeId, - consumers: [SERVER_APP_ID, ALERTING_FEATURE_ID], + consumers: [SERVER_APP_ID], })); export const getSecurityBaseKibanaFeature = ({ From fdefdb6c396d850f56d4666ab61d4afb7cce3797 Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Sat, 21 Sep 2024 20:00:27 +0300 Subject: [PATCH 059/106] Add o11y schema --- .../src/schemas/generated/observability_threshold_schema.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/kbn-alerts-as-data-utils/src/schemas/generated/observability_threshold_schema.ts b/packages/kbn-alerts-as-data-utils/src/schemas/generated/observability_threshold_schema.ts index 06163a4c558357..2f08e082aebeab 100644 --- a/packages/kbn-alerts-as-data-utils/src/schemas/generated/observability_threshold_schema.ts +++ b/packages/kbn-alerts-as-data-utils/src/schemas/generated/observability_threshold_schema.ts @@ -6,7 +6,6 @@ * your election, the "Elastic License 2.0", the "GNU Affero General Public * License v3.0 only", or the "Server Side Public License, v 1". */ - // ---------------------------------- WARNING ---------------------------------- // this file was generated, and should not be edited by hand // ---------------------------------- WARNING ---------------------------------- From c9a347e17c0d4b31644629744592dfa4e4515bac Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Sun, 22 Sep 2024 15:00:28 +0300 Subject: [PATCH 060/106] Fix getAlertsIndexRoute query schema --- .../routes/__mocks__/request_responses.ts | 2 +- .../server/routes/get_alert_index.test.ts | 22 +++++++++++++++++++ .../server/routes/get_alert_index.ts | 13 +++++++++-- 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/rule_registry/server/routes/__mocks__/request_responses.ts b/x-pack/plugins/rule_registry/server/routes/__mocks__/request_responses.ts index e884b8f842000a..e81094ce39e057 100644 --- a/x-pack/plugins/rule_registry/server/routes/__mocks__/request_responses.ts +++ b/x-pack/plugins/rule_registry/server/routes/__mocks__/request_responses.ts @@ -12,7 +12,7 @@ export const getReadIndexRequest = () => requestMock.create({ method: 'get', path: `${BASE_RAC_ALERTS_API_PATH}/index`, - query: { ruleTypeIds: 'siem' }, + query: { ruleTypeIds: 'siem.esqlRule' }, }); export const getReadRequest = () => diff --git a/x-pack/plugins/rule_registry/server/routes/get_alert_index.test.ts b/x-pack/plugins/rule_registry/server/routes/get_alert_index.test.ts index fd1b3afbb0d5e1..28d901dc5a137d 100644 --- a/x-pack/plugins/rule_registry/server/routes/get_alert_index.test.ts +++ b/x-pack/plugins/rule_registry/server/routes/get_alert_index.test.ts @@ -31,6 +31,28 @@ describe('getAlertsIndexRoute', () => { expect(response.body).toEqual({ index_name: ['alerts-security.alerts'] }); }); + test('accepts an array of string ', async () => { + const ruleTypeIds = ['foo', 'bar']; + + await server.inject({ ...getReadIndexRequest(), query: { ruleTypeIds } }, context); + + expect(clients.rac.getAuthorizedAlertsIndices).toHaveBeenCalledWith(ruleTypeIds); + }); + + test('accepts a single string', async () => { + const ruleTypeIds = 'foo'; + + await server.inject({ ...getReadIndexRequest(), query: { ruleTypeIds } }, context); + + expect(clients.rac.getAuthorizedAlertsIndices).toHaveBeenCalledWith([ruleTypeIds]); + }); + + test('accepts not defined ryleTypeIds', async () => { + await server.inject({ ...getReadIndexRequest(), query: {} }, context); + + expect(clients.rac.getAuthorizedAlertsIndices).toHaveBeenCalledWith(undefined); + }); + describe('request validation', () => { test('rejects invalid query params', async () => { await expect( diff --git a/x-pack/plugins/rule_registry/server/routes/get_alert_index.ts b/x-pack/plugins/rule_registry/server/routes/get_alert_index.ts index 39a4149d860b67..531fbcec63f05d 100644 --- a/x-pack/plugins/rule_registry/server/routes/get_alert_index.ts +++ b/x-pack/plugins/rule_registry/server/routes/get_alert_index.ts @@ -21,7 +21,7 @@ export const getAlertsIndexRoute = (router: IRouter) = query: buildRouteValidation( t.exact( t.partial({ - ruleTypeIds: t.string, + ruleTypeIds: t.union([t.string, t.array(t.string)]), }) ) ), @@ -35,7 +35,16 @@ export const getAlertsIndexRoute = (router: IRouter) = const racContext = await context.rac; const alertsClient = await racContext.getAlertsClient(); const { ruleTypeIds } = request.query; - const indexName = await alertsClient.getAuthorizedAlertsIndices(ruleTypeIds?.split(',')); + + const ruleTypeIdsAsArray = + ruleTypeIds != null + ? Array.isArray(ruleTypeIds) + ? ruleTypeIds + : [ruleTypeIds] + : ruleTypeIds; + + const indexName = await alertsClient.getAuthorizedAlertsIndices(ruleTypeIdsAsArray); + return response.ok({ body: { index_name: indexName }, }); From fcb0cb7d9267c8c4239240a7c2bb6970ebfdef50 Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Sun, 22 Sep 2024 16:25:52 +0300 Subject: [PATCH 061/106] Fix issues when detecting siem rule types --- .../hooks/use_alerts_data_view.test.tsx | 23 +++++++++++++++++++ .../src/common/hooks/use_alerts_data_view.ts | 2 +- .../search_strategy/search_strategy.test.ts | 22 ++++++++++++++++++ .../server/search_strategy/search_strategy.ts | 4 ++-- .../components/stack_alerts_page.tsx | 2 +- 5 files changed, 49 insertions(+), 4 deletions(-) diff --git a/packages/kbn-alerts-ui-shared/src/common/hooks/use_alerts_data_view.test.tsx b/packages/kbn-alerts-ui-shared/src/common/hooks/use_alerts_data_view.test.tsx index c1c45cfb838fea..47597f7142a5d3 100644 --- a/packages/kbn-alerts-ui-shared/src/common/hooks/use_alerts_data_view.test.tsx +++ b/packages/kbn-alerts-ui-shared/src/common/hooks/use_alerts_data_view.test.tsx @@ -131,6 +131,29 @@ describe('useAlertsDataView', () => { expect(mockFetchAlertsFields).toHaveBeenCalledTimes(0); }); + it('does not fetch anything with empty array nor create a virtual data view', async () => { + const { result, waitFor } = renderHook( + () => + useAlertsDataView({ + ...mockServices, + ruleTypeIds: [], + }), + { + wrapper, + } + ); + + await waitFor(() => + expect(result.current).toEqual({ + isLoading: false, + dataView: undefined, + }) + ); + expect(mockFetchAlertsIndexNames).toHaveBeenCalledTimes(0); + expect(mockFetchAlertsFields).toHaveBeenCalledTimes(0); + expect(mockServices.dataViewsService.create).not.toHaveBeenCalled(); + }); + it('returns an undefined data view if any of the queries fails', async () => { mockFetchAlertsIndexNames.mockRejectedValue('error'); diff --git a/packages/kbn-alerts-ui-shared/src/common/hooks/use_alerts_data_view.ts b/packages/kbn-alerts-ui-shared/src/common/hooks/use_alerts_data_view.ts index bcd821b76608eb..e80c7919bdaef2 100644 --- a/packages/kbn-alerts-ui-shared/src/common/hooks/use_alerts_data_view.ts +++ b/packages/kbn-alerts-ui-shared/src/common/hooks/use_alerts_data_view.ts @@ -96,7 +96,7 @@ export const useAlertsDataView = ({ ruleTypeIds, }: UseAlertsDataViewParams): UseAlertsDataViewResult => { const includesSecurity = ruleTypeIds.some(isSiemRuleType); - const isOnlySecurity = ruleTypeIds.every(isSiemRuleType); + const isOnlySecurity = ruleTypeIds.length > 0 && ruleTypeIds.every(isSiemRuleType); const hasMixedFeatureIds = !isOnlySecurity && includesSecurity; const { diff --git a/x-pack/plugins/rule_registry/server/search_strategy/search_strategy.test.ts b/x-pack/plugins/rule_registry/server/search_strategy/search_strategy.test.ts index b6706485a08d5d..6ce679a2108486 100644 --- a/x-pack/plugins/rule_registry/server/search_strategy/search_strategy.test.ts +++ b/x-pack/plugins/rule_registry/server/search_strategy/search_strategy.test.ts @@ -210,6 +210,28 @@ describe('ruleRegistrySearchStrategyProvider()', () => { ); }); + it('should not throw an error with empty rule type ids', async () => { + const request: RuleRegistrySearchRequest = { + ruleTypeIds: [], + }; + + const options = {}; + const deps = { + request: {}, + }; + + getAuthorizedRuleTypesMock.mockResolvedValue([]); + getAlertIndicesAliasMock.mockReturnValue([]); + + const strategy = ruleRegistrySearchStrategyProvider(data, alerting, logger, security, spaces); + + await expect( + lastValueFrom( + strategy.search(request, options, deps as unknown as SearchStrategyDependencies) + ) + ).resolves.not.toThrow(); + }); + it('should use internal user when requesting o11y alerts as RBAC is applied', async () => { const request: RuleRegistrySearchRequest = { ruleTypeIds: ['.es-query'], diff --git a/x-pack/plugins/rule_registry/server/search_strategy/search_strategy.ts b/x-pack/plugins/rule_registry/server/search_strategy/search_strategy.ts index 40bd1bbf82dcf0..14f9c1f55300ac 100644 --- a/x-pack/plugins/rule_registry/server/search_strategy/search_strategy.ts +++ b/x-pack/plugins/rule_registry/server/search_strategy/search_strategy.ts @@ -54,8 +54,8 @@ export const ruleRegistrySearchStrategyProvider = ( // is different than every other solution so we need to special case // those requests. const isAnyRuleTypeESAuthorized = request.ruleTypeIds.some(isSiemRuleType); - - const isEachRuleTypeESAuthorized = request.ruleTypeIds.every(isSiemRuleType); + const isEachRuleTypeESAuthorized = + request.ruleTypeIds.length > 0 && request.ruleTypeIds.every(isSiemRuleType); const registeredRuleTypes = alerting.listTypes(); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_page/components/stack_alerts_page.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_page/components/stack_alerts_page.tsx index 5ae519ba6f4406..8bc43ebb86b4ac 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_page/components/stack_alerts_page.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_page/components/stack_alerts_page.tsx @@ -86,8 +86,8 @@ const PageContent = () => { } = useLoadRuleTypesQuery({ filteredRuleTypes: [] }); const ruleTypeIdsByFeatureId = useRuleTypeIdsByFeatureId(ruleTypesIndex); - const browsingSiem = ruleTypeIds.length === 1 && isSiemRuleType(ruleTypeIds[0]); const filteringBySolution = ruleTypeIds.length > 0; + const browsingSiem = filteringBySolution && ruleTypeIds.every(isSiemRuleType); const ruleTypeIdsByFeatureIdEntries = Object.entries(ruleTypeIdsByFeatureId); const quickFilters = useMemo(() => { From b7a68a2d78770e24ea0edb0b9a5a7cd8b32a135f Mon Sep 17 00:00:00 2001 From: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Date: Sun, 22 Sep 2024 13:38:22 +0000 Subject: [PATCH 062/106] [CI] Auto-commit changed files from 'node scripts/notice' --- x-pack/packages/security-solution/features/tsconfig.json | 1 - 1 file changed, 1 deletion(-) diff --git a/x-pack/packages/security-solution/features/tsconfig.json b/x-pack/packages/security-solution/features/tsconfig.json index b37b81f709e9e8..2c153f831721d7 100644 --- a/x-pack/packages/security-solution/features/tsconfig.json +++ b/x-pack/packages/security-solution/features/tsconfig.json @@ -17,7 +17,6 @@ "@kbn/cases-plugin", "@kbn/securitysolution-rules", "@kbn/securitysolution-list-constants", - "@kbn/alerting-plugin", ], "exclude": ["target/**/*"] } From 8f4f1e0707b31bce7042435ac508d24494f37282 Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Mon, 23 Sep 2024 12:02:35 +0300 Subject: [PATCH 063/106] Fix test imports --- .../observability/metric_threshold_rule.ts | 7 ++----- .../functional/apps/infra/metrics_source_configuration.ts | 7 ++----- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/x-pack/test/alerting_api_integration/observability/metric_threshold_rule.ts b/x-pack/test/alerting_api_integration/observability/metric_threshold_rule.ts index bc36566f91f52d..c935cc8dd8fb5d 100644 --- a/x-pack/test/alerting_api_integration/observability/metric_threshold_rule.ts +++ b/x-pack/test/alerting_api_integration/observability/metric_threshold_rule.ts @@ -8,12 +8,9 @@ import moment from 'moment'; import expect from '@kbn/expect'; import { cleanup, generate, Dataset, PartialConfig } from '@kbn/data-forge'; -import { - Aggregators, - InfraRuleType, - MetricThresholdParams, -} from '@kbn/infra-plugin/common/alerting/metrics'; +import { Aggregators, MetricThresholdParams } from '@kbn/infra-plugin/common/alerting/metrics'; import { COMPARATORS } from '@kbn/alerting-comparators'; +import { InfraRuleType } from '@kbn/rule-data-utils'; import { waitForDocumentInIndex, waitForAlertInIndex, diff --git a/x-pack/test/functional/apps/infra/metrics_source_configuration.ts b/x-pack/test/functional/apps/infra/metrics_source_configuration.ts index 46d20489e4d36c..39c6b33d2f3e27 100644 --- a/x-pack/test/functional/apps/infra/metrics_source_configuration.ts +++ b/x-pack/test/functional/apps/infra/metrics_source_configuration.ts @@ -7,13 +7,10 @@ import { cleanup, Dataset, generate, PartialConfig } from '@kbn/data-forge'; import expect from '@kbn/expect'; -import { - Aggregators, - InfraRuleType, - MetricThresholdParams, -} from '@kbn/infra-plugin/common/alerting/metrics'; +import { Aggregators, MetricThresholdParams } from '@kbn/infra-plugin/common/alerting/metrics'; import { COMPARATORS } from '@kbn/alerting-comparators'; +import { InfraRuleType } from '@kbn/rule-data-utils'; import { createRule } from '../../../alerting_api_integration/observability/helpers/alerting_api_helper'; import { waitForDocumentInIndex, From fa0439fd8dcbac63527c971518ee08536f064e45 Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Thu, 26 Sep 2024 15:46:25 +0300 Subject: [PATCH 064/106] Change _aggregate API to use ruleTypeIds --- .../routes/rule/apis/aggregate/schemas/v1.ts | 2 +- .../rule/methods/aggregate/aggregate_rules.ts | 19 +- .../schemas/aggregate_options_schema.ts | 2 +- .../rule/methods/aggregate/types/index.ts | 8 - .../authorization/alerting_authorization.ts | 4 - .../aggregate/aggregate_rules_route.test.ts | 4 + .../transform_aggregate_query_request/v1.ts | 4 +- .../rules_client/common/filters.test.ts | 409 ++++++++++++++++++ .../server/rules_client/common/filters.ts | 84 ++++ .../components/related_alerts.tsx | 12 +- .../public/pages/alerts/alerts.tsx | 3 +- .../server/lib/get_authz_filter.ts | 4 +- .../hooks/use_load_rule_aggregations.test.tsx | 4 + .../hooks/use_load_rule_aggregations_query.ts | 6 +- .../lib/rule_api/aggregate.test.ts | 34 ++ .../application/lib/rule_api/aggregate.ts | 4 +- .../lib/rule_api/aggregate_helpers.ts | 2 +- .../rule_api/aggregate_kuery_filter.test.ts | 81 ++++ .../lib/rule_api/aggregate_kuery_filter.ts | 4 +- .../group2/tests/alerting/aggregate.ts | 247 +++++++++++ .../group2/tests/alerting/index.ts | 1 + .../{aggregate_post.ts => aggregate.ts} | 94 +++- .../tests/alerting/group1/index.ts | 2 +- 23 files changed, 992 insertions(+), 42 deletions(-) create mode 100644 x-pack/plugins/alerting/server/rules_client/common/filters.test.ts create mode 100644 x-pack/plugins/alerting/server/rules_client/common/filters.ts create mode 100644 x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/aggregate_kuery_filter.test.ts create mode 100644 x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/aggregate.ts rename x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/{aggregate_post.ts => aggregate.ts} (67%) diff --git a/x-pack/plugins/alerting/common/routes/rule/apis/aggregate/schemas/v1.ts b/x-pack/plugins/alerting/common/routes/rule/apis/aggregate/schemas/v1.ts index 95f07bf3f7bda3..fccc922df4415c 100644 --- a/x-pack/plugins/alerting/common/routes/rule/apis/aggregate/schemas/v1.ts +++ b/x-pack/plugins/alerting/common/routes/rule/apis/aggregate/schemas/v1.ts @@ -24,7 +24,7 @@ export const aggregateRulesRequestBodySchema = schema.object({ ) ), filter: schema.maybe(schema.string()), - filter_consumers: schema.maybe(schema.arrayOf(schema.string())), + rule_type_ids: schema.maybe(schema.arrayOf(schema.string())), }); export const aggregateRulesResponseBodySchema = schema.object({ diff --git a/x-pack/plugins/alerting/server/application/rule/methods/aggregate/aggregate_rules.ts b/x-pack/plugins/alerting/server/application/rule/methods/aggregate/aggregate_rules.ts index 4418e8ccf8c74a..24a9e2f46d6e22 100644 --- a/x-pack/plugins/alerting/server/application/rule/methods/aggregate/aggregate_rules.ts +++ b/x-pack/plugins/alerting/server/application/rule/methods/aggregate/aggregate_rules.ts @@ -5,7 +5,12 @@ * 2.0. */ -import { KueryNode, nodeBuilder } from '@kbn/es-query'; +import type { KueryNode } from '@kbn/es-query'; +import { + buildRuleTypeIdsFilter, + combineFilterWithAuthorizationFilter, + combineFilters, +} from '../../../../rules_client/common/filters'; import { findRulesSo } from '../../../../data/rule'; import { AlertingAuthorizationEntity } from '../../../../authorization'; import { ruleAuditEvent, RuleAuditAction } from '../../../../rules_client/common/audit_events'; @@ -28,8 +33,8 @@ export async function aggregateRules>( authorizationTuple = await context.authorization.getFindAuthorizationFilter({ authorizationEntity: AlertingAuthorizationEntity.Rule, filterOpts: alertingAuthorizationFilterOpts, - ruleTypeIds, }); + validateRuleAggregationFields(aggs); aggregateOptionsSchema.validate(options); } catch (error) { @@ -44,15 +49,17 @@ export async function aggregateRules>( const { filter: authorizationFilter } = authorizationTuple; const filterKueryNode = buildKueryNodeFilter(filter); + const ruleTypeIdsFilter = buildRuleTypeIdsFilter(ruleTypeIds); + const combinedFilters = combineFilters([filterKueryNode, ruleTypeIdsFilter]); const { aggregations } = await findRulesSo({ savedObjectsClient: context.unsecuredSavedObjectsClient, savedObjectsFindOptions: { ...restOptions, - filter: - authorizationFilter && filterKueryNode - ? nodeBuilder.and([filterKueryNode, authorizationFilter as KueryNode]) - : authorizationFilter, + filter: combineFilterWithAuthorizationFilter( + combinedFilters, + authorizationFilter as KueryNode + ), page, perPage, aggs, diff --git a/x-pack/plugins/alerting/server/application/rule/methods/aggregate/schemas/aggregate_options_schema.ts b/x-pack/plugins/alerting/server/application/rule/methods/aggregate/schemas/aggregate_options_schema.ts index 7250094160a04f..35b166385b46f0 100644 --- a/x-pack/plugins/alerting/server/application/rule/methods/aggregate/schemas/aggregate_options_schema.ts +++ b/x-pack/plugins/alerting/server/application/rule/methods/aggregate/schemas/aggregate_options_schema.ts @@ -16,7 +16,7 @@ export const aggregateOptionsSchema = schema.object({ id: schema.string(), }) ), - filterConsumers: schema.maybe(schema.arrayOf(schema.string())), + ruleTypeIds: schema.maybe(schema.arrayOf(schema.string())), // filter type is `string | KueryNode`, but `KueryNode` has no schema to import yet filter: schema.maybe( schema.oneOf([schema.string(), schema.recordOf(schema.string(), schema.any())]) diff --git a/x-pack/plugins/alerting/server/application/rule/methods/aggregate/types/index.ts b/x-pack/plugins/alerting/server/application/rule/methods/aggregate/types/index.ts index 47e76dc7500e6d..e146928efcfff6 100644 --- a/x-pack/plugins/alerting/server/application/rule/methods/aggregate/types/index.ts +++ b/x-pack/plugins/alerting/server/application/rule/methods/aggregate/types/index.ts @@ -9,17 +9,9 @@ import { TypeOf } from '@kbn/config-schema'; import { KueryNode } from '@kbn/es-query'; import { aggregateOptionsSchema } from '../schemas'; -type AggregateOptionsSchemaTypes = TypeOf; export type AggregateOptions = TypeOf & { - search?: AggregateOptionsSchemaTypes['search']; - defaultSearchOperator?: AggregateOptionsSchemaTypes['defaultSearchOperator']; - searchFields?: AggregateOptionsSchemaTypes['searchFields']; - hasReference?: AggregateOptionsSchemaTypes['hasReference']; // Adding filter as in schema it's defined as any instead of KueryNode filter?: string | KueryNode; - page?: AggregateOptionsSchemaTypes['page']; - perPage?: AggregateOptionsSchemaTypes['perPage']; - ruleTypeIds?: string[]; }; export interface AggregateParams { diff --git a/x-pack/plugins/alerting/server/authorization/alerting_authorization.ts b/x-pack/plugins/alerting/server/authorization/alerting_authorization.ts index 19c2222c931e98..76c432a95706b7 100644 --- a/x-pack/plugins/alerting/server/authorization/alerting_authorization.ts +++ b/x-pack/plugins/alerting/server/authorization/alerting_authorization.ts @@ -62,7 +62,6 @@ interface GetAuthorizationFilterParams { authorizationEntity: AlertingAuthorizationEntity; filterOpts: AlertingAuthorizationFilterOpts; operation: WriteOperations | ReadOperations; - ruleTypeIds?: string[]; } interface GetAuthorizedRuleTypesWithAuthorizedConsumersParams { @@ -79,7 +78,6 @@ interface GetAllAuthorizedRuleTypesFindOperationParams { interface GetFindAuthorizationFilterParams { authorizationEntity: AlertingAuthorizationEntity; filterOpts: AlertingAuthorizationFilterOpts; - ruleTypeIds?: string[]; } interface GetAuthorizedRuleTypesParams { @@ -271,7 +269,6 @@ export class AlertingAuthorization { ensureRuleTypeIsAuthorized: (ruleTypeId: string, consumer: string, auth: string) => void; }> { return this.getAuthorizationFilter({ - ruleTypeIds: params.ruleTypeIds, operation: ReadOperations.Find, authorizationEntity: params.authorizationEntity, filterOpts: params.filterOpts, @@ -296,7 +293,6 @@ export class AlertingAuthorization { }> { if (this.authorization && this.shouldCheckAuthorization()) { const { authorizedRuleTypes } = await this._getAuthorizedRuleTypesWithAuthorizedConsumers({ - ruleTypeIds: params.ruleTypeIds, operations: [params.operation], authorizationEntity: params.authorizationEntity, }); diff --git a/x-pack/plugins/alerting/server/routes/rule/apis/aggregate/aggregate_rules_route.test.ts b/x-pack/plugins/alerting/server/routes/rule/apis/aggregate/aggregate_rules_route.test.ts index 77221de2d714bd..74a94cbba80a19 100644 --- a/x-pack/plugins/alerting/server/routes/rule/apis/aggregate/aggregate_rules_route.test.ts +++ b/x-pack/plugins/alerting/server/routes/rule/apis/aggregate/aggregate_rules_route.test.ts @@ -145,6 +145,7 @@ describe('aggregateRulesRoute', () => { { body: { default_search_operator: 'AND', + rule_type_ids: ['foo'], }, }, ['ok'] @@ -237,6 +238,9 @@ describe('aggregateRulesRoute', () => { }, "options": Object { "defaultSearchOperator": "AND", + "ruleTypeIds": Array [ + "foo", + ], }, }, ] diff --git a/x-pack/plugins/alerting/server/routes/rule/apis/aggregate/transforms/transform_aggregate_query_request/v1.ts b/x-pack/plugins/alerting/server/routes/rule/apis/aggregate/transforms/transform_aggregate_query_request/v1.ts index baa6b9bb46f9c0..5f72c2ab84f146 100644 --- a/x-pack/plugins/alerting/server/routes/rule/apis/aggregate/transforms/transform_aggregate_query_request/v1.ts +++ b/x-pack/plugins/alerting/server/routes/rule/apis/aggregate/transforms/transform_aggregate_query_request/v1.ts @@ -13,13 +13,13 @@ export const transformAggregateQueryRequest: RewriteRequestCase ({ defaultSearchOperator, ...(hasReference ? { hasReference } : {}), ...(searchFields ? { searchFields } : {}), ...(search ? { search } : {}), - ...(filterConsumers ? { filterConsumers } : {}), + ...(ruleTypeIds ? { ruleTypeIds } : {}), ...(filter ? { filter } : {}), }); diff --git a/x-pack/plugins/alerting/server/rules_client/common/filters.test.ts b/x-pack/plugins/alerting/server/rules_client/common/filters.test.ts new file mode 100644 index 00000000000000..f334547bf71f8a --- /dev/null +++ b/x-pack/plugins/alerting/server/rules_client/common/filters.test.ts @@ -0,0 +1,409 @@ +/* + * 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 { nodeBuilder } from '@kbn/es-query'; +import { + buildFilter, + buildRuleTypeIdsFilter, + combineFilterWithAuthorizationFilter, + combineFilters, +} from './filters'; + +describe('filters', () => { + describe('combineFilterWithAuthorizationFilter', () => { + it('returns undefined if neither a filter or authorizationFilter are passed', () => { + expect(combineFilterWithAuthorizationFilter()).toBeUndefined(); + }); + + it('returns a single KueryNode when only a filter is passed in', () => { + const node = nodeBuilder.is('a', 'hello'); + expect(combineFilterWithAuthorizationFilter(node)).toMatchInlineSnapshot(` + Object { + "arguments": Array [ + Object { + "isQuoted": false, + "type": "literal", + "value": "a", + }, + Object { + "isQuoted": false, + "type": "literal", + "value": "hello", + }, + ], + "function": "is", + "type": "function", + } + `); + }); + + it('returns a single KueryNode when only an authorizationFilter is passed in', () => { + const node = nodeBuilder.is('a', 'hello'); + expect(combineFilterWithAuthorizationFilter(undefined, node)).toMatchInlineSnapshot(` + Object { + "arguments": Array [ + Object { + "isQuoted": false, + "type": "literal", + "value": "a", + }, + Object { + "isQuoted": false, + "type": "literal", + "value": "hello", + }, + ], + "function": "is", + "type": "function", + } + `); + }); + + it("returns a single KueryNode and'ing together the passed in parameters", () => { + const node = nodeBuilder.is('a', 'hello'); + const node2 = nodeBuilder.is('b', 'hi'); + + expect(combineFilterWithAuthorizationFilter(node, node2)).toMatchInlineSnapshot(` + Object { + "arguments": Array [ + Object { + "arguments": Array [ + Object { + "isQuoted": false, + "type": "literal", + "value": "a", + }, + Object { + "isQuoted": false, + "type": "literal", + "value": "hello", + }, + ], + "function": "is", + "type": "function", + }, + Object { + "arguments": Array [ + Object { + "isQuoted": false, + "type": "literal", + "value": "b", + }, + Object { + "isQuoted": false, + "type": "literal", + "value": "hi", + }, + ], + "function": "is", + "type": "function", + }, + ], + "function": "and", + "type": "function", + } + `); + }); + + it("returns a single KueryNode and'ing together the passed in parameters in opposite order", () => { + const node = nodeBuilder.is('a', 'hello'); + const node2 = nodeBuilder.is('b', 'hi'); + + expect(combineFilterWithAuthorizationFilter(node2, node)).toMatchInlineSnapshot(` + Object { + "arguments": Array [ + Object { + "arguments": Array [ + Object { + "isQuoted": false, + "type": "literal", + "value": "b", + }, + Object { + "isQuoted": false, + "type": "literal", + "value": "hi", + }, + ], + "function": "is", + "type": "function", + }, + Object { + "arguments": Array [ + Object { + "isQuoted": false, + "type": "literal", + "value": "a", + }, + Object { + "isQuoted": false, + "type": "literal", + "value": "hello", + }, + ], + "function": "is", + "type": "function", + }, + ], + "function": "and", + "type": "function", + } + `); + }); + }); + + describe('buildFilter', () => { + it('returns undefined if filters is undefined', () => { + expect(buildFilter({ filters: undefined, field: 'abc', operator: 'or' })).toBeUndefined(); + }); + + it('returns undefined if filters is is an empty array', () => { + expect(buildFilter({ filters: [], field: 'abc', operator: 'or' })).toBeUndefined(); + }); + + it('returns a KueryNode using or operator', () => { + expect(buildFilter({ filters: ['value1'], field: 'abc', operator: 'or' })) + .toMatchInlineSnapshot(` + Object { + "arguments": Array [ + Object { + "isQuoted": false, + "type": "literal", + "value": "alert.attributes.abc", + }, + Object { + "isQuoted": false, + "type": "literal", + "value": "value1", + }, + ], + "function": "is", + "type": "function", + } + `); + }); + + it("returns multiple nodes or'd together", () => { + expect(buildFilter({ filters: ['value1', 'value2'], field: 'abc', operator: 'or' })) + .toMatchInlineSnapshot(` + Object { + "arguments": Array [ + Object { + "arguments": Array [ + Object { + "isQuoted": false, + "type": "literal", + "value": "alert.attributes.abc", + }, + Object { + "isQuoted": false, + "type": "literal", + "value": "value1", + }, + ], + "function": "is", + "type": "function", + }, + Object { + "arguments": Array [ + Object { + "isQuoted": false, + "type": "literal", + "value": "alert.attributes.abc", + }, + Object { + "isQuoted": false, + "type": "literal", + "value": "value2", + }, + ], + "function": "is", + "type": "function", + }, + ], + "function": "or", + "type": "function", + } + `); + }); + + it('does not escape special kql characters in the filter values', () => { + const specialCharacters = 'awesome:()\\<>"*'; + + expect(buildFilter({ filters: [specialCharacters], field: 'abc', operator: 'or' })) + .toMatchInlineSnapshot(` + Object { + "arguments": Array [ + Object { + "isQuoted": false, + "type": "literal", + "value": "alert.attributes.abc", + }, + Object { + "isQuoted": false, + "type": "literal", + "value": "awesome:()\\\\<>\\"*", + }, + ], + "function": "is", + "type": "function", + } + `); + }); + }); + + describe('combineFilters', () => { + it('returns undefined if the nodes are undefined or null', () => { + expect(combineFilters([null, undefined])).toBeUndefined(); + }); + + it('combines the filters correctly', () => { + const node = nodeBuilder.is('a', 'hello'); + const node2 = nodeBuilder.is('b', 'hi'); + + expect(combineFilters([node, null, undefined, node2])).toMatchInlineSnapshot(` + Object { + "arguments": Array [ + Object { + "arguments": Array [ + Object { + "isQuoted": false, + "type": "literal", + "value": "a", + }, + Object { + "isQuoted": false, + "type": "literal", + "value": "hello", + }, + ], + "function": "is", + "type": "function", + }, + Object { + "arguments": Array [ + Object { + "isQuoted": false, + "type": "literal", + "value": "b", + }, + Object { + "isQuoted": false, + "type": "literal", + "value": "hi", + }, + ], + "function": "is", + "type": "function", + }, + ], + "function": "and", + "type": "function", + } + `); + }); + + it('combines the filters correctly with an operator', () => { + const node = nodeBuilder.is('a', 'hello'); + const node2 = nodeBuilder.is('b', 'hi'); + + expect(combineFilters([node, null, undefined, node2], 'or')).toMatchInlineSnapshot(` + Object { + "arguments": Array [ + Object { + "arguments": Array [ + Object { + "isQuoted": false, + "type": "literal", + "value": "a", + }, + Object { + "isQuoted": false, + "type": "literal", + "value": "hello", + }, + ], + "function": "is", + "type": "function", + }, + Object { + "arguments": Array [ + Object { + "isQuoted": false, + "type": "literal", + "value": "b", + }, + Object { + "isQuoted": false, + "type": "literal", + "value": "hi", + }, + ], + "function": "is", + "type": "function", + }, + ], + "function": "or", + "type": "function", + } + `); + }); + }); + + describe('buildRuleTypeIdsFilter', () => { + it('returns undefined if ruleTypeIds is undefined', () => { + expect(buildRuleTypeIdsFilter()).toBeUndefined(); + }); + + it('returns undefined if ruleTypeIds is is an empty array', () => { + expect(buildRuleTypeIdsFilter([])).toBeUndefined(); + }); + + it('builds the filter correctly', () => { + expect(buildRuleTypeIdsFilter(['foo', 'bar'])).toMatchInlineSnapshot(` + Object { + "arguments": Array [ + Object { + "arguments": Array [ + Object { + "isQuoted": false, + "type": "literal", + "value": "alert.attributes.alertTypeId", + }, + Object { + "isQuoted": false, + "type": "literal", + "value": "foo", + }, + ], + "function": "is", + "type": "function", + }, + Object { + "arguments": Array [ + Object { + "isQuoted": false, + "type": "literal", + "value": "alert.attributes.alertTypeId", + }, + Object { + "isQuoted": false, + "type": "literal", + "value": "bar", + }, + ], + "function": "is", + "type": "function", + }, + ], + "function": "or", + "type": "function", + } + `); + }); + }); +}); diff --git a/x-pack/plugins/alerting/server/rules_client/common/filters.ts b/x-pack/plugins/alerting/server/rules_client/common/filters.ts new file mode 100644 index 00000000000000..5246449c642bee --- /dev/null +++ b/x-pack/plugins/alerting/server/rules_client/common/filters.ts @@ -0,0 +1,84 @@ +/* + * 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 { KueryNode, nodeBuilder } from '@kbn/es-query'; +import { RULE_SAVED_OBJECT_TYPE } from '../..'; + +export const NodeBuilderOperators = { + and: 'and', + or: 'or', +} as const; + +type NodeBuilderOperatorsType = keyof typeof NodeBuilderOperators; + +interface FilterField { + filters?: string | string[]; + field: string; + operator: NodeBuilderOperatorsType; + type?: string; +} + +export const buildFilter = ({ + filters, + field, + operator, + type = RULE_SAVED_OBJECT_TYPE, +}: FilterField): KueryNode | undefined => { + if (filters === undefined) { + return; + } + + const filtersAsArray = Array.isArray(filters) ? filters : [filters]; + + if (filtersAsArray.length === 0) { + return; + } + + return nodeBuilder[operator]( + filtersAsArray.map((filter) => nodeBuilder.is(`${type}.attributes.${field}`, filter)) + ); +}; + +export const buildRuleTypeIdsFilter = (ruleTypeIds?: string[]) => { + if (!ruleTypeIds || !ruleTypeIds?.length) { + return; + } + + return buildFilter({ filters: ruleTypeIds, field: 'alertTypeId', operator: 'or' }); +}; + +/** + * Combines Kuery nodes and accepts an array with a mixture of undefined and KueryNodes. This will filter out the undefined + * filters and return a KueryNode with the filters combined using the specified operator which defaults to and if not defined. + */ +export function combineFilters( + nodes: Array, + operator: NodeBuilderOperatorsType = NodeBuilderOperators.and +): KueryNode | undefined { + const filters = nodes.filter(Boolean) as KueryNode[]; + + if (filters.length <= 0) { + return; + } + + return nodeBuilder[operator](filters); +} + +export const combineFilterWithAuthorizationFilter = ( + filter?: KueryNode, + authorizationFilter?: KueryNode +) => { + if (!filter && !authorizationFilter) { + return; + } + + const kueries = [ + ...(filter !== undefined ? [filter] : []), + ...(authorizationFilter !== undefined ? [authorizationFilter] : []), + ]; + return nodeBuilder.and(kueries); +}; diff --git a/x-pack/plugins/observability_solution/observability/public/pages/alert_details/components/related_alerts.tsx b/x-pack/plugins/observability_solution/observability/public/pages/alert_details/components/related_alerts.tsx index c74a4558d47f7f..d84f2b3832c2a5 100644 --- a/x-pack/plugins/observability_solution/observability/public/pages/alert_details/components/related_alerts.tsx +++ b/x-pack/plugins/observability_solution/observability/public/pages/alert_details/components/related_alerts.tsx @@ -8,11 +8,15 @@ import React, { useState, useRef, useEffect } from 'react'; import { EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui'; import { getPaddedAlertTimeRange } from '@kbn/observability-get-padded-alert-time-range-util'; -import { ALERT_END, ALERT_START, ALERT_UUID } from '@kbn/rule-data-utils'; +import { + ALERT_END, + ALERT_START, + ALERT_UUID, + OBSERVABILITY_RULE_TYPE_IDS, +} from '@kbn/rule-data-utils'; import { BoolQuery, Filter, type Query } from '@kbn/es-query'; import { AlertsGrouping } from '@kbn/alerts-grouping'; -import { observabilityAlertFeatureIds } from '../../../../common/constants'; import { TopAlert } from '../../..'; import { AlertSearchBarContainerState, @@ -100,7 +104,7 @@ export function InternalRelatedAlerts({ alert, groups, tags }: Props) { {esQuery && ( - featureIds={observabilityAlertFeatureIds} + ruleTypeIds={OBSERVABILITY_RULE_TYPE_IDS} defaultFilters={ALERT_STATUS_FILTER[alertSearchBarStateProps.status] ?? DEFAULT_FILTERS} from={alertSearchBarStateProps.rangeFrom} to={alertSearchBarStateProps.rangeTo} @@ -124,7 +128,7 @@ export function InternalRelatedAlerts({ alert, groups, tags }: Props) { return ( , - operation: WriteOperations.Update | ReadOperations.Get | ReadOperations.Find, - ruleTypeIds?: string[] + operation: WriteOperations.Update | ReadOperations.Get | ReadOperations.Find ) { const { filter } = await authorization.getAuthorizationFilter({ authorizationEntity: AlertingAuthorizationEntity.Alert, @@ -29,7 +28,6 @@ export async function getAuthzFilter( fieldNames: { consumer: ALERT_RULE_CONSUMER, ruleTypeId: ALERT_RULE_TYPE_ID }, }, operation, - ruleTypeIds, }); return filter; } diff --git a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rule_aggregations.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rule_aggregations.test.tsx index c0e143119f6fad..ff2074b2dca519 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rule_aggregations.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rule_aggregations.test.tsx @@ -73,6 +73,7 @@ describe('useLoadRuleAggregations', () => { }, enabled: true, refresh: undefined, + ruleTypeIds: [], }; const { rerender, result, waitForNextUpdate } = renderHook( @@ -94,6 +95,7 @@ describe('useLoadRuleAggregations', () => { ruleLastRunOutcomesFilter: [], ruleStatusesFilter: [], tagsFilter: [], + ruleTypeIds: [], }) ); expect(result.current.rulesStatusesTotal).toEqual(MOCK_AGGS.ruleExecutionStatus); @@ -113,6 +115,7 @@ describe('useLoadRuleAggregations', () => { }, enabled: true, refresh: undefined, + ruleTypeIds: ['foo'], }; const { rerender, result, waitForNextUpdate } = renderHook( @@ -134,6 +137,7 @@ describe('useLoadRuleAggregations', () => { ruleStatusesFilter: ['enabled', 'snoozed'] as RuleStatus[], tagsFilter: ['tag1', 'tag2'], ruleLastRunOutcomesFilter: ['outcome1', 'outcome2'], + ruleTypeIds: ['foo'], }) ); expect(result.current.rulesStatusesTotal).toEqual(MOCK_AGGS.ruleExecutionStatus); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rule_aggregations_query.ts b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rule_aggregations_query.ts index b7f5be03257297..2f5ba3bd13943b 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rule_aggregations_query.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rule_aggregations_query.ts @@ -25,12 +25,12 @@ const initializeAggregationResult = (values: readonly string[]) => { interface UseLoadRuleAggregationsQueryProps { filters: RulesListFilters; enabled: boolean; - filterConsumers?: string[]; + ruleTypeIds?: string[]; refresh?: Date; } export const useLoadRuleAggregationsQuery = (props: UseLoadRuleAggregationsQueryProps) => { - const { filters, enabled, refresh, filterConsumers } = props; + const { filters, enabled, refresh, ruleTypeIds } = props; const { http, @@ -47,7 +47,7 @@ export const useLoadRuleAggregationsQuery = (props: UseLoadRuleAggregationsQuery ruleLastRunOutcomesFilter: filters.ruleLastRunOutcomes, ruleStatusesFilter: filters.ruleStatuses, tagsFilter: filters.tags, - filterConsumers, + ruleTypeIds, }); }; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/aggregate.test.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/aggregate.test.ts index a5ae973f14d97f..f88734cd1f90dc 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/aggregate.test.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/aggregate.test.ts @@ -324,4 +324,38 @@ describe('loadRuleAggregations', () => { ] `); }); + + test('should call aggregate API with ruleTypeIds', async () => { + const resolvedValue = { + rule_execution_status: { + ok: 4, + active: 2, + error: 1, + pending: 1, + unknown: 0, + }, + }; + + http.post.mockResolvedValueOnce(resolvedValue); + + const result = await loadRuleAggregations({ http, ruleTypeIds: ['foo'] }); + expect(result).toEqual({ + ruleExecutionStatus: { + ok: 4, + active: 2, + error: 1, + pending: 1, + unknown: 0, + }, + }); + + expect(http.post.mock.calls[0]).toMatchInlineSnapshot(` + Array [ + "/internal/alerting/rules/_aggregate", + Object { + "body": "{\\"default_search_operator\\":\\"AND\\",\\"rule_type_ids\\":[\\"foo\\"]}", + }, + ] + `); + }); }); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/aggregate.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/aggregate.ts index 8edb10811bd8e3..c40679dc9dd807 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/aggregate.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/aggregate.ts @@ -44,7 +44,7 @@ export async function loadRuleAggregations({ ruleExecutionStatusesFilter, ruleStatusesFilter, tagsFilter, - filterConsumers, + ruleTypeIds, }: LoadRuleAggregationsProps): Promise { const filters = mapFiltersToKql({ typesFilter, @@ -61,7 +61,7 @@ export async function loadRuleAggregations({ search: searchText, filter: filters.length ? filters.join(' and ') : undefined, default_search_operator: 'AND', - filter_consumers: filterConsumers, + rule_type_ids: ruleTypeIds, }), } ); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/aggregate_helpers.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/aggregate_helpers.ts index 29462f07d5eec2..95a82c969a16a7 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/aggregate_helpers.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/aggregate_helpers.ts @@ -67,7 +67,7 @@ export interface LoadRuleAggregationsProps { ruleLastRunOutcomesFilter?: string[]; ruleStatusesFilter?: RuleStatus[]; tagsFilter?: string[]; - filterConsumers?: string[]; + ruleTypeIds?: string[]; } export interface LoadRuleTagsProps { diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/aggregate_kuery_filter.test.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/aggregate_kuery_filter.test.ts new file mode 100644 index 00000000000000..154b7209305ca6 --- /dev/null +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/aggregate_kuery_filter.test.ts @@ -0,0 +1,81 @@ +/* + * 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 { httpServiceMock } from '@kbn/core/public/mocks'; +import { loadRuleAggregationsWithKueryFilter } from './aggregate_kuery_filter'; + +const http = httpServiceMock.createStartContract(); + +describe('loadRuleAggregationsWithKueryFilter', () => { + beforeEach(() => jest.resetAllMocks()); + + test('should call aggregate API with base parameters', async () => { + const resolvedValue = { + rule_execution_status: { + ok: 4, + active: 2, + error: 1, + pending: 1, + unknown: 0, + }, + }; + http.post.mockResolvedValueOnce(resolvedValue); + + const result = await loadRuleAggregationsWithKueryFilter({ http }); + expect(result).toEqual({ + ruleExecutionStatus: { + ok: 4, + active: 2, + error: 1, + pending: 1, + unknown: 0, + }, + }); + expect(http.post.mock.calls[0]).toMatchInlineSnapshot(` + Array [ + "/internal/alerting/rules/_aggregate", + Object { + "body": "{\\"default_search_operator\\":\\"AND\\"}", + }, + ] + `); + }); + + test('should call aggregate API with ruleTypeIds', async () => { + const resolvedValue = { + rule_execution_status: { + ok: 4, + active: 2, + error: 1, + pending: 1, + unknown: 0, + }, + }; + + http.post.mockResolvedValueOnce(resolvedValue); + + const result = await loadRuleAggregationsWithKueryFilter({ http, ruleTypeIds: ['foo'] }); + expect(result).toEqual({ + ruleExecutionStatus: { + ok: 4, + active: 2, + error: 1, + pending: 1, + unknown: 0, + }, + }); + + expect(http.post.mock.calls[0]).toMatchInlineSnapshot(` + Array [ + "/internal/alerting/rules/_aggregate", + Object { + "body": "{\\"rule_type_ids\\":[\\"foo\\"],\\"default_search_operator\\":\\"AND\\"}", + }, + ] + `); + }); +}); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/aggregate_kuery_filter.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/aggregate_kuery_filter.ts index a0e270ddf2f67c..8e0506568820ba 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/aggregate_kuery_filter.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/aggregate_kuery_filter.ts @@ -21,7 +21,7 @@ export async function loadRuleAggregationsWithKueryFilter({ ruleExecutionStatusesFilter, ruleStatusesFilter, tagsFilter, - filterConsumers, + ruleTypeIds, }: LoadRuleAggregationsProps): Promise { const filtersKueryNode = mapFiltersToKueryNode({ typesFilter, @@ -37,7 +37,7 @@ export async function loadRuleAggregationsWithKueryFilter({ { body: JSON.stringify({ ...(filtersKueryNode ? { filter: JSON.stringify(filtersKueryNode) } : {}), - filter_consumers: filterConsumers, + rule_type_ids: ruleTypeIds, default_search_operator: 'AND', }), } diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/aggregate.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/aggregate.ts new file mode 100644 index 00000000000000..8d0718897d2c8f --- /dev/null +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/aggregate.ts @@ -0,0 +1,247 @@ +/* + * 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 expect from '@kbn/expect'; +import { Space, User } from '../../../../common/types'; +import { UserAtSpaceScenarios } from '../../../scenarios'; +import { getUrlPrefix, getTestRuleData, ObjectRemover, getEventLog } from '../../../../common/lib'; +import { FtrProviderContext } from '../../../../common/ftr_provider_context'; + +// eslint-disable-next-line import/no-default-export +export default function createAggregateTests({ getService }: FtrProviderContext) { + const supertest = getService('supertest'); + const supertestWithoutAuth = getService('supertestWithoutAuth'); + const retry = getService('retry'); + + const getEventLogWithRetry = async (id: string, space: Space) => { + await retry.try(async () => { + return await getEventLog({ + getService, + spaceId: space.id, + type: 'alert', + id, + provider: 'alerting', + actions: new Map([['execute', { equal: 1 }]]), + }); + }); + }; + + describe('aggregate', () => { + const objectRemover = new ObjectRemover(supertest); + + afterEach(async () => { + await objectRemover.removeAll(); + }); + + for (const scenario of UserAtSpaceScenarios) { + const { user, space } = scenario; + + describe(scenario.id, () => { + it('should aggregate alert status totals', async () => { + const NumOkAlerts = 4; + const NumActiveAlerts = 1; + const NumErrorAlerts = 2; + + const okAlertIds: string[] = []; + const activeAlertIds: string[] = []; + const errorAlertIds: string[] = []; + + await Promise.all( + [...Array(NumOkAlerts)].map(async () => { + const okAlertId = await createTestAlert( + { + /** + * The _aggregate calls is made + * to get all stats across all rule types + * that the user has access to. Only a subset + * of users have access to the test.restricted-noop/alertsRestrictedFixture + * pair. The differences in the stats ensure that even though we request + * the stats for all rule types only for the ones that the user has access to + * are returned. + * */ + rule_type_id: 'test.restricted-noop', + schedule: { interval: '24h' }, + consumer: 'alertsRestrictedFixture', + }, + space, + user + ); + + okAlertIds.push(okAlertId); + + objectRemover.add(space.id, okAlertId, 'rule', 'alerting'); + }) + ); + + await Promise.all(okAlertIds.map((id) => getEventLogWithRetry(id, space))); + + await Promise.all( + [...Array(NumActiveAlerts)].map(async () => { + const activeAlertId = await createTestAlert( + { + rule_type_id: 'test.patternFiring', + schedule: { interval: '24h' }, + params: { + pattern: { instance: new Array(100).fill(true) }, + }, + }, + space, + user + ); + + activeAlertIds.push(activeAlertId); + objectRemover.add(space.id, activeAlertId, 'rule', 'alerting'); + }) + ); + + await Promise.all(activeAlertIds.map((id) => getEventLogWithRetry(id, space))); + + await Promise.all( + [...Array(NumErrorAlerts)].map(async () => { + const errorAlertId = await createTestAlert( + { + rule_type_id: 'test.throw', + schedule: { interval: '24h' }, + }, + space, + user + ); + + errorAlertIds.push(errorAlertId); + objectRemover.add(space.id, errorAlertId, 'rule', 'alerting'); + }) + ); + + await Promise.all(errorAlertIds.map((id) => getEventLogWithRetry(id, space))); + + switch (scenario.id) { + case 'no_kibana_privileges at space1': + case 'space_1_all at space2': + await aggregate({ + space, + user, + expectedStatusCode: 403, + expectedResponse: { + error: 'Forbidden', + message: 'Unauthorized to find rules for any rule types', + statusCode: 403, + }, + }); + break; + case 'space_1_all at space1': + case 'space_1_all_alerts_none_actions at space1': + await aggregate({ + space, + user, + expectedStatusCode: 200, + expectedResponse: { + rule_enabled_status: { + disabled: 0, + enabled: 3, + }, + rule_execution_status: { + ok: 0, + active: NumActiveAlerts, + error: NumErrorAlerts, + pending: 0, + unknown: 0, + warning: 0, + }, + rule_last_run_outcome: { + succeeded: 1, + warning: 0, + failed: 2, + }, + rule_muted_status: { + muted: 0, + unmuted: 3, + }, + rule_snoozed_status: { + snoozed: 0, + }, + rule_tags: ['foo'], + }, + }); + break; + case 'global_read at space1': + case 'superuser at space1': + case 'space_1_all_with_restricted_fixture at space1': + await aggregate({ + space, + user, + expectedStatusCode: 200, + expectedResponse: { + rule_enabled_status: { + disabled: 0, + enabled: 7, + }, + rule_execution_status: { + ok: NumOkAlerts, + active: NumActiveAlerts, + error: NumErrorAlerts, + pending: 0, + unknown: 0, + warning: 0, + }, + rule_last_run_outcome: { + succeeded: 5, + warning: 0, + failed: 2, + }, + rule_muted_status: { + muted: 0, + unmuted: 7, + }, + rule_snoozed_status: { + snoozed: 0, + }, + rule_tags: ['foo'], + }, + }); + break; + default: + throw new Error(`Scenario untested: ${JSON.stringify(scenario)}`); + } + }); + }); + } + }); + + async function createTestAlert(testAlertOverrides = {}, space: Space, user: User) { + const { body: createdAlert } = await supertest + .post(`${getUrlPrefix(space.id)}/api/alerting/rule`) + .set('kbn-xsrf', 'foo') + .send(getTestRuleData(testAlertOverrides)) + .auth(user.username, user.password) + .expect(200); + + return createdAlert.id; + } + + const aggregate = async ({ + space, + user, + expectedStatusCode, + expectedResponse, + }: { + space: Space; + user: User; + expectedStatusCode: number; + expectedResponse: Record; + }) => { + await retry.try(async () => { + const response = await supertestWithoutAuth + .post(`${getUrlPrefix(space.id)}/internal/alerting/rules/_aggregate`) + .set('kbn-xsrf', 'foo') + .auth(user.username, user.password) + .send({}); + + expect(response.status).to.eql(expectedStatusCode); + expect(response.body).to.eql(expectedResponse); + }); + }; +} diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/index.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/index.ts index 245425e0bbfeab..57812331cdff8f 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/index.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/index.ts @@ -32,6 +32,7 @@ export default function alertingTests({ loadTestFile, getService }: FtrProviderC await tearDown(getService); }); + loadTestFile(require.resolve('./aggregate')); loadTestFile(require.resolve('./mute_all')); loadTestFile(require.resolve('./mute_instance')); loadTestFile(require.resolve('./unmute_all')); diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/aggregate_post.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/aggregate.ts similarity index 67% rename from x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/aggregate_post.ts rename to x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/aggregate.ts index 6269e9bff6e2bc..57181eb00a05a5 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/aggregate_post.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/aggregate.ts @@ -28,10 +28,12 @@ export default function createAggregateTests({ getService }: FtrProviderContext) }); }; - describe('aggregate post', () => { + describe('aggregate', () => { const objectRemover = new ObjectRemover(supertest); - afterEach(() => objectRemover.removeAll()); + afterEach(async () => { + await objectRemover.removeAll(); + }); it('should aggregate when there are no alerts', async () => { const response = await supertest @@ -157,6 +159,94 @@ export default function createAggregateTests({ getService }: FtrProviderContext) }); }); + it('should aggregate only filtered rules', async () => { + const NumOkAlerts = 4; + const NumActiveAlerts = 1; + const NumErrorAlerts = 2; + + const okAlertIds: string[] = []; + const activeAlertIds: string[] = []; + const errorAlertIds: string[] = []; + + await Promise.all( + [...Array(NumOkAlerts)].map(async () => { + const okAlertId = await createTestAlert({ + rule_type_id: 'test.noop', + schedule: { interval: '24h' }, + }); + okAlertIds.push(okAlertId); + objectRemover.add(Spaces.space1.id, okAlertId, 'rule', 'alerting'); + }) + ); + + await Promise.all(okAlertIds.map((id) => getEventLogWithRetry(id))); + + await Promise.all( + [...Array(NumActiveAlerts)].map(async () => { + const activeAlertId = await createTestAlert({ + rule_type_id: 'test.patternFiring', + schedule: { interval: '24h' }, + params: { + pattern: { instance: new Array(100).fill(true) }, + }, + }); + activeAlertIds.push(activeAlertId); + objectRemover.add(Spaces.space1.id, activeAlertId, 'rule', 'alerting'); + }) + ); + + await Promise.all(activeAlertIds.map((id) => getEventLogWithRetry(id))); + + await Promise.all( + [...Array(NumErrorAlerts)].map(async () => { + const errorAlertId = await createTestAlert({ + rule_type_id: 'test.throw', + schedule: { interval: '24h' }, + }); + errorAlertIds.push(errorAlertId); + objectRemover.add(Spaces.space1.id, errorAlertId, 'rule', 'alerting'); + }) + ); + + await Promise.all(errorAlertIds.map((id) => getEventLogWithRetry(id))); + + await retry.try(async () => { + const response = await supertest + .post(`${getUrlPrefix(Spaces.space1.id)}/internal/alerting/rules/_aggregate`) + .set('kbn-xsrf', 'foo') + .send({ rule_type_ids: ['test.noop'] }); + + expect(response.status).to.eql(200); + expect(response.body).to.eql({ + rule_enabled_status: { + disabled: 0, + enabled: 4, + }, + rule_execution_status: { + ok: NumOkAlerts, + active: 0, + error: 0, + pending: 0, + unknown: 0, + warning: 0, + }, + rule_last_run_outcome: { + succeeded: 4, + warning: 0, + failed: 0, + }, + rule_muted_status: { + muted: 0, + unmuted: 4, + }, + rule_snoozed_status: { + snoozed: 0, + }, + rule_tags: ['foo'], + }); + }); + }); + describe('tags limit', () => { it('should be 50 be default', async () => { const numOfAlerts = 3; diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/index.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/index.ts index 7a0c24878d07fc..458bc887d02d15 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/index.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/index.ts @@ -14,7 +14,7 @@ export default function alertingTests({ loadTestFile, getService }: FtrProviderC before(async () => await buildUp(getService)); after(async () => await tearDown(getService)); - loadTestFile(require.resolve('./aggregate_post')); + loadTestFile(require.resolve('./aggregate')); loadTestFile(require.resolve('./create')); loadTestFile(require.resolve('./delete')); loadTestFile(require.resolve('./disable')); From 4532eff0437ac5463471447743b4688b1cd935c4 Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Fri, 27 Sep 2024 16:57:05 +0300 Subject: [PATCH 065/106] Add support of rule_type_ids in the Find API --- .../common/routes/rule/apis/find/index.ts | 7 +- .../routes/rule/apis/find/schemas/v1.ts | 37 +- .../common/routes/rule/apis/find/types/v1.ts | 3 +- .../rule/methods/find/find_rules.test.ts | 52 +- .../rule/methods/find/find_rules.ts | 23 +- .../find/schemas/find_rules_schemas.ts | 3 +- .../methods/find/types/find_rules_types.ts | 1 - .../rule/apis/find/find_rules_route.test.ts | 829 ++++++++++-------- .../routes/rule/apis/find/find_rules_route.ts | 138 +-- .../transform_find_rules_body/v1.ts | 40 +- .../public/pages/rules/rules_tab.tsx | 5 +- .../application/hooks/use_load_rules_query.ts | 8 +- .../public/application/lib/rule_api/rules.ts | 2 + .../application/lib/rule_api/rules_helpers.ts | 2 +- .../lib/rule_api/rules_kuery_filter.ts | 4 +- .../rules_list/components/rules_list.test.tsx | 2 +- .../group1/tests/alerting/find.ts | 238 ++--- .../{find_with_post.ts => find_internal.ts} | 273 +++--- .../group1/tests/alerting/index.ts | 2 +- .../spaces_only/tests/alerting/group1/find.ts | 23 + 20 files changed, 967 insertions(+), 725 deletions(-) rename x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/{find_with_post.ts => find_internal.ts} (76%) diff --git a/x-pack/plugins/alerting/common/routes/rule/apis/find/index.ts b/x-pack/plugins/alerting/common/routes/rule/apis/find/index.ts index 7722521d2b7074..308fabf56372a0 100644 --- a/x-pack/plugins/alerting/common/routes/rule/apis/find/index.ts +++ b/x-pack/plugins/alerting/common/routes/rule/apis/find/index.ts @@ -8,8 +8,13 @@ export { findRulesRequestQuerySchema } from './schemas/latest'; export type { FindRulesRequestQuery, FindRulesResponse } from './types/latest'; -export { findRulesRequestQuerySchema as findRulesRequestQuerySchemaV1 } from './schemas/v1'; +export { + findRulesRequestQuerySchema as findRulesRequestQuerySchemaV1, + findRulesInternalRequestQuerySchema as findRulesInternalRequestQuerySchemaV1, +} from './schemas/v1'; + export type { FindRulesRequestQuery as FindRulesRequestQueryV1, + FindRulesInternalRequestQuery as FindRulesInternalRequestQueryV1, FindRulesResponse as FindRulesResponseV1, } from './types/latest'; diff --git a/x-pack/plugins/alerting/common/routes/rule/apis/find/schemas/v1.ts b/x-pack/plugins/alerting/common/routes/rule/apis/find/schemas/v1.ts index 1dece949a9556d..17470025be8bf0 100644 --- a/x-pack/plugins/alerting/common/routes/rule/apis/find/schemas/v1.ts +++ b/x-pack/plugins/alerting/common/routes/rule/apis/find/schemas/v1.ts @@ -93,13 +93,38 @@ export const findRulesRequestQuerySchema = schema.object({ }, }) ), - filter_consumers: schema.maybe( - schema.arrayOf( - schema.string({ - meta: { - description: 'List of consumers to filter.', - }, +}); + +export const findRulesInternalRequestQuerySchema = schema.object({ + per_page: schema.number({ + defaultValue: 10, + min: 0, + }), + page: schema.number({ + defaultValue: 1, + min: 1, + meta: { + description: 'The page number to return.', + }, + }), + search: schema.maybe(schema.string()), + default_search_operator: schema.oneOf([schema.literal('OR'), schema.literal('AND')], { + defaultValue: 'OR', + }), + search_fields: schema.maybe(schema.oneOf([schema.arrayOf(schema.string()), schema.string()])), + sort_field: schema.maybe(schema.string()), + sort_order: schema.maybe(schema.oneOf([schema.literal('asc'), schema.literal('desc')])), + has_reference: schema.maybe( + // use nullable as maybe is currently broken + // in config-schema + schema.nullable( + schema.object({ + type: schema.string(), + id: schema.string(), }) ) ), + fields: schema.maybe(schema.arrayOf(schema.string())), + filter: schema.maybe(schema.string()), + rule_type_ids: schema.maybe(schema.arrayOf(schema.string())), }); diff --git a/x-pack/plugins/alerting/common/routes/rule/apis/find/types/v1.ts b/x-pack/plugins/alerting/common/routes/rule/apis/find/types/v1.ts index 271e791282f43a..ca497be58c1857 100644 --- a/x-pack/plugins/alerting/common/routes/rule/apis/find/types/v1.ts +++ b/x-pack/plugins/alerting/common/routes/rule/apis/find/types/v1.ts @@ -7,9 +7,10 @@ import type { TypeOf } from '@kbn/config-schema'; import { RuleParamsV1, RuleResponseV1 } from '../../../response'; -import { findRulesRequestQuerySchemaV1 } from '..'; +import { findRulesRequestQuerySchemaV1, findRulesInternalRequestQuerySchemaV1 } from '..'; export type FindRulesRequestQuery = TypeOf; +export type FindRulesInternalRequestQuery = TypeOf; export interface FindRulesResponse { body: { diff --git a/x-pack/plugins/alerting/server/application/rule/methods/find/find_rules.test.ts b/x-pack/plugins/alerting/server/application/rule/methods/find/find_rules.test.ts index 6a3b22714ef7ba..6742a4b2292715 100644 --- a/x-pack/plugins/alerting/server/application/rule/methods/find/find_rules.test.ts +++ b/x-pack/plugins/alerting/server/application/rule/methods/find/find_rules.test.ts @@ -15,7 +15,7 @@ import { import { taskManagerMock } from '@kbn/task-manager-plugin/server/mocks'; import { ruleTypeRegistryMock } from '../../../../rule_type_registry.mock'; import { alertingAuthorizationMock } from '../../../../authorization/alerting_authorization.mock'; -import { nodeTypes, fromKueryExpression } from '@kbn/es-query'; +import { nodeTypes, fromKueryExpression, toKqlExpression } from '@kbn/es-query'; import { encryptedSavedObjectsMock } from '@kbn/encrypted-saved-objects-plugin/server/mocks'; import { actionsAuthorizationMock } from '@kbn/actions-plugin/server/mocks'; import { AlertingAuthorization } from '../../../../authorization/alerting_authorization'; @@ -226,7 +226,7 @@ describe('find()', () => { Array [ Object { "fields": undefined, - "filter": null, + "filter": undefined, "sortField": undefined, "type": "alert", }, @@ -340,7 +340,7 @@ describe('find()', () => { Array [ Object { "fields": undefined, - "filter": null, + "filter": undefined, "sortField": undefined, "type": "alert", }, @@ -452,7 +452,7 @@ describe('find()', () => { Array [ Object { "fields": undefined, - "filter": null, + "filter": undefined, "sortField": undefined, "type": "alert", }, @@ -1025,12 +1025,54 @@ describe('find()', () => { expect(unsecuredSavedObjectsClient.find).toHaveBeenCalledWith({ fields: ['tags', 'alertTypeId', 'consumer'], - filter: null, + filter: undefined, sortField: undefined, type: RULE_SAVED_OBJECT_TYPE, }); expect(ensureRuleTypeIsAuthorized).toHaveBeenCalledWith('myType', 'myApp', 'rule'); }); + + test('calls getFindAuthorizationFilter correctly', async () => { + authorization.getFindAuthorizationFilter.mockResolvedValue({ + ensureRuleTypeIsAuthorized() {}, + }); + + const rulesClient = new RulesClient(rulesClientParams); + await rulesClient.find({ options: { ruleTypeIds: ['foo'] } }); + + expect(authorization.getFindAuthorizationFilter).toHaveBeenCalledWith({ + authorizationEntity: 'rule', + filterOpts: { + fieldNames: { + consumer: 'alert.attributes.consumer', + ruleTypeId: 'alert.attributes.alertTypeId', + }, + type: 'kql', + }, + }); + }); + + test('combines the filters with the auth filter correctly', async () => { + const filter = fromKueryExpression( + 'alert.attributes.alertTypeId:myType and alert.attributes.consumer:myApp' + ); + + authorization.getFindAuthorizationFilter.mockResolvedValue({ + filter, + ensureRuleTypeIsAuthorized() {}, + }); + + const rulesClient = new RulesClient(rulesClientParams); + await rulesClient.find({ + options: { ruleTypeIds: ['foo'], filter: `alert.attributes.tags: ['bar']` }, + }); + + const finalFilter = unsecuredSavedObjectsClient.find.mock.calls[0][0].filter; + + expect(toKqlExpression(finalFilter)).toMatchInlineSnapshot( + `"((alert.attributes.tags: ['bar'] AND alert.attributes.alertTypeId: foo) AND (alert.attributes.alertTypeId: myType AND alert.attributes.consumer: myApp))"` + ); + }); }); describe('auditLogger', () => { diff --git a/x-pack/plugins/alerting/server/application/rule/methods/find/find_rules.ts b/x-pack/plugins/alerting/server/application/rule/methods/find/find_rules.ts index e3ad28f35c6867..3529cac8fb4bfa 100644 --- a/x-pack/plugins/alerting/server/application/rule/methods/find/find_rules.ts +++ b/x-pack/plugins/alerting/server/application/rule/methods/find/find_rules.ts @@ -7,8 +7,13 @@ import Boom from '@hapi/boom'; import { pick } from 'lodash'; -import { KueryNode, nodeBuilder } from '@kbn/es-query'; +import { KueryNode } from '@kbn/es-query'; import { AlertConsumers } from '@kbn/rule-data-utils'; +import { + buildRuleTypeIdsFilter, + combineFilterWithAuthorizationFilter, + combineFilters, +} from '../../../../rules_client/common/filters'; import { AlertingAuthorizationEntity } from '../../../../authorization/types'; import { SanitizedRule, Rule as DeprecatedRule, RawRule } from '../../../../types'; import { ruleAuditEvent, RuleAuditAction } from '../../../../rules_client/common/audit_events'; @@ -46,7 +51,7 @@ export async function findRules( ): Promise> { const { options, excludeFromPublicApi = false, includeSnoozeData = false } = params || {}; - const { fields, filterRuleTypeIds, ...restOptions } = options || {}; + const { fields, ruleTypeIds, ...restOptions } = options || {}; try { if (params) { @@ -61,7 +66,6 @@ export async function findRules( authorizationTuple = await context.authorization.getFindAuthorizationFilter({ authorizationEntity: AlertingAuthorizationEntity.Rule, filterOpts: alertingAuthorizationFilterOpts, - ruleTypeIds: filterRuleTypeIds, }); } catch (error) { context.auditLogger?.log( @@ -76,6 +80,7 @@ export async function findRules( const { filter: authorizationFilter, ensureRuleTypeIsAuthorized } = authorizationTuple; const filterKueryNode = buildKueryNodeFilter(restOptions.filter as string | KueryNode); let sortField = mapSortField(restOptions.sortField); + if (excludeFromPublicApi) { try { validateOperationOnAttributes( @@ -111,6 +116,13 @@ export async function findRules( modifyFilterKueryNode({ astFilter: filterKueryNode }); } + const ruleTypeIdsFilter = buildRuleTypeIdsFilter(ruleTypeIds); + const combinedFilters = combineFilters([filterKueryNode, ruleTypeIdsFilter]); + const finalFilter = combineFilterWithAuthorizationFilter( + combinedFilters, + authorizationFilter as KueryNode + ); + const { page, per_page: perPage, @@ -121,10 +133,7 @@ export async function findRules( savedObjectsFindOptions: { ...modifiedOptions, sortField, - filter: - (authorizationFilter && filterKueryNode - ? nodeBuilder.and([filterKueryNode, authorizationFilter as KueryNode]) - : authorizationFilter) ?? filterKueryNode, + filter: finalFilter, fields: fields ? includeFieldsRequiredForAuthentication(fields) : fields, }, }); diff --git a/x-pack/plugins/alerting/server/application/rule/methods/find/schemas/find_rules_schemas.ts b/x-pack/plugins/alerting/server/application/rule/methods/find/schemas/find_rules_schemas.ts index 31d6cadaebff0b..62e6dd94a8497a 100644 --- a/x-pack/plugins/alerting/server/application/rule/methods/find/schemas/find_rules_schemas.ts +++ b/x-pack/plugins/alerting/server/application/rule/methods/find/schemas/find_rules_schemas.ts @@ -28,7 +28,7 @@ export const findRulesOptionsSchema = schema.object( filter: schema.maybe( schema.oneOf([schema.string(), schema.recordOf(schema.string(), schema.any())]) ), - filterRuleTypeIds: schema.maybe(schema.arrayOf(schema.string())), + ruleTypeIds: schema.maybe(schema.arrayOf(schema.string())), }, { unknowns: 'allow' } ); @@ -37,5 +37,4 @@ export const findRulesParamsSchema = schema.object({ options: schema.maybe(findRulesOptionsSchema), excludeFromPublicApi: schema.maybe(schema.boolean()), includeSnoozeData: schema.maybe(schema.boolean()), - ruleTypeIds: schema.maybe(schema.arrayOf(schema.string())), }); diff --git a/x-pack/plugins/alerting/server/application/rule/methods/find/types/find_rules_types.ts b/x-pack/plugins/alerting/server/application/rule/methods/find/types/find_rules_types.ts index 615a5b5db8672f..77694f150c5a9e 100644 --- a/x-pack/plugins/alerting/server/application/rule/methods/find/types/find_rules_types.ts +++ b/x-pack/plugins/alerting/server/application/rule/methods/find/types/find_rules_types.ts @@ -9,5 +9,4 @@ import { TypeOf } from '@kbn/config-schema'; import { findRulesOptionsSchema, findRulesParamsSchema } from '../schemas'; export type FindRulesOptions = TypeOf; - export type FindRulesParams = TypeOf; diff --git a/x-pack/plugins/alerting/server/routes/rule/apis/find/find_rules_route.test.ts b/x-pack/plugins/alerting/server/routes/rule/apis/find/find_rules_route.test.ts index 4e3c9b635ec3ac..0b4d4af0d654ce 100644 --- a/x-pack/plugins/alerting/server/routes/rule/apis/find/find_rules_route.test.ts +++ b/x-pack/plugins/alerting/server/routes/rule/apis/find/find_rules_route.test.ts @@ -5,7 +5,7 @@ * 2.0. */ import { usageCountersServiceMock } from '@kbn/usage-collection-plugin/server/usage_counters/usage_counters_service.mock'; -import { findRulesRoute } from './find_rules_route'; +import { findInternalRulesRoute, findRulesRoute } from './find_rules_route'; import { httpServiceMock } from '@kbn/core/server/mocks'; import { licenseStateMock } from '../../../../lib/license_state.mock'; import { verifyApiAccess } from '../../../../lib/license_api_access'; @@ -30,408 +30,549 @@ beforeEach(() => { }); describe('findRulesRoute', () => { - it('finds rules with proper parameters', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); + describe('Public', () => { + it('finds rules with proper parameters', async () => { + const licenseState = licenseStateMock.create(); + const router = httpServiceMock.createRouter(); - findRulesRoute(router, licenseState); + findRulesRoute(router, licenseState); - const [config, handler] = router.get.mock.calls[0]; + const [config, handler] = router.get.mock.calls[0]; - expect(config.path).toMatchInlineSnapshot(`"/api/alerting/rules/_find"`); + expect(config.path).toMatchInlineSnapshot(`"/api/alerting/rules/_find"`); - const findResult = { - page: 1, - perPage: 1, - total: 0, - data: [], - }; - rulesClient.find.mockResolvedValueOnce(findResult); + const findResult = { + page: 1, + perPage: 1, + total: 0, + data: [], + }; + rulesClient.find.mockResolvedValueOnce(findResult); - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { - query: { - per_page: 1, - page: 1, - default_search_operator: 'OR', - }, - }, - ['ok'] - ); - - expect(await handler(context, req, res)).toMatchInlineSnapshot(` - Object { - "body": Object { - "data": Array [], - "page": 1, - "per_page": 1, - "total": 0, - }, - } - `); - - expect(rulesClient.find).toHaveBeenCalledTimes(1); - expect(rulesClient.find.mock.calls[0]).toMatchInlineSnapshot(` - Array [ - Object { - "excludeFromPublicApi": true, - "includeSnoozeData": true, - "options": Object { - "defaultSearchOperator": "OR", - "page": 1, - "perPage": 1, + const [context, req, res] = mockHandlerArguments( + { rulesClient }, + { + query: { + per_page: 1, + page: 1, + default_search_operator: 'OR', }, }, - ] - `); + ['ok'] + ); + + expect(await handler(context, req, res)).toMatchInlineSnapshot(` + Object { + "body": Object { + "data": Array [], + "page": 1, + "per_page": 1, + "total": 0, + }, + } + `); - expect(res.ok).toHaveBeenCalledWith({ - body: { - page: 1, - per_page: 1, - total: 0, - data: [], - }, + expect(rulesClient.find).toHaveBeenCalledTimes(1); + expect(rulesClient.find.mock.calls[0]).toMatchInlineSnapshot(` + Array [ + Object { + "excludeFromPublicApi": true, + "includeSnoozeData": true, + "options": Object { + "defaultSearchOperator": "OR", + "page": 1, + "perPage": 1, + }, + }, + ] + `); + + expect(res.ok).toHaveBeenCalledWith({ + body: { + page: 1, + per_page: 1, + total: 0, + data: [], + }, + }); }); - }); - it('should rewrite the rule and actions correctly', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); + it('should rewrite the rule and actions correctly', async () => { + const licenseState = licenseStateMock.create(); + const router = httpServiceMock.createRouter(); - findRulesRoute(router, licenseState); + findRulesRoute(router, licenseState); - const [config, handler] = router.get.mock.calls[0]; + const [config, handler] = router.get.mock.calls[0]; - expect(config.path).toMatchInlineSnapshot(`"/api/alerting/rules/_find"`); + expect(config.path).toMatchInlineSnapshot(`"/api/alerting/rules/_find"`); - const findResult = { - page: 1, - perPage: 1, - total: 0, - data: [ - { - id: '3d534c70-582b-11ec-8995-2b1578a3bc5d', - notifyWhen: 'onActiveAlert' as const, - alertTypeId: '.index-threshold', - name: 'stressing index-threshold 37/200', - consumer: 'alerts', - tags: [], - enabled: true, - throttle: null, - apiKey: null, - apiKeyOwner: '2889684073', - createdBy: 'elastic', - updatedBy: '2889684073', - muteAll: false, - mutedInstanceIds: [], - schedule: { - interval: '1s', - }, - snoozeSchedule: [], - actions: [ - { - actionTypeId: '.server-log', - params: { - message: 'alert 37: {{context.message}}', + const findResult = { + page: 1, + perPage: 1, + total: 0, + data: [ + { + id: '3d534c70-582b-11ec-8995-2b1578a3bc5d', + notifyWhen: 'onActiveAlert' as const, + alertTypeId: '.index-threshold', + name: 'stressing index-threshold 37/200', + consumer: 'alerts', + tags: [], + enabled: true, + throttle: null, + apiKey: null, + apiKeyOwner: '2889684073', + createdBy: 'elastic', + updatedBy: '2889684073', + muteAll: false, + mutedInstanceIds: [], + schedule: { + interval: '1s', + }, + snoozeSchedule: [], + actions: [ + { + actionTypeId: '.server-log', + params: { + message: 'alert 37: {{context.message}}', + }, + group: 'threshold met', + id: '3619a0d0-582b-11ec-8995-2b1578a3bc5d', + uuid: '123-456', }, - group: 'threshold met', - id: '3619a0d0-582b-11ec-8995-2b1578a3bc5d', - uuid: '123-456', + ], + systemActions: [ + { actionTypeId: '.test', id: 'system_action-id', params: {}, uuid: '789' }, + ], + params: { x: 42 }, + updatedAt: new Date('2024-03-21T13:15:00.498Z'), + createdAt: new Date('2024-03-21T13:15:00.498Z'), + scheduledTaskId: '52125fb0-5895-11ec-ae69-bb65d1a71b72', + executionStatus: { + status: 'ok' as const, + lastExecutionDate: new Date('2024-03-21T13:15:00.498Z'), + lastDuration: 1194, }, - ], - systemActions: [ - { actionTypeId: '.test', id: 'system_action-id', params: {}, uuid: '789' }, - ], - params: { x: 42 }, - updatedAt: new Date('2024-03-21T13:15:00.498Z'), - createdAt: new Date('2024-03-21T13:15:00.498Z'), - scheduledTaskId: '52125fb0-5895-11ec-ae69-bb65d1a71b72', - executionStatus: { - status: 'ok' as const, - lastExecutionDate: new Date('2024-03-21T13:15:00.498Z'), - lastDuration: 1194, + revision: 0, }, - revision: 0, - }, - ], - }; + ], + }; - rulesClient.find.mockResolvedValueOnce(findResult); + rulesClient.find.mockResolvedValueOnce(findResult); - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { - query: { - per_page: 1, - page: 1, - default_search_operator: 'OR', + const [context, req, res] = mockHandlerArguments( + { rulesClient }, + { + query: { + per_page: 1, + page: 1, + default_search_operator: 'OR', + }, }, - }, - ['ok'] - ); - - expect(await handler(context, req, res)).toMatchInlineSnapshot(` - Object { - "body": Object { - "data": Array [ - Object { - "actions": Array [ + ['ok'] + ); + + expect(await handler(context, req, res)).toMatchInlineSnapshot(` + Object { + "body": Object { + "data": Array [ + Object { + "actions": Array [ + Object { + "connector_type_id": ".server-log", + "group": "threshold met", + "id": "3619a0d0-582b-11ec-8995-2b1578a3bc5d", + "params": Object { + "message": "alert 37: {{context.message}}", + }, + "uuid": "123-456", + }, + Object { + "connector_type_id": ".test", + "id": "system_action-id", + "params": Object {}, + "uuid": "789", + }, + ], + "api_key_owner": "2889684073", + "consumer": "alerts", + "created_at": "2024-03-21T13:15:00.498Z", + "created_by": "elastic", + "enabled": true, + "execution_status": Object { + "last_duration": 1194, + "last_execution_date": "2024-03-21T13:15:00.498Z", + "status": "ok", + }, + "id": "3d534c70-582b-11ec-8995-2b1578a3bc5d", + "mute_all": false, + "muted_alert_ids": Array [], + "name": "stressing index-threshold 37/200", + "notify_when": "onActiveAlert", + "params": Object { + "x": 42, + }, + "revision": 0, + "rule_type_id": ".index-threshold", + "schedule": Object { + "interval": "1s", + }, + "scheduled_task_id": "52125fb0-5895-11ec-ae69-bb65d1a71b72", + "snooze_schedule": Array [], + "tags": Array [], + "throttle": null, + "updated_at": "2024-03-21T13:15:00.498Z", + "updated_by": "2889684073", + }, + ], + "page": 1, + "per_page": 1, + "total": 0, + }, + } + `); + + expect(rulesClient.find).toHaveBeenCalledTimes(1); + expect(rulesClient.find.mock.calls[0]).toMatchInlineSnapshot(` + Array [ Object { - "connector_type_id": ".server-log", - "group": "threshold met", - "id": "3619a0d0-582b-11ec-8995-2b1578a3bc5d", - "params": Object { - "message": "alert 37: {{context.message}}", + "excludeFromPublicApi": true, + "includeSnoozeData": true, + "options": Object { + "defaultSearchOperator": "OR", + "page": 1, + "perPage": 1, }, - "uuid": "123-456", }, - Object { - "connector_type_id": ".test", - "id": "system_action-id", - "params": Object {}, - "uuid": "789", + ] + `); + + expect(res.ok).toHaveBeenCalledWith({ + body: { + page: 1, + per_page: 1, + total: 0, + data: [ + { + actions: [ + { + connector_type_id: '.server-log', + group: 'threshold met', + id: '3619a0d0-582b-11ec-8995-2b1578a3bc5d', + params: { + message: 'alert 37: {{context.message}}', + }, + uuid: '123-456', + }, + { + connector_type_id: '.test', + id: 'system_action-id', + params: {}, + uuid: '789', }, ], - "api_key_owner": "2889684073", - "consumer": "alerts", - "created_at": "2024-03-21T13:15:00.498Z", - "created_by": "elastic", - "enabled": true, - "execution_status": Object { - "last_duration": 1194, - "last_execution_date": "2024-03-21T13:15:00.498Z", - "status": "ok", + api_key_owner: '2889684073', + consumer: 'alerts', + created_at: '2024-03-21T13:15:00.498Z', + created_by: 'elastic', + enabled: true, + execution_status: { + last_duration: 1194, + last_execution_date: '2024-03-21T13:15:00.498Z', + status: 'ok', }, - "id": "3d534c70-582b-11ec-8995-2b1578a3bc5d", - "mute_all": false, - "muted_alert_ids": Array [], - "name": "stressing index-threshold 37/200", - "notify_when": "onActiveAlert", - "params": Object { - "x": 42, + id: '3d534c70-582b-11ec-8995-2b1578a3bc5d', + mute_all: false, + muted_alert_ids: [], + name: 'stressing index-threshold 37/200', + notify_when: 'onActiveAlert', + params: { + x: 42, }, - "revision": 0, - "rule_type_id": ".index-threshold", - "schedule": Object { - "interval": "1s", + revision: 0, + rule_type_id: '.index-threshold', + schedule: { + interval: '1s', }, - "scheduled_task_id": "52125fb0-5895-11ec-ae69-bb65d1a71b72", - "snooze_schedule": Array [], - "tags": Array [], - "throttle": null, - "updated_at": "2024-03-21T13:15:00.498Z", - "updated_by": "2889684073", + scheduled_task_id: '52125fb0-5895-11ec-ae69-bb65d1a71b72', + snooze_schedule: [], + tags: [], + throttle: null, + updated_at: '2024-03-21T13:15:00.498Z', + updated_by: '2889684073', }, ], - "page": 1, - "per_page": 1, - "total": 0, }, - } - `); - - expect(rulesClient.find).toHaveBeenCalledTimes(1); - expect(rulesClient.find.mock.calls[0]).toMatchInlineSnapshot(` - Array [ - Object { - "excludeFromPublicApi": true, - "includeSnoozeData": true, - "options": Object { - "defaultSearchOperator": "OR", - "page": 1, - "perPage": 1, - }, - }, - ] - `); + }); + }); + + it('ensures the license allows finding rules', async () => { + const licenseState = licenseStateMock.create(); + const router = httpServiceMock.createRouter(); + + findRulesRoute(router, licenseState); - expect(res.ok).toHaveBeenCalledWith({ - body: { + const [, handler] = router.get.mock.calls[0]; + + rulesClient.find.mockResolvedValueOnce({ page: 1, - per_page: 1, + perPage: 1, total: 0, - data: [ - { - actions: [ - { - connector_type_id: '.server-log', - group: 'threshold met', - id: '3619a0d0-582b-11ec-8995-2b1578a3bc5d', - params: { - message: 'alert 37: {{context.message}}', - }, - uuid: '123-456', - }, - { - connector_type_id: '.test', - id: 'system_action-id', - params: {}, - uuid: '789', - }, - ], - api_key_owner: '2889684073', - consumer: 'alerts', - created_at: '2024-03-21T13:15:00.498Z', - created_by: 'elastic', - enabled: true, - execution_status: { - last_duration: 1194, - last_execution_date: '2024-03-21T13:15:00.498Z', - status: 'ok', - }, - id: '3d534c70-582b-11ec-8995-2b1578a3bc5d', - mute_all: false, - muted_alert_ids: [], - name: 'stressing index-threshold 37/200', - notify_when: 'onActiveAlert', - params: { - x: 42, - }, - revision: 0, - rule_type_id: '.index-threshold', - schedule: { - interval: '1s', - }, - scheduled_task_id: '52125fb0-5895-11ec-ae69-bb65d1a71b72', - snooze_schedule: [], - tags: [], - throttle: null, - updated_at: '2024-03-21T13:15:00.498Z', - updated_by: '2889684073', + data: [], + }); + + const [context, req, res] = mockHandlerArguments( + { rulesClient }, + { + query: { + per_page: 1, + page: 1, + default_search_operator: 'OR', }, - ], - }, + } + ); + + await handler(context, req, res); + + expect(verifyApiAccess).toHaveBeenCalledWith(licenseState); }); - }); - it('ensures the license allows finding rules', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); + it('ensures the license check prevents finding rules', async () => { + const licenseState = licenseStateMock.create(); + const router = httpServiceMock.createRouter(); + + (verifyApiAccess as jest.Mock).mockImplementation(() => { + throw new Error('OMG'); + }); + + findRulesRoute(router, licenseState); - findRulesRoute(router, licenseState); + const [, handler] = router.get.mock.calls[0]; - const [, handler] = router.get.mock.calls[0]; + const [context, req, res] = mockHandlerArguments( + {}, + { + query: { + per_page: 1, + page: 1, + default_search_operator: 'OR', + }, + }, + ['ok'] + ); + await expect(handler(context, req, res)).rejects.toMatchInlineSnapshot(`[Error: OMG]`); - rulesClient.find.mockResolvedValueOnce({ - page: 1, - perPage: 1, - total: 0, - data: [], + expect(verifyApiAccess).toHaveBeenCalledWith(licenseState); }); - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { - query: { - per_page: 1, - page: 1, - default_search_operator: 'OR', + it('should track calls with deprecated param values', async () => { + const licenseState = licenseStateMock.create(); + const router = httpServiceMock.createRouter(); + + findRulesRoute(router, licenseState, mockUsageCounter); + const findResult = { + page: 1, + perPage: 1, + total: 0, + data: [], + }; + rulesClient.find.mockResolvedValueOnce(findResult); + const [, handler] = router.get.mock.calls[0]; + const [context, req, res] = mockHandlerArguments( + { rulesClient }, + { + params: {}, + query: { + search_fields: ['alertTypeId:1', 'message:foo'], + search: 'alertTypeId:2', + sort_field: 'alertTypeId', + }, }, - } - ); + ['ok'] + ); + await handler(context, req, res); + expect(trackLegacyTerminology).toHaveBeenCalledTimes(1); + expect((trackLegacyTerminology as jest.Mock).mock.calls[0][0]).toStrictEqual([ + 'alertTypeId:2', + ['alertTypeId:1', 'message:foo'], + 'alertTypeId', + ]); + }); - await handler(context, req, res); + it('should track calls to deprecated functionality', async () => { + const licenseState = licenseStateMock.create(); + const router = httpServiceMock.createRouter(); - expect(verifyApiAccess).toHaveBeenCalledWith(licenseState); - }); + findRulesRoute(router, licenseState, mockUsageCounter); - it('ensures the license check prevents finding rules', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); + const findResult = { + page: 1, + perPage: 1, + total: 0, + data: [], + }; + rulesClient.find.mockResolvedValueOnce(findResult); - (verifyApiAccess as jest.Mock).mockImplementation(() => { - throw new Error('OMG'); + const [, handler] = router.get.mock.calls[0]; + const [context, req, res] = mockHandlerArguments( + { rulesClient }, + { + params: {}, + query: { + fields: ['foo', 'bar'], + per_page: 1, + page: 1, + default_search_operator: 'OR', + }, + }, + ['ok'] + ); + await handler(context, req, res); + expect(mockUsageCounter.incrementCounter).toHaveBeenCalledWith({ + counterName: `alertingFieldsUsage`, + counterType: 'alertingFieldsUsage', + incrementBy: 1, + }); }); - findRulesRoute(router, licenseState); + it('should not support rule_type_ids', async () => { + const licenseState = licenseStateMock.create(); + const router = httpServiceMock.createRouter(); - const [, handler] = router.get.mock.calls[0]; + findRulesRoute(router, licenseState); - const [context, req, res] = mockHandlerArguments( - {}, - { - query: { - per_page: 1, - page: 1, - default_search_operator: 'OR', + const [config, handler] = router.get.mock.calls[0]; + + expect(config.path).toMatchInlineSnapshot(`"/api/alerting/rules/_find"`); + + const findResult = { + page: 1, + perPage: 1, + total: 0, + data: [], + }; + rulesClient.find.mockResolvedValueOnce(findResult); + + const [context, req, res] = mockHandlerArguments( + { rulesClient }, + { + query: { + per_page: 1, + page: 1, + default_search_operator: 'OR', + rule_type_ids: ['foo'], + }, }, - }, - ['ok'] - ); - await expect(handler(context, req, res)).rejects.toMatchInlineSnapshot(`[Error: OMG]`); + ['ok'] + ); + + expect(await handler(context, req, res)).toMatchInlineSnapshot(` + Object { + "body": Object { + "data": Array [], + "page": 1, + "per_page": 1, + "total": 0, + }, + } + `); - expect(verifyApiAccess).toHaveBeenCalledWith(licenseState); - }); + expect(rulesClient.find).toHaveBeenCalledTimes(1); + expect(rulesClient.find.mock.calls[0]).toMatchInlineSnapshot(` + Array [ + Object { + "excludeFromPublicApi": true, + "includeSnoozeData": true, + "options": Object { + "defaultSearchOperator": "OR", + "page": 1, + "perPage": 1, + }, + }, + ] + `); - it('should track calls with deprecated param values', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - findRulesRoute(router, licenseState, mockUsageCounter); - const findResult = { - page: 1, - perPage: 1, - total: 0, - data: [], - }; - rulesClient.find.mockResolvedValueOnce(findResult); - const [, handler] = router.get.mock.calls[0]; - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { - params: {}, - query: { - search_fields: ['alertTypeId:1', 'message:foo'], - search: 'alertTypeId:2', - sort_field: 'alertTypeId', + expect(res.ok).toHaveBeenCalledWith({ + body: { + page: 1, + per_page: 1, + total: 0, + data: [], }, - }, - ['ok'] - ); - await handler(context, req, res); - expect(trackLegacyTerminology).toHaveBeenCalledTimes(1); - expect((trackLegacyTerminology as jest.Mock).mock.calls[0][0]).toStrictEqual([ - 'alertTypeId:2', - ['alertTypeId:1', 'message:foo'], - 'alertTypeId', - ]); + }); + }); }); - it('should track calls to deprecated functionality', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - findRulesRoute(router, licenseState, mockUsageCounter); - - const findResult = { - page: 1, - perPage: 1, - total: 0, - data: [], - }; - rulesClient.find.mockResolvedValueOnce(findResult); - - const [, handler] = router.get.mock.calls[0]; - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { - params: {}, - query: { - fields: ['foo', 'bar'], - per_page: 1, + describe('Internal', () => { + it('finds rules with proper parameters', async () => { + const licenseState = licenseStateMock.create(); + const router = httpServiceMock.createRouter(); + + findInternalRulesRoute(router, licenseState); + + const [config, handler] = router.post.mock.calls[0]; + + expect(config.path).toMatchInlineSnapshot(`"/internal/alerting/rules/_find"`); + + const findResult = { + page: 1, + perPage: 1, + total: 0, + data: [], + }; + rulesClient.find.mockResolvedValueOnce(findResult); + + const [context, req, res] = mockHandlerArguments( + { rulesClient }, + { + body: { + per_page: 1, + page: 1, + default_search_operator: 'OR', + rule_type_ids: ['foo'], + }, + }, + ['ok'] + ); + + expect(await handler(context, req, res)).toMatchInlineSnapshot(` + Object { + "body": Object { + "data": Array [], + "page": 1, + "per_page": 1, + "total": 0, + }, + } + `); + + expect(rulesClient.find).toHaveBeenCalledTimes(1); + expect(rulesClient.find.mock.calls[0]).toMatchInlineSnapshot(` + Array [ + Object { + "excludeFromPublicApi": false, + "includeSnoozeData": true, + "options": Object { + "defaultSearchOperator": "OR", + "page": 1, + "perPage": 1, + "ruleTypeIds": Array [ + "foo", + ], + }, + }, + ] + `); + + expect(res.ok).toHaveBeenCalledWith({ + body: { page: 1, - default_search_operator: 'OR', + per_page: 1, + total: 0, + data: [], }, - }, - ['ok'] - ); - await handler(context, req, res); - expect(mockUsageCounter.incrementCounter).toHaveBeenCalledWith({ - counterName: `alertingFieldsUsage`, - counterType: 'alertingFieldsUsage', - incrementBy: 1, + }); }); }); }); diff --git a/x-pack/plugins/alerting/server/routes/rule/apis/find/find_rules_route.ts b/x-pack/plugins/alerting/server/routes/rule/apis/find/find_rules_route.ts index 1b328b71402a77..584ebbb3843562 100644 --- a/x-pack/plugins/alerting/server/routes/rule/apis/find/find_rules_route.ts +++ b/x-pack/plugins/alerting/server/routes/rule/apis/find/find_rules_route.ts @@ -9,8 +9,12 @@ import { IRouter } from '@kbn/core/server'; import { UsageCounter } from '@kbn/usage-collection-plugin/server'; import { ILicenseState } from '../../../../lib'; import { verifyAccessAndContext } from '../../../lib'; -import { findRulesRequestQuerySchemaV1 } from '../../../../../common/routes/rule/apis/find'; +import { + findRulesInternalRequestQuerySchemaV1, + findRulesRequestQuerySchemaV1, +} from '../../../../../common/routes/rule/apis/find'; import type { + FindRulesInternalRequestQueryV1, FindRulesRequestQueryV1, FindRulesResponseV1, } from '../../../../../common/routes/rule/apis/find'; @@ -22,6 +26,7 @@ import { } from '../../../../types'; import { trackLegacyTerminology } from '../../../lib/track_legacy_terminology'; import { transformFindRulesBodyV1, transformFindRulesResponseV1 } from './transforms'; +import { transformFindRulesInternalBody } from './transforms/transform_find_rules_body/v1'; interface BuildFindRulesRouteParams { licenseState: ILicenseState; @@ -38,79 +43,82 @@ const buildFindRulesRoute = ({ excludeFromPublicApi = false, usageCounter, }: BuildFindRulesRouteParams) => { - router.get( - { - path, - options: { - access: 'public', - summary: 'Get information about rules', - tags: ['oas-tag:alerting'], - }, - validate: { - request: { - query: findRulesRequestQuerySchemaV1, + if (path !== INTERNAL_ALERTING_API_FIND_RULES_PATH) { + router.get( + { + path, + options: { + access: 'public', + summary: 'Get information about rules', + tags: ['oas-tag:alerting'], }, - response: { - 200: { - body: () => ruleResponseSchemaV1, - description: 'Indicates a successful call.', - }, - 400: { - description: 'Indicates an invalid schema or parameters.', + validate: { + request: { + query: findRulesRequestQuerySchemaV1, }, - 403: { - description: 'Indicates that this call is forbidden.', + response: { + 200: { + body: () => ruleResponseSchemaV1, + description: 'Indicates a successful call.', + }, + 400: { + description: 'Indicates an invalid schema or parameters.', + }, + 403: { + description: 'Indicates that this call is forbidden.', + }, }, }, }, - }, - router.handleLegacyErrors( - verifyAccessAndContext(licenseState, async function (context, req, res) { - const alertingContext = await context.alerting; - const rulesClient = await alertingContext.getRulesClient(); - - const query: FindRulesRequestQueryV1 = req.query; - - trackLegacyTerminology( - [query.search, query.search_fields, query.sort_field].filter(Boolean) as string[], - usageCounter - ); - - const options = transformFindRulesBodyV1({ - ...query, - has_reference: query.has_reference || undefined, - search_fields: searchFieldsAsArray(query.search_fields), - }); - - if (req.query.fields) { - usageCounter?.incrementCounter({ - counterName: `alertingFieldsUsage`, - counterType: 'alertingFieldsUsage', - incrementBy: 1, + router.handleLegacyErrors( + verifyAccessAndContext(licenseState, async function (context, req, res) { + const alertingContext = await context.alerting; + const rulesClient = await alertingContext.getRulesClient(); + + const query: FindRulesRequestQueryV1 = req.query; + + trackLegacyTerminology( + [query.search, query.search_fields, query.sort_field].filter(Boolean) as string[], + usageCounter + ); + + const options = transformFindRulesBodyV1({ + ...query, + has_reference: query.has_reference || undefined, + search_fields: searchFieldsAsArray(query.search_fields), + }); + + if (req.query.fields) { + usageCounter?.incrementCounter({ + counterName: `alertingFieldsUsage`, + counterType: 'alertingFieldsUsage', + incrementBy: 1, + }); + } + + const findResult = await rulesClient.find({ + options, + excludeFromPublicApi, + includeSnoozeData: true, + }); + + const responseBody: FindRulesResponseV1['body'] = + transformFindRulesResponseV1(findResult, options.fields); + + return res.ok({ + body: responseBody, }); - } - - const findResult = await rulesClient.find({ - options, - excludeFromPublicApi, - includeSnoozeData: true, - }); - - const responseBody: FindRulesResponseV1['body'] = - transformFindRulesResponseV1(findResult, options.fields); - - return res.ok({ - body: responseBody, - }); - }) - ) - ); + }) + ) + ); + } + if (path === INTERNAL_ALERTING_API_FIND_RULES_PATH) { router.post( { path, validate: { - body: findRulesRequestQuerySchemaV1, + body: findRulesInternalRequestQuerySchemaV1, }, }, router.handleLegacyErrors( @@ -118,7 +126,7 @@ const buildFindRulesRoute = ({ const alertingContext = await context.alerting; const rulesClient = await alertingContext.getRulesClient(); - const body: FindRulesRequestQueryV1 = req.body; + const body: FindRulesInternalRequestQueryV1 = req.body; trackLegacyTerminology( [req.body.search, req.body.search_fields, req.body.sort_field].filter( @@ -127,7 +135,7 @@ const buildFindRulesRoute = ({ usageCounter ); - const options = transformFindRulesBodyV1({ + const options = transformFindRulesInternalBody({ ...body, has_reference: body.has_reference || undefined, search_fields: searchFieldsAsArray(body.search_fields), diff --git a/x-pack/plugins/alerting/server/routes/rule/apis/find/transforms/transform_find_rules_body/v1.ts b/x-pack/plugins/alerting/server/routes/rule/apis/find/transforms/transform_find_rules_body/v1.ts index a2f9d3c99b00d9..562da0fb63cdbc 100644 --- a/x-pack/plugins/alerting/server/routes/rule/apis/find/transforms/transform_find_rules_body/v1.ts +++ b/x-pack/plugins/alerting/server/routes/rule/apis/find/transforms/transform_find_rules_body/v1.ts @@ -5,7 +5,10 @@ * 2.0. */ -import type { FindRulesRequestQueryV1 } from '../../../../../../../common/routes/rule/apis/find'; +import type { + FindRulesInternalRequestQueryV1, + FindRulesRequestQueryV1, +} from '../../../../../../../common/routes/rule/apis/find'; import { FindRulesOptions } from '../../../../../../application/rule/methods/find'; export const transformFindRulesBody = (params: FindRulesRequestQueryV1): FindRulesOptions => { @@ -20,7 +23,6 @@ export const transformFindRulesBody = (params: FindRulesRequestQueryV1): FindRul has_reference: hasReference, fields, filter, - filter_consumers: filterConsumers, } = params; return { ...(page ? { page } : {}), @@ -29,7 +31,39 @@ export const transformFindRulesBody = (params: FindRulesRequestQueryV1): FindRul ...(filter ? { filter } : {}), ...(defaultSearchOperator ? { defaultSearchOperator } : {}), ...(perPage ? { perPage } : {}), - ...(filterConsumers ? { filterConsumers } : {}), + ...(sortField ? { sortField } : {}), + ...(sortOrder ? { sortOrder } : {}), + ...(hasReference ? { hasReference } : {}), + ...(searchFields + ? { searchFields: Array.isArray(searchFields) ? searchFields : [searchFields] } + : {}), + }; +}; + +export const transformFindRulesInternalBody = ( + params: FindRulesInternalRequestQueryV1 +): FindRulesOptions => { + const { + per_page: perPage, + page, + search, + default_search_operator: defaultSearchOperator, + search_fields: searchFields, + sort_field: sortField, + sort_order: sortOrder, + has_reference: hasReference, + fields, + filter, + rule_type_ids: ruleTypeIds, + } = params; + return { + ...(page ? { page } : {}), + ...(search ? { search } : {}), + ...(fields ? { fields } : {}), + ...(filter ? { filter } : {}), + ...(defaultSearchOperator ? { defaultSearchOperator } : {}), + ...(perPage ? { perPage } : {}), + ...(ruleTypeIds ? { ruleTypeIds } : {}), ...(sortField ? { sortField } : {}), ...(sortOrder ? { sortOrder } : {}), ...(hasReference ? { hasReference } : {}), diff --git a/x-pack/plugins/observability_solution/observability/public/pages/rules/rules_tab.tsx b/x-pack/plugins/observability_solution/observability/public/pages/rules/rules_tab.tsx index ae896b66d990fd..ed7778d3a1b8a2 100644 --- a/x-pack/plugins/observability_solution/observability/public/pages/rules/rules_tab.tsx +++ b/x-pack/plugins/observability_solution/observability/public/pages/rules/rules_tab.tsx @@ -9,10 +9,9 @@ import React, { useState } from 'react'; import { useHistory } from 'react-router-dom'; import { createKbnUrlStateStorage } from '@kbn/kibana-utils-plugin/public'; import { RuleStatus } from '@kbn/triggers-actions-ui-plugin/public'; -import { AlertConsumers } from '@kbn/rule-data-utils'; +import { AlertConsumers, OBSERVABILITY_RULE_TYPE_IDS } from '@kbn/rule-data-utils'; import { useKibana } from '../../utils/kibana_react'; import { useGetFilteredRuleTypes } from '../../hooks/use_get_filtered_rule_types'; -import { observabilityAlertFeatureIds } from '../../../common/constants'; interface RulesTabProps { setRefresh: React.Dispatch>; @@ -75,7 +74,7 @@ export function RulesTab({ setRefresh, stateRefresh }: RulesTabProps) { return ( & { sort: LoadRulesProps['sort']; enabled: boolean; refresh?: Date; - filterConsumers?: string[]; + ruleTypeIds?: string[]; hasReference?: { type: string; id: string; @@ -28,7 +28,7 @@ type UseLoadRulesQueryProps = Omit & { }; export const useLoadRulesQuery = (props: UseLoadRulesQueryProps) => { - const { filterConsumers, filters, page, sort, onPage, enabled, refresh, hasReference } = props; + const { ruleTypeIds, filters, page, sort, onPage, enabled, refresh, hasReference } = props; const { http, notifications: { toasts }, @@ -56,7 +56,7 @@ export const useLoadRulesQuery = (props: UseLoadRulesQueryProps) => { { refresh: refresh?.toISOString(), }, - filterConsumers, + ruleTypeIds, hasReference, ], queryFn: () => { @@ -73,7 +73,7 @@ export const useLoadRulesQuery = (props: UseLoadRulesQueryProps) => { tagsFilter: filters.tags, kueryNode: filters.kueryNode, sort, - filterConsumers, + ruleTypeIds, hasReference, }); }, diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/rules.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/rules.ts index 07a992c66c96ce..99df9a1f85adda 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/rules.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/rules.ts @@ -21,6 +21,7 @@ export async function loadRules({ ruleStatusesFilter, tagsFilter, sort = { field: 'name', direction: 'asc' }, + ruleTypeIds, }: LoadRulesProps): Promise<{ page: number; perPage: number; @@ -51,6 +52,7 @@ export async function loadRules({ default_search_operator: 'AND', sort_field: sort.field, sort_order: sort.direction, + ...(ruleTypeIds ? { rule_type_ids: ruleTypeIds } : {}), }, }); return { diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/rules_helpers.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/rules_helpers.ts index 4f8a8627bab52b..3c4efd34ab1d09 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/rules_helpers.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/rules_helpers.ts @@ -24,7 +24,7 @@ export interface LoadRulesProps { ruleStatusesFilter?: RuleStatus[]; sort?: Sorting; kueryNode?: KueryNode; - filterConsumers?: string[]; + ruleTypeIds?: string[]; hasReference?: { type: string; id: string; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/rules_kuery_filter.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/rules_kuery_filter.ts index 7c731dbfb016c9..74aaf7abb7cd40 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/rules_kuery_filter.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/rules_kuery_filter.ts @@ -24,7 +24,7 @@ export async function loadRulesWithKueryFilter({ tagsFilter, sort = { field: 'name', direction: 'asc' }, kueryNode, - filterConsumers, + ruleTypeIds, hasReference, }: LoadRulesProps): Promise<{ page: number; @@ -58,8 +58,8 @@ export async function loadRulesWithKueryFilter({ ...(filtersKueryNode ? { filter: JSON.stringify(filtersKueryNode) } : {}), sort_field: sort.field, sort_order: sort.direction, - filter_consumers: filterConsumers, ...(hasReference ? { has_reference: hasReference } : {}), + ...(ruleTypeIds ? { rule_type_ids: ruleTypeIds } : {}), }), }); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list.test.tsx index efedf01a92f842..e2e4e9908524d2 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list.test.tsx @@ -296,7 +296,7 @@ describe('rules_list component empty', () => { fetchActiveMaintenanceWindowsMock.mockResolvedValue([ { ...RUNNING_MAINTENANCE_WINDOW_1, categoryIds: ['securitySolution'] }, ]); - renderWithProviders(); + renderWithProviders(); await expect( screen.findByText('Rule notifications are stopped while maintenance windows are running.') ).rejects.toThrow(); diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/find.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/find.ts index 8c11b69db03bea..1d22b66cb80459 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/find.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/find.ts @@ -6,21 +6,20 @@ */ import expect from '@kbn/expect'; -import { Agent as SuperTestAgent } from 'supertest'; import { chunk, omit } from 'lodash'; import { v4 as uuidv4 } from 'uuid'; -import { SupertestWithoutAuthProviderType } from '@kbn/ftr-common-functional-services'; import { SuperuserAtSpace1, UserAtSpaceScenarios } from '../../../scenarios'; import { getUrlPrefix, getTestRuleData, ObjectRemover } from '../../../../common/lib'; import { FtrProviderContext } from '../../../../common/ftr_provider_context'; -const findTestUtils = ( - describeType: 'internal' | 'public', - objectRemover: ObjectRemover, - supertest: SuperTestAgent, - supertestWithoutAuth: SupertestWithoutAuthProviderType -) => { - describe(describeType, () => { +// eslint-disable-next-line import/no-default-export +export default function createFindTests({ getService }: FtrProviderContext) { + const supertest = getService('supertest'); + const supertestWithoutAuth = getService('supertestWithoutAuth'); + + describe('find', () => { + const objectRemover = new ObjectRemover(supertest); + afterEach(async () => { await objectRemover.removeAll(); }); @@ -66,9 +65,9 @@ const findTestUtils = ( const response = await supertestWithoutAuth .get( - `${getUrlPrefix(space.id)}/${ - describeType === 'public' ? 'api' : 'internal' - }/alerting/rules/_find?search=test.noop&search_fields=alertTypeId` + `${getUrlPrefix( + space.id + )}/public/alerting/rules/_find?search=test.noop&search_fields=alertTypeId` ) .auth(user.username, user.password); @@ -92,8 +91,7 @@ const findTestUtils = ( expect(response.body.per_page).to.be.greaterThan(0); expect(response.body.total).to.be.greaterThan(0); const match = response.body.data.find((obj: any) => obj.id === createdAlert.id); - const activeSnoozes = match.active_snoozes; - const hasActiveSnoozes = !!(activeSnoozes || []).filter((obj: any) => obj).length; + expect(match).to.eql({ id: createdAlert.id, name: 'abc', @@ -133,14 +131,6 @@ const findTestUtils = ( execution_status: match.execution_status, ...(match.next_run ? { next_run: match.next_run } : {}), ...(match.last_run ? { last_run: match.last_run } : {}), - ...(describeType === 'internal' - ? { - monitoring: match.monitoring, - snooze_schedule: match.snooze_schedule, - ...(hasActiveSnoozes && { active_snoozes: activeSnoozes }), - is_snoozed_until: null, - } - : {}), }); expect(Date.parse(match.created_at)).to.be.greaterThan(0); expect(Date.parse(match.updated_at)).to.be.greaterThan(0); @@ -190,9 +180,9 @@ const findTestUtils = ( const response = await supertestWithoutAuth .get( - `${getUrlPrefix(space.id)}/${ - describeType === 'public' ? 'api' : 'internal' - }/alerting/rules/_find?per_page=${perPage}&sort_field=createdAt` + `${getUrlPrefix( + space.id + )}/public/alerting/rules/_find?per_page=${perPage}&sort_field=createdAt` ) .auth(user.username, user.password); @@ -239,9 +229,9 @@ const findTestUtils = ( const secondResponse = await supertestWithoutAuth .get( - `${getUrlPrefix(space.id)}/${ - describeType === 'public' ? 'api' : 'internal' - }/alerting/rules/_find?per_page=${perPage}&sort_field=createdAt&page=2` + `${getUrlPrefix( + space.id + )}/public/alerting/rules/_find?per_page=${perPage}&sort_field=createdAt&page=2` ) .auth(user.username, user.password); @@ -286,9 +276,9 @@ const findTestUtils = ( const response = await supertestWithoutAuth .get( - `${getUrlPrefix(space.id)}/${ - describeType === 'public' ? 'api' : 'internal' - }/alerting/rules/_find?filter=alert.attributes.actions:{ actionTypeId: test.noop }` + `${getUrlPrefix( + space.id + )}/public/alerting/rules/_find?filter=alert.attributes.actions:{ actionTypeId: test.noop }` ) .auth(user.username, user.password); @@ -312,8 +302,7 @@ const findTestUtils = ( expect(response.body.per_page).to.be.greaterThan(0); expect(response.body.total).to.be.greaterThan(0); const match = response.body.data.find((obj: any) => obj.id === createdAlert.id); - const activeSnoozes = match.active_snoozes; - const hasActiveSnoozes = !!(activeSnoozes || []).filter((obj: any) => obj).length; + expect(match).to.eql({ id: createdAlert.id, name: 'abc', @@ -347,14 +336,6 @@ const findTestUtils = ( revision: 0, ...(match.next_run ? { next_run: match.next_run } : {}), ...(match.last_run ? { last_run: match.last_run } : {}), - ...(describeType === 'internal' - ? { - monitoring: match.monitoring, - snooze_schedule: match.snooze_schedule, - ...(hasActiveSnoozes && { active_snoozes: activeSnoozes }), - is_snoozed_until: null, - } - : {}), }); expect(Date.parse(match.created_at)).to.be.greaterThan(0); expect(Date.parse(match.updated_at)).to.be.greaterThan(0); @@ -396,9 +377,9 @@ const findTestUtils = ( const response = await supertestWithoutAuth .get( - `${getUrlPrefix(space.id)}/${ - describeType === 'public' ? 'api' : 'internal' - }/alerting/rules/_find?filter=alert.attributes.alertTypeId:test.restricted-noop&fields=["tags"]&sort_field=createdAt` + `${getUrlPrefix( + space.id + )}/public/alerting/rules/_find?filter=alert.attributes.alertTypeId:test.restricted-noop&fields=["tags"]&sort_field=createdAt` ) .auth(user.username, user.password); @@ -429,19 +410,11 @@ const findTestUtils = ( id: createdAlert.id, actions: [], tags: [myTag], - ...(describeType === 'internal' && { - snooze_schedule: [], - is_snoozed_until: null, - }), }); expect(omit(matchSecond, 'updatedAt')).to.eql({ id: createdSecondAlert.id, actions: [], tags: [myTag], - ...(describeType === 'internal' && { - snooze_schedule: [], - is_snoozed_until: null, - }), }); break; default: @@ -481,9 +454,9 @@ const findTestUtils = ( const response = await supertestWithoutAuth .get( - `${getUrlPrefix(space.id)}/${ - describeType === 'public' ? 'api' : 'internal' - }/alerting/rules/_find?filter=alert.attributes.alertTypeId:test.restricted-noop&fields=["tags","executionStatus"]&sort_field=createdAt` + `${getUrlPrefix( + space.id + )}/public/alerting/rules/_find?filter=alert.attributes.alertTypeId:test.restricted-noop&fields=["tags","executionStatus"]&sort_field=createdAt` ) .auth(user.username, user.password); @@ -515,20 +488,12 @@ const findTestUtils = ( actions: [], tags: [myTag], execution_status: matchFirst.execution_status, - ...(describeType === 'internal' && { - snooze_schedule: [], - is_snoozed_until: null, - }), }); expect(omit(matchSecond, 'updatedAt')).to.eql({ id: createdSecondAlert.id, actions: [], tags: [myTag], execution_status: matchSecond.execution_status, - ...(describeType === 'internal' && { - snooze_schedule: [], - is_snoozed_until: null, - }), }); break; default: @@ -546,9 +511,9 @@ const findTestUtils = ( const response = await supertestWithoutAuth .get( - `${getUrlPrefix('other')}/${ - describeType === 'public' ? 'api' : 'internal' - }/alerting/rules/_find?search=test.noop&search_fields=alertTypeId` + `${getUrlPrefix( + 'other' + )}/public/alerting/rules/_find?search=test.noop&search_fields=alertTypeId` ) .auth(user.username, user.password); @@ -581,87 +546,70 @@ const findTestUtils = ( }); }); } - }); - describe('Actions', () => { - const { user, space } = SuperuserAtSpace1; - - it('should return the actions correctly', async () => { - const { body: createdAction } = await supertest - .post(`${getUrlPrefix(space.id)}/api/actions/connector`) - .set('kbn-xsrf', 'foo') - .send({ - name: 'MY action', - connector_type_id: 'test.noop', - config: {}, - secrets: {}, - }) - .expect(200); - - const { body: createdRule1 } = await supertest - .post(`${getUrlPrefix(space.id)}/api/alerting/rule`) - .set('kbn-xsrf', 'foo') - .send( - getTestRuleData({ - enabled: true, - actions: [ - { - id: createdAction.id, - group: 'default', - params: {}, - }, - { - id: 'system-connector-test.system-action', - params: {}, - }, - ], + describe('Actions', () => { + const { user, space } = SuperuserAtSpace1; + + it('should return the actions correctly', async () => { + const { body: createdAction } = await supertest + .post(`${getUrlPrefix(space.id)}/api/actions/connector`) + .set('kbn-xsrf', 'foo') + .send({ + name: 'MY action', + connector_type_id: 'test.noop', + config: {}, + secrets: {}, }) - ) - .expect(200); - - objectRemover.add(space.id, createdRule1.id, 'rule', 'alerting'); - - const response = await supertestWithoutAuth - .get(`${getUrlPrefix(space.id)}/api/alerting/rules/_find`) - .set('kbn-xsrf', 'foo') - .auth(user.username, user.password); - - const action = response.body.data[0].actions[0]; - const systemAction = response.body.data[0].actions[1]; - const { uuid, ...restAction } = action; - const { uuid: systemActionUuid, ...restSystemAction } = systemAction; - - expect([restAction, restSystemAction]).to.eql([ - { - id: createdAction.id, - connector_type_id: 'test.noop', - group: 'default', - params: {}, - }, - { - id: 'system-connector-test.system-action', - connector_type_id: 'test.system-action', - params: {}, - }, - , - ]); - }); - }); -}; - -// eslint-disable-next-line import/no-default-export -export default function createFindTests({ getService }: FtrProviderContext) { - const supertest = getService('supertest'); - const supertestWithoutAuth = getService('supertestWithoutAuth'); - - describe('find', () => { - const objectRemover = new ObjectRemover(supertest); - - afterEach(async () => { - await objectRemover.removeAll(); + .expect(200); + + const { body: createdRule1 } = await supertest + .post(`${getUrlPrefix(space.id)}/api/alerting/rule`) + .set('kbn-xsrf', 'foo') + .send( + getTestRuleData({ + enabled: true, + actions: [ + { + id: createdAction.id, + group: 'default', + params: {}, + }, + { + id: 'system-connector-test.system-action', + params: {}, + }, + ], + }) + ) + .expect(200); + + objectRemover.add(space.id, createdRule1.id, 'rule', 'alerting'); + + const response = await supertestWithoutAuth + .get(`${getUrlPrefix(space.id)}/api/alerting/rules/_find`) + .set('kbn-xsrf', 'foo') + .auth(user.username, user.password); + + const action = response.body.data[0].actions[0]; + const systemAction = response.body.data[0].actions[1]; + const { uuid, ...restAction } = action; + const { uuid: systemActionUuid, ...restSystemAction } = systemAction; + + expect([restAction, restSystemAction]).to.eql([ + { + id: createdAction.id, + connector_type_id: 'test.noop', + group: 'default', + params: {}, + }, + { + id: 'system-connector-test.system-action', + connector_type_id: 'test.system-action', + params: {}, + }, + , + ]); + }); }); - - findTestUtils('public', objectRemover, supertest, supertestWithoutAuth); - findTestUtils('internal', objectRemover, supertest, supertestWithoutAuth); }); } diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/find_with_post.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/find_internal.ts similarity index 76% rename from x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/find_with_post.ts rename to x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/find_internal.ts index f221b5869dd6b9..c062082d54567b 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/find_with_post.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/find_internal.ts @@ -6,27 +6,28 @@ */ import expect from '@kbn/expect'; -import { Agent as SuperTestAgent } from 'supertest'; import { chunk, omit } from 'lodash'; import { v4 as uuidv4 } from 'uuid'; -import { SupertestWithoutAuthProviderType } from '@kbn/ftr-common-functional-services'; +import { Space } from '../../../../common/types'; import { UserAtSpaceScenarios } from '../../../scenarios'; import { getUrlPrefix, getTestRuleData, ObjectRemover } from '../../../../common/lib'; import { FtrProviderContext } from '../../../../common/ftr_provider_context'; -const findTestUtils = ( - describeType: 'internal' | 'public', - objectRemover: ObjectRemover, - supertest: SuperTestAgent, - supertestWithoutAuth: SupertestWithoutAuthProviderType -) => { - describe(describeType, () => { +// eslint-disable-next-line import/no-default-export +export default function createFindTests({ getService }: FtrProviderContext) { + const supertest = getService('supertest'); + const supertestWithoutAuth = getService('supertestWithoutAuth'); + + describe('find internal', () => { + const objectRemover = new ObjectRemover(supertest); + afterEach(async () => { await objectRemover.removeAll(); }); for (const scenario of UserAtSpaceScenarios) { const { user, space } = scenario; + describe(scenario.id, () => { it('should handle find alert request appropriately', async () => { const { body: createdAlert } = await supertest @@ -37,11 +38,7 @@ const findTestUtils = ( objectRemover.add(space.id, createdAlert.id, 'rule', 'alerting'); const response = await supertestWithoutAuth - .post( - `${getUrlPrefix(space.id)}/${ - describeType === 'public' ? 'api' : 'internal' - }/alerting/rules/_find` - ) + .post(`${getUrlPrefix(space.id)}/internal/alerting/rules/_find`) .set('kbn-xsrf', 'foo') .auth(user.username, user.password) .send({ @@ -97,14 +94,10 @@ const findTestUtils = ( execution_status: match.execution_status, ...(match.next_run ? { next_run: match.next_run } : {}), ...(match.last_run ? { last_run: match.last_run } : {}), - ...(describeType === 'internal' - ? { - monitoring: match.monitoring, - snooze_schedule: match.snooze_schedule, - ...(hasActiveSnoozes && { active_snoozes: activeSnoozes }), - is_snoozed_until: null, - } - : {}), + monitoring: match.monitoring, + snooze_schedule: match.snooze_schedule, + ...(hasActiveSnoozes && { active_snoozes: activeSnoozes }), + is_snoozed_until: null, }); expect(Date.parse(match.created_at)).to.be.greaterThan(0); expect(Date.parse(match.updated_at)).to.be.greaterThan(0); @@ -115,49 +108,20 @@ const findTestUtils = ( }); it('should filter out types that the user is not authorized to `get` retaining pagination', async () => { - async function createNoOpAlert(overrides = {}) { - const alert = getTestRuleData(overrides); - const { body: createdAlert } = await supertest - .post(`${getUrlPrefix(space.id)}/api/alerting/rule`) - .set('kbn-xsrf', 'foo') - .send(alert) - .expect(200); - objectRemover.add(space.id, createdAlert.id, 'rule', 'alerting'); - return { - id: createdAlert.id, - rule_type_id: alert.rule_type_id, - }; - } - function createRestrictedNoOpAlert() { - return createNoOpAlert({ - rule_type_id: 'test.restricted-noop', - consumer: 'alertsRestrictedFixture', - }); - } - function createUnrestrictedNoOpAlert() { - return createNoOpAlert({ - rule_type_id: 'test.unrestricted-noop', - consumer: 'alertsFixture', - }); - } const allAlerts = []; - allAlerts.push(await createNoOpAlert()); - allAlerts.push(await createNoOpAlert()); - allAlerts.push(await createRestrictedNoOpAlert()); - allAlerts.push(await createUnrestrictedNoOpAlert()); - allAlerts.push(await createUnrestrictedNoOpAlert()); - allAlerts.push(await createRestrictedNoOpAlert()); - allAlerts.push(await createNoOpAlert()); - allAlerts.push(await createNoOpAlert()); + allAlerts.push(await createNoOpAlert(space)); + allAlerts.push(await createNoOpAlert(space)); + allAlerts.push(await createRestrictedNoOpAlert(space)); + allAlerts.push(await createUnrestrictedNoOpAlert(space)); + allAlerts.push(await createUnrestrictedNoOpAlert(space)); + allAlerts.push(await createRestrictedNoOpAlert(space)); + allAlerts.push(await createNoOpAlert(space)); + allAlerts.push(await createNoOpAlert(space)); const perPage = 4; const response = await supertestWithoutAuth - .post( - `${getUrlPrefix(space.id)}/${ - describeType === 'public' ? 'api' : 'internal' - }/alerting/rules/_find` - ) + .post(`${getUrlPrefix(space.id)}/internal/alerting/rules/_find`) .set('kbn-xsrf', 'foo') .auth(user.username, user.password) .send({ @@ -199,23 +163,24 @@ const findTestUtils = ( expect(response.body.per_page).to.be.equal(perPage); expect(response.body.total).to.be.equal(8); - { - const [firstPage, secondPage] = chunk( - allAlerts.map((alert) => alert.id), - perPage - ); - expect(response.body.data.map((alert: any) => alert.id)).to.eql(firstPage); - - const secondResponse = await supertestWithoutAuth - .get( - `${getUrlPrefix(space.id)}/${ - describeType === 'public' ? 'api' : 'internal' - }/alerting/rules/_find?per_page=${perPage}&sort_field=createdAt&page=2` - ) - .auth(user.username, user.password); - - expect(secondResponse.body.data.map((alert: any) => alert.id)).to.eql(secondPage); - } + const [firstPage, secondPage] = chunk( + allAlerts.map((alert) => alert.id), + perPage + ); + expect(response.body.data.map((alert: any) => alert.id)).to.eql(firstPage); + + const secondResponse = await supertestWithoutAuth + .post(`${getUrlPrefix(space.id)}/internal/alerting/rules/_find`) + .set('kbn-xsrf', 'foo') + .auth(user.username, user.password) + .send({ + per_page: perPage, + sort_field: 'createdAt', + page: '2', + }); + + expect(secondResponse.statusCode).to.eql(200); + expect(secondResponse.body.data.map((alert: any) => alert.id)).to.eql(secondPage); break; default: @@ -254,11 +219,7 @@ const findTestUtils = ( objectRemover.add(space.id, createdAlert.id, 'rule', 'alerting'); const response = await supertestWithoutAuth - .post( - `${getUrlPrefix(space.id)}/${ - describeType === 'public' ? 'api' : 'internal' - }/alerting/rules/_find` - ) + .post(`${getUrlPrefix(space.id)}/internal/alerting/rules/_find`) .set('kbn-xsrf', 'foo') .auth(user.username, user.password) .send({ @@ -320,14 +281,10 @@ const findTestUtils = ( execution_status: match.execution_status, ...(match.next_run ? { next_run: match.next_run } : {}), ...(match.last_run ? { last_run: match.last_run } : {}), - ...(describeType === 'internal' - ? { - monitoring: match.monitoring, - snooze_schedule: match.snooze_schedule, - ...(hasActiveSnoozes && { active_snoozes: activeSnoozes }), - is_snoozed_until: null, - } - : {}), + monitoring: match.monitoring, + snooze_schedule: match.snooze_schedule, + ...(hasActiveSnoozes && { active_snoozes: activeSnoozes }), + is_snoozed_until: null, }); expect(Date.parse(match.created_at)).to.be.greaterThan(0); expect(Date.parse(match.updated_at)).to.be.greaterThan(0); @@ -368,11 +325,7 @@ const findTestUtils = ( objectRemover.add(space.id, createdSecondAlert.id, 'rule', 'alerting'); const response = await supertestWithoutAuth - .post( - `${getUrlPrefix(space.id)}/${ - describeType === 'public' ? 'api' : 'internal' - }/alerting/rules/_find` - ) + .post(`${getUrlPrefix(space.id)}/internal/alerting/rules/_find`) .set('kbn-xsrf', 'foo') .auth(user.username, user.password) .send({ @@ -408,19 +361,15 @@ const findTestUtils = ( id: createdAlert.id, actions: [], tags: [myTag], - ...(describeType === 'internal' && { - snooze_schedule: [], - is_snoozed_until: null, - }), + snooze_schedule: [], + is_snoozed_until: null, }); expect(omit(matchSecond, 'updatedAt')).to.eql({ id: createdSecondAlert.id, actions: [], tags: [myTag], - ...(describeType === 'internal' && { - snooze_schedule: [], - is_snoozed_until: null, - }), + snooze_schedule: [], + is_snoozed_until: null, }); break; default: @@ -459,11 +408,7 @@ const findTestUtils = ( objectRemover.add(space.id, createdSecondAlert.id, 'rule', 'alerting'); const response = await supertestWithoutAuth - .post( - `${getUrlPrefix(space.id)}/${ - describeType === 'public' ? 'api' : 'internal' - }/alerting/rules/_find` - ) + .post(`${getUrlPrefix(space.id)}/internal/alerting/rules/_find`) .set('kbn-xsrf', 'foo') .auth(user.username, user.password) .send({ @@ -500,20 +445,16 @@ const findTestUtils = ( actions: [], tags: [myTag], execution_status: matchFirst.execution_status, - ...(describeType === 'internal' && { - snooze_schedule: [], - is_snoozed_until: null, - }), + snooze_schedule: [], + is_snoozed_until: null, }); expect(omit(matchSecond, 'updatedAt')).to.eql({ id: createdSecondAlert.id, actions: [], tags: [myTag], execution_status: matchSecond.execution_status, - ...(describeType === 'internal' && { - snooze_schedule: [], - is_snoozed_until: null, - }), + snooze_schedule: [], + is_snoozed_until: null, }); break; default: @@ -530,11 +471,7 @@ const findTestUtils = ( objectRemover.add(space.id, createdAlert.id, 'rule', 'alerting'); const response = await supertestWithoutAuth - .post( - `${getUrlPrefix('other')}/${ - describeType === 'public' ? 'api' : 'internal' - }/alerting/rules/_find` - ) + .post(`${getUrlPrefix('other')}/internal/alerting/rules/_find`) .set('kbn-xsrf', 'foo') .auth(user.username, user.password) .send({ @@ -569,23 +506,93 @@ const findTestUtils = ( throw new Error(`Scenario untested: ${JSON.stringify(scenario)}`); } }); + + it('should filter by rule type IDs correctly', async () => { + await createNoOpAlert(space); + await createRestrictedNoOpAlert(space); + await createUnrestrictedNoOpAlert(space); + + const perPage = 10; + const ruleTypeIds = ['test.restricted-noop', 'test.noop']; + + const response = await supertestWithoutAuth + .post(`${getUrlPrefix(space.id)}/internal/alerting/rules/_find`) + .set('kbn-xsrf', 'foo') + .auth(user.username, user.password) + .send({ + per_page: perPage, + sort_field: 'createdAt', + rule_type_ids: ruleTypeIds, + }); + + switch (scenario.id) { + case 'no_kibana_privileges at space1': + case 'space_1_all at space2': + expect(response.statusCode).to.eql(403); + expect(response.body).to.eql({ + error: 'Forbidden', + message: `Unauthorized to find rules for any rule types`, + statusCode: 403, + }); + break; + case 'space_1_all at space1': + case 'space_1_all_alerts_none_actions at space1': + expect(response.statusCode).to.eql(200); + expect(response.body.total).to.be.equal(1); + + expect( + response.body.data.every( + (rule: { rule_type_id: string }) => rule.rule_type_id === 'test.noop' + ) + ).to.be.eql(true); + break; + case 'global_read at space1': + case 'superuser at space1': + case 'space_1_all_with_restricted_fixture at space1': + expect(response.statusCode).to.eql(200); + expect(response.body.total).to.be.equal(2); + + expect( + response.body.data.every((rule: { rule_type_id: string }) => + ruleTypeIds.includes(rule.rule_type_id) + ) + ).to.be.eql(true); + break; + default: + throw new Error(`Scenario untested: ${JSON.stringify(scenario)}`); + } + }); }); } - }); -}; -// eslint-disable-next-line import/no-default-export -export default function createFindTests({ getService }: FtrProviderContext) { - const supertest = getService('supertest'); - const supertestWithoutAuth = getService('supertestWithoutAuth'); + async function createNoOpAlert(space: Space, overrides = {}) { + const alert = getTestRuleData(overrides); + const { body: createdAlert } = await supertest + .post(`${getUrlPrefix(space.id)}/api/alerting/rule`) + .set('kbn-xsrf', 'foo') + .send(alert) + .expect(200); - describe('find with post', () => { - const objectRemover = new ObjectRemover(supertest); + objectRemover.add(space.id, createdAlert.id, 'rule', 'alerting'); - afterEach(async () => { - await objectRemover.removeAll(); - }); + return { + id: createdAlert.id, + rule_type_id: alert.rule_type_id, + }; + } - findTestUtils('internal', objectRemover, supertest, supertestWithoutAuth); + function createRestrictedNoOpAlert(space: Space) { + return createNoOpAlert(space, { + rule_type_id: 'test.restricted-noop', + consumer: 'alertsRestrictedFixture', + }); + } + + function createUnrestrictedNoOpAlert(space: Space) { + return createNoOpAlert(space, { + rule_type_id: 'test.unrestricted-noop', + consumer: 'alertsFixture', + }); + } }); } diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/index.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/index.ts index ec938e8dc4abbb..dc85feb741eb8f 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/index.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/index.ts @@ -22,7 +22,7 @@ export default function alertingTests({ loadTestFile, getService }: FtrProviderC loadTestFile(require.resolve('./backfill')); loadTestFile(require.resolve('./find')); - loadTestFile(require.resolve('./find_with_post')); + loadTestFile(require.resolve('./find_internal')); loadTestFile(require.resolve('./create')); loadTestFile(require.resolve('./delete')); loadTestFile(require.resolve('./disable')); diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/find.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/find.ts index c8aeba2b7e2108..eb133f33a37a81 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/find.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/find.ts @@ -386,5 +386,28 @@ export default function createFindTests({ getService }: FtrProviderContext) { expect(Date.parse(match.updatedAt)).to.be.greaterThan(0); }); }); + + describe('public', function () { + it('should throw when using rule_type_ids', async () => { + const { body: createdAlert } = await supertest + .post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`) + .set('kbn-xsrf', 'foo') + .send(getTestRuleData()) + .expect(200); + + objectRemover.add(Spaces.space1.id, createdAlert.id, 'rule', 'alerting'); + + const response = await supertest.get( + `${getUrlPrefix(Spaces.space1.id)}/api/alerting/rules/_find?rule_type_ids=foo` + ); + + expect(response.statusCode).to.eql(400); + expect(response.body).to.eql({ + statusCode: 400, + error: 'Bad Request', + message: '[request query.rule_type_ids]: definition for this key is missing', + }); + }); + }); }); } From fdd178a50c1fb9caa553179c0e73089e0a647f2c Mon Sep 17 00:00:00 2001 From: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Date: Fri, 27 Sep 2024 14:51:51 +0000 Subject: [PATCH 066/106] [CI] Auto-commit changed files from 'node scripts/capture_oas_snapshot --include-path /api/status --include-path /api/alerting/rule/ --include-path /api/alerting/rules --include-path /api/actions --update' --- oas_docs/bundle.json | 12 ------------ oas_docs/bundle.serverless.json | 12 ------------ 2 files changed, 24 deletions(-) diff --git a/oas_docs/bundle.json b/oas_docs/bundle.json index 5fd690a2f6ceb5..930ee5657bf76f 100644 --- a/oas_docs/bundle.json +++ b/oas_docs/bundle.json @@ -5361,18 +5361,6 @@ "schema": { "type": "string" } - }, - { - "in": "query", - "name": "filter_consumers", - "required": false, - "schema": { - "items": { - "description": "List of consumers to filter.", - "type": "string" - }, - "type": "array" - } } ], "responses": { diff --git a/oas_docs/bundle.serverless.json b/oas_docs/bundle.serverless.json index 5fd690a2f6ceb5..930ee5657bf76f 100644 --- a/oas_docs/bundle.serverless.json +++ b/oas_docs/bundle.serverless.json @@ -5361,18 +5361,6 @@ "schema": { "type": "string" } - }, - { - "in": "query", - "name": "filter_consumers", - "required": false, - "schema": { - "items": { - "description": "List of consumers to filter.", - "type": "string" - }, - "type": "array" - } } ], "responses": { From 1d5f50ff256fd4efd998fdf7d0e2d7481f8bed57 Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Sun, 29 Sep 2024 17:29:42 +0300 Subject: [PATCH 067/106] Fix find API integration tests --- .../group1/tests/alerting/find.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/find.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/find.ts index 1d22b66cb80459..6eea7fde92768f 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/find.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/find.ts @@ -67,7 +67,7 @@ export default function createFindTests({ getService }: FtrProviderContext) { .get( `${getUrlPrefix( space.id - )}/public/alerting/rules/_find?search=test.noop&search_fields=alertTypeId` + )}/api/alerting/rules/_find?search=test.noop&search_fields=alertTypeId` ) .auth(user.username, user.password); @@ -182,7 +182,7 @@ export default function createFindTests({ getService }: FtrProviderContext) { .get( `${getUrlPrefix( space.id - )}/public/alerting/rules/_find?per_page=${perPage}&sort_field=createdAt` + )}/api/alerting/rules/_find?per_page=${perPage}&sort_field=createdAt` ) .auth(user.username, user.password); @@ -231,7 +231,7 @@ export default function createFindTests({ getService }: FtrProviderContext) { .get( `${getUrlPrefix( space.id - )}/public/alerting/rules/_find?per_page=${perPage}&sort_field=createdAt&page=2` + )}/api/alerting/rules/_find?per_page=${perPage}&sort_field=createdAt&page=2` ) .auth(user.username, user.password); @@ -278,7 +278,7 @@ export default function createFindTests({ getService }: FtrProviderContext) { .get( `${getUrlPrefix( space.id - )}/public/alerting/rules/_find?filter=alert.attributes.actions:{ actionTypeId: test.noop }` + )}/api/alerting/rules/_find?filter=alert.attributes.actions:{ actionTypeId: test.noop }` ) .auth(user.username, user.password); @@ -379,7 +379,7 @@ export default function createFindTests({ getService }: FtrProviderContext) { .get( `${getUrlPrefix( space.id - )}/public/alerting/rules/_find?filter=alert.attributes.alertTypeId:test.restricted-noop&fields=["tags"]&sort_field=createdAt` + )}/api/alerting/rules/_find?filter=alert.attributes.alertTypeId:test.restricted-noop&fields=["tags"]&sort_field=createdAt` ) .auth(user.username, user.password); @@ -456,7 +456,7 @@ export default function createFindTests({ getService }: FtrProviderContext) { .get( `${getUrlPrefix( space.id - )}/public/alerting/rules/_find?filter=alert.attributes.alertTypeId:test.restricted-noop&fields=["tags","executionStatus"]&sort_field=createdAt` + )}/api/alerting/rules/_find?filter=alert.attributes.alertTypeId:test.restricted-noop&fields=["tags","executionStatus"]&sort_field=createdAt` ) .auth(user.username, user.password); @@ -513,7 +513,7 @@ export default function createFindTests({ getService }: FtrProviderContext) { .get( `${getUrlPrefix( 'other' - )}/public/alerting/rules/_find?search=test.noop&search_fields=alertTypeId` + )}/api/alerting/rules/_find?search=test.noop&search_fields=alertTypeId` ) .auth(user.username, user.password); From e09a12c58b86e1d73765a9f7888136d65f464143 Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Sun, 29 Sep 2024 18:02:33 +0300 Subject: [PATCH 068/106] Remove unecessary ruleTypeIds props --- .../src/alerts_search_bar/index.tsx | 6 ++---- .../src/alerts_search_bar/types.ts | 3 +-- .../rule_actions/rule_actions_alerts_filter.test.tsx | 8 ++++---- .../rule_actions/rule_actions_alerts_filter.tsx | 5 +---- .../src/rule_form/rule_actions/rule_actions_item.tsx | 1 - .../rule_actions/rule_actions_settings.test.tsx | 9 --------- .../rule_form/rule_actions/rule_actions_settings.tsx | 11 +++++------ .../components/maintenance_window_scoped_query.tsx | 2 +- .../action_connector_form/action_type_form.test.tsx | 10 +++++++++- .../action_connector_form/action_type_form.tsx | 3 +-- 10 files changed, 24 insertions(+), 34 deletions(-) diff --git a/packages/kbn-alerts-ui-shared/src/alerts_search_bar/index.tsx b/packages/kbn-alerts-ui-shared/src/alerts_search_bar/index.tsx index 73210ff9e96494..c4e44c39980172 100644 --- a/packages/kbn-alerts-ui-shared/src/alerts_search_bar/index.tsx +++ b/packages/kbn-alerts-ui-shared/src/alerts_search_bar/index.tsx @@ -18,13 +18,11 @@ import { useLoadRuleTypesQuery, useAlertsDataView, useRuleAADFields } from '../c export type { AlertsSearchBarProps } from './types'; -const EMPTY_RULE_TYPE_IDS: string[] = []; const SA_ALERTS = { type: 'alerts', fields: {} } as SuggestionsAbstraction; export const AlertsSearchBar = ({ appName, disableQueryLanguageSwitcher = false, - ruleTypeIds = EMPTY_RULE_TYPE_IDS, ruleTypeId, query, filters, @@ -45,7 +43,7 @@ export const AlertsSearchBar = ({ }: AlertsSearchBarProps) => { const [queryLanguage, setQueryLanguage] = useState('kuery'); const { dataView } = useAlertsDataView({ - ruleTypeIds, + ruleTypeIds: [ruleTypeId], http, toasts, dataViewsService, @@ -74,7 +72,7 @@ export const AlertsSearchBar = ({ }); const isSecurity = - (ruleTypeIds && ruleTypeIds.length === 1 && isSiemRuleType(ruleTypeIds[0])) || + (ruleTypeId && isSiemRuleType(ruleTypeId)) || (ruleType && ruleTypeId && ruleType.ruleTypesState.data.get(ruleTypeId)?.producer === AlertConsumers.SIEM); diff --git a/packages/kbn-alerts-ui-shared/src/alerts_search_bar/types.ts b/packages/kbn-alerts-ui-shared/src/alerts_search_bar/types.ts index cca55a623eb586..43f58a8cc3bebf 100644 --- a/packages/kbn-alerts-ui-shared/src/alerts_search_bar/types.ts +++ b/packages/kbn-alerts-ui-shared/src/alerts_search_bar/types.ts @@ -17,7 +17,6 @@ export type QueryLanguageType = 'lucene' | 'kuery'; export interface AlertsSearchBarProps { appName: string; disableQueryLanguageSwitcher?: boolean; - ruleTypeIds: string[]; rangeFrom?: string; rangeTo?: string; query?: string; @@ -27,7 +26,7 @@ export interface AlertsSearchBarProps { showSubmitButton?: boolean; placeholder?: string; submitOnBlur?: boolean; - ruleTypeId?: string; + ruleTypeId: string; onQueryChange?: (query: { dateRange: { from: string; to: string; mode?: 'absolute' | 'relative' }; query?: string; diff --git a/packages/kbn-alerts-ui-shared/src/rule_form/rule_actions/rule_actions_alerts_filter.test.tsx b/packages/kbn-alerts-ui-shared/src/rule_form/rule_actions/rule_actions_alerts_filter.test.tsx index d3ef68206cfa46..685c0ac643c830 100644 --- a/packages/kbn-alerts-ui-shared/src/rule_form/rule_actions/rule_actions_alerts_filter.test.tsx +++ b/packages/kbn-alerts-ui-shared/src/rule_form/rule_actions/rule_actions_alerts_filter.test.tsx @@ -103,7 +103,7 @@ describe('ruleActionsAlertsFilter', () => { action={getAction('1')} onChange={mockOnChange} appName="stackAlerts" - featureIds={['stackAlerts']} + ruleTypeId=".es-query" /> ); @@ -116,7 +116,7 @@ describe('ruleActionsAlertsFilter', () => { action={getAction('1')} onChange={mockOnChange} appName="stackAlerts" - featureIds={['stackAlerts']} + ruleTypeId=".es-query" /> ); @@ -138,7 +138,7 @@ describe('ruleActionsAlertsFilter', () => { })} onChange={mockOnChange} appName="stackAlerts" - featureIds={['stackAlerts']} + ruleTypeId=".es-query" /> ); @@ -160,7 +160,7 @@ describe('ruleActionsAlertsFilter', () => { })} onChange={mockOnChange} appName="stackAlerts" - featureIds={['stackAlerts']} + ruleTypeId=".es-query" /> ); diff --git a/packages/kbn-alerts-ui-shared/src/rule_form/rule_actions/rule_actions_alerts_filter.tsx b/packages/kbn-alerts-ui-shared/src/rule_form/rule_actions/rule_actions_alerts_filter.tsx index 8d08322561bc37..57f167bff098b1 100644 --- a/packages/kbn-alerts-ui-shared/src/rule_form/rule_actions/rule_actions_alerts_filter.tsx +++ b/packages/kbn-alerts-ui-shared/src/rule_form/rule_actions/rule_actions_alerts_filter.tsx @@ -24,8 +24,7 @@ export interface RuleActionsAlertsFilterProps { action: RuleAction; onChange: (update?: AlertsFilter['query']) => void; appName: string; - ruleTypeIds: string[]; - ruleTypeId?: string; + ruleTypeId: string; plugins?: { http: RuleFormPlugins['http']; notifications: RuleFormPlugins['notifications']; @@ -38,7 +37,6 @@ export const RuleActionsAlertsFilter = ({ action, onChange, appName, - ruleTypeIds, ruleTypeId, plugins: propsPlugins, }: RuleActionsAlertsFilterProps) => { @@ -109,7 +107,6 @@ export const RuleActionsAlertsFilter = ({ unifiedSearchBar={unifiedSearch.ui.SearchBar} dataViewsService={dataViews} appName={appName} - ruleTypeIds={ruleTypeIds} ruleTypeId={ruleTypeId} disableQueryLanguageSwitcher={true} query={query.kql} diff --git a/packages/kbn-alerts-ui-shared/src/rule_form/rule_actions/rule_actions_item.tsx b/packages/kbn-alerts-ui-shared/src/rule_form/rule_actions/rule_actions_item.tsx index b80a79a69cfcf6..2ef6d21155ecf0 100644 --- a/packages/kbn-alerts-ui-shared/src/rule_form/rule_actions/rule_actions_item.tsx +++ b/packages/kbn-alerts-ui-shared/src/rule_form/rule_actions/rule_actions_item.tsx @@ -482,7 +482,6 @@ export const RuleActionsItem = (props: RuleActionsItemProps) => { {tab === SETTINGS_TAB && ( setUseDefaultMessage(true)} onNotifyWhenChange={onNotifyWhenChange} onActionGroupChange={onActionGroupChange} diff --git a/packages/kbn-alerts-ui-shared/src/rule_form/rule_actions/rule_actions_settings.test.tsx b/packages/kbn-alerts-ui-shared/src/rule_form/rule_actions/rule_actions_settings.test.tsx index a9b9a5b9cc4546..c2eb16d3f07058 100644 --- a/packages/kbn-alerts-ui-shared/src/rule_form/rule_actions/rule_actions_settings.test.tsx +++ b/packages/kbn-alerts-ui-shared/src/rule_form/rule_actions/rule_actions_settings.test.tsx @@ -168,7 +168,6 @@ describe('ruleActionsSettings', () => { render( { render( { notifyWhen: 'onActionGroupChange', }, })} - producerId="stackAlerts" onUseDefaultMessageChange={mockOnUseDefaultMessageChange} onNotifyWhenChange={mockOnNotifyWhenChange} onActionGroupChange={mockOnActionGroupChange} @@ -261,7 +258,6 @@ describe('ruleActionsSettings', () => { notifyWhen: 'onActionGroupChange', }, })} - producerId="stackAlerts" onUseDefaultMessageChange={mockOnUseDefaultMessageChange} onNotifyWhenChange={mockOnNotifyWhenChange} onActionGroupChange={mockOnActionGroupChange} @@ -278,7 +274,6 @@ describe('ruleActionsSettings', () => { render( { render( { render( { render( { render( void; onNotifyWhenChange: (frequency: RuleActionFrequency) => void; onActionGroupChange: (group: string) => void; @@ -131,7 +130,6 @@ export interface RuleActionsSettingsProps { export const RuleActionsSettings = (props: RuleActionsSettingsProps) => { const { action, - producerId, onUseDefaultMessageChange, onNotifyWhenChange, onActionGroupChange, @@ -190,12 +188,14 @@ export const RuleActionsSettings = (props: RuleActionsSettingsProps) => { minimumActionThrottleUnit, }); + const ruleTypeId = selectedRuleType.id; + const showActionAlertsFilter = hasFieldsForAad({ ruleType: selectedRuleType, consumer, validConsumers, - }) || producerId === AlertConsumers.SIEM; + }) || isSiemRuleType(ruleTypeId); return ( @@ -258,9 +258,8 @@ export const RuleActionsSettings = (props: RuleActionsSettingsProps) => { diff --git a/x-pack/plugins/alerting/public/pages/maintenance_windows/components/maintenance_window_scoped_query.tsx b/x-pack/plugins/alerting/public/pages/maintenance_windows/components/maintenance_window_scoped_query.tsx index 3c5f69b38b8d77..36393f7d817b30 100644 --- a/x-pack/plugins/alerting/public/pages/maintenance_windows/components/maintenance_window_scoped_query.tsx +++ b/x-pack/plugins/alerting/public/pages/maintenance_windows/components/maintenance_window_scoped_query.tsx @@ -75,7 +75,7 @@ export const MaintenanceWindowScopedQuery = React.memo( { const wrapper = mountWithIntl( getActionTypeForm({ index: 1, + ruleTypeId: '.es-query', actionItem: { id: '123', actionTypeId: '.pagerduty', @@ -190,6 +191,7 @@ describe('action_type_form', () => { {getActionTypeForm({ index: 1, + ruleTypeId: '.es-query', actionItem: { id: '123', actionTypeId: '.pagerduty', @@ -239,6 +241,7 @@ describe('action_type_form', () => { {getActionTypeForm({ index: 1, + ruleTypeId: 'siem.esqlRule', actionItem: { id: '123', actionTypeId: '.pagerduty', @@ -288,6 +291,7 @@ describe('action_type_form', () => { const wrapper = mountWithIntl( getActionTypeForm({ index: 1, + ruleTypeId: '.es-query', actionItem: { id: '123', actionTypeId: '.pagerduty', @@ -340,6 +344,7 @@ describe('action_type_form', () => { const wrapper = mountWithIntl( getActionTypeForm({ index: 1, + ruleTypeId: '.es-query', actionItem: { id: '123', actionTypeId: '.pagerduty', @@ -413,6 +418,7 @@ describe('action_type_form', () => { {getActionTypeForm({ index: 1, actionItem, + ruleTypeId: '.es-query', setActionFrequencyProperty: () => { actionItem.frequency = { notifyWhen: RuleNotifyWhen.ACTIVE, @@ -551,6 +557,7 @@ describe('action_type_form', () => { {getActionTypeForm({ index: 1, + ruleTypeId: '.es-query', actionItem, notifyWhenSelectOptions: CUSTOM_NOTIFY_WHEN_OPTIONS, })} @@ -604,6 +611,7 @@ describe('action_type_form', () => { {getActionTypeForm({ index: 1, + ruleTypeId: '.es-query', actionItem, notifyWhenSelectOptions: CUSTOM_NOTIFY_WHEN_OPTIONS, })} @@ -664,7 +672,7 @@ function getActionTypeForm({ messageVariables?: ActionVariables; summaryMessageVariables?: ActionVariables; notifyWhenSelectOptions?: NotifyWhenSelectOptions[]; - ruleTypeId?: string; + ruleTypeId: string; producerId?: string; featureId?: string; }) { diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_type_form.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_type_form.tsx index e6dfe26bb638dd..70d602ac34bd39 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_type_form.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_type_form.tsx @@ -96,7 +96,7 @@ export type ActionTypeFormProps = { notifyWhenSelectOptions?: NotifyWhenSelectOptions[]; featureId: string; producerId: string; - ruleTypeId?: string; + ruleTypeId: string; hasFieldsForAAD?: boolean; disableErrorMessages?: boolean; } & Pick< @@ -507,7 +507,6 @@ export const ActionTypeForm = ({ setActionAlertsFilterProperty('query', query, index)} - ruleTypeIds={ruleTypeId ? [ruleTypeId] : []} appName={featureId!} ruleTypeId={ruleTypeId} plugins={{ From c27937f4ea45004b24a9f3188812a1c3993a6cad Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Sun, 29 Sep 2024 18:38:24 +0300 Subject: [PATCH 069/106] Use the ruleTypeIds filter in the search strategy --- .../server/routes/legacy/health.test.ts | 2 +- .../alerting/server/task_runner/types.ts | 2 +- .../lib/get_rule_type_ids_filter.test.tsx | 26 +++++++++++++ .../server/lib/get_rule_type_ids_filter.tsx | 13 +++++++ .../search_strategy/search_strategy.test.ts | 37 +++++++++++++++++++ .../server/search_strategy/search_strategy.ts | 12 +++++- .../action_connector_form/action_form.tsx | 2 +- .../alerts_table/alerts_table_state.test.tsx | 4 +- .../rules_list/components/rules_list.tsx | 10 ++--- 9 files changed, 95 insertions(+), 13 deletions(-) create mode 100644 x-pack/plugins/rule_registry/server/lib/get_rule_type_ids_filter.test.tsx create mode 100644 x-pack/plugins/rule_registry/server/lib/get_rule_type_ids_filter.tsx diff --git a/x-pack/plugins/alerting/server/routes/legacy/health.test.ts b/x-pack/plugins/alerting/server/routes/legacy/health.test.ts index 93256c4dfd3f6e..a372415408a3d4 100644 --- a/x-pack/plugins/alerting/server/routes/legacy/health.test.ts +++ b/x-pack/plugins/alerting/server/routes/legacy/health.test.ts @@ -95,7 +95,7 @@ describe('healthRoute', () => { }); it('should have internal access for serverless', async () => { - rulesClient.listRuleTypes.mockResolvedValueOnce(new Set(ruleTypes)); + rulesClient.listRuleTypes.mockResolvedValueOnce(ruleTypes); const router = httpServiceMock.createRouter(); const licenseState = licenseStateMock.create(); diff --git a/x-pack/plugins/alerting/server/task_runner/types.ts b/x-pack/plugins/alerting/server/task_runner/types.ts index 8598987e12f9dd..bab07e642c5a78 100644 --- a/x-pack/plugins/alerting/server/task_runner/types.ts +++ b/x-pack/plugins/alerting/server/task_runner/types.ts @@ -169,7 +169,7 @@ export interface TaskRunnerContext { encryptedSavedObjectsClient: EncryptedSavedObjectsClient; eventLogger: IEventLogger; executionContext: ExecutionContextStart; - getRulesClientWithRequest(request: KibanaRequest): RulesClientApi; + getRulesClientWithRequest(request: KibanaRequest): Promise; kibanaBaseUrl: string | undefined; logger: Logger; maintenanceWindowsService: MaintenanceWindowsService; diff --git a/x-pack/plugins/rule_registry/server/lib/get_rule_type_ids_filter.test.tsx b/x-pack/plugins/rule_registry/server/lib/get_rule_type_ids_filter.test.tsx new file mode 100644 index 00000000000000..77c70d5ae2234c --- /dev/null +++ b/x-pack/plugins/rule_registry/server/lib/get_rule_type_ids_filter.test.tsx @@ -0,0 +1,26 @@ +/* + * 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 { getRuleTypeIdsFilter } from './get_rule_type_ids_filter'; + +describe('getRuleTypeIdsFilter()', () => { + it('should return a spaces filter', () => { + expect(getRuleTypeIdsFilter(['foo', 'bar'])).toStrictEqual({ + terms: { + 'kibana.alert.rule.rule_type_id': ['foo', 'bar'], + }, + }); + }); + + it('should return undefined if no rule type ids are provided', () => { + expect(getRuleTypeIdsFilter()).toBeUndefined(); + }); + + it('should return undefined if an empty array is provided', () => { + expect(getRuleTypeIdsFilter([])).toBeUndefined(); + }); +}); diff --git a/x-pack/plugins/rule_registry/server/lib/get_rule_type_ids_filter.tsx b/x-pack/plugins/rule_registry/server/lib/get_rule_type_ids_filter.tsx new file mode 100644 index 00000000000000..f204d6d17acffb --- /dev/null +++ b/x-pack/plugins/rule_registry/server/lib/get_rule_type_ids_filter.tsx @@ -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 { ALERT_RULE_TYPE_ID } from '../../common/technical_rule_data_field_names'; + +export function getRuleTypeIdsFilter(ruleTypeIds?: string[]) { + return ruleTypeIds && ruleTypeIds.length > 0 + ? { terms: { [ALERT_RULE_TYPE_ID]: ruleTypeIds } } + : undefined; +} diff --git a/x-pack/plugins/rule_registry/server/search_strategy/search_strategy.test.ts b/x-pack/plugins/rule_registry/server/search_strategy/search_strategy.test.ts index 6ce679a2108486..eed1c4e378ebfb 100644 --- a/x-pack/plugins/rule_registry/server/search_strategy/search_strategy.test.ts +++ b/x-pack/plugins/rule_registry/server/search_strategy/search_strategy.test.ts @@ -538,4 +538,41 @@ describe('ruleRegistrySearchStrategyProvider()', () => { expect(err.statusCode).toBe(500); expect(err.message).toBe('plain error message'); }); + + it('should apply the rule type IDs filter', async () => { + const request: RuleRegistrySearchRequest = { + ruleTypeIds: ['siem.esqlRule'], + }; + + const options = {}; + const deps = { + request: {}, + }; + + getAuthorizedRuleTypesMock.mockResolvedValue([]); + getAlertIndicesAliasMock.mockReturnValue(['security-siem']); + + const strategy = ruleRegistrySearchStrategyProvider(data, alerting, logger, security, spaces); + + await lastValueFrom( + strategy.search(request, options, deps as unknown as SearchStrategyDependencies) + ); + + const arg0 = searchStrategySearch.mock.calls[0][0]; + expect(arg0.params.body.query).toMatchInlineSnapshot(` + Object { + "bool": Object { + "filter": Array [ + Object { + "terms": Object { + "kibana.alert.rule.rule_type_id": Array [ + "siem.esqlRule", + ], + }, + }, + ], + }, + } + `); + }); }); diff --git a/x-pack/plugins/rule_registry/server/search_strategy/search_strategy.ts b/x-pack/plugins/rule_registry/server/search_strategy/search_strategy.ts index 14f9c1f55300ac..852e9c80ab4eb3 100644 --- a/x-pack/plugins/rule_registry/server/search_strategy/search_strategy.ts +++ b/x-pack/plugins/rule_registry/server/search_strategy/search_strategy.ts @@ -27,6 +27,7 @@ import type { RuleRegistrySearchRequest, RuleRegistrySearchResponse } from '../. import { MAX_ALERT_SEARCH_SIZE } from '../../common/constants'; import { AlertAuditAction, alertAuditEvent } from '..'; import { getSpacesFilter, getAuthzFilter } from '../lib'; +import { getRuleTypeIdsFilter } from '../lib/get_rule_type_ids_filter'; export const EMPTY_RESPONSE: RuleRegistrySearchResponse = { rawResponse: {} as RuleRegistrySearchResponse['rawResponse'], @@ -90,8 +91,7 @@ export const ruleRegistrySearchStrategyProvider = ( if (!isAnyRuleTypeESAuthorized && ruleTypeIds.length > 0) { authzFilter = (await getAuthzFilter( authorization, - ReadOperations.Find, - ruleTypeIds + ReadOperations.Find )) as estypes.QueryDslQueryContainer; } @@ -120,13 +120,21 @@ export const ruleRegistrySearchStrategyProvider = ( ? request.query?.bool?.filter : [request.query?.bool?.filter] : []; + if (authzFilter) { filter.push(authzFilter); } + if (space?.id) { filter.push(getSpacesFilter(space.id) as estypes.QueryDslQueryContainer); } + const ruleTypeFilter = getRuleTypeIdsFilter(request.ruleTypeIds); + + if (ruleTypeFilter) { + filter.push(ruleTypeFilter); + } + const sort = request.sort ?? []; const query = { diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_form.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_form.tsx index 940583ea5bcedf..69704dab10682e 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_form.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_form.tsx @@ -70,7 +70,7 @@ export interface ActionAccordionFormProps { ) => void; featureId: string; producerId: string; - ruleTypeId?: string; + ruleTypeId: string; messageVariables?: ActionVariables; summaryMessageVariables?: ActionVariables; setHasActionsDisabled?: (value: boolean) => void; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/alerts_table_state.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/alerts_table_state.test.tsx index e9be0205aef625..99ed78b7fc80cf 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/alerts_table_state.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/alerts_table_state.test.tsx @@ -897,9 +897,7 @@ describe('AlertsTableState', () => { }); it('should insert a new field as column when its not a default one', async () => { - const { getByTestId, findByTestId, queryByTestId } = render( - - ); + const { findByTestId, queryByTestId } = render(); expect(queryByTestId(`dataGridHeaderCell-${AlertsField.uuid}`)).toBe(null); fireEvent.click(await findByTestId('show-field-browser')); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list.tsx index a36068125a6a56..c68d276e28f378 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list.tsx @@ -115,7 +115,7 @@ const RuleAdd = lazy(() => import('../../rule_form/rule_add')); const RuleEdit = lazy(() => import('../../rule_form/rule_edit')); export interface RulesListProps { - filterConsumers?: string[]; + ruleTypeIds?: string[]; filteredRuleTypes?: string[]; lastResponseFilter?: string[]; lastRunOutcomeFilter?: string[]; @@ -156,7 +156,7 @@ const initialPercentileOptions = Object.values(Percentiles).map((percentile) => const EMPTY_ARRAY: string[] = []; export const RulesList = ({ - filterConsumers, + ruleTypeIds, filteredRuleTypes = EMPTY_ARRAY, lastResponseFilter, lastRunOutcomeFilter, @@ -280,7 +280,7 @@ export const RulesList = ({ // Fetch rules const { rulesState, loadRules, hasData, lastUpdate } = useLoadRulesQuery({ - filterConsumers, + ruleTypeIds, filters: computedFilter, hasDefaultRuleTypesFiltersOn, page, @@ -293,7 +293,7 @@ export const RulesList = ({ // Fetch status aggregation const { loadRuleAggregations, rulesStatusesTotal, rulesLastRunOutcomesTotal } = useLoadRuleAggregationsQuery({ - filterConsumers, + ruleTypeIds, filters: computedFilter, enabled: canLoadRules, refresh, @@ -756,7 +756,7 @@ export const RulesList = ({ {showSearchBar && !isEmpty(filters.ruleParams) ? ( ) : null} - + Date: Sun, 29 Sep 2024 19:01:56 +0300 Subject: [PATCH 070/106] Use the ruleTypeIds filter in the alerts client --- .../alert_data_client/alerts_client.test.ts | 151 ++++++++++++++++++ .../server/alert_data_client/alerts_client.ts | 14 +- 2 files changed, 159 insertions(+), 6 deletions(-) create mode 100644 x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.test.ts diff --git a/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.test.ts b/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.test.ts new file mode 100644 index 00000000000000..f1e793d104fbc3 --- /dev/null +++ b/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.test.ts @@ -0,0 +1,151 @@ +/* + * 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 { coreMock, loggingSystemMock } from '@kbn/core/server/mocks'; +import { alertingAuthorizationMock } from '@kbn/alerting-plugin/server/authorization/alerting_authorization.mock'; +import { ruleDataServiceMock } from '../rule_data_plugin_service/rule_data_plugin_service.mock'; +import { AlertsClient, ConstructorOptions } from './alerts_client'; +import { fromKueryExpression } from '@kbn/es-query'; + +describe('AlertsClient', () => { + const alertingAuthMock = alertingAuthorizationMock.create(); + const ruleDataService = ruleDataServiceMock.create(); + const requestHandlerContext = coreMock.createRequestHandlerContext(); + const esClientMock = requestHandlerContext.elasticsearch.client.asCurrentUser; + + let alertsClient: AlertsClient; + + beforeEach(() => { + jest.clearAllMocks(); + alertingAuthMock.getSpaceId.mockReturnValue('space-1'); + alertingAuthMock.getAllAuthorizedRuleTypesFindOperation.mockResolvedValue( + new Map([ + [ + 'test-rule-type-1', + { + id: 'test-rule-type-1', + authorizedConsumers: { foo: { all: true, read: true } }, + }, + ], + ]) + ); + + alertingAuthMock.getAuthorizationFilter.mockResolvedValue({ + filter: fromKueryExpression( + 'alert.attributes.alertTypeId: test-rule-type-1 AND alert.attributes.consumer: foo' + ), + ensureRuleTypeIsAuthorized: jest.fn(), + }); + + const alertsClientParams: ConstructorOptions = { + logger: loggingSystemMock.create().get(), + authorization: alertingAuthMock, + esClient: esClientMock, + ruleDataService, + getRuleType: jest.fn(), + getRuleList: jest.fn(), + getAlertIndicesAlias: jest.fn(), + }; + + alertsClient = new AlertsClient(alertsClientParams); + }); + + describe('find', () => { + it('creates the ruleTypeIds filter correctly', async () => { + await alertsClient.find({ ruleTypeIds: ['test-rule-type-1', 'test-rule-type-2'] }); + + expect(esClientMock.search.mock.calls[0][0]).toMatchInlineSnapshot(` + Object { + "body": Object { + "_source": undefined, + "aggs": undefined, + "fields": Array [ + "kibana.alert.rule.rule_type_id", + "kibana.alert.rule.consumer", + "kibana.alert.workflow_status", + "kibana.space_ids", + ], + "query": Object { + "bool": Object { + "filter": Array [ + Object { + "arguments": Array [ + Object { + "arguments": Array [ + Object { + "isQuoted": false, + "type": "literal", + "value": "alert.attributes.alertTypeId", + }, + Object { + "isQuoted": false, + "type": "literal", + "value": "test-rule-type-1", + }, + ], + "function": "is", + "type": "function", + }, + Object { + "arguments": Array [ + Object { + "isQuoted": false, + "type": "literal", + "value": "alert.attributes.consumer", + }, + Object { + "isQuoted": false, + "type": "literal", + "value": "foo", + }, + ], + "function": "is", + "type": "function", + }, + ], + "function": "and", + "type": "function", + }, + Object { + "term": Object { + "kibana.space_ids": "space-1", + }, + }, + Object { + "terms": Object { + "kibana.alert.rule.rule_type_id": Array [ + "test-rule-type-1", + "test-rule-type-2", + ], + }, + }, + ], + "must": Array [], + "must_not": Array [], + "should": Array [], + }, + }, + "runtime_mappings": undefined, + "size": undefined, + "sort": Array [ + Object { + "@timestamp": Object { + "order": "asc", + "unmapped_type": "date", + }, + }, + ], + "track_total_hits": undefined, + }, + "ignore_unavailable": true, + "index": ".alerts-*", + "seq_no_primary_term": true, + } + `); + }); + }); +}); diff --git a/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts b/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts index a9781d4817735d..43c870ad6a83f5 100644 --- a/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts +++ b/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts @@ -62,6 +62,7 @@ import { MAX_ALERTS_PAGES, MAX_PAGINATED_ALERTS, } from './constants'; +import { getRuleTypeIdsFilter } from '../lib/get_rule_type_ids_filter'; // TODO: Fix typings https://github.com/elastic/kibana/issues/101776 type NonNullableProps = Omit & { @@ -456,13 +457,12 @@ export class AlertsClient { ruleTypeIds?: string[] ) { try { - const authzFilter = (await getAuthzFilter( - this.authorization, - operation, - ruleTypeIds - )) as Filter; + const authzFilter = (await getAuthzFilter(this.authorization, operation)) as Filter; const spacesFilter = getSpacesFilter(alertSpaceId) as unknown as Filter; + const ruleTypeIdsFilter = getRuleTypeIdsFilter(ruleTypeIds) as unknown as Filter; + let esQuery; + if (id != null) { esQuery = { query: `_id:${id}`, language: 'kuery' }; } else if (typeof query === 'string') { @@ -470,12 +470,14 @@ export class AlertsClient { } else if (query != null && typeof query === 'object') { esQuery = []; } + const builtQuery = buildEsQuery( undefined, esQuery == null ? { query: ``, language: 'kuery' } : esQuery, - [authzFilter, spacesFilter], + [authzFilter, spacesFilter, ruleTypeIdsFilter], config ); + if (query != null && typeof query === 'object') { return { ...builtQuery, From c1be2825fe52885b38cfa503c78a70f2eb435f5e Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Mon, 30 Sep 2024 11:30:54 +0300 Subject: [PATCH 071/106] Make rule type ID optional again --- packages/kbn-alerts-ui-shared/src/alerts_search_bar/index.tsx | 2 +- packages/kbn-alerts-ui-shared/src/alerts_search_bar/types.ts | 2 +- .../src/rule_form/rule_actions/rule_actions_alerts_filter.tsx | 2 +- x-pack/plugins/monitoring/public/alerts/alert_form.test.tsx | 1 + .../sections/action_connector_form/action_form.test.tsx | 1 + .../application/sections/action_connector_form/action_form.tsx | 2 +- .../sections/action_connector_form/action_type_form.tsx | 2 +- 7 files changed, 7 insertions(+), 5 deletions(-) diff --git a/packages/kbn-alerts-ui-shared/src/alerts_search_bar/index.tsx b/packages/kbn-alerts-ui-shared/src/alerts_search_bar/index.tsx index c4e44c39980172..af4713dbfa8392 100644 --- a/packages/kbn-alerts-ui-shared/src/alerts_search_bar/index.tsx +++ b/packages/kbn-alerts-ui-shared/src/alerts_search_bar/index.tsx @@ -43,7 +43,7 @@ export const AlertsSearchBar = ({ }: AlertsSearchBarProps) => { const [queryLanguage, setQueryLanguage] = useState('kuery'); const { dataView } = useAlertsDataView({ - ruleTypeIds: [ruleTypeId], + ruleTypeIds: ruleTypeId != null ? [ruleTypeId] : [], http, toasts, dataViewsService, diff --git a/packages/kbn-alerts-ui-shared/src/alerts_search_bar/types.ts b/packages/kbn-alerts-ui-shared/src/alerts_search_bar/types.ts index 43f58a8cc3bebf..d091cc1ba690dc 100644 --- a/packages/kbn-alerts-ui-shared/src/alerts_search_bar/types.ts +++ b/packages/kbn-alerts-ui-shared/src/alerts_search_bar/types.ts @@ -26,7 +26,7 @@ export interface AlertsSearchBarProps { showSubmitButton?: boolean; placeholder?: string; submitOnBlur?: boolean; - ruleTypeId: string; + ruleTypeId?: string; onQueryChange?: (query: { dateRange: { from: string; to: string; mode?: 'absolute' | 'relative' }; query?: string; diff --git a/packages/kbn-alerts-ui-shared/src/rule_form/rule_actions/rule_actions_alerts_filter.tsx b/packages/kbn-alerts-ui-shared/src/rule_form/rule_actions/rule_actions_alerts_filter.tsx index 57f167bff098b1..3c5ef33deedb1b 100644 --- a/packages/kbn-alerts-ui-shared/src/rule_form/rule_actions/rule_actions_alerts_filter.tsx +++ b/packages/kbn-alerts-ui-shared/src/rule_form/rule_actions/rule_actions_alerts_filter.tsx @@ -24,7 +24,7 @@ export interface RuleActionsAlertsFilterProps { action: RuleAction; onChange: (update?: AlertsFilter['query']) => void; appName: string; - ruleTypeId: string; + ruleTypeId?: string; plugins?: { http: RuleFormPlugins['http']; notifications: RuleFormPlugins['notifications']; diff --git a/x-pack/plugins/monitoring/public/alerts/alert_form.test.tsx b/x-pack/plugins/monitoring/public/alerts/alert_form.test.tsx index 2cca4638876c9b..f1e84753820fe9 100644 --- a/x-pack/plugins/monitoring/public/alerts/alert_form.test.tsx +++ b/x-pack/plugins/monitoring/public/alerts/alert_form.test.tsx @@ -270,6 +270,7 @@ describe('alert_form', () => { actionTypeRegistry={actionTypeRegistry} featureId="alerting" producerId="alerting" + ruleTypeId=".es-query" /> diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_form.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_form.test.tsx index 74b528ba7a64af..2c5f159d0a76f2 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_form.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_form.test.tsx @@ -399,6 +399,7 @@ describe('action_form', () => { } actionTypeRegistry={actionTypeRegistry} setHasActionsWithBrokenConnector={setHasActionsWithBrokenConnector} + ruleTypeId=".es-query" /> ); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_form.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_form.tsx index 69704dab10682e..940583ea5bcedf 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_form.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_form.tsx @@ -70,7 +70,7 @@ export interface ActionAccordionFormProps { ) => void; featureId: string; producerId: string; - ruleTypeId: string; + ruleTypeId?: string; messageVariables?: ActionVariables; summaryMessageVariables?: ActionVariables; setHasActionsDisabled?: (value: boolean) => void; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_type_form.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_type_form.tsx index 70d602ac34bd39..3079a6cf75b4dc 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_type_form.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_type_form.tsx @@ -96,7 +96,7 @@ export type ActionTypeFormProps = { notifyWhenSelectOptions?: NotifyWhenSelectOptions[]; featureId: string; producerId: string; - ruleTypeId: string; + ruleTypeId?: string; hasFieldsForAAD?: boolean; disableErrorMessages?: boolean; } & Pick< From 46097ff177f042b047bcec2d8b3e3245ce85f004 Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Mon, 30 Sep 2024 13:18:57 +0300 Subject: [PATCH 072/106] Fix find URLs --- .../server/task_runner/rule_loader.test.ts | 2 +- .../application/lib/rule_api/alert_index.ts | 25 ------------------- .../tests/alerting/group1/create.ts | 9 +++---- .../tests/alerting/group2/update.ts | 9 +++---- 4 files changed, 9 insertions(+), 36 deletions(-) delete mode 100644 x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/alert_index.ts diff --git a/x-pack/plugins/alerting/server/task_runner/rule_loader.test.ts b/x-pack/plugins/alerting/server/task_runner/rule_loader.test.ts index 0aa3625b67e2aa..a6e50c9192110d 100644 --- a/x-pack/plugins/alerting/server/task_runner/rule_loader.test.ts +++ b/x-pack/plugins/alerting/server/task_runner/rule_loader.test.ts @@ -78,7 +78,7 @@ describe('rule_loader', () => { jest.restoreAllMocks(); }); - describe('await validateRuleAndCreateFakeRequest()', () => { + describe('validateRuleAndCreateFakeRequest()', () => { describe('succeeds', () => { test('validates and returns the results', async () => { const result = await validateRuleAndCreateFakeRequest({ diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/alert_index.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/alert_index.ts deleted file mode 100644 index dd8eb336289b20..00000000000000 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/alert_index.ts +++ /dev/null @@ -1,25 +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 { BASE_RAC_ALERTS_API_PATH } from '@kbn/rule-registry-plugin/common'; -import { HttpSetup } from '@kbn/core/public'; - -export async function fetchAlertIndexNames({ - http, - ruleTypeIds, -}: { - http: HttpSetup; - ruleTypeIds: string; -}): Promise { - const { index_name: indexNamesStr = [] } = await http.get<{ index_name: string[] }>( - `${BASE_RAC_ALERTS_API_PATH}/index`, - { - query: { ruleTypeIds }, - } - ); - return indexNamesStr; -} diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/create.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/create.ts index 8c9780aec843ab..2c4faf9d649017 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/create.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/create.ts @@ -340,11 +340,10 @@ export default function createAlertTests({ getService }: FtrProviderContext) { ) .expect(200); - const response = await supertest.get( - `${getUrlPrefix( - Spaces.space1.id - )}/internal/alerting/rules/_find?filter=alert.attributes.params.risk_score:40` - ); + const response = await supertest + .post(`${getUrlPrefix(Spaces.space1.id)}/internal/alerting/rules/_find`) + .set('kbn-xsrf', 'foo') + .send({ filter: 'alert.attributes.params.risk_score:40' }); expect(response.status).to.eql(200); objectRemover.add(Spaces.space1.id, createResponse.body.id, 'rule', 'alerting'); diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group2/update.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group2/update.ts index 9de2664338b076..ba312424f37223 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group2/update.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group2/update.ts @@ -85,11 +85,10 @@ export default function createUpdateTests({ getService }: FtrProviderContext) { expect(Date.parse(response.body.next_run)).to.be.greaterThan(0); } - response = await supertest.get( - `${getUrlPrefix( - Spaces.space1.id - )}/internal/alerting/rules/_find?filter=alert.attributes.params.risk_score:40` - ); + response = await supertest + .post(`${getUrlPrefix(Spaces.space1.id)}/internal/alerting/rules/_find`) + .set('kbn-xsrf', 'foo') + .send({ filter: 'alert.attributes.params.risk_score:40' }); expect(response.body.data[0].mapped_params).to.eql({ risk_score: 40, From e0a9061c1f2476d4744aa7670c4e4906ef5da121 Mon Sep 17 00:00:00 2001 From: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Date: Mon, 30 Sep 2024 11:07:06 +0000 Subject: [PATCH 073/106] [CI] Auto-commit changed files from 'make api-docs && make api-docs-staging' --- oas_docs/output/kibana.serverless.staging.yaml | 8 -------- oas_docs/output/kibana.serverless.yaml | 8 -------- oas_docs/output/kibana.staging.yaml | 8 -------- oas_docs/output/kibana.yaml | 8 -------- 4 files changed, 32 deletions(-) diff --git a/oas_docs/output/kibana.serverless.staging.yaml b/oas_docs/output/kibana.serverless.staging.yaml index cf5cdbac0e9a4c..97285129c912cb 100644 --- a/oas_docs/output/kibana.serverless.staging.yaml +++ b/oas_docs/output/kibana.serverless.staging.yaml @@ -4409,14 +4409,6 @@ paths: required: false schema: type: string - - in: query - name: filter_consumers - required: false - schema: - items: - description: List of consumers to filter. - type: string - type: array responses: '200': content: diff --git a/oas_docs/output/kibana.serverless.yaml b/oas_docs/output/kibana.serverless.yaml index 675e8c0903b2f2..37556e7e429397 100644 --- a/oas_docs/output/kibana.serverless.yaml +++ b/oas_docs/output/kibana.serverless.yaml @@ -4409,14 +4409,6 @@ paths: required: false schema: type: string - - in: query - name: filter_consumers - required: false - schema: - items: - description: List of consumers to filter. - type: string - type: array responses: '200': content: diff --git a/oas_docs/output/kibana.staging.yaml b/oas_docs/output/kibana.staging.yaml index c70f9b4bce4543..8545525dc82101 100644 --- a/oas_docs/output/kibana.staging.yaml +++ b/oas_docs/output/kibana.staging.yaml @@ -4789,14 +4789,6 @@ paths: required: false schema: type: string - - in: query - name: filter_consumers - required: false - schema: - items: - description: List of consumers to filter. - type: string - type: array responses: '200': content: diff --git a/oas_docs/output/kibana.yaml b/oas_docs/output/kibana.yaml index 947ae1155041f0..a18e7090aceb66 100644 --- a/oas_docs/output/kibana.yaml +++ b/oas_docs/output/kibana.yaml @@ -4789,14 +4789,6 @@ paths: required: false schema: type: string - - in: query - name: filter_consumers - required: false - schema: - items: - description: List of consumers to filter. - type: string - type: array responses: '200': content: From ddefd3b3e7c85a16b2a9e73176c7fa4a4c534026 Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Thu, 3 Oct 2024 11:21:37 +0300 Subject: [PATCH 074/106] Support filtering by consumers in the aggregate API --- .../routes/rule/apis/aggregate/schemas/v1.ts | 1 + .../methods/aggregate/aggregate_rules.test.ts | 265 ++++++++++++++++++ .../rule/methods/aggregate/aggregate_rules.ts | 6 +- .../schemas/aggregate_options_schema.ts | 1 + .../transform_aggregate_query_request/v1.ts | 2 + .../rules_client/common/filters.test.ts | 54 ++++ .../server/rules_client/common/filters.ts | 8 + .../group2/tests/alerting/aggregate.ts | 134 ++++++++- .../security_and_spaces/scenarios.ts | 3 +- .../tests/alerting/group1/aggregate.ts | 79 +++++- 10 files changed, 547 insertions(+), 6 deletions(-) diff --git a/x-pack/plugins/alerting/common/routes/rule/apis/aggregate/schemas/v1.ts b/x-pack/plugins/alerting/common/routes/rule/apis/aggregate/schemas/v1.ts index fccc922df4415c..57a9499779add3 100644 --- a/x-pack/plugins/alerting/common/routes/rule/apis/aggregate/schemas/v1.ts +++ b/x-pack/plugins/alerting/common/routes/rule/apis/aggregate/schemas/v1.ts @@ -25,6 +25,7 @@ export const aggregateRulesRequestBodySchema = schema.object({ ), filter: schema.maybe(schema.string()), rule_type_ids: schema.maybe(schema.arrayOf(schema.string())), + consumers: schema.maybe(schema.arrayOf(schema.string())), }); export const aggregateRulesResponseBodySchema = schema.object({ diff --git a/x-pack/plugins/alerting/server/application/rule/methods/aggregate/aggregate_rules.test.ts b/x-pack/plugins/alerting/server/application/rule/methods/aggregate/aggregate_rules.test.ts index 25be70e73a0573..aed95800dbbe3e 100644 --- a/x-pack/plugins/alerting/server/application/rule/methods/aggregate/aggregate_rules.test.ts +++ b/x-pack/plugins/alerting/server/application/rule/methods/aggregate/aggregate_rules.test.ts @@ -388,6 +388,271 @@ describe('aggregate()', () => { ]); }); + test('supports filtering by rule type IDs when aggregating', async () => { + const authFilter = fromKueryExpression( + 'alert.attributes.alertTypeId:myType and alert.attributes.consumer:myApp' + ); + + authorization.getFindAuthorizationFilter.mockResolvedValue({ + filter: authFilter, + ensureRuleTypeIsAuthorized() {}, + }); + + const rulesClient = new RulesClient(rulesClientParams); + await rulesClient.aggregate({ + options: { ruleTypeIds: ['my-rule-type-id'] }, + aggs: defaultRuleAggregationFactory(), + }); + + expect(unsecuredSavedObjectsClient.find).toHaveBeenCalledTimes(1); + expect(unsecuredSavedObjectsClient.find.mock.calls[0]).toMatchInlineSnapshot(` + Array [ + Object { + "aggs": Object { + "enabled": Object { + "terms": Object { + "field": "alert.attributes.enabled", + }, + }, + "muted": Object { + "terms": Object { + "field": "alert.attributes.muteAll", + }, + }, + "outcome": Object { + "terms": Object { + "field": "alert.attributes.lastRun.outcome", + }, + }, + "snoozed": Object { + "aggs": Object { + "count": Object { + "filter": Object { + "exists": Object { + "field": "alert.attributes.snoozeSchedule.duration", + }, + }, + }, + }, + "nested": Object { + "path": "alert.attributes.snoozeSchedule", + }, + }, + "status": Object { + "terms": Object { + "field": "alert.attributes.executionStatus.status", + }, + }, + "tags": Object { + "terms": Object { + "field": "alert.attributes.tags", + "order": Object { + "_key": "asc", + }, + "size": 50, + }, + }, + }, + "filter": Object { + "arguments": Array [ + Object { + "arguments": Array [ + Object { + "isQuoted": false, + "type": "literal", + "value": "alert.attributes.alertTypeId", + }, + Object { + "isQuoted": false, + "type": "literal", + "value": "my-rule-type-id", + }, + ], + "function": "is", + "type": "function", + }, + Object { + "arguments": Array [ + Object { + "arguments": Array [ + Object { + "isQuoted": false, + "type": "literal", + "value": "alert.attributes.alertTypeId", + }, + Object { + "isQuoted": false, + "type": "literal", + "value": "myType", + }, + ], + "function": "is", + "type": "function", + }, + Object { + "arguments": Array [ + Object { + "isQuoted": false, + "type": "literal", + "value": "alert.attributes.consumer", + }, + Object { + "isQuoted": false, + "type": "literal", + "value": "myApp", + }, + ], + "function": "is", + "type": "function", + }, + ], + "function": "and", + "type": "function", + }, + ], + "function": "and", + "type": "function", + }, + "page": 1, + "perPage": 0, + "type": "alert", + }, + ] + `); + }); + + test('supports filtering by consumers when aggregating', async () => { + const authFilter = fromKueryExpression( + 'alert.attributes.alertTypeId:myType and alert.attributes.consumer:myApp' + ); + authorization.getFindAuthorizationFilter.mockResolvedValue({ + filter: authFilter, + ensureRuleTypeIsAuthorized() {}, + }); + + const rulesClient = new RulesClient(rulesClientParams); + await rulesClient.aggregate({ + options: { consumers: ['my-consumer'] }, + aggs: defaultRuleAggregationFactory(), + }); + + expect(unsecuredSavedObjectsClient.find).toHaveBeenCalledTimes(1); + expect(unsecuredSavedObjectsClient.find.mock.calls[0]).toMatchInlineSnapshot(` + Array [ + Object { + "aggs": Object { + "enabled": Object { + "terms": Object { + "field": "alert.attributes.enabled", + }, + }, + "muted": Object { + "terms": Object { + "field": "alert.attributes.muteAll", + }, + }, + "outcome": Object { + "terms": Object { + "field": "alert.attributes.lastRun.outcome", + }, + }, + "snoozed": Object { + "aggs": Object { + "count": Object { + "filter": Object { + "exists": Object { + "field": "alert.attributes.snoozeSchedule.duration", + }, + }, + }, + }, + "nested": Object { + "path": "alert.attributes.snoozeSchedule", + }, + }, + "status": Object { + "terms": Object { + "field": "alert.attributes.executionStatus.status", + }, + }, + "tags": Object { + "terms": Object { + "field": "alert.attributes.tags", + "order": Object { + "_key": "asc", + }, + "size": 50, + }, + }, + }, + "filter": Object { + "arguments": Array [ + Object { + "arguments": Array [ + Object { + "isQuoted": false, + "type": "literal", + "value": "alert.attributes.consumer", + }, + Object { + "isQuoted": false, + "type": "literal", + "value": "my-consumer", + }, + ], + "function": "is", + "type": "function", + }, + Object { + "arguments": Array [ + Object { + "arguments": Array [ + Object { + "isQuoted": false, + "type": "literal", + "value": "alert.attributes.alertTypeId", + }, + Object { + "isQuoted": false, + "type": "literal", + "value": "myType", + }, + ], + "function": "is", + "type": "function", + }, + Object { + "arguments": Array [ + Object { + "isQuoted": false, + "type": "literal", + "value": "alert.attributes.consumer", + }, + Object { + "isQuoted": false, + "type": "literal", + "value": "myApp", + }, + ], + "function": "is", + "type": "function", + }, + ], + "function": "and", + "type": "function", + }, + ], + "function": "and", + "type": "function", + }, + "page": 1, + "perPage": 0, + "type": "alert", + }, + ] + `); + }); + test('logs audit event when not authorized to aggregate rules', async () => { const rulesClient = new RulesClient({ ...rulesClientParams, auditLogger }); authorization.getFindAuthorizationFilter.mockRejectedValue(new Error('Unauthorized')); diff --git a/x-pack/plugins/alerting/server/application/rule/methods/aggregate/aggregate_rules.ts b/x-pack/plugins/alerting/server/application/rule/methods/aggregate/aggregate_rules.ts index 24a9e2f46d6e22..e7efe215aed77d 100644 --- a/x-pack/plugins/alerting/server/application/rule/methods/aggregate/aggregate_rules.ts +++ b/x-pack/plugins/alerting/server/application/rule/methods/aggregate/aggregate_rules.ts @@ -7,6 +7,7 @@ import type { KueryNode } from '@kbn/es-query'; import { + buildConsumersFilter, buildRuleTypeIdsFilter, combineFilterWithAuthorizationFilter, combineFilters, @@ -26,7 +27,7 @@ export async function aggregateRules>( params: AggregateParams ): Promise { const { options = {}, aggs } = params; - const { filter, page = 1, perPage = 0, ruleTypeIds, ...restOptions } = options; + const { filter, page = 1, perPage = 0, ruleTypeIds, consumers, ...restOptions } = options; let authorizationTuple; try { @@ -50,7 +51,8 @@ export async function aggregateRules>( const { filter: authorizationFilter } = authorizationTuple; const filterKueryNode = buildKueryNodeFilter(filter); const ruleTypeIdsFilter = buildRuleTypeIdsFilter(ruleTypeIds); - const combinedFilters = combineFilters([filterKueryNode, ruleTypeIdsFilter]); + const consumersFilter = buildConsumersFilter(consumers); + const combinedFilters = combineFilters([filterKueryNode, ruleTypeIdsFilter, consumersFilter]); const { aggregations } = await findRulesSo({ savedObjectsClient: context.unsecuredSavedObjectsClient, diff --git a/x-pack/plugins/alerting/server/application/rule/methods/aggregate/schemas/aggregate_options_schema.ts b/x-pack/plugins/alerting/server/application/rule/methods/aggregate/schemas/aggregate_options_schema.ts index 35b166385b46f0..d26f48e2462f5f 100644 --- a/x-pack/plugins/alerting/server/application/rule/methods/aggregate/schemas/aggregate_options_schema.ts +++ b/x-pack/plugins/alerting/server/application/rule/methods/aggregate/schemas/aggregate_options_schema.ts @@ -17,6 +17,7 @@ export const aggregateOptionsSchema = schema.object({ }) ), ruleTypeIds: schema.maybe(schema.arrayOf(schema.string())), + consumers: schema.maybe(schema.arrayOf(schema.string())), // filter type is `string | KueryNode`, but `KueryNode` has no schema to import yet filter: schema.maybe( schema.oneOf([schema.string(), schema.recordOf(schema.string(), schema.any())]) diff --git a/x-pack/plugins/alerting/server/routes/rule/apis/aggregate/transforms/transform_aggregate_query_request/v1.ts b/x-pack/plugins/alerting/server/routes/rule/apis/aggregate/transforms/transform_aggregate_query_request/v1.ts index 5f72c2ab84f146..ae13f08d0afa50 100644 --- a/x-pack/plugins/alerting/server/routes/rule/apis/aggregate/transforms/transform_aggregate_query_request/v1.ts +++ b/x-pack/plugins/alerting/server/routes/rule/apis/aggregate/transforms/transform_aggregate_query_request/v1.ts @@ -14,6 +14,7 @@ export const transformAggregateQueryRequest: RewriteRequestCase ({ defaultSearchOperator, @@ -21,5 +22,6 @@ export const transformAggregateQueryRequest: RewriteRequestCase { `); }); }); + + describe('buildConsumersFilter', () => { + it('returns undefined if ruleTypeIds is undefined', () => { + expect(buildConsumersFilter()).toBeUndefined(); + }); + + it('returns undefined if ruleTypeIds is is an empty array', () => { + expect(buildConsumersFilter([])).toBeUndefined(); + }); + + it('builds the filter correctly', () => { + expect(buildConsumersFilter(['foo', 'bar'])).toMatchInlineSnapshot(` + Object { + "arguments": Array [ + Object { + "arguments": Array [ + Object { + "isQuoted": false, + "type": "literal", + "value": "alert.attributes.consumer", + }, + Object { + "isQuoted": false, + "type": "literal", + "value": "foo", + }, + ], + "function": "is", + "type": "function", + }, + Object { + "arguments": Array [ + Object { + "isQuoted": false, + "type": "literal", + "value": "alert.attributes.consumer", + }, + Object { + "isQuoted": false, + "type": "literal", + "value": "bar", + }, + ], + "function": "is", + "type": "function", + }, + ], + "function": "or", + "type": "function", + } + `); + }); + }); }); diff --git a/x-pack/plugins/alerting/server/rules_client/common/filters.ts b/x-pack/plugins/alerting/server/rules_client/common/filters.ts index 5246449c642bee..b0c3ccc5e1ec18 100644 --- a/x-pack/plugins/alerting/server/rules_client/common/filters.ts +++ b/x-pack/plugins/alerting/server/rules_client/common/filters.ts @@ -51,6 +51,14 @@ export const buildRuleTypeIdsFilter = (ruleTypeIds?: string[]) => { return buildFilter({ filters: ruleTypeIds, field: 'alertTypeId', operator: 'or' }); }; +export const buildConsumersFilter = (consumers?: string[]) => { + if (!consumers || !consumers?.length) { + return; + } + + return buildFilter({ filters: consumers, field: 'consumer', operator: 'or' }); +}; + /** * Combines Kuery nodes and accepts an array with a mixture of undefined and KueryNodes. This will filter out the undefined * filters and return a KueryNode with the filters combined using the specified operator which defaults to and if not defined. diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/aggregate.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/aggregate.ts index 8d0718897d2c8f..dde153aca402e4 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/aggregate.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/aggregate.ts @@ -7,7 +7,7 @@ import expect from '@kbn/expect'; import { Space, User } from '../../../../common/types'; -import { UserAtSpaceScenarios } from '../../../scenarios'; +import { Space1AllAtSpace1, SuperuserAtSpace1, UserAtSpaceScenarios } from '../../../scenarios'; import { getUrlPrefix, getTestRuleData, ObjectRemover, getEventLog } from '../../../../common/lib'; import { FtrProviderContext } from '../../../../common/ftr_provider_context'; @@ -209,6 +209,134 @@ export default function createAggregateTests({ getService }: FtrProviderContext) }); }); } + + describe('filtering', () => { + it('should return the correct rule stats when trying to exploit RBAC through the ruleTypeIds parameter', async () => { + const { user, space } = Space1AllAtSpace1; + + const okAlertId = await createTestAlert( + { + rule_type_id: 'test.restricted-noop', + schedule: { interval: '24h' }, + consumer: 'alertsRestrictedFixture', + }, + SuperuserAtSpace1.space, + SuperuserAtSpace1.user + ); + + const activeAlertId = await createTestAlert( + { + rule_type_id: 'test.patternFiring', + schedule: { interval: '24h' }, + params: { + pattern: { instance: new Array(100).fill(true) }, + }, + }, + SuperuserAtSpace1.space, + SuperuserAtSpace1.user + ); + + objectRemover.add(SuperuserAtSpace1.space.id, okAlertId, 'rule', 'alerting'); + objectRemover.add(SuperuserAtSpace1.space.id, activeAlertId, 'rule', 'alerting'); + + await aggregate({ + space, + user, + params: { rule_type_ids: ['test.restricted-noop', 'test.patternFiring'] }, + expectedStatusCode: 200, + expectedResponse: { + rule_enabled_status: { + disabled: 0, + enabled: 1, + }, + rule_execution_status: { + ok: 0, + active: 1, + error: 0, + pending: 0, + unknown: 0, + warning: 0, + }, + rule_last_run_outcome: { + succeeded: 1, + warning: 0, + failed: 0, + }, + rule_muted_status: { + muted: 0, + unmuted: 1, + }, + rule_snoozed_status: { + snoozed: 0, + }, + rule_tags: ['foo'], + }, + }); + }); + + it('should return the correct rule stats when trying to exploit RBAC through the consumer parameter', async () => { + const { user, space } = Space1AllAtSpace1; + + const okAlertId = await createTestAlert( + { + rule_type_id: 'test.restricted-noop', + schedule: { interval: '24h' }, + consumer: 'alertsRestrictedFixture', + }, + SuperuserAtSpace1.space, + SuperuserAtSpace1.user + ); + + const activeAlertId = await createTestAlert( + { + rule_type_id: 'test.patternFiring', + schedule: { interval: '24h' }, + params: { + pattern: { instance: new Array(100).fill(true) }, + }, + }, + SuperuserAtSpace1.space, + SuperuserAtSpace1.user + ); + + objectRemover.add(SuperuserAtSpace1.space.id, okAlertId, 'rule', 'alerting'); + objectRemover.add(SuperuserAtSpace1.space.id, activeAlertId, 'rule', 'alerting'); + + await aggregate({ + space, + user, + params: { consumers: ['alertsRestrictedFixture', 'alertsFixture'] }, + expectedStatusCode: 200, + expectedResponse: { + rule_enabled_status: { + disabled: 0, + enabled: 1, + }, + rule_execution_status: { + ok: 0, + active: 1, + error: 0, + pending: 0, + unknown: 0, + warning: 0, + }, + rule_last_run_outcome: { + succeeded: 1, + warning: 0, + failed: 0, + }, + rule_muted_status: { + muted: 0, + unmuted: 1, + }, + rule_snoozed_status: { + snoozed: 0, + }, + rule_tags: ['foo'], + }, + }); + }); + }); }); async function createTestAlert(testAlertOverrides = {}, space: Space, user: User) { @@ -227,18 +355,20 @@ export default function createAggregateTests({ getService }: FtrProviderContext) user, expectedStatusCode, expectedResponse, + params = {}, }: { space: Space; user: User; expectedStatusCode: number; expectedResponse: Record; + params?: Record; }) => { await retry.try(async () => { const response = await supertestWithoutAuth .post(`${getUrlPrefix(space.id)}/internal/alerting/rules/_aggregate`) .set('kbn-xsrf', 'foo') .auth(user.username, user.password) - .send({}); + .send(params); expect(response.status).to.eql(expectedStatusCode); expect(response.body).to.eql(expectedResponse); diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/scenarios.ts b/x-pack/test/alerting_api_integration/security_and_spaces/scenarios.ts index a852657e0b8913..b27631c57b6c4f 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/scenarios.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/scenarios.ts @@ -259,7 +259,8 @@ const GlobalReadAtSpace1: GlobalReadAtSpace1 = { interface Space1AllAtSpace1 extends Scenario { id: 'space_1_all at space1'; } -const Space1AllAtSpace1: Space1AllAtSpace1 = { + +export const Space1AllAtSpace1: Space1AllAtSpace1 = { id: 'space_1_all at space1', user: Space1All, space: Space1, diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/aggregate.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/aggregate.ts index 57181eb00a05a5..c1553d1ef8d9e8 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/aggregate.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/aggregate.ts @@ -159,7 +159,7 @@ export default function createAggregateTests({ getService }: FtrProviderContext) }); }); - it('should aggregate only filtered rules', async () => { + it('should aggregate only filtered rules by rule type IDs', async () => { const NumOkAlerts = 4; const NumActiveAlerts = 1; const NumErrorAlerts = 2; @@ -247,6 +247,83 @@ export default function createAggregateTests({ getService }: FtrProviderContext) }); }); + it('should aggregate only filtered rules by consumer', async () => { + const NumOkAlerts = 4; + const NumActiveAlerts = 1; + const NumErrorAlerts = 2; + + const okAlertIds: string[] = []; + const activeAlertIds: string[] = []; + const errorAlertIds: string[] = []; + + await Promise.all( + [...Array(NumOkAlerts)].map(async () => { + const okAlertId = await createTestAlert({ + rule_type_id: 'test.restricted-noop', + schedule: { interval: '24h' }, + consumer: 'alertsRestrictedFixture', + }); + okAlertIds.push(okAlertId); + objectRemover.add(Spaces.space1.id, okAlertId, 'rule', 'alerting'); + }) + ); + + await Promise.all(okAlertIds.map((id) => getEventLogWithRetry(id))); + + await Promise.all( + [...Array(NumActiveAlerts)].map(async () => { + const activeAlertId = await createTestAlert({ + rule_type_id: 'test.patternFiring', + schedule: { interval: '24h' }, + params: { + pattern: { instance: new Array(100).fill(true) }, + }, + }); + activeAlertIds.push(activeAlertId); + objectRemover.add(Spaces.space1.id, activeAlertId, 'rule', 'alerting'); + }) + ); + + await Promise.all(activeAlertIds.map((id) => getEventLogWithRetry(id))); + + await Promise.all( + [...Array(NumErrorAlerts)].map(async () => { + const errorAlertId = await createTestAlert({ + rule_type_id: 'test.throw', + schedule: { interval: '24h' }, + }); + errorAlertIds.push(errorAlertId); + objectRemover.add(Spaces.space1.id, errorAlertId, 'rule', 'alerting'); + }) + ); + + await Promise.all(errorAlertIds.map((id) => getEventLogWithRetry(id))); + + await retry.try(async () => { + const response = await supertest + .post(`${getUrlPrefix(Spaces.space1.id)}/internal/alerting/rules/_aggregate`) + .set('kbn-xsrf', 'foo') + .send({ consumers: ['alertsFixture'] }); + + expect(response.status).to.eql(200); + expect(response.body).to.eql({ + rule_execution_status: { + error: NumErrorAlerts, + active: NumActiveAlerts, + ok: 0, + pending: 0, + unknown: 0, + warning: 0, + }, + rule_last_run_outcome: { failed: 2, succeeded: 1, warning: 0 }, + rule_enabled_status: { enabled: 3, disabled: 0 }, + rule_muted_status: { muted: 0, unmuted: 3 }, + rule_snoozed_status: { snoozed: 0 }, + rule_tags: ['foo'], + }); + }); + }); + describe('tags limit', () => { it('should be 50 be default', async () => { const numOfAlerts = 3; From 8589fb563315db7e6c250aa0b0e1af0650b1b92d Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Thu, 3 Oct 2024 14:03:42 +0300 Subject: [PATCH 075/106] Support filtering by consumers while aggregating in the UI --- .../settings/indices_configuration_panel.tsx | 5 +- .../source_configuration_settings.tsx | 4 +- .../public/pages/alerts/alerts.tsx | 6 +-- .../public/pages/rules/rules_tab.tsx | 2 + .../hooks/use_load_rule_aggregations.test.tsx | 17 ++++--- .../hooks/use_load_rule_aggregations_query.ts | 7 +-- .../lib/rule_api/aggregate.test.ts | 46 +++---------------- .../application/lib/rule_api/aggregate.ts | 4 +- .../lib/rule_api/aggregate_helpers.ts | 2 +- .../rule_api/aggregate_kuery_filter.test.ts | 34 ++++++++++++++ .../lib/rule_api/aggregate_kuery_filter.ts | 4 +- .../components/stack_alerts_page.tsx | 2 +- .../alerts_page/hooks/use_rule_stats.tsx | 12 ++++- .../rules_list/components/rules_list.tsx | 3 ++ 14 files changed, 84 insertions(+), 64 deletions(-) diff --git a/x-pack/plugins/observability_solution/infra/public/pages/logs/settings/indices_configuration_panel.tsx b/x-pack/plugins/observability_solution/infra/public/pages/logs/settings/indices_configuration_panel.tsx index 8f42b4cf1bc6a0..333dfca2688067 100644 --- a/x-pack/plugins/observability_solution/infra/public/pages/logs/settings/indices_configuration_panel.tsx +++ b/x-pack/plugins/observability_solution/infra/public/pages/logs/settings/indices_configuration_panel.tsx @@ -19,7 +19,7 @@ import { import { EuiCallOut } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { loadRuleAggregations } from '@kbn/triggers-actions-ui-plugin/public'; -import { LOG_THRESHOLD_ALERT_TYPE_ID } from '@kbn/rule-data-utils'; +import { AlertConsumers, LOG_THRESHOLD_ALERT_TYPE_ID } from '@kbn/rule-data-utils'; import { rulesLocatorID, RulesParams } from '@kbn/observability-plugin/public'; import { EuiLink } from '@elastic/eui'; @@ -93,7 +93,8 @@ export const IndicesConfigurationPanel = React.memo<{ if (http) { const { ruleExecutionStatus } = await loadRuleAggregations({ http, - typesFilter: [LOG_THRESHOLD_ALERT_TYPE_ID], + ruleTypeIds: [LOG_THRESHOLD_ALERT_TYPE_ID], + consumers: [AlertConsumers.LOGS], }); const numberOfRules = Object.values(ruleExecutionStatus).reduce( (acc, value) => acc + value, diff --git a/x-pack/plugins/observability_solution/infra/public/pages/metrics/settings/source_configuration_settings.tsx b/x-pack/plugins/observability_solution/infra/public/pages/metrics/settings/source_configuration_settings.tsx index de078dcb354df5..7d791120c3a55d 100644 --- a/x-pack/plugins/observability_solution/infra/public/pages/metrics/settings/source_configuration_settings.tsx +++ b/x-pack/plugins/observability_solution/infra/public/pages/metrics/settings/source_configuration_settings.tsx @@ -22,6 +22,7 @@ import { import { loadRuleAggregations } from '@kbn/triggers-actions-ui-plugin/public'; import { HttpSetup } from '@kbn/core-http-browser'; import { + AlertConsumers, METRIC_INVENTORY_THRESHOLD_ALERT_TYPE_ID, METRIC_THRESHOLD_ALERT_TYPE_ID, } from '@kbn/rule-data-utils'; @@ -58,7 +59,8 @@ export const SourceConfigurationSettings = ({ if (http) { const { ruleExecutionStatus } = await loadRuleAggregations({ http, - typesFilter: [METRIC_INVENTORY_THRESHOLD_ALERT_TYPE_ID, METRIC_THRESHOLD_ALERT_TYPE_ID], + ruleTypeIds: [METRIC_INVENTORY_THRESHOLD_ALERT_TYPE_ID, METRIC_THRESHOLD_ALERT_TYPE_ID], + consumers: [AlertConsumers.INFRASTRUCTURE], }); const numberOfRules = Object.values(ruleExecutionStatus).reduce( (acc, value) => acc + value, diff --git a/x-pack/plugins/observability_solution/observability/public/pages/alerts/alerts.tsx b/x-pack/plugins/observability_solution/observability/public/pages/alerts/alerts.tsx index 1a9222d74abbf3..e3657d065da9fe 100644 --- a/x-pack/plugins/observability_solution/observability/public/pages/alerts/alerts.tsx +++ b/x-pack/plugins/observability_solution/observability/public/pages/alerts/alerts.tsx @@ -38,7 +38,7 @@ import { } from '../../components/alert_search_bar/containers'; import { calculateTimeRangeBucketSize } from '../overview/helpers/calculate_bucket_size'; import { getAlertSummaryTimeRange } from '../../utils/alert_summary_widget'; -import { ALERTS_URL_STORAGE_KEY } from '../../../common/constants'; +import { ALERTS_URL_STORAGE_KEY, observabilityAlertFeatureIds } from '../../../common/constants'; import { ALERTS_PAGE_ALERTS_TABLE_CONFIG_ID } from '../../constants'; import { useGetAvailableRulesWithDescriptions } from '../../hooks/use_get_available_rules_with_descriptions'; import { HeaderMenu } from '../overview/components/header_menu/header_menu'; @@ -172,8 +172,8 @@ function InternalAlertsPage() { try { const response = await loadRuleAggregations({ http, - typesFilter: filteredRuleTypes, - ruleTypeIds: OBSERVABILITY_RULE_TYPE_IDS, + ruleTypeIds: filteredRuleTypes, + consumers: observabilityAlertFeatureIds, }); const { ruleExecutionStatus, ruleMutedStatus, ruleEnabledStatus, ruleSnoozedStatus } = response; diff --git a/x-pack/plugins/observability_solution/observability/public/pages/rules/rules_tab.tsx b/x-pack/plugins/observability_solution/observability/public/pages/rules/rules_tab.tsx index ed7778d3a1b8a2..6342320570f623 100644 --- a/x-pack/plugins/observability_solution/observability/public/pages/rules/rules_tab.tsx +++ b/x-pack/plugins/observability_solution/observability/public/pages/rules/rules_tab.tsx @@ -10,6 +10,7 @@ import { useHistory } from 'react-router-dom'; import { createKbnUrlStateStorage } from '@kbn/kibana-utils-plugin/public'; import { RuleStatus } from '@kbn/triggers-actions-ui-plugin/public'; import { AlertConsumers, OBSERVABILITY_RULE_TYPE_IDS } from '@kbn/rule-data-utils'; +import { observabilityAlertFeatureIds } from '../../../common'; import { useKibana } from '../../utils/kibana_react'; import { useGetFilteredRuleTypes } from '../../hooks/use_get_filtered_rule_types'; @@ -75,6 +76,7 @@ export function RulesTab({ setRefresh, stateRefresh }: RulesTabProps) { return ( { }); it('should call loadRuleAggregations API and handle result', async () => { - const params = { + const params: UseLoadRuleAggregationsQueryProps = { filters: { searchText: '', - types: [], actionTypes: [], ruleExecutionStatuses: [], ruleLastRunOutcomes: [], @@ -74,6 +76,7 @@ describe('useLoadRuleAggregations', () => { enabled: true, refresh: undefined, ruleTypeIds: [], + consumers: [], }; const { rerender, result, waitForNextUpdate } = renderHook( @@ -89,23 +92,22 @@ describe('useLoadRuleAggregations', () => { expect(loadRuleAggregationsWithKueryFilter).toBeCalledWith( expect.objectContaining({ searchText: '', - typesFilter: [], actionTypesFilter: [], ruleExecutionStatusesFilter: [], ruleLastRunOutcomesFilter: [], ruleStatusesFilter: [], tagsFilter: [], ruleTypeIds: [], + consumers: [], }) ); expect(result.current.rulesStatusesTotal).toEqual(MOCK_AGGS.ruleExecutionStatus); }); it('should call loadRuleAggregation API with params and handle result', async () => { - const params = { + const params: UseLoadRuleAggregationsQueryProps = { filters: { searchText: 'test', - types: ['type1', 'type2'], actionTypes: ['action1', 'action2'], ruleExecutionStatuses: ['status1', 'status2'], ruleParams: {}, @@ -116,6 +118,7 @@ describe('useLoadRuleAggregations', () => { enabled: true, refresh: undefined, ruleTypeIds: ['foo'], + consumers: ['bar'], }; const { rerender, result, waitForNextUpdate } = renderHook( @@ -131,13 +134,13 @@ describe('useLoadRuleAggregations', () => { expect(loadRuleAggregationsWithKueryFilter).toBeCalledWith( expect.objectContaining({ searchText: 'test', - typesFilter: ['type1', 'type2'], actionTypesFilter: ['action1', 'action2'], ruleExecutionStatusesFilter: ['status1', 'status2'], ruleStatusesFilter: ['enabled', 'snoozed'] as RuleStatus[], tagsFilter: ['tag1', 'tag2'], ruleLastRunOutcomesFilter: ['outcome1', 'outcome2'], ruleTypeIds: ['foo'], + consumers: ['bar'], }) ); expect(result.current.rulesStatusesTotal).toEqual(MOCK_AGGS.ruleExecutionStatus); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rule_aggregations_query.ts b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rule_aggregations_query.ts index 2f5ba3bd13943b..c588959dedf522 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rule_aggregations_query.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rule_aggregations_query.ts @@ -22,15 +22,16 @@ const initializeAggregationResult = (values: readonly string[]) => { ); }; -interface UseLoadRuleAggregationsQueryProps { +export interface UseLoadRuleAggregationsQueryProps { filters: RulesListFilters; enabled: boolean; ruleTypeIds?: string[]; + consumers?: string[]; refresh?: Date; } export const useLoadRuleAggregationsQuery = (props: UseLoadRuleAggregationsQueryProps) => { - const { filters, enabled, refresh, ruleTypeIds } = props; + const { filters, enabled, refresh, ruleTypeIds, consumers } = props; const { http, @@ -41,13 +42,13 @@ export const useLoadRuleAggregationsQuery = (props: UseLoadRuleAggregationsQuery return loadRuleAggregationsWithKueryFilter({ http, searchText: filters.searchText, - typesFilter: filters.types, actionTypesFilter: filters.actionTypes, ruleExecutionStatusesFilter: filters.ruleExecutionStatuses, ruleLastRunOutcomesFilter: filters.ruleLastRunOutcomes, ruleStatusesFilter: filters.ruleStatuses, tagsFilter: filters.tags, ruleTypeIds, + consumers, }); }; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/aggregate.test.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/aggregate.test.ts index f88734cd1f90dc..b546748d695e42 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/aggregate.test.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/aggregate.test.ts @@ -113,7 +113,7 @@ describe('loadRuleAggregations', () => { `); }); - test('should call aggregate API with typesFilter', async () => { + test('should call aggregate API with ruleTypeIds', async () => { const resolvedValue = { rule_execution_status: { ok: 4, @@ -127,7 +127,7 @@ describe('loadRuleAggregations', () => { const result = await loadRuleAggregations({ http, - typesFilter: ['foo', 'bar'], + ruleTypeIds: ['foo', 'bar'], }); expect(result).toEqual({ ruleExecutionStatus: { @@ -142,13 +142,13 @@ describe('loadRuleAggregations', () => { Array [ "/internal/alerting/rules/_aggregate", Object { - "body": "{\\"filter\\":\\"alert.attributes.alertTypeId:(foo or bar)\\",\\"default_search_operator\\":\\"AND\\"}", + "body": "{\\"default_search_operator\\":\\"AND\\",\\"rule_type_ids\\":[\\"foo\\",\\"bar\\"]}", }, ] `); }); - test('should call aggregate API with actionTypesFilter and typesFilter', async () => { + test('should call aggregate API with actionTypesFilter and ruleTypeIds', async () => { const resolvedValue = { rule_execution_status: { ok: 4, @@ -164,7 +164,7 @@ describe('loadRuleAggregations', () => { http, searchText: 'baz', actionTypesFilter: ['action', 'type'], - typesFilter: ['foo', 'bar'], + ruleTypeIds: ['foo', 'bar'], }); expect(result).toEqual({ ruleExecutionStatus: { @@ -179,7 +179,7 @@ describe('loadRuleAggregations', () => { Array [ "/internal/alerting/rules/_aggregate", Object { - "body": "{\\"search_fields\\":\\"[\\\\\\"name\\\\\\",\\\\\\"tags\\\\\\"]\\",\\"search\\":\\"baz\\",\\"filter\\":\\"alert.attributes.alertTypeId:(foo or bar) and (alert.attributes.actions:{ actionTypeId:action } OR alert.attributes.actions:{ actionTypeId:type })\\",\\"default_search_operator\\":\\"AND\\"}", + "body": "{\\"search_fields\\":\\"[\\\\\\"name\\\\\\",\\\\\\"tags\\\\\\"]\\",\\"search\\":\\"baz\\",\\"filter\\":\\"(alert.attributes.actions:{ actionTypeId:action } OR alert.attributes.actions:{ actionTypeId:type })\\",\\"default_search_operator\\":\\"AND\\",\\"rule_type_ids\\":[\\"foo\\",\\"bar\\"]}", }, ] `); @@ -324,38 +324,4 @@ describe('loadRuleAggregations', () => { ] `); }); - - test('should call aggregate API with ruleTypeIds', async () => { - const resolvedValue = { - rule_execution_status: { - ok: 4, - active: 2, - error: 1, - pending: 1, - unknown: 0, - }, - }; - - http.post.mockResolvedValueOnce(resolvedValue); - - const result = await loadRuleAggregations({ http, ruleTypeIds: ['foo'] }); - expect(result).toEqual({ - ruleExecutionStatus: { - ok: 4, - active: 2, - error: 1, - pending: 1, - unknown: 0, - }, - }); - - expect(http.post.mock.calls[0]).toMatchInlineSnapshot(` - Array [ - "/internal/alerting/rules/_aggregate", - Object { - "body": "{\\"default_search_operator\\":\\"AND\\",\\"rule_type_ids\\":[\\"foo\\"]}", - }, - ] - `); - }); }); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/aggregate.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/aggregate.ts index c40679dc9dd807..af855075cca871 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/aggregate.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/aggregate.ts @@ -39,15 +39,14 @@ export async function loadRuleTags({ export async function loadRuleAggregations({ http, searchText, - typesFilter, actionTypesFilter, ruleExecutionStatusesFilter, ruleStatusesFilter, tagsFilter, ruleTypeIds, + consumers, }: LoadRuleAggregationsProps): Promise { const filters = mapFiltersToKql({ - typesFilter, actionTypesFilter, ruleExecutionStatusesFilter, ruleStatusesFilter, @@ -62,6 +61,7 @@ export async function loadRuleAggregations({ filter: filters.length ? filters.join(' and ') : undefined, default_search_operator: 'AND', rule_type_ids: ruleTypeIds, + consumers, }), } ); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/aggregate_helpers.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/aggregate_helpers.ts index 95a82c969a16a7..fb787c249aeb91 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/aggregate_helpers.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/aggregate_helpers.ts @@ -61,13 +61,13 @@ export const rewriteTagsBodyRes: RewriteRequestCase = ({ export interface LoadRuleAggregationsProps { http: HttpSetup; searchText?: string; - typesFilter?: string[]; actionTypesFilter?: string[]; ruleExecutionStatusesFilter?: string[]; ruleLastRunOutcomesFilter?: string[]; ruleStatusesFilter?: RuleStatus[]; tagsFilter?: string[]; ruleTypeIds?: string[]; + consumers?: string[]; } export interface LoadRuleTagsProps { diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/aggregate_kuery_filter.test.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/aggregate_kuery_filter.test.ts index 154b7209305ca6..a76147033fe65c 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/aggregate_kuery_filter.test.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/aggregate_kuery_filter.test.ts @@ -78,4 +78,38 @@ describe('loadRuleAggregationsWithKueryFilter', () => { ] `); }); + + test('should call aggregate API with consumers', async () => { + const resolvedValue = { + rule_execution_status: { + ok: 4, + active: 2, + error: 1, + pending: 1, + unknown: 0, + }, + }; + + http.post.mockResolvedValueOnce(resolvedValue); + + const result = await loadRuleAggregationsWithKueryFilter({ http, consumers: ['foo'] }); + expect(result).toEqual({ + ruleExecutionStatus: { + ok: 4, + active: 2, + error: 1, + pending: 1, + unknown: 0, + }, + }); + + expect(http.post.mock.calls[0]).toMatchInlineSnapshot(` + Array [ + "/internal/alerting/rules/_aggregate", + Object { + "body": "{\\"default_search_operator\\":\\"AND\\",\\"consumers\\":[\\"foo\\"]}", + }, + ] + `); + }); }); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/aggregate_kuery_filter.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/aggregate_kuery_filter.ts index 8e0506568820ba..dce41afcc81103 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/aggregate_kuery_filter.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/aggregate_kuery_filter.ts @@ -16,15 +16,14 @@ import { mapFiltersToKueryNode } from './map_filters_to_kuery_node'; export async function loadRuleAggregationsWithKueryFilter({ http, searchText, - typesFilter, actionTypesFilter, ruleExecutionStatusesFilter, ruleStatusesFilter, tagsFilter, ruleTypeIds, + consumers, }: LoadRuleAggregationsProps): Promise { const filtersKueryNode = mapFiltersToKueryNode({ - typesFilter, actionTypesFilter, tagsFilter, ruleExecutionStatusesFilter, @@ -39,6 +38,7 @@ export async function loadRuleAggregationsWithKueryFilter({ ...(filtersKueryNode ? { filter: JSON.stringify(filtersKueryNode) } : {}), rule_type_ids: ruleTypeIds, default_search_operator: 'AND', + consumers, }), } ); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_page/components/stack_alerts_page.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_page/components/stack_alerts_page.tsx index 8bc43ebb86b4ac..d78253ae4ed865 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_page/components/stack_alerts_page.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_page/components/stack_alerts_page.tsx @@ -78,7 +78,7 @@ const PageContent = () => { } = useKibana().services; const [esQuery, setEsQuery] = useState({ bool: {} } as { bool: BoolQuery }); const [ruleTypeIds, setRuleTypeIds] = useState([]); - const ruleStats = useRuleStats(); + const ruleStats = useRuleStats({ ruleTypeIds }); const { ruleTypesState: { data: ruleTypesIndex, initialLoad: isInitialLoadingRuleTypes }, diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_page/hooks/use_rule_stats.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_page/hooks/use_rule_stats.tsx index 06e371979d9801..4d3841672defb5 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_page/hooks/use_rule_stats.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_page/hooks/use_rule_stats.tsx @@ -23,7 +23,12 @@ const Divider = styled.div` height: 100%; `; -export const useRuleStats = () => { +interface Props { + ruleTypeIds?: string[]; + consumers?: string[]; +} + +export const useRuleStats = ({ ruleTypeIds, consumers }: Props = {}) => { const { http, notifications: { toasts }, @@ -46,7 +51,10 @@ export const useRuleStats = () => { try { const response = await loadRuleAggregations({ http, + ruleTypeIds, + consumers, }); + const { ruleExecutionStatus, ruleMutedStatus, ruleEnabledStatus, ruleSnoozedStatus } = response; if (ruleExecutionStatus && ruleMutedStatus && ruleEnabledStatus && ruleSnoozedStatus) { @@ -73,7 +81,7 @@ export const useRuleStats = () => { } finally { setLoading(false); } - }, [http, toasts]); + }, [consumers, http, ruleTypeIds, toasts]); useEffect(() => { loadRuleStats(); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list.tsx index c68d276e28f378..c052219ae955cf 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list.tsx @@ -116,6 +116,7 @@ const RuleEdit = lazy(() => import('../../rule_form/rule_edit')); export interface RulesListProps { ruleTypeIds?: string[]; + consumers?: string[]; filteredRuleTypes?: string[]; lastResponseFilter?: string[]; lastRunOutcomeFilter?: string[]; @@ -157,6 +158,7 @@ const EMPTY_ARRAY: string[] = []; export const RulesList = ({ ruleTypeIds, + consumers, filteredRuleTypes = EMPTY_ARRAY, lastResponseFilter, lastRunOutcomeFilter, @@ -294,6 +296,7 @@ export const RulesList = ({ const { loadRuleAggregations, rulesStatusesTotal, rulesLastRunOutcomesTotal } = useLoadRuleAggregationsQuery({ ruleTypeIds, + consumers, filters: computedFilter, enabled: canLoadRules, refresh, From b3422217a4aa095ff0ff6c1b56338705c8694a09 Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Fri, 4 Oct 2024 14:25:52 +0300 Subject: [PATCH 076/106] Support filtering by consumers in the find API --- .../routes/rule/apis/find/schemas/v1.ts | 1 + .../methods/aggregate/aggregate_rules.test.ts | 259 +----------- .../rule/methods/aggregate/aggregate_rules.ts | 5 +- .../rule/methods/find/find_rules.test.ts | 10 +- .../rule/methods/find/find_rules.ts | 10 +- .../find/schemas/find_rules_schemas.ts | 1 + .../rule/apis/find/find_rules_route.test.ts | 71 ++++ .../transform_find_rules_body/v1.ts | 2 + .../group1/tests/alerting/find_internal.ts | 90 +++- .../spaces_only/tests/alerting/group1/find.ts | 225 +++++----- .../tests/alerting/group1/find_internal.ts | 392 ++++++++++++++++++ .../tests/alerting/group1/index.ts | 1 + 12 files changed, 690 insertions(+), 377 deletions(-) create mode 100644 x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/find_internal.ts diff --git a/x-pack/plugins/alerting/common/routes/rule/apis/find/schemas/v1.ts b/x-pack/plugins/alerting/common/routes/rule/apis/find/schemas/v1.ts index 17470025be8bf0..8cc487ba91b22b 100644 --- a/x-pack/plugins/alerting/common/routes/rule/apis/find/schemas/v1.ts +++ b/x-pack/plugins/alerting/common/routes/rule/apis/find/schemas/v1.ts @@ -127,4 +127,5 @@ export const findRulesInternalRequestQuerySchema = schema.object({ fields: schema.maybe(schema.arrayOf(schema.string())), filter: schema.maybe(schema.string()), rule_type_ids: schema.maybe(schema.arrayOf(schema.string())), + consumers: schema.maybe(schema.arrayOf(schema.string())), }); diff --git a/x-pack/plugins/alerting/server/application/rule/methods/aggregate/aggregate_rules.test.ts b/x-pack/plugins/alerting/server/application/rule/methods/aggregate/aggregate_rules.test.ts index aed95800dbbe3e..b313005140ec95 100644 --- a/x-pack/plugins/alerting/server/application/rule/methods/aggregate/aggregate_rules.test.ts +++ b/x-pack/plugins/alerting/server/application/rule/methods/aggregate/aggregate_rules.test.ts @@ -23,7 +23,7 @@ import { auditLoggerMock } from '@kbn/security-plugin/server/audit/mocks'; import { getBeforeSetup, setGlobalDate } from '../../../../rules_client/tests/lib'; import { RegistryRuleType } from '../../../../rule_type_registry'; -import { fromKueryExpression, nodeTypes } from '@kbn/es-query'; +import { fromKueryExpression, nodeTypes, toKqlExpression } from '@kbn/es-query'; import { RecoveredActionGroup } from '../../../../../common'; import { DefaultRuleAggregationResult } from '../../../../routes/rule/apis/aggregate/types'; import { defaultRuleAggregationFactory } from '.'; @@ -388,7 +388,7 @@ describe('aggregate()', () => { ]); }); - test('supports filtering by rule type IDs when aggregating', async () => { + test('combines the filters with the auth filter correctly', async () => { const authFilter = fromKueryExpression( 'alert.attributes.alertTypeId:myType and alert.attributes.consumer:myApp' ); @@ -400,257 +400,20 @@ describe('aggregate()', () => { const rulesClient = new RulesClient(rulesClientParams); await rulesClient.aggregate({ - options: { ruleTypeIds: ['my-rule-type-id'] }, + options: { + ruleTypeIds: ['my-rule-type-id'], + consumers: ['bar'], + filter: `alert.attributes.tags: ['bar']`, + }, aggs: defaultRuleAggregationFactory(), }); - expect(unsecuredSavedObjectsClient.find).toHaveBeenCalledTimes(1); - expect(unsecuredSavedObjectsClient.find.mock.calls[0]).toMatchInlineSnapshot(` - Array [ - Object { - "aggs": Object { - "enabled": Object { - "terms": Object { - "field": "alert.attributes.enabled", - }, - }, - "muted": Object { - "terms": Object { - "field": "alert.attributes.muteAll", - }, - }, - "outcome": Object { - "terms": Object { - "field": "alert.attributes.lastRun.outcome", - }, - }, - "snoozed": Object { - "aggs": Object { - "count": Object { - "filter": Object { - "exists": Object { - "field": "alert.attributes.snoozeSchedule.duration", - }, - }, - }, - }, - "nested": Object { - "path": "alert.attributes.snoozeSchedule", - }, - }, - "status": Object { - "terms": Object { - "field": "alert.attributes.executionStatus.status", - }, - }, - "tags": Object { - "terms": Object { - "field": "alert.attributes.tags", - "order": Object { - "_key": "asc", - }, - "size": 50, - }, - }, - }, - "filter": Object { - "arguments": Array [ - Object { - "arguments": Array [ - Object { - "isQuoted": false, - "type": "literal", - "value": "alert.attributes.alertTypeId", - }, - Object { - "isQuoted": false, - "type": "literal", - "value": "my-rule-type-id", - }, - ], - "function": "is", - "type": "function", - }, - Object { - "arguments": Array [ - Object { - "arguments": Array [ - Object { - "isQuoted": false, - "type": "literal", - "value": "alert.attributes.alertTypeId", - }, - Object { - "isQuoted": false, - "type": "literal", - "value": "myType", - }, - ], - "function": "is", - "type": "function", - }, - Object { - "arguments": Array [ - Object { - "isQuoted": false, - "type": "literal", - "value": "alert.attributes.consumer", - }, - Object { - "isQuoted": false, - "type": "literal", - "value": "myApp", - }, - ], - "function": "is", - "type": "function", - }, - ], - "function": "and", - "type": "function", - }, - ], - "function": "and", - "type": "function", - }, - "page": 1, - "perPage": 0, - "type": "alert", - }, - ] - `); - }); - - test('supports filtering by consumers when aggregating', async () => { - const authFilter = fromKueryExpression( - 'alert.attributes.alertTypeId:myType and alert.attributes.consumer:myApp' - ); - authorization.getFindAuthorizationFilter.mockResolvedValue({ - filter: authFilter, - ensureRuleTypeIsAuthorized() {}, - }); - - const rulesClient = new RulesClient(rulesClientParams); - await rulesClient.aggregate({ - options: { consumers: ['my-consumer'] }, - aggs: defaultRuleAggregationFactory(), - }); + const finalFilter = unsecuredSavedObjectsClient.find.mock.calls[0][0].filter; expect(unsecuredSavedObjectsClient.find).toHaveBeenCalledTimes(1); - expect(unsecuredSavedObjectsClient.find.mock.calls[0]).toMatchInlineSnapshot(` - Array [ - Object { - "aggs": Object { - "enabled": Object { - "terms": Object { - "field": "alert.attributes.enabled", - }, - }, - "muted": Object { - "terms": Object { - "field": "alert.attributes.muteAll", - }, - }, - "outcome": Object { - "terms": Object { - "field": "alert.attributes.lastRun.outcome", - }, - }, - "snoozed": Object { - "aggs": Object { - "count": Object { - "filter": Object { - "exists": Object { - "field": "alert.attributes.snoozeSchedule.duration", - }, - }, - }, - }, - "nested": Object { - "path": "alert.attributes.snoozeSchedule", - }, - }, - "status": Object { - "terms": Object { - "field": "alert.attributes.executionStatus.status", - }, - }, - "tags": Object { - "terms": Object { - "field": "alert.attributes.tags", - "order": Object { - "_key": "asc", - }, - "size": 50, - }, - }, - }, - "filter": Object { - "arguments": Array [ - Object { - "arguments": Array [ - Object { - "isQuoted": false, - "type": "literal", - "value": "alert.attributes.consumer", - }, - Object { - "isQuoted": false, - "type": "literal", - "value": "my-consumer", - }, - ], - "function": "is", - "type": "function", - }, - Object { - "arguments": Array [ - Object { - "arguments": Array [ - Object { - "isQuoted": false, - "type": "literal", - "value": "alert.attributes.alertTypeId", - }, - Object { - "isQuoted": false, - "type": "literal", - "value": "myType", - }, - ], - "function": "is", - "type": "function", - }, - Object { - "arguments": Array [ - Object { - "isQuoted": false, - "type": "literal", - "value": "alert.attributes.consumer", - }, - Object { - "isQuoted": false, - "type": "literal", - "value": "myApp", - }, - ], - "function": "is", - "type": "function", - }, - ], - "function": "and", - "type": "function", - }, - ], - "function": "and", - "type": "function", - }, - "page": 1, - "perPage": 0, - "type": "alert", - }, - ] - `); + expect(toKqlExpression(finalFilter)).toMatchInlineSnapshot( + `"((alert.attributes.tags: ['bar'] OR alert.attributes.alertTypeId: my-rule-type-id OR alert.attributes.consumer: bar) AND (alert.attributes.alertTypeId: myType AND alert.attributes.consumer: myApp))"` + ); }); test('logs audit event when not authorized to aggregate rules', async () => { diff --git a/x-pack/plugins/alerting/server/application/rule/methods/aggregate/aggregate_rules.ts b/x-pack/plugins/alerting/server/application/rule/methods/aggregate/aggregate_rules.ts index e7efe215aed77d..edc9c360e2e331 100644 --- a/x-pack/plugins/alerting/server/application/rule/methods/aggregate/aggregate_rules.ts +++ b/x-pack/plugins/alerting/server/application/rule/methods/aggregate/aggregate_rules.ts @@ -52,7 +52,10 @@ export async function aggregateRules>( const filterKueryNode = buildKueryNodeFilter(filter); const ruleTypeIdsFilter = buildRuleTypeIdsFilter(ruleTypeIds); const consumersFilter = buildConsumersFilter(consumers); - const combinedFilters = combineFilters([filterKueryNode, ruleTypeIdsFilter, consumersFilter]); + const combinedFilters = combineFilters( + [filterKueryNode, ruleTypeIdsFilter, consumersFilter], + 'or' + ); const { aggregations } = await findRulesSo({ savedObjectsClient: context.unsecuredSavedObjectsClient, diff --git a/x-pack/plugins/alerting/server/application/rule/methods/find/find_rules.test.ts b/x-pack/plugins/alerting/server/application/rule/methods/find/find_rules.test.ts index f1696165cd206a..1f65c6863451c7 100644 --- a/x-pack/plugins/alerting/server/application/rule/methods/find/find_rules.test.ts +++ b/x-pack/plugins/alerting/server/application/rule/methods/find/find_rules.test.ts @@ -1040,7 +1040,7 @@ describe('find()', () => { }); const rulesClient = new RulesClient(rulesClientParams); - await rulesClient.find({ options: { ruleTypeIds: ['foo'] } }); + await rulesClient.find({ options: { ruleTypeIds: ['foo'], consumers: ['bar'] } }); expect(authorization.getFindAuthorizationFilter).toHaveBeenCalledWith({ authorizationEntity: 'rule', @@ -1066,13 +1066,17 @@ describe('find()', () => { const rulesClient = new RulesClient(rulesClientParams); await rulesClient.find({ - options: { ruleTypeIds: ['foo'], filter: `alert.attributes.tags: ['bar']` }, + options: { + ruleTypeIds: ['foo'], + consumers: ['bar'], + filter: `alert.attributes.tags: ['bar']`, + }, }); const finalFilter = unsecuredSavedObjectsClient.find.mock.calls[0][0].filter; expect(toKqlExpression(finalFilter)).toMatchInlineSnapshot( - `"((alert.attributes.tags: ['bar'] AND alert.attributes.alertTypeId: foo) AND (alert.attributes.alertTypeId: myType AND alert.attributes.consumer: myApp))"` + `"((alert.attributes.tags: ['bar'] OR alert.attributes.alertTypeId: foo OR alert.attributes.consumer: bar) AND (alert.attributes.alertTypeId: myType AND alert.attributes.consumer: myApp))"` ); }); }); diff --git a/x-pack/plugins/alerting/server/application/rule/methods/find/find_rules.ts b/x-pack/plugins/alerting/server/application/rule/methods/find/find_rules.ts index 6c1f849d7298dc..2b09ce982715be 100644 --- a/x-pack/plugins/alerting/server/application/rule/methods/find/find_rules.ts +++ b/x-pack/plugins/alerting/server/application/rule/methods/find/find_rules.ts @@ -10,6 +10,7 @@ import { pick } from 'lodash'; import { KueryNode } from '@kbn/es-query'; import { AlertConsumers } from '@kbn/rule-data-utils'; import { + buildConsumersFilter, buildRuleTypeIdsFilter, combineFilterWithAuthorizationFilter, combineFilters, @@ -51,7 +52,7 @@ export async function findRules( ): Promise> { const { options, excludeFromPublicApi = false, includeSnoozeData = false } = params || {}; - const { fields, ruleTypeIds, ...restOptions } = options || {}; + const { fields, ruleTypeIds, consumers, ...restOptions } = options || {}; try { if (params) { @@ -117,7 +118,12 @@ export async function findRules( } const ruleTypeIdsFilter = buildRuleTypeIdsFilter(ruleTypeIds); - const combinedFilters = combineFilters([filterKueryNode, ruleTypeIdsFilter]); + const consumersFilter = buildConsumersFilter(consumers); + const combinedFilters = combineFilters( + [filterKueryNode, ruleTypeIdsFilter, consumersFilter], + 'or' + ); + const finalFilter = combineFilterWithAuthorizationFilter( combinedFilters, authorizationFilter as KueryNode diff --git a/x-pack/plugins/alerting/server/application/rule/methods/find/schemas/find_rules_schemas.ts b/x-pack/plugins/alerting/server/application/rule/methods/find/schemas/find_rules_schemas.ts index 62e6dd94a8497a..aec95d7f2c0610 100644 --- a/x-pack/plugins/alerting/server/application/rule/methods/find/schemas/find_rules_schemas.ts +++ b/x-pack/plugins/alerting/server/application/rule/methods/find/schemas/find_rules_schemas.ts @@ -29,6 +29,7 @@ export const findRulesOptionsSchema = schema.object( schema.oneOf([schema.string(), schema.recordOf(schema.string(), schema.any())]) ), ruleTypeIds: schema.maybe(schema.arrayOf(schema.string())), + consumers: schema.maybe(schema.arrayOf(schema.string())), }, { unknowns: 'allow' } ); diff --git a/x-pack/plugins/alerting/server/routes/rule/apis/find/find_rules_route.test.ts b/x-pack/plugins/alerting/server/routes/rule/apis/find/find_rules_route.test.ts index 0b4d4af0d654ce..fef036975d29b0 100644 --- a/x-pack/plugins/alerting/server/routes/rule/apis/find/find_rules_route.test.ts +++ b/x-pack/plugins/alerting/server/routes/rule/apis/find/find_rules_route.test.ts @@ -502,6 +502,73 @@ describe('findRulesRoute', () => { }, }); }); + + it('should not support consumers', async () => { + const licenseState = licenseStateMock.create(); + const router = httpServiceMock.createRouter(); + + findRulesRoute(router, licenseState); + + const [config, handler] = router.get.mock.calls[0]; + + expect(config.path).toMatchInlineSnapshot(`"/api/alerting/rules/_find"`); + + const findResult = { + page: 1, + perPage: 1, + total: 0, + data: [], + }; + rulesClient.find.mockResolvedValueOnce(findResult); + + const [context, req, res] = mockHandlerArguments( + { rulesClient }, + { + query: { + per_page: 1, + page: 1, + default_search_operator: 'OR', + consumers: ['foo'], + }, + }, + ['ok'] + ); + + expect(await handler(context, req, res)).toMatchInlineSnapshot(` + Object { + "body": Object { + "data": Array [], + "page": 1, + "per_page": 1, + "total": 0, + }, + } + `); + + expect(rulesClient.find).toHaveBeenCalledTimes(1); + expect(rulesClient.find.mock.calls[0]).toMatchInlineSnapshot(` + Array [ + Object { + "excludeFromPublicApi": true, + "includeSnoozeData": true, + "options": Object { + "defaultSearchOperator": "OR", + "page": 1, + "perPage": 1, + }, + }, + ] + `); + + expect(res.ok).toHaveBeenCalledWith({ + body: { + page: 1, + per_page: 1, + total: 0, + data: [], + }, + }); + }); }); describe('Internal', () => { @@ -531,6 +598,7 @@ describe('findRulesRoute', () => { page: 1, default_search_operator: 'OR', rule_type_ids: ['foo'], + consumers: ['bar'], }, }, ['ok'] @@ -554,6 +622,9 @@ describe('findRulesRoute', () => { "excludeFromPublicApi": false, "includeSnoozeData": true, "options": Object { + "consumers": Array [ + "bar", + ], "defaultSearchOperator": "OR", "page": 1, "perPage": 1, diff --git a/x-pack/plugins/alerting/server/routes/rule/apis/find/transforms/transform_find_rules_body/v1.ts b/x-pack/plugins/alerting/server/routes/rule/apis/find/transforms/transform_find_rules_body/v1.ts index 562da0fb63cdbc..e46606eca36e70 100644 --- a/x-pack/plugins/alerting/server/routes/rule/apis/find/transforms/transform_find_rules_body/v1.ts +++ b/x-pack/plugins/alerting/server/routes/rule/apis/find/transforms/transform_find_rules_body/v1.ts @@ -55,6 +55,7 @@ export const transformFindRulesInternalBody = ( fields, filter, rule_type_ids: ruleTypeIds, + consumers, } = params; return { ...(page ? { page } : {}), @@ -64,6 +65,7 @@ export const transformFindRulesInternalBody = ( ...(defaultSearchOperator ? { defaultSearchOperator } : {}), ...(perPage ? { perPage } : {}), ...(ruleTypeIds ? { ruleTypeIds } : {}), + ...(consumers ? { consumers } : {}), ...(sortField ? { sortField } : {}), ...(sortOrder ? { sortOrder } : {}), ...(hasReference ? { hasReference } : {}), diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/find_internal.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/find_internal.ts index c062082d54567b..63221152dffb3e 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/find_internal.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/find_internal.ts @@ -9,7 +9,7 @@ import expect from '@kbn/expect'; import { chunk, omit } from 'lodash'; import { v4 as uuidv4 } from 'uuid'; import { Space } from '../../../../common/types'; -import { UserAtSpaceScenarios } from '../../../scenarios'; +import { Space1AllAtSpace1, SuperuserAtSpace1, UserAtSpaceScenarios } from '../../../scenarios'; import { getUrlPrefix, getTestRuleData, ObjectRemover } from '../../../../common/lib'; import { FtrProviderContext } from '../../../../common/ftr_provider_context'; @@ -565,6 +565,94 @@ export default function createFindTests({ getService }: FtrProviderContext) { }); } + describe('filtering', () => { + it('should return the correct rules when trying to exploit RBAC through the ruleTypeIds parameter', async () => { + const { user, space } = Space1AllAtSpace1; + + const { body: createdAlert1 } = await supertest + .post(`${getUrlPrefix(SuperuserAtSpace1.space.id)}/api/alerting/rule`) + .set('kbn-xsrf', 'foo') + .send( + getTestRuleData({ + rule_type_id: 'test.restricted-noop', + consumer: 'alertsRestrictedFixture', + }) + ) + .auth(SuperuserAtSpace1.user.username, SuperuserAtSpace1.user.password) + .expect(200); + + const { body: createdAlert2 } = await supertest + .post(`${getUrlPrefix(SuperuserAtSpace1.space.id)}/api/alerting/rule`) + .set('kbn-xsrf', 'foo') + .send( + getTestRuleData({ + rule_type_id: 'test.noop', + consumer: 'alertsFixture', + }) + ) + .auth(SuperuserAtSpace1.user.username, SuperuserAtSpace1.user.password) + .expect(200); + + objectRemover.add(SuperuserAtSpace1.space.id, createdAlert1.id, 'rule', 'alerting'); + objectRemover.add(SuperuserAtSpace1.space.id, createdAlert2.id, 'rule', 'alerting'); + + const response = await supertestWithoutAuth + .post(`${getUrlPrefix(space.id)}/internal/alerting/rules/_find`) + .set('kbn-xsrf', 'foo') + .auth(user.username, user.password) + .send({ + rule_type_ids: ['test.noop', 'test.restricted-noop'], + }); + + expect(response.status).to.eql(200); + expect(response.body.total).to.equal(1); + expect(response.body.data[0].rule_type_id).to.eql('test.noop'); + }); + + it('should return the correct rules when trying to exploit RBAC through the consumers parameter', async () => { + const { user, space } = Space1AllAtSpace1; + + const { body: createdAlert1 } = await supertest + .post(`${getUrlPrefix(SuperuserAtSpace1.space.id)}/api/alerting/rule`) + .set('kbn-xsrf', 'foo') + .send( + getTestRuleData({ + rule_type_id: 'test.restricted-noop', + consumer: 'alertsRestrictedFixture', + }) + ) + .auth(SuperuserAtSpace1.user.username, SuperuserAtSpace1.user.password) + .expect(200); + + const { body: createdAlert2 } = await supertest + .post(`${getUrlPrefix(SuperuserAtSpace1.space.id)}/api/alerting/rule`) + .set('kbn-xsrf', 'foo') + .send( + getTestRuleData({ + rule_type_id: 'test.noop', + consumer: 'alertsFixture', + }) + ) + .auth(SuperuserAtSpace1.user.username, SuperuserAtSpace1.user.password) + .expect(200); + + objectRemover.add(SuperuserAtSpace1.space.id, createdAlert1.id, 'rule', 'alerting'); + objectRemover.add(SuperuserAtSpace1.space.id, createdAlert2.id, 'rule', 'alerting'); + + const response = await supertestWithoutAuth + .post(`${getUrlPrefix(space.id)}/internal/alerting/rules/_find`) + .set('kbn-xsrf', 'foo') + .auth(user.username, user.password) + .send({ + consumers: ['alertsFixture', 'alertsRestrictedFixture'], + }); + + expect(response.status).to.eql(200); + expect(response.body.total).to.equal(1); + expect(response.body.data[0].consumer).to.eql('alertsFixture'); + }); + }); + async function createNoOpAlert(space: Space, overrides = {}) { const alert = getTestRuleData(overrides); const { body: createdAlert } = await supertest diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/find.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/find.ts index eb133f33a37a81..cb4dfe145d56e7 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/find.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/find.ts @@ -26,15 +26,20 @@ async function createAlert( return createdAlert; } -const findTestUtils = ( - describeType: 'internal' | 'public', - supertest: SuperTestAgent, - objectRemover: ObjectRemover -) => { - describe(describeType, () => { - afterEach(() => objectRemover.removeAll()); +// eslint-disable-next-line import/no-default-export +export default function createFindTests({ getService }: FtrProviderContext) { + const supertest = getService('supertest'); + + describe('find', () => { + const objectRemover = new ObjectRemover(supertest); + + afterEach(async () => { + await objectRemover.removeAll(); + }); + describe('handle find alert request', function () { this.tags('skipFIPS'); + it('should handle find alert request appropriately', async () => { const { body: createdAction } = await supertest .post(`${getUrlPrefix(Spaces.space1.id)}/api/actions/connector`) @@ -72,9 +77,9 @@ const findTestUtils = ( objectRemover.add(Spaces.space1.id, createdAlert.id, 'rule', 'alerting'); const response = await supertest.get( - `${getUrlPrefix(Spaces.space1.id)}/${ - describeType === 'public' ? 'api' : 'internal' - }/alerting/rules/_find?search=test.noop&search_fields=alertTypeId` + `${getUrlPrefix( + Spaces.space1.id + )}/api/alerting/rules/_find?search=test.noop&search_fields=alertTypeId` ); expect(response.status).to.eql(200); @@ -82,8 +87,7 @@ const findTestUtils = ( expect(response.body.per_page).to.be.greaterThan(0); expect(response.body.total).to.be.greaterThan(0); const match = response.body.data.find((obj: any) => obj.id === createdAlert.id); - const activeSnoozes = match.active_snoozes; - const hasActiveSnoozes = !!(activeSnoozes || []).filter((obj: any) => obj).length; + expect(match).to.eql({ id: createdAlert.id, name: 'abc', @@ -123,14 +127,6 @@ const findTestUtils = ( execution_status: match.execution_status, ...(match.next_run ? { next_run: match.next_run } : {}), ...(match.last_run ? { last_run: match.last_run } : {}), - ...(describeType === 'internal' - ? { - monitoring: match.monitoring, - snooze_schedule: match.snooze_schedule, - ...(hasActiveSnoozes && { active_snoozes: activeSnoozes }), - is_snoozed_until: null, - } - : {}), }); expect(Date.parse(match.created_at)).to.be.greaterThan(0); expect(Date.parse(match.updated_at)).to.be.greaterThan(0); @@ -147,9 +143,9 @@ const findTestUtils = ( await supertest .get( - `${getUrlPrefix(Spaces.other.id)}/${ - describeType === 'public' ? 'api' : 'internal' - }/alerting/rules/_find?search=test.noop&search_fields=alertTypeId` + `${getUrlPrefix( + Spaces.other.id + )}/api/alerting/rules/_find?search=test.noop&search_fields=alertTypeId` ) .expect(200, { page: 1, @@ -186,62 +182,50 @@ const findTestUtils = ( ]); }); - it(`it should${ - describeType === 'public' ? ' NOT' : '' - } allow filter on monitoring attributes`, async () => { + it(`it should NOT allow filter on monitoring attributes`, async () => { const response = await supertest.get( - `${getUrlPrefix(Spaces.space1.id)}/${ - describeType === 'public' ? 'api' : 'internal' - }/alerting/rules/_find?filter=alert.attributes.monitoring.run.calculated_metrics.success_ratio>50` + `${getUrlPrefix( + Spaces.space1.id + )}/api/alerting/rules/_find?filter=alert.attributes.monitoring.run.calculated_metrics.success_ratio>50` ); - expect(response.status).to.eql(describeType === 'internal' ? 200 : 400); - if (describeType === 'public') { - expect(response.body.message).to.eql( - 'Error find rules: Filter is not supported on this field alert.attributes.monitoring.run.calculated_metrics.success_ratio' - ); - } + expect(response.status).to.eql(400); + expect(response.body.message).to.eql( + 'Error find rules: Filter is not supported on this field alert.attributes.monitoring.run.calculated_metrics.success_ratio' + ); }); - it(`it should${ - describeType === 'public' ? ' NOT' : '' - } allow ordering on monitoring attributes`, async () => { + it(`it should NOT allow ordering on monitoring attributes`, async () => { const response = await supertest.get( - `${getUrlPrefix(Spaces.space1.id)}/${ - describeType === 'public' ? 'api' : 'internal' - }/alerting/rules/_find?sort_field=monitoring.run.calculated_metrics.success_ratio` + `${getUrlPrefix( + Spaces.space1.id + )}/api/alerting/rules/_find?sort_field=monitoring.run.calculated_metrics.success_ratio` ); - expect(response.status).to.eql(describeType === 'internal' ? 200 : 400); - if (describeType === 'public') { - expect(response.body.message).to.eql( - 'Error find rules: Sort is not supported on this field monitoring.run.calculated_metrics.success_ratio' - ); - } + expect(response.status).to.eql(400); + expect(response.body.message).to.eql( + 'Error find rules: Sort is not supported on this field monitoring.run.calculated_metrics.success_ratio' + ); }); - it(`it should${ - describeType === 'public' ? ' NOT' : '' - } allow search_fields on monitoring attributes`, async () => { + it(`it should NOT allow search_fields on monitoring attributes`, async () => { const response = await supertest.get( - `${getUrlPrefix(Spaces.space1.id)}/${ - describeType === 'public' ? 'api' : 'internal' - }/alerting/rules/_find?search_fields=monitoring.run.calculated_metrics.success_ratio&search=50` + `${getUrlPrefix( + Spaces.space1.id + )}/api/alerting/rules/_find?search_fields=monitoring.run.calculated_metrics.success_ratio&search=50` ); - expect(response.status).to.eql(describeType === 'internal' ? 200 : 400); - if (describeType === 'public') { - expect(response.body.message).to.eql( - 'Error find rules: Search field monitoring.run.calculated_metrics.success_ratio not supported' - ); - } + expect(response.status).to.eql(400); + expect(response.body.message).to.eql( + 'Error find rules: Search field monitoring.run.calculated_metrics.success_ratio not supported' + ); }); it('should filter on string parameters', async () => { const response = await supertest.get( - `${getUrlPrefix(Spaces.space1.id)}/${ - describeType === 'public' ? 'api' : 'internal' - }/alerting/rules/_find?filter=alert.attributes.params.strValue:"my b"` + `${getUrlPrefix( + Spaces.space1.id + )}/api/alerting/rules/_find?filter=alert.attributes.params.strValue:"my b"` ); expect(response.status).to.eql(200); @@ -251,9 +235,7 @@ const findTestUtils = ( it('should filter on kueryNode parameters', async () => { const response = await supertest.get( - `${getUrlPrefix(Spaces.space1.id)}/${ - describeType === 'public' ? 'api' : 'internal' - }/alerting/rules/_find?filter=${JSON.stringify( + `${getUrlPrefix(Spaces.space1.id)}/api/alerting/rules/_find?filter=${JSON.stringify( fromKueryExpression('alert.attributes.params.strValue:"my b"') )}` ); @@ -265,9 +247,9 @@ const findTestUtils = ( it('should sort by parameters', async () => { const response = await supertest.get( - `${getUrlPrefix(Spaces.space1.id)}/${ - describeType === 'public' ? 'api' : 'internal' - }/alerting/rules/_find?sort_field=params.severity&sort_order=asc` + `${getUrlPrefix( + Spaces.space1.id + )}/api/alerting/rules/_find?sort_field=params.severity&sort_order=asc` ); expect(response.body.data[0].params.severity).to.equal('low'); expect(response.body.data[1].params.severity).to.equal('medium'); @@ -276,9 +258,9 @@ const findTestUtils = ( it('should search by parameters', async () => { const response = await supertest.get( - `${getUrlPrefix(Spaces.space1.id)}/${ - describeType === 'public' ? 'api' : 'internal' - }/alerting/rules/_find?search_fields=params.severity&search=medium` + `${getUrlPrefix( + Spaces.space1.id + )}/api/alerting/rules/_find?search_fields=params.severity&search=medium` ); expect(response.status).to.eql(200); @@ -288,51 +270,73 @@ const findTestUtils = ( it('should filter on parameters', async () => { const response = await supertest.get( - `${getUrlPrefix(Spaces.space1.id)}/${ - describeType === 'public' ? 'api' : 'internal' - }/alerting/rules/_find?filter=alert.attributes.params.risk_score:40` + `${getUrlPrefix( + Spaces.space1.id + )}/api/alerting/rules/_find?filter=alert.attributes.params.risk_score:40` ); expect(response.status).to.eql(200); expect(response.body.total).to.equal(1); expect(response.body.data[0].params.risk_score).to.eql(40); - if (describeType === 'public') { - expect(response.body.data[0].mapped_params).to.eql(undefined); - } + expect(response.body.data[0].mapped_params).to.eql(undefined); }); it('should error if filtering on mapped parameters directly using the public API', async () => { const response = await supertest.get( - `${getUrlPrefix(Spaces.space1.id)}/${ - describeType === 'public' ? 'api' : 'internal' - }/alerting/rules/_find?filter=alert.attributes.mapped_params.risk_score:40` + `${getUrlPrefix( + Spaces.space1.id + )}/api/alerting/rules/_find?filter=alert.attributes.mapped_params.risk_score:40` ); - if (describeType === 'public') { - expect(response.status).to.eql(400); - expect(response.body.message).to.eql( - 'Error find rules: Filter is not supported on this field alert.attributes.mapped_params.risk_score' - ); - } else { - expect(response.status).to.eql(200); - } + expect(response.status).to.eql(400); + expect(response.body.message).to.eql( + 'Error find rules: Filter is not supported on this field alert.attributes.mapped_params.risk_score' + ); }); - }); - }); -}; -// eslint-disable-next-line import/no-default-export -export default function createFindTests({ getService }: FtrProviderContext) { - const supertest = getService('supertest'); + it('should throw when using rule_type_ids', async () => { + const { body: createdAlert } = await supertest + .post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`) + .set('kbn-xsrf', 'foo') + .send(getTestRuleData()) + .expect(200); - describe('find', () => { - const objectRemover = new ObjectRemover(supertest); + objectRemover.add(Spaces.space1.id, createdAlert.id, 'rule', 'alerting'); + + const response = await supertest.get( + `${getUrlPrefix(Spaces.space1.id)}/api/alerting/rules/_find?rule_type_ids=foo` + ); - afterEach(() => objectRemover.removeAll()); + expect(response.statusCode).to.eql(400); + expect(response.body).to.eql({ + statusCode: 400, + error: 'Bad Request', + message: '[request query.rule_type_ids]: definition for this key is missing', + }); + }); - findTestUtils('public', supertest, objectRemover); - findTestUtils('internal', supertest, objectRemover); + it('should throw when using consumers', async () => { + const { body: createdAlert } = await supertest + .post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`) + .set('kbn-xsrf', 'foo') + .send(getTestRuleData()) + .expect(200); + + objectRemover.add(Spaces.space1.id, createdAlert.id, 'rule', 'alerting'); + + const response = await supertest.get( + `${getUrlPrefix(Spaces.space1.id)}/api/alerting/rules/_find?consumers=foo` + ); + + expect(response.statusCode).to.eql(400); + expect(response.body).to.eql({ + statusCode: 400, + error: 'Bad Request', + message: '[request query.consumers]: definition for this key is missing', + }); + }); + }); describe('legacy', function () { this.tags('skipFIPS'); @@ -386,28 +390,5 @@ export default function createFindTests({ getService }: FtrProviderContext) { expect(Date.parse(match.updatedAt)).to.be.greaterThan(0); }); }); - - describe('public', function () { - it('should throw when using rule_type_ids', async () => { - const { body: createdAlert } = await supertest - .post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`) - .set('kbn-xsrf', 'foo') - .send(getTestRuleData()) - .expect(200); - - objectRemover.add(Spaces.space1.id, createdAlert.id, 'rule', 'alerting'); - - const response = await supertest.get( - `${getUrlPrefix(Spaces.space1.id)}/api/alerting/rules/_find?rule_type_ids=foo` - ); - - expect(response.statusCode).to.eql(400); - expect(response.body).to.eql({ - statusCode: 400, - error: 'Bad Request', - message: '[request query.rule_type_ids]: definition for this key is missing', - }); - }); - }); }); } diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/find_internal.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/find_internal.ts new file mode 100644 index 00000000000000..fd95788dfde2d8 --- /dev/null +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/find_internal.ts @@ -0,0 +1,392 @@ +/* + * 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 expect from '@kbn/expect'; +import { Agent as SuperTestAgent } from 'supertest'; +import { fromKueryExpression } from '@kbn/es-query'; +import { Spaces } from '../../../scenarios'; +import { getUrlPrefix, getTestRuleData, ObjectRemover } from '../../../../common/lib'; +import { FtrProviderContext } from '../../../../common/ftr_provider_context'; + +async function createAlert( + objectRemover: ObjectRemover, + supertest: SuperTestAgent, + overwrites = {} +) { + const { body: createdAlert } = await supertest + .post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`) + .set('kbn-xsrf', 'foo') + .send(getTestRuleData(overwrites)) + .expect(200); + + objectRemover.add(Spaces.space1.id, createdAlert.id, 'rule', 'alerting'); + return createdAlert; +} + +// eslint-disable-next-line import/no-default-export +export default function createFindTests({ getService }: FtrProviderContext) { + const supertest = getService('supertest'); + + describe('find', () => { + const objectRemover = new ObjectRemover(supertest); + + afterEach(async () => { + await objectRemover.removeAll(); + }); + + describe('handle find alert request', function () { + this.tags('skipFIPS'); + + it('should handle find alert request appropriately', async () => { + const { body: createdAction } = await supertest + .post(`${getUrlPrefix(Spaces.space1.id)}/api/actions/connector`) + .set('kbn-xsrf', 'foo') + .send({ + name: 'MY action', + connector_type_id: 'test.noop', + config: {}, + secrets: {}, + }) + .expect(200); + + const { body: createdAlert } = await supertest + .post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`) + .set('kbn-xsrf', 'foo') + .send( + getTestRuleData({ + actions: [ + { + group: 'default', + id: createdAction.id, + params: {}, + frequency: { + summary: false, + notify_when: 'onThrottleInterval', + throttle: '1m', + }, + }, + ], + notify_when: undefined, + throttle: undefined, + }) + ) + .expect(200); + objectRemover.add(Spaces.space1.id, createdAlert.id, 'rule', 'alerting'); + + const response = await supertest + .post(`${getUrlPrefix(Spaces.space1.id)}/internal/alerting/rules/_find`) + .set('kbn-xsrf', 'foo') + .send({ + search: 'test.noop', + search_fields: 'alertTypeId', + }); + + expect(response.status).to.eql(200); + expect(response.body.page).to.equal(1); + expect(response.body.per_page).to.be.greaterThan(0); + expect(response.body.total).to.be.greaterThan(0); + const match = response.body.data.find((obj: any) => obj.id === createdAlert.id); + const activeSnoozes = match.active_snoozes; + const hasActiveSnoozes = !!(activeSnoozes || []).filter((obj: any) => obj).length; + expect(match).to.eql({ + id: createdAlert.id, + name: 'abc', + tags: ['foo'], + rule_type_id: 'test.noop', + revision: 0, + running: false, + consumer: 'alertsFixture', + schedule: { interval: '1m' }, + enabled: true, + actions: [ + { + group: 'default', + id: createdAction.id, + connector_type_id: 'test.noop', + params: {}, + frequency: { + summary: false, + notify_when: 'onThrottleInterval', + throttle: '1m', + }, + uuid: match.actions[0].uuid, + }, + ], + params: {}, + created_by: null, + api_key_owner: null, + api_key_created_by_user: null, + scheduled_task_id: match.scheduled_task_id, + updated_by: null, + throttle: null, + notify_when: null, + mute_all: false, + muted_alert_ids: [], + created_at: match.created_at, + updated_at: match.updated_at, + execution_status: match.execution_status, + ...(match.next_run ? { next_run: match.next_run } : {}), + ...(match.last_run ? { last_run: match.last_run } : {}), + monitoring: match.monitoring, + snooze_schedule: match.snooze_schedule, + ...(hasActiveSnoozes && { active_snoozes: activeSnoozes }), + is_snoozed_until: null, + }); + + expect(Date.parse(match.created_at)).to.be.greaterThan(0); + expect(Date.parse(match.updated_at)).to.be.greaterThan(0); + }); + }); + + it(`shouldn't find alert from another space`, async () => { + const { body: createdAlert } = await supertest + .post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`) + .set('kbn-xsrf', 'foo') + .send(getTestRuleData()) + .expect(200); + objectRemover.add(Spaces.space1.id, createdAlert.id, 'rule', 'alerting'); + + await supertest + .post(`${getUrlPrefix(Spaces.other.id)}/internal/alerting/rules/_find`) + .send({ + search: 'test.noop', + search_fields: 'alertTypeId', + }) + .expect(200, { + page: 1, + per_page: 10, + total: 0, + data: [], + }); + }); + + describe('basic functionality', () => { + beforeEach(async () => { + await Promise.all([ + createAlert(objectRemover, supertest, { params: { strValue: 'my a' } }), + createAlert(objectRemover, supertest, { params: { strValue: 'my b' } }), + createAlert(objectRemover, supertest, { params: { strValue: 'my c' } }), + createAlert(objectRemover, supertest, { + params: { + risk_score: 60, + severity: 'high', + }, + }), + createAlert(objectRemover, supertest, { + params: { + risk_score: 40, + severity: 'medium', + }, + }), + createAlert(objectRemover, supertest, { + params: { + risk_score: 20, + severity: 'low', + }, + }), + ]); + }); + + it(`it should allow filter on monitoring attributes`, async () => { + const response = await supertest + .post(`${getUrlPrefix(Spaces.space1.id)}/internal/alerting/rules/_find`) + .set('kbn-xsrf', 'foo') + .send({ + filter: 'alert.attributes.monitoring.run.calculated_metrics.success_ratio>50', + }); + + expect(response.status).to.eql(200); + }); + + it(`it should allow ordering on monitoring attributes`, async () => { + const response = await supertest + .post(`${getUrlPrefix(Spaces.space1.id)}/internal/alerting/rules/_find`) + .set('kbn-xsrf', 'foo') + .send({ + sort_field: 'monitoring.run.calculated_metrics.success_ratio', + }); + + expect(response.status).to.eql(200); + }); + + it(`it should allow search_fields on monitoring attributes`, async () => { + const response = await supertest + .post(`${getUrlPrefix(Spaces.space1.id)}/internal/alerting/rules/_find`) + .set('kbn-xsrf', 'foo') + .send({ + search_fields: 'monitoring.run.calculated_metrics.success_ratio&search=50', + }); + + expect(response.status).to.eql(200); + }); + + it('should filter on string parameters', async () => { + const response = await supertest + .post(`${getUrlPrefix(Spaces.space1.id)}/internal/alerting/rules/_find`) + .set('kbn-xsrf', 'foo') + .send({ + filter: `alert.attributes.params.strValue:"my b"`, + }); + + expect(response.status).to.eql(200); + expect(response.body.total).to.equal(1); + expect(response.body.data[0].params.strValue).to.eql('my b'); + }); + + it('should filter on kueryNode parameters', async () => { + const response = await supertest + .post(`${getUrlPrefix(Spaces.space1.id)}/internal/alerting/rules/_find`) + .set('kbn-xsrf', 'foo') + .send({ + filter: `${JSON.stringify( + fromKueryExpression('alert.attributes.params.strValue:"my b"') + )}`, + }); + + expect(response.status).to.eql(200); + expect(response.body.total).to.equal(1); + expect(response.body.data[0].params.strValue).to.eql('my b'); + }); + + it('should sort by parameters', async () => { + const response = await supertest + .post(`${getUrlPrefix(Spaces.space1.id)}/internal/alerting/rules/_find`) + .set('kbn-xsrf', 'foo') + .send({ + sort_field: 'params.severity', + sort_order: 'asc', + }); + + expect(response.body.data[0].params.severity).to.equal('low'); + expect(response.body.data[1].params.severity).to.equal('medium'); + expect(response.body.data[2].params.severity).to.equal('high'); + }); + + it('should search by parameters', async () => { + const response = await supertest + .post(`${getUrlPrefix(Spaces.space1.id)}/internal/alerting/rules/_find`) + .set('kbn-xsrf', 'foo') + .send({ + search_fields: 'params.severity', + search: 'medium', + }); + + expect(response.status).to.eql(200); + expect(response.body.total).to.equal(1); + expect(response.body.data[0].params.severity).to.eql('medium'); + }); + + it('should filter on parameters', async () => { + const response = await supertest + .post(`${getUrlPrefix(Spaces.space1.id)}/internal/alerting/rules/_find`) + .set('kbn-xsrf', 'foo') + .send({ + filter: 'alert.attributes.params.risk_score:40', + }); + + expect(response.status).to.eql(200); + expect(response.body.total).to.equal(1); + expect(response.body.data[0].params.risk_score).to.eql(40); + }); + }); + + it('should filter rules by rule type IDs', async () => { + await createAlert(objectRemover, supertest, { + rule_type_id: 'test.noop', + consumer: 'alertsFixture', + }); + + await createAlert(objectRemover, supertest, { + rule_type_id: 'test.restricted-noop', + consumer: 'alertsRestrictedFixture', + }); + + const response = await supertest + .post(`${getUrlPrefix(Spaces.space1.id)}/internal/alerting/rules/_find`) + .set('kbn-xsrf', 'foo') + .send({ + rule_type_ids: ['test.restricted-noop'], + }); + + expect(response.status).to.eql(200); + expect(response.body.total).to.equal(1); + expect(response.body.data[0].rule_type_id).to.eql('test.restricted-noop'); + }); + + it('should filter rules by consumers', async () => { + await createAlert(objectRemover, supertest, { + rule_type_id: 'test.noop', + consumer: 'alertsFixture', + }); + + await createAlert(objectRemover, supertest, { + rule_type_id: 'test.restricted-noop', + consumer: 'alertsRestrictedFixture', + }); + + const response = await supertest + .post(`${getUrlPrefix(Spaces.space1.id)}/internal/alerting/rules/_find`) + .set('kbn-xsrf', 'foo') + .send({ + consumers: ['alertsRestrictedFixture'], + }); + + expect(response.status).to.eql(200); + expect(response.body.total).to.equal(1); + expect(response.body.data[0].consumer).to.eql('alertsRestrictedFixture'); + }); + + describe('legacy', function () { + this.tags('skipFIPS'); + it('should handle find alert request appropriately', async () => { + const { body: createdAlert } = await supertest + .post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`) + .set('kbn-xsrf', 'foo') + .send(getTestRuleData()) + .expect(200); + objectRemover.add(Spaces.space1.id, createdAlert.id, 'rule', 'alerting'); + + const response = await supertest.get(`${getUrlPrefix(Spaces.space1.id)}/api/alerts/_find`); + + expect(response.status).to.eql(200); + expect(response.body.page).to.equal(1); + expect(response.body.perPage).to.be.greaterThan(0); + expect(response.body.total).to.be.greaterThan(0); + const match = response.body.data.find((obj: any) => obj.id === createdAlert.id); + expect(match).to.eql({ + id: createdAlert.id, + name: 'abc', + tags: ['foo'], + alertTypeId: 'test.noop', + consumer: 'alertsFixture', + schedule: { interval: '1m' }, + enabled: true, + actions: [], + params: {}, + createdBy: null, + apiKeyOwner: null, + apiKeyCreatedByUser: null, + scheduledTaskId: match.scheduledTaskId, + updatedBy: null, + throttle: '1m', + notifyWhen: 'onThrottleInterval', + muteAll: false, + mutedInstanceIds: [], + createdAt: match.createdAt, + updatedAt: match.updatedAt, + executionStatus: match.executionStatus, + revision: 0, + running: false, + ...(match.nextRun ? { nextRun: match.nextRun } : {}), + ...(match.lastRun ? { lastRun: match.lastRun } : {}), + }); + expect(Date.parse(match.createdAt)).to.be.greaterThan(0); + expect(Date.parse(match.updatedAt)).to.be.greaterThan(0); + }); + }); + }); +} diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/index.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/index.ts index 458bc887d02d15..d750fd7bcfb4ef 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/index.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/index.ts @@ -20,6 +20,7 @@ export default function alertingTests({ loadTestFile, getService }: FtrProviderC loadTestFile(require.resolve('./disable')); loadTestFile(require.resolve('./enable')); loadTestFile(require.resolve('./find')); + loadTestFile(require.resolve('./find_internal')); loadTestFile(require.resolve('./get')); loadTestFile(require.resolve('./get_alert_state')); loadTestFile(require.resolve('./get_alert_summary')); From d2d9c27eef7b89dadb6b33dd3a570121c97fe857 Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Sun, 6 Oct 2024 13:23:53 +0300 Subject: [PATCH 077/106] Support filtering by consumers while finding rules in the UI --- .../use_fetch_slos_with_burn_rate_rules.ts | 12 ++--- .../rule_management/api/api.test.ts | 50 ++++--------------- .../rule_management/api/api.ts | 8 +-- .../application/hooks/use_load_rules_query.ts | 7 +-- .../application/lib/rule_api/rules.test.ts | 32 ++++++++---- .../public/application/lib/rule_api/rules.ts | 4 +- .../application/lib/rule_api/rules_helpers.ts | 2 +- .../lib/rule_api/rules_kuery_filter.ts | 4 +- .../connector_rules_list.tsx | 4 +- .../alerts_table/alerts_table_state.tsx | 4 +- .../hooks/alert_mute/use_get_muted_alerts.tsx | 2 +- .../hooks/apis/get_rules_muted_alerts.ts | 10 ++-- .../rules_list/components/rules_list.tsx | 1 + 13 files changed, 60 insertions(+), 80 deletions(-) diff --git a/x-pack/plugins/observability_solution/slo/public/hooks/use_fetch_slos_with_burn_rate_rules.ts b/x-pack/plugins/observability_solution/slo/public/hooks/use_fetch_slos_with_burn_rate_rules.ts index 34cfa36bfcab8d..b37765d93970e4 100644 --- a/x-pack/plugins/observability_solution/slo/public/hooks/use_fetch_slos_with_burn_rate_rules.ts +++ b/x-pack/plugins/observability_solution/slo/public/hooks/use_fetch_slos_with_burn_rate_rules.ts @@ -12,7 +12,7 @@ import { useQuery, } from '@tanstack/react-query'; import type { Rule } from '@kbn/triggers-actions-ui-plugin/public'; -import { BASE_ALERTING_API_PATH } from '@kbn/alerting-plugin/common'; +import { INTERNAL_ALERTING_API_FIND_RULES_PATH } from '@kbn/alerting-plugin/common'; import { HttpSetup } from '@kbn/core/public'; import { useKibana } from '../utils/kibana_react'; import { sloKeys } from './query_key_factory'; @@ -54,17 +54,15 @@ async function fetchRules({ http: HttpSetup; signal?: AbortSignal; }) { - const filter = 'alert.attributes.alertTypeId:slo.rules.burnRate'; - - const query = { + const body = { search, - filter, fields: ['id', 'params.windows', 'name'], per_page: 1000, + rule_type_ids: ['slo.rules.burnRate'], }; - const response = await http.get(`${BASE_ALERTING_API_PATH}/rules/_find`, { - query, + const response = await http.post(INTERNAL_ALERTING_API_FIND_RULES_PATH, { + body: JSON.stringify({ ...body }), signal, }); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/api/api.test.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_management/api/api.test.ts index d10bb4bb03e084..09ec46ee133f38 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/api/api.test.ts +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/api/api.test.ts @@ -850,46 +850,16 @@ describe('Detections Rules API', () => { test('requests snooze settings of multiple rules by their IDs', () => { fetchRulesSnoozeSettings({ ids: ['id1', 'id2'] }); - - expect(fetchMock).toHaveBeenCalledWith( - expect.any(String), - expect.objectContaining({ - query: expect.objectContaining({ - filter: 'alert.id:"alert:id1" or alert.id:"alert:id2"', - }), - }) - ); - }); - - test('requests the same number of rules as the number of ids provided', () => { - fetchRulesSnoozeSettings({ ids: ['id1', 'id2'] }); - - expect(fetchMock).toHaveBeenCalledWith( - expect.any(String), - expect.objectContaining({ - query: expect.objectContaining({ - per_page: 2, - }), - }) - ); - }); - - test('requests only snooze settings fields', () => { - fetchRulesSnoozeSettings({ ids: ['id1', 'id2'] }); - - expect(fetchMock).toHaveBeenCalledWith( - expect.any(String), - expect.objectContaining({ - query: expect.objectContaining({ - fields: JSON.stringify([ - 'muteAll', - 'activeSnoozes', - 'isSnoozedUntil', - 'snoozeSchedule', - ]), - }), - }) - ); + expect(fetchMock.mock.calls[0]).toMatchInlineSnapshot(` + Array [ + "/internal/alerting/rules/_find", + Object { + "body": "{\\"rule_type_ids\\":[\\"id1\\",\\"id2\\"],\\"fields\\":\\"[\\\\\\"muteAll\\\\\\",\\\\\\"activeSnoozes\\\\\\",\\\\\\"isSnoozedUntil\\\\\\",\\\\\\"snoozeSchedule\\\\\\"]\\",\\"per_page\\":2}", + "method": "POST", + "signal": undefined, + }, + ] + `); }); test('returns mapped data', async () => { diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/api/api.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_management/api/api.ts index c86606d0d81377..c293f6fa7ac037 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/api/api.ts +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/api/api.ts @@ -241,12 +241,12 @@ export const fetchRulesSnoozeSettings = async ({ const response = await KibanaServices.get().http.fetch( INTERNAL_ALERTING_API_FIND_RULES_PATH, { - method: 'GET', - query: { - filter: ids.map((x) => `alert.id:"alert:${x}"`).join(' or '), + method: 'POST', + body: JSON.stringify({ + rule_type_ids: ids, fields: JSON.stringify(['muteAll', 'activeSnoozes', 'isSnoozedUntil', 'snoozeSchedule']), per_page: ids.length, - }, + }), signal, } ); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rules_query.ts b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rules_query.ts index e3093bb62894d0..51a7d64b35967c 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rules_query.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rules_query.ts @@ -21,6 +21,7 @@ type UseLoadRulesQueryProps = Omit & { enabled: boolean; refresh?: Date; ruleTypeIds?: string[]; + consumers?: string[]; hasReference?: { type: string; id: string; @@ -28,7 +29,8 @@ type UseLoadRulesQueryProps = Omit & { }; export const useLoadRulesQuery = (props: UseLoadRulesQueryProps) => { - const { ruleTypeIds, filters, page, sort, onPage, enabled, refresh, hasReference } = props; + const { ruleTypeIds, consumers, filters, page, sort, onPage, enabled, refresh, hasReference } = + props; const { http, notifications: { toasts }, @@ -45,7 +47,6 @@ export const useLoadRulesQuery = (props: UseLoadRulesQueryProps) => { 'loadRules', filters.tags, filters.searchText, - filters.types, filters.actionTypes, filters.ruleStatuses, filters.ruleLastRunOutcomes, @@ -64,7 +65,6 @@ export const useLoadRulesQuery = (props: UseLoadRulesQueryProps) => { http, page, searchText: filters.searchText, - typesFilter: filters.types, actionTypesFilter: filters.actionTypes, ruleExecutionStatusesFilter: filters.ruleExecutionStatuses, ruleLastRunOutcomesFilter: filters.ruleLastRunOutcomes, @@ -74,6 +74,7 @@ export const useLoadRulesQuery = (props: UseLoadRulesQueryProps) => { kueryNode: filters.kueryNode, sort, ruleTypeIds, + consumers, hasReference, }); }, diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/rules.test.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/rules.test.ts index b5a09e5a716f9b..79d248dcc1a06c 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/rules.test.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/rules.test.ts @@ -121,7 +121,7 @@ describe('loadRules', () => { `); }); - test('should call find API with typesFilter', async () => { + test('should call find API with ruleTypeIds', async () => { const resolvedValue = { page: 1, per_page: 10, @@ -132,24 +132,30 @@ describe('loadRules', () => { const result = await loadRules({ http, - typesFilter: ['foo', 'bar'], + ruleTypeIds: ['foo', 'bar'], page: { index: 0, size: 10 }, }); + expect(result).toEqual({ page: 1, perPage: 10, total: 0, data: [], }); + expect(http.get.mock.calls[0]).toMatchInlineSnapshot(` Array [ "/internal/alerting/rules/_find", Object { "query": Object { "default_search_operator": "AND", - "filter": "alert.attributes.alertTypeId:(foo or bar)", + "filter": undefined, "page": 1, "per_page": 10, + "rule_type_ids": Array [ + "foo", + "bar", + ], "search": undefined, "search_fields": undefined, "sort_field": "name", @@ -160,7 +166,7 @@ describe('loadRules', () => { `); }); - test('should call find API with actionTypesFilter and typesFilter', async () => { + test('should call find API with actionTypesFilter and ruleTypeIds', async () => { const resolvedValue = { page: 1, per_page: 10, @@ -172,7 +178,7 @@ describe('loadRules', () => { const result = await loadRules({ http, searchText: 'baz', - typesFilter: ['foo', 'bar'], + ruleTypeIds: ['foo', 'bar'], page: { index: 0, size: 10 }, }); expect(result).toEqual({ @@ -187,9 +193,13 @@ describe('loadRules', () => { Object { "query": Object { "default_search_operator": "AND", - "filter": "alert.attributes.alertTypeId:(foo or bar)", + "filter": undefined, "page": 1, "per_page": 10, + "rule_type_ids": Array [ + "foo", + "bar", + ], "search": "baz", "search_fields": "[\\"name\\",\\"tags\\"]", "sort_field": "name", @@ -200,7 +210,7 @@ describe('loadRules', () => { `); }); - test('should call find API with searchText and tagsFilter and typesFilter', async () => { + test('should call find API with searchText and tagsFilter and ruleTypeIds', async () => { const resolvedValue = { page: 1, per_page: 10, @@ -212,7 +222,7 @@ describe('loadRules', () => { const result = await loadRules({ http, searchText: 'apples, foo, baz', - typesFilter: ['foo', 'bar'], + ruleTypeIds: ['foo', 'bar'], page: { index: 0, size: 10 }, }); expect(result).toEqual({ @@ -227,9 +237,13 @@ describe('loadRules', () => { Object { "query": Object { "default_search_operator": "AND", - "filter": "alert.attributes.alertTypeId:(foo or bar)", + "filter": undefined, "page": 1, "per_page": 10, + "rule_type_ids": Array [ + "foo", + "bar", + ], "search": "apples, foo, baz", "search_fields": "[\\"name\\",\\"tags\\"]", "sort_field": "name", diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/rules.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/rules.ts index 99df9a1f85adda..c7baffdb55b56b 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/rules.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/rules.ts @@ -15,13 +15,13 @@ export async function loadRules({ http, page, searchText, - typesFilter, actionTypesFilter, ruleExecutionStatusesFilter, ruleStatusesFilter, tagsFilter, sort = { field: 'name', direction: 'asc' }, ruleTypeIds, + consumers, }: LoadRulesProps): Promise<{ page: number; perPage: number; @@ -29,7 +29,6 @@ export async function loadRules({ data: Rule[]; }> { const filters = mapFiltersToKql({ - typesFilter, actionTypesFilter, tagsFilter, ruleExecutionStatusesFilter, @@ -53,6 +52,7 @@ export async function loadRules({ sort_field: sort.field, sort_order: sort.direction, ...(ruleTypeIds ? { rule_type_ids: ruleTypeIds } : {}), + ...(consumers ? { consumers } : {}), }, }); return { diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/rules_helpers.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/rules_helpers.ts index 3c4efd34ab1d09..b2de0d62c8fab4 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/rules_helpers.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/rules_helpers.ts @@ -15,7 +15,6 @@ export interface LoadRulesProps { http: HttpSetup; page: Pagination; searchText?: string; - typesFilter?: string[]; actionTypesFilter?: string[]; tagsFilter?: string[]; ruleExecutionStatusesFilter?: string[]; @@ -25,6 +24,7 @@ export interface LoadRulesProps { sort?: Sorting; kueryNode?: KueryNode; ruleTypeIds?: string[]; + consumers?: string[]; hasReference?: { type: string; id: string; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/rules_kuery_filter.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/rules_kuery_filter.ts index 74aaf7abb7cd40..346e491aba82ad 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/rules_kuery_filter.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/rules_kuery_filter.ts @@ -15,7 +15,6 @@ export async function loadRulesWithKueryFilter({ http, page, searchText, - typesFilter, actionTypesFilter, ruleExecutionStatusesFilter, ruleLastRunOutcomesFilter, @@ -26,6 +25,7 @@ export async function loadRulesWithKueryFilter({ kueryNode, ruleTypeIds, hasReference, + consumers, }: LoadRulesProps): Promise<{ page: number; perPage: number; @@ -33,7 +33,6 @@ export async function loadRulesWithKueryFilter({ data: Rule[]; }> { const filtersKueryNode = mapFiltersToKueryNode({ - typesFilter, actionTypesFilter, tagsFilter, ruleExecutionStatusesFilter, @@ -60,6 +59,7 @@ export async function loadRulesWithKueryFilter({ sort_order: sort.direction, ...(hasReference ? { has_reference: hasReference } : {}), ...(ruleTypeIds ? { rule_type_ids: ruleTypeIds } : {}), + ...(consumers ? { consumers } : {}), }), }); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/connector_rules_list.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/connector_rules_list.tsx index c2e89eb31fe847..719cd0fef2377c 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/connector_rules_list.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/connector_rules_list.tsx @@ -73,7 +73,6 @@ export const ConnectorRulesList = (props: ConnectorRulesListProps) => { const ruleFilters = useMemo(() => { const baseFilters = { searchText: searchFilter, - types: ruleTypeIds, }; if (connector.isPreconfigured) { @@ -105,10 +104,11 @@ export const ConnectorRulesList = (props: ConnectorRulesListProps) => { id: connector.id, }, }; - }, [connector, searchFilter, ruleTypeIds]); + }, [connector, searchFilter]); const { rulesState } = useLoadRulesQuery({ ...ruleFilters, + ruleTypeIds, hasDefaultRuleTypesFiltersOn: ruleTypeIds.length === 0, page, sort, diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/alerts_table_state.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/alerts_table_state.tsx index 53c2091bd8b112..edc23d353afb81 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/alerts_table_state.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/alerts_table_state.tsx @@ -360,11 +360,11 @@ const AlertsTableStateWithQueryProvider = memo( } }, [alerts, isLoading, isSuccess, onLoaded]); - const mutedAlertIds = useMemo(() => { + const mutedRuleIds = useMemo(() => { return [...new Set(alerts.map((a) => a['kibana.alert.rule.uuid']![0]))]; }, [alerts]); - const { data: mutedAlerts } = useGetMutedAlerts(mutedAlertIds); + const { data: mutedAlerts } = useGetMutedAlerts(mutedRuleIds); const overriddenActions = useMemo(() => { return { toggleColumn: onToggleColumn }; }, [onToggleColumn]); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/alert_mute/use_get_muted_alerts.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/alert_mute/use_get_muted_alerts.tsx index 08f172451ca238..1ca6cbb22ea97c 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/alert_mute/use_get_muted_alerts.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/alert_mute/use_get_muted_alerts.tsx @@ -25,7 +25,7 @@ export const useGetMutedAlerts = (ruleIds: string[], enabled = true) => { return useQuery( triggersActionsUiQueriesKeys.mutedAlerts(), ({ signal }) => - getMutedAlerts(http, { ids: ruleIds }, signal).then(({ data: rules }) => + getMutedAlerts(http, { ruleIds }, signal).then(({ data: rules }) => rules?.reduce((mutedAlerts, rule) => { mutedAlerts[rule.id] = rule.muted_alert_ids; return mutedAlerts; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/apis/get_rules_muted_alerts.ts b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/apis/get_rules_muted_alerts.ts index 5a2f2fcc21c6b6..d9baef548dafce 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/apis/get_rules_muted_alerts.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/apis/get_rules_muted_alerts.ts @@ -6,7 +6,6 @@ */ import { HttpStart } from '@kbn/core-http-browser'; -import { nodeBuilder } from '@kbn/es-query'; const INTERNAL_FIND_RULES_URL = '/internal/alerting/rules/_find'; @@ -21,18 +20,15 @@ export interface FindRulesResponse { export const getMutedAlerts = async ( http: HttpStart, - params: { ids: string[] }, + params: { ruleIds: string[] }, signal?: AbortSignal ) => { - const filterNode = nodeBuilder.or( - params.ids.map((id) => nodeBuilder.is('alert.id', `alert:${id}`)) - ); return http.post(INTERNAL_FIND_RULES_URL, { body: JSON.stringify({ - filter: JSON.stringify(filterNode), + rule_type_ids: params.ruleIds, fields: ['id', 'mutedInstanceIds'], page: 1, - per_page: params.ids.length, + per_page: params.ruleIds.length, }), signal, }); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list.tsx index c052219ae955cf..838bb5379fdc08 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list.tsx @@ -283,6 +283,7 @@ export const RulesList = ({ // Fetch rules const { rulesState, loadRules, hasData, lastUpdate } = useLoadRulesQuery({ ruleTypeIds, + consumers, filters: computedFilter, hasDefaultRuleTypesFiltersOn, page, From b284fdaa215ec19e50ff2f6110b2b04024fc73cc Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Sun, 6 Oct 2024 13:57:22 +0300 Subject: [PATCH 078/106] Add type filters back --- .../application/hooks/use_load_rules_query.ts | 2 + .../application/lib/rule_api/rules.test.ts | 114 +++++++++++++++--- .../public/application/lib/rule_api/rules.ts | 2 + .../application/lib/rule_api/rules_helpers.ts | 1 + .../lib/rule_api/rules_kuery_filter.ts | 2 + .../rules_list/components/rules_list.tsx | 1 + 6 files changed, 102 insertions(+), 20 deletions(-) diff --git a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rules_query.ts b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rules_query.ts index 51a7d64b35967c..7806e6ce1e6aa1 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rules_query.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rules_query.ts @@ -47,6 +47,7 @@ export const useLoadRulesQuery = (props: UseLoadRulesQueryProps) => { 'loadRules', filters.tags, filters.searchText, + filters.types, filters.actionTypes, filters.ruleStatuses, filters.ruleLastRunOutcomes, @@ -65,6 +66,7 @@ export const useLoadRulesQuery = (props: UseLoadRulesQueryProps) => { http, page, searchText: filters.searchText, + typesFilter: filters.types, actionTypesFilter: filters.actionTypes, ruleExecutionStatusesFilter: filters.ruleExecutionStatuses, ruleLastRunOutcomesFilter: filters.ruleLastRunOutcomes, diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/rules.test.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/rules.test.ts index 79d248dcc1a06c..a7eb5160b12d12 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/rules.test.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/rules.test.ts @@ -121,7 +121,7 @@ describe('loadRules', () => { `); }); - test('should call find API with ruleTypeIds', async () => { + test('should call find API with typesFilter', async () => { const resolvedValue = { page: 1, per_page: 10, @@ -132,30 +132,24 @@ describe('loadRules', () => { const result = await loadRules({ http, - ruleTypeIds: ['foo', 'bar'], + typesFilter: ['foo', 'bar'], page: { index: 0, size: 10 }, }); - expect(result).toEqual({ page: 1, perPage: 10, total: 0, data: [], }); - expect(http.get.mock.calls[0]).toMatchInlineSnapshot(` Array [ "/internal/alerting/rules/_find", Object { "query": Object { "default_search_operator": "AND", - "filter": undefined, + "filter": "alert.attributes.alertTypeId:(foo or bar)", "page": 1, "per_page": 10, - "rule_type_ids": Array [ - "foo", - "bar", - ], "search": undefined, "search_fields": undefined, "sort_field": "name", @@ -166,7 +160,7 @@ describe('loadRules', () => { `); }); - test('should call find API with actionTypesFilter and ruleTypeIds', async () => { + test('should call find API with actionTypesFilter and typesFilter', async () => { const resolvedValue = { page: 1, per_page: 10, @@ -178,7 +172,7 @@ describe('loadRules', () => { const result = await loadRules({ http, searchText: 'baz', - ruleTypeIds: ['foo', 'bar'], + typesFilter: ['foo', 'bar'], page: { index: 0, size: 10 }, }); expect(result).toEqual({ @@ -193,13 +187,9 @@ describe('loadRules', () => { Object { "query": Object { "default_search_operator": "AND", - "filter": undefined, + "filter": "alert.attributes.alertTypeId:(foo or bar)", "page": 1, "per_page": 10, - "rule_type_ids": Array [ - "foo", - "bar", - ], "search": "baz", "search_fields": "[\\"name\\",\\"tags\\"]", "sort_field": "name", @@ -210,6 +200,46 @@ describe('loadRules', () => { `); }); + test('should call find API with searchText and tagsFilter and typesFilter', async () => { + const resolvedValue = { + page: 1, + per_page: 10, + total: 0, + data: [], + }; + http.get.mockResolvedValueOnce(resolvedValue); + + const result = await loadRules({ + http, + searchText: 'apples, foo, baz', + typesFilter: ['foo', 'bar'], + page: { index: 0, size: 10 }, + }); + expect(result).toEqual({ + page: 1, + perPage: 10, + total: 0, + data: [], + }); + expect(http.get.mock.calls[0]).toMatchInlineSnapshot(` + Array [ + "/internal/alerting/rules/_find", + Object { + "query": Object { + "default_search_operator": "AND", + "filter": "alert.attributes.alertTypeId:(foo or bar)", + "page": 1, + "per_page": 10, + "search": "apples, foo, baz", + "search_fields": "[\\"name\\",\\"tags\\"]", + "sort_field": "name", + "sort_order": "asc", + }, + }, + ] + `); + }); + test('should call find API with searchText and tagsFilter and ruleTypeIds', async () => { const resolvedValue = { page: 1, @@ -222,7 +252,8 @@ describe('loadRules', () => { const result = await loadRules({ http, searchText: 'apples, foo, baz', - ruleTypeIds: ['foo', 'bar'], + typesFilter: ['foo', 'bar'], + ruleTypeIds: ['one', 'two'], page: { index: 0, size: 10 }, }); expect(result).toEqual({ @@ -237,12 +268,12 @@ describe('loadRules', () => { Object { "query": Object { "default_search_operator": "AND", - "filter": undefined, + "filter": "alert.attributes.alertTypeId:(foo or bar)", "page": 1, "per_page": 10, "rule_type_ids": Array [ - "foo", - "bar", + "one", + "two", ], "search": "apples, foo, baz", "search_fields": "[\\"name\\",\\"tags\\"]", @@ -388,4 +419,47 @@ describe('loadRules', () => { ] `); }); + + test('should call find API with ruleTypeIds', async () => { + const resolvedValue = { + page: 1, + per_page: 10, + total: 0, + data: [], + }; + http.get.mockResolvedValueOnce(resolvedValue); + + const result = await loadRules({ + http, + ruleTypeIds: ['foo', 'bar'], + page: { index: 0, size: 10 }, + }); + expect(result).toEqual({ + page: 1, + perPage: 10, + total: 0, + data: [], + }); + expect(http.get.mock.calls[0]).toMatchInlineSnapshot(` + Array [ + "/internal/alerting/rules/_find", + Object { + "query": Object { + "default_search_operator": "AND", + "filter": undefined, + "page": 1, + "per_page": 10, + "rule_type_ids": Array [ + "foo", + "bar", + ], + "search": undefined, + "search_fields": undefined, + "sort_field": "name", + "sort_order": "asc", + }, + }, + ] + `); + }); }); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/rules.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/rules.ts index c7baffdb55b56b..8c17f18065c844 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/rules.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/rules.ts @@ -15,6 +15,7 @@ export async function loadRules({ http, page, searchText, + typesFilter, actionTypesFilter, ruleExecutionStatusesFilter, ruleStatusesFilter, @@ -29,6 +30,7 @@ export async function loadRules({ data: Rule[]; }> { const filters = mapFiltersToKql({ + typesFilter, actionTypesFilter, tagsFilter, ruleExecutionStatusesFilter, diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/rules_helpers.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/rules_helpers.ts index b2de0d62c8fab4..aa1e2d1dac26ff 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/rules_helpers.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/rules_helpers.ts @@ -15,6 +15,7 @@ export interface LoadRulesProps { http: HttpSetup; page: Pagination; searchText?: string; + typesFilter?: string[]; actionTypesFilter?: string[]; tagsFilter?: string[]; ruleExecutionStatusesFilter?: string[]; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/rules_kuery_filter.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/rules_kuery_filter.ts index 346e491aba82ad..c765f8f478041c 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/rules_kuery_filter.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/rules_kuery_filter.ts @@ -15,6 +15,7 @@ export async function loadRulesWithKueryFilter({ http, page, searchText, + typesFilter, actionTypesFilter, ruleExecutionStatusesFilter, ruleLastRunOutcomesFilter, @@ -33,6 +34,7 @@ export async function loadRulesWithKueryFilter({ data: Rule[]; }> { const filtersKueryNode = mapFiltersToKueryNode({ + typesFilter, actionTypesFilter, tagsFilter, ruleExecutionStatusesFilter, diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list.tsx index 838bb5379fdc08..851400605a805e 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list.tsx @@ -269,6 +269,7 @@ export const RulesList = ({ const rulesTypesFilter = isEmpty(filters.types) ? authorizedRuleTypes.map((art) => art.id) : filters.types; + const hasDefaultRuleTypesFiltersOn = isEmpty(filters.types); const computedFilter = useMemo(() => { From 301559e51eb6d2e3d9614018c7a09dcc9f8f3247 Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Sun, 6 Oct 2024 14:10:50 +0300 Subject: [PATCH 079/106] Add stack rules to o11y --- .../observability/common/constants.ts | 4 +++- .../alert_search_bar/alert_search_bar.test.tsx | 4 ++-- .../alert_search_bar/alert_search_bar.tsx | 4 ++-- .../alerts/get_alerts_page_table_configuration.tsx | 5 +++-- .../alert_details/components/alert_history.tsx | 11 ++++------- .../alert_details/components/related_alerts.tsx | 12 ++++-------- .../observability/public/pages/alerts/alerts.tsx | 13 ++++++++----- .../public/pages/overview/overview.tsx | 7 ++++--- .../public/pages/rule_details/rule_details.tsx | 10 ++++++---- .../observability/public/pages/rules/rules_tab.tsx | 5 +++-- .../server/functions/alerts.ts | 4 ++-- .../slo/alerts/components/slo_alerts_summary.tsx | 4 ++-- .../slo/server/services/get_slos_overview.ts | 11 ++--------- 13 files changed, 45 insertions(+), 49 deletions(-) diff --git a/x-pack/plugins/observability_solution/observability/common/constants.ts b/x-pack/plugins/observability_solution/observability/common/constants.ts index 0286e4bef08257..5b995990d2a700 100644 --- a/x-pack/plugins/observability_solution/observability/common/constants.ts +++ b/x-pack/plugins/observability_solution/observability/common/constants.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { AlertConsumers } from '@kbn/rule-data-utils'; +import { AlertConsumers, ES_QUERY_ID, OBSERVABILITY_RULE_TYPE_IDS } from '@kbn/rule-data-utils'; import type { ValidFeatureId } from '@kbn/rule-data-utils'; import type { RuleCreationValidConsumer } from '@kbn/triggers-actions-ui-plugin/public'; @@ -29,3 +29,5 @@ export const observabilityRuleCreationValidConsumers: RuleCreationValidConsumer[ ]; export const EventsAsUnit = 'events'; + +export const OBSERVABILITY_RULE_TYPE_IDS_WITH_STACK = [...OBSERVABILITY_RULE_TYPE_IDS, ES_QUERY_ID]; diff --git a/x-pack/plugins/observability_solution/observability/public/components/alert_search_bar/alert_search_bar.test.tsx b/x-pack/plugins/observability_solution/observability/public/components/alert_search_bar/alert_search_bar.test.tsx index c1a38f22f16025..8a9a9e8f4da5cf 100644 --- a/x-pack/plugins/observability_solution/observability/public/components/alert_search_bar/alert_search_bar.test.tsx +++ b/x-pack/plugins/observability_solution/observability/public/components/alert_search_bar/alert_search_bar.test.tsx @@ -13,7 +13,7 @@ import { uiSettingsServiceMock } from '@kbn/core-ui-settings-browser-mocks'; import { ObservabilityAlertSearchBarProps, Services } from './types'; import { ObservabilityAlertSearchBar } from './alert_search_bar'; import { render } from '../../utils/test_helper'; -import { OBSERVABILITY_RULE_TYPE_IDS } from '@kbn/rule-data-utils'; +import { OBSERVABILITY_RULE_TYPE_IDS_WITH_STACK } from '../../../common/constants'; const getAlertsSearchBarMock = jest.fn(); const ALERT_SEARCH_BAR_DATA_TEST_SUBJ = 'alerts-search-bar'; @@ -69,7 +69,7 @@ describe('ObservabilityAlertSearchBar', () => { expect(getAlertsSearchBarMock).toHaveBeenCalledWith( expect.objectContaining({ appName: 'testAppName', - ruleTypeIds: OBSERVABILITY_RULE_TYPE_IDS, + ruleTypeIds: OBSERVABILITY_RULE_TYPE_IDS_WITH_STACK, rangeFrom: 'now-15m', rangeTo: 'now', query: '', diff --git a/x-pack/plugins/observability_solution/observability/public/components/alert_search_bar/alert_search_bar.tsx b/x-pack/plugins/observability_solution/observability/public/components/alert_search_bar/alert_search_bar.tsx index 98ec9093923e05..089319e796a903 100644 --- a/x-pack/plugins/observability_solution/observability/public/components/alert_search_bar/alert_search_bar.tsx +++ b/x-pack/plugins/observability_solution/observability/public/components/alert_search_bar/alert_search_bar.tsx @@ -11,7 +11,7 @@ import React, { useCallback, useEffect } from 'react'; import { i18n } from '@kbn/i18n'; import { Filter, Query } from '@kbn/es-query'; import { getEsQueryConfig } from '@kbn/data-plugin/common'; -import { OBSERVABILITY_RULE_TYPE_IDS } from '@kbn/rule-data-utils'; +import { OBSERVABILITY_RULE_TYPE_IDS_WITH_STACK } from '../../../common/constants'; import { AlertsStatusFilter } from './components'; import { ALERT_STATUS_QUERY, DEFAULT_QUERIES, DEFAULT_QUERY_STRING } from './constants'; import { ObservabilityAlertSearchBarProps } from './types'; @@ -161,7 +161,7 @@ export function ObservabilityAlertSearchBar({ {esQuery && ( - ruleTypeIds={OBSERVABILITY_RULE_TYPE_IDS} + ruleTypeIds={OBSERVABILITY_RULE_TYPE_IDS_WITH_STACK} defaultFilters={ALERT_STATUS_FILTER[alertSearchBarStateProps.status] ?? DEFAULT_FILTERS} from={alertSearchBarStateProps.rangeFrom} to={alertSearchBarStateProps.rangeTo} @@ -125,7 +121,7 @@ export function InternalRelatedAlerts({ alert, kuery }: Props) { return ( {esQuery && ( - ruleTypeIds={OBSERVABILITY_RULE_TYPE_IDS} + ruleTypeIds={OBSERVABILITY_RULE_TYPE_IDS_WITH_STACK} defaultFilters={ ALERT_STATUS_FILTER[alertSearchBarStateProps.status] ?? DEFAULT_FILTERS } @@ -281,7 +284,7 @@ function InternalAlertsPage() { return ( Date: Thu, 10 Oct 2024 16:28:44 +0300 Subject: [PATCH 080/106] Support filtering by consumers in the search strategy --- .../search_strategy_types.ts | 1 + .../server/lib/get_consumers_filter.test.tsx | 26 +++ .../server/lib/get_consumers_filter.tsx | 13 ++ .../lib/get_rule_type_ids_filter.test.tsx | 2 +- .../search_strategy/search_strategy.test.ts | 62 ++++++- .../server/search_strategy/search_strategy.ts | 12 +- .../tests/basic/search_strategy.ts | 151 ++++++++++++++++-- 7 files changed, 248 insertions(+), 19 deletions(-) create mode 100644 x-pack/plugins/rule_registry/server/lib/get_consumers_filter.test.tsx create mode 100644 x-pack/plugins/rule_registry/server/lib/get_consumers_filter.tsx diff --git a/packages/kbn-alerting-types/search_strategy_types.ts b/packages/kbn-alerting-types/search_strategy_types.ts index 19f0d5b7379c19..9df72e4fa78861 100644 --- a/packages/kbn-alerting-types/search_strategy_types.ts +++ b/packages/kbn-alerting-types/search_strategy_types.ts @@ -18,6 +18,7 @@ import type { Alert } from './alert_type'; export type RuleRegistrySearchRequest = IEsSearchRequest & { ruleTypeIds: string[]; + consumers?: string[]; fields?: QueryDslFieldAndFormat[]; query?: Pick; sort?: SortCombinations[]; diff --git a/x-pack/plugins/rule_registry/server/lib/get_consumers_filter.test.tsx b/x-pack/plugins/rule_registry/server/lib/get_consumers_filter.test.tsx new file mode 100644 index 00000000000000..600177e1c33ea6 --- /dev/null +++ b/x-pack/plugins/rule_registry/server/lib/get_consumers_filter.test.tsx @@ -0,0 +1,26 @@ +/* + * 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 { getConsumersFilter } from './get_consumers_filter'; + +describe('getConsumersFilter()', () => { + it('should return a consumers filter', () => { + expect(getConsumersFilter(['foo', 'bar'])).toStrictEqual({ + terms: { + 'kibana.alert.rule.consumer': ['foo', 'bar'], + }, + }); + }); + + it('should return undefined if no consumers are provided', () => { + expect(getConsumersFilter()).toBeUndefined(); + }); + + it('should return undefined if an empty array is provided', () => { + expect(getConsumersFilter([])).toBeUndefined(); + }); +}); diff --git a/x-pack/plugins/rule_registry/server/lib/get_consumers_filter.tsx b/x-pack/plugins/rule_registry/server/lib/get_consumers_filter.tsx new file mode 100644 index 00000000000000..c5089416b7ef54 --- /dev/null +++ b/x-pack/plugins/rule_registry/server/lib/get_consumers_filter.tsx @@ -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 { ALERT_RULE_CONSUMER } from '../../common/technical_rule_data_field_names'; + +export function getConsumersFilter(consumers?: string[]) { + return consumers && consumers.length > 0 + ? { terms: { [ALERT_RULE_CONSUMER]: consumers } } + : undefined; +} diff --git a/x-pack/plugins/rule_registry/server/lib/get_rule_type_ids_filter.test.tsx b/x-pack/plugins/rule_registry/server/lib/get_rule_type_ids_filter.test.tsx index 77c70d5ae2234c..7254f25256c2f8 100644 --- a/x-pack/plugins/rule_registry/server/lib/get_rule_type_ids_filter.test.tsx +++ b/x-pack/plugins/rule_registry/server/lib/get_rule_type_ids_filter.test.tsx @@ -8,7 +8,7 @@ import { getRuleTypeIdsFilter } from './get_rule_type_ids_filter'; describe('getRuleTypeIdsFilter()', () => { - it('should return a spaces filter', () => { + it('should return a rule type ids filter', () => { expect(getRuleTypeIdsFilter(['foo', 'bar'])).toStrictEqual({ terms: { 'kibana.alert.rule.rule_type_id': ['foo', 'bar'], diff --git a/x-pack/plugins/rule_registry/server/search_strategy/search_strategy.test.ts b/x-pack/plugins/rule_registry/server/search_strategy/search_strategy.test.ts index eed1c4e378ebfb..5073bcd4d95bd8 100644 --- a/x-pack/plugins/rule_registry/server/search_strategy/search_strategy.test.ts +++ b/x-pack/plugins/rule_registry/server/search_strategy/search_strategy.test.ts @@ -8,7 +8,7 @@ import { lastValueFrom, of } from 'rxjs'; import { merge } from 'lodash'; import { loggerMock } from '@kbn/logging-mocks'; import { ALERT_EVENTS_FIELDS } from '@kbn/alerts-as-data-utils'; -import { ruleRegistrySearchStrategyProvider, EMPTY_RESPONSE } from './search_strategy'; +import { ruleRegistrySearchStrategyProvider } from './search_strategy'; import { dataPluginMock } from '@kbn/data-plugin/server/mocks'; import { SearchStrategyDependencies } from '@kbn/data-plugin/server'; import { alertsMock } from '@kbn/alerting-plugin/server/mocks'; @@ -156,7 +156,20 @@ describe('ruleRegistrySearchStrategyProvider()', () => { strategy.search(request, options, deps as unknown as SearchStrategyDependencies) ); - expect(result).toBe(EMPTY_RESPONSE); + expect(result).toMatchInlineSnapshot(` + Object { + "inspect": Object { + "dsl": Array [ + "{}", + ], + }, + "rawResponse": Object { + "hits": Object { + "total": 0, + }, + }, + } + `); }); it('should not apply rbac filters for siem rule types', async () => { @@ -575,4 +588,49 @@ describe('ruleRegistrySearchStrategyProvider()', () => { } `); }); + + it('should apply the consumers filter', async () => { + const request: RuleRegistrySearchRequest = { + ruleTypeIds: ['siem.esqlRule'], + consumers: ['alerts'], + }; + + const options = {}; + const deps = { + request: {}, + }; + + getAuthorizedRuleTypesMock.mockResolvedValue([]); + getAlertIndicesAliasMock.mockReturnValue(['security-siem']); + + const strategy = ruleRegistrySearchStrategyProvider(data, alerting, logger, security, spaces); + + await lastValueFrom( + strategy.search(request, options, deps as unknown as SearchStrategyDependencies) + ); + + const arg0 = searchStrategySearch.mock.calls[0][0]; + expect(arg0.params.body.query).toMatchInlineSnapshot(` + Object { + "bool": Object { + "filter": Array [ + Object { + "terms": Object { + "kibana.alert.rule.consumer": Array [ + "alerts", + ], + }, + }, + Object { + "terms": Object { + "kibana.alert.rule.rule_type_id": Array [ + "siem.esqlRule", + ], + }, + }, + ], + }, + } + `); + }); }); diff --git a/x-pack/plugins/rule_registry/server/search_strategy/search_strategy.ts b/x-pack/plugins/rule_registry/server/search_strategy/search_strategy.ts index 852e9c80ab4eb3..f74e27866da4b2 100644 --- a/x-pack/plugins/rule_registry/server/search_strategy/search_strategy.ts +++ b/x-pack/plugins/rule_registry/server/search_strategy/search_strategy.ts @@ -6,10 +6,10 @@ */ import Boom from '@hapi/boom'; -import { map, mergeMap, catchError } from 'rxjs'; +import { map, mergeMap, catchError, of } from 'rxjs'; import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { Logger } from '@kbn/core/server'; -import { from, of } from 'rxjs'; +import { from } from 'rxjs'; import { ENHANCED_ES_SEARCH_STRATEGY } from '@kbn/data-plugin/common'; import { ISearchStrategy, PluginStart } from '@kbn/data-plugin/server'; import { @@ -28,9 +28,10 @@ import { MAX_ALERT_SEARCH_SIZE } from '../../common/constants'; import { AlertAuditAction, alertAuditEvent } from '..'; import { getSpacesFilter, getAuthzFilter } from '../lib'; import { getRuleTypeIdsFilter } from '../lib/get_rule_type_ids_filter'; +import { getConsumersFilter } from '../lib/get_consumers_filter'; export const EMPTY_RESPONSE: RuleRegistrySearchResponse = { - rawResponse: {} as RuleRegistrySearchResponse['rawResponse'], + rawResponse: { hits: { total: 0 } } as RuleRegistrySearchResponse['rawResponse'], }; export const RULE_SEARCH_STRATEGY_NAME = 'privateRuleRegistryAlertsSearchStrategy'; @@ -130,6 +131,11 @@ export const ruleRegistrySearchStrategyProvider = ( } const ruleTypeFilter = getRuleTypeIdsFilter(request.ruleTypeIds); + const consumersFilter = getConsumersFilter(request.consumers); + + if (consumersFilter) { + filter.push(consumersFilter); + } if (ruleTypeFilter) { filter.push(ruleTypeFilter); diff --git a/x-pack/test/rule_registry/security_and_spaces/tests/basic/search_strategy.ts b/x-pack/test/rule_registry/security_and_spaces/tests/basic/search_strategy.ts index 73faabf7936e0b..78ef1da93cec1b 100644 --- a/x-pack/test/rule_registry/security_and_spaces/tests/basic/search_strategy.ts +++ b/x-pack/test/rule_registry/security_and_spaces/tests/basic/search_strategy.ts @@ -233,6 +233,84 @@ export default ({ getService }: FtrProviderContext) => { validateRuleTypeIds(result, apmRuleTypeIds); }); + it('should return alerts from different rules', async () => { + const ruleTypeIds = [...apmRuleTypeIds, 'logs.alert.document.count']; + + const result = await secureBsearch.send({ + supertestWithoutAuth, + auth: { + username: obsOnlySpacesAll.username, + password: obsOnlySpacesAll.password, + }, + referer: 'test', + kibanaVersion, + internalOrigin: 'Kibana', + options: { + ruleTypeIds, + }, + strategy: 'privateRuleRegistryAlertsSearchStrategy', + space: 'default', + }); + + expect(result.rawResponse.hits.total).to.eql(14); + + validateRuleTypeIds(result, ruleTypeIds); + }); + + it('should filter alerts by rule type IDs with consumers', async () => { + const result = await secureBsearch.send({ + supertestWithoutAuth, + auth: { + username: obsOnlySpacesAll.username, + password: obsOnlySpacesAll.password, + }, + referer: 'test', + kibanaVersion, + internalOrigin: 'Kibana', + options: { + ruleTypeIds: apmRuleTypeIds, + consumers: ['alerts', 'logs'], + }, + strategy: 'privateRuleRegistryAlertsSearchStrategy', + space: 'default', + }); + + expect(result.rawResponse.hits.total).to.eql(9); + + validateRuleTypeIds(result, apmRuleTypeIds); + }); + + it('should filter alerts by consumers with rule type IDs', async () => { + const ruleTypeIds = [...apmRuleTypeIds, 'logs.alert.document.count']; + + const result = await secureBsearch.send({ + supertestWithoutAuth, + auth: { + username: obsOnlySpacesAll.username, + password: obsOnlySpacesAll.password, + }, + referer: 'test', + kibanaVersion, + internalOrigin: 'Kibana', + options: { + ruleTypeIds, + consumers: ['alerts'], + }, + strategy: 'privateRuleRegistryAlertsSearchStrategy', + space: 'default', + }); + + /** + *There are five documents of rule type logs.alert.document.count + * The four have the consumer set to alerts + * and the one has the consumer set to logs. + * All apm rule types (nine in total) have consumer set to alerts. + */ + expect(result.rawResponse.hits.total).to.eql(13); + + validateRuleTypeIds(result, ruleTypeIds); + }); + it('should not by pass our RBAC authz filter with a should filter for rule type ids', async () => { const result = await secureBsearch.send({ supertestWithoutAuth, @@ -254,7 +332,7 @@ export default ({ getService }: FtrProviderContext) => { should: [ { match: { - 'kibana.alert.rule.rule_type_id': 'logs.alert.document.count', + 'kibana.alert.rule.rule_type_id': 'metrics.alert.inventory.threshold', }, }, ], @@ -297,7 +375,7 @@ export default ({ getService }: FtrProviderContext) => { should: [ { match: { - 'kibana.alert.rule.consumer': 'logs', + 'kibana.alert.rule.consumer': 'infrastructure', }, }, ], @@ -340,7 +418,7 @@ export default ({ getService }: FtrProviderContext) => { should: [ { match: { - 'kibana.alert.rule.rule_type_id': 'logs.alert.document.count', + 'kibana.alert.rule.rule_type_id': 'metrics.alert.inventory.threshold', }, }, ], @@ -381,7 +459,7 @@ export default ({ getService }: FtrProviderContext) => { should: [ { match: { - 'kibana.alert.rule.consumer': 'logs', + 'kibana.alert.rule.consumer': 'infrastructure', }, }, ], @@ -487,7 +565,49 @@ export default ({ getService }: FtrProviderContext) => { validateRuleTypeIds(result, apmRuleTypeIds); }); - it('should return 403 if the user does not have access to any alerts', async () => { + it('should not by pass our RBAC authz filter with the ruleTypeIds and consumers parameter', async () => { + const ruleTypeIds = [ + ...apmRuleTypeIds, + 'metrics.alert.inventory.threshold', + 'metrics.alert.threshold', + '.es-query', + ]; + + const result = await secureBsearch.send({ + supertestWithoutAuth, + auth: { + /** + * obsOnlySpacesAll does not have access to the following pairs: + * + * Rule type ID: metrics.alert.inventory.threshold + * Consumer: alerts + * + * Rule type ID: metrics.alert.threshold + * Consumer: alerts + * + * Rule type ID: .es-query + * Consumer: discover + */ + username: obsOnlySpacesAll.username, + password: obsOnlySpacesAll.password, + }, + referer: 'test', + kibanaVersion, + internalOrigin: 'Kibana', + options: { + ruleTypeIds, + consumers: ['alerts', 'discover'], + }, + strategy: 'privateRuleRegistryAlertsSearchStrategy', + space: 'default', + }); + + expect(result.rawResponse.hits.total).to.eql(9); + + validateRuleTypeIds(result, apmRuleTypeIds); + }); + + it('should not return any alerts if the user does not have access to any alerts', async () => { const result = await secureBsearch.send({ supertestWithoutAuth, auth: { @@ -504,8 +624,7 @@ export default ({ getService }: FtrProviderContext) => { space: 'default', }); - expect(result.statusCode).to.eql(403); - expect(result.message).to.eql('Unauthorized to find alerts for any rule types'); + expect(result.rawResponse.hits.total).to.eql(0); }); it('should not return alerts that the user does not have access to', async () => { @@ -592,11 +711,13 @@ export default ({ getService }: FtrProviderContext) => { kibanaVersion, internalOrigin: 'Kibana', options: { - featureIds: ['discover'], + ruleTypeIds: ['.es-query'], }, strategy: 'privateRuleRegistryAlertsSearchStrategy', }); + validateRuleTypeIds(result, ['.es-query']); + expect(result.rawResponse.hits.total).to.eql(1); const consumers = result.rawResponse.hits.hits.map((hit) => { @@ -617,11 +738,13 @@ export default ({ getService }: FtrProviderContext) => { kibanaVersion, internalOrigin: 'Kibana', options: { - featureIds: ['discover'], + ruleTypeIds: ['.es-query'], }, strategy: 'privateRuleRegistryAlertsSearchStrategy', }); + validateRuleTypeIds(result, ['.es-query']); + expect(result.rawResponse.hits.total).to.eql(1); const consumers = result.rawResponse.hits.hits.map((hit) => { @@ -642,13 +765,12 @@ export default ({ getService }: FtrProviderContext) => { kibanaVersion, internalOrigin: 'Kibana', options: { - featureIds: ['discover'], + ruleTypeIds: ['.es-query'], }, strategy: 'privateRuleRegistryAlertsSearchStrategy', }); - expect(result.statusCode).to.be(500); - expect(result.message).to.be('Unauthorized to find alerts for any rule types'); + expect(result.rawResponse.hits.total).to.eql(0); }); }); @@ -668,13 +790,16 @@ export default ({ getService }: FtrProviderContext) => { }, strategy: 'privateRuleRegistryAlertsSearchStrategy', }); - expect(result.rawResponse).to.eql({}); + + expect(result.rawResponse.hits.total).to.eql(0); }); }); }); }; const validateRuleTypeIds = (result: RuleRegistrySearchResponse, ruleTypeIdsToVerify: string[]) => { + expect(result.rawResponse.hits.total).to.greaterThan(0); + const ruleTypeIds = result.rawResponse.hits.hits .map((hit) => { return hit.fields?.['kibana.alert.rule.rule_type_id']; From 60292a61a98d13c9f1c44c82936833c9cae61ad5 Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Thu, 10 Oct 2024 16:29:35 +0300 Subject: [PATCH 081/106] Add discover consumer to stack feature for es query rule type --- .../stack_alerts/server/feature.test.ts | 27 ++++++++++--------- x-pack/plugins/stack_alerts/server/feature.ts | 18 +++++++++++-- 2 files changed, 31 insertions(+), 14 deletions(-) diff --git a/x-pack/plugins/stack_alerts/server/feature.test.ts b/x-pack/plugins/stack_alerts/server/feature.test.ts index 8db6b2f4e0b9ad..9c65ac29fa1cd8 100644 --- a/x-pack/plugins/stack_alerts/server/feature.test.ts +++ b/x-pack/plugins/stack_alerts/server/feature.test.ts @@ -52,28 +52,29 @@ describe('Stack Alerts Feature Privileges', () => { "stackAlerts", "alerts", ], - "ruleTypeId": ".es-query", + "ruleTypeId": "transform_health", }, Object { "consumers": Array [ "stackAlerts", "alerts", ], - "ruleTypeId": "transform_health", + "ruleTypeId": "xpack.ml.anomaly_detection_alert", }, Object { "consumers": Array [ "stackAlerts", "alerts", ], - "ruleTypeId": "xpack.ml.anomaly_detection_alert", + "ruleTypeId": "observability.rules.custom_threshold", }, Object { "consumers": Array [ "stackAlerts", "alerts", + "discover", ], - "ruleTypeId": "observability.rules.custom_threshold", + "ruleTypeId": ".es-query", }, ] `); @@ -99,28 +100,29 @@ describe('Stack Alerts Feature Privileges', () => { "stackAlerts", "alerts", ], - "ruleTypeId": ".es-query", + "ruleTypeId": "transform_health", }, Object { "consumers": Array [ "stackAlerts", "alerts", ], - "ruleTypeId": "transform_health", + "ruleTypeId": "xpack.ml.anomaly_detection_alert", }, Object { "consumers": Array [ "stackAlerts", "alerts", ], - "ruleTypeId": "xpack.ml.anomaly_detection_alert", + "ruleTypeId": "observability.rules.custom_threshold", }, Object { "consumers": Array [ "stackAlerts", "alerts", + "discover", ], - "ruleTypeId": "observability.rules.custom_threshold", + "ruleTypeId": ".es-query", }, ] `); @@ -146,28 +148,29 @@ describe('Stack Alerts Feature Privileges', () => { "stackAlerts", "alerts", ], - "ruleTypeId": ".es-query", + "ruleTypeId": "transform_health", }, Object { "consumers": Array [ "stackAlerts", "alerts", ], - "ruleTypeId": "transform_health", + "ruleTypeId": "xpack.ml.anomaly_detection_alert", }, Object { "consumers": Array [ "stackAlerts", "alerts", ], - "ruleTypeId": "xpack.ml.anomaly_detection_alert", + "ruleTypeId": "observability.rules.custom_threshold", }, Object { "consumers": Array [ "stackAlerts", "alerts", + "discover", ], - "ruleTypeId": "observability.rules.custom_threshold", + "ruleTypeId": ".es-query", }, ] `); diff --git a/x-pack/plugins/stack_alerts/server/feature.ts b/x-pack/plugins/stack_alerts/server/feature.ts index ff7178da735ed9..98899881da577c 100644 --- a/x-pack/plugins/stack_alerts/server/feature.ts +++ b/x-pack/plugins/stack_alerts/server/feature.ts @@ -21,11 +21,11 @@ import { ID as IndexThreshold } from './rule_types/index_threshold/rule_type'; import { GEO_CONTAINMENT_ID as GeoContainment } from './rule_types/geo_containment'; const TransformHealth = TRANSFORM_RULE_TYPE.TRANSFORM_HEALTH; +const DISCOVER_CONSUMER = 'discover'; -const alertingFeatures = [ +const basicAlertingFeatures = [ IndexThreshold, GeoContainment, - ElasticsearchQuery, TransformHealth, ML_ANOMALY_DETECTION_RULE_TYPE_ID, OBSERVABILITY_THRESHOLD_RULE_TYPE_ID, @@ -34,6 +34,20 @@ const alertingFeatures = [ consumers: [STACK_ALERTS_FEATURE_ID, ALERTING_FEATURE_ID], })); +/** + * We need to add the discover consumer + * to support legacy ES rules that were + * created with the discover consumer. + * + * Issue: https://github.com/elastic/kibana/issues/184595 + */ +const esQueryAlertingFeature = { + ruleTypeId: ElasticsearchQuery, + consumers: [STACK_ALERTS_FEATURE_ID, ALERTING_FEATURE_ID, DISCOVER_CONSUMER], +}; + +const alertingFeatures = [...basicAlertingFeatures, esQueryAlertingFeature]; + export const BUILT_IN_ALERTS_FEATURE: KibanaFeatureConfig = { id: STACK_ALERTS_FEATURE_ID, name: i18n.translate('xpack.stackAlerts.featureRegistry.actionsFeatureName', { From e55e4e7778d3934dfec122c2f51d0cdb3d52acb6 Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Thu, 10 Oct 2024 16:34:03 +0300 Subject: [PATCH 082/106] Fix issues with find rules filtering --- .../rule/methods/find/find_rules.test.ts | 2 +- .../application/rule/methods/find/find_rules.ts | 2 +- .../observability/common/constants.ts | 14 ++++++++++++-- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/alerting/server/application/rule/methods/find/find_rules.test.ts b/x-pack/plugins/alerting/server/application/rule/methods/find/find_rules.test.ts index 1f65c6863451c7..369549d839c798 100644 --- a/x-pack/plugins/alerting/server/application/rule/methods/find/find_rules.test.ts +++ b/x-pack/plugins/alerting/server/application/rule/methods/find/find_rules.test.ts @@ -1076,7 +1076,7 @@ describe('find()', () => { const finalFilter = unsecuredSavedObjectsClient.find.mock.calls[0][0].filter; expect(toKqlExpression(finalFilter)).toMatchInlineSnapshot( - `"((alert.attributes.tags: ['bar'] OR alert.attributes.alertTypeId: foo OR alert.attributes.consumer: bar) AND (alert.attributes.alertTypeId: myType AND alert.attributes.consumer: myApp))"` + `"((alert.attributes.tags: ['bar'] AND alert.attributes.alertTypeId: foo AND alert.attributes.consumer: bar) AND (alert.attributes.alertTypeId: myType AND alert.attributes.consumer: myApp))"` ); }); }); diff --git a/x-pack/plugins/alerting/server/application/rule/methods/find/find_rules.ts b/x-pack/plugins/alerting/server/application/rule/methods/find/find_rules.ts index 56bd3124ac0e15..26441a44744730 100644 --- a/x-pack/plugins/alerting/server/application/rule/methods/find/find_rules.ts +++ b/x-pack/plugins/alerting/server/application/rule/methods/find/find_rules.ts @@ -121,7 +121,7 @@ export async function findRules( const consumersFilter = buildConsumersFilter(consumers); const combinedFilters = combineFilters( [filterKueryNode, ruleTypeIdsFilter, consumersFilter], - 'or' + 'and' ); const finalFilter = combineFilterWithAuthorizationFilter( diff --git a/x-pack/plugins/observability_solution/observability/common/constants.ts b/x-pack/plugins/observability_solution/observability/common/constants.ts index 5b995990d2a700..d948ffe60a7ed4 100644 --- a/x-pack/plugins/observability_solution/observability/common/constants.ts +++ b/x-pack/plugins/observability_solution/observability/common/constants.ts @@ -5,7 +5,12 @@ * 2.0. */ -import { AlertConsumers, ES_QUERY_ID, OBSERVABILITY_RULE_TYPE_IDS } from '@kbn/rule-data-utils'; +import { + AlertConsumers, + ES_QUERY_ID, + ML_ANOMALY_DETECTION_RULE_TYPE_ID, + OBSERVABILITY_RULE_TYPE_IDS, +} from '@kbn/rule-data-utils'; import type { ValidFeatureId } from '@kbn/rule-data-utils'; import type { RuleCreationValidConsumer } from '@kbn/triggers-actions-ui-plugin/public'; @@ -20,6 +25,7 @@ export const observabilityAlertFeatureIds: ValidFeatureId[] = [ AlertConsumers.UPTIME, AlertConsumers.SLO, AlertConsumers.OBSERVABILITY, + AlertConsumers.ALERTS, ]; export const observabilityRuleCreationValidConsumers: RuleCreationValidConsumer[] = [ @@ -30,4 +36,8 @@ export const observabilityRuleCreationValidConsumers: RuleCreationValidConsumer[ export const EventsAsUnit = 'events'; -export const OBSERVABILITY_RULE_TYPE_IDS_WITH_STACK = [...OBSERVABILITY_RULE_TYPE_IDS, ES_QUERY_ID]; +export const OBSERVABILITY_RULE_TYPE_IDS_WITH_STACK = [ + ...OBSERVABILITY_RULE_TYPE_IDS, + ES_QUERY_ID, + ML_ANOMALY_DETECTION_RULE_TYPE_ID, +]; From 0430634503c49096129b9197020e8d0bb128d066 Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Thu, 10 Oct 2024 17:42:39 +0300 Subject: [PATCH 083/106] Pass the consumers to the alerts table --- .../apis/search_alerts/search_alerts.test.tsx | 2 ++ .../apis/search_alerts/search_alerts.ts | 8 +++++- .../hooks/use_search_alerts_query.test.tsx | 28 +++++++++++++++++++ .../common/hooks/use_search_alerts_query.ts | 2 ++ .../components/case_view_alerts.test.tsx | 1 + .../case_view/components/case_view_alerts.tsx | 2 ++ x-pack/plugins/ml/common/constants/alerts.ts | 2 ++ .../explorer/alerts/alerts_panel.tsx | 2 ++ .../anomaly_detection_alerts_state_service.ts | 2 ++ .../components/app/alerts_overview/index.tsx | 1 + .../shared/alerts/alerts_overview.tsx | 1 + .../tabs/alerts/alerts_tab_content.tsx | 1 + .../components/related_alerts.tsx | 6 +++- .../public/pages/alerts/alerts.tsx | 1 + .../public/pages/overview/overview.tsx | 6 +++- .../components/rule_details_tabs.tsx | 2 ++ .../alerts/components/slo_alerts_table.tsx | 3 +- .../components/slo_detail_alerts.tsx | 1 + .../monitor_alerts/monitor_detail_alerts.tsx | 1 + .../tabs/alerts_tab/index.tsx | 2 ++ .../components/alerts_table/index.tsx | 3 +- .../alerts_table/alerts_table_state.tsx | 7 ++++- .../alerts_table/hooks/use_bulk_actions.ts | 7 ++--- 23 files changed, 80 insertions(+), 11 deletions(-) diff --git a/packages/kbn-alerts-ui-shared/src/common/apis/search_alerts/search_alerts.test.tsx b/packages/kbn-alerts-ui-shared/src/common/apis/search_alerts/search_alerts.test.tsx index 9f73dcce9df135..98a1e4cf978f7c 100644 --- a/packages/kbn-alerts-ui-shared/src/common/apis/search_alerts/search_alerts.test.tsx +++ b/packages/kbn-alerts-ui-shared/src/common/apis/search_alerts/search_alerts.test.tsx @@ -205,6 +205,7 @@ describe('searchAlerts', () => { const params: SearchAlertsParams = { data: mockDataPlugin as unknown as DataPublicPluginStart, ruleTypeIds: ['siem.esqlRule'], + consumers: ['siem'], fields: [ { field: 'kibana.rule.type.id', include_unmapped: true }, { field: '*', include_unmapped: true }, @@ -238,6 +239,7 @@ describe('searchAlerts', () => { expect(mockDataPlugin.search.search).toHaveBeenCalledWith( { ruleTypeIds: params.ruleTypeIds, + consumers: params.consumers, fields: [...params.fields!], pagination: { pageIndex: params.pageIndex, diff --git a/packages/kbn-alerts-ui-shared/src/common/apis/search_alerts/search_alerts.ts b/packages/kbn-alerts-ui-shared/src/common/apis/search_alerts/search_alerts.ts index d7779e300b6619..232d1bf20fc68a 100644 --- a/packages/kbn-alerts-ui-shared/src/common/apis/search_alerts/search_alerts.ts +++ b/packages/kbn-alerts-ui-shared/src/common/apis/search_alerts/search_alerts.ts @@ -36,9 +36,13 @@ export interface SearchAlertsParams { // Parameters /** - * Array of rule type ids used for authorization and area-based filtering + * Array of rule type ids used area-based filtering */ ruleTypeIds: string[]; + /** + * Array of consumers used area-based filtering + */ + consumers?: string[]; /** * ES query to perform on the affected alert indices */ @@ -80,6 +84,7 @@ export const searchAlerts = ({ data, signal, ruleTypeIds, + consumers, fields, query, sort, @@ -92,6 +97,7 @@ export const searchAlerts = ({ .search( { ruleTypeIds, + consumers, fields, query, pagination: { pageIndex, pageSize }, diff --git a/packages/kbn-alerts-ui-shared/src/common/hooks/use_search_alerts_query.test.tsx b/packages/kbn-alerts-ui-shared/src/common/hooks/use_search_alerts_query.test.tsx index 2af5775620e8ac..875fb56209c4de 100644 --- a/packages/kbn-alerts-ui-shared/src/common/hooks/use_search_alerts_query.test.tsx +++ b/packages/kbn-alerts-ui-shared/src/common/hooks/use_search_alerts_query.test.tsx @@ -99,6 +99,7 @@ describe('useSearchAlertsQuery', () => { const params: UseSearchAlertsQueryParams = { data: mockDataPlugin as unknown as DataPublicPluginStart, ruleTypeIds: ['siem.esqlRule'], + consumers: ['siem'], fields: [ { field: 'kibana.rule.type.id', include_unmapped: true }, { field: '*', include_unmapped: true }, @@ -125,6 +126,33 @@ describe('useSearchAlertsQuery', () => { queryClient.removeQueries(); }); + it('calls searchAlerts with correct arguments', async () => { + const { result, waitForValueToChange } = renderHook(() => useSearchAlertsQuery(params), { + wrapper, + }); + + await waitForValueToChange(() => result.current.data); + + expect(mockDataPlugin.search.search).toHaveBeenCalledWith( + { + consumers: ['siem'], + fields: [ + { field: 'kibana.rule.type.id', include_unmapped: true }, + { field: '*', include_unmapped: true }, + ], + pagination: { pageIndex: 0, pageSize: 10 }, + query: { ids: { values: ['alert-id-1'] } }, + ruleTypeIds: ['siem.esqlRule'], + runtimeMappings: undefined, + sort: [], + }, + { + abortSignal: expect.any(AbortSignal), + strategy: 'privateRuleRegistryAlertsSearchStrategy', + } + ); + }); + it('returns the response correctly', async () => { const { result, waitForValueToChange } = renderHook(() => useSearchAlertsQuery(params), { wrapper, diff --git a/packages/kbn-alerts-ui-shared/src/common/hooks/use_search_alerts_query.ts b/packages/kbn-alerts-ui-shared/src/common/hooks/use_search_alerts_query.ts index 9645e1e44ad873..4450afa788c39d 100644 --- a/packages/kbn-alerts-ui-shared/src/common/hooks/use_search_alerts_query.ts +++ b/packages/kbn-alerts-ui-shared/src/common/hooks/use_search_alerts_query.ts @@ -30,6 +30,7 @@ export const queryKeyPrefix = ['alerts', searchAlerts.name]; export const useSearchAlertsQuery = ({ data, ...params }: UseSearchAlertsQueryParams) => { const { ruleTypeIds, + consumers, fields, query = { bool: {}, @@ -50,6 +51,7 @@ export const useSearchAlertsQuery = ({ data, ...params }: UseSearchAlertsQueryPa data, signal, ruleTypeIds, + consumers, fields, query, sort, diff --git a/x-pack/plugins/cases/public/components/case_view/components/case_view_alerts.test.tsx b/x-pack/plugins/cases/public/components/case_view/components/case_view_alerts.test.tsx index c6bad3b2bf7357..7366acf6e051f4 100644 --- a/x-pack/plugins/cases/public/components/case_view/components/case_view_alerts.test.tsx +++ b/x-pack/plugins/cases/public/components/case_view/components/case_view_alerts.test.tsx @@ -90,6 +90,7 @@ describe('CaseUI View Page activity tab', () => { alertsTableConfigurationRegistry: expect.anything(), configurationId: 'case-details-alerts-observability', ruleTypeIds: ['log-threshold'], + consumers: ['observability'], id: 'case-details-alerts-observability', query: { ids: { diff --git a/x-pack/plugins/cases/public/components/case_view/components/case_view_alerts.tsx b/x-pack/plugins/cases/public/components/case_view/components/case_view_alerts.tsx index f44a56b609b4c6..6f8223b5305f1d 100644 --- a/x-pack/plugins/cases/public/components/case_view/components/case_view_alerts.tsx +++ b/x-pack/plugins/cases/public/components/case_view/components/case_view_alerts.tsx @@ -58,6 +58,7 @@ export const CaseViewAlerts = ({ caseData, onAlertsTableLoaded }: CaseViewAlerts caseData.owner === SECURITY_SOLUTION_OWNER ? SECURITY_SOLUTION_RULE_TYPE_IDS : alertData?.ruleTypeIds ?? [], + consumers: alertData?.featureIds, query: alertIdsQuery, showAlertStatusWithFlapping: caseData.owner !== SECURITY_SOLUTION_OWNER, onLoaded: onAlertsTableLoaded, @@ -67,6 +68,7 @@ export const CaseViewAlerts = ({ caseData, onAlertsTableLoaded }: CaseViewAlerts configId, caseData.owner, alertData?.ruleTypeIds, + alertData?.featureIds, alertIdsQuery, onAlertsTableLoaded, ] diff --git a/x-pack/plugins/ml/common/constants/alerts.ts b/x-pack/plugins/ml/common/constants/alerts.ts index 1128a217d11fe2..cda61c342b1445 100644 --- a/x-pack/plugins/ml/common/constants/alerts.ts +++ b/x-pack/plugins/ml/common/constants/alerts.ts @@ -12,6 +12,7 @@ import { ALERT_RULE_NAME, ALERT_START, ALERT_STATUS, + AlertConsumers, ML_ANOMALY_DETECTION_RULE_TYPE_ID, } from '@kbn/rule-data-utils'; import type { JobsHealthTests } from '../types/alerts'; @@ -22,6 +23,7 @@ export const ML_ALERT_TYPES = { } as const; export const ML_RULE_TYPE_IDS = Object.values(ML_ALERT_TYPES); +export const ML_VALID_CONSUMERS = [AlertConsumers.ML]; export type MlAlertType = (typeof ML_ALERT_TYPES)[keyof typeof ML_ALERT_TYPES]; diff --git a/x-pack/plugins/ml/public/application/explorer/alerts/alerts_panel.tsx b/x-pack/plugins/ml/public/application/explorer/alerts/alerts_panel.tsx index baca3c542b2f74..b974d15c4c4133 100644 --- a/x-pack/plugins/ml/public/application/explorer/alerts/alerts_panel.tsx +++ b/x-pack/plugins/ml/public/application/explorer/alerts/alerts_panel.tsx @@ -19,6 +19,7 @@ import { ALERT_STATUS_ACTIVE, type AlertStatus } from '@kbn/rule-data-utils'; import type { AlertsTableStateProps } from '@kbn/triggers-actions-ui-plugin/public/application/sections/alerts_table/alerts_table_state'; import React, { type FC, useState } from 'react'; import useObservable from 'react-use/lib/useObservable'; +import { ML_VALID_CONSUMERS } from '../../../../common/constants/alerts'; import { ML_RULE_TYPE_IDS } from '../../../../common'; import { ML_ALERTS_CONFIG_ID } from '../../../alerting/anomaly_detection_alerts_table/register_alerts_table_configuration'; import { CollapsiblePanel } from '../../components/collapsible_panel'; @@ -49,6 +50,7 @@ export const AlertsPanel: FC = () => { configurationId: ML_ALERTS_CONFIG_ID, id: `ml-details-alerts`, ruleTypeIds: ML_RULE_TYPE_IDS, + consumers: ML_VALID_CONSUMERS, query: alertsQuery, showAlertStatusWithFlapping: true, cellContext: { diff --git a/x-pack/plugins/ml/public/application/explorer/alerts/anomaly_detection_alerts_state_service.ts b/x-pack/plugins/ml/public/application/explorer/alerts/anomaly_detection_alerts_state_service.ts index d5d4f710a34c96..82bd60a4802ab1 100644 --- a/x-pack/plugins/ml/public/application/explorer/alerts/anomaly_detection_alerts_state_service.ts +++ b/x-pack/plugins/ml/public/application/explorer/alerts/anomaly_detection_alerts_state_service.ts @@ -30,6 +30,7 @@ import { ALERT_ANOMALY_TIMESTAMP, ML_ALERT_TYPES, ML_RULE_TYPE_IDS, + ML_VALID_CONSUMERS, } from '../../../../common/constants/alerts'; import { StateService } from '../../services/state_service'; import type { AnomalyTimelineStateService } from '../anomaly_timeline_state_service'; @@ -176,6 +177,7 @@ export class AnomalyDetectionAlertsStateService extends StateService { .search( { ruleTypeIds: ML_RULE_TYPE_IDS, + consumers: ML_VALID_CONSUMERS, query, }, { strategy: 'privateRuleRegistryAlertsSearchStrategy' } diff --git a/x-pack/plugins/observability_solution/apm/public/components/app/alerts_overview/index.tsx b/x-pack/plugins/observability_solution/apm/public/components/app/alerts_overview/index.tsx index 59cca37012cfac..29e447faeac497 100644 --- a/x-pack/plugins/observability_solution/apm/public/components/app/alerts_overview/index.tsx +++ b/x-pack/plugins/observability_solution/apm/public/components/app/alerts_overview/index.tsx @@ -108,6 +108,7 @@ export function AlertsOverview() { id={'service-overview-alerts'} configurationId={AlertConsumers.OBSERVABILITY} ruleTypeIds={APM_RULE_TYPE_IDS} + consumers={[AlertConsumers.APM]} query={esQuery} showAlertStatusWithFlapping cellContext={{ observabilityRuleTypeRegistry }} diff --git a/x-pack/plugins/observability_solution/infra/public/components/shared/alerts/alerts_overview.tsx b/x-pack/plugins/observability_solution/infra/public/components/shared/alerts/alerts_overview.tsx index bb5bffb6c71949..0b719ccbebf347 100644 --- a/x-pack/plugins/observability_solution/infra/public/components/shared/alerts/alerts_overview.tsx +++ b/x-pack/plugins/observability_solution/infra/public/components/shared/alerts/alerts_overview.tsx @@ -126,6 +126,7 @@ export const AlertsOverview = ({ id={'assetDetailsAlertsTable'} configurationId={AlertConsumers.OBSERVABILITY} ruleTypeIds={INFRA_RULE_TYPE_IDS} + consumers={[AlertConsumers.INFRASTRUCTURE]} showAlertStatusWithFlapping query={alertsEsQueryByStatus} initialPageSize={5} diff --git a/x-pack/plugins/observability_solution/infra/public/pages/metrics/hosts/components/tabs/alerts/alerts_tab_content.tsx b/x-pack/plugins/observability_solution/infra/public/pages/metrics/hosts/components/tabs/alerts/alerts_tab_content.tsx index 36c3e1f0564141..febad140f26d9c 100644 --- a/x-pack/plugins/observability_solution/infra/public/pages/metrics/hosts/components/tabs/alerts/alerts_tab_content.tsx +++ b/x-pack/plugins/observability_solution/infra/public/pages/metrics/hosts/components/tabs/alerts/alerts_tab_content.tsx @@ -80,6 +80,7 @@ export const AlertsTabContent = () => { alertsTableConfigurationRegistry={alertsTableConfigurationRegistry} configurationId={AlertConsumers.OBSERVABILITY} ruleTypeIds={INFRA_RULE_TYPE_IDS} + consumers={[AlertConsumers.INFRASTRUCTURE]} id={ALERTS_TABLE_ID} initialPageSize={ALERTS_PER_PAGE} query={alertsEsQueryByStatus} diff --git a/x-pack/plugins/observability_solution/observability/public/pages/alert_details/components/related_alerts.tsx b/x-pack/plugins/observability_solution/observability/public/pages/alert_details/components/related_alerts.tsx index f7e59e6b0762f6..a4284ef5b0664d 100644 --- a/x-pack/plugins/observability_solution/observability/public/pages/alert_details/components/related_alerts.tsx +++ b/x-pack/plugins/observability_solution/observability/public/pages/alert_details/components/related_alerts.tsx @@ -12,7 +12,10 @@ import { ALERT_END, ALERT_START, ALERT_UUID } from '@kbn/rule-data-utils'; import { BoolQuery, Filter, type Query } from '@kbn/es-query'; import { AlertsGrouping } from '@kbn/alerts-grouping'; -import { OBSERVABILITY_RULE_TYPE_IDS_WITH_STACK } from '../../../../common/constants'; +import { + OBSERVABILITY_RULE_TYPE_IDS_WITH_STACK, + observabilityAlertFeatureIds, +} from '../../../../common/constants'; import { TopAlert } from '../../..'; import { AlertSearchBarContainerState, @@ -122,6 +125,7 @@ export function InternalRelatedAlerts({ alert, kuery }: Props) { = ({ attackDiscovery, replacements }) configurationId: configId, id: `attack-discovery-alerts-${attackDiscovery.id}`, ruleTypeIds: SECURITY_SOLUTION_RULE_TYPE_IDS, + consumers: [AlertConsumers.SIEM], query: alertIdsQuery, showAlertStatusWithFlapping: false, }), diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_table/index.tsx b/x-pack/plugins/security_solution/public/detections/components/alerts_table/index.tsx index 1c40fd49f878da..65f3569e2d1e2a 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_table/index.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_table/index.tsx @@ -12,7 +12,7 @@ import type { FC } from 'react'; import React, { useRef, useEffect, useState, useCallback, useMemo } from 'react'; import type { AlertsTableStateProps } from '@kbn/triggers-actions-ui-plugin/public/application/sections/alerts_table/alerts_table_state'; import type { Alert } from '@kbn/triggers-actions-ui-plugin/public/types'; -import { ALERT_BUILDING_BLOCK_TYPE } from '@kbn/rule-data-utils'; +import { ALERT_BUILDING_BLOCK_TYPE, AlertConsumers } from '@kbn/rule-data-utils'; import styled from 'styled-components'; import { useDispatch } from 'react-redux'; import { getEsQueryConfig } from '@kbn/data-plugin/public'; @@ -277,6 +277,7 @@ export const AlertsTableComponent: FC = ({ // stores separate configuration based on the view of the table id: `detection-engine-alert-table-${configId}-${tableView}`, ruleTypeIds: SECURITY_SOLUTION_RULE_TYPE_IDS, + consumers: [AlertConsumers.SIEM], query: finalBoolQuery, gridStyle, shouldHighlightRow, diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/alerts_table_state.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/alerts_table_state.tsx index edc23d353afb81..928854a7ade991 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/alerts_table_state.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/alerts_table_state.tsx @@ -68,6 +68,7 @@ export type AlertsTableStateProps = { configurationId: string; id: string; ruleTypeIds: string[]; + consumers?: string[]; query: Pick; initialPageSize?: number; browserFields?: BrowserFields; @@ -192,6 +193,7 @@ const AlertsTableStateWithQueryProvider = memo( configurationId, id, ruleTypeIds, + consumers, query, initialPageSize = DEFAULT_ALERTS_PAGE_SIZE, leadingControlColumns = DEFAULT_LEADING_CONTROL_COLUMNS, @@ -300,6 +302,7 @@ const AlertsTableStateWithQueryProvider = memo( const [queryParams, setQueryParams] = useState({ ruleTypeIds, + consumers, fields, query, sort, @@ -311,6 +314,7 @@ const AlertsTableStateWithQueryProvider = memo( useEffect(() => { setQueryParams(({ pageIndex: oldPageIndex, pageSize: oldPageSize, ...prevQueryParams }) => ({ ruleTypeIds, + consumers, fields, query, sort, @@ -318,6 +322,7 @@ const AlertsTableStateWithQueryProvider = memo( // Go back to the first page if the query changes pageIndex: !deepEqual(prevQueryParams, { ruleTypeIds, + consumers, fields, query, sort, @@ -327,7 +332,7 @@ const AlertsTableStateWithQueryProvider = memo( : oldPageIndex, pageSize: oldPageSize, })); - }, [ruleTypeIds, fields, query, runtimeMappings, sort]); + }, [ruleTypeIds, fields, query, runtimeMappings, sort, consumers]); const { data: alertsData, diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_bulk_actions.ts b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_bulk_actions.ts index 74da460fca6662..1f35d02f8d72f9 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_bulk_actions.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_bulk_actions.ts @@ -7,7 +7,7 @@ import { useCallback, useContext, useEffect, useMemo } from 'react'; import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { useKibana } from '@kbn/kibana-react-plugin/public'; -import { ALERT_CASE_IDS } from '@kbn/rule-data-utils'; +import { ALERT_CASE_IDS, isSiemRuleType } from '@kbn/rule-data-utils'; import { AlertsTableContext } from '../contexts/alerts_table_context'; import { AlertsTableConfigurationRegistry, @@ -305,10 +305,7 @@ export function useBulkActions({ }); const initialItems = useMemo(() => { - return [ - ...caseBulkActions, - ...(ruleTypeIds?.some((ruleTypeId) => ruleTypeId.includes('siem')) ? [] : untrackBulkActions), - ]; + return [...caseBulkActions, ...(ruleTypeIds?.some(isSiemRuleType) ? [] : untrackBulkActions)]; }, [caseBulkActions, ruleTypeIds, untrackBulkActions]); const bulkActions = useMemo(() => { From eaf3376cd20a38008e4ed594fc470dcd65445553 Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Thu, 10 Oct 2024 18:07:51 +0300 Subject: [PATCH 084/106] Update alert as data client to support filtering by consumers --- .../alert_data_client/alerts_client.test.ts | 93 +++++++++++++++++++ .../server/alert_data_client/alerts_client.ts | 26 +++++- 2 files changed, 115 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.test.ts b/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.test.ts index f1e793d104fbc3..77215955277dc6 100644 --- a/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.test.ts +++ b/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.test.ts @@ -147,5 +147,98 @@ describe('AlertsClient', () => { } `); }); + + it('creates the consumers filter correctly', async () => { + await alertsClient.find({ consumers: ['test-consumer-1', 'test-consumer-2'] }); + + expect(esClientMock.search.mock.calls[0][0]).toMatchInlineSnapshot(` + Object { + "body": Object { + "_source": undefined, + "aggs": undefined, + "fields": Array [ + "kibana.alert.rule.rule_type_id", + "kibana.alert.rule.consumer", + "kibana.alert.workflow_status", + "kibana.space_ids", + ], + "query": Object { + "bool": Object { + "filter": Array [ + Object { + "arguments": Array [ + Object { + "arguments": Array [ + Object { + "isQuoted": false, + "type": "literal", + "value": "alert.attributes.alertTypeId", + }, + Object { + "isQuoted": false, + "type": "literal", + "value": "test-rule-type-1", + }, + ], + "function": "is", + "type": "function", + }, + Object { + "arguments": Array [ + Object { + "isQuoted": false, + "type": "literal", + "value": "alert.attributes.consumer", + }, + Object { + "isQuoted": false, + "type": "literal", + "value": "foo", + }, + ], + "function": "is", + "type": "function", + }, + ], + "function": "and", + "type": "function", + }, + Object { + "term": Object { + "kibana.space_ids": "space-1", + }, + }, + Object { + "terms": Object { + "kibana.alert.rule.consumer": Array [ + "test-consumer-1", + "test-consumer-2", + ], + }, + }, + ], + "must": Array [], + "must_not": Array [], + "should": Array [], + }, + }, + "runtime_mappings": undefined, + "size": undefined, + "sort": Array [ + Object { + "@timestamp": Object { + "order": "asc", + "unmapped_type": "date", + }, + }, + ], + "track_total_hits": undefined, + }, + "ignore_unavailable": true, + "index": ".alerts-*", + "seq_no_primary_term": true, + } + `); + }); }); }); diff --git a/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts b/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts index 43c870ad6a83f5..5530ad77658dd8 100644 --- a/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts +++ b/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts @@ -63,6 +63,7 @@ import { MAX_PAGINATED_ALERTS, } from './constants'; import { getRuleTypeIdsFilter } from '../lib/get_rule_type_ids_filter'; +import { getConsumersFilter } from '../lib/get_consumers_filter'; // TODO: Fix typings https://github.com/elastic/kibana/issues/101776 type NonNullableProps = Omit & { @@ -134,6 +135,7 @@ interface GetAlertSummaryParams { gte: string; lte: string; ruleTypeIds: string[]; + consumers?: string[]; filter?: estypes.QueryDslQueryContainer[]; fixedInterval?: string; } @@ -150,6 +152,7 @@ interface SearchAlertsParams { sort?: estypes.SortOptions[]; lastSortIds?: Array; ruleTypeIds?: string[]; + consumers?: string[]; runtimeMappings?: MappingRuntimeFields; } @@ -291,6 +294,7 @@ export class AlertsClient { sort, lastSortIds = [], ruleTypeIds, + consumers, runtimeMappings, }: SearchAlertsParams) { try { @@ -311,7 +315,8 @@ export class AlertsClient { alertSpaceId, operation, config, - ruleTypeIds + ruleTypeIds, + consumers ), aggs, _source, @@ -454,12 +459,14 @@ export class AlertsClient { alertSpaceId: string, operation: WriteOperations.Update | ReadOperations.Get | ReadOperations.Find, config: EsQueryConfig, - ruleTypeIds?: string[] + ruleTypeIds?: string[], + consumers?: string[] ) { try { const authzFilter = (await getAuthzFilter(this.authorization, operation)) as Filter; const spacesFilter = getSpacesFilter(alertSpaceId) as unknown as Filter; const ruleTypeIdsFilter = getRuleTypeIdsFilter(ruleTypeIds) as unknown as Filter; + const consumersFilter = getConsumersFilter(consumers) as unknown as Filter; let esQuery; @@ -474,7 +481,7 @@ export class AlertsClient { const builtQuery = buildEsQuery( undefined, esQuery == null ? { query: ``, language: 'kuery' } : esQuery, - [authzFilter, spacesFilter, ruleTypeIdsFilter], + [authzFilter, spacesFilter, ruleTypeIdsFilter, consumersFilter], config ); @@ -638,6 +645,7 @@ export class AlertsClient { gte, lte, ruleTypeIds, + consumers, filter, fixedInterval = '1m', }: GetAlertSummaryParams) { @@ -709,6 +717,7 @@ export class AlertsClient { }, size: 0, ruleTypeIds, + consumers, }); let activeAlertCount = 0; @@ -980,6 +989,7 @@ export class AlertsClient { >({ aggs, ruleTypeIds, + consumers, index, query, search_after: searchAfter, @@ -991,6 +1001,7 @@ export class AlertsClient { }: { aggs?: object; ruleTypeIds?: string[]; + consumers?: string[]; index?: string; query?: object; search_after?: Array; @@ -1011,6 +1022,7 @@ export class AlertsClient { const alertsSearchResponse = await this.searchAlerts({ ruleTypeIds, + consumers, query, aggs, _source, @@ -1041,6 +1053,7 @@ export class AlertsClient { */ public async getGroupAggregations({ ruleTypeIds, + consumers, groupByField, aggregations, filters, @@ -1049,9 +1062,13 @@ export class AlertsClient { sort = [{ unitsCount: { order: 'desc' } }], }: { /** - * The rule type IDs the alerts belong to, used for authorization + * The rule type IDs the alerts belong to. Used for filtering. */ ruleTypeIds: string[]; + /** + * The consumers the alerts belong to. Used for filtering. + */ + consumers?: string[]; /** * The field to group by * @example "kibana.alert.rule.name" @@ -1094,6 +1111,7 @@ export class AlertsClient { { groupByFields: estypes.AggregationsMultiBucketAggregateBase<{ key: string }> } >({ ruleTypeIds, + consumers, aggs: { groupByFields: { terms: { From bb937262707bbecf157f396621cf34af83269632 Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Sun, 13 Oct 2024 11:38:29 +0300 Subject: [PATCH 085/106] Update to UI to use consumers for RAC APIs --- .../components/alerts_grouping_level.test.tsx | 58 ++++ .../src/components/alerts_grouping_level.tsx | 3 + .../src/mocks/grouping_props.mock.tsx | 2 + packages/kbn-alerts-grouping/src/types.ts | 4 + .../hooks/use_find_alerts_query.test.tsx | 53 +++ .../src/common/hooks/use_find_alerts_query.ts | 5 +- ...t_alerts_group_aggregations_query.test.tsx | 1 + ...use_get_alerts_group_aggregations_query.ts | 1 + .../src/hooks/use_alerts_history.test.tsx | 162 +++++---- .../src/hooks/use_alerts_history.ts | 6 + .../shared/alerts/alerts_overview.tsx | 1 + .../public/hooks/use_alerts_count.test.ts | 5 +- .../infra/public/hooks/use_alerts_count.ts | 7 +- .../tabs/alerts/alerts_tab_content.tsx | 1 + .../components/tabs/alerts_tab_badge.tsx | 2 + .../components/alert_history.tsx | 7 +- .../components/related_alerts.tsx | 1 + .../public/pages/alerts/alerts.tsx | 2 + .../public/pages/overview/overview.tsx | 1 + .../pages/rule_details/rule_details.tsx | 2 + .../alerts/components/slo_alerts_summary.tsx | 3 +- .../public/hooks/use_fetch_active_alerts.ts | 13 +- .../hooks/use_fetch_active_alerts.ts | 8 +- .../tests/find_alerts.test.ts | 219 +++++++++++- .../get_alerts_group_aggregations.test.ts | 3 + .../tests/get_alerts_summary.test.ts | 311 ++++++++++++++++++ .../routes/__mocks__/request_responses.ts | 1 + .../rule_registry/server/routes/find.ts | 3 + .../server/routes/get_alert_summary.test.ts | 36 ++ .../server/routes/get_alert_summary.ts | 11 +- .../get_alerts_group_aggregations.test.ts | 40 +++ .../routes/get_alerts_group_aggregations.ts | 31 +- .../hooks/use_load_alert_summary.ts | 14 +- .../alert_summary_widget.tsx | 2 + .../sections/alert_summary_widget/types.ts | 1 + 35 files changed, 908 insertions(+), 112 deletions(-) create mode 100644 packages/kbn-alerts-ui-shared/src/common/hooks/use_find_alerts_query.test.tsx create mode 100644 x-pack/plugins/rule_registry/server/alert_data_client/tests/get_alerts_summary.test.ts diff --git a/packages/kbn-alerts-grouping/src/components/alerts_grouping_level.test.tsx b/packages/kbn-alerts-grouping/src/components/alerts_grouping_level.test.tsx index 5548c14fcf26f1..b908b07caf7a16 100644 --- a/packages/kbn-alerts-grouping/src/components/alerts_grouping_level.test.tsx +++ b/packages/kbn-alerts-grouping/src/components/alerts_grouping_level.test.tsx @@ -55,6 +55,10 @@ const mockGroupingLevelProps: Omit = { describe('AlertsGroupingLevel', () => { let buildEsQuerySpy: jest.SpyInstance; + beforeEach(() => { + jest.clearAllMocks(); + }); + beforeAll(() => { buildEsQuerySpy = jest.spyOn(buildEsQueryModule, 'buildEsQuery'); }); @@ -119,4 +123,58 @@ describe('AlertsGroupingLevel', () => { Object.keys(groupingSearchResponse.aggregations) ); }); + + it('should calls useGetAlertsGroupAggregationsQuery with correct props', () => { + render( + + {() => } + + ); + + expect(mockUseGetAlertsGroupAggregationsQuery.mock.calls).toMatchInlineSnapshot(` + Array [ + Array [ + Object { + "enabled": true, + "http": Object { + "get": [MockFunction], + }, + "params": Object { + "aggregations": Object {}, + "consumers": Array [ + "stackAlerts", + ], + "filters": Array [ + Object { + "bool": Object { + "filter": Array [], + "must": Array [], + "must_not": Array [], + "should": Array [], + }, + }, + Object { + "range": Object { + "kibana.alert.time_range": Object { + "gte": "2020-07-07T08:20:18.966Z", + "lte": "2020-07-08T08:20:18.966Z", + }, + }, + }, + ], + "groupByField": "selectedGroup", + "pageIndex": 0, + "pageSize": 10, + "ruleTypeIds": Array [ + ".es-query", + ], + }, + "toasts": Object { + "addDanger": [MockFunction], + }, + }, + ], + ] + `); + }); }); diff --git a/packages/kbn-alerts-grouping/src/components/alerts_grouping_level.tsx b/packages/kbn-alerts-grouping/src/components/alerts_grouping_level.tsx index 47ffb1fb1b4d06..02fd5d33e23790 100644 --- a/packages/kbn-alerts-grouping/src/components/alerts_grouping_level.tsx +++ b/packages/kbn-alerts-grouping/src/components/alerts_grouping_level.tsx @@ -47,6 +47,7 @@ const typedMemo: (c: T) => T = memo; export const AlertsGroupingLevel = typedMemo( ({ ruleTypeIds, + consumers, defaultFilters = DEFAULT_FILTERS, from, getGrouping, @@ -87,6 +88,7 @@ export const AlertsGroupingLevel = typedMemo( const aggregationsQuery = useMemo(() => { return { ruleTypeIds, + consumers, groupByField: selectedGroup, aggregations: getAggregationsByGroupingField(selectedGroup)?.reduce( (acc, val) => Object.assign(acc, val), @@ -107,6 +109,7 @@ export const AlertsGroupingLevel = typedMemo( pageSize, }; }, [ + consumers, filters, from, getAggregationsByGroupingField, diff --git a/packages/kbn-alerts-grouping/src/mocks/grouping_props.mock.tsx b/packages/kbn-alerts-grouping/src/mocks/grouping_props.mock.tsx index f891e2e10c1a78..510c7c8fdb8964 100644 --- a/packages/kbn-alerts-grouping/src/mocks/grouping_props.mock.tsx +++ b/packages/kbn-alerts-grouping/src/mocks/grouping_props.mock.tsx @@ -13,6 +13,7 @@ import { AlertsGroupingProps } from '../types'; export const mockGroupingId = 'test'; export const mockRuleTypeIds = ['.es-query']; +export const mockConsumers = ['stackAlerts']; export const mockDate = { from: '2020-07-07T08:20:18.966Z', @@ -30,6 +31,7 @@ export const mockGroupingProps: Omit = { ...mockDate, groupingId: mockGroupingId, ruleTypeIds: mockRuleTypeIds, + consumers: mockConsumers, defaultGroupingOptions: mockOptions, getAggregationsByGroupingField: () => [], getGroupStats: () => [{ title: 'Stat', component: }], diff --git a/packages/kbn-alerts-grouping/src/types.ts b/packages/kbn-alerts-grouping/src/types.ts index f6557e40381086..f1eb9ef00fee8b 100644 --- a/packages/kbn-alerts-grouping/src/types.ts +++ b/packages/kbn-alerts-grouping/src/types.ts @@ -65,6 +65,10 @@ export interface AlertsGroupingProps< * The alerting rule type ids this grouping covers */ ruleTypeIds: string[]; + /** + * The alerting consumers this grouping covers + */ + consumers?: string[]; /** * Time filter start */ diff --git a/packages/kbn-alerts-ui-shared/src/common/hooks/use_find_alerts_query.test.tsx b/packages/kbn-alerts-ui-shared/src/common/hooks/use_find_alerts_query.test.tsx new file mode 100644 index 00000000000000..4fe37fd7a6035d --- /dev/null +++ b/packages/kbn-alerts-ui-shared/src/common/hooks/use_find_alerts_query.test.tsx @@ -0,0 +1,53 @@ +/* + * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import React from 'react'; +import { renderHook } from '@testing-library/react-hooks'; +import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; +import { testQueryClientConfig } from '../test_utils/test_query_client_config'; +import { httpServiceMock } from '@kbn/core-http-browser-mocks'; +import { notificationServiceMock } from '@kbn/core-notifications-browser-mocks'; +import { useFindAlertsQuery } from './use_find_alerts_query'; + +describe('useFindAlertsQuery', () => { + const mockServices = { + http: httpServiceMock.createStartContract(), + toasts: notificationServiceMock.createStartContract().toasts, + }; + + const queryClient = new QueryClient(testQueryClientConfig); + + const wrapper: React.FC> = ({ children }) => ( + {children} + ); + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('calls the api correctly', async () => { + const { result, waitForValueToChange } = renderHook( + () => + useFindAlertsQuery({ + ...mockServices, + params: { ruleTypeIds: ['foo'], consumers: ['bar'] }, + }), + { + wrapper, + } + ); + + await waitForValueToChange(() => result.current.isLoading, { timeout: 5000 }); + + expect(mockServices.http.post).toHaveBeenCalledTimes(1); + expect(mockServices.http.post).toBeCalledWith('/internal/rac/alerts/find', { + body: '{"consumers":["bar"],"rule_type_ids":["foo"]}', + }); + }); +}); diff --git a/packages/kbn-alerts-ui-shared/src/common/hooks/use_find_alerts_query.ts b/packages/kbn-alerts-ui-shared/src/common/hooks/use_find_alerts_query.ts index 615e2825f8805d..41e85a6bc83e02 100644 --- a/packages/kbn-alerts-ui-shared/src/common/hooks/use_find_alerts_query.ts +++ b/packages/kbn-alerts-ui-shared/src/common/hooks/use_find_alerts_query.ts @@ -19,7 +19,7 @@ export interface UseFindAlertsQueryProps { http: HttpStart; toasts: ToastsStart; enabled?: boolean; - params: ISearchRequestParams & { rule_type_ids?: string[] }; + params: ISearchRequestParams & { ruleTypeIds?: string[]; consumers?: string[] }; } /** @@ -34,6 +34,7 @@ export const useFindAlertsQuery = ({ enabled = true, params, }: UseFindAlertsQueryProps) => { + const { ruleTypeIds, ...rest } = params; const onErrorFn = (error: Error) => { if (error) { toasts.addDanger( @@ -48,7 +49,7 @@ export const useFindAlertsQuery = ({ queryKey: ['findAlerts', JSON.stringify(params)], queryFn: () => http.post>(`${BASE_RAC_ALERTS_API_PATH}/find`, { - body: JSON.stringify(params), + body: JSON.stringify({ ...rest, rule_type_ids: ruleTypeIds }), }), onError: onErrorFn, refetchOnWindowFocus: false, diff --git a/packages/kbn-alerts-ui-shared/src/common/hooks/use_get_alerts_group_aggregations_query.test.tsx b/packages/kbn-alerts-ui-shared/src/common/hooks/use_get_alerts_group_aggregations_query.test.tsx index 8f499b29ce1b6a..11f1aef2fa349e 100644 --- a/packages/kbn-alerts-ui-shared/src/common/hooks/use_get_alerts_group_aggregations_query.test.tsx +++ b/packages/kbn-alerts-ui-shared/src/common/hooks/use_get_alerts_group_aggregations_query.test.tsx @@ -41,6 +41,7 @@ const toasts = mockToasts as unknown as ToastsStart; const params = { ruleTypeIds: ['.es-query'], + consumers: ['stackAlerts'], groupByField: 'kibana.alert.rule.name', }; diff --git a/packages/kbn-alerts-ui-shared/src/common/hooks/use_get_alerts_group_aggregations_query.ts b/packages/kbn-alerts-ui-shared/src/common/hooks/use_get_alerts_group_aggregations_query.ts index 1a27dfb5fc95b3..e3c2d42a391e94 100644 --- a/packages/kbn-alerts-ui-shared/src/common/hooks/use_get_alerts_group_aggregations_query.ts +++ b/packages/kbn-alerts-ui-shared/src/common/hooks/use_get_alerts_group_aggregations_query.ts @@ -25,6 +25,7 @@ export interface UseGetAlertsGroupAggregationsQueryProps { enabled?: boolean; params: { ruleTypeIds: string[]; + consumers?: string[]; groupByField: string; aggregations?: Record; filters?: QueryDslQueryContainer[]; diff --git a/x-pack/packages/observability/alert_details/src/hooks/use_alerts_history.test.tsx b/x-pack/packages/observability/alert_details/src/hooks/use_alerts_history.test.tsx index 12b398c9321b2b..2707a0cecd185c 100644 --- a/x-pack/packages/observability/alert_details/src/hooks/use_alerts_history.test.tsx +++ b/x-pack/packages/observability/alert_details/src/hooks/use_alerts_history.test.tsx @@ -5,9 +5,9 @@ * 2.0. */ import React from 'react'; -import { HttpSetup } from '@kbn/core-http-browser'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { act, renderHook } from '@testing-library/react-hooks'; +import { httpServiceMock } from '@kbn/core-http-browser-mocks'; import { type UseAlertsHistory, useAlertsHistory, @@ -24,6 +24,11 @@ const queryClient = new QueryClient({ queries: { retry: false, cacheTime: 0 }, }, }); + +const mockServices = { + http: httpServiceMock.createStartContract(), +}; + const wrapper = ({ children }: any) => ( {children} ); @@ -33,7 +38,7 @@ describe('useAlertsHistory', () => { const end = '2023-05-10T00:00:00.000Z'; const ruleId = 'cfd36e60-ef22-11ed-91eb-b7893acacfe2'; - afterEach(() => { + beforeEach(() => { jest.clearAllMocks(); }); @@ -60,15 +65,12 @@ describe('useAlertsHistory', () => { }); it('returns no data when API error', async () => { - const http = { - post: jest.fn().mockImplementation(() => { - throw new Error('ES error'); - }), - } as unknown as HttpSetup; + mockServices.http.post.mockRejectedValueOnce(new Error('ES error')); + const { result, waitFor } = renderHook( () => useAlertsHistory({ - http, + ...mockServices, ruleTypeIds: ['apm'], ruleId, dateRange: { from: start, to: end }, @@ -86,53 +88,52 @@ describe('useAlertsHistory', () => { }); it('returns the alert history chart data', async () => { - const http = { - post: jest.fn().mockResolvedValue({ - hits: { total: { value: 32, relation: 'eq' }, max_score: null, hits: [] }, - aggregations: { - avgTimeToRecoverUS: { doc_count: 28, recoveryTime: { value: 134959464.2857143 } }, - histogramTriggeredAlerts: { - buckets: [ - { key_as_string: '2023-04-10T00:00:00.000Z', key: 1681084800000, doc_count: 0 }, - { key_as_string: '2023-04-11T00:00:00.000Z', key: 1681171200000, doc_count: 0 }, - { key_as_string: '2023-04-12T00:00:00.000Z', key: 1681257600000, doc_count: 0 }, - { key_as_string: '2023-04-13T00:00:00.000Z', key: 1681344000000, doc_count: 0 }, - { key_as_string: '2023-04-14T00:00:00.000Z', key: 1681430400000, doc_count: 0 }, - { key_as_string: '2023-04-15T00:00:00.000Z', key: 1681516800000, doc_count: 0 }, - { key_as_string: '2023-04-16T00:00:00.000Z', key: 1681603200000, doc_count: 0 }, - { key_as_string: '2023-04-17T00:00:00.000Z', key: 1681689600000, doc_count: 0 }, - { key_as_string: '2023-04-18T00:00:00.000Z', key: 1681776000000, doc_count: 0 }, - { key_as_string: '2023-04-19T00:00:00.000Z', key: 1681862400000, doc_count: 0 }, - { key_as_string: '2023-04-20T00:00:00.000Z', key: 1681948800000, doc_count: 0 }, - { key_as_string: '2023-04-21T00:00:00.000Z', key: 1682035200000, doc_count: 0 }, - { key_as_string: '2023-04-22T00:00:00.000Z', key: 1682121600000, doc_count: 0 }, - { key_as_string: '2023-04-23T00:00:00.000Z', key: 1682208000000, doc_count: 0 }, - { key_as_string: '2023-04-24T00:00:00.000Z', key: 1682294400000, doc_count: 0 }, - { key_as_string: '2023-04-25T00:00:00.000Z', key: 1682380800000, doc_count: 0 }, - { key_as_string: '2023-04-26T00:00:00.000Z', key: 1682467200000, doc_count: 0 }, - { key_as_string: '2023-04-27T00:00:00.000Z', key: 1682553600000, doc_count: 0 }, - { key_as_string: '2023-04-28T00:00:00.000Z', key: 1682640000000, doc_count: 0 }, - { key_as_string: '2023-04-29T00:00:00.000Z', key: 1682726400000, doc_count: 0 }, - { key_as_string: '2023-04-30T00:00:00.000Z', key: 1682812800000, doc_count: 0 }, - { key_as_string: '2023-05-01T00:00:00.000Z', key: 1682899200000, doc_count: 0 }, - { key_as_string: '2023-05-02T00:00:00.000Z', key: 1682985600000, doc_count: 0 }, - { key_as_string: '2023-05-03T00:00:00.000Z', key: 1683072000000, doc_count: 0 }, - { key_as_string: '2023-05-04T00:00:00.000Z', key: 1683158400000, doc_count: 0 }, - { key_as_string: '2023-05-05T00:00:00.000Z', key: 1683244800000, doc_count: 0 }, - { key_as_string: '2023-05-06T00:00:00.000Z', key: 1683331200000, doc_count: 0 }, - { key_as_string: '2023-05-07T00:00:00.000Z', key: 1683417600000, doc_count: 0 }, - { key_as_string: '2023-05-08T00:00:00.000Z', key: 1683504000000, doc_count: 0 }, - { key_as_string: '2023-05-09T00:00:00.000Z', key: 1683590400000, doc_count: 0 }, - { key_as_string: '2023-05-10T00:00:00.000Z', key: 1683676800000, doc_count: 32 }, - ], - }, + mockServices.http.post.mockResolvedValueOnce({ + hits: { total: { value: 32, relation: 'eq' }, max_score: null, hits: [] }, + aggregations: { + avgTimeToRecoverUS: { doc_count: 28, recoveryTime: { value: 134959464.2857143 } }, + histogramTriggeredAlerts: { + buckets: [ + { key_as_string: '2023-04-10T00:00:00.000Z', key: 1681084800000, doc_count: 0 }, + { key_as_string: '2023-04-11T00:00:00.000Z', key: 1681171200000, doc_count: 0 }, + { key_as_string: '2023-04-12T00:00:00.000Z', key: 1681257600000, doc_count: 0 }, + { key_as_string: '2023-04-13T00:00:00.000Z', key: 1681344000000, doc_count: 0 }, + { key_as_string: '2023-04-14T00:00:00.000Z', key: 1681430400000, doc_count: 0 }, + { key_as_string: '2023-04-15T00:00:00.000Z', key: 1681516800000, doc_count: 0 }, + { key_as_string: '2023-04-16T00:00:00.000Z', key: 1681603200000, doc_count: 0 }, + { key_as_string: '2023-04-17T00:00:00.000Z', key: 1681689600000, doc_count: 0 }, + { key_as_string: '2023-04-18T00:00:00.000Z', key: 1681776000000, doc_count: 0 }, + { key_as_string: '2023-04-19T00:00:00.000Z', key: 1681862400000, doc_count: 0 }, + { key_as_string: '2023-04-20T00:00:00.000Z', key: 1681948800000, doc_count: 0 }, + { key_as_string: '2023-04-21T00:00:00.000Z', key: 1682035200000, doc_count: 0 }, + { key_as_string: '2023-04-22T00:00:00.000Z', key: 1682121600000, doc_count: 0 }, + { key_as_string: '2023-04-23T00:00:00.000Z', key: 1682208000000, doc_count: 0 }, + { key_as_string: '2023-04-24T00:00:00.000Z', key: 1682294400000, doc_count: 0 }, + { key_as_string: '2023-04-25T00:00:00.000Z', key: 1682380800000, doc_count: 0 }, + { key_as_string: '2023-04-26T00:00:00.000Z', key: 1682467200000, doc_count: 0 }, + { key_as_string: '2023-04-27T00:00:00.000Z', key: 1682553600000, doc_count: 0 }, + { key_as_string: '2023-04-28T00:00:00.000Z', key: 1682640000000, doc_count: 0 }, + { key_as_string: '2023-04-29T00:00:00.000Z', key: 1682726400000, doc_count: 0 }, + { key_as_string: '2023-04-30T00:00:00.000Z', key: 1682812800000, doc_count: 0 }, + { key_as_string: '2023-05-01T00:00:00.000Z', key: 1682899200000, doc_count: 0 }, + { key_as_string: '2023-05-02T00:00:00.000Z', key: 1682985600000, doc_count: 0 }, + { key_as_string: '2023-05-03T00:00:00.000Z', key: 1683072000000, doc_count: 0 }, + { key_as_string: '2023-05-04T00:00:00.000Z', key: 1683158400000, doc_count: 0 }, + { key_as_string: '2023-05-05T00:00:00.000Z', key: 1683244800000, doc_count: 0 }, + { key_as_string: '2023-05-06T00:00:00.000Z', key: 1683331200000, doc_count: 0 }, + { key_as_string: '2023-05-07T00:00:00.000Z', key: 1683417600000, doc_count: 0 }, + { key_as_string: '2023-05-08T00:00:00.000Z', key: 1683504000000, doc_count: 0 }, + { key_as_string: '2023-05-09T00:00:00.000Z', key: 1683590400000, doc_count: 0 }, + { key_as_string: '2023-05-10T00:00:00.000Z', key: 1683676800000, doc_count: 32 }, + ], }, - }), - } as unknown as HttpSetup; + }, + }); + const { result, waitFor } = renderHook( () => useAlertsHistory({ - http, + ...mockServices, ruleTypeIds: ['apm'], ruleId, dateRange: { from: start, to: end }, @@ -154,26 +155,24 @@ describe('useAlertsHistory', () => { it('calls http post including instanceId query', async () => { const controller = new AbortController(); const signal = controller.signal; - const mockedHttpPost = jest.fn(); - const http = { - post: mockedHttpPost.mockResolvedValue({ - hits: { total: { value: 32, relation: 'eq' }, max_score: null, hits: [] }, - aggregations: { - avgTimeToRecoverUS: { doc_count: 28, recoveryTime: { value: 134959464.2857143 } }, - histogramTriggeredAlerts: { - buckets: [ - { key_as_string: '2023-04-10T00:00:00.000Z', key: 1681084800000, doc_count: 0 }, - ], - }, + mockServices.http.post.mockResolvedValueOnce({ + hits: { total: { value: 32, relation: 'eq' }, max_score: null, hits: [] }, + aggregations: { + avgTimeToRecoverUS: { doc_count: 28, recoveryTime: { value: 134959464.2857143 } }, + histogramTriggeredAlerts: { + buckets: [ + { key_as_string: '2023-04-10T00:00:00.000Z', key: 1681084800000, doc_count: 0 }, + ], }, - }), - } as unknown as HttpSetup; + }, + }); const { result, waitFor } = renderHook( () => useAlertsHistory({ - http, + ...mockServices, ruleTypeIds: ['apm'], + consumers: ['foo'], ruleId, dateRange: { from: start, to: end }, instanceId: 'instance-1', @@ -186,9 +185,10 @@ describe('useAlertsHistory', () => { await act(async () => { await waitFor(() => result.current.isSuccess); }); - expect(mockedHttpPost).toBeCalledWith('/internal/rac/alerts/find', { + + expect(mockServices.http.post).toBeCalledWith('/internal/rac/alerts/find', { body: - '{"size":0,"rule_type_ids":["apm"],"query":{"bool":{"must":[' + + '{"size":0,"rule_type_ids":["apm"],"consumers":["foo"],"query":{"bool":{"must":[' + '{"term":{"kibana.alert.rule.uuid":"cfd36e60-ef22-11ed-91eb-b7893acacfe2"}},' + '{"term":{"kibana.alert.instance.id":"instance-1"}},' + '{"range":{"kibana.alert.time_range":{"from":"2023-04-10T00:00:00.000Z","to":"2023-05-10T00:00:00.000Z"}}}]}},' + @@ -203,25 +203,22 @@ describe('useAlertsHistory', () => { it('calls http post without * instanceId query', async () => { const controller = new AbortController(); const signal = controller.signal; - const mockedHttpPost = jest.fn(); - const http = { - post: mockedHttpPost.mockResolvedValue({ - hits: { total: { value: 32, relation: 'eq' }, max_score: null, hits: [] }, - aggregations: { - avgTimeToRecoverUS: { doc_count: 28, recoveryTime: { value: 134959464.2857143 } }, - histogramTriggeredAlerts: { - buckets: [ - { key_as_string: '2023-04-10T00:00:00.000Z', key: 1681084800000, doc_count: 0 }, - ], - }, + mockServices.http.post.mockResolvedValueOnce({ + hits: { total: { value: 32, relation: 'eq' }, max_score: null, hits: [] }, + aggregations: { + avgTimeToRecoverUS: { doc_count: 28, recoveryTime: { value: 134959464.2857143 } }, + histogramTriggeredAlerts: { + buckets: [ + { key_as_string: '2023-04-10T00:00:00.000Z', key: 1681084800000, doc_count: 0 }, + ], }, - }), - } as unknown as HttpSetup; + }, + }); const { result, waitFor } = renderHook( () => useAlertsHistory({ - http, + ...mockServices, ruleTypeIds: ['apm'], ruleId, dateRange: { from: start, to: end }, @@ -235,7 +232,8 @@ describe('useAlertsHistory', () => { await act(async () => { await waitFor(() => result.current.isSuccess); }); - expect(mockedHttpPost).toBeCalledWith('/internal/rac/alerts/find', { + + expect(mockServices.http.post).toBeCalledWith('/internal/rac/alerts/find', { body: '{"size":0,"rule_type_ids":["apm"],"query":{"bool":{"must":[' + '{"term":{"kibana.alert.rule.uuid":"cfd36e60-ef22-11ed-91eb-b7893acacfe2"}},' + diff --git a/x-pack/packages/observability/alert_details/src/hooks/use_alerts_history.ts b/x-pack/packages/observability/alert_details/src/hooks/use_alerts_history.ts index 51e316313b24f4..06a81f3c7ac8a0 100644 --- a/x-pack/packages/observability/alert_details/src/hooks/use_alerts_history.ts +++ b/x-pack/packages/observability/alert_details/src/hooks/use_alerts_history.ts @@ -21,6 +21,7 @@ import { useQuery } from '@tanstack/react-query'; export interface Props { http: HttpSetup | undefined; ruleTypeIds: string[]; + consumers?: string[]; ruleId: string; dateRange: { from: string; @@ -49,6 +50,7 @@ export const EMPTY_ALERTS_HISTORY = { export function useAlertsHistory({ ruleTypeIds, + consumers, ruleId, dateRange, http, @@ -62,6 +64,7 @@ export function useAlertsHistory({ } return fetchTriggeredAlertsHistory({ ruleTypeIds, + consumers, http, ruleId, dateRange, @@ -99,6 +102,7 @@ interface AggsESResponse { export async function fetchTriggeredAlertsHistory({ ruleTypeIds, + consumers, http, ruleId, dateRange, @@ -106,6 +110,7 @@ export async function fetchTriggeredAlertsHistory({ instanceId, }: { ruleTypeIds: string[]; + consumers?: string[]; http: HttpSetup; ruleId: string; dateRange: { @@ -121,6 +126,7 @@ export async function fetchTriggeredAlertsHistory({ body: JSON.stringify({ size: 0, rule_type_ids: ruleTypeIds, + consumers, query: { bool: { must: [ diff --git a/x-pack/plugins/observability_solution/infra/public/components/shared/alerts/alerts_overview.tsx b/x-pack/plugins/observability_solution/infra/public/components/shared/alerts/alerts_overview.tsx index 0b719ccbebf347..6e0f5535f7e532 100644 --- a/x-pack/plugins/observability_solution/infra/public/components/shared/alerts/alerts_overview.tsx +++ b/x-pack/plugins/observability_solution/infra/public/components/shared/alerts/alerts_overview.tsx @@ -113,6 +113,7 @@ export const AlertsOverview = ({ { }; describe('useAlertsCount', () => { - const ruleTypeIds: string[] = ['metrics.alert.inventory.threshold']; + const ruleTypeIds = ['metrics.alert.inventory.threshold']; + const consumers = ['foo']; beforeAll(() => { mockUseKibana(); @@ -91,6 +92,7 @@ describe('useAlertsCount', () => { const { waitForNextUpdate } = renderHook(() => useAlertsCount({ ruleTypeIds, + consumers, query, }) ); @@ -104,6 +106,7 @@ describe('useAlertsCount', () => { }, }, rule_type_ids: ruleTypeIds, + consumers, query, size: 0, }); diff --git a/x-pack/plugins/observability_solution/infra/public/hooks/use_alerts_count.ts b/x-pack/plugins/observability_solution/infra/public/hooks/use_alerts_count.ts index b0a28219b9a1fb..aab542d597f92f 100644 --- a/x-pack/plugins/observability_solution/infra/public/hooks/use_alerts_count.ts +++ b/x-pack/plugins/observability_solution/infra/public/hooks/use_alerts_count.ts @@ -18,11 +18,13 @@ import { InfraClientCoreStart } from '../types'; interface UseAlertsCountProps { ruleTypeIds: string[]; + consumers?: string[]; query?: estypes.QueryDslQueryContainer; } interface FetchAlertsCountParams { ruleTypeIds: string[]; + consumers?: string[]; query?: estypes.QueryDslQueryContainer; http: HttpSetup; signal: AbortSignal; @@ -35,7 +37,7 @@ export interface AlertsCount { const ALERT_STATUS = 'kibana.alert.status'; -export function useAlertsCount({ ruleTypeIds, query }: UseAlertsCountProps) { +export function useAlertsCount({ ruleTypeIds, consumers, query }: UseAlertsCountProps) { const { http } = useKibana().services; const abortCtrlRef = useRef(new AbortController()); @@ -46,6 +48,7 @@ export function useAlertsCount({ ruleTypeIds, query }: UseAlertsCountProps) { abortCtrlRef.current = new AbortController(); return fetchAlertsCount({ ruleTypeIds, + consumers, query, http, signal: abortCtrlRef.current.signal, @@ -71,6 +74,7 @@ export function useAlertsCount({ ruleTypeIds, query }: UseAlertsCountProps) { async function fetchAlertsCount({ ruleTypeIds, + consumers, http, query, signal, @@ -85,6 +89,7 @@ async function fetchAlertsCount({ }, }, rule_type_ids: ruleTypeIds, + consumers, query, size: 0, }), diff --git a/x-pack/plugins/observability_solution/infra/public/pages/metrics/hosts/components/tabs/alerts/alerts_tab_content.tsx b/x-pack/plugins/observability_solution/infra/public/pages/metrics/hosts/components/tabs/alerts/alerts_tab_content.tsx index febad140f26d9c..54757a9bea3a8e 100644 --- a/x-pack/plugins/observability_solution/infra/public/pages/metrics/hosts/components/tabs/alerts/alerts_tab_content.tsx +++ b/x-pack/plugins/observability_solution/infra/public/pages/metrics/hosts/components/tabs/alerts/alerts_tab_content.tsx @@ -136,6 +136,7 @@ const MemoAlertSummaryWidget = React.memo( { const { alertsCount, loading, error } = useAlertsCount({ ruleTypeIds: INFRA_RULE_TYPE_IDS, + consumers: [AlertConsumers.INFRASTRUCTURE], query: alertsEsQuery, }); diff --git a/x-pack/plugins/observability_solution/observability/public/pages/alert_details/components/alert_history.tsx b/x-pack/plugins/observability_solution/observability/public/pages/alert_details/components/alert_history.tsx index 52c2f95f27c290..bd8b9c49865280 100644 --- a/x-pack/plugins/observability_solution/observability/public/pages/alert_details/components/alert_history.tsx +++ b/x-pack/plugins/observability_solution/observability/public/pages/alert_details/components/alert_history.tsx @@ -19,7 +19,10 @@ import { i18n } from '@kbn/i18n'; import { ALERT_INSTANCE_ID, ALERT_RULE_UUID } from '@kbn/rule-data-utils'; import { useAlertsHistory } from '@kbn/observability-alert-details'; import type { Rule } from '@kbn/triggers-actions-ui-plugin/public'; -import { OBSERVABILITY_RULE_TYPE_IDS_WITH_STACK } from '../../../../common/constants'; +import { + OBSERVABILITY_RULE_TYPE_IDS_WITH_STACK, + observabilityAlertFeatureIds, +} from '../../../../common/constants'; import { convertTo } from '../../../../common/utils/formatters'; import { useKibana } from '../../../utils/kibana_react'; import { TopAlert } from '../../..'; @@ -52,6 +55,7 @@ export function AlertHistoryChart({ rule, alert }: Props) { } = useAlertsHistory({ http, ruleTypeIds: OBSERVABILITY_RULE_TYPE_IDS_WITH_STACK, + consumers: observabilityAlertFeatureIds, ruleId: rule.id, dateRange, instanceId, @@ -151,6 +155,7 @@ export function AlertHistoryChart({ rule, alert }: Props) { ruleTypeIds={OBSERVABILITY_RULE_TYPE_IDS_WITH_STACK} + consumers={observabilityAlertFeatureIds} defaultFilters={ALERT_STATUS_FILTER[alertSearchBarStateProps.status] ?? DEFAULT_FILTERS} from={alertSearchBarStateProps.rangeFrom} to={alertSearchBarStateProps.rangeTo} diff --git a/x-pack/plugins/observability_solution/observability/public/pages/alerts/alerts.tsx b/x-pack/plugins/observability_solution/observability/public/pages/alerts/alerts.tsx index 54e2dc35910aab..1b7b4fd1900b7c 100644 --- a/x-pack/plugins/observability_solution/observability/public/pages/alerts/alerts.tsx +++ b/x-pack/plugins/observability_solution/observability/public/pages/alerts/alerts.tsx @@ -249,6 +249,7 @@ function InternalAlertsPage() { ruleTypeIds={OBSERVABILITY_RULE_TYPE_IDS_WITH_STACK} + consumers={observabilityAlertFeatureIds} defaultFilters={ ALERT_STATUS_FILTER[alertSearchBarStateProps.status] ?? DEFAULT_FILTERS } diff --git a/x-pack/plugins/observability_solution/observability/public/pages/overview/overview.tsx b/x-pack/plugins/observability_solution/observability/public/pages/overview/overview.tsx index 06fc20fcf0352c..b527c6924c9f83 100644 --- a/x-pack/plugins/observability_solution/observability/public/pages/overview/overview.tsx +++ b/x-pack/plugins/observability_solution/observability/public/pages/overview/overview.tsx @@ -234,6 +234,7 @@ export function OverviewPage() { > (`${BASE_RAC_ALERTS_API_PATH}/find`, { body: JSON.stringify({ - feature_ids: [AlertConsumers.SLO, AlertConsumers.OBSERVABILITY], + ruleTypeIds: [SLO_RULE_TYPE_IDS], + consumers: [AlertConsumers.SLO, AlertConsumers.OBSERVABILITY], size: 0, query: { bool: { @@ -67,11 +71,6 @@ export function useFetchActiveAlerts({ }, }, }, - { - term: { - 'kibana.alert.rule.rule_type_id': 'slo.rules.burnRate', - }, - }, { term: { 'kibana.alert.status': 'active', diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitor_details/hooks/use_fetch_active_alerts.ts b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitor_details/hooks/use_fetch_active_alerts.ts index f81601e3ed4133..8c909cd3cfa3b0 100644 --- a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitor_details/hooks/use_fetch_active_alerts.ts +++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitor_details/hooks/use_fetch_active_alerts.ts @@ -6,7 +6,10 @@ */ import { BASE_RAC_ALERTS_API_PATH } from '@kbn/rule-registry-plugin/common'; -import { AlertConsumers } from '@kbn/rule-registry-plugin/common/technical_rule_data_field_names'; +import { + AlertConsumers, + UPTIME_RULE_TYPE_IDS, +} from '@kbn/rule-registry-plugin/common/technical_rule_data_field_names'; import { useFetcher } from '@kbn/observability-shared-plugin/public'; import { useKibana } from '@kbn/kibana-react-plugin/public'; import { useParams } from 'react-router-dom'; @@ -25,7 +28,8 @@ export function useFetchActiveAlerts() { const { loading, data } = useFetcher(async () => { return await http.post(`${BASE_RAC_ALERTS_API_PATH}/find`, { body: JSON.stringify({ - feature_ids: [AlertConsumers.UPTIME], + ruleTypeIds: [UPTIME_RULE_TYPE_IDS], + consumers: [AlertConsumers.UPTIME], size: 0, track_total_hits: true, query: { diff --git a/x-pack/plugins/rule_registry/server/alert_data_client/tests/find_alerts.test.ts b/x-pack/plugins/rule_registry/server/alert_data_client/tests/find_alerts.test.ts index 08fd08716a22f2..c554ee4d61f996 100644 --- a/x-pack/plugins/rule_registry/server/alert_data_client/tests/find_alerts.test.ts +++ b/x-pack/plugins/rule_registry/server/alert_data_client/tests/find_alerts.test.ts @@ -17,6 +17,7 @@ import { elasticsearchClientMock } from '@kbn/core-elasticsearch-client-server-m import { alertingAuthorizationMock } from '@kbn/alerting-plugin/server/authorization/alerting_authorization.mock'; import { auditLoggerMock } from '@kbn/security-plugin/server/audit/mocks'; import { ruleDataServiceMock } from '../../rule_data_plugin_service/rule_data_plugin_service.mock'; +import { JsonObject } from '@kbn/utility-types'; describe('find()', () => { const alertingAuthMock = alertingAuthorizationMock.create(); @@ -49,11 +50,58 @@ describe('find()', () => { ], ]); + const filter = { + bool: { + filter: [ + { + bool: { + should: [ + { + bool: { + filter: [ + { + bool: { + should: [{ match: { 'kibana.alert.rule.rule_type_id': '.es-query' } }], + minimum_should_match: 1, + }, + }, + { + bool: { + should: [ + { + bool: { + should: [{ match: { 'kibana.alert.rule.consumer': 'stackAlerts' } }], + minimum_should_match: 1, + }, + }, + { + bool: { + should: [{ match: { 'kibana.alert.rule.consumer': 'alerts' } }], + minimum_should_match: 1, + }, + }, + ], + minimum_should_match: 1, + }, + }, + ], + }, + }, + ], + minimum_should_match: 1, + }, + }, + { term: { 'kibana.space_ids': 'default' } }, + { terms: { 'kibana.alert.rule.rule_type_id': ['.es-query'] } }, + ], + }, + }; + beforeEach(() => { jest.resetAllMocks(); alertingAuthMock.getSpaceId.mockImplementation(() => DEFAULT_SPACE); alertingAuthMock.getAuthorizationFilter.mockResolvedValue({ - filter: undefined, + filter: filter as unknown as JsonObject, ensureRuleTypeIsAuthorized: jest.fn(), }); alertingAuthMock.getAllAuthorizedRuleTypes.mockResolvedValue({ @@ -109,18 +157,24 @@ describe('find()', () => { const query = { match: { [ALERT_WORKFLOW_STATUS]: 'open' } }; const index = '.alerts-observability.apm.alerts'; const ruleTypeIds = ['siem.esqlRule', 'siem.eqlRule']; + const consumers = ['siem']; + const result = await alertsClient.find({ query, index, ruleTypeIds, + consumers, }); + expect(searchAlertsSpy).toHaveBeenCalledWith( expect.objectContaining({ query, index, ruleTypeIds, + consumers, }) ); + expect(result).toMatchInlineSnapshot(` Object { "_shards": Object { @@ -173,11 +227,100 @@ describe('find()', () => { "query": Object { "bool": Object { "filter": Array [ + Object { + "bool": Object { + "filter": Array [ + Object { + "bool": Object { + "minimum_should_match": 1, + "should": Array [ + Object { + "bool": Object { + "filter": Array [ + Object { + "bool": Object { + "minimum_should_match": 1, + "should": Array [ + Object { + "match": Object { + "kibana.alert.rule.rule_type_id": ".es-query", + }, + }, + ], + }, + }, + Object { + "bool": Object { + "minimum_should_match": 1, + "should": Array [ + Object { + "bool": Object { + "minimum_should_match": 1, + "should": Array [ + Object { + "match": Object { + "kibana.alert.rule.consumer": "stackAlerts", + }, + }, + ], + }, + }, + Object { + "bool": Object { + "minimum_should_match": 1, + "should": Array [ + Object { + "match": Object { + "kibana.alert.rule.consumer": "alerts", + }, + }, + ], + }, + }, + ], + }, + }, + ], + }, + }, + ], + }, + }, + Object { + "term": Object { + "kibana.space_ids": "default", + }, + }, + Object { + "terms": Object { + "kibana.alert.rule.rule_type_id": Array [ + ".es-query", + ], + }, + }, + ], + }, + }, Object { "term": Object { "kibana.space_ids": "test_default_space_id", }, }, + Object { + "terms": Object { + "kibana.alert.rule.rule_type_id": Array [ + "siem.esqlRule", + "siem.eqlRule", + ], + }, + }, + Object { + "terms": Object { + "kibana.alert.rule.consumer": Array [ + "siem", + ], + }, + }, ], "must": Array [ Object { @@ -306,6 +449,80 @@ describe('find()', () => { "query": Object { "bool": Object { "filter": Array [ + Object { + "bool": Object { + "filter": Array [ + Object { + "bool": Object { + "minimum_should_match": 1, + "should": Array [ + Object { + "bool": Object { + "filter": Array [ + Object { + "bool": Object { + "minimum_should_match": 1, + "should": Array [ + Object { + "match": Object { + "kibana.alert.rule.rule_type_id": ".es-query", + }, + }, + ], + }, + }, + Object { + "bool": Object { + "minimum_should_match": 1, + "should": Array [ + Object { + "bool": Object { + "minimum_should_match": 1, + "should": Array [ + Object { + "match": Object { + "kibana.alert.rule.consumer": "stackAlerts", + }, + }, + ], + }, + }, + Object { + "bool": Object { + "minimum_should_match": 1, + "should": Array [ + Object { + "match": Object { + "kibana.alert.rule.consumer": "alerts", + }, + }, + ], + }, + }, + ], + }, + }, + ], + }, + }, + ], + }, + }, + Object { + "term": Object { + "kibana.space_ids": "default", + }, + }, + Object { + "terms": Object { + "kibana.alert.rule.rule_type_id": Array [ + ".es-query", + ], + }, + }, + ], + }, + }, Object { "term": Object { "kibana.space_ids": "test_default_space_id", diff --git a/x-pack/plugins/rule_registry/server/alert_data_client/tests/get_alerts_group_aggregations.test.ts b/x-pack/plugins/rule_registry/server/alert_data_client/tests/get_alerts_group_aggregations.test.ts index fb539ed7cee49d..2bcafffdeebaba 100644 --- a/x-pack/plugins/rule_registry/server/alert_data_client/tests/get_alerts_group_aggregations.test.ts +++ b/x-pack/plugins/rule_registry/server/alert_data_client/tests/get_alerts_group_aggregations.test.ts @@ -71,6 +71,7 @@ describe('getGroupAggregations()', () => { alertsClient.find = jest.fn().mockResolvedValue({ aggregations: {} }); const ruleTypeIds = ['.es-query']; + const consumers = ['stackAlerts']; const groupByField = 'kibana.alert.rule.name'; const aggregations = { @@ -84,6 +85,7 @@ describe('getGroupAggregations()', () => { await alertsClient.getGroupAggregations({ ruleTypeIds, + consumers, groupByField, aggregations, filters, @@ -93,6 +95,7 @@ describe('getGroupAggregations()', () => { expect(alertsClient.find).toHaveBeenCalledWith({ ruleTypeIds, + consumers, aggs: { groupByFields: { terms: { diff --git a/x-pack/plugins/rule_registry/server/alert_data_client/tests/get_alerts_summary.test.ts b/x-pack/plugins/rule_registry/server/alert_data_client/tests/get_alerts_summary.test.ts new file mode 100644 index 00000000000000..deb3b82058843f --- /dev/null +++ b/x-pack/plugins/rule_registry/server/alert_data_client/tests/get_alerts_summary.test.ts @@ -0,0 +1,311 @@ +/* + * 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 { AlertsClient, ConstructorOptions } from '../alerts_client'; +import { loggingSystemMock } from '@kbn/core/server/mocks'; +import { elasticsearchClientMock } from '@kbn/core-elasticsearch-client-server-mocks'; +import { alertingAuthorizationMock } from '@kbn/alerting-plugin/server/authorization/alerting_authorization.mock'; +import { auditLoggerMock } from '@kbn/security-plugin/server/audit/mocks'; +import { ruleDataServiceMock } from '../../rule_data_plugin_service/rule_data_plugin_service.mock'; +import { JsonObject } from '@kbn/utility-types'; + +jest.mock('uuid', () => ({ v4: () => 'unique-value' })); + +const alertingAuthMock = alertingAuthorizationMock.create(); +const esClientMock = elasticsearchClientMock.createElasticsearchClient(); +const auditLogger = auditLoggerMock.create(); + +const alertsClientParams: jest.Mocked = { + logger: loggingSystemMock.create().get(), + authorization: alertingAuthMock, + esClient: esClientMock, + auditLogger, + ruleDataService: ruleDataServiceMock.create(), + getRuleType: jest.fn(), + getRuleList: jest.fn(), + getAlertIndicesAlias: jest.fn().mockReturnValue(['stack-index']), +}; + +const DEFAULT_SPACE = 'test_default_space_id'; +const authorizedRuleTypes = new Map([ + [ + '.es-query', + { + producer: 'stackAlerts', + id: '.es-query', + alerts: { + context: 'stack', + }, + authorizedConsumers: {}, + }, + ], +]); + +const filter = { + bool: { + filter: [ + { + bool: { + should: [ + { + bool: { + filter: [ + { + bool: { + should: [{ match: { 'kibana.alert.rule.rule_type_id': '.es-query' } }], + minimum_should_match: 1, + }, + }, + { + bool: { + should: [ + { + bool: { + should: [{ match: { 'kibana.alert.rule.consumer': 'stackAlerts' } }], + minimum_should_match: 1, + }, + }, + { + bool: { + should: [{ match: { 'kibana.alert.rule.consumer': 'alerts' } }], + minimum_should_match: 1, + }, + }, + ], + minimum_should_match: 1, + }, + }, + ], + }, + }, + ], + minimum_should_match: 1, + }, + }, + { term: { 'kibana.space_ids': 'default' } }, + { terms: { 'kibana.alert.rule.rule_type_id': ['.es-query'] } }, + ], + }, +}; + +describe('getAlertSummary()', () => { + beforeEach(() => { + jest.clearAllMocks(); + alertingAuthMock.getSpaceId.mockImplementation(() => DEFAULT_SPACE); + alertingAuthMock.getAllAuthorizedRuleTypesFindOperation.mockResolvedValue(authorizedRuleTypes); + alertingAuthMock.getAuthorizationFilter.mockResolvedValue({ + filter: filter as unknown as JsonObject, + ensureRuleTypeIsAuthorized: jest.fn(), + }); + }); + + test('calls find() with the correct params', async () => { + const alertsClient = new AlertsClient(alertsClientParams) as jest.Mocked; + alertsClient.find = jest.fn().mockResolvedValue({ aggregations: {} }); + + const ruleTypeIds = ['.es-query']; + const consumers = ['stackAlerts']; + + await alertsClient.getAlertSummary({ + gte: 'now-1d/d', + lte: 'now/d', + ruleTypeIds, + consumers, + }); + + expect(esClientMock.search.mock.calls).toMatchInlineSnapshot(` + Array [ + Array [ + Object { + "body": Object { + "_source": undefined, + "aggs": Object { + "active_alerts_bucket": Object { + "date_histogram": Object { + "extended_bounds": Object { + "max": "now/d", + "min": "now-1d/d", + }, + "field": "kibana.alert.time_range", + "fixed_interval": "1m", + "hard_bounds": Object { + "max": "now/d", + "min": "now-1d/d", + }, + "min_doc_count": 0, + }, + }, + "count": Object { + "terms": Object { + "field": "kibana.alert.status", + }, + }, + "recovered_alerts": Object { + "aggs": Object { + "container": Object { + "date_histogram": Object { + "extended_bounds": Object { + "max": "now/d", + "min": "now-1d/d", + }, + "field": "kibana.alert.end", + "fixed_interval": "1m", + "min_doc_count": 0, + }, + }, + }, + "filter": Object { + "term": Object { + "kibana.alert.status": "recovered", + }, + }, + }, + }, + "fields": Array [ + "kibana.alert.rule.rule_type_id", + "kibana.alert.rule.consumer", + "kibana.alert.workflow_status", + "kibana.space_ids", + ], + "query": Object { + "bool": Object { + "filter": Array [ + Object { + "bool": Object { + "filter": Array [ + Object { + "bool": Object { + "minimum_should_match": 1, + "should": Array [ + Object { + "bool": Object { + "filter": Array [ + Object { + "bool": Object { + "minimum_should_match": 1, + "should": Array [ + Object { + "match": Object { + "kibana.alert.rule.rule_type_id": ".es-query", + }, + }, + ], + }, + }, + Object { + "bool": Object { + "minimum_should_match": 1, + "should": Array [ + Object { + "bool": Object { + "minimum_should_match": 1, + "should": Array [ + Object { + "match": Object { + "kibana.alert.rule.consumer": "stackAlerts", + }, + }, + ], + }, + }, + Object { + "bool": Object { + "minimum_should_match": 1, + "should": Array [ + Object { + "match": Object { + "kibana.alert.rule.consumer": "alerts", + }, + }, + ], + }, + }, + ], + }, + }, + ], + }, + }, + ], + }, + }, + Object { + "term": Object { + "kibana.space_ids": "default", + }, + }, + Object { + "terms": Object { + "kibana.alert.rule.rule_type_id": Array [ + ".es-query", + ], + }, + }, + ], + }, + }, + Object { + "term": Object { + "kibana.space_ids": "test_default_space_id", + }, + }, + Object { + "terms": Object { + "kibana.alert.rule.rule_type_id": Array [ + ".es-query", + ], + }, + }, + Object { + "terms": Object { + "kibana.alert.rule.consumer": Array [ + "stackAlerts", + ], + }, + }, + ], + "must": Array [ + Object { + "bool": Object { + "filter": Array [ + Object { + "range": Object { + "kibana.alert.time_range": Object { + "gt": "now-1d/d", + "lt": "now/d", + }, + }, + }, + ], + }, + }, + ], + "must_not": Array [], + "should": Array [], + }, + }, + "runtime_mappings": undefined, + "size": 0, + "sort": Array [ + Object { + "@timestamp": Object { + "order": "asc", + "unmapped_type": "date", + }, + }, + ], + "track_total_hits": undefined, + }, + "ignore_unavailable": true, + "index": "stack-index", + "seq_no_primary_term": true, + }, + ], + ] + `); + }); +}); diff --git a/x-pack/plugins/rule_registry/server/routes/__mocks__/request_responses.ts b/x-pack/plugins/rule_registry/server/routes/__mocks__/request_responses.ts index e81094ce39e057..1f3df5f6757281 100644 --- a/x-pack/plugins/rule_registry/server/routes/__mocks__/request_responses.ts +++ b/x-pack/plugins/rule_registry/server/routes/__mocks__/request_responses.ts @@ -59,6 +59,7 @@ export const getAlertsGroupAggregationsRequest = () => 'slo.rules.burnRate', 'xpack.uptime.alerts.durationAnomaly', ], + consumers: ['apm'], groupByField: 'kibana.alert.rule.name', aggregations: { unitsCount: { diff --git a/x-pack/plugins/rule_registry/server/routes/find.ts b/x-pack/plugins/rule_registry/server/routes/find.ts index b9c7fef331c1c5..3869ce07c36bfa 100644 --- a/x-pack/plugins/rule_registry/server/routes/find.ts +++ b/x-pack/plugins/rule_registry/server/routes/find.ts @@ -26,6 +26,7 @@ export const findAlertsByQueryRoute = (router: IRouter t.partial({ aggs: t.record(t.string, t.intersection([metricsAggsSchemas, bucketAggsSchemas])), rule_type_ids: t.union([t.array(t.string), t.undefined]), + consumers: t.union([t.array(t.string), t.undefined]), index: t.string, query: t.object, search_after: t.union([t.array(t.number), t.array(t.string), t.undefined]), @@ -47,6 +48,7 @@ export const findAlertsByQueryRoute = (router: IRouter const { aggs, rule_type_ids: ruleTypeIds, + consumers, index, query, // eslint-disable-next-line @typescript-eslint/naming-convention @@ -62,6 +64,7 @@ export const findAlertsByQueryRoute = (router: IRouter const alerts = await alertsClient.find({ aggs, ruleTypeIds, + consumers, index, query, search_after, diff --git a/x-pack/plugins/rule_registry/server/routes/get_alert_summary.test.ts b/x-pack/plugins/rule_registry/server/routes/get_alert_summary.test.ts index 7a1ec09b9dba5e..cdb433b68157d1 100644 --- a/x-pack/plugins/rule_registry/server/routes/get_alert_summary.test.ts +++ b/x-pack/plugins/rule_registry/server/routes/get_alert_summary.test.ts @@ -112,5 +112,41 @@ describe('getAlertSummaryRoute', () => { `"Request was rejected with message: 'invalid keys \\"boop\\"'"` ); }); + + test('rejects without ruleTypeIds', async () => { + await expect( + server.inject( + requestMock.create({ + method: 'post', + path: `${BASE_RAC_ALERTS_API_PATH}/_alert_summary`, + body: { + gte: '2020-12-16T15:00:00.000Z', + lte: '2020-12-16T16:00:00.000Z', + }, + }), + context + ) + ).rejects.toThrowErrorMatchingInlineSnapshot( + `"Request was rejected with message: 'Invalid value \\"undefined\\" supplied to \\"ruleTypeIds\\"'"` + ); + }); + + test('accepts consumers', async () => { + await expect( + server.inject( + requestMock.create({ + method: 'post', + path: `${BASE_RAC_ALERTS_API_PATH}/_alert_summary`, + body: { + gte: '2020-12-16T15:00:00.000Z', + lte: '2020-12-16T16:00:00.000Z', + consumers: ['foo'], + ruleTypeIds: ['bar'], + }, + }), + context + ) + ).resolves.not.toThrow(); + }); }); }); diff --git a/x-pack/plugins/rule_registry/server/routes/get_alert_summary.ts b/x-pack/plugins/rule_registry/server/routes/get_alert_summary.ts index 7d3994fd4ee01d..259bea7bbcc4dd 100644 --- a/x-pack/plugins/rule_registry/server/routes/get_alert_summary.ts +++ b/x-pack/plugins/rule_registry/server/routes/get_alert_summary.ts @@ -34,6 +34,7 @@ export const getAlertSummaryRoute = (router: IRouter) t.partial({ fixed_interval: t.string, filter: t.array(t.object), + consumers: t.array(t.string), }) ), ]) @@ -48,7 +49,14 @@ export const getAlertSummaryRoute = (router: IRouter) try { const racContext = await context.rac; const alertsClient = await racContext.getAlertsClient(); - const { gte, lte, ruleTypeIds, filter, fixed_interval: fixedInterval } = request.body; + const { + gte, + lte, + ruleTypeIds, + consumers, + filter, + fixed_interval: fixedInterval, + } = request.body; if ( !( moment(gte, 'YYYY-MM-DDTHH:mm:ss.SSSZ', true).isValid() && @@ -68,6 +76,7 @@ export const getAlertSummaryRoute = (router: IRouter) gte, lte, ruleTypeIds, + consumers, filter: filter as estypes.QueryDslQueryContainer[], fixedInterval, }); diff --git a/x-pack/plugins/rule_registry/server/routes/get_alerts_group_aggregations.test.ts b/x-pack/plugins/rule_registry/server/routes/get_alerts_group_aggregations.test.ts index 888a8686c02981..252780b59945c0 100644 --- a/x-pack/plugins/rule_registry/server/routes/get_alerts_group_aggregations.test.ts +++ b/x-pack/plugins/rule_registry/server/routes/get_alerts_group_aggregations.test.ts @@ -298,4 +298,44 @@ describe('getAlertsGroupAggregations', () => { message: 'Unable to get alerts', }); }); + + test('rejects without ruleTypeIds', async () => { + await expect( + server.inject( + requestMock.create({ + method: 'post', + path: `${BASE_RAC_ALERTS_API_PATH}/_group_aggregations`, + body: { + groupByField: 'kibana.alert.rule.name', + }, + }), + context + ) + ).rejects.toThrowErrorMatchingInlineSnapshot( + `"Request was rejected with message: 'Invalid value \\"undefined\\" supplied to \\"ruleTypeIds\\"'"` + ); + }); + + test('accepts consumers', async () => { + await expect( + server.inject( + requestMock.create({ + method: 'post', + path: `${BASE_RAC_ALERTS_API_PATH}/_group_aggregations`, + body: { + ruleTypeIds: [ + 'apm.anomaly', + 'logs.alert.document.count', + 'metrics.alert.threshold', + 'slo.rules.burnRate', + 'xpack.uptime.alerts.durationAnomaly', + ], + groupByField: 'kibana.alert.rule.name', + consumers: ['foo'], + }, + }), + context + ) + ).resolves.not.toThrow(); + }); }); diff --git a/x-pack/plugins/rule_registry/server/routes/get_alerts_group_aggregations.ts b/x-pack/plugins/rule_registry/server/routes/get_alerts_group_aggregations.ts index a56f6659b669eb..ea3f9cc7d05301 100644 --- a/x-pack/plugins/rule_registry/server/routes/get_alerts_group_aggregations.ts +++ b/x-pack/plugins/rule_registry/server/routes/get_alerts_group_aggregations.ts @@ -22,17 +22,24 @@ export const getAlertsGroupAggregations = (router: IRouter { const { ruleTypeIds, + consumers, groupByField, aggregations, filters, @@ -55,6 +63,7 @@ export const getAlertsGroupAggregations = (router: IRouter({ isLoading: true, @@ -52,6 +58,7 @@ export function useLoadAlertSummary({ ruleTypeIds, timeRange, filter }: UseLoadA try { const { activeAlertCount, activeAlerts, recoveredAlertCount } = await fetchAlertSummary({ ruleTypeIds, + consumers, filter, http, signal: abortCtrlRef.current.signal, @@ -79,7 +86,7 @@ export function useLoadAlertSummary({ ruleTypeIds, timeRange, filter }: UseLoadA } } } - }, [ruleTypeIds, filter, http, timeRange]); + }, [ruleTypeIds, consumers, filter, http, timeRange]); useEffect(() => { loadAlertSummary(); @@ -90,6 +97,7 @@ export function useLoadAlertSummary({ ruleTypeIds, timeRange, filter }: UseLoadA async function fetchAlertSummary({ ruleTypeIds, + consumers, filter, http, signal, @@ -97,6 +105,7 @@ async function fetchAlertSummary({ }: { http: HttpSetup; ruleTypeIds: string[]; + consumers?: string[]; signal: AbortSignal; timeRange: AlertSummaryTimeRange; filter?: estypes.QueryDslQueryContainer; @@ -108,6 +117,7 @@ async function fetchAlertSummary({ gte: utcFrom, lte: utcTo, ruleTypeIds, + consumers, filter: [filter], }), }); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_summary_widget/alert_summary_widget.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_summary_widget/alert_summary_widget.tsx index 098f2719f94fa1..9fcc195a17ecf3 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_summary_widget/alert_summary_widget.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_summary_widget/alert_summary_widget.tsx @@ -20,6 +20,7 @@ import { AlertSummaryWidgetDependencies, DependencyProps } from './types'; export const AlertSummaryWidget = ({ chartProps, ruleTypeIds, + consumers, filter, fullSize, onClick = () => {}, @@ -35,6 +36,7 @@ export const AlertSummaryWidget = ({ error, } = useLoadAlertSummary({ ruleTypeIds, + consumers, filter, timeRange, }); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_summary_widget/types.ts b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_summary_widget/types.ts index c696c8e3f8d0fa..88b40289cb6e09 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_summary_widget/types.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_summary_widget/types.ts @@ -49,6 +49,7 @@ export interface DependencyProps { export interface AlertSummaryWidgetProps { ruleTypeIds?: string[]; + consumers?: string[]; filter?: estypes.QueryDslQueryContainer; fullSize?: boolean; onClick?: (status?: AlertStatus) => void; From 4a0369672b0ff0018120ae798c6413da1e855d8a Mon Sep 17 00:00:00 2001 From: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Date: Sun, 13 Oct 2024 08:49:38 +0000 Subject: [PATCH 086/106] [CI] Auto-commit changed files from 'node scripts/notice' --- x-pack/packages/observability/alert_details/tsconfig.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/packages/observability/alert_details/tsconfig.json b/x-pack/packages/observability/alert_details/tsconfig.json index a349651fdff7ef..d1b4c3fb2ce234 100644 --- a/x-pack/packages/observability/alert_details/tsconfig.json +++ b/x-pack/packages/observability/alert_details/tsconfig.json @@ -17,9 +17,9 @@ ], "kbn_references": [ "@kbn/i18n", - "@kbn/core-http-browser", "@kbn/rule-data-utils", "@kbn/core", - "@kbn/rule-registry-plugin" + "@kbn/rule-registry-plugin", + "@kbn/core-http-browser-mocks" ] } From f5adf3eed03116b9e74bfa4351462d401bd058c9 Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Sun, 13 Oct 2024 13:49:13 +0300 Subject: [PATCH 087/106] Fix aggregation filtering bug --- .../application/rule/methods/aggregate/aggregate_rules.test.ts | 2 +- .../application/rule/methods/aggregate/aggregate_rules.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/alerting/server/application/rule/methods/aggregate/aggregate_rules.test.ts b/x-pack/plugins/alerting/server/application/rule/methods/aggregate/aggregate_rules.test.ts index b313005140ec95..23ccbf97cb6ce8 100644 --- a/x-pack/plugins/alerting/server/application/rule/methods/aggregate/aggregate_rules.test.ts +++ b/x-pack/plugins/alerting/server/application/rule/methods/aggregate/aggregate_rules.test.ts @@ -412,7 +412,7 @@ describe('aggregate()', () => { expect(unsecuredSavedObjectsClient.find).toHaveBeenCalledTimes(1); expect(toKqlExpression(finalFilter)).toMatchInlineSnapshot( - `"((alert.attributes.tags: ['bar'] OR alert.attributes.alertTypeId: my-rule-type-id OR alert.attributes.consumer: bar) AND (alert.attributes.alertTypeId: myType AND alert.attributes.consumer: myApp))"` + `"((alert.attributes.tags: ['bar'] AND alert.attributes.alertTypeId: my-rule-type-id AND alert.attributes.consumer: bar) AND (alert.attributes.alertTypeId: myType AND alert.attributes.consumer: myApp))"` ); }); diff --git a/x-pack/plugins/alerting/server/application/rule/methods/aggregate/aggregate_rules.ts b/x-pack/plugins/alerting/server/application/rule/methods/aggregate/aggregate_rules.ts index edc9c360e2e331..307e27184ca7e2 100644 --- a/x-pack/plugins/alerting/server/application/rule/methods/aggregate/aggregate_rules.ts +++ b/x-pack/plugins/alerting/server/application/rule/methods/aggregate/aggregate_rules.ts @@ -54,7 +54,7 @@ export async function aggregateRules>( const consumersFilter = buildConsumersFilter(consumers); const combinedFilters = combineFilters( [filterKueryNode, ruleTypeIdsFilter, consumersFilter], - 'or' + 'and' ); const { aggregations } = await findRulesSo({ From e0aff9576b940849dbaa7a387f09e57788d462c7 Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Sun, 13 Oct 2024 14:32:15 +0300 Subject: [PATCH 088/106] Fix search strategy empty response --- .../server/search_strategy/search_strategy.test.ts | 1 + .../rule_registry/server/search_strategy/search_strategy.ts | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/rule_registry/server/search_strategy/search_strategy.test.ts b/x-pack/plugins/rule_registry/server/search_strategy/search_strategy.test.ts index 5073bcd4d95bd8..294553d4ef2bb2 100644 --- a/x-pack/plugins/rule_registry/server/search_strategy/search_strategy.test.ts +++ b/x-pack/plugins/rule_registry/server/search_strategy/search_strategy.test.ts @@ -165,6 +165,7 @@ describe('ruleRegistrySearchStrategyProvider()', () => { }, "rawResponse": Object { "hits": Object { + "hits": Array [], "total": 0, }, }, diff --git a/x-pack/plugins/rule_registry/server/search_strategy/search_strategy.ts b/x-pack/plugins/rule_registry/server/search_strategy/search_strategy.ts index f74e27866da4b2..2ecc15f6be2d3c 100644 --- a/x-pack/plugins/rule_registry/server/search_strategy/search_strategy.ts +++ b/x-pack/plugins/rule_registry/server/search_strategy/search_strategy.ts @@ -31,7 +31,9 @@ import { getRuleTypeIdsFilter } from '../lib/get_rule_type_ids_filter'; import { getConsumersFilter } from '../lib/get_consumers_filter'; export const EMPTY_RESPONSE: RuleRegistrySearchResponse = { - rawResponse: { hits: { total: 0 } } as RuleRegistrySearchResponse['rawResponse'], + rawResponse: { + hits: { total: 0, hits: [] }, + } as unknown as RuleRegistrySearchResponse['rawResponse'], }; export const RULE_SEARCH_STRATEGY_NAME = 'privateRuleRegistryAlertsSearchStrategy'; From 5ca68f469ecb4b27dc7b95c1fee9a0634f07f2a7 Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Mon, 14 Oct 2024 11:54:46 +0300 Subject: [PATCH 089/106] Make the stack alerts table work with the new changes --- .../src/components/alerts_grouping.test.tsx | 2 + .../src/rule_types/stack_rules.ts | 2 + ...rting_authorization_client_factory.test.ts | 2 +- .../observability/common/constants.ts | 6 +- .../public/application/lib/search_filters.ts | 10 +- .../components/stack_alerts_page.tsx | 155 ++++++++++++++---- .../hooks/use_rule_type_ids_by_feature_id.ts | 6 +- .../sections/alerts_search_bar/constants.ts | 5 +- .../url_synced_alerts_search_bar.tsx | 36 ++-- .../alerts_table/alerts_table_state.test.tsx | 10 ++ .../alerts_table/alerts_table_state.tsx | 2 +- .../sections/alerts_table/constants.ts | 8 +- 12 files changed, 179 insertions(+), 65 deletions(-) diff --git a/packages/kbn-alerts-grouping/src/components/alerts_grouping.test.tsx b/packages/kbn-alerts-grouping/src/components/alerts_grouping.test.tsx index 9bcf5af59fa3c7..0137953b2313c8 100644 --- a/packages/kbn-alerts-grouping/src/components/alerts_grouping.test.tsx +++ b/packages/kbn-alerts-grouping/src/components/alerts_grouping.test.tsx @@ -24,6 +24,7 @@ import { useAlertsGroupingState } from '../contexts/alerts_grouping_context'; import { I18nProvider } from '@kbn/i18n-react'; import { mockRuleTypeIds, + mockConsumers, mockDate, mockGroupingProps, mockGroupingId, @@ -147,6 +148,7 @@ describe('AlertsGrouping', () => { params: { aggregations: {}, ruleTypeIds: mockRuleTypeIds, + consumers: mockConsumers, groupByField: 'kibana.alert.rule.name', filters: [ { diff --git a/packages/kbn-rule-data-utils/src/rule_types/stack_rules.ts b/packages/kbn-rule-data-utils/src/rule_types/stack_rules.ts index b5c6ed8213eff5..c01ed834a4b894 100644 --- a/packages/kbn-rule-data-utils/src/rule_types/stack_rules.ts +++ b/packages/kbn-rule-data-utils/src/rule_types/stack_rules.ts @@ -10,3 +10,5 @@ export const STACK_ALERTS_FEATURE_ID = 'stackAlerts'; export const ES_QUERY_ID = '.es-query'; export const ML_ANOMALY_DETECTION_RULE_TYPE_ID = 'xpack.ml.anomaly_detection_alert'; + +export const STACK_RULE_TYPE_IDS = [ES_QUERY_ID, ML_ANOMALY_DETECTION_RULE_TYPE_ID]; diff --git a/x-pack/plugins/alerting/server/alerting_authorization_client_factory.test.ts b/x-pack/plugins/alerting/server/alerting_authorization_client_factory.test.ts index 1f477a840ce4ad..f29b7acb8eee3c 100644 --- a/x-pack/plugins/alerting/server/alerting_authorization_client_factory.test.ts +++ b/x-pack/plugins/alerting/server/alerting_authorization_client_factory.test.ts @@ -15,7 +15,7 @@ import { featuresPluginMock } from '@kbn/features-plugin/server/mocks'; jest.mock('./authorization/alerting_authorization'); -describe('setAlertsToUntracked()', () => { +describe('AlertingAuthorizationClientFactory', () => { const features = featuresPluginMock.createStart(); const securityPluginStart = securityMock.createStart(); const alertingAuthorizationClientFactoryParams: jest.Mocked = diff --git a/x-pack/plugins/observability_solution/observability/common/constants.ts b/x-pack/plugins/observability_solution/observability/common/constants.ts index d948ffe60a7ed4..97ec9c224b35e8 100644 --- a/x-pack/plugins/observability_solution/observability/common/constants.ts +++ b/x-pack/plugins/observability_solution/observability/common/constants.ts @@ -7,8 +7,7 @@ import { AlertConsumers, - ES_QUERY_ID, - ML_ANOMALY_DETECTION_RULE_TYPE_ID, + STACK_RULE_TYPE_IDS, OBSERVABILITY_RULE_TYPE_IDS, } from '@kbn/rule-data-utils'; import type { ValidFeatureId } from '@kbn/rule-data-utils'; @@ -38,6 +37,5 @@ export const EventsAsUnit = 'events'; export const OBSERVABILITY_RULE_TYPE_IDS_WITH_STACK = [ ...OBSERVABILITY_RULE_TYPE_IDS, - ES_QUERY_ID, - ML_ANOMALY_DETECTION_RULE_TYPE_ID, + ...STACK_RULE_TYPE_IDS, ]; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/search_filters.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/search_filters.ts index 31f7175904526d..bc57a1736e86df 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/search_filters.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/search_filters.ts @@ -18,7 +18,7 @@ const $state = { }; export type AlertsFeatureIdsFilter = PhrasesFilter & { - meta: PhrasesFilter['meta'] & { ruleTypeIds: string[] }; + meta: PhrasesFilter['meta'] & { ruleTypeIds: string[]; consumers: string[] }; }; /** @@ -68,6 +68,7 @@ export const createMatchPhrasesFilter = ( params: values, value: undefined, ruleTypeIds: [], + consumers: [], }, $state, query: { @@ -91,8 +92,13 @@ export const createRuleProducerFilter = (producer: AlertConsumers) => /** * Creates a match_phrase filter targeted to filtering alerts by rule type ids */ -export const createRuleTypesFilter = (ruleTypeIds: string[], alias: string) => { +export const createRuleTypesFilter = ( + ruleTypeIds: string[], + consumers: string[], + alias: string +) => { const filter = createMatchPhrasesFilter(ALERT_RULE_TYPE_ID, ruleTypeIds, alias); filter.meta.ruleTypeIds = ruleTypeIds; + filter.meta.consumers = consumers; return filter; }; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_page/components/stack_alerts_page.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_page/components/stack_alerts_page.tsx index d78253ae4ed865..f5a39ab5ac0d3d 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_page/components/stack_alerts_page.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_page/components/stack_alerts_page.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import React, { lazy, Suspense, useEffect, useMemo, useState } from 'react'; +import React, { lazy, Suspense, useCallback, useEffect, useMemo, useState } from 'react'; import { i18n } from '@kbn/i18n'; import { EuiBetaBadge, @@ -24,7 +24,7 @@ import { isSiemRuleType, } from '@kbn/rule-data-utils'; import { QueryClientProvider } from '@tanstack/react-query'; -import { BoolQuery } from '@kbn/es-query'; +import { BoolQuery, Filter } from '@kbn/es-query'; import { FormattedMessage } from '@kbn/i18n-react'; import { ALERTS_PAGE_ID } from '../../../../common/constants'; import { QuickFiltersMenuItem } from '../../alerts_search_bar/quick_filters'; @@ -41,12 +41,21 @@ import { Provider, } from '../../alerts_search_bar/use_alert_search_bar_state_container'; import { getCurrentDocTitle } from '../../../lib/doc_title'; -import { createMatchPhraseFilter, createRuleTypesFilter } from '../../../lib/search_filters'; +import { + AlertsFeatureIdsFilter, + createMatchPhraseFilter, + createRuleTypesFilter, +} from '../../../lib/search_filters'; import { useLoadRuleTypesQuery } from '../../../hooks/use_load_rule_types_query'; import { nonNullable } from '../../../../../common/utils'; -import { useRuleTypeIdsByFeatureId } from '../hooks/use_rule_type_ids_by_feature_id'; +import { + RuleTypeIdsByFeatureId, + useRuleTypeIdsByFeatureId, +} from '../hooks/use_rule_type_ids_by_feature_id'; import { TECH_PREVIEW_DESCRIPTION, TECH_PREVIEW_LABEL } from '../../translations'; import { AlertsTableSupportedConsumers } from '../../alerts_table/types'; +import { NON_SIEM_CONSUMERS } from '../../alerts_search_bar/constants'; + const AlertsTable = lazy(() => import('../../alerts_table/alerts_table_state')); /** @@ -56,7 +65,7 @@ export const StackAlertsPage = () => { return ( - + ); @@ -70,15 +79,11 @@ const getFeatureFilterLabel = (featureName: string) => }, }); -const PageContent = () => { +const PageContentWrapperComponent: React.FC = () => { const { chrome: { docTitle }, setBreadcrumbs, - alertsTableConfigurationRegistry, } = useKibana().services; - const [esQuery, setEsQuery] = useState({ bool: {} } as { bool: BoolQuery }); - const [ruleTypeIds, setRuleTypeIds] = useState([]); - const ruleStats = useRuleStats({ ruleTypeIds }); const { ruleTypesState: { data: ruleTypesIndex, initialLoad: isInitialLoadingRuleTypes }, @@ -86,31 +91,110 @@ const PageContent = () => { } = useLoadRuleTypesQuery({ filteredRuleTypes: [] }); const ruleTypeIdsByFeatureId = useRuleTypeIdsByFeatureId(ruleTypesIndex); - const filteringBySolution = ruleTypeIds.length > 0; - const browsingSiem = filteringBySolution && ruleTypeIds.every(isSiemRuleType); + + useEffect(() => { + setBreadcrumbs([getAlertingSectionBreadcrumb('alerts')]); + docTitle.change(getCurrentDocTitle('alerts')); + }, [docTitle, setBreadcrumbs]); + + return !isInitialLoadingRuleTypes ? ( + + ) : null; +}; + +const PageContentWrapper = React.memo(PageContentWrapperComponent); + +interface PageContentProps { + isLoading: boolean; + authorizedToReadAnyRules: boolean; + ruleTypeIdsByFeatureId: RuleTypeIdsByFeatureId; +} + +const PageContentComponent: React.FC = ({ + isLoading, + authorizedToReadAnyRules, + ruleTypeIdsByFeatureId, +}) => { + const { alertsTableConfigurationRegistry } = useKibana().services; const ruleTypeIdsByFeatureIdEntries = Object.entries(ruleTypeIdsByFeatureId); + const [esQuery, setEsQuery] = useState({ bool: {} } as { bool: BoolQuery }); + const [ruleTypeIds, setRuleTypeIds] = useState(() => + getInitialRuleTypeIds(ruleTypeIdsByFeatureId) + ); + + const [consumers, setConsumers] = useState(NON_SIEM_CONSUMERS); + + const [selectedFilters, setSelectedFilters] = useState([]); + const ruleStats = useRuleStats({ ruleTypeIds }); + const isFilteringSecurityRules = ruleTypeIds.every(isSiemRuleType); + + const onFilterSelected = useCallback( + (filters: Filter[]) => { + const newRuleTypeIds = [ + ...new Set( + filters + .flatMap((ruleTypeId) => (ruleTypeId as AlertsFeatureIdsFilter).meta.ruleTypeIds) + .filter(nonNullable) + ), + ]; + + const newConsumers = [ + ...new Set( + filters + .flatMap((ruleTypeId) => (ruleTypeId as AlertsFeatureIdsFilter).meta.consumers) + .filter(nonNullable) + ), + ]; + + setSelectedFilters(filters as AlertsFeatureIdsFilter[]); + + if (newRuleTypeIds.length > 0) { + setRuleTypeIds(newRuleTypeIds); + setConsumers(newConsumers); + return; + } + + setRuleTypeIds(getInitialRuleTypeIds(ruleTypeIdsByFeatureId)); + setConsumers(NON_SIEM_CONSUMERS); + }, + [ruleTypeIdsByFeatureId] + ); + const quickFilters = useMemo(() => { const filters: QuickFiltersMenuItem[] = []; if (ruleTypeIdsByFeatureIdEntries.length > 0) { filters.push( ...ruleTypeIdsByFeatureIdEntries - .map(([featureId, _ruleTypeIds]) => { - const producerData = alertProducersData[featureId as AlertsTableSupportedConsumers]; + .map(([consumer, _ruleTypeIds]) => { + const producerData = alertProducersData[consumer as AlertsTableSupportedConsumers]; if (!producerData) { return null; } const filterLabel = getFeatureFilterLabel(producerData.displayName); - const disabled = - filteringBySolution && featureId === AlertConsumers.SIEM - ? !browsingSiem - : browsingSiem; + const shouldDisable = + (isFilteringSecurityRules && consumer !== AlertConsumers.SIEM) || + (!isFilteringSecurityRules && consumer === AlertConsumers.SIEM); + + const isQuickFilterSelected = _ruleTypeIds.every((ruleTypeId) => + ruleTypeIds.includes(ruleTypeId) + ); + + const disabled = selectedFilters.length > 0 && (shouldDisable || isQuickFilterSelected); return { name: filterLabel, icon: producerData.icon, - filter: createRuleTypesFilter(_ruleTypeIds, filterLabel), + filter: createRuleTypesFilter( + _ruleTypeIds, + producerData.subFeatureIds ?? [consumer], + filterLabel + ), disabled, }; }) @@ -129,18 +213,12 @@ const PageContent = () => { })), }); return filters; - }, [browsingSiem, filteringBySolution, ruleTypeIdsByFeatureIdEntries]); - - const tableConfigurationId = useMemo( - // TODO in preparation for using solution-specific configurations - () => ALERT_TABLE_GLOBAL_CONFIG_ID, - [] - ); - - useEffect(() => { - setBreadcrumbs([getAlertingSectionBreadcrumb('alerts')]); - docTitle.change(getCurrentDocTitle('alerts')); - }, [docTitle, setBreadcrumbs]); + }, [ + isFilteringSecurityRules, + ruleTypeIds, + ruleTypeIdsByFeatureIdEntries, + selectedFilters.length, + ]); return ( <> @@ -165,7 +243,7 @@ const PageContent = () => { rightSideItems={ruleStats} /> - {!isInitialLoadingRuleTypes && !authorizedToReadAnyRules ? ( + {!isLoading && !authorizedToReadAnyRules ? ( ) : ( @@ -175,8 +253,8 @@ const PageContent = () => { showFilterControls showFilterBar quickFilters={quickFilters} - onRuleTypesChanged={setRuleTypeIds} onEsQueryChange={setEsQuery} + onFilterSelected={onFilterSelected} /> }> { // columns alignment from breaking after a change in the number of columns key={ruleTypeIds.join()} id="stack-alerts-page-table" - configurationId={tableConfigurationId} + configurationId={ALERT_TABLE_GLOBAL_CONFIG_ID} alertsTableConfigurationRegistry={alertsTableConfigurationRegistry} ruleTypeIds={ruleTypeIds} + consumers={consumers} query={esQuery} showAlertStatusWithFlapping initialPageSize={20} @@ -197,3 +276,11 @@ const PageContent = () => { ); }; + +const PageContent = React.memo(PageContentComponent); + +const getInitialRuleTypeIds = (ruleTypeIdsByFeatureId: RuleTypeIdsByFeatureId): string[] => + Object.entries(ruleTypeIdsByFeatureId) + .filter(([featureId]) => featureId !== AlertConsumers.SIEM) + .map(([_, _ruleTypeIds]) => _ruleTypeIds) + .flat(); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_page/hooks/use_rule_type_ids_by_feature_id.ts b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_page/hooks/use_rule_type_ids_by_feature_id.ts index cc80d73b1fcbc0..1380f9655d479a 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_page/hooks/use_rule_type_ids_by_feature_id.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_page/hooks/use_rule_type_ids_by_feature_id.ts @@ -12,7 +12,7 @@ import { observabilityFeatureIds, stackFeatureIds } from '../../alerts_table/con import { MULTI_CONSUMER_RULE_TYPE_IDS } from '../../../constants'; import { RuleTypeIndex } from '../../../../types'; -type RuleTypeIdsByFeatureId = Partial< +export type RuleTypeIdsByFeatureId = Partial< Record< | typeof AlertConsumers.SIEM | typeof AlertConsumers.OBSERVABILITY @@ -22,13 +22,15 @@ type RuleTypeIdsByFeatureId = Partial< > >; +const EMPTY_OBJECT = {}; + /** * Groups all rule type ids under their respective feature id */ export const useRuleTypeIdsByFeatureId = (ruleTypesIndex: RuleTypeIndex) => useMemo((): RuleTypeIdsByFeatureId => { if (!ruleTypesIndex?.size) { - return {}; + return EMPTY_OBJECT; } const map = Array.from(ruleTypesIndex.entries()).reduce>>( diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_search_bar/constants.ts b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_search_bar/constants.ts index 408d4d17147434..35399664000543 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_search_bar/constants.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_search_bar/constants.ts @@ -10,5 +10,6 @@ import { AlertConsumers } from '@kbn/rule-data-utils'; export const NO_INDEX_PATTERNS: DataView[] = []; export const ALERTS_SEARCH_BAR_PARAMS_URL_STORAGE_KEY = 'searchBarParams'; -export const ALL_FEATURE_IDS = Object.values(AlertConsumers); -export const NON_SIEM_FEATURE_IDS = ALL_FEATURE_IDS.filter((fid) => fid !== AlertConsumers.SIEM); +export const NON_SIEM_CONSUMERS = Object.values(AlertConsumers).filter( + (fid) => fid !== AlertConsumers.SIEM +); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_search_bar/url_synced_alerts_search_bar.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_search_bar/url_synced_alerts_search_bar.tsx index 529d6c3f7c3ad8..175d9538918e76 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_search_bar/url_synced_alerts_search_bar.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_search_bar/url_synced_alerts_search_bar.tsx @@ -11,13 +11,11 @@ import { i18n } from '@kbn/i18n'; import { AlertFilterControls } from '@kbn/alerts-ui-shared/src/alert_filter_controls'; import { ControlGroupRenderer } from '@kbn/controls-plugin/public'; import { Storage } from '@kbn/kibana-utils-plugin/public'; -import { AlertsFeatureIdsFilter } from '../../lib/search_filters'; import { useKibana } from '../../..'; import { useAlertSearchBarStateContainer } from './use_alert_search_bar_state_container'; import { ALERTS_SEARCH_BAR_PARAMS_URL_STORAGE_KEY } from './constants'; import { AlertsSearchBarProps } from './types'; import AlertsSearchBar from './alerts_search_bar'; -import { nonNullable } from '../../../../common/utils'; import { buildEsQuery } from './build_es_query'; const INVALID_QUERY_STRING_TOAST_TITLE = i18n.translate( @@ -34,16 +32,17 @@ export interface UrlSyncedAlertsSearchBarProps > { showFilterControls?: boolean; onEsQueryChange: (esQuery: { bool: BoolQuery }) => void; - onRuleTypesChanged?: (ruleTypeIds: string[]) => void; + onFilterSelected?: (filters: Filter[]) => void; } /** * An abstraction over AlertsSearchBar that syncs the query state with the url */ export const UrlSyncedAlertsSearchBar = ({ + ruleTypeIds, showFilterControls = false, onEsQueryChange, - onRuleTypesChanged, + onFilterSelected, ...rest }: UrlSyncedAlertsSearchBarProps) => { const { @@ -100,13 +99,25 @@ export const UrlSyncedAlertsSearchBar = ({ filters: [...filters, ...controlFilters], }) ); + + onFilterSelected?.(filters); } catch (error) { toasts.addError(error, { title: INVALID_QUERY_STRING_TOAST_TITLE, }); onKueryChange(''); } - }, [controlFilters, filters, kuery, onEsQueryChange, onKueryChange, rangeFrom, rangeTo, toasts]); + }, [ + controlFilters, + filters, + kuery, + onEsQueryChange, + onFilterSelected, + onKueryChange, + rangeFrom, + rangeTo, + toasts, + ]); const onQueryChange = useCallback>( ({ query, dateRange }) => { @@ -119,18 +130,6 @@ export const UrlSyncedAlertsSearchBar = ({ [onKueryChange, onRangeFromChange, onRangeToChange, setSavedQuery, timeFilterService] ); - const onFiltersUpdated = (updatedFilters: Filter[]) => { - onRuleTypesChanged?.([ - ...new Set( - updatedFilters - .flatMap((ruleTypeId) => (ruleTypeId as AlertsFeatureIdsFilter).meta.ruleTypeIds) - .filter(nonNullable) - ), - ]); - - onFiltersChange(updatedFilters); - }; - const filterControlsStorageKey = useMemo( () => ['alertsSearchBar', spaceId, 'filterControls'].filter(Boolean).join('.'), [spaceId] @@ -144,10 +143,11 @@ export const UrlSyncedAlertsSearchBar = ({ query={kuery} onQuerySubmit={onQueryChange} filters={filters} - onFiltersUpdated={onFiltersUpdated} + onFiltersUpdated={onFiltersChange} savedQuery={savedQuery} onSavedQueryUpdated={setSavedQuery} onClearSavedQuery={clearSavedQuery} + ruleTypeIds={ruleTypeIds} {...rest} /> {showFilterControls && ( diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/alerts_table_state.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/alerts_table_state.test.tsx index 99ed78b7fc80cf..9db58d26d92517 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/alerts_table_state.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/alerts_table_state.test.tsx @@ -959,6 +959,16 @@ describe('AlertsTableState', () => { expect(result.getByTestId('alertsStateTableEmptyState')).toBeTruthy(); }); + it('should render an empty screen when the data are undefined', async () => { + mockUseSearchAlertsQuery.mockReturnValue({ + data: undefined, + refetch: refetchMock, + }); + + const result = render(); + expect(result.getByTestId('alertsStateTableEmptyState')).toBeTruthy(); + }); + describe('inspect button', () => { it('should hide the inspect button by default', () => { render(); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/alerts_table_state.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/alerts_table_state.tsx index 3172674f46370b..93bb4f18dfe9a8 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/alerts_table_state.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/alerts_table_state.tsx @@ -583,7 +583,7 @@ const AlertsTableStateWithQueryProvider = memo( return ( - {!isLoading && alertsCount === 0 && ( + {!isLoading && alertsCount <= 0 && ( = { From cfdb8a9c90d070105149bc46b3cfb7dbe68cefdc Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Tue, 15 Oct 2024 15:20:52 +0300 Subject: [PATCH 090/106] Fix merging conflicts --- .../rule/methods/rule_types/rule_types.ts | 3 +- .../routes/rule/apis/list_types/rule_types.ts | 2 +- .../transform_rule_types_response/v1.ts | 4 +- .../alerting/server/rules_client/types.ts | 4 -- x-pack/plugins/event_log/README.md | 57 ++++++++++--------- 5 files changed, 34 insertions(+), 36 deletions(-) diff --git a/x-pack/plugins/alerting/server/application/rule/methods/rule_types/rule_types.ts b/x-pack/plugins/alerting/server/application/rule/methods/rule_types/rule_types.ts index 264a31beed7d51..4bcb6fdece3e24 100644 --- a/x-pack/plugins/alerting/server/application/rule/methods/rule_types/rule_types.ts +++ b/x-pack/plugins/alerting/server/application/rule/methods/rule_types/rule_types.ts @@ -8,9 +8,10 @@ import { AlertingAuthorizationEntity, ReadOperations, + RegistryAlertTypeWithAuth, WriteOperations, } from '../../../../authorization'; -import { RegistryAlertTypeWithAuth, RulesClientContext } from '../../../../rules_client/types'; +import { RulesClientContext } from '../../../../rules_client/types'; export async function listRuleTypes( context: RulesClientContext diff --git a/x-pack/plugins/alerting/server/routes/rule/apis/list_types/rule_types.ts b/x-pack/plugins/alerting/server/routes/rule/apis/list_types/rule_types.ts index d6f2ffbe9af0c2..cf19a5aab15549 100644 --- a/x-pack/plugins/alerting/server/routes/rule/apis/list_types/rule_types.ts +++ b/x-pack/plugins/alerting/server/routes/rule/apis/list_types/rule_types.ts @@ -28,7 +28,7 @@ export const ruleTypesRoute = ( }, router.handleLegacyErrors( verifyAccessAndContext(licenseState, async function (context, req, res) { - const rulesClient = (await context.alerting).getRulesClient(); + const rulesClient = await (await context.alerting).getRulesClient(); const ruleTypes = await rulesClient.listRuleTypes(); const responseBody: TypesRulesResponseBodyV1 = transformRuleTypesResponseV1(ruleTypes); diff --git a/x-pack/plugins/alerting/server/routes/rule/apis/list_types/transforms/transform_rule_types_response/v1.ts b/x-pack/plugins/alerting/server/routes/rule/apis/list_types/transforms/transform_rule_types_response/v1.ts index 54a5874331c86e..e331fd9133332d 100644 --- a/x-pack/plugins/alerting/server/routes/rule/apis/list_types/transforms/transform_rule_types_response/v1.ts +++ b/x-pack/plugins/alerting/server/routes/rule/apis/list_types/transforms/transform_rule_types_response/v1.ts @@ -10,9 +10,9 @@ import { RegistryAlertTypeWithAuth } from '../../../../../../authorization'; import type { TypesRulesResponseBodyV1 } from '../../../../../../../common/routes/rule/apis/list_types'; export const transformRuleTypesResponse = ( - ruleTypes: Set + ruleTypes: RegistryAlertTypeWithAuth[] ): TypesRulesResponseBodyV1 => { - return Array.from(ruleTypes).map((ruleType: RegistryAlertTypeWithAuth) => { + return ruleTypes.map((ruleType: RegistryAlertTypeWithAuth) => { return { ...(ruleType.actionGroups ? { action_groups: ruleType.actionGroups } : {}), ...(ruleType.actionVariables ? { action_variables: ruleType.actionVariables } : {}), diff --git a/x-pack/plugins/alerting/server/rules_client/types.ts b/x-pack/plugins/alerting/server/rules_client/types.ts index 9a701e1c95c81c..afcb4e1037a6c0 100644 --- a/x-pack/plugins/alerting/server/rules_client/types.ts +++ b/x-pack/plugins/alerting/server/rules_client/types.ts @@ -23,7 +23,6 @@ import { TaskManagerStartContract } from '@kbn/task-manager-plugin/server'; import { IEventLogClient, IEventLogger } from '@kbn/event-log-plugin/server'; import { AuditLogger } from '@kbn/security-plugin/server'; import { DistributiveOmit } from '@elastic/eui'; -import { RegistryRuleType } from '../rule_type_registry'; import { RuleTypeRegistry, IntervalSchedule, @@ -108,9 +107,6 @@ export type NormalizedAlertActionWithGeneratedValues = | NormalizedAlertDefaultActionWithGeneratedValues | NormalizedAlertSystemActionWithGeneratedValues; -export interface RegistryAlertTypeWithAuth extends RegistryRuleType { - authorizedConsumers: string[]; -} export type CreateAPIKeyResult = | { apiKeysEnabled: false } | { apiKeysEnabled: true; result: SecurityPluginGrantAPIKeyResult }; diff --git a/x-pack/plugins/event_log/README.md b/x-pack/plugins/event_log/README.md index ae2117fcd8ad4f..eb80f39c71c245 100644 --- a/x-pack/plugins/event_log/README.md +++ b/x-pack/plugins/event_log/README.md @@ -45,7 +45,8 @@ alias used to deal with rolled over indices from ILM. With the data stream, there's a little less set up, and the bulk writing is slightly different. The default data stream / alias name is `.kibana-event-log-ds`. -To search across all versions' event logs, use `.kibana-event-log-*`; +To search across all versions' event logs, use `rrrrrrrrrrrrrrrrrrrrr + it will search over data streams and aliases as expected. The event log indices are controlled by ILM. The ILM policy is initially created @@ -249,21 +250,21 @@ Collects event information from the event log for the selected saved object by t Params: -|Property|Description|Type| -|---|---|---| -|type|The type of the saved object whose events you're trying to get.|string| -|id|The id of the saved object.|string| +| Property | Description | Type | +| -------- | --------------------------------------------------------------- | ------ | +| type | The type of the saved object whose events you're trying to get. | string | +| id | The id of the saved object. | string | Query: -|Property|Description|Type| -|---|---|---| -|page|The page number.|number| -|per_page|The number of events to return per page.|number| -|sort|Array of sort fields and order for the response. Each sort object specifies `sort_field` and `sort_order` where `sort_order` is either `asc` or `desc`.|object| -|filter|A KQL string that you filter with an attribute from the event. It should look like `event.action:(execute)`.|string| -|start|The date to start looking for saved object events in the event log. Either an ISO date string, or a duration string that indicates the time since now.|string| -|end|The date to stop looking for saved object events in the event log. Either an ISO date string, or a duration string that indicates the time since now.|string| +| Property | Description | Type | +| -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ | +| page | The page number. | number | +| per_page | The number of events to return per page. | number | +| sort | Array of sort fields and order for the response. Each sort object specifies `sort_field` and `sort_order` where `sort_order` is either `asc` or `desc`. | object | +| filter | A KQL string that you filter with an attribute from the event. It should look like `event.action:(execute)`. | string | +| start | The date to start looking for saved object events in the event log. Either an ISO date string, or a duration string that indicates the time since now. | string | +| end | The date to stop looking for saved object events in the event log. Either an ISO date string, or a duration string that indicates the time since now. | string | Response body: @@ -275,27 +276,27 @@ Collects event information from the event log for the selected saved object by t Params: -|Property|Description|Type| -|---|---|---| -|type|The type of the saved object whose events you're trying to get.|string| +| Property | Description | Type | +| -------- | --------------------------------------------------------------- | ------ | +| type | The type of the saved object whose events you're trying to get. | string | Query: -|Property|Description|Type| -|---|---|---| -|page|The page number.|number| -|per_page|The number of events to return per page.|number| -|sort|Array of sort fields and order for the response. Each sort object specifies `sort_field` and `sort_order` where `sort_order` is either `asc` or `desc`.|object| -|filter|A KQL string that you filter with an attribute from the event. It should look like `event.action:(execute)`.|string| -|start|The date to start looking for saved object events in the event log. Either an ISO date string, or a duration string that indicates the time since now.|string| -|end|The date to stop looking for saved object events in the event log. Either an ISO date string, or a duration string that indicates the time since now.|string| +| Property | Description | Type | +| -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ | +| page | The page number. | number | +| per_page | The number of events to return per page. | number | +| sort | Array of sort fields and order for the response. Each sort object specifies `sort_field` and `sort_order` where `sort_order` is either `asc` or `desc`. | object | +| filter | A KQL string that you filter with an attribute from the event. It should look like `event.action:(execute)`. | string | +| start | The date to start looking for saved object events in the event log. Either an ISO date string, or a duration string that indicates the time since now. | string | +| end | The date to stop looking for saved object events in the event log. Either an ISO date string, or a duration string that indicates the time since now. | string | Request Body: -|Property|Description|Type| -|---|---|---| -|ids|The array ids of the saved object.|string array| -|legacyIds|The array legacy ids of the saved object. This filter applies to the rules creted in Kibana versions before 8.0.0.|string array| +| Property | Description | Type | +| --------- | ------------------------------------------------------------------------------------------------------------------ | ------------ | +| ids | The array ids of the saved object. | string array | +| legacyIds | The array legacy ids of the saved object. This filter applies to the rules creted in Kibana versions before 8.0.0. | string array | Response body: From ef72303b876cf29f9947e64b8306a65c2ec4988d Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Tue, 15 Oct 2024 19:23:51 +0300 Subject: [PATCH 091/106] Initialize auth class without auth for 404 space errors --- .../alerting_authorization_client_factory.ts | 2 +- .../alerting_authorization.test.ts | 40 +++++++++++-------- .../authorization/alerting_authorization.ts | 2 +- x-pack/plugins/rule_registry/server/plugin.ts | 4 +- 4 files changed, 27 insertions(+), 21 deletions(-) diff --git a/x-pack/plugins/alerting/server/alerting_authorization_client_factory.ts b/x-pack/plugins/alerting/server/alerting_authorization_client_factory.ts index de18a232c84ed9..8c5a772501f2bd 100644 --- a/x-pack/plugins/alerting/server/alerting_authorization_client_factory.ts +++ b/x-pack/plugins/alerting/server/alerting_authorization_client_factory.ts @@ -38,7 +38,7 @@ export class AlertingAuthorizationClientFactory { public async create(request: KibanaRequest): Promise { this.validateInitialization(); - return await AlertingAuthorization.create({ + return AlertingAuthorization.create({ authorization: this.options.securityPluginStart?.authz, request, getSpace: this.options.getSpace, diff --git a/x-pack/plugins/alerting/server/authorization/alerting_authorization.test.ts b/x-pack/plugins/alerting/server/authorization/alerting_authorization.test.ts index 296b451990d5d0..5e7a19a79dcc95 100644 --- a/x-pack/plugins/alerting/server/authorization/alerting_authorization.test.ts +++ b/x-pack/plugins/alerting/server/authorization/alerting_authorization.test.ts @@ -391,25 +391,31 @@ describe('AlertingAuthorization', () => { await expect(authPromise).rejects.toThrow(); }); - it('construct the AlertingAuthorization with empty features if the error is boom and 403', async () => { - getSpace.mockRejectedValue( - new Boom.Boom('Server error', { statusCode: 403, message: 'my error message' }) - ); + it.each([403, 404])( + `construct the AlertingAuthorization with empty features if the error is boom and %s`, + async (errorStatusCode: number) => { + getSpace.mockRejectedValue( + new Boom.Boom('Server error', { + statusCode: errorStatusCode, + message: 'my error message', + }) + ); - const auth = await AlertingAuthorization.create({ - request, - ruleTypeRegistry, - getSpaceId, - features, - getSpace, - authorization: securityStart.authz, - }); + const auth = await AlertingAuthorization.create({ + request, + ruleTypeRegistry, + getSpaceId, + features, + getSpace, + authorization: securityStart.authz, + }); - // @ts-expect-error: allRegisteredConsumers is a private method of the auth class - expect(auth.ruleTypesConsumersMap).toMatchInlineSnapshot(`Map {}`); - // @ts-expect-error: allRegisteredConsumers is a private method of the auth class - expect(auth.allRegisteredConsumers).toMatchInlineSnapshot(`Set {}`); - }); + // @ts-expect-error: allRegisteredConsumers is a private method of the auth class + expect(auth.ruleTypesConsumersMap).toMatchInlineSnapshot(`Map {}`); + // @ts-expect-error: allRegisteredConsumers is a private method of the auth class + expect(auth.allRegisteredConsumers).toMatchInlineSnapshot(`Set {}`); + } + ); it('throws an error if the error is boom but not 403', async () => { expect.assertions(1); diff --git a/x-pack/plugins/alerting/server/authorization/alerting_authorization.ts b/x-pack/plugins/alerting/server/authorization/alerting_authorization.ts index 76c432a95706b7..6365dd0198e6de 100644 --- a/x-pack/plugins/alerting/server/authorization/alerting_authorization.ts +++ b/x-pack/plugins/alerting/server/authorization/alerting_authorization.ts @@ -133,7 +133,7 @@ export class AlertingAuthorization { try { maybeSpace = await getSpace(request); } catch (error) { - if (Boom.isBoom(error) && error.output.statusCode === 403) { + if (Boom.isBoom(error) && [403, 404].includes(error.output.statusCode)) { return new AlertingAuthorization({ request, authorization, diff --git a/x-pack/plugins/rule_registry/server/plugin.ts b/x-pack/plugins/rule_registry/server/plugin.ts index 36b8d242151e55..d4bcc500f8037f 100644 --- a/x-pack/plugins/rule_registry/server/plugin.ts +++ b/x-pack/plugins/rule_registry/server/plugin.ts @@ -165,7 +165,7 @@ export class RuleRegistryPlugin logger, esClient: core.elasticsearch.client.asInternalUser, // NOTE: Alerts share the authorization client with the alerting plugin - getAlertingAuthorization(request: KibanaRequest) { + async getAlertingAuthorization(request: KibanaRequest) { return plugins.alerting.getAlertingAuthorizationWithRequest(request); }, securityPluginSetup: security, @@ -175,7 +175,7 @@ export class RuleRegistryPlugin getAlertIndicesAlias: plugins.alerting.getAlertIndicesAlias, }); - const getRacClientWithRequest = (request: KibanaRequest) => { + const getRacClientWithRequest = async (request: KibanaRequest) => { return alertsClientFactory.create(request); }; From ffbf2508762920aeb47721662861362e098f2347 Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Tue, 15 Oct 2024 20:10:50 +0300 Subject: [PATCH 092/106] Fix tests --- .../hooks/alert_mute/use_get_muted_alerts.test.tsx | 2 +- .../sections/alerts_table/hooks/use_bulk_actions.test.tsx | 2 +- .../apps/observability/pages/alerts/custom_threshold.ts | 2 +- .../security_and_spaces/tests/basic/get_alerts_index.ts | 3 ++- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/alert_mute/use_get_muted_alerts.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/alert_mute/use_get_muted_alerts.test.tsx index 8d65532c5f10a4..96bee3d9979e3a 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/alert_mute/use_get_muted_alerts.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/alert_mute/use_get_muted_alerts.test.tsx @@ -40,7 +40,7 @@ describe('useGetMutedAlerts', () => { await waitFor(() => { expect(muteAlertInstanceSpy).toHaveBeenCalledWith( expect.anything(), - { ids: ruleIds }, + { ruleIds }, expect.any(AbortSignal) ); }); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_bulk_actions.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_bulk_actions.test.tsx index e03dd9aaffe6f5..ae6c35d3c9ae5b 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_bulk_actions.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_bulk_actions.test.tsx @@ -397,7 +397,7 @@ describe('bulk action hooks', () => { query: {}, casesConfig, refresh, - ruleTypeIds: ['siem'], + ruleTypeIds: ['siem.esqlRule'], }), { wrapper: appMockRender.AppWrapper, diff --git a/x-pack/test/observability_functional/apps/observability/pages/alerts/custom_threshold.ts b/x-pack/test/observability_functional/apps/observability/pages/alerts/custom_threshold.ts index 38d308a17e7b04..ec581fb0f21004 100644 --- a/x-pack/test/observability_functional/apps/observability/pages/alerts/custom_threshold.ts +++ b/x-pack/test/observability_functional/apps/observability/pages/alerts/custom_threshold.ts @@ -209,7 +209,7 @@ export default ({ getService }: FtrProviderContext) => { }); it('saved the rule correctly', async () => { - const { body: rules } = await supertest.get('/internal/alerting/rules/_find'); + const { body: rules } = await supertest.get('/api/alerting/rules/_find'); expect(rules.data.length).toEqual(1); expect(rules.data[0]).toEqual( diff --git a/x-pack/test/rule_registry/security_and_spaces/tests/basic/get_alerts_index.ts b/x-pack/test/rule_registry/security_and_spaces/tests/basic/get_alerts_index.ts index 4205d6671577b2..604cff34865d95 100644 --- a/x-pack/test/rule_registry/security_and_spaces/tests/basic/get_alerts_index.ts +++ b/x-pack/test/rule_registry/security_and_spaces/tests/basic/get_alerts_index.ts @@ -36,11 +36,12 @@ export default ({ getService }: FtrProviderContext) => { expectedStatusCode: number = 200 ) => { const resp = await supertestWithoutAuth - .get(`${getSpaceUrlPrefix(space)}${ALERTS_INDEX_URL}}`) + .get(`${getSpaceUrlPrefix(space)}${ALERTS_INDEX_URL}`) .query({ ruleTypeIds }) .auth(user.username, user.password) .set('kbn-xsrf', 'true') .expect(expectedStatusCode); + return resp.body.index_name as string[]; }; From 31af86cfc6958a6ed902b8df9c9734ce47ad9c1d Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Tue, 15 Oct 2024 23:53:17 +0300 Subject: [PATCH 093/106] Filiter also by the alerts consumer in o11y apps --- .../apm/public/components/app/alerts_overview/index.tsx | 2 +- .../infra/public/components/shared/alerts/alerts_overview.tsx | 4 ++-- .../hosts/components/tabs/alerts/alerts_tab_content.tsx | 4 ++-- .../embeddable/slo/alerts/components/slo_alerts_summary.tsx | 2 +- .../embeddable/slo/alerts/components/slo_alerts_table.tsx | 2 +- .../public/pages/slo_details/components/slo_detail_alerts.tsx | 2 +- .../monitor_details/monitor_alerts/monitor_detail_alerts.tsx | 2 +- 7 files changed, 9 insertions(+), 9 deletions(-) diff --git a/x-pack/plugins/observability_solution/apm/public/components/app/alerts_overview/index.tsx b/x-pack/plugins/observability_solution/apm/public/components/app/alerts_overview/index.tsx index 29e447faeac497..ab867180d95e3e 100644 --- a/x-pack/plugins/observability_solution/apm/public/components/app/alerts_overview/index.tsx +++ b/x-pack/plugins/observability_solution/apm/public/components/app/alerts_overview/index.tsx @@ -108,7 +108,7 @@ export function AlertsOverview() { id={'service-overview-alerts'} configurationId={AlertConsumers.OBSERVABILITY} ruleTypeIds={APM_RULE_TYPE_IDS} - consumers={[AlertConsumers.APM]} + consumers={[AlertConsumers.APM, AlertConsumers.ALERTS]} query={esQuery} showAlertStatusWithFlapping cellContext={{ observabilityRuleTypeRegistry }} diff --git a/x-pack/plugins/observability_solution/infra/public/components/shared/alerts/alerts_overview.tsx b/x-pack/plugins/observability_solution/infra/public/components/shared/alerts/alerts_overview.tsx index 6e0f5535f7e532..fe8678d72b7a4f 100644 --- a/x-pack/plugins/observability_solution/infra/public/components/shared/alerts/alerts_overview.tsx +++ b/x-pack/plugins/observability_solution/infra/public/components/shared/alerts/alerts_overview.tsx @@ -113,7 +113,7 @@ export const AlertsOverview = ({ { alertsTableConfigurationRegistry={alertsTableConfigurationRegistry} configurationId={AlertConsumers.OBSERVABILITY} ruleTypeIds={INFRA_RULE_TYPE_IDS} - consumers={[AlertConsumers.INFRASTRUCTURE]} + consumers={[AlertConsumers.INFRASTRUCTURE, AlertConsumers.ALERTS]} id={ALERTS_TABLE_ID} initialPageSize={ALERTS_PER_PAGE} query={alertsEsQueryByStatus} @@ -136,7 +136,7 @@ const MemoAlertSummaryWidget = React.memo( Date: Tue, 15 Oct 2024 23:53:59 +0300 Subject: [PATCH 094/106] Fix integration tests --- .../spaces_only/tests/alerting/group1/find_internal.ts | 1 + .../apps/observability/pages/rules_page.ts | 5 ++++- .../tests/basic/get_browser_fields_by_rule_type_ids.ts | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/find_internal.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/find_internal.ts index fd95788dfde2d8..01e2248831492f 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/find_internal.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/find_internal.ts @@ -152,6 +152,7 @@ export default function createFindTests({ getService }: FtrProviderContext) { await supertest .post(`${getUrlPrefix(Spaces.other.id)}/internal/alerting/rules/_find`) + .set('kbn-xsrf', 'foo') .send({ search: 'test.noop', search_fields: 'alertTypeId', diff --git a/x-pack/test/observability_functional/apps/observability/pages/rules_page.ts b/x-pack/test/observability_functional/apps/observability/pages/rules_page.ts index abc2534efaf8a6..a10a1e8c928d4a 100644 --- a/x-pack/test/observability_functional/apps/observability/pages/rules_page.ts +++ b/x-pack/test/observability_functional/apps/observability/pages/rules_page.ts @@ -29,8 +29,11 @@ export default ({ getService, getPageObjects }: FtrProviderContext) => { const { body: { data: rules }, } = await supertest - .get(`${INTERNAL_RULE_ENDPOINT}/_find?search=${name}&search_fields=name`) + .post(`${INTERNAL_RULE_ENDPOINT}/_find`) + .set('kbn-xsrf', 'foo') + .send({ search: name, search_fields: 'name' }) .expect(200); + return rules.find((rule: any) => rule.name === name); } diff --git a/x-pack/test/rule_registry/security_and_spaces/tests/basic/get_browser_fields_by_rule_type_ids.ts b/x-pack/test/rule_registry/security_and_spaces/tests/basic/get_browser_fields_by_rule_type_ids.ts index cb369aefa1675d..ac05dad573c65d 100644 --- a/x-pack/test/rule_registry/security_and_spaces/tests/basic/get_browser_fields_by_rule_type_ids.ts +++ b/x-pack/test/rule_registry/security_and_spaces/tests/basic/get_browser_fields_by_rule_type_ids.ts @@ -85,8 +85,8 @@ export default ({ getService }: FtrProviderContext) => { 'monitor', 'observer', 'orchestrator', - 'slo', 'service', + 'slo', 'tls', 'url', ]); From c0a3b79d7a2dda1b173d920728d96e7939c9946f Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Wed, 16 Oct 2024 10:24:22 +0300 Subject: [PATCH 095/106] Fix security solution cypress tests --- .../public/detection_engine/rule_management/api/api.test.ts | 2 +- .../public/detection_engine/rule_management/api/api.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/api/api.test.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_management/api/api.test.ts index 09ec46ee133f38..7fbd6a8367c315 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/api/api.test.ts +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/api/api.test.ts @@ -854,7 +854,7 @@ describe('Detections Rules API', () => { Array [ "/internal/alerting/rules/_find", Object { - "body": "{\\"rule_type_ids\\":[\\"id1\\",\\"id2\\"],\\"fields\\":\\"[\\\\\\"muteAll\\\\\\",\\\\\\"activeSnoozes\\\\\\",\\\\\\"isSnoozedUntil\\\\\\",\\\\\\"snoozeSchedule\\\\\\"]\\",\\"per_page\\":2}", + "body": "{\\"filter\\":\\"alert.id:\\\\\\"alert:id1\\\\\\" or alert.id:\\\\\\"alert:id2\\\\\\"\\",\\"fields\\":\\"[\\\\\\"muteAll\\\\\\",\\\\\\"activeSnoozes\\\\\\",\\\\\\"isSnoozedUntil\\\\\\",\\\\\\"snoozeSchedule\\\\\\"]\\",\\"per_page\\":2}", "method": "POST", "signal": undefined, }, diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/api/api.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_management/api/api.ts index c293f6fa7ac037..1e2ee1be7a47a1 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/api/api.ts +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/api/api.ts @@ -243,7 +243,7 @@ export const fetchRulesSnoozeSettings = async ({ { method: 'POST', body: JSON.stringify({ - rule_type_ids: ids, + filter: ids.map((x) => `alert.id:"alert:${x}"`).join(' or '), fields: JSON.stringify(['muteAll', 'activeSnoozes', 'isSnoozedUntil', 'snoozeSchedule']), per_page: ids.length, }), From 8e33dcc27b02dad54a103f32f74c952850396cd9 Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Wed, 16 Oct 2024 14:11:16 +0300 Subject: [PATCH 096/106] Fix cypress rule snoozing test --- .../rule_management/rule_actions/snoozing/rule_snoozing.cy.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/rule_actions/snoozing/rule_snoozing.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/rule_actions/snoozing/rule_snoozing.cy.ts index 270a9146f65a9f..9622cb94bdd4f5 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/rule_actions/snoozing/rule_snoozing.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/rule_actions/snoozing/rule_snoozing.cy.ts @@ -217,7 +217,7 @@ describe('rule snoozing', { tags: ['@ess', '@serverless', '@skipInServerlessMKI' describe('Handling errors', () => { it('shows an error if unable to load snooze settings', () => { createRule(getNewRule({ name: 'Test rule', enabled: false })).then(({ body: rule }) => { - cy.intercept('GET', `${INTERNAL_ALERTING_API_FIND_RULES_PATH}*`, { + cy.intercept('POST', `${INTERNAL_ALERTING_API_FIND_RULES_PATH}*`, { statusCode: 500, }); From 8fe619055e7e356e6a063700b68587b8fb3d21fb Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Wed, 16 Oct 2024 18:13:40 +0300 Subject: [PATCH 097/106] Use rule type IDs instead of a single rule type ID in the alerts search bar --- .../alert_filter_controls/filter_group.tsx | 1 - .../src/alerts_search_bar/index.test.tsx | 10 +-- .../src/alerts_search_bar/index.tsx | 38 +++++------ .../src/alerts_search_bar/types.ts | 2 +- .../src/common/hooks/index.ts | 1 - .../src/common/hooks/use_alerts_data_view.ts | 6 +- .../src/common/hooks/use_rule_aad_fields.ts | 63 ------------------- .../rule_actions_alerts_filter.test.tsx | 1 - .../rule_actions_alerts_filter.tsx | 4 +- .../feature_privilege_builder/alerting.ts | 2 +- .../maintenance_window_scoped_query.tsx | 2 +- .../application/hooks/use_rule_aad_fields.ts | 58 ----------------- .../alerts_search_bar.test.tsx | 10 --- .../alerts_search_bar/alerts_search_bar.tsx | 36 ++++++----- .../sections/alerts_search_bar/types.ts | 3 +- .../plugins/features_provider/server/index.ts | 47 ++++++++++---- .../perform_bulk_action_ess.ts | 1 - 17 files changed, 84 insertions(+), 201 deletions(-) delete mode 100644 packages/kbn-alerts-ui-shared/src/common/hooks/use_rule_aad_fields.ts delete mode 100644 x-pack/plugins/triggers_actions_ui/public/application/hooks/use_rule_aad_fields.ts diff --git a/packages/kbn-alerts-ui-shared/src/alert_filter_controls/filter_group.tsx b/packages/kbn-alerts-ui-shared/src/alert_filter_controls/filter_group.tsx index f395ab784e848d..a5f69495337768 100644 --- a/packages/kbn-alerts-ui-shared/src/alert_filter_controls/filter_group.tsx +++ b/packages/kbn-alerts-ui-shared/src/alert_filter_controls/filter_group.tsx @@ -44,7 +44,6 @@ import { URL_PARAM_ARRAY_EXCEPTION_MSG } from './translations'; export const FilterGroup = (props: PropsWithChildren) => { const { - featureIds, dataViewId, onFiltersChange, timeRange, diff --git a/packages/kbn-alerts-ui-shared/src/alerts_search_bar/index.test.tsx b/packages/kbn-alerts-ui-shared/src/alerts_search_bar/index.test.tsx index a7ae24e88dd71f..5154b281148dde 100644 --- a/packages/kbn-alerts-ui-shared/src/alerts_search_bar/index.test.tsx +++ b/packages/kbn-alerts-ui-shared/src/alerts_search_bar/index.test.tsx @@ -12,7 +12,7 @@ import { fireEvent, render, screen, waitFor } from '@testing-library/react'; import { dataPluginMock } from '@kbn/data-plugin/public/mocks'; import { Filter, FilterStateStore } from '@kbn/es-query'; import { ToastsStart } from '@kbn/core-notifications-browser'; -import { useLoadRuleTypesQuery, useRuleAADFields, useAlertsDataView } from '../common/hooks'; +import { useLoadRuleTypesQuery, useAlertsDataView } from '../common/hooks'; import { AlertsSearchBar } from '.'; import { HttpStart } from '@kbn/core-http-browser'; @@ -49,11 +49,6 @@ jest.mocked(useLoadRuleTypesQuery).mockReturnValue({ isSuccess: false, }); -jest.mocked(useRuleAADFields).mockReturnValue({ - aadFields: [], - loading: false, -}); - const unifiedSearchBarMock = jest.fn().mockImplementation((props) => ( +)); + describe('AlertsSearchBar', () => { beforeEach(() => { + jest.clearAllMocks(); + mockUseKibana.mockReturnValue({ services: { data: mockDataPlugin, unifiedSearch: { ui: { - SearchBar: jest.fn().mockImplementation((props) => ( - - )), + SearchBar: unifiedSearchBarMock, }, }, notifications: { toasts: { addWarning: jest.fn() } } as unknown as NotificationsStart, @@ -78,10 +66,6 @@ describe('AlertsSearchBar', () => { }); }); - beforeEach(() => { - jest.clearAllMocks(); - }); - it('renders correctly', async () => { render( { expect(mockDataPlugin.query.filterManager.setFilters).toHaveBeenCalledWith(filters); }); }); + + it('calls the unifiedSearchBar correctly for security rule types', async () => { + render( + + ); + + await waitFor(() => { + expect(unifiedSearchBarMock).toHaveBeenCalledWith( + expect.objectContaining({ + suggestionsAbstraction: undefined, + }), + {} + ); + }); + }); + + it('calls the unifiedSearchBar correctly for NON security rule types', async () => { + render( + + ); + + await waitFor(() => { + expect(unifiedSearchBarMock).toHaveBeenCalledWith( + expect.objectContaining({ + suggestionsAbstraction: { type: 'alerts', fields: {} }, + }), + {} + ); + }); + }); + + it('calls the unifiedSearchBar with correct index patters', async () => { + render( + + ); + + await waitFor(() => { + expect(unifiedSearchBarMock).toHaveBeenCalledWith( + expect.objectContaining({ + indexPatterns: [ + { + fields: [ + { aggregatable: true, name: 'event.action', searchable: true, type: 'string' }, + ], + title: '.esQuery,apm.anomaly', + }, + ], + }), + {} + ); + }); + }); + + it('calls the unifiedSearchBar with correct index patters without rule types', async () => { + render( + + ); + + await waitFor(() => { + expect(unifiedSearchBarMock).toHaveBeenCalledWith( + expect.objectContaining({ + indexPatterns: [ + { + fields: [ + { aggregatable: true, name: 'event.action', searchable: true, type: 'string' }, + ], + title: '.alerts-*', + }, + ], + }), + {} + ); + }); + }); + + it('calls the unifiedSearchBar with correct index patters without data views', async () => { + jest.mocked(useAlertsDataView).mockReturnValue({ + isLoading: false, + dataView: undefined, + }); + + render( + + ); + + await waitFor(() => { + expect(unifiedSearchBarMock).toHaveBeenCalledWith( + expect.objectContaining({ + indexPatterns: [], + }), + {} + ); + }); + }); }); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_search_bar/alerts_search_bar.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_search_bar/alerts_search_bar.tsx index 507ba58474bb86..0a5c18fab9d8c4 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_search_bar/alerts_search_bar.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_search_bar/alerts_search_bar.tsx @@ -9,7 +9,7 @@ import React, { useCallback, useMemo, useState } from 'react'; import { useKibana } from '@kbn/kibana-react-plugin/public'; import { compareFilters, Query, TimeRange } from '@kbn/es-query'; import { SuggestionsAbstraction } from '@kbn/unified-search-plugin/public/typeahead/suggestions_component'; -import { AlertConsumers, isSiemRuleType } from '@kbn/rule-data-utils'; +import { isSiemRuleType } from '@kbn/rule-data-utils'; import { EuiContextMenuPanelDescriptor, EuiContextMenuPanelItemDescriptor } from '@elastic/eui'; import { useAlertsDataView } from '@kbn/alerts-ui-shared/src/common/hooks/use_alerts_data_view'; import { isQuickFiltersGroup, QuickFiltersMenuItem } from './quick_filters'; @@ -17,7 +17,6 @@ import { NO_INDEX_PATTERNS } from './constants'; import { SEARCH_BAR_PLACEHOLDER } from './translations'; import { AlertsSearchBarProps, QueryLanguageType } from './types'; import { TriggersAndActionsUiServices } from '../../..'; -import { useLoadRuleTypesQuery } from '../../hooks/use_load_rule_types_query'; const SA_ALERTS = { type: 'alerts', fields: {} } as SuggestionsAbstraction; @@ -73,20 +72,7 @@ export function AlertsSearchBar({ return null; }, [dataView, ruleTypeIds]); - const ruleType = useLoadRuleTypesQuery({ - filteredRuleTypes: ruleTypeIds ?? [], - enabled: Boolean(ruleTypeIds?.length), - }); - - const allProducers = new Set( - ruleTypeIds - ?.map((ruleTypeId) => ruleType.ruleTypesState.data.get(ruleTypeId)?.producer) - .filter((ruleTypeId): ruleTypeId is string => Boolean(ruleTypeId)) ?? [] - ); - - const hasSiemRuleTypes = ruleTypeIds?.some(isSiemRuleType) ?? false; - const isSiemProducer = allProducers.has(AlertConsumers.SIEM); - const isSecurity = hasSiemRuleTypes || isSiemProducer; + const isSecurity = ruleTypeIds?.some(isSiemRuleType) ?? false; const onSearchQuerySubmit = useCallback( ( diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/apis/get_rules_muted_alerts.test.ts b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/apis/get_rules_muted_alerts.test.ts new file mode 100644 index 00000000000000..d0f1a39f7cedec --- /dev/null +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/apis/get_rules_muted_alerts.test.ts @@ -0,0 +1,46 @@ +/* + * 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 { httpServiceMock } from '@kbn/core/public/mocks'; +import { getMutedAlerts } from './get_rules_muted_alerts'; + +const http = httpServiceMock.createStartContract(); + +describe('getMutedAlerts', () => { + const apiRes = { + page: 1, + per_page: 10, + total: 0, + data: [], + }; + + beforeEach(() => { + jest.clearAllMocks(); + + http.post.mockResolvedValueOnce(apiRes); + }); + + test('should call find API with correct params', async () => { + const result = await getMutedAlerts(http, { ruleIds: ['foo'] }); + + expect(result).toEqual({ + page: 1, + per_page: 10, + total: 0, + data: [], + }); + + expect(http.post.mock.calls[0]).toMatchInlineSnapshot(` + Array [ + "/internal/alerting/rules/_find", + Object { + "body": "{\\"rule_type_ids\\":[\\"foo\\"],\\"fields\\":[\\"id\\",\\"mutedInstanceIds\\"],\\"page\\":1,\\"per_page\\":1}", + "signal": undefined, + }, + ] + `); + }); +}); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_bulk_untrack_alerts_by_query.test.ts b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_bulk_untrack_alerts_by_query.test.ts new file mode 100644 index 00000000000000..5de16dd70ce521 --- /dev/null +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_bulk_untrack_alerts_by_query.test.ts @@ -0,0 +1,53 @@ +/* + * 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 { act, renderHook } from '@testing-library/react-hooks'; +import { AppMockRenderer, createAppMockRenderer } from '../../test_utils'; +import { AlertsQueryContext } from '@kbn/alerts-ui-shared/src/common/contexts/alerts_query_context'; +import { useBulkUntrackAlertsByQuery } from './use_bulk_untrack_alerts_by_query'; +import { createStartServicesMock } from '../../../../common/lib/kibana/kibana_react.mock'; +import { TriggersAndActionsUiServices } from '../../../..'; + +const mockUseKibanaReturnValue: TriggersAndActionsUiServices = createStartServicesMock(); + +jest.mock('../../../../common/lib/kibana', () => ({ + useKibana: jest.fn(() => ({ + services: mockUseKibanaReturnValue, + })), +})); + +const response = {}; + +describe('useBulkUntrackAlertsByQuery', () => { + const httpMock = mockUseKibanaReturnValue.http.post as jest.Mock; + + let appMockRender: AppMockRenderer; + + beforeEach(() => { + jest.clearAllMocks(); + appMockRender = createAppMockRenderer(AlertsQueryContext); + }); + + it('calls the api when invoked with the correct parameters', async () => { + httpMock.mockResolvedValue(response); + + const { result, waitFor } = renderHook(() => useBulkUntrackAlertsByQuery(), { + wrapper: appMockRender.AppWrapper, + }); + + await act(async () => { + // @ts-expect-error: no need to specify a query + await result.current.mutateAsync({ ruleTypeIds: ['foo'], query: [] }); + }); + + await waitFor(() => { + expect(httpMock).toHaveBeenCalledWith('/internal/alerting/alerts/_bulk_untrack_by_query', { + body: '{"query":[],"rule_type_ids":["foo"]}', + }); + }); + }); +}); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list.test.tsx index 78fac525c75c66..35249777dedbad 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list.test.tsx @@ -225,8 +225,7 @@ describe('Update Api Key', () => { }); }); -// Failing: See https://github.com/elastic/kibana/issues/182435 -describe.skip('rules_list component empty', () => { +describe('rules_list component empty', () => { beforeEach(() => { fetchActiveMaintenanceWindowsMock.mockResolvedValue([]); loadRulesWithKueryFilter.mockResolvedValue({ @@ -282,28 +281,6 @@ describe.skip('rules_list component empty', () => { expect(await screen.findByTestId('createFirstRuleEmptyPrompt')).toBeInTheDocument(); }); - it('renders MaintenanceWindowCallout if one exists', async () => { - fetchActiveMaintenanceWindowsMock.mockResolvedValue([RUNNING_MAINTENANCE_WINDOW_1]); - renderWithProviders(); - expect( - await screen.findByText( - 'Rule notifications are stopped while maintenance windows are running.' - ) - ).toBeInTheDocument(); - expect(fetchActiveMaintenanceWindowsMock).toHaveBeenCalledTimes(1); - }); - - it("hides MaintenanceWindowCallout if filterConsumers does not match the running maintenance window's category", async () => { - fetchActiveMaintenanceWindowsMock.mockResolvedValue([ - { ...RUNNING_MAINTENANCE_WINDOW_1, categoryIds: ['securitySolution'] }, - ]); - renderWithProviders(); - await expect( - screen.findByText('Rule notifications are stopped while maintenance windows are running.') - ).rejects.toThrow(); - expect(fetchActiveMaintenanceWindowsMock).toHaveBeenCalledTimes(1); - }); - it('renders Create rule button', async () => { renderWithProviders(); @@ -319,6 +296,7 @@ describe.skip('rules_list component empty', () => { describe('rules_list ', () => { let ruleTypeRegistry: jest.Mocked; let actionTypeRegistry: jest.Mocked>; + beforeEach(() => { (getIsExperimentalFeatureEnabled as jest.Mock).mockImplementation(() => false); loadRulesWithKueryFilter.mockResolvedValue({ @@ -1403,3 +1381,99 @@ describe('rules_list with show only capability', () => { }); }); }); + +describe('MaintenanceWindowsMock', () => { + beforeEach(() => { + fetchActiveMaintenanceWindowsMock.mockResolvedValue([]); + + loadRulesWithKueryFilter.mockResolvedValue({ + page: 1, + perPage: 10000, + total: 0, + data: [], + }); + + loadActionTypes.mockResolvedValue([ + { + id: 'test', + name: 'Test', + }, + { + id: 'test2', + name: 'Test2', + }, + ]); + + loadRuleTypes.mockResolvedValue([ruleTypeFromApi]); + loadAllActions.mockResolvedValue([]); + loadRuleAggregationsWithKueryFilter.mockResolvedValue({}); + loadRuleTags.mockResolvedValue({ + data: ruleTags, + page: 1, + perPage: 50, + total: 4, + }); + + const actionTypeRegistry = actionTypeRegistryMock.create(); + const ruleTypeRegistry = ruleTypeRegistryMock.create(); + + ruleTypeRegistry.list.mockReturnValue([ruleType]); + actionTypeRegistry.list.mockReturnValue([]); + useKibanaMock().services.application.capabilities = { + ...useKibanaMock().services.application.capabilities, + [MAINTENANCE_WINDOW_FEATURE_ID]: { + save: true, + show: true, + }, + }; + useKibanaMock().services.ruleTypeRegistry = ruleTypeRegistry; + useKibanaMock().services.actionTypeRegistry = actionTypeRegistry; + }); + + afterEach(() => { + jest.clearAllMocks(); + queryClient.clear(); + cleanup(); + }); + + it('renders MaintenanceWindowCallout if one exists', async () => { + fetchActiveMaintenanceWindowsMock.mockResolvedValue([RUNNING_MAINTENANCE_WINDOW_1]); + renderWithProviders(); + + expect( + await screen.findByText('One or more maintenance windows are running') + ).toBeInTheDocument(); + + expect(fetchActiveMaintenanceWindowsMock).toHaveBeenCalledTimes(1); + }); + + it('hides MaintenanceWindowCallout if the category ID is not supported', async () => { + loadRuleTypes.mockResolvedValue([{ ...ruleTypeFromApi, category: 'observability' }]); + fetchActiveMaintenanceWindowsMock.mockResolvedValue([ + { ...RUNNING_MAINTENANCE_WINDOW_1, categoryIds: ['securitySolution'] }, + ]); + + renderWithProviders(); + + await expect( + screen.findByText('Rule notifications are stopped while maintenance windows are running.') + ).rejects.toThrow(); + + expect(fetchActiveMaintenanceWindowsMock).toHaveBeenCalledTimes(1); + }); + + it('shows MaintenanceWindowCallout for a specific category', async () => { + loadRuleTypes.mockResolvedValue([{ ...ruleTypeFromApi, category: 'observability' }]); + fetchActiveMaintenanceWindowsMock.mockResolvedValue([ + { ...RUNNING_MAINTENANCE_WINDOW_1, categoryIds: ['securitySolution', 'observability'] }, + ]); + + renderWithProviders(); + + expect( + await screen.findByText('A maintenance window is running for Observability rules') + ).toBeInTheDocument(); + + expect(fetchActiveMaintenanceWindowsMock).toHaveBeenCalledTimes(1); + }); +}); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list.tsx index 8bab554ec63fdf..c0b56fa2245193 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list.tsx @@ -771,12 +771,16 @@ export const RulesList = ({ const numberRulesToDelete = rulesToBulkEdit.length || numberOfSelectedItems; + const allRuleCategories = getAllUniqueRuleTypeCategories( + Array.from(ruleTypesState.data.values()) + ); + return ( <> {showSearchBar && !isEmpty(filters.ruleParams) ? ( ) : null} - + ids.includes(rule.id)); } + +const getAllUniqueRuleTypeCategories = (ruleTypes: RuleType[]) => { + const categories = new Set(ruleTypes.map((ruleType) => ruleType.category)); + + return Array.from(categories).filter(Boolean); +}; From 0c5fabd248a59f4d3e48022868a35048e9e8a25a Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Mon, 21 Oct 2024 09:50:25 +0300 Subject: [PATCH 105/106] Remove o11y checks in the consumer dropdown --- x-pack/plugins/cases/common/constants/owners.ts | 2 -- x-pack/plugins/cases/common/utils/owner.test.ts | 9 +++++++++ x-pack/plugins/cases/common/utils/owner.ts | 7 ++++++- .../rule_form_consumer_selection.test.tsx | 13 ------------- .../rule_form/rule_form_consumer_selection.tsx | 15 +++++---------- 5 files changed, 20 insertions(+), 26 deletions(-) diff --git a/x-pack/plugins/cases/common/constants/owners.ts b/x-pack/plugins/cases/common/constants/owners.ts index 776649e82745ac..79db38345e5661 100644 --- a/x-pack/plugins/cases/common/constants/owners.ts +++ b/x-pack/plugins/cases/common/constants/owners.ts @@ -51,7 +51,6 @@ export const OWNER_INFO: Record = { AlertConsumers.SLO, AlertConsumers.UPTIME, AlertConsumers.MONITORING, - AlertConsumers.ALERTS, ], }, [GENERAL_CASES_OWNER]: { @@ -65,7 +64,6 @@ export const OWNER_INFO: Record = { AlertConsumers.STACK_ALERTS, AlertConsumers.EXAMPLE, AlertConsumers.DISCOVER, - AlertConsumers.ALERTS, ], }, } as const; diff --git a/x-pack/plugins/cases/common/utils/owner.test.ts b/x-pack/plugins/cases/common/utils/owner.test.ts index 02008a701b658b..4e005750ad36f9 100644 --- a/x-pack/plugins/cases/common/utils/owner.test.ts +++ b/x-pack/plugins/cases/common/utils/owner.test.ts @@ -80,5 +80,14 @@ describe('owner utils', () => { expect(owner).toBe(OWNER_INFO.securitySolution.id); }); + + it('fallbacks to producer when the consumer is alerts', () => { + const owner = getOwnerFromRuleConsumerProducer({ + consumer: AlertConsumers.ALERTS, + producer: AlertConsumers.OBSERVABILITY, + }); + + expect(owner).toBe(OWNER_INFO.observability.id); + }); }); }); diff --git a/x-pack/plugins/cases/common/utils/owner.ts b/x-pack/plugins/cases/common/utils/owner.ts index 7bde7220233db2..569830b509935f 100644 --- a/x-pack/plugins/cases/common/utils/owner.ts +++ b/x-pack/plugins/cases/common/utils/owner.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { AlertConsumers } from '@kbn/rule-data-utils'; import { OWNER_INFO } from '../constants'; import type { Owner } from '../constants/types'; @@ -29,9 +30,13 @@ export const getOwnerFromRuleConsumerProducer = ({ return OWNER_INFO.securitySolution.id; } + // Fallback to producer if the consumer is alerts or undefined + const validRuleConsumerToFound = + consumer === AlertConsumers.ALERTS || consumer == null ? producer : consumer; + for (const value of Object.values(OWNER_INFO)) { const foundConsumer = value.validRuleConsumers?.find( - (validConsumer) => validConsumer === consumer || validConsumer === producer + (validConsumer) => validConsumer === validRuleConsumerToFound ); if (foundConsumer) { diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_form/rule_form_consumer_selection.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_form/rule_form_consumer_selection.test.tsx index bec46c682919b8..17dc478b219821 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_form/rule_form_consumer_selection.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_form/rule_form_consumer_selection.test.tsx @@ -162,19 +162,6 @@ describe('RuleFormConsumerSelectionModal', () => { expect(screen.queryByTestId('ruleFormConsumerSelect')).not.toBeInTheDocument(); }); - it('should display nothing if observability is one of the consumers', () => { - render( - - ); - - expect(screen.queryByTestId('ruleFormConsumerSelect')).not.toBeInTheDocument(); - }); - it('should display the initial selected consumer', () => { render( { const { consumers, errors, onChange, selectedConsumer, initialSelectedConsumer } = props; const isInvalid = (errors?.consumer as string[])?.length > 0; + const handleOnChange = useCallback( (selected: Array>) => { if (selected.length > 0) { @@ -93,6 +94,7 @@ export const RuleFormConsumerSelection = (props: RuleFormConsumerSelectionProps) }, [onChange] ); + const validatedSelectedConsumer = useMemo(() => { if ( selectedConsumer && @@ -103,6 +105,7 @@ export const RuleFormConsumerSelection = (props: RuleFormConsumerSelectionProps) } return null; }, [selectedConsumer, consumers]); + const selectedOptions = useMemo( () => validatedSelectedConsumer @@ -146,18 +149,10 @@ export const RuleFormConsumerSelection = (props: RuleFormConsumerSelectionProps) // eslint-disable-next-line react-hooks/exhaustive-deps }, []); - useEffect(() => { - if (consumers.length === 1) { - onChange(consumers[0] as RuleCreationValidConsumer); - } else if (consumers.includes(AlertConsumers.OBSERVABILITY)) { - onChange(AlertConsumers.OBSERVABILITY as RuleCreationValidConsumer); - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [consumers]); - - if (consumers.length <= 1 || consumers.includes(AlertConsumers.OBSERVABILITY)) { + if (consumers.length <= 1) { return null; } + return ( Date: Mon, 21 Oct 2024 10:51:26 +0300 Subject: [PATCH 106/106] Use constant for rule types when registering o11y serverless feature privilege --- .../observability/server/plugin.ts | 20 ++----------------- 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/x-pack/plugins/observability_solution/observability/server/plugin.ts b/x-pack/plugins/observability_solution/observability/server/plugin.ts index 50415854983936..5b39e37f51d755 100644 --- a/x-pack/plugins/observability_solution/observability/server/plugin.ts +++ b/x-pack/plugins/observability_solution/observability/server/plugin.ts @@ -24,14 +24,6 @@ import { FeaturesPluginSetup } from '@kbn/features-plugin/server'; import { hiddenTypes as filesSavedObjectTypes } from '@kbn/files-plugin/server/saved_objects'; import type { GuidedOnboardingPluginSetup } from '@kbn/guided-onboarding-plugin/server'; import { i18n } from '@kbn/i18n'; -import { - ApmRuleType, - ES_QUERY_ID, - ML_ANOMALY_DETECTION_RULE_TYPE_ID, - METRIC_INVENTORY_THRESHOLD_ALERT_TYPE_ID, - OBSERVABILITY_THRESHOLD_RULE_TYPE_ID, - SLO_BURN_RATE_RULE_TYPE_ID, -} from '@kbn/rule-data-utils'; import { RuleRegistryPluginSetupContract } from '@kbn/rule-registry-plugin/server'; import { SharePluginSetup } from '@kbn/share-plugin/server'; import { SpacesPluginSetup, SpacesPluginStart } from '@kbn/spaces-plugin/server'; @@ -57,6 +49,7 @@ import { registerRoutes } from './routes/register_routes'; import { threshold } from './saved_objects/threshold'; import { AlertDetailsContextualInsightsService } from './services'; import { uiSettings } from './ui_settings'; +import { OBSERVABILITY_RULE_TYPE_IDS_WITH_STACK } from '../common/constants'; export type ObservabilityPluginSetup = ReturnType; @@ -77,16 +70,7 @@ interface PluginStart { dataViews: DataViewsServerPluginStart; } -const o11yRuleTypes = [ - SLO_BURN_RATE_RULE_TYPE_ID, - OBSERVABILITY_THRESHOLD_RULE_TYPE_ID, - ES_QUERY_ID, - ML_ANOMALY_DETECTION_RULE_TYPE_ID, - METRIC_INVENTORY_THRESHOLD_ALERT_TYPE_ID, - ...Object.values(ApmRuleType), -]; - -const alertingFeatures = o11yRuleTypes.map((ruleTypeId) => ({ +const alertingFeatures = OBSERVABILITY_RULE_TYPE_IDS_WITH_STACK.map((ruleTypeId) => ({ ruleTypeId, consumers: [observabilityFeatureId, ALERTING_FEATURE_ID], }));