pass middleware tests

This commit is contained in:
AJ ONeal 2016-08-09 14:05:47 -04:00
parent 73645a4459
commit 285cc8f95b
4 changed files with 152 additions and 24 deletions

View File

@ -45,7 +45,7 @@ Install
one for managing certificate storage and the other for handling ACME challenges. one for managing certificate storage and the other for handling ACME challenges.
The default storage plugin is [`le-store-certbot`](https://github.com/Daplie/le-store-certbot) The default storage plugin is [`le-store-certbot`](https://github.com/Daplie/le-store-certbot)
and the default challenger is [`le-challenge-fs`](https://github.com/Daplie/le-challenge-fs). and the default challenge is [`le-challenge-fs`](https://github.com/Daplie/le-challenge-fs).
```bash ```bash
npm install --save letsencrypt@2.x npm install --save letsencrypt@2.x
@ -108,7 +108,7 @@ var leStore = require('le-store-certbot').create({
// ACME Challenge Handlers // ACME Challenge Handlers
var leChallenger = require('le-challenge-fs').create({ var leChallenge = require('le-challenge-fs').create({
webrootPath: '~/letsencrypt/var/' // or template string such as webrootPath: '~/letsencrypt/var/' // or template string such as
, debug: false // '/srv/www/:hostname/.well-known/acme-challenge' , debug: false // '/srv/www/:hostname/.well-known/acme-challenge'
}); });
@ -122,7 +122,7 @@ function leAgree(opts, agreeCb) {
le = LE.create({ le = LE.create({
server: LE.stagingServerUrl // or LE.productionServerUrl server: LE.stagingServerUrl // or LE.productionServerUrl
, store: leStore // handles saving of config, accounts, and certificates , store: leStore // handles saving of config, accounts, and certificates
, challenger: leChallenger // handles /.well-known/acme-challege keys and tokens , challenge: leChallenge // handles /.well-known/acme-challege keys and tokens
, agreeToTerms: leAgree // hook to allow user to view and accept LE TOS , agreeToTerms: leAgree // hook to allow user to view and accept LE TOS
, debug: false , debug: false
}); });

View File

@ -27,7 +27,7 @@ var u; // undefined
LE._undefined = { LE._undefined = {
acme: u acme: u
, store: u , store: u
, challenger: u , challenge: u
, register: u , register: u
, check: u , check: u
@ -40,6 +40,8 @@ LE._undefined = {
, server: u , server: u
, agreeToTerms: u , agreeToTerms: u
, _ipc: u , _ipc: u
, duplicate: u
, _acmeUrls: u
}; };
LE._undefine = function (le) { LE._undefine = function (le) {
Object.keys(LE._undefined).forEach(function (key) { Object.keys(LE._undefined).forEach(function (key) {
@ -55,7 +57,7 @@ LE.create = function (le) {
le.acme = le.acme || ACME.create({ debug: le.debug }); 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.challenger = le.challenger || require('le-store-certbot').create({ debug: le.debug }); le.challenge = le.challenge || require('le-challenge-certbot').create({ debug: le.debug });
le.core = require('./lib/core'); le.core = require('./lib/core');
le = LE._undefine(le); le = LE._undefine(le);
@ -102,14 +104,14 @@ LE.create = function (le) {
} }
}); });
if (le.challenger.create) { if (le.challenge.create) {
le.challenger = le.challenger.create(le); le.challenge = le.challenge.create(le);
} }
le.challenger = PromiseA.promisifyAll(le.challenger); le.challenge = PromiseA.promisifyAll(le.challenge);
le._challengerOpts = le.challenger.getOptions(); le._challengeOpts = le.challenge.getOptions();
Object.keys(le._challengerOpts).forEach(function (key) { Object.keys(le._challengeOpts).forEach(function (key) {
if (!(key in le)) { if (!(key in le)) {
le[key] = le._challengerOpts[key]; le[key] = le._challengeOpts[key];
} }
}); });
@ -126,9 +128,10 @@ LE.create = function (le) {
return le.core.certificates.checkAsync(args); return le.core.certificates.checkAsync(args);
}; };
le.middleware = function () { le.middleware = le.middleware || require('./lib/middleware');
return require('./lib/middleware')(le); if (le.middleware.create) {
}; le.middleware = le.middleware.create(le);
}
return le; return le;
}; };

View File

@ -1,30 +1,53 @@
'use strict'; 'use strict';
module.exports = function (le) { var utils = require('./utils');
function log(debug) {
if (debug) {
var args = Array.prototype.slice.call(arguments);
args.shift();
args.unshift("[le/lib/middleware.js]");
console.log.apply(console, args);
}
}
module.exports.create = function (le) {
if (!le.challenge || !le.challenge.get) {
throw new Error("middleware requires challenge plugin with get method");
}
log(le.debug, "created middleware");
return function () { return function () {
var prefix = le.acmeChallengePrefix; // /.well-known/acme-challenge/:token var prefix = le.acmeChallengePrefix; // /.well-known/acme-challenge/:token
return function (req, res, next) { return function (req, res, next) {
if (0 !== req.url.indexOf(prefix)) { if (0 !== req.url.indexOf(prefix)) {
log(le.debug, "no match, skipping middleware");
next(); next();
return; return;
} }
var key = req.url.slice(prefix.length); log(le.debug, "this must be tinder, 'cuz it's a match!");
var token = req.url.slice(prefix.length);
var hostname = req.hostname || (req.headers.host || '').toLowerCase().replace(/:*/, ''); var hostname = req.hostname || (req.headers.host || '').toLowerCase().replace(/:*/, '');
log(le.debug, "hostname", hostname, "token", token);
var copy = utils.merge({}, le);
copy = utils.tplCopy(copy);
// TODO tpl copy? // TODO tpl copy?
le.challenger.getAsync(le, hostname, key).then(function (token) { le.challenge.get(copy, hostname, token, function (err, secret) {
if (!token) { if (err || !token) {
res.status = 404; res.statusCode = 404;
res.send("Error: These aren't the tokens you're looking for. Move along."); res.setHeader('Content-Type', 'application/json; charset=utf-8');
res.end('{ "error": { "message": "Error: These aren\'t the tokens you\'re looking for. Move along." } }');
return; return;
} }
res.send(token); res.setHeader('Content-Type', 'text/plain; charset=utf-8');
}, function (/*err*/) { res.end(secret);
res.status = 404;
res.send("Error: These aren't the tokens you're looking for. Move along.");
}); });
}; };
}; };

View File

@ -0,0 +1,102 @@
'use strict';
var PromiseA = require('bluebird');
var requestAsync = PromiseA.promisify(require('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'
, webrootPath: '~/letsencrypt.test/var/:hostname'
})
, challenge: require('le-challenge-fs').create({
webrootPath: '~/letsencrypt.test/var/:hostname'
})
, debug: true
});
var utils = require('../lib/utils');
if ('/.well-known/acme-challenge/' !== LE.acmeChallengePrefix) {
throw new Error("Bad constant 'acmeChallengePrefix'");
}
var baseUrl;
var domain = 'example.com';
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({}, le);
copy = utils.tplCopy(copy);
return PromiseA.promisify(le.challenge.set)(copy, domain, 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({}, le);
copy = utils.tplCopy(copy);
return PromiseA.promisify(le.challenge.remove)(copy, domain, 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://localhost.daplie.com:' + 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();