moving some parts to letsencrypt-express
This commit is contained in:
parent
28ec4cc83a
commit
22e1d768af
108
index.js
108
index.js
|
@ -34,39 +34,6 @@ LE.merge = function merge(defaults, args) {
|
||||||
return copy;
|
return copy;
|
||||||
};
|
};
|
||||||
|
|
||||||
LE.cacheCertInfo = function (args, certInfo, ipc, handlers) {
|
|
||||||
// TODO IPC via process and worker to guarantee no races
|
|
||||||
// rather than just "really good odds"
|
|
||||||
|
|
||||||
var hostname = args.domains[0];
|
|
||||||
var now = Date.now();
|
|
||||||
|
|
||||||
// Stagger randomly by plus 0% to 25% to prevent all caches expiring at once
|
|
||||||
var rnd1 = (crypto.randomBytes(1)[0] / 255);
|
|
||||||
var memorizeFor = Math.floor(handlers.memorizeFor + ((handlers.memorizeFor / 4) * rnd1));
|
|
||||||
// Stagger randomly to renew between n and 2n days before renewal is due
|
|
||||||
// this *greatly* reduces the risk of multiple cluster processes renewing the same domain at once
|
|
||||||
var rnd2 = (crypto.randomBytes(1)[0] / 255);
|
|
||||||
var bestIfUsedBy = certInfo.expiresAt - (handlers.renewWithin + Math.floor(handlers.renewWithin * rnd2));
|
|
||||||
// Stagger randomly by plus 0 to 5 min to reduce risk of multiple cluster processes
|
|
||||||
// renewing at once on boot when the certs have expired
|
|
||||||
var rnd3 = (crypto.randomBytes(1)[0] / 255);
|
|
||||||
var renewTimeout = Math.floor((5 * 60 * 1000) * rnd3);
|
|
||||||
|
|
||||||
certInfo.context = tls.createSecureContext({
|
|
||||||
key: certInfo.key
|
|
||||||
, cert: certInfo.cert
|
|
||||||
//, ciphers // node's defaults are great
|
|
||||||
});
|
|
||||||
certInfo.loadedAt = now;
|
|
||||||
certInfo.memorizeFor = memorizeFor;
|
|
||||||
certInfo.bestIfUsedBy = bestIfUsedBy;
|
|
||||||
certInfo.renewTimeout = renewTimeout;
|
|
||||||
|
|
||||||
ipc[hostname] = certInfo;
|
|
||||||
return ipc[hostname];
|
|
||||||
};
|
|
||||||
|
|
||||||
// backend, defaults, handlers
|
// backend, defaults, handlers
|
||||||
LE.create = function (defaults, handlers, backend) {
|
LE.create = function (defaults, handlers, backend) {
|
||||||
var d, b, h;
|
var d, b, h;
|
||||||
|
@ -267,21 +234,22 @@ LE.create = function (defaults, handlers, backend) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//console.log("[NLE]: begin registration");
|
//console.log("[NLE]: begin registration");
|
||||||
return backend.registerAsync(copy).then(function () {
|
return backend.registerAsync(copy).then(function (pems) {
|
||||||
//console.log("[NLE]: end registration");
|
//console.log("[NLE]: end registration");
|
||||||
// calls fetch because fetch calls cacheCertInfo
|
cb(null, pems);
|
||||||
return le.fetch(args, cb);
|
//return le.fetch(args, cb);
|
||||||
}, cb);
|
}, cb);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
, _fetchHelper: function (args, cb) {
|
, _fetchHelper: function (args, cb) {
|
||||||
return backend.fetchAsync(args).then(function (certInfo) {
|
return backend.fetchAsync(args).then(function (certInfo) {
|
||||||
if (!certInfo) {
|
if (args.debug) {
|
||||||
cb(null, null);
|
console.log('[LE] debug is on');
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
if (true || args.debug) {
|
||||||
var now = Date.now();
|
console.log('[LE] raw fetch certs', certInfo);
|
||||||
|
}
|
||||||
|
if (!certInfo) { cb(null, null); return; }
|
||||||
|
|
||||||
// key, cert, issuedAt, lifetime, expiresAt
|
// key, cert, issuedAt, lifetime, expiresAt
|
||||||
if (!certInfo.expiresAt) {
|
if (!certInfo.expiresAt) {
|
||||||
|
@ -290,53 +258,19 @@ LE.create = function (defaults, handlers, backend) {
|
||||||
if (!certInfo.lifetime) {
|
if (!certInfo.lifetime) {
|
||||||
certInfo.lifetime = (certInfo.lifetime || handlers.lifetime);
|
certInfo.lifetime = (certInfo.lifetime || handlers.lifetime);
|
||||||
}
|
}
|
||||||
|
|
||||||
// a pretty good hard buffer
|
// a pretty good hard buffer
|
||||||
certInfo.expiresAt -= (1 * 24 * 60 * 60 * 100);
|
certInfo.expiresAt -= (1 * 24 * 60 * 60 * 100);
|
||||||
certInfo = LE.cacheCertInfo(args, certInfo, ipc, handlers);
|
|
||||||
if (now > certInfo.bestIfUsedBy && !certInfo.timeout) {
|
|
||||||
// EXPIRING
|
|
||||||
if (now > certInfo.expiresAt) {
|
|
||||||
// EXPIRED
|
|
||||||
certInfo.renewTimeout = Math.floor(certInfo.renewTimeout / 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
certInfo.timeout = setTimeout(function () {
|
cb(null, certInfo);
|
||||||
le.register(args, cb);
|
|
||||||
}, certInfo.renewTimeout);
|
|
||||||
}
|
|
||||||
cb(null, certInfo.context);
|
|
||||||
}, cb);
|
}, cb);
|
||||||
}
|
}
|
||||||
, fetch: function (args, cb) {
|
, fetch: function (args, cb) {
|
||||||
var hostname = args.domains[0];
|
|
||||||
// TODO don't call now() every time because this is hot code
|
|
||||||
var now = Date.now();
|
|
||||||
var certInfo = ipc[hostname];
|
|
||||||
|
|
||||||
// TODO once ECDSA is available, wait for cert renewal if its due
|
|
||||||
if (certInfo) {
|
|
||||||
if (now > certInfo.bestIfUsedBy && !certInfo.timeout) {
|
|
||||||
// EXPIRING
|
|
||||||
if (now > certInfo.expiresAt) {
|
|
||||||
// EXPIRED
|
|
||||||
certInfo.renewTimeout = Math.floor(certInfo.renewTimeout / 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
certInfo.timeout = setTimeout(function () {
|
|
||||||
le.register(args, cb);
|
|
||||||
}, certInfo.renewTimeout);
|
|
||||||
}
|
|
||||||
cb(null, certInfo.context);
|
|
||||||
|
|
||||||
if ((now - certInfo.loadedAt) < (certInfo.memorizeFor)) {
|
|
||||||
// these aren't stale, so don't fall through
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
le._fetchHelper(args, cb);
|
le._fetchHelper(args, cb);
|
||||||
}
|
}
|
||||||
|
, renew: function (args, cb) {
|
||||||
|
args.duplicate = false;
|
||||||
|
le.register(args, cb);
|
||||||
|
}
|
||||||
, register: function (args, cb) {
|
, register: function (args, cb) {
|
||||||
if (!Array.isArray(args.domains)) {
|
if (!Array.isArray(args.domains)) {
|
||||||
cb(new Error('args.domains should be an array of domains'));
|
cb(new Error('args.domains should be an array of domains'));
|
||||||
|
@ -349,16 +283,10 @@ LE.create = function (defaults, handlers, backend) {
|
||||||
le._fetchHelper(args, function (err, hit) {
|
le._fetchHelper(args, function (err, hit) {
|
||||||
var hostname = args.domains[0];
|
var hostname = args.domains[0];
|
||||||
|
|
||||||
if (err) {
|
if (err) { cb(err); return; }
|
||||||
cb(err);
|
else if (hit) { cb(null, hit); return; }
|
||||||
return;
|
|
||||||
}
|
|
||||||
else if (hit) {
|
|
||||||
cb(null, hit);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
return le._registerHelper(args, function (err) {
|
return le._registerHelper(args, function (err, pems) {
|
||||||
if (err) {
|
if (err) {
|
||||||
cb(err);
|
cb(err);
|
||||||
return;
|
return;
|
||||||
|
@ -366,7 +294,7 @@ LE.create = function (defaults, handlers, backend) {
|
||||||
|
|
||||||
le._fetchHelper(args, function (err, cache) {
|
le._fetchHelper(args, function (err, cache) {
|
||||||
if (cache) {
|
if (cache) {
|
||||||
cb(null, cache.context);
|
cb(null, cache);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,118 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var PromiseA = require('bluebird');
|
||||||
|
var LeCore = require('letiny-core');
|
||||||
|
var leCrypto = LeCore.leCrypto;
|
||||||
|
var path = require('path');
|
||||||
|
var mkdirpAsync = PromiseA.promisify(require('mkdirp'));
|
||||||
|
var fs = PromiseA.promisifyAll(require('fs'));
|
||||||
|
|
||||||
|
function createAccount(args, handlers) {
|
||||||
|
var os = require("os");
|
||||||
|
var localname = os.hostname();
|
||||||
|
|
||||||
|
// TODO support ECDSA
|
||||||
|
// arg.rsaBitLength args.rsaExponent
|
||||||
|
return leCrypto.generateRsaKeypairAsync(args.rsaBitLength, args.rsaExponent).then(function (pems) {
|
||||||
|
/* pems = { privateKeyPem, privateKeyJwk, publicKeyPem, publicKeyMd5 } */
|
||||||
|
|
||||||
|
return LeCore.registerNewAccountAsync({
|
||||||
|
email: args.email
|
||||||
|
, newRegUrl: args._acmeUrls.newReg
|
||||||
|
, agreeToTerms: function (tosUrl, agree) {
|
||||||
|
// args.email = email; // already there
|
||||||
|
args.tosUrl = tosUrl;
|
||||||
|
handlers.agreeToTerms(args, agree);
|
||||||
|
}
|
||||||
|
, accountPrivateKeyPem: pems.privateKeyPem
|
||||||
|
|
||||||
|
, debug: args.debug || handlers.debug
|
||||||
|
}).then(function (body) {
|
||||||
|
var accountDir = path.join(args.accountsDir, pems.publicKeyMd5);
|
||||||
|
|
||||||
|
return mkdirpAsync(accountDir).then(function () {
|
||||||
|
|
||||||
|
var isoDate = new Date().toISOString();
|
||||||
|
var accountMeta = {
|
||||||
|
creation_host: localname
|
||||||
|
, creation_dt: isoDate
|
||||||
|
};
|
||||||
|
|
||||||
|
return PromiseA.all([
|
||||||
|
// meta.json {"creation_host": "ns1.redirect-www.org", "creation_dt": "2015-12-11T04:14:38Z"}
|
||||||
|
fs.writeFileAsync(path.join(accountDir, 'meta.json'), JSON.stringify(accountMeta), 'utf8')
|
||||||
|
// private_key.json { "e", "d", "n", "q", "p", "kty", "qi", "dp", "dq" }
|
||||||
|
, fs.writeFileAsync(path.join(accountDir, 'private_key.json'), JSON.stringify(pems.privateKeyJwk), 'utf8')
|
||||||
|
// regr.json:
|
||||||
|
/*
|
||||||
|
{ body: { contact: [ 'mailto:coolaj86@gmail.com' ],
|
||||||
|
agreement: 'https://letsencrypt.org/documents/LE-SA-v1.0.1-July-27-2015.pdf',
|
||||||
|
key: { e: 'AQAB', kty: 'RSA', n: '...' } },
|
||||||
|
uri: 'https://acme-v01.api.letsencrypt.org/acme/reg/71272',
|
||||||
|
new_authzr_uri: 'https://acme-v01.api.letsencrypt.org/acme/new-authz',
|
||||||
|
terms_of_service: 'https://letsencrypt.org/documents/LE-SA-v1.0.1-July-27-2015.pdf' }
|
||||||
|
*/
|
||||||
|
, fs.writeFileAsync(path.join(accountDir, 'regr.json'), JSON.stringify({ body: body }), 'utf8')
|
||||||
|
]).then(function () {
|
||||||
|
return pems;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function getAccount(accountId, args, handlers) {
|
||||||
|
var accountDir = path.join(args.accountsDir, accountId);
|
||||||
|
var files = {};
|
||||||
|
var configs = ['meta.json', 'private_key.json', 'regr.json'];
|
||||||
|
|
||||||
|
return PromiseA.all(configs.map(function (filename) {
|
||||||
|
var keyname = filename.slice(0, -5);
|
||||||
|
|
||||||
|
return fs.readFileAsync(path.join(accountDir, filename), 'utf8').then(function (text) {
|
||||||
|
var data;
|
||||||
|
|
||||||
|
try {
|
||||||
|
data = JSON.parse(text);
|
||||||
|
} catch(e) {
|
||||||
|
files[keyname] = { error: e };
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
files[keyname] = data;
|
||||||
|
}, function (err) {
|
||||||
|
files[keyname] = { error: err };
|
||||||
|
});
|
||||||
|
})).then(function () {
|
||||||
|
|
||||||
|
if (!Object.keys(files).every(function (key) {
|
||||||
|
return !files[key].error;
|
||||||
|
})) {
|
||||||
|
// TODO log renewal.conf
|
||||||
|
console.warn("Account '" + accountId + "' was currupt. No big deal (I think?). Creating a new one...");
|
||||||
|
return createAccount(args, handlers);
|
||||||
|
}
|
||||||
|
|
||||||
|
return leCrypto.parseAccountPrivateKeyAsync(files.private_key).then(function (keypair) {
|
||||||
|
files.accountId = accountId; // md5sum(publicKeyPem)
|
||||||
|
files.publicKeyMd5 = accountId; // md5sum(publicKeyPem)
|
||||||
|
files.publicKeyPem = keypair.publicKeyPem; // ascii PEM: ----BEGIN...
|
||||||
|
files.privateKeyPem = keypair.privateKeyPem; // ascii PEM: ----BEGIN...
|
||||||
|
files.privateKeyJson = keypair.private_key; // json { n: ..., e: ..., iq: ..., etc }
|
||||||
|
|
||||||
|
return files;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function getAccountByEmail(/*args*/) {
|
||||||
|
// If we read 10,000 account directories looking for
|
||||||
|
// just one email address, that could get crazy.
|
||||||
|
// We should have a folder per email and list
|
||||||
|
// each account as a file in the folder
|
||||||
|
// TODO
|
||||||
|
return PromiseA.resolve(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports.getAccountByEmail = getAccountByEmail;
|
||||||
|
module.exports.getAccount = getAccount;
|
|
@ -5,24 +5,38 @@ var PromiseA = require('bluebird');
|
||||||
|
|
||||||
module.exports.fetchFromDisk = function (args, defaults) {
|
module.exports.fetchFromDisk = function (args, defaults) {
|
||||||
var hostname = args.domains[0];
|
var hostname = args.domains[0];
|
||||||
var crtpath = (args.fullchainPath || defaults.fullchainPath)
|
var certPath = (args.fullchainPath || defaults.fullchainPath)
|
||||||
|| (defaults.configDir
|
|| (defaults.configDir
|
||||||
+ (args.fullchainTpl || defaults.fullchainTpl || ':hostname/fullchain.pem').replace(/:hostname/, hostname));
|
+ (args.fullchainTpl || defaults.fullchainTpl || ':hostname/fullchain.pem').replace(/:hostname/, hostname));
|
||||||
var privpath = (args.privkeyPath || defaults.privkeyPath)
|
var privkeyPath = (args.privkeyPath || defaults.privkeyPath)
|
||||||
|| (defaults.configDir
|
|| (defaults.configDir
|
||||||
+ (args.privkeyTpl || defaults.privkeyTpl || ':hostname/privkey.pem').replace(/:hostname/, hostname));
|
+ (args.privkeyTpl || defaults.privkeyTpl || ':hostname/privkey.pem').replace(/:hostname/, hostname));
|
||||||
|
var chainPath = (args.chainPath || defaults.chainPath)
|
||||||
|
|| (defaults.configDir
|
||||||
|
+ (args.chainTpl || defaults.chainTpl || ':hostname/chain.pem').replace(/:hostname/, hostname));
|
||||||
|
/*
|
||||||
|
var fullchainPath = (args.fullchainPath || defaults.fullchainPath)
|
||||||
|
|| (defaults.configDir
|
||||||
|
+ (args.fullchainTpl || defaults.fullchainTpl || ':hostname/fullchain.pem').replace(/:hostname/, hostname));
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
return PromiseA.all([
|
return PromiseA.all([
|
||||||
fs.readFileAsync(privpath, 'ascii')
|
fs.readFileAsync(privkeyPath, 'ascii')
|
||||||
, fs.readFileAsync(crtpath, 'ascii')
|
, fs.readFileAsync(certPath, 'ascii')
|
||||||
|
, fs.readFileAsync(chainPath, 'ascii')
|
||||||
|
//, fs.readFileAsync(fullchainPath, 'ascii')
|
||||||
// stat the file, not the link
|
// stat the file, not the link
|
||||||
, fs.statAsync(crtpath)
|
, fs.statAsync(certPath)
|
||||||
]).then(function (arr) {
|
]).then(function (arr) {
|
||||||
|
// TODO parse certificate to determine lifetime and expiresAt
|
||||||
return {
|
return {
|
||||||
key: arr[0] // privkey.pem
|
key: arr[0] // privkey.pem
|
||||||
, cert: arr[1] // fullchain.pem
|
, cert: arr[1] // cert.pem
|
||||||
// TODO parse centificate for lifetime / expiresAt
|
, chain: arr[2] // chain.pem
|
||||||
, issuedAt: arr[2].mtime.valueOf()
|
, fullchain: arr[1] + '\n' + arr[2] // fullchain.pem
|
||||||
|
|
||||||
|
, issuedAt: arr[4].mtime.valueOf() // ???
|
||||||
};
|
};
|
||||||
}, function () {
|
}, function () {
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -3,12 +3,11 @@
|
||||||
var PromiseA = require('bluebird');
|
var PromiseA = require('bluebird');
|
||||||
var mkdirpAsync = PromiseA.promisify(require('mkdirp'));
|
var mkdirpAsync = PromiseA.promisify(require('mkdirp'));
|
||||||
var path = require('path');
|
var path = require('path');
|
||||||
var fs = PromiseA.promisifyAll(require('fs'));
|
|
||||||
var sfs = require('safe-replace');
|
var sfs = require('safe-replace');
|
||||||
|
|
||||||
var LE = require('../');
|
var LE = require('../');
|
||||||
var LeCore = PromiseA.promisifyAll(require('letiny-core'));
|
var LeCore = PromiseA.promisifyAll(require('letiny-core'));
|
||||||
var leCrypto = PromiseA.promisifyAll(LeCore.leCrypto);
|
var leCrypto = PromiseA.promisifyAll(LeCore.leCrypto);
|
||||||
|
var Accounts = require('./accounts');
|
||||||
|
|
||||||
var fetchFromConfigLiveDir = require('./common').fetchFromDisk;
|
var fetchFromConfigLiveDir = require('./common').fetchFromDisk;
|
||||||
|
|
||||||
|
@ -30,115 +29,10 @@ function getAcmeUrls(args) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function createAccount(args, handlers) {
|
|
||||||
var os = require("os");
|
|
||||||
var localname = os.hostname();
|
|
||||||
|
|
||||||
// TODO support ECDSA
|
|
||||||
// arg.rsaBitLength args.rsaExponent
|
|
||||||
return leCrypto.generateRsaKeypairAsync(args.rsaBitLength, args.rsaExponent).then(function (pems) {
|
|
||||||
/* pems = { privateKeyPem, privateKeyJwk, publicKeyPem, publicKeyMd5 } */
|
|
||||||
|
|
||||||
return LeCore.registerNewAccountAsync({
|
|
||||||
email: args.email
|
|
||||||
, newRegUrl: args._acmeUrls.newReg
|
|
||||||
, agreeToTerms: function (tosUrl, agree) {
|
|
||||||
// args.email = email; // already there
|
|
||||||
args.tosUrl = tosUrl;
|
|
||||||
handlers.agreeToTerms(args, agree);
|
|
||||||
}
|
|
||||||
, accountPrivateKeyPem: pems.privateKeyPem
|
|
||||||
|
|
||||||
, debug: args.debug || handlers.debug
|
|
||||||
}).then(function (body) {
|
|
||||||
var accountDir = path.join(args.accountsDir, pems.publicKeyMd5);
|
|
||||||
|
|
||||||
return mkdirpAsync(accountDir).then(function () {
|
|
||||||
|
|
||||||
var isoDate = new Date().toISOString();
|
|
||||||
var accountMeta = {
|
|
||||||
creation_host: localname
|
|
||||||
, creation_dt: isoDate
|
|
||||||
};
|
|
||||||
|
|
||||||
return PromiseA.all([
|
|
||||||
// meta.json {"creation_host": "ns1.redirect-www.org", "creation_dt": "2015-12-11T04:14:38Z"}
|
|
||||||
fs.writeFileAsync(path.join(accountDir, 'meta.json'), JSON.stringify(accountMeta), 'utf8')
|
|
||||||
// private_key.json { "e", "d", "n", "q", "p", "kty", "qi", "dp", "dq" }
|
|
||||||
, fs.writeFileAsync(path.join(accountDir, 'private_key.json'), JSON.stringify(pems.privateKeyJwk), 'utf8')
|
|
||||||
// regr.json:
|
|
||||||
/*
|
|
||||||
{ body: { contact: [ 'mailto:coolaj86@gmail.com' ],
|
|
||||||
agreement: 'https://letsencrypt.org/documents/LE-SA-v1.0.1-July-27-2015.pdf',
|
|
||||||
key: { e: 'AQAB', kty: 'RSA', n: '...' } },
|
|
||||||
uri: 'https://acme-v01.api.letsencrypt.org/acme/reg/71272',
|
|
||||||
new_authzr_uri: 'https://acme-v01.api.letsencrypt.org/acme/new-authz',
|
|
||||||
terms_of_service: 'https://letsencrypt.org/documents/LE-SA-v1.0.1-July-27-2015.pdf' }
|
|
||||||
*/
|
|
||||||
, fs.writeFileAsync(path.join(accountDir, 'regr.json'), JSON.stringify({ body: body }), 'utf8')
|
|
||||||
]).then(function () {
|
|
||||||
return pems;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function getAccount(accountId, args, handlers) {
|
|
||||||
var accountDir = path.join(args.accountsDir, accountId);
|
|
||||||
var files = {};
|
|
||||||
var configs = ['meta.json', 'private_key.json', 'regr.json'];
|
|
||||||
|
|
||||||
return PromiseA.all(configs.map(function (filename) {
|
|
||||||
var keyname = filename.slice(0, -5);
|
|
||||||
|
|
||||||
return fs.readFileAsync(path.join(accountDir, filename), 'utf8').then(function (text) {
|
|
||||||
var data;
|
|
||||||
|
|
||||||
try {
|
|
||||||
data = JSON.parse(text);
|
|
||||||
} catch(e) {
|
|
||||||
files[keyname] = { error: e };
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
files[keyname] = data;
|
|
||||||
}, function (err) {
|
|
||||||
files[keyname] = { error: err };
|
|
||||||
});
|
|
||||||
})).then(function () {
|
|
||||||
|
|
||||||
if (!Object.keys(files).every(function (key) {
|
|
||||||
return !files[key].error;
|
|
||||||
})) {
|
|
||||||
// TODO log renewal.conf
|
|
||||||
console.warn("Account '" + accountId + "' was currupt. No big deal (I think?). Creating a new one...");
|
|
||||||
return createAccount(args, handlers);
|
|
||||||
}
|
|
||||||
|
|
||||||
return leCrypto.parseAccountPrivateKeyAsync(files.private_key).then(function (keypair) {
|
|
||||||
files.accountId = accountId; // md5sum(publicKeyPem)
|
|
||||||
files.publicKeyMd5 = accountId; // md5sum(publicKeyPem)
|
|
||||||
files.publicKeyPem = keypair.publicKeyPem; // ascii PEM: ----BEGIN...
|
|
||||||
files.privateKeyPem = keypair.privateKeyPem; // ascii PEM: ----BEGIN...
|
|
||||||
files.privateKeyJson = keypair.private_key; // json { n: ..., e: ..., iq: ..., etc }
|
|
||||||
|
|
||||||
return files;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function getAccountByEmail(args) {
|
|
||||||
// If we read 10,000 account directories looking for
|
|
||||||
// just one email address, that could get crazy.
|
|
||||||
// We should have a folder per email and list
|
|
||||||
// each account as a file in the folder
|
|
||||||
// TODO
|
|
||||||
return PromiseA.resolve(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getCertificateAsync(account, args, defaults, handlers) {
|
function getCertificateAsync(account, args, defaults, handlers) {
|
||||||
var pyconf = PromiseA.promisifyAll(require('pyconf'));
|
//var pyconf = PromiseA.promisifyAll(require('pyconf'));
|
||||||
|
|
||||||
return leCrypto.generateRsaKeypairAsync(args.rsaBitLength, args.rsaExponent).then(function (domain) {
|
return leCrypto.generateRsaKeypairAsync(args.rsaBitLength, args.rsaExponent).then(function (domain) {
|
||||||
return LeCore.getCertificateAsync({
|
return LeCore.getCertificateAsync({
|
||||||
|
@ -156,7 +50,8 @@ function getCertificateAsync(account, args, defaults, handlers) {
|
||||||
handlers.setChallenge(args, key, value, done);
|
handlers.setChallenge(args, key, value, done);
|
||||||
}
|
}
|
||||||
else if (5 === handlers.setChallenge.length) {
|
else if (5 === handlers.setChallenge.length) {
|
||||||
handlers.setChallenge(args, domain, key, value, done);
|
// TODO merge templates with domain
|
||||||
|
handlers.setChallenge(defaults, domain, key, value, done);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
done(new Error("handlers.setChallenge receives the wrong number of arguments"));
|
done(new Error("handlers.setChallenge receives the wrong number of arguments"));
|
||||||
|
@ -169,7 +64,8 @@ function getCertificateAsync(account, args, defaults, handlers) {
|
||||||
handlers.removeChallenge(args, key, done);
|
handlers.removeChallenge(args, key, done);
|
||||||
}
|
}
|
||||||
else if (4 === handlers.removeChallenge.length) {
|
else if (4 === handlers.removeChallenge.length) {
|
||||||
handlers.removeChallenge(args, domain, key, done);
|
// TODO merge templates with domain
|
||||||
|
handlers.removeChallenge(defaults, domain, key, done);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
done(new Error("handlers.removeChallenge receives the wrong number of arguments"));
|
done(new Error("handlers.removeChallenge receives the wrong number of arguments"));
|
||||||
|
@ -225,7 +121,7 @@ function registerWithAcme(args, defaults, handlers) {
|
||||||
return accountId;
|
return accountId;
|
||||||
}, function (err) {
|
}, function (err) {
|
||||||
if ("ENOENT" === err.code) {
|
if ("ENOENT" === err.code) {
|
||||||
return getAccountByEmail(args, handlers);
|
return Accounts.getAccountByEmail(args, handlers);
|
||||||
}
|
}
|
||||||
|
|
||||||
return PromiseA.reject(err);
|
return PromiseA.reject(err);
|
||||||
|
@ -235,9 +131,9 @@ function registerWithAcme(args, defaults, handlers) {
|
||||||
args._acmeUrls = urls;
|
args._acmeUrls = urls;
|
||||||
|
|
||||||
if (accountId) {
|
if (accountId) {
|
||||||
return getAccount(accountId, args, handlers);
|
return Accounts.getAccount(accountId, args, handlers);
|
||||||
} else {
|
} else {
|
||||||
return createAccount(args, handlers);
|
return Accounts.createAccount(args, handlers);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}).then(function (account) {
|
}).then(function (account) {
|
||||||
|
|
Loading…
Reference in New Issue