fix ssl bugs, account for proxyable apps

This commit is contained in:
AJ ONeal 2015-02-21 01:16:38 +00:00
parent 64e04ee5e3
commit e7d0769270
1 changed files with 47 additions and 33 deletions

View File

@ -150,7 +150,12 @@ module.exports.create = function (securePort, certsPath, vhostsdir) {
if (localApp.create) { if (localApp.create) {
// TODO read local config.yml and pass it in // TODO read local config.yml and pass it in
// TODO pass in websocket // TODO pass in websocket
localApp = localApp.create(/*config*/); localApp = localApp.create(secureServer, {
dummyCerts: dummyCerts
, hostname: domaininfo.hostname
, port: securePort
, url: domaininfo.pathname
});
if (!localApp) { if (!localApp) {
return getDummyAppContext(null, "[ERROR] no app was returned by app.js for " + domaininfo.driname); return getDummyAppContext(null, "[ERROR] no app was returned by app.js for " + domaininfo.driname);
} }
@ -174,7 +179,12 @@ module.exports.create = function (securePort, certsPath, vhostsdir) {
function loadDomainVhosts() { function loadDomainVhosts() {
domainMerged.forEach(function (domainApp) { domainMerged.forEach(function (domainApp) {
console.log('[log] loaded mounts for domain ' + domainApp.hostname); if (domainApp._loaded) {
return;
}
console.log('[log] [once] Loading mounts for ' + domainApp.hostname);
domainApp._loaded = true;
app.use(vhost(domainApp.hostname, domainApp.apps)); app.use(vhost(domainApp.hostname, domainApp.apps));
app.use(vhost('www.' + domainApp.hostname, domainApp.apps)); app.use(vhost('www.' + domainApp.hostname, domainApp.apps));
}); });
@ -185,6 +195,7 @@ module.exports.create = function (securePort, certsPath, vhostsdir) {
var vhost = (req.headers.host || '').split(':')[0]; var vhost = (req.headers.host || '').split(':')[0];
// the matching domain didn't catch it // the matching domain didn't catch it
console.log('[log] vhost:', vhost);
if (domainMergeMap[vhost]) { if (domainMergeMap[vhost]) {
next(); next();
return; return;
@ -199,13 +210,15 @@ module.exports.create = function (securePort, certsPath, vhostsdir) {
return forEachAsync(domainMergeMap[vhost].apps, function (fn) { return forEachAsync(domainMergeMap[vhost].apps, function (fn) {
return new PromiseA(function (resolve) { return new PromiseA(function (resolve) {
function next(err) {
if (err) {
reject(err);
}
resolve();
}
try { try {
fn(req, res, function (err) { fn(req, res, next);
if (err) {
reject(err);
}
resolve();
});
} catch(e) { } catch(e) {
reject(e); reject(e);
} }
@ -229,7 +242,8 @@ module.exports.create = function (securePort, certsPath, vhostsdir) {
// return forEachAsync(rootDomains, loadCerts); // return forEachAsync(rootDomains, loadCerts);
// TODO load these even more lazily // TODO load these even more lazily
return forEachAsync(readNewVhosts(), loadDomainMounts).then(loadDomainVhosts).then(function () { return forEachAsync(readNewVhosts(), loadDomainMounts).then(loadDomainVhosts).then(function () {
app.use(hotloadApp); console.log('[log] TODO fix and use hotload');
//app.use(hotloadApp);
resolve(app); resolve(app);
return; return;
}); });
@ -269,55 +283,48 @@ module.exports.create = function (securePort, certsPath, vhostsdir) {
} }
try { try {
secureContexts[domainname] = createSecureContext(secOpts).context; secureContexts[domainname] = createSecureContext(secOpts);
} catch(err) { } catch(err) {
console.error("[ERROR] Certificates in '" + certsPath + "' could not be used:"); console.error("[ERROR] Certificates in '" + certsPath + "' could not be used:");
console.error(err); console.error(err);
return null; return null;
} }
if (!secureContexts[domainname]) {
console.error("[ERROR] Sanity check fail, no cert for '" + domainname + "'");
return null;
}
return secureContexts[domainname]; return secureContexts[domainname];
} }
function createSecureServer() { function createSecureServer() {
var dummyCerts = loadDummyCerts(); var localDummyCerts = loadDummyCerts();
var secureOpts = { var secureOpts = {
// fallback / default dummy certs // fallback / default dummy certs
key: dummyCerts.key key: localDummyCerts.key
, cert: dummyCerts.cert , cert: localDummyCerts.cert
, ca: dummyCerts.ca , ca: localDummyCerts.ca
}; };
function addSniWorkaroundCallback() { function addSniWorkaroundCallback() {
//SNICallback is passed the domain name, see NodeJS docs on TLS //SNICallback is passed the domain name, see NodeJS docs on TLS
secureOpts.SNICallback = function (domainname, cb) { secureOpts.SNICallback = function (domainname, cb) {
console.log('[log] SNI:', domainname);
if (!secureContexts.dummy) { if (!secureContexts.dummy) {
secureContexts.dummy = createSecureContext(dummyCerts); console.log('[log] Loading dummy certs');
secureContexts.dummy = createSecureContext(localDummyCerts);
} }
var secureContext = secureContexts[domainname] if (!secureContexts[domainname]) {
|| loadCerts(domainname) console.log('[log] Loading certs for', domainname);
|| secureContexts.dummy secureContexts[domainname] = loadCerts(domainname);
//|| createSecureContext(dummyCerts)
//|| createSecureContext(loadDummyCerts())
;
if (!secureContext) {
// testing with shared dummy
//secureContext = secureContexts.dummy;
// testing passing bad argument
//secureContext = createSecureContext(loadDummyCerts);
// testing with fresh dummy
secureContext = createSecureContext(loadDummyCerts());
} }
// workaround for v0.12 / v1.2 backwards compat bug // workaround for v0.12 / v1.2 backwards compat bug
if ('function' === typeof cb) { if ('function' === typeof cb) {
cb(null, secureContext); cb(null, secureContexts[domainname] || secureContexts.dummy);
} else { } else {
return secureContext; return secureContexts[domainname] || secureContexts.dummy;
} }
}; };
} }
@ -346,6 +353,13 @@ module.exports.create = function (securePort, certsPath, vhostsdir) {
// Get up and listening as absolutely quickly as possible // Get up and listening as absolutely quickly as possible
secureServer.on('request', function (req, res) { secureServer.on('request', function (req, res) {
if (/(^|\.)_proxyable\./.test(req.headers.host)) {
// device-id-12345678._proxyable.myapp.mydomain.com => myapp.mydomain.com
// _proxyable.myapp.mydomain.com => myapp.mydomain.com
// TODO myapp.mydomain.com.proxyable.com => myapp.mydomain.com
req.headers.host = req.headers.host.replace(/.*\.?_proxyable\./, '');
}
loadPromise().then(function (app) { loadPromise().then(function (app) {
app(req, res); app(req, res);
}); });