v2.7.23: regression bugfixes: node v6 and cloudflare dns-01
This commit is contained in:
parent
93b9158b1b
commit
5316af67be
|
@ -0,0 +1,21 @@
|
|||
'use strict';
|
||||
|
||||
function requireBluebird() {
|
||||
try {
|
||||
return require('bluebird');
|
||||
} catch(e) {
|
||||
console.error("");
|
||||
console.error("DON'T PANIC. You're running an old version of node with incomplete Promise support.");
|
||||
console.error("EASY FIX: `npm install --save bluebird`");
|
||||
console.error("");
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
if ('undefined' === typeof Promise) {
|
||||
global.Promise = requireBluebird();
|
||||
}
|
||||
|
||||
if ('function' !== typeof require('util').promisify) {
|
||||
require('util').promisify = requireBluebird().promisify;
|
||||
}
|
35
lib/core.js
35
lib/core.js
|
@ -1,11 +1,7 @@
|
|||
'use strict';
|
||||
/*global Promise*/
|
||||
require('./compat.js');
|
||||
|
||||
var PromiseA;
|
||||
try {
|
||||
PromiseA = require('bluebird');
|
||||
} catch(e) {
|
||||
PromiseA = global.Promise;
|
||||
}
|
||||
var util = require('util');
|
||||
function promisifyAll(obj) {
|
||||
var aobj = {};
|
||||
|
@ -42,7 +38,7 @@ module.exports.create = function (gl) {
|
|||
|
||||
// TODO check response header on request for cache time
|
||||
if ((now - gl._ipc.acmeUrlsUpdatedAt) < 10 * 60 * 1000) {
|
||||
return PromiseA.resolve(gl._ipc.acmeUrls);
|
||||
return Promise.resolve(gl._ipc.acmeUrls);
|
||||
}
|
||||
|
||||
// TODO acme-v2/nocompat
|
||||
|
@ -79,7 +75,7 @@ module.exports.create = function (gl) {
|
|||
+ " and 'rsaKeySize' must be 2048 or greater."
|
||||
);
|
||||
err.code = 'E_ARGS';
|
||||
return PromiseA.reject(err);
|
||||
return Promise.reject(err);
|
||||
}
|
||||
|
||||
return utils.testEmail(args.email).then(function () {
|
||||
|
@ -156,9 +152,9 @@ module.exports.create = function (gl) {
|
|||
if (newAccountKeypair) {
|
||||
accountKeypairPromise = gl.store.accounts.setKeypairAsync(args, keypair);
|
||||
}
|
||||
return PromiseA.resolve(accountKeypairPromise).then(function () {
|
||||
return Promise.resolve(accountKeypairPromise).then(function () {
|
||||
// TODO move templating of arguments to right here?
|
||||
if (!gl.store.accounts.setAsync) { return PromiseA.resolve({ keypair: keypair }); }
|
||||
if (!gl.store.accounts.setAsync) { return Promise.resolve({ keypair: keypair }); }
|
||||
return gl.store.accounts.setAsync(args, reg).then(function (account) {
|
||||
if (account && 'object' !== typeof account) {
|
||||
throw new Error("store.accounts.setAsync should either return 'null' or an object with at least a string 'id'");
|
||||
|
@ -181,7 +177,7 @@ module.exports.create = function (gl) {
|
|||
if (gl.store.accounts.checkAsync) {
|
||||
accountPromise = core.accounts.checkAsync(args);
|
||||
}
|
||||
return PromiseA.resolve(accountPromise).then(function (account) {
|
||||
return Promise.resolve(accountPromise).then(function (account) {
|
||||
if (!account) { return core.accounts.registerAsync(args); }
|
||||
if (account.keypair) { return account; }
|
||||
|
||||
|
@ -201,7 +197,7 @@ module.exports.create = function (gl) {
|
|||
var requiredArgs = ['accountId', 'email', 'domains', 'domain'];
|
||||
if (!(args.account && (args.account.id || args.account.kid))
|
||||
&& !requiredArgs.some(function (key) { return -1 !== Object.keys(args).indexOf(key); })) {
|
||||
return PromiseA.reject(new Error(
|
||||
return Promise.reject(new Error(
|
||||
"In order to register or retrieve an account one of '" + requiredArgs.join("', '") + "' must be present"
|
||||
));
|
||||
}
|
||||
|
@ -213,7 +209,7 @@ module.exports.create = function (gl) {
|
|||
|
||||
// we can re-register the same account until we're blue in the face and it's all the same
|
||||
// of course, we can also skip the lookup if we do store the account, but whatever
|
||||
if (!gl.store.accounts.checkAsync) { return PromiseA.resolve(null); }
|
||||
if (!gl.store.accounts.checkAsync) { return Promise.resolve(null); }
|
||||
return gl.store.accounts.checkAsync(args).then(function (account) {
|
||||
|
||||
if (!account) {
|
||||
|
@ -240,7 +236,7 @@ module.exports.create = function (gl) {
|
|||
args = utils.tplCopy(copy);
|
||||
|
||||
if (!Array.isArray(args.domains)) {
|
||||
return PromiseA.reject(new Error('args.domains should be an array of domains'));
|
||||
return Promise.reject(new Error('args.domains should be an array of domains'));
|
||||
}
|
||||
//if (-1 === args.domains.indexOf(args.subject)) // TODO relax the constraint once acme-v2 handles subject?
|
||||
if (args.subject !== args.domains[0]) {
|
||||
|
@ -250,7 +246,7 @@ module.exports.create = function (gl) {
|
|||
console.warn('\topts.domains: (set by you in approveDomains()) ' + args.domains.join(','));
|
||||
console.warn("Updating your code will prevent weird, random, hard-to-repro bugs during renewals");
|
||||
console.warn("(also this will be required in the next major version of greenlock)");
|
||||
//return PromiseA.reject(new Error('certificate subject (primary domain) must be the first in opts.domains'));
|
||||
//return Promise.reject(new Error('certificate subject (primary domain) must be the first in opts.domains'));
|
||||
}
|
||||
if (!(args.domains.length && args.domains.every(utils.isValidDomain))) {
|
||||
// NOTE: this library can't assume to handle the http loopback
|
||||
|
@ -258,7 +254,7 @@ module.exports.create = function (gl) {
|
|||
// so we do not check dns records or attempt a loopback here
|
||||
err = new Error("invalid domain name(s): '(" + args.subject + ') ' + args.domains.join(',') + "'");
|
||||
err.code = "INVALID_DOMAIN";
|
||||
return PromiseA.reject(err);
|
||||
return Promise.reject(err);
|
||||
}
|
||||
|
||||
// If a previous request to (re)register a certificate is already underway we need
|
||||
|
@ -384,6 +380,9 @@ module.exports.create = function (gl) {
|
|||
Object.keys(challenge).forEach(function (key) {
|
||||
done[key] = challenge[key];
|
||||
});
|
||||
// regression bugfix for le-challenge-cloudflare
|
||||
// (_acme-challege => _greenlock-dryrun-XXXX)
|
||||
copy.acmePrefix = (challenge.dnsHost||'').replace(/\.*/, '') || copy.acmePrefix;
|
||||
gl.challenges[challenge.type].set(copy, challenge.altname, challenge.token, challenge.keyAuthorization, done);
|
||||
}
|
||||
};
|
||||
|
@ -429,7 +428,7 @@ module.exports.create = function (gl) {
|
|||
args.keypair = domainKeypair;
|
||||
promise = gl.store.certificates.setKeypairAsync(args, domainKeypair);
|
||||
}
|
||||
return PromiseA.resolve(promise).then(function () {
|
||||
return Promise.resolve(promise).then(function () {
|
||||
return gl.store.certificates.setAsync(args).then(function () {
|
||||
return results;
|
||||
});
|
||||
|
@ -455,7 +454,7 @@ module.exports.create = function (gl) {
|
|||
+ new Date(renewableAt).toISOString() + "'. Set { duplicate: true } to force."
|
||||
);
|
||||
err.code = 'E_NOT_RENEWABLE';
|
||||
return PromiseA.reject(err);
|
||||
return Promise.reject(err);
|
||||
}
|
||||
|
||||
// Either the cert has entered its renewal period
|
||||
|
|
20
lib/utils.js
20
lib/utils.js
|
@ -1,12 +1,12 @@
|
|||
'use strict';
|
||||
require('./compat.js');
|
||||
|
||||
var path = require('path');
|
||||
var homeRe = new RegExp("^~(\\/|\\\\|\\" + path.sep + ")");
|
||||
// very basic check. Allows *.example.com.
|
||||
var re = /^(\*\.)?[a-zA-Z0-9\.\-]+$/;
|
||||
var punycode = require('punycode');
|
||||
var promisify = (require('util').promisify || require('bluebird').promisify);
|
||||
var dnsResolveMxAsync = promisify(require('dns').resolveMx);
|
||||
var dnsResolveMxAsync = require('util').promisify(require('dns').resolveMx);
|
||||
|
||||
module.exports.attachCertInfo = function (results) {
|
||||
var certInfo = require('cert-info').info(results.cert);
|
||||
|
@ -54,12 +54,24 @@ module.exports.merge = function (/*defaults, args*/) {
|
|||
|
||||
allDefaults.forEach(function (defaults) {
|
||||
Object.keys(defaults).forEach(function (key) {
|
||||
copy[key] = defaults[key];
|
||||
if ('challenges' === key && copy[key] && defaults[key]) {
|
||||
Object.keys(defaults[key]).forEach(function (k) {
|
||||
copy[key][k] = defaults[key][k];
|
||||
});
|
||||
} else {
|
||||
copy[key] = defaults[key];
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
Object.keys(args).forEach(function (key) {
|
||||
copy[key] = args[key];
|
||||
if ('challenges' === key && copy[key] && args[key]) {
|
||||
Object.keys(args[key]).forEach(function (k) {
|
||||
copy[key][k] = args[key][k];
|
||||
});
|
||||
} else {
|
||||
copy[key] = args[key];
|
||||
}
|
||||
});
|
||||
|
||||
return copy;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "greenlock",
|
||||
"version": "2.7.22",
|
||||
"version": "2.7.23",
|
||||
"description": "Greenlock is Let's Encrypt (ACME) client for node.js",
|
||||
"homepage": "https://greenlock.domains/",
|
||||
"main": "index.js",
|
||||
|
|
|
@ -1,106 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
var PromiseA = require('bluebird');
|
||||
var path = require('path');
|
||||
var requestAsync = PromiseA.promisify(require('@coolaj86/request'));
|
||||
var LE = require('../').LE;
|
||||
var le = LE.create({
|
||||
server: 'staging'
|
||||
, acme: require('le-acme-core').ACME.create()
|
||||
, store: require('le-store-certbot').create({
|
||||
configDir: '~/letsencrypt.test/etc'.split('/').join(path.sep)
|
||||
, webrootPath: '~/letsencrypt.test/var/:hostname'.split('/').join(path.sep)
|
||||
})
|
||||
, challenge: require('le-challenge-fs').create({
|
||||
webrootPath: '~/letsencrypt.test/var/:hostname'.split('/').join(path.sep)
|
||||
})
|
||||
, debug: true
|
||||
});
|
||||
var utils = require('../lib/utils');
|
||||
|
||||
if ('/.well-known/acme-challenge/' !== LE.acmeChallengePrefix) {
|
||||
throw new Error("Bad constant 'acmeChallengePrefix'");
|
||||
}
|
||||
|
||||
var baseUrl;
|
||||
// could use localhost as well, but for the sake of an FQDN for testing, we use this
|
||||
// also, example.com is just a junk domain to make sure that it is ignored
|
||||
// (even though it should always be an array of only one element in lib/core.js)
|
||||
var domains = [ 'localhost.daplie.com', 'example.com' ]; // or just localhost
|
||||
var token = 'token-id';
|
||||
var secret = 'key-secret';
|
||||
|
||||
var tests = [
|
||||
function () {
|
||||
console.log('Test Url:', baseUrl + token);
|
||||
return requestAsync({ url: baseUrl + token }).then(function (req) {
|
||||
if (404 !== req.statusCode) {
|
||||
console.log(req.statusCode);
|
||||
throw new Error("Should be status 404");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
, function () {
|
||||
var copy = utils.merge({ domains: domains }, le);
|
||||
copy = utils.tplCopy(copy);
|
||||
return PromiseA.promisify(le.challenge.set)(copy, domains[0], token, secret);
|
||||
}
|
||||
|
||||
, function () {
|
||||
return requestAsync(baseUrl + token).then(function (req) {
|
||||
if (200 !== req.statusCode) {
|
||||
console.log(req.statusCode, req.body);
|
||||
throw new Error("Should be status 200");
|
||||
}
|
||||
|
||||
if (req.body !== secret) {
|
||||
console.error(token, secret, req.body);
|
||||
throw new Error("req.body should be secret");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
, function () {
|
||||
var copy = utils.merge({ domains: domains }, le);
|
||||
copy = utils.tplCopy(copy);
|
||||
return PromiseA.promisify(le.challenge.remove)(copy, domains[0], token);
|
||||
}
|
||||
|
||||
, function () {
|
||||
return requestAsync(baseUrl + token).then(function (req) {
|
||||
if (404 !== req.statusCode) {
|
||||
console.log(req.statusCode);
|
||||
throw new Error("Should be status 404");
|
||||
}
|
||||
});
|
||||
}
|
||||
];
|
||||
|
||||
function run() {
|
||||
//var express = require(express);
|
||||
var server = require('http').createServer(le.middleware());
|
||||
server.listen(0, function () {
|
||||
console.log('Server running, proceeding to test.');
|
||||
baseUrl = 'http://' + domains[0] + ':' + server.address().port + LE.acmeChallengePrefix;
|
||||
|
||||
function next() {
|
||||
var test = tests.shift();
|
||||
if (!test) {
|
||||
console.info('All tests passed');
|
||||
server.close();
|
||||
return;
|
||||
}
|
||||
|
||||
test().then(next, function (err) {
|
||||
console.error('ERROR');
|
||||
console.error(err.stack);
|
||||
server.close();
|
||||
});
|
||||
}
|
||||
|
||||
next();
|
||||
});
|
||||
}
|
||||
|
||||
run();
|
Loading…
Reference in New Issue