closer to v1
This commit is contained in:
parent
b630c118cc
commit
263eed0475
113
README.md
113
README.md
|
@ -1,41 +1,12 @@
|
||||||
acme-v2.js
|
acme-v2.js (draft 11)
|
||||||
==========
|
==========
|
||||||
|
|
||||||
| Sponsored by [ppl](https://ppl.family)
|
| Sponsored by [ppl](https://ppl.family)
|
||||||
|
|
||||||
A framework for building letsencrypt clients (and other ACME v2 clients), forked from `le-acme-core.js`.
|
A framework for building letsencrypt v2 (IETF ACME draft 11), forked from `le-acme-core.js`.
|
||||||
|
|
||||||
Summary of spec that I'm working off of here: https://git.coolaj86.com/coolaj86/greenlock.js/issues/5#issuecomment-8
|
Summary of spec that I'm working off of here: https://git.coolaj86.com/coolaj86/greenlock.js/issues/5#issuecomment-8
|
||||||
|
|
||||||
In progress
|
|
||||||
|
|
||||||
* Mar 15, 2018 - get directory
|
|
||||||
* Mar 15, 2018 - get nonce
|
|
||||||
* Mar 15, 2018 - generate account keypair
|
|
||||||
* Mar 15, 2018 - create account
|
|
||||||
* Mar 16, 2018 - new order
|
|
||||||
* Mar 16, 2018 - get challenges
|
|
||||||
* Mar 20, 2018 - respond to challenges
|
|
||||||
* Mar 20, 2018 - generate domain keypair
|
|
||||||
* Mar 20, 2018 - finalize order (submit csr)
|
|
||||||
* Mar 20, 2018 - poll for status
|
|
||||||
* Mar 20, 2018 - download certificate
|
|
||||||
* Mar 20, 2018 - SUCCESS - got a test certificate (hard-coded)
|
|
||||||
* Mar 21, 2018 - can now accept values (not hard coded)
|
|
||||||
* Mar 21, 2018 - *mostly* matches le-acme-core.js API
|
|
||||||
* Apr 5, 2018 - completely match api for acme v1 (le-acme-core.js)
|
|
||||||
* Apr 5, 2018 - test wildcard
|
|
||||||
* Apr 5, 2018 - test two subdomains
|
|
||||||
* Apr 5, 2018 - test subdomains and its wildcard
|
|
||||||
* Apr 5, 2018 - test http and dns challenges (success and failure)
|
|
||||||
* Apr 5, 2018 - export http and dns challenge tests
|
|
||||||
* Apr 10, 2018 - tested backwards-compatibility using greenlock.js
|
|
||||||
|
|
||||||
Todo
|
|
||||||
|
|
||||||
* support ECDSA keys
|
|
||||||
* Apr 5, 2018 - appears that sometimes 'pending' status cannot be progressed to 'processing' nor 'deactivated'
|
|
||||||
|
|
||||||
## Let's Encrypt Directory URLs
|
## Let's Encrypt Directory URLs
|
||||||
|
|
||||||
```
|
```
|
||||||
|
@ -48,7 +19,48 @@ https://acme-v02.api.letsencrypt.org/directory
|
||||||
https://acme-staging-v02.api.letsencrypt.org/directory
|
https://acme-staging-v02.api.letsencrypt.org/directory
|
||||||
```
|
```
|
||||||
|
|
||||||
## API
|
## Two API versions, Two Implementations
|
||||||
|
|
||||||
|
This library (acme-v2.js) supports ACME [*draft 11*](https://tools.ietf.org/html/draft-ietf-acme-acme-11),
|
||||||
|
otherwise known as Let's Encrypt v2 (or v02).
|
||||||
|
|
||||||
|
* ACME draft 11
|
||||||
|
* Let's Encrypt v2
|
||||||
|
* Let's Encrypt v02
|
||||||
|
|
||||||
|
The predecessor (le-acme-core) supports Let's Encrypt v1 (or v01), which was a
|
||||||
|
[hodge-podge of various drafts](https://github.com/letsencrypt/boulder/blob/master/docs/acme-divergences.md)
|
||||||
|
of the ACME spec early on.
|
||||||
|
|
||||||
|
* ACME early draft
|
||||||
|
* Let's Encrypt v1
|
||||||
|
* Let's Encrypt v01
|
||||||
|
|
||||||
|
This library maintains compatibility with le-acme-core so that it can be used as a **drop-in replacement**
|
||||||
|
and requires **no changes to existing code**,
|
||||||
|
but also provides an updated API more congruent with draft 11.
|
||||||
|
|
||||||
|
## le-acme-core-compatible API (recommended)
|
||||||
|
|
||||||
|
Status: Stable, Locked, Bugfix-only
|
||||||
|
|
||||||
|
```
|
||||||
|
var RSA = require('rsa-compat').RSA;
|
||||||
|
var acme = require('acme-v2/compat.js').ACME.create({ RSA: RSA });
|
||||||
|
|
||||||
|
//
|
||||||
|
// Use exactly the same as le-acme-core
|
||||||
|
//
|
||||||
|
```
|
||||||
|
|
||||||
|
See documentation at <https://git.coolaj86.com/coolaj86/le-acme-core.js>
|
||||||
|
|
||||||
|
## draft API (dev)
|
||||||
|
|
||||||
|
Status: Almost stable, not locked
|
||||||
|
|
||||||
|
This API is a simple evolution of le-acme-core,
|
||||||
|
but tries to provide a better mapping to the new draft 11 APIs.
|
||||||
|
|
||||||
```
|
```
|
||||||
var ACME = require('acme-v2').ACME.create({
|
var ACME = require('acme-v2').ACME.create({
|
||||||
|
@ -110,6 +122,41 @@ Helpers & Stuff
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
// Constants
|
// Constants
|
||||||
ACME.acmeChallengePrefix // /.well-known/acme-challenge/
|
ACME.challengePrefixes['http-01'] // '/.well-known/acme-challenge'
|
||||||
|
ACME.challengePrefixes['dns-01'] // '_acme-challenge'
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Todo
|
||||||
|
----
|
||||||
|
|
||||||
|
* support ECDSA keys
|
||||||
|
* Apr 5, 2018 - appears that sometimes 'pending' status cannot be progressed to 'processing' nor 'deactivated'
|
||||||
|
* this may be a bug in the staging API as it appears it cannot be cancelled either, but returns success status code
|
||||||
|
|
||||||
|
Changelog
|
||||||
|
---------
|
||||||
|
|
||||||
|
* v1.0.0
|
||||||
|
* Compat API is ready for use
|
||||||
|
* Eliminate debug logging
|
||||||
|
* Apr 10, 2018 - tested backwards-compatibility using greenlock.js
|
||||||
|
* Apr 5, 2018 - export http and dns challenge tests
|
||||||
|
* Apr 5, 2018 - test http and dns challenges (success and failure)
|
||||||
|
* Apr 5, 2018 - test subdomains and its wildcard
|
||||||
|
* Apr 5, 2018 - test two subdomains
|
||||||
|
* Apr 5, 2018 - test wildcard
|
||||||
|
* Apr 5, 2018 - completely match api for acme v1 (le-acme-core.js)
|
||||||
|
* Mar 21, 2018 - *mostly* matches le-acme-core.js API
|
||||||
|
* Mar 21, 2018 - can now accept values (not hard coded)
|
||||||
|
* Mar 20, 2018 - SUCCESS - got a test certificate (hard-coded)
|
||||||
|
* Mar 20, 2018 - download certificate
|
||||||
|
* Mar 20, 2018 - poll for status
|
||||||
|
* Mar 20, 2018 - finalize order (submit csr)
|
||||||
|
* Mar 20, 2018 - generate domain keypair
|
||||||
|
* Mar 20, 2018 - respond to challenges
|
||||||
|
* Mar 16, 2018 - get challenges
|
||||||
|
* Mar 16, 2018 - new order
|
||||||
|
* Mar 15, 2018 - create account
|
||||||
|
* Mar 15, 2018 - generate account keypair
|
||||||
|
* Mar 15, 2018 - get nonce
|
||||||
|
* Mar 15, 2018 - get directory
|
||||||
|
|
|
@ -50,6 +50,7 @@ function create(deps) {
|
||||||
};
|
};
|
||||||
acme2.stagingServerUrl = module.exports.defaults.stagingServerUrl;
|
acme2.stagingServerUrl = module.exports.defaults.stagingServerUrl;
|
||||||
acme2.productionServerUrl = module.exports.defaults.productionServerUrl;
|
acme2.productionServerUrl = module.exports.defaults.productionServerUrl;
|
||||||
|
acme2.acmeChallengePrefix = module.exports.defaults.acmeChallengePrefix;
|
||||||
return acme2;
|
return acme2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,11 +64,12 @@ module.exports.defaults = {
|
||||||
//, keyType: 'rsa' // ecdsa
|
//, keyType: 'rsa' // ecdsa
|
||||||
//, keySize: 2048 // 256
|
//, keySize: 2048 // 256
|
||||||
, rsaKeySize: 2048 // 256
|
, rsaKeySize: 2048 // 256
|
||||||
|
, acmeChallengePrefix: '/.well-known/acme-challenge/';
|
||||||
};
|
};
|
||||||
Object.keys(module.exports.defaults).forEach(function (key) {
|
Object.keys(module.exports.defaults).forEach(function (key) {
|
||||||
module.exports.ACME[key] = module.exports.defaults[key];
|
module.exports.ACME[key] = module.exports.defaults[key];
|
||||||
});
|
});
|
||||||
Object.keys(ACME2).forEach(function (key) {
|
Object.keys(ACME2).forEach(function (key) {
|
||||||
module.exports.ACME[key] = ACME2[key];
|
module.exports.ACME[key] = ACME2[key];
|
||||||
module.exports.ACME.create = create;
|
|
||||||
});
|
});
|
||||||
|
module.exports.ACME.create = create;
|
||||||
|
|
12
node.js
12
node.js
|
@ -8,15 +8,13 @@
|
||||||
|
|
||||||
var ACME = module.exports.ACME = {};
|
var ACME = module.exports.ACME = {};
|
||||||
|
|
||||||
ACME.acmeChallengePrefix = '/.well-known/acme-challenge/';
|
ACME.challengePrefixes = {
|
||||||
ACME.acmeChallengeDnsPrefix = '_acme-challenge';
|
|
||||||
ACME.acmeChallengePrefixes = {
|
|
||||||
'http-01': '/.well-known/acme-challenge'
|
'http-01': '/.well-known/acme-challenge'
|
||||||
, 'dns-01': '_acme-challenge'
|
, 'dns-01': '_acme-challenge'
|
||||||
};
|
};
|
||||||
ACME.challengeTests = {
|
ACME.challengeTests = {
|
||||||
'http-01': function (me, auth) {
|
'http-01': function (me, auth) {
|
||||||
var url = 'http://' + auth.hostname + ACME.acmeChallengePrefixes['http-01'] + '/' + auth.token;
|
var url = 'http://' + auth.hostname + ACME.challengePrefixes['http-01'] + '/' + auth.token;
|
||||||
return me._request({ url: url }).then(function (resp) {
|
return me._request({ url: url }).then(function (resp) {
|
||||||
var err;
|
var err;
|
||||||
|
|
||||||
|
@ -32,7 +30,7 @@ ACME.challengeTests = {
|
||||||
, 'dns-01': function (me, auth) {
|
, 'dns-01': function (me, auth) {
|
||||||
return me._dig({
|
return me._dig({
|
||||||
type: 'TXT'
|
type: 'TXT'
|
||||||
, name: ACME.acmeChallengePrefixes['dns-01'] + '.' + auth.hostname
|
, name: ACME.challengePrefixes['dns-01'] + '.' + auth.hostname
|
||||||
}).then(function (ans) {
|
}).then(function (ans) {
|
||||||
var err;
|
var err;
|
||||||
|
|
||||||
|
@ -562,9 +560,7 @@ ACME.create = function create(me) {
|
||||||
if (!me) { me = {}; }
|
if (!me) { me = {}; }
|
||||||
//
|
//
|
||||||
me.debug = true;
|
me.debug = true;
|
||||||
me.acmeChallengePrefix = ACME.acmeChallengePrefix;
|
me.challengePrefixes = ACME.challengePrefixes;
|
||||||
me.acmeChallengeDnsPrefix = ACME.acmeChallengeDnsPrefix;
|
|
||||||
me.acmeChallengePrefixes = ACME.acmeChallengePrefixes;
|
|
||||||
me.RSA = me.RSA || require('rsa-compat').RSA;
|
me.RSA = me.RSA || require('rsa-compat').RSA;
|
||||||
me.request = me.request || require('request');
|
me.request = me.request || require('request');
|
||||||
me._dig = function (query) {
|
me._dig = function (query) {
|
||||||
|
|
|
@ -31,11 +31,11 @@ module.exports.run = function run(web, chType, email, accountKeypair, domainKeyp
|
||||||
console.log("");
|
console.log("");
|
||||||
|
|
||||||
if ('http-01' === opts.type) {
|
if ('http-01' === opts.type) {
|
||||||
pathname = opts.hostname + acme2.acmeChallengePrefixes['http-01'] + "/" + opts.token;
|
pathname = opts.hostname + acme2.challengePrefixes['http-01'] + "/" + opts.token;
|
||||||
console.log("Put the string '" + opts.keyAuthorization + "' into a file at '" + pathname + "'");
|
console.log("Put the string '" + opts.keyAuthorization + "' into a file at '" + pathname + "'");
|
||||||
console.log("echo '" + opts.keyAuthorization + "' > '" + pathname + "'");
|
console.log("echo '" + opts.keyAuthorization + "' > '" + pathname + "'");
|
||||||
} else if ('dns-01' === opts.type) {
|
} else if ('dns-01' === opts.type) {
|
||||||
pathname = acme2.acmeChallengeDnsPrefix + "." + opts.hostname.replace(/^\*\./, '');
|
pathname = acme2.challengePrefixes['dns-01'] + "." + opts.hostname.replace(/^\*\./, '');
|
||||||
console.log("Put the string '" + opts.dnsAuthorization + "' into the TXT record '" + pathname + "'");
|
console.log("Put the string '" + opts.dnsAuthorization + "' into the TXT record '" + pathname + "'");
|
||||||
console.log("ddig TXT " + pathname + " '" + opts.dnsAuthorization + "'");
|
console.log("ddig TXT " + pathname + " '" + opts.dnsAuthorization + "'");
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -33,11 +33,11 @@ module.exports.run = function run(web, chType, email, accountKeypair, domainKeyp
|
||||||
console.log("");
|
console.log("");
|
||||||
|
|
||||||
if ('http-01' === opts.type) {
|
if ('http-01' === opts.type) {
|
||||||
pathname = opts.hostname + acme2.acmeChallengePrefixes['http-01'] + "/" + opts.token;
|
pathname = opts.hostname + acme2.challengePrefixes['http-01'] + "/" + opts.token;
|
||||||
console.log("Put the string '" + opts.keyAuthorization + "' into a file at '" + pathname + "'");
|
console.log("Put the string '" + opts.keyAuthorization + "' into a file at '" + pathname + "'");
|
||||||
console.log("echo '" + opts.keyAuthorization + "' > '" + pathname + "'");
|
console.log("echo '" + opts.keyAuthorization + "' > '" + pathname + "'");
|
||||||
} else if ('dns-01' === opts.type) {
|
} else if ('dns-01' === opts.type) {
|
||||||
pathname = acme2.acmeChallengeDnsPrefix + "." + opts.hostname.replace(/^\*\./, '');;
|
pathname = acme2.challengePrefixes['dns-01'] + "." + opts.hostname.replace(/^\*\./, '');;
|
||||||
console.log("Put the string '" + opts.dnsAuthorization + "' into the TXT record '" + pathname + "'");
|
console.log("Put the string '" + opts.dnsAuthorization + "' into the TXT record '" + pathname + "'");
|
||||||
console.log("ddig TXT " + pathname + " '" + opts.dnsAuthorization + "'");
|
console.log("ddig TXT " + pathname + " '" + opts.dnsAuthorization + "'");
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Reference in New Issue