Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
ad66f73729
commit
fb14fb049d
15 changed files with 37 additions and 173 deletions
|
@ -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"]
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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(),
|
||||
},
|
||||
|
|
|
@ -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 });
|
||||
}
|
||||
})
|
||||
}
|
||||
);
|
||||
};
|
||||
|
|
|
@ -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 });
|
||||
})
|
||||
}
|
||||
);
|
||||
};
|
||||
|
|
|
@ -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 });
|
||||
}
|
||||
})
|
||||
}
|
||||
);
|
||||
};
|
||||
|
|
|
@ -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 });
|
||||
}
|
||||
})
|
||||
}
|
||||
);
|
||||
};
|
||||
|
|
|
@ -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 });
|
||||
})
|
||||
}
|
||||
);
|
||||
};
|
||||
|
|
|
@ -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 });
|
||||
}
|
||||
})
|
||||
}
|
||||
);
|
||||
};
|
||||
|
|
|
@ -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 });
|
||||
}
|
||||
})
|
||||
}
|
||||
);
|
||||
};
|
||||
|
|
|
@ -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';
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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}",
|
||||
|
|
|
@ -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}",
|
||||
|
|
Loading…
Reference in a new issue