Compare commits
	
		
			26 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 2fd9678ab5 | |||
|  | 7a6c2ae573 | ||
|  | 4758dc2bd2 | ||
| d28d82130c | |||
|  | 3a41c3006c | ||
| bfe1737b9b | |||
|  | 9172d4c98e | ||
|  | 530b25f691 | ||
|  | d85f4070f3 | ||
|  | 51bcc1f20a | ||
|  | f79c62032c | ||
|  | 3ed2d45d3d | ||
|  | d0e20a44cd | ||
|  | 10978ab99a | ||
|  | 72fb7b7c07 | ||
|  | 72646ced80 | ||
|  | 9f01021948 | ||
|  | f63070ce54 | ||
|  | 6126222e8f | ||
|  | 7288d14fac | ||
|  | 681c0edc71 | ||
|  | f350ae44c1 | ||
|  | 6b1b168e5a | ||
|  | a97c5933d6 | ||
|  | a8b9817415 | ||
|  | fe635a965c | 
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -29,3 +29,5 @@ build/Release | |||||||
| # Dependency directory | # Dependency directory | ||||||
| # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git | ||||||
| node_modules | node_modules | ||||||
|  | .idea | ||||||
|  | .DS_Store | ||||||
|  | |||||||
							
								
								
									
										2
									
								
								AUTHORS
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								AUTHORS
									
									
									
									
									
								
							| @ -1,3 +1,3 @@ | |||||||
