[ML] Categorization examples privilege check (#57375) (#57785)

* [ML] Categorization examples privilege check

* adding privileges check to endpoint

* fixing typo

* moving privilege check to router

* removing unused variable

* rebasing master

* removing comment

Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>

Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
This commit is contained in:
James Gowdy 2020-02-17 13:02:00 +00:00 committed by GitHub
parent 1bba65e863
commit ef7bf84503
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 41 additions and 23 deletions

View file

@ -8,11 +8,7 @@ import { datafeedsProvider } from './datafeeds';
import { jobsProvider } from './jobs';
import { groupsProvider } from './groups';
import { newJobCapsProvider } from './new_job_caps';
import {
newJobChartsProvider,
categorizationExamplesProvider,
topCategoriesProvider,
} from './new_job';
import { newJobChartsProvider, topCategoriesProvider } from './new_job';
export function jobServiceProvider(callAsCurrentUser) {
return {
@ -21,7 +17,6 @@ export function jobServiceProvider(callAsCurrentUser) {
...groupsProvider(callAsCurrentUser),
...newJobCapsProvider(callAsCurrentUser),
...newJobChartsProvider(callAsCurrentUser),
...categorizationExamplesProvider(callAsCurrentUser),
...topCategoriesProvider(callAsCurrentUser),
};
}

View file

@ -17,7 +17,10 @@ import { ValidationResults } from './validation_results';
const CHUNK_SIZE = 100;
export function categorizationExamplesProvider(callWithRequest: callWithRequestType) {
export function categorizationExamplesProvider(
callWithRequest: callWithRequestType,
callWithInternalUser: callWithRequestType
) {
const validationResults = new ValidationResults();
async function categorizationExamples(
@ -109,7 +112,7 @@ export function categorizationExamplesProvider(callWithRequest: callWithRequestT
}
async function loadTokens(examples: string[], analyzer: CategorizationAnalyzer) {
const { tokens }: { tokens: Token[] } = await callWithRequest('indices.analyze', {
const { tokens }: { tokens: Token[] } = await callWithInternalUser('indices.analyze', {
body: {
...getAnalyzer(analyzer),
text: examples,

View file

@ -6,18 +6,6 @@
import { schema } from '@kbn/config-schema';
const analyzerSchema = {
tokenizer: schema.string(),
filter: schema.maybe(
schema.arrayOf(
schema.object({
type: schema.string(),
stopwords: schema.arrayOf(schema.maybe(schema.string())),
})
)
),
};
export const categorizationFieldExamplesSchema = {
indexPatternTitle: schema.string(),
query: schema.any(),
@ -26,7 +14,7 @@ export const categorizationFieldExamplesSchema = {
timeField: schema.maybe(schema.string()),
start: schema.number(),
end: schema.number(),
analyzer: schema.object(analyzerSchema),
analyzer: schema.any(),
};
export const chartSchema = {

View file

@ -4,10 +4,13 @@
* you may not use this file except in compliance with the Elastic License.
*/
import Boom from 'boom';
import { schema } from '@kbn/config-schema';
import { IScopedClusterClient } from 'src/core/server';
import { licensePreRoutingFactory } from '../new_platform/licence_check_pre_routing_factory';
import { wrapError } from '../client/error_wrapper';
import { RouteInitialization } from '../new_platform/plugin';
import { isSecurityDisabled } from '../lib/security_utils';
import {
categorizationFieldExamplesSchema,
chartSchema,
@ -21,11 +24,31 @@ import {
} from '../new_platform/job_service_schema';
// @ts-ignore no declaration module
import { jobServiceProvider } from '../models/job_service';
import { categorizationExamplesProvider } from '../models/job_service/new_job';
/**
* Routes for job service
*/
export function jobServiceRoutes({ xpackMainPlugin, router }: RouteInitialization) {
async function hasPermissionToCreateJobs(
callAsCurrentUser: IScopedClusterClient['callAsCurrentUser']
) {
if (isSecurityDisabled(xpackMainPlugin) === true) {
return true;
}
const resp = await callAsCurrentUser('ml.privilegeCheck', {
body: {
cluster: [
'cluster:admin/xpack/ml/job/put',
'cluster:admin/xpack/ml/job/open',
'cluster:admin/xpack/ml/datafeeds/put',
],
},
});
return resp.has_all_requested;
}
/**
* @apiGroup JobService
*
@ -545,8 +568,17 @@ export function jobServiceRoutes({ xpackMainPlugin, router }: RouteInitializatio
},
licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => {
try {
const { validateCategoryExamples } = jobServiceProvider(
context.ml!.mlClient.callAsCurrentUser
// due to the use of the _analyze endpoint which is called by the kibana user,
// basic job creation privileges are required to use this endpoint
if ((await hasPermissionToCreateJobs(context.ml!.mlClient.callAsCurrentUser)) === false) {
throw Boom.forbidden(
'Insufficient privileges, the machine_learning_admin role is required.'
);
}
const { validateCategoryExamples } = categorizationExamplesProvider(
context.ml!.mlClient.callAsCurrentUser,
context.ml!.mlClient.callAsInternalUser
);
const {
indexPatternTitle,