[cli] Add bin/kibana-encryption-keys (#82838)

Co-authored-by: Aleh Zasypkin <aleh.zasypkin@gmail.com>
Co-authored-by: Tyler Smalley <tylersmalley@me.com>
This commit is contained in:
Jonathan Budzenski 2020-11-19 12:41:48 -06:00
parent 5231a27bb6
commit 47d788d946
28 changed files with 606 additions and 27 deletions

View file

@ -0,0 +1,20 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
require('../src/cli_encryption_keys/dev');

View file

@ -0,0 +1,23 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`encryption key generation interactive should write to disk partial keys 1`] = `
Array [
Array [
"/foo/bar",
"#xpack.encryptedSavedObjects.encryptionKey
#Used to encrypt stored objects such as dashboards and visualizations
#https://www.elastic.co/guide/en/kibana/current/xpack-security-secure-saved-objects.html#xpack-security-secure-saved-objects
#xpack.reporting.encryptionKey
#Used to encrypt saved reports
#https://www.elastic.co/guide/en/kibana/current/reporting-settings-kb.html#general-reporting-settings
#xpack.security.encryptionKey
#Used to encrypt session information
#https://www.elastic.co/guide/en/kibana/current/security-settings-kb.html#security-session-and-cookie-settings
xpack.encryptedSavedObjects.encryptionKey: random-key
",
],
]
`;

View file

@ -0,0 +1,56 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { pkg } from '../core/server/utils';
import Command from '../cli/command';
import { EncryptionConfig } from './encryption_config';
import { generateCli } from './generate';
const argv = process.env.kbnWorkerArgv
? JSON.parse(process.env.kbnWorkerArgv)
: process.argv.slice();
const program = new Command('bin/kibana-encryption-keys');
program.version(pkg.version).description('A tool for managing encryption keys');
const encryptionConfig = new EncryptionConfig();
generateCli(program, encryptionConfig);
program
.command('help <command>')
.description('Get the help for a specific command')
.action(function (cmdName) {
const cmd = Object.values(program.commands).find((command) => command._name === cmdName);
if (!cmd) return program.error(`unknown command ${cmdName}`);
cmd.help();
});
program.command('*', null, { noHelp: true }).action(function (cmd) {
program.error(`unknown command ${cmd}`);
});
// check for no command name
const subCommand = argv[2] && !String(argv[2][0]).match(/^-|^\.|\//);
if (!subCommand) {
program.defaultHelp();
}
program.parse(process.argv);

View file

@ -0,0 +1,21 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
require('../setup_node_env');
require('./cli_encryption_keys');

View file

@ -0,0 +1,21 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
require('../setup_node_env/dist');
require('./cli_encryption_keys');

View file

@ -0,0 +1,86 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import crypto from 'crypto';
import { join } from 'path';
import { get } from 'lodash';
import { readFileSync } from 'fs';
import { safeLoad } from 'js-yaml';
import { getConfigDirectory } from '@kbn/utils';
export class EncryptionConfig {
#config = safeLoad(readFileSync(join(getConfigDirectory(), 'kibana.yml')));
#encryptionKeyPaths = [
'xpack.encryptedSavedObjects.encryptionKey',
'xpack.reporting.encryptionKey',
'xpack.security.encryptionKey',
];
#encryptionMeta = {
'xpack.encryptedSavedObjects.encryptionKey': {
docs:
'https://www.elastic.co/guide/en/kibana/current/xpack-security-secure-saved-objects.html#xpack-security-secure-saved-objects',
description: 'Used to encrypt stored objects such as dashboards and visualizations',
},
'xpack.reporting.encryptionKey': {
docs:
'https://www.elastic.co/guide/en/kibana/current/reporting-settings-kb.html#general-reporting-settings',
description: 'Used to encrypt saved reports',
},
'xpack.security.encryptionKey': {
docs:
'https://www.elastic.co/guide/en/kibana/current/security-settings-kb.html#security-session-and-cookie-settings',
description: 'Used to encrypt session information',
},
};
_getEncryptionKey(key) {
return get(this.#config, key);
}
_hasEncryptionKey(key) {
return !!get(this.#config, key);
}
_generateEncryptionKey() {
return crypto.randomBytes(16).toString('hex');
}
docs({ comment } = {}) {
const commentString = comment ? '#' : '';
let docs = '';
this.#encryptionKeyPaths.forEach((key) => {
docs += `${commentString}${key}
${commentString}${this.#encryptionMeta[key].description}
${commentString}${this.#encryptionMeta[key].docs}
\n`;
});
return docs;
}
generate({ force = false }) {
const output = {};
this.#encryptionKeyPaths.forEach((key) => {
if (force || !this._hasEncryptionKey(key)) {
output[key] = this._generateEncryptionKey();
}
});
return output;
}
}