| ISRG | ISRG | ||||||
| Anatol Sommer <anatol@anatol.at> | Anatol Sommer <anatol@anatol.at> | ||||||
| AJ ONeal <aj@daplie.com> (https://daplie.com/) | AJ ONeal <coolaj86@gmail.com> (https://coolaj86.com/) | ||||||
|  | |||||||
							
								
								
									
										29
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										29
									
								
								README.md
									
									
									
									
									
								
							| @ -1,6 +1,6 @@ | |||||||
| # le-acme-core | # le-acme-core | ||||||
| 
 | 
 | ||||||
| Looking for **letiny-core**? Check the [v1.x branch](https://github.com/Daplie/le-acme-core/tree/v1.x). | Looking for **letiny-core**? Check the [v1.x branch](https://git.coolaj86.com/coolaj86/le-acme-core.js/tree/v1.x). | ||||||
| 
 | 
 | ||||||
| <!-- rename to le-acme-core --> | <!-- rename to le-acme-core --> | ||||||
| 
 | 
 | ||||||
| @ -13,14 +13,17 @@ Supports all of: | |||||||
|   * browser WebCrypto (not implemented, but... Let's Encrypt over WebRTC anyone?) |   * browser WebCrypto (not implemented, but... Let's Encrypt over WebRTC anyone?) | ||||||
|   * any javascript implementation |   * any javascript implementation | ||||||
| 
 | 
 | ||||||
|  | # NEW: Let's Encrypt v2 Support | ||||||
|  | Let's Encrypt v2 (aka ACME v2 or ACME draft 11) is available in [acme-v2.js](https://git.coolaj86.com/coolaj86/acme-v2.js) | ||||||
|  | 
 | ||||||
| ### These aren't the droids you're looking for | ### These aren't the droids you're looking for | ||||||
| 
 | 
 | ||||||
| This is a library / framework for building letsencrypt clients. | This is a library / framework for building letsencrypt clients. | ||||||
| You probably want one of these pre-built clients instead: | You probably want one of these pre-built clients instead: | ||||||
| 
 | 
 | ||||||
|   * [`letsencrypt`](https://github.com/Daplie/node-letsencrypt) (compatible with the official client) |   * [`letsencrypt`](https://git.coolaj86.com/coolaj86/greenlock.js) (compatible with the official client) | ||||||
|   * `letiny` (lightweight client cli) |   * `letiny` (lightweight client cli) | ||||||
|   * [`letsencrypt-express`](https://github.com/Daplie/letsencrypt-express) (automatic https for express) |   * [`letsencrypt-express`](https://git.coolaj86.com/coolaj86/greenlock-express.js) (automatic https for express) | ||||||
| 
 | 
 | ||||||
| ## Install & Usage: | ## Install & Usage: | ||||||
| 
 | 
 | ||||||
| @ -42,11 +45,9 @@ For **testing** and **development**, you can also inject the dependencies you wa | |||||||
| 'use strict'; | 'use strict'; | ||||||
| 
 | 
 | ||||||
| var ACME = require('le-acme-core').ACME.create({ | var ACME = require('le-acme-core').ACME.create({ | ||||||
|   request: require('request') |  | ||||||
| , RSA: require('rsa-compat').RSA | , RSA: require('rsa-compat').RSA | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| // now uses node `request` (could also use jQuery or Angular in the browser) |  | ||||||
| ACME.getAcmeUrls(discoveryUrl, function (err, urls) { | ACME.getAcmeUrls(discoveryUrl, function (err, urls) { | ||||||
|   console.log(urls); |   console.log(urls); | ||||||
| }); | }); | ||||||
| @ -81,7 +82,7 @@ Install le-acme-core and its dependencies. **Note**: it's okay if you're on wind | |||||||
| and `ursa` fails to compile. It'll still work. | and `ursa` fails to compile. It'll still work. | ||||||
| 
 | 
 | ||||||
| ```bash | ```bash | ||||||
| git clone https://github.com/Daplie/le-acme-core.git ~/le-acme-core | git clone https://git.coolaj86.com/coolaj86/le-acme-core.js.git ~/le-acme-core | ||||||
| pushd ~/le-acme-core | pushd ~/le-acme-core | ||||||
| 
 | 
 | ||||||
| npm install | npm install | ||||||
| @ -155,7 +156,7 @@ ACME.Acme                               // Signs requests with JWK | |||||||
| 
 | 
 | ||||||
| Below you'll find a stripped-down example. You can see the full example in the example folder. | Below you'll find a stripped-down example. You can see the full example in the example folder. | ||||||
| 
 | 
 | ||||||
| * [example/](https://github.com/Daplie/le-acme-core/blob/master/example/) | * [example/](https://git.coolaj86.com/coolaj86/le-acme-core.js/blob/master/example/) | ||||||
| 
 | 
 | ||||||
| #### Register Account & Domain | #### Register Account & Domain | ||||||
| 
 | 
 | ||||||
| @ -225,7 +226,7 @@ function runDemo() { | |||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| **But wait**, there's more! | **But wait**, there's more! | ||||||
| See [example/letsencrypt.js](https://github.com/Daplie/le-acme-core/blob/master/example/letsencrypt.js) | See [example/letsencrypt.js](https://git.coolaj86.com/coolaj86/le-acme-core.js/blob/master/example/letsencrypt.js) | ||||||
| 
 | 
 | ||||||
| #### Run a Server on 80, 443, and 5001 (https/tls) | #### Run a Server on 80, 443, and 5001 (https/tls) | ||||||
| 
 | 
 | ||||||
| @ -238,7 +239,7 @@ var http = require('http'); | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| var LeCore = deps.LeCore; | var LeCore = deps.LeCore; | ||||||
| var httpsOptions = deps.httpsOptions; | var tlsOptions = deps.tlsOptions; | ||||||
| var challengeStore = deps.challengeStore; | var challengeStore = deps.challengeStore; | ||||||
| var certStore = deps.certStore; | var certStore = deps.certStore; | ||||||
| 
 | 
 | ||||||
| @ -263,7 +264,7 @@ function acmeResponder(req, res) { | |||||||
| // | // | ||||||
| // Server | // Server | ||||||
| // | // | ||||||
| https.createServer(httpsOptions, acmeResponder).listen(5001, function () { | https.createServer(tlsOptions, acmeResponder).listen(5001, function () { | ||||||
|   console.log('Listening https on', this.address()); |   console.log('Listening https on', this.address()); | ||||||
| }); | }); | ||||||
| http.createServer(acmeResponder).listen(80, function () { | http.createServer(acmeResponder).listen(80, function () { | ||||||
| @ -272,7 +273,7 @@ http.createServer(acmeResponder).listen(80, function () { | |||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| **But wait**, there's more! | **But wait**, there's more! | ||||||
| See [example/serve.js](https://github.com/Daplie/le-acme-core/blob/master/example/serve.js) | See [example/serve.js](https://git.coolaj86.com/coolaj86/le-acme-core.js/blob/master/example/serve.js) | ||||||
| 
 | 
 | ||||||
| #### Put some storage in place | #### Put some storage in place | ||||||
| 
 | 
 | ||||||
| @ -313,14 +314,14 @@ var certStore = { | |||||||
| **But wait**, there's more! | **But wait**, there's more! | ||||||
| See | See | ||||||
| 
 | 
 | ||||||
| * [example/challenge-store.js](https://github.com/Daplie/le-acme-core/blob/master/challenge-store.js) | * [example/challenge-store.js](https://git.coolaj86.com/coolaj86/le-acme-core.js/blob/master/challenge-store.js) | ||||||
| * [example/cert-store.js](https://github.com/Daplie/le-acme-core/blob/master/cert-store.js) | * [example/cert-store.js](https://git.coolaj86.com/coolaj86/le-acme-core.js/blob/master/cert-store.js) | ||||||
| 
 | 
 | ||||||
| ## Authors | ## Authors | ||||||
| 
 | 
 | ||||||
|   * ISRG |   * ISRG | ||||||
|   * Anatol Sommer  (https://github.com/anatolsommer) |   * Anatol Sommer  (https://github.com/anatolsommer) | ||||||
|   * AJ ONeal <aj@daplie.com> (https://daplie.com) |   * AJ ONeal <coolaj86@gmail.com> (https://coolaj86.com) | ||||||
| 
 | 
 | ||||||
| ## Licence | ## Licence | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,6 +1,6 @@ | |||||||
| /*! | /*! | ||||||
|  * letiny-core |  * letiny-core | ||||||
|  * Copyright(c) 2015 AJ ONeal <aj@daplie.com> https://daplie.com
 |  * Copyright(c) 2015 AJ ONeal <coolaj86@gmail.com> https://coolaj86.com
 | ||||||
|  * Apache-2.0 OR MIT (and hence also MPL 2.0) |  * Apache-2.0 OR MIT (and hence also MPL 2.0) | ||||||
| */ | */ | ||||||
| 'use strict'; | 'use strict'; | ||||||
|  | |||||||
| @ -1,6 +1,6 @@ | |||||||
| /*! | /*! | ||||||
|  * letiny-core |  * letiny-core | ||||||
|  * Copyright(c) 2015 AJ ONeal <aj@daplie.com> https://daplie.com
 |  * Copyright(c) 2015 AJ ONeal <coolaj86@gmail.com> https://coolaj86.com
 | ||||||
|  * Apache-2.0 OR MIT (and hence also MPL 2.0) |  * Apache-2.0 OR MIT (and hence also MPL 2.0) | ||||||
| */ | */ | ||||||
| 'use strict'; | 'use strict'; | ||||||
|  | |||||||
| @ -1,12 +1,12 @@ | |||||||
| /*! | /*! | ||||||
|  * letiny-core |  * letiny-core | ||||||
|  * Copyright(c) 2015 AJ ONeal <aj@daplie.com> https://daplie.com
 |  * Copyright(c) 2015 AJ ONeal <coolaj86@gmail.com> https://coolaj86.com
 | ||||||
|  * Apache-2.0 OR MIT (and hence also MPL 2.0) |  * Apache-2.0 OR MIT (and hence also MPL 2.0) | ||||||
| */ | */ | ||||||
| 'use strict'; | 'use strict'; | ||||||
| 
 | 
 | ||||||
| //var LeCore = require('letiny-core');
 | //var LeCore = require('letiny-core');
 | ||||||
| var LeCore = require('../'); | var LeCore = require('../').ACME.create(); | ||||||
| 
 | 
 | ||||||
| var email = process.argv[2] || 'user@example.com';    // CHANGE TO YOUR EMAIL
 | var email = process.argv[2] || 'user@example.com';    // CHANGE TO YOUR EMAIL
 | ||||||
| var domains = [process.argv[3] || 'example.com'];     // CHANGE TO YOUR DOMAIN
 | var domains = [process.argv[3] || 'example.com'];     // CHANGE TO YOUR DOMAIN
 | ||||||
| @ -17,8 +17,8 @@ var certStore = require('./cert-store'); | |||||||
| var serve = require('./serve'); | var serve = require('./serve'); | ||||||
| var closer; | var closer; | ||||||
| 
 | 
 | ||||||
| var accountPrivateKeyPem = null; | var accountKeypair = null; | ||||||
| var domainPrivateKeyPem = null; | var domainKeypair = null; | ||||||
| var acmeUrls = null; | var acmeUrls = null; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @ -44,14 +44,14 @@ function init() { | |||||||
| 
 | 
 | ||||||
| function getPrivateKeys(cb) { | function getPrivateKeys(cb) { | ||||||
|     console.log('Generating Account Keypair'); |     console.log('Generating Account Keypair'); | ||||||
|     console.log("(Note: if you're using forge and not ursa, this will take a long time"); |     const RSA = require('rsa-compat').RSA; | ||||||
|     LeCore.leCrypto.generateRsaKeypair(2048, 65537, function (err, pems) { |     RSA.generateKeypair(2048, 65537, {}, function (err, pems) { | ||||||
| 
 | 
 | ||||||
|         accountPrivateKeyPem = pems.privateKeyPem; |         accountKeypair = pems; | ||||||
|         console.log('Generating Domain Keypair'); |         console.log('Generating Domain Keypair'); | ||||||
|         LeCore.leCrypto.generateRsaKeypair(2048, 65537, function (err, pems) { |         RSA.generateKeypair(2048, 65537, {}, function (err, pems2) { | ||||||
| 
 | 
 | ||||||
|             domainPrivateKeyPem = pems.privateKeyPem; |             domainKeypair = pems2; | ||||||
|             cb(); |             cb(); | ||||||
|         }); |         }); | ||||||
|     }); |     }); | ||||||
| @ -62,7 +62,7 @@ function runDemo() { | |||||||
|     LeCore.registerNewAccount( |     LeCore.registerNewAccount( | ||||||
|         { newRegUrl: acmeUrls.newReg |         { newRegUrl: acmeUrls.newReg | ||||||
|         , email: email |         , email: email | ||||||
|         , accountPrivateKeyPem: accountPrivateKeyPem |         , accountKeypair: accountKeypair | ||||||
|         , agreeToTerms: function (tosUrl, done) { |         , agreeToTerms: function (tosUrl, done) { | ||||||
| 
 | 
 | ||||||
|               // agree to the exact version of these terms
 |               // agree to the exact version of these terms
 | ||||||
| @ -82,8 +82,8 @@ function runDemo() { | |||||||
|                 { newAuthzUrl: acmeUrls.newAuthz |                 { newAuthzUrl: acmeUrls.newAuthz | ||||||
|                 , newCertUrl: acmeUrls.newCert |                 , newCertUrl: acmeUrls.newCert | ||||||
| 
 | 
 | ||||||
|                 , domainPrivateKeyPem: domainPrivateKeyPem |                 , domainKeypair: domainKeypair | ||||||
|                 , accountPrivateKeyPem: accountPrivateKeyPem |                 , accountKeypair: accountKeypair | ||||||
|                 , domains: domains |                 , domains: domains | ||||||
| 
 | 
 | ||||||
|                 , setChallenge: challengeStore.set |                 , setChallenge: challengeStore.set | ||||||
| @ -111,8 +111,7 @@ function runDemo() { | |||||||
| //
 | //
 | ||||||
| closer = serve.init({ | closer = serve.init({ | ||||||
|   LeCore: LeCore |   LeCore: LeCore | ||||||
|   // needs a default key and cert chain, anything will do
 | , tlsOptions: {} | ||||||
| , httpsOptions: require('localhost.daplie.com-certificates') |  | ||||||
| , challengeStore: challengeStore | , challengeStore: challengeStore | ||||||
| , certStore: certStore | , certStore: certStore | ||||||
| }); | }); | ||||||
|  | |||||||
| @ -1,6 +1,6 @@ | |||||||
| /*! | /*! | ||||||
|  * letiny-core |  * letiny-core | ||||||
|  * Copyright(c) 2015 AJ ONeal <aj@daplie.com> https://daplie.com
 |  * Copyright(c) 2015 AJ ONeal <coolaj86@gmail.com> https://coolaj86.com
 | ||||||
|  * Apache-2.0 OR MIT (and hence also MPL 2.0) |  * Apache-2.0 OR MIT (and hence also MPL 2.0) | ||||||
| */ | */ | ||||||
| 'use strict'; | 'use strict'; | ||||||
| @ -15,7 +15,7 @@ module.exports.init = function (deps) { | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|   var LeCore = deps.LeCore; |   var LeCore = deps.LeCore; | ||||||
|   var httpsOptions = deps.httpsOptions; |   var tlsOptions = deps.tlsOptions || deps.httpsOptions; | ||||||
|   var challengeStore = deps.challengeStore; |   var challengeStore = deps.challengeStore; | ||||||
|   var certStore = deps.certStore; |   var certStore = deps.certStore; | ||||||
| 
 | 
 | ||||||
| @ -63,11 +63,11 @@ module.exports.init = function (deps) { | |||||||
|   //
 |   //
 | ||||||
|   // Server
 |   // Server
 | ||||||
|   //
 |   //
 | ||||||
|   httpsOptions.SNICallback = certGetter; |   tlsOptions.SNICallback = certGetter; | ||||||
|   https.createServer(httpsOptions, acmeResponder).listen(443, function () { |   https.createServer(tlsOptions, acmeResponder).listen(443, function () { | ||||||
|     console.log('Listening https on', this.address()); |     console.log('Listening https on', this.address()); | ||||||
|   }); |   }); | ||||||
|   https.createServer(httpsOptions, acmeResponder).listen(5001, function () { |   https.createServer(tlsOptions, acmeResponder).listen(5001, function () { | ||||||
|     console.log('Listening https on', this.address()); |     console.log('Listening https on', this.address()); | ||||||
|   }); |   }); | ||||||
|   http.createServer(acmeResponder).listen(80, function () { |   http.createServer(acmeResponder).listen(80, function () { | ||||||
|  | |||||||
| @ -8,10 +8,10 @@ | |||||||
| 
 | 
 | ||||||
| module.exports.create = function (deps) { | module.exports.create = function (deps) { | ||||||
| 
 | 
 | ||||||
|   var NOOP=function () { |   var NOOP = function () { | ||||||
|   }; |   }; | ||||||
|   var log=NOOP; |   var log = NOOP; | ||||||
|   var request=require('request'); |   var acmeRequest = deps.acmeRequest; | ||||||
|   var RSA = deps.RSA; |   var RSA = deps.RSA; | ||||||
|   var generateSignature = RSA.signJws; |   var generateSignature = RSA.signJws; | ||||||
| 
 | 
 | ||||||
| @ -30,7 +30,7 @@ module.exports.create = function (deps) { | |||||||
|   Acme.prototype.getNonce=function(url, cb) { |   Acme.prototype.getNonce=function(url, cb) { | ||||||
|     var self=this; |     var self=this; | ||||||
| 
 | 
 | ||||||
|     request.head({ |     acmeRequest.create().head({ | ||||||
|       url:url, |       url:url, | ||||||
|     }, function(err, res/*, body*/) { |     }, function(err, res/*, body*/) { | ||||||
|       if (err) { |       if (err) { | ||||||
| @ -73,10 +73,10 @@ module.exports.create = function (deps) { | |||||||
| 
 | 
 | ||||||
| //process.exit(1);
 | //process.exit(1);
 | ||||||
| //return;
 | //return;
 | ||||||
|     return request.post({ |     return acmeRequest.create().post({ | ||||||
|       url:url, |       url: url | ||||||
|       body:signed, |     , body: signed | ||||||
|       encoding:null |     , encoding: null | ||||||
|     }, function(err, res, body) { |     }, function(err, res, body) { | ||||||
|       var parsed; |       var parsed; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,12 +1,12 @@ | |||||||
| /*! | /*! | ||||||
|  * letiny-core |  * letiny-core | ||||||
|  * Copyright(c) 2015 AJ ONeal <aj@daplie.com> https://daplie.com
 |  * Copyright(c) 2015 AJ ONeal <coolaj86@gmail.com> https://coolaj86.com
 | ||||||
|  * Apache-2.0 OR MIT (and hence also MPL 2.0) |  * Apache-2.0 OR MIT (and hence also MPL 2.0) | ||||||
| */ | */ | ||||||
| 'use strict'; | 'use strict'; | ||||||
| 
 | 
 | ||||||
| module.exports.create = function (deps) { | module.exports.create = function (deps) { | ||||||
|   var request = deps.request; |   var acmeRequest = deps.acmeRequest; | ||||||
|   var knownUrls = deps.LeCore.knownEndpoints; |   var knownUrls = deps.LeCore.knownEndpoints; | ||||||
| 
 | 
 | ||||||
|   function getAcmeUrls(acmeDiscoveryUrl, cb) { |   function getAcmeUrls(acmeDiscoveryUrl, cb) { | ||||||
| @ -15,7 +15,7 @@ module.exports.create = function (deps) { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // TODO check response header on request for cache time
 |     // TODO check response header on request for cache time
 | ||||||
|     return request({ |     return acmeRequest.create()({ | ||||||
|       url: acmeDiscoveryUrl |       url: acmeDiscoveryUrl | ||||||
|     , encoding: 'utf8' |     , encoding: 'utf8' | ||||||
|     }, function (err, resp) { |     }, function (err, resp) { | ||||||
| @ -39,11 +39,6 @@ module.exports.create = function (deps) { | |||||||
|         } |         } | ||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
|       if (4 !== Object.keys(data).length) { |  | ||||||
|         console.warn("This Let's Encrypt / ACME server has been updated with urls that this client doesn't understand"); |  | ||||||
|         console.warn(data); |  | ||||||
|       } |  | ||||||
| 
 |  | ||||||
|       if (!knownUrls.every(function (url) { |       if (!knownUrls.every(function (url) { | ||||||
|         return data[url]; |         return data[url]; | ||||||
|       })) { |       })) { | ||||||
| @ -56,6 +51,7 @@ module.exports.create = function (deps) { | |||||||
|       , newCert: data['new-cert'] |       , newCert: data['new-cert'] | ||||||
|       , newReg: data['new-reg'] |       , newReg: data['new-reg'] | ||||||
|       , revokeCert: data['revoke-cert'] |       , revokeCert: data['revoke-cert'] | ||||||
|  |       , keyChange: data['key-change'] | ||||||
|       }); |       }); | ||||||
|     }); |     }); | ||||||
|   } |   } | ||||||
|  | |||||||
| @ -24,7 +24,7 @@ function certBufferToPem(cert) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| module.exports.create = function (deps) { | module.exports.create = function (deps) { | ||||||
|   var request = deps.request; |   var acmeRequest = deps.acmeRequest; | ||||||
|   var Acme = deps.Acme; |   var Acme = deps.Acme; | ||||||
|   var RSA = deps.RSA; |   var RSA = deps.RSA; | ||||||
| 
 | 
 | ||||||
| @ -193,7 +193,7 @@ module.exports.create = function (deps) { | |||||||
| 
 | 
 | ||||||
|       if (authz.status==='pending') { |       if (authz.status==='pending') { | ||||||
|         setTimeout(function() { |         setTimeout(function() { | ||||||
|           request({ |           acmeRequest.create()({ | ||||||
|             method: 'GET' |             method: 'GET' | ||||||
|           , url: state.authorizationUrl |           , url: state.authorizationUrl | ||||||
|           }, function(err, res, body) { |           }, function(err, res, body) { | ||||||
| @ -278,7 +278,7 @@ module.exports.create = function (deps) { | |||||||
| 
 | 
 | ||||||
|       state.certificate=body; |       state.certificate=body; | ||||||
|       certUrl=res.headers.location; |       certUrl=res.headers.location; | ||||||
|       request({ |       acmeRequest.create()({ | ||||||
|         method: 'GET' |         method: 'GET' | ||||||
|       , url: certUrl |       , url: certUrl | ||||||
|       , encoding: null |       , encoding: null | ||||||
| @ -310,7 +310,7 @@ module.exports.create = function (deps) { | |||||||
| 
 | 
 | ||||||
|     function downloadIssuerCert(links) { |     function downloadIssuerCert(links) { | ||||||
|       log('Requesting issuer certificate...'); |       log('Requesting issuer certificate...'); | ||||||
|       request({ |       acmeRequest.create()({ | ||||||
|         method: 'GET' |         method: 'GET' | ||||||
|       , url: links.up |       , url: links.up | ||||||
|       , encoding: null |       , encoding: null | ||||||
|  | |||||||
							
								
								
									
										72
									
								
								lib/le-acme-request.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								lib/le-acme-request.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,72 @@ | |||||||
|  | /*! | ||||||
|  |  * le-acme-core | ||||||
|  |  * Author: Kelly Johnson | ||||||
|  |  * Copyright 2017 | ||||||
|  |  * Apache-2.0 OR MIT (and hence also MPL 2.0) | ||||||
|  |  */ | ||||||
|  | 'use strict'; | ||||||
|  | 
 | ||||||
|  | const request = require('request'); | ||||||
|  | const pkgJSON = require('../package.json'); | ||||||
|  | const version = pkgJSON.version; | ||||||
|  | const os = require('os'); | ||||||
|  | 
 | ||||||
|  | const uaDefaults = { | ||||||
|  |   pkg: `Greenlock/${version}` | ||||||
|  |   , os: ` (${os.type()}; ${process.arch} ${os.platform()} ${os.release()})` | ||||||
|  |   , node: ` Node.js/${process.version}` | ||||||
|  |   , user: '' | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | let currentUAProps; | ||||||
|  | 
 | ||||||
|  | function getUaString() { | ||||||
|  |   let userAgent = ''; | ||||||
|  |   for (let key in currentUAProps) { | ||||||
|  |     userAgent += currentUAProps[key]; | ||||||
|  |   } | ||||||
|  |   return userAgent.trim(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function getRequest() { | ||||||
|  |   return request.defaults({ | ||||||
|  |     headers: { | ||||||
|  |       'User-Agent': getUaString() | ||||||
|  |     } | ||||||
|  |   }); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function resetUa() { | ||||||
|  |   currentUAProps = {}; | ||||||
|  |   for (let key in uaDefaults) { | ||||||
|  |     currentUAProps[key] = uaDefaults[key]; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function addUaString(string) { | ||||||
|  |   currentUAProps.user += ` ${string}`; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function omitUaProperties(opts) { | ||||||
|  |   if (opts.all) { | ||||||
|  |     currentUAProps = {}; | ||||||
|  |   } else { | ||||||
|  |     for (let key in opts) { | ||||||
|  |       currentUAProps[key] = ''; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Set our UA to begin with
 | ||||||
|  | resetUa(); | ||||||
|  | 
 | ||||||
|  | module.exports = { | ||||||
|  |   create: function create() { | ||||||
|  |     // get deps and modify here if need be
 | ||||||
|  |     return getRequest(); | ||||||
|  |   } | ||||||
|  |   , addUaString: addUaString | ||||||
|  |   , omitUaProperties: omitUaProperties | ||||||
|  |   , resetUa: resetUa | ||||||
|  |   , getUaString: getUaString | ||||||
|  | }; | ||||||
| @ -8,7 +8,7 @@ | |||||||
| 'use strict'; | 'use strict'; | ||||||
| module.exports.create = function (deps) { | module.exports.create = function (deps) { | ||||||
|   var NOOP=function () {}, log=NOOP; |   var NOOP=function () {}, log=NOOP; | ||||||
|   var request=deps.request; |   var acmeRequest = deps.acmeRequest; | ||||||
|   var RSA = deps.RSA; |   var RSA = deps.RSA; | ||||||
|   var Acme = deps.Acme; |   var Acme = deps.Acme; | ||||||
| 
 | 
 | ||||||
| @ -24,7 +24,11 @@ module.exports.create = function (deps) { | |||||||
|     function getTerms(err, res) { |     function getTerms(err, res) { | ||||||
|       var links; |       var links; | ||||||
| 
 | 
 | ||||||
|       if (err || Math.floor(res.statusCode/100)!==2) { |       if (err) { | ||||||
|  |         return handleErr(err, 'Registration request failed: ' + err.toString()); | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       if (Math.floor(res.statusCode/100)!==2) { | ||||||
|         return handleErr(err, 'Registration request failed: ' + res.body.toString('utf8')); |         return handleErr(err, 'Registration request failed: ' + res.body.toString('utf8')); | ||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
| @ -51,7 +55,7 @@ module.exports.create = function (deps) { | |||||||
|           state.agreeTerms = agree; |           state.agreeTerms = agree; | ||||||
|           state.termsUrl=links['terms-of-service']; |           state.termsUrl=links['terms-of-service']; | ||||||
|           log(state.termsUrl); |           log(state.termsUrl); | ||||||
|           request.get(state.termsUrl, getAgreement); |           acmeRequest.create().get(state.termsUrl, getAgreement); | ||||||
|         }); |         }); | ||||||
|       } else { |       } else { | ||||||
|         cb(null, null); |         cb(null, null); | ||||||
|  | |||||||
							
								
								
									
										7
									
								
								node.js
									
									
									
									
									
								
							
							
						
						
									
										7
									
								
								node.js
									
									
									
									
									
								
							| @ -1,6 +1,6 @@ | |||||||
| /*! | /*! | ||||||
|  * letiny-core |  * letiny-core | ||||||
|  * Copyright(c) 2015 AJ ONeal <aj@daplie.com> https://daplie.com
 |  * Copyright(c) 2015 AJ ONeal <coolaj86@gmail.com> https://coolaj86.com
 | ||||||
|  * Apache-2.0 OR MIT (and hence also MPL 2.0) |  * Apache-2.0 OR MIT (and hence also MPL 2.0) | ||||||
| */ | */ | ||||||
| 'use strict'; | 'use strict'; | ||||||
| @ -9,7 +9,7 @@ var defaults = { | |||||||
|   productionServerUrl:    'https://acme-v01.api.letsencrypt.org/directory' |   productionServerUrl:    'https://acme-v01.api.letsencrypt.org/directory' | ||||||
| , stagingServerUrl:       'https://acme-staging.api.letsencrypt.org/directory' | , stagingServerUrl:       'https://acme-staging.api.letsencrypt.org/directory' | ||||||
| , acmeChallengePrefix:    '/.well-known/acme-challenge/' | , acmeChallengePrefix:    '/.well-known/acme-challenge/' | ||||||
| , knownEndpoints:         [ 'new-authz', 'new-cert', 'new-reg', 'revoke-cert' ] | , knownEndpoints:         [ 'new-authz', 'new-cert', 'new-reg', 'revoke-cert', 'key-change' ] | ||||||
| , challengeType:          'http-01' | , challengeType:          'http-01' | ||||||
| , rsaKeySize:             2048 | , rsaKeySize:             2048 | ||||||
| }; | }; | ||||||
| @ -24,10 +24,11 @@ function create(deps) { | |||||||
|   }); |   }); | ||||||
| 
 | 
 | ||||||
|   deps.RSA = deps.RSA || require('rsa-compat').RSA; |   deps.RSA = deps.RSA || require('rsa-compat').RSA; | ||||||
|   deps.request = deps.request || require('request'); |   deps.acmeRequest = require('./lib/le-acme-request'); | ||||||
|   deps.Acme = require('./lib/acme-client').create(deps); |   deps.Acme = require('./lib/acme-client').create(deps); | ||||||
| 
 | 
 | ||||||
|   deps.LeCore.Acme = deps.Acme; |   deps.LeCore.Acme = deps.Acme; | ||||||
|  |   deps.LeCore.acmeRequest = deps.acmeRequest; | ||||||
|   deps.LeCore.getAcmeUrls = require('./lib/get-acme-urls').create(deps); |   deps.LeCore.getAcmeUrls = require('./lib/get-acme-urls').create(deps); | ||||||
|   deps.LeCore.registerNewAccount = require('./lib/register-new-account').create(deps); |   deps.LeCore.registerNewAccount = require('./lib/register-new-account').create(deps); | ||||||
|   deps.LeCore.getCertificate = require('./lib/get-certificate').create(deps); |   deps.LeCore.getCertificate = require('./lib/get-certificate').create(deps); | ||||||
|  | |||||||
							
								
								
									
										19
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								package.json
									
									
									
									
									
								
							| @ -1,6 +1,6 @@ | |||||||
| { | { | ||||||
|   "name": "le-acme-core", |   "name": "le-acme-core", | ||||||
|   "version": "2.0.7", |   "version": "2.1.4", | ||||||
|   "description": "A framework for building letsencrypt clients, forked from letiny", |   "description": "A framework for building letsencrypt clients, forked from letiny", | ||||||
|   "main": "node.js", |   "main": "node.js", | ||||||
|   "browser": "browser.js", |   "browser": "browser.js", | ||||||
| @ -8,18 +8,15 @@ | |||||||
|     "example": "example", |     "example": "example", | ||||||
|     "test": "test" |     "test": "test" | ||||||
|   }, |   }, | ||||||
|   "scripts": { |  | ||||||
|     "test": "node example/letsencrypt.js" |  | ||||||
|   }, |  | ||||||
|   "repository": { |   "repository": { | ||||||
|     "type": "git", |     "type": "git", | ||||||
|     "url": "git+https://github.com/Daplie/le-acme-core.git" |     "url": "git+https://git.coolaj86.com/coolaj86/le-acme-core.js.git" | ||||||
|   }, |   }, | ||||||
|   "license": "MPL-2.0", |   "license": "MPL-2.0", | ||||||
|   "bugs": { |   "bugs": { | ||||||
|     "url": "https://github.com/Daplie/le-acme-core/issues" |     "url": "https://git.coolaj86.com/coolaj86/le-acme-core.js/issues" | ||||||
|   }, |   }, | ||||||
|   "homepage": "https://github.com/Daplie/le-acme-core#readme", |   "homepage": "https://git.coolaj86.com/coolaj86/le-acme-core.js#readme", | ||||||
|   "keywords": [ |   "keywords": [ | ||||||
|     "le-acme", |     "le-acme", | ||||||
|     "le-acme-", |     "le-acme-", | ||||||
| @ -33,6 +30,12 @@ | |||||||
|   ], |   ], | ||||||
|   "dependencies": { |   "dependencies": { | ||||||
|     "request": "^2.74.0", |     "request": "^2.74.0", | ||||||
|     "rsa-compat": "^1.2.7" |     "rsa-compat": "^1.3.2" | ||||||
|  |   }, | ||||||
|  |   "devDependencies": { | ||||||
|  |     "better-assert": "^1.0.2", | ||||||
|  |     "chai": "^3.5.0", | ||||||
|  |     "chai-string": "^1.3.0", | ||||||
|  |     "request-debug": "^0.2.0" | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  | |||||||
							
								
								
									
										74
									
								
								test/test-request.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								test/test-request.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,74 @@ | |||||||
|  | /*! | ||||||
|  |  * le-acme-core | ||||||
|  |  * Author: Kelly Johnson | ||||||
|  |  * Copyright 2017 | ||||||
|  |  * Apache-2.0 OR MIT (and hence also MPL 2.0) | ||||||
|  |  */ | ||||||
|  | 'use strict'; | ||||||
|  | 
 | ||||||
|  | const acmeRequest = require('../lib/le-acme-request'); | ||||||
|  | const debugRequest = require('request-debug'); | ||||||
|  | const chai = require('chai'); | ||||||
|  | chai.use(require('chai-string')); | ||||||
|  | const expect = chai.expect; | ||||||
|  | 
 | ||||||
|  | const productId = 'Greenlock'; | ||||||
|  | const UA = 'User-Agent'; | ||||||
|  | 
 | ||||||
|  | function checkRequest(req, done, tester) { | ||||||
|  |   debugRequest(req, function dbg(type, data, r) { | ||||||
|  |     if (type !== 'request') return;  // Only interested in the request
 | ||||||
|  |     expect(data.headers).to.have.property(UA); | ||||||
|  |     let uaString = data.headers[UA]; | ||||||
|  |     tester(uaString); | ||||||
|  |     req.stopDebugging(); | ||||||
|  |     done(); | ||||||
|  |   }); | ||||||
|  |   req('http://www.google.com', function (error, response, body) { | ||||||
|  |   }); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | describe('le-acme-request', function () { | ||||||
|  | 
 | ||||||
|  |   beforeEach(function () { | ||||||
|  |     acmeRequest.resetUa(); | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   it('should build User-Agent string', function () { | ||||||
|  |     let uaString = acmeRequest.getUaString(); | ||||||
|  |     expect(uaString).to.startsWith(productId); | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   it('should have proper User-Agent in request', function (done) { | ||||||
|  |     let request = acmeRequest.create(); | ||||||
|  |     checkRequest(request, done, function (uaString) { | ||||||
|  |       expect(uaString).to.startsWith(productId); | ||||||
|  |     }); | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   it('should add custom string to User Agent', function (done) { | ||||||
|  |     let testStr = 'check it'; | ||||||
|  |     acmeRequest.addUaString(testStr); | ||||||
|  |     let request = acmeRequest.create(); | ||||||
|  |     checkRequest(request, done, function (uaString) { | ||||||
|  |       // Added space to ensure str was properly appended
 | ||||||
|  |       expect(uaString).to.endsWith(` ${testStr}`); | ||||||
|  |     }); | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   it('should remove all items from User Agent', function (done) { | ||||||
|  |     acmeRequest.omitUaProperties({all: true}); | ||||||
|  |     let request = acmeRequest.create(); | ||||||
|  |     checkRequest(request, done, function (uaString) { | ||||||
|  |       expect(uaString).to.be.empty; | ||||||
|  |     }); | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   it('should remove one item from User Agent', function (done) { | ||||||
|  |     acmeRequest.omitUaProperties({pkg: true}); | ||||||
|  |     const request = acmeRequest.create(); | ||||||
|  |     checkRequest(request, done, function (uaString) { | ||||||
|  |       expect(uaString).to.not.have.string(productId); | ||||||
|  |     }); | ||||||
|  |   }); | ||||||
|  | }); | ||||||
| @ -1,5 +1,5 @@ | |||||||
| var forge=require('node-forge'), assert=require('better-assert'), fs=require('fs'), | var forge=require('node-forge'), assert=require('better-assert'), fs=require('fs'), | ||||||
|   letiny=require('../lib/client'), config=require('./config.json'), |   letiny=require('../'), config=require('./config.json'), | ||||||
|   res, newReg='https://acme-staging.api.letsencrypt.org/acme/new-reg'; |   res, newReg='https://acme-staging.api.letsencrypt.org/acme/new-reg'; | ||||||
| 
 | 
 | ||||||
| config.newReg=config.newReg || newReg; | config.newReg=config.newReg || newReg; | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user