From 05f0e25382a74487b4cb3712c806efff72825da1 Mon Sep 17 00:00:00 2001 From: Dominique Belcher Date: Wed, 14 Aug 2024 21:47:43 -0400 Subject: [PATCH 01/15] slo - remove manage_transform and manage_ingest_pipeline privilege requirement by using secondary auth --- .../slo/server/routes/slo/route.ts | 75 ++++++++++++------- .../slo/server/services/create_slo.ts | 14 ++-- .../slo/server/services/delete_slo.ts | 7 +- .../slo/server/services/get_diagnosis.ts | 2 +- .../slo/server/services/reset_slo.ts | 14 ++-- .../services/summay_transform_manager.ts | 31 +++++--- .../slo/server/services/transform_manager.ts | 29 ++++--- .../slo/server/services/update_slo.ts | 27 ++++--- 8 files changed, 127 insertions(+), 72 deletions(-) diff --git a/x-pack/plugins/observability_solution/slo/server/routes/slo/route.ts b/x-pack/plugins/observability_solution/slo/server/routes/slo/route.ts index 3a06e653c8159..0e66998470c9f 100644 --- a/x-pack/plugins/observability_solution/slo/server/routes/slo/route.ts +++ b/x-pack/plugins/observability_solution/slo/server/routes/slo/route.ts @@ -105,27 +105,30 @@ const createSLORoute = createSloServerRoute({ const dataViews = await dependencies.getDataViewsStart(); const spaceId = (await spaces?.spacesService?.getActiveSpace(request))?.id ?? 'default'; - const esClient = (await context.core).elasticsearch.client.asCurrentUser; + const core = await context.core; + const scopedClusterClient = core.elasticsearch.client; + const esClient = core.elasticsearch.client.asCurrentUser; const basePath = dependencies.pluginsSetup.core.http.basePath; - const soClient = (await context.core).savedObjects.client; + const soClient = core.savedObjects.client; const repository = new KibanaSavedObjectsSLORepository(soClient, logger); const dataViewsService = await dataViews.dataViewsServiceFactory(soClient, esClient); const transformManager = new DefaultTransformManager( transformGenerators, - esClient, + scopedClusterClient, logger, spaceId, dataViewsService ); const summaryTransformManager = new DefaultSummaryTransformManager( new DefaultSummaryTransformGenerator(), - esClient, + scopedClusterClient, logger ); const createSLO = new CreateSLO( esClient, + scopedClusterClient, repository, transformManager, summaryTransformManager, @@ -154,25 +157,28 @@ const inspectSLORoute = createSloServerRoute({ const dataViews = await dependencies.getDataViewsStart(); const spaceId = (await spaces?.spacesService?.getActiveSpace(request))?.id ?? 'default'; const basePath = dependencies.pluginsSetup.core.http.basePath; - const esClient = (await context.core).elasticsearch.client.asCurrentUser; - const soClient = (await context.core).savedObjects.client; + const core = await context.core; + const scopedClusterClient = core.elasticsearch.client; + const esClient = core.elasticsearch.client.asCurrentUser; + const soClient = core.savedObjects.client; const repository = new KibanaSavedObjectsSLORepository(soClient, logger); const dataViewsService = await dataViews.dataViewsServiceFactory(soClient, esClient); const transformManager = new DefaultTransformManager( transformGenerators, - esClient, + scopedClusterClient, logger, spaceId, dataViewsService ); const summaryTransformManager = new DefaultSummaryTransformManager( new DefaultSummaryTransformGenerator(), - esClient, + scopedClusterClient, logger ); const createSLO = new CreateSLO( esClient, + scopedClusterClient, repository, transformManager, summaryTransformManager, @@ -200,20 +206,22 @@ const updateSLORoute = createSloServerRoute({ const dataViews = await dependencies.getDataViewsStart(); const basePath = dependencies.pluginsSetup.core.http.basePath; - const esClient = (await context.core).elasticsearch.client.asCurrentUser; - const soClient = (await context.core).savedObjects.client; + const core = await context.core; + const scopedClusterClient = core.elasticsearch.client; + const esClient = core.elasticsearch.client.asCurrentUser; + const soClient = core.savedObjects.client; const dataViewsService = await dataViews.dataViewsServiceFactory(soClient, esClient); const repository = new KibanaSavedObjectsSLORepository(soClient, logger); const transformManager = new DefaultTransformManager( transformGenerators, - esClient, + scopedClusterClient, logger, spaceId, dataViewsService ); const summaryTransformManager = new DefaultSummaryTransformManager( new DefaultSummaryTransformGenerator(), - esClient, + scopedClusterClient, logger ); @@ -222,6 +230,7 @@ const updateSLORoute = createSloServerRoute({ transformManager, summaryTransformManager, esClient, + scopedClusterClient, logger, spaceId, basePath @@ -247,8 +256,10 @@ const deleteSLORoute = createSloServerRoute({ const spaceId = (await spaces?.spacesService?.getActiveSpace(request))?.id ?? 'default'; const dataViews = await dependencies.getDataViewsStart(); - const esClient = (await context.core).elasticsearch.client.asCurrentUser; - const soClient = (await context.core).savedObjects.client; + const core = await context.core; + const scopedClusterClient = core.elasticsearch.client; + const esClient = core.elasticsearch.client.asCurrentUser; + const soClient = core.savedObjects.client; const rulesClient = await dependencies.getRulesClientWithRequest(request); const dataViewsService = await dataViews.dataViewsServiceFactory(soClient, esClient); @@ -256,7 +267,7 @@ const deleteSLORoute = createSloServerRoute({ const repository = new KibanaSavedObjectsSLORepository(soClient, logger); const transformManager = new DefaultTransformManager( transformGenerators, - esClient, + scopedClusterClient, logger, spaceId, dataViewsService @@ -264,7 +275,7 @@ const deleteSLORoute = createSloServerRoute({ const summaryTransformManager = new DefaultSummaryTransformManager( new DefaultSummaryTransformGenerator(), - esClient, + scopedClusterClient, logger ); @@ -273,6 +284,7 @@ const deleteSLORoute = createSloServerRoute({ transformManager, summaryTransformManager, esClient, + scopedClusterClient, rulesClient ); @@ -319,20 +331,22 @@ const enableSLORoute = createSloServerRoute({ const spaceId = (await spaces?.spacesService?.getActiveSpace(request))?.id ?? 'default'; const dataViews = await dependencies.getDataViewsStart(); - const soClient = (await context.core).savedObjects.client; - const esClient = (await context.core).elasticsearch.client.asCurrentUser; + const core = await context.core; + const scopedClusterClient = core.elasticsearch.client; + const soClient = core.savedObjects.client; + const esClient = core.elasticsearch.client.asCurrentUser; const dataViewsService = await dataViews.dataViewsServiceFactory(soClient, esClient); const repository = new KibanaSavedObjectsSLORepository(soClient, logger); const transformManager = new DefaultTransformManager( transformGenerators, - esClient, + scopedClusterClient, logger, spaceId, dataViewsService ); const summaryTransformManager = new DefaultSummaryTransformManager( new DefaultSummaryTransformGenerator(), - esClient, + scopedClusterClient, logger ); @@ -358,20 +372,22 @@ const disableSLORoute = createSloServerRoute({ const spaceId = (await spaces?.spacesService?.getActiveSpace(request))?.id ?? 'default'; const dataViews = await dependencies.getDataViewsStart(); - const soClient = (await context.core).savedObjects.client; - const esClient = (await context.core).elasticsearch.client.asCurrentUser; + const core = await context.core; + const scopedClusterClient = core.elasticsearch.client; + const soClient = core.savedObjects.client; + const esClient = core.elasticsearch.client.asCurrentUser; const dataViewsService = await dataViews.dataViewsServiceFactory(soClient, esClient); const repository = new KibanaSavedObjectsSLORepository(soClient, logger); const transformManager = new DefaultTransformManager( transformGenerators, - esClient, + scopedClusterClient, logger, spaceId, dataViewsService ); const summaryTransformManager = new DefaultSummaryTransformManager( new DefaultSummaryTransformGenerator(), - esClient, + scopedClusterClient, logger ); @@ -396,27 +412,30 @@ const resetSLORoute = createSloServerRoute({ const spaces = await dependencies.getSpacesStart(); const dataViews = await dependencies.getDataViewsStart(); const spaceId = (await spaces?.spacesService?.getActiveSpace(request))?.id ?? 'default'; - const soClient = (await context.core).savedObjects.client; - const esClient = (await context.core).elasticsearch.client.asCurrentUser; + const core = await context.core; + const scopedClusterClient = core.elasticsearch.client; + const soClient = core.savedObjects.client; + const esClient = core.elasticsearch.client.asCurrentUser; const basePath = dependencies.pluginsSetup.core.http.basePath; const dataViewsService = await dataViews.dataViewsServiceFactory(soClient, esClient); const repository = new KibanaSavedObjectsSLORepository(soClient, logger); const transformManager = new DefaultTransformManager( transformGenerators, - esClient, + scopedClusterClient, logger, spaceId, dataViewsService ); const summaryTransformManager = new DefaultSummaryTransformManager( new DefaultSummaryTransformGenerator(), - esClient, + scopedClusterClient, logger ); const resetSLO = new ResetSLO( esClient, + scopedClusterClient, repository, transformManager, summaryTransformManager, diff --git a/x-pack/plugins/observability_solution/slo/server/services/create_slo.ts b/x-pack/plugins/observability_solution/slo/server/services/create_slo.ts index f3abb8554f3dd..0f6885dd44c6c 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/create_slo.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/create_slo.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - +import { IScopedClusterClient } from '@kbn/core/server'; import { TransformPutTransformRequest } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { ElasticsearchClient, IBasePath, Logger } from '@kbn/core/server'; import { ALL_VALUE, CreateSLOParams, CreateSLOResponse } from '@kbn/slo-schema'; @@ -32,6 +32,7 @@ import { getTransformQueryComposite } from './utils/get_transform_compite_query' export class CreateSLO { constructor( private esClient: ElasticsearchClient, + private scopedClusterClient: IScopedClusterClient, private repository: SLORepository, private transformManager: TransformManager, private summaryTransformManager: TransformManager, @@ -53,11 +54,14 @@ export class CreateSLO { const summaryTransformId = getSLOSummaryTransformId(slo.id, slo.revision); try { await retryTransientEsErrors( - () => this.esClient.ingest.putPipeline(getSLOPipelineTemplate(slo)), + () => + this.scopedClusterClient.asSecondaryAuthUser.ingest.putPipeline( + getSLOPipelineTemplate(slo) + ), { logger: this.logger } ); rollbackOperations.push(() => - this.esClient.ingest.deletePipeline( + this.scopedClusterClient.asSecondaryAuthUser.ingest.deletePipeline( { id: getSLOPipelineId(slo.id, slo.revision) }, { ignore: [404] } ) @@ -71,13 +75,13 @@ export class CreateSLO { await retryTransientEsErrors( () => - this.esClient.ingest.putPipeline( + this.scopedClusterClient.asSecondaryAuthUser.ingest.putPipeline( getSLOSummaryPipelineTemplate(slo, this.spaceId, this.basePath) ), { logger: this.logger } ); rollbackOperations.push(() => - this.esClient.ingest.deletePipeline( + this.scopedClusterClient.asSecondaryAuthUser.ingest.deletePipeline( { id: getSLOSummaryPipelineId(slo.id, slo.revision) }, { ignore: [404] } ) diff --git a/x-pack/plugins/observability_solution/slo/server/services/delete_slo.ts b/x-pack/plugins/observability_solution/slo/server/services/delete_slo.ts index 9bd64727e286b..e86fab0a1620d 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/delete_slo.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/delete_slo.ts @@ -6,7 +6,7 @@ */ import { RulesClientApi } from '@kbn/alerting-plugin/server/types'; -import { ElasticsearchClient } from '@kbn/core/server'; +import { ElasticsearchClient, IScopedClusterClient } from '@kbn/core/server'; import { getSLOPipelineId, getSLOSummaryPipelineId, @@ -25,6 +25,7 @@ export class DeleteSLO { private transformManager: TransformManager, private summaryTransformManager: TransformManager, private esClient: ElasticsearchClient, + private scopedClusterClient: IScopedClusterClient, private rulesClient: RulesClientApi ) {} @@ -40,14 +41,14 @@ export class DeleteSLO { await this.transformManager.uninstall(rollupTransformId); await retryTransientEsErrors(() => - this.esClient.ingest.deletePipeline( + this.scopedClusterClient.asSecondaryAuthUser.ingest.deletePipeline( { id: getSLOPipelineId(slo.id, slo.revision) }, { ignore: [404] } ) ); await retryTransientEsErrors(() => - this.esClient.ingest.deletePipeline( + this.scopedClusterClient.asSecondaryAuthUser.ingest.deletePipeline( { id: getSLOSummaryPipelineId(slo.id, slo.revision) }, { ignore: [404] } ) diff --git a/x-pack/plugins/observability_solution/slo/server/services/get_diagnosis.ts b/x-pack/plugins/observability_solution/slo/server/services/get_diagnosis.ts index 38c183316a591..5b16598e816d5 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/get_diagnosis.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/get_diagnosis.ts @@ -14,7 +14,7 @@ export async function getGlobalDiagnosis( ) { const licenseInfo = licensing.license.toJSON(); const userWritePrivileges = await esClient.security.hasPrivileges({ - cluster: ['manage_transform', 'manage_ingest_pipelines'], + cluster: [], index: [{ names: '.slo-*', privileges: ['all'] }], }); const userReadPrivileges = await esClient.security.hasPrivileges({ diff --git a/x-pack/plugins/observability_solution/slo/server/services/reset_slo.ts b/x-pack/plugins/observability_solution/slo/server/services/reset_slo.ts index 3eb5dc6d89672..f69651ff2ad8a 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/reset_slo.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/reset_slo.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { ElasticsearchClient, IBasePath, Logger } from '@kbn/core/server'; +import { ElasticsearchClient, IBasePath, Logger, IScopedClusterClient } from '@kbn/core/server'; import { resetSLOResponseSchema } from '@kbn/slo-schema'; import { getSLOPipelineId, @@ -27,6 +27,7 @@ import { TransformManager } from './transform_manager'; export class ResetSLO { constructor( private esClient: ElasticsearchClient, + private scopedClusterClient: IScopedClusterClient, private repository: SLORepository, private transformManager: TransformManager, private summaryTransformManager: TransformManager, @@ -50,7 +51,10 @@ export class ResetSLO { try { await retryTransientEsErrors( - () => this.esClient.ingest.putPipeline(getSLOPipelineTemplate(slo)), + () => + this.scopedClusterClient.asSecondaryAuthUser.ingest.putPipeline( + getSLOPipelineTemplate(slo) + ), { logger: this.logger } ); @@ -59,7 +63,7 @@ export class ResetSLO { await retryTransientEsErrors( () => - this.esClient.ingest.putPipeline( + this.scopedClusterClient.asSecondaryAuthUser.ingest.putPipeline( getSLOSummaryPipelineTemplate(slo, this.spaceId, this.basePath) ), { logger: this.logger } @@ -87,12 +91,12 @@ export class ResetSLO { await this.summaryTransformManager.uninstall(summaryTransformId); await this.transformManager.stop(rollupTransformId); await this.transformManager.uninstall(rollupTransformId); - await this.esClient.ingest.deletePipeline( + await this.scopedClusterClient.asSecondaryAuthUser.ingest.deletePipeline( { id: getSLOSummaryPipelineId(slo.id, slo.revision) }, { ignore: [404] } ); - await this.esClient.ingest.deletePipeline( + await this.scopedClusterClient.asSecondaryAuthUser.ingest.deletePipeline( { id: getSLOPipelineId(slo.id, slo.revision) }, { ignore: [404] } ); diff --git a/x-pack/plugins/observability_solution/slo/server/services/summay_transform_manager.ts b/x-pack/plugins/observability_solution/slo/server/services/summay_transform_manager.ts index 5529591a81e20..27d24e7fb5039 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/summay_transform_manager.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/summay_transform_manager.ts @@ -6,7 +6,7 @@ */ import { TransformPutTransformRequest } from '@elastic/elasticsearch/lib/api/types'; -import { ElasticsearchClient, Logger } from '@kbn/core/server'; +import { IScopedClusterClient, Logger } from '@kbn/core/server'; import { SLODefinition } from '../domain/models'; import { SecurityException } from '../errors'; import { retryTransientEsErrors } from '../utils/retry'; @@ -18,16 +18,19 @@ type TransformId = string; export class DefaultSummaryTransformManager implements TransformManager { constructor( private generator: SummaryTransformGenerator, - private esClient: ElasticsearchClient, + private scopedClusterClient: IScopedClusterClient, private logger: Logger ) {} async install(slo: SLODefinition): Promise { const transformParams = await this.generator.generate(slo); try { - await retryTransientEsErrors(() => this.esClient.transform.putTransform(transformParams), { - logger: this.logger, - }); + await retryTransientEsErrors( + () => this.scopedClusterClient.asSecondaryAuthUser.transform.putTransform(transformParams), + { + logger: this.logger, + } + ); } catch (err) { this.logger.error(`Cannot create summary transform for SLO [${slo.id}]`); if (err.meta?.body?.error?.type === 'security_exception') { @@ -47,7 +50,10 @@ export class DefaultSummaryTransformManager implements TransformManager { async preview(transformId: string): Promise { try { await retryTransientEsErrors( - () => this.esClient.transform.previewTransform({ transform_id: transformId }), + () => + this.scopedClusterClient.asSecondaryAuthUser.transform.previewTransform({ + transform_id: transformId, + }), { logger: this.logger } ); } catch (err) { @@ -60,8 +66,13 @@ export class DefaultSummaryTransformManager implements TransformManager { try { await retryTransientEsErrors( () => - this.esClient.transform.startTransform({ transform_id: transformId }, { ignore: [409] }), - { logger: this.logger } + this.scopedClusterClient.asSecondaryAuthUser.transform.startTransform( + { transform_id: transformId }, + { ignore: [409] } + ), + { + logger: this.logger, + } ); } catch (err) { this.logger.error(`Cannot start SLO summary transform [${transformId}]`); @@ -73,7 +84,7 @@ export class DefaultSummaryTransformManager implements TransformManager { try { await retryTransientEsErrors( () => - this.esClient.transform.stopTransform( + this.scopedClusterClient.asSecondaryAuthUser.transform.stopTransform( { transform_id: transformId, wait_for_completion: true, force: true }, { ignore: [404] } ), @@ -89,7 +100,7 @@ export class DefaultSummaryTransformManager implements TransformManager { try { await retryTransientEsErrors( () => - this.esClient.transform.deleteTransform( + this.scopedClusterClient.asSecondaryAuthUser.transform.deleteTransform( { transform_id: transformId, force: true }, { ignore: [404] } ), diff --git a/x-pack/plugins/observability_solution/slo/server/services/transform_manager.ts b/x-pack/plugins/observability_solution/slo/server/services/transform_manager.ts index 822817962a2e9..7e5ddce8bcad6 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/transform_manager.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/transform_manager.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { ElasticsearchClient, Logger } from '@kbn/core/server'; +import { IScopedClusterClient, Logger } from '@kbn/core/server'; import { TransformPutTransformRequest } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { DataViewsService } from '@kbn/data-views-plugin/server'; @@ -28,7 +28,7 @@ export interface TransformManager { export class DefaultTransformManager implements TransformManager { constructor( private generators: Record, - private esClient: ElasticsearchClient, + private scopedClusterClient: IScopedClusterClient, private logger: Logger, private spaceId: string, private dataViewService: DataViewsService @@ -47,9 +47,12 @@ export class DefaultTransformManager implements TransformManager { this.dataViewService ); try { - await retryTransientEsErrors(() => this.esClient.transform.putTransform(transformParams), { - logger: this.logger, - }); + await retryTransientEsErrors( + () => this.scopedClusterClient.asSecondaryAuthUser.transform.putTransform(transformParams), + { + logger: this.logger, + } + ); } catch (err) { this.logger.error(`Cannot create SLO transform for indicator type [${slo.indicator.type}]`); if (err.meta?.body?.error?.type === 'security_exception') { @@ -75,7 +78,10 @@ export class DefaultTransformManager implements TransformManager { async preview(transformId: string): Promise { try { await retryTransientEsErrors( - () => this.esClient.transform.previewTransform({ transform_id: transformId }), + () => + this.scopedClusterClient.asSecondaryAuthUser.transform.previewTransform({ + transform_id: transformId, + }), { logger: this.logger } ); } catch (err) { @@ -88,7 +94,10 @@ export class DefaultTransformManager implements TransformManager { try { await retryTransientEsErrors( () => - this.esClient.transform.startTransform({ transform_id: transformId }, { ignore: [409] }), + this.scopedClusterClient.asSecondaryAuthUser.transform.startTransform( + { transform_id: transformId }, + { ignore: [409] } + ), { logger: this.logger } ); await this.scheduleNowTransform(transformId); @@ -102,7 +111,7 @@ export class DefaultTransformManager implements TransformManager { try { await retryTransientEsErrors( () => - this.esClient.transform.stopTransform( + this.scopedClusterClient.asSecondaryAuthUser.transform.stopTransform( { transform_id: transformId, wait_for_completion: true, force: true }, { ignore: [404] } ), @@ -118,7 +127,7 @@ export class DefaultTransformManager implements TransformManager { try { await retryTransientEsErrors( () => - this.esClient.transform.deleteTransform( + this.scopedClusterClient.asSecondaryAuthUser.transform.deleteTransform( { transform_id: transformId, force: true }, { ignore: [404] } ), @@ -131,7 +140,7 @@ export class DefaultTransformManager implements TransformManager { } async scheduleNowTransform(transformId: TransformId) { - this.esClient.transform + this.scopedClusterClient.asSecondaryAuthUser.transform .scheduleNowTransform({ transform_id: transformId }) .then(() => { this.logger.debug(`SLO transform [${transformId}] scheduled now successfully`); diff --git a/x-pack/plugins/observability_solution/slo/server/services/update_slo.ts b/x-pack/plugins/observability_solution/slo/server/services/update_slo.ts index 3175402eb1476..0f1967800d1df 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/update_slo.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/update_slo.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { ElasticsearchClient, IBasePath, Logger } from '@kbn/core/server'; +import { ElasticsearchClient, IBasePath, Logger, IScopedClusterClient } from '@kbn/core/server'; import { UpdateSLOParams, UpdateSLOResponse, updateSLOResponseSchema } from '@kbn/slo-schema'; import { asyncForEach } from '@kbn/std'; import { isEqual, pick } from 'lodash'; @@ -34,6 +34,7 @@ export class UpdateSLO { private transformManager: TransformManager, private summaryTransformManager: TransformManager, private esClient: ElasticsearchClient, + private scopedClusterClient: IScopedClusterClient, private logger: Logger, private spaceId: string, private basePath: IBasePath @@ -77,11 +78,14 @@ export class UpdateSLO { try { await retryTransientEsErrors( - () => this.esClient.ingest.putPipeline(getSLOPipelineTemplate(updatedSlo)), + () => + this.scopedClusterClient.asSecondaryAuthUser.ingest.putPipeline( + getSLOPipelineTemplate(updatedSlo) + ), { logger: this.logger } ); rollbackOperations.push(() => - this.esClient.ingest.deletePipeline( + this.scopedClusterClient.asSecondaryAuthUser.ingest.deletePipeline( { id: getSLOPipelineId(updatedSlo.id, updatedSlo.revision) }, { ignore: [404] } ) @@ -89,7 +93,7 @@ export class UpdateSLO { await retryTransientEsErrors( () => - this.esClient.ingest.putPipeline( + this.scopedClusterClient.asSecondaryAuthUser.ingest.putPipeline( getSLOSummaryPipelineTemplate(updatedSlo, this.spaceId, this.basePath) ), { logger: this.logger } @@ -122,11 +126,14 @@ export class UpdateSLO { try { await retryTransientEsErrors( - () => this.esClient.ingest.putPipeline(getSLOPipelineTemplate(updatedSlo)), + () => + this.scopedClusterClient.asSecondaryAuthUser.ingest.putPipeline( + getSLOPipelineTemplate(updatedSlo) + ), { logger: this.logger } ); rollbackOperations.push(() => - this.esClient.ingest.deletePipeline( + this.scopedClusterClient.asSecondaryAuthUser.ingest.deletePipeline( { id: getSLOPipelineId(updatedSlo.id, updatedSlo.revision) }, { ignore: [404] } ) @@ -140,13 +147,13 @@ export class UpdateSLO { await retryTransientEsErrors( () => - this.esClient.ingest.putPipeline( + this.scopedClusterClient.asSecondaryAuthUser.ingest.putPipeline( getSLOSummaryPipelineTemplate(updatedSlo, this.spaceId, this.basePath) ), { logger: this.logger } ); rollbackOperations.push(() => - this.esClient.ingest.deletePipeline( + this.scopedClusterClient.asSecondaryAuthUser.ingest.deletePipeline( { id: getSLOSummaryPipelineId(updatedSlo.id, updatedSlo.revision) }, { ignore: [404] } ) @@ -208,12 +215,12 @@ export class UpdateSLO { await this.summaryTransformManager.stop(originalSummaryTransformId); await this.summaryTransformManager.uninstall(originalSummaryTransformId); - await this.esClient.ingest.deletePipeline( + await this.scopedClusterClient.asSecondaryAuthUser.ingest.deletePipeline( { id: getSLOSummaryPipelineId(originalSlo.id, originalSlo.revision) }, { ignore: [404] } ); - await this.esClient.ingest.deletePipeline( + await this.scopedClusterClient.asSecondaryAuthUser.ingest.deletePipeline( { id: getSLOPipelineId(originalSlo.id, originalSlo.revision) }, { ignore: [404] } ); From 1e2478342a8a8752b4d5663a639a6d4121c2a2cf Mon Sep 17 00:00:00 2001 From: Dominique Belcher Date: Thu, 15 Aug 2024 15:02:03 -0400 Subject: [PATCH 02/15] adjust tests --- .../slo/server/services/create_slo.test.ts | 20 +++++++-- .../slo/server/services/delete_slo.test.ts | 7 ++- .../slo/server/services/reset_slo.test.ts | 6 ++- .../server/services/transform_manager.test.ts | 45 ++++++++++++------- .../slo/server/services/update_slo.test.ts | 16 ++++--- 5 files changed, 67 insertions(+), 27 deletions(-) diff --git a/x-pack/plugins/observability_solution/slo/server/services/create_slo.test.ts b/x-pack/plugins/observability_solution/slo/server/services/create_slo.test.ts index 1acc263a2d655..9499294eeb89b 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/create_slo.test.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/create_slo.test.ts @@ -10,6 +10,7 @@ import { elasticsearchServiceMock, httpServiceMock, loggingSystemMock, + ScopedClusterClientMock, } from '@kbn/core/server/mocks'; import { MockedLogger } from '@kbn/logging-mocks'; import { CreateSLO } from './create_slo'; @@ -25,6 +26,7 @@ import { TransformManager } from './transform_manager'; describe('CreateSLO', () => { let mockEsClient: ElasticsearchClientMock; + let mockScopedClusterClient: ScopedClusterClientMock; let mockLogger: jest.Mocked; let mockRepository: jest.Mocked; let mockTransformManager: jest.Mocked; @@ -35,12 +37,14 @@ describe('CreateSLO', () => { beforeEach(() => { mockEsClient = elasticsearchServiceMock.createElasticsearchClient(); + mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); mockLogger = loggingSystemMock.createLogger(); mockRepository = createSLORepositoryMock(); mockTransformManager = createTransformManagerMock(); mockSummaryTransformManager = createSummaryTransformManagerMock(); createSLO = new CreateSLO( mockEsClient, + mockScopedClusterClient, mockRepository, mockTransformManager, mockSummaryTransformManager, @@ -82,7 +86,9 @@ describe('CreateSLO', () => { expect(mockTransformManager.install).toHaveBeenCalled(); expect(mockTransformManager.start).toHaveBeenCalled(); - expect(mockEsClient.ingest.putPipeline.mock.calls[0]).toMatchSnapshot(); + expect( + mockScopedClusterClient.asSecondaryAuthUser.ingest.putPipeline.mock.calls[0] + ).toMatchSnapshot(); expect(mockSummaryTransformManager.install).toHaveBeenCalled(); expect(mockSummaryTransformManager.start).toHaveBeenCalled(); expect(mockEsClient.index.mock.calls[0]).toMatchSnapshot(); @@ -165,7 +171,9 @@ describe('CreateSLO', () => { ); expect(mockRepository.deleteById).toHaveBeenCalled(); - expect(mockEsClient.ingest.deletePipeline).toHaveBeenCalledTimes(1); + expect( + mockScopedClusterClient.asSecondaryAuthUser.ingest.deletePipeline + ).toHaveBeenCalledTimes(1); expect(mockSummaryTransformManager.stop).not.toHaveBeenCalled(); expect(mockSummaryTransformManager.uninstall).not.toHaveBeenCalled(); @@ -186,7 +194,9 @@ describe('CreateSLO', () => { expect(mockRepository.deleteById).toHaveBeenCalled(); expect(mockTransformManager.stop).toHaveBeenCalled(); expect(mockTransformManager.uninstall).toHaveBeenCalled(); - expect(mockEsClient.ingest.deletePipeline).toHaveBeenCalledTimes(2); + expect( + mockScopedClusterClient.asSecondaryAuthUser.ingest.deletePipeline + ).toHaveBeenCalledTimes(2); expect(mockSummaryTransformManager.uninstall).toHaveBeenCalled(); expect(mockSummaryTransformManager.stop).not.toHaveBeenCalled(); @@ -203,7 +213,9 @@ describe('CreateSLO', () => { expect(mockRepository.deleteById).toHaveBeenCalled(); expect(mockTransformManager.stop).toHaveBeenCalled(); expect(mockTransformManager.uninstall).toHaveBeenCalled(); - expect(mockEsClient.ingest.deletePipeline).toHaveBeenCalledTimes(2); + expect( + mockScopedClusterClient.asSecondaryAuthUser.ingest.deletePipeline + ).toHaveBeenCalledTimes(2); expect(mockSummaryTransformManager.stop).toHaveBeenCalled(); expect(mockSummaryTransformManager.uninstall).toHaveBeenCalled(); }); diff --git a/x-pack/plugins/observability_solution/slo/server/services/delete_slo.test.ts b/x-pack/plugins/observability_solution/slo/server/services/delete_slo.test.ts index 506151da864d3..2b8a2352f8026 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/delete_slo.test.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/delete_slo.test.ts @@ -8,7 +8,7 @@ import { rulesClientMock } from '@kbn/alerting-plugin/server/rules_client.mock'; import { RulesClientApi } from '@kbn/alerting-plugin/server/types'; import { ElasticsearchClient } from '@kbn/core/server'; -import { elasticsearchServiceMock } from '@kbn/core/server/mocks'; +import { elasticsearchServiceMock, ScopedClusterClientMock } from '@kbn/core/server/mocks'; import { DeleteSLO } from './delete_slo'; import { createAPMTransactionErrorRateIndicator, createSLO } from './fixtures/slo'; import { @@ -24,6 +24,7 @@ describe('DeleteSLO', () => { let mockTransformManager: jest.Mocked; let mockSummaryTransformManager: jest.Mocked; let mockEsClient: jest.Mocked; + let mockScopedClusterClient: ScopedClusterClientMock; let mockRulesClient: jest.Mocked; let deleteSLO: DeleteSLO; @@ -32,12 +33,14 @@ describe('DeleteSLO', () => { mockTransformManager = createTransformManagerMock(); mockSummaryTransformManager = createSummaryTransformManagerMock(); mockEsClient = elasticsearchServiceMock.createElasticsearchClient(); + mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); mockRulesClient = rulesClientMock.create(); deleteSLO = new DeleteSLO( mockRepository, mockTransformManager, mockSummaryTransformManager, mockEsClient, + mockScopedClusterClient, mockRulesClient ); }); @@ -57,7 +60,7 @@ describe('DeleteSLO', () => { expect(mockSummaryTransformManager.uninstall).toMatchSnapshot(); expect(mockTransformManager.stop).toMatchSnapshot(); expect(mockTransformManager.uninstall).toMatchSnapshot(); - expect(mockEsClient.ingest.deletePipeline).toMatchSnapshot(); + expect(mockScopedClusterClient.asSecondaryAuthUser.ingest.deletePipeline).toMatchSnapshot(); expect(mockEsClient.deleteByQuery).toMatchSnapshot(); expect(mockRulesClient.bulkDeleteRules).toMatchSnapshot(); expect(mockRepository.deleteById).toMatchSnapshot(); diff --git a/x-pack/plugins/observability_solution/slo/server/services/reset_slo.test.ts b/x-pack/plugins/observability_solution/slo/server/services/reset_slo.test.ts index 6f9a8dda4a128..efbf3eedb52e1 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/reset_slo.test.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/reset_slo.test.ts @@ -10,6 +10,7 @@ import { elasticsearchServiceMock, httpServiceMock, loggingSystemMock, + ScopedClusterClientMock, } from '@kbn/core/server/mocks'; import { MockedLogger } from '@kbn/logging-mocks'; @@ -31,6 +32,7 @@ describe('ResetSLO', () => { let mockTransformManager: jest.Mocked; let mockSummaryTransformManager: jest.Mocked; let mockEsClient: jest.Mocked; + let mockScopedClusterClient: ScopedClusterClientMock; let loggerMock: jest.Mocked; let resetSLO: ResetSLO; @@ -39,9 +41,11 @@ describe('ResetSLO', () => { mockRepository = createSLORepositoryMock(); mockTransformManager = createTransformManagerMock(); mockEsClient = elasticsearchServiceMock.createElasticsearchClient(); + mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); mockSummaryTransformManager = createSummaryTransformManagerMock(); resetSLO = new ResetSLO( mockEsClient, + mockScopedClusterClient, mockRepository, mockTransformManager, mockSummaryTransformManager, @@ -76,7 +80,7 @@ describe('ResetSLO', () => { expect(mockSummaryTransformManager.install).toMatchSnapshot(); expect(mockSummaryTransformManager.start).toMatchSnapshot(); - expect(mockEsClient.ingest.putPipeline).toMatchSnapshot(); + expect(mockScopedClusterClient.asSecondaryAuthUser.ingest.putPipeline).toMatchSnapshot(); expect(mockTransformManager.install).toMatchSnapshot(); expect(mockTransformManager.start).toMatchSnapshot(); diff --git a/x-pack/plugins/observability_solution/slo/server/services/transform_manager.test.ts b/x-pack/plugins/observability_solution/slo/server/services/transform_manager.test.ts index 7e6cf50c169fa..0f16dfd2cf19e 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/transform_manager.test.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/transform_manager.test.ts @@ -8,6 +8,7 @@ import { ElasticsearchClientMock, + ScopedClusterClientMock, elasticsearchServiceMock, loggingSystemMock, } from '@kbn/core/server/mocks'; @@ -31,11 +32,13 @@ import { DataViewsService } from '@kbn/data-views-plugin/common'; describe('TransformManager', () => { let esClientMock: ElasticsearchClientMock; + let scopedClusterClientMock: ScopedClusterClientMock; let loggerMock: jest.Mocked; const spaceId = 'default'; beforeEach(() => { esClientMock = elasticsearchServiceMock.createElasticsearchClient(); + scopedClusterClientMock = elasticsearchServiceMock.createScopedClusterClient(); loggerMock = loggingSystemMock.createLogger(); }); @@ -48,7 +51,7 @@ describe('TransformManager', () => { }; const service = new DefaultTransformManager( generators, - esClientMock, + scopedClusterClientMock, loggerMock, spaceId, dataViewsService @@ -66,7 +69,7 @@ describe('TransformManager', () => { }; const transformManager = new DefaultTransformManager( generators, - esClientMock, + scopedClusterClientMock, loggerMock, spaceId, dataViewsService @@ -87,7 +90,7 @@ describe('TransformManager', () => { }; const transformManager = new DefaultTransformManager( generators, - esClientMock, + scopedClusterClientMock, loggerMock, spaceId, dataViewsService @@ -96,7 +99,9 @@ describe('TransformManager', () => { const transformId = await transformManager.install(slo); - expect(esClientMock.transform.putTransform).toHaveBeenCalledTimes(1); + expect( + scopedClusterClientMock.asSecondaryAuthUser.transform.putTransform + ).toHaveBeenCalledTimes(1); expect(transformId).toBe(`slo-${slo.id}-${slo.revision}`); }); }); @@ -109,7 +114,7 @@ describe('TransformManager', () => { }; const transformManager = new DefaultTransformManager( generators, - esClientMock, + scopedClusterClientMock, loggerMock, spaceId, dataViewsService @@ -117,7 +122,9 @@ describe('TransformManager', () => { await transformManager.preview('slo-transform-id'); - expect(esClientMock.transform.previewTransform).toHaveBeenCalledTimes(1); + expect( + scopedClusterClientMock.asSecondaryAuthUser.transform.previewTransform + ).toHaveBeenCalledTimes(1); }); }); @@ -129,7 +136,7 @@ describe('TransformManager', () => { }; const transformManager = new DefaultTransformManager( generators, - esClientMock, + scopedClusterClientMock, loggerMock, spaceId, dataViewsService @@ -137,7 +144,9 @@ describe('TransformManager', () => { await transformManager.start('slo-transform-id'); - expect(esClientMock.transform.startTransform).toHaveBeenCalledTimes(1); + expect( + scopedClusterClientMock.asSecondaryAuthUser.transform.startTransform + ).toHaveBeenCalledTimes(1); }); }); @@ -149,7 +158,7 @@ describe('TransformManager', () => { }; const transformManager = new DefaultTransformManager( generators, - esClientMock, + scopedClusterClientMock, loggerMock, spaceId, dataViewsService @@ -157,7 +166,9 @@ describe('TransformManager', () => { await transformManager.stop('slo-transform-id'); - expect(esClientMock.transform.stopTransform).toHaveBeenCalledTimes(1); + expect( + scopedClusterClientMock.asSecondaryAuthUser.transform.stopTransform + ).toHaveBeenCalledTimes(1); }); }); @@ -169,7 +180,7 @@ describe('TransformManager', () => { }; const transformManager = new DefaultTransformManager( generators, - esClientMock, + scopedClusterClientMock, loggerMock, spaceId, dataViewsService @@ -177,11 +188,13 @@ describe('TransformManager', () => { await transformManager.uninstall('slo-transform-id'); - expect(esClientMock.transform.deleteTransform).toHaveBeenCalledTimes(1); + expect( + scopedClusterClientMock.asSecondaryAuthUser.transform.deleteTransform + ).toHaveBeenCalledTimes(1); }); it('retries on transient error', async () => { - esClientMock.transform.deleteTransform.mockRejectedValueOnce( + scopedClusterClientMock.asSecondaryAuthUser.transform.deleteTransform.mockRejectedValueOnce( new EsErrors.ConnectionError('irrelevant') ); // @ts-ignore defining only a subset of the possible SLI @@ -190,7 +203,7 @@ describe('TransformManager', () => { }; const transformManager = new DefaultTransformManager( generators, - esClientMock, + scopedClusterClientMock, loggerMock, spaceId, dataViewsService @@ -198,7 +211,9 @@ describe('TransformManager', () => { await transformManager.uninstall('slo-transform-id'); - expect(esClientMock.transform.deleteTransform).toHaveBeenCalledTimes(2); + expect( + scopedClusterClientMock.asSecondaryAuthUser.transform.deleteTransform + ).toHaveBeenCalledTimes(2); }); }); }); diff --git a/x-pack/plugins/observability_solution/slo/server/services/update_slo.test.ts b/x-pack/plugins/observability_solution/slo/server/services/update_slo.test.ts index 7f8f8ff1e3150..37855bd4d8fa4 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/update_slo.test.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/update_slo.test.ts @@ -10,6 +10,7 @@ import { elasticsearchServiceMock, httpServiceMock, loggingSystemMock, + ScopedClusterClientMock, } from '@kbn/core/server/mocks'; import { MockedLogger } from '@kbn/logging-mocks'; import { UpdateSLOParams } from '@kbn/slo-schema'; @@ -42,6 +43,7 @@ describe('UpdateSLO', () => { let mockRepository: jest.Mocked; let mockTransformManager: jest.Mocked; let mockEsClient: jest.Mocked; + let mockScopedClusterClient: ScopedClusterClientMock; let mockLogger: jest.Mocked; let mockSummaryTransformManager: jest.Mocked; let updateSLO: UpdateSLO; @@ -52,11 +54,13 @@ describe('UpdateSLO', () => { mockLogger = loggingSystemMock.createLogger(); mockSummaryTransformManager = createSummaryTransformManagerMock(); mockEsClient = elasticsearchServiceMock.createElasticsearchClient(); + mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); updateSLO = new UpdateSLO( mockRepository, mockTransformManager, mockSummaryTransformManager, mockEsClient, + mockScopedClusterClient, mockLogger, 'some-space', httpServiceMock.createStartContract().basePath @@ -76,7 +80,7 @@ describe('UpdateSLO', () => { expect(mockSummaryTransformManager.start).not.toBeCalled(); expect(mockEsClient.deleteByQuery).not.toBeCalled(); - expect(mockEsClient.ingest.putPipeline).not.toBeCalled(); + expect(mockScopedClusterClient.asSecondaryAuthUser.ingest.putPipeline).not.toBeCalled(); } it('returns early with a fully identical SLO payload', async () => { @@ -313,7 +317,9 @@ describe('UpdateSLO', () => { ).rejects.toThrowError('Transform install error'); expect(mockRepository.save).toHaveBeenCalledWith(originalSlo); - expect(mockEsClient.ingest.deletePipeline).toHaveBeenCalledTimes(1); // for the sli only + expect( + mockScopedClusterClient.asSecondaryAuthUser.ingest.deletePipeline + ).toHaveBeenCalledTimes(1); // for the sli only expect(mockSummaryTransformManager.stop).not.toHaveBeenCalled(); expect(mockSummaryTransformManager.uninstall).not.toHaveBeenCalled(); @@ -339,7 +345,7 @@ describe('UpdateSLO', () => { expect(mockRepository.save).toHaveBeenCalledWith(originalSlo); expect(mockSummaryTransformManager.uninstall).toHaveBeenCalled(); - expect(mockEsClient.ingest.deletePipeline).toHaveBeenCalled(); + expect(mockScopedClusterClient.asSecondaryAuthUser.ingest.deletePipeline).toHaveBeenCalled(); expect(mockTransformManager.stop).toHaveBeenCalled(); expect(mockTransformManager.uninstall).toHaveBeenCalled(); @@ -351,7 +357,7 @@ describe('UpdateSLO', () => { expect(mockTransformManager.install).toHaveBeenCalled(); expect(mockTransformManager.start).toHaveBeenCalled(); - expect(mockEsClient.ingest.putPipeline).toHaveBeenCalled(); + expect(mockScopedClusterClient.asSecondaryAuthUser.ingest.putPipeline).toHaveBeenCalled(); expect(mockSummaryTransformManager.install).toHaveBeenCalled(); expect(mockSummaryTransformManager.start).toHaveBeenCalled(); @@ -368,7 +374,7 @@ describe('UpdateSLO', () => { expect(mockSummaryTransformManager.stop).toHaveBeenCalledWith(summaryTransformId); expect(mockSummaryTransformManager.uninstall).toHaveBeenCalledWith(summaryTransformId); - expect(mockEsClient.ingest.deletePipeline).toHaveBeenCalled(); + expect(mockScopedClusterClient.asSecondaryAuthUser.ingest.deletePipeline).toHaveBeenCalled(); expect(mockEsClient.deleteByQuery).toHaveBeenCalledTimes(2); expect(mockEsClient.deleteByQuery).toHaveBeenNthCalledWith( From 501b9ba3422fefd294b9acbb9ae71d18d34e0fc3 Mon Sep 17 00:00:00 2001 From: Dominique Belcher Date: Thu, 15 Aug 2024 15:21:20 -0400 Subject: [PATCH 03/15] update slo health --- .../slo/server/routes/slo/route.ts | 8 +++-- .../server/services/get_slo_health.test.ts | 6 ++-- .../slo/server/services/get_slo_health.ts | 35 +++++++++++-------- 3 files changed, 29 insertions(+), 20 deletions(-) diff --git a/x-pack/plugins/observability_solution/slo/server/routes/slo/route.ts b/x-pack/plugins/observability_solution/slo/server/routes/slo/route.ts index 0e66998470c9f..fffbd7aa1e924 100644 --- a/x-pack/plugins/observability_solution/slo/server/routes/slo/route.ts +++ b/x-pack/plugins/observability_solution/slo/server/routes/slo/route.ts @@ -617,11 +617,13 @@ const fetchSloHealthRoute = createSloServerRoute({ handler: async ({ context, params, logger }) => { await assertPlatinumLicense(context); - const soClient = (await context.core).savedObjects.client; - const esClient = (await context.core).elasticsearch.client.asCurrentUser; + const core = await context.core; + const scopedClusterClient = core.elasticsearch.client; + const soClient = core.savedObjects.client; + const esClient = core.elasticsearch.client.asCurrentUser; const repository = new KibanaSavedObjectsSLORepository(soClient, logger); - const getSLOHealth = new GetSLOHealth(esClient, repository); + const getSLOHealth = new GetSLOHealth(esClient, scopedClusterClient, repository); return await getSLOHealth.execute(params.body); }, diff --git a/x-pack/plugins/observability_solution/slo/server/services/get_slo_health.test.ts b/x-pack/plugins/observability_solution/slo/server/services/get_slo_health.test.ts index ce1522de40ada..b7087308bee68 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/get_slo_health.test.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/get_slo_health.test.ts @@ -6,7 +6,7 @@ */ import { ElasticsearchClient } from '@kbn/core/server'; -import { elasticsearchServiceMock } from '@kbn/core/server/mocks'; +import { ScopedClusterClientMock, elasticsearchServiceMock } from '@kbn/core/server/mocks'; import { ALL_VALUE } from '@kbn/slo-schema'; import { getSLOSummaryTransformId, getSLOTransformId } from '../../common/constants'; import { createSLO } from './fixtures/slo'; @@ -22,12 +22,14 @@ import { SLORepository } from './slo_repository'; describe('GetSLOHealth', () => { let mockRepository: jest.Mocked; let mockEsClient: jest.Mocked; + let mockScopedClusterClient: ScopedClusterClientMock; let getSLOHealth: GetSLOHealth; beforeEach(() => { mockRepository = createSLORepositoryMock(); mockEsClient = elasticsearchServiceMock.createElasticsearchClient(); - getSLOHealth = new GetSLOHealth(mockEsClient, mockRepository); + mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); + getSLOHealth = new GetSLOHealth(mockEsClient, mockScopedClusterClient, mockRepository); }); it('returns the health and state', async () => { diff --git a/x-pack/plugins/observability_solution/slo/server/services/get_slo_health.ts b/x-pack/plugins/observability_solution/slo/server/services/get_slo_health.ts index 76493e8a7f4e4..585bf7ef5d4e2 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/get_slo_health.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/get_slo_health.ts @@ -6,7 +6,7 @@ */ import { TransformGetTransformStatsTransformStats } from '@elastic/elasticsearch/lib/api/types'; -import { ElasticsearchClient } from '@kbn/core/server'; +import { ElasticsearchClient, IScopedClusterClient } from '@kbn/core/server'; import { FetchSLOHealthParams, FetchSLOHealthResponse, @@ -28,7 +28,11 @@ const LAG_THRESHOLD_MINUTES = 10; const STALE_THRESHOLD_MINUTES = 2 * 24 * 60; export class GetSLOHealth { - constructor(private esClient: ElasticsearchClient, private repository: SLORepository) {} + constructor( + private esClient: ElasticsearchClient, + private scopedClusterClient: IScopedClusterClient, + private repository: SLORepository + ) {} public async execute(params: FetchSLOHealthParams): Promise { const sloIds = params.list.map(({ sloId }) => sloId); @@ -91,19 +95,20 @@ export class GetSLOHealth { private async getTransformStats( sloList: SLODefinition[] ): Promise> { - const transformStats = await this.esClient.transform.getTransformStats( - { - transform_id: sloList - .map((slo: SLODefinition) => [ - getSLOTransformId(slo.id, slo.revision), - getSLOSummaryTransformId(slo.id, slo.revision), - ]) - .flat(), - allow_no_match: true, - size: sloList.length * 2, - }, - { ignore: [404] } - ); + const transformStats = + await this.scopedClusterClient.asSecondaryAuthUser.transform.getTransformStats( + { + transform_id: sloList + .map((slo: SLODefinition) => [ + getSLOTransformId(slo.id, slo.revision), + getSLOSummaryTransformId(slo.id, slo.revision), + ]) + .flat(), + allow_no_match: true, + size: sloList.length * 2, + }, + { ignore: [404] } + ); return keyBy(transformStats.transforms, (transform) => transform.id); } From 56902e5af8a745d2a05c34690b8b46456238333f Mon Sep 17 00:00:00 2001 From: Dominique Belcher Date: Mon, 19 Aug 2024 20:13:49 -0400 Subject: [PATCH 04/15] adjust requirements for write user --- .../slo/server/services/get_diagnosis.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/x-pack/plugins/observability_solution/slo/server/services/get_diagnosis.ts b/x-pack/plugins/observability_solution/slo/server/services/get_diagnosis.ts index 5b16598e816d5..0f06a16f40c67 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/get_diagnosis.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/get_diagnosis.ts @@ -14,8 +14,7 @@ export async function getGlobalDiagnosis( ) { const licenseInfo = licensing.license.toJSON(); const userWritePrivileges = await esClient.security.hasPrivileges({ - cluster: [], - index: [{ names: '.slo-*', privileges: ['all'] }], + index: [{ names: '.slo-*', privileges: ['write', 'read', 'view_index_metadata'] }], }); const userReadPrivileges = await esClient.security.hasPrivileges({ index: [{ names: '.slo-*', privileges: ['read'] }], From 1f7883f73387f6a343c23f745e4fac50bdaf337e Mon Sep 17 00:00:00 2001 From: Dominique Belcher Date: Tue, 20 Aug 2024 12:07:03 -0400 Subject: [PATCH 05/15] update privilege set and tests --- .../slo/server/services/get_diagnosis.ts | 25 ++++++- .../api_integration/apis/slos/create_slo.ts | 47 +++--------- .../api_integration/apis/slos/delete_slo.ts | 13 ++-- .../apis/slos/fetch_historical_summary.ts | 1 + .../test/api_integration/apis/slos/get_slo.ts | 20 ++--- .../api_integration/apis/slos/reset_slo.ts | 21 ++---- .../api_integration/apis/slos/update_slo.ts | 1 + x-pack/test/api_integration/services/slo.ts | 73 ++++++++++++++++--- 8 files changed, 119 insertions(+), 82 deletions(-) diff --git a/x-pack/plugins/observability_solution/slo/server/services/get_diagnosis.ts b/x-pack/plugins/observability_solution/slo/server/services/get_diagnosis.ts index 0f06a16f40c67..f7a03d0aa06b7 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/get_diagnosis.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/get_diagnosis.ts @@ -8,13 +8,36 @@ import { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; import { LicensingApiRequestHandlerContext } from '@kbn/licensing-plugin/server'; +export const MINIMUM_INDEX_PRIVILEGE_SET_EDITOR = [ + 'write', + 'read', + 'view_index_metadata', + 'manage', + 'auto_configure', +]; +export const TOTAL_INDEX_PRIVILEGE_SET_EDITOR = [ + 'write', + 'read', + 'read_cross_cluster', + 'view_index_metadata', + 'manage', + 'auto_configure', +]; +export const MINIMUM_INDEX_PRIVILEGE_SET_VIEWER = ['read']; +export const TOTAL_INDEX_PRIVILEGE_SET_VIEWER = ['read', 'read_cross_cluster']; + export async function getGlobalDiagnosis( esClient: ElasticsearchClient, licensing: LicensingApiRequestHandlerContext ) { const licenseInfo = licensing.license.toJSON(); const userWritePrivileges = await esClient.security.hasPrivileges({ - index: [{ names: '.slo-*', privileges: ['write', 'read', 'view_index_metadata'] }], + index: [ + { + names: '.slo-*', + privileges: ['write', 'read', 'view_index_metadata', 'manage', 'auto_configure'], + }, + ], }); const userReadPrivileges = await esClient.security.hasPrivileges({ index: [{ names: '.slo-*', privileges: ['read'] }], diff --git a/x-pack/test/api_integration/apis/slos/create_slo.ts b/x-pack/test/api_integration/apis/slos/create_slo.ts index 4b458558b233e..71ce8434a61f1 100644 --- a/x-pack/test/api_integration/apis/slos/create_slo.ts +++ b/x-pack/test/api_integration/apis/slos/create_slo.ts @@ -29,6 +29,7 @@ export default function ({ getService }: FtrProviderContext) { let createSLOInput: CreateSLOInput; before(async () => { + await slo.createUser(); await loadTestData(getService); await slo.deleteAllSLOs(); }); @@ -47,12 +48,7 @@ export default function ({ getService }: FtrProviderContext) { }); it('creates a new slo and transforms', async () => { - const apiResponse = await supertestAPI - .post('/api/observability/slos') - .set('kbn-xsrf', 'true') - .set('x-elastic-internal-origin', 'foo') - .send(createSLOInput) - .expect(200); + const apiResponse = await slo.create(createSLOInput); expect(apiResponse.body).property('id'); @@ -113,7 +109,7 @@ export default function ({ getService }: FtrProviderContext) { transforms: [ { id: `slo-${id}-1`, - authorization: { roles: ['superuser'] }, + authorization: { roles: ['slo_editor', 'editor'] }, version: '10.0.0', create_time: rollUpTransformResponse.body.transforms[0].create_time, source: { @@ -193,7 +189,7 @@ export default function ({ getService }: FtrProviderContext) { transforms: [ { id: `slo-summary-${id}-1`, - authorization: { roles: ['superuser'] }, + authorization: { roles: ['slo_editor', 'editor'] }, version: '10.0.0', create_time: summaryTransform.body.transforms[0].create_time, source: { @@ -372,12 +368,7 @@ export default function ({ getService }: FtrProviderContext) { it('creates instanceId for SLOs with multi groupBy', async () => { createSLOInput.groupBy = ['system.network.name', 'event.dataset']; - const apiResponse = await supertestAPI - .post('/api/observability/slos') - .set('kbn-xsrf', 'true') - .set('x-elastic-internal-origin', 'foo') - .send(createSLOInput) - .expect(200); + const apiResponse = await slo.create(createSLOInput); expect(apiResponse.body).property('id'); @@ -396,12 +387,7 @@ export default function ({ getService }: FtrProviderContext) { it('creates instanceId for SLOs with single groupBy', async () => { createSLOInput.groupBy = 'system.network.name'; - const apiResponse = await supertestAPI - .post('/api/observability/slos') - .set('kbn-xsrf', 'true') - .set('x-elastic-internal-origin', 'foo') - .send(createSLOInput) - .expect(200); + const apiResponse = await slo.create(createSLOInput); expect(apiResponse.body).property('id'); @@ -418,12 +404,7 @@ export default function ({ getService }: FtrProviderContext) { it('creates instanceId for SLOs without groupBy ([])', async () => { createSLOInput.groupBy = []; - const apiResponse = await supertestAPI - .post('/api/observability/slos') - .set('kbn-xsrf', 'true') - .set('x-elastic-internal-origin', 'foo') - .send(createSLOInput) - .expect(200); + const apiResponse = await slo.create(createSLOInput); expect(apiResponse.body).property('id'); @@ -440,12 +421,7 @@ export default function ({ getService }: FtrProviderContext) { it('creates instanceId for SLOs without groupBy (["*"])', async () => { createSLOInput.groupBy = ['*']; - const apiResponse = await supertestAPI - .post('/api/observability/slos') - .set('kbn-xsrf', 'true') - .set('x-elastic-internal-origin', 'foo') - .send(createSLOInput) - .expect(200); + const apiResponse = await slo.create(createSLOInput); expect(apiResponse.body).property('id'); @@ -462,12 +438,7 @@ export default function ({ getService }: FtrProviderContext) { it('creates instanceId for SLOs without groupBy ("")', async () => { createSLOInput.groupBy = ''; - const apiResponse = await supertestAPI - .post('/api/observability/slos') - .set('kbn-xsrf', 'true') - .set('x-elastic-internal-origin', 'foo') - .send(createSLOInput) - .expect(200); + const apiResponse = await slo.create(createSLOInput); expect(apiResponse.body).property('id'); diff --git a/x-pack/test/api_integration/apis/slos/delete_slo.ts b/x-pack/test/api_integration/apis/slos/delete_slo.ts index 65efd7a001153..7f2816457a0ec 100644 --- a/x-pack/test/api_integration/apis/slos/delete_slo.ts +++ b/x-pack/test/api_integration/apis/slos/delete_slo.ts @@ -29,6 +29,7 @@ export default function ({ getService }: FtrProviderContext) { let createSLOInput: CreateSLOInput; before(async () => { + await slo.createUser(); await slo.deleteAllSLOs(); await sloEsClient.deleteTestSourceData(); loadTestData(getService); @@ -48,7 +49,11 @@ export default function ({ getService }: FtrProviderContext) { }); it('deletes new slo saved object and transforms', async () => { - const id = await slo.create(createSLOInput); + const response = await slo.create(createSLOInput); + + expect(response.body).property('id'); + + const { id } = response.body; const savedObject = await kibanaServer.savedObjects.find({ type: SO_SLO_TYPE, @@ -86,11 +91,7 @@ export default function ({ getService }: FtrProviderContext) { // expect summary transform to be created expect(summaryTransform.body.transforms[0].id).eql(`slo-summary-${id}-1`); - await supertestAPI - .delete(`/api/observability/slos/${id}`) - .set('kbn-xsrf', 'true') - .send() - .expect(204); + await slo.delete(id); }); // await retry.tryForTime(150 * 1000, async () => { diff --git a/x-pack/test/api_integration/apis/slos/fetch_historical_summary.ts b/x-pack/test/api_integration/apis/slos/fetch_historical_summary.ts index b8ca6a03b3d8e..96f8e21c8c593 100644 --- a/x-pack/test/api_integration/apis/slos/fetch_historical_summary.ts +++ b/x-pack/test/api_integration/apis/slos/fetch_historical_summary.ts @@ -23,6 +23,7 @@ export default function ({ getService }: FtrProviderContext) { describe('fetch historical summary', () => { before(async () => { + await sloApi.createUser(); const now = moment().startOf('minute'); const curr = now.clone().subtract(30, 'days'); const end = now.clone().add(5, 'minutes'); diff --git a/x-pack/test/api_integration/apis/slos/get_slo.ts b/x-pack/test/api_integration/apis/slos/get_slo.ts index b2cd64db05e71..eafa35ed70c3b 100644 --- a/x-pack/test/api_integration/apis/slos/get_slo.ts +++ b/x-pack/test/api_integration/apis/slos/get_slo.ts @@ -35,6 +35,7 @@ export default function ({ getService }: FtrProviderContext) { }; before(async () => { + await slo.createUser(); await slo.deleteAllSLOs(); await sloEsClient.deleteTestSourceData(); await loadTestData(getService); @@ -55,7 +56,7 @@ export default function ({ getService }: FtrProviderContext) { await sloEsClient.deleteTestSourceData(); }); - it('gets slo by id and calculates SLI - occurances rolling', async () => { + it('gets slo by id and calculates SLI - occurrences rolling', async () => { const id = await createSLO({ groupBy: '*', }); @@ -87,7 +88,7 @@ export default function ({ getService }: FtrProviderContext) { groupBy: '*', groupings: {}, id, - settings: { syncDelay: '1m', frequency: '1m' }, + settings: { syncDelay: '1m', frequency: '1m', preventInitialBackfill: false }, revision: 1, enabled: true, createdAt: getResponse.body.createdAt, @@ -103,6 +104,9 @@ export default function ({ getService }: FtrProviderContext) { remaining: -49, isEstimated: false, }, + fiveMinuteBurnRate: 40, + oneDayBurnRate: 50, + oneHourBurnRate: 50, status: 'VIOLATED', }, }); @@ -383,11 +387,7 @@ export default function ({ getService }: FtrProviderContext) { it('gets slo definitions', async () => { const id = await createSLO(); const secondId = await createSLO({ name: 'test name int' }); - const response = await supertestAPI - .get(`/api/observability/slos/_definitions`) - .set('kbn-xsrf', 'true') - .send() - .expect(200); + const response = await slo.getDefinitions(); expect(response.body).toEqual({ page: 1, @@ -466,11 +466,7 @@ export default function ({ getService }: FtrProviderContext) { }); // can search by name - const searchResponse = await supertestAPI - .get(`/api/observability/slos/_definitions?search=api`) - .set('kbn-xsrf', 'true') - .send() - .expect(200); + const searchResponse = await slo.getDefinitions({ search: 'api' }); expect(searchResponse.body.total).toEqual(1); diff --git a/x-pack/test/api_integration/apis/slos/reset_slo.ts b/x-pack/test/api_integration/apis/slos/reset_slo.ts index 014e546b2b639..dd3b32bed507a 100644 --- a/x-pack/test/api_integration/apis/slos/reset_slo.ts +++ b/x-pack/test/api_integration/apis/slos/reset_slo.ts @@ -16,7 +16,7 @@ export default function ({ getService }: FtrProviderContext) { describe('Reset SLOs', function () { this.tags('skipCloud'); - const supertestAPI = getService('supertest'); + const supertestAPI = getService('supertestWithoutAuth'); const kibanaServer = getService('kibanaServer'); const esClient = getService('es'); const logger = getService('log'); @@ -25,6 +25,7 @@ export default function ({ getService }: FtrProviderContext) { before(async () => { await sloEsClient.deleteTestSourceData(); + await slo.createUser(); await slo.deleteAllSLOs(); await loadTestData(getService); }); @@ -79,25 +80,13 @@ export default function ({ getService }: FtrProviderContext) { }, }); - const responseBeforeReset = await supertestAPI - .get(`/api/observability/slos/_definitions`) - .set('kbn-xsrf', 'true') - .send() - .expect(200); + const responseBeforeReset = await slo.getDefinitions(); expect(responseBeforeReset.body.results[0].version).eql(1); - await supertestAPI - .post(`/api/observability/slos/${id}/_reset`) - .set('kbn-xsrf', 'true') - .send() - .expect(200); + await slo.reset(id); - const responseAfterReset = await supertestAPI - .get(`/api/observability/slos/_definitions`) - .set('kbn-xsrf', 'true') - .send() - .expect(200); + const responseAfterReset = await slo.getDefinitions(); expect(responseAfterReset.body.results[0].version).eql(2); }); diff --git a/x-pack/test/api_integration/apis/slos/update_slo.ts b/x-pack/test/api_integration/apis/slos/update_slo.ts index 76e19d6ba20a0..7bf6967bd26a3 100644 --- a/x-pack/test/api_integration/apis/slos/update_slo.ts +++ b/x-pack/test/api_integration/apis/slos/update_slo.ts @@ -26,6 +26,7 @@ export default function ({ getService }: FtrProviderContext) { let createSLOInput: CreateSLOInput; before(async () => { + await slo.createUser(); await slo.deleteAllSLOs(); await loadTestData(getService); }); diff --git a/x-pack/test/api_integration/services/slo.ts b/x-pack/test/api_integration/services/slo.ts index c7b765dddf613..8a698b9cbe571 100644 --- a/x-pack/test/api_integration/services/slo.ts +++ b/x-pack/test/api_integration/services/slo.ts @@ -4,8 +4,8 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - import { SLO_SUMMARY_DESTINATION_INDEX_NAME } from '@kbn/slo-plugin/common/constants'; +import { TOTAL_INDEX_PRIVILEGE_SET_EDITOR } from '@kbn/slo-plugin/server/services/get_diagnosis'; import { CreateSLOInput, fetchHistoricalSummaryParamsSchema, @@ -21,39 +21,93 @@ type FetchHistoricalSummaryParams = t.OutputOf< >; export function SloApiProvider({ getService }: FtrProviderContext) { - const supertest = getService('supertest'); + const supertest = getService('supertestWithoutAuth'); const esClient = getService('es'); + const security = getService('security'); + + const { transform } = getService('esArchiver'); return { + async createUser(params: CreateUserParams) { + const username = 'slo_editor'; + const roleName = 'slo_editor'; + try { + await security.user.delete(username); + await security.role.delete(roleName); + } catch (error) { + const status = error.response.status; + if (status !== 404) { + throw error; + } + } + const password = 'changeme'; + + await security.role.create(roleName, { + elasticsearch: { + indices: [ + { + names: ['.slo-*'], + privileges: TOTAL_INDEX_PRIVILEGE_SET_EDITOR, + }, + ], + }, + }); + + await security.user.create(username, { + password, + roles: [roleName, 'editor'], + }); + }, async create(params: CreateSLOInput) { const slo = await supertest .post('/api/observability/slos') .set('kbn-xsrf', 'true') + .auth('slo_editor', 'changeme') .send(params) .expect(200); - const { id } = slo.body; + return slo; + }, + async reset(id: string) { + const response = supertest + .post(`/api/observability/slos/${id}/_reset`) + .auth('slo_editor', 'changeme') + .set('kbn-xsrf', 'true') + .send() + .expect(200); - const reqBody = [{ id: `slo-${id}-1` }, { id: `slo-summary-${id}-1` }]; - await supertest - .post(`/internal/transform/schedule_now_transforms`) + return response; + }, + async getDefinitions() { + const response = await supertest + .get(`/api/observability/slos/_definitions`) .set('kbn-xsrf', 'true') - .set('elastic-api-version', '1') - .send(reqBody) + .auth('slo_editor', 'changeme') + .send() .expect(200); - return id; + return response; + }, + async delete(id: string) { + await supertest + .delete(`/api/observability/slos/${id}`) + .set('kbn-xsrf', 'true') + .auth('slo_editor', 'changeme') + .send() + .expect(204); }, async deleteAllSLOs() { const response = await supertest .get(`/api/observability/slos/_definitions`) .set('kbn-xsrf', 'true') + .auth('slo_editor', 'changeme') .send() .expect(200); for (const { id } of (response.body as FindSLODefinitionsResponse).results) { await supertest .delete(`/api/observability/slos/${id}`) .set('kbn-xsrf', 'true') + .auth('slo_editor', 'changeme') .send() .expect(204); } @@ -65,6 +119,7 @@ export function SloApiProvider({ getService }: FtrProviderContext) { const { body } = await supertest .post(`/internal/observability/slos/_historical_summary`) .set('kbn-xsrf', 'foo') + .auth('slo_editor', 'changeme') .set('elastic-api-version', '1') .send(params); From 3afcd42f9c877487f77405232b74201440fe20c5 Mon Sep 17 00:00:00 2001 From: Aleh Zasypkin Date: Wed, 21 Aug 2024 16:50:33 +0200 Subject: [PATCH 06/15] fix(security, http): expose authentication headers in the authentication result when HTTP authentication is used --- .../authentication/providers/http.test.ts | 32 +++++++++---------- .../server/authentication/providers/http.ts | 6 +++- 2 files changed, 21 insertions(+), 17 deletions(-) diff --git a/x-pack/plugins/security/server/authentication/providers/http.test.ts b/x-pack/plugins/security/server/authentication/providers/http.test.ts index 90ff62294ff3f..d599b6be2d9c3 100644 --- a/x-pack/plugins/security/server/authentication/providers/http.test.ts +++ b/x-pack/plugins/security/server/authentication/providers/http.test.ts @@ -133,10 +133,10 @@ describe('HTTPAuthenticationProvider', () => { }); await expect(provider.authenticate(request)).resolves.toEqual( - AuthenticationResult.succeeded({ - ...user, - authentication_provider: { type: 'http', name: 'http' }, - }) + AuthenticationResult.succeeded( + { ...user, authentication_provider: { type: 'http', name: 'http' } }, + { authHeaders: { authorization: header } } + ) ); expectAuthenticateCall(mockOptions.client, { headers: { authorization: header } }); @@ -160,10 +160,10 @@ describe('HTTPAuthenticationProvider', () => { }); await expect(provider.authenticate(request)).resolves.toEqual( - AuthenticationResult.succeeded({ - ...user, - authentication_provider: { type: 'http', name: 'http' }, - }) + AuthenticationResult.succeeded( + { ...user, authentication_provider: { type: 'http', name: 'http' } }, + { authHeaders: { authorization: header } } + ) ); expectAuthenticateCall(mockOptions.client, { headers: { authorization: header } }); @@ -187,10 +187,10 @@ describe('HTTPAuthenticationProvider', () => { }); await expect(provider.authenticate(request)).resolves.toEqual( - AuthenticationResult.succeeded({ - ...user, - authentication_provider: { type: 'http', name: 'http' }, - }) + AuthenticationResult.succeeded( + { ...user, authentication_provider: { type: 'http', name: 'http' } }, + { authHeaders: { authorization: header } } + ) ); expectAuthenticateCall(mockOptions.client, { headers: { authorization: header } }); @@ -217,10 +217,10 @@ describe('HTTPAuthenticationProvider', () => { }); await expect(provider.authenticate(request)).resolves.toEqual( - AuthenticationResult.succeeded({ - ...user, - authentication_provider: { type: 'http', name: 'http' }, - }) + AuthenticationResult.succeeded( + { ...user, authentication_provider: { type: 'http', name: 'http' } }, + { authHeaders: { authorization: header } } + ) ); expectAuthenticateCall(mockOptions.client, { headers: { authorization: header } }); diff --git a/x-pack/plugins/security/server/authentication/providers/http.ts b/x-pack/plugins/security/server/authentication/providers/http.ts index e23ec826ed2e1..ab7971871c704 100644 --- a/x-pack/plugins/security/server/authentication/providers/http.ts +++ b/x-pack/plugins/security/server/authentication/providers/http.ts @@ -113,7 +113,11 @@ export class HTTPAuthenticationProvider extends BaseAuthenticationProvider { return AuthenticationResult.notHandled(); } - return AuthenticationResult.succeeded(user); + return AuthenticationResult.succeeded(user, { + // Even though the `Authorization` header is already present in the HTTP headers of the original request, + // we still need to expose it to the Core authentication service for consistency. + authHeaders: { authorization: authorizationHeader.toString() }, + }); } catch (err) { this.logger.debug( () => From 8a990971029d2b412e6c1d89e4e1376f8a86b231 Mon Sep 17 00:00:00 2001 From: Dominique Belcher Date: Wed, 21 Aug 2024 11:52:52 -0400 Subject: [PATCH 07/15] adjust jest test --- .../slo/server/services/get_slo_health.test.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/x-pack/plugins/observability_solution/slo/server/services/get_slo_health.test.ts b/x-pack/plugins/observability_solution/slo/server/services/get_slo_health.test.ts index b7087308bee68..2e9dfb51e79a3 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/get_slo_health.test.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/get_slo_health.test.ts @@ -130,7 +130,7 @@ describe('GetSLOHealth', () => { }); // @ts-ignore - mockEsClient.transform.getTransformStats.mockResolvedValue({ + mockScopedClusterClient.asSecondaryAuthUser.transform.getTransformStats.mockResolvedValue({ transforms: [ { id: getSLOTransformId(slo.id, slo.revision), health: { status: 'green' } }, { id: getSLOSummaryTransformId(slo.id, slo.revision), health: { status: 'green' } }, @@ -181,7 +181,7 @@ describe('GetSLOHealth', () => { }); // @ts-ignore - mockEsClient.transform.getTransformStats.mockResolvedValue({ + mockScopedClusterClient.asSecondaryAuthUser.transform.getTransformStats.mockResolvedValue({ transforms: [ { id: getSLOTransformId(slo.id, slo.revision), health: { status: 'yellow' } }, { id: getSLOSummaryTransformId(slo.id, slo.revision), health: { status: 'green' } }, @@ -242,7 +242,7 @@ describe('GetSLOHealth', () => { }); // @ts-ignore - mockEsClient.transform.getTransformStats.mockResolvedValue({ + mockScopedClusterClient.asSecondaryAuthUser.transform.getTransformStats.mockResolvedValue({ transforms: [ { id: getSLOTransformId(slo.id, slo.revision), health: { status: 'green' } }, { id: getSLOSummaryTransformId(slo.id, slo.revision), health: { status: 'green' } }, @@ -288,7 +288,7 @@ describe('GetSLOHealth', () => { }); // @ts-ignore - mockEsClient.transform.getTransformStats.mockResolvedValue({ + mockScopedClusterClient.asSecondaryAuthUser.transform.getTransformStats.mockResolvedValue({ transforms: [ { id: getSLOTransformId(slo.id, slo.revision), health: { status: 'green' } }, { id: getSLOSummaryTransformId(slo.id, slo.revision), health: { status: 'green' } }, @@ -334,7 +334,7 @@ describe('GetSLOHealth', () => { }); // @ts-ignore - mockEsClient.transform.getTransformStats.mockResolvedValue({ + mockScopedClusterClient.asSecondaryAuthUser.transform.getTransformStats.mockResolvedValue({ transforms: [ { id: getSLOTransformId(slo.id, slo.revision), health: { status: 'green' } }, { id: getSLOSummaryTransformId(slo.id, slo.revision), health: { status: 'green' } }, From 47b7ef4f0919c61bfc82a9b89b8c1db6795e4bf6 Mon Sep 17 00:00:00 2001 From: Dominique Belcher Date: Wed, 21 Aug 2024 15:10:52 -0400 Subject: [PATCH 08/15] adjust tests and types --- .../server/services/get_slo_health.test.ts | 52 +++++++++++++++---- .../server/services/transform_manager.test.ts | 3 -- x-pack/test/api_integration/services/slo.ts | 4 +- .../slo/embeddables/overview_embeddable.ts | 1 + 4 files changed, 43 insertions(+), 17 deletions(-) diff --git a/x-pack/plugins/observability_solution/slo/server/services/get_slo_health.test.ts b/x-pack/plugins/observability_solution/slo/server/services/get_slo_health.test.ts index 2e9dfb51e79a3..a6553e6f069aa 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/get_slo_health.test.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/get_slo_health.test.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - +import type { TransformGetTransformStatsTransformStats } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { ElasticsearchClient } from '@kbn/core/server'; import { ScopedClusterClientMock, elasticsearchServiceMock } from '@kbn/core/server/mocks'; import { ALL_VALUE } from '@kbn/slo-schema'; @@ -132,8 +132,14 @@ describe('GetSLOHealth', () => { // @ts-ignore mockScopedClusterClient.asSecondaryAuthUser.transform.getTransformStats.mockResolvedValue({ transforms: [ - { id: getSLOTransformId(slo.id, slo.revision), health: { status: 'green' } }, - { id: getSLOSummaryTransformId(slo.id, slo.revision), health: { status: 'green' } }, + { + id: getSLOTransformId(slo.id, slo.revision), + health: { status: 'green' }, + } as TransformGetTransformStatsTransformStats, + { + id: getSLOSummaryTransformId(slo.id, slo.revision), + health: { status: 'green' }, + } as TransformGetTransformStatsTransformStats, ], }); @@ -183,8 +189,14 @@ describe('GetSLOHealth', () => { // @ts-ignore mockScopedClusterClient.asSecondaryAuthUser.transform.getTransformStats.mockResolvedValue({ transforms: [ - { id: getSLOTransformId(slo.id, slo.revision), health: { status: 'yellow' } }, - { id: getSLOSummaryTransformId(slo.id, slo.revision), health: { status: 'green' } }, + { + id: getSLOTransformId(slo.id, slo.revision), + health: { status: 'yellow' }, + } as TransformGetTransformStatsTransformStats, + { + id: getSLOSummaryTransformId(slo.id, slo.revision), + health: { status: 'green' }, + } as TransformGetTransformStatsTransformStats, ], }); @@ -244,8 +256,14 @@ describe('GetSLOHealth', () => { // @ts-ignore mockScopedClusterClient.asSecondaryAuthUser.transform.getTransformStats.mockResolvedValue({ transforms: [ - { id: getSLOTransformId(slo.id, slo.revision), health: { status: 'green' } }, - { id: getSLOSummaryTransformId(slo.id, slo.revision), health: { status: 'green' } }, + { + id: getSLOTransformId(slo.id, slo.revision), + health: { status: 'green' }, + } as TransformGetTransformStatsTransformStats, + { + id: getSLOSummaryTransformId(slo.id, slo.revision), + health: { status: 'green' }, + } as TransformGetTransformStatsTransformStats, ], }); @@ -290,8 +308,14 @@ describe('GetSLOHealth', () => { // @ts-ignore mockScopedClusterClient.asSecondaryAuthUser.transform.getTransformStats.mockResolvedValue({ transforms: [ - { id: getSLOTransformId(slo.id, slo.revision), health: { status: 'green' } }, - { id: getSLOSummaryTransformId(slo.id, slo.revision), health: { status: 'green' } }, + { + id: getSLOTransformId(slo.id, slo.revision), + health: { status: 'green' }, + } as TransformGetTransformStatsTransformStats, + { + id: getSLOSummaryTransformId(slo.id, slo.revision), + health: { status: 'green' }, + } as TransformGetTransformStatsTransformStats, ], }); @@ -336,8 +360,14 @@ describe('GetSLOHealth', () => { // @ts-ignore mockScopedClusterClient.asSecondaryAuthUser.transform.getTransformStats.mockResolvedValue({ transforms: [ - { id: getSLOTransformId(slo.id, slo.revision), health: { status: 'green' } }, - { id: getSLOSummaryTransformId(slo.id, slo.revision), health: { status: 'green' } }, + { + id: getSLOTransformId(slo.id, slo.revision), + health: { status: 'green' }, + } as TransformGetTransformStatsTransformStats, + { + id: getSLOSummaryTransformId(slo.id, slo.revision), + health: { status: 'green' }, + } as TransformGetTransformStatsTransformStats, ], }); diff --git a/x-pack/plugins/observability_solution/slo/server/services/transform_manager.test.ts b/x-pack/plugins/observability_solution/slo/server/services/transform_manager.test.ts index 0f16dfd2cf19e..b7b5d7ba4fcd9 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/transform_manager.test.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/transform_manager.test.ts @@ -7,7 +7,6 @@ /* eslint-disable max-classes-per-file */ import { - ElasticsearchClientMock, ScopedClusterClientMock, elasticsearchServiceMock, loggingSystemMock, @@ -31,13 +30,11 @@ import { dataViewsService } from '@kbn/data-views-plugin/server/mocks'; import { DataViewsService } from '@kbn/data-views-plugin/common'; describe('TransformManager', () => { - let esClientMock: ElasticsearchClientMock; let scopedClusterClientMock: ScopedClusterClientMock; let loggerMock: jest.Mocked; const spaceId = 'default'; beforeEach(() => { - esClientMock = elasticsearchServiceMock.createElasticsearchClient(); scopedClusterClientMock = elasticsearchServiceMock.createScopedClusterClient(); loggerMock = loggingSystemMock.createLogger(); }); diff --git a/x-pack/test/api_integration/services/slo.ts b/x-pack/test/api_integration/services/slo.ts index 8a698b9cbe571..3d4d21ee4ea81 100644 --- a/x-pack/test/api_integration/services/slo.ts +++ b/x-pack/test/api_integration/services/slo.ts @@ -25,10 +25,8 @@ export function SloApiProvider({ getService }: FtrProviderContext) { const esClient = getService('es'); const security = getService('security'); - const { transform } = getService('esArchiver'); - return { - async createUser(params: CreateUserParams) { + async createUser() { const username = 'slo_editor'; const roleName = 'slo_editor'; try { diff --git a/x-pack/test/functional/apps/slo/embeddables/overview_embeddable.ts b/x-pack/test/functional/apps/slo/embeddables/overview_embeddable.ts index 5a531d6cf5bb5..3624513b7cbb7 100644 --- a/x-pack/test/functional/apps/slo/embeddables/overview_embeddable.ts +++ b/x-pack/test/functional/apps/slo/embeddables/overview_embeddable.ts @@ -23,6 +23,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { describe('overview embeddable', function () { before(async () => { await loadTestData(getService); + await slo.createUser(); await slo.deleteAllSLOs(); await slo.create(sloData); await PageObjects.dashboard.navigateToApp(); From 2edb72f39a7b3ca1df5b6370acc91b4eb89c7806 Mon Sep 17 00:00:00 2001 From: shahzad31 Date: Thu, 22 Aug 2024 11:25:55 +0200 Subject: [PATCH 09/15] fix test types --- x-pack/test/api_integration/services/slo.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/x-pack/test/api_integration/services/slo.ts b/x-pack/test/api_integration/services/slo.ts index 3d4d21ee4ea81..953e4234a7bc9 100644 --- a/x-pack/test/api_integration/services/slo.ts +++ b/x-pack/test/api_integration/services/slo.ts @@ -76,9 +76,10 @@ export function SloApiProvider({ getService }: FtrProviderContext) { return response; }, - async getDefinitions() { + async getDefinitions({ search }: { search?: string } = {}) { + const url = `/api/observability/slos/_definitions${search ? `?search=${search}` : ''}`; const response = await supertest - .get(`/api/observability/slos/_definitions`) + .get(url) .set('kbn-xsrf', 'true') .auth('slo_editor', 'changeme') .send() From 50876afaa06c1de4c168e4ca4d043019f60d7cf7 Mon Sep 17 00:00:00 2001 From: Panagiota Mitsopoulou Date: Thu, 22 Aug 2024 13:47:27 +0300 Subject: [PATCH 10/15] fix check types --- x-pack/test/api_integration/apis/slos/reset_slo.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/x-pack/test/api_integration/apis/slos/reset_slo.ts b/x-pack/test/api_integration/apis/slos/reset_slo.ts index dd3b32bed507a..cccac8f1796be 100644 --- a/x-pack/test/api_integration/apis/slos/reset_slo.ts +++ b/x-pack/test/api_integration/apis/slos/reset_slo.ts @@ -16,7 +16,6 @@ export default function ({ getService }: FtrProviderContext) { describe('Reset SLOs', function () { this.tags('skipCloud'); - const supertestAPI = getService('supertestWithoutAuth'); const kibanaServer = getService('kibanaServer'); const esClient = getService('es'); const logger = getService('log'); From fb37216add7a12970205ccaa7194bc037a0aa3a0 Mon Sep 17 00:00:00 2001 From: Dominique Belcher Date: Thu, 22 Aug 2024 09:27:08 -0400 Subject: [PATCH 11/15] adjust global diagnosis --- .../slo/server/services/get_diagnosis.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/observability_solution/slo/server/services/get_diagnosis.ts b/x-pack/plugins/observability_solution/slo/server/services/get_diagnosis.ts index f7a03d0aa06b7..499c758dc00d7 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/get_diagnosis.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/get_diagnosis.ts @@ -35,12 +35,12 @@ export async function getGlobalDiagnosis( index: [ { names: '.slo-*', - privileges: ['write', 'read', 'view_index_metadata', 'manage', 'auto_configure'], + privileges: MINIMUM_INDEX_PRIVILEGE_SET_EDITOR, }, ], }); const userReadPrivileges = await esClient.security.hasPrivileges({ - index: [{ names: '.slo-*', privileges: ['read'] }], + index: [{ names: '.slo-*', privileges: MINIMUM_INDEX_PRIVILEGE_SET_VIEWER }], }); return { From d838b3c0fa38a5a35f32aba9a4c7f462aad4e315 Mon Sep 17 00:00:00 2001 From: Dominique Belcher Date: Thu, 22 Aug 2024 14:07:12 -0400 Subject: [PATCH 12/15] adjust content and index pattern --- .../components/slo/slo_permissions_callout/index.tsx | 4 ++-- .../slo/server/services/get_diagnosis.ts | 4 ++-- x-pack/test/api_integration/services/slo.ts | 2 +- .../services/transform/security_common.ts | 12 ++++++++++-- 4 files changed, 15 insertions(+), 7 deletions(-) diff --git a/x-pack/plugins/observability_solution/slo/public/components/slo/slo_permissions_callout/index.tsx b/x-pack/plugins/observability_solution/slo/public/components/slo/slo_permissions_callout/index.tsx index 720f31ccea3fa..ec21537b1d19e 100644 --- a/x-pack/plugins/observability_solution/slo/public/components/slo/slo_permissions_callout/index.tsx +++ b/x-pack/plugins/observability_solution/slo/public/components/slo/slo_permissions_callout/index.tsx @@ -46,7 +46,7 @@ export function SloPermissionsCallout() {
  • @@ -62,7 +62,7 @@ export function SloPermissionsCallout() {
  • diff --git a/x-pack/plugins/observability_solution/slo/server/services/get_diagnosis.ts b/x-pack/plugins/observability_solution/slo/server/services/get_diagnosis.ts index 499c758dc00d7..a7a2f3a24c96c 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/get_diagnosis.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/get_diagnosis.ts @@ -34,13 +34,13 @@ export async function getGlobalDiagnosis( const userWritePrivileges = await esClient.security.hasPrivileges({ index: [ { - names: '.slo-*', + names: '.slo-observability.*', privileges: MINIMUM_INDEX_PRIVILEGE_SET_EDITOR, }, ], }); const userReadPrivileges = await esClient.security.hasPrivileges({ - index: [{ names: '.slo-*', privileges: MINIMUM_INDEX_PRIVILEGE_SET_VIEWER }], + index: [{ names: '.slo-observability.*', privileges: MINIMUM_INDEX_PRIVILEGE_SET_VIEWER }], }); return { diff --git a/x-pack/test/api_integration/services/slo.ts b/x-pack/test/api_integration/services/slo.ts index 953e4234a7bc9..d0d6cdc190e0e 100644 --- a/x-pack/test/api_integration/services/slo.ts +++ b/x-pack/test/api_integration/services/slo.ts @@ -44,7 +44,7 @@ export function SloApiProvider({ getService }: FtrProviderContext) { elasticsearch: { indices: [ { - names: ['.slo-*'], + names: ['.slo-observability.*'], privileges: TOTAL_INDEX_PRIVILEGE_SET_EDITOR, }, ], diff --git a/x-pack/test_serverless/api_integration/services/transform/security_common.ts b/x-pack/test_serverless/api_integration/services/transform/security_common.ts index c112ef7572509..d94dba0ee190c 100644 --- a/x-pack/test_serverless/api_integration/services/transform/security_common.ts +++ b/x-pack/test_serverless/api_integration/services/transform/security_common.ts @@ -8,6 +8,10 @@ import { ProvidedType } from '@kbn/test'; import { Client } from '@elastic/elasticsearch'; +import { + TOTAL_INDEX_PRIVILEGE_SET_EDITOR, + TOTAL_INDEX_PRIVILEGE_SET_VIEWER, +} from '@kbn/slo-plugin/server/services/get_diagnosis'; import { FtrProviderContext } from '../../ftr_provider_context'; export type TransformSecurityCommon = ProvidedType; @@ -33,14 +37,18 @@ export function TransformSecurityCommonProvider({ getService }: FtrProviderConte { name: 'transform_dest', elasticsearch: { - indices: [{ names: ['.slo-*'], privileges: ['read', 'index', 'manage', 'delete'] }], + indices: [ + { names: ['.slo-observability.*'], privileges: TOTAL_INDEX_PRIVILEGE_SET_EDITOR }, + ], }, kibana: [], }, { name: 'transform_dest_readonly', elasticsearch: { - indices: [{ names: ['.slo-*'], privileges: ['read'] }], + indices: [ + { names: ['.slo-observability.*'], privileges: TOTAL_INDEX_PRIVILEGE_SET_VIEWER }, + ], }, kibana: [], }, From dfa5e65a379f7fa4b42c65e0caf4698458abafe0 Mon Sep 17 00:00:00 2001 From: Dominique Belcher Date: Mon, 26 Aug 2024 09:43:47 -0400 Subject: [PATCH 13/15] adjust content --- .../public/components/slo/slo_permissions_callout/index.tsx | 6 ------ x-pack/plugins/translations/translations/fr-FR.json | 1 - x-pack/plugins/translations/translations/ja-JP.json | 1 - x-pack/plugins/translations/translations/zh-CN.json | 1 - 4 files changed, 9 deletions(-) diff --git a/x-pack/plugins/observability_solution/slo/public/components/slo/slo_permissions_callout/index.tsx b/x-pack/plugins/observability_solution/slo/public/components/slo/slo_permissions_callout/index.tsx index ec21537b1d19e..ff5e45fa857ae 100644 --- a/x-pack/plugins/observability_solution/slo/public/components/slo/slo_permissions_callout/index.tsx +++ b/x-pack/plugins/observability_solution/slo/public/components/slo/slo_permissions_callout/index.tsx @@ -65,12 +65,6 @@ export function SloPermissionsCallout() { defaultMessage="'read', 'view_index_metadata', 'write', 'manage' and 'auto_configure' permission on index pattern: .slo-observability.*" />
  • -
  • - -
  • Date: Wed, 28 Aug 2024 13:22:53 -0400 Subject: [PATCH 14/15] remove unnecessary autoconfigure privilege --- .../slo/public/components/slo/slo_permissions_callout/index.tsx | 2 +- .../observability_solution/slo/server/services/get_diagnosis.ts | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/x-pack/plugins/observability_solution/slo/public/components/slo/slo_permissions_callout/index.tsx b/x-pack/plugins/observability_solution/slo/public/components/slo/slo_permissions_callout/index.tsx index ff5e45fa857ae..bf49fa4393282 100644 --- a/x-pack/plugins/observability_solution/slo/public/components/slo/slo_permissions_callout/index.tsx +++ b/x-pack/plugins/observability_solution/slo/public/components/slo/slo_permissions_callout/index.tsx @@ -62,7 +62,7 @@ export function SloPermissionsCallout() {
  • diff --git a/x-pack/plugins/observability_solution/slo/server/services/get_diagnosis.ts b/x-pack/plugins/observability_solution/slo/server/services/get_diagnosis.ts index a7a2f3a24c96c..7a090de252c1d 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/get_diagnosis.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/get_diagnosis.ts @@ -13,7 +13,6 @@ export const MINIMUM_INDEX_PRIVILEGE_SET_EDITOR = [ 'read', 'view_index_metadata', 'manage', - 'auto_configure', ]; export const TOTAL_INDEX_PRIVILEGE_SET_EDITOR = [ 'write', @@ -21,7 +20,6 @@ export const TOTAL_INDEX_PRIVILEGE_SET_EDITOR = [ 'read_cross_cluster', 'view_index_metadata', 'manage', - 'auto_configure', ]; export const MINIMUM_INDEX_PRIVILEGE_SET_VIEWER = ['read']; export const TOTAL_INDEX_PRIVILEGE_SET_VIEWER = ['read', 'read_cross_cluster']; From d979dba63b38be88d113a3244f5f37329bb2a701 Mon Sep 17 00:00:00 2001 From: Dominique Belcher Date: Wed, 28 Aug 2024 13:43:42 -0400 Subject: [PATCH 15/15] adjust get tests --- .../test/api_integration/apis/slos/get_slo.ts | 39 +++++++++++++------ 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/x-pack/test/api_integration/apis/slos/get_slo.ts b/x-pack/test/api_integration/apis/slos/get_slo.ts index eafa35ed70c3b..274c2535a4630 100644 --- a/x-pack/test/api_integration/apis/slos/get_slo.ts +++ b/x-pack/test/api_integration/apis/slos/get_slo.ts @@ -57,9 +57,10 @@ export default function ({ getService }: FtrProviderContext) { }); it('gets slo by id and calculates SLI - occurrences rolling', async () => { - const id = await createSLO({ + const response = await createSLO({ groupBy: '*', }); + const id = response.body.id; await retry.tryForTime(300 * 1000, async () => { const getResponse = await supertestAPI @@ -114,13 +115,14 @@ export default function ({ getService }: FtrProviderContext) { }); it('gets slo by id and calculates SLI - occurences calendarAligned', async () => { - const id = await createSLO({ + const response = await createSLO({ groupBy: '*', timeWindow: { duration: '1w', type: 'calendarAligned', }, }); + const id = response.body.id; await retry.tryForTime(300 * 1000, async () => { const getResponse = await supertestAPI @@ -150,7 +152,7 @@ export default function ({ getService }: FtrProviderContext) { groupBy: '*', groupings: {}, id, - settings: { syncDelay: '1m', frequency: '1m' }, + settings: { syncDelay: '1m', frequency: '1m', preventInitialBackfill: false }, revision: 1, enabled: true, createdAt: getResponse.body.createdAt, @@ -166,6 +168,9 @@ export default function ({ getService }: FtrProviderContext) { remaining: -49, isEstimated: true, }, + fiveMinuteBurnRate: 40, + oneDayBurnRate: 50, + oneHourBurnRate: 50, status: 'VIOLATED', }, }); @@ -173,7 +178,7 @@ export default function ({ getService }: FtrProviderContext) { }); it('gets slo by id and calculates SLI - timeslices rolling', async () => { - const id = await createSLO({ + const response = await createSLO({ groupBy: '*', timeWindow: { duration: '7d', @@ -186,6 +191,7 @@ export default function ({ getService }: FtrProviderContext) { timesliceWindow: '1m', }, }); + const id = response.body.id; await retry.tryForTime(300 * 1000, async () => { const getResponse = await supertestAPI @@ -219,7 +225,7 @@ export default function ({ getService }: FtrProviderContext) { groupBy: '*', groupings: {}, id, - settings: { syncDelay: '1m', frequency: '1m' }, + settings: { syncDelay: '1m', frequency: '1m', preventInitialBackfill: false }, revision: 1, enabled: true, createdAt: getResponse.body.createdAt, @@ -227,7 +233,7 @@ export default function ({ getService }: FtrProviderContext) { version: 2, instanceId: '*', meta: {}, - summary: { + summary: expect.objectContaining({ sliValue: 0.5, errorBudget: { initial: 0.01, @@ -236,13 +242,13 @@ export default function ({ getService }: FtrProviderContext) { isEstimated: false, }, status: 'VIOLATED', - }, + }), }); }); }); it('gets slo by id and calculates SLI - timeslices calendarAligned', async () => { - const id = await createSLO({ + const response = await createSLO({ groupBy: '*', timeWindow: { duration: '1w', @@ -255,6 +261,7 @@ export default function ({ getService }: FtrProviderContext) { timesliceWindow: '10m', }, }); + const id = response.body.id; await retry.tryForTime(300 * 1000, async () => { const getResponse = await supertestAPI @@ -287,7 +294,7 @@ export default function ({ getService }: FtrProviderContext) { groupBy: '*', groupings: {}, id, - settings: { syncDelay: '1m', frequency: '1m' }, + settings: { syncDelay: '1m', frequency: '1m', preventInitialBackfill: false }, revision: 1, enabled: true, createdAt: getResponse.body.createdAt, @@ -303,6 +310,9 @@ export default function ({ getService }: FtrProviderContext) { remaining: 0.801587, isEstimated: false, }, + fiveMinuteBurnRate: 40, + oneDayBurnRate: 50, + oneHourBurnRate: 50, status: 'DEGRADING', }, }); @@ -357,7 +367,8 @@ export default function ({ getService }: FtrProviderContext) { }); it('gets slos instances', async () => { - const id = await createSLO(); + const createResponse = await createSLO(); + const id = createResponse.body.id; await retry.tryForTime(400 * 1000, async () => { const response = await supertestAPI @@ -385,8 +396,10 @@ export default function ({ getService }: FtrProviderContext) { }); it('gets slo definitions', async () => { - const id = await createSLO(); - const secondId = await createSLO({ name: 'test name int' }); + const createResponse = await createSLO(); + const id = createResponse.body.id; + const secondCreateResponse = await createSLO({ name: 'test name int' }); + const secondId = secondCreateResponse.body.id; const response = await slo.getDefinitions(); expect(response.body).toEqual({ @@ -418,6 +431,7 @@ export default function ({ getService }: FtrProviderContext) { settings: { frequency: '1m', syncDelay: '1m', + preventInitialBackfill: false, }, tags: ['test'], timeWindow: { @@ -452,6 +466,7 @@ export default function ({ getService }: FtrProviderContext) { settings: { frequency: '1m', syncDelay: '1m', + preventInitialBackfill: false, }, tags: ['test'], timeWindow: {