updates for Greenlock v3

This commit is contained in:
AJ ONeal 2019-10-21 13:45:47 -06:00
parent f7fd435443
commit c5757d2650
6 changed files with 114 additions and 65 deletions

64
acme.js
View File

@ -8,11 +8,13 @@
require('@root/encoding/bytes'); require('@root/encoding/bytes');
var Enc = require('@root/encoding/base64'); var Enc = require('@root/encoding/base64');
var ACME = module.exports; var ACME = module.exports;
//var Keypairs = exports.Keypairs || {}; var Keypairs = require('@root/keypairs');
//var CSR = exports.CSR; var CSR = require('@root/csr');
var sha2 = require('@root/keypairs/lib/node/sha2.js'); var sha2 = require('@root/keypairs/lib/node/sha2.js');
var http = require('./lib/node/http.js'); var http = require('./lib/node/http.js');
var native = require('./native.js');
ACME.formatPemChain = function formatPemChain(str) { ACME.formatPemChain = function formatPemChain(str) {
return ( return (
str str
@ -95,6 +97,7 @@ ACME.challengeTests = {
ACME._directory = function(me) { ACME._directory = function(me) {
// GET-as-GET ok // GET-as-GET ok
// TODO cache the directory URL
return me.request({ method: 'GET', url: me.directoryUrl, json: true }); return me.request({ method: 'GET', url: me.directoryUrl, json: true });
}; };
ACME._getNonce = function(me) { ACME._getNonce = function(me) {
@ -345,12 +348,6 @@ ACME._testChallengeOptions = function() {
token: 'test-' + chToken + '-1', token: 'test-' + chToken + '-1',
_wildcard: true _wildcard: true
}, },
{
type: 'tls-sni-01',
status: 'pending',
url: 'https://acme-staging-v02.example.com/2',
token: 'test-' + chToken + '-2'
},
{ {
type: 'tls-alpn-01', type: 'tls-alpn-01',
status: 'pending', status: 'pending',
@ -1317,8 +1314,8 @@ ACME.create = function create(me) {
} }
// me.debug = true; // me.debug = true;
me.challengePrefixes = ACME.challengePrefixes; me.challengePrefixes = ACME.challengePrefixes;
me.Keypairs = me.Keypairs || require('@root/keypairs'); me.Keypairs = me.Keypairs || Keypairs;
me.CSR = me.CSR || require('@root/csr'); me.CSR = me.CSR || CSR;
me._nonces = []; me._nonces = [];
me._canUse = {}; me._canUse = {};
if (!me._baseUrl) { if (!me._baseUrl) {
@ -1328,7 +1325,7 @@ ACME.create = function create(me) {
//me.request = me.request || require('@root/request'); //me.request = me.request || require('@root/request');
if (!me.dns01) { if (!me.dns01) {
me.dns01 = function(ch) { me.dns01 = function(ch) {
return ACME._dns01(me, ch); return native._dns01(me, ch);
}; };
} }
// backwards compat // backwards compat
@ -1337,7 +1334,7 @@ ACME.create = function create(me) {
} }
if (!me.http01) { if (!me.http01) {
me.http01 = function(ch) { me.http01 = function(ch) {
return ACME._http01(me, ch); return native._http01(me, ch);
}; };
} }
@ -1362,19 +1359,10 @@ ACME.create = function create(me) {
'you must supply either the ACME directory url as a string or an object of the ACME urls' 'you must supply either the ACME directory url as a string or an object of the ACME urls'
); );
} }
var p = Promise.resolve(); var p = Promise.resolve();
if (!me.skipChallengeTest) { if (!me.skipChallengeTest) {
p = me p = native._canCheck(me);
.request({ url: me._baseUrl + '/api/_acme_api_/' })
.then(function(resp) {
if (resp.body.success) {
me._canCheck['http-01'] = true;
me._canCheck['dns-01'] = true;
}
})
.catch(function() {
// ignore
});
} }
return p.then(function() { return p.then(function() {
return ACME._directory(me).then(function(resp) { return ACME._directory(me).then(function(resp) {
@ -1530,36 +1518,6 @@ ACME._prnd = function(n) {
ACME._toHex = function(pair) { ACME._toHex = function(pair) {
return parseInt(pair, 10).toString(16); return parseInt(pair, 10).toString(16);
}; };
ACME._dns01 = function(me, ch) {
return new me.request({
url: me._baseUrl + '/api/dns/' + ch.dnsHost + '?type=TXT'
}).then(function(resp) {
var err;
if (!resp.body || !Array.isArray(resp.body.answer)) {
err = new Error('failed to get DNS response');
console.error(err);
throw err;
}
if (!resp.body.answer.length) {
err = new Error('failed to get DNS answer record in response');
console.error(err);
throw err;
}
return {
answer: resp.body.answer.map(function(ans) {
return { data: ans.data, ttl: ans.ttl };
})
};
});
};
ACME._http01 = function(me, ch) {
var url = encodeURIComponent(ch.challengeUrl);
return new me.request({
url: me._baseUrl + '/api/http?url=' + url
}).then(function(resp) {
return resp.body;
});
};
ACME._removeChallenge = function(me, options, auth) { ACME._removeChallenge = function(me, options, auth) {
var challengers = options.challenges || {}; var challengers = options.challenges || {};
var ch = auth.challenge; var ch = auth.challenge;

49
browser.js Normal file
View File

@ -0,0 +1,49 @@
'use strict';
var native = module.exports;
native._canCheck = function(me) {
return me
.request({ url: me._baseUrl + '/api/_acme_api_/' })
.then(function(resp) {
if (resp.body.success) {
me._canCheck['http-01'] = true;
me._canCheck['dns-01'] = true;
}
})
.catch(function() {
// ignore
});
};
native._dns01 = function(me, ch) {
return new me.request({
url: me._baseUrl + '/api/dns/' + ch.dnsHost + '?type=TXT'
}).then(function(resp) {
var err;
if (!resp.body || !Array.isArray(resp.body.answer)) {
err = new Error('failed to get DNS response');
console.error(err);
throw err;
}
if (!resp.body.answer.length) {
err = new Error('failed to get DNS answer record in response');
console.error(err);
throw err;
}
return {
answer: resp.body.answer.map(function(ans) {
return { data: ans.data, ttl: ans.ttl };
})
};
});
};
native._http01 = function(me, ch) {
var url = encodeURIComponent(ch.challengeUrl);
return new me.request({
url: me._baseUrl + '/api/http?url=' + url
}).then(function(resp) {
return resp.body;
});
};

32
native.js Normal file
View File

@ -0,0 +1,32 @@
'use strict';
var native = module.exports;
var promisify = require('util').promisify;
var resolveTxt = promisify(require('dns').resolveTxt);
native._canCheck = function(me) {
me._canCheck['http-01'] = true;
me._canCheck['dns-01'] = true;
return Promise.resolve();
};
native._dns01 = function(me, ch) {
// TODO use digd.js
return resolveTxt(ch.dnsHost).then(function(records) {
return {
answer: records.map(function(rr) {
return {
data: rr
};
})
};
});
};
native._http01 = function(me, ch) {
return new me.request({
url: ch.challengeUrl
}).then(function(resp) {
return resp.body;
});
};

20
package-lock.json generated
View File

@ -1,6 +1,6 @@
{ {
"name": "@root/acme", "name": "@root/acme",
"version": "3.0.0-wip.3", "version": "3.0.0-wip.4",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {
@ -16,6 +16,7 @@
"version": "0.8.1", "version": "0.8.1",
"resolved": "https://registry.npmjs.org/@root/csr/-/csr-0.8.1.tgz", "resolved": "https://registry.npmjs.org/@root/csr/-/csr-0.8.1.tgz",
"integrity": "sha512-hKl0VuE549TK6SnS2Yn9nRvKbFZXn/oAg+dZJU/tlKl/f/0yRXeuUzf8akg3JjtJq+9E592zDqeXZ7yyrg8fSQ==", "integrity": "sha512-hKl0VuE549TK6SnS2Yn9nRvKbFZXn/oAg+dZJU/tlKl/f/0yRXeuUzf8akg3JjtJq+9E592zDqeXZ7yyrg8fSQ==",
"dev": true,
"requires": { "requires": {
"@root/asn1": "^1.0.0", "@root/asn1": "^1.0.0",
"@root/pem": "^1.0.4", "@root/pem": "^1.0.4",
@ -117,13 +118,20 @@
} }
}, },
"dns-suite": { "dns-suite": {
"version": "1.2.12", "version": "1.2.13",
"resolved": "https://registry.npmjs.org/dns-suite/-/dns-suite-1.2.12.tgz", "resolved": "https://registry.npmjs.org/dns-suite/-/dns-suite-1.2.13.tgz",
"integrity": "sha512-K4LWqmJT/T2QLaGCJ+qRvrT9DicKs5XxXYXw6uIZ1apdwyfToQk7K9AZbpFd0FLRdZG809v2vAcsquPbQh+Ipg==", "integrity": "sha512-veYKPHUc2RfRCe7c4G/iKxhRv0S4InJ3JsW8tEhW6Yb7dn3ac34iozC6cNX0uzHYZUw0BG5V9Fu65L1bx1GeBg==",
"dev": true, "dev": true,
"requires": { "requires": {
"bluebird": "^3.5.0", "@root/hexdump": "^1.1.1"
"hexdump.js": "git+https://git.coolaj86.com/coolaj86/hexdump.js#v1.0.4" },
"dependencies": {
"@root/hexdump": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@root/hexdump/-/hexdump-1.1.1.tgz",
"integrity": "sha512-AmrmLOutlzctR599ittO06lINOco1TIqb0c1wu83fP2Eoi5iSvx7kVWC4mDufze8rxPewC+aQOx4e6Pw7izV4A==",
"dev": true
}
} }
}, },
"dotenv": { "dotenv": {

View File

@ -1,10 +1,11 @@
{ {
"name": "@root/acme", "name": "@root/acme",
"version": "3.0.0-wip.3", "version": "3.0.0-wip.4",
"description": "Free SSL certificates through Let's Encrypt, right in your browser", "description": "Free SSL certificates for Node.js and Browsers. Issued via Let's Encrypt",
"homepage": "https://rootprojects.org/acme/", "homepage": "https://rootprojects.org/acme/",
"main": "acme.js", "main": "acme.js",
"browser": { "browser": {
"./native.js": "./browser.js",
"./lib/node/sha2.js": "./lib/browser/sha2.js", "./lib/node/sha2.js": "./lib/browser/sha2.js",
"./lib/node/http.js": "./lib/browser/http.js" "./lib/node/http.js": "./lib/browser/http.js"
}, },
@ -14,7 +15,7 @@
"dist" "dist"
], ],
"scripts": { "scripts": {
"build": "nodex bin/bundle.js", "build": "node_xxx bin/bundle.js",
"lint": "jshint lib bin", "lint": "jshint lib bin",
"test": "node server.js", "test": "node server.js",
"start": "node server.js" "start": "node server.js"
@ -26,10 +27,10 @@
"keywords": [ "keywords": [
"ACME", "ACME",
"Let's Encrypt", "Let's Encrypt",
"browser",
"EC", "EC",
"RSA", "RSA",
"CSR", "CSR",
"browser",
"greenlock", "greenlock",
"VanillaJS", "VanillaJS",
"ZeroSSL" "ZeroSSL"
@ -37,7 +38,6 @@
"author": "AJ ONeal <coolaj86@gmail.com> (https://coolaj86.com/)", "author": "AJ ONeal <coolaj86@gmail.com> (https://coolaj86.com/)",
"license": "MPL-2.0", "license": "MPL-2.0",
"dependencies": { "dependencies": {
"@root/csr": "^0.8.1",
"@root/encoding": "^1.0.1", "@root/encoding": "^1.0.1",
"@root/keypairs": "^0.9.0", "@root/keypairs": "^0.9.0",
"@root/pem": "^1.0.4", "@root/pem": "^1.0.4",
@ -45,8 +45,9 @@
"@root/x509": "^0.7.2" "@root/x509": "^0.7.2"
}, },
"devDependencies": { "devDependencies": {
"@root/csr": "^0.8.1",
"dig.js": "^1.3.9", "dig.js": "^1.3.9",
"dns-suite": "^1.2.12", "dns-suite": "^1.2.13",
"dotenv": "^8.1.0", "dotenv": "^8.1.0",
"punycode": "^1.4.1" "punycode": "^1.4.1"
}, },

View File

@ -95,6 +95,7 @@ async function happyPath(accKty, srvKty, rnd) {
accountKeypair: { privateKeyJwk: accountKeypair.private }, accountKeypair: { privateKeyJwk: accountKeypair.private },
subscriberEmail: config.email subscriberEmail: config.email
}); });
// TODO top-level agree // TODO top-level agree
function agree(tos) { function agree(tos) {
if (config.debug) { if (config.debug) {