[ML] Fixing licensing after server NP cutover (#58853)

* [ML] Fixing licensing after server NP cutover

* client side refactor

* management refactor

* moving management license check

* adding server side license class

* added common license class

* client sides using license class

* updating server api guards

* fix privileges tests

* updating translations

* fixing disabled tabs on basic license

* refactoring client side license checks

* setting license initialized flag

* fixing license check on index data viz

Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
This commit is contained in:
James Gowdy 2020-03-03 18:57:40 +00:00 committed by GitHub
parent 2dcd3cc4c6
commit fd5c6c16cd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
62 changed files with 538 additions and 717 deletions

View file

@ -0,0 +1,7 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
export { MlLicense, LicenseStatus, MINIMUM_FULL_LICENSE, MINIMUM_LICENSE } from './ml_license';

View file

@ -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<ILicense>,
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;
}
}

View file

@ -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<AppProps> = ({ 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<AppProps> = ({ coreStart, deps }) => {
http: coreStart.http,
security: deps.security,
});
const mlLicense = setLicenseCache(deps.licensing);
deps.onAppLeave(actions => {
mlLicense.unsubscribe();
clearCache();
return actions.default();
});

View file

@ -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', () => ({

View file

@ -81,13 +81,18 @@ export const MainTabs: FC<Props> = ({ tabId, disableLinks }) => {
return (
<EuiTabs display="condensed">
{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 ? (
<EuiTab key={`${id}-key`} className={'mlNavigationMenu__mainTab'} disabled={true}>
{tab.name}
</EuiTab>
) : (
<EuiLink
data-test-subj={testSubject + (id === selectedTabId ? ' selected' : '')}
href={`#/${defaultPathId}${fullGlobalStateString}`}
@ -98,7 +103,6 @@ export const MainTabs: FC<Props> = ({ tabId, disableLinks }) => {
className={'mlNavigationMenu__mainTab'}
onClick={() => onSelectedTabChanged(id)}
isSelected={id === selectedTabId}
disabled={tab.disabled}
>
{tab.name}
</EuiTab>

View file

@ -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';

View file

@ -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';

View file

@ -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';

View file

@ -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';

View file

@ -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);
});
});
});

View file

@ -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<void>} 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<void>} 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(<EuiCallOut iconType="iInCircle" color="warning" title={message} />)
);
}
}
}
// 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();
}

View file

@ -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(<EuiCallOut iconType="iInCircle" color="warning" title={message} />)
);
}
}

View file

@ -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';

View file

@ -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();
}

View file

@ -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,

View file

@ -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';

View file

@ -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';

View file

@ -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';

View file

@ -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<PageProps> = ({ location, deps }) => {
checkBasicLicense,
loadIndexPatterns: () => loadIndexPatterns(deps.indexPatterns),
checkFindFileStructurePrivilege,
getMlNodeCount,
});
return (
<PageLoader context={context}>

View file

@ -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';

View file

@ -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';

View file

@ -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';

View file

@ -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';

View file

@ -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';

View file

@ -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';

View file

@ -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';

View file

@ -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';

View file

@ -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,
}));

View file

@ -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,
}));

View file

@ -76,6 +76,7 @@ export function setDependencyCache(deps: Partial<DependencyCache>) {
cache.XSRF = deps.XSRF || null;
cache.application = deps.application || null;
cache.http = deps.http || null;
cache.security = deps.security || null;
}
export function getTimefilter() {

View file

@ -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(),
},

View file

@ -8,7 +8,7 @@ import { Plugin, CoreStart, CoreSetup } from 'src/core/public';
import { MlDependencies } from './application/app';
export class MlPlugin implements Plugin<Setup, Start> {
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<Setup, Start> {
data,
__LEGACY,
security,
licensing,
});
},
});

View file

@ -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);
});
});
});
});
});
});

View file

@ -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,
};
}

View file

@ -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();

View file

@ -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<boolean>,
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

View file

@ -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';

View file

@ -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<any, any, any>) {
return guard(() => this.isFullLicense(), handler);
}
public basicLicenseAPIGuard(handler: RequestHandler<any, any, any>) {
return guard(() => this.isMinimumLicense(), handler);
}
}
function guard(check: () => boolean, handler: RequestHandler<any, any, any>) {
return (
context: RequestHandlerContext,
request: KibanaRequest,
response: KibanaResponseFactory
) => {
if (check() === false) {
return response.forbidden();
}
return handler(context, request, response);
};
}

View file

@ -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';

View file

@ -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',
},
]);
}
}

View file

@ -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();
}
}

View file

@ -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

View file

@ -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,

View file

@ -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);

View file

@ -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(

View file

@ -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 },

View file

@ -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', {

View file

@ -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);

View file

@ -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;

View file

@ -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);

View file

@ -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 },

View file

@ -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

View file

@ -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;

View file

@ -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<typeof modelMemoryLimitSchema>;
/**
* 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({

View file

@ -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<any, any, any>
): RequestHandler<any, any, any> => {
// 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);
};
};

View file

@ -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);

View file

@ -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,

View file

@ -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);

View file

@ -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),

View file

@ -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;
}

View file

@ -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 日",

View file

@ -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 天",