v3.0.0: update for greenlock v2.7+

This commit is contained in:
AJ ONeal 2019-04-02 20:59:11 -06:00
parent 0285cf74ab
commit 498c8e53b3
4 changed files with 121 additions and 78 deletions

52
LICENSE
View File

@ -1,21 +1,41 @@
Copyright 2016-2019 AJ ONeal
This is open source software; you can redistribute it and/or modify it under the
terms of either:
a) the "MIT License"
b) the "Apache-2.0 License"
MIT License MIT License
Copyright (c) 2016 Daplie, Inc Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
Permission is hereby granted, free of charge, to any person obtaining a copy The above copyright notice and this permission notice shall be included in all
of this software and associated documentation files (the "Software"), to deal copies or substantial portions of the Software.
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
copies or substantial portions of the Software. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR Apache-2.0 License Summary
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE Licensed under the Apache License, Version 2.0 (the "License");
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER you may not use this file except in compliance with the License.
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, You may obtain a copy of the License at
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@ -1,5 +1,4 @@
le-challenge-dns # le-challenge-dns
================
| A [Root](https://rootprojects.org) Project | A [Root](https://rootprojects.org) Project
| [greenlock.js](https://git.coolaj86.com/coolaj86/greenlock.js) (library) | [greenlock.js](https://git.coolaj86.com/coolaj86/greenlock.js) (library)
@ -21,19 +20,19 @@ press [enter] to continue the process.
_acme-challenge.example.com TXT xxxxxxxxxxxxxxxx TTL 60 _acme-challenge.example.com TXT xxxxxxxxxxxxxxxx TTL 60
``` ```
Install ## Install
-------
```bash ```bash
npm install --save le-challenge-dns@2.x npm install --save le-challenge-dns@3.x
``` ```
Usage If you have `greenlock@v2.6` or lower, you'll need the old `le-challenge-dns@3.x` instead.
-----
## Usage
The challenge can be set globally like this: The challenge can be set globally like this:
```bash ```js
var leChallengeDns = require('le-challenge-dns').create({ var leChallengeDns = require('le-challenge-dns').create({
debug: false debug: false
}); });
@ -41,21 +40,37 @@ var leChallengeDns = require('le-challenge-dns').create({
var Greenlock = require('greenlock'); var Greenlock = require('greenlock');
Greenlock.create({ Greenlock.create({
server: LE.stagingServerUrl // Change to LE.productionServerUrl in production ...
, challengeType: 'dns-01'
, challenges: { , challenges: {
'dns-01': leChallengeDns 'dns-01': leChallengeDns
} }
, approveDomains: [ 'example.com' ] , approveDomains: [ 'example.com', '*.example.com' ]
}); });
``` ```
In can also be set in the `approveDomains` callback instead, like this: In can also be set in the `approveDomains` callback instead, like this:
``` ```js
function approveDomains(opts, certs, cb) { function approveDomains(opts, certs, cb) {
opts.challenges = { 'dns-01': leChallengeDns };
... ...
opts.subject = 'example.com'
opts.domains = [ 'example.com', '*.example.com' ];
cb(null, { options: opts, certs: certs });
}
```
If you didn't make the dns challenge globally available in the main greenlock config,
you can make it locally available here:
```js
function approveDomains(opts, certs, cb) {
...
if (!opts.challenges) { opts.challenges = {}; }
opts.challenges['dns-01'] = leChallengeDns;
opts.challenges['http-01'] = ...
cb(null, { options: opts, certs: certs }); cb(null, { options: opts, certs: certs });
} }
``` ```
@ -63,19 +78,33 @@ function approveDomains(opts, certs, cb) {
NOTE: If you request a certificate with 6 domains listed, NOTE: If you request a certificate with 6 domains listed,
it will require 6 individual challenges. it will require 6 individual challenges.
Exposed Methods ## Exposed Methods
---------------
For ACME Challenge: For ACME Challenge:
* `set(opts, domain, challange, keyAuthorization, done)` * `set(opts, done)`
* `get(defaults, domain, challenge, done)` * `remove(opts, done)`
* `remove(defaults, domain, challenge, done)`
Note: `get()` is a no-op for `dns-01`. The options object has whatever options were set in `approveDomains()` as well as the `challenge`:
```js
{ challenge: {
identifier: { type: 'dns', value: 'example.com'
, wildcard: true
, altname: '*.example.com'
, type: 'dns-01'
, token: 'xxxxxx'
, keyAuthorization: 'xxxxxx.abc123'
, dnsHost: '_acme-challenge.example.com'
, dnsAuthorization: 'abc123'
, expires: '1970-01-01T00:00:00Z'
}
}
```
Note: There's no `get()` because it's the DNS server, not the Greenlock server, that answers the requests.
(though I suppose you could implement it if you happen to run your DNS and webserver together... kinda weird though)
For greenlock.js internals: For greenlock.js internals:
* `getOptions()` returns the internal defaults merged with the user-supplied options * `options` stores the internal defaults merged with the user-supplied options
* `loopback(defaults, domain, challange, done)` performs a dns lookup of the txt record
* `test(opts, domain, challange, keyAuthorization, done)` runs set, loopback, remove, loopback

View File

@ -4,48 +4,44 @@ var Challenge = module.exports;
Challenge.create = function (defaults) { Challenge.create = function (defaults) {
return { return {
getOptions: function () { options: defaults
return defaults || {};
}
, set: Challenge.set , set: Challenge.set
, get: Challenge.get , get: Challenge.get
, remove: Challenge.remove , remove: Challenge.remove
, loopback: Challenge.loopback
, test: Challenge.test
}; };
}; };
// Show the user the token and key and wait for them to be ready to continue // Show the user the token and key and wait for them to be ready to continue
Challenge.set = function (args, domain, challenge, keyAuthorization, cb) { Challenge.set = function (args, cb) {
var keyAuthDigest = require('crypto').createHash('sha256').update(keyAuthorization||'').digest('base64') if (!args.challenge) {
.replace(/\+/g, '-') console.error("please update to greenlock v2.7+");
.replace(/\//g, '_') process.exit();
.replace(/=+$/g, '') }
; var opts = args.challenge;
var challengeDomain = domain;
if (this.leDnsResponse) { if (this.leDnsResponse) {
this.leDnsResponse(challenge, keyAuthorization, keyAuthDigest, challengeDomain, domain) this.leDnsResponse(opts.token, opts.keyAuthorization, opts.dnsAuthorization, opts.dnsHost, opts.altname)
.then(function (/*successMessage*/) { .then(function (/*successMessage*/) {
cb(null); cb(null);
}); });
} else { } else {
console.info(""); console.info("");
console.info("Challenge for '" + domain + "'"); console.info("Challenge for '" + opts.altname + "'");
console.info(""); console.info("");
console.info("We now present (for you copy-and-paste pleasure) your ACME Challenge"); console.info("We now present (for you copy-and-paste pleasure) your ACME Challenge");
console.info("public Challenge and secret KeyAuthorization and Digest, in that order, respectively:");
console.info(challenge);
console.info(keyAuthorization);
console.info(keyAuthDigest);
console.info(""); console.info("");
console.info(challengeDomain + "\tTXT " + keyAuthDigest + "\tTTL 60"); console.info(opts.dnsHost + "\tTXT " + opts.dnsAuthorization + "\tTTL 60");
console.info(""); console.info("");
console.info(JSON.stringify({ console.info(JSON.stringify({
domain: domain identifier: opts.identifier
, challenge: challenge , wildcard: opts.wildcard
, keyAuthorization: keyAuthorization , altname: opts.altname
, keyAuthDigest: keyAuthDigest , type: opts.type
, token: opts.token
, keyAuthorization: opts.keyAuthorization
, dnsHost: opts.dnsHost
, dnsAuthorization: opts.dnsAuthorization
, expires: opts.expires
}, null, ' ').replace(/^/gm, '\t')); }, null, ' ').replace(/^/gm, '\t'));
console.info(""); console.info("");
console.info("hit enter to continue..."); console.info("hit enter to continue...");
@ -58,13 +54,14 @@ Challenge.set = function (args, domain, challenge, keyAuthorization, cb) {
}; };
// nothing to do here, that's why it's manual // nothing to do here, that's why it's manual
Challenge.get = function (defaults, domain, challenge, cb) { Challenge.get = function (defaults, cb) {
// defaults.challenge
cb(null); cb(null);
}; };
// might as well tell the user that whatever they were setting up has been checked // might as well tell the user that whatever they were setting up has been checked
Challenge.remove = function (args, domain, challenge, cb) { Challenge.remove = function (args, cb) {
console.info("Challenge for '" + domain + "' complete. You may remove it."); console.info("Challenge complete. You may remove the DNS-01 challenge record:");
console.info("\t" + args.challenge.altname + "\tTXT\t" + args.challenge.dnsAuthorization);
cb(null); cb(null);
//});
}; };

View File

@ -1,7 +1,7 @@
{ {
"name": "le-challenge-dns", "name": "le-challenge-dns",
"version": "2.3.2", "version": "3.0.0",
"description": "A manual (interactive CLI) dns-based strategy for node-letsencrypt for setting, retrieving, and clearing ACME DNS-01 challenges issued by the ACME server", "description": "A manual (interactive CLI) dns-based strategy for Greenlock / Let's Encrypt / ACME DNS-01 challenges",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
"test": "node test.js" "test": "node test.js"
@ -11,21 +11,18 @@
"url": "git+https://git.coolaj86.com/coolaj86/le-challenge-dns.js.git" "url": "git+https://git.coolaj86.com/coolaj86/le-challenge-dns.js.git"
}, },
"keywords": [ "keywords": [
"le", "Let's Encrypt",
"Greenlock",
"ACME",
"dns-01",
"wildcard",
"wildcards",
"letsencrypt", "letsencrypt",
"le-challenge",
"le-challenge-",
"le-challenge-dns",
"manual", "manual",
"interactive", "interactive",
"cli", "cli",
"acme",
"Let's Encrypt v2",
"LetsEncrypt",
"challenge",
"dns", "dns",
"cluster", "challenge"
"ephemeral"
], ],
"author": "AJ ONeal <coolaj86@gmail.com> (https://coolaj86.com/)", "author": "AJ ONeal <coolaj86@gmail.com> (https://coolaj86.com/)",
"license": "(MIT OR Apache-2.0)", "license": "(MIT OR Apache-2.0)",