From 1b12c3973b7d38ab1d7bf34326adce21ef5886de Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Thu, 11 Aug 2016 18:44:35 -0400 Subject: [PATCH] it... works? YES!!!! --- lib/master.js | 16 ++++++++++++---- lib/worker.js | 29 +++++++++++++++++++++++++---- serve.js | 42 ++++++++++++++++++++++++++++++++++++------ 3 files changed, 73 insertions(+), 14 deletions(-) diff --git a/lib/master.js b/lib/master.js index 16b2cd0..92e25a8 100644 --- a/lib/master.js +++ b/lib/master.js @@ -1,7 +1,10 @@ 'use strict'; module.exports.create = function (opts) { - if (!opts.letsencrypt) { opts.letsencrypt = require('letsencrypt').create({ server: opts.server }); } + if (!opts.letsencrypt) { opts.letsencrypt = require('letsencrypt').create({ + server: opts.server + , webrootPath: require('os').tmpdir() + require('path').sep + 'acme-challenge' + }); } if ('function' !== typeof opts.approveDomains) { throw new Error("You must provide opts.approveDomains(domain, certs, callback) to approve certificates"); } @@ -33,16 +36,21 @@ module.exports.create = function (opts) { } log(opts.debug, 'about to approveDomains'); - opts.approveDomains(msg.domain, msg.certs, function (err, results) { + opts.approveDomains(msg.options, msg.certs, function (err, results) { if (err) { log(opts.debug, 'Approval got ERROR', err.stack || err); - worker.send({ type: 'LE_RESPONSE', domain: msg.domain, error: err }); + worker.send({ + type: 'LE_RESPONSE' + , domain: msg.domain + , error: { message: err.message, code: err.code, stack: err.stack } + }); return; } var promise; - // /* + // + /* var certs = require('localhost.daplie.com-certificates').merge({ subject: msg.domain , altnames: [ msg.domain ] diff --git a/lib/worker.js b/lib/worker.js index 8d4d993..e5b2e72 100644 --- a/lib/worker.js +++ b/lib/worker.js @@ -21,16 +21,37 @@ module.exports.create = function (opts) { notBefore: opts.notBefore || (10 * 24 * 60 * 60 * 1000) , notAfter: opts.notAfter || (5 * 24 * 60 * 60 * 1000) , getCertificates: function (domain, certs, cb) { - opts.approveDomains(domain, certs, function (err, certs) { - process.send({ type: 'LE_REQUEST', domain: domain, options: { domains: [domain] }, certs: certs }); + var workerOptions = { domains: [ domain ] }; + opts.approveDomains(workerOptions, certs, function (_err, results) { + if (_err) { + cb(_err); + return; + } + + var err = new Error("___MESSAGE___"); + process.send({ type: 'LE_REQUEST', domain: domain, options: results.options, certs: results.certs }); process.on('message', function (msg) { log(opts.debug, 'Message from master'); log(opts.debug, msg); - if (msg.domain === domain) { - cb(null, msg.certs); + if (msg.domain !== domain) { + return; } + + if (msg.error) { + err.message = msg.error.message || "unknown error sent from cluster master to worker"; + err.stack.replace("___MESSAGE___", err.message); + err = { + message: err.message + , stack: err.stack + , data: { options: workerOptions, certs: certs } + }; + } else { + err = null; + } + + cb(err, msg.certs); }); }); } diff --git a/serve.js b/serve.js index 1bb964c..88a68ab 100644 --- a/serve.js +++ b/serve.js @@ -1,6 +1,8 @@ 'use strict'; var cluster = require('cluster'); +// TODO the le-challenge-<> should be shared between worker and server +var webrootPath = require('os').tmpdir() + require('path').sep + 'acme-challenge'; function runMaster() { var numCores = 2; // // Math.max(2, require('os').cpus().length) @@ -11,17 +13,18 @@ function runMaster() { , server: 'staging' + , webrootPath: webrootPath - , approveDomains: function (domain, certs, cb) { + , approveDomains: function (masterOptions, certs, cb) { // Depending on your setup it may be more efficient // for you to implement the approveDomains function // in your master or in your workers. // // Since we implement it in the worker (below) in this example // we'll give it an immediate approval here in the master - var results = { domain: domain, options: { domains: [domain] }, certs: certs }; + var results = { domain: masterOptions.domain, options: masterOptions, certs: certs }; cb(null, results); } }); @@ -37,24 +40,51 @@ function runWorker() { var worker = require('./lib/worker').create({ debug: true + + // We want both to renew well before the expiration date // and also to stagger the renewals, just a touch // here we specify to renew between 10 and 15 days , notBefore: 15 * 24 * 60 * 60 * 1000 , notAfter: 10 * 24 * 60 * 60 * 1000 // optional - , webrootPath: require('os').tmpdir() + require('path').sep + 'acme-challenge' + + + , webrootPath: webrootPath + + + /* + challenge: { + get: function (ignored, domain, token, cb) { + cb(null, keyAuthorization); + } + } , getChallenge: function (domain, token, cb) { - // the default behavior is to pass a message to master, + // the default behavior is to use le-challenge-fs + // TODO maybe provide a built-in option to pass a message to master to use its + // but you could overwrite that with a function to pass a message to master or, // but if needed for performance, that can be overwritten here cb(null, ); } */ - , approveDomains: function (domain, certs, cb) { + + + // There are two approval processes: + // 1. emails are tied to private keys (accounts) which must agree to the tos url + // 2. domains are tied to accounts (and should be verifiable via loopback) + , approveDomains: function (workerOptions, certs, cb) { // opts = { domains, email, agreeTos, tosUrl } // certs = { subject, altnames, expiresAt, issuedAt } - var results = { domain: domain, options: { domains: [domain] }, certs: certs }; + var results = { + domain: workerOptions.domains[0] + , options: { + domains: certs && certs.altnames || workerOptions.domains + , email: 'aj@daplie.com' + , agreeTos: true + } + , certs: certs + };