Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add SSL support when starting Elasticsearch from yarn es #42527

Merged
merged 10 commits into from
Aug 7, 2019
3 changes: 2 additions & 1 deletion packages/kbn-es/src/cli_commands/archive.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ exports.help = (defaults = {}) => {
--install-path Installation path, defaults to 'source' within base-path
--password Sets password for elastic user [default: ${password}]
--password.[user] Sets password for native realm user [default: ${password}]
--ssl Sets up SSL on Elasticsearch
-E Additional key=value settings to pass to Elasticsearch

Example:
Expand All @@ -56,7 +57,7 @@ exports.run = async (defaults = {}) => {
default: defaults,
});

const cluster = new Cluster();
const cluster = new Cluster({ ssl: options.ssl });
const [, path] = options._;

if (!path || !path.endsWith('tar.gz')) {
Expand Down
3 changes: 2 additions & 1 deletion packages/kbn-es/src/cli_commands/snapshot.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ exports.help = (defaults = {}) => {
--password.[user] Sets password for native realm user [default: ${password}]
-E Additional key=value settings to pass to Elasticsearch
--download-only Download the snapshot but don't actually start it
--ssl Sets up SSL on Elasticsearch

Example:

Expand All @@ -62,7 +63,7 @@ exports.run = async (defaults = {}) => {
default: defaults,
});

const cluster = new Cluster();
const cluster = new Cluster({ ssl: options.ssl });
if (options['download-only']) {
await cluster.downloadSnapshot(options);
} else {
Expand Down
3 changes: 2 additions & 1 deletion packages/kbn-es/src/cli_commands/source.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ exports.help = (defaults = {}) => {
--data-archive Path to zip or tarball containing an ES data directory to seed the cluster with.
--password Sets password for elastic user [default: ${password}]
--password.[user] Sets password for native realm user [default: ${password}]
--ssl Sets up SSL on Elasticsearch
-E Additional key=value settings to pass to Elasticsearch

Example:
Expand All @@ -58,7 +59,7 @@ exports.run = async (defaults = {}) => {
default: defaults,
});

const cluster = new Cluster();
const cluster = new Cluster({ ssl: options.ssl });
const { installPath } = await cluster.installSource(options);

if (options.dataArchive) {
Expand Down
36 changes: 30 additions & 6 deletions packages/kbn-es/src/cluster.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
* under the License.
*/

const fs = require('fs');
const util = require('util');
const execa = require('execa');
const chalk = require('chalk');
const path = require('path');
Expand All @@ -33,6 +35,8 @@ const { createCliError } = require('./errors');
const { promisify } = require('util');
const treeKillAsync = promisify(require('tree-kill'));
const { parseSettings, SettingsFilter } = require('./settings');
const { caCertPath, esKeyPath, esCertPath } = require('./constants');
const readFile = util.promisify(fs.readFile);

// listen to data on stream until map returns anything but undefined
const first = (stream, map) =>
Expand All @@ -48,8 +52,10 @@ const first = (stream, map) =>
});

exports.Cluster = class Cluster {
constructor(log = defaultLog) {
constructor({ log = defaultLog, ssl = false } = {}) {
this._log = log;
this._ssl = ssl;
this._caCertPromise = ssl ? readFile(caCertPath) : undefined;
}

/**
Expand Down Expand Up @@ -251,10 +257,21 @@ exports.Cluster = class Cluster {
this._log.info(chalk.bold('Starting'));
this._log.indent(4);

const args = parseSettings(
extractConfigFiles(options.esArgs || [], installPath, { log: this._log }),
{ filter: SettingsFilter.NonSecureOnly }
).reduce(
// Add to esArgs if ssl is enabled
const esArgs = (typeof options.esArgs === 'string'
mikecote marked this conversation as resolved.
Show resolved Hide resolved
? [options.esArgs]
: options.esArgs || []
).slice(0);
if (this._ssl) {
esArgs.push('xpack.security.http.ssl.enabled=true');
esArgs.push(`xpack.security.http.ssl.key=${esKeyPath}`);
esArgs.push(`xpack.security.http.ssl.certificate=${esCertPath}`);
esArgs.push(`xpack.security.http.ssl.certificate_authorities=${caCertPath}`);
}

const args = parseSettings(extractConfigFiles(esArgs, installPath, { log: this._log }), {
filter: SettingsFilter.NonSecureOnly,
}).reduce(
(acc, [settingName, settingValue]) => acc.concat(['-E', `${settingName}=${settingValue}`]),
[]
);
Expand Down Expand Up @@ -282,7 +299,14 @@ exports.Cluster = class Cluster {

// once the http port is available setup the native realm
this._nativeRealmSetup = httpPort.then(async port => {
const nativeRealm = new NativeRealm(options.password, port, this._log);
const caCert = await this._caCertPromise;
const nativeRealm = new NativeRealm({
port,
caCert,
log: this._log,
elasticPassword: options.password,
protocol: this._ssl ? 'https' : 'http',
mikecote marked this conversation as resolved.
Show resolved Hide resolved
});
await nativeRealm.setPasswords(options);
});

Expand Down
24 changes: 24 additions & 0 deletions packages/kbn-es/src/constants.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* 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.
*/

const path = require('path');

exports.caCertPath = path.resolve(__dirname, '../../../test/dev_certs/ca.crt');
mikecote marked this conversation as resolved.
Show resolved Hide resolved
exports.esKeyPath = path.resolve(__dirname, '../../../test/dev_certs/elasticsearch.key');
exports.esCertPath = path.resolve(__dirname, '../../../test/dev_certs/elasticsearch.crt');
44 changes: 26 additions & 18 deletions packages/kbn-es/src/integration_tests/__fixtures__/es_bin.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,11 @@
* under the License.
*/

const { createServer } = require('http');
const fs = require('fs');
const { format: formatUrl } = require('url');
const { exitCode, start } = JSON.parse(process.argv[2]);
const { exitCode, start, ssl } = JSON.parse(process.argv[2]);
const { createServer } = ssl ? require('https') : require('http');
const { esKeyPath, esCertPath } = require('../../constants');

process.exitCode = exitCode;

Expand All @@ -30,27 +32,33 @@ if (!start) {
}

let serverUrl;
const server = createServer((req, res) => {
const url = new URL(req.url, serverUrl);
const send = (code, body) => {
res.writeHead(code, { 'content-type': 'application/json' });
res.end(JSON.stringify(body));
};
const server = createServer(
{
key: ssl ? fs.readFileSync(esKeyPath) : undefined,
cert: ssl ? fs.readFileSync(esCertPath) : undefined,
},
(req, res) => {
const url = new URL(req.url, serverUrl);
const send = (code, body) => {
res.writeHead(code, { 'content-type': 'application/json' });
res.end(JSON.stringify(body));
};

if (url.pathname === '/_xpack') {
return send(400, {
if (url.pathname === '/_xpack') {
return send(400, {
error: {
reason: 'foo bar',
},
});
}

return send(404, {
error: {
reason: 'foo bar',
reason: 'not found',
},
});
}

return send(404, {
error: {
reason: 'not found',
},
});
});
);

// setup server auto close after 1 second of silence
let serverCloseTimer;
Expand Down
Loading