[ML] Moving privileges checks to server (#39585)
* [ML] Moving privileges checks to server * removing unused include * adding tests * adding general kibana type * adding coments and extra test * fixing type issue
This commit is contained in:
parent
3e48e62a47
commit
4f28b25daf
|
@ -4,5 +4,4 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
export type Cluster = Record<string, boolean>;
|
||||
export type Privileges = Record<string, boolean>;
|
||||
export type callWithRequestType = (action: string, params?: any) => Promise<any>;
|
70
x-pack/legacy/plugins/ml/common/types/privileges.ts
Normal file
70
x-pack/legacy/plugins/ml/common/types/privileges.ts
Normal file
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
//
|
||||
|
||||
export interface Privileges {
|
||||
// Anomaly Detection
|
||||
canGetJobs: boolean;
|
||||
canCreateJob: boolean;
|
||||
canDeleteJob: boolean;
|
||||
canOpenJob: boolean;
|
||||
canCloseJob: boolean;
|
||||
canForecastJob: boolean;
|
||||
canGetDatafeeds: boolean;
|
||||
canStartStopDatafeed: boolean;
|
||||
canUpdateJob: boolean;
|
||||
canUpdateDatafeed: boolean;
|
||||
canPreviewDatafeed: boolean;
|
||||
// Calendars
|
||||
canGetCalendars: boolean;
|
||||
canCreateCalendar: boolean;
|
||||
canDeleteCalendar: boolean;
|
||||
// Filters
|
||||
canGetFilters: boolean;
|
||||
canCreateFilter: boolean;
|
||||
canDeleteFilter: boolean;
|
||||
// File Data Visualizer
|
||||
canFindFileStructure: boolean;
|
||||
// Data Frames
|
||||
canGetDataFrameJobs: boolean;
|
||||
canDeleteDataFrameJob: boolean;
|
||||
canPreviewDataFrameJob: boolean;
|
||||
canCreateDataFrameJob: boolean;
|
||||
canStartStopDataFrameJob: boolean;
|
||||
}
|
||||
|
||||
export function getDefaultPrivileges(): Privileges {
|
||||
return {
|
||||
// Anomaly Detection
|
||||
canGetJobs: false,
|
||||
canCreateJob: false,
|
||||
canDeleteJob: false,
|
||||
canOpenJob: false,
|
||||
canCloseJob: false,
|
||||
canForecastJob: false,
|
||||
canGetDatafeeds: false,
|
||||
canStartStopDatafeed: false,
|
||||
canUpdateJob: false,
|
||||
canUpdateDatafeed: false,
|
||||
canPreviewDatafeed: false,
|
||||
// Calendars
|
||||
canGetCalendars: false,
|
||||
canCreateCalendar: false,
|
||||
canDeleteCalendar: false,
|
||||
// Filters
|
||||
canGetFilters: false,
|
||||
canCreateFilter: false,
|
||||
canDeleteFilter: false,
|
||||
// File Data Visualizer
|
||||
canFindFileStructure: false,
|
||||
// Data Frames
|
||||
canGetDataFrameJobs: false,
|
||||
canDeleteDataFrameJob: false,
|
||||
canPreviewDataFrameJob: false,
|
||||
canCreateDataFrameJob: false,
|
||||
canStartStopDataFrameJob: false,
|
||||
};
|
||||
}
|
|
@ -139,6 +139,6 @@ export async function hasImportPermission(indexName) {
|
|||
];
|
||||
}
|
||||
|
||||
const resp = await ml.checkPrivilege(priv);
|
||||
const resp = await ml.hasPrivileges(priv);
|
||||
return (resp.securityDisabled === true || resp.has_all_requested === true);
|
||||
}
|
||||
|
|
|
@ -9,10 +9,10 @@ import { i18n } from '@kbn/i18n';
|
|||
// @ts-ignore
|
||||
import { hasLicenseExpired } from '../license/check_license';
|
||||
|
||||
import { Privileges } from './common';
|
||||
import { Privileges, getDefaultPrivileges } from '../../common/types/privileges';
|
||||
import { getPrivileges } from './get_privileges';
|
||||
|
||||
let privileges: Privileges = {};
|
||||
let privileges: Privileges = getDefaultPrivileges();
|
||||
|
||||
export function checkGetJobsPrivilege(kbnUrl: any): Promise<Privileges> {
|
||||
return new Promise((resolve, reject) => {
|
||||
|
@ -100,7 +100,7 @@ export function checkCreateDataFrameJobsPrivilege(kbnUrl: any): Promise<Privileg
|
|||
|
||||
// check the privilege type and the license to see whether a user has permission to access a feature.
|
||||
// takes the name of the privilege variable as specified in get_privileges.js
|
||||
export function checkPermission(privilegeType: string) {
|
||||
export function checkPermission(privilegeType: keyof Privileges) {
|
||||
const licenseHasExpired = hasLicenseExpired();
|
||||
return privileges[privilegeType] === true && licenseHasExpired !== true;
|
||||
}
|
||||
|
|
|
@ -5,249 +5,21 @@
|
|||
*/
|
||||
|
||||
import { ml } from '../services/ml_api_service';
|
||||
// @ts-ignore
|
||||
import { setUpgradeInProgress } from '../services/upgrade_service';
|
||||
|
||||
import { Cluster, Privileges } from './common';
|
||||
import { setUpgradeInProgress } from '../services/upgrade_service';
|
||||
import { Privileges, getDefaultPrivileges } from '../../common/types/privileges';
|
||||
|
||||
export function getPrivileges(): Promise<Privileges> {
|
||||
const privileges: Privileges = {
|
||||
// Anomaly Detection
|
||||
canGetJobs: false,
|
||||
canCreateJob: false,
|
||||
canDeleteJob: false,
|
||||
canOpenJob: false,
|
||||
canCloseJob: false,
|
||||
canForecastJob: false,
|
||||
canGetDatafeeds: false,
|
||||
canStartStopDatafeed: false,
|
||||
canUpdateJob: false,
|
||||
canUpdateDatafeed: false,
|
||||
canPreviewDatafeed: false,
|
||||
// Calendars
|
||||
canGetCalendars: false,
|
||||
canCreateCalendar: false,
|
||||
canDeleteCalendar: false,
|
||||
// Filters
|
||||
canGetFilters: false,
|
||||
canCreateFilter: false,
|
||||
canDeleteFilter: false,
|
||||
// File Data Visualizer
|
||||
canFindFileStructure: false,
|
||||
// Data Frames
|
||||
canGetDataFrameJobs: false,
|
||||
canDeleteDataFrameJob: false,
|
||||
canPreviewDataFrameJob: false,
|
||||
canCreateDataFrameJob: false,
|
||||
canStartStopDataFrameJob: false,
|
||||
};
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const priv = {
|
||||
cluster: [
|
||||
'cluster:monitor/data_frame/get',
|
||||
'cluster:monitor/data_frame/stats/get',
|
||||
'cluster:monitor/xpack/ml/job/get',
|
||||
'cluster:monitor/xpack/ml/job/stats/get',
|
||||
'cluster:monitor/xpack/ml/datafeeds/get',
|
||||
'cluster:monitor/xpack/ml/datafeeds/stats/get',
|
||||
'cluster:monitor/xpack/ml/calendars/get',
|
||||
'cluster:admin/data_frame/delete',
|
||||
'cluster:admin/data_frame/preview',
|
||||
'cluster:admin/data_frame/put',
|
||||
'cluster:admin/data_frame/start',
|
||||
'cluster:admin/data_frame/start_task',
|
||||
'cluster:admin/data_frame/stop',
|
||||
'cluster:admin/xpack/ml/job/put',
|
||||
'cluster:admin/xpack/ml/job/delete',
|
||||
'cluster:admin/xpack/ml/job/update',
|
||||
'cluster:admin/xpack/ml/job/open',
|
||||
'cluster:admin/xpack/ml/job/close',
|
||||
'cluster:admin/xpack/ml/job/forecast',
|
||||
'cluster:admin/xpack/ml/datafeeds/put',
|
||||
'cluster:admin/xpack/ml/datafeeds/delete',
|
||||
'cluster:admin/xpack/ml/datafeeds/start',
|
||||
'cluster:admin/xpack/ml/datafeeds/stop',
|
||||
'cluster:admin/xpack/ml/datafeeds/update',
|
||||
'cluster:admin/xpack/ml/datafeeds/preview',
|
||||
'cluster:admin/xpack/ml/calendars/put',
|
||||
'cluster:admin/xpack/ml/calendars/delete',
|
||||
'cluster:admin/xpack/ml/calendars/jobs/update',
|
||||
'cluster:admin/xpack/ml/calendars/events/post',
|
||||
'cluster:admin/xpack/ml/calendars/events/delete',
|
||||
'cluster:admin/xpack/ml/filters/put',
|
||||
'cluster:admin/xpack/ml/filters/get',
|
||||
'cluster:admin/xpack/ml/filters/update',
|
||||
'cluster:admin/xpack/ml/filters/delete',
|
||||
'cluster:monitor/xpack/ml/findfilestructure',
|
||||
],
|
||||
};
|
||||
|
||||
ml.checkPrivilege(priv)
|
||||
.then(resp => {
|
||||
if (resp.upgradeInProgress === true) {
|
||||
ml.checkMlPrivileges()
|
||||
.then(({ privileges, upgradeInProgress }) => {
|
||||
if (upgradeInProgress === true) {
|
||||
setUpgradeInProgress(true);
|
||||
// only check for getting endpoints
|
||||
// force all to be true if security is disabled
|
||||
setGettingPrivileges(resp.cluster, privileges, resp.securityDisabled === true);
|
||||
} else if (resp.securityDisabled) {
|
||||
// if security has been disabled, securityDisabled is returned from the endpoint
|
||||
// therefore set all privileges to true
|
||||
Object.keys(privileges).forEach(k => (privileges[k] = true));
|
||||
} else {
|
||||
setGettingPrivileges(resp.cluster, privileges);
|
||||
setActionPrivileges(resp.cluster, privileges);
|
||||
}
|
||||
|
||||
resolve(privileges);
|
||||
})
|
||||
.catch(() => {
|
||||
reject(privileges);
|
||||
reject(getDefaultPrivileges());
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function setGettingPrivileges(
|
||||
cluster: Cluster = {},
|
||||
privileges: Privileges = {},
|
||||
forceTrue = false
|
||||
) {
|
||||
// Anomaly Detection
|
||||
if (
|
||||
forceTrue ||
|
||||
(cluster['cluster:monitor/xpack/ml/job/get'] &&
|
||||
cluster['cluster:monitor/xpack/ml/job/stats/get'])
|
||||
) {
|
||||
privileges.canGetJobs = true;
|
||||
}
|
||||
|
||||
if (
|
||||
forceTrue ||
|
||||
(cluster['cluster:monitor/xpack/ml/datafeeds/get'] &&
|
||||
cluster['cluster:monitor/xpack/ml/datafeeds/stats/get'])
|
||||
) {
|
||||
privileges.canGetDatafeeds = true;
|
||||
}
|
||||
|
||||
// Calendars
|
||||
if (forceTrue || cluster['cluster:monitor/xpack/ml/calendars/get']) {
|
||||
privileges.canGetCalendars = true;
|
||||
}
|
||||
|
||||
// Filters
|
||||
if (forceTrue || cluster['cluster:admin/xpack/ml/filters/get']) {
|
||||
privileges.canGetFilters = true;
|
||||
}
|
||||
|
||||
// File Data Visualizer
|
||||
if (forceTrue || cluster['cluster:monitor/xpack/ml/findfilestructure']) {
|
||||
privileges.canFindFileStructure = true;
|
||||
}
|
||||
|
||||
// Data Frames
|
||||
if (
|
||||
forceTrue ||
|
||||
(cluster['cluster:monitor/data_frame/get'] && cluster['cluster:monitor/data_frame/stats/get'])
|
||||
) {
|
||||
privileges.canGetDataFrameJobs = true;
|
||||
}
|
||||
}
|
||||
|
||||
function setActionPrivileges(cluster: Cluster = {}, privileges: Privileges = {}) {
|
||||
// Anomaly Detection
|
||||
if (
|
||||
cluster['cluster:admin/xpack/ml/job/put'] &&
|
||||
cluster['cluster:admin/xpack/ml/job/open'] &&
|
||||
cluster['cluster:admin/xpack/ml/datafeeds/put']
|
||||
) {
|
||||
privileges.canCreateJob = true;
|
||||
}
|
||||
|
||||
if (cluster['cluster:admin/xpack/ml/job/update']) {
|
||||
privileges.canUpdateJob = true;
|
||||
}
|
||||
|
||||
if (cluster['cluster:admin/xpack/ml/job/open']) {
|
||||
privileges.canOpenJob = true;
|
||||
}
|
||||
|
||||
if (cluster['cluster:admin/xpack/ml/job/close']) {
|
||||
privileges.canCloseJob = true;
|
||||
}
|
||||
|
||||
if (cluster['cluster:admin/xpack/ml/job/forecast']) {
|
||||
privileges.canForecastJob = true;
|
||||
}
|
||||
|
||||
if (
|
||||
cluster['cluster:admin/xpack/ml/job/delete'] &&
|
||||
cluster['cluster:admin/xpack/ml/datafeeds/delete']
|
||||
) {
|
||||
privileges.canDeleteJob = true;
|
||||
}
|
||||
|
||||
if (
|
||||
cluster['cluster:admin/xpack/ml/job/open'] &&
|
||||
cluster['cluster:admin/xpack/ml/datafeeds/start'] &&
|
||||
cluster['cluster:admin/xpack/ml/datafeeds/stop']
|
||||
) {
|
||||
privileges.canStartStopDatafeed = true;
|
||||
}
|
||||
|
||||
if (cluster['cluster:admin/xpack/ml/datafeeds/update']) {
|
||||
privileges.canUpdateDatafeed = true;
|
||||
}
|
||||
|
||||
if (cluster['cluster:admin/xpack/ml/datafeeds/preview']) {
|
||||
privileges.canPreviewDatafeed = true;
|
||||
}
|
||||
|
||||
// Calendars
|
||||
if (
|
||||
cluster['cluster:admin/xpack/ml/calendars/put'] &&
|
||||
cluster['cluster:admin/xpack/ml/calendars/jobs/update'] &&
|
||||
cluster['cluster:admin/xpack/ml/calendars/events/post']
|
||||
) {
|
||||
privileges.canCreateCalendar = true;
|
||||
}
|
||||
|
||||
if (
|
||||
cluster['cluster:admin/xpack/ml/calendars/delete'] &&
|
||||
cluster['cluster:admin/xpack/ml/calendars/events/delete']
|
||||
) {
|
||||
privileges.canDeleteCalendar = true;
|
||||
}
|
||||
|
||||
// Filters
|
||||
if (
|
||||
cluster['cluster:admin/xpack/ml/filters/put'] &&
|
||||
cluster['cluster:admin/xpack/ml/filters/update']
|
||||
) {
|
||||
privileges.canCreateFilter = true;
|
||||
}
|
||||
|
||||
if (cluster['cluster:admin/xpack/ml/filters/delete']) {
|
||||
privileges.canDeleteFilter = true;
|
||||
}
|
||||
|
||||
// Data Frames
|
||||
if (cluster['cluster:admin/data_frame/put']) {
|
||||
privileges.canCreateDataFrameJob = true;
|
||||
}
|
||||
|
||||
if (cluster['cluster:admin/data_frame/delete']) {
|
||||
privileges.canDeleteDataFrameJob = true;
|
||||
}
|
||||
|
||||
if (cluster['cluster:admin/data_frame/preview']) {
|
||||
privileges.canPreviewDataFrameJob = true;
|
||||
}
|
||||
|
||||
if (
|
||||
cluster['cluster:admin/data_frame/start'] &&
|
||||
cluster['cluster:admin/data_frame/start_task'] &&
|
||||
cluster['cluster:admin/data_frame/stop']
|
||||
) {
|
||||
privileges.canStartStopDataFrameJob = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
|
||||
import { Annotation } from '../../../common/types/annotations';
|
||||
import { Privileges } from '../../../common/types/privileges';
|
||||
|
||||
// TODO This is not a complete representation of all methods of `ml.*`.
|
||||
// It just satisfies needs for other parts of the code area which use
|
||||
|
@ -30,7 +31,8 @@ declare interface Ml {
|
|||
stopDataFrameTransformsJob(jobId: string): Promise<any>;
|
||||
};
|
||||
|
||||
checkPrivilege(obj: object): Promise<any>;
|
||||
hasPrivileges(obj: object): Promise<any>;
|
||||
checkMlPrivileges(): Promise<{ privileges: Privileges; upgradeInProgress: boolean }>;
|
||||
esSearch: any;
|
||||
getIndices(): Promise<EsIndex[]>;
|
||||
|
||||
|
|
|
@ -211,7 +211,7 @@ export const ml = {
|
|||
});
|
||||
},
|
||||
|
||||
checkPrivilege(obj) {
|
||||
hasPrivileges(obj) {
|
||||
return http({
|
||||
url: `${basePath}/_has_privileges`,
|
||||
method: 'POST',
|
||||
|
@ -219,6 +219,13 @@ export const ml = {
|
|||
});
|
||||
},
|
||||
|
||||
checkMlPrivileges() {
|
||||
return http({
|
||||
url: `${basePath}/ml_privileges`,
|
||||
method: 'GET',
|
||||
});
|
||||
},
|
||||
|
||||
getNotificationSettings() {
|
||||
return http({
|
||||
url: `${basePath}/notification_settings`,
|
||||
|
|
|
@ -4,13 +4,12 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
let upgradeInProgress: boolean = false;
|
||||
|
||||
let upgradeInProgress = false;
|
||||
|
||||
export function setUpgradeInProgress(show) {
|
||||
export function setUpgradeInProgress(show: boolean) {
|
||||
upgradeInProgress = show;
|
||||
}
|
||||
|
||||
export function isUpgradeInProgress() {
|
||||
export function isUpgradeInProgress(): boolean {
|
||||
return upgradeInProgress;
|
||||
}
|
|
@ -0,0 +1,170 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
export function callWithRequestProvider(testType: string) {
|
||||
switch (testType) {
|
||||
case 'partialPrivileges':
|
||||
return partialPrivileges;
|
||||
case 'fullPrivileges':
|
||||
return fullPrivileges;
|
||||
case 'upgradeWithFullPrivileges':
|
||||
return upgradeWithFullPrivileges;
|
||||
case 'upgradeWithPartialPrivileges':
|
||||
return upgradeWithPartialPrivileges;
|
||||
|
||||
default:
|
||||
return fullPrivileges;
|
||||
}
|
||||
}
|
||||
|
||||
const fullPrivileges = async (action: string, params?: any) => {
|
||||
switch (action) {
|
||||
case 'ml.privilegeCheck':
|
||||
return {
|
||||
username: 'test2',
|
||||
has_all_requested: false,
|
||||
cluster: fullClusterPrivileges,
|
||||
index: {},
|
||||
application: {},
|
||||
};
|
||||
case 'ml.info':
|
||||
return { upgrade_mode: false };
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
const partialPrivileges = async (action: string, params?: any) => {
|
||||
switch (action) {
|
||||
case 'ml.privilegeCheck':
|
||||
return {
|
||||
username: 'test2',
|
||||
has_all_requested: false,
|
||||
cluster: partialClusterPrivileges,
|
||||
index: {},
|
||||
application: {},
|
||||
};
|
||||
case 'ml.info':
|
||||
return { upgrade_mode: false };
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
const upgradeWithFullPrivileges = async (action: string, params?: any) => {
|
||||
switch (action) {
|
||||
case 'ml.privilegeCheck':
|
||||
return {
|
||||
username: 'elastic',
|
||||
has_all_requested: true,
|
||||
cluster: fullClusterPrivileges,
|
||||
index: {},
|
||||
application: {},
|
||||
};
|
||||
case 'ml.info':
|
||||
return { upgrade_mode: true };
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
const upgradeWithPartialPrivileges = async (action: string, params?: any) => {
|
||||
switch (action) {
|
||||
case 'ml.privilegeCheck':
|
||||
return {
|
||||
username: 'test2',
|
||||
has_all_requested: false,
|
||||
cluster: partialClusterPrivileges,
|
||||
index: {},
|
||||
application: {},
|
||||
};
|
||||
case 'ml.info':
|
||||
return { upgrade_mode: true };
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
const fullClusterPrivileges = {
|
||||
'cluster:admin/xpack/ml/datafeeds/delete': true,
|
||||
'cluster:admin/xpack/ml/datafeeds/update': true,
|
||||
'cluster:admin/xpack/ml/job/forecast': true,
|
||||
'cluster:monitor/xpack/ml/job/stats/get': true,
|
||||
'cluster:admin/xpack/ml/filters/delete': true,
|
||||
'cluster:admin/xpack/ml/datafeeds/preview': true,
|
||||
'cluster:admin/xpack/ml/datafeeds/start': true,
|
||||
'cluster:admin/xpack/ml/filters/put': true,
|
||||
'cluster:admin/xpack/ml/datafeeds/stop': true,
|
||||
'cluster:monitor/xpack/ml/calendars/get': true,
|
||||
'cluster:admin/xpack/ml/filters/get': true,
|
||||
'cluster:monitor/xpack/ml/datafeeds/get': true,
|
||||
'cluster:admin/data_frame/start_task': true,
|
||||
'cluster:admin/xpack/ml/filters/update': true,
|
||||
'cluster:admin/xpack/ml/calendars/events/post': true,
|
||||
'cluster:monitor/data_frame/get': true,
|
||||
'cluster:admin/xpack/ml/job/close': true,
|
||||
'cluster:monitor/xpack/ml/datafeeds/stats/get': true,
|
||||
'cluster:admin/data_frame/preview': true,
|
||||
'cluster:admin/xpack/ml/calendars/jobs/update': true,
|
||||
'cluster:admin/data_frame/put': true,
|
||||
'cluster:admin/xpack/ml/calendars/put': true,
|
||||
'cluster:monitor/data_frame/stats/get': true,
|
||||
'cluster:admin/data_frame/stop': true,
|
||||
'cluster:admin/xpack/ml/calendars/events/delete': true,
|
||||
'cluster:admin/xpack/ml/datafeeds/put': true,
|
||||
'cluster:admin/xpack/ml/job/open': true,
|
||||
'cluster:admin/xpack/ml/job/delete': true,
|
||||
'cluster:monitor/xpack/ml/job/get': true,
|
||||
'cluster:admin/data_frame/delete': true,
|
||||
'cluster:admin/xpack/ml/job/put': true,
|
||||
'cluster:admin/xpack/ml/job/update': true,
|
||||
'cluster:admin/data_frame/start': true,
|
||||
'cluster:admin/xpack/ml/calendars/delete': true,
|
||||
'cluster:monitor/xpack/ml/findfilestructure': true,
|
||||
};
|
||||
|
||||
// the same as ml_user role
|
||||
const partialClusterPrivileges = {
|
||||
'cluster:admin/xpack/ml/datafeeds/delete': false,
|
||||
'cluster:admin/xpack/ml/datafeeds/update': false,
|
||||
'cluster:admin/xpack/ml/job/forecast': false,
|
||||
'cluster:monitor/xpack/ml/job/stats/get': true,
|
||||
'cluster:admin/xpack/ml/filters/delete': false,
|
||||
'cluster:admin/xpack/ml/datafeeds/preview': false,
|
||||
'cluster:admin/xpack/ml/datafeeds/start': false,
|
||||
'cluster:admin/xpack/ml/filters/put': false,
|
||||
'cluster:admin/xpack/ml/datafeeds/stop': false,
|
||||
'cluster:monitor/xpack/ml/calendars/get': true,
|
||||
'cluster:admin/xpack/ml/filters/get': false,
|
||||
'cluster:monitor/xpack/ml/datafeeds/get': true,
|
||||
'cluster:admin/data_frame/start_task': false,
|
||||
'cluster:admin/xpack/ml/filters/update': false,
|
||||
'cluster:admin/xpack/ml/calendars/events/post': false,
|
||||
'cluster:monitor/data_frame/get': false,
|
||||
'cluster:admin/xpack/ml/job/close': false,
|
||||
'cluster:monitor/xpack/ml/datafeeds/stats/get': true,
|
||||
'cluster:admin/data_frame/preview': false,
|
||||
'cluster:admin/xpack/ml/calendars/jobs/update': false,
|
||||
'cluster:admin/data_frame/put': false,
|
||||
'cluster:admin/xpack/ml/calendars/put': false,
|
||||
'cluster:monitor/data_frame/stats/get': false,
|
||||
'cluster:admin/data_frame/stop': false,
|
||||
'cluster:admin/xpack/ml/calendars/events/delete': false,
|
||||
'cluster:admin/xpack/ml/datafeeds/put': false,
|
||||
'cluster:admin/xpack/ml/job/open': false,
|
||||
'cluster:admin/xpack/ml/job/delete': false,
|
||||
'cluster:monitor/xpack/ml/job/get': true,
|
||||
'cluster:admin/data_frame/delete': false,
|
||||
'cluster:admin/xpack/ml/job/put': false,
|
||||
'cluster:admin/xpack/ml/job/update': false,
|
||||
'cluster:admin/data_frame/start': false,
|
||||
'cluster:admin/xpack/ml/calendars/delete': false,
|
||||
'cluster:monitor/xpack/ml/findfilestructure': true,
|
||||
};
|
|
@ -0,0 +1,267 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { callWithRequestProvider } from './__mocks__/call_with_request';
|
||||
import { privilegesProvider } from './check_privileges';
|
||||
import { mlPrivileges } from './privileges';
|
||||
|
||||
const xpackMainPluginWithSecurity = {
|
||||
info: {
|
||||
isAvailable: () => true,
|
||||
feature: () => ({
|
||||
isEnabled: () => true,
|
||||
}),
|
||||
},
|
||||
};
|
||||
|
||||
const xpackMainPluginWithOutSecurity = {
|
||||
info: {
|
||||
isAvailable: () => true,
|
||||
feature: () => ({
|
||||
isEnabled: () => false,
|
||||
}),
|
||||
},
|
||||
};
|
||||
|
||||
describe('check_privileges', () => {
|
||||
describe('getPrivileges() - right number of privileges', () => {
|
||||
test('es privileges count', async done => {
|
||||
const count = mlPrivileges.cluster.length;
|
||||
expect(count).toBe(35);
|
||||
done();
|
||||
});
|
||||
|
||||
test('kibana privileges count', async done => {
|
||||
const callWithRequest = callWithRequestProvider('partialPrivileges');
|
||||
const { getPrivileges } = privilegesProvider(callWithRequest, xpackMainPluginWithSecurity);
|
||||
const { privileges } = await getPrivileges();
|
||||
const count = Object.keys(privileges).length;
|
||||
expect(count).toBe(23);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
describe('getPrivileges() with security', () => {
|
||||
test('ml_user privileges only', async done => {
|
||||
const callWithRequest = callWithRequestProvider('partialPrivileges');
|
||||
const { getPrivileges } = privilegesProvider(callWithRequest, xpackMainPluginWithSecurity);
|
||||
const { privileges, upgradeInProgress } = await getPrivileges();
|
||||
expect(upgradeInProgress).toBe(false);
|
||||
expect(privileges.canGetJobs).toBe(true);
|
||||
expect(privileges.canCreateJob).toBe(false);
|
||||
expect(privileges.canDeleteJob).toBe(false);
|
||||
expect(privileges.canOpenJob).toBe(false);
|
||||
expect(privileges.canCloseJob).toBe(false);
|
||||
expect(privileges.canForecastJob).toBe(false);
|
||||
expect(privileges.canGetDatafeeds).toBe(true);
|
||||
expect(privileges.canStartStopDatafeed).toBe(false);
|
||||
expect(privileges.canUpdateJob).toBe(false);
|
||||
expect(privileges.canUpdateDatafeed).toBe(false);
|
||||
expect(privileges.canPreviewDatafeed).toBe(false);
|
||||
expect(privileges.canGetCalendars).toBe(true);
|
||||
expect(privileges.canCreateCalendar).toBe(false);
|
||||
expect(privileges.canDeleteCalendar).toBe(false);
|
||||
expect(privileges.canGetFilters).toBe(false);
|
||||
expect(privileges.canCreateFilter).toBe(false);
|
||||
expect(privileges.canDeleteFilter).toBe(false);
|
||||
expect(privileges.canFindFileStructure).toBe(true);
|
||||
expect(privileges.canGetDataFrameJobs).toBe(false);
|
||||
expect(privileges.canDeleteDataFrameJob).toBe(false);
|
||||
expect(privileges.canPreviewDataFrameJob).toBe(false);
|
||||
expect(privileges.canCreateDataFrameJob).toBe(false);
|
||||
expect(privileges.canStartStopDataFrameJob).toBe(false);
|
||||
done();
|
||||
});
|
||||
|
||||
test('full privileges', async done => {
|
||||
const callWithRequest = callWithRequestProvider('fullPrivileges');
|
||||
const { getPrivileges } = privilegesProvider(callWithRequest, xpackMainPluginWithSecurity);
|
||||
const { privileges, upgradeInProgress } = await getPrivileges();
|
||||
expect(upgradeInProgress).toBe(false);
|
||||
expect(privileges.canGetJobs).toBe(true);
|
||||
expect(privileges.canCreateJob).toBe(true);
|
||||
expect(privileges.canDeleteJob).toBe(true);
|
||||
expect(privileges.canOpenJob).toBe(true);
|
||||
expect(privileges.canCloseJob).toBe(true);
|
||||
expect(privileges.canForecastJob).toBe(true);
|
||||
expect(privileges.canGetDatafeeds).toBe(true);
|
||||
expect(privileges.canStartStopDatafeed).toBe(true);
|
||||
expect(privileges.canUpdateJob).toBe(true);
|
||||
expect(privileges.canUpdateDatafeed).toBe(true);
|
||||
expect(privileges.canPreviewDatafeed).toBe(true);
|
||||
expect(privileges.canGetCalendars).toBe(true);
|
||||
expect(privileges.canCreateCalendar).toBe(true);
|
||||
expect(privileges.canDeleteCalendar).toBe(true);
|
||||
expect(privileges.canGetFilters).toBe(true);
|
||||
expect(privileges.canCreateFilter).toBe(true);
|
||||
expect(privileges.canDeleteFilter).toBe(true);
|
||||
expect(privileges.canFindFileStructure).toBe(true);
|
||||
expect(privileges.canGetDataFrameJobs).toBe(true);
|
||||
expect(privileges.canDeleteDataFrameJob).toBe(true);
|
||||
expect(privileges.canPreviewDataFrameJob).toBe(true);
|
||||
expect(privileges.canCreateDataFrameJob).toBe(true);
|
||||
expect(privileges.canStartStopDataFrameJob).toBe(true);
|
||||
done();
|
||||
});
|
||||
|
||||
test('upgrade in progress with full privileges', async done => {
|
||||
const callWithRequest = callWithRequestProvider('upgradeWithFullPrivileges');
|
||||
const { getPrivileges } = privilegesProvider(callWithRequest, xpackMainPluginWithSecurity);
|
||||
const { privileges, upgradeInProgress } = await getPrivileges();
|
||||
expect(upgradeInProgress).toBe(true);
|
||||
expect(privileges.canGetJobs).toBe(true);
|
||||
expect(privileges.canCreateJob).toBe(false);
|
||||
expect(privileges.canDeleteJob).toBe(false);
|
||||
expect(privileges.canOpenJob).toBe(false);
|
||||
expect(privileges.canCloseJob).toBe(false);
|
||||
expect(privileges.canForecastJob).toBe(false);
|
||||
expect(privileges.canGetDatafeeds).toBe(true);
|
||||
expect(privileges.canStartStopDatafeed).toBe(false);
|
||||
expect(privileges.canUpdateJob).toBe(false);
|
||||
expect(privileges.canUpdateDatafeed).toBe(false);
|
||||
expect(privileges.canPreviewDatafeed).toBe(false);
|
||||
expect(privileges.canGetCalendars).toBe(true);
|
||||
expect(privileges.canCreateCalendar).toBe(false);
|
||||
expect(privileges.canDeleteCalendar).toBe(false);
|
||||
expect(privileges.canGetFilters).toBe(true);
|
||||
expect(privileges.canCreateFilter).toBe(false);
|
||||
expect(privileges.canDeleteFilter).toBe(false);
|
||||
expect(privileges.canFindFileStructure).toBe(true);
|
||||
expect(privileges.canGetDataFrameJobs).toBe(true);
|
||||
expect(privileges.canDeleteDataFrameJob).toBe(false);
|
||||
expect(privileges.canPreviewDataFrameJob).toBe(false);
|
||||
expect(privileges.canCreateDataFrameJob).toBe(false);
|
||||
expect(privileges.canStartStopDataFrameJob).toBe(false);
|
||||
done();
|
||||
});
|
||||
|
||||
test('upgrade in progress with partial privileges', async done => {
|
||||
const callWithRequest = callWithRequestProvider('upgradeWithPartialPrivileges');
|
||||
const { getPrivileges } = privilegesProvider(callWithRequest, xpackMainPluginWithSecurity);
|
||||
const { privileges, upgradeInProgress } = await getPrivileges();
|
||||
expect(upgradeInProgress).toBe(true);
|
||||
expect(privileges.canGetJobs).toBe(true);
|
||||
expect(privileges.canCreateJob).toBe(false);
|
||||
expect(privileges.canDeleteJob).toBe(false);
|
||||
expect(privileges.canOpenJob).toBe(false);
|
||||
expect(privileges.canCloseJob).toBe(false);
|
||||
expect(privileges.canForecastJob).toBe(false);
|
||||
expect(privileges.canGetDatafeeds).toBe(true);
|
||||
expect(privileges.canStartStopDatafeed).toBe(false);
|
||||
expect(privileges.canUpdateJob).toBe(false);
|
||||
expect(privileges.canUpdateDatafeed).toBe(false);
|
||||
expect(privileges.canPreviewDatafeed).toBe(false);
|
||||
expect(privileges.canGetCalendars).toBe(true);
|
||||
expect(privileges.canCreateCalendar).toBe(false);
|
||||
expect(privileges.canDeleteCalendar).toBe(false);
|
||||
expect(privileges.canGetFilters).toBe(false);
|
||||
expect(privileges.canCreateFilter).toBe(false);
|
||||
expect(privileges.canDeleteFilter).toBe(false);
|
||||
expect(privileges.canFindFileStructure).toBe(true);
|
||||
expect(privileges.canGetDataFrameJobs).toBe(false);
|
||||
expect(privileges.canDeleteDataFrameJob).toBe(false);
|
||||
expect(privileges.canPreviewDataFrameJob).toBe(false);
|
||||
expect(privileges.canCreateDataFrameJob).toBe(false);
|
||||
expect(privileges.canStartStopDataFrameJob).toBe(false);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
describe('getPrivileges() without security', () => {
|
||||
test('ml_user privileges only', async done => {
|
||||
const callWithRequest = callWithRequestProvider('partialPrivileges');
|
||||
const { getPrivileges } = privilegesProvider(callWithRequest, xpackMainPluginWithOutSecurity);
|
||||
const { privileges, upgradeInProgress } = await getPrivileges();
|
||||
expect(upgradeInProgress).toBe(false);
|
||||
expect(privileges.canGetJobs).toBe(true);
|
||||
expect(privileges.canCreateJob).toBe(true);
|
||||
expect(privileges.canDeleteJob).toBe(true);
|
||||
expect(privileges.canOpenJob).toBe(true);
|
||||
expect(privileges.canCloseJob).toBe(true);
|
||||
expect(privileges.canForecastJob).toBe(true);
|
||||
expect(privileges.canGetDatafeeds).toBe(true);
|
||||
expect(privileges.canStartStopDatafeed).toBe(true);
|
||||
expect(privileges.canUpdateJob).toBe(true);
|
||||
expect(privileges.canUpdateDatafeed).toBe(true);
|
||||
expect(privileges.canPreviewDatafeed).toBe(true);
|
||||
expect(privileges.canGetCalendars).toBe(true);
|
||||
expect(privileges.canCreateCalendar).toBe(true);
|
||||
expect(privileges.canDeleteCalendar).toBe(true);
|
||||
expect(privileges.canGetFilters).toBe(true);
|
||||
expect(privileges.canCreateFilter).toBe(true);
|
||||
expect(privileges.canDeleteFilter).toBe(true);
|
||||
expect(privileges.canFindFileStructure).toBe(true);
|
||||
expect(privileges.canGetDataFrameJobs).toBe(true);
|
||||
expect(privileges.canDeleteDataFrameJob).toBe(true);
|
||||
expect(privileges.canPreviewDataFrameJob).toBe(true);
|
||||
expect(privileges.canCreateDataFrameJob).toBe(true);
|
||||
expect(privileges.canStartStopDataFrameJob).toBe(true);
|
||||
done();
|
||||
});
|
||||
|
||||
test('upgrade in progress with full privileges', async done => {
|
||||
const callWithRequest = callWithRequestProvider('upgradeWithFullPrivileges');
|
||||
const { getPrivileges } = privilegesProvider(callWithRequest, xpackMainPluginWithOutSecurity);
|
||||
const { privileges, upgradeInProgress } = await getPrivileges();
|
||||
expect(upgradeInProgress).toBe(true);
|
||||
expect(privileges.canGetJobs).toBe(true);
|
||||
expect(privileges.canCreateJob).toBe(false);
|
||||
expect(privileges.canDeleteJob).toBe(false);
|
||||
expect(privileges.canOpenJob).toBe(false);
|
||||
expect(privileges.canCloseJob).toBe(false);
|
||||
expect(privileges.canForecastJob).toBe(false);
|
||||
expect(privileges.canGetDatafeeds).toBe(true);
|
||||
expect(privileges.canStartStopDatafeed).toBe(false);
|
||||
expect(privileges.canUpdateJob).toBe(false);
|
||||
expect(privileges.canUpdateDatafeed).toBe(false);
|
||||
expect(privileges.canPreviewDatafeed).toBe(false);
|
||||
expect(privileges.canGetCalendars).toBe(true);
|
||||
expect(privileges.canCreateCalendar).toBe(false);
|
||||
expect(privileges.canDeleteCalendar).toBe(false);
|
||||
expect(privileges.canGetFilters).toBe(true);
|
||||
expect(privileges.canCreateFilter).toBe(false);
|
||||
expect(privileges.canDeleteFilter).toBe(false);
|
||||
expect(privileges.canFindFileStructure).toBe(true);
|
||||
expect(privileges.canGetDataFrameJobs).toBe(true);
|
||||
expect(privileges.canDeleteDataFrameJob).toBe(false);
|
||||
expect(privileges.canPreviewDataFrameJob).toBe(false);
|
||||
expect(privileges.canCreateDataFrameJob).toBe(false);
|
||||
expect(privileges.canStartStopDataFrameJob).toBe(false);
|
||||
done();
|
||||
});
|
||||
|
||||
test('upgrade in progress with partial privileges', async done => {
|
||||
const callWithRequest = callWithRequestProvider('upgradeWithPartialPrivileges');
|
||||
const { getPrivileges } = privilegesProvider(callWithRequest, xpackMainPluginWithOutSecurity);
|
||||
const { privileges, upgradeInProgress } = await getPrivileges();
|
||||
expect(upgradeInProgress).toBe(true);
|
||||
expect(privileges.canGetJobs).toBe(true);
|
||||
expect(privileges.canCreateJob).toBe(false);
|
||||
expect(privileges.canDeleteJob).toBe(false);
|
||||
expect(privileges.canOpenJob).toBe(false);
|
||||
expect(privileges.canCloseJob).toBe(false);
|
||||
expect(privileges.canForecastJob).toBe(false);
|
||||
expect(privileges.canGetDatafeeds).toBe(true);
|
||||
expect(privileges.canStartStopDatafeed).toBe(false);
|
||||
expect(privileges.canUpdateJob).toBe(false);
|
||||
expect(privileges.canUpdateDatafeed).toBe(false);
|
||||
expect(privileges.canPreviewDatafeed).toBe(false);
|
||||
expect(privileges.canGetCalendars).toBe(true);
|
||||
expect(privileges.canCreateCalendar).toBe(false);
|
||||
expect(privileges.canDeleteCalendar).toBe(false);
|
||||
expect(privileges.canGetFilters).toBe(true);
|
||||
expect(privileges.canCreateFilter).toBe(false);
|
||||
expect(privileges.canDeleteFilter).toBe(false);
|
||||
expect(privileges.canFindFileStructure).toBe(true);
|
||||
expect(privileges.canGetDataFrameJobs).toBe(true);
|
||||
expect(privileges.canDeleteDataFrameJob).toBe(false);
|
||||
expect(privileges.canPreviewDataFrameJob).toBe(false);
|
||||
expect(privileges.canCreateDataFrameJob).toBe(false);
|
||||
expect(privileges.canStartStopDataFrameJob).toBe(false);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,200 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { Privileges, getDefaultPrivileges } from '../../../common/types/privileges';
|
||||
import { callWithRequestType } from '../../../common/types/kibana';
|
||||
import { isSecurityDisabled } from '../../lib/security_utils';
|
||||
import { upgradeCheckProvider } from './upgrade';
|
||||
|
||||
import { mlPrivileges } from './privileges';
|
||||
|
||||
type ClusterPrivilege = Record<string, boolean>;
|
||||
|
||||
interface Response {
|
||||
privileges: Privileges;
|
||||
upgradeInProgress: boolean;
|
||||
}
|
||||
|
||||
export function privilegesProvider(callWithRequest: callWithRequestType, xpackMainPlugin: any) {
|
||||
const { isUpgradeInProgress } = upgradeCheckProvider(callWithRequest);
|
||||
async function getPrivileges(): Promise<Response> {
|
||||
// get the default privileges, forced to be false.
|
||||
const privileges = getDefaultPrivileges();
|
||||
|
||||
const upgradeInProgress = await isUpgradeInProgress();
|
||||
const securityDisabled = isSecurityDisabled(xpackMainPlugin);
|
||||
|
||||
if (securityDisabled === true) {
|
||||
if (upgradeInProgress === true) {
|
||||
// if security is disabled and an upgrade in is progress,
|
||||
// force all "getting" privileges to be true
|
||||
// leaving all "setting" privileges to be the default false
|
||||
setGettingPrivileges({}, privileges, true);
|
||||
} else {
|
||||
// if no upgrade is in progress,
|
||||
// get all privileges forced to true
|
||||
Object.keys(privileges).forEach(k => (privileges[k as keyof Privileges] = true));
|
||||
}
|
||||
} else {
|
||||
// security enabled
|
||||
// load all ml privileges for this user.
|
||||
const { cluster } = await callWithRequest('ml.privilegeCheck', { body: mlPrivileges });
|
||||
setGettingPrivileges(cluster, privileges);
|
||||
if (upgradeInProgress === false) {
|
||||
// if an upgrade is in progress, don't apply the "setting"
|
||||
// privileges. leave them to be the default false.
|
||||
setActionPrivileges(cluster, privileges);
|
||||
}
|
||||
}
|
||||
return { privileges, upgradeInProgress };
|
||||
}
|
||||
return { getPrivileges };
|
||||
}
|
||||
|
||||
function setGettingPrivileges(
|
||||
cluster: ClusterPrivilege = {},
|
||||
privileges: Privileges,
|
||||
forceTrue = false
|
||||
) {
|
||||
// Anomaly Detection
|
||||
if (
|
||||
forceTrue ||
|
||||
(cluster['cluster:monitor/xpack/ml/job/get'] &&
|
||||
cluster['cluster:monitor/xpack/ml/job/stats/get'])
|
||||
) {
|
||||
privileges.canGetJobs = true;
|
||||
}
|
||||
|
||||
if (
|
||||
forceTrue ||
|
||||
(cluster['cluster:monitor/xpack/ml/datafeeds/get'] &&
|
||||
cluster['cluster:monitor/xpack/ml/datafeeds/stats/get'])
|
||||
) {
|
||||
privileges.canGetDatafeeds = true;
|
||||
}
|
||||
|
||||
// Calendars
|
||||
if (forceTrue || cluster['cluster:monitor/xpack/ml/calendars/get']) {
|
||||
privileges.canGetCalendars = true;
|
||||
}
|
||||
|
||||
// Filters
|
||||
if (forceTrue || cluster['cluster:admin/xpack/ml/filters/get']) {
|
||||
privileges.canGetFilters = true;
|
||||
}
|
||||
|
||||
// File Data Visualizer
|
||||
if (forceTrue || cluster['cluster:monitor/xpack/ml/findfilestructure']) {
|
||||
privileges.canFindFileStructure = true;
|
||||
}
|
||||
|
||||
// Data Frames
|
||||
if (
|
||||
forceTrue ||
|
||||
(cluster['cluster:monitor/data_frame/get'] && cluster['cluster:monitor/data_frame/stats/get'])
|
||||
) {
|
||||
privileges.canGetDataFrameJobs = true;
|
||||
}
|
||||
}
|
||||
|
||||
function setActionPrivileges(cluster: ClusterPrivilege = {}, privileges: Privileges) {
|
||||
// Anomaly Detection
|
||||
if (
|
||||
cluster['cluster:admin/xpack/ml/job/put'] &&
|
||||
cluster['cluster:admin/xpack/ml/job/open'] &&
|
||||
cluster['cluster:admin/xpack/ml/datafeeds/put']
|
||||
) {
|
||||
privileges.canCreateJob = true;
|
||||
}
|
||||
|
||||
if (cluster['cluster:admin/xpack/ml/job/update']) {
|
||||
privileges.canUpdateJob = true;
|
||||
}
|
||||
|
||||
if (cluster['cluster:admin/xpack/ml/job/open']) {
|
||||
privileges.canOpenJob = true;
|
||||
}
|
||||
|
||||
if (cluster['cluster:admin/xpack/ml/job/close']) {
|
||||
privileges.canCloseJob = true;
|
||||
}
|
||||
|
||||
if (cluster['cluster:admin/xpack/ml/job/forecast']) {
|
||||
privileges.canForecastJob = true;
|
||||
}
|
||||
|
||||
if (
|
||||
cluster['cluster:admin/xpack/ml/job/delete'] &&
|
||||
cluster['cluster:admin/xpack/ml/datafeeds/delete']
|
||||
) {
|
||||
privileges.canDeleteJob = true;
|
||||
}
|
||||
|
||||
if (
|
||||
cluster['cluster:admin/xpack/ml/job/open'] &&
|
||||
cluster['cluster:admin/xpack/ml/datafeeds/start'] &&
|
||||
cluster['cluster:admin/xpack/ml/datafeeds/stop']
|
||||
) {
|
||||
privileges.canStartStopDatafeed = true;
|
||||
}
|
||||
|
||||
if (cluster['cluster:admin/xpack/ml/datafeeds/update']) {
|
||||
privileges.canUpdateDatafeed = true;
|
||||
}
|
||||
|
||||
if (cluster['cluster:admin/xpack/ml/datafeeds/preview']) {
|
||||
privileges.canPreviewDatafeed = true;
|
||||
}
|
||||
|
||||
// Calendars
|
||||
if (
|
||||
cluster['cluster:admin/xpack/ml/calendars/put'] &&
|
||||
cluster['cluster:admin/xpack/ml/calendars/jobs/update'] &&
|
||||
cluster['cluster:admin/xpack/ml/calendars/events/post']
|
||||
) {
|
||||
privileges.canCreateCalendar = true;
|
||||
}
|
||||
|
||||
if (
|
||||
cluster['cluster:admin/xpack/ml/calendars/delete'] &&
|
||||
cluster['cluster:admin/xpack/ml/calendars/events/delete']
|
||||
) {
|
||||
privileges.canDeleteCalendar = true;
|
||||
}
|
||||
|
||||
// Filters
|
||||
if (
|
||||
cluster['cluster:admin/xpack/ml/filters/put'] &&
|
||||
cluster['cluster:admin/xpack/ml/filters/update']
|
||||
) {
|
||||
privileges.canCreateFilter = true;
|
||||
}
|
||||
|
||||
if (cluster['cluster:admin/xpack/ml/filters/delete']) {
|
||||
privileges.canDeleteFilter = true;
|
||||
}
|
||||
|
||||
// Data Frames
|
||||
if (cluster['cluster:admin/data_frame/put']) {
|
||||
privileges.canCreateDataFrameJob = true;
|
||||
}
|
||||
|
||||
if (cluster['cluster:admin/data_frame/delete']) {
|
||||
privileges.canDeleteDataFrameJob = true;
|
||||
}
|
||||
|
||||
if (cluster['cluster:admin/data_frame/preview']) {
|
||||
privileges.canPreviewDataFrameJob = true;
|
||||
}
|
||||
|
||||
if (
|
||||
cluster['cluster:admin/data_frame/start'] &&
|
||||
cluster['cluster:admin/data_frame/start_task'] &&
|
||||
cluster['cluster:admin/data_frame/stop']
|
||||
) {
|
||||
privileges.canStartStopDataFrameJob = true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
export { privilegesProvider } from './check_privileges';
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
export const mlPrivileges = {
|
||||
cluster: [
|
||||
'cluster:monitor/data_frame/get',
|
||||
'cluster:monitor/data_frame/stats/get',
|
||||
'cluster:monitor/xpack/ml/job/get',
|
||||
'cluster:monitor/xpack/ml/job/stats/get',
|
||||
'cluster:monitor/xpack/ml/datafeeds/get',
|
||||
'cluster:monitor/xpack/ml/datafeeds/stats/get',
|
||||
'cluster:monitor/xpack/ml/calendars/get',
|
||||
'cluster:admin/data_frame/delete',
|
||||
'cluster:admin/data_frame/preview',
|
||||
'cluster:admin/data_frame/put',
|
||||
'cluster:admin/data_frame/start',
|
||||
'cluster:admin/data_frame/start_task',
|
||||
'cluster:admin/data_frame/stop',
|
||||
'cluster:admin/xpack/ml/job/put',
|
||||
'cluster:admin/xpack/ml/job/delete',
|
||||
'cluster:admin/xpack/ml/job/update',
|
||||
'cluster:admin/xpack/ml/job/open',
|
||||
'cluster:admin/xpack/ml/job/close',
|
||||
'cluster:admin/xpack/ml/job/forecast',
|
||||
'cluster:admin/xpack/ml/datafeeds/put',
|
||||
'cluster:admin/xpack/ml/datafeeds/delete',
|
||||
'cluster:admin/xpack/ml/datafeeds/start',
|
||||
'cluster:admin/xpack/ml/datafeeds/stop',
|
||||
'cluster:admin/xpack/ml/datafeeds/update',
|
||||
'cluster:admin/xpack/ml/datafeeds/preview',
|
||||
'cluster:admin/xpack/ml/calendars/put',
|
||||
'cluster:admin/xpack/ml/calendars/delete',
|
||||
'cluster:admin/xpack/ml/calendars/jobs/update',
|
||||
'cluster:admin/xpack/ml/calendars/events/post',
|
||||
'cluster:admin/xpack/ml/calendars/events/delete',
|
||||
'cluster:admin/xpack/ml/filters/put',
|
||||
'cluster:admin/xpack/ml/filters/get',
|
||||
'cluster:admin/xpack/ml/filters/update',
|
||||
'cluster:admin/xpack/ml/filters/delete',
|
||||
'cluster:monitor/xpack/ml/findfilestructure',
|
||||
],
|
||||
};
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { mlLog } from '../../client/log';
|
||||
import { callWithRequestType } from '../../../common/types/kibana';
|
||||
|
||||
export function upgradeCheckProvider(callWithRequest: callWithRequestType) {
|
||||
async function isUpgradeInProgress(): Promise<boolean> {
|
||||
let upgradeInProgress = false;
|
||||
try {
|
||||
const info = await callWithRequest('ml.info');
|
||||
// if ml indices are currently being migrated, upgrade_mode will be set to true
|
||||
// pass this back with the privileges to allow for the disabling of UI controls.
|
||||
upgradeInProgress = info.upgrade_mode === true;
|
||||
} catch (error) {
|
||||
// if the ml.info check fails, it could be due to the user having insufficient privileges
|
||||
// most likely they do not have the ml_user role and therefore will be blocked from using
|
||||
// ML at all. However, we need to catch this error so the privilege check doesn't fail.
|
||||
if (error.status === 403) {
|
||||
mlLog.info(
|
||||
'Unable to determine whether upgrade is being performed due to insufficient user privileges'
|
||||
);
|
||||
} else {
|
||||
mlLog.warn('Unable to determine whether upgrade is being performed');
|
||||
}
|
||||
}
|
||||
return upgradeInProgress;
|
||||
}
|
||||
return { isUpgradeInProgress };
|
||||
}
|
7
x-pack/legacy/plugins/ml/server/lib/security_utils.d.ts
vendored
Normal file
7
x-pack/legacy/plugins/ml/server/lib/security_utils.d.ts
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
export function isSecurityDisabled(xpackMainPlugin: any): boolean;
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
import { callWithRequestFactory } from '../client/call_with_request_factory';
|
||||
import { callWithInternalUserFactory } from '../client/call_with_internal_user_factory';
|
||||
import { privilegesProvider } from '../lib/check_privileges';
|
||||
import { mlLog } from '../client/log';
|
||||
|
||||
import { wrapError } from '../client/errors';
|
||||
|
@ -82,6 +83,23 @@ export function systemRoutes({ commonRouteConfig, elasticsearchPlugin, route, xp
|
|||
}
|
||||
});
|
||||
|
||||
route({
|
||||
method: 'GET',
|
||||
path: '/api/ml/ml_privileges',
|
||||
async handler(request) {
|
||||
const callWithRequest = callWithRequestFactory(elasticsearchPlugin, request);
|
||||
try {
|
||||
const { getPrivileges } = privilegesProvider(callWithRequest, xpackMainPlugin);
|
||||
return await getPrivileges();
|
||||
} catch (error) {
|
||||
return wrapError(error);
|
||||
}
|
||||
},
|
||||
config: {
|
||||
...commonRouteConfig
|
||||
}
|
||||
});
|
||||
|
||||
route({
|
||||
method: 'GET',
|
||||
path: '/api/ml/ml_node_count',
|
||||
|
|
Loading…
Reference in a new issue