minor refactor

This commit is contained in:
AJ ONeal 2016-03-31 02:39:15 -04:00
parent c2fc1e76e1
commit 3a86624b8b
3 changed files with 86 additions and 105 deletions

View File

@ -14,12 +14,23 @@ var cluster = require('cluster');
//var minWorkers = 2; //var minWorkers = 2;
var numCores = 2; // Math.max(minWorkers, require('os').cpus().length); var numCores = 2; // Math.max(minWorkers, require('os').cpus().length);
var workers = []; var workers = [];
var state = { firstRun: true };
function fork() {
if (workers.length < numCores) {
workers.push(cluster.fork());
}
}
cluster.on('online', function (worker) {
console.info('[MASTER] Worker ' + worker.process.pid + ' is online');
fork();
var config = { var config = {
externalPort: 443 // world accessible externalPort: 443 // world accessible
, externalPortInsecure: 80 // world accessible , externalPortInsecure: 80 // world accessible
// TODO externalInsecurePort? // TODO externalInsecurePort?
, locked: false // TODO XXX , locked: false // TODO XXX
, ipcKey: null
// XXX // XXX
// TODO needs mappings from db // TODO needs mappings from db
// TODO autoconfig Caddy caddy // TODO autoconfig Caddy caddy
@ -29,7 +40,63 @@ var config = {
, bin: '/usr/local/bin/caddy' , bin: '/usr/local/bin/caddy'
, sitespath: path.join(__dirname, 'sites-enabled') , sitespath: path.join(__dirname, 'sites-enabled')
} }
, redirects: [ };
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')
];
// TODO communicate config with environment vars?
var info = {
type: 'walnut.init'
, conf: {
protocol: useCaddy ? 'http' : 'https'
, externalPort: config.externalPort
, localPort: config.localPort
, insecurePort: config.insecurePort
, certPaths: useCaddy ? null : certPaths
, trustProxy: useCaddy ? true : false
}
};
function touchMaster(msg) {
if ('walnut.webserver.listening' !== msg.type) {
console.warn('[MASTER] received unexpected message from worker');
console.warn(msg);
return;
}
// calls init if init has not been called
state.caddy = caddy;
state.workers = workers;
require('../lib/master').touch(config, state).then(function (results) {
//var memstore = results.memstore;
var sqlstore = results.sqlstore;
info.type = 'walnut.webserver.onrequest';
// 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": "*", "value": false } // default no-www
, { "ip": false, "id": "daplie.domains", "value": null } , { "ip": false, "id": "daplie.domains", "value": null }
@ -45,77 +112,19 @@ var config = {
, { "ip": true, "id": "yes.daplie.domains", "value": true } , { "ip": true, "id": "yes.daplie.domains", "value": true }
, { "ip": true, "id": "*.yes.daplie.domains", "value": true } , { "ip": true, "id": "*.yes.daplie.domains", "value": true }
, { "ip": true, "id": "ns1.daplie.domains", "value": false } , { "ip": true, "id": "ns1.daplie.domains", "value": false }
] ];
// TODO use sqlite3 or autogenerate ? // TODO use sqlite3 or autogenerate ?
, privkey: require('fs').readFileSync(__dirname + '/../../' + '/nsx.redirect-www.org.key.pem', 'ascii') info.conf.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') info.conf.pubkey = require('fs').readFileSync(__dirname + '/../../' + '/nsx.redirect-www.org.key.pem.pub', 'ascii');
// keys // keys
// letsencrypt // letsencrypt
// com.example.provider // com.example.provider
// com.example.consumer // 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
function fork() {
if (workers.length < numCores) {
workers.push(cluster.fork());
}
}
cluster.on('online', function (worker) {
console.info('[MASTER] Worker ' + worker.process.pid + ' is online');
fork();
// TODO XXX Should these be configurable? If so, where?
var certPaths = [
path.join(__dirname, 'certs', 'live')
, path.join(__dirname, 'letsencrypt', 'live')
];
// TODO communicate config with environment vars?
var info = {
type: 'walnut.init'
, conf: {
protocol: useCaddy ? 'http' : 'https'
, 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
}
};
worker.send(info);
function touchMaster(msg) {
if ('walnut.webserver.listening' !== msg.type) {
console.warn('[MASTER] received unexpected message from worker');
console.warn(msg);
return;
}
// calls init if init has not been called
state.caddy = caddy;
state.workers = workers;
require('../lib/master').touch(config, state).then(function () {
info.type = 'walnut.webserver.onrequest';
info.conf.ipcKey = config.ipcKey;
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;
worker.send(info); worker.send(info);
}); });
} }
worker.send(info);
worker.on('message', touchMaster); worker.on('message', touchMaster);
}); });
@ -136,9 +145,3 @@ cluster.on('exit', function (worker, code, signal) {
}); });
fork(); fork();
if (useCaddy) {
caddy = require('../lib/spawn-caddy').create(config);
// relies on { localPort, locked }
caddy.spawn(config);
}

View File

@ -21,36 +21,30 @@ module.exports.create = function (securePort, insecurePort, info, serverCallback
} }
function redirectHttps(req, res) { 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 // Let it do this once they visit the https site
// res.setHeader('Strict-Transport-Security', 'max-age=10886400; includeSubDomains; preload'); // res.setHeader('Strict-Transport-Security', 'max-age=10886400; includeSubDomains; preload');
var host = req.headers.host || ''; var host = req.headers.host || '';
var url = req.url; 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 // TODO
// allow exceptions for the case of arduino and whatnot that cannot handle https? // 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/ // http://evothings.com/is-it-possible-to-secure-micro-controllers-used-within-iot/
// needs ECDSA? // 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 escapeHtml = require('escape-html');
var newLocation = 'https://' var newLocation = 'https://'
+ host.replace(/:\d+/, ':' + securePort) + url + host.replace(/:\d+/, ':' + securePort) + url

View File

@ -2,12 +2,10 @@
var cluster = require('cluster'); var cluster = require('cluster');
var PromiseA = require('bluebird'); var PromiseA = require('bluebird');
var memstore;
var sqlstore;
// TODO // TODO
// var rootMasterKey; // var rootMasterKey;
function init(conf/*, state*/) { function init(conf, state) {
if (!conf.ipcKey) { if (!conf.ipcKey) {
conf.ipcKey = require('crypto').randomBytes(16).toString('base64'); 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')() , store: cluster.isMaster && null //new require('express-session/session/memory')()
// TODO implement // TODO implement
, key: conf.ipcKey , key: conf.ipcKey
}).then(function (_memstore) {
memstore = _memstore;
return memstore;
}) })
, sqlite3.createServer({ , sqlite3.createServer({
verbose: null verbose: null
, sock: conf.sqlite3Sock , sock: conf.sqlite3Sock
, ipcKey: conf.ipcKey , ipcKey: conf.ipcKey
}).then(function (_sqlstore) {
sqlstore = _sqlstore;
return sqlstore;
}) })
]).then(function (/*args*/) { ]).then(function (args) {
return conf; state.memstore = args[0];
/* state.sqlstore = args[1];
{ return {
conf: conf conf: conf
, memstore: memstore // args[0] , memstore: args[0]
, sqlstore: sqlstore // args[1] , sqlstore: args[1]
}; };
*/
}); });
return promise; return promise;
@ -83,13 +74,6 @@ function touch(conf, state) {
conf.initialized = true; conf.initialized = true;
return conf; return conf;
}); });
/*
setInterval(function () {
console.log('SIGUSR1 to caddy');
return caddy.update(caddyConf);
}, 10 * 60 * 1000);
*/
} }
module.exports.init = init; module.exports.init = init;