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 000000000000..e901a9545897 --- /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 000000000000..8b631bf6ffb4 --- /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 3acb24ac6e17..4c956bfabecc 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 206b9e01bab8..b881bfe4f1fe 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 dce5e7ad52b0..695783883d02 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 e7ba57e25354..6be2d18e5974 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 0f56f78c708e..254788c52a7a 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 debadba19051..dddf64ce2cfd 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 84c07651d323..fbf42ef62265 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 9ce0ec04befb..000000000000 --- 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 4af753ddb4d1..be5b702742ba 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; +/** + * 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; +} - 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); +/** + * 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(); } + + return mlLicense.fullLicenseResolver(); } -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 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(); } + + return mlLicense.basicLicenseResolver(); } -// 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(); - }); -} - -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() - ); - } - } -} -// 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(); -} - +/** + * 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 000000000000..22cb3260d696 --- /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 000000000000..0b6866d52d07 --- /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 000000000000..13809e15135e --- /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 a05de8b0d088..16bb3ddfd1c9 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 6cc06231a08d..ec9695a2ce66 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 5fc1ea533e87..acaf3f3acd0c 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 e89834018f5e..d257a9c080c3 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 b4ccccd0776e..174b3e3b4b33 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 74ab916cb443..a3dbc9f97124 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 ae35d783517d..9411b415e4e4 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 b1e00158efb9..ccb99985cb70 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 c1bfaa2fe6c1..9d5c4e9c0b0a 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 7af2e49e3a69..bf039e3bd235 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 9c5c06b76247..6839ad833cb0 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 752b889490e5..7b8bd6c3c81a 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 10efb2dcc60c..10ccc0987fe5 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 8dc174040f9c..5f61ccf47e9d 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 677703bceeca..3ea8e0c39fbb 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 6d1dfa96ca03..c167d7e7c3d4 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 7dfcf6a99c21..0c6c0bd8dd29 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 1061bb1b6b62..c0369a74c070 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 942dbe372261..000000000000 --- 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 5bf3d590a191..000000000000 --- 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 0690aa53576a..4dd9100e1b67 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 a427780d1334..f26040385b9f 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 f2c070fd44b6..9c4271b65b00 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 000000000000..7602ab4919e8 --- /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 c922c9eb7c02..50553cfa7b88 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 2082538adfed..3fd99051a248 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 b5adf1fedec7..a3f573373843 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 bcc0238c366a..16483bf8b887 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 7bf2fb7bc690..5e1ca72a7200 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 ae494d357889..5d1161e928d1 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 0a93320c05eb..7ed1aa02b24a 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 e4d068784def..b37c80b815e1 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 e3bce4c1328e..c1ee83934099 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 bc092190c2c6..f4d4e5759a10 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 1d724a884335..69ec79704dee 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 d5530668b260..1f8891c247c6 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 e01a7a0cbad2..fe66cc8b0139 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 38df28e17ec0..5c6d8023cc17 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 e15888088d3a..9ad2f80a1e66 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 ae2e6885ba0f..7d5a7a228597 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 a371af1abf2d..000000000000 --- 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 c9b005d4e43f..a51718acb742 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 b68d2441333f..59458b1e486d 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 77c998acc9f2..7a12e5196b9a 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 36a9ea1447f5..a0d7d312c04d 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 550abadb3c06..aeb4c505ec55 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 43f2e1956adf..0e2a842db19c 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -7537,9 +7537,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 328afa513337..95bc32a9a1c5 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -7537,9 +7537,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 天",