[RAC] Fix index names used by RBAC, delete hardcoded map of Kibana features to index names (#109567) (#110068)
**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 Co-authored-by: Georgii Gorbachev <georgii.gorbachev@elastic.co>
This commit is contained in:
parent
aa7680e3c1
commit
8db2bc1374
|
@ -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<AlertConsumers, string | string[]> = {
|
||||
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);
|
||||
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -72,7 +72,6 @@ export function AlertsPage({ routeParams }: AlertsPageProps) {
|
|||
registrationContexts: [
|
||||
'observability.apm',
|
||||
'observability.logs',
|
||||
'observability.infrastructure',
|
||||
'observability.metrics',
|
||||
'observability.uptime',
|
||||
],
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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<Obj extends {}, Props extends keyof Obj> = Omit<Obj, Props> &
|
||||
|
@ -71,6 +70,7 @@ export interface ConstructorOptions {
|
|||
authorization: PublicMethodsOf<AlertingAuthorization>;
|
||||
auditLogger?: AuditLogger;
|
||||
esClient: ElasticsearchClient;
|
||||
ruleDataService: RuleDataPluginService;
|
||||
}
|
||||
|
||||
export interface UpdateOptions<Params extends AlertTypeParams> {
|
||||
|
@ -115,15 +115,17 @@ export class AlertsClient {
|
|||
private readonly authorization: PublicMethodsOf<AlertingAuthorization>;
|
||||
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;
|
||||
|
|
|
@ -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,
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -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<AlertingAuthorization>;
|
||||
securityPluginSetup: SecurityPluginSetup | undefined;
|
||||
ruleDataService: RuleDataPluginService | null;
|
||||
}
|
||||
|
||||
export class AlertsClientFactory {
|
||||
|
@ -26,6 +28,7 @@ export class AlertsClientFactory {
|
|||
request: KibanaRequest
|
||||
) => PublicMethodsOf<AlertingAuthorization>;
|
||||
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<AlertsClient> {
|
||||
|
@ -50,6 +54,7 @@ export class AlertsClientFactory {
|
|||
authorization: getAlertingAuthorization(request),
|
||||
auditLogger: securityPluginSetup?.audit.asScoped(request),
|
||||
esClient: this.esClient,
|
||||
ruleDataService: this.ruleDataService!,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<ConstructorOptions> = {
|
|||
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',
|
||||
|
|
|
@ -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<ConstructorOptions> = {
|
|||
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 {
|
||||
|
|
|
@ -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<ConstructorOptions> = {
|
|||
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(`
|
||||
|
|
|
@ -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<ConstructorOptions> = {
|
|||
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 {
|
||||
|
|
|
@ -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) => {
|
||||
|
|
|
@ -29,6 +29,6 @@ export const getUpdateRequest = () =>
|
|||
body: {
|
||||
status: 'closed',
|
||||
ids: ['alert-1'],
|
||||
index: '.alerts-observability-apm*',
|
||||
index: '.alerts-observability.apm.alerts*',
|
||||
},
|
||||
});
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -12,18 +12,17 @@ type Schema = PublicMethodsOf<RuleDataPluginService>;
|
|||
|
||||
const createRuleDataPluginService = () => {
|
||||
const mocked: jest.Mocked<Schema> = {
|
||||
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<PublicMethodsOf<RuleDataPluginService>>;
|
||||
} = {
|
||||
export const ruleDataPluginServiceMock = {
|
||||
create: createRuleDataPluginService,
|
||||
};
|
||||
|
|
|
@ -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<string, IndexInfo>;
|
||||
private readonly indicesByFeatureId: Map<string, IndexInfo[]>;
|
||||
private readonly resourceInstaller: ResourceInstaller;
|
||||
private installCommonResources: Promise<Either<Error, 'ok'>>;
|
||||
private isInitialized: boolean;
|
||||
private registeredIndices: Map<string, IndexInfo> = 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<WaitResult> => {
|
||||
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 getRegisteredIndexInfo(registrationContext: string): IndexInfo | undefined {
|
||||
return this.registeredIndices.get(registrationContext);
|
||||
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 findIndicesByFeature(featureId: ValidFeatureId, dataset?: Dataset): IndexInfo[] {
|
||||
const foundIndices = this.indicesByFeatureId.get(featureId) ?? [];
|
||||
return dataset ? foundIndices.filter((i) => i.indexOptions.dataset === dataset) : foundIndices;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 .
|
||||
|
|
|
@ -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 .
|
||||
|
|
|
@ -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 .
|
||||
-d "{\"query\": { \"match\": { \"kibana.alert.status\": \"open\" }}, \"index\":\".alerts-observability.apm.alerts\"}" | jq .
|
||||
|
|
|
@ -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 .
|
||||
|
|
|
@ -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 .
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"type": "index",
|
||||
"value": {
|
||||
"index": ".alerts-observability-apm",
|
||||
"index": ".alerts-observability.apm.alerts",
|
||||
"mappings": {
|
||||
"properties": {
|
||||
"message": {
|
||||
|
|
|
@ -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';
|
||||
|
||||
|
|
|
@ -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';
|
||||
|
||||
|
|
|
@ -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';
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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 },
|
||||
|
|
|
@ -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) => {
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in a new issue