From 17e409b158f7b0d1372d5e790753cca0552c5b43 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Thu, 6 Jun 2019 23:04:51 -0600 Subject: [PATCH] v3.1.0: update docs, default to testing full zones --- README.md | 206 +++++++++++++++++++++++++++------------------------ index.js | 10 ++- package.json | 2 +- 3 files changed, 117 insertions(+), 101 deletions(-) diff --git a/README.md b/README.md index a017ce8..21cc274 100644 --- a/README.md +++ b/README.md @@ -19,20 +19,31 @@ npm install --save-dev acme-challenge-test@3.x ## Usage ```js -var tester = require("acme-challenge-test"); +var tester = require('acme-challenge-test'); //var challenger = require('acme-http-01-cli').create({}); //var challenger = require('acme-dns-01-cli').create({}); -var challenger = require("./YOUR-CHALLENGE-STRATEGY").create({ - YOUR_TOKEN_OPTION: 'SOME_API_KEY' +var challenger = require('./YOUR-CHALLENGE-STRATEGY').create({ + YOUR_TOKEN_OPTION: 'SOME_API_KEY' }); // The dry-run tests can pass on, literally, 'example.com' // but the integration tests require that you have control over the domain -var domain = "example.com"; +var zone = 'example.com'; -tester.test("http-01", domain, challenger).then(function() { - console.info("PASS"); +tester.testZone('dns-01', zone, challenger).then(function() { + console.info('PASS'); +}); +``` + +**Note**: If the service you are testing only handles individual records +(not multiple records in a zone), you can use `testRecord` instead: + +```js +var record = 'foo.example.com'; + +tester.testRecord('dns-01', record, challenger).then(function() { + console.info('PASS'); }); ``` @@ -44,7 +55,11 @@ which you should use as a model for any plugins that you create. - [`acme-http-01-cli`](https://git.rootprojects.org/root/acme-http-01-cli.js) - [`acme-dns-01-cli`](https://git.rootprojects.org/root/acme-dns-01-cli.js) -You can find other implementations by searching npm for [acme-http-01-](https://www.npmjs.com/search?q=acme-http-01-) and [acme-dns-01-](https://www.npmjs.com/search?q=acme-dns-01-). +You can find other implementations by searching npm for [acme-http-01-](https://www.npmjs.com/search?q=acme-http-01-) +and [acme-dns-01-](https://www.npmjs.com/search?q=acme-dns-01-). + +If you are building a plugin, please let us know. +We would like to co-author and help maintain and promote your module. ## Example @@ -62,30 +77,30 @@ var tester = require('acme-challenge-test'); var domain = 'example.com'; tester - .test('http-01', domain, { - // Should set a TXT record for dnsHost with dnsAuthorization and ttl || 300 - set: function(opts) { - console.log('set opts:', opts); - throw new Error('set not implemented'); - }, + .testRecord('http-01', domain, { + // Should set a TXT record for dnsHost with dnsAuthorization and ttl || 300 + set: function(opts) { + console.log('set opts:', opts); + throw new Error('set not implemented'); + }, - // Should remove the *one* TXT record for dnsHost with dnsAuthorization - // Should NOT remove otherrecords for dnsHost (wildcard shares dnsHost with - // non-wildcard) - remove: function(opts) { - console.log('remove opts:', opts); - throw new Error('remove not implemented'); - }, + // Should remove the *one* TXT record for dnsHost with dnsAuthorization + // Should NOT remove otherrecords for dnsHost (wildcard shares dnsHost with + // non-wildcard) + remove: function(opts) { + console.log('remove opts:', opts); + throw new Error('remove not implemented'); + }, - // Should get the record via the DNS server's API - get: function(opts) { - console.log('get opts:', opts); - throw new Error('get not implemented'); - } - }) - .then(function() { - console.info('PASS'); - }); + // Should get the record via the DNS server's API + get: function(opts) { + console.log('get opts:', opts); + throw new Error('get not implemented'); + } + }) + .then(function() { + console.info('PASS'); + }); ``` ## dns-01 vs http-01 @@ -107,79 +122,78 @@ Here's a quick pseudo stub-out of what a test-passing plugin object might look l ```js tester - .test('dns-01', 'example.com', { - - set: function(opts) { - var ch = opts.challenge; - // { type: 'dns-01' // or 'http-01' - // , identifier: { type: 'dns', value: 'example.com' } - // , wildcard: false - // , token: 'xxxx' - // , keyAuthorization: 'xxxx.yyyy' - // , dnsHost: '_acme-challenge.example.com' - // , dnsAuthorization: 'zzzz' } + .testZone('dns-01', 'example.com', { + set: function(opts) { + var ch = opts.challenge; + // { type: 'dns-01' // or 'http-01' + // , identifier: { type: 'dns', value: 'example.com' } + // , wildcard: false + // , token: 'xxxx' + // , keyAuthorization: 'xxxx.yyyy' + // , dnsHost: '_acme-challenge.example.com' + // , dnsAuthorization: 'zzzz' } - return YourApi('POST', 'https://example.com/api/dns/txt', { - host: ch.dnsHost, - record: ch.dnsAuthorization - }); - }, - - get: function(query) { - var ch = query.challenge; - // { type: 'dns-01' // or 'http-01', 'tls-alpn-01', etc - // , identifier: { type: 'dns', value: 'example.com' } - // // http-01 only - // , token: 'xxxx' - // , url: '...' // for testing and debugging - // // dns-01 only, for testing / dubgging - // , altname: '...' - // , dnsHost: '...' - // , wildcard: false } - // Note: query.identifier.value is different for http-01 than for dns-01 + return YourApi('POST', 'https://example.com/api/dns/txt', { + host: ch.dnsHost, + record: ch.dnsAuthorization + }); + }, - return YourApi('GET', 'https://example.com/api/dns/txt', { - host: ch.dnsHost - }).then(function(secret) { - // http-01 - //return { keyAuthorization: secret }; - // dns-01 - return { dnsAuthorization: secret }; - }); - }, - - remove: function(opts) { - var ch = opts.challenge; - // same options as in `set()` (which are not the same as `get()` + get: function(query) { + var ch = query.challenge; + // { type: 'dns-01' // or 'http-01', 'tls-alpn-01', etc + // , identifier: { type: 'dns', value: 'example.com' } + // // http-01 only + // , token: 'xxxx' + // , url: '...' // for testing and debugging + // // dns-01 only, for testing / dubgging + // , altname: '...' + // , dnsHost: '...' + // , wildcard: false } + // Note: query.identifier.value is different for http-01 than for dns-01 - return YourApi('DELETE', 'https://example.com/api/dns/txt/' + ch.dnsHost); - } - }) - .then(function() { - console.info('PASS'); - }); + return YourApi('GET', 'https://example.com/api/dns/txt', { + host: ch.dnsHost + }).then(function(secret) { + // http-01 + //return { keyAuthorization: secret }; + // dns-01 + return { dnsAuthorization: secret }; + }); + }, + + remove: function(opts) { + var ch = opts.challenge; + // same options as in `set()` (which are not the same as `get()` + + return YourApi('DELETE', 'https://example.com/api/dns/txt/' + ch.dnsHost); + } + }) + .then(function() { + console.info('PASS'); + }); ``` Where `YourApi` might look something like this: ```js var YourApi = function createApi(config) { - var request = require('@root/request'); - request = require('util').promisify(request); - - return function (method, url, body) { - return request({ - method: method, - url: url, - json: body || true, - headers: { - Authorization: 'Bearer ' + config.apiToken - } - }).then(function(resp) { - return resp.body; - }); - } -} + var request = require('@root/request'); + request = require('util').promisify(request); + + return function(method, url, body) { + return request({ + method: method, + url: url, + json: body || true, + headers: { + Authorization: 'Bearer ' + config.apiToken + } + }).then(function(resp) { + return resp.body; + }); + }; +}; ``` ### Two notes: @@ -191,6 +205,6 @@ location on an http serever, set DNS records, or add the appropriate data to the Note 2: -* When `altname` is `foo.example.com` the `dnsHost` will be `_acme-challenge.foo.example.com` -* When `altname` is `*.foo.example.com` the `dnsHost` will _still_ be `_acme-challenge.foo.example.com`!! -* When `altname` is `bar.foo.example.com` the `dnsHost` will be `_acme-challenge.bar.foo.example.com` +- When `altname` is `foo.example.com` the `dnsHost` will be `_acme-challenge.foo.example.com` +- When `altname` is `*.foo.example.com` the `dnsHost` will _still_ be `_acme-challenge.foo.example.com`!! +- When `altname` is `bar.foo.example.com` the `dnsHost` will be `_acme-challenge.bar.foo.example.com` diff --git a/index.js b/index.js index 0582083..4a55220 100644 --- a/index.js +++ b/index.js @@ -179,7 +179,7 @@ function run(challenger, opts) { }); } -module.exports.test = function(type, zone, challenger) { +function testZone(type, zone, challenger) { var domains = [zone, 'foo.' + zone]; if ('dns-01' === type) { domains.push('*.foo.' + zone); @@ -191,7 +191,7 @@ module.exports.test = function(type, zone, challenger) { return; } console.info("TEST '%s'", domain); - return testOne(type, domain, challenger).then(function() { + return testRecord(type, domain, challenger).then(function() { console.info("PASS '%s'", domain); return next(); }); @@ -208,7 +208,7 @@ module.exports.test = function(type, zone, challenger) { }); }; -function testOne(type, altname, challenger) { +function testRecord(type, altname, challenger) { var expires = new Date(Date.now() + 10 * 60 * 1000).toISOString(); var token = crypto.randomBytes(8).toString('hex'); var thumb = crypto.randomBytes(16).toString('hex'); @@ -248,4 +248,6 @@ function testOne(type, altname, challenger) { return run(challenger, { challenge: challenge }); } -module.exports._test = testOne; +module.exports.testRecord = testRecord; +module.exports.testZone = testZone; +module.exports.test = testZone; diff --git a/package.json b/package.json index ff4ba9a..4acbe1b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "acme-challenge-test", - "version": "3.0.5", + "version": "3.1.0", "description": "The base set of tests for all ACME challenge strategies. Any `acme-http-01-`, `acme-dns-01-`, `acme-challenge-`, or greenlock plugin should be able to pass these tests.", "main": "index.js", "homepage": "https://git.rootprojects.org/root/acme-challenge-test.js",