From ae1af16bdc2df590bceaf1b08094f6a506195246 Mon Sep 17 00:00:00 2001 From: Georgii Gorbachev Date: Wed, 25 Aug 2021 16:29:16 +0200 Subject: [PATCH] [RAC] Fix index names used by RBAC, delete hardcoded map of Kibana features to index names (#109567) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit **Ticket:** https://github.com/elastic/kibana/issues/102089 🚨 **This PR is critical for Observability 7.15** 🚨 ## Summary This PR introduces changes that fix the usage of alerts-as-data index naming in RBAC. It builds on top of https://github.com/elastic/kibana/pull/109346 and replaces https://github.com/elastic/kibana/pull/108872. TODO: - [x] Address https://github.com/elastic/kibana/pull/109346#pullrequestreview-735158370 - [x] Make changes to `AlertsClient.getAuthorizedAlertsIndices()` so it starts using `RuleDataService` to get index names by feature ids. - [x] Delete the hardcoded `mapConsumerToIndexName` where we had incorrect index names. - [x] Close https://github.com/elastic/kibana/pull/108872 ### Checklist Delete any items that are not applicable to this PR. - [ ] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios --- .../src/alerts_as_data_rbac.ts | 12 +----- .../common/es_glob_patterns.test.ts | 6 +-- .../public/pages/alerts/index.tsx | 1 - .../observability/server/routes/rules.ts | 3 +- x-pack/plugins/rule_registry/README.md | 4 +- .../server/alert_data_client/alerts_client.ts | 37 +++++++++++-------- .../alerts_client_factory.test.ts | 4 ++ .../alerts_client_factory.ts | 9 ++++- .../tests/bulk_update.test.ts | 25 +++++++------ .../tests/find_alerts.test.ts | 27 ++++++++------ .../alert_data_client/tests/get.test.ts | 26 ++++++++----- .../alert_data_client/tests/update.test.ts | 37 ++++++++++--------- x-pack/plugins/rule_registry/server/plugin.ts | 3 +- .../routes/__mocks__/request_responses.ts | 2 +- .../server/routes/update_alert_by_id.test.ts | 8 ++-- .../rule_data_plugin_service.mock.ts | 7 ++-- .../rule_data_plugin_service.ts | 31 ++++++++++++---- .../bulk_update_observability_alert_by_ids.sh | 6 +-- ...ulk_update_observability_alert_by_query.sh | 2 +- .../scripts/find_observability_alert.sh | 2 +- .../server/scripts/get_observability_alert.sh | 2 +- .../scripts/update_observability_alert.sh | 2 +- .../server/lib/alerts/test_utils/index.ts | 2 +- .../rule_registry/alerts/data.json | 6 +-- .../rule_registry/alerts/mappings.json | 2 +- .../tests/basic/bulk_update_alerts.ts | 2 +- .../tests/basic/find_alerts.ts | 2 +- .../tests/basic/get_alert_by_id.ts | 2 +- .../tests/basic/update_alert.ts | 2 +- .../tests/trial/get_alerts.ts | 4 +- .../tests/trial/update_alert.ts | 6 +-- .../tests/trial/get_alert_by_id.ts | 2 +- .../spaces_only/tests/trial/update_alert.ts | 2 +- 33 files changed, 162 insertions(+), 126 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 48f9d705da27d8..d167b17b83f233 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 @@ -26,17 +26,9 @@ export const 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 const mapConsumerToIndexName: Record = { - apm: '.alerts-observability-apm', - logs: '.alerts-observability.logs', - infrastructure: '.alerts-observability.metrics', - observability: '.alerts-observability', - siem: '.alerts-security.alerts', - uptime: '.alerts-observability.uptime', -}; -export type ValidFeatureId = keyof typeof mapConsumerToIndexName; +export type ValidFeatureId = AlertConsumers; -export const validFeatureIds = Object.keys(mapConsumerToIndexName); +export const validFeatureIds = Object.values(AlertConsumers).map((v) => v as string); export const isValidFeatureId = (a: unknown): a is ValidFeatureId => typeof a === 'string' && validFeatureIds.includes(a); diff --git a/x-pack/plugins/monitoring/common/es_glob_patterns.test.ts b/x-pack/plugins/monitoring/common/es_glob_patterns.test.ts index 64250d0b3c5aea..0b868a418a61b2 100644 --- a/x-pack/plugins/monitoring/common/es_glob_patterns.test.ts +++ b/x-pack/plugins/monitoring/common/es_glob_patterns.test.ts @@ -19,7 +19,7 @@ const testIndices = [ '.ds-metrics-system.process.summary-default-2021.05.25-00000', '.kibana_shahzad_9', '.kibana-felix-log-stream_8.0.0_001', - '.kibana_smith_alerts-observability-apm-000001', + '.kibana_smith_alerts-observability.apm.alerts-000001', '.ds-logs-endpoint.events.process-default-2021.05.26-000001', '.kibana_dominiqueclarke54_8.0.0_001', '.kibana-cmarcondes-19_8.0.0_001', @@ -63,7 +63,7 @@ const onlySystemIndices = [ '.ds-metrics-system.process.summary-default-2021.05.25-00000', '.kibana_shahzad_9', '.kibana-felix-log-stream_8.0.0_001', - '.kibana_smith_alerts-observability-apm-000001', + '.kibana_smith_alerts-observability.apm.alerts-000001', '.ds-logs-endpoint.events.process-default-2021.05.26-000001', '.kibana_dominiqueclarke54_8.0.0_001', '.kibana-cmarcondes-19_8.0.0_001', @@ -85,7 +85,7 @@ const kibanaNoTaskIndices = [ '.kibana_shahzad_1', '.kibana_shahzad_9', '.kibana-felix-log-stream_8.0.0_001', - '.kibana_smith_alerts-observability-apm-000001', + '.kibana_smith_alerts-observability.apm.alerts-000001', '.kibana_dominiqueclarke54_8.0.0_001', '.kibana-cmarcondes-19_8.0.0_001', '.kibana_dominiqueclarke55-alerts-8.0.0-000001', diff --git a/x-pack/plugins/observability/public/pages/alerts/index.tsx b/x-pack/plugins/observability/public/pages/alerts/index.tsx index 751307196fa196..6e2323bb4c54bb 100644 --- a/x-pack/plugins/observability/public/pages/alerts/index.tsx +++ b/x-pack/plugins/observability/public/pages/alerts/index.tsx @@ -72,7 +72,6 @@ export function AlertsPage({ routeParams }: AlertsPageProps) { registrationContexts: [ 'observability.apm', 'observability.logs', - 'observability.infrastructure', 'observability.metrics', 'observability.uptime', ], diff --git a/x-pack/plugins/observability/server/routes/rules.ts b/x-pack/plugins/observability/server/routes/rules.ts index a9039e4a66211c..b4682116f1205b 100644 --- a/x-pack/plugins/observability/server/routes/rules.ts +++ b/x-pack/plugins/observability/server/routes/rules.ts @@ -6,6 +6,7 @@ */ import * as t from 'io-ts'; +import { Dataset } from '../../../rule_registry/server'; import { createObservabilityServerRoute } from './create_observability_server_route'; import { createObservabilityServerRouteRepository } from './create_observability_server_route_repository'; @@ -24,7 +25,7 @@ const alertsDynamicIndexPatternRoute = createObservabilityServerRoute({ const { namespace, registrationContexts } = params.query; const indexNames = registrationContexts.flatMap((registrationContext) => { const indexName = ruleDataService - .getRegisteredIndexInfo(registrationContext) + .findIndexByName(registrationContext, Dataset.alerts) ?.getPrimaryAlias(namespace); if (indexName != null) { diff --git a/x-pack/plugins/rule_registry/README.md b/x-pack/plugins/rule_registry/README.md index ef9a3252c41d71..ad2080aa1f44a7 100644 --- a/x-pack/plugins/rule_registry/README.md +++ b/x-pack/plugins/rule_registry/README.md @@ -73,7 +73,7 @@ await plugins.ruleRegistry.createOrUpdateComponentTemplate({ await plugins.ruleRegistry.createOrUpdateIndexTemplate({ name: plugins.ruleRegistry.getFullAssetName('apm-index-template'), body: { - index_patterns: [plugins.ruleRegistry.getFullAssetName('observability-apm*')], + index_patterns: [plugins.ruleRegistry.getFullAssetName('observability.apm*')], composed_of: [ // Technical component template, required plugins.ruleRegistry.getFullAssetName(TECHNICAL_COMPONENT_TEMPLATE_NAME), @@ -85,7 +85,7 @@ await plugins.ruleRegistry.createOrUpdateIndexTemplate({ // Finally, create the rule data client that can be injected into rule type // executors and API endpoints const ruleDataClient = new RuleDataClient({ - alias: plugins.ruleRegistry.getFullAssetName('observability-apm'), + alias: plugins.ruleRegistry.getFullAssetName('observability.apm'), getClusterClient: async () => { const coreStart = await getCoreStart(); return coreStart.elasticsearch.client.asInternalUser; 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 090978949e2fd7..d8e3a3bae7b023 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 @@ -13,14 +13,13 @@ import type { getEsQueryConfig as getEsQueryConfigTyped, getSafeSortIds as getSafeSortIdsTyped, isValidFeatureId as isValidFeatureIdTyped, - mapConsumerToIndexName as mapConsumerToIndexNameTyped, STATUS_VALUES, + ValidFeatureId, } from '@kbn/rule-data-utils'; import { getEsQueryConfig as getEsQueryConfigNonTyped, getSafeSortIds as getSafeSortIdsNonTyped, isValidFeatureId as isValidFeatureIdNonTyped, - mapConsumerToIndexName as mapConsumerToIndexNameNonTyped, // @ts-expect-error } from '@kbn/rule-data-utils/target_node/alerts_as_data_rbac'; @@ -42,11 +41,11 @@ import { SPACE_IDS, } from '../../common/technical_rule_data_field_names'; import { ParsedTechnicalFields } from '../../common/parse_technical_fields'; +import { Dataset, RuleDataPluginService } from '../rule_data_plugin_service'; const getEsQueryConfig: typeof getEsQueryConfigTyped = getEsQueryConfigNonTyped; const getSafeSortIds: typeof getSafeSortIdsTyped = getSafeSortIdsNonTyped; const isValidFeatureId: typeof isValidFeatureIdTyped = isValidFeatureIdNonTyped; -const mapConsumerToIndexName: typeof mapConsumerToIndexNameTyped = mapConsumerToIndexNameNonTyped; // TODO: Fix typings https://github.com/elastic/kibana/issues/101776 type NonNullableProps = Omit & @@ -71,6 +70,7 @@ export interface ConstructorOptions { authorization: PublicMethodsOf; auditLogger?: AuditLogger; esClient: ElasticsearchClient; + ruleDataService: RuleDataPluginService; } export interface UpdateOptions { @@ -115,15 +115,17 @@ export class AlertsClient { private readonly authorization: PublicMethodsOf; private readonly esClient: ElasticsearchClient; private readonly spaceId: string | undefined; + private readonly ruleDataService: RuleDataPluginService; - constructor({ auditLogger, authorization, logger, esClient }: ConstructorOptions) { - this.logger = logger; - this.authorization = authorization; - this.esClient = esClient; - this.auditLogger = auditLogger; + constructor(options: ConstructorOptions) { + this.logger = options.logger; + this.authorization = options.authorization; + this.esClient = options.esClient; + this.auditLogger = options.auditLogger; // If spaceId is undefined, it means that spaces is disabled // Otherwise, if space is enabled and not specified, it is "default" this.spaceId = this.authorization.getSpaceId(); + this.ruleDataService = options.ruleDataService; } private getOutcome( @@ -666,15 +668,18 @@ export class AlertsClient { authorizedFeatures.add(ruleType.producer); } - const toReturn = Array.from(authorizedFeatures).flatMap((feature) => { - if (featureIds.includes(feature) && isValidFeatureId(feature)) { - if (feature === 'siem') { - return `${mapConsumerToIndexName[feature]}-${this.spaceId}`; - } else { - return `${mapConsumerToIndexName[feature]}`; - } + const validAuthorizedFeatures = Array.from(authorizedFeatures).filter( + (feature): feature is ValidFeatureId => + featureIds.includes(feature) && isValidFeatureId(feature) + ); + + const toReturn = validAuthorizedFeatures.flatMap((feature) => { + const indices = this.ruleDataService.findIndicesByFeature(feature, Dataset.alerts); + if (feature === 'siem') { + return indices.map((i) => `${i.baseName}-${this.spaceId}`); + } else { + return indices.map((i) => i.baseName); } - return []; }); return toReturn; 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 9e1941f7797220..1187d4675787b5 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 @@ -13,6 +13,8 @@ import { loggingSystemMock } from 'src/core/server/mocks'; import { securityMock } from '../../../security/server/mocks'; import { AuditLogger } from '../../../security/server'; import { alertingAuthorizationMock } from '../../../alerting/server/authorization/alerting_authorization.mock'; +import { ruleDataPluginServiceMock } from '../rule_data_plugin_service/rule_data_plugin_service.mock'; +import { RuleDataPluginService } from '../rule_data_plugin_service'; jest.mock('./alerts_client'); @@ -24,6 +26,7 @@ const alertsClientFactoryParams: AlertsClientFactoryProps = { getAlertingAuthorization: (_: KibanaRequest) => alertingAuthMock, securityPluginSetup, esClient: {} as ElasticsearchClient, + ruleDataService: (ruleDataPluginServiceMock.create() as unknown) as RuleDataPluginService, }; const fakeRequest = ({ @@ -64,6 +67,7 @@ describe('AlertsClientFactory', () => { logger: alertsClientFactoryParams.logger, auditLogger, esClient: {}, + ruleDataService: alertsClientFactoryParams.ruleDataService, }); }); 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 43a3827b28972b..c1ff6d5d56ea93 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 @@ -5,10 +5,11 @@ * 2.0. */ -import { ElasticsearchClient, KibanaRequest, Logger } from 'src/core/server'; import { PublicMethodsOf } from '@kbn/utility-types'; -import { SecurityPluginSetup } from '../../../security/server'; +import { ElasticsearchClient, KibanaRequest, Logger } from 'src/core/server'; import { AlertingAuthorization } from '../../../alerting/server'; +import { SecurityPluginSetup } from '../../../security/server'; +import { RuleDataPluginService } from '../rule_data_plugin_service'; import { AlertsClient } from './alerts_client'; export interface AlertsClientFactoryProps { @@ -16,6 +17,7 @@ export interface AlertsClientFactoryProps { esClient: ElasticsearchClient; getAlertingAuthorization: (request: KibanaRequest) => PublicMethodsOf; securityPluginSetup: SecurityPluginSetup | undefined; + ruleDataService: RuleDataPluginService | null; } export class AlertsClientFactory { @@ -26,6 +28,7 @@ export class AlertsClientFactory { request: KibanaRequest ) => PublicMethodsOf; private securityPluginSetup!: SecurityPluginSetup | undefined; + private ruleDataService!: RuleDataPluginService | null; public initialize(options: AlertsClientFactoryProps) { /** @@ -40,6 +43,7 @@ export class AlertsClientFactory { this.logger = options.logger; this.esClient = options.esClient; this.securityPluginSetup = options.securityPluginSetup; + this.ruleDataService = options.ruleDataService; } public async create(request: KibanaRequest): Promise { @@ -50,6 +54,7 @@ export class AlertsClientFactory { authorization: getAlertingAuthorization(request), auditLogger: securityPluginSetup?.audit.asScoped(request), esClient: this.esClient, + ruleDataService: this.ruleDataService!, }); } } 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 11066ffddfaddd..3606d90d22414c 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 @@ -18,6 +18,8 @@ import { elasticsearchClientMock } from 'src/core/server/elasticsearch/client/mo import { alertingAuthorizationMock } from '../../../../alerting/server/authorization/alerting_authorization.mock'; import { AuditLogger } from '../../../../security/server'; import { AlertingAuthorizationEntity } from '../../../../alerting/server'; +import { ruleDataPluginServiceMock } from '../../rule_data_plugin_service/rule_data_plugin_service.mock'; +import { RuleDataPluginService } from '../../rule_data_plugin_service'; const alertingAuthMock = alertingAuthorizationMock.create(); const esClientMock = elasticsearchClientMock.createElasticsearchClient(); @@ -30,6 +32,7 @@ const alertsClientParams: jest.Mocked = { authorization: alertingAuthMock, esClient: esClientMock, auditLogger, + ruleDataService: (ruleDataPluginServiceMock.create() as unknown) as RuleDataPluginService, }; const DEFAULT_SPACE = 'test_default_space_id'; @@ -78,7 +81,7 @@ describe('bulkUpdate()', () => { describe('ids', () => { describe('audit log', () => { test('logs successful event in audit logger', async () => { - const indexName = '.alerts-observability-apm.alerts'; + const indexName = '.alerts-observability.apm.alerts'; const alertsClient = new AlertsClient(alertsClientParams); esClientMock.mget.mockResolvedValueOnce( elasticsearchClientMock.createApiResponse({ @@ -107,7 +110,7 @@ describe('bulkUpdate()', () => { { update: { _id: fakeAlertId, - _index: '.alerts-observability-apm.alerts', + _index: '.alerts-observability.apm.alerts', result: 'updated', status: 200, }, @@ -135,7 +138,7 @@ describe('bulkUpdate()', () => { }); test('audit error access if user is unauthorized for given alert', async () => { - const indexName = '.alerts-observability-apm.alerts'; + const indexName = '.alerts-observability.apm.alerts'; const alertsClient = new AlertsClient(alertsClientParams); esClientMock.mget.mockResolvedValueOnce( elasticsearchClientMock.createApiResponse({ @@ -181,7 +184,7 @@ describe('bulkUpdate()', () => { }); test('logs multiple error events in audit logger', async () => { - const indexName = '.alerts-observability-apm.alerts'; + const indexName = '.alerts-observability.apm.alerts'; const alertsClient = new AlertsClient(alertsClientParams); esClientMock.mget.mockResolvedValueOnce( elasticsearchClientMock.createApiResponse({ @@ -257,7 +260,7 @@ describe('bulkUpdate()', () => { describe('query', () => { describe('audit log', () => { test('logs successful event in audit logger', async () => { - const indexName = '.alerts-observability-apm.alerts'; + const indexName = '.alerts-observability.apm.alerts'; const alertsClient = new AlertsClient(alertsClientParams); esClientMock.search.mockResolvedValueOnce( elasticsearchClientMock.createApiResponse({ @@ -276,7 +279,7 @@ describe('bulkUpdate()', () => { hits: [ { _id: fakeAlertId, - _index: '.alerts-observability-apm.alerts', + _index: '.alerts-observability.apm.alerts', _source: { [ALERT_RULE_TYPE_ID]: 'apm.error_rate', [ALERT_RULE_CONSUMER]: 'apm', @@ -317,7 +320,7 @@ describe('bulkUpdate()', () => { }); test('audit error access if user is unauthorized for given alert', async () => { - const indexName = '.alerts-observability-apm.alerts'; + const indexName = '.alerts-observability.apm.alerts'; const alertsClient = new AlertsClient(alertsClientParams); esClientMock.search.mockResolvedValueOnce( elasticsearchClientMock.createApiResponse({ @@ -336,7 +339,7 @@ describe('bulkUpdate()', () => { hits: [ { _id: fakeAlertId, - _index: '.alerts-observability-apm.alerts', + _index: '.alerts-observability.apm.alerts', _source: { [ALERT_RULE_TYPE_ID]: fakeRuleTypeId, [ALERT_RULE_CONSUMER]: 'apm', @@ -378,7 +381,7 @@ describe('bulkUpdate()', () => { }); test('logs multiple error events in audit logger', async () => { - const indexName = '.alerts-observability-apm.alerts'; + const indexName = '.alerts-observability.apm.alerts'; const alertsClient = new AlertsClient(alertsClientParams); esClientMock.search.mockResolvedValueOnce( elasticsearchClientMock.createApiResponse({ @@ -397,7 +400,7 @@ describe('bulkUpdate()', () => { hits: [ { _id: successfulAuthzHit, - _index: '.alerts-observability-apm.alerts', + _index: '.alerts-observability.apm.alerts', _source: { [ALERT_RULE_TYPE_ID]: 'apm.error_rate', [ALERT_RULE_CONSUMER]: 'apm', @@ -407,7 +410,7 @@ describe('bulkUpdate()', () => { }, { _id: unsuccessfulAuthzHit, - _index: '.alerts-observability-apm.alerts', + _index: '.alerts-observability.apm.alerts', _source: { [ALERT_RULE_TYPE_ID]: fakeRuleTypeId, [ALERT_RULE_CONSUMER]: '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 1e6601c7b08625..f103fd5778e833 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 @@ -18,6 +18,8 @@ import { elasticsearchClientMock } from 'src/core/server/elasticsearch/client/mo import { alertingAuthorizationMock } from '../../../../alerting/server/authorization/alerting_authorization.mock'; import { AuditLogger } from '../../../../security/server'; import { AlertingAuthorizationEntity } from '../../../../alerting/server'; +import { ruleDataPluginServiceMock } from '../../rule_data_plugin_service/rule_data_plugin_service.mock'; +import { RuleDataPluginService } from '../../rule_data_plugin_service'; const alertingAuthMock = alertingAuthorizationMock.create(); const esClientMock = elasticsearchClientMock.createElasticsearchClient(); @@ -30,6 +32,7 @@ const alertsClientParams: jest.Mocked = { authorization: alertingAuthMock, esClient: esClientMock, auditLogger, + ruleDataService: (ruleDataPluginServiceMock.create() as unknown) as RuleDataPluginService, }; const DEFAULT_SPACE = 'test_default_space_id'; @@ -90,7 +93,7 @@ describe('find()', () => { { found: true, _type: 'alert', - _index: '.alerts-observability-apm', + _index: '.alerts-observability.apm.alerts', _id: 'NoxgpHkBqbdrfX07MqXV', _version: 1, _seq_no: 362, @@ -110,7 +113,7 @@ describe('find()', () => { ); const result = await alertsClient.find({ query: { match: { [ALERT_WORKFLOW_STATUS]: 'open' } }, - index: '.alerts-observability-apm', + index: '.alerts-observability.apm.alerts', }); expect(result).toMatchInlineSnapshot(` Object { @@ -124,7 +127,7 @@ describe('find()', () => { "hits": Array [ Object { "_id": "NoxgpHkBqbdrfX07MqXV", - "_index": ".alerts-observability-apm", + "_index": ".alerts-observability.apm.alerts", "_primary_term": 2, "_seq_no": 362, "_source": Object { @@ -194,7 +197,7 @@ describe('find()', () => { "track_total_hits": undefined, }, "ignore_unavailable": true, - "index": ".alerts-observability-apm", + "index": ".alerts-observability.apm.alerts", "seq_no_primary_term": true, }, ] @@ -221,7 +224,7 @@ describe('find()', () => { { found: true, _type: 'alert', - _index: '.alerts-observability-apm', + _index: '.alerts-observability.apm.alerts', _id: 'NoxgpHkBqbdrfX07MqXV', _version: 1, _seq_no: 362, @@ -241,7 +244,7 @@ describe('find()', () => { ); await alertsClient.find({ query: { match: { [ALERT_WORKFLOW_STATUS]: 'open' } }, - index: '.alerts-observability-apm', + index: '.alerts-observability.apm.alerts', }); expect(auditLogger.log).toHaveBeenCalledWith({ @@ -252,7 +255,7 @@ describe('find()', () => { }); test('audit error access if user is unauthorized for given alert', async () => { - const indexName = '.alerts-observability-apm'; + const indexName = '.alerts-observability.apm.alerts'; const fakeAlertId = 'myfakeid1'; // fakeRuleTypeId will cause authz to fail const fakeRuleTypeId = 'fake.rule'; @@ -296,7 +299,7 @@ describe('find()', () => { await expect( alertsClient.find({ query: { match: { [ALERT_WORKFLOW_STATUS]: 'open' } }, - index: '.alerts-observability-apm', + 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 @@ -326,7 +329,7 @@ describe('find()', () => { await expect( alertsClient.find({ query: { match: { [ALERT_WORKFLOW_STATUS]: 'open' } }, - index: '.alerts-observability-apm', + 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 @@ -354,7 +357,7 @@ describe('find()', () => { { found: true, _type: 'alert', - _index: '.alerts-observability-apm', + _index: '.alerts-observability.apm.alerts', _id: 'NoxgpHkBqbdrfX07MqXV', _version: 1, _seq_no: 362, @@ -378,7 +381,7 @@ describe('find()', () => { const alertsClient = new AlertsClient(alertsClientParams); const result = await alertsClient.find({ query: { match: { [ALERT_WORKFLOW_STATUS]: 'open' } }, - index: '.alerts-observability-apm', + index: '.alerts-observability.apm.alerts', }); expect(result).toMatchInlineSnapshot(` @@ -393,7 +396,7 @@ describe('find()', () => { "hits": Array [ Object { "_id": "NoxgpHkBqbdrfX07MqXV", - "_index": ".alerts-observability-apm", + "_index": ".alerts-observability.apm.alerts", "_primary_term": 2, "_seq_no": 362, "_source": Object { 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 2f299142166d6b..e04a04dbe3b8e7 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 @@ -18,6 +18,8 @@ import { elasticsearchClientMock } from 'src/core/server/elasticsearch/client/mo import { alertingAuthorizationMock } from '../../../../alerting/server/authorization/alerting_authorization.mock'; import { AuditLogger } from '../../../../security/server'; import { AlertingAuthorizationEntity } from '../../../../alerting/server'; +import { ruleDataPluginServiceMock } from '../../rule_data_plugin_service/rule_data_plugin_service.mock'; +import { RuleDataPluginService } from '../../rule_data_plugin_service'; const alertingAuthMock = alertingAuthorizationMock.create(); const esClientMock = elasticsearchClientMock.createElasticsearchClient(); @@ -30,6 +32,7 @@ const alertsClientParams: jest.Mocked = { authorization: alertingAuthMock, esClient: esClientMock, auditLogger, + ruleDataService: (ruleDataPluginServiceMock.create() as unknown) as RuleDataPluginService, }; const DEFAULT_SPACE = 'test_default_space_id'; @@ -91,7 +94,7 @@ describe('get()', () => { { found: true, _type: 'alert', - _index: '.alerts-observability-apm', + _index: '.alerts-observability.apm.alerts', _id: 'NoxgpHkBqbdrfX07MqXV', _version: 1, _seq_no: 362, @@ -109,7 +112,7 @@ describe('get()', () => { }, }) ); - const result = await alertsClient.get({ id: '1', index: '.alerts-observability-apm' }); + const result = await alertsClient.get({ id: '1', index: '.alerts-observability.apm.alerts' }); expect(result).toMatchInlineSnapshot(` Object { "kibana.alert.rule.consumer": "apm", @@ -173,7 +176,7 @@ describe('get()', () => { "track_total_hits": undefined, }, "ignore_unavailable": true, - "index": ".alerts-observability-apm", + "index": ".alerts-observability.apm.alerts", "seq_no_primary_term": true, }, ] @@ -200,7 +203,7 @@ describe('get()', () => { { found: true, _type: 'alert', - _index: '.alerts-observability-apm', + _index: '.alerts-observability.apm.alerts', _id: 'NoxgpHkBqbdrfX07MqXV', _version: 1, _seq_no: 362, @@ -218,7 +221,10 @@ describe('get()', () => { }, }) ); - await alertsClient.get({ id: 'NoxgpHkBqbdrfX07MqXV', index: '.alerts-observability-apm' }); + await alertsClient.get({ + id: 'NoxgpHkBqbdrfX07MqXV', + index: '.alerts-observability.apm.alerts', + }); expect(auditLogger.log).toHaveBeenCalledWith({ error: undefined, @@ -228,7 +234,7 @@ describe('get()', () => { }); test('audit error access if user is unauthorized for given alert', async () => { - const indexName = '.alerts-observability-apm.alerts'; + const indexName = '.alerts-observability.apm.alerts'; const fakeAlertId = 'myfakeid1'; // fakeRuleTypeId will cause authz to fail const fakeRuleTypeId = 'fake.rule'; @@ -269,7 +275,7 @@ describe('get()', () => { }) ); - await expect(alertsClient.get({ id: fakeAlertId, index: '.alerts-observability-apm.alerts' })) + await expect(alertsClient.get({ id: fakeAlertId, index: '.alerts-observability.apm.alerts' })) .rejects.toThrowErrorMatchingInlineSnapshot(` "Unable to retrieve alert details for alert with id of \\"myfakeid1\\" or with query \\"undefined\\" and operation get Error: Error: Unauthorized for fake.rule and apm" @@ -296,7 +302,7 @@ describe('get()', () => { esClientMock.search.mockRejectedValue(error); await expect( - alertsClient.get({ id: 'NoxgpHkBqbdrfX07MqXV', index: '.alerts-observability-apm' }) + alertsClient.get({ id: 'NoxgpHkBqbdrfX07MqXV', index: '.alerts-observability.apm.alerts' }) ).rejects.toThrowErrorMatchingInlineSnapshot(` "Unable to retrieve alert details for alert with id of \\"NoxgpHkBqbdrfX07MqXV\\" or with query \\"undefined\\" and operation get Error: Error: something went wrong" @@ -323,7 +329,7 @@ describe('get()', () => { { found: true, _type: 'alert', - _index: '.alerts-observability-apm', + _index: '.alerts-observability.apm.alerts', _id: 'NoxgpHkBqbdrfX07MqXV', _version: 1, _seq_no: 362, @@ -347,7 +353,7 @@ describe('get()', () => { const alertsClient = new AlertsClient(alertsClientParams); const result = await alertsClient.get({ id: 'NoxgpHkBqbdrfX07MqXV', - index: '.alerts-observability-apm', + index: '.alerts-observability.apm.alerts', }); expect(result).toMatchInlineSnapshot(` 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 90ca2da06ccdfa..b71bddff53696e 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 @@ -18,6 +18,8 @@ import { elasticsearchClientMock } from 'src/core/server/elasticsearch/client/mo import { alertingAuthorizationMock } from '../../../../alerting/server/authorization/alerting_authorization.mock'; import { AuditLogger } from '../../../../security/server'; import { AlertingAuthorizationEntity } from '../../../../alerting/server'; +import { ruleDataPluginServiceMock } from '../../rule_data_plugin_service/rule_data_plugin_service.mock'; +import { RuleDataPluginService } from '../../rule_data_plugin_service'; const alertingAuthMock = alertingAuthorizationMock.create(); const esClientMock = elasticsearchClientMock.createElasticsearchClient(); @@ -30,6 +32,7 @@ const alertsClientParams: jest.Mocked = { authorization: alertingAuthMock, esClient: esClientMock, auditLogger, + ruleDataService: (ruleDataPluginServiceMock.create() as unknown) as RuleDataPluginService, }; const DEFAULT_SPACE = 'test_default_space_id'; @@ -91,7 +94,7 @@ describe('update()', () => { { found: true, _type: 'alert', - _index: '.alerts-observability-apm', + _index: '.alerts-observability.apm.alerts', _id: 'NoxgpHkBqbdrfX07MqXV', _source: { [ALERT_RULE_TYPE_ID]: 'apm.error_rate', @@ -109,7 +112,7 @@ describe('update()', () => { esClientMock.update.mockResolvedValueOnce( elasticsearchClientMock.createApiResponse({ body: { - _index: '.alerts-observability-apm', + _index: '.alerts-observability.apm.alerts', _id: 'NoxgpHkBqbdrfX07MqXV', _version: 2, result: 'updated', @@ -123,12 +126,12 @@ describe('update()', () => { id: '1', status: 'closed', _version: undefined, - index: '.alerts-observability-apm', + index: '.alerts-observability.apm.alerts', }); expect(result).toMatchInlineSnapshot(` Object { "_id": "NoxgpHkBqbdrfX07MqXV", - "_index": ".alerts-observability-apm", + "_index": ".alerts-observability.apm.alerts", "_primary_term": 1, "_seq_no": 1, "_shards": Object { @@ -150,7 +153,7 @@ describe('update()', () => { }, }, "id": "1", - "index": ".alerts-observability-apm", + "index": ".alerts-observability.apm.alerts", "refresh": "wait_for", }, ] @@ -177,7 +180,7 @@ describe('update()', () => { { found: true, _type: 'alert', - _index: '.alerts-observability-apm', + _index: '.alerts-observability.apm.alerts', _id: 'NoxgpHkBqbdrfX07MqXV', _source: { [ALERT_RULE_TYPE_ID]: 'apm.error_rate', @@ -195,7 +198,7 @@ describe('update()', () => { esClientMock.update.mockResolvedValueOnce( elasticsearchClientMock.createApiResponse({ body: { - _index: '.alerts-observability-apm', + _index: '.alerts-observability.apm.alerts', _id: 'NoxgpHkBqbdrfX07MqXV', _version: 2, result: 'updated', @@ -209,7 +212,7 @@ describe('update()', () => { id: 'NoxgpHkBqbdrfX07MqXV', status: 'closed', _version: undefined, - index: '.alerts-observability-apm', + index: '.alerts-observability.apm.alerts', }); expect(auditLogger.log).toHaveBeenCalledWith({ @@ -225,7 +228,7 @@ describe('update()', () => { }); test('audit error update if user is unauthorized for given alert', async () => { - const indexName = '.alerts-observability-apm.alerts'; + const indexName = '.alerts-observability.apm.alerts'; const fakeAlertId = 'myfakeid1'; // fakeRuleTypeId will cause authz to fail const fakeRuleTypeId = 'fake.rule'; @@ -271,7 +274,7 @@ describe('update()', () => { id: fakeAlertId, status: 'closed', _version: '1', - index: '.alerts-observability-apm', + index: '.alerts-observability.apm.alerts', }) ).rejects.toThrowErrorMatchingInlineSnapshot(` "Unable to retrieve alert details for alert with id of \\"myfakeid1\\" or with query \\"undefined\\" and operation update @@ -303,7 +306,7 @@ describe('update()', () => { id: 'NoxgpHkBqbdrfX07MqXV', status: 'closed', _version: undefined, - index: '.alerts-observability-apm', + index: '.alerts-observability.apm.alerts', }) ).rejects.toThrowErrorMatchingInlineSnapshot(` "Unable to retrieve alert details for alert with id of \\"NoxgpHkBqbdrfX07MqXV\\" or with query \\"undefined\\" and operation update @@ -332,7 +335,7 @@ describe('update()', () => { { found: true, _type: 'alert', - _index: '.alerts-observability-apm', + _index: '.alerts-observability.apm.alerts', _id: 'NoxgpHkBqbdrfX07MqXV', _source: { [ALERT_RULE_TYPE_ID]: 'apm.error_rate', @@ -354,7 +357,7 @@ describe('update()', () => { id: 'NoxgpHkBqbdrfX07MqXV', status: 'closed', _version: undefined, - index: '.alerts-observability-apm', + index: '.alerts-observability.apm.alerts', }) ).rejects.toThrowErrorMatchingInlineSnapshot(`"something went wrong on update"`); expect(auditLogger.log).toHaveBeenCalledWith({ @@ -389,7 +392,7 @@ describe('update()', () => { { found: true, _type: 'alert', - _index: '.alerts-observability-apm', + _index: '.alerts-observability.apm.alerts', _id: 'NoxgpHkBqbdrfX07MqXV', _version: 2, _seq_no: 362, @@ -411,7 +414,7 @@ describe('update()', () => { esClientMock.update.mockResolvedValueOnce( elasticsearchClientMock.createApiResponse({ body: { - _index: '.alerts-observability-apm', + _index: '.alerts-observability.apm.alerts', _id: 'NoxgpHkBqbdrfX07MqXV', _version: 2, result: 'updated', @@ -429,13 +432,13 @@ describe('update()', () => { id: 'NoxgpHkBqbdrfX07MqXV', status: 'closed', _version: undefined, - index: '.alerts-observability-apm', + index: '.alerts-observability.apm.alerts', }); expect(result).toMatchInlineSnapshot(` Object { "_id": "NoxgpHkBqbdrfX07MqXV", - "_index": ".alerts-observability-apm", + "_index": ".alerts-observability.apm.alerts", "_primary_term": 1, "_seq_no": 1, "_shards": Object { diff --git a/x-pack/plugins/rule_registry/server/plugin.ts b/x-pack/plugins/rule_registry/server/plugin.ts index ed6f19cd3af56e..cb1810420c2cd6 100644 --- a/x-pack/plugins/rule_registry/server/plugin.ts +++ b/x-pack/plugins/rule_registry/server/plugin.ts @@ -125,7 +125,7 @@ export class RuleRegistryPlugin core: CoreStart, plugins: RuleRegistryPluginStartDependencies ): RuleRegistryPluginStartContract { - const { logger, alertsClientFactory, security } = this; + const { logger, alertsClientFactory, ruleDataService, security } = this; alertsClientFactory.initialize({ logger, @@ -135,6 +135,7 @@ export class RuleRegistryPlugin return plugins.alerting.getAlertingAuthorizationWithRequest(request); }, securityPluginSetup: security, + ruleDataService, }); const getRacClientWithRequest = (request: KibanaRequest) => { 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 d591e01c9fff6a..6793bfceb34d2c 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 @@ -29,6 +29,6 @@ export const getUpdateRequest = () => body: { status: 'closed', ids: ['alert-1'], - index: '.alerts-observability-apm*', + index: '.alerts-observability.apm.alerts*', }, }); diff --git a/x-pack/plugins/rule_registry/server/routes/update_alert_by_id.test.ts b/x-pack/plugins/rule_registry/server/routes/update_alert_by_id.test.ts index 7ec699491ca83e..8d701bc224eda0 100644 --- a/x-pack/plugins/rule_registry/server/routes/update_alert_by_id.test.ts +++ b/x-pack/plugins/rule_registry/server/routes/update_alert_by_id.test.ts @@ -20,7 +20,7 @@ describe('updateAlertByIdRoute', () => { ({ clients, context } = requestContextMock.createTools()); clients.rac.update.mockResolvedValue({ - _index: '.alerts-observability-apm', + _index: '.alerts-observability.apm.alerts', _id: 'NoxgpHkBqbdrfX07MqXV', _version: 'WzM2MiwyXQ==', result: 'updated', @@ -37,7 +37,7 @@ describe('updateAlertByIdRoute', () => { expect(response.status).toEqual(200); expect(response.body).toEqual({ - _index: '.alerts-observability-apm', + _index: '.alerts-observability.apm.alerts', _id: 'NoxgpHkBqbdrfX07MqXV', _version: 'WzM2MiwyXQ==', result: 'updated', @@ -58,7 +58,7 @@ describe('updateAlertByIdRoute', () => { body: { status: 'closed', ids: 'alert-1', - index: '.alerts-observability-apm*', + index: '.alerts-observability.apm.alerts*', }, }), context @@ -77,7 +77,7 @@ describe('updateAlertByIdRoute', () => { body: { notStatus: 'closed', ids: ['alert-1'], - index: '.alerts-observability-apm*', + index: '.alerts-observability.apm.alerts*', }, }), context 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 f95ed8c6994b68..c50a982741b0c2 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 @@ -12,18 +12,17 @@ type Schema = PublicMethodsOf; const createRuleDataPluginService = () => { const mocked: jest.Mocked = { - getRegisteredIndexInfo: jest.fn(), getResourcePrefix: jest.fn(), getResourceName: jest.fn(), isWriteEnabled: jest.fn(), initializeService: jest.fn(), initializeIndex: jest.fn(), + findIndexByName: jest.fn(), + findIndicesByFeature: jest.fn(), }; return mocked; }; -export const ruleDataPluginServiceMock: { - create: () => jest.Mocked>; -} = { +export const ruleDataPluginServiceMock = { create: createRuleDataPluginService, }; 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 734518e86d172a..a417ba289d83a2 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 @@ -6,12 +6,13 @@ */ import { Either, isLeft, left, right } from 'fp-ts/lib/Either'; +import { ValidFeatureId } from '@kbn/rule-data-utils'; import { ElasticsearchClient, Logger } from 'kibana/server'; import { IRuleDataClient, RuleDataClient, WaitResult } from '../rule_data_client'; import { IndexInfo } from './index_info'; -import { IndexOptions } from './index_options'; +import { Dataset, IndexOptions } from './index_options'; import { ResourceInstaller } from './resource_installer'; import { joinWithDash } from './utils'; @@ -26,12 +27,16 @@ interface ConstructorOptions { * A service for creating and using Elasticsearch indices for alerts-as-data. */ export class RuleDataPluginService { + private readonly indicesByBaseName: Map; + private readonly indicesByFeatureId: Map; private readonly resourceInstaller: ResourceInstaller; private installCommonResources: Promise>; private isInitialized: boolean; - private registeredIndices: Map = new Map(); constructor(private readonly options: ConstructorOptions) { + this.indicesByBaseName = new Map(); + this.indicesByFeatureId = new Map(); + this.resourceInstaller = new ResourceInstaller({ getResourceName: (name) => this.getResourceName(name), getClusterClient: options.getClusterClient, @@ -106,7 +111,9 @@ export class RuleDataPluginService { indexOptions, }); - this.registeredIndices.set(indexOptions.registrationContext, indexInfo); + const indicesAssociatedWithFeature = this.indicesByFeatureId.get(indexOptions.feature) ?? []; + this.indicesByFeatureId.set(indexOptions.feature, [...indicesAssociatedWithFeature, indexInfo]); + this.indicesByBaseName.set(indexInfo.baseName, indexInfo); const waitUntilClusterClientAvailable = async (): Promise => { try { @@ -153,11 +160,19 @@ export class RuleDataPluginService { } /** - * Looks up the index information associated with the given `registrationContext`. - * @param registrationContext - * @returns the IndexInfo or undefined + * Looks up the index information associated with the given registration context and dataset. + */ + public findIndexByName(registrationContext: string, dataset: Dataset): IndexInfo | null { + const baseName = this.getResourceName(`${registrationContext}.${dataset}`); + return this.indicesByBaseName.get(baseName) ?? null; + } + + /** + * Looks up the index information associated with the given Kibana "feature". + * Note: features are used in RBAC. */ - public getRegisteredIndexInfo(registrationContext: string): IndexInfo | undefined { - return this.registeredIndices.get(registrationContext); + public findIndicesByFeature(featureId: ValidFeatureId, dataset?: Dataset): IndexInfo[] { + const foundIndices = this.indicesByFeatureId.get(featureId) ?? []; + return dataset ? foundIndices.filter((i) => i.indexOptions.dataset === dataset) : foundIndices; } } diff --git a/x-pack/plugins/rule_registry/server/scripts/bulk_update_observability_alert_by_ids.sh b/x-pack/plugins/rule_registry/server/scripts/bulk_update_observability_alert_by_ids.sh index 7c7c7d0ab679b4..460a514dd2f481 100755 --- a/x-pack/plugins/rule_registry/server/scripts/bulk_update_observability_alert_by_ids.sh +++ b/x-pack/plugins/rule_registry/server/scripts/bulk_update_observability_alert_by_ids.sh @@ -25,6 +25,6 @@ curl -s -k \ -H 'kbn-xsrf: 123' \ -u observer:changeme \ -X POST ${KIBANA_URL}${SPACE_URL}/internal/rac/alerts/bulk_update \ --d "{\"ids\": $IDS, \"status\":\"$STATUS\", \"index\":\".alerts-observability-apm\"}" | jq . -# -d "{\"ids\": $IDS, \"query\": \"kibana.rac.alert.status: open\", \"status\":\"$STATUS\", \"index\":\".alerts-observability-apm\"}" | jq . -# -d "{\"ids\": $IDS, \"status\":\"$STATUS\", \"index\":\".alerts-observability-apm\"}" | jq . +-d "{\"ids\": $IDS, \"status\":\"$STATUS\", \"index\":\".alerts-observability.apm.alerts\"}" | jq . +# -d "{\"ids\": $IDS, \"query\": \"kibana.rac.alert.status: open\", \"status\":\"$STATUS\", \"index\":\".alerts-observability.apm.alerts\"}" | jq . +# -d "{\"ids\": $IDS, \"status\":\"$STATUS\", \"index\":\".alerts-observability.apm.alerts\"}" | jq . diff --git a/x-pack/plugins/rule_registry/server/scripts/bulk_update_observability_alert_by_query.sh b/x-pack/plugins/rule_registry/server/scripts/bulk_update_observability_alert_by_query.sh index 4bcfd53b122999..8f04707c6c299d 100755 --- a/x-pack/plugins/rule_registry/server/scripts/bulk_update_observability_alert_by_query.sh +++ b/x-pack/plugins/rule_registry/server/scripts/bulk_update_observability_alert_by_query.sh @@ -25,4 +25,4 @@ curl -s -k \ -H 'kbn-xsrf: 123' \ -u observer:changeme \ -X POST ${KIBANA_URL}${SPACE_URL}/internal/rac/alerts/bulk_update \ --d "{\"query\": \"$QUERY\", \"status\":\"$STATUS\", \"index\":\".alerts-observability-apm\"}" | jq . +-d "{\"query\": \"$QUERY\", \"status\":\"$STATUS\", \"index\":\".alerts-observability.apm.alerts\"}" | jq . diff --git a/x-pack/plugins/rule_registry/server/scripts/find_observability_alert.sh b/x-pack/plugins/rule_registry/server/scripts/find_observability_alert.sh index 4c4ee5f75836c2..abdef9dfcb6460 100755 --- a/x-pack/plugins/rule_registry/server/scripts/find_observability_alert.sh +++ b/x-pack/plugins/rule_registry/server/scripts/find_observability_alert.sh @@ -26,4 +26,4 @@ curl -v \ -H 'kbn-xsrf: 123' \ -u observer:changeme \ -X POST ${KIBANA_URL}${SPACE_URL}/internal/rac/alerts/find \ --d "{\"query\": { \"match\": { \"kibana.alert.status\": \"open\" }}, \"index\":\".alerts-observability-apm\"}" | jq . \ No newline at end of file +-d "{\"query\": { \"match\": { \"kibana.alert.status\": \"open\" }}, \"index\":\".alerts-observability.apm.alerts\"}" | jq . diff --git a/x-pack/plugins/rule_registry/server/scripts/get_observability_alert.sh b/x-pack/plugins/rule_registry/server/scripts/get_observability_alert.sh index 1b34910c2b737f..1aa6486f9b4033 100755 --- a/x-pack/plugins/rule_registry/server/scripts/get_observability_alert.sh +++ b/x-pack/plugins/rule_registry/server/scripts/get_observability_alert.sh @@ -19,4 +19,4 @@ cd .. # Example: ./get_observability_alert.sh hunter curl -v -k \ -u $USER:changeme \ - -X GET "${KIBANA_URL}${SPACE_URL}/internal/rac/alerts?id=$ID&index=.alerts-observability-apm" | jq . + -X GET "${KIBANA_URL}${SPACE_URL}/internal/rac/alerts?id=$ID&index=.alerts-observability.apm.alerts" | jq . diff --git a/x-pack/plugins/rule_registry/server/scripts/update_observability_alert.sh b/x-pack/plugins/rule_registry/server/scripts/update_observability_alert.sh index f61fcf2662aa37..d33ff3017b3813 100755 --- a/x-pack/plugins/rule_registry/server/scripts/update_observability_alert.sh +++ b/x-pack/plugins/rule_registry/server/scripts/update_observability_alert.sh @@ -25,4 +25,4 @@ curl -s -k \ -H 'kbn-xsrf: 123' \ -u observer:changeme \ -X POST ${KIBANA_URL}${SPACE_URL}/internal/rac/alerts \ - -d "{\"ids\": $IDS, \"status\":\"$STATUS\", \"index\":\".alerts-observability-apm\"}" | jq . + -d "{\"ids\": $IDS, \"status\":\"$STATUS\", \"index\":\".alerts-observability.apm.alerts\"}" | jq . diff --git a/x-pack/plugins/uptime/server/lib/alerts/test_utils/index.ts b/x-pack/plugins/uptime/server/lib/alerts/test_utils/index.ts index 1927162f647723..f78ce1d198c7f2 100644 --- a/x-pack/plugins/uptime/server/lib/alerts/test_utils/index.ts +++ b/x-pack/plugins/uptime/server/lib/alerts/test_utils/index.ts @@ -73,7 +73,7 @@ export const createRuleTypeMocks = ( }; }, isWriteEnabled: jest.fn(() => true), - indexName: '.alerts-observability.synthetics.alerts', + indexName: '.alerts-observability.uptime.alerts', } as unknown) as IRuleDataClient, }, services, diff --git a/x-pack/test/functional/es_archives/rule_registry/alerts/data.json b/x-pack/test/functional/es_archives/rule_registry/alerts/data.json index 7291dd2c65fa52..284c6e9519cc1a 100644 --- a/x-pack/test/functional/es_archives/rule_registry/alerts/data.json +++ b/x-pack/test/functional/es_archives/rule_registry/alerts/data.json @@ -1,7 +1,7 @@ { "type": "doc", "value": { - "index": ".alerts-observability-apm", + "index": ".alerts-observability.apm.alerts", "id": "NoxgpHkBqbdrfX07MqXV", "source": { "event.kind" : "signal", @@ -18,7 +18,7 @@ { "type": "doc", "value": { - "index": ".alerts-observability-apm", + "index": ".alerts-observability.apm.alerts", "id": "space1alert", "source": { "event.kind" : "signal", @@ -35,7 +35,7 @@ { "type": "doc", "value": { - "index": ".alerts-observability-apm", + "index": ".alerts-observability.apm.alerts", "id": "space2alert", "source": { "event.kind" : "signal", diff --git a/x-pack/test/functional/es_archives/rule_registry/alerts/mappings.json b/x-pack/test/functional/es_archives/rule_registry/alerts/mappings.json index 943457ad6cd85d..f55241f25c90e6 100644 --- a/x-pack/test/functional/es_archives/rule_registry/alerts/mappings.json +++ b/x-pack/test/functional/es_archives/rule_registry/alerts/mappings.json @@ -1,7 +1,7 @@ { "type": "index", "value": { - "index": ".alerts-observability-apm", + "index": ".alerts-observability.apm.alerts", "mappings": { "properties": { "message": { 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 815b346c15d1a5..d9f04f206cb371 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 @@ -55,7 +55,7 @@ export default ({ getService }: FtrProviderContext) => { const SPACE1 = 'space1'; const SPACE2 = 'space2'; const APM_ALERT_ID = 'NoxgpHkBqbdrfX07MqXV'; - const APM_ALERT_INDEX = '.alerts-observability-apm'; + const APM_ALERT_INDEX = '.alerts-observability.apm.alerts'; const SECURITY_SOLUTION_ALERT_ID = '020202'; const SECURITY_SOLUTION_ALERT_INDEX = '.alerts-security.alerts'; 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 f6fcff64db3a3d..9b8c334c7f9da3 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 @@ -54,7 +54,7 @@ export default ({ getService }: FtrProviderContext) => { const SPACE1 = 'space1'; const SPACE2 = 'space2'; const APM_ALERT_ID = 'NoxgpHkBqbdrfX07MqXV'; - const APM_ALERT_INDEX = '.alerts-observability-apm'; + const APM_ALERT_INDEX = '.alerts-observability.apm.alerts'; const SECURITY_SOLUTION_ALERT_ID = '020202'; const SECURITY_SOLUTION_ALERT_INDEX = '.alerts-security.alerts'; diff --git a/x-pack/test/rule_registry/security_and_spaces/tests/basic/get_alert_by_id.ts b/x-pack/test/rule_registry/security_and_spaces/tests/basic/get_alert_by_id.ts index 1f1da40eee70ee..b968f8db176c81 100644 --- a/x-pack/test/rule_registry/security_and_spaces/tests/basic/get_alert_by_id.ts +++ b/x-pack/test/rule_registry/security_and_spaces/tests/basic/get_alert_by_id.ts @@ -54,7 +54,7 @@ export default ({ getService }: FtrProviderContext) => { const SPACE1 = 'space1'; const SPACE2 = 'space2'; const APM_ALERT_ID = 'NoxgpHkBqbdrfX07MqXV'; - const APM_ALERT_INDEX = '.alerts-observability-apm'; + const APM_ALERT_INDEX = '.alerts-observability.apm.alerts'; const SECURITY_SOLUTION_ALERT_ID = '020202'; const SECURITY_SOLUTION_ALERT_INDEX = '.alerts-security.alerts'; 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 348aedb258f7ef..df4bdf08d68509 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 @@ -53,7 +53,7 @@ export default ({ getService }: FtrProviderContext) => { const SPACE1 = 'space1'; const SPACE2 = 'space2'; const APM_ALERT_ID = 'NoxgpHkBqbdrfX07MqXV'; - const APM_ALERT_INDEX = '.alerts-observability-apm'; + const APM_ALERT_INDEX = '.alerts-observability.apm.alerts'; const SECURITY_SOLUTION_ALERT_ID = '020202'; const SECURITY_SOLUTION_ALERT_INDEX = '.alerts-security.alerts'; const ALERT_VERSION = Buffer.from(JSON.stringify([0, 1]), 'utf8').toString('base64'); // required for optimistic concurrency control 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 56c2ba94c5ad30..a97e9182c9b492 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 @@ -38,9 +38,9 @@ export default ({ getService }: FtrProviderContext) => { .set('kbn-xsrf', 'true') .expect(200); const observabilityIndex = indexNames?.index_name?.find( - (indexName) => indexName === '.alerts-observability-apm' + (indexName) => indexName === '.alerts-observability.apm.alerts' ); - expect(observabilityIndex).to.eql('.alerts-observability-apm'); + expect(observabilityIndex).to.eql('.alerts-observability.apm.alerts'); return observabilityIndex; }; 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 ffb79a0e52e123..0308573abf99ab 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 @@ -36,9 +36,9 @@ export default ({ getService }: FtrProviderContext) => { .set('kbn-xsrf', 'true') .expect(200); const observabilityIndex = indexNames?.index_name?.find( - (indexName) => indexName === '.alerts-observability-apm' + (indexName) => indexName === '.alerts-observability.apm.alerts' ); - expect(observabilityIndex).to.eql('.alerts-observability-apm'); + expect(observabilityIndex).to.eql('.alerts-observability.apm.alerts'); return observabilityIndex; }; @@ -107,7 +107,7 @@ export default ({ getService }: FtrProviderContext) => { .expect(200); expect(omit(['_version', '_seq_no'], res.body)).to.eql({ success: true, - _index: '.alerts-observability-apm', + _index: '.alerts-observability.apm.alerts', _id: 'NoxgpHkBqbdrfX07MqXV', result: 'updated', _shards: { total: 2, successful: 1, failed: 0 }, diff --git a/x-pack/test/rule_registry/spaces_only/tests/trial/get_alert_by_id.ts b/x-pack/test/rule_registry/spaces_only/tests/trial/get_alert_by_id.ts index 373acd9e8a8840..4cf7a9610b59bb 100644 --- a/x-pack/test/rule_registry/spaces_only/tests/trial/get_alert_by_id.ts +++ b/x-pack/test/rule_registry/spaces_only/tests/trial/get_alert_by_id.ts @@ -22,7 +22,7 @@ export default ({ getService }: FtrProviderContext) => { const SPACE1 = 'space1'; const SPACE2 = 'space2'; const APM_ALERT_ID = 'NoxgpHkBqbdrfX07MqXV'; - const APM_ALERT_INDEX = '.alerts-observability-apm'; + const APM_ALERT_INDEX = '.alerts-observability.apm.alerts'; const SECURITY_SOLUTION_ALERT_INDEX = '.alerts-security.alerts'; const getAPMIndexName = async (user: User) => { 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 24642059139408..040b8de49be90f 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 @@ -21,7 +21,7 @@ export default ({ getService }: FtrProviderContext) => { const SPACE1 = 'space1'; const SPACE2 = 'space2'; const APM_ALERT_ID = 'NoxgpHkBqbdrfX07MqXV'; - const APM_ALERT_INDEX = '.alerts-observability-apm'; + const APM_ALERT_INDEX = '.alerts-observability.apm.alerts'; const SECURITY_SOLUTION_ALERT_INDEX = '.alerts-security.alerts'; const ALERT_VERSION = Buffer.from(JSON.stringify([0, 1]), 'utf8').toString('base64'); // required for optimistic concurrency control