View file

@ -0,0 +1,83 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { EncryptionConfig } from './encryption_config';
import crypto from 'crypto';
import fs from 'fs';
describe('encryption key configuration', () => {
let encryptionConfig = null;
beforeEach(() => {
jest.spyOn(fs, 'readFileSync').mockReturnValue('xpack.security.encryptionKey: foo');
jest.spyOn(crypto, 'randomBytes').mockReturnValue('random-key');
encryptionConfig = new EncryptionConfig();
});
it('should be able to check for encryption keys', () => {
expect(encryptionConfig._hasEncryptionKey('xpack.reporting.encryptionKey')).toEqual(false);
expect(encryptionConfig._hasEncryptionKey('xpack.security.encryptionKey')).toEqual(true);
});
it('should be able to get encryption keys', () => {
expect(encryptionConfig._getEncryptionKey('xpack.reporting.encryptionKey')).toBeUndefined();
expect(encryptionConfig._getEncryptionKey('xpack.security.encryptionKey')).toEqual('foo');
});
it('should generate a key', () => {
expect(encryptionConfig._generateEncryptionKey()).toEqual('random-key');
});
it('should only generate unset keys', () => {
const output = encryptionConfig.generate({ force: false });
expect(output['xpack.security.encryptionKey']).toEqual(undefined);
expect(output['xpack.reporting.encryptionKey']).toEqual('random-key');
});
it('should regenerate all keys if the force flag is set', () => {
const output = encryptionConfig.generate({ force: true });
expect(output['xpack.security.encryptionKey']).toEqual('random-key');
expect(output['xpack.reporting.encryptionKey']).toEqual('random-key');
expect(output['xpack.encryptedSavedObjects.encryptionKey']).toEqual('random-key');
});
it('should set encryptedObjects and reporting with a default configuration', () => {
const output = encryptionConfig.generate({});
expect(output['xpack.security.encryptionKey']).toBeUndefined();
expect(output['xpack.encryptedSavedObjects.encryptionKey']).toEqual('random-key');
expect(output['xpack.reporting.encryptionKey']).toEqual('random-key');
});
});

View file

@ -0,0 +1,59 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { safeDump } from 'js-yaml';
import { isEmpty } from 'lodash';
import { interactive } from './interactive';
import { Logger } from '../cli_plugin/lib/logger';
export async function generate(encryptionConfig, command) {
const logger = new Logger();
const keys = encryptionConfig.generate({ force: command.force });
if (isEmpty(keys)) {
logger.log('No keys to write. Use the --force flag to generate new keys.');
} else {
if (!command.quiet) {
logger.log('## Kibana Encryption Key Generation Utility\n');
logger.log(
`The 'generate' command guides you through the process of setting encryption keys for:\n`
);
logger.log(encryptionConfig.docs());
logger.log(
'Already defined settings are ignored and can be regenerated using the --force flag. Check the documentation links for instructions on how to rotate encryption keys.'
);
logger.log('Definitions should be set in the kibana.yml used configure Kibana.\n');
}
if (command.interactive) {
await interactive(keys, encryptionConfig.docs({ comment: true }), logger);
} else {
if (!command.quiet) logger.log('Settings:');
logger.log(safeDump(keys));
}
}
}
export function generateCli(program, encryptionConfig) {
program
.command('generate')
.description('Generates encryption keys')
.option('-i, --interactive', 'interactive output')
.option('-q, --quiet', 'do not include instructions')
.option('-f, --force', 'generate new keys for all settings')
.action(generate.bind(null, encryptionConfig));
}

View file

@ -0,0 +1,56 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { EncryptionConfig } from './encryption_config';
import { generate } from './generate';
import { Logger } from '../cli_plugin/lib/logger';
describe('encryption key generation', () => {
const encryptionConfig = new EncryptionConfig();
beforeEach(() => {
Logger.prototype.log = jest.fn();
});
it('should generate a new encryption config', () => {
const command = {
force: false,
interactive: false,
quiet: false,
};
generate(encryptionConfig, command);
const keys = Logger.prototype.log.mock.calls[6][0];
expect(keys.search('xpack.encryptedSavedObjects.encryptionKey')).toBeGreaterThanOrEqual(0);
expect(keys.search('xpack.reporting.encryptionKey')).toBeGreaterThanOrEqual(0);
expect(keys.search('xpack.security.encryptionKey')).toBeGreaterThanOrEqual(0);
expect(keys.search('foo.bar')).toEqual(-1);
});
it('should only output keys if the quiet flag is set', () => {
generate(encryptionConfig, { quiet: true });
const keys = Logger.prototype.log.mock.calls[0][0];
const nextLog = Logger.prototype.log.mock.calls[1];
expect(keys.search('xpack.encryptedSavedObjects.encryptionKey')).toBeGreaterThanOrEqual(0);
expect(nextLog).toEqual(undefined);
});
afterEach(() => {
jest.restoreAllMocks();
});
});

View file

@ -0,0 +1,55 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { writeFileSync } from 'fs';
import { join } from 'path';
import { confirm, question } from '../cli_keystore/utils';
import { getConfigDirectory } from '@kbn/utils';
import { safeDump } from 'js-yaml';
export async function interactive(keys, docs, logger) {
const settings = Object.keys(keys);
logger.log(
'This tool will ask you a number of questions in order to generate the right set of keys for your needs.\n'
);
const setKeys = {};
for (const setting of settings) {
const include = await confirm(`Set ${setting}?`);
if (include) setKeys[setting] = keys[setting];
}
const count = Object.keys(setKeys).length;
const plural = count > 1 ? 's were' : ' was';
logger.log('');
if (!count) return logger.log('No keys were generated');
logger.log(`The following key${plural} generated:`);
logger.log(Object.keys(setKeys).join('\n'));
logger.log('');
const write = await confirm('Save generated keys to a sample Kibana configuration file?');
if (write) {
const defaultSaveLocation = join(getConfigDirectory(), 'kibana.sample.yml');
const promptedSaveLocation = await question(
`What filename should be used for the sample Kibana config file? [${defaultSaveLocation}])`
);
const saveLocation = promptedSaveLocation || defaultSaveLocation;
writeFileSync(saveLocation, docs + safeDump(setKeys));
logger.log(`Wrote configuration to ${saveLocation}`);
} else {
logger.log('\nSettings:');
logger.log(safeDump(setKeys));
}
}

View file

@ -0,0 +1,69 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { EncryptionConfig } from './encryption_config';
import { generate } from './generate';
import { Logger } from '../cli_plugin/lib/logger';
import * as prompt from '../cli_keystore/utils/prompt';
import fs from 'fs';
import crypto from 'crypto';
describe('encryption key generation interactive', () => {
const encryptionConfig = new EncryptionConfig();
beforeEach(() => {
Logger.prototype.log = jest.fn();
});
it('should prompt the user to write keys if the interactive flag is set', async () => {
jest
.spyOn(prompt, 'confirm')
.mockResolvedValueOnce(true)
.mockResolvedValueOnce(true)
.mockResolvedValueOnce(true)
.mockResolvedValueOnce(false);
jest.spyOn(prompt, 'question');
await generate(encryptionConfig, { interactive: true });
expect(prompt.confirm.mock.calls).toEqual([
['Set xpack.encryptedSavedObjects.encryptionKey?'],
['Set xpack.reporting.encryptionKey?'],
['Set xpack.security.encryptionKey?'],
['Save generated keys to a sample Kibana configuration file?'],
]);
expect(prompt.question).not.toHaveBeenCalled();
});
it('should write to disk partial keys', async () => {
jest
.spyOn(prompt, 'confirm')
.mockResolvedValueOnce(true)
.mockResolvedValueOnce(false)
.mockResolvedValueOnce(false)
.mockResolvedValueOnce(true);
jest.spyOn(prompt, 'question').mockResolvedValue('/foo/bar');
jest.spyOn(crypto, 'randomBytes').mockReturnValue('random-key');
fs.writeFileSync = jest.fn();
await generate(encryptionConfig, { interactive: true });
expect(fs.writeFileSync.mock.calls).toMatchSnapshot();
});
afterEach(() => {
jest.restoreAllMocks();
});
});

View file

@ -0,0 +1,29 @@
#!/bin/sh
SCRIPT=$0
# SCRIPT may be an arbitrarily deep series of symlinks. Loop until we have the concrete path.
while [ -h "$SCRIPT" ] ; do
ls=$(ls -ld "$SCRIPT")
# Drop everything prior to ->
link=$(expr "$ls" : '.*-> \(.*\)$')
if expr "$link" : '/.*' > /dev/null; then
SCRIPT="$link"
else
SCRIPT=$(dirname "$SCRIPT")/"$link"
fi
done
DIR="$(dirname "${SCRIPT}")/.."
CONFIG_DIR=${KBN_PATH_CONF:-"$DIR/config"}
NODE="${DIR}/node/bin/node"
test -x "$NODE"
if [ ! -x "$NODE" ]; then
echo "unable to find usable node.js executable."
exit 1
fi
if [ -f "${CONFIG_DIR}/node.options" ]; then
KBN_NODE_OPTS="$(grep -v ^# < ${CONFIG_DIR}/node.options | xargs)"
fi
NODE_OPTIONS="$KBN_NODE_OPTS $NODE_OPTIONS" "${NODE}" "${DIR}/src/cli_encryption_keys/dist" "$@"

View file

@ -27,6 +27,7 @@ export default {
'<rootDir>/src/legacy/server',
'<rootDir>/src/cli',
'<rootDir>/src/cli_keystore',
'<rootDir>/src/cli_encryption_keys',
'<rootDir>/src/cli_plugin',
'<rootDir>/packages/kbn-test/target/functional_test_runner',
'<rootDir>/src/dev',

View file

@ -172,7 +172,7 @@ describe('execute()', () => {
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"`
`"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."`
);
});

View file

@ -41,7 +41,7 @@ export function createExecutionEnqueuerFunction({
) {
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`
`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.`
);
}

View file

@ -322,7 +322,7 @@ test('throws an error when passing isESOUsingEphemeralEncryptionKey with value o
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"`
`"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."`
);
});

View file

@ -74,7 +74,7 @@ export class ActionExecutor {
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`
`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.`
);
}

View file

@ -56,7 +56,7 @@ describe('Actions Plugin', () => {
await plugin.setup(coreSetup as any, pluginsSetup);
expect(pluginsSetup.encryptedSavedObjects.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.'
'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.'
);
});
@ -116,7 +116,7 @@ describe('Actions Plugin', () => {
httpServerMock.createResponseFactory()
)) as unknown) as RequestHandlerContext['actions'];
expect(() => actionsContextHandler!.getActionsClient()).toThrowErrorMatchingInlineSnapshot(
`"Unable to create actions client due to the Encrypted Saved Objects plugin using an ephemeral encryption key. Please set xpack.encryptedSavedObjects.encryptionKey in kibana.yml"`
`"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."`
);
});
});
@ -252,7 +252,7 @@ describe('Actions Plugin', () => {
await expect(
pluginStart.getActionsClientWithRequest(httpServerMock.createKibanaRequest())
).rejects.toThrowErrorMatchingInlineSnapshot(
`"Unable to create actions client due to the Encrypted Saved Objects plugin using an ephemeral encryption key. Please set xpack.encryptedSavedObjects.encryptionKey in kibana.yml"`
`"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."`
);
});
});

View file

@ -171,7 +171,7 @@ export class ActionsPlugin implements Plugin<Promise<PluginSetupContract>, Plugi
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.'
'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.'
);
}
@ -292,7 +292,7 @@ export class ActionsPlugin implements Plugin<Promise<PluginSetupContract>, Plugi
) => {
if (isESOUsingEphemeralEncryptionKey === true) {
throw new Error(
`Unable to create actions client due to the Encrypted Saved Objects plugin using an ephemeral encryption key. Please set xpack.encryptedSavedObjects.encryptionKey in kibana.yml`
`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.`
);
}
@ -446,7 +446,7 @@ export class ActionsPlugin implements Plugin<Promise<PluginSetupContract>, Plugi
getActionsClient: () => {
if (isESOUsingEphemeralEncryptionKey === true) {
throw new Error(
`Unable to create actions client due to the Encrypted Saved Objects plugin using an ephemeral encryption key. Please set xpack.encryptedSavedObjects.encryptionKey in kibana.yml`
`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.`
);
}
return new ActionsClient({

View file

@ -52,7 +52,7 @@ describe('Alerting Plugin', () => {
expect(statusMock.set).toHaveBeenCalledTimes(1);
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.'
'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.'
);
});
});
@ -113,7 +113,7 @@ describe('Alerting Plugin', () => {
expect(() =>
startContract.getAlertsClientWithRequest({} as KibanaRequest)
).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"`
`"Unable to create alerts 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."`
);
});

View file

@ -169,7 +169,7 @@ export class AlertingPlugin {
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.'
'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.'
);
}
@ -296,7 +296,7 @@ export class AlertingPlugin {
const getAlertsClientWithRequest = (request: KibanaRequest) => {
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`
`Unable to create alerts 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.`
);
}
return alertsClientFactory!.create(request, core.savedObjects);

View file

@ -138,7 +138,7 @@ describe('createConfig()', () => {
expect(loggingSystemMock.collect(logger).warn).toMatchInlineSnapshot(`
Array [
Array [
"Generating a random key for xpack.encryptedSavedObjects.encryptionKey. To be able to decrypt encrypted saved objects attributes after restart, please set xpack.encryptedSavedObjects.encryptionKey in kibana.yml",
"Generating a random key for xpack.encryptedSavedObjects.encryptionKey. To decrypt encrypted saved objects attributes after restart, please set xpack.encryptedSavedObjects.encryptionKey in the kibana.yml or use the bin/kibana-encryption-keys command.",
],
]
`);

View file

@ -39,8 +39,8 @@ export function createConfig(config: TypeOf<typeof ConfigSchema>, logger: Logger
if (encryptionKey === undefined) {
logger.warn(
'Generating a random key for xpack.encryptedSavedObjects.encryptionKey. ' +
'To be able to decrypt encrypted saved objects attributes after restart, ' +
'please set xpack.encryptedSavedObjects.encryptionKey in kibana.yml'
'To decrypt encrypted saved objects attributes after restart, ' +
'please set xpack.encryptedSavedObjects.encryptionKey in the kibana.yml or use the bin/kibana-encryption-keys command.'
);
encryptionKey = crypto.randomBytes(16).toString('hex');

View file

@ -235,7 +235,7 @@ export class FleetPlugin
if (isESOUsingEphemeralEncryptionKey) {
if (this.logger) {
this.logger.warn(
'Fleet APIs are disabled due to the Encrypted Saved Objects plugin using an ephemeral encryption key. Please set xpack.encryptedSavedObjects.encryptionKey in kibana.yml.'
'Fleet 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.'
);
}
} else {

View file

@ -70,7 +70,7 @@ describe('Reporting server createConfig$', () => {
`);
expect((mockLogger.warn as any).mock.calls.length).toBe(1);
expect((mockLogger.warn as any).mock.calls[0]).toMatchObject([
'Generating a random key for xpack.reporting.encryptionKey. To prevent sessions from being invalidated on restart, please set xpack.reporting.encryptionKey in kibana.yml',
'Generating a random key for xpack.reporting.encryptionKey. To prevent sessions from being invalidated on restart, please set xpack.reporting.encryptionKey in the kibana.yml or use the bin/kibana-encryption-keys command.',
]);
});

View file

@ -35,7 +35,7 @@ export function createConfig$(
i18n.translate('xpack.reporting.serverConfig.randomEncryptionKey', {
defaultMessage:
'Generating a random key for xpack.reporting.encryptionKey. To prevent sessions from being invalidated on ' +
'restart, please set xpack.reporting.encryptionKey in kibana.yml',
'restart, please set xpack.reporting.encryptionKey in the kibana.yml or use the bin/kibana-encryption-keys command.',
})
);
encryptionKey = crypto.randomBytes(16).toString('hex');

View file

@ -1119,12 +1119,12 @@ describe('createConfig()', () => {
expect(config.encryptionKey).toEqual('ab'.repeat(16));
expect(loggingSystemMock.collect(logger).warn).toMatchInlineSnapshot(`
Array [
Array [
"Generating a random key for xpack.security.encryptionKey. To prevent sessions from being invalidated on restart, please set xpack.security.encryptionKey in kibana.yml",
],
]
`);
Array [
Array [
"Generating a random key for xpack.security.encryptionKey. To prevent sessions from being invalidated on restart, please set xpack.security.encryptionKey in the kibana.yml or use the bin/kibana-encryption-keys command.",
],
]
`);
});
it('should log a warning if SSL is not configured', async () => {

View file

@ -252,7 +252,7 @@ export function createConfig(
if (encryptionKey === undefined) {
logger.warn(
'Generating a random key for xpack.security.encryptionKey. To prevent sessions from being invalidated on ' +
'restart, please set xpack.security.encryptionKey in kibana.yml'
'restart, please set xpack.security.encryptionKey in the kibana.yml or use the bin/kibana-encryption-keys command.'
);
encryptionKey = crypto.randomBytes(16).toString('hex');