it... works? YES!!!!

This commit is contained in:
AJ ONeal 2016-08-11 18:44:35 -04:00
parent 6764ed3684
commit 1b12c3973b
3 changed files with 73 additions and 14 deletions

View File

@ -1,7 +1,10 @@
'use strict'; 'use strict';
module.exports.create = function (opts) { 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) { if ('function' !== typeof opts.approveDomains) {
throw new Error("You must provide opts.approveDomains(domain, certs, callback) to approve certificates"); 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'); 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) { if (err) {
log(opts.debug, 'Approval got ERROR', err.stack || 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; return;
} }
var promise; var promise;
// /* //
/*
var certs = require('localhost.daplie.com-certificates').merge({ var certs = require('localhost.daplie.com-certificates').merge({
subject: msg.domain subject: msg.domain
, altnames: [ msg.domain ] , altnames: [ msg.domain ]

View File

@ -21,16 +21,37 @@ module.exports.create = function (opts) {
notBefore: opts.notBefore || (10 * 24 * 60 * 60 * 1000) notBefore: opts.notBefore || (10 * 24 * 60 * 60 * 1000)
, notAfter: opts.notAfter || (5 * 24 * 60 * 60 * 1000) , notAfter: opts.notAfter || (5 * 24 * 60 * 60 * 1000)
, getCertificates: function (domain, certs, cb) { , getCertificates: function (domain, certs, cb) {
opts.approveDomains(domain, certs, function (err, certs) { var workerOptions = { domains: [ domain ] };
process.send({ type: 'LE_REQUEST', domain: domain, options: { domains: [domain] }, certs: certs }); 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) { process.on('message', function (msg) {
log(opts.debug, 'Message from master'); log(opts.debug, 'Message from master');
log(opts.debug, msg); log(opts.debug, msg);
if (msg.domain === domain) { if (msg.domain !== domain) {
cb(null, msg.certs); 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);
}); });
}); });
} }

View File

@ -1,6 +1,8 @@
'use strict'; 'use strict';
var cluster = require('cluster'); var cluster = require('cluster');
// TODO the le-challenge-<<strategy>> should be shared between worker and server
var webrootPath = require('os').tmpdir() + require('path').sep + 'acme-challenge';
function runMaster() { function runMaster() {
var numCores = 2; // // Math.max(2, require('os').cpus().length) var numCores = 2; // // Math.max(2, require('os').cpus().length)
@ -11,17 +13,18 @@ function runMaster() {
, server: 'staging' , server: 'staging'
, webrootPath: webrootPath
, approveDomains: function (domain, certs, cb) { , approveDomains: function (masterOptions, certs, cb) {
// Depending on your setup it may be more efficient // Depending on your setup it may be more efficient
// for you to implement the approveDomains function // for you to implement the approveDomains function
// in your master or in your workers. // in your master or in your workers.
// //
// Since we implement it in the worker (below) in this example // Since we implement it in the worker (below) in this example
// we'll give it an immediate approval here in the master // 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); cb(null, results);
} }
}); });
@ -37,24 +40,51 @@ function runWorker() {
var worker = require('./lib/worker').create({ var worker = require('./lib/worker').create({
debug: true debug: true
// We want both to renew well before the expiration date // We want both to renew well before the expiration date
// and also to stagger the renewals, just a touch // and also to stagger the renewals, just a touch
// here we specify to renew between 10 and 15 days // here we specify to renew between 10 and 15 days
, notBefore: 15 * 24 * 60 * 60 * 1000 , notBefore: 15 * 24 * 60 * 60 * 1000
, notAfter: 10 * 24 * 60 * 60 * 1000 // optional , 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) { , 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 // but if needed for performance, that can be overwritten here
cb(null, ); 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 } // opts = { domains, email, agreeTos, tosUrl }
// certs = { subject, altnames, expiresAt, issuedAt } // 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
};