v3.0.0: update for greenlock v2.7+
This commit is contained in:
parent
0285cf74ab
commit
498c8e53b3
52
LICENSE
52
LICENSE
|
@ -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.
|
||||||
|
|
73
README.md
73
README.md
|
@ -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
|
|
||||||
|
|
51
index.js
51
index.js
|
@ -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);
|
||||||
//});
|
|
||||||
};
|
};
|
||||||
|
|
21
package.json
21
package.json
|
@ -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)",
|
||||||
|
|
Loading…
Reference in New Issue