diff --git a/index.js b/index.js index a59a8ac..5f6067e 100644 --- a/index.js +++ b/index.js @@ -114,6 +114,19 @@ LE.create = function (le) { le[key] = le._challengeOpts[key]; } }); + // TODO wrap these here and now with tplCopy? + if (5 !== le.challenge.set.length) { + throw new Error("le.challenge.set receives the wrong number of arguments." + + " You must define setChallenge as function (opts, domain, key, val, cb) { }"); + } + if (4 !== le.challenge.get.length) { + throw new Error("le.challenge.get receives the wrong number of arguments." + + " You must define getChallenge as function (opts, domain, key, cb) { }"); + } + if (4 !== le.challenge.remove.length) { + throw new Error("le.challenge.remove receives the wrong number of arguments." + + " You must define removeChallenge as function (opts, domain, key, cb) { }"); + } if (le.core.create) { le.core = le.core.create(le); diff --git a/lib/core.js b/lib/core.js index 4c5aea0..2ccad60 100644 --- a/lib/core.js +++ b/lib/core.js @@ -1,5 +1,14 @@ 'use strict'; +function log(debug) { + if (debug) { + var args = Array.prototype.slice.call(arguments); + args.shift(); + args.unshift("[le/lib/core.js]"); + console.log.apply(console, args); + } +} + module.exports.create = function (le) { var PromiseA = require('bluebird'); var utils = require('./utils'); @@ -55,8 +64,10 @@ module.exports.create = function (le) { var keypairOpts = { public: true, pem: true }; var promise = le.store.accounts.checkKeypairAsync(args).then(function (keypair) { - return RSA.import(keypair); - }, function (/*err*/) { + if (keypair) { + return RSA.import(keypair); + } + if (args.accountKeypair) { return le.store.accounts.setKeypairAsync(args, RSA.import(args.accountKeypair)); } @@ -169,6 +180,8 @@ module.exports.create = function (le) { return PromiseA.reject(err); } + // TODO renewal cb + // accountId and or email return core.accounts.getAsync(copy).then(function (account) { copy.account = account; @@ -176,8 +189,10 @@ module.exports.create = function (le) { var keypairOpts = { public: true, pem: true }; var promise = le.store.certificates.checkKeypairAsync(args).then(function (keypair) { - return RSA.import(keypair); - }, function (/*err*/) { + if (keypair) { + return RSA.import(keypair); + } + if (args.domainKeypair) { return le.store.certificates.setKeypairAsync(args, RSA.import(args.domainKeypair)); } @@ -199,7 +214,10 @@ module.exports.create = function (le) { return core.getAcmeUrlsAsync(args).then(function (urls) { args._acmeUrls = urls; - return le.acme.getCertificateAsync({ + log(args.debug, 'BEFORE CERT'); + log(args.debug, args); + throw new Error("Stop! Don't do it!"); + var certReq = { debug: args.debug || le.debug , newAuthzUrl: args._acmeUrls.newAuthz @@ -209,43 +227,35 @@ module.exports.create = function (le) { , domainKeypair: domainKeypair , domains: args.domains , challengeType: args.challengeType + }; - // - // IMPORTANT - // - // setChallenge and removeChallenge are handed defaults - // instead of args because getChallenge does not have - // access to args - // (args is per-request, defaults is per instance) - // - , setChallenge: function (domain, key, value, done) { - var copy = utils.merge({ domains: [domain] }, le); - utils.tplCopy(copy); + // + // IMPORTANT + // + // setChallenge and removeChallenge are handed defaults + // instead of args because getChallenge does not have + // access to args + // (args is per-request, defaults is per instance) + // + // Each of these fires individually for each domain, + // even though the certificate on the whole may have many domains + // + certReq.setChallenge = function (domain, key, value, done) { + log(args.debug, "setChallenge called for '" + domain + "'"); + var copy = utils.merge({ domains: [domain] }, le); + utils.tplCopy(copy); - //args.domains = [domain]; - args.domains = args.domains || [domain]; + le.challenge.set(copy, domain, key, value, done); + }; + certReq.removeChallenge = function (domain, key, done) { + log(args.debug, "setChallenge called for '" + domain + "'"); + var copy = utils.merge({ domains: [domain] }, le); + utils.tplCopy(copy); - if (5 !== le.challenger.set.length) { - done(new Error("le.challenger.set receives the wrong number of arguments." - + " You must define setChallenge as function (opts, domain, key, val, cb) { }")); - return; - } + le.challenge.remove(copy, domain, key, done); + }; - le.challenger.set(copy, domain, key, value, done); - } - , removeChallenge: function (domain, key, done) { - var copy = utils.merge({ domains: [domain] }, le); - utils.tplCopy(copy); - - if (4 !== le.challenger.remove.length) { - done(new Error("le.challenger.remove receives the wrong number of arguments." - + " You must define removeChallenge as function (opts, domain, key, cb) { }")); - return; - } - - le.challenger.remove(copy, domain, key, done); - } - }).then(utils.attachCertInfo); + return le.acme.getCertificateAsync(certReq).then(utils.attachCertInfo); }); }).then(function (results) { // { cert, chain, privkey } @@ -260,6 +270,7 @@ module.exports.create = function (le) { // Certificates , renewAsync: function (args) { // TODO fetch email address (accountBydomain) if not present + // store.config.getAsync(args.domains).then(function (config) { /*...*/ }); return core.certificates.registerAsync(args); } // Certificates @@ -284,6 +295,7 @@ module.exports.create = function (le) { return core.certificates.checkAsync(args).then(function (certs) { if (!certs) { // There is no cert available + log(args.debug, "no certificate found"); return core.certificates.registerAsync(args); } @@ -291,16 +303,26 @@ module.exports.create = function (le) { //var halfLife = (certs.expiresAt - certs.issuedAt) / 2; //var renewable = (Date.now() - certs.issuedAt) > halfLife; + log(args.debug, "Expires At", new Date(certs.expiresAt).toISOString()); + log(args.debug, "Renewable At", new Date(renewableAt).toISOString()); if (args.duplicate || Date.now() >= renewableAt) { // The cert is more than half-expired // We're forcing a refresh via 'dupliate: true' + log(args.debug, "Renewing!"); + if (Array.isArray(certs.domains) && certs.domains.length && args.domains.length <= 2) { + // this is a renewal, therefore we should renewal ALL of the domains + // associated with this certificate, unless args.domains is a list larger + // than example.com,www.example.com + // TODO check www. prefix + args.domains = certs.domains; + } return core.certificates.renewAsync(args); } return PromiseA.reject(new Error( "[ERROR] Certificate issued at '" + new Date(certs.issuedAt).toISOString() + "' and expires at '" - + new Date(certs.expiresAt).toISOString() + "'. Ignoring renewal attempt until half-life at '" + + new Date(certs.expiresAt).toISOString() + "'. Ignoring renewal attempt until '" + new Date(renewableAt).toISOString() + "'. Set { duplicate: true } to force." )); }).then(function (results) {