[node] Enable openssl legacy provider (#163190)

This is to prevent a breaking change in a minor release of Kibana due to
an underlying upgrade of Node.js to v18.
The legacy provider can be disabled by removing
`--openssl-legacy-provider` in `config/node.options`.

[Node.js
documentation](https://nodejs.org/docs/latest-v18.x/api/cli.html#--openssl-legacy-provider)
[OpenSSL
documentation](https://www.openssl.org/docs/man3.0/man7/OSSL_PROVIDER-legacy.html)

---------

Co-authored-by: Thomas Watson <w@tson.dk>
This commit is contained in:
Jon 2023-08-30 13:51:10 -05:00 committed by GitHub
parent a511426e83
commit aebd6f3923
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 132 additions and 2 deletions

View file

@ -10,3 +10,6 @@
## restore < Node 16 default DNS lookup behavior ## restore < Node 16 default DNS lookup behavior
--dns-result-order=ipv4first --dns-result-order=ipv4first
## enable OpenSSL 3 legacy provider
--openssl-legacy-provider

View file

@ -118,3 +118,12 @@ The option accepts a limit in MB:
-------- --------
--max-old-space-size=2048 --max-old-space-size=2048
-------- --------
[float]
[[openssl-legacy-provider]]
=== OpenSSL Legacy Provider
Starting in 8.10.0, {kib} has upgraded its runtime environment, Node.js, from version 16 to version 18 and with it the underlying version of OpenSSL to version 3.
Algorithms deemed legacy by OpenSSL 3 have been re-enabled to avoid potential breaking changes in a minor version release of {kib}.
If SSL certificates configured for {kib} are not using any of the legacy algorithms mentioned in the https://www.openssl.org/docs/man3.0/man7/OSSL_PROVIDER-legacy.html[OpenSSL legacy provider documentation],
we recommend disabling this setting by removing `--openssl-legacy-provider` in the `node.options` config file.

View file

@ -54,7 +54,8 @@ it('builds a generated plugin into a viable archive', async () => {
}; };
expect(filterLogs(generateProc.all)).toMatchInlineSnapshot(` expect(filterLogs(generateProc.all)).toMatchInlineSnapshot(`
" succ 🎉 "Kibana is currently running with legacy OpenSSL providers enabled! For details and instructions on how to disable see https://www.elastic.co/guide/en/kibana/current/production.html#openssl-legacy-provider
succ 🎉
Your plugin has been created in plugins/foo_test_plugin Your plugin has been created in plugins/foo_test_plugin
" "
@ -73,7 +74,8 @@ it('builds a generated plugin into a viable archive', async () => {
); );
expect(filterLogs(buildProc.all)).toMatchInlineSnapshot(` expect(filterLogs(buildProc.all)).toMatchInlineSnapshot(`
" info deleting the build and target directories "Kibana is currently running with legacy OpenSSL providers enabled! For details and instructions on how to disable see https://www.elastic.co/guide/en/kibana/current/production.html#openssl-legacy-provider
info deleting the build and target directories
info run bazel and build required artifacts for the optimizer info run bazel and build required artifacts for the optimizer
succ bazel run successfully and artifacts were created succ bazel run successfully and artifacts were created
info running @kbn/optimizer info running @kbn/optimizer

View file

@ -127,6 +127,9 @@ COPY --chown=1000:0 config/serverless.es.yml /usr/share/kibana/config/serverless
COPY --chown=1000:0 config/serverless.oblt.yml /usr/share/kibana/config/serverless.oblt.yml COPY --chown=1000:0 config/serverless.oblt.yml /usr/share/kibana/config/serverless.oblt.yml
COPY --chown=1000:0 config/serverless.security.yml /usr/share/kibana/config/serverless.security.yml COPY --chown=1000:0 config/serverless.security.yml /usr/share/kibana/config/serverless.security.yml
{{/serverless}} {{/serverless}}
{{^opensslLegacyProvider}}
RUN sed 's/\(--openssl-legacy-provider\)/#\1/' -i config/node.options
{{/opensslLegacyProvider}}
# Add the launcher/wrapper script. It knows how to interpret environment # Add the launcher/wrapper script. It knows how to interpret environment
# variables and translate them to Kibana CLI options. # variables and translate them to Kibana CLI options.

View file

@ -19,6 +19,7 @@ function generator(options: TemplateContext) {
packageManager: options.baseImage.includes('ubi') ? 'microdnf' : 'apt-get', packageManager: options.baseImage.includes('ubi') ? 'microdnf' : 'apt-get',
ubi: options.baseImage.includes('ubi'), ubi: options.baseImage.includes('ubi'),
ubuntu: options.baseImage === 'ubuntu', ubuntu: options.baseImage === 'ubuntu',
opensslLegacyProvider: !(options.cloud || options.serverless),
...options, ...options,
}); });
} }

View file

@ -0,0 +1,18 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
var branch = require('../../../package.json').branch;
var docsBranch = branch.match(/^\d\.\d\d?$/) || 'current';
var openSSLLegacyProviderEnabled = require('./openssl_legacy_provider_enabled')();
if (openSSLLegacyProviderEnabled) {
console.log(
'Kibana is currently running with legacy OpenSSL providers enabled! For details and instructions on how to disable see https://www.elastic.co/guide/en/kibana/' +
docsBranch +
'/production.html#openssl-legacy-provider'
);
}

View file

@ -0,0 +1,14 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
var crypto = require('crypto');
// The blowfish cipher is only available when node is running with the --openssl-legacy-provider flag
module.exports = function () {
return crypto.getCiphers().includes('blowfish');
};

View file

@ -0,0 +1,78 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
var spawnSync = require('child_process').spawnSync;
describe('openSSLLegacyProviderEnabled', function () {
function runLegacyProviderCheck(execOptions, nodeOptions) {
var result = spawnSync(
process.execPath,
(execOptions ? execOptions.split(' ') : []).concat([
'-p',
"require('./openssl_legacy_provider_enabled')()",
]),
{
env: {
NODE_OPTIONS: nodeOptions || '',
},
encoding: 'utf-8',
cwd: __dirname,
}
);
var stdout = result.stdout.trim();
return stdout === 'true';
}
it('should be disabled by default', function () {
expect(runLegacyProviderCheck()).toBe(false);
});
describe('using NODE_OPTIONS', function () {
it('should be enabled when --openssl-legacy-provider is set', function () {
expect(runLegacyProviderCheck(null, '--openssl-legacy-provider')).toBe(true);
});
it('should be enabled when --openssl-legacy-provider is set after --no-openssl-legacy-provider', function () {
expect(
runLegacyProviderCheck(null, '--no-openssl-legacy-provider --openssl-legacy-provider')
).toBe(true);
});
it('should be disabled when --no-openssl-legacy-provider is set', function () {
expect(runLegacyProviderCheck(null, '--no-openssl-legacy-provider')).toBe(false);
});
it('should be disabled when --no-openssl-legacy-provider is set after --openssl-legacy-provider', function () {
expect(
runLegacyProviderCheck(null, '--openssl-legacy-provider --no-openssl-legacy-provider')
).toBe(false);
});
});
describe('using exec arguments', function () {
it('should be enabled when --openssl-legacy-provider is set', function () {
expect(runLegacyProviderCheck('--openssl-legacy-provider')).toBe(true);
});
it('should be enabled when --openssl-legacy-provider is set after --no-openssl-legacy-provider', function () {
expect(runLegacyProviderCheck('--no-openssl-legacy-provider --openssl-legacy-provider')).toBe(
true
);
});
it('should be disabled when --no-openssl-legacy-provider is set', function () {
expect(runLegacyProviderCheck('--no-openssl-legacy-provider')).toBe(false);
});
it('should be disabled when --no-openssl-legacy-provider is set after --openssl-legacy-provider', function () {
expect(runLegacyProviderCheck('--openssl-legacy-provider --no-openssl-legacy-provider')).toBe(
false
);
});
});
});

View file

@ -14,3 +14,4 @@ require('./harden');
require('symbol-observable'); require('symbol-observable');
require('source-map-support').install(); require('source-map-support').install();
require('./node_version_validator'); require('./node_version_validator');
require('./openssl_legacy_provider');

View file

@ -6,6 +6,7 @@
"include": [ "include": [
"harden/**/*", "harden/**/*",
"root/**/*", "root/**/*",
"openssl_legacy_provider/**/*",
"*.js", "*.js",
"*.ts", "*.ts",
], ],