Skip to content

Commit

Permalink
Disable action plugin functionality when ESO plugin is using an ephem…
Browse files Browse the repository at this point in the history
…eral encryption key (elastic#56906)

* Disable actions client when ESO using generated key

* Add test for getActionsClientWithRequest

* Add other part to plugin.test.ts

* Cleanup tests a bit

* Cleanup tests

* plugin.test.ts cleanup

* Add warning logs on setup

Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
  • Loading branch information
mikecote and elasticmachine committed Feb 12, 2020
1 parent eda1e00 commit 3375e31
Show file tree
Hide file tree
Showing 13 changed files with 294 additions and 15 deletions.
28 changes: 28 additions & 0 deletions x-pack/legacy/plugins/alerting/server/plugin.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,34 @@ import { licensingMock } from '../../../../plugins/licensing/server/mocks';
import { encryptedSavedObjectsMock } from '../../../../plugins/encrypted_saved_objects/server/mocks';

describe('Alerting Plugin', () => {
describe('setup()', () => {
it('should log warning when Encrypted Saved Objects plugin is using an ephemeral encryption key', 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
);

expect(encryptedSavedObjectsSetup.usingEphemeralEncryptionKey).toEqual(true);
expect(context.logger.get().warn).toHaveBeenCalledWith(
'APIs are disabled due to the Encrypted Saved Objects plugin using an ephemeral encryption key. Please set xpack.encryptedSavedObjects.encryptionKey in kibana.yml.'
);
});
});

describe('start()', () => {
/**
* HACK: This test has put together to ensuire the function "getAlertsClientWithRequest"
Expand Down
6 changes: 6 additions & 0 deletions x-pack/legacy/plugins/alerting/server/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,12 @@ export class Plugin {
this.isESOUsingEphemeralEncryptionKey =
plugins.encryptedSavedObjects.usingEphemeralEncryptionKey;

if (this.isESOUsingEphemeralEncryptionKey) {
this.logger.warn(
'APIs are disabled due to the Encrypted Saved Objects plugin using an ephemeral encryption key. Please set xpack.encryptedSavedObjects.encryptionKey in kibana.yml.'
);
}

// Encrypted attributes
plugins.encryptedSavedObjects.registerType({
type: 'alert',
Expand Down
4 changes: 3 additions & 1 deletion x-pack/plugins/actions/server/action_type_registry.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ import { configUtilsMock } from './actions_config.mock';
const mockTaskManager = taskManagerMock.setup();
const actionTypeRegistryParams = {
taskManager: mockTaskManager,
taskRunnerFactory: new TaskRunnerFactory(new ActionExecutor()),
taskRunnerFactory: new TaskRunnerFactory(
new ActionExecutor({ isESOUsingEphemeralEncryptionKey: false })
),
actionsConfigUtils: configUtilsMock,
};

Expand Down
8 changes: 6 additions & 2 deletions x-pack/plugins/actions/server/actions_client.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ const mockTaskManager = taskManagerMock.setup();

const actionTypeRegistryParams = {
taskManager: mockTaskManager,
taskRunnerFactory: new TaskRunnerFactory(new ActionExecutor()),
taskRunnerFactory: new TaskRunnerFactory(
new ActionExecutor({ isESOUsingEphemeralEncryptionKey: false })
),
actionsConfigUtils: configUtilsMock,
};

Expand Down Expand Up @@ -204,7 +206,9 @@ describe('create()', () => {

const localActionTypeRegistryParams = {
taskManager: mockTaskManager,
taskRunnerFactory: new TaskRunnerFactory(new ActionExecutor()),
taskRunnerFactory: new TaskRunnerFactory(
new ActionExecutor({ isESOUsingEphemeralEncryptionKey: false })
),
actionsConfigUtils: localConfigUtils,
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ export function createActionTypeRegistry(): {
const logger = loggingServiceMock.create().get() as jest.Mocked<Logger>;
const actionTypeRegistry = new ActionTypeRegistry({
taskManager: taskManagerMock.setup(),
taskRunnerFactory: new TaskRunnerFactory(new ActionExecutor()),
taskRunnerFactory: new TaskRunnerFactory(
new ActionExecutor({ isESOUsingEphemeralEncryptionKey: false })
),
actionsConfigUtils: configUtilsMock,
});
registerBuiltInActionTypes({
Expand Down
23 changes: 23 additions & 0 deletions x-pack/plugins/actions/server/create_execute_function.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ describe('execute()', () => {
getBasePath,
taskManager: mockTaskManager,
getScopedSavedObjectsClient: jest.fn().mockReturnValueOnce(savedObjectsClient),
isESOUsingEphemeralEncryptionKey: false,
});
savedObjectsClient.get.mockResolvedValueOnce({
id: '123',
Expand Down Expand Up @@ -71,6 +72,7 @@ describe('execute()', () => {
getBasePath,
taskManager: mockTaskManager,
getScopedSavedObjectsClient,
isESOUsingEphemeralEncryptionKey: false,
});
savedObjectsClient.get.mockResolvedValueOnce({
id: '123',
Expand Down Expand Up @@ -118,6 +120,7 @@ describe('execute()', () => {
getBasePath,
taskManager: mockTaskManager,
getScopedSavedObjectsClient,
isESOUsingEphemeralEncryptionKey: false,
});
savedObjectsClient.get.mockResolvedValueOnce({
id: '123',
Expand Down Expand Up @@ -155,4 +158,24 @@ describe('execute()', () => {
},
});
});

test('throws when passing isESOUsingEphemeralEncryptionKey with true as a value', async () => {
const getScopedSavedObjectsClient = jest.fn().mockReturnValueOnce(savedObjectsClient);
const executeFn = createExecuteFunction({
getBasePath,
taskManager: mockTaskManager,
getScopedSavedObjectsClient,
isESOUsingEphemeralEncryptionKey: true,
});
await expect(
executeFn({
id: '123',
params: { baz: false },
spaceId: 'default',
apiKey: null,
})
).rejects.toThrowErrorMatchingInlineSnapshot(
`"Unable to execute action due to the Encrypted Saved Objects plugin using an ephemeral encryption key. Please set xpack.encryptedSavedObjects.encryptionKey in kibana.yml"`
);
});
});
8 changes: 8 additions & 0 deletions x-pack/plugins/actions/server/create_execute_function.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ interface CreateExecuteFunctionOptions {
taskManager: TaskManagerStartContract;
getScopedSavedObjectsClient: (request: any) => SavedObjectsClientContract;
getBasePath: GetBasePathFunction;
isESOUsingEphemeralEncryptionKey: boolean;
}

export interface ExecuteOptions {
Expand All @@ -25,8 +26,15 @@ export function createExecuteFunction({
getBasePath,
taskManager,
getScopedSavedObjectsClient,
isESOUsingEphemeralEncryptionKey,
}: CreateExecuteFunctionOptions) {
return async function execute({ id, params, spaceId, apiKey }: ExecuteOptions) {
if (isESOUsingEphemeralEncryptionKey === true) {
throw new Error(
`Unable to execute action due to the Encrypted Saved Objects plugin using an ephemeral encryption key. Please set xpack.encryptedSavedObjects.encryptionKey in kibana.yml`
);
}

const requestHeaders: Record<string, string> = {};

if (apiKey) {
Expand Down
4 changes: 3 additions & 1 deletion x-pack/plugins/actions/server/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@
import { PluginInitializerContext } from '../../../../src/core/server';
import { ActionsPlugin } from './plugin';
import { configSchema } from './config';
import { ActionsClient as ActionsClientClass } from './actions_client';

export type ActionsClient = PublicMethodsOf<ActionsClientClass>;

export { ActionsPlugin, ActionResult, ActionTypeExecutorOptions, ActionType } from './types';
export { ActionsClient } from './actions_client';
export { PluginSetupContract, PluginStartContract } from './plugin';

export const plugin = (initContext: PluginInitializerContext) => new ActionsPlugin(initContext);
Expand Down
30 changes: 25 additions & 5 deletions x-pack/plugins/actions/server/lib/action_executor.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ import { actionTypeRegistryMock } from '../action_type_registry.mock';
import { encryptedSavedObjectsMock } from '../../../encrypted_saved_objects/server/mocks';
import { savedObjectsClientMock, loggingServiceMock } from '../../../../../src/core/server/mocks';
import { eventLoggerMock } from '../../../event_log/server/mocks';
import { spacesServiceMock } from '../../../spaces/server/spaces_service/spaces_service.mock';

const actionExecutor = new ActionExecutor();
const actionExecutor = new ActionExecutor({ isESOUsingEphemeralEncryptionKey: false });
const savedObjectsClient = savedObjectsClientMock.create();

function getServices() {
Expand All @@ -33,18 +34,20 @@ const executeParams = {
request: {} as KibanaRequest,
};

const spacesMock = spacesServiceMock.createSetupContract();
actionExecutor.initialize({
logger: loggingServiceMock.create().get(),
spaces: {
getSpaceId: () => 'some-namespace',
} as any,
spaces: spacesMock,
getServices,
actionTypeRegistry,
encryptedSavedObjectsPlugin,
eventLogger: eventLoggerMock.create(),
});

beforeEach(() => jest.resetAllMocks());
beforeEach(() => {
jest.resetAllMocks();
spacesMock.getSpaceId.mockReturnValue('some-namespace');
});

test('successfully executes', async () => {
const actionType = {
Expand Down Expand Up @@ -219,3 +222,20 @@ test('returns an error if actionType is not enabled', async () => {
}
`);
});

test('throws an error when passing isESOUsingEphemeralEncryptionKey with value of true', async () => {
const customActionExecutor = new ActionExecutor({ isESOUsingEphemeralEncryptionKey: true });
customActionExecutor.initialize({
logger: loggingServiceMock.create().get(),
spaces: spacesMock,
getServices,
actionTypeRegistry,
encryptedSavedObjectsPlugin,
eventLogger: eventLoggerMock.create(),
});
await expect(
customActionExecutor.execute(executeParams)
).rejects.toThrowErrorMatchingInlineSnapshot(
`"Unable to execute action due to the Encrypted Saved Objects plugin using an ephemeral encryption key. Please set xpack.encryptedSavedObjects.encryptionKey in kibana.yml"`
);
});
11 changes: 11 additions & 0 deletions x-pack/plugins/actions/server/lib/action_executor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ export type ActionExecutorContract = PublicMethodsOf<ActionExecutor>;
export class ActionExecutor {
private isInitialized = false;
private actionExecutorContext?: ActionExecutorContext;
private readonly isESOUsingEphemeralEncryptionKey: boolean;

constructor({ isESOUsingEphemeralEncryptionKey }: { isESOUsingEphemeralEncryptionKey: boolean }) {
this.isESOUsingEphemeralEncryptionKey = isESOUsingEphemeralEncryptionKey;
}

public initialize(actionExecutorContext: ActionExecutorContext) {
if (this.isInitialized) {
Expand All @@ -55,6 +60,12 @@ export class ActionExecutor {
throw new Error('ActionExecutor not initialized');
}

if (this.isESOUsingEphemeralEncryptionKey === true) {
throw new Error(
`Unable to execute action due to the Encrypted Saved Objects plugin using an ephemeral encryption key. Please set xpack.encryptedSavedObjects.encryptionKey in kibana.yml`
);
}

const {
spaces,
getServices,
Expand Down
8 changes: 6 additions & 2 deletions x-pack/plugins/actions/server/lib/task_runner_factory.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,14 +78,18 @@ beforeEach(() => {
});

test(`throws an error if factory isn't initialized`, () => {
const factory = new TaskRunnerFactory(new ActionExecutor());
const factory = new TaskRunnerFactory(
new ActionExecutor({ isESOUsingEphemeralEncryptionKey: false })
);
expect(() =>
factory.create({ taskInstance: mockedTaskInstance })
).toThrowErrorMatchingInlineSnapshot(`"TaskRunnerFactory not initialized"`);
});

test(`throws an error if factory is already initialized`, () => {
const factory = new TaskRunnerFactory(new ActionExecutor());
const factory = new TaskRunnerFactory(
new ActionExecutor({ isESOUsingEphemeralEncryptionKey: false })
);
factory.initialize(taskRunnerFactoryInitializerParams);
expect(() =>
factory.initialize(taskRunnerFactoryInitializerParams)
Expand Down
Loading

0 comments on commit 3375e31

Please sign in to comment.