Compare commits

...

2 Commits

Author SHA1 Message Date
AJ ONeal cd48c624fa yay for promise-only tests working 2018-04-05 02:28:29 -06:00
AJ ONeal 055c75cc94 yay for test with callback options working 2018-04-05 02:13:20 -06:00
6 changed files with 124 additions and 98 deletions

View File

@ -23,10 +23,11 @@ In progress
* Mar 20, 2018 - SUCCESS - got a test certificate (hard-coded) * Mar 20, 2018 - SUCCESS - got a test certificate (hard-coded)
* Mar 21, 2018 - can now accept values (not hard coded) * Mar 21, 2018 - can now accept values (not hard coded)
* Mar 21, 2018 - *mostly* matches le-acme-core.js API * Mar 21, 2018 - *mostly* matches le-acme-core.js API
* Apr 5, 2018 - completely match api for acme v1 (le-acme-core.js)
Todo Todo
* completely match api for acme v1 (le-acme-core.js) * test wildcard
* test http and dns challenges * test http and dns challenges
* export http and dns challenge tests * export http and dns challenge tests
* support ECDSA keys * support ECDSA keys

14
node.js
View File

@ -9,6 +9,11 @@
var ACME = module.exports.ACME = {}; var ACME = module.exports.ACME = {};
ACME.acmeChallengePrefix = '/.well-known/acme-challenge/'; ACME.acmeChallengePrefix = '/.well-known/acme-challenge/';
ACME.acmeChallengeDnsPrefix = '_acme-challenge';
ACME.acmeChallengePrefixes = {
'http-01': '/.well-known/acme-challenge/'
, 'dns-01': '_acme-challenge'
};
ACME._getUserAgentString = function (deps) { ACME._getUserAgentString = function (deps) {
var uaDefaults = { var uaDefaults = {
@ -368,6 +373,7 @@ ACME._getCertificate = function (me, options) {
console.log('[acme-v2] certificates.create'); console.log('[acme-v2] certificates.create');
return ACME._getNonce(me).then(function () { return ACME._getNonce(me).then(function () {
console.log("27 &#&#&#&#&#&#&&##&#&#&#&#&#&#&#&");
var body = { var body = {
identifiers: options.domains.map(function (hostname) { identifiers: options.domains.map(function (hostname) {
return { type: "dns" , value: hostname }; return { type: "dns" , value: hostname };
@ -401,6 +407,11 @@ ACME._getCertificate = function (me, options) {
me._finalize = resp.body.finalize; me._finalize = resp.body.finalize;
//console.log('[DEBUG] finalize:', me._finalize); return; //console.log('[DEBUG] finalize:', me._finalize); return;
if (!me._authorizations) {
console.log("&#&#&#&#&#&#&&##&#&#&#&#&#&#&#&");
}
console.log("47 &#&#&#&#&#&#&&##&#&#&#&#&#&#&#&");
//return resp.body; //return resp.body;
return Promise.all(me._authorizations.map(function (authUrl, i) { return Promise.all(me._authorizations.map(function (authUrl, i) {
console.log("Authorizations map #" + i); console.log("Authorizations map #" + i);
@ -425,6 +436,7 @@ ACME._getCertificate = function (me, options) {
return ACME._postChallenge(me, options, results.identifier, challenge); return ACME._postChallenge(me, options, results.identifier, challenge);
}); });
})).then(function () { })).then(function () {
console.log("37 &#&#&#&#&#&#&&##&#&#&#&#&#&#&#&");
var validatedDomains = body.identifiers.map(function (ident) { var validatedDomains = body.identifiers.map(function (ident) {
return ident.value; return ident.value;
}); });
@ -444,6 +456,8 @@ ACME._getCertificate = function (me, options) {
ACME.create = function create(me) { ACME.create = function create(me) {
if (!me) { me = {}; } if (!me) { me = {}; }
me.acmeChallengePrefix = ACME.acmeChallengePrefix; me.acmeChallengePrefix = ACME.acmeChallengePrefix;
me.acmeChallengeDnsPrefix = ACME.acmeChallengeDnsPrefix;
me.acmeChallengePrefixes = ACME.acmeChallengePrefixes;
me.RSA = me.RSA || require('rsa-compat').RSA; me.RSA = me.RSA || require('rsa-compat').RSA;
me.request = me.request || require('request'); me.request = me.request || require('request');
me.promisify = me.promisify || require('util').promisify; me.promisify = me.promisify || require('util').promisify;

View File

@ -1,21 +1,17 @@
'use strict'; 'use strict';
module.exports.run = function run(web, chType, email) { module.exports.run = function run(web, chType, email, accountKeypair, domainKeypair) {
var RSA = require('rsa-compat').RSA; var RSA = require('rsa-compat').RSA;
var directoryUrl = 'https://acme-staging-v02.api.letsencrypt.org/directory'; var directoryUrl = 'https://acme-staging-v02.api.letsencrypt.org/directory';
var acme2 = require('./compat').ACME.create({ RSA: RSA }); var acme2 = require('./').ACME.create({ RSA: RSA });
// [ 'test.ppl.family' ] 'coolaj86@gmail.com''http-01' // [ 'test.ppl.family' ] 'coolaj86@gmail.com''http-01'
console.log(web, chType, email); acme2.init(directoryUrl).then(function () {
return;
acme2.init(directoryUrl).then(function (body) {
console.log(body);
return;
var options = { var options = {
agreeToTerms: function (tosUrl, agree) { agreeToTerms: function (tosUrl, agree) {
agree(null, tosUrl); agree(null, tosUrl);
} }
, setChallenge: function (opts, cb) { , setChallenge: function (opts, cb) {
var pathname;
console.log(""); console.log("");
console.log('identifier:'); console.log('identifier:');
@ -34,40 +30,50 @@ module.exports.run = function run(web, chType, email) {
console.log(opts.dnsAuthorization); console.log(opts.dnsAuthorization);
console.log(""); console.log("");
console.log("Put the string '" + opts.keyAuthorization + "' into a file at '" + opts.hostname + "/" + opts.token + "'"); if ('http-01' === opts.type) {
console.log("\nThen hit the 'any' key to continue (must be specifically the 'any' key)..."); pathname = opts.hostname + acme2.acmeChallengePrefix + "/" + opts.token;
console.log("Put the string '" + opts.keyAuthorization + "' into a file at '" + pathname + "'");
console.log("echo '" + opts.keyAuthorization + "' > '" + pathname + "'");
} else if ('dns-01' === opts.type) {
pathname = acme2.acmeChallengeDnsPrefix + "." + opts.hostname.replace(/^\*\./, '');
console.log("Put the string '" + opts.dnsAuthorization + "' into the TXT record '" + pathname + "'");
console.log("ddig TXT " + pathname + " '" + opts.dnsAuthorization + "'");
} else {
cb(new Error("[acme-v2] unrecognized challenge type"));
return;
}
console.log("\nThen hit the 'any' key to continue...");
function onAny() { function onAny() {
console.log("'any' key was hit");
process.stdin.pause(); process.stdin.pause();
process.stdin.removeEventListener('data', onAny); process.stdin.removeListener('data', onAny);
process.stdin.setRawMode(false); process.stdin.setRawMode(false);
cb(); cb();
} }
process.stdin.setRawMode(true); process.stdin.setRawMode(true);
process.stdin.resume(); process.stdin.resume();
process.stdin.on('data', onAny); process.stdin.on('data', onAny);
} }
, removeChallenge: function (opts, cb) { , removeChallenge: function (opts, cb) {
// hostname, key // hostname, key
console.log('[DEBUG] remove challenge', hostname, key); console.log('[acme-v2] remove challenge', opts.hostname, opts.keyAuthorization);
setTimeout(cb, 1 * 1000); setTimeout(cb, 1 * 1000);
} }
, challengeType: chType , challengeType: chType
, email: email , email: email
, accountKeypair: RSA.import({ privateKeyPem: require('fs').readFileSync(__dirname + '/account.privkey.pem') }) , accountKeypair: accountKeypair
, domainKeypair: RSA.import({ privateKeyPem: require('fs').readFileSync(__dirname + '/privkey.pem') }) , domainKeypair: domainKeypair
, domains: web , domains: web
}; };
acme2.registerNewAccount(options).then(function (account) { acme2.accounts.create(options).then(function (account) {
console.log('account:'); console.log('[acme-v2] account:');
console.log(account); console.log(account);
acme2.getCertificate(options, function (fullchainPem) { acme2.certificates.create(options).then(function (fullchainPem) {
console.log('[acme-v2] A fullchain.pem:'); console.log('[acme-v2] fullchain.pem:');
console.log(fullchainPem);
}).then(function (fullchainPem) {
console.log('[acme-v2] B fullchain.pem:');
console.log(fullchainPem); console.log(fullchainPem);
}); });
}); });

View File

@ -2,22 +2,22 @@
var RSA = require('rsa-compat').RSA; var RSA = require('rsa-compat').RSA;
module.exports.run = function (web, chType, email) { module.exports.run = function (web, chType, email, accountKeypair, domainKeypair) {
console.log('[DEBUG] run', web, chType, email); console.log('[DEBUG] run', web, chType, email);
var acme2 = require('./compat.js').ACME.create({ RSA: RSA }); var acme2 = require('./compat.js').ACME.create({ RSA: RSA });
acme2.getAcmeUrls(acme2.stagingServerUrl, function (err, body) { acme2.getAcmeUrls(acme2.stagingServerUrl, function (err/*, directoryUrls*/) {
if (err) { console.log('err 1'); throw err; } if (err) { console.log('err 1'); throw err; }
console.log(body);
var options = { var options = {
agreeToTerms: function (tosUrl, agree) { agreeToTerms: function (tosUrl, agree) {
agree(null, tosUrl); agree(null, tosUrl);
} }
, setChallenge: function (hostname, token, val, cb) { , setChallenge: function (hostname, token, val, cb) {
console.log("Put the string '" + val + "' into a file at '" + hostname + "/" + acme2.acmeChallengePrefix + "/" + token + "'"); var pathname = hostname + acme2.acmeChallengePrefix + "/" + token;
console.log("echo '" + val + "' > '" + hostname + "/" + acme2.acmeChallengePrefix + "/" + token + "'"); console.log("Put the string '" + val + "' into a file at '" + pathname + "'");
console.log("\nThen hit the 'any' key to continue (must be specifically the 'any' key)..."); console.log("echo '" + val + "' > '" + pathname + "'");
console.log("\nThen hit the 'any' key to continue...");
function onAny() { function onAny() {
console.log("'any' key was hit"); console.log("'any' key was hit");
@ -37,8 +37,8 @@ module.exports.run = function (web, chType, email) {
} }
, challengeType: chType , challengeType: chType
, email: email , email: email
, accountKeypair: RSA.import({ privateKeyPem: require('fs').readFileSync(__dirname + '/account.privkey.pem') }) , accountKeypair: accountKeypair
, domainKeypair: RSA.import({ privateKeyPem: require('fs').readFileSync(__dirname + '/privkey.pem') }) , domainKeypair: domainKeypair
, domains: web , domains: web
}; };

36
test.js
View File

@ -1,5 +1,6 @@
'use strict'; 'use strict';
var RSA = require('rsa-compat').RSA;
var readline = require('readline'); var readline = require('readline');
var rl = readline.createInterface({ var rl = readline.createInterface({
input: process.stdin, input: process.stdin,
@ -7,9 +8,9 @@ var rl = readline.createInterface({
}); });
function getWeb() { function getWeb() {
rl.question('What web address(es) would you like to get certificates for? (ex: example.com,*.example.com) ', function (web) { rl.question('What web address(es) would you like to get certificates for? (ex: example.com,*.example.com) ', function (web) {
web = (web||'').trim().split(/,/g); web = (web||'').trim().split(/,/g);
if (!web[0]) { getWeb(); return; } if (!web[0]) { getWeb(); return; }
if (web.some(function (w) { return '*' === w[0]; })) { if (web.some(function (w) { return '*' === w[0]; })) {
console.log('Wildcard domains must use dns-01'); console.log('Wildcard domains must use dns-01');
@ -17,29 +18,30 @@ function getWeb() {
} else { } else {
getChallengeType(web); getChallengeType(web);
} }
}); });
} }
function getChallengeType(web) { function getChallengeType(web) {
rl.question('What challenge will you be testing today? http-01 or dns-01? [http-01] ', function (chType) { rl.question('What challenge will you be testing today? http-01 or dns-01? [http-01] ', function (chType) {
chType = (chType||'').trim(); chType = (chType||'').trim();
if (!chType) { chType = 'http-01'; } if (!chType) { chType = 'http-01'; }
getEmail(web, chType); getEmail(web, chType);
}); });
} }
function getEmail(web, chType) { function getEmail(web, chType) {
rl.question('What email should we use? (optional) ', function (email) { rl.question('What email should we use? (optional) ', function (email) {
email = (email||'').trim(); email = (email||'').trim();
if (!email) { email = null; } if (!email) { email = null; }
rl.close(); rl.close();
console.log("[DEBUG] rl blah blah"); var accountKeypair = RSA.import({ privateKeyPem: require('fs').readFileSync(__dirname + '/account.privkey.pem') });
require('./test.compat.js').run(web, chType, email); var domainKeypair = RSA.import({ privateKeyPem: require('fs').readFileSync(__dirname + '/privkey.pem') });
//require('./test.cb.js').run(web, chType, email); //require('./test.compat.js').run(web, chType, email, accountKeypair, domainKeypair);
//require('./test.promise.js').run(web, chType, email); //require('./test.cb.js').run(web, chType, email, accountKeypair, domainKeypair);
}); require('./test.promise.js').run(web, chType, email, accountKeypair, domainKeypair);
});
} }
getWeb(); getWeb();

View File

@ -1,82 +1,85 @@
'use strict'; 'use strict';
/* global Promise */ /* global Promise */
module.exports.run = function run(web, chType, email, accountKeypair, domainKeypair) {
module.exports.run = function run(web, chType, email) {
var RSA = require('rsa-compat').RSA; var RSA = require('rsa-compat').RSA;
var directoryUrl = 'https://acme-staging-v02.api.letsencrypt.org/directory'; var directoryUrl = 'https://acme-staging-v02.api.letsencrypt.org/directory';
var acme2 = require('./compat').ACME.create({ RSA: RSA }); var acme2 = require('./').ACME.create({ RSA: RSA });
// [ 'test.ppl.family' ] 'coolaj86@gmail.com''http-01' // [ 'test.ppl.family' ] 'coolaj86@gmail.com''http-01'
console.log(web, chType, email); acme2.init(directoryUrl).then(function () {
return;
acme2.init(directoryUrl).then(function (body) {
console.log(body);
return;
var options = { var options = {
agreeToTerms: function (tosUrl, agree) { agreeToTerms: function (tosUrl) {
agree(null, tosUrl); return Promise.resolve(tosUrl);
} }
, setChallenge: function (opts) { , setChallenge: function (opts) {
return new Promise(function (resolve, reject) {
var pathname;
console.log(""); console.log("");
console.log('identifier:'); console.log('identifier:');
console.log(opts.identifier); console.log(opts.identifier);
console.log('hostname:'); console.log('hostname:');
console.log(opts.hostname); console.log(opts.hostname);
console.log('type:'); console.log('type:');
console.log(opts.type); console.log(opts.type);
console.log('token:'); console.log('token:');
console.log(opts.token); console.log(opts.token);
console.log('thumbprint:'); console.log('thumbprint:');
console.log(opts.thumbprint); console.log(opts.thumbprint);
console.log('keyAuthorization:'); console.log('keyAuthorization:');
console.log(opts.keyAuthorization); console.log(opts.keyAuthorization);
console.log('dnsAuthorization:'); console.log('dnsAuthorization:');
console.log(opts.dnsAuthorization); console.log(opts.dnsAuthorization);
console.log(""); console.log("");
console.log("Put the string '" + opts.keyAuthorization + "' into a file at '" + opts.hostname + "/" + opts.token + "'"); if ('http-01' === opts.type) {
console.log("\nThen hit the 'any' key to continue (must be specifically the 'any' key)..."); pathname = opts.hostname + acme2.acmeChallengePrefix + "/" + opts.token;
console.log("Put the string '" + opts.keyAuthorization + "' into a file at '" + pathname + "'");
return new Promise(function (resolve) { console.log("echo '" + opts.keyAuthorization + "' > '" + pathname + "'");
function onAny() { } else if ('dns-01' === opts.type) {
process.stdin.pause(); pathname = acme2.acmeChallengeDnsPrefix + "." + opts.hostname.replace(/^\*\./, '');;
process.stdin.removeEventListener('data', onAny); console.log("Put the string '" + opts.dnsAuthorization + "' into the TXT record '" + pathname + "'");
process.stdin.setRawMode(false); console.log("ddig TXT " + pathname + " '" + opts.dnsAuthorization + "'");
} else {
resolve(); reject(new Error("[acme-v2] unrecognized challenge type"));
return;
} }
console.log("\nThen hit the 'any' key to continue...");
function onAny() {
console.log("'any' key was hit");
process.stdin.pause();
process.stdin.removeListener('data', onAny);
process.stdin.setRawMode(false);
resolve();
return;
}
process.stdin.setRawMode(true); process.stdin.setRawMode(true);
process.stdin.resume(); process.stdin.resume();
process.stdin.on('data', onAny); process.stdin.on('data', onAny);
}); });
} }
, removeChallenge: function (opts) { , removeChallenge: function (opts) {
// hostname, key console.log('[acme-v2] remove challenge', opts.hostname, opts.keyAuthorization);
console.log('[DEBUG] remove challenge', opts.hostname, opts.keyAuthorization);
console.log("Remove the file '" + opts.hostname + "/" + opts.token + "'");
return new Promise(function (resolve) { return new Promise(function (resolve) {
// hostname, key
setTimeout(resolve, 1 * 1000); setTimeout(resolve, 1 * 1000);
}); });
} }
, challengeType: chType , challengeType: chType
, email: email , email: email
, accountKeypair: RSA.import({ privateKeyPem: require('fs').readFileSync(__dirname + '/account.privkey.pem') }) , accountKeypair: accountKeypair
, domainKeypair: RSA.import({ privateKeyPem: require('fs').readFileSync(__dirname + '/privkey.pem') }) , domainKeypair: domainKeypair
, domains: web , domains: web
}; };
acme2.registerNewAccount(options).then(function (account) { acme2.accounts.create(options).then(function (account) {
console.log('account:'); console.log('[acme-v2] account:');
console.log(account); console.log(account);
acme2.getCertificate(options, function (fullchainPem) { acme2.certificates.create(options).then(function (fullchainPem) {
console.log('[acme-v2] A fullchain.pem:'); console.log('[acme-v2] fullchain.pem:');
console.log(fullchainPem);
}).then(function (fullchainPem) {
console.log('[acme-v2] B fullchain.pem:');
console.log(fullchainPem); console.log(fullchainPem);
}); });
}); });