[BeatsCM] error on issues dont disable (#25149)
* display error messages for failed checks vs disableing plugin * update text * change order of check * tweak security check * re-disable on invalid license, update text * update text * tweaks * tweak text
This commit is contained in:
parent
36de9e8325
commit
73ce55289b
|
@ -58,13 +58,20 @@ export class KibanaFrameworkAdapter implements FrameworkAdapter {
|
||||||
this.rootComponent = component;
|
this.rootComponent = component;
|
||||||
};
|
};
|
||||||
|
|
||||||
public hadValidLicense() {
|
public hasValidLicense() {
|
||||||
if (!this.xpackInfo) {
|
if (!this.xpackInfo) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return this.xpackInfo.get('features.beats_management.licenseValid', false);
|
return this.xpackInfo.get('features.beats_management.licenseValid', false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public licenseExpired() {
|
||||||
|
if (!this.xpackInfo) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return this.xpackInfo.get('features.beats_management.licenseExpired', false);
|
||||||
|
}
|
||||||
|
|
||||||
public securityEnabled() {
|
public securityEnabled() {
|
||||||
if (!this.xpackInfo) {
|
if (!this.xpackInfo) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -83,8 +90,9 @@ export class KibanaFrameworkAdapter implements FrameworkAdapter {
|
||||||
|
|
||||||
public registerManagementSection(pluginId: string, displayName: string, basePath: string) {
|
public registerManagementSection(pluginId: string, displayName: string, basePath: string) {
|
||||||
this.register(this.uiModule);
|
this.register(this.uiModule);
|
||||||
|
|
||||||
this.hookAngular(() => {
|
this.hookAngular(() => {
|
||||||
if (this.hadValidLicense() && this.securityEnabled()) {
|
if (this.hasValidLicense()) {
|
||||||
const registerSection = () =>
|
const registerSection = () =>
|
||||||
this.management.register(pluginId, {
|
this.management.register(pluginId, {
|
||||||
display: 'Beats', // TODO these need to be config options not hard coded in the adapter
|
display: 'Beats', // TODO these need to be config options not hard coded in the adapter
|
||||||
|
@ -92,7 +100,6 @@ export class KibanaFrameworkAdapter implements FrameworkAdapter {
|
||||||
order: 30,
|
order: 30,
|
||||||
});
|
});
|
||||||
const getSection = () => this.management.getSection(pluginId);
|
const getSection = () => this.management.getSection(pluginId);
|
||||||
|
|
||||||
const section = this.management.hasItem(pluginId) ? getSection() : registerSection();
|
const section = this.management.hasItem(pluginId) ? getSection() : registerSection();
|
||||||
|
|
||||||
section.register(pluginId, {
|
section.register(pluginId, {
|
||||||
|
@ -132,7 +139,13 @@ export class KibanaFrameworkAdapter implements FrameworkAdapter {
|
||||||
const xpackInfo = Private(this.XPackInfoProvider);
|
const xpackInfo = Private(this.XPackInfoProvider);
|
||||||
|
|
||||||
this.xpackInfo = xpackInfo;
|
this.xpackInfo = xpackInfo;
|
||||||
this.shieldUser = await $injector.get('ShieldUser').getCurrent().$promise;
|
if (this.securityEnabled()) {
|
||||||
|
try {
|
||||||
|
this.shieldUser = await $injector.get('ShieldUser').getCurrent().$promise;
|
||||||
|
} catch (e) {
|
||||||
|
// errors when security disabled, even though we check first because angular
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
|
@ -55,6 +55,9 @@ export interface FrameworkAdapter {
|
||||||
scope: string[];
|
scope: string[];
|
||||||
username: string;
|
username: string;
|
||||||
};
|
};
|
||||||
|
licenseExpired(): boolean;
|
||||||
|
securityEnabled(): boolean;
|
||||||
|
hasValidLicense(): boolean;
|
||||||
setUISettings(key: string, value: any): void;
|
setUISettings(key: string, value: any): void;
|
||||||
render(component: React.ReactElement<any>): void;
|
render(component: React.ReactElement<any>): void;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
||||||
|
*/
|
||||||
|
import * as React from 'react';
|
||||||
|
import { NoDataLayout } from '../components/layouts/no_data';
|
||||||
|
|
||||||
|
export const EnforceSecurityPage: React.SFC<any> = () => (
|
||||||
|
<NoDataLayout title="Security is not enabled" actionSection={[]}>
|
||||||
|
<p>You must enable security in Kibana and Elasticsearch to use Beats central management.</p>
|
||||||
|
</NoDataLayout>
|
||||||
|
);
|
|
@ -0,0 +1,16 @@
|
||||||
|
/*
|
||||||
|
* 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 * as React from 'react';
|
||||||
|
import { NoDataLayout } from '../components/layouts/no_data';
|
||||||
|
|
||||||
|
export const InvalidLicensePage: React.SFC<any> = () => (
|
||||||
|
<NoDataLayout title="Expired license" actionSection={[]}>
|
||||||
|
<p>
|
||||||
|
Your current license is expired. Enrolled Beats will continue to work, but you need a valid
|
||||||
|
license to access the Beats Management UI.
|
||||||
|
</p>
|
||||||
|
</NoDataLayout>
|
||||||
|
);
|
|
@ -7,7 +7,7 @@ import * as React from 'react';
|
||||||
import { NoDataLayout } from '../components/layouts/no_data';
|
import { NoDataLayout } from '../components/layouts/no_data';
|
||||||
|
|
||||||
export const NoAccessPage: React.SFC<any> = () => (
|
export const NoAccessPage: React.SFC<any> = () => (
|
||||||
<NoDataLayout title="Access Denied" actionSection={[]}>
|
<NoDataLayout title="Access denied" actionSection={[]}>
|
||||||
<p>
|
<p>
|
||||||
You are not authorized to access Beats central management. To use Beats central management,
|
You are not authorized to access Beats central management. To use Beats central management,
|
||||||
you need the privileges granted by the `beats_admin` role.
|
you need the privileges granted by the `beats_admin` role.
|
||||||
|
|
|
@ -6,11 +6,12 @@
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { HashRouter, Redirect, Route, Switch } from 'react-router-dom';
|
import { HashRouter, Redirect, Route, Switch } from 'react-router-dom';
|
||||||
|
|
||||||
import { Header } from './components/layouts/header';
|
import { Header } from './components/layouts/header';
|
||||||
import { BreadcrumbConsumer, RouteWithBreadcrumb } from './components/route_with_breadcrumb';
|
import { BreadcrumbConsumer, RouteWithBreadcrumb } from './components/route_with_breadcrumb';
|
||||||
import { FrontendLibs } from './lib/lib';
|
import { FrontendLibs } from './lib/lib';
|
||||||
import { BeatDetailsPage } from './pages/beat';
|
import { BeatDetailsPage } from './pages/beat';
|
||||||
|
import { EnforceSecurityPage } from './pages/enforce_security';
|
||||||
|
import { InvalidLicensePage } from './pages/invalid_license';
|
||||||
import { MainPages } from './pages/main';
|
import { MainPages } from './pages/main';
|
||||||
import { NoAccessPage } from './pages/no_access';
|
import { NoAccessPage } from './pages/no_access';
|
||||||
import { TagPage } from './pages/tag';
|
import { TagPage } from './pages/tag';
|
||||||
|
@ -37,6 +38,8 @@ export const PageRouter: React.SFC<{ libs: FrontendLibs }> = ({ libs }) => {
|
||||||
)}
|
)}
|
||||||
</BreadcrumbConsumer>
|
</BreadcrumbConsumer>
|
||||||
<Switch>
|
<Switch>
|
||||||
|
{libs.framework.licenseExpired() && <Route render={() => <InvalidLicensePage />} />}
|
||||||
|
{!libs.framework.securityEnabled() && <Route render={() => <EnforceSecurityPage />} />}
|
||||||
{!libs.framework.getCurrentUser() ||
|
{!libs.framework.getCurrentUser() ||
|
||||||
(!libs.framework.getCurrentUser().roles.includes('beats_admin') &&
|
(!libs.framework.getCurrentUser().roles.includes('beats_admin') &&
|
||||||
!libs.framework.getCurrentUser().roles.includes('superuser') && (
|
!libs.framework.getCurrentUser().roles.includes('superuser') && (
|
||||||
|
|
|
@ -62,9 +62,6 @@ export class KibanaBackendFrameworkAdapter implements BackendFrameworkAdapter {
|
||||||
}
|
}
|
||||||
|
|
||||||
public exposeStaticDir(urlPath: string, dir: string): void {
|
public exposeStaticDir(urlPath: string, dir: string): void {
|
||||||
if (!this.isSecurityEnabled()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.server.route({
|
this.server.route({
|
||||||
handler: {
|
handler: {
|
||||||
directory: {
|
directory: {
|
||||||
|
@ -101,7 +98,7 @@ export class KibanaBackendFrameworkAdapter implements BackendFrameworkAdapter {
|
||||||
|
|
||||||
if (
|
if (
|
||||||
wrappedRequest.user.kind === 'authenticated' &&
|
wrappedRequest.user.kind === 'authenticated' &&
|
||||||
!wrappedRequest.user.roles.includes('superuser') &&
|
(!wrappedRequest.user.roles.includes('superuser') || !wrappedRequest.user.roles) &&
|
||||||
difference(requiredRoles, wrappedRequest.user.roles).length !== 0
|
difference(requiredRoles, wrappedRequest.user.roles).length !== 0
|
||||||
) {
|
) {
|
||||||
return h.response().code(403);
|
return h.response().code(403);
|
||||||
|
@ -126,13 +123,6 @@ export class KibanaBackendFrameworkAdapter implements BackendFrameworkAdapter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private isSecurityEnabled = () => {
|
|
||||||
return (
|
|
||||||
this.server.plugins.xpack_main.info.isAvailable() &&
|
|
||||||
this.server.plugins.xpack_main.info.feature('security').isEnabled()
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
// TODO make key a param
|
// TODO make key a param
|
||||||
private validateConfig() {
|
private validateConfig() {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
|
@ -172,6 +162,7 @@ export class KibanaBackendFrameworkAdapter implements BackendFrameworkAdapter {
|
||||||
return {
|
return {
|
||||||
securityEnabled: true,
|
securityEnabled: true,
|
||||||
licenseValid: false,
|
licenseValid: false,
|
||||||
|
licenseExpired: false,
|
||||||
message: `Your ${licenseType} license does not support Beats central management features. Please upgrade your license.`,
|
message: `Your ${licenseType} license does not support Beats central management features. Please upgrade your license.`,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -180,7 +171,8 @@ export class KibanaBackendFrameworkAdapter implements BackendFrameworkAdapter {
|
||||||
if (!isLicenseActive) {
|
if (!isLicenseActive) {
|
||||||
return {
|
return {
|
||||||
securityEnabled: true,
|
securityEnabled: true,
|
||||||
licenseValid: false,
|
licenseValid: true,
|
||||||
|
licenseExpired: true,
|
||||||
message: `You cannot edit, create, or delete your Beats central management configurations because your ${licenseType} license has expired.`,
|
message: `You cannot edit, create, or delete your Beats central management configurations because your ${licenseType} license has expired.`,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -193,6 +185,8 @@ export class KibanaBackendFrameworkAdapter implements BackendFrameworkAdapter {
|
||||||
return {
|
return {
|
||||||
securityEnabled: false,
|
securityEnabled: false,
|
||||||
licenseValid: true,
|
licenseValid: true,
|
||||||
|
licenseExpired: false,
|
||||||
|
|
||||||
message,
|
message,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -201,6 +195,7 @@ export class KibanaBackendFrameworkAdapter implements BackendFrameworkAdapter {
|
||||||
return {
|
return {
|
||||||
securityEnabled: true,
|
securityEnabled: true,
|
||||||
licenseValid: true,
|
licenseValid: true,
|
||||||
|
licenseExpired: false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue