addressing race condition mentioned in issue #72

This commit is contained in:
tigerbot 2017-04-06 14:21:12 -06:00
parent da2cc50061
commit 3a1324f464
1 changed files with 39 additions and 5 deletions

View File

@ -14,6 +14,7 @@ module.exports.create = function (le) {
var utils = require('./utils');
var RSA = PromiseA.promisifyAll(require('rsa-compat').RSA);
var log = le.log || _log; // allow custom log
var pendingRegistrations = {};
var core = {
//
@ -183,13 +184,45 @@ module.exports.create = function (le) {
return PromiseA.reject(err);
}
// If a previous request to (re)register a certificate is already underway we need
// to return the same promise created before rather than registering things twice.
// I'm not 100% sure how to properly handle the case where someone registers domain
// lists with some but not all elements common, nor am I sure that's even a case that
// is allowed to happen anyway. But for now we act like the list is completely the
// same if any elements are the same.
var promise;
args.domains.some(function (name) {
if (pendingRegistrations.hasOwnProperty(name)) {
promise = pendingRegistrations[name];
return true;
}
});
if (promise) {
return promise;
}
promise = core.certificates._runRegistration(args);
// Now that the registration is actually underway we need to make sure any subsequent
// registration attempts return the same promise until it is completed (but not after
// it is completed).
args.domains.forEach(function (name) {
pendingRegistrations[name] = promise;
});
function clearPending() {
args.domains.forEach(function (name) {
delete pendingRegistrations[name];
});
}
promise.then(clearPending, clearPending);
return promise;
}
, _runRegistration: function (args) {
// TODO renewal cb
// accountId and or email
return core.accounts.getAsync(copy).then(function (account) {
copy.account = account;
//var account = args.account;
var keypairOpts = { public: true, pem: true };
return core.accounts.getAsync(args).then(function (account) {
args.account = account;
var promise = le.store.certificates.checkKeypairAsync(args).then(function (keypair) {
if (keypair) {
@ -200,6 +233,7 @@ module.exports.create = function (le) {
return le.store.certificates.setKeypairAsync(args, RSA.import(args.domainKeypair));
}
var keypairOpts = { public: true, pem: true };
return RSA.generateKeypairAsync(args.rsaKeySize, 65537, keypairOpts).then(function (keypair) {
keypair.privateKeyPem = RSA.exportPrivatePem(keypair);
keypair.publicKeyPem = RSA.exportPublicPem(keypair);