Compare commits
3 Commits
Author | SHA1 | Date |
---|---|---|
|
19ae7f120c | |
|
4ee2f81535 | |
|
6db2e9b308 |
45
README.md
45
README.md
|
@ -1,10 +1,15 @@
|
||||||
# [le-challenge-http](https://git.coolaj86.com/coolaj86/le-challenge-http.js)
|
# [acme-http-01-cli](https://git.rootprojects.org/root/acme-http-01-cli.js) | a [Root](https://rootprojects.org) project
|
||||||
|
|
||||||
| A [Root](https://rootprojects.org) Project |
|
|
||||||
|
|
||||||
An extremely simple reference implementation
|
An extremely simple reference implementation
|
||||||
of an ACME (Let's Encrypt) http-01 challenge strategy
|
of an ACME (Let's Encrypt) http-01 challenge strategy.
|
||||||
for [Greenlock](https://git.coolaj86.com/coolaj86/greenlock-express.js) v2.7+ (and v3).
|
|
||||||
|
This generic implementation can be adapted to work with any node.js ACME client,
|
||||||
|
although it was built for [Greenlock](https://git.rootprojects.org/root/greenlock-express.js)
|
||||||
|
and [ACME.js](https://git.rootprojects.org/root/acme-v2.js).
|
||||||
|
|
||||||
|
```
|
||||||
|
GET http://example.com/.well-known/acme-challenge/xxxxxxxxxxxxxxxx
|
||||||
|
```
|
||||||
|
|
||||||
* Prints the ACME challenge URL and Key Authorization to the terminal
|
* Prints the ACME challenge URL and Key Authorization to the terminal
|
||||||
* (waits for you to hit enter before continuing)
|
* (waits for you to hit enter before continuing)
|
||||||
|
@ -13,15 +18,15 @@ for [Greenlock](https://git.coolaj86.com/coolaj86/greenlock-express.js) v2.7+ (a
|
||||||
|
|
||||||
Other ACME Challenge Reference Implementations:
|
Other ACME Challenge Reference Implementations:
|
||||||
|
|
||||||
* [le-challenge-manual](https://git.coolaj86.com/coolaj86/le-challenge-manual.js.git)
|
* [acme-http-01-fs](https://git.rootprojects.org/root/acme-http-01-webroot.js.git)
|
||||||
* [**le-challenge-http**](https://git.coolaj86.com/coolaj86/le-challenge-http.js.git)
|
* [**acme-http-01-cli**](https://git.rootprojects.org/root/acme-http-01-cli.js.git)
|
||||||
* [le-challenge-dns](https://git.coolaj86.com/coolaj86/le-challenge-dns.js.git)
|
* [acme-dns-01-cli](https://git.rootprojects.org/root/acme-dns-01-cli.js.git)
|
||||||
|
|
||||||
Install
|
Install
|
||||||
-------
|
-------
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm install --save le-challenge-http@3.x
|
npm install --save acme-http-01-cli@3.x
|
||||||
```
|
```
|
||||||
|
|
||||||
Usage
|
Usage
|
||||||
|
@ -32,9 +37,9 @@ var Greenlock = require('greenlock');
|
||||||
|
|
||||||
Greenlock.create({
|
Greenlock.create({
|
||||||
...
|
...
|
||||||
, challenges: { 'http-01': require('le-challenge-http').create({ debug: true })
|
, challenges: { 'http-01': require('acme-http-01-cli').create({ debug: true })
|
||||||
, 'dns-01': require('le-challenge-dns')
|
, 'dns-01': require('acme-dns-01-cli')
|
||||||
, 'tls-alpn-01': require('le-challenge-manual')
|
, 'tls-alpn-01': require('acme-tls-alpn-01-cli')
|
||||||
}
|
}
|
||||||
...
|
...
|
||||||
});
|
});
|
||||||
|
@ -87,3 +92,19 @@ it's not always implemented and the options are much more limited in scope:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
# Legal & Rules of the Road
|
||||||
|
|
||||||
|
Greenlock™ and Bluecrypt™ are [trademarks](https://rootprojects.org/legal/#trademark) of AJ ONeal
|
||||||
|
|
||||||
|
The rule of thumb is "attribute, but don't confuse". For example:
|
||||||
|
|
||||||
|
> Built with [Greenlock](https://git.rootprojects.org/root/greenlock.js) (a [Root](https://rootprojects.org) project).
|
||||||
|
|
||||||
|
Please [contact us](mailto:aj@therootcompany.com) if you have any questions in regards to our trademark,
|
||||||
|
attribution, and/or visible source policies. We want to build great software and a great community.
|
||||||
|
|
||||||
|
[Greenlock™](https://git.rootprojects.org/root/greenlock.js) |
|
||||||
|
MPL-2.0 |
|
||||||
|
[Terms of Use](https://therootcompany.com/legal/#terms) |
|
||||||
|
[Privacy Policy](https://therootcompany.com/legal/#privacy)
|
||||||
|
|
17
index.js
17
index.js
|
@ -40,6 +40,7 @@ Challenge.create = function (config) {
|
||||||
|
|
||||||
// Prints the challenge URL and keyAuthorization to the screen
|
// Prints the challenge URL and keyAuthorization to the screen
|
||||||
// (so that you can go set it and then continue)
|
// (so that you can go set it and then continue)
|
||||||
|
// if you need per-run / per-domain options set them in approveDomains() and they'll be on 'args' here.
|
||||||
Challenge._setHttp = function (args, cb) {
|
Challenge._setHttp = function (args, cb) {
|
||||||
// Note: You can receive cb and use that, or omit cb and return a Promise
|
// Note: You can receive cb and use that, or omit cb and return a Promise
|
||||||
|
|
||||||
|
@ -79,7 +80,7 @@ Challenge._removeHttp = function (args) {
|
||||||
|
|
||||||
var ch = args.challenge;
|
var ch = args.challenge;
|
||||||
console.info("");
|
console.info("");
|
||||||
console.info("[ACME http-01 '" + ch.altname + "' COMPLETE]");
|
console.info("[ACME http-01 '" + ch.altname + "' COMPLETE]: " + ch.status);
|
||||||
console.info("Challenge complete. You may now remove the challenge file:");
|
console.info("Challenge complete. You may now remove the challenge file:");
|
||||||
console.info("");
|
console.info("");
|
||||||
console.info('\thttp://' + ch.altname + '/.well-known/acme-challenge/' + ch.token);
|
console.info('\thttp://' + ch.altname + '/.well-known/acme-challenge/' + ch.token);
|
||||||
|
@ -89,15 +90,17 @@ Challenge._removeHttp = function (args) {
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
// nothing to do here, that's why it's manual
|
|
||||||
Challenge._getHttp = function (args) {
|
Challenge._getHttp = function (args) {
|
||||||
// Note: Here I'm You can receive cb and use that, or omit cb and return a Promise
|
|
||||||
var ch = args.challenge;
|
var ch = args.challenge;
|
||||||
|
var altname = ch.altname || ch.identifier.value;
|
||||||
|
var hostname = ch.hostname || ch.identifier.value;
|
||||||
|
|
||||||
if (!Challenge._getCache[ch.altname + ':' + ch.token]) {
|
console.log(args);
|
||||||
Challenge._getCache[ch.altname + ':' + ch.token] = true;
|
if (ch._test || !Challenge._getCache[ch.token]) {
|
||||||
|
Challenge._getCache[ch.token] = true;
|
||||||
console.info("");
|
console.info("");
|
||||||
console.info('GET http://' + ch.altname + '/.well-known/acme-challenge/' + ch.token);
|
console.info("[ACME " + ch.type + " '" + altname + "' REQUEST]: " + ch.status);
|
||||||
|
console.info('GET http://' + hostname + '/.well-known/acme-challenge/' + ch.token);
|
||||||
console.info("(paste in the \"Key Authorization\" you received a moment ago to respond)");
|
console.info("(paste in the \"Key Authorization\" you received a moment ago to respond)");
|
||||||
process.stdout.write("> ");
|
process.stdout.write("> ");
|
||||||
}
|
}
|
||||||
|
@ -110,7 +113,7 @@ Challenge._getHttp = function (args) {
|
||||||
process.stdin.once('data', function (chunk) {
|
process.stdin.once('data', function (chunk) {
|
||||||
process.stdin.pause();
|
process.stdin.pause();
|
||||||
|
|
||||||
var result = chunk.toString('utf8');
|
var result = chunk.toString('utf8').trim();
|
||||||
try {
|
try {
|
||||||
result = JSON.parse(result);
|
result = JSON.parse(result);
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"name": "le-challenge-manual",
|
"name": "greenlock-challenge-http",
|
||||||
"version": "2.1.1",
|
"version": "3.0.0",
|
||||||
"lockfileVersion": 1
|
"lockfileVersion": 1
|
||||||
}
|
}
|
||||||
|
|
12
package.json
12
package.json
|
@ -1,15 +1,15 @@
|
||||||
{
|
{
|
||||||
"name": "le-challenge-http",
|
"name": "acme-http-01-cli",
|
||||||
"version": "3.0.0",
|
"version": "3.0.2",
|
||||||
"description": "A very simple reference implementation of an ACME http-01 challenge for Greenlock v2.7+ (and v3)",
|
"description": "A very simple reference implementation of an ACME http-01 challenge for Greenlock v2.7+ (and v3)",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"homepage": "https://git.coolaj86.com/coolaj86/le-challenge-http.js",
|
"homepage": "https://greenlock.domains/",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "node test.js"
|
"test": "node test.js"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://git.coolaj86.com/coolaj86/le-challenge-http.js.git"
|
"url": "https://git.rootprojects.org/root/acme-http-01-cli.js.git"
|
||||||
},
|
},
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"Let's Encrypt",
|
"Let's Encrypt",
|
||||||
|
@ -20,9 +20,9 @@
|
||||||
"cli",
|
"cli",
|
||||||
"commandline"
|
"commandline"
|
||||||
],
|
],
|
||||||
"author": "AJ ONeal <coolaj86@gmail.com> (https://coolaj86.com/)",
|
"author": "AJ ONeal <solderjs@gmail.com> (https://solderjs.com/)",
|
||||||
"license": "MPL-2.0",
|
"license": "MPL-2.0",
|
||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://git.coolaj86.com/coolaj86/le-challenge-http.js/issues"
|
"url": "https://git.rootprojects.org/root/acme-http-01-cli.js/issues"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
49
test.js
49
test.js
|
@ -1,50 +1,19 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
/*global Promise*/
|
|
||||||
|
|
||||||
var challenge = require('./').create({});
|
var tester = require('greenlock-challenge-test');
|
||||||
|
|
||||||
var opts = challenge.getOptions && challenge.getOptions() || challenge.options;
|
var type = 'http-01';
|
||||||
|
//var challenger = require('greenlock-challenge-http').create({});
|
||||||
|
var challenger = require('./').create({});
|
||||||
|
|
||||||
function run() {
|
// The dry-run tests can pass on, literally, 'example.com'
|
||||||
// this will cause the prompt to appear
|
// but the integration tests require that you have control over the domain
|
||||||
return new Promise(function (resolve, reject) {
|
var domain = 'example.com';
|
||||||
challenge.set(opts, function () {
|
|
||||||
// this will cause the final completion message to appear
|
|
||||||
return Promise.resolve(challenge.remove(opts)).then(resolve).catch(reject);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
opts.challenge = {
|
tester.test(type, domain, challenger).then(function () {
|
||||||
type: 'http-01'
|
|
||||||
, identifier: { type: 'dns', value: 'example.com' }
|
|
||||||
, wildcard: false
|
|
||||||
, expires: '2012-01-01T12:00:00.000Z'
|
|
||||||
, token: 'abc123'
|
|
||||||
, thumbprint: '<<account key thumbprint>>'
|
|
||||||
, keyAuthorization: 'abc123.xxxx'
|
|
||||||
, dnsHost: '_acme-challenge.example.com'
|
|
||||||
, dnsAuthorization: 'yyyy'
|
|
||||||
, altname: 'example.com'
|
|
||||||
};
|
|
||||||
run(opts).then(function () {
|
|
||||||
opts.challenge = {
|
|
||||||
type: 'dns-01'
|
|
||||||
, identifier: { type: 'dns', value: 'example.com' }
|
|
||||||
, wildcard: true
|
|
||||||
, expires: '2012-01-01T12:00:00.000Z'
|
|
||||||
, token: 'abc123'
|
|
||||||
, thumbprint: '<<account key thumbprint>>'
|
|
||||||
, keyAuthorization: 'abc123.xxxx'
|
|
||||||
, dnsHost: '_acme-challenge.example.com'
|
|
||||||
, dnsAuthorization: 'yyyy'
|
|
||||||
, altname: '*.example.com'
|
|
||||||
};
|
|
||||||
return run(opts);
|
|
||||||
}).then(function () {
|
|
||||||
console.info("PASS");
|
console.info("PASS");
|
||||||
}).catch(function (err) {
|
}).catch(function (err) {
|
||||||
console.error("FAIL");
|
console.error("FAIL");
|
||||||
console.error(err);
|
console.error(err);
|
||||||
process.exit(17);
|
process.exit(19);
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue