diff --git a/README.md b/README.md index e181bd95..0ffbbc1f 100644 --- a/README.md +++ b/README.md @@ -103,6 +103,15 @@ Then you need to run the server with `-S` for enabling SSL and `-C` for your cer http-server -S -C cert.pem ``` +If you wish to use a passphrase with your private key you can include one in the openssl command via the -passout parameter (using password of foobar) + + +e.g. +`openssl req -newkey rsa:2048 -passout pass:foobar -keyout key.pem -x509 -days 365 -out cert.pem` + +For security reasons, the passphrase will only be read from the `NODE_HTTP_SERVER_SSL_PASSPHRASE` environment variable. + + This is what should be output if successful: ``` sh diff --git a/bin/http-server b/bin/http-server index ed92ab7d..3b9e59d2 100755 --- a/bin/http-server +++ b/bin/http-server @@ -68,6 +68,7 @@ if (argv.h || argv.help) { var port = argv.p || argv.port || parseInt(process.env.PORT, 10), host = argv.a || '0.0.0.0', tls = argv.S || argv.tls, + sslPassphrase = process.env.NODE_HTTP_SERVER_SSL_PASSPHRASE, proxy = argv.P || argv.proxy, proxyOptions = argv['proxy-options'], utc = argv.U || argv.utc, @@ -175,7 +176,8 @@ function listen(port) { if (tls) { options.https = { cert: argv.C || argv.cert || 'cert.pem', - key: argv.K || argv.key || 'key.pem' + key: argv.K || argv.key || 'key.pem', + passphrase: sslPassphrase, }; try { fs.lstatSync(options.https.cert); diff --git a/doc/http-server.1 b/doc/http-server.1 index d4aa4397..bbd87e82 100644 --- a/doc/http-server.1 +++ b/doc/http-server.1 @@ -114,6 +114,7 @@ If not specified, uses cert.pem. .BI \-K ", " \-\-key " " [\fIFILE\fR] Path to SSL key file. If not specified, uses key.pem. +Passphrase will be read from NODE_HTTP_SERVER_SSL_PASSPHRASE (if set) .TP .BI \-r ", " \-\-robots " " [\fIUSER\-AGENT\fR] diff --git a/lib/http-server.js b/lib/http-server.js index a3fdea78..0b11fd2b 100644 --- a/lib/http-server.js +++ b/lib/http-server.js @@ -173,7 +173,11 @@ function HttpServer(options) { serverOptions.https = options.https; } - this.server = union.createServer(serverOptions); + this.server = serverOptions.https && serverOptions.https.passphrase + // if passphrase is set, shim must be used as union does not support + ? require('./shims/https-server-shim')(serverOptions) + : union.createServer(serverOptions); + if (options.timeout !== undefined) { this.server.setTimeout(options.timeout); } diff --git a/lib/shims/https-server-shim.js b/lib/shims/https-server-shim.js new file mode 100644 index 00000000..30d4fc58 --- /dev/null +++ b/lib/shims/https-server-shim.js @@ -0,0 +1,67 @@ +/* eslint-disable no-process-env */ +/* eslint-disable no-sync */ +var https = require('https'); +var fs = require('fs'); +var core = require('union/lib/core'); +var RoutingStream = require('union/lib/routing-stream'); + +module.exports = function (options) { + var isArray = Array.isArray(options.after); + var credentials; + + if (!options) { + throw new Error('options is required to create a server'); + } + + function requestHandler(req, res) { + var routingStream = new RoutingStream({ + before: options.before, + buffer: options.buffer, + after: + isArray && + options.after.map(function (After) { + return new After(); + }), + request: req, + response: res, + limit: options.limit, + headers: options.headers + }); + + routingStream.on('error', function (err) { + var fn = options.onError || core.errorHandler; + fn(err, routingStream, routingStream.target, function () { + routingStream.target.emit('next'); + }); + }); + + req.pipe(routingStream); + } + + var serverOptions; + + serverOptions = options.https; + if (!serverOptions.key || !serverOptions.cert) { + throw new Error( + 'Both options key and cert are required.' + ); + } + + credentials = { + key: fs.readFileSync(serverOptions.key), + cert: fs.readFileSync(serverOptions.cert), + passphrase: process.env.NODE_HTTP_SERVER_SSL_PASSPHRASE + }; + + if (serverOptions.ca) { + serverOptions.ca = !Array.isArray(serverOptions.ca) + ? [serverOptions.ca] + : serverOptions.ca; + + credentials.ca = serverOptions.ca.map(function (ca) { + return fs.readFileSync(ca); + }); + } + + return https.createServer(credentials, requestHandler); +};