mirror of
				https://github.com/therootcompany/greenlock.js.git
				synced 2024-11-16 17:29:00 +00:00 
			
		
		
		
	v2.7.23: regression bugfixes: node v6 and cloudflare dns-01
This commit is contained in:
		
							parent
							
								
									93b9158b1b
								
							
						
					
					
						commit
						5316af67be
					
				
							
								
								
									
										21
									
								
								lib/compat.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								lib/compat.js
									
									
									
									
									
										Normal file
									
								
							@ -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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user