diff --git a/x-pack/platform/plugins/shared/dataset_quality/server/routes/data_streams/failed_docs/routes.ts b/x-pack/platform/plugins/shared/dataset_quality/server/routes/data_streams/failed_docs/routes.ts index f6bbd05d03da..e8a4bfd50d3c 100644 --- a/x-pack/platform/plugins/shared/dataset_quality/server/routes/data_streams/failed_docs/routes.ts +++ b/x-pack/platform/plugins/shared/dataset_quality/server/routes/data_streams/failed_docs/routes.ts @@ -32,6 +32,13 @@ const failedDocsRoute = createDatasetQualityServerRoute({ options: { tags: [], }, + security: { + authz: { + enabled: false, + reason: + 'This API delegates security to the currently logged in user and their Elasticsearch permissions.', + }, + }, async handler(resources): Promise<{ failedDocs: DataStreamDocsStat[]; }> { @@ -75,6 +82,13 @@ const failedDocsDetailsRoute = createDatasetQualityServerRoute({ options: { tags: [], }, + security: { + authz: { + enabled: false, + reason: + 'This API delegates security to the currently logged in user and their Elasticsearch permissions.', + }, + }, async handler(resources): Promise { const { context, params, getEsCapabilities } = resources; const coreContext = await context.core; @@ -106,6 +120,13 @@ const failedDocsErrorsRoute = createDatasetQualityServerRoute({ options: { tags: [], }, + security: { + authz: { + enabled: false, + reason: + 'This API delegates security to the currently logged in user and their Elasticsearch permissions.', + }, + }, async handler(resources): Promise { const { context, params, getEsCapabilities } = resources; const coreContext = await context.core; diff --git a/x-pack/platform/plugins/shared/dataset_quality/server/routes/data_streams/routes.ts b/x-pack/platform/plugins/shared/dataset_quality/server/routes/data_streams/routes.ts index 14951244ab0e..a12048d9235d 100644 --- a/x-pack/platform/plugins/shared/dataset_quality/server/routes/data_streams/routes.ts +++ b/x-pack/platform/plugins/shared/dataset_quality/server/routes/data_streams/routes.ts @@ -52,6 +52,13 @@ const statsRoute = createDatasetQualityServerRoute({ options: { tags: [], }, + security: { + authz: { + enabled: false, + reason: + 'This API delegates security to the currently logged in user and their Elasticsearch permissions.', + }, + }, async handler(resources): Promise<{ datasetUserPrivileges: DatasetUserPrivileges; dataStreamsStats: DataStreamStat[]; @@ -111,6 +118,13 @@ const degradedDocsRoute = createDatasetQualityServerRoute({ options: { tags: [], }, + security: { + authz: { + enabled: false, + reason: + 'This API delegates security to the currently logged in user and their Elasticsearch permissions.', + }, + }, async handler(resources): Promise<{ degradedDocs: DataStreamDocsStat[]; }> { @@ -138,6 +152,13 @@ const totalDocsRoute = createDatasetQualityServerRoute({ options: { tags: [], }, + security: { + authz: { + enabled: false, + reason: + 'This API delegates security to the currently logged in user and their Elasticsearch permissions.', + }, + }, async handler(resources): Promise<{ totalDocs: DataStreamDocsStat[]; }> { @@ -177,6 +198,13 @@ const nonAggregatableDatasetsRoute = createDatasetQualityServerRoute({ options: { tags: [], }, + security: { + authz: { + enabled: false, + reason: + 'This API delegates security to the currently logged in user and their Elasticsearch permissions.', + }, + }, async handler(resources): Promise { const { context, params } = resources; const coreContext = await context.core; @@ -201,6 +229,13 @@ const nonAggregatableDatasetRoute = createDatasetQualityServerRoute({ options: { tags: [], }, + security: { + authz: { + enabled: false, + reason: + 'This API delegates security to the currently logged in user and their Elasticsearch permissions.', + }, + }, async handler(resources): Promise { const { context, params } = resources; const coreContext = await context.core; @@ -228,6 +263,13 @@ const degradedFieldsRoute = createDatasetQualityServerRoute({ options: { tags: [], }, + security: { + authz: { + enabled: false, + reason: + 'This API delegates security to the currently logged in user and their Elasticsearch permissions.', + }, + }, async handler(resources): Promise { const { context, params } = resources; const { dataStream } = params.path; @@ -255,6 +297,13 @@ const degradedFieldValuesRoute = createDatasetQualityServerRoute({ options: { tags: [], }, + security: { + authz: { + enabled: false, + reason: + 'This API delegates security to the currently logged in user and their Elasticsearch permissions.', + }, + }, async handler(resources): Promise { const { context, params } = resources; const { dataStream, degradedField } = params.path; @@ -280,6 +329,13 @@ const dataStreamSettingsRoute = createDatasetQualityServerRoute({ options: { tags: [], }, + security: { + authz: { + enabled: false, + reason: + 'This API delegates security to the currently logged in user and their Elasticsearch permissions.', + }, + }, async handler(resources): Promise { const { context, params } = resources; const { dataStream } = params.path; @@ -307,8 +363,15 @@ const checkAndLoadIntegrationRoute = createDatasetQualityServerRoute({ options: { tags: [], }, + security: { + authz: { + enabled: false, + reason: + 'This API delegates security to the currently logged in user and their Elasticsearch permissions.', + }, + }, async handler(resources): Promise { - const { context, params, plugins, logger } = resources; + const { context, params, plugins, logger, request } = resources; const { dataStream } = params.path; const coreContext = await context.core; @@ -316,7 +379,7 @@ const checkAndLoadIntegrationRoute = createDatasetQualityServerRoute({ const esClient = coreContext.elasticsearch.client.asCurrentUser; const fleetPluginStart = await plugins.fleet.start(); - const packageClient = fleetPluginStart.packageService.asInternalUser; + const packageClient = fleetPluginStart.packageService.asScoped(request); const integration = await checkAndLoadIntegration({ esClient, @@ -340,6 +403,13 @@ const dataStreamDetailsRoute = createDatasetQualityServerRoute({ options: { tags: [], }, + security: { + authz: { + enabled: false, + reason: + 'This API delegates security to the currently logged in user and their Elasticsearch permissions.', + }, + }, async handler(resources): Promise { const { context, params, getEsCapabilities } = resources; const { dataStream } = params.path; @@ -376,6 +446,13 @@ const analyzeDegradedFieldRoute = createDatasetQualityServerRoute({ options: { tags: [], }, + security: { + authz: { + enabled: false, + reason: + 'This API delegates security to the currently logged in user and their Elasticsearch permissions.', + }, + }, async handler(resources): Promise { const { context, params } = resources; const coreContext = await context.core; @@ -405,6 +482,13 @@ const updateFieldLimitRoute = createDatasetQualityServerRoute({ options: { tags: [], }, + security: { + authz: { + enabled: false, + reason: + 'This API delegates security to the currently logged in user and their Elasticsearch permissions.', + }, + }, async handler(resources): Promise { const { context, params } = resources; const coreContext = await context.core; @@ -430,6 +514,13 @@ const rolloverDataStream = createDatasetQualityServerRoute({ options: { tags: [], }, + security: { + authz: { + enabled: false, + reason: + 'This API delegates security to the currently logged in user and their Elasticsearch permissions.', + }, + }, async handler(resources): Promise { const { context, params } = resources; const coreContext = await context.core; diff --git a/x-pack/platform/plugins/shared/dataset_quality/server/routes/integrations/routes.ts b/x-pack/platform/plugins/shared/dataset_quality/server/routes/integrations/routes.ts index dfeb2f3329ba..3782e206f375 100644 --- a/x-pack/platform/plugins/shared/dataset_quality/server/routes/integrations/routes.ts +++ b/x-pack/platform/plugins/shared/dataset_quality/server/routes/integrations/routes.ts @@ -16,13 +16,20 @@ const integrationsRoute = createDatasetQualityServerRoute({ options: { tags: [], }, + security: { + authz: { + enabled: false, + reason: + 'This API delegates security to the currently logged in user and their Elasticsearch permissions.', + }, + }, async handler(resources): Promise<{ integrations: IntegrationType[]; }> { - const { plugins, logger } = resources; + const { plugins, logger, request } = resources; const fleetPluginStart = await plugins.fleet.start(); - const packageClient = fleetPluginStart.packageService.asInternalUser; + const packageClient = fleetPluginStart.packageService.asScoped(request); const integrations = await getIntegrations({ packageClient, logger }); @@ -40,13 +47,20 @@ const integrationDashboardsRoute = createDatasetQualityServerRoute({ options: { tags: [], }, + security: { + authz: { + enabled: false, + reason: + 'This API delegates security to the currently logged in user and their Elasticsearch permissions.', + }, + }, async handler(resources): Promise { - const { context, params, plugins } = resources; + const { context, params, plugins, request } = resources; const { integration } = params.path; const { savedObjects } = await context.core; const fleetPluginStart = await plugins.fleet.start(); - const packageClient = fleetPluginStart.packageService.asInternalUser; + const packageClient = fleetPluginStart.packageService.asScoped(request); const integrationDashboards = await getIntegrationDashboards( packageClient, diff --git a/x-pack/test/functional/apps/dataset_quality/dataset_quality_privileges.ts b/x-pack/test/functional/apps/dataset_quality/dataset_quality_privileges.ts index b7eacc68dd6c..b7162f5a2aa6 100644 --- a/x-pack/test/functional/apps/dataset_quality/dataset_quality_privileges.ts +++ b/x-pack/test/functional/apps/dataset_quality/dataset_quality_privileges.ts @@ -170,19 +170,12 @@ export default function ({ getService, getPageObjects }: DatasetQualityFtrProvid await PageObjects.datasetQuality.navigateTo(); }); - it('"View dashboards" and "See integration" are hidden for underprivileged user', async () => { + it('"View dashboards" is hidden for underprivileged user', async () => { await PageObjects.datasetQuality.navigateToDetails({ dataStream: apacheAccessDataStreamName, }); await PageObjects.datasetQuality.openIntegrationActionsMenu(); - // "See Integration" is hidden - await testSubjects.missingOrFail( - PageObjects.datasetQuality.testSubjectSelectors.datasetQualityDetailsIntegrationAction( - 'Overview' - ) - ); - // "View Dashboards" is hidden await testSubjects.missingOrFail( PageObjects.datasetQuality.testSubjectSelectors.datasetQualityDetailsIntegrationAction( @@ -217,7 +210,7 @@ async function createDatasetQualityUserWithRole( feature: { dataQuality: [hasDataQualityPrivileges ? 'all' : 'none'], discover: ['all'], - fleet: ['none'], + fleet: ['read'], }, spaces: ['*'], }, diff --git a/x-pack/test_serverless/functional/test_suites/observability/dataset_quality/dataset_quality_summary.ts b/x-pack/test_serverless/functional/test_suites/observability/dataset_quality/dataset_quality_summary.ts index ac4a2597f3d9..3f1daa48e8af 100644 --- a/x-pack/test_serverless/functional/test_suites/observability/dataset_quality/dataset_quality_summary.ts +++ b/x-pack/test_serverless/functional/test_suites/observability/dataset_quality/dataset_quality_summary.ts @@ -10,6 +10,7 @@ import { FtrProviderContext } from '../../../ftr_provider_context'; import { datasetNames, getInitialTestLogs, getLogsForDataset } from './data'; export default function ({ getService, getPageObjects }: FtrProviderContext) { + const retry = getService('retry'); const PageObjects = getPageObjects([ 'common', 'datasetQuality', @@ -61,12 +62,17 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { it('shows poor, degraded and good count as 0 and all dataset as healthy', async () => { await PageObjects.datasetQuality.refreshTable(); - const summary = await PageObjects.datasetQuality.parseSummaryPanel(excludeKeysFromServerless); - expect(summary).to.eql({ - datasetHealthPoor: '0', - datasetHealthDegraded: '0', - datasetHealthGood: '3', - activeDatasets: '0 of 3', + // Sometimes the summary flashes with wrong count, retry to stabilize. This should be fixed at the root, but for now we retry. + await retry.try(async () => { + const summary = await PageObjects.datasetQuality.parseSummaryPanel( + excludeKeysFromServerless + ); + expect(summary).to.eql({ + datasetHealthPoor: '0', + datasetHealthDegraded: '0', + datasetHealthGood: '3', + activeDatasets: '0 of 3', + }); }); });