Compare commits
24 Commits
0abdb0b279
...
6286883fc2
Author | SHA1 | Date |
---|---|---|
AJ ONeal | 6286883fc2 | |
AJ ONeal | 6c054cf241 | |
AJ ONeal | 4b448fdf6b | |
AJ ONeal | 8fb396cfe9 | |
AJ ONeal | 5171a7d1e0 | |
AJ ONeal | 66f2574dbc | |
AJ ONeal | 21a937c491 | |
AJ ONeal | bfe68c04c7 | |
AJ ONeal | d1187b77de | |
AJ ONeal | 03f6b2dff1 | |
AJ ONeal | 5061b7391d | |
AJ ONeal | e2cca83a8c | |
AJ ONeal | 2e02eba962 | |
AJ ONeal | eb6819c7be | |
AJ ONeal | 59f896ac62 | |
AJ ONeal | 825001bfb8 | |
AJ ONeal | 772dd22516 | |
AJ ONeal | 96ef6ab36e | |
AJ ONeal | 84e21d2385 | |
Stanislav Panasik | f8f3086f1b | |
AJ ONeal | 4cd1a03d8a | |
AJ ONeal | 2b5877e495 | |
AJ ONeal | a2795e78c2 | |
AJ ONeal | 016632b06b |
43
README.md
43
README.md
|
@ -1,13 +1,16 @@
|
||||||
greenlock (node-letsencrypt)
|
| Sponsored by [ppl](https://ppl.family)
|
||||||
=========
|
| [acme-v2.js](https://git.coolaj86.com/coolaj86/acme-v2.js)
|
||||||
|
| **greenlock** ([npm](https://www.npmjs.com/package/greenlock))
|
||||||
| **greenlock**
|
|
||||||
| [greenlock-cli](https://git.coolaj86.com/coolaj86/greenlock-cli.js)
|
| [greenlock-cli](https://git.coolaj86.com/coolaj86/greenlock-cli.js)
|
||||||
| [greenlock-express](https://git.coolaj86.com/coolaj86/greenlock-express.js)
|
| [greenlock-express](https://git.coolaj86.com/coolaj86/greenlock-express.js)
|
||||||
|
([koa](https://git.coolaj86.com/coolaj86/greenlock-koa.js))
|
||||||
|
([hapi](https://git.coolaj86.com/coolaj86/greenlock-hapi.js))
|
||||||
| [greenlock-cluster](https://git.coolaj86.com/coolaj86/greenlock-cluster.js)
|
| [greenlock-cluster](https://git.coolaj86.com/coolaj86/greenlock-cluster.js)
|
||||||
| [greenlock-koa](https://git.coolaj86.com/coolaj86/greenlock-koa.js)
|
|
|
||||||
| [greenlock-hapi](https://git.coolaj86.com/coolaj86/greenlock-hapi.js)
|
|
||||||
| Sponsored by [Daplie](https://daplie.com)
|
Greenlock™ for node.js
|
||||||
|
=====
|
||||||
|
(previously node-letsencrypt)
|
||||||
|
|
||||||
Automatic [Let's Encrypt](https://letsencrypt.org) (ACME) HTTPS / TLS / SSL Certificates for node.js
|
Automatic [Let's Encrypt](https://letsencrypt.org) (ACME) HTTPS / TLS / SSL Certificates for node.js
|
||||||
|
|
||||||
|
@ -30,6 +33,8 @@ see [greenlock-koa (previously letsencrypt-koa)](https://git.coolaj86.com/coolaj
|
||||||
For `bash`, `fish`, `zsh`, `cmd.exe`, `PowerShell`
|
For `bash`, `fish`, `zsh`, `cmd.exe`, `PowerShell`
|
||||||
see [**greenlock-cli** (previously letsencrypt-cli)](https://git.coolaj86.com/coolaj86/greenlock-cli.js).
|
see [**greenlock-cli** (previously letsencrypt-cli)](https://git.coolaj86.com/coolaj86/greenlock-cli.js).
|
||||||
|
|
||||||
|
### Now supports **Let's Encrypt v2**!!
|
||||||
|
|
||||||
Install
|
Install
|
||||||
=======
|
=======
|
||||||
|
|
||||||
|
@ -125,7 +130,18 @@ function leAgree(opts, agreeCb) {
|
||||||
}
|
}
|
||||||
|
|
||||||
le = LE.create({
|
le = LE.create({
|
||||||
server: LE.stagingServerUrl // or LE.productionServerUrl
|
version: 'draft-11' // 'draft-11' or 'v01'
|
||||||
|
// 'draft-11' is for Let's Encrypt v2 otherwise known as ACME draft 11
|
||||||
|
// 'v02' is an alias for 'draft-11'
|
||||||
|
// 'v01' is for the pre-spec Let's Encrypt v1
|
||||||
|
//
|
||||||
|
// staging API
|
||||||
|
server: 'https://acme-staging-v02.api.letsencrypt.org/directory'
|
||||||
|
|
||||||
|
//
|
||||||
|
// production API
|
||||||
|
//server: 'https://acme-v02.api.letsencrypt.org/directory'
|
||||||
|
|
||||||
, store: leStore // handles saving of config, accounts, and certificates
|
, store: leStore // handles saving of config, accounts, and certificates
|
||||||
, challenges: {
|
, challenges: {
|
||||||
'http-01': leHttpChallenge // handles /.well-known/acme-challege keys and tokens
|
'http-01': leHttpChallenge // handles /.well-known/acme-challege keys and tokens
|
||||||
|
@ -135,6 +151,11 @@ le = LE.create({
|
||||||
, challengeType: 'http-01' // default to this challenge type
|
, challengeType: 'http-01' // default to this challenge type
|
||||||
, agreeToTerms: leAgree // hook to allow user to view and accept LE TOS
|
, agreeToTerms: leAgree // hook to allow user to view and accept LE TOS
|
||||||
//, sni: require('le-sni-auto').create({}) // handles sni callback
|
//, sni: require('le-sni-auto').create({}) // handles sni callback
|
||||||
|
|
||||||
|
// renewals happen at a random time within this window
|
||||||
|
, renewWithin: 14 * 24 * 60 * 60 * 1000 // certificate renewal may begin at this time
|
||||||
|
, renewBy: 10 * 24 * 60 * 60 * 1000 // certificate renewal should happen by this time
|
||||||
|
|
||||||
, debug: false
|
, debug: false
|
||||||
//, log: function (debug) {console.log.apply(console, args);} // handles debug outputs
|
//, log: function (debug) {console.log.apply(console, args);} // handles debug outputs
|
||||||
});
|
});
|
||||||
|
@ -261,7 +282,11 @@ See https://git.coolaj86.com/coolaj86/le-challenge-fs.js
|
||||||
|
|
||||||
Change History
|
Change History
|
||||||
==============
|
==============
|
||||||
|
* v2.2 - Let's Encrypt v2 Support
|
||||||
|
* v2.2.4 - don't promisify all of `dns`
|
||||||
|
* v2.2.3 - `renewWithin` default to 14 days
|
||||||
|
* v2.2.2 - replace git dependency with npm
|
||||||
|
* v2.2.1 - April 2018 **Let's Encrypt v2** support
|
||||||
* v2.1.17 - Nov 5th 2017 migrate back to personal repo
|
* v2.1.17 - Nov 5th 2017 migrate back to personal repo
|
||||||
* v2.1.9 - Jan 18th 2017 renamed to greenlock
|
* v2.1.9 - Jan 18th 2017 renamed to greenlock
|
||||||
* v2.0.2 - Aug 9th 2016 update readme
|
* v2.0.2 - Aug 9th 2016 update readme
|
||||||
|
|
111
index.js
111
index.js
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
var DAY = 24 * 60 * 60 * 1000;
|
var DAY = 24 * 60 * 60 * 1000;
|
||||||
//var MIN = 60 * 1000;
|
//var MIN = 60 * 1000;
|
||||||
var ACME = require('le-acme-core').ACME;
|
var ACME = require('acme-v2/compat').ACME;
|
||||||
|
|
||||||
var LE = module.exports;
|
var LE = module.exports;
|
||||||
LE.LE = LE;
|
LE.LE = LE;
|
||||||
|
@ -19,12 +19,12 @@ function _log(debug) {
|
||||||
}
|
}
|
||||||
|
|
||||||
LE.defaults = {
|
LE.defaults = {
|
||||||
productionServerUrl: ACME.productionServerUrl
|
productionServerUrl: 'https://acme-v02.api.letsencrypt.org/directory'
|
||||||
, stagingServerUrl: ACME.stagingServerUrl
|
, stagingServerUrl: 'https://acme-staging-v02.api.letsencrypt.org/directory'
|
||||||
|
|
||||||
, rsaKeySize: ACME.rsaKeySize || 2048
|
, rsaKeySize: ACME.rsaKeySize || 2048
|
||||||
, challengeType: ACME.challengeType || 'http-01'
|
, challengeType: ACME.challengeType || 'http-01'
|
||||||
, challengeTypes: ACME.challengeTypes || [ 'http-01', 'tls-sni-01', 'dns-01' ]
|
, challengeTypes: ACME.challengeTypes || [ 'http-01', 'dns-01' ]
|
||||||
|
|
||||||
, acmeChallengePrefix: ACME.acmeChallengePrefix
|
, acmeChallengePrefix: ACME.acmeChallengePrefix
|
||||||
};
|
};
|
||||||
|
@ -53,6 +53,7 @@ LE._undefined = {
|
||||||
, rsaKeySize: u
|
, rsaKeySize: u
|
||||||
, challengeType: u
|
, challengeType: u
|
||||||
, server: u
|
, server: u
|
||||||
|
, version: u
|
||||||
, agreeToTerms: u
|
, agreeToTerms: u
|
||||||
, _ipc: u
|
, _ipc: u
|
||||||
, duplicate: u
|
, duplicate: u
|
||||||
|
@ -70,7 +71,6 @@ LE._undefine = function (le) {
|
||||||
LE.create = function (le) {
|
LE.create = function (le) {
|
||||||
var PromiseA = require('bluebird');
|
var PromiseA = require('bluebird');
|
||||||
|
|
||||||
le.acme = le.acme || ACME.create({ debug: le.debug });
|
|
||||||
le.store = le.store || require('le-store-certbot').create({ debug: le.debug });
|
le.store = le.store || require('le-store-certbot').create({ debug: le.debug });
|
||||||
le.core = require('./lib/core');
|
le.core = require('./lib/core');
|
||||||
var log = le.log || _log;
|
var log = le.log || _log;
|
||||||
|
@ -81,9 +81,11 @@ LE.create = function (le) {
|
||||||
if (!le.challenges['http-01']) {
|
if (!le.challenges['http-01']) {
|
||||||
le.challenges['http-01'] = require('le-challenge-fs').create({ debug: le.debug });
|
le.challenges['http-01'] = require('le-challenge-fs').create({ debug: le.debug });
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
if (!le.challenges['tls-sni-01']) {
|
if (!le.challenges['tls-sni-01']) {
|
||||||
le.challenges['tls-sni-01'] = require('le-challenge-sni').create({ debug: le.debug });
|
le.challenges['tls-sni-01'] = require('le-challenge-sni').create({ debug: le.debug });
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
if (!le.challenges['dns-01']) {
|
if (!le.challenges['dns-01']) {
|
||||||
try {
|
try {
|
||||||
le.challenges['dns-01'] = require('le-challenge-ddns').create({ debug: le.debug });
|
le.challenges['dns-01'] = require('le-challenge-ddns').create({ debug: le.debug });
|
||||||
|
@ -101,11 +103,12 @@ LE.create = function (le) {
|
||||||
le.rsaKeySize = le.rsaKeySize || LE.rsaKeySize;
|
le.rsaKeySize = le.rsaKeySize || LE.rsaKeySize;
|
||||||
le.challengeType = le.challengeType || LE.challengeType;
|
le.challengeType = le.challengeType || LE.challengeType;
|
||||||
le._ipc = ipc;
|
le._ipc = ipc;
|
||||||
|
le._communityPackage = le._communityPackage || 'greenlock.js';
|
||||||
le.agreeToTerms = le.agreeToTerms || function (args, agreeCb) {
|
le.agreeToTerms = le.agreeToTerms || function (args, agreeCb) {
|
||||||
agreeCb(new Error("'agreeToTerms' was not supplied to LE and 'agreeTos' was not supplied to LE.register"));
|
agreeCb(new Error("'agreeToTerms' was not supplied to LE and 'agreeTos' was not supplied to LE.register"));
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!le.renewWithin) { le.renewWithin = 7 * DAY; }
|
if (!le.renewWithin) { le.renewWithin = 14 * DAY; }
|
||||||
// renewBy has a default in le-sni-auto
|
// renewBy has a default in le-sni-auto
|
||||||
|
|
||||||
if (!le.server) {
|
if (!le.server) {
|
||||||
|
@ -118,6 +121,42 @@ LE.create = function (le) {
|
||||||
le.server = LE.productionServerUrl;
|
le.server = LE.productionServerUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (-1 !== [ 'https://acme-v01.api.letsencrypt.org/directory'
|
||||||
|
, 'https://acme-staging.api.letsencrypt.org/directory' ].indexOf(le.server)) {
|
||||||
|
ACME = require('le-acme-core').ACME;
|
||||||
|
console.warn("Let's Encrypt v1 is deprecated. Please update to Let's Encrypt v2 (ACME draft 11)");
|
||||||
|
}
|
||||||
|
else if (-1 !== [ 'https://acme-v02.api.letsencrypt.org/directory'
|
||||||
|
, 'https://acme-staging-v02.api.letsencrypt.org/directory' ].indexOf(le.server)) {
|
||||||
|
if ('v02' !== le.version && 'draft-11' !== le.version) {
|
||||||
|
ACME = require('le-acme-core').ACME;
|
||||||
|
if ('v01' !== le.version) {
|
||||||
|
//console.warn("Please specify version: 'v01' (Let's Encrypt v1) or 'draft-11' (Let's Encrypt v2 / ACME draft 11)");
|
||||||
|
console.warn("");
|
||||||
|
console.warn("");
|
||||||
|
console.warn("");
|
||||||
|
console.warn("====================================================================");
|
||||||
|
console.warn("== greenlock.js (v2.2.0+) ==");
|
||||||
|
console.warn("====================================================================");
|
||||||
|
console.warn("");
|
||||||
|
console.warn("Please specify 'version' option:");
|
||||||
|
console.warn("");
|
||||||
|
console.warn(" 'v01' for Let's Encrypt v1");
|
||||||
|
console.warn(" or");
|
||||||
|
console.warn(" 'draft-11' for Let's Encrypt v2 and ACME draft 11");
|
||||||
|
console.warn(" ('v02' is an alias of 'draft-11'");
|
||||||
|
console.warn("");
|
||||||
|
console.warn("====================================================================");
|
||||||
|
console.warn("== this will be required from version v2.3 forward ==");
|
||||||
|
console.warn("====================================================================");
|
||||||
|
console.warn("");
|
||||||
|
console.warn("");
|
||||||
|
console.warn("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
le.acme = le.acme || ACME.create({ debug: le.debug });
|
||||||
if (le.acme.create) {
|
if (le.acme.create) {
|
||||||
le.acme = le.acme.create(le);
|
le.acme = le.acme.create(le);
|
||||||
}
|
}
|
||||||
|
@ -183,6 +222,7 @@ LE.create = function (le) {
|
||||||
+ " You must define removeChallenge as function (opts, domain, token, cb) { }");
|
+ " You must define removeChallenge as function (opts, domain, token, cb) { }");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
if (!le._challengeWarn && (!challenger.loopback || 4 !== challenger.loopback.length)) {
|
if (!le._challengeWarn && (!challenger.loopback || 4 !== challenger.loopback.length)) {
|
||||||
le._challengeWarn = true;
|
le._challengeWarn = true;
|
||||||
console.warn("le.challenges[" + challengeType + "].loopback should be defined as function (opts, domain, token, cb) { ... } and should prove (by external means) that the ACME server challenge '" + challengeType + "' will succeed");
|
console.warn("le.challenges[" + challengeType + "].loopback should be defined as function (opts, domain, token, cb) { ... } and should prove (by external means) that the ACME server challenge '" + challengeType + "' will succeed");
|
||||||
|
@ -191,6 +231,7 @@ LE.create = function (le) {
|
||||||
le._challengeWarn = true;
|
le._challengeWarn = true;
|
||||||
console.warn("le.challenges[" + challengeType + "].test should be defined as function (opts, domain, token, keyAuthorization, cb) { ... } and should prove (by external means) that the ACME server challenge '" + challengeType + "' will succeed");
|
console.warn("le.challenges[" + challengeType + "].test should be defined as function (opts, domain, token, keyAuthorization, cb) { ... } and should prove (by external means) that the ACME server challenge '" + challengeType + "' will succeed");
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
});
|
});
|
||||||
|
|
||||||
le.sni = le.sni || null;
|
le.sni = le.sni || null;
|
||||||
|
@ -219,6 +260,7 @@ LE.create = function (le) {
|
||||||
lexOpts.domains = le.approvedDomains.slice(0);
|
lexOpts.domains = le.approvedDomains.slice(0);
|
||||||
lexOpts.email = le.email;
|
lexOpts.email = le.email;
|
||||||
lexOpts.agreeTos = le.agreeTos;
|
lexOpts.agreeTos = le.agreeTos;
|
||||||
|
lexOpts.communityMember = lexOpts.communityMember;
|
||||||
return cb(null, { options: lexOpts, certs: certs });
|
return cb(null, { options: lexOpts, certs: certs });
|
||||||
}
|
}
|
||||||
log(le.debug, 'unapproved domain', lexOpts.domains, le.approvedDomains);
|
log(le.debug, 'unapproved domain', lexOpts.domains, le.approvedDomains);
|
||||||
|
@ -231,36 +273,53 @@ LE.create = function (le) {
|
||||||
log(le.debug, 'le.getCertificates called for', domain, 'with certs for', certs && certs.altnames || 'NONE');
|
log(le.debug, 'le.getCertificates called for', domain, 'with certs for', certs && certs.altnames || 'NONE');
|
||||||
var opts = { domain: domain, domains: certs && certs.altnames || [ domain ] };
|
var opts = { domain: domain, domains: certs && certs.altnames || [ domain ] };
|
||||||
|
|
||||||
le.approveDomains(opts, certs, function (_err, results) {
|
try {
|
||||||
if (_err) {
|
le.approveDomains(opts, certs, function (_err, results) {
|
||||||
log(le.debug, 'le.approveDomains called with error', _err);
|
if (_err) {
|
||||||
cb(_err);
|
log(le.debug, 'le.approveDomains called with error', _err);
|
||||||
return;
|
cb(_err);
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
log(le.debug, 'le.approveDomains called with certs for', results.certs && results.certs.altnames || 'NONE', 'and options:');
|
log(le.debug, 'le.approveDomains called with certs for', results.certs && results.certs.altnames || 'NONE', 'and options:');
|
||||||
log(le.debug, results.options);
|
log(le.debug, results.options);
|
||||||
|
|
||||||
var promise;
|
var promise;
|
||||||
|
|
||||||
if (results.certs) {
|
if (results.certs) {
|
||||||
log(le.debug, 'le renewing');
|
log(le.debug, 'le renewing');
|
||||||
promise = le.core.certificates.renewAsync(results.options, results.certs);
|
promise = le.core.certificates.renewAsync(results.options, results.certs);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
log(le.debug, 'le getting from disk or registering new');
|
log(le.debug, 'le getting from disk or registering new');
|
||||||
promise = le.core.certificates.getAsync(results.options);
|
promise = le.core.certificates.getAsync(results.options);
|
||||||
}
|
}
|
||||||
|
|
||||||
return promise.then(function (certs) { cb(null, certs); }, cb);
|
return promise.then(function (certs) { cb(null, certs); }, function (e) {
|
||||||
});
|
if (le.debug) { console.debug("Error"); console.debug(e); }
|
||||||
|
cb(e);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} catch(e) {
|
||||||
|
console.error("[ERROR] Something went wrong in approveDomains:");
|
||||||
|
console.error(e);
|
||||||
|
console.error("BUT WAIT! Good news: It's probably your fault, so you can probably fix it.");
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
le.sni = le.sni || require('le-sni-auto');
|
le.sni = le.sni || require('le-sni-auto');
|
||||||
if (le.sni.create) {
|
if (le.sni.create) {
|
||||||
le.sni = le.sni.create(le);
|
le.sni = le.sni.create(le);
|
||||||
}
|
}
|
||||||
le.tlsOptions.SNICallback = le.sni.sniCallback;
|
le.tlsOptions.SNICallback = function (domain, cb) {
|
||||||
|
try {
|
||||||
|
le.sni.sniCallback(domain, cb);
|
||||||
|
} catch(e) {
|
||||||
|
console.error("[ERROR] Something went wrong in the SNICallback:");
|
||||||
|
console.error(e);
|
||||||
|
cb(e);
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
if (!le.tlsOptions.key || !le.tlsOptions.cert) {
|
if (!le.tlsOptions.key || !le.tlsOptions.cert) {
|
||||||
le.tlsOptions = require('localhost.daplie.me-certificates').merge(le.tlsOptions);
|
le.tlsOptions = require('localhost.daplie.me-certificates').merge(le.tlsOptions);
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
function addCommunityMember(pkg, email, domains) {
|
||||||
|
setTimeout(function () {
|
||||||
|
var https = require('https');
|
||||||
|
var req = https.request({
|
||||||
|
hostname: 'api.ppl.family'
|
||||||
|
, port: 443
|
||||||
|
, path: '/api/ppl.family/public/list'
|
||||||
|
, method: 'POST'
|
||||||
|
, headers: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
}
|
||||||
|
}, function (err, resp) {
|
||||||
|
if (err) { return; }
|
||||||
|
resp.on('data', function () {});
|
||||||
|
});
|
||||||
|
req.write(JSON.stringify({
|
||||||
|
address: email
|
||||||
|
, comment: (pkg || 'community') + ' member w/ ' + (domains||[]).map(function (d) {
|
||||||
|
return require('crypto').createHash('sha1').update(d).digest('base64')
|
||||||
|
.replace(/\//g, '_').replace(/\+/g, '-').replace(/=/g, '');
|
||||||
|
}).join(',')
|
||||||
|
}));
|
||||||
|
req.end();
|
||||||
|
}, 50);
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports.add = addCommunityMember;
|
12
lib/core.js
12
lib/core.js
|
@ -387,11 +387,23 @@ module.exports.create = function (le) {
|
||||||
return core.certificates.checkAsync(args).then(function (certs) {
|
return core.certificates.checkAsync(args).then(function (certs) {
|
||||||
if (!certs) {
|
if (!certs) {
|
||||||
// There is no cert available
|
// There is no cert available
|
||||||
|
if (args.communityMember && !args._communityMemberAdded) {
|
||||||
|
try {
|
||||||
|
require('./community').add(args._communityPackage + ' reg', args.email, args.domains);
|
||||||
|
} catch(e) { /* ignore */ }
|
||||||
|
args._communityMemberAdded = true;
|
||||||
|
}
|
||||||
return core.certificates.registerAsync(args);
|
return core.certificates.registerAsync(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (core.certificates._isRenewable(args, certs)) {
|
if (core.certificates._isRenewable(args, certs)) {
|
||||||
// it's time to renew the available cert
|
// it's time to renew the available cert
|
||||||
|
if (args.communityMember && !args._communityMemberAdded) {
|
||||||
|
try {
|
||||||
|
require('./community').add(args._communityPackage + ' renew', args.email, args.domains);
|
||||||
|
} catch(e) { /* ignore */ }
|
||||||
|
args._communityMemberAdded = true;
|
||||||
|
}
|
||||||
certs.renewing = core.certificates.renewAsync(args, certs);
|
certs.renewing = core.certificates.renewAsync(args, certs);
|
||||||
if (args.waitForRenewal) {
|
if (args.waitForRenewal) {
|
||||||
return certs.renewing;
|
return certs.renewing;
|
||||||
|
|
13
lib/utils.js
13
lib/utils.js
|
@ -2,10 +2,11 @@
|
||||||
|
|
||||||
var path = require('path');
|
var path = require('path');
|
||||||
var homeRe = new RegExp("^~(\\/|\\\\|\\" + path.sep + ")");
|
var homeRe = new RegExp("^~(\\/|\\\\|\\" + path.sep + ")");
|
||||||
var re = /^[a-zA-Z0-9\.\-]+$/;
|
// very basic check. Allows *.example.com.
|
||||||
|
var re = /^(\*\.)?[a-zA-Z0-9\.\-]+$/;
|
||||||
var punycode = require('punycode');
|
var punycode = require('punycode');
|
||||||
var PromiseA = require('bluebird');
|
var promisify = (require('util').promisify || require('bluebird').promisify);
|
||||||
var dns = PromiseA.promisifyAll(require('dns'));
|
var dnsResolveMxAsync = promisify(require('dns').resolveMx);
|
||||||
|
|
||||||
module.exports.attachCertInfo = function (results) {
|
module.exports.attachCertInfo = function (results) {
|
||||||
// XXX Note: Parsing the certificate info comes at a great cost (~500kb)
|
// XXX Note: Parsing the certificate info comes at a great cost (~500kb)
|
||||||
|
@ -107,10 +108,10 @@ module.exports.testEmail = function (email) {
|
||||||
if (2 !== parts.length || !parts[0] || !parts[1]) {
|
if (2 !== parts.length || !parts[0] || !parts[1]) {
|
||||||
err = new Error("malformed email address '" + email + "'");
|
err = new Error("malformed email address '" + email + "'");
|
||||||
err.code = 'E_EMAIL';
|
err.code = 'E_EMAIL';
|
||||||
return PromiseA.reject(err);
|
return Promise.reject(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
return dns.resolveMxAsync(parts[1]).then(function (records) {
|
return dnsResolveMxAsync(parts[1]).then(function (records) {
|
||||||
// records only returns when there is data
|
// records only returns when there is data
|
||||||
if (!records.length) {
|
if (!records.length) {
|
||||||
throw new Error("sanity check fail: success, but no MX records returned");
|
throw new Error("sanity check fail: success, but no MX records returned");
|
||||||
|
@ -120,7 +121,7 @@ module.exports.testEmail = function (email) {
|
||||||
if ('ENODATA' === err.code) {
|
if ('ENODATA' === err.code) {
|
||||||
err = new Error("no MX records found for '" + parts[1] + "'");
|
err = new Error("no MX records found for '" + parts[1] + "'");
|
||||||
err.code = 'E_EMAIL';
|
err.code = 'E_EMAIL';
|
||||||
return PromiseA.reject(err);
|
return Promise.reject(err);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
43
package.json
43
package.json
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "greenlock",
|
"name": "greenlock",
|
||||||
"version": "2.1.17",
|
"version": "2.2.10",
|
||||||
"description": "Let's Encrypt for node.js on npm",
|
"description": "Let's Encrypt for node.js on npm",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
@ -11,14 +11,35 @@
|
||||||
"url": "git+https://git.coolaj86.com/coolaj86/greenlock.js.git"
|
"url": "git+https://git.coolaj86.com/coolaj86/greenlock.js.git"
|
||||||
},
|
},
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"greenlock",
|
"acmev2",
|
||||||
|
"acmev02",
|
||||||
|
"acme-v2",
|
||||||
|
"acme-v02",
|
||||||
|
"acme",
|
||||||
|
"acme2",
|
||||||
|
"acme11",
|
||||||
|
"acme-draft11",
|
||||||
|
"acme-draft-11",
|
||||||
|
"draft",
|
||||||
|
"11",
|
||||||
|
"free",
|
||||||
|
"ssl",
|
||||||
|
"tls",
|
||||||
|
"https",
|
||||||
|
"Let's Encrypt",
|
||||||
"letsencrypt",
|
"letsencrypt",
|
||||||
|
"letsencrypt-v2",
|
||||||
|
"letsencrypt-v02",
|
||||||
|
"letsencryptv2",
|
||||||
|
"letsencryptv02",
|
||||||
|
"letsencrypt2",
|
||||||
|
"v2",
|
||||||
|
"v02",
|
||||||
|
"greenlock",
|
||||||
"letsencrypt.org",
|
"letsencrypt.org",
|
||||||
"le",
|
"le",
|
||||||
"Let's Encrypt",
|
|
||||||
"lejs",
|
"lejs",
|
||||||
"le.js",
|
"le.js",
|
||||||
"acme",
|
|
||||||
"node",
|
"node",
|
||||||
"nodejs",
|
"nodejs",
|
||||||
"node.js",
|
"node.js",
|
||||||
|
@ -33,20 +54,26 @@
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"request": "^2.75.0"
|
"request": "^2.75.0"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {},
|
"optionalDependencies": {
|
||||||
|
"bluebird": "^3.5.1"
|
||||||
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"acme-v2": "^1.0.2",
|
||||||
"asn1js": "^1.2.12",
|
"asn1js": "^1.2.12",
|
||||||
"bluebird": "^3.0.6",
|
|
||||||
"certpem": "^1.0.0",
|
"certpem": "^1.0.0",
|
||||||
"homedir": "^0.6.0",
|
"homedir": "^0.6.0",
|
||||||
"le-acme-core": "^2.0.5",
|
"le-acme-core": "^2.1.2",
|
||||||
"le-challenge-fs": "^2.0.2",
|
"le-challenge-fs": "^2.0.2",
|
||||||
"le-challenge-sni": "^2.0.0",
|
"le-challenge-sni": "^2.0.0",
|
||||||
"le-sni-auto": "^2.1.0",
|
"le-sni-auto": "^2.1.3",
|
||||||
"le-store-certbot": "^2.0.3",
|
"le-store-certbot": "^2.0.3",
|
||||||
"localhost.daplie.me-certificates": "^1.3.0",
|
"localhost.daplie.me-certificates": "^1.3.0",
|
||||||
"node.extend": "^1.1.5",
|
"node.extend": "^1.1.5",
|
||||||
"pkijs": "^1.3.27",
|
"pkijs": "^1.3.27",
|
||||||
"rsa-compat": "^1.2.1"
|
"rsa-compat": "^1.2.1"
|
||||||
|
},
|
||||||
|
"gitDependencies": {
|
||||||
|
"acme-v2": "git+https://git.coolaj86.com/coolaj86/acme-v2.js.git#v1.0",
|
||||||
|
"le-acme-core": "git+https://git.coolaj86.com/coolaj86/le-acme-core.js.git#v2.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue