From 0f25951f3ce7fbec8b735c8f49db483be8ff5218 Mon Sep 17 00:00:00 2001 From: James Gowdy Date: Wed, 4 Mar 2020 08:16:51 +0000 Subject: [PATCH] [ML] Fixing licensing after server NP cutover --- .../legacy/plugins/ml/common/license/index.ts | 7 + .../plugins/ml/common/license/ml_license.ts | 78 ++++++++ .../plugins/ml/public/application/app.tsx | 11 +- .../anomalies_table/anomalies_table.test.js | 2 +- .../components/navigation_menu/main_tabs.tsx | 10 +- .../navigation_menu/navigation_menu.tsx | 2 +- .../datavisualizer_selector.tsx | 2 +- .../results_links/results_links.tsx | 2 +- .../datavisualizer/index_based/page.tsx | 2 +- .../license/__tests__/check_license.js | 36 ---- .../application/license/check_license.tsx | 160 ++++++----------- .../application/license/expired_warning.tsx | 26 +++ .../ml/public/application/license/index.ts | 13 ++ .../application/license/ml_client_license.ts | 51 ++++++ .../ml/public/application/management/index.ts | 29 ++- .../application/privilege/check_privilege.ts | 2 +- .../public/application/routing/resolvers.ts | 2 +- .../routes/datavisualizer/datavisualizer.tsx | 2 +- .../routes/datavisualizer/file_based.tsx | 4 +- .../routes/datavisualizer/index_based.tsx | 2 +- .../routes/new_job/index_or_search.tsx | 2 +- .../application/routing/routes/overview.tsx | 2 +- .../routing/routes/settings/calendar_list.tsx | 2 +- .../routes/settings/calendar_new_edit.tsx | 2 +- .../routing/routes/settings/filter_list.tsx | 2 +- .../routes/settings/filter_list_new_edit.tsx | 2 +- .../routing/routes/settings/settings.tsx | 2 +- .../calendars/edit/new_calendar.test.js | 2 +- .../calendars/list/calendars_list.test.js | 2 +- .../application/util/dependency_cache.ts | 1 + x-pack/legacy/plugins/ml/public/legacy.ts | 12 +- x-pack/legacy/plugins/ml/public/plugin.ts | 3 +- .../lib/check_license/check_license.test.ts | 167 ------------------ .../server/lib/check_license/check_license.ts | 82 --------- .../check_privileges/check_privileges.test.ts | 65 ++++--- .../lib/check_privileges/check_privileges.ts | 14 +- .../lib/{check_license => license}/index.ts | 2 +- .../server/lib/license/ml_server_license.ts | 35 ++++ .../ml/server/lib/sample_data_sets/index.ts | 2 +- .../lib/sample_data_sets/sample_data_sets.ts | 41 +++-- x-pack/plugins/ml/server/plugin.ts | 62 ++----- .../plugins/ml/server/routes/annotations.ts | 9 +- .../ml/server/routes/anomaly_detectors.ts | 33 ++-- x-pack/plugins/ml/server/routes/calendars.ts | 13 +- .../ml/server/routes/data_frame_analytics.ts | 25 ++- .../ml/server/routes/data_visualizer.ts | 7 +- x-pack/plugins/ml/server/routes/datafeeds.ts | 23 ++- .../ml/server/routes/fields_service.ts | 8 +- .../ml/server/routes/file_data_visualizer.ts | 7 +- x-pack/plugins/ml/server/routes/filters.ts | 15 +- x-pack/plugins/ml/server/routes/indices.ts | 5 +- .../ml/server/routes/job_audit_messages.ts | 7 +- .../plugins/ml/server/routes/job_service.ts | 42 +++-- .../ml/server/routes/job_validation.ts | 18 +- .../license_check_pre_routing_factory.ts | 33 ---- x-pack/plugins/ml/server/routes/modules.ts | 11 +- .../ml/server/routes/notification_settings.ts | 5 +- .../ml/server/routes/results_service.ts | 13 +- x-pack/plugins/ml/server/routes/system.ts | 19 +- x-pack/plugins/ml/server/types.ts | 3 +- .../translations/translations/ja-JP.json | 3 - .../translations/translations/zh-CN.json | 3 - 62 files changed, 535 insertions(+), 714 deletions(-) create mode 100644 x-pack/legacy/plugins/ml/common/license/index.ts create mode 100644 x-pack/legacy/plugins/ml/common/license/ml_license.ts delete mode 100644 x-pack/legacy/plugins/ml/public/application/license/__tests__/check_license.js create mode 100644 x-pack/legacy/plugins/ml/public/application/license/expired_warning.tsx create mode 100644 x-pack/legacy/plugins/ml/public/application/license/index.ts create mode 100644 x-pack/legacy/plugins/ml/public/application/license/ml_client_license.ts delete mode 100644 x-pack/plugins/ml/server/lib/check_license/check_license.test.ts delete mode 100644 x-pack/plugins/ml/server/lib/check_license/check_license.ts rename x-pack/plugins/ml/server/lib/{check_license => license}/index.ts (81%) create mode 100644 x-pack/plugins/ml/server/lib/license/ml_server_license.ts delete mode 100644 x-pack/plugins/ml/server/routes/license_check_pre_routing_factory.ts diff --git a/x-pack/legacy/plugins/ml/common/license/index.ts b/x-pack/legacy/plugins/ml/common/license/index.ts new file mode 100644 index 0000000000000..e901a9545897b --- /dev/null +++ b/x-pack/legacy/plugins/ml/common/license/index.ts @@ -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 { MlLicense, LicenseStatus, MINIMUM_FULL_LICENSE, MINIMUM_LICENSE } from './ml_license'; diff --git a/x-pack/legacy/plugins/ml/common/license/ml_license.ts b/x-pack/legacy/plugins/ml/common/license/ml_license.ts new file mode 100644 index 0000000000000..8b631bf6ffb46 --- /dev/null +++ b/x-pack/legacy/plugins/ml/common/license/ml_license.ts @@ -0,0 +1,78 @@ +/* + * 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 { Observable, Subscription } from 'rxjs'; +import { ILicense, LICENSE_CHECK_STATE } from '../../../../../plugins/licensing/common/types'; +import { PLUGIN_ID } from '../constants/app'; + +export const MINIMUM_LICENSE = 'basic'; +export const MINIMUM_FULL_LICENSE = 'platinum'; + +export interface LicenseStatus { + isValid: boolean; + isSecurityEnabled: boolean; + message?: string; +} + +export class MlLicense { + private _licenseSubscription: Subscription | null = null; + private _license: ILicense | null = null; + private _isSecurityEnabled: boolean = false; + private _hasLicenseExpired: boolean = false; + private _isMlEnabled: boolean = false; + private _isMinimumLicense: boolean = false; + private _isFullLicense: boolean = false; + private _initialized: boolean = false; + + public setup( + license$: Observable, + postInitFunctions?: Array<(lic: MlLicense) => void> + ) { + this._licenseSubscription = license$.subscribe(async license => { + const { isEnabled: securityIsEnabled } = license.getFeature('security'); + + this._license = license; + this._isSecurityEnabled = securityIsEnabled; + this._hasLicenseExpired = this._license.status === 'expired'; + this._isMlEnabled = this._license.getFeature(PLUGIN_ID).isEnabled; + this._isMinimumLicense = + this._license.check(PLUGIN_ID, MINIMUM_LICENSE).state === LICENSE_CHECK_STATE.Valid; + this._isFullLicense = + this._license.check(PLUGIN_ID, MINIMUM_FULL_LICENSE).state === LICENSE_CHECK_STATE.Valid; + + if (this._initialized === false && postInitFunctions !== undefined) { + postInitFunctions.forEach(f => f(this)); + } + this._initialized = true; + }); + } + + public unsubscribe() { + if (this._licenseSubscription !== null) { + this._licenseSubscription.unsubscribe(); + } + } + + public isSecurityEnabled() { + return this._isSecurityEnabled; + } + + public hasLicenseExpired() { + return this._hasLicenseExpired; + } + + public isMlEnabled() { + return this._isMlEnabled; + } + + public isMinimumLicense() { + return this._isMinimumLicense; + } + + public isFullLicense() { + return this._isFullLicense; + } +} diff --git a/x-pack/legacy/plugins/ml/public/application/app.tsx b/x-pack/legacy/plugins/ml/public/application/app.tsx index 3acb24ac6e173..4c956bfabecc9 100644 --- a/x-pack/legacy/plugins/ml/public/application/app.tsx +++ b/x-pack/legacy/plugins/ml/public/application/app.tsx @@ -13,15 +13,18 @@ import { AppMountParameters, CoreStart } from 'kibana/public'; import { DataPublicPluginStart } from 'src/plugins/data/public'; import { SecurityPluginSetup } from '../../../../../plugins/security/public'; +import { LicensingPluginSetup } from '../../../../../plugins/licensing/public'; import { KibanaContextProvider } from '../../../../../../src/plugins/kibana_react/public'; import { setDependencyCache, clearCache } from './util/dependency_cache'; +import { setLicenseCache } from './license'; import { MlRouter } from './routing'; export interface MlDependencies extends AppMountParameters { data: DataPublicPluginStart; security: SecurityPluginSetup; + licensing: LicensingPluginSetup; __LEGACY: { XSRF: string; }; @@ -36,14 +39,14 @@ const App: FC = ({ coreStart, deps }) => { setDependencyCache({ indexPatterns: deps.data.indexPatterns, timefilter: deps.data.query.timefilter, + fieldFormats: deps.data.fieldFormats, + autocomplete: deps.data.autocomplete, config: coreStart.uiSettings!, chrome: coreStart.chrome!, docLinks: coreStart.docLinks!, toastNotifications: coreStart.notifications.toasts, overlays: coreStart.overlays, recentlyAccessed: coreStart.chrome!.recentlyAccessed, - fieldFormats: deps.data.fieldFormats, - autocomplete: deps.data.autocomplete, basePath: coreStart.http.basePath, savedObjectsClient: coreStart.savedObjects.client, XSRF: deps.__LEGACY.XSRF, @@ -51,7 +54,11 @@ const App: FC = ({ coreStart, deps }) => { http: coreStart.http, security: deps.security, }); + + const mlLicense = setLicenseCache(deps.licensing); + deps.onAppLeave(actions => { + mlLicense.unsubscribe(); clearCache(); return actions.default(); }); diff --git a/x-pack/legacy/plugins/ml/public/application/components/anomalies_table/anomalies_table.test.js b/x-pack/legacy/plugins/ml/public/application/components/anomalies_table/anomalies_table.test.js index 206b9e01bab8c..b881bfe4f1fe6 100644 --- a/x-pack/legacy/plugins/ml/public/application/components/anomalies_table/anomalies_table.test.js +++ b/x-pack/legacy/plugins/ml/public/application/components/anomalies_table/anomalies_table.test.js @@ -11,7 +11,7 @@ import { getColumns } from './anomalies_table_columns'; jest.mock('../../privilege/check_privilege', () => ({ checkPermission: () => false, })); -jest.mock('../../license/check_license', () => ({ +jest.mock('../../license', () => ({ hasLicenseExpired: () => false, })); jest.mock('../../privilege/get_privileges', () => ({ diff --git a/x-pack/legacy/plugins/ml/public/application/components/navigation_menu/main_tabs.tsx b/x-pack/legacy/plugins/ml/public/application/components/navigation_menu/main_tabs.tsx index dce5e7ad52b09..695783883d02e 100644 --- a/x-pack/legacy/plugins/ml/public/application/components/navigation_menu/main_tabs.tsx +++ b/x-pack/legacy/plugins/ml/public/application/components/navigation_menu/main_tabs.tsx @@ -81,13 +81,18 @@ export const MainTabs: FC = ({ tabId, disableLinks }) => { return ( {tabs.map((tab: Tab) => { - const id = tab.id; + const { id, disabled } = tab; const testSubject = TAB_DATA[id].testSubject; const defaultPathId = TAB_DATA[id].pathId || id; // globalState (e.g. selected jobs and time range) should be retained when changing pages. // appState will not be considered. const fullGlobalStateString = globalState !== undefined ? `?_g=${encode(globalState)}` : ''; - return ( + + return disabled ? ( + + {tab.name} + + ) : ( = ({ tabId, disableLinks }) => { className={'mlNavigationMenu__mainTab'} onClick={() => onSelectedTabChanged(id)} isSelected={id === selectedTabId} - disabled={tab.disabled} > {tab.name} diff --git a/x-pack/legacy/plugins/ml/public/application/components/navigation_menu/navigation_menu.tsx b/x-pack/legacy/plugins/ml/public/application/components/navigation_menu/navigation_menu.tsx index e7ba57e25354e..6be2d18e59741 100644 --- a/x-pack/legacy/plugins/ml/public/application/components/navigation_menu/navigation_menu.tsx +++ b/x-pack/legacy/plugins/ml/public/application/components/navigation_menu/navigation_menu.tsx @@ -7,7 +7,7 @@ import React, { Fragment, FC } from 'react'; import { EuiFlexGroup, EuiFlexItem, EuiHorizontalRule } from '@elastic/eui'; -import { isFullLicense } from '../../license/check_license'; +import { isFullLicense } from '../../license'; import { TopNav } from './top_nav'; import { MainTabs } from './main_tabs'; diff --git a/x-pack/legacy/plugins/ml/public/application/datavisualizer/datavisualizer_selector.tsx b/x-pack/legacy/plugins/ml/public/application/datavisualizer/datavisualizer_selector.tsx index 0f56f78c708ee..254788c52a7a8 100644 --- a/x-pack/legacy/plugins/ml/public/application/datavisualizer/datavisualizer_selector.tsx +++ b/x-pack/legacy/plugins/ml/public/application/datavisualizer/datavisualizer_selector.tsx @@ -22,7 +22,7 @@ import { import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import { isFullLicense } from '../license/check_license'; +import { isFullLicense } from '../license'; import { useTimefilter } from '../contexts/kibana'; import { NavigationMenu } from '../components/navigation_menu'; diff --git a/x-pack/legacy/plugins/ml/public/application/datavisualizer/file_based/components/results_links/results_links.tsx b/x-pack/legacy/plugins/ml/public/application/datavisualizer/file_based/components/results_links/results_links.tsx index debadba19051b..dddf64ce2cfd3 100644 --- a/x-pack/legacy/plugins/ml/public/application/datavisualizer/file_based/components/results_links/results_links.tsx +++ b/x-pack/legacy/plugins/ml/public/application/datavisualizer/file_based/components/results_links/results_links.tsx @@ -9,7 +9,7 @@ import moment from 'moment'; import { FormattedMessage } from '@kbn/i18n/react'; import { EuiFlexGroup, EuiFlexItem, EuiCard, EuiIcon } from '@elastic/eui'; import { ml } from '../../../../services/ml_api_service'; -import { isFullLicense } from '../../../../license/check_license'; +import { isFullLicense } from '../../../../license'; import { checkPermission } from '../../../../privilege/check_privilege'; import { mlNodesAvailable } from '../../../../ml_nodes_check/check_ml_nodes'; import { useMlKibana } from '../../../../contexts/kibana'; diff --git a/x-pack/legacy/plugins/ml/public/application/datavisualizer/index_based/page.tsx b/x-pack/legacy/plugins/ml/public/application/datavisualizer/index_based/page.tsx index 84c07651d323d..fbf42ef62265c 100644 --- a/x-pack/legacy/plugins/ml/public/application/datavisualizer/index_based/page.tsx +++ b/x-pack/legacy/plugins/ml/public/application/datavisualizer/index_based/page.tsx @@ -31,7 +31,7 @@ import { SavedSearchSavedObject } from '../../../../common/types/kibana'; import { NavigationMenu } from '../../components/navigation_menu'; import { ML_JOB_FIELD_TYPES } from '../../../../common/constants/field_types'; import { SEARCH_QUERY_LANGUAGE } from '../../../../common/constants/search'; -import { isFullLicense } from '../../license/check_license'; +import { isFullLicense } from '../../license'; import { checkPermission } from '../../privilege/check_privilege'; import { mlNodesAvailable } from '../../ml_nodes_check/check_ml_nodes'; import { FullTimeRangeSelector } from '../../components/full_time_range_selector'; diff --git a/x-pack/legacy/plugins/ml/public/application/license/__tests__/check_license.js b/x-pack/legacy/plugins/ml/public/application/license/__tests__/check_license.js deleted file mode 100644 index 9ce0ec04befb6..0000000000000 --- a/x-pack/legacy/plugins/ml/public/application/license/__tests__/check_license.js +++ /dev/null @@ -1,36 +0,0 @@ -/* - * 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 expect from '@kbn/expect'; -import { xpackInfo } from '../../../../../xpack_main/public/services/xpack_info'; -import { LICENSE_STATUS_VALID } from '../../../../../../common/constants/license_status'; -import { xpackFeatureAvailable } from '../check_license'; - -const initialInfo = { - features: { - watcher: { - status: LICENSE_STATUS_VALID, - }, - }, -}; - -describe('ML - check license', () => { - describe('xpackFeatureAvailable', () => { - beforeEach(() => { - xpackInfo.setAll(initialInfo); - }); - - it('returns true for enabled feature', () => { - const result = xpackFeatureAvailable('watcher'); - expect(result).to.be(true); - }); - - it('returns false for disabled feature', () => { - const result = xpackFeatureAvailable('noSuchFeature'); - expect(result).to.be(false); - }); - }); -}); diff --git a/x-pack/legacy/plugins/ml/public/application/license/check_license.tsx b/x-pack/legacy/plugins/ml/public/application/license/check_license.tsx index 4af753ddb4d1f..be5b702742baa 100644 --- a/x-pack/legacy/plugins/ml/public/application/license/check_license.tsx +++ b/x-pack/legacy/plugins/ml/public/application/license/check_license.tsx @@ -4,126 +4,74 @@ * you may not use this file except in compliance with the Elastic License. */ -import React from 'react'; -import { EuiCallOut } from '@elastic/eui'; -import { toMountPoint } from '../../../../../../../src/plugins/kibana_react/public'; -// @ts-ignore No declaration file for module -import { xpackInfo } from '../../../../xpack_main/public/services/xpack_info'; -import { LICENSE_TYPE } from '../../../common/constants/license'; -import { LICENSE_STATUS_VALID } from '../../../../../common/constants/license_status'; -import { getOverlays } from '../util/dependency_cache'; +import { LicensingPluginSetup } from '../../../../../../plugins/licensing/public'; +import { MlClientLicense } from './ml_client_license'; -let licenseHasExpired = true; -let licenseType: LICENSE_TYPE | null = null; -let expiredLicenseBannerId: string; +let mlLicense: MlClientLicense | null = null; -export function checkFullLicense() { - const features = getFeatures(); - licenseType = features.licenseType; - - if (features.isAvailable === false) { - // ML is not enabled - return redirectToKibana(); - } else if (features.licenseType === LICENSE_TYPE.BASIC) { - // ML is enabled, but only with a basic or gold license - return redirectToBasic(); - } else { - // ML is enabled - setLicenseExpired(features); - return Promise.resolve(features); - } +/** + * Create a new mlLicense and cache it for later checks + * + * @export + * @param {LicensingPluginSetup} licensingSetup + * @returns {MlClientLicense} + */ +export function setLicenseCache(licensingSetup: LicensingPluginSetup) { + mlLicense = new MlClientLicense(); + mlLicense.setup(licensingSetup.license$); + return mlLicense; } -export function checkBasicLicense() { - const features = getFeatures(); - licenseType = features.licenseType; - - if (features.isAvailable === false) { - // ML is not enabled - return redirectToKibana(); - } else { - // ML is enabled - setLicenseExpired(features); - return Promise.resolve(features); +/** + * Used as routing resolver to stop the loading of a page if the current license + * is a trial, platinum or enterprise. + * + * @export + * @returns {Promise} Promise which resolves if the license is trial, platinum or enterprise and rejects if it isn't. + */ +export async function checkFullLicense() { + if (mlLicense === null) { + // this should never happen + console.error('ML Licensing not initialized'); // eslint-disable-line + return Promise.reject(); } -} -// a wrapper for checkFullLicense which doesn't resolve if the license has expired. -// this is used by all create jobs pages to redirect back to the jobs list -// if the user's license has expired. -export function checkLicenseExpired() { - return checkFullLicense() - .then((features: any) => { - if (features.hasExpired) { - window.location.href = '#/jobs'; - return Promise.reject(); - } else { - return Promise.resolve(features); - } - }) - .catch(() => { - return Promise.reject(); - }); + return mlLicense.fullLicenseResolver(); } -function setLicenseExpired(features: any) { - licenseHasExpired = features.hasExpired || false; - // If the license has expired ML app will still work for 7 days and then - // the job management endpoints (e.g. create job, start datafeed) will be restricted. - // Therefore we need to keep the app enabled but show an info banner to the user. - if (licenseHasExpired) { - const message = features.message; - if (expiredLicenseBannerId === undefined) { - // Only show the banner once with no way to dismiss it - const overlays = getOverlays(); - expiredLicenseBannerId = overlays.banners.add( - toMountPoint() - ); - } +/** + * Used as routing resolver to stop the loading of a page if the current license + * is at least basic. + * + * @export + * @returns {Promise} Promise resolves if the license is at least basic and rejects if it isn't. + */ +export async function checkBasicLicense() { + if (mlLicense === null) { + // this should never happen + console.error('ML Licensing not initialized'); // eslint-disable-line + return Promise.reject(); } -} -// Temporary hack for cutting over server to NP -function getFeatures() { - return { - isAvailable: true, - showLinks: true, - enableLinks: true, - licenseType: 1, - hasExpired: false, - }; - // return xpackInfo.get('features.ml'); -} - -function redirectToKibana() { - window.location.href = '/'; - return Promise.reject(); -} -function redirectToBasic() { - window.location.href = '#/datavisualizer'; - return Promise.reject(); + return mlLicense.basicLicenseResolver(); } +/** + * Check to see if the current license has expired + * + * @export + * @returns {boolean} + */ export function hasLicenseExpired() { - return licenseHasExpired; + return mlLicense !== null && mlLicense.hasLicenseExpired(); } +/** + * Check to see if the current license is trial, platinum or enterprise. + * + * @export + * @returns {boolean} + */ export function isFullLicense() { - return licenseType === LICENSE_TYPE.FULL; -} - -export function xpackFeatureAvailable(feature: string) { - // each plugin can register their own set of features. - // so we need specific checks for each one. - // this list can grow if we need to check other plugin's features. - switch (feature) { - case 'watcher': - // watcher only has a license status feature - // if watcher is disabled in kibana.yml, the feature is completely missing from xpackInfo - return xpackInfo.get(`features.${feature}.status`, false) === LICENSE_STATUS_VALID; - default: - // historically plugins have used `isAvailable` as a catch all for - // license and feature enabled checks - return xpackInfo.get(`features.${feature}.isAvailable`, false); - } + return mlLicense !== null && mlLicense.isFullLicense(); } diff --git a/x-pack/legacy/plugins/ml/public/application/license/expired_warning.tsx b/x-pack/legacy/plugins/ml/public/application/license/expired_warning.tsx new file mode 100644 index 0000000000000..22cb3260d6969 --- /dev/null +++ b/x-pack/legacy/plugins/ml/public/application/license/expired_warning.tsx @@ -0,0 +1,26 @@ +/* + * 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 React from 'react'; +import { i18n } from '@kbn/i18n'; +import { EuiCallOut } from '@elastic/eui'; +import { toMountPoint } from '../../../../../../../src/plugins/kibana_react/public'; +import { getOverlays } from '../util/dependency_cache'; + +let expiredLicenseBannerId: string; + +export function showExpiredLicenseWarning() { + if (expiredLicenseBannerId === undefined) { + const message = i18n.translate('xpack.ml.checkLicense.licenseHasExpiredMessage', { + defaultMessage: 'Your Machine Learning license has expired.', + }); + // Only show the banner once with no way to dismiss it + const overlays = getOverlays(); + expiredLicenseBannerId = overlays.banners.add( + toMountPoint() + ); + } +} diff --git a/x-pack/legacy/plugins/ml/public/application/license/index.ts b/x-pack/legacy/plugins/ml/public/application/license/index.ts new file mode 100644 index 0000000000000..0b6866d52d070 --- /dev/null +++ b/x-pack/legacy/plugins/ml/public/application/license/index.ts @@ -0,0 +1,13 @@ +/* + * 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 { + checkBasicLicense, + checkFullLicense, + hasLicenseExpired, + isFullLicense, + setLicenseCache, +} from './check_license'; diff --git a/x-pack/legacy/plugins/ml/public/application/license/ml_client_license.ts b/x-pack/legacy/plugins/ml/public/application/license/ml_client_license.ts new file mode 100644 index 0000000000000..13809e15135e8 --- /dev/null +++ b/x-pack/legacy/plugins/ml/public/application/license/ml_client_license.ts @@ -0,0 +1,51 @@ +/* + * 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 { MlLicense } from '../../../common/license'; +import { showExpiredLicenseWarning } from './expired_warning'; + +export class MlClientLicense extends MlLicense { + fullLicenseResolver() { + if (this.isMlEnabled() === false || this.isMinimumLicense() === false) { + // ML is not enabled or the license isn't at least basic + return redirectToKibana(); + } + + if (this.isFullLicense() === false) { + // ML is enabled, but only with a basic or gold license + return redirectToBasic(); + } + + // ML is enabled + if (this.hasLicenseExpired()) { + showExpiredLicenseWarning(); + } + return Promise.resolve(); + } + + basicLicenseResolver() { + if (this.isMlEnabled() === false || this.isMinimumLicense() === false) { + // ML is not enabled or the license isn't at least basic + return redirectToKibana(); + } + + // ML is enabled + if (this.hasLicenseExpired()) { + showExpiredLicenseWarning(); + } + return Promise.resolve(); + } +} + +function redirectToKibana() { + window.location.href = '/'; + return Promise.reject(); +} + +function redirectToBasic() { + window.location.href = '#/datavisualizer'; + return Promise.reject(); +} diff --git a/x-pack/legacy/plugins/ml/public/application/management/index.ts b/x-pack/legacy/plugins/ml/public/application/management/index.ts index a05de8b0d0880..16bb3ddfd1c9b 100644 --- a/x-pack/legacy/plugins/ml/public/application/management/index.ts +++ b/x-pack/legacy/plugins/ml/public/application/management/index.ts @@ -10,21 +10,36 @@ * you may not use this file except in compliance with the Elastic License. */ +import { npSetup } from 'ui/new_platform'; import { management } from 'ui/management'; import { i18n } from '@kbn/i18n'; import chrome from 'ui/chrome'; import { metadata } from 'ui/metadata'; -// @ts-ignore No declaration file for module -import { xpackInfo } from '../../../../xpack_main/public/services/xpack_info'; import { JOBS_LIST_PATH } from './management_urls'; -import { LICENSE_TYPE } from '../../../common/constants/license'; import { setDependencyCache } from '../util/dependency_cache'; import './jobs_list'; +import { + LicensingPluginSetup, + LICENSE_CHECK_STATE, +} from '../../../../../../plugins/licensing/public'; +import { PLUGIN_ID } from '../../../common/constants/app'; +import { MINIMUM_FULL_LICENSE } from '../../../common/license'; -if ( - xpackInfo.get('features.ml.showLinks', false) === true && - xpackInfo.get('features.ml.licenseType') === LICENSE_TYPE.FULL -) { +type PluginsSetupExtended = typeof npSetup.plugins & { + // adds licensing which isn't in the PluginsSetup interface, but does exist + licensing: LicensingPluginSetup; +}; + +const plugins = npSetup.plugins as PluginsSetupExtended; +const licencingSubscription = plugins.licensing.license$.subscribe(license => { + if (license.check(PLUGIN_ID, MINIMUM_FULL_LICENSE).state === LICENSE_CHECK_STATE.Valid) { + initManagementSection(); + // unsubscribe, we only want to register the plugin once. + licencingSubscription.unsubscribe(); + } +}); + +function initManagementSection() { const legacyBasePath = { prepend: chrome.addBasePath, get: chrome.getBasePath, diff --git a/x-pack/legacy/plugins/ml/public/application/privilege/check_privilege.ts b/x-pack/legacy/plugins/ml/public/application/privilege/check_privilege.ts index 6cc06231a08d0..ec9695a2ce668 100644 --- a/x-pack/legacy/plugins/ml/public/application/privilege/check_privilege.ts +++ b/x-pack/legacy/plugins/ml/public/application/privilege/check_privilege.ts @@ -6,7 +6,7 @@ import { i18n } from '@kbn/i18n'; -import { hasLicenseExpired } from '../license/check_license'; +import { hasLicenseExpired } from '../license'; import { Privileges, getDefaultPrivileges } from '../../../common/types/privileges'; import { getPrivileges, getManageMlPrivileges } from './get_privileges'; diff --git a/x-pack/legacy/plugins/ml/public/application/routing/resolvers.ts b/x-pack/legacy/plugins/ml/public/application/routing/resolvers.ts index 5fc1ea533e87f..acaf3f3acd0c8 100644 --- a/x-pack/legacy/plugins/ml/public/application/routing/resolvers.ts +++ b/x-pack/legacy/plugins/ml/public/application/routing/resolvers.ts @@ -5,7 +5,7 @@ */ import { loadIndexPatterns, loadSavedSearches } from '../util/index_utils'; -import { checkFullLicense } from '../license/check_license'; +import { checkFullLicense } from '../license'; import { checkGetJobsPrivilege } from '../privilege/check_privilege'; import { getMlNodeCount } from '../ml_nodes_check/check_ml_nodes'; import { loadMlServerInfo } from '../services/ml_server_info'; diff --git a/x-pack/legacy/plugins/ml/public/application/routing/routes/datavisualizer/datavisualizer.tsx b/x-pack/legacy/plugins/ml/public/application/routing/routes/datavisualizer/datavisualizer.tsx index e89834018f5e6..d257a9c080c35 100644 --- a/x-pack/legacy/plugins/ml/public/application/routing/routes/datavisualizer/datavisualizer.tsx +++ b/x-pack/legacy/plugins/ml/public/application/routing/routes/datavisualizer/datavisualizer.tsx @@ -15,7 +15,7 @@ import { MlRoute, PageLoader, PageProps } from '../../router'; import { useResolver } from '../../use_resolver'; import { DatavisualizerSelector } from '../../../datavisualizer'; -import { checkBasicLicense } from '../../../license/check_license'; +import { checkBasicLicense } from '../../../license'; import { checkFindFileStructurePrivilege } from '../../../privilege/check_privilege'; import { DATA_VISUALIZER_BREADCRUMB, ML_BREADCRUMB } from '../../breadcrumbs'; diff --git a/x-pack/legacy/plugins/ml/public/application/routing/routes/datavisualizer/file_based.tsx b/x-pack/legacy/plugins/ml/public/application/routing/routes/datavisualizer/file_based.tsx index b4ccccd0776eb..174b3e3b4b338 100644 --- a/x-pack/legacy/plugins/ml/public/application/routing/routes/datavisualizer/file_based.tsx +++ b/x-pack/legacy/plugins/ml/public/application/routing/routes/datavisualizer/file_based.tsx @@ -16,11 +16,10 @@ import { MlRoute, PageLoader, PageProps } from '../../router'; import { useResolver } from '../../use_resolver'; import { FileDataVisualizerPage } from '../../../datavisualizer/file_based'; -import { checkBasicLicense } from '../../../license/check_license'; +import { checkBasicLicense } from '../../../license'; import { checkFindFileStructurePrivilege } from '../../../privilege/check_privilege'; import { loadIndexPatterns } from '../../../util/index_utils'; -import { getMlNodeCount } from '../../../ml_nodes_check'; import { DATA_VISUALIZER_BREADCRUMB, ML_BREADCRUMB } from '../../breadcrumbs'; const breadcrumbs = [ @@ -45,7 +44,6 @@ const PageWrapper: FC = ({ location, deps }) => { checkBasicLicense, loadIndexPatterns: () => loadIndexPatterns(deps.indexPatterns), checkFindFileStructurePrivilege, - getMlNodeCount, }); return ( diff --git a/x-pack/legacy/plugins/ml/public/application/routing/routes/datavisualizer/index_based.tsx b/x-pack/legacy/plugins/ml/public/application/routing/routes/datavisualizer/index_based.tsx index 74ab916cb443f..a3dbc9f97124c 100644 --- a/x-pack/legacy/plugins/ml/public/application/routing/routes/datavisualizer/index_based.tsx +++ b/x-pack/legacy/plugins/ml/public/application/routing/routes/datavisualizer/index_based.tsx @@ -11,7 +11,7 @@ import { MlRoute, PageLoader, PageProps } from '../../router'; import { useResolver } from '../../use_resolver'; import { Page } from '../../../datavisualizer/index_based'; -import { checkBasicLicense } from '../../../license/check_license'; +import { checkBasicLicense } from '../../../license'; import { checkGetJobsPrivilege } from '../../../privilege/check_privilege'; import { loadIndexPatterns } from '../../../util/index_utils'; import { checkMlNodesAvailable } from '../../../ml_nodes_check'; diff --git a/x-pack/legacy/plugins/ml/public/application/routing/routes/new_job/index_or_search.tsx b/x-pack/legacy/plugins/ml/public/application/routing/routes/new_job/index_or_search.tsx index ae35d783517d3..9411b415e4e4d 100644 --- a/x-pack/legacy/plugins/ml/public/application/routing/routes/new_job/index_or_search.tsx +++ b/x-pack/legacy/plugins/ml/public/application/routing/routes/new_job/index_or_search.tsx @@ -11,7 +11,7 @@ import { useResolver } from '../../use_resolver'; import { basicResolvers } from '../../resolvers'; import { Page, preConfiguredJobRedirect } from '../../../jobs/new_job/pages/index_or_search'; import { ANOMALY_DETECTION_BREADCRUMB, ML_BREADCRUMB } from '../../breadcrumbs'; -import { checkBasicLicense } from '../../../license/check_license'; +import { checkBasicLicense } from '../../../license'; import { loadIndexPatterns } from '../../../util/index_utils'; import { checkGetJobsPrivilege } from '../../../privilege/check_privilege'; import { checkMlNodesAvailable } from '../../../ml_nodes_check'; diff --git a/x-pack/legacy/plugins/ml/public/application/routing/routes/overview.tsx b/x-pack/legacy/plugins/ml/public/application/routing/routes/overview.tsx index b1e00158efb94..ccb99985cb70c 100644 --- a/x-pack/legacy/plugins/ml/public/application/routing/routes/overview.tsx +++ b/x-pack/legacy/plugins/ml/public/application/routing/routes/overview.tsx @@ -12,7 +12,7 @@ import { MlRoute, PageLoader, PageProps } from '../router'; import { useResolver } from '../use_resolver'; import { OverviewPage } from '../../overview'; -import { checkFullLicense } from '../../license/check_license'; +import { checkFullLicense } from '../../license'; import { checkGetJobsPrivilege } from '../../privilege/check_privilege'; import { getMlNodeCount } from '../../ml_nodes_check'; import { loadMlServerInfo } from '../../services/ml_server_info'; diff --git a/x-pack/legacy/plugins/ml/public/application/routing/routes/settings/calendar_list.tsx b/x-pack/legacy/plugins/ml/public/application/routing/routes/settings/calendar_list.tsx index c1bfaa2fe6c1e..9d5c4e9c0b0a0 100644 --- a/x-pack/legacy/plugins/ml/public/application/routing/routes/settings/calendar_list.tsx +++ b/x-pack/legacy/plugins/ml/public/application/routing/routes/settings/calendar_list.tsx @@ -16,7 +16,7 @@ import { MlRoute, PageLoader, PageProps } from '../../router'; import { useResolver } from '../../use_resolver'; import { useTimefilter } from '../../../contexts/kibana'; -import { checkFullLicense } from '../../../license/check_license'; +import { checkFullLicense } from '../../../license'; import { checkGetJobsPrivilege, checkPermission } from '../../../privilege/check_privilege'; import { getMlNodeCount } from '../../../ml_nodes_check/check_ml_nodes'; import { CalendarsList } from '../../../settings/calendars'; diff --git a/x-pack/legacy/plugins/ml/public/application/routing/routes/settings/calendar_new_edit.tsx b/x-pack/legacy/plugins/ml/public/application/routing/routes/settings/calendar_new_edit.tsx index 7af2e49e3a69e..bf039e3bd2354 100644 --- a/x-pack/legacy/plugins/ml/public/application/routing/routes/settings/calendar_new_edit.tsx +++ b/x-pack/legacy/plugins/ml/public/application/routing/routes/settings/calendar_new_edit.tsx @@ -16,7 +16,7 @@ import { MlRoute, PageLoader, PageProps } from '../../router'; import { useResolver } from '../../use_resolver'; import { useTimefilter } from '../../../contexts/kibana'; -import { checkFullLicense } from '../../../license/check_license'; +import { checkFullLicense } from '../../../license'; import { checkGetJobsPrivilege, checkPermission } from '../../../privilege/check_privilege'; import { checkMlNodesAvailable } from '../../../ml_nodes_check/check_ml_nodes'; import { NewCalendar } from '../../../settings/calendars'; diff --git a/x-pack/legacy/plugins/ml/public/application/routing/routes/settings/filter_list.tsx b/x-pack/legacy/plugins/ml/public/application/routing/routes/settings/filter_list.tsx index 9c5c06b76247c..6839ad833cb06 100644 --- a/x-pack/legacy/plugins/ml/public/application/routing/routes/settings/filter_list.tsx +++ b/x-pack/legacy/plugins/ml/public/application/routing/routes/settings/filter_list.tsx @@ -16,7 +16,7 @@ import { MlRoute, PageLoader, PageProps } from '../../router'; import { useResolver } from '../../use_resolver'; import { useTimefilter } from '../../../contexts/kibana'; -import { checkFullLicense } from '../../../license/check_license'; +import { checkFullLicense } from '../../../license'; import { checkGetJobsPrivilege, checkPermission } from '../../../privilege/check_privilege'; import { getMlNodeCount } from '../../../ml_nodes_check/check_ml_nodes'; import { FilterLists } from '../../../settings/filter_lists'; diff --git a/x-pack/legacy/plugins/ml/public/application/routing/routes/settings/filter_list_new_edit.tsx b/x-pack/legacy/plugins/ml/public/application/routing/routes/settings/filter_list_new_edit.tsx index 752b889490e58..7b8bd6c3c81ac 100644 --- a/x-pack/legacy/plugins/ml/public/application/routing/routes/settings/filter_list_new_edit.tsx +++ b/x-pack/legacy/plugins/ml/public/application/routing/routes/settings/filter_list_new_edit.tsx @@ -16,7 +16,7 @@ import { MlRoute, PageLoader, PageProps } from '../../router'; import { useResolver } from '../../use_resolver'; import { useTimefilter } from '../../../contexts/kibana'; -import { checkFullLicense } from '../../../license/check_license'; +import { checkFullLicense } from '../../../license'; import { checkGetJobsPrivilege, checkPermission } from '../../../privilege/check_privilege'; import { checkMlNodesAvailable } from '../../../ml_nodes_check/check_ml_nodes'; import { EditFilterList } from '../../../settings/filter_lists'; diff --git a/x-pack/legacy/plugins/ml/public/application/routing/routes/settings/settings.tsx b/x-pack/legacy/plugins/ml/public/application/routing/routes/settings/settings.tsx index 10efb2dcc60c7..10ccc0987fe5d 100644 --- a/x-pack/legacy/plugins/ml/public/application/routing/routes/settings/settings.tsx +++ b/x-pack/legacy/plugins/ml/public/application/routing/routes/settings/settings.tsx @@ -15,7 +15,7 @@ import { MlRoute, PageLoader, PageProps } from '../../router'; import { useResolver } from '../../use_resolver'; import { useTimefilter } from '../../../contexts/kibana'; -import { checkFullLicense } from '../../../license/check_license'; +import { checkFullLicense } from '../../../license'; import { checkGetJobsPrivilege, checkPermission } from '../../../privilege/check_privilege'; import { getMlNodeCount } from '../../../ml_nodes_check/check_ml_nodes'; import { Settings } from '../../../settings'; diff --git a/x-pack/legacy/plugins/ml/public/application/settings/calendars/edit/new_calendar.test.js b/x-pack/legacy/plugins/ml/public/application/settings/calendars/edit/new_calendar.test.js index 8dc174040f9c8..5f61ccf47e9d7 100644 --- a/x-pack/legacy/plugins/ml/public/application/settings/calendars/edit/new_calendar.test.js +++ b/x-pack/legacy/plugins/ml/public/application/settings/calendars/edit/new_calendar.test.js @@ -10,7 +10,7 @@ jest.mock('../../../components/navigation_menu', () => ({ jest.mock('../../../privilege/check_privilege', () => ({ checkPermission: () => true, })); -jest.mock('../../../license/check_license', () => ({ +jest.mock('../../../license', () => ({ hasLicenseExpired: () => false, isFullLicense: () => false, })); diff --git a/x-pack/legacy/plugins/ml/public/application/settings/calendars/list/calendars_list.test.js b/x-pack/legacy/plugins/ml/public/application/settings/calendars/list/calendars_list.test.js index 677703bceeca7..3ea8e0c39fbb2 100644 --- a/x-pack/legacy/plugins/ml/public/application/settings/calendars/list/calendars_list.test.js +++ b/x-pack/legacy/plugins/ml/public/application/settings/calendars/list/calendars_list.test.js @@ -16,7 +16,7 @@ jest.mock('../../../components/navigation_menu', () => ({ jest.mock('../../../privilege/check_privilege', () => ({ checkPermission: () => true, })); -jest.mock('../../../license/check_license', () => ({ +jest.mock('../../../license', () => ({ hasLicenseExpired: () => false, isFullLicense: () => false, })); diff --git a/x-pack/legacy/plugins/ml/public/application/util/dependency_cache.ts b/x-pack/legacy/plugins/ml/public/application/util/dependency_cache.ts index 6d1dfa96ca03e..c167d7e7c3d42 100644 --- a/x-pack/legacy/plugins/ml/public/application/util/dependency_cache.ts +++ b/x-pack/legacy/plugins/ml/public/application/util/dependency_cache.ts @@ -76,6 +76,7 @@ export function setDependencyCache(deps: Partial) { cache.XSRF = deps.XSRF || null; cache.application = deps.application || null; cache.http = deps.http || null; + cache.security = deps.security || null; } export function getTimefilter() { diff --git a/x-pack/legacy/plugins/ml/public/legacy.ts b/x-pack/legacy/plugins/ml/public/legacy.ts index 7dfcf6a99c213..0c6c0bd8dd29e 100644 --- a/x-pack/legacy/plugins/ml/public/legacy.ts +++ b/x-pack/legacy/plugins/ml/public/legacy.ts @@ -8,14 +8,24 @@ import chrome from 'ui/chrome'; import { npSetup, npStart } from 'ui/new_platform'; import { PluginInitializerContext } from 'src/core/public'; import { SecurityPluginSetup } from '../../../../plugins/security/public'; +import { LicensingPluginSetup } from '../../../../plugins/licensing/public'; import { plugin } from '.'; const pluginInstance = plugin({} as PluginInitializerContext); +type PluginsSetupExtended = typeof npSetup.plugins & { + // adds plugins which aren't in the PluginsSetup interface, but do exist + security: SecurityPluginSetup; + licensing: LicensingPluginSetup; +}; + +const setupDependencies = npSetup.plugins as PluginsSetupExtended; + export const setup = pluginInstance.setup(npSetup.core, { data: npStart.plugins.data, - security: ((npSetup.plugins as unknown) as { security: SecurityPluginSetup }).security, // security isn't in the PluginsSetup interface, but does exist + security: setupDependencies.security, + licensing: setupDependencies.licensing, __LEGACY: { XSRF: chrome.getXsrfToken(), }, diff --git a/x-pack/legacy/plugins/ml/public/plugin.ts b/x-pack/legacy/plugins/ml/public/plugin.ts index 1061bb1b6b62b..c0369a74c070a 100644 --- a/x-pack/legacy/plugins/ml/public/plugin.ts +++ b/x-pack/legacy/plugins/ml/public/plugin.ts @@ -8,7 +8,7 @@ import { Plugin, CoreStart, CoreSetup } from 'src/core/public'; import { MlDependencies } from './application/app'; export class MlPlugin implements Plugin { - setup(core: CoreSetup, { data, security, __LEGACY }: MlDependencies) { + setup(core: CoreSetup, { data, security, licensing, __LEGACY }: MlDependencies) { core.application.register({ id: 'ml', title: 'Machine learning', @@ -23,6 +23,7 @@ export class MlPlugin implements Plugin { data, __LEGACY, security, + licensing, }); }, }); diff --git a/x-pack/plugins/ml/server/lib/check_license/check_license.test.ts b/x-pack/plugins/ml/server/lib/check_license/check_license.test.ts deleted file mode 100644 index 942dbe3722617..0000000000000 --- a/x-pack/plugins/ml/server/lib/check_license/check_license.test.ts +++ /dev/null @@ -1,167 +0,0 @@ -/* - * 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 expect from '@kbn/expect'; -import sinon from 'sinon'; -import { set } from 'lodash'; -import { LicenseCheckResult } from '../../types'; -import { checkLicense } from './check_license'; - -describe('check_license', () => { - let mockLicenseInfo: LicenseCheckResult; - beforeEach(() => (mockLicenseInfo = {} as LicenseCheckResult)); - - describe('license information is undefined', () => { - it('should set isAvailable to false', () => { - expect(checkLicense(undefined as any).isAvailable).to.be(false); - }); - - it('should set showLinks to true', () => { - expect(checkLicense(undefined as any).showLinks).to.be(true); - }); - - it('should set enableLinks to false', () => { - expect(checkLicense(undefined as any).enableLinks).to.be(false); - }); - - it('should set a message', () => { - expect(checkLicense(undefined as any).message).to.not.be(undefined); - }); - }); - - describe('license information is not available', () => { - beforeEach(() => { - mockLicenseInfo.isAvailable = false; - }); - - it('should set isAvailable to false', () => { - expect(checkLicense(mockLicenseInfo).isAvailable).to.be(false); - }); - - it('should set showLinks to true', () => { - expect(checkLicense(mockLicenseInfo).showLinks).to.be(true); - }); - - it('should set enableLinks to false', () => { - expect(checkLicense(mockLicenseInfo).enableLinks).to.be(false); - }); - - it('should set a message', () => { - expect(checkLicense(mockLicenseInfo).message).to.not.be(undefined); - }); - }); - - describe('license information is available', () => { - beforeEach(() => { - mockLicenseInfo.isAvailable = true; - mockLicenseInfo.type = 'basic'; - }); - - describe('& ML is disabled in Elasticsearch', () => { - beforeEach(() => { - set( - mockLicenseInfo, - 'feature', - sinon - .stub() - .withArgs('ml') - .returns({ isEnabled: false }) - ); - }); - - it('should set showLinks to false', () => { - expect(checkLicense(mockLicenseInfo).showLinks).to.be(false); - }); - - it('should set isAvailable to false', () => { - expect(checkLicense(mockLicenseInfo).isAvailable).to.be(false); - }); - - it('should set enableLinks to false', () => { - expect(checkLicense(mockLicenseInfo).enableLinks).to.be(false); - }); - - it('should set a message', () => { - expect(checkLicense(mockLicenseInfo).message).to.not.be(undefined); - }); - }); - - describe('& ML is enabled in Elasticsearch', () => { - beforeEach(() => { - mockLicenseInfo.isEnabled = true; - }); - - describe('& license is >= platinum', () => { - beforeEach(() => { - mockLicenseInfo.type = 'platinum'; - }); - describe('& license is active', () => { - beforeEach(() => { - mockLicenseInfo.isActive = true; - }); - - it('should set isAvailable to true', () => { - expect(checkLicense(mockLicenseInfo).isAvailable).to.be(true); - }); - - it('should set showLinks to true', () => { - expect(checkLicense(mockLicenseInfo).showLinks).to.be(true); - }); - - it('should set enableLinks to true', () => { - expect(checkLicense(mockLicenseInfo).enableLinks).to.be(true); - }); - - it('should not set a message', () => { - expect(checkLicense(mockLicenseInfo).message).to.be(undefined); - }); - }); - - describe('& license is expired', () => { - beforeEach(() => { - mockLicenseInfo.isActive = false; - }); - - it('should set isAvailable to true', () => { - expect(checkLicense(mockLicenseInfo).isAvailable).to.be(true); - }); - - it('should set showLinks to true', () => { - expect(checkLicense(mockLicenseInfo).showLinks).to.be(true); - }); - - it('should set enableLinks to true', () => { - expect(checkLicense(mockLicenseInfo).enableLinks).to.be(true); - }); - - it('should set a message', () => { - expect(checkLicense(mockLicenseInfo).message).to.not.be(undefined); - }); - }); - }); - - describe('& license is basic', () => { - beforeEach(() => { - mockLicenseInfo.type = 'basic'; - }); - - describe('& license is active', () => { - beforeEach(() => { - mockLicenseInfo.isActive = true; - }); - - it('should set isAvailable to true', () => { - expect(checkLicense(mockLicenseInfo).isAvailable).to.be(true); - }); - - it('should set showLinks to true', () => { - expect(checkLicense(mockLicenseInfo).showLinks).to.be(true); - }); - }); - }); - }); - }); -}); diff --git a/x-pack/plugins/ml/server/lib/check_license/check_license.ts b/x-pack/plugins/ml/server/lib/check_license/check_license.ts deleted file mode 100644 index 5bf3d590a1912..0000000000000 --- a/x-pack/plugins/ml/server/lib/check_license/check_license.ts +++ /dev/null @@ -1,82 +0,0 @@ -/* - * 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 { i18n } from '@kbn/i18n'; -import { - LICENSE_TYPE, - VALID_FULL_LICENSE_MODES, -} from '../../../../../legacy/plugins/ml/common/constants/license'; -import { LicenseCheckResult } from '../../types'; - -interface Response { - isAvailable: boolean; - showLinks: boolean; - enableLinks: boolean; - licenseType?: LICENSE_TYPE; - hasExpired?: boolean; - message?: string; -} - -export function checkLicense(licenseCheckResult: LicenseCheckResult): Response { - // If, for some reason, we cannot get the license information - // from Elasticsearch, assume worst case and disable the Machine Learning UI - if (licenseCheckResult === undefined || !licenseCheckResult.isAvailable) { - return { - isAvailable: false, - showLinks: true, - enableLinks: false, - message: i18n.translate( - 'xpack.ml.checkLicense.licenseInformationNotAvailableThisTimeMessage', - { - defaultMessage: - 'You cannot use Machine Learning because license information is not available at this time.', - } - ), - }; - } - - const featureEnabled = licenseCheckResult.isEnabled; - if (!featureEnabled) { - return { - isAvailable: false, - showLinks: false, - enableLinks: false, - message: i18n.translate('xpack.ml.checkLicense.mlIsUnavailableMessage', { - defaultMessage: 'Machine Learning is unavailable', - }), - }; - } - - const isLicenseModeValid = - licenseCheckResult.type && VALID_FULL_LICENSE_MODES.includes(licenseCheckResult.type); - const licenseType = isLicenseModeValid === true ? LICENSE_TYPE.FULL : LICENSE_TYPE.BASIC; - const isLicenseActive = licenseCheckResult.isActive; - const licenseTypeName = licenseCheckResult.type; - - // Platinum or trial license is valid but not active, i.e. expired - if (licenseType === LICENSE_TYPE.FULL && isLicenseActive === false) { - return { - isAvailable: true, - showLinks: true, - enableLinks: true, - hasExpired: true, - licenseType, - message: i18n.translate('xpack.ml.checkLicense.licenseHasExpiredMessage', { - defaultMessage: 'Your {licenseTypeName} Machine Learning license has expired.', - values: { licenseTypeName }, - }), - }; - } - - // License is valid and active - return { - isAvailable: true, - showLinks: true, - enableLinks: true, - licenseType, - hasExpired: false, - }; -} diff --git a/x-pack/plugins/ml/server/lib/check_privileges/check_privileges.test.ts b/x-pack/plugins/ml/server/lib/check_privileges/check_privileges.test.ts index 0690aa53576a5..4dd9100e1b67a 100644 --- a/x-pack/plugins/ml/server/lib/check_privileges/check_privileges.test.ts +++ b/x-pack/plugins/ml/server/lib/check_privileges/check_privileges.test.ts @@ -7,30 +7,27 @@ import { callWithRequestProvider } from './__mocks__/call_with_request'; import { privilegesProvider } from './check_privileges'; import { mlPrivileges } from './privileges'; +import { MlLicense } from '../../../../../legacy/plugins/ml/common/license'; -const licenseCheckResultWithSecurity = { - isAvailable: true, - isEnabled: true, - isSecurityDisabled: false, - type: 'platinum', - isActive: true, -}; +const mlLicenseWithSecurity = { + isSecurityEnabled: () => true, + isFullLicense: () => true, +} as MlLicense; -const licenseCheckResultWithOutSecurity = { - ...licenseCheckResultWithSecurity, - isSecurityDisabled: true, -}; +const mlLicenseWithOutSecurity = { + isSecurityEnabled: () => false, + isFullLicense: () => true, +} as MlLicense; -const licenseCheckResultWithOutSecurityBasicLicense = { - ...licenseCheckResultWithSecurity, - isSecurityDisabled: true, - type: 'basic', -}; +const mlLicenseWithOutSecurityBasicLicense = { + isSecurityEnabled: () => false, + isFullLicense: () => false, +} as MlLicense; -const licenseCheckResultWithSecurityBasicLicense = { - ...licenseCheckResultWithSecurity, - type: 'basic', -}; +const mlLicenseWithSecurityBasicLicense = { + isSecurityEnabled: () => true, + isFullLicense: () => false, +} as MlLicense; const mlIsEnabled = async () => true; const mlIsNotEnabled = async () => false; @@ -47,7 +44,7 @@ describe('check_privileges', () => { const callWithRequest = callWithRequestProvider('partialPrivileges'); const { getPrivileges } = privilegesProvider( callWithRequest, - licenseCheckResultWithSecurity, + mlLicenseWithSecurity, mlIsEnabled ); const { capabilities } = await getPrivileges(); @@ -62,7 +59,7 @@ describe('check_privileges', () => { const callWithRequest = callWithRequestProvider('partialPrivileges'); const { getPrivileges } = privilegesProvider( callWithRequest, - licenseCheckResultWithSecurity, + mlLicenseWithSecurity, mlIsEnabled ); const { capabilities, upgradeInProgress, mlFeatureEnabledInSpace } = await getPrivileges(); @@ -97,7 +94,7 @@ describe('check_privileges', () => { const callWithRequest = callWithRequestProvider('fullPrivileges'); const { getPrivileges } = privilegesProvider( callWithRequest, - licenseCheckResultWithSecurity, + mlLicenseWithSecurity, mlIsEnabled ); const { capabilities, upgradeInProgress, mlFeatureEnabledInSpace } = await getPrivileges(); @@ -132,7 +129,7 @@ describe('check_privileges', () => { const callWithRequest = callWithRequestProvider('upgradeWithFullPrivileges'); const { getPrivileges } = privilegesProvider( callWithRequest, - licenseCheckResultWithSecurity, + mlLicenseWithSecurity, mlIsEnabled ); const { capabilities, upgradeInProgress, mlFeatureEnabledInSpace } = await getPrivileges(); @@ -167,7 +164,7 @@ describe('check_privileges', () => { const callWithRequest = callWithRequestProvider('upgradeWithPartialPrivileges'); const { getPrivileges } = privilegesProvider( callWithRequest, - licenseCheckResultWithSecurity, + mlLicenseWithSecurity, mlIsEnabled ); const { capabilities, upgradeInProgress, mlFeatureEnabledInSpace } = await getPrivileges(); @@ -202,7 +199,7 @@ describe('check_privileges', () => { const callWithRequest = callWithRequestProvider('partialPrivileges'); const { getPrivileges } = privilegesProvider( callWithRequest, - licenseCheckResultWithSecurityBasicLicense, + mlLicenseWithSecurityBasicLicense, mlIsEnabled ); const { capabilities, upgradeInProgress, mlFeatureEnabledInSpace } = await getPrivileges(); @@ -237,7 +234,7 @@ describe('check_privileges', () => { const callWithRequest = callWithRequestProvider('fullPrivileges'); const { getPrivileges } = privilegesProvider( callWithRequest, - licenseCheckResultWithSecurityBasicLicense, + mlLicenseWithSecurityBasicLicense, mlIsEnabled ); const { capabilities, upgradeInProgress, mlFeatureEnabledInSpace } = await getPrivileges(); @@ -272,7 +269,7 @@ describe('check_privileges', () => { const callWithRequest = callWithRequestProvider('fullPrivileges'); const { getPrivileges } = privilegesProvider( callWithRequest, - licenseCheckResultWithSecurity, + mlLicenseWithSecurity, mlIsNotEnabled ); const { capabilities, upgradeInProgress, mlFeatureEnabledInSpace } = await getPrivileges(); @@ -309,7 +306,7 @@ describe('check_privileges', () => { const callWithRequest = callWithRequestProvider('partialPrivileges'); const { getPrivileges } = privilegesProvider( callWithRequest, - licenseCheckResultWithOutSecurity, + mlLicenseWithOutSecurity, mlIsEnabled ); const { capabilities, upgradeInProgress, mlFeatureEnabledInSpace } = await getPrivileges(); @@ -344,7 +341,7 @@ describe('check_privileges', () => { const callWithRequest = callWithRequestProvider('upgradeWithFullPrivileges'); const { getPrivileges } = privilegesProvider( callWithRequest, - licenseCheckResultWithOutSecurity, + mlLicenseWithOutSecurity, mlIsEnabled ); const { capabilities, upgradeInProgress, mlFeatureEnabledInSpace } = await getPrivileges(); @@ -379,7 +376,7 @@ describe('check_privileges', () => { const callWithRequest = callWithRequestProvider('upgradeWithPartialPrivileges'); const { getPrivileges } = privilegesProvider( callWithRequest, - licenseCheckResultWithOutSecurity, + mlLicenseWithOutSecurity, mlIsEnabled ); const { capabilities, upgradeInProgress, mlFeatureEnabledInSpace } = await getPrivileges(); @@ -414,7 +411,7 @@ describe('check_privileges', () => { const callWithRequest = callWithRequestProvider('partialPrivileges'); const { getPrivileges } = privilegesProvider( callWithRequest, - licenseCheckResultWithOutSecurityBasicLicense, + mlLicenseWithOutSecurityBasicLicense, mlIsEnabled ); const { capabilities, upgradeInProgress, mlFeatureEnabledInSpace } = await getPrivileges(); @@ -449,7 +446,7 @@ describe('check_privileges', () => { const callWithRequest = callWithRequestProvider('fullPrivileges'); const { getPrivileges } = privilegesProvider( callWithRequest, - licenseCheckResultWithOutSecurityBasicLicense, + mlLicenseWithOutSecurityBasicLicense, mlIsEnabled ); const { capabilities, upgradeInProgress, mlFeatureEnabledInSpace } = await getPrivileges(); @@ -484,7 +481,7 @@ describe('check_privileges', () => { const callWithRequest = callWithRequestProvider('partialPrivileges'); const { getPrivileges } = privilegesProvider( callWithRequest, - licenseCheckResultWithOutSecurity, + mlLicenseWithOutSecurity, mlIsNotEnabled ); const { capabilities, upgradeInProgress, mlFeatureEnabledInSpace } = await getPrivileges(); diff --git a/x-pack/plugins/ml/server/lib/check_privileges/check_privileges.ts b/x-pack/plugins/ml/server/lib/check_privileges/check_privileges.ts index a427780d13344..f26040385b9f5 100644 --- a/x-pack/plugins/ml/server/lib/check_privileges/check_privileges.ts +++ b/x-pack/plugins/ml/server/lib/check_privileges/check_privileges.ts @@ -10,9 +10,7 @@ import { getDefaultPrivileges, } from '../../../../../legacy/plugins/ml/common/types/privileges'; import { upgradeCheckProvider } from './upgrade'; -import { checkLicense } from '../check_license'; -import { LICENSE_TYPE } from '../../../../../legacy/plugins/ml/common/constants/license'; -import { LicenseCheckResult } from '../../types'; +import { MlLicense } from '../../../../../legacy/plugins/ml/common/license'; import { mlPrivileges } from './privileges'; @@ -27,7 +25,7 @@ interface Response { export function privilegesProvider( callAsCurrentUser: IScopedClusterClient['callAsCurrentUser'], - licenseCheckResult: LicenseCheckResult, + mlLicense: MlLicense, isMlEnabledInSpace: () => Promise, ignoreSpaces: boolean = false ) { @@ -37,9 +35,9 @@ export function privilegesProvider( const privileges = getDefaultPrivileges(); const upgradeInProgress = await isUpgradeInProgress(); - const securityDisabled = licenseCheckResult.isSecurityDisabled; - const license = checkLicense(licenseCheckResult); - const isPlatinumOrTrialLicense = license.licenseType === LICENSE_TYPE.FULL; + const isSecurityEnabled = mlLicense.isSecurityEnabled(); + + const isPlatinumOrTrialLicense = mlLicense.isFullLicense(); const mlFeatureEnabledInSpace = await isMlEnabledInSpace(); const setGettingPrivileges = isPlatinumOrTrialLicense @@ -61,7 +59,7 @@ export function privilegesProvider( }; } - if (securityDisabled === true) { + if (isSecurityEnabled === false) { if (upgradeInProgress === true) { // if security is disabled and an upgrade in is progress, // force all "getting" privileges to be true diff --git a/x-pack/plugins/ml/server/lib/check_license/index.ts b/x-pack/plugins/ml/server/lib/license/index.ts similarity index 81% rename from x-pack/plugins/ml/server/lib/check_license/index.ts rename to x-pack/plugins/ml/server/lib/license/index.ts index f2c070fd44b6e..9c4271b65b00d 100644 --- a/x-pack/plugins/ml/server/lib/check_license/index.ts +++ b/x-pack/plugins/ml/server/lib/license/index.ts @@ -4,4 +4,4 @@ * you may not use this file except in compliance with the Elastic License. */ -export { checkLicense } from './check_license'; +export { MlServerLicense } from './ml_server_license'; diff --git a/x-pack/plugins/ml/server/lib/license/ml_server_license.ts b/x-pack/plugins/ml/server/lib/license/ml_server_license.ts new file mode 100644 index 0000000000000..7602ab4919e81 --- /dev/null +++ b/x-pack/plugins/ml/server/lib/license/ml_server_license.ts @@ -0,0 +1,35 @@ +/* + * 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 { + KibanaRequest, + KibanaResponseFactory, + RequestHandler, + RequestHandlerContext, +} from 'src/core/server'; + +import { MlLicense } from '../../../../../legacy/plugins/ml/common/license'; + +export class MlServerLicense extends MlLicense { + public fullLicenseAPIGuard(handler: RequestHandler) { + return guard(() => this.isFullLicense(), handler); + } + public basicLicenseAPIGuard(handler: RequestHandler) { + return guard(() => this.isMinimumLicense(), handler); + } +} + +function guard(check: () => boolean, handler: RequestHandler) { + return ( + context: RequestHandlerContext, + request: KibanaRequest, + response: KibanaResponseFactory + ) => { + if (check() === false) { + return response.forbidden(); + } + return handler(context, request, response); + }; +} diff --git a/x-pack/plugins/ml/server/lib/sample_data_sets/index.ts b/x-pack/plugins/ml/server/lib/sample_data_sets/index.ts index c922c9eb7c029..50553cfa7b889 100644 --- a/x-pack/plugins/ml/server/lib/sample_data_sets/index.ts +++ b/x-pack/plugins/ml/server/lib/sample_data_sets/index.ts @@ -4,4 +4,4 @@ * you may not use this file except in compliance with the Elastic License. */ -export { addLinksToSampleDatasets } from './sample_data_sets'; +export { initSampleDataSets } from './sample_data_sets'; diff --git a/x-pack/plugins/ml/server/lib/sample_data_sets/sample_data_sets.ts b/x-pack/plugins/ml/server/lib/sample_data_sets/sample_data_sets.ts index 2082538adfed1..3fd99051a2484 100644 --- a/x-pack/plugins/ml/server/lib/sample_data_sets/sample_data_sets.ts +++ b/x-pack/plugins/ml/server/lib/sample_data_sets/sample_data_sets.ts @@ -5,23 +5,32 @@ */ import { i18n } from '@kbn/i18n'; +import { MlLicense } from '../../../../../legacy/plugins/ml/common/license'; +import { PluginsSetup } from '../../types'; -export function addLinksToSampleDatasets(server: any) { - const sampleDataLinkLabel = i18n.translate('xpack.ml.sampleDataLinkLabel', { - defaultMessage: 'ML jobs', - }); +export function initSampleDataSets(mlLicense: MlLicense, plugins: PluginsSetup) { + if (mlLicense.isMlEnabled() && mlLicense.isFullLicense()) { + const sampleDataLinkLabel = i18n.translate('xpack.ml.sampleDataLinkLabel', { + defaultMessage: 'ML jobs', + }); + const { addAppLinksToSampleDataset } = plugins.home.sampleData; - server.addAppLinksToSampleDataset('ecommerce', { - path: - '/app/ml#/modules/check_view_or_create?id=sample_data_ecommerce&index=ff959d40-b880-11e8-a6d9-e546fe2bba5f', - label: sampleDataLinkLabel, - icon: 'machineLearningApp', - }); + addAppLinksToSampleDataset('ecommerce', [ + { + path: + '/app/ml#/modules/check_view_or_create?id=sample_data_ecommerce&index=ff959d40-b880-11e8-a6d9-e546fe2bba5f', + label: sampleDataLinkLabel, + icon: 'machineLearningApp', + }, + ]); - server.addAppLinksToSampleDataset('logs', { - path: - '/app/ml#/modules/check_view_or_create?id=sample_data_weblogs&index=90943e30-9a47-11e8-b64d-95841ca0b247', - label: sampleDataLinkLabel, - icon: 'machineLearningApp', - }); + addAppLinksToSampleDataset('logs', [ + { + path: + '/app/ml#/modules/check_view_or_create?id=sample_data_weblogs&index=90943e30-9a47-11e8-b64d-95841ca0b247', + label: sampleDataLinkLabel, + icon: 'machineLearningApp', + }, + ]); + } } diff --git a/x-pack/plugins/ml/server/plugin.ts b/x-pack/plugins/ml/server/plugin.ts index b5adf1fedec79..a3f5733738432 100644 --- a/x-pack/plugins/ml/server/plugin.ts +++ b/x-pack/plugins/ml/server/plugin.ts @@ -6,15 +6,14 @@ import { i18n } from '@kbn/i18n'; import { CoreSetup, IScopedClusterClient, Logger, PluginInitializerContext } from 'src/core/server'; -import { LicenseCheckResult, PluginsSetup, RouteInitialization } from './types'; +import { PluginsSetup, RouteInitialization } from './types'; import { PLUGIN_ID } from '../../../legacy/plugins/ml/common/constants/app'; -import { VALID_FULL_LICENSE_MODES } from '../../../legacy/plugins/ml/common/constants/license'; // @ts-ignore: could not find declaration file for module import { elasticsearchJsPlugin } from './client/elasticsearch_ml'; import { makeMlUsageCollector } from './lib/ml_telemetry'; import { initMlServerLog } from './client/log'; -import { addLinksToSampleDatasets } from './lib/sample_data_sets'; +import { initSampleDataSets } from './lib/sample_data_sets'; import { annotationRoutes } from './routes/annotations'; import { calendars } from './routes/calendars'; @@ -33,6 +32,8 @@ import { jobValidationRoutes } from './routes/job_validation'; import { notificationRoutes } from './routes/notification_settings'; import { resultsServiceRoutes } from './routes/results_service'; import { systemRoutes } from './routes/system'; +import { MlLicense } from '../../../legacy/plugins/ml/common/license'; +import { MlServerLicense } from './lib/license'; declare module 'kibana/server' { interface RequestHandlerContext { @@ -43,25 +44,17 @@ declare module 'kibana/server' { } export class MlServerPlugin { - private readonly pluginId: string = PLUGIN_ID; private log: Logger; private version: string; - - private licenseCheckResults: LicenseCheckResult = { - isAvailable: false, - isActive: false, - isEnabled: false, - isSecurityDisabled: false, - }; + private mlLicense: MlServerLicense; constructor(ctx: PluginInitializerContext) { this.log = ctx.logger.get(); this.version = ctx.env.packageInfo.branch; + this.mlLicense = new MlServerLicense(); } public setup(coreSetup: CoreSetup, plugins: PluginsSetup) { - let sampleLinksInitialized = false; - plugins.features.registerFeature({ id: PLUGIN_ID, name: i18n.translate('xpack.ml.featureRegistry.mlFeatureName', { @@ -87,6 +80,10 @@ export class MlServerPlugin { }, }); + this.mlLicense.setup(plugins.licensing.license$, [ + (mlLicense: MlLicense) => initSampleDataSets(mlLicense, plugins), + ]); + // Can access via router's handler function 'context' parameter - context.ml.mlClient const mlClient = coreSetup.elasticsearch.createClient(PLUGIN_ID, { plugins: [elasticsearchJsPlugin], @@ -100,7 +97,7 @@ export class MlServerPlugin { const routeInit: RouteInitialization = { router: coreSetup.http.createRouter(), - getLicenseCheckResults: () => this.licenseCheckResults, + mlLicense: this.mlLicense, }; annotationRoutes(routeInit, plugins.security); @@ -127,42 +124,11 @@ export class MlServerPlugin { coreSetup.getStartServices().then(([core]) => { makeMlUsageCollector(plugins.usageCollection, core.savedObjects); }); - - plugins.licensing.license$.subscribe(async license => { - const { isEnabled: securityIsEnabled } = license.getFeature('security'); - // @ts-ignore isAvailable is not read - const { isAvailable, isEnabled } = license.getFeature(this.pluginId); - - this.licenseCheckResults = { - isActive: license.isActive, - // This `isAvailable` check for the ml plugin returns false for a basic license - // ML should be available on basic with reduced functionality (only file data visualizer) - // TODO: This will need to be updated in the second step of this cutover to NP. - isAvailable: isEnabled, - isEnabled, - isSecurityDisabled: securityIsEnabled === false, - type: license.type, - }; - - if (sampleLinksInitialized === false) { - sampleLinksInitialized = true; - // Add links to the Kibana sample data sets if ml is enabled - // and license is trial or platinum. - if (isEnabled === true && plugins.home) { - if ( - this.licenseCheckResults.type && - VALID_FULL_LICENSE_MODES.includes(this.licenseCheckResults.type) - ) { - addLinksToSampleDatasets({ - addAppLinksToSampleDataset: plugins.home.sampleData.addAppLinksToSampleDataset, - }); - } - } - } - }); } public start() {} - public stop() {} + public stop() { + this.mlLicense.unsubscribe(); + } } diff --git a/x-pack/plugins/ml/server/routes/annotations.ts b/x-pack/plugins/ml/server/routes/annotations.ts index bcc0238c366a3..16483bf8b887e 100644 --- a/x-pack/plugins/ml/server/routes/annotations.ts +++ b/x-pack/plugins/ml/server/routes/annotations.ts @@ -13,7 +13,6 @@ import { SecurityPluginSetup } from '../../../security/server'; import { isAnnotationsFeatureAvailable } from '../lib/check_annotations'; import { annotationServiceProvider } from '../models/annotation_service'; import { wrapError } from '../client/error_wrapper'; -import { licensePreRoutingFactory } from './license_check_pre_routing_factory'; import { RouteInitialization } from '../types'; import { deleteAnnotationSchema, @@ -36,7 +35,7 @@ function getAnnotationsFeatureUnavailableErrorMessage() { * Routes for annotations */ export function annotationRoutes( - { router, getLicenseCheckResults }: RouteInitialization, + { router, mlLicense }: RouteInitialization, securityPlugin: SecurityPluginSetup ) { /** @@ -61,7 +60,7 @@ export function annotationRoutes( body: schema.object(getAnnotationsSchema), }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const { getAnnotations } = annotationServiceProvider(context); const resp = await getAnnotations(request.body); @@ -92,7 +91,7 @@ export function annotationRoutes( body: schema.object(indexAnnotationSchema), }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const annotationsFeatureAvailable = await isAnnotationsFeatureAvailable( context.ml!.mlClient.callAsCurrentUser @@ -131,7 +130,7 @@ export function annotationRoutes( params: schema.object(deleteAnnotationSchema), }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const annotationsFeatureAvailable = await isAnnotationsFeatureAvailable( context.ml!.mlClient.callAsCurrentUser diff --git a/x-pack/plugins/ml/server/routes/anomaly_detectors.ts b/x-pack/plugins/ml/server/routes/anomaly_detectors.ts index 7bf2fb7bc6903..5e1ca72a7200d 100644 --- a/x-pack/plugins/ml/server/routes/anomaly_detectors.ts +++ b/x-pack/plugins/ml/server/routes/anomaly_detectors.ts @@ -6,7 +6,6 @@ import { schema } from '@kbn/config-schema'; import { wrapError } from '../client/error_wrapper'; -import { licensePreRoutingFactory } from './license_check_pre_routing_factory'; import { RouteInitialization } from '../types'; import { anomalyDetectionJobSchema, @@ -16,7 +15,7 @@ import { /** * Routes for the anomaly detectors */ -export function jobRoutes({ router, getLicenseCheckResults }: RouteInitialization) { +export function jobRoutes({ router, mlLicense }: RouteInitialization) { /** * @apiGroup AnomalyDetectors * @@ -32,7 +31,7 @@ export function jobRoutes({ router, getLicenseCheckResults }: RouteInitializatio path: '/api/ml/anomaly_detectors', validate: false, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const results = await context.ml!.mlClient.callAsCurrentUser('ml.jobs'); return response.ok({ @@ -62,7 +61,7 @@ export function jobRoutes({ router, getLicenseCheckResults }: RouteInitializatio }), }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const { jobId } = request.params; const results = await context.ml!.mlClient.callAsCurrentUser('ml.jobs', { jobId }); @@ -90,7 +89,7 @@ export function jobRoutes({ router, getLicenseCheckResults }: RouteInitializatio path: '/api/ml/anomaly_detectors/_stats', validate: false, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const results = await context.ml!.mlClient.callAsCurrentUser('ml.jobStats'); return response.ok({ @@ -120,7 +119,7 @@ export function jobRoutes({ router, getLicenseCheckResults }: RouteInitializatio }), }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const { jobId } = request.params; const results = await context.ml!.mlClient.callAsCurrentUser('ml.jobStats', { jobId }); @@ -152,7 +151,7 @@ export function jobRoutes({ router, getLicenseCheckResults }: RouteInitializatio body: schema.object({ ...anomalyDetectionJobSchema }), }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const { jobId } = request.params; const results = await context.ml!.mlClient.callAsCurrentUser('ml.addJob', { @@ -187,7 +186,7 @@ export function jobRoutes({ router, getLicenseCheckResults }: RouteInitializatio body: schema.object({ ...anomalyDetectionUpdateJobSchema }), }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const { jobId } = request.params; const results = await context.ml!.mlClient.callAsCurrentUser('ml.updateJob', { @@ -221,7 +220,7 @@ export function jobRoutes({ router, getLicenseCheckResults }: RouteInitializatio }), }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const { jobId } = request.params; const results = await context.ml!.mlClient.callAsCurrentUser('ml.openJob', { @@ -254,7 +253,7 @@ export function jobRoutes({ router, getLicenseCheckResults }: RouteInitializatio }), }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const options: { jobId: string; force?: boolean } = { jobId: request.params.jobId, @@ -291,7 +290,7 @@ export function jobRoutes({ router, getLicenseCheckResults }: RouteInitializatio }), }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const options: { jobId: string; force?: boolean } = { jobId: request.params.jobId, @@ -326,7 +325,7 @@ export function jobRoutes({ router, getLicenseCheckResults }: RouteInitializatio body: schema.any(), }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const results = await context.ml!.mlClient.callAsCurrentUser('ml.validateDetector', { body: request.body, @@ -359,7 +358,7 @@ export function jobRoutes({ router, getLicenseCheckResults }: RouteInitializatio body: schema.object({ duration: schema.any() }), }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const jobId = request.params.jobId; const duration = request.body.duration; @@ -407,7 +406,7 @@ export function jobRoutes({ router, getLicenseCheckResults }: RouteInitializatio }), }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const results = await context.ml!.mlClient.callAsCurrentUser('ml.records', { jobId: request.params.jobId, @@ -456,7 +455,7 @@ export function jobRoutes({ router, getLicenseCheckResults }: RouteInitializatio }), }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const results = await context.ml!.mlClient.callAsCurrentUser('ml.buckets', { jobId: request.params.jobId, @@ -499,7 +498,7 @@ export function jobRoutes({ router, getLicenseCheckResults }: RouteInitializatio }), }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const results = await context.ml!.mlClient.callAsCurrentUser('ml.overallBuckets', { jobId: request.params.jobId, @@ -537,7 +536,7 @@ export function jobRoutes({ router, getLicenseCheckResults }: RouteInitializatio }), }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const options = { jobId: request.params.jobId, diff --git a/x-pack/plugins/ml/server/routes/calendars.ts b/x-pack/plugins/ml/server/routes/calendars.ts index ae494d3578890..5d1161e928d11 100644 --- a/x-pack/plugins/ml/server/routes/calendars.ts +++ b/x-pack/plugins/ml/server/routes/calendars.ts @@ -6,7 +6,6 @@ import { RequestHandlerContext } from 'src/core/server'; import { schema } from '@kbn/config-schema'; -import { licensePreRoutingFactory } from './license_check_pre_routing_factory'; import { wrapError } from '../client/error_wrapper'; import { RouteInitialization } from '../types'; import { calendarSchema } from './schemas/calendars_schema'; @@ -42,13 +41,13 @@ function getCalendarsByIds(context: RequestHandlerContext, calendarIds: string) return cal.getCalendarsByIds(calendarIds); } -export function calendars({ router, getLicenseCheckResults }: RouteInitialization) { +export function calendars({ router, mlLicense }: RouteInitialization) { router.get( { path: '/api/ml/calendars', validate: false, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const resp = await getAllCalendars(context); @@ -68,7 +67,7 @@ export function calendars({ router, getLicenseCheckResults }: RouteInitializatio params: schema.object({ calendarIds: schema.string() }), }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { let returnValue; try { const calendarIds = request.params.calendarIds.split(','); @@ -95,7 +94,7 @@ export function calendars({ router, getLicenseCheckResults }: RouteInitializatio body: schema.object({ ...calendarSchema }), }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const body = request.body; const resp = await newCalendar(context, body); @@ -117,7 +116,7 @@ export function calendars({ router, getLicenseCheckResults }: RouteInitializatio body: schema.object({ ...calendarSchema }), }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const { calendarId } = request.params; const body = request.body; @@ -139,7 +138,7 @@ export function calendars({ router, getLicenseCheckResults }: RouteInitializatio params: schema.object({ calendarId: schema.string() }), }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const { calendarId } = request.params; const resp = await deleteCalendar(context, calendarId); diff --git a/x-pack/plugins/ml/server/routes/data_frame_analytics.ts b/x-pack/plugins/ml/server/routes/data_frame_analytics.ts index 0a93320c05eb5..7ed1aa02b24ab 100644 --- a/x-pack/plugins/ml/server/routes/data_frame_analytics.ts +++ b/x-pack/plugins/ml/server/routes/data_frame_analytics.ts @@ -7,7 +7,6 @@ import { schema } from '@kbn/config-schema'; import { wrapError } from '../client/error_wrapper'; import { analyticsAuditMessagesProvider } from '../models/data_frame_analytics/analytics_audit_messages'; -import { licensePreRoutingFactory } from './license_check_pre_routing_factory'; import { RouteInitialization } from '../types'; import { dataAnalyticsJobConfigSchema, @@ -18,7 +17,7 @@ import { /** * Routes for the data frame analytics */ -export function dataFrameAnalyticsRoutes({ router, getLicenseCheckResults }: RouteInitialization) { +export function dataFrameAnalyticsRoutes({ router, mlLicense }: RouteInitialization) { /** * @apiGroup DataFrameAnalytics * @@ -36,7 +35,7 @@ export function dataFrameAnalyticsRoutes({ router, getLicenseCheckResults }: Rou params: schema.object({ analyticsId: schema.maybe(schema.string()) }), }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const results = await context.ml!.mlClient.callAsCurrentUser('ml.getDataFrameAnalytics'); return response.ok({ @@ -64,7 +63,7 @@ export function dataFrameAnalyticsRoutes({ router, getLicenseCheckResults }: Rou params: schema.object({ analyticsId: schema.string() }), }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const { analyticsId } = request.params; const results = await context.ml!.mlClient.callAsCurrentUser('ml.getDataFrameAnalytics', { @@ -91,7 +90,7 @@ export function dataFrameAnalyticsRoutes({ router, getLicenseCheckResults }: Rou path: '/api/ml/data_frame/analytics/_stats', validate: false, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const results = await context.ml!.mlClient.callAsCurrentUser( 'ml.getDataFrameAnalyticsStats' @@ -121,7 +120,7 @@ export function dataFrameAnalyticsRoutes({ router, getLicenseCheckResults }: Rou params: schema.object({ analyticsId: schema.string() }), }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const { analyticsId } = request.params; const results = await context.ml!.mlClient.callAsCurrentUser( @@ -159,7 +158,7 @@ export function dataFrameAnalyticsRoutes({ router, getLicenseCheckResults }: Rou body: schema.object(dataAnalyticsJobConfigSchema), }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const { analyticsId } = request.params; const results = await context.ml!.mlClient.callAsCurrentUser( @@ -192,7 +191,7 @@ export function dataFrameAnalyticsRoutes({ router, getLicenseCheckResults }: Rou body: schema.object({ ...dataAnalyticsEvaluateSchema }), }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const results = await context.ml!.mlClient.callAsCurrentUser( 'ml.evaluateDataFrameAnalytics', @@ -232,7 +231,7 @@ export function dataFrameAnalyticsRoutes({ router, getLicenseCheckResults }: Rou body: schema.object({ ...dataAnalyticsExplainSchema }), }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const results = await context.ml!.mlClient.callAsCurrentUser( 'ml.explainDataFrameAnalytics', @@ -267,7 +266,7 @@ export function dataFrameAnalyticsRoutes({ router, getLicenseCheckResults }: Rou }), }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const { analyticsId } = request.params; const results = await context.ml!.mlClient.callAsCurrentUser( @@ -303,7 +302,7 @@ export function dataFrameAnalyticsRoutes({ router, getLicenseCheckResults }: Rou }), }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const { analyticsId } = request.params; const results = await context.ml!.mlClient.callAsCurrentUser('ml.startDataFrameAnalytics', { @@ -337,7 +336,7 @@ export function dataFrameAnalyticsRoutes({ router, getLicenseCheckResults }: Rou }), }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const options: { analyticsId: string; force?: boolean | undefined } = { analyticsId: request.params.analyticsId, @@ -377,7 +376,7 @@ export function dataFrameAnalyticsRoutes({ router, getLicenseCheckResults }: Rou params: schema.object({ analyticsId: schema.string() }), }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const { analyticsId } = request.params; const { getAnalyticsAuditMessages } = analyticsAuditMessagesProvider( diff --git a/x-pack/plugins/ml/server/routes/data_visualizer.ts b/x-pack/plugins/ml/server/routes/data_visualizer.ts index e4d068784def1..b37c80b815e1a 100644 --- a/x-pack/plugins/ml/server/routes/data_visualizer.ts +++ b/x-pack/plugins/ml/server/routes/data_visualizer.ts @@ -12,7 +12,6 @@ import { dataVisualizerFieldStatsSchema, dataVisualizerOverallStatsSchema, } from './schemas/data_visualizer_schema'; -import { licensePreRoutingFactory } from './license_check_pre_routing_factory'; import { RouteInitialization } from '../types'; function getOverallStats( @@ -68,7 +67,7 @@ function getStatsForFields( /** * Routes for the index data visualizer. */ -export function dataVisualizerRoutes({ router, getLicenseCheckResults }: RouteInitialization) { +export function dataVisualizerRoutes({ router, mlLicense }: RouteInitialization) { /** * @apiGroup DataVisualizer * @@ -83,7 +82,7 @@ export function dataVisualizerRoutes({ router, getLicenseCheckResults }: RouteIn path: '/api/ml/data_visualizer/get_field_stats/{indexPatternTitle}', validate: dataVisualizerFieldStatsSchema, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.basicLicenseAPIGuard(async (context, request, response) => { try { const { params: { indexPatternTitle }, @@ -135,7 +134,7 @@ export function dataVisualizerRoutes({ router, getLicenseCheckResults }: RouteIn path: '/api/ml/data_visualizer/get_overall_stats/{indexPatternTitle}', validate: dataVisualizerOverallStatsSchema, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.basicLicenseAPIGuard(async (context, request, response) => { try { const { params: { indexPatternTitle }, diff --git a/x-pack/plugins/ml/server/routes/datafeeds.ts b/x-pack/plugins/ml/server/routes/datafeeds.ts index e3bce4c1328e4..c1ee839340996 100644 --- a/x-pack/plugins/ml/server/routes/datafeeds.ts +++ b/x-pack/plugins/ml/server/routes/datafeeds.ts @@ -5,7 +5,6 @@ */ import { schema } from '@kbn/config-schema'; -import { licensePreRoutingFactory } from './license_check_pre_routing_factory'; import { wrapError } from '../client/error_wrapper'; import { RouteInitialization } from '../types'; import { startDatafeedSchema, datafeedConfigSchema } from './schemas/datafeeds_schema'; @@ -13,7 +12,7 @@ import { startDatafeedSchema, datafeedConfigSchema } from './schemas/datafeeds_s /** * Routes for datafeed service */ -export function dataFeedRoutes({ router, getLicenseCheckResults }: RouteInitialization) { +export function dataFeedRoutes({ router, mlLicense }: RouteInitialization) { /** * @apiGroup DatafeedService * @@ -26,7 +25,7 @@ export function dataFeedRoutes({ router, getLicenseCheckResults }: RouteInitiali path: '/api/ml/datafeeds', validate: false, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const resp = await context.ml!.mlClient.callAsCurrentUser('ml.datafeeds'); @@ -53,7 +52,7 @@ export function dataFeedRoutes({ router, getLicenseCheckResults }: RouteInitiali params: schema.object({ datafeedId: schema.string() }), }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const datafeedId = request.params.datafeedId; const resp = await context.ml!.mlClient.callAsCurrentUser('ml.datafeeds', { datafeedId }); @@ -79,7 +78,7 @@ export function dataFeedRoutes({ router, getLicenseCheckResults }: RouteInitiali path: '/api/ml/datafeeds/_stats', validate: false, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const resp = await context.ml!.mlClient.callAsCurrentUser('ml.datafeedStats'); @@ -106,7 +105,7 @@ export function dataFeedRoutes({ router, getLicenseCheckResults }: RouteInitiali params: schema.object({ datafeedId: schema.string() }), }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const datafeedId = request.params.datafeedId; const resp = await context.ml!.mlClient.callAsCurrentUser('ml.datafeedStats', { @@ -137,7 +136,7 @@ export function dataFeedRoutes({ router, getLicenseCheckResults }: RouteInitiali body: datafeedConfigSchema, }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const datafeedId = request.params.datafeedId; const resp = await context.ml!.mlClient.callAsCurrentUser('ml.addDatafeed', { @@ -169,7 +168,7 @@ export function dataFeedRoutes({ router, getLicenseCheckResults }: RouteInitiali body: datafeedConfigSchema, }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const datafeedId = request.params.datafeedId; const resp = await context.ml!.mlClient.callAsCurrentUser('ml.updateDatafeed', { @@ -201,7 +200,7 @@ export function dataFeedRoutes({ router, getLicenseCheckResults }: RouteInitiali query: schema.maybe(schema.object({ force: schema.maybe(schema.any()) })), }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const options: { datafeedId: string; force?: boolean } = { datafeedId: request.params.jobId, @@ -237,7 +236,7 @@ export function dataFeedRoutes({ router, getLicenseCheckResults }: RouteInitiali body: startDatafeedSchema, }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const datafeedId = request.params.datafeedId; const { start, end } = request.body; @@ -271,7 +270,7 @@ export function dataFeedRoutes({ router, getLicenseCheckResults }: RouteInitiali params: schema.object({ datafeedId: schema.string() }), }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const datafeedId = request.params.datafeedId; @@ -302,7 +301,7 @@ export function dataFeedRoutes({ router, getLicenseCheckResults }: RouteInitiali params: schema.object({ datafeedId: schema.string() }), }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const datafeedId = request.params.datafeedId; const resp = await context.ml!.mlClient.callAsCurrentUser('ml.datafeedPreview', { diff --git a/x-pack/plugins/ml/server/routes/fields_service.ts b/x-pack/plugins/ml/server/routes/fields_service.ts index bc092190c2c62..f4d4e5759a105 100644 --- a/x-pack/plugins/ml/server/routes/fields_service.ts +++ b/x-pack/plugins/ml/server/routes/fields_service.ts @@ -5,7 +5,6 @@ */ import { RequestHandlerContext } from 'src/core/server'; -import { licensePreRoutingFactory } from './license_check_pre_routing_factory'; import { wrapError } from '../client/error_wrapper'; import { RouteInitialization } from '../types'; import { @@ -29,7 +28,7 @@ function getTimeFieldRange(context: RequestHandlerContext, payload: any) { /** * Routes for fields service */ -export function fieldsService({ router, getLicenseCheckResults }: RouteInitialization) { +export function fieldsService({ router, mlLicense }: RouteInitialization) { /** * @apiGroup FieldsService * @@ -44,7 +43,8 @@ export function fieldsService({ router, getLicenseCheckResults }: RouteInitializ body: getCardinalityOfFieldsSchema, }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const resp = await getCardinalityOfFields(context, request.body); @@ -71,7 +71,7 @@ export function fieldsService({ router, getLicenseCheckResults }: RouteInitializ body: getTimeFieldRangeSchema, }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.basicLicenseAPIGuard(async (context, request, response) => { try { const resp = await getTimeFieldRange(context, request.body); diff --git a/x-pack/plugins/ml/server/routes/file_data_visualizer.ts b/x-pack/plugins/ml/server/routes/file_data_visualizer.ts index 1d724a8843350..69ec79704deee 100644 --- a/x-pack/plugins/ml/server/routes/file_data_visualizer.ts +++ b/x-pack/plugins/ml/server/routes/file_data_visualizer.ts @@ -18,7 +18,6 @@ import { Mappings, } from '../models/file_data_visualizer'; -import { licensePreRoutingFactory } from './license_check_pre_routing_factory'; import { RouteInitialization } from '../types'; import { incrementFileDataVisualizerIndexCreationCount } from '../lib/ml_telemetry'; @@ -43,7 +42,7 @@ function importData( /** * Routes for the file data visualizer. */ -export function fileDataVisualizerRoutes({ router, getLicenseCheckResults }: RouteInitialization) { +export function fileDataVisualizerRoutes({ router, mlLicense }: RouteInitialization) { /** * @apiGroup FileDataVisualizer * @@ -82,7 +81,7 @@ export function fileDataVisualizerRoutes({ router, getLicenseCheckResults }: Rou }, }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.basicLicenseAPIGuard(async (context, request, response) => { try { const result = await analyzeFiles(context, request.body, request.query); return response.ok({ body: result }); @@ -124,7 +123,7 @@ export function fileDataVisualizerRoutes({ router, getLicenseCheckResults }: Rou }, }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.basicLicenseAPIGuard(async (context, request, response) => { try { const { id } = request.query; const { index, data, settings, mappings, ingestPipeline } = request.body; diff --git a/x-pack/plugins/ml/server/routes/filters.ts b/x-pack/plugins/ml/server/routes/filters.ts index d5530668b2606..1f8891c247c67 100644 --- a/x-pack/plugins/ml/server/routes/filters.ts +++ b/x-pack/plugins/ml/server/routes/filters.ts @@ -6,7 +6,6 @@ import { RequestHandlerContext } from 'src/core/server'; import { schema } from '@kbn/config-schema'; -import { licensePreRoutingFactory } from './license_check_pre_routing_factory'; import { wrapError } from '../client/error_wrapper'; import { RouteInitialization } from '../types'; import { createFilterSchema, updateFilterSchema } from './schemas/filters_schema'; @@ -44,7 +43,7 @@ function deleteFilter(context: RequestHandlerContext, filterId: string) { return mgr.deleteFilter(filterId); } -export function filtersRoutes({ router, getLicenseCheckResults }: RouteInitialization) { +export function filtersRoutes({ router, mlLicense }: RouteInitialization) { /** * @apiGroup Filters * @@ -60,7 +59,7 @@ export function filtersRoutes({ router, getLicenseCheckResults }: RouteInitializ path: '/api/ml/filters', validate: false, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const resp = await getAllFilters(context); @@ -90,7 +89,7 @@ export function filtersRoutes({ router, getLicenseCheckResults }: RouteInitializ params: schema.object({ filterId: schema.string() }), }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const resp = await getFilter(context, request.params.filterId); return response.ok({ @@ -119,7 +118,7 @@ export function filtersRoutes({ router, getLicenseCheckResults }: RouteInitializ body: schema.object(createFilterSchema), }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const body = request.body; const resp = await newFilter(context, body); @@ -151,7 +150,7 @@ export function filtersRoutes({ router, getLicenseCheckResults }: RouteInitializ body: schema.object(updateFilterSchema), }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const { filterId } = request.params; const body = request.body; @@ -182,7 +181,7 @@ export function filtersRoutes({ router, getLicenseCheckResults }: RouteInitializ params: schema.object({ filterId: schema.string() }), }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const { filterId } = request.params; const resp = await deleteFilter(context, filterId); @@ -212,7 +211,7 @@ export function filtersRoutes({ router, getLicenseCheckResults }: RouteInitializ path: '/api/ml/filters/_stats', validate: false, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const resp = await getAllFilterStats(context); diff --git a/x-pack/plugins/ml/server/routes/indices.ts b/x-pack/plugins/ml/server/routes/indices.ts index e01a7a0cbad28..fe66cc8b01396 100644 --- a/x-pack/plugins/ml/server/routes/indices.ts +++ b/x-pack/plugins/ml/server/routes/indices.ts @@ -6,13 +6,12 @@ import { schema } from '@kbn/config-schema'; import { wrapError } from '../client/error_wrapper'; -import { licensePreRoutingFactory } from './license_check_pre_routing_factory'; import { RouteInitialization } from '../types'; /** * Indices routes. */ -export function indicesRoutes({ router, getLicenseCheckResults }: RouteInitialization) { +export function indicesRoutes({ router, mlLicense }: RouteInitialization) { /** * @apiGroup Indices * @@ -30,7 +29,7 @@ export function indicesRoutes({ router, getLicenseCheckResults }: RouteInitializ }), }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const { body: { index, fields: requestFields }, diff --git a/x-pack/plugins/ml/server/routes/job_audit_messages.ts b/x-pack/plugins/ml/server/routes/job_audit_messages.ts index 38df28e17ec0d..5c6d8023cc172 100644 --- a/x-pack/plugins/ml/server/routes/job_audit_messages.ts +++ b/x-pack/plugins/ml/server/routes/job_audit_messages.ts @@ -5,7 +5,6 @@ */ import { schema } from '@kbn/config-schema'; -import { licensePreRoutingFactory } from './license_check_pre_routing_factory'; import { wrapError } from '../client/error_wrapper'; import { RouteInitialization } from '../types'; import { jobAuditMessagesProvider } from '../models/job_audit_messages'; @@ -13,7 +12,7 @@ import { jobAuditMessagesProvider } from '../models/job_audit_messages'; /** * Routes for job audit message routes */ -export function jobAuditMessagesRoutes({ router, getLicenseCheckResults }: RouteInitialization) { +export function jobAuditMessagesRoutes({ router, mlLicense }: RouteInitialization) { /** * @apiGroup JobAuditMessages * @@ -29,7 +28,7 @@ export function jobAuditMessagesRoutes({ router, getLicenseCheckResults }: Route query: schema.maybe(schema.object({ from: schema.maybe(schema.any()) })), }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const { getJobAuditMessages } = jobAuditMessagesProvider( context.ml!.mlClient.callAsCurrentUser @@ -62,7 +61,7 @@ export function jobAuditMessagesRoutes({ router, getLicenseCheckResults }: Route query: schema.maybe(schema.object({ from: schema.maybe(schema.any()) })), }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const { getJobAuditMessages } = jobAuditMessagesProvider( context.ml!.mlClient.callAsCurrentUser diff --git a/x-pack/plugins/ml/server/routes/job_service.ts b/x-pack/plugins/ml/server/routes/job_service.ts index e15888088d3a1..9ad2f80a1e66b 100644 --- a/x-pack/plugins/ml/server/routes/job_service.ts +++ b/x-pack/plugins/ml/server/routes/job_service.ts @@ -7,7 +7,6 @@ import Boom from 'boom'; import { schema } from '@kbn/config-schema'; import { IScopedClusterClient } from 'src/core/server'; -import { licensePreRoutingFactory } from './license_check_pre_routing_factory'; import { wrapError } from '../client/error_wrapper'; import { RouteInitialization } from '../types'; import { @@ -28,12 +27,11 @@ import { categorizationExamplesProvider } from '../models/job_service/new_job'; /** * Routes for job service */ -export function jobServiceRoutes({ router, getLicenseCheckResults }: RouteInitialization) { +export function jobServiceRoutes({ router, mlLicense }: RouteInitialization) { async function hasPermissionToCreateJobs( callAsCurrentUser: IScopedClusterClient['callAsCurrentUser'] ) { - const { isSecurityDisabled } = getLicenseCheckResults(); - if (isSecurityDisabled === true) { + if (mlLicense.isSecurityEnabled() === false) { return true; } @@ -63,7 +61,7 @@ export function jobServiceRoutes({ router, getLicenseCheckResults }: RouteInitia body: schema.object(forceStartDatafeedSchema), }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const { forceStartDatafeeds } = jobServiceProvider(context.ml!.mlClient.callAsCurrentUser); const { datafeedIds, start, end } = request.body; @@ -92,7 +90,7 @@ export function jobServiceRoutes({ router, getLicenseCheckResults }: RouteInitia body: schema.object(datafeedIdsSchema), }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const { stopDatafeeds } = jobServiceProvider(context.ml!.mlClient.callAsCurrentUser); const { datafeedIds } = request.body; @@ -121,7 +119,7 @@ export function jobServiceRoutes({ router, getLicenseCheckResults }: RouteInitia body: schema.object(jobIdsSchema), }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const { deleteJobs } = jobServiceProvider(context.ml!.mlClient.callAsCurrentUser); const { jobIds } = request.body; @@ -150,7 +148,7 @@ export function jobServiceRoutes({ router, getLicenseCheckResults }: RouteInitia body: schema.object(jobIdsSchema), }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const { closeJobs } = jobServiceProvider(context.ml!.mlClient.callAsCurrentUser); const { jobIds } = request.body; @@ -179,7 +177,7 @@ export function jobServiceRoutes({ router, getLicenseCheckResults }: RouteInitia body: schema.object(jobIdsSchema), }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const { jobsSummary } = jobServiceProvider(context.ml!.mlClient.callAsCurrentUser); const { jobIds } = request.body; @@ -208,7 +206,7 @@ export function jobServiceRoutes({ router, getLicenseCheckResults }: RouteInitia body: schema.object(jobsWithTimerangeSchema), }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const { jobsWithTimerange } = jobServiceProvider(context.ml!.mlClient.callAsCurrentUser); const { dateFormatTz } = request.body; @@ -237,7 +235,7 @@ export function jobServiceRoutes({ router, getLicenseCheckResults }: RouteInitia body: schema.object(jobIdsSchema), }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const { createFullJobsList } = jobServiceProvider(context.ml!.mlClient.callAsCurrentUser); const { jobIds } = request.body; @@ -264,7 +262,7 @@ export function jobServiceRoutes({ router, getLicenseCheckResults }: RouteInitia path: '/api/ml/jobs/groups', validate: false, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const { getAllGroups } = jobServiceProvider(context.ml!.mlClient.callAsCurrentUser); const resp = await getAllGroups(); @@ -292,7 +290,7 @@ export function jobServiceRoutes({ router, getLicenseCheckResults }: RouteInitia body: schema.object(updateGroupsSchema), }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const { updateGroups } = jobServiceProvider(context.ml!.mlClient.callAsCurrentUser); const { jobs } = request.body; @@ -319,7 +317,7 @@ export function jobServiceRoutes({ router, getLicenseCheckResults }: RouteInitia path: '/api/ml/jobs/deleting_jobs_tasks', validate: false, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const { deletingJobTasks } = jobServiceProvider(context.ml!.mlClient.callAsCurrentUser); const resp = await deletingJobTasks(); @@ -347,7 +345,7 @@ export function jobServiceRoutes({ router, getLicenseCheckResults }: RouteInitia body: schema.object(jobIdsSchema), }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const { jobsExist } = jobServiceProvider(context.ml!.mlClient.callAsCurrentUser); const { jobIds } = request.body; @@ -377,7 +375,7 @@ export function jobServiceRoutes({ router, getLicenseCheckResults }: RouteInitia query: schema.maybe(schema.object({ rollup: schema.maybe(schema.string()) })), }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const { indexPattern } = request.params; const isRollup = request.query.rollup === 'true'; @@ -408,7 +406,7 @@ export function jobServiceRoutes({ router, getLicenseCheckResults }: RouteInitia body: schema.object(chartSchema), }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const { indexPatternTitle, @@ -461,7 +459,7 @@ export function jobServiceRoutes({ router, getLicenseCheckResults }: RouteInitia body: schema.object(chartSchema), }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const { indexPatternTitle, @@ -509,7 +507,7 @@ export function jobServiceRoutes({ router, getLicenseCheckResults }: RouteInitia path: '/api/ml/jobs/all_jobs_and_group_ids', validate: false, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const { getAllJobAndGroupIds } = jobServiceProvider(context.ml!.mlClient.callAsCurrentUser); const resp = await getAllJobAndGroupIds(); @@ -537,7 +535,7 @@ export function jobServiceRoutes({ router, getLicenseCheckResults }: RouteInitia body: schema.object(lookBackProgressSchema), }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const { getLookBackProgress } = jobServiceProvider(context.ml!.mlClient.callAsCurrentUser); const { jobId, start, end } = request.body; @@ -566,7 +564,7 @@ export function jobServiceRoutes({ router, getLicenseCheckResults }: RouteInitia body: schema.object(categorizationFieldExamplesSchema), }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { // 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 @@ -625,7 +623,7 @@ export function jobServiceRoutes({ router, getLicenseCheckResults }: RouteInitia body: schema.object(topCategoriesSchema), }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const { topCategories } = jobServiceProvider(context.ml!.mlClient.callAsCurrentUser); const { jobId, count } = request.body; diff --git a/x-pack/plugins/ml/server/routes/job_validation.ts b/x-pack/plugins/ml/server/routes/job_validation.ts index ae2e6885ba0f3..7d5a7a2285977 100644 --- a/x-pack/plugins/ml/server/routes/job_validation.ts +++ b/x-pack/plugins/ml/server/routes/job_validation.ts @@ -7,7 +7,6 @@ import Boom from 'boom'; import { RequestHandlerContext } from 'src/core/server'; import { schema, TypeOf } from '@kbn/config-schema'; -import { licensePreRoutingFactory } from './license_check_pre_routing_factory'; import { wrapError } from '../client/error_wrapper'; import { RouteInitialization } from '../types'; import { @@ -25,10 +24,7 @@ type CalculateModelMemoryLimitPayload = TypeOf; /** * Routes for job validation */ -export function jobValidationRoutes( - { getLicenseCheckResults, router }: RouteInitialization, - version: string -) { +export function jobValidationRoutes({ router, mlLicense }: RouteInitialization, version: string) { function calculateModelMemoryLimit( context: RequestHandlerContext, payload: CalculateModelMemoryLimitPayload @@ -70,13 +66,13 @@ export function jobValidationRoutes( body: estimateBucketSpanSchema, }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { let errorResp; const resp = await estimateBucketSpanFactory( context.ml!.mlClient.callAsCurrentUser, context.core.elasticsearch.adminClient.callAsInternalUser, - getLicenseCheckResults().isSecurityDisabled + mlLicense.isSecurityEnabled() === false )(request.body) // this catch gets triggered when the estimation code runs without error // but isn't able to come up with a bucket span estimation. @@ -117,7 +113,7 @@ export function jobValidationRoutes( body: modelMemoryLimitSchema, }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const resp = await calculateModelMemoryLimit(context, request.body); @@ -144,7 +140,7 @@ export function jobValidationRoutes( body: schema.object(validateCardinalitySchema), }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const resp = await validateCardinality( context.ml!.mlClient.callAsCurrentUser, @@ -174,7 +170,7 @@ export function jobValidationRoutes( body: validateJobSchema, }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { // version corresponds to the version used in documentation links. const resp = await validateJob( @@ -182,7 +178,7 @@ export function jobValidationRoutes( request.body, version, context.core.elasticsearch.adminClient.callAsInternalUser, - getLicenseCheckResults().isSecurityDisabled + mlLicense.isSecurityEnabled() === false ); return response.ok({ diff --git a/x-pack/plugins/ml/server/routes/license_check_pre_routing_factory.ts b/x-pack/plugins/ml/server/routes/license_check_pre_routing_factory.ts deleted file mode 100644 index a371af1abf2d1..0000000000000 --- a/x-pack/plugins/ml/server/routes/license_check_pre_routing_factory.ts +++ /dev/null @@ -1,33 +0,0 @@ -/* - * 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 { - KibanaRequest, - KibanaResponseFactory, - RequestHandler, - RequestHandlerContext, -} from 'src/core/server'; -import { LicenseCheckResult } from '../types'; - -export const licensePreRoutingFactory = ( - getLicenseCheckResults: () => LicenseCheckResult, - handler: RequestHandler -): RequestHandler => { - // License checking and enable/disable logic - return function licensePreRouting( - ctx: RequestHandlerContext, - request: KibanaRequest, - response: KibanaResponseFactory - ) { - const licenseCheckResults = getLicenseCheckResults(); - - if (!licenseCheckResults.isAvailable) { - return response.forbidden(); - } - - return handler(ctx, request, response); - }; -}; diff --git a/x-pack/plugins/ml/server/routes/modules.ts b/x-pack/plugins/ml/server/routes/modules.ts index c9b005d4e43f9..a51718acb7425 100644 --- a/x-pack/plugins/ml/server/routes/modules.ts +++ b/x-pack/plugins/ml/server/routes/modules.ts @@ -9,7 +9,6 @@ import { RequestHandlerContext } from 'kibana/server'; import { DatafeedOverride, JobOverride } from '../../../../legacy/plugins/ml/common/types/modules'; import { wrapError } from '../client/error_wrapper'; import { DataRecognizer } from '../models/data_recognizer'; -import { licensePreRoutingFactory } from './license_check_pre_routing_factory'; import { getModuleIdParamSchema, setupModuleBodySchema } from './schemas/modules'; import { RouteInitialization } from '../types'; @@ -65,7 +64,7 @@ function dataRecognizerJobsExist(context: RequestHandlerContext, moduleId: strin /** * Recognizer routes. */ -export function dataRecognizer({ router, getLicenseCheckResults }: RouteInitialization) { +export function dataRecognizer({ router, mlLicense }: RouteInitialization) { /** * @apiGroup DataRecognizer * @@ -84,7 +83,7 @@ export function dataRecognizer({ router, getLicenseCheckResults }: RouteInitiali }), }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const { indexPatternTitle } = request.params; const results = await recognize(context, indexPatternTitle); @@ -114,7 +113,7 @@ export function dataRecognizer({ router, getLicenseCheckResults }: RouteInitiali }), }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { let { moduleId } = request.params; if (moduleId === '') { @@ -150,7 +149,7 @@ export function dataRecognizer({ router, getLicenseCheckResults }: RouteInitiali body: setupModuleBodySchema, }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const { moduleId } = request.params; @@ -207,7 +206,7 @@ export function dataRecognizer({ router, getLicenseCheckResults }: RouteInitiali }), }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const { moduleId } = request.params; const result = await dataRecognizerJobsExist(context, moduleId); diff --git a/x-pack/plugins/ml/server/routes/notification_settings.ts b/x-pack/plugins/ml/server/routes/notification_settings.ts index b68d2441333f9..59458b1e486db 100644 --- a/x-pack/plugins/ml/server/routes/notification_settings.ts +++ b/x-pack/plugins/ml/server/routes/notification_settings.ts @@ -4,14 +4,13 @@ * you may not use this file except in compliance with the Elastic License. */ -import { licensePreRoutingFactory } from './license_check_pre_routing_factory'; import { wrapError } from '../client/error_wrapper'; import { RouteInitialization } from '../types'; /** * Routes for notification settings */ -export function notificationRoutes({ router, getLicenseCheckResults }: RouteInitialization) { +export function notificationRoutes({ router, mlLicense }: RouteInitialization) { /** * @apiGroup NotificationSettings * @@ -24,7 +23,7 @@ export function notificationRoutes({ router, getLicenseCheckResults }: RouteInit path: '/api/ml/notification_settings', validate: false, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const params = { includeDefaults: true, diff --git a/x-pack/plugins/ml/server/routes/results_service.ts b/x-pack/plugins/ml/server/routes/results_service.ts index 77c998acc9f27..7a12e5196b9a5 100644 --- a/x-pack/plugins/ml/server/routes/results_service.ts +++ b/x-pack/plugins/ml/server/routes/results_service.ts @@ -6,7 +6,6 @@ import { RequestHandlerContext } from 'src/core/server'; import { schema } from '@kbn/config-schema'; -import { licensePreRoutingFactory } from './license_check_pre_routing_factory'; import { wrapError } from '../client/error_wrapper'; import { RouteInitialization } from '../types'; import { @@ -74,7 +73,7 @@ function getPartitionFieldsValues(context: RequestHandlerContext, payload: any) /** * Routes for results service */ -export function resultsServiceRoutes({ router, getLicenseCheckResults }: RouteInitialization) { +export function resultsServiceRoutes({ router, mlLicense }: RouteInitialization) { /** * @apiGroup ResultsService * @@ -89,7 +88,7 @@ export function resultsServiceRoutes({ router, getLicenseCheckResults }: RouteIn body: schema.object(anomaliesTableDataSchema), }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const resp = await getAnomaliesTableData(context, request.body); @@ -116,7 +115,7 @@ export function resultsServiceRoutes({ router, getLicenseCheckResults }: RouteIn body: schema.object(categoryDefinitionSchema), }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const resp = await getCategoryDefinition(context, request.body); @@ -143,7 +142,7 @@ export function resultsServiceRoutes({ router, getLicenseCheckResults }: RouteIn body: schema.object(maxAnomalyScoreSchema), }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const resp = await getMaxAnomalyScore(context, request.body); @@ -170,7 +169,7 @@ export function resultsServiceRoutes({ router, getLicenseCheckResults }: RouteIn body: schema.object(categoryExamplesSchema), }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const resp = await getCategoryExamples(context, request.body); @@ -197,7 +196,7 @@ export function resultsServiceRoutes({ router, getLicenseCheckResults }: RouteIn body: schema.object(partitionFieldValuesSchema), }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const resp = await getPartitionFieldsValues(context, request.body); diff --git a/x-pack/plugins/ml/server/routes/system.ts b/x-pack/plugins/ml/server/routes/system.ts index 36a9ea1447f58..a0d7d312c04d4 100644 --- a/x-pack/plugins/ml/server/routes/system.ts +++ b/x-pack/plugins/ml/server/routes/system.ts @@ -12,14 +12,13 @@ import { wrapError } from '../client/error_wrapper'; import { mlLog } from '../client/log'; import { privilegesProvider } from '../lib/check_privileges'; import { spacesUtilsProvider } from '../lib/spaces_utils'; -import { licensePreRoutingFactory } from './license_check_pre_routing_factory'; import { RouteInitialization, SystemRouteDeps } from '../types'; /** * System routes */ export function systemRoutes( - { getLicenseCheckResults, router }: RouteInitialization, + { router, mlLicense }: RouteInitialization, { spacesPlugin, cloud }: SystemRouteDeps ) { async function getNodeCount(context: RequestHandlerContext) { @@ -56,7 +55,7 @@ export function systemRoutes( body: schema.maybe(schema.any()), }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.basicLicenseAPIGuard(async (context, request, response) => { try { let upgradeInProgress = false; try { @@ -77,7 +76,7 @@ export function systemRoutes( } } - if (getLicenseCheckResults().isSecurityDisabled) { + if (mlLicense.isSecurityEnabled() === false) { // if xpack.security.enabled has been explicitly set to false // return that security is disabled and don't call the privilegeCheck endpoint return response.ok({ @@ -116,7 +115,7 @@ export function systemRoutes( }), }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.basicLicenseAPIGuard(async (context, request, response) => { try { const ignoreSpaces = request.query && request.query.ignoreSpaces === 'true'; // if spaces is disabled force isMlEnabledInSpace to be true @@ -127,7 +126,7 @@ export function systemRoutes( const { getPrivileges } = privilegesProvider( context.ml!.mlClient.callAsCurrentUser, - getLicenseCheckResults(), + mlLicense, isMlEnabledInSpace, ignoreSpaces ); @@ -152,11 +151,11 @@ export function systemRoutes( path: '/api/ml/ml_node_count', validate: false, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.basicLicenseAPIGuard(async (context, request, response) => { try { // check for basic license first for consistency with other // security disabled checks - if (getLicenseCheckResults().isSecurityDisabled) { + if (mlLicense.isSecurityEnabled() === false) { return response.ok({ body: await getNodeCount(context), }); @@ -203,7 +202,7 @@ export function systemRoutes( path: '/api/ml/info', validate: false, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.basicLicenseAPIGuard(async (context, request, response) => { try { const info = await context.ml!.mlClient.callAsCurrentUser('ml.info'); const cloudId = cloud && cloud.cloudId; @@ -231,7 +230,7 @@ export function systemRoutes( body: schema.maybe(schema.any()), }, }, - licensePreRoutingFactory(getLicenseCheckResults, async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { return response.ok({ body: await context.ml!.mlClient.callAsCurrentUser('search', request.body), diff --git a/x-pack/plugins/ml/server/types.ts b/x-pack/plugins/ml/server/types.ts index 550abadb3c06f..aeb4c505ec55e 100644 --- a/x-pack/plugins/ml/server/types.ts +++ b/x-pack/plugins/ml/server/types.ts @@ -12,6 +12,7 @@ import { SecurityPluginSetup } from '../../security/server'; import { PluginSetupContract as FeaturesPluginSetup } from '../../features/server'; import { LicensingPluginSetup } from '../../licensing/server'; import { SpacesPluginSetup } from '../../spaces/server'; +import { MlServerLicense } from './lib/license'; export interface LicenseCheckResult { isAvailable: boolean; @@ -39,5 +40,5 @@ export interface PluginsSetup { export interface RouteInitialization { router: IRouter; - getLicenseCheckResults: () => LicenseCheckResult; + mlLicense: MlServerLicense; } diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index dbab88da973a1..84651319775fd 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -7533,9 +7533,6 @@ "xpack.ml.calendarsList.table.idColumnName": "ID", "xpack.ml.calendarsList.table.jobsColumnName": "ジョブ", "xpack.ml.calendarsList.table.newButtonLabel": "新規", - "xpack.ml.checkLicense.licenseHasExpiredMessage": "{licenseTypeName} 機械学習ライセンスが期限切れになりました。", - "xpack.ml.checkLicense.licenseInformationNotAvailableThisTimeMessage": "現在ライセンス情報が利用できないため機械学習を使用できません。", - "xpack.ml.checkLicense.mlIsUnavailableMessage": "機械学習が利用できません", "xpack.ml.controls.checkboxShowCharts.showChartsCheckboxLabel": "チャートを表示", "xpack.ml.controls.selectInterval.autoLabel": "自動", "xpack.ml.controls.selectInterval.dayLabel": "1 日", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index afd12dba8ada7..a9dccd20fb916 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -7533,9 +7533,6 @@ "xpack.ml.calendarsList.table.idColumnName": "ID", "xpack.ml.calendarsList.table.jobsColumnName": "作业", "xpack.ml.calendarsList.table.newButtonLabel": "新建", - "xpack.ml.checkLicense.licenseHasExpiredMessage": "您的 {licenseTypeName} Machine Learning 许可证已过期。", - "xpack.ml.checkLicense.licenseInformationNotAvailableThisTimeMessage": "您不能使用 Machine Learning,因为许可证信息当前不可用。", - "xpack.ml.checkLicense.mlIsUnavailableMessage": "Machine Learning 不可用", "xpack.ml.controls.checkboxShowCharts.showChartsCheckboxLabel": "显示图表", "xpack.ml.controls.selectInterval.autoLabel": "自动", "xpack.ml.controls.selectInterval.dayLabel": "1 天",