Remove license check from Ingest Node Pipelines UI (#100189) (#100959)

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
CJ Cenizal 2021-05-29 10:26:59 -07:00 committed by GitHub
parent ad66f73729
commit fb14fb049d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 37 additions and 173 deletions

View file

@ -3,7 +3,7 @@
"version": "kibana",
"server": true,
"ui": true,
"requiredPlugins": ["licensing", "management", "features", "share"],
"requiredPlugins": ["management", "features", "share"],
"optionalPlugins": ["security", "usageCollection"],
"configPath": ["xpack", "ingest_pipelines"],
"requiredBundles": ["esUiShared", "kibanaReact"]

View file

@ -5,9 +5,8 @@
* 2.0.
*/
import { PluginInitializerContext } from '../../../../src/core/server';
import { IngestPipelinesPlugin } from './plugin';
export function plugin(initializerContext: PluginInitializerContext) {
return new IngestPipelinesPlugin(initializerContext);
export function plugin() {
return new IngestPipelinesPlugin();
}

View file

@ -5,47 +5,22 @@
* 2.0.
*/
import { i18n } from '@kbn/i18n';
import { CoreSetup, Plugin } from 'kibana/server';
import { PluginInitializerContext, CoreSetup, Plugin, Logger } from 'kibana/server';
import { PLUGIN_ID, PLUGIN_MIN_LICENSE_TYPE } from '../common/constants';
import { License } from './services';
import { ApiRoutes } from './routes';
import { handleEsError } from './shared_imports';
import { Dependencies } from './types';
export class IngestPipelinesPlugin implements Plugin<void, void, any, any> {
private readonly logger: Logger;
private readonly license: License;
private readonly apiRoutes: ApiRoutes;
constructor({ logger }: PluginInitializerContext) {
this.logger = logger.get();
this.license = new License();
constructor() {
this.apiRoutes = new ApiRoutes();
}
public setup({ http }: CoreSetup, { licensing, security, features }: Dependencies) {
this.logger.debug('ingest_pipelines: setup');
public setup({ http }: CoreSetup, { security, features }: Dependencies) {
const router = http.createRouter();
this.license.setup(
{
pluginId: PLUGIN_ID,
minimumLicenseType: PLUGIN_MIN_LICENSE_TYPE,
defaultErrorMessage: i18n.translate('xpack.ingestPipelines.licenseCheckErrorMessage', {
defaultMessage: 'License check failed',
}),
},
{
licensing,
logger: this.logger,
}
);
features.registerElasticsearchFeature({
id: 'ingest_pipelines',
management: {
@ -61,7 +36,6 @@ export class IngestPipelinesPlugin implements Plugin<void, void, any, any> {
this.apiRoutes.setup({
router,
license: this.license,
config: {
isSecurityEnabled: () => security !== undefined && security.license.isEnabled(),
},

View file

@ -20,7 +20,6 @@ const bodySchema = schema.object({
export const registerCreateRoute = ({
router,
license,
lib: { handleEsError },
}: RouteDependencies): void => {
router.post(
@ -30,7 +29,7 @@ export const registerCreateRoute = ({
body: bodySchema,
},
},
license.guardApiRoute(async (ctx, req, res) => {
async (ctx, req, res) => {
const { client: clusterClient } = ctx.core.elasticsearch;
const pipeline = req.body as Pipeline;
@ -74,6 +73,6 @@ export const registerCreateRoute = ({
} catch (error) {
return handleEsError({ error, response: res });
}
})
}
);
};

View file

@ -14,7 +14,7 @@ const paramsSchema = schema.object({
names: schema.string(),
});
export const registerDeleteRoute = ({ router, license }: RouteDependencies): void => {
export const registerDeleteRoute = ({ router }: RouteDependencies): void => {
router.delete(
{
path: `${API_BASE_PATH}/{names}`,
@ -22,7 +22,7 @@ export const registerDeleteRoute = ({ router, license }: RouteDependencies): voi
params: paramsSchema,
},
},
license.guardApiRoute(async (ctx, req, res) => {
async (ctx, req, res) => {
const { client: clusterClient } = ctx.core.elasticsearch;
const { names } = req.params;
const pipelineNames = names.split(',');
@ -48,6 +48,6 @@ export const registerDeleteRoute = ({ router, license }: RouteDependencies): voi
);
return res.ok({ body: response });
})
}
);
};

View file

@ -17,7 +17,6 @@ const paramsSchema = schema.object({
export const registerDocumentsRoute = ({
router,
license,
lib: { handleEsError },
}: RouteDependencies): void => {
router.get(
@ -27,7 +26,7 @@ export const registerDocumentsRoute = ({
params: paramsSchema,
},
},
license.guardApiRoute(async (ctx, req, res) => {
async (ctx, req, res) => {
const { client: clusterClient } = ctx.core.elasticsearch;
const { index, id } = req.params;
@ -46,6 +45,6 @@ export const registerDocumentsRoute = ({
} catch (error) {
return handleEsError({ error, response: res });
}
})
}
);
};

View file

@ -15,32 +15,25 @@ const paramsSchema = schema.object({
name: schema.string(),
});
export const registerGetRoutes = ({
router,
license,
lib: { handleEsError },
}: RouteDependencies): void => {
export const registerGetRoutes = ({ router, lib: { handleEsError } }: RouteDependencies): void => {
// Get all pipelines
router.get(
{ path: API_BASE_PATH, validate: false },
license.guardApiRoute(async (ctx, req, res) => {
const { client: clusterClient } = ctx.core.elasticsearch;
router.get({ path: API_BASE_PATH, validate: false }, async (ctx, req, res) => {
const { client: clusterClient } = ctx.core.elasticsearch;
try {
const { body: pipelines } = await clusterClient.asCurrentUser.ingest.getPipeline();
try {
const { body: pipelines } = await clusterClient.asCurrentUser.ingest.getPipeline();
return res.ok({ body: deserializePipelines(pipelines) });
} catch (error) {
const esErrorResponse = handleEsError({ error, response: res });
if (esErrorResponse.status === 404) {
// ES returns 404 when there are no pipelines
// Instead, we return an empty array and 200 status back to the client
return res.ok({ body: [] });
}
return esErrorResponse;
return res.ok({ body: deserializePipelines(pipelines) });
} catch (error) {
const esErrorResponse = handleEsError({ error, response: res });
if (esErrorResponse.status === 404) {
// ES returns 404 when there are no pipelines
// Instead, we return an empty array and 200 status back to the client
return res.ok({ body: [] });
}
})
);
return esErrorResponse;
}
});
// Get single pipeline
router.get(
@ -50,7 +43,7 @@ export const registerGetRoutes = ({
params: paramsSchema,
},
},
license.guardApiRoute(async (ctx, req, res) => {
async (ctx, req, res) => {
const { client: clusterClient } = ctx.core.elasticsearch;
const { name } = req.params;
@ -68,6 +61,6 @@ export const registerGetRoutes = ({
} catch (error) {
return handleEsError({ error, response: res });
}
})
}
);
};

View file

@ -17,13 +17,13 @@ const extractMissingPrivileges = (privilegesObject: { [key: string]: boolean } =
return privileges;
}, []);
export const registerPrivilegesRoute = ({ license, router, config }: RouteDependencies) => {
export const registerPrivilegesRoute = ({ router, config }: RouteDependencies) => {
router.get(
{
path: `${API_BASE_PATH}/privileges`,
validate: false,
},
license.guardApiRoute(async (ctx, req, res) => {
async (ctx, req, res) => {
const privilegesResult: Privileges = {
hasAllPrivileges: true,
missingPrivileges: {
@ -51,6 +51,6 @@ export const registerPrivilegesRoute = ({ license, router, config }: RouteDepend
privilegesResult.hasAllPrivileges = hasAllPrivileges;
return res.ok({ body: privilegesResult });
})
}
);
};

View file

@ -19,7 +19,6 @@ const bodySchema = schema.object({
export const registerSimulateRoute = ({
router,
license,
lib: { handleEsError },
}: RouteDependencies): void => {
router.post(
@ -29,7 +28,7 @@ export const registerSimulateRoute = ({
body: bodySchema,
},
},
license.guardApiRoute(async (ctx, req, res) => {
async (ctx, req, res) => {
const { client: clusterClient } = ctx.core.elasticsearch;
const { pipeline, documents, verbose } = req.body;
@ -47,6 +46,6 @@ export const registerSimulateRoute = ({
} catch (error) {
return handleEsError({ error, response: res });
}
})
}
);
};

View file

@ -19,7 +19,6 @@ const paramsSchema = schema.object({
export const registerUpdateRoute = ({
router,
license,
lib: { handleEsError },
}: RouteDependencies): void => {
router.put(
@ -30,7 +29,7 @@ export const registerUpdateRoute = ({
params: paramsSchema,
},
},
license.guardApiRoute(async (ctx, req, res) => {
async (ctx, req, res) => {
const { client: clusterClient } = ctx.core.elasticsearch;
const { name } = req.params;
// eslint-disable-next-line @typescript-eslint/naming-convention
@ -54,6 +53,6 @@ export const registerUpdateRoute = ({
} catch (error) {
return handleEsError({ error, response: res });
}
})
}
);
};

View file

@ -1,8 +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
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
export { License } from './license';

View file

@ -1,84 +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
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { Logger } from 'src/core/server';
import {
KibanaRequest,
KibanaResponseFactory,
RequestHandler,
RequestHandlerContext,
} from 'kibana/server';
import { LicensingPluginSetup } from '../../../licensing/server';
import { LicenseType } from '../../../licensing/common/types';
export interface LicenseStatus {
isValid: boolean;
message?: string;
}
interface SetupSettings {
pluginId: string;
minimumLicenseType: LicenseType;
defaultErrorMessage: string;
}
export class License {
private licenseStatus: LicenseStatus = {
isValid: false,
message: 'Invalid License',
};
setup(
{ pluginId, minimumLicenseType, defaultErrorMessage }: SetupSettings,
{ licensing, logger }: { licensing: LicensingPluginSetup; logger: Logger }
) {
licensing.license$.subscribe((license) => {
const { state, message } = license.check(pluginId, minimumLicenseType);
const hasRequiredLicense = state === 'valid';
if (hasRequiredLicense) {
this.licenseStatus = { isValid: true };
} else {
this.licenseStatus = {
isValid: false,
message: message || defaultErrorMessage,
};
if (message) {
logger.info(message);
}
}
});
}
guardApiRoute<P, Q, B>(handler: RequestHandler<P, Q, B>) {
const license = this;
return function licenseCheck(
ctx: RequestHandlerContext,
request: KibanaRequest<P, Q, B>,
response: KibanaResponseFactory
) {
const licenseStatus = license.getStatus();
if (!licenseStatus.isValid) {
return response.customError({
body: {
message: licenseStatus.message || '',
},
statusCode: 403,
});
}
return handler(ctx, request, response);
};
}
getStatus() {
return this.licenseStatus;
}
}

View file

@ -6,21 +6,17 @@
*/
import { IRouter } from 'src/core/server';
import { LicensingPluginSetup } from '../../licensing/server';
import { SecurityPluginSetup } from '../../security/server';
import { PluginSetupContract as FeaturesPluginSetup } from '../../features/server';
import { License } from './services';
import { handleEsError } from './shared_imports';
export interface Dependencies {
security: SecurityPluginSetup;
features: FeaturesPluginSetup;
licensing: LicensingPluginSetup;
}
export interface RouteDependencies {
router: IRouter;
license: License;
config: {
isSecurityEnabled: () => boolean;
};

View file

@ -12362,7 +12362,6 @@
"xpack.ingestPipelines.form.unknownError": "不明なエラーが発生しました。",
"xpack.ingestPipelines.form.versionFieldLabel": "バージョン (任意) ",
"xpack.ingestPipelines.form.versionToggleDescription": "バージョン番号を追加",
"xpack.ingestPipelines.licenseCheckErrorMessage": "ライセンス確認失敗",
"xpack.ingestPipelines.list.listTitle": "Ingestードパイプライン",
"xpack.ingestPipelines.list.loadErrorReloadLinkLabel": "再試行してください。",
"xpack.ingestPipelines.list.loadErrorTitle": "パイプラインを読み込めません。{reloadLink}",

View file

@ -12528,7 +12528,6 @@
"xpack.ingestPipelines.form.unknownError": "发生了未知错误。",
"xpack.ingestPipelines.form.versionFieldLabel": "版本 (可选) ",
"xpack.ingestPipelines.form.versionToggleDescription": "添加版本号",
"xpack.ingestPipelines.licenseCheckErrorMessage": "许可证检查失败",
"xpack.ingestPipelines.list.listTitle": "采集节点管道",
"xpack.ingestPipelines.list.loadErrorReloadLinkLabel": "请重试。",
"xpack.ingestPipelines.list.loadErrorTitle": "无法加载管道。{reloadLink}",