From 3a86624b8bc2bbaef99b3308b195ab46f28a6c48 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Thu, 31 Mar 2016 02:39:15 -0400 Subject: [PATCH] minor refactor --- boot/master.js | 129 +++++++++++++++++++++-------------------- lib/insecure-server.js | 32 +++++----- lib/master.js | 30 +++------- 3 files changed, 86 insertions(+), 105 deletions(-) diff --git a/boot/master.js b/boot/master.js index 5442a39..0f058da 100644 --- a/boot/master.js +++ b/boot/master.js @@ -14,52 +14,7 @@ var cluster = require('cluster'); //var minWorkers = 2; var numCores = 2; // Math.max(minWorkers, require('os').cpus().length); var workers = []; -var config = { - externalPort: 443 // world accessible -, externalPortInsecure: 80 // world accessible -// TODO externalInsecurePort? -, locked: false // TODO XXX -, ipcKey: null - // XXX - // TODO needs mappings from db - // TODO autoconfig Caddy caddy - // XXX -, caddy: { - conf: __dirname + '/Caddyfile' - , bin: '/usr/local/bin/caddy' - , sitespath: path.join(__dirname, 'sites-enabled') - } -, redirects: [ - { "ip": false, "id": "*", "value": false } // default no-www - - , { "ip": false, "id": "daplie.domains", "value": null } - , { "ip": false, "id": "*.daplie.domains", "value": false } - , { "ip": false, "id": "no.daplie.domains", "value": false } - , { "ip": false, "id": "*.no.daplie.domains", "value": false } - , { "ip": false, "id": "ns2.daplie.domains", "value": false } - - , { "ip": true, "id": "maybe.daplie.domains", "value": null } - , { "ip": true, "id": "*.maybe.daplie.domains", "value": null } - - , { "ip": true, "id": "www.daplie.domains", "value": null } - , { "ip": true, "id": "yes.daplie.domains", "value": true } - , { "ip": true, "id": "*.yes.daplie.domains", "value": true } - , { "ip": true, "id": "ns1.daplie.domains", "value": false } - ] - // TODO use sqlite3 or autogenerate ? -, privkey: require('fs').readFileSync(__dirname + '/../../' + '/nsx.redirect-www.org.key.pem', 'ascii') -, pubkey: require('fs').readFileSync(__dirname + '/../../' + '/nsx.redirect-www.org.key.pem.pub', 'ascii') -// keys -// letsencrypt -// com.example.provider -// com.example.consumer -}; -var useCaddy = require('fs').existsSync(config.caddy.bin); -var state = {}; -var caddy; - -config.localPort = process.argv[2] || (useCaddy ? 4080 : 443); // system / local network -config.insecurePort = process.argv[3] || (useCaddy ? 80 : 80); // meh +var state = { firstRun: true }; function fork() { if (workers.length < numCores) { @@ -71,10 +26,39 @@ cluster.on('online', function (worker) { console.info('[MASTER] Worker ' + worker.process.pid + ' is online'); fork(); + var config = { + externalPort: 443 // world accessible + , externalPortInsecure: 80 // world accessible + // TODO externalInsecurePort? + , locked: false // TODO XXX + // XXX + // TODO needs mappings from db + // TODO autoconfig Caddy caddy + // XXX + , caddy: { + conf: __dirname + '/Caddyfile' + , bin: '/usr/local/bin/caddy' + , sitespath: path.join(__dirname, 'sites-enabled') + } + }; + var useCaddy = require('fs').existsSync(config.caddy.bin); + var caddy; + + config.localPort = process.argv[2] || (useCaddy ? 4080 : 443); // system / local network + config.insecurePort = process.argv[3] || (useCaddy ? 80 : 80); // meh + if (state.firstRun) { + state.firstRun = false; + if (useCaddy) { + caddy = require('../lib/spawn-caddy').create(config); + // relies on { localPort, locked } + caddy.spawn(config); + } + } + // TODO XXX Should these be configurable? If so, where? var certPaths = [ - path.join(__dirname, 'certs', 'live') - , path.join(__dirname, 'letsencrypt', 'live') + path.join(__dirname, '..', '..', 'certs', 'live') + , path.join(__dirname, '..', '..', 'letsencrypt', 'live') ]; // TODO communicate config with environment vars? var info = { @@ -84,16 +68,10 @@ cluster.on('online', function (worker) { , externalPort: config.externalPort , localPort: config.localPort , insecurePort: config.insecurePort - , trustProxy: useCaddy ? true : false , certPaths: useCaddy ? null : certPaths - , ipcKey: null - // TODO let this load after server is listening - , 'org.oauth3.consumer': config['org.oauth3.consumer'] - , 'org.oauth3.provider': config['org.oauth3.provider'] - , keys: config.keys + , trustProxy: useCaddy ? true : false } }; - worker.send(info); function touchMaster(msg) { if ('walnut.webserver.listening' !== msg.type) { @@ -105,17 +83,48 @@ cluster.on('online', function (worker) { // calls init if init has not been called state.caddy = caddy; state.workers = workers; - require('../lib/master').touch(config, state).then(function () { + require('../lib/master').touch(config, state).then(function (results) { + //var memstore = results.memstore; + var sqlstore = results.sqlstore; info.type = 'walnut.webserver.onrequest'; - info.conf.ipcKey = config.ipcKey; + // TODO let this load after server is listening + info.conf['org.oauth3.consumer'] = config['org.oauth3.consumer']; + info.conf['org.oauth3.provider'] = config['org.oauth3.provider']; + info.conf.keys = config.keys; info.conf.memstoreSock = config.memstoreSock; info.conf.sqlite3Sock = config.sqlite3Sock; // TODO get this from db config instead info.conf.privkey = config.privkey; info.conf.pubkey = config.pubkey; + info.conf.redirects = [ + { "ip": false, "id": "*", "value": false } // default no-www + + , { "ip": false, "id": "daplie.domains", "value": null } + , { "ip": false, "id": "*.daplie.domains", "value": false } + , { "ip": false, "id": "no.daplie.domains", "value": false } + , { "ip": false, "id": "*.no.daplie.domains", "value": false } + , { "ip": false, "id": "ns2.daplie.domains", "value": false } + + , { "ip": true, "id": "maybe.daplie.domains", "value": null } + , { "ip": true, "id": "*.maybe.daplie.domains", "value": null } + + , { "ip": true, "id": "www.daplie.domains", "value": null } + , { "ip": true, "id": "yes.daplie.domains", "value": true } + , { "ip": true, "id": "*.yes.daplie.domains", "value": true } + , { "ip": true, "id": "ns1.daplie.domains", "value": false } + ]; + // TODO use sqlite3 or autogenerate ? + info.conf.privkey = require('fs').readFileSync(__dirname + '/../../' + '/nsx.redirect-www.org.key.pem', 'ascii'); + info.conf.pubkey = require('fs').readFileSync(__dirname + '/../../' + '/nsx.redirect-www.org.key.pem.pub', 'ascii'); + // keys + // letsencrypt + // com.example.provider + // com.example.consumer worker.send(info); }); } + + worker.send(info); worker.on('message', touchMaster); }); @@ -136,9 +145,3 @@ cluster.on('exit', function (worker, code, signal) { }); fork(); - -if (useCaddy) { - caddy = require('../lib/spawn-caddy').create(config); - // relies on { localPort, locked } - caddy.spawn(config); -} diff --git a/lib/insecure-server.js b/lib/insecure-server.js index afb2a28..1dc5837 100644 --- a/lib/insecure-server.js +++ b/lib/insecure-server.js @@ -21,36 +21,30 @@ module.exports.create = function (securePort, insecurePort, info, serverCallback } function redirectHttps(req, res) { + if (req.headers.host && /^\/.well-known\/acme-challenge/.test(req.url) && useAppInsecurely(req, res)) { + return true; + } + // TODO + // XXX NOTE: info.conf.redirects may or may not be loaded at first + // the object will be modified when the config is loaded + if (!redirectives && info.redirects || info.conf.redirects) { + redirectives = require('./hostname-redirects').compile(info.redirects || info.conf.redirects); + } + if (require('./no-www').scrubTheDub(req, res, redirectives)) { + return true; + } + // Let it do this once they visit the https site // res.setHeader('Strict-Transport-Security', 'max-age=10886400; includeSubDomains; preload'); var host = req.headers.host || ''; var url = req.url; - // TODO - // XXX NOTE: info.conf.redirects may or may not be loaded at first - // the object will be modified when the config is loaded - if (!redirectives && info.conf.redirects) { - redirectives = require('./hostname-redirects').compile(info.conf.redirects); - } - if (require('./no-www').scrubTheDub(req, res, redirectives)) { - return true; - } - // TODO // allow exceptions for the case of arduino and whatnot that cannot handle https? // http://evothings.com/is-it-possible-to-secure-micro-controllers-used-within-iot/ // needs ECDSA? - console.warn('HARD-CODED HTTPS EXCEPTION in insecure-server.js'); - if (/redirect-www.org$/.test(host) && useAppInsecurely(req, res)) { - return true; - } - if (/^\/.well-known\/acme-challenge/.test(req.url) && useAppInsecurely(req, res)) { - console.log('exception for acme-challenge'); - return true; - } - var escapeHtml = require('escape-html'); var newLocation = 'https://' + host.replace(/:\d+/, ':' + securePort) + url diff --git a/lib/master.js b/lib/master.js index 80ea606..5b79575 100644 --- a/lib/master.js +++ b/lib/master.js @@ -2,12 +2,10 @@ var cluster = require('cluster'); var PromiseA = require('bluebird'); -var memstore; -var sqlstore; // TODO // var rootMasterKey; -function init(conf/*, state*/) { +function init(conf, state) { if (!conf.ipcKey) { conf.ipcKey = require('crypto').randomBytes(16).toString('base64'); } @@ -46,27 +44,20 @@ function init(conf/*, state*/) { , store: cluster.isMaster && null //new require('express-session/session/memory')() // TODO implement , key: conf.ipcKey - }).then(function (_memstore) { - memstore = _memstore; - return memstore; }) , sqlite3.createServer({ verbose: null , sock: conf.sqlite3Sock , ipcKey: conf.ipcKey - }).then(function (_sqlstore) { - sqlstore = _sqlstore; - return sqlstore; }) - ]).then(function (/*args*/) { - return conf; - /* - { + ]).then(function (args) { + state.memstore = args[0]; + state.sqlstore = args[1]; + return { conf: conf - , memstore: memstore // args[0] - , sqlstore: sqlstore // args[1] + , memstore: args[0] + , sqlstore: args[1] }; - */ }); return promise; @@ -83,13 +74,6 @@ function touch(conf, state) { conf.initialized = true; return conf; }); - - /* - setInterval(function () { - console.log('SIGUSR1 to caddy'); - return caddy.update(caddyConf); - }, 10 * 60 * 1000); - */ } module.exports.init = init;