From e74ab191fecf2d7ce64a1229c7a37c7ec1166069 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mike=20C=C3=B4t=C3=A9?= Date: Tue, 4 Feb 2020 14:54:27 -0500 Subject: [PATCH] Disable creating alerts client instances when ESO plugin is using an ephemeral encryption key (#56676) --- .../legacy/plugins/alerting/server/index.ts | 5 +- .../plugins/alerting/server/plugin.test.ts | 113 ++++++++++++++++++ .../legacy/plugins/alerting/server/plugin.ts | 18 ++- .../lib/detection_engine/rules/types.ts | 2 +- 4 files changed, 131 insertions(+), 7 deletions(-) create mode 100644 x-pack/legacy/plugins/alerting/server/plugin.test.ts diff --git a/x-pack/legacy/plugins/alerting/server/index.ts b/x-pack/legacy/plugins/alerting/server/index.ts index 2f8356c0e9d014..44ae1964ec98a3 100644 --- a/x-pack/legacy/plugins/alerting/server/index.ts +++ b/x-pack/legacy/plugins/alerting/server/index.ts @@ -4,7 +4,10 @@ * you may not use this file except in compliance with the Elastic License. */ +import { AlertsClient as AlertsClientClass } from './alerts_client'; + +export type AlertsClient = PublicMethodsOf; + export { init } from './init'; export { AlertType, AlertingPlugin, AlertExecutorOptions } from './types'; -export { AlertsClient } from './alerts_client'; export { PluginSetupContract, PluginStartContract } from './plugin'; diff --git a/x-pack/legacy/plugins/alerting/server/plugin.test.ts b/x-pack/legacy/plugins/alerting/server/plugin.test.ts new file mode 100644 index 00000000000000..50142434a86ddf --- /dev/null +++ b/x-pack/legacy/plugins/alerting/server/plugin.test.ts @@ -0,0 +1,113 @@ +/* + * 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 { Plugin } from './plugin'; +import { coreMock } from '../../../../../src/core/server/mocks'; +import { licensingMock } from '../../../../plugins/licensing/server/mocks'; +import { encryptedSavedObjectsMock } from '../../../../plugins/encrypted_saved_objects/server/mocks'; + +describe('Alerting Plugin', () => { + describe('start()', () => { + /** + * HACK: This test has put together to ensuire the function "getAlertsClientWithRequest" + * throws when needed. There's a lot of blockers for writing a proper test like + * misisng plugin start/setup mocks for taskManager and actions plugin, core.http.route + * is actually not a function in Kibana Platform, etc. This test contains what is needed + * to get to the necessary function within start(). + */ + describe('getAlertsClientWithRequest()', () => { + it('throws error when encryptedSavedObjects plugin has usingEphemeralEncryptionKey set to true', async () => { + const context = coreMock.createPluginInitializerContext(); + const plugin = new Plugin(context); + + const coreSetup = coreMock.createSetup(); + const encryptedSavedObjectsSetup = encryptedSavedObjectsMock.createSetup(); + await plugin.setup( + { + ...coreSetup, + http: { + ...coreSetup.http, + route: jest.fn(), + }, + } as any, + { + licensing: licensingMock.createSetup(), + encryptedSavedObjects: encryptedSavedObjectsSetup, + } as any + ); + + const startContract = plugin.start( + coreMock.createStart() as any, + { + actions: { + execute: jest.fn(), + getActionsClientWithRequest: jest.fn(), + }, + } as any + ); + + expect(encryptedSavedObjectsSetup.usingEphemeralEncryptionKey).toEqual(true); + expect(() => + startContract.getAlertsClientWithRequest({} as any) + ).toThrowErrorMatchingInlineSnapshot( + `"Unable to create alerts client due to the Encrypted Saved Objects plugin using an ephemeral encryption key. Please set xpack.encryptedSavedObjects.encryptionKey in kibana.yml"` + ); + }); + + it(`doesn't throw error when encryptedSavedObjects plugin has usingEphemeralEncryptionKey set to false`, async () => { + const context = coreMock.createPluginInitializerContext(); + const plugin = new Plugin(context); + + const coreSetup = coreMock.createSetup(); + const encryptedSavedObjectsSetup = { + ...encryptedSavedObjectsMock.createSetup(), + usingEphemeralEncryptionKey: false, + }; + await plugin.setup( + { + ...coreSetup, + http: { + ...coreSetup.http, + route: jest.fn(), + }, + } as any, + { + licensing: licensingMock.createSetup(), + encryptedSavedObjects: encryptedSavedObjectsSetup, + } as any + ); + + const startContract = plugin.start( + coreMock.createStart() as any, + { + actions: { + execute: jest.fn(), + getActionsClientWithRequest: jest.fn(), + }, + spaces: () => null, + } as any + ); + + const fakeRequest = { + headers: {}, + getBasePath: () => '', + path: '/', + route: { settings: {} }, + url: { + href: '/', + }, + raw: { + req: { + url: '/', + }, + }, + getSavedObjectsClient: jest.fn(), + }; + await startContract.getAlertsClientWithRequest(fakeRequest as any); + }); + }); + }); +}); diff --git a/x-pack/legacy/plugins/alerting/server/plugin.ts b/x-pack/legacy/plugins/alerting/server/plugin.ts index 3218d9eeb2ef46..a4de7af376fb04 100644 --- a/x-pack/legacy/plugins/alerting/server/plugin.ts +++ b/x-pack/legacy/plugins/alerting/server/plugin.ts @@ -42,7 +42,7 @@ export interface PluginSetupContract { } export interface PluginStartContract { listTypes: AlertTypeRegistry['list']; - getAlertsClientWithRequest(request: Hapi.Request): AlertsClient; + getAlertsClientWithRequest(request: Hapi.Request): PublicMethodsOf; } export class Plugin { @@ -52,6 +52,7 @@ export class Plugin { private adminClient?: IClusterClient; private serverBasePath?: string; private licenseState: LicenseState | null = null; + private isESOUsingEphemeralEncryptionKey?: boolean; constructor(initializerContext: AlertingPluginInitializerContext) { this.logger = initializerContext.logger.get('plugins', 'alerting'); @@ -63,8 +64,9 @@ export class Plugin { plugins: AlertingPluginsSetup ): Promise { this.adminClient = core.elasticsearch.adminClient; - this.licenseState = new LicenseState(plugins.licensing.license$); + this.isESOUsingEphemeralEncryptionKey = + plugins.encryptedSavedObjects.usingEphemeralEncryptionKey; // Encrypted attributes plugins.encryptedSavedObjects.registerType({ @@ -106,7 +108,7 @@ export class Plugin { } public start(core: AlertingCoreStart, plugins: AlertingPluginsStart): PluginStartContract { - const { adminClient, serverBasePath } = this; + const { adminClient, serverBasePath, isESOUsingEphemeralEncryptionKey } = this; function spaceIdToNamespace(spaceId?: string): string | undefined { const spacesPlugin = plugins.spaces(); @@ -147,8 +149,14 @@ export class Plugin { return { listTypes: this.alertTypeRegistry!.list.bind(this.alertTypeRegistry!), - getAlertsClientWithRequest: (request: Hapi.Request) => - alertsClientFactory!.create(KibanaRequest.from(request), request), + getAlertsClientWithRequest: (request: Hapi.Request) => { + if (isESOUsingEphemeralEncryptionKey === true) { + throw new Error( + `Unable to create alerts client due to the Encrypted Saved Objects plugin using an ephemeral encryption key. Please set xpack.encryptedSavedObjects.encryptionKey in kibana.yml` + ); + } + return alertsClientFactory!.create(KibanaRequest.from(request), request); + }, }; } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/types.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/types.ts index 1b13a010bbea39..1d423c8b375d11 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/types.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/types.ts @@ -14,7 +14,7 @@ import { SavedObjectsClientContract, } from 'kibana/server'; import { SIGNALS_ID } from '../../../../common/constants'; -import { AlertsClient } from '../../../../../alerting/server/alerts_client'; +import { AlertsClient } from '../../../../../alerting/server'; import { ActionsClient } from '../../../../../../../plugins/actions/server'; import { RuleAlertParams, RuleTypeParams, RuleAlertParamsRest } from '../types'; import { RequestFacade } from '../../../types';