forked from root/acme.js
		
	closer to v1
This commit is contained in:
		
							parent
							
								
									69b624c632
								
							
						
					
					
						commit
						8af828a737
					
				
							
								
								
									
										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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user