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 (#56906) (#57486)

* 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 <[email protected]>

Co-authored-by: Elastic Machine <[email protected]>
  • Loading branch information
mikecote and elasticmachine authored Feb 12, 2020
1 parent 4e75d5b commit 3194cd0
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 3194cd0

Please sign in to comment.