Skip to content

Commit

Permalink
Do not generate an ephemeral encryption key in production. (#81511)
Browse files Browse the repository at this point in the history
  • Loading branch information
azasypkin authored Feb 10, 2021
1 parent 634c0b3 commit 03a53b9
Show file tree
Hide file tree
Showing 30 changed files with 543 additions and 238 deletions.
4 changes: 1 addition & 3 deletions x-pack/plugins/actions/server/action_type_registry.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,7 @@ beforeEach(() => {
actionTypeRegistryParams = {
licensing: licensingMock.createSetup(),
taskManager: mockTaskManager,
taskRunnerFactory: new TaskRunnerFactory(
new ActionExecutor({ isESOUsingEphemeralEncryptionKey: false })
),
taskRunnerFactory: new TaskRunnerFactory(new ActionExecutor({ isESOCanEncrypt: true })),
actionsConfigUtils: mockedActionsConfig,
licenseState: mockedLicenseState,
preconfiguredActions: [
Expand Down
8 changes: 2 additions & 6 deletions x-pack/plugins/actions/server/actions_client.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,7 @@ beforeEach(() => {
actionTypeRegistryParams = {
licensing: licensingMock.createSetup(),
taskManager: mockTaskManager,
taskRunnerFactory: new TaskRunnerFactory(
new ActionExecutor({ isESOUsingEphemeralEncryptionKey: false })
),
taskRunnerFactory: new TaskRunnerFactory(new ActionExecutor({ isESOCanEncrypt: true })),
actionsConfigUtils: actionsConfigMock.create(),
licenseState: mockedLicenseState,
preconfiguredActions: [],
Expand Down Expand Up @@ -411,9 +409,7 @@ describe('create()', () => {
const localActionTypeRegistryParams = {
licensing: licensingMock.createSetup(),
taskManager: mockTaskManager,
taskRunnerFactory: new TaskRunnerFactory(
new ActionExecutor({ isESOUsingEphemeralEncryptionKey: false })
),
taskRunnerFactory: new TaskRunnerFactory(new ActionExecutor({ isESOCanEncrypt: true })),
actionsConfigUtils: localConfigUtils,
licenseState: licenseStateMock.create(),
preconfiguredActions: [],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,7 @@ export function createActionTypeRegistry(): {
const actionTypeRegistry = new ActionTypeRegistry({
taskManager: taskManagerMock.createSetup(),
licensing: licensingMock.createSetup(),
taskRunnerFactory: new TaskRunnerFactory(
new ActionExecutor({ isESOUsingEphemeralEncryptionKey: false })
),
taskRunnerFactory: new TaskRunnerFactory(new ActionExecutor({ isESOCanEncrypt: true })),
actionsConfigUtils: actionsConfigMock.create(),
licenseState: licenseStateMock.create(),
preconfiguredActions: [],
Expand Down
14 changes: 7 additions & 7 deletions x-pack/plugins/actions/server/create_execute_function.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ describe('execute()', () => {
const executeFn = createExecutionEnqueuerFunction({
taskManager: mockTaskManager,
actionTypeRegistry,
isESOUsingEphemeralEncryptionKey: false,
isESOCanEncrypt: true,
preconfiguredActions: [],
});
savedObjectsClient.get.mockResolvedValueOnce({
Expand Down Expand Up @@ -87,7 +87,7 @@ describe('execute()', () => {
const executeFn = createExecutionEnqueuerFunction({
taskManager: mockTaskManager,
actionTypeRegistry: actionTypeRegistryMock.create(),
isESOUsingEphemeralEncryptionKey: false,
isESOCanEncrypt: true,
preconfiguredActions: [
{
id: '123',
Expand Down Expand Up @@ -158,10 +158,10 @@ describe('execute()', () => {
);
});

test('throws when passing isESOUsingEphemeralEncryptionKey with true as a value', async () => {
test('throws when passing isESOCanEncrypt with false as a value', async () => {
const executeFn = createExecutionEnqueuerFunction({
taskManager: mockTaskManager,
isESOUsingEphemeralEncryptionKey: true,
isESOCanEncrypt: false,
actionTypeRegistry: actionTypeRegistryMock.create(),
preconfiguredActions: [],
});
Expand All @@ -173,15 +173,15 @@ describe('execute()', () => {
apiKey: null,
})
).rejects.toThrowErrorMatchingInlineSnapshot(
`"Unable to execute action because the Encrypted Saved Objects plugin uses an ephemeral encryption key. Please set xpack.encryptedSavedObjects.encryptionKey in the kibana.yml or use the bin/kibana-encryption-keys command."`
`"Unable to execute action because the Encrypted Saved Objects plugin is missing encryption key. Please set xpack.encryptedSavedObjects.encryptionKey in the kibana.yml or use the bin/kibana-encryption-keys command."`
);
});

test('should ensure action type is enabled', async () => {
const mockedActionTypeRegistry = actionTypeRegistryMock.create();
const executeFn = createExecutionEnqueuerFunction({
taskManager: mockTaskManager,
isESOUsingEphemeralEncryptionKey: false,
isESOCanEncrypt: true,
actionTypeRegistry: mockedActionTypeRegistry,
preconfiguredActions: [],
});
Expand Down Expand Up @@ -211,7 +211,7 @@ describe('execute()', () => {
const mockedActionTypeRegistry = actionTypeRegistryMock.create();
const executeFn = createExecutionEnqueuerFunction({
taskManager: mockTaskManager,
isESOUsingEphemeralEncryptionKey: false,
isESOCanEncrypt: true,
actionTypeRegistry: mockedActionTypeRegistry,
preconfiguredActions: [
{
Expand Down
8 changes: 4 additions & 4 deletions x-pack/plugins/actions/server/create_execute_function.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { isSavedObjectExecutionSource } from './lib';

interface CreateExecuteFunctionOptions {
taskManager: TaskManagerStartContract;
isESOUsingEphemeralEncryptionKey: boolean;
isESOCanEncrypt: boolean;
actionTypeRegistry: ActionTypeRegistryContract;
preconfiguredActions: PreConfiguredAction[];
}
Expand All @@ -33,16 +33,16 @@ export type ExecutionEnqueuer = (
export function createExecutionEnqueuerFunction({
taskManager,
actionTypeRegistry,
isESOUsingEphemeralEncryptionKey,
isESOCanEncrypt,
preconfiguredActions,
}: CreateExecuteFunctionOptions) {
return async function execute(
unsecuredSavedObjectsClient: SavedObjectsClientContract,
{ id, params, spaceId, source, apiKey }: ExecuteOptions
) {
if (isESOUsingEphemeralEncryptionKey === true) {
if (!isESOCanEncrypt) {
throw new Error(
`Unable to execute action because the Encrypted Saved Objects plugin uses an ephemeral encryption key. Please set xpack.encryptedSavedObjects.encryptionKey in the kibana.yml or use the bin/kibana-encryption-keys command.`
`Unable to execute action because the Encrypted Saved Objects plugin is missing encryption key. Please set xpack.encryptedSavedObjects.encryptionKey in the kibana.yml or use the bin/kibana-encryption-keys command.`
);
}

Expand Down
8 changes: 4 additions & 4 deletions x-pack/plugins/actions/server/lib/action_executor.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { ActionType } from '../types';
import { actionsMock, actionsClientMock } from '../mocks';
import { pick } from 'lodash';

const actionExecutor = new ActionExecutor({ isESOUsingEphemeralEncryptionKey: false });
const actionExecutor = new ActionExecutor({ isESOCanEncrypt: true });
const services = actionsMock.createServices();

const actionsClient = actionsClientMock.create();
Expand Down Expand Up @@ -310,8 +310,8 @@ test('should not throws an error if actionType is preconfigured', async () => {
});
});

test('throws an error when passing isESOUsingEphemeralEncryptionKey with value of true', async () => {
const customActionExecutor = new ActionExecutor({ isESOUsingEphemeralEncryptionKey: true });
test('throws an error when passing isESOCanEncrypt with value of false', async () => {
const customActionExecutor = new ActionExecutor({ isESOCanEncrypt: false });
customActionExecutor.initialize({
logger: loggingSystemMock.create().get(),
spaces: spacesMock,
Expand All @@ -325,7 +325,7 @@ test('throws an error when passing isESOUsingEphemeralEncryptionKey with value o
await expect(
customActionExecutor.execute(executeParams)
).rejects.toThrowErrorMatchingInlineSnapshot(
`"Unable to execute action because the Encrypted Saved Objects plugin uses an ephemeral encryption key. Please set xpack.encryptedSavedObjects.encryptionKey in the kibana.yml or use the bin/kibana-encryption-keys command."`
`"Unable to execute action because the Encrypted Saved Objects plugin is missing encryption key. Please set xpack.encryptedSavedObjects.encryptionKey in the kibana.yml or use the bin/kibana-encryption-keys command."`
);
});

Expand Down
10 changes: 5 additions & 5 deletions x-pack/plugins/actions/server/lib/action_executor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,10 @@ export type ActionExecutorContract = PublicMethodsOf<ActionExecutor>;
export class ActionExecutor {
private isInitialized = false;
private actionExecutorContext?: ActionExecutorContext;
private readonly isESOUsingEphemeralEncryptionKey: boolean;
private readonly isESOCanEncrypt: boolean;

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

public initialize(actionExecutorContext: ActionExecutorContext) {
Expand All @@ -72,9 +72,9 @@ export class ActionExecutor {
throw new Error('ActionExecutor not initialized');
}

if (this.isESOUsingEphemeralEncryptionKey === true) {
if (!this.isESOCanEncrypt) {
throw new Error(
`Unable to execute action because the Encrypted Saved Objects plugin uses an ephemeral encryption key. Please set xpack.encryptedSavedObjects.encryptionKey in the kibana.yml or use the bin/kibana-encryption-keys command.`
`Unable to execute action because the Encrypted Saved Objects plugin is missing encryption key. Please set xpack.encryptedSavedObjects.encryptionKey in the kibana.yml or use the bin/kibana-encryption-keys command.`
);
}

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

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

test(`throws an error if factory is already initialized`, () => {
const factory = new TaskRunnerFactory(
new ActionExecutor({ isESOUsingEphemeralEncryptionKey: false })
);
const factory = new TaskRunnerFactory(new ActionExecutor({ isESOCanEncrypt: true }));
factory.initialize(taskRunnerFactoryInitializerParams);
expect(() =>
factory.initialize(taskRunnerFactoryInitializerParams)
Expand Down
44 changes: 17 additions & 27 deletions x-pack/plugins/actions/server/plugin.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,25 +51,21 @@ describe('Actions Plugin', () => {
};
});

it('should log warning when Encrypted Saved Objects plugin is using an ephemeral encryption key', async () => {
// coreMock.createSetup doesn't support Plugin generics
// eslint-disable-next-line @typescript-eslint/no-explicit-any
await plugin.setup(coreSetup as any, pluginsSetup);
expect(pluginsSetup.encryptedSavedObjects.usingEphemeralEncryptionKey).toEqual(true);
it('should log warning when Encrypted Saved Objects plugin is missing encryption key', async () => {
await plugin.setup(coreSetup, pluginsSetup);
expect(pluginsSetup.encryptedSavedObjects.canEncrypt).toEqual(false);
expect(context.logger.get().warn).toHaveBeenCalledWith(
'APIs are disabled because the Encrypted Saved Objects plugin uses an ephemeral encryption key. Please set xpack.encryptedSavedObjects.encryptionKey in the kibana.yml or use the bin/kibana-encryption-keys command.'
'APIs are disabled because the Encrypted Saved Objects plugin is missing encryption key. Please set xpack.encryptedSavedObjects.encryptionKey in the kibana.yml or use the bin/kibana-encryption-keys command.'
);
});

describe('routeHandlerContext.getActionsClient()', () => {
it('should not throw error when ESO plugin not using a generated key', async () => {
// coreMock.createSetup doesn't support Plugin generics
// eslint-disable-next-line @typescript-eslint/no-explicit-any
await plugin.setup(coreSetup as any, {
it('should not throw error when ESO plugin has encryption key', async () => {
await plugin.setup(coreSetup, {
...pluginsSetup,
encryptedSavedObjects: {
...pluginsSetup.encryptedSavedObjects,
usingEphemeralEncryptionKey: false,
canEncrypt: true,
},
});

Expand Down Expand Up @@ -99,10 +95,8 @@ describe('Actions Plugin', () => {
actionsContextHandler!.getActionsClient();
});

it('should throw error when ESO plugin using a generated key', async () => {
// coreMock.createSetup doesn't support Plugin generics
// eslint-disable-next-line @typescript-eslint/no-explicit-any
await plugin.setup(coreSetup as any, pluginsSetup);
it('should throw error when ESO plugin is missing encryption key', async () => {
await plugin.setup(coreSetup, pluginsSetup);

expect(coreSetup.http.registerRouteHandlerContext).toHaveBeenCalledTimes(1);
const handler = coreSetup.http.registerRouteHandlerContext.mock.calls[0] as [
Expand All @@ -123,7 +117,7 @@ describe('Actions Plugin', () => {
httpServerMock.createResponseFactory()
)) as unknown) as ActionsApiRequestHandlerContext;
expect(() => actionsContextHandler!.getActionsClient()).toThrowErrorMatchingInlineSnapshot(
`"Unable to create actions client because the Encrypted Saved Objects plugin uses an ephemeral encryption key. Please set xpack.encryptedSavedObjects.encryptionKey in the kibana.yml or use the bin/kibana-encryption-keys command."`
`"Unable to create actions client because the Encrypted Saved Objects plugin is missing encryption key. Please set xpack.encryptedSavedObjects.encryptionKey in the kibana.yml or use the bin/kibana-encryption-keys command."`
);
});
});
Expand Down Expand Up @@ -234,32 +228,28 @@ describe('Actions Plugin', () => {
expect(pluginStart.isActionExecutable('preconfiguredServerLog', '.server-log')).toBe(true);
});

it('should not throw error when ESO plugin not using a generated key', async () => {
// coreMock.createSetup doesn't support Plugin generics
// eslint-disable-next-line @typescript-eslint/no-explicit-any
await plugin.setup(coreSetup as any, {
it('should not throw error when ESO plugin has encryption key', async () => {
await plugin.setup(coreSetup, {
...pluginsSetup,
encryptedSavedObjects: {
...pluginsSetup.encryptedSavedObjects,
usingEphemeralEncryptionKey: false,
canEncrypt: true,
},
});
const pluginStart = await plugin.start(coreStart, pluginsStart);

await pluginStart.getActionsClientWithRequest(httpServerMock.createKibanaRequest());
});

it('should throw error when ESO plugin using generated key', async () => {
// coreMock.createSetup doesn't support Plugin generics
// eslint-disable-next-line @typescript-eslint/no-explicit-any
await plugin.setup(coreSetup as any, pluginsSetup);
it('should throw error when ESO plugin is missing encryption key', async () => {
await plugin.setup(coreSetup, pluginsSetup);
const pluginStart = await plugin.start(coreStart, pluginsStart);

expect(pluginsSetup.encryptedSavedObjects.usingEphemeralEncryptionKey).toEqual(true);
expect(pluginsSetup.encryptedSavedObjects.canEncrypt).toEqual(false);
await expect(
pluginStart.getActionsClientWithRequest(httpServerMock.createKibanaRequest())
).rejects.toThrowErrorMatchingInlineSnapshot(
`"Unable to create actions client because the Encrypted Saved Objects plugin uses an ephemeral encryption key. Please set xpack.encryptedSavedObjects.encryptionKey in the kibana.yml or use the bin/kibana-encryption-keys command."`
`"Unable to create actions client because the Encrypted Saved Objects plugin is missing encryption key. Please set xpack.encryptedSavedObjects.encryptionKey in the kibana.yml or use the bin/kibana-encryption-keys command."`
);
});
});
Expand Down
Loading

0 comments on commit 03a53b9

Please sign in to comment.