mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
# 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:
parent
24f82ee808
commit
55de686094
5 changed files with 146 additions and 21 deletions
|
@ -32,6 +32,13 @@ const failedDocsRoute = createDatasetQualityServerRoute({
|
||||||
options: {
|
options: {
|
||||||
tags: [],
|
tags: [],
|
||||||
},
|
},
|
||||||
|
security: {
|
||||||
|
authz: {
|
||||||
|
enabled: false,
|
||||||
|
reason:
|
||||||
|
'This API delegates security to the currently logged in user and their Elasticsearch permissions.',
|
||||||
|
},
|
||||||
|
},
|
||||||
async handler(resources): Promise<{
|
async handler(resources): Promise<{
|
||||||
failedDocs: DataStreamDocsStat[];
|
failedDocs: DataStreamDocsStat[];
|
||||||
}> {
|
}> {
|
||||||
|
@ -75,6 +82,13 @@ const failedDocsDetailsRoute = createDatasetQualityServerRoute({
|
||||||
options: {
|
options: {
|
||||||
tags: [],
|
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> {
|
async handler(resources): Promise<FailedDocsDetails> {
|
||||||
const { context, params, getEsCapabilities } = resources;
|
const { context, params, getEsCapabilities } = resources;
|
||||||
const coreContext = await context.core;
|
const coreContext = await context.core;
|
||||||
|
@ -106,6 +120,13 @@ const failedDocsErrorsRoute = createDatasetQualityServerRoute({
|
||||||
options: {
|
options: {
|
||||||
tags: [],
|
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> {
|
async handler(resources): Promise<FailedDocsErrorsResponse> {
|
||||||
const { context, params, getEsCapabilities } = resources;
|
const { context, params, getEsCapabilities } = resources;
|
||||||
const coreContext = await context.core;
|
const coreContext = await context.core;
|
||||||
|
|
|
@ -52,6 +52,13 @@ const statsRoute = createDatasetQualityServerRoute({
|
||||||
options: {
|
options: {
|
||||||
tags: [],
|
tags: [],
|
||||||
},
|
},
|
||||||
|
security: {
|
||||||
|
authz: {
|
||||||
|
enabled: false,
|
||||||
|
reason:
|
||||||
|
'This API delegates security to the currently logged in user and their Elasticsearch permissions.',
|
||||||
|
},
|
||||||
|
},
|
||||||
async handler(resources): Promise<{
|
async handler(resources): Promise<{
|
||||||
datasetUserPrivileges: DatasetUserPrivileges;
|
datasetUserPrivileges: DatasetUserPrivileges;
|
||||||
dataStreamsStats: DataStreamStat[];
|
dataStreamsStats: DataStreamStat[];
|
||||||
|
@ -111,6 +118,13 @@ const degradedDocsRoute = createDatasetQualityServerRoute({
|
||||||
options: {
|
options: {
|
||||||
tags: [],
|
tags: [],
|
||||||
},
|
},
|
||||||
|
security: {
|
||||||
|
authz: {
|
||||||
|
enabled: false,
|
||||||
|
reason:
|
||||||
|
'This API delegates security to the currently logged in user and their Elasticsearch permissions.',
|
||||||
|
},
|
||||||
|
},
|
||||||
async handler(resources): Promise<{
|
async handler(resources): Promise<{
|
||||||
degradedDocs: DataStreamDocsStat[];
|
degradedDocs: DataStreamDocsStat[];
|
||||||
}> {
|
}> {
|
||||||
|
@ -138,6 +152,13 @@ const totalDocsRoute = createDatasetQualityServerRoute({
|
||||||
options: {
|
options: {
|
||||||
tags: [],
|
tags: [],
|
||||||
},
|
},
|
||||||
|
security: {
|
||||||
|
authz: {
|
||||||
|
enabled: false,
|
||||||
|
reason:
|
||||||
|
'This API delegates security to the currently logged in user and their Elasticsearch permissions.',
|
||||||
|
},
|
||||||
|
},
|
||||||
async handler(resources): Promise<{
|
async handler(resources): Promise<{
|
||||||
totalDocs: DataStreamDocsStat[];
|
totalDocs: DataStreamDocsStat[];
|
||||||
}> {
|
}> {
|
||||||
|
@ -177,6 +198,13 @@ const nonAggregatableDatasetsRoute = createDatasetQualityServerRoute({
|
||||||
options: {
|
options: {
|
||||||
tags: [],
|
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> {
|
async handler(resources): Promise<NonAggregatableDatasets> {
|
||||||
const { context, params } = resources;
|
const { context, params } = resources;
|
||||||
const coreContext = await context.core;
|
const coreContext = await context.core;
|
||||||
|
@ -201,6 +229,13 @@ const nonAggregatableDatasetRoute = createDatasetQualityServerRoute({
|
||||||
options: {
|
options: {
|
||||||
tags: [],
|
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> {
|
async handler(resources): Promise<NonAggregatableDatasets> {
|
||||||
const { context, params } = resources;
|
const { context, params } = resources;
|
||||||
const coreContext = await context.core;
|
const coreContext = await context.core;
|
||||||
|
@ -228,6 +263,13 @@ const degradedFieldsRoute = createDatasetQualityServerRoute({
|
||||||
options: {
|
options: {
|
||||||
tags: [],
|
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> {
|
async handler(resources): Promise<DegradedFieldResponse> {
|
||||||
const { context, params } = resources;
|
const { context, params } = resources;
|
||||||
const { dataStream } = params.path;
|
const { dataStream } = params.path;
|
||||||
|
@ -255,6 +297,13 @@ const degradedFieldValuesRoute = createDatasetQualityServerRoute({
|
||||||
options: {
|
options: {
|
||||||
tags: [],
|
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> {
|
async handler(resources): Promise<DegradedFieldValues> {
|
||||||
const { context, params } = resources;
|
const { context, params } = resources;
|
||||||
const { dataStream, degradedField } = params.path;
|
const { dataStream, degradedField } = params.path;
|
||||||
|
@ -280,6 +329,13 @@ const dataStreamSettingsRoute = createDatasetQualityServerRoute({
|
||||||
options: {
|
options: {
|
||||||
tags: [],
|
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> {
|
async handler(resources): Promise<DataStreamSettings> {
|
||||||
const { context, params } = resources;
|
const { context, params } = resources;
|
||||||
const { dataStream } = params.path;
|
const { dataStream } = params.path;
|
||||||
|
@ -307,8 +363,15 @@ const checkAndLoadIntegrationRoute = createDatasetQualityServerRoute({
|
||||||
options: {
|
options: {
|
||||||
tags: [],
|
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> {
|
async handler(resources): Promise<CheckAndLoadIntegrationResponse> {
|
||||||
const { context, params, plugins, logger } = resources;
|
const { context, params, plugins, logger, request } = resources;
|
||||||
const { dataStream } = params.path;
|
const { dataStream } = params.path;
|
||||||
const coreContext = await context.core;
|
const coreContext = await context.core;
|
||||||
|
|
||||||
|
@ -316,7 +379,7 @@ const checkAndLoadIntegrationRoute = createDatasetQualityServerRoute({
|
||||||
const esClient = coreContext.elasticsearch.client.asCurrentUser;
|
const esClient = coreContext.elasticsearch.client.asCurrentUser;
|
||||||
|
|
||||||
const fleetPluginStart = await plugins.fleet.start();
|
const fleetPluginStart = await plugins.fleet.start();
|
||||||
const packageClient = fleetPluginStart.packageService.asInternalUser;
|
const packageClient = fleetPluginStart.packageService.asScoped(request);
|
||||||
|
|
||||||
const integration = await checkAndLoadIntegration({
|
const integration = await checkAndLoadIntegration({
|
||||||
esClient,
|
esClient,
|
||||||
|
@ -340,6 +403,13 @@ const dataStreamDetailsRoute = createDatasetQualityServerRoute({
|
||||||
options: {
|
options: {
|
||||||
tags: [],
|
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> {
|
async handler(resources): Promise<DataStreamDetails> {
|
||||||
const { context, params, getEsCapabilities } = resources;
|
const { context, params, getEsCapabilities } = resources;
|
||||||
const { dataStream } = params.path;
|
const { dataStream } = params.path;
|
||||||
|
@ -376,6 +446,13 @@ const analyzeDegradedFieldRoute = createDatasetQualityServerRoute({
|
||||||
options: {
|
options: {
|
||||||
tags: [],
|
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> {
|
async handler(resources): Promise<DegradedFieldAnalysis> {
|
||||||
const { context, params } = resources;
|
const { context, params } = resources;
|
||||||
const coreContext = await context.core;
|
const coreContext = await context.core;
|
||||||
|
@ -405,6 +482,13 @@ const updateFieldLimitRoute = createDatasetQualityServerRoute({
|
||||||
options: {
|
options: {
|
||||||
tags: [],
|
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> {
|
async handler(resources): Promise<UpdateFieldLimitResponse> {
|
||||||
const { context, params } = resources;
|
const { context, params } = resources;
|
||||||
const coreContext = await context.core;
|
const coreContext = await context.core;
|
||||||
|
@ -430,6 +514,13 @@ const rolloverDataStream = createDatasetQualityServerRoute({
|
||||||
options: {
|
options: {
|
||||||
tags: [],
|
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> {
|
async handler(resources): Promise<DataStreamRolloverResponse> {
|
||||||
const { context, params } = resources;
|
const { context, params } = resources;
|
||||||
const coreContext = await context.core;
|
const coreContext = await context.core;
|
||||||
|
|
|
@ -16,13 +16,20 @@ const integrationsRoute = createDatasetQualityServerRoute({
|
||||||
options: {
|
options: {
|
||||||
tags: [],
|
tags: [],
|
||||||
},
|
},
|
||||||
|
security: {
|
||||||
|
authz: {
|
||||||
|
enabled: false,
|
||||||
|
reason:
|
||||||
|
'This API delegates security to the currently logged in user and their Elasticsearch permissions.',
|
||||||
|
},
|
||||||
|
},
|
||||||
async handler(resources): Promise<{
|
async handler(resources): Promise<{
|
||||||
integrations: IntegrationType[];
|
integrations: IntegrationType[];
|
||||||
}> {
|
}> {
|
||||||
const { plugins, logger } = resources;
|
const { plugins, logger, request } = resources;
|
||||||
|
|
||||||
const fleetPluginStart = await plugins.fleet.start();
|
const fleetPluginStart = await plugins.fleet.start();
|
||||||
const packageClient = fleetPluginStart.packageService.asInternalUser;
|
const packageClient = fleetPluginStart.packageService.asScoped(request);
|
||||||
|
|
||||||
const integrations = await getIntegrations({ packageClient, logger });
|
const integrations = await getIntegrations({ packageClient, logger });
|
||||||
|
|
||||||
|
@ -40,13 +47,20 @@ const integrationDashboardsRoute = createDatasetQualityServerRoute({
|
||||||
options: {
|
options: {
|
||||||
tags: [],
|
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> {
|
async handler(resources): Promise<IntegrationDashboardsResponse> {
|
||||||
const { context, params, plugins } = resources;
|
const { context, params, plugins, request } = resources;
|
||||||
const { integration } = params.path;
|
const { integration } = params.path;
|
||||||
const { savedObjects } = await context.core;
|
const { savedObjects } = await context.core;
|
||||||
|
|
||||||
const fleetPluginStart = await plugins.fleet.start();
|
const fleetPluginStart = await plugins.fleet.start();
|
||||||
const packageClient = fleetPluginStart.packageService.asInternalUser;
|
const packageClient = fleetPluginStart.packageService.asScoped(request);
|
||||||
|
|
||||||
const integrationDashboards = await getIntegrationDashboards(
|
const integrationDashboards = await getIntegrationDashboards(
|
||||||
packageClient,
|
packageClient,
|
||||||
|
|
|
@ -170,19 +170,12 @@ export default function ({ getService, getPageObjects }: DatasetQualityFtrProvid
|
||||||
await PageObjects.datasetQuality.navigateTo();
|
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({
|
await PageObjects.datasetQuality.navigateToDetails({
|
||||||
dataStream: apacheAccessDataStreamName,
|
dataStream: apacheAccessDataStreamName,
|
||||||
});
|
});
|
||||||
await PageObjects.datasetQuality.openIntegrationActionsMenu();
|
await PageObjects.datasetQuality.openIntegrationActionsMenu();
|
||||||
|
|
||||||
// "See Integration" is hidden
|
|
||||||
await testSubjects.missingOrFail(
|
|
||||||
PageObjects.datasetQuality.testSubjectSelectors.datasetQualityDetailsIntegrationAction(
|
|
||||||
'Overview'
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
// "View Dashboards" is hidden
|
// "View Dashboards" is hidden
|
||||||
await testSubjects.missingOrFail(
|
await testSubjects.missingOrFail(
|
||||||
PageObjects.datasetQuality.testSubjectSelectors.datasetQualityDetailsIntegrationAction(
|
PageObjects.datasetQuality.testSubjectSelectors.datasetQualityDetailsIntegrationAction(
|
||||||
|
@ -217,7 +210,7 @@ async function createDatasetQualityUserWithRole(
|
||||||
feature: {
|
feature: {
|
||||||
dataQuality: [hasDataQualityPrivileges ? 'all' : 'none'],
|
dataQuality: [hasDataQualityPrivileges ? 'all' : 'none'],
|
||||||
discover: ['all'],
|
discover: ['all'],
|
||||||
fleet: ['none'],
|
fleet: ['read'],
|
||||||
},
|
},
|
||||||
spaces: ['*'],
|
spaces: ['*'],
|
||||||
},
|
},
|
||||||
|
|
|
@ -10,6 +10,7 @@ import { FtrProviderContext } from '../../../ftr_provider_context';
|
||||||
import { datasetNames, getInitialTestLogs, getLogsForDataset } from './data';
|
import { datasetNames, getInitialTestLogs, getLogsForDataset } from './data';
|
||||||
|
|
||||||
export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
|
const retry = getService('retry');
|
||||||
const PageObjects = getPageObjects([
|
const PageObjects = getPageObjects([
|
||||||
'common',
|
'common',
|
||||||
'datasetQuality',
|
'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 () => {
|
it('shows poor, degraded and good count as 0 and all dataset as healthy', async () => {
|
||||||
await PageObjects.datasetQuality.refreshTable();
|
await PageObjects.datasetQuality.refreshTable();
|
||||||
const summary = await PageObjects.datasetQuality.parseSummaryPanel(excludeKeysFromServerless);
|
// Sometimes the summary flashes with wrong count, retry to stabilize. This should be fixed at the root, but for now we retry.
|
||||||
expect(summary).to.eql({
|
await retry.try(async () => {
|
||||||
datasetHealthPoor: '0',
|
const summary = await PageObjects.datasetQuality.parseSummaryPanel(
|
||||||
datasetHealthDegraded: '0',
|
excludeKeysFromServerless
|
||||||
datasetHealthGood: '3',
|
);
|
||||||
activeDatasets: '0 of 3',
|
expect(summary).to.eql({
|
||||||
|
datasetHealthPoor: '0',
|
||||||
|
datasetHealthDegraded: '0',
|
||||||
|
datasetHealthGood: '3',
|
||||||
|
activeDatasets: '0 of 3',
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue