Compare commits

..

No commits in common. "master" and "v3.0.0" have entirely different histories.

5 changed files with 67 additions and 60 deletions

View File

@ -1,15 +1,10 @@
# [acme-http-01-cli](https://git.rootprojects.org/root/acme-http-01-cli.js) | a [Root](https://rootprojects.org) project # [le-challenge-http](https://git.coolaj86.com/coolaj86/le-challenge-http.js)
| 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)
@ -18,15 +13,15 @@ GET http://example.com/.well-known/acme-challenge/xxxxxxxxxxxxxxxx
Other ACME Challenge Reference Implementations: Other ACME Challenge Reference Implementations:
* [acme-http-01-fs](https://git.rootprojects.org/root/acme-http-01-webroot.js.git) * [le-challenge-manual](https://git.coolaj86.com/coolaj86/le-challenge-manual.js.git)
* [**acme-http-01-cli**](https://git.rootprojects.org/root/acme-http-01-cli.js.git) * [**le-challenge-http**](https://git.coolaj86.com/coolaj86/le-challenge-http.js.git)
* [acme-dns-01-cli](https://git.rootprojects.org/root/acme-dns-01-cli.js.git) * [le-challenge-dns](https://git.coolaj86.com/coolaj86/le-challenge-dns.js.git)
Install Install
------- -------
```bash ```bash
npm install --save acme-http-01-cli@3.x npm install --save le-challenge-http@3.x
``` ```
Usage Usage
@ -37,9 +32,9 @@ var Greenlock = require('greenlock');
Greenlock.create({ Greenlock.create({
... ...
, challenges: { 'http-01': require('acme-http-01-cli').create({ debug: true }) , challenges: { 'http-01': require('le-challenge-http').create({ debug: true })
, 'dns-01': require('acme-dns-01-cli') , 'dns-01': require('le-challenge-dns')
, 'tls-alpn-01': require('acme-tls-alpn-01-cli') , 'tls-alpn-01': require('le-challenge-manual')
} }
... ...
}); });
@ -92,19 +87,3 @@ 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)

View File

@ -40,7 +40,6 @@ 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
@ -80,7 +79,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]: " + ch.status); console.info("[ACME http-01 '" + ch.altname + "' COMPLETE]");
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);
@ -90,17 +89,15 @@ 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;
console.log(args); if (!Challenge._getCache[ch.altname + ':' + ch.token]) {
if (ch._test || !Challenge._getCache[ch.token]) { Challenge._getCache[ch.altname + ':' + ch.token] = true;
Challenge._getCache[ch.token] = true;
console.info(""); console.info("");
console.info("[ACME " + ch.type + " '" + altname + "' REQUEST]: " + ch.status); console.info('GET http://' + ch.altname + '/.well-known/acme-challenge/' + ch.token);
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("> ");
} }
@ -113,7 +110,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').trim(); var result = chunk.toString('utf8');
try { try {
result = JSON.parse(result); result = JSON.parse(result);
} catch(e) { } catch(e) {

4
package-lock.json generated
View File

@ -1,5 +1,5 @@
{ {
"name": "greenlock-challenge-http", "name": "le-challenge-manual",
"version": "3.0.0", "version": "2.1.1",
"lockfileVersion": 1 "lockfileVersion": 1
} }

View File

@ -1,15 +1,15 @@
{ {
"name": "acme-http-01-cli", "name": "le-challenge-http",
"version": "3.0.2", "version": "3.0.0",
"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://greenlock.domains/", "homepage": "https://git.coolaj86.com/coolaj86/le-challenge-http.js",
"scripts": { "scripts": {
"test": "node test.js" "test": "node test.js"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
"url": "https://git.rootprojects.org/root/acme-http-01-cli.js.git" "url": "https://git.coolaj86.com/coolaj86/le-challenge-http.js.git"
}, },
"keywords": [ "keywords": [
"Let's Encrypt", "Let's Encrypt",
@ -20,9 +20,9 @@
"cli", "cli",
"commandline" "commandline"
], ],
"author": "AJ ONeal <solderjs@gmail.com> (https://solderjs.com/)", "author": "AJ ONeal <coolaj86@gmail.com> (https://coolaj86.com/)",
"license": "MPL-2.0", "license": "MPL-2.0",
"bugs": { "bugs": {
"url": "https://git.rootprojects.org/root/acme-http-01-cli.js/issues" "url": "https://git.coolaj86.com/coolaj86/le-challenge-http.js/issues"
} }
} }

49
test.js
View File

@ -1,19 +1,50 @@
'use strict'; 'use strict';
/*global Promise*/
var tester = require('greenlock-challenge-test'); var challenge = require('./').create({});
var type = 'http-01'; var opts = challenge.getOptions && challenge.getOptions() || challenge.options;
//var challenger = require('greenlock-challenge-http').create({});
var challenger = require('./').create({});
// The dry-run tests can pass on, literally, 'example.com' function run() {
// but the integration tests require that you have control over the domain // this will cause the prompt to appear
var domain = 'example.com'; return new Promise(function (resolve, reject) {
challenge.set(opts, function () {
// this will cause the final completion message to appear
return Promise.resolve(challenge.remove(opts)).then(resolve).catch(reject);
});
});
}
tester.test(type, domain, challenger).then(function () { opts.challenge = {
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(19); process.exit(17);
}); });