[8.x] [Dataset quality] Authz migration (#208343) (#208817)

# Backport

This will backport the following commits from `main` to `8.x`:
- [[Dataset quality] Authz migration
(#208343)](https://github.com/elastic/kibana/pull/208343)

<!--- Backport version: 9.4.3 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sqren/backport)

<!--BACKPORT [{"author":{"name":"Yngrid
Coello","email":"yngrid.coello@elastic.co"},"sourceCommit":{"committedDate":"2025-01-29T17:59:59Z","message":"[Dataset
quality] Authz migration (#208343)\n\nCloses
https://github.com/elastic/kibana/issues/206392.\n\n---------\n\nCo-authored-by:
Joe Reuter
<johannes.reuter@elastic.co>","sha":"cefe0c823b5a84c0f008b8fb7c3779f17ae4c511","branchLabelMapping":{"^v9.0.0$":"main","^v8.18.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","v9.0.0","backport:prev-minor"],"title":"[Dataset
quality] Authz
migration","number":208343,"url":"https://github.com/elastic/kibana/pull/208343","mergeCommit":{"message":"[Dataset
quality] Authz migration (#208343)\n\nCloses
https://github.com/elastic/kibana/issues/206392.\n\n---------\n\nCo-authored-by:
Joe Reuter
<johannes.reuter@elastic.co>","sha":"cefe0c823b5a84c0f008b8fb7c3779f17ae4c511"}},"sourceBranch":"main","suggestedTargetBranches":[],"targetPullRequestStates":[{"branch":"main","label":"v9.0.0","branchLabelMappingKey":"^v9.0.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/208343","number":208343,"mergeCommit":{"message":"[Dataset
quality] Authz migration (#208343)\n\nCloses
https://github.com/elastic/kibana/issues/206392.\n\n---------\n\nCo-authored-by:
Joe Reuter
<johannes.reuter@elastic.co>","sha":"cefe0c823b5a84c0f008b8fb7c3779f17ae4c511"}}]}]
BACKPORT-->

Co-authored-by: Yngrid Coello <yngrid.coello@elastic.co>
This commit is contained in:
Kibana Machine 2025-01-30 07:10:47 +11:00 committed by GitHub
parent 24f82ee808
commit 55de686094
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 146 additions and 21 deletions

View file

@ -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<FailedDocsDetails> {
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<FailedDocsErrorsResponse> {
const { context, params, getEsCapabilities } = resources;
const coreContext = await context.core;

View file

@ -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<NonAggregatableDatasets> {
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<NonAggregatableDatasets> {
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<DegradedFieldResponse> {
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<DegradedFieldValues> {
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<DataStreamSettings> {
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<CheckAndLoadIntegrationResponse> {
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<DataStreamDetails> {
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<DegradedFieldAnalysis> {
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<UpdateFieldLimitResponse> {
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<DataStreamRolloverResponse> {
const { context, params } = resources;
const coreContext = await context.core;

View file

@ -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<IntegrationDashboardsResponse> {
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,

View file

@ -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: ['*'],
},

View file

@ -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',
});
});
});