Browse Source

pass middleware tests

greenlock
AJ ONeal 8 years ago
parent
commit
285cc8f95b
  1. 6
      README.md
  2. 25
      index.js
  3. 43
      lib/middleware.js
  4. 102
      tests/challenge-middleware.js

6
README.md

@ -45,7 +45,7 @@ Install
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)
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
npm install --save letsencrypt@2.x
@ -108,7 +108,7 @@ var leStore = require('le-store-certbot').create({
// 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
, debug: false // '/srv/www/:hostname/.well-known/acme-challenge'
});
@ -122,7 +122,7 @@ function leAgree(opts, agreeCb) {
le = LE.create({
server: LE.stagingServerUrl // or LE.productionServerUrl
, 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
, debug: false
});

25
index.js

@ -27,7 +27,7 @@ var u; // undefined
LE._undefined = {
acme: u
, store: u
, challenger: u
, challenge: u
, register: u
, check: u
@ -40,6 +40,8 @@ LE._undefined = {
, server: u
, agreeToTerms: u
, _ipc: u
, duplicate: u
, _acmeUrls: u
};
LE._undefine = function (le) {
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.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 = LE._undefine(le);
@ -102,14 +104,14 @@ LE.create = function (le) {
}
});
if (le.challenger.create) {
le.challenger = le.challenger.create(le);
if (le.challenge.create) {
le.challenge = le.challenge.create(le);
}
le.challenger = PromiseA.promisifyAll(le.challenger);
le._challengerOpts = le.challenger.getOptions();
Object.keys(le._challengerOpts).forEach(function (key) {
le.challenge = PromiseA.promisifyAll(le.challenge);
le._challengeOpts = le.challenge.getOptions();
Object.keys(le._challengeOpts).forEach(function (key) {
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);
};
le.middleware = function () {
return require('./lib/middleware')(le);
};
le.middleware = le.middleware || require('./lib/middleware');
if (le.middleware.create) {
le.middleware = le.middleware.create(le);
}
return le;
};

43
lib/middleware.js

@ -1,30 +1,53 @@
'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 () {
var prefix = le.acmeChallengePrefix; // /.well-known/acme-challenge/:token
return function (req, res, next) {
if (0 !== req.url.indexOf(prefix)) {
log(le.debug, "no match, skipping middleware");
next();
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(/:*/, '');
log(le.debug, "hostname", hostname, "token", token);
var copy = utils.merge({}, le);
copy = utils.tplCopy(copy);
// TODO tpl copy?
le.challenger.getAsync(le, hostname, key).then(function (token) {
if (!token) {
res.status = 404;
res.send("Error: These aren't the tokens you're looking for. Move along.");
le.challenge.get(copy, hostname, token, function (err, secret) {
if (err || !token) {
res.statusCode = 404;
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;
}
res.send(token);
}, function (/*err*/) {
res.status = 404;
res.send("Error: These aren't the tokens you're looking for. Move along.");
res.setHeader('Content-Type', 'text/plain; charset=utf-8');
res.end(secret);
});
};
};

102
tests/challenge-middleware.js

@ -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();
Loading…
Cancel
Save