From 8b7535f6259ca4bcc6cd1b89412ffb27b4d71077 Mon Sep 17 00:00:00 2001 From: Chris Jones Date: Sat, 9 Oct 2021 16:53:49 +1100 Subject: [PATCH 1/5] add passphrase option add a shim to enable configuring ssl passphrase update readme --- README.md | 9 +++++ bin/http-server | 4 ++- lib/http-server.js | 6 +++- lib/shims/https-server-shim.js | 61 ++++++++++++++++++++++++++++++++++ 4 files changed, 78 insertions(+), 2 deletions(-) create mode 100644 lib/shims/https-server-shim.js diff --git a/README.md b/README.md index ec6f4c9a..d9a4438b 100644 --- a/README.md +++ b/README.md @@ -102,6 +102,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 rather than the command line http-server will read this 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 91ced18d..893e6f91 100755 --- a/bin/http-server +++ b/bin/http-server @@ -61,6 +61,7 @@ if (argv.h || argv.help) { var port = argv.p || argv.port || parseInt(process.env.PORT, 10), host = argv.a || '0.0.0.0', ssl = argv.S || argv.ssl, + sslPassphrase = process.env.NODE_HTTP_SERVER_SSL_PASSPHRASE, proxy = argv.P || argv.proxy, utc = argv.U || argv.utc, version = argv.v || argv.version, @@ -143,7 +144,8 @@ function listen(port) { if (ssl) { 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/lib/http-server.js b/lib/http-server.js index 996db6fd..af669b88 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 = options.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..9be8b690 --- /dev/null +++ b/lib/shims/https-server-shim.js @@ -0,0 +1,61 @@ +var https = require('https'); +var fs = require('fs'); +var RoutingStream = require('union/lib/routing-stream'); + +module.exports = function (options) { + var isArray = Array.isArray(options.after), + 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, + credentials; + + serverOptions = options.https; + if (!serverOptions.key || !serverOptions.cert) { + throw new Error('Both options.' + key + '.`key` and options.' + key + '.`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); +}; \ No newline at end of file From d21714fe7b4dc1caabbfa0c7b00d505e35ad47e0 Mon Sep 17 00:00:00 2001 From: Chris Jones Date: Sat, 9 Oct 2021 17:05:49 +1100 Subject: [PATCH 2/5] add passphrase info to http-server.1 in doc --- doc/http-server.1 | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/http-server.1 b/doc/http-server.1 index 671e156d..445b6009 100644 --- a/doc/http-server.1 +++ b/doc/http-server.1 @@ -110,6 +110,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] From d482a2fe08af8853bd0787abd06c875a00f5bb60 Mon Sep 17 00:00:00 2001 From: Chris Jones Date: Fri, 15 Oct 2021 19:35:10 +1100 Subject: [PATCH 3/5] Update README.md Co-authored-by: Jade Michael Thornton --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d9a4438b..5d70a79c 100644 --- a/README.md +++ b/README.md @@ -108,7 +108,7 @@ If you wish to use a passphrase with your private key you can include one in the e.g. `openssl req -newkey rsa:2048 -passout pass:foobar -keyout key.pem -x509 -days 365 -out cert.pem` -For security reasons rather than the command line http-server will read this from the `NODE_HTTP_SERVER_SSL_PASSPHRASE` environment variable. +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: From df39f60322fddc8bb2799368b96344d513f4e6be Mon Sep 17 00:00:00 2001 From: Chris Jones Date: Fri, 15 Oct 2021 19:49:54 +1100 Subject: [PATCH 4/5] fix broken unit test --- lib/http-server.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/http-server.js b/lib/http-server.js index a3ad627a..0b11fd2b 100644 --- a/lib/http-server.js +++ b/lib/http-server.js @@ -173,7 +173,7 @@ function HttpServer(options) { serverOptions.https = options.https; } - this.server = options.https.passphrase + 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); From 7c510cf95cf1eb10bbd210664d32350df250f61e Mon Sep 17 00:00:00 2001 From: Chris Jones Date: Fri, 15 Oct 2021 20:37:47 +1100 Subject: [PATCH 5/5] fix errors and formatting in shim --- lib/shims/https-server-shim.js | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/lib/shims/https-server-shim.js b/lib/shims/https-server-shim.js index 9be8b690..30d4fc58 100644 --- a/lib/shims/https-server-shim.js +++ b/lib/shims/https-server-shim.js @@ -1,10 +1,13 @@ +/* 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), - credentials; + var isArray = Array.isArray(options.after); + var credentials; if (!options) { throw new Error('options is required to create a server'); @@ -14,9 +17,11 @@ module.exports = function (options) { var routingStream = new RoutingStream({ before: options.before, buffer: options.buffer, - after: isArray && options.after.map(function (After) { - return new After; - }), + after: + isArray && + options.after.map(function (After) { + return new After(); + }), request: req, response: res, limit: options.limit, @@ -33,16 +38,17 @@ module.exports = function (options) { req.pipe(routingStream); } - var serverOptions, - credentials; + var serverOptions; serverOptions = options.https; if (!serverOptions.key || !serverOptions.cert) { - throw new Error('Both options.' + key + '.`key` and options.' + key + '.`cert` are required.'); + throw new Error( + 'Both options key and cert are required.' + ); } credentials = { - key: fs.readFileSync(serverOptions.key), + key: fs.readFileSync(serverOptions.key), cert: fs.readFileSync(serverOptions.cert), passphrase: process.env.NODE_HTTP_SERVER_SSL_PASSPHRASE }; @@ -50,7 +56,7 @@ module.exports = function (options) { if (serverOptions.ca) { serverOptions.ca = !Array.isArray(serverOptions.ca) ? [serverOptions.ca] - : serverOptions.ca + : serverOptions.ca; credentials.ca = serverOptions.ca.map(function (ca) { return fs.readFileSync(ca); @@ -58,4 +64,4 @@ module.exports = function (options) { } return https.createServer(credentials, requestHandler); -}; \ No newline at end of file +};