mirror of
				https://github.com/therootcompany/acme.js.git
				synced 2024-11-16 17:29:00 +00:00 
			
		
		
		
	add .prettierrc, and make prettier
This commit is contained in:
		
							parent
							
								
									466de61232
								
							
						
					
					
						commit
						f2b6772f5c
					
				
							
								
								
									
										8
									
								
								.prettierrc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								.prettierrc
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,8 @@ | ||||
| { | ||||
|   "bracketSpacing": true, | ||||
|   "printWidth": 80, | ||||
|   "singleQuote": true, | ||||
|   "tabWidth": 2, | ||||
|   "trailingComma": "none", | ||||
|   "useTabs": true | ||||
| } | ||||
							
								
								
									
										118
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										118
									
								
								README.md
									
									
									
									
									
								
							| @ -8,21 +8,21 @@ | ||||
| 
 | ||||
| # [acme-v2.js](https://git.coolaj86.com/coolaj86/acme-v2.js) | ||||
| 
 | ||||
| A lightweight, **Low Dependency*** framework for building | ||||
| A lightweight, **Low Dependency**\* framework for building | ||||
| Let's Encrypt v2 (ACME draft 12) clients, successor to `le-acme-core.js`. | ||||
| Built [by request](https://git.coolaj86.com/coolaj86/greenlock.js/issues/5#issuecomment-8). | ||||
| 
 | ||||
| * <small>although `node-forge` and `ursa` are included as `optionalDependencies` | ||||
| \* <small>although `node-forge` and `ursa` are included as `optionalDependencies` | ||||
| for backwards compatibility with older versions of node, there are no other | ||||
| dependencies except those that I wrote for this (and related) projects.</small> | ||||
| 
 | ||||
| ## Looking for Quick 'n' Easy™? | ||||
| 
 | ||||
| If you're looking to *build a webserver*, try [greenlock.js](https://git.coolaj86.com/coolaj86/greenlock.js). | ||||
| If you're looking for an *ACME-enabled webserver*, try [goldilocks.js](https://git.coolaj86.com/coolaj86/goldilocks.js). | ||||
| If you're looking to _build a webserver_, try [greenlock.js](https://git.coolaj86.com/coolaj86/greenlock.js). | ||||
| If you're looking for an _ACME-enabled webserver_, try [goldilocks.js](https://git.coolaj86.com/coolaj86/goldilocks.js). | ||||
| 
 | ||||
| * [greenlock.js](https://git.coolaj86.com/coolaj86/greenlock.js) | ||||
| * [goldilocks.js](https://git.coolaj86.com/coolaj86/goldilocks.js) | ||||
| - [greenlock.js](https://git.coolaj86.com/coolaj86/greenlock.js) | ||||
| - [goldilocks.js](https://git.coolaj86.com/coolaj86/goldilocks.js) | ||||
| 
 | ||||
| ## How to build ACME clients | ||||
| 
 | ||||
| @ -77,20 +77,20 @@ https://acme-staging-v02.api.letsencrypt.org/directory | ||||
| 
 | ||||
| ## Two API versions, Two Implementations | ||||
| 
 | ||||
| This library (acme-v2.js) supports ACME [*draft 11*](https://tools.ietf.org/html/draft-ietf-acme-acme-11), | ||||
| 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 | ||||
| - 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 | ||||
| - 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**, | ||||
| @ -102,7 +102,7 @@ Status: Stable, Locked, Bugfix-only | ||||
| 
 | ||||
| See Full Documentation at <https://git.coolaj86.com/coolaj86/le-acme-core.js> | ||||
| 
 | ||||
| ``` | ||||
| ```js | ||||
| var RSA = require('rsa-compat').RSA; | ||||
| var acme = require('acme-v2/compat.js').ACME.create({ RSA: RSA }); | ||||
| 
 | ||||
| @ -118,7 +118,7 @@ Status: Almost stable, but **not semver locked** | ||||
| This API is a simple evolution of le-acme-core, | ||||
| but tries to provide a better mapping to the new draft 11 APIs. | ||||
| 
 | ||||
| ``` | ||||
| ```js | ||||
| // Create Instance (Dependency Injection) | ||||
| var ACME = require('acme-v2').ACME.create({ | ||||
|   RSA: require('rsa-compat').RSA | ||||
| @ -187,54 +187,54 @@ Helpers & Stuff | ||||
| 
 | ||||
| ```javascript | ||||
| // Constants | ||||
| ACME.challengePrefixes['http-01']             // '/.well-known/acme-challenge' | ||||
| ACME.challengePrefixes['dns-01']              // '_acme-challenge' | ||||
| ACME.challengePrefixes['http-01']; // '/.well-known/acme-challenge' | ||||
| ACME.challengePrefixes['dns-01']; // '_acme-challenge' | ||||
| ``` | ||||
| 
 | ||||
| # Changelog | ||||
| 
 | ||||
| * v1.5 | ||||
|   * perform full test challenge first (even before nonce) | ||||
| * v1.3 | ||||
|   * Use node RSA keygen by default | ||||
|   * No non-optional external deps! | ||||
| * v1.2 | ||||
|   * fix some API out-of-specness | ||||
|   * doc some magic numbers (status) | ||||
|   * updated deps | ||||
| * v1.1.0 | ||||
|   * reduce dependencies (use lightweight @coolaj86/request instead of request) | ||||
| * v1.0.5 - cleanup logging | ||||
| * v1.0.4 - v6- compat use `promisify` from node's util or bluebird | ||||
| * v1.0.3 - documentation cleanup | ||||
| * v1.0.2 | ||||
|   * use `options.contact` to provide raw contact array | ||||
|   * made `options.email` optional | ||||
|   * file cleanup | ||||
| * v1.0.1 | ||||
|   * 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 | ||||
| - v1.5 | ||||
|   - perform full test challenge first (even before nonce) | ||||
| - v1.3 | ||||
|   - Use node RSA keygen by default | ||||
|   - No non-optional external deps! | ||||
| - v1.2 | ||||
|   - fix some API out-of-specness | ||||
|   - doc some magic numbers (status) | ||||
|   - updated deps | ||||
| - v1.1.0 | ||||
|   - reduce dependencies (use lightweight @coolaj86/request instead of request) | ||||
| - v1.0.5 - cleanup logging | ||||
| - v1.0.4 - v6- compat use `promisify` from node's util or bluebird | ||||
| - v1.0.3 - documentation cleanup | ||||
| - v1.0.2 | ||||
|   - use `options.contact` to provide raw contact array | ||||
|   - made `options.email` optional | ||||
|   - file cleanup | ||||
| - v1.0.1 | ||||
|   - 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 | ||||
| 
 | ||||
| # Legal | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										123
									
								
								compat.js
									
									
									
									
									
								
							
							
						
						
									
										123
									
								
								compat.js
									
									
									
									
									
								
							| @ -8,74 +8,87 @@ | ||||
| var ACME2 = require('./').ACME; | ||||
| 
 | ||||
| function resolveFn(cb) { | ||||
|   return function (val) { | ||||
|     // nextTick to get out of Promise chain
 | ||||
|     process.nextTick(function () { cb(null, val); }); | ||||
|   }; | ||||
| 	return function(val) { | ||||
| 		// nextTick to get out of Promise chain
 | ||||
| 		process.nextTick(function() { | ||||
| 			cb(null, val); | ||||
| 		}); | ||||
| 	}; | ||||
| } | ||||
| function rejectFn(cb) { | ||||
|   return function (err) { | ||||
|     console.error('[acme-v2] handled(?) rejection as errback:'); | ||||
|     console.error(err.stack); | ||||
| 	return function(err) { | ||||
| 		console.error('[acme-v2] handled(?) rejection as errback:'); | ||||
| 		console.error(err.stack); | ||||
| 
 | ||||
|     // nextTick to get out of Promise chain
 | ||||
|     process.nextTick(function () { cb(err); }); | ||||
| 		// nextTick to get out of Promise chain
 | ||||
| 		process.nextTick(function() { | ||||
| 			cb(err); | ||||
| 		}); | ||||
| 
 | ||||
|     // do not resolve promise further
 | ||||
|     return new Promise(function () {}); | ||||
|   }; | ||||
| 		// do not resolve promise further
 | ||||
| 		return new Promise(function() {}); | ||||
| 	}; | ||||
| } | ||||
| 
 | ||||
| function create(deps) { | ||||
|   deps.LeCore = {}; | ||||
|   var acme2 = ACME2.create(deps); | ||||
|   acme2.registerNewAccount = function (options, cb) { | ||||
|     acme2.accounts.create(options).then(resolveFn(cb), rejectFn(cb)); | ||||
|   }; | ||||
|   acme2.getCertificate = function (options, cb) { | ||||
|     options.agreeToTerms = options.agreeToTerms || function (tos) { | ||||
|       return Promise.resolve(tos); | ||||
|     }; | ||||
|     acme2.certificates.create(options).then(function (certs) { | ||||
|       var privkeyPem = acme2.RSA.exportPrivatePem(options.domainKeypair); | ||||
|       certs.privkey = privkeyPem; | ||||
|       resolveFn(cb)(certs); | ||||
|     }, rejectFn(cb)); | ||||
|   }; | ||||
|   acme2.getAcmeUrls = function (options, cb) { | ||||
|     acme2.init(options).then(resolveFn(cb), rejectFn(cb)); | ||||
|   }; | ||||
|   acme2.getOptions = function () { | ||||
|     var defs = {}; | ||||
| 	deps.LeCore = {}; | ||||
| 	var acme2 = ACME2.create(deps); | ||||
| 	acme2.registerNewAccount = function(options, cb) { | ||||
| 		acme2.accounts.create(options).then(resolveFn(cb), rejectFn(cb)); | ||||
| 	}; | ||||
| 	acme2.getCertificate = function(options, cb) { | ||||
| 		options.agreeToTerms = | ||||
| 			options.agreeToTerms || | ||||
| 			function(tos) { | ||||
| 				return Promise.resolve(tos); | ||||
| 			}; | ||||
| 		acme2.certificates.create(options).then(function(certs) { | ||||
| 			var privkeyPem = acme2.RSA.exportPrivatePem(options.domainKeypair); | ||||
| 			certs.privkey = privkeyPem; | ||||
| 			resolveFn(cb)(certs); | ||||
| 		}, rejectFn(cb)); | ||||
| 	}; | ||||
| 	acme2.getAcmeUrls = function(options, cb) { | ||||
| 		acme2.init(options).then(resolveFn(cb), rejectFn(cb)); | ||||
| 	}; | ||||
| 	acme2.getOptions = function() { | ||||
| 		var defs = {}; | ||||
| 
 | ||||
|     Object.keys(module.exports.defaults).forEach(function (key) { | ||||
|       defs[key] = defs[deps] || module.exports.defaults[key]; | ||||
|     }); | ||||
| 		Object.keys(module.exports.defaults).forEach(function(key) { | ||||
| 			defs[key] = defs[deps] || module.exports.defaults[key]; | ||||
| 		}); | ||||
| 
 | ||||
|     return defs; | ||||
|   }; | ||||
|   acme2.stagingServerUrl = module.exports.defaults.stagingServerUrl; | ||||
|   acme2.productionServerUrl = module.exports.defaults.productionServerUrl; | ||||
|   acme2.acmeChallengePrefix = module.exports.defaults.acmeChallengePrefix; | ||||
|   return acme2; | ||||
| 		return defs; | ||||
| 	}; | ||||
| 	acme2.stagingServerUrl = module.exports.defaults.stagingServerUrl; | ||||
| 	acme2.productionServerUrl = module.exports.defaults.productionServerUrl; | ||||
| 	acme2.acmeChallengePrefix = module.exports.defaults.acmeChallengePrefix; | ||||
| 	return acme2; | ||||
| } | ||||
| 
 | ||||
| module.exports.ACME = { }; | ||||
| module.exports.ACME = {}; | ||||
| module.exports.defaults = { | ||||
|   productionServerUrl:    'https://acme-v02.api.letsencrypt.org/directory' | ||||
| , stagingServerUrl:       'https://acme-staging-v02.api.letsencrypt.org/directory' | ||||
| , knownEndpoints:         [ 'keyChange', 'meta', 'newAccount', 'newNonce', 'newOrder', 'revokeCert' ] | ||||
| , challengeTypes:         [ 'http-01', 'dns-01' ] | ||||
| , challengeType:          'http-01' | ||||
| //, keyType:                'rsa' // ecdsa
 | ||||
| //, keySize:                2048 // 256
 | ||||
| , rsaKeySize:             2048 // 256
 | ||||
| , acmeChallengePrefix:    '/.well-known/acme-challenge/' | ||||
| 	productionServerUrl: 'https://acme-v02.api.letsencrypt.org/directory', | ||||
| 	stagingServerUrl: 'https://acme-staging-v02.api.letsencrypt.org/directory', | ||||
| 	knownEndpoints: [ | ||||
| 		'keyChange', | ||||
| 		'meta', | ||||
| 		'newAccount', | ||||
| 		'newNonce', | ||||
| 		'newOrder', | ||||
| 		'revokeCert' | ||||
| 	], | ||||
| 	challengeTypes: ['http-01', 'dns-01'], | ||||
| 	challengeType: 'http-01', | ||||
| 	//, keyType:                'rsa' // ecdsa
 | ||||
| 	//, keySize:                2048 // 256
 | ||||
| 	rsaKeySize: 2048, // 256
 | ||||
| 	acmeChallengePrefix: '/.well-known/acme-challenge/' | ||||
| }; | ||||
| Object.keys(module.exports.defaults).forEach(function (key) { | ||||
|   module.exports.ACME[key] = module.exports.defaults[key]; | ||||
| Object.keys(module.exports.defaults).forEach(function(key) { | ||||
| 	module.exports.ACME[key] = module.exports.defaults[key]; | ||||
| }); | ||||
| Object.keys(ACME2).forEach(function (key) { | ||||
|   module.exports.ACME[key] = ACME2[key]; | ||||
| Object.keys(ACME2).forEach(function(key) { | ||||
| 	module.exports.ACME[key] = ACME2[key]; | ||||
| }); | ||||
| module.exports.ACME.create = create; | ||||
|  | ||||
							
								
								
									
										139
									
								
								examples/cli.js
									
									
									
									
									
								
							
							
						
						
									
										139
									
								
								examples/cli.js
									
									
									
									
									
								
							| @ -7,66 +7,125 @@ | ||||
| var RSA = require('rsa-compat').RSA; | ||||
| var readline = require('readline'); | ||||
| var rl = readline.createInterface({ | ||||
|   input: process.stdin, | ||||
|   output: process.stdout | ||||
| 	input: process.stdin, | ||||
| 	output: process.stdout | ||||
| }); | ||||
| 
 | ||||
| require('./genkeypair.js'); | ||||
| 
 | ||||
| function getWeb() { | ||||
|   rl.question('What web address(es) would you like to get certificates for? (ex: example.com,*.example.com) ', function (web) { | ||||
|     web = (web||'').trim().split(/,/g); | ||||
|     if (!web[0]) { getWeb(); return; } | ||||
| 	rl.question( | ||||
| 		'What web address(es) would you like to get certificates for? (ex: example.com,*.example.com) ', | ||||
| 		function(web) { | ||||
| 			web = (web || '').trim().split(/,/g); | ||||
| 			if (!web[0]) { | ||||
| 				getWeb(); | ||||
| 				return; | ||||
| 			} | ||||
| 
 | ||||
|     if (web.some(function (w) { return '*' === w[0]; })) { | ||||
|       console.log('Wildcard domains must use dns-01'); | ||||
|       getEmail(web, 'dns-01'); | ||||
|     } else { | ||||
|       getChallengeType(web); | ||||
|     } | ||||
|   }); | ||||
| 			if ( | ||||
| 				web.some(function(w) { | ||||
| 					return '*' === w[0]; | ||||
| 				}) | ||||
| 			) { | ||||
| 				console.log('Wildcard domains must use dns-01'); | ||||
| 				getEmail(web, 'dns-01'); | ||||
| 			} else { | ||||
| 				getChallengeType(web); | ||||
| 			} | ||||
| 		} | ||||
| 	); | ||||
| } | ||||
| 
 | ||||
| function getChallengeType(web) { | ||||
|   rl.question('What challenge will you be testing today? http-01 or dns-01? [http-01] ', function (chType) { | ||||
|     chType = (chType||'').trim(); | ||||
|     if (!chType) { chType = 'http-01'; } | ||||
| 	rl.question( | ||||
| 		'What challenge will you be testing today? http-01 or dns-01? [http-01] ', | ||||
| 		function(chType) { | ||||
| 			chType = (chType || '').trim(); | ||||
| 			if (!chType) { | ||||
| 				chType = 'http-01'; | ||||
| 			} | ||||
| 
 | ||||
|     getEmail(web, chType); | ||||
|   }); | ||||
| 			getEmail(web, chType); | ||||
| 		} | ||||
| 	); | ||||
| } | ||||
| 
 | ||||
| function getEmail(web, chType) { | ||||
|   rl.question('What email should we use? (optional) ', function (email) { | ||||
|     email = (email||'').trim(); | ||||
|     if (!email) { email = null; } | ||||
| 	rl.question('What email should we use? (optional) ', function(email) { | ||||
| 		email = (email || '').trim(); | ||||
| 		if (!email) { | ||||
| 			email = null; | ||||
| 		} | ||||
| 
 | ||||
|     getApiStyle(web, chType, email); | ||||
|   }); | ||||
| 		getApiStyle(web, chType, email); | ||||
| 	}); | ||||
| } | ||||
| 
 | ||||
| function getApiStyle(web, chType, email) { | ||||
|   var defaultStyle = 'compat'; | ||||
|   rl.question('What API style would you like to test? v1-compat or promise? [v1-compat] ', function (apiStyle) { | ||||
|     apiStyle = (apiStyle||'').trim(); | ||||
|     if (!apiStyle) { apiStyle = 'v1-compat'; } | ||||
| 	var defaultStyle = 'compat'; | ||||
| 	rl.question( | ||||
| 		'What API style would you like to test? v1-compat or promise? [v1-compat] ', | ||||
| 		function(apiStyle) { | ||||
| 			apiStyle = (apiStyle || '').trim(); | ||||
| 			if (!apiStyle) { | ||||
| 				apiStyle = 'v1-compat'; | ||||
| 			} | ||||
| 
 | ||||
|     rl.close(); | ||||
| 			rl.close(); | ||||
| 
 | ||||
|     var RSA = require('rsa-compat').RSA; | ||||
|     var accountKeypair = RSA.import({ privateKeyPem: require('fs').readFileSync(__dirname + '/../tests/account.privkey.pem') }); | ||||
|     var domainKeypair = RSA.import({ privateKeyPem: require('fs').readFileSync(__dirname + '/../tests/privkey.pem') }); | ||||
|     var directoryUrl = 'https://acme-staging-v02.api.letsencrypt.org/directory'; | ||||
| 			var RSA = require('rsa-compat').RSA; | ||||
| 			var accountKeypair = RSA.import({ | ||||
| 				privateKeyPem: require('fs').readFileSync( | ||||
| 					__dirname + '/../tests/account.privkey.pem' | ||||
| 				) | ||||
| 			}); | ||||
| 			var domainKeypair = RSA.import({ | ||||
| 				privateKeyPem: require('fs').readFileSync( | ||||
| 					__dirname + '/../tests/privkey.pem' | ||||
| 				) | ||||
| 			}); | ||||
| 			var directoryUrl = | ||||
| 				'https://acme-staging-v02.api.letsencrypt.org/directory'; | ||||
| 
 | ||||
|     if ('promise' === apiStyle) { | ||||
|       require('../tests/promise.js').run(directoryUrl, RSA, web, chType, email, accountKeypair, domainKeypair); | ||||
|     } else if ('cb' === apiStyle) { | ||||
|       require('../tests/cb.js').run(directoryUrl, RSA, web, chType, email, accountKeypair, domainKeypair); | ||||
|     } else { | ||||
|       if ('v1-compat' !== apiStyle) { console.warn("Didn't understand '" + apiStyle + "', using 'v1-compat' instead..."); } | ||||
|       require('../tests/compat.js').run(directoryUrl, RSA, web, chType, email, accountKeypair, domainKeypair); | ||||
|     } | ||||
|   }); | ||||
| 			if ('promise' === apiStyle) { | ||||
| 				require('../tests/promise.js').run( | ||||
| 					directoryUrl, | ||||
| 					RSA, | ||||
| 					web, | ||||
| 					chType, | ||||
| 					email, | ||||
| 					accountKeypair, | ||||
| 					domainKeypair | ||||
| 				); | ||||
| 			} else if ('cb' === apiStyle) { | ||||
| 				require('../tests/cb.js').run( | ||||
| 					directoryUrl, | ||||
| 					RSA, | ||||
| 					web, | ||||
| 					chType, | ||||
| 					email, | ||||
| 					accountKeypair, | ||||
| 					domainKeypair | ||||
| 				); | ||||
| 			} else { | ||||
| 				if ('v1-compat' !== apiStyle) { | ||||
| 					console.warn( | ||||
| 						"Didn't understand '" + apiStyle + "', using 'v1-compat' instead..." | ||||
| 					); | ||||
| 				} | ||||
| 				require('../tests/compat.js').run( | ||||
| 					directoryUrl, | ||||
| 					RSA, | ||||
| 					web, | ||||
| 					chType, | ||||
| 					email, | ||||
| 					accountKeypair, | ||||
| 					domainKeypair | ||||
| 				); | ||||
| 			} | ||||
| 		} | ||||
| 	); | ||||
| } | ||||
| 
 | ||||
| getWeb(); | ||||
|  | ||||
| @ -6,21 +6,21 @@ var RSA = require('rsa-compat').RSA; | ||||
| var fs = require('fs'); | ||||
| 
 | ||||
| if (!fs.existsSync(__dirname + '/../tests/account.privkey.pem')) { | ||||
|   RSA.generateKeypair(2048, 65537, {}, function (err, keypair) { | ||||
|     console.log(keypair); | ||||
|     var privkeyPem = RSA.exportPrivatePem(keypair) | ||||
|     console.log(privkeyPem); | ||||
| 	RSA.generateKeypair(2048, 65537, {}, function(err, keypair) { | ||||
| 		console.log(keypair); | ||||
| 		var privkeyPem = RSA.exportPrivatePem(keypair); | ||||
| 		console.log(privkeyPem); | ||||
| 
 | ||||
|     fs.writeFileSync(__dirname + '/../tests/account.privkey.pem', privkeyPem); | ||||
|   }); | ||||
| 		fs.writeFileSync(__dirname + '/../tests/account.privkey.pem', privkeyPem); | ||||
| 	}); | ||||
| } | ||||
| 
 | ||||
| if (!fs.existsSync(__dirname + '/../tests/privkey.pem')) { | ||||
|   RSA.generateKeypair(2048, 65537, {}, function (err, keypair) { | ||||
|     console.log(keypair); | ||||
|     var privkeyPem = RSA.exportPrivatePem(keypair) | ||||
|     console.log(privkeyPem); | ||||
| 	RSA.generateKeypair(2048, 65537, {}, function(err, keypair) { | ||||
| 		console.log(keypair); | ||||
| 		var privkeyPem = RSA.exportPrivatePem(keypair); | ||||
| 		console.log(privkeyPem); | ||||
| 
 | ||||
|     fs.writeFileSync(__dirname + '/../tests/privkey.pem', privkeyPem); | ||||
|   }); | ||||
| 		fs.writeFileSync(__dirname + '/../tests/privkey.pem', privkeyPem); | ||||
| 	}); | ||||
| } | ||||
|  | ||||
| @ -6,6 +6,8 @@ | ||||
| 
 | ||||
| var http = require('http'); | ||||
| var express = require('express'); | ||||
| var server = http.createServer(express.static('../tests')).listen(80, function () { | ||||
|   console.log('Listening on', this.address()); | ||||
| }); | ||||
| var server = http | ||||
| 	.createServer(express.static('../tests')) | ||||
| 	.listen(80, function() { | ||||
| 		console.log('Listening on', this.address()); | ||||
| 	}); | ||||
|  | ||||
| @ -5,11 +5,16 @@ | ||||
| 'use strict'; | ||||
| 
 | ||||
| var https = require('https'); | ||||
| var server = https.createServer({ | ||||
|   key: require('fs').readFileSync('../tests/privkey.pem') | ||||
| , cert: require('fs').readFileSync('../tests/fullchain.pem') | ||||
| }, function (req, res) { | ||||
|   res.end("Hello, World!"); | ||||
| }).listen(443, function () { | ||||
|   console.log('Listening on', this.address()); | ||||
| }); | ||||
| var server = https | ||||
| 	.createServer( | ||||
| 		{ | ||||
| 			key: require('fs').readFileSync('../tests/privkey.pem'), | ||||
| 			cert: require('fs').readFileSync('../tests/fullchain.pem') | ||||
| 		}, | ||||
| 		function(req, res) { | ||||
| 			res.end('Hello, World!'); | ||||
| 		} | ||||
| 	) | ||||
| 	.listen(443, function() { | ||||
| 		console.log('Listening on', this.address()); | ||||
| 	}); | ||||
|  | ||||
							
								
								
									
										76
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										76
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							| @ -1,40 +1,40 @@ | ||||
| { | ||||
|   "name": "acme-v2", | ||||
|   "version": "1.7.6", | ||||
|   "lockfileVersion": 1, | ||||
|   "requires": true, | ||||
|   "dependencies": { | ||||
|     "@coolaj86/urequest": { | ||||
|       "version": "1.3.7", | ||||
|       "resolved": "https://registry.npmjs.org/@coolaj86/urequest/-/urequest-1.3.7.tgz", | ||||
|       "integrity": "sha512-PPrVYra9aWvZjSCKl/x1pJ9ZpXda1652oJrPBYy5rQumJJMkmTBN3ux+sK2xAUwVvv2wnewDlaQaHLxLwSHnIA==" | ||||
|     }, | ||||
|     "eckles": { | ||||
|       "version": "1.4.1", | ||||
|       "resolved": "https://registry.npmjs.org/eckles/-/eckles-1.4.1.tgz", | ||||
|       "integrity": "sha512-auWyk/k8oSkVHaD4RxkPadKsLUcIwKgr/h8F7UZEueFDBO7BsE4y+H6IMUDbfqKIFPg/9MxV6KcBdJCmVVcxSA==" | ||||
|     }, | ||||
|     "keypairs": { | ||||
|       "version": "1.2.14", | ||||
|       "resolved": "https://registry.npmjs.org/keypairs/-/keypairs-1.2.14.tgz", | ||||
|       "integrity": "sha512-ZoZfZMygyB0QcjSlz7Rh6wT2CJasYEHBPETtmHZEfxuJd7bnsOG5AdtPZqHZBT+hoHvuWCp/4y8VmvTvH0Y9uA==", | ||||
|       "requires": { | ||||
|         "eckles": "^1.4.1", | ||||
|         "rasha": "^1.2.4" | ||||
|       } | ||||
|     }, | ||||
|     "rasha": { | ||||
|       "version": "1.2.5", | ||||
|       "resolved": "https://registry.npmjs.org/rasha/-/rasha-1.2.5.tgz", | ||||
|       "integrity": "sha512-KxtX+/fBk+wM7O3CNgwjSh5elwFilLvqWajhr6wFr2Hd63JnKTTi43Tw+Jb1hxJQWOwoya+NZWR2xztn3hCrTw==" | ||||
|     }, | ||||
|     "rsa-compat": { | ||||
|       "version": "2.0.6", | ||||
|       "resolved": "https://registry.npmjs.org/rsa-compat/-/rsa-compat-2.0.6.tgz", | ||||
|       "integrity": "sha512-bQmpscAQec9442RaghDybrHMy1twQ3nUZOgTlqntio1yru+rMnDV64uGRzKp7dJ4VVhNv3mLh3X4MNON+YM0dA==", | ||||
|       "requires": { | ||||
|         "keypairs": "^1.2.14" | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| 	"name": "acme-v2", | ||||
| 	"version": "1.7.6", | ||||
| 	"lockfileVersion": 1, | ||||
| 	"requires": true, | ||||
| 	"dependencies": { | ||||
| 		"@coolaj86/urequest": { | ||||
| 			"version": "1.3.7", | ||||
| 			"resolved": "https://registry.npmjs.org/@coolaj86/urequest/-/urequest-1.3.7.tgz", | ||||
| 			"integrity": "sha512-PPrVYra9aWvZjSCKl/x1pJ9ZpXda1652oJrPBYy5rQumJJMkmTBN3ux+sK2xAUwVvv2wnewDlaQaHLxLwSHnIA==" | ||||
| 		}, | ||||
| 		"eckles": { | ||||
| 			"version": "1.4.1", | ||||
| 			"resolved": "https://registry.npmjs.org/eckles/-/eckles-1.4.1.tgz", | ||||
| 			"integrity": "sha512-auWyk/k8oSkVHaD4RxkPadKsLUcIwKgr/h8F7UZEueFDBO7BsE4y+H6IMUDbfqKIFPg/9MxV6KcBdJCmVVcxSA==" | ||||
| 		}, | ||||
| 		"keypairs": { | ||||
| 			"version": "1.2.14", | ||||
| 			"resolved": "https://registry.npmjs.org/keypairs/-/keypairs-1.2.14.tgz", | ||||
| 			"integrity": "sha512-ZoZfZMygyB0QcjSlz7Rh6wT2CJasYEHBPETtmHZEfxuJd7bnsOG5AdtPZqHZBT+hoHvuWCp/4y8VmvTvH0Y9uA==", | ||||
| 			"requires": { | ||||
| 				"eckles": "^1.4.1", | ||||
| 				"rasha": "^1.2.4" | ||||
| 			} | ||||
| 		}, | ||||
| 		"rasha": { | ||||
| 			"version": "1.2.5", | ||||
| 			"resolved": "https://registry.npmjs.org/rasha/-/rasha-1.2.5.tgz", | ||||
| 			"integrity": "sha512-KxtX+/fBk+wM7O3CNgwjSh5elwFilLvqWajhr6wFr2Hd63JnKTTi43Tw+Jb1hxJQWOwoya+NZWR2xztn3hCrTw==" | ||||
| 		}, | ||||
| 		"rsa-compat": { | ||||
| 			"version": "2.0.6", | ||||
| 			"resolved": "https://registry.npmjs.org/rsa-compat/-/rsa-compat-2.0.6.tgz", | ||||
| 			"integrity": "sha512-bQmpscAQec9442RaghDybrHMy1twQ3nUZOgTlqntio1yru+rMnDV64uGRzKp7dJ4VVhNv3mLh3X4MNON+YM0dA==", | ||||
| 			"requires": { | ||||
| 				"keypairs": "^1.2.14" | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
							
								
								
									
										60
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										60
									
								
								package.json
									
									
									
									
									
								
							| @ -1,32 +1,32 @@ | ||||
| { | ||||
|   "name": "acme-v2", | ||||
|   "version": "1.7.7", | ||||
|   "description": "Free SSL. A framework for building Let's Encrypt v2 clients, and other ACME v2 (draft 11) clients. Successor to le-acme-core.js", | ||||
|   "homepage": "https://git.coolaj86.com/coolaj86/acme-v2.js", | ||||
|   "main": "node.js", | ||||
|   "scripts": { | ||||
|     "test": "echo \"Error: no test specified\" && exit 1" | ||||
|   }, | ||||
|   "repository": { | ||||
|     "type": "git", | ||||
|     "url": "ssh://gitea@git.coolaj86.com:22042/coolaj86/acme-v2.js.git" | ||||
|   }, | ||||
|   "keywords": [ | ||||
|     "Let's Encrypt", | ||||
|     "ACME", | ||||
|     "v02", | ||||
|     "v2", | ||||
|     "draft-11", | ||||
|     "draft-12", | ||||
|     "free ssl", | ||||
|     "tls", | ||||
|     "automated https", | ||||
|     "letsencrypt" | ||||
|   ], | ||||
|   "author": "AJ ONeal <coolaj86@gmail.com> (https://coolaj86.com/)", | ||||
|   "license": "MPL-2.0", | ||||
|   "dependencies": { | ||||
|     "@coolaj86/urequest": "^1.3.6", | ||||
|     "rsa-compat": "^2.0.6" | ||||
|   } | ||||
| 	"name": "acme-v2", | ||||
| 	"version": "1.7.7", | ||||
| 	"description": "Free SSL. A framework for building Let's Encrypt v2 clients, and other ACME v2 (draft 11) clients. Successor to le-acme-core.js", | ||||
| 	"homepage": "https://git.coolaj86.com/coolaj86/acme-v2.js", | ||||
| 	"main": "node.js", | ||||
| 	"scripts": { | ||||
| 		"test": "echo \"Error: no test specified\" && exit 1" | ||||
| 	}, | ||||
| 	"repository": { | ||||
| 		"type": "git", | ||||
| 		"url": "ssh://gitea@git.coolaj86.com:22042/coolaj86/acme-v2.js.git" | ||||
| 	}, | ||||
| 	"keywords": [ | ||||
| 		"Let's Encrypt", | ||||
| 		"ACME", | ||||
| 		"v02", | ||||
| 		"v2", | ||||
| 		"draft-11", | ||||
| 		"draft-12", | ||||
| 		"free ssl", | ||||
| 		"tls", | ||||
| 		"automated https", | ||||
| 		"letsencrypt" | ||||
| 	], | ||||
| 	"author": "AJ ONeal <coolaj86@gmail.com> (https://coolaj86.com/)", | ||||
| 	"license": "MPL-2.0", | ||||
| 	"dependencies": { | ||||
| 		"@coolaj86/urequest": "^1.3.6", | ||||
| 		"rsa-compat": "^2.0.6" | ||||
| 	} | ||||
| } | ||||
|  | ||||
							
								
								
									
										175
									
								
								tests/cb.js
									
									
									
									
									
								
							
							
						
						
									
										175
									
								
								tests/cb.js
									
									
									
									
									
								
							| @ -4,80 +4,115 @@ | ||||
|  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 | ||||
| 'use strict'; | ||||
| 
 | ||||
| module.exports.run = function run(directoryUrl, RSA, web, chType, email, accountKeypair, domainKeypair) { | ||||
|   // [ 'test.ppl.family' ] 'coolaj86@gmail.com''http-01'
 | ||||
|   var acme2 = require('../').ACME.create({ RSA: RSA }); | ||||
|   acme2.init(directoryUrl).then(function () { | ||||
|     var options = { | ||||
|       agreeToTerms: function (tosUrl, agree) { | ||||
|         agree(null, tosUrl); | ||||
|       } | ||||
|     , setChallenge: function (opts, cb) { | ||||
|         var pathname; | ||||
| module.exports.run = function run( | ||||
| 	directoryUrl, | ||||
| 	RSA, | ||||
| 	web, | ||||
| 	chType, | ||||
| 	email, | ||||
| 	accountKeypair, | ||||
| 	domainKeypair | ||||
| ) { | ||||
| 	// [ 'test.ppl.family' ] 'coolaj86@gmail.com''http-01'
 | ||||
| 	var acme2 = require('../').ACME.create({ RSA: RSA }); | ||||
| 	acme2.init(directoryUrl).then(function() { | ||||
| 		var options = { | ||||
| 			agreeToTerms: function(tosUrl, agree) { | ||||
| 				agree(null, tosUrl); | ||||
| 			}, | ||||
| 			setChallenge: function(opts, cb) { | ||||
| 				var pathname; | ||||
| 
 | ||||
|         console.log(""); | ||||
|         console.log('identifier:'); | ||||
|         console.log(opts.identifier); | ||||
|         console.log('hostname:'); | ||||
|         console.log(opts.hostname); | ||||
|         console.log('type:'); | ||||
|         console.log(opts.type); | ||||
|         console.log('token:'); | ||||
|         console.log(opts.token); | ||||
|         console.log('thumbprint:'); | ||||
|         console.log(opts.thumbprint); | ||||
|         console.log('keyAuthorization:'); | ||||
|         console.log(opts.keyAuthorization); | ||||
|         console.log('dnsAuthorization:'); | ||||
|         console.log(opts.dnsAuthorization); | ||||
|         console.log(""); | ||||
| 				console.log(''); | ||||
| 				console.log('identifier:'); | ||||
| 				console.log(opts.identifier); | ||||
| 				console.log('hostname:'); | ||||
| 				console.log(opts.hostname); | ||||
| 				console.log('type:'); | ||||
| 				console.log(opts.type); | ||||
| 				console.log('token:'); | ||||
| 				console.log(opts.token); | ||||
| 				console.log('thumbprint:'); | ||||
| 				console.log(opts.thumbprint); | ||||
| 				console.log('keyAuthorization:'); | ||||
| 				console.log(opts.keyAuthorization); | ||||
| 				console.log('dnsAuthorization:'); | ||||
| 				console.log(opts.dnsAuthorization); | ||||
| 				console.log(''); | ||||
| 
 | ||||
|         if ('http-01' === opts.type) { | ||||
|           pathname = opts.hostname + acme2.challengePrefixes['http-01'] + "/" + opts.token; | ||||
|           console.log("Put the string '" + opts.keyAuthorization + "' into a file at '" + pathname + "'"); | ||||
|           console.log("echo '" + opts.keyAuthorization + "' > '" + pathname + "'"); | ||||
|         } else if ('dns-01' === opts.type) { | ||||
|           pathname = acme2.challengePrefixes['dns-01'] + "." + opts.hostname.replace(/^\*\./, ''); | ||||
|           console.log("Put the string '" + opts.dnsAuthorization + "' into the TXT record '" + pathname + "'"); | ||||
|           console.log("ddig TXT " + pathname + " '" + opts.dnsAuthorization + "'"); | ||||
|         } else { | ||||
|           cb(new Error("[acme-v2] unrecognized challenge type")); | ||||
|           return; | ||||
|         } | ||||
|         console.log("\nThen hit the 'any' key to continue..."); | ||||
| 				if ('http-01' === opts.type) { | ||||
| 					pathname = | ||||
| 						opts.hostname + | ||||
| 						acme2.challengePrefixes['http-01'] + | ||||
| 						'/' + | ||||
| 						opts.token; | ||||
| 					console.log( | ||||
| 						"Put the string '" + | ||||
| 							opts.keyAuthorization + | ||||
| 							"' into a file at '" + | ||||
| 							pathname + | ||||
| 							"'" | ||||
| 					); | ||||
| 					console.log( | ||||
| 						"echo '" + opts.keyAuthorization + "' > '" + pathname + "'" | ||||
| 					); | ||||
| 				} else if ('dns-01' === opts.type) { | ||||
| 					pathname = | ||||
| 						acme2.challengePrefixes['dns-01'] + | ||||
| 						'.' + | ||||
| 						opts.hostname.replace(/^\*\./, ''); | ||||
| 					console.log( | ||||
| 						"Put the string '" + | ||||
| 							opts.dnsAuthorization + | ||||
| 							"' into the TXT record '" + | ||||
| 							pathname + | ||||
| 							"'" | ||||
| 					); | ||||
| 					console.log( | ||||
| 						'ddig TXT ' + pathname + " '" + opts.dnsAuthorization + "'" | ||||
| 					); | ||||
| 				} else { | ||||
| 					cb(new Error('[acme-v2] unrecognized challenge type')); | ||||
| 					return; | ||||
| 				} | ||||
| 				console.log("\nThen hit the 'any' key to continue..."); | ||||
| 
 | ||||
|         function onAny() { | ||||
|           console.log("'any' key was hit"); | ||||
|           process.stdin.pause(); | ||||
|           process.stdin.removeListener('data', onAny); | ||||
|           process.stdin.setRawMode(false); | ||||
|           cb(); | ||||
|         } | ||||
| 				function onAny() { | ||||
| 					console.log("'any' key was hit"); | ||||
| 					process.stdin.pause(); | ||||
| 					process.stdin.removeListener('data', onAny); | ||||
| 					process.stdin.setRawMode(false); | ||||
| 					cb(); | ||||
| 				} | ||||
| 
 | ||||
|         process.stdin.setRawMode(true); | ||||
|         process.stdin.resume(); | ||||
|         process.stdin.on('data', onAny); | ||||
|       } | ||||
|     , removeChallenge: function (opts, cb) { | ||||
|         // hostname, key
 | ||||
|         console.log('[acme-v2] remove challenge', opts.hostname, opts.keyAuthorization); | ||||
|         setTimeout(cb, 1 * 1000); | ||||
|       } | ||||
|     , challengeType: chType | ||||
|     , email: email | ||||
|     , accountKeypair: accountKeypair | ||||
|     , domainKeypair: domainKeypair | ||||
|     , domains: web | ||||
|     }; | ||||
| 				process.stdin.setRawMode(true); | ||||
| 				process.stdin.resume(); | ||||
| 				process.stdin.on('data', onAny); | ||||
| 			}, | ||||
| 			removeChallenge: function(opts, cb) { | ||||
| 				// hostname, key
 | ||||
| 				console.log( | ||||
| 					'[acme-v2] remove challenge', | ||||
| 					opts.hostname, | ||||
| 					opts.keyAuthorization | ||||
| 				); | ||||
| 				setTimeout(cb, 1 * 1000); | ||||
| 			}, | ||||
| 			challengeType: chType, | ||||
| 			email: email, | ||||
| 			accountKeypair: accountKeypair, | ||||
| 			domainKeypair: domainKeypair, | ||||
| 			domains: web | ||||
| 		}; | ||||
| 
 | ||||
|     acme2.accounts.create(options).then(function (account) { | ||||
|       console.log('[acme-v2] account:'); | ||||
|       console.log(account); | ||||
| 		acme2.accounts.create(options).then(function(account) { | ||||
| 			console.log('[acme-v2] account:'); | ||||
| 			console.log(account); | ||||
| 
 | ||||
|       acme2.certificates.create(options).then(function (fullchainPem) { | ||||
|         console.log('[acme-v2] fullchain.pem:'); | ||||
|         console.log(fullchainPem); | ||||
|       }); | ||||
|     }); | ||||
|   }); | ||||
| 			acme2.certificates.create(options).then(function(fullchainPem) { | ||||
| 				console.log('[acme-v2] fullchain.pem:'); | ||||
| 				console.log(fullchainPem); | ||||
| 			}); | ||||
| 		}); | ||||
| 	}); | ||||
| }; | ||||
|  | ||||
							
								
								
									
										150
									
								
								tests/compat.js
									
									
									
									
									
								
							
							
						
						
									
										150
									
								
								tests/compat.js
									
									
									
									
									
								
							| @ -4,69 +4,103 @@ | ||||
|  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 | ||||
| 'use strict'; | ||||
| 
 | ||||
| module.exports.run = function (directoryUrl, RSA, web, chType, email, accountKeypair, domainKeypair) { | ||||
|   console.log('[DEBUG] run', web, chType, email); | ||||
| module.exports.run = function( | ||||
| 	directoryUrl, | ||||
| 	RSA, | ||||
| 	web, | ||||
| 	chType, | ||||
| 	email, | ||||
| 	accountKeypair, | ||||
| 	domainKeypair | ||||
| ) { | ||||
| 	console.log('[DEBUG] run', web, chType, email); | ||||
| 
 | ||||
|   var acme2 = require('../compat.js').ACME.create({ RSA: RSA }); | ||||
|   acme2.getAcmeUrls(acme2.stagingServerUrl, function (err/*, directoryUrls*/) { | ||||
|     if (err) { console.log('err 1'); throw err; } | ||||
| 	var acme2 = require('../compat.js').ACME.create({ RSA: RSA }); | ||||
| 	acme2.getAcmeUrls(acme2.stagingServerUrl, function(err /*, directoryUrls*/) { | ||||
| 		if (err) { | ||||
| 			console.log('err 1'); | ||||
| 			throw err; | ||||
| 		} | ||||
| 
 | ||||
|     var options = { | ||||
|       agreeToTerms: function (tosUrl, agree) { | ||||
|         agree(null, tosUrl); | ||||
|       } | ||||
|     , setChallenge: function (hostname, token, val, cb) { | ||||
|         var pathname; | ||||
| 		var options = { | ||||
| 			agreeToTerms: function(tosUrl, agree) { | ||||
| 				agree(null, tosUrl); | ||||
| 			}, | ||||
| 			setChallenge: function(hostname, token, val, cb) { | ||||
| 				var pathname; | ||||
| 
 | ||||
|         if ('http-01' === cb.type) { | ||||
|           pathname = hostname + acme2.acmeChallengePrefix + token; | ||||
|           console.log("Put the string '" + val /*keyAuthorization*/ + "' into a file at '" + pathname + "'"); | ||||
|           console.log("echo '" + val /*keyAuthorization*/ + "' > '" + pathname + "'"); | ||||
|           console.log("\nThen hit the 'any' key to continue..."); | ||||
|         } else if ('dns-01' === cb.type) { | ||||
|           // forwards-backwards compat
 | ||||
|           pathname = acme2.challengePrefixes['dns-01'] + "." + hostname.replace(/^\*\./, ''); | ||||
|           console.log("Put the string '" + cb.dnsAuthorization + "' into the TXT record '" + pathname + "'"); | ||||
|           console.log("dig TXT " + pathname + " '" + cb.dnsAuthorization + "'"); | ||||
|           console.log("\nThen hit the 'any' key to continue..."); | ||||
|         } else { | ||||
|           cb(new Error("[acme-v2] unrecognized challenge type: " + cb.type)); | ||||
|           return; | ||||
|         } | ||||
| 				if ('http-01' === cb.type) { | ||||
| 					pathname = hostname + acme2.acmeChallengePrefix + token; | ||||
| 					console.log( | ||||
| 						"Put the string '" + | ||||
| 						val /*keyAuthorization*/ + | ||||
| 							"' into a file at '" + | ||||
| 							pathname + | ||||
| 							"'" | ||||
| 					); | ||||
| 					console.log( | ||||
| 						"echo '" + val /*keyAuthorization*/ + "' > '" + pathname + "'" | ||||
| 					); | ||||
| 					console.log("\nThen hit the 'any' key to continue..."); | ||||
| 				} else if ('dns-01' === cb.type) { | ||||
| 					// forwards-backwards compat
 | ||||
| 					pathname = | ||||
| 						acme2.challengePrefixes['dns-01'] + | ||||
| 						'.' + | ||||
| 						hostname.replace(/^\*\./, ''); | ||||
| 					console.log( | ||||
| 						"Put the string '" + | ||||
| 							cb.dnsAuthorization + | ||||
| 							"' into the TXT record '" + | ||||
| 							pathname + | ||||
| 							"'" | ||||
| 					); | ||||
| 					console.log('dig TXT ' + pathname + " '" + cb.dnsAuthorization + "'"); | ||||
| 					console.log("\nThen hit the 'any' key to continue..."); | ||||
| 				} else { | ||||
| 					cb(new Error('[acme-v2] unrecognized challenge type: ' + cb.type)); | ||||
| 					return; | ||||
| 				} | ||||
| 
 | ||||
|         function onAny() { | ||||
|           console.log("'any' key was hit"); | ||||
|           process.stdin.pause(); | ||||
|           process.stdin.removeListener('data', onAny); | ||||
|           process.stdin.setRawMode(false); | ||||
|           cb(); | ||||
|         } | ||||
| 				function onAny() { | ||||
| 					console.log("'any' key was hit"); | ||||
| 					process.stdin.pause(); | ||||
| 					process.stdin.removeListener('data', onAny); | ||||
| 					process.stdin.setRawMode(false); | ||||
| 					cb(); | ||||
| 				} | ||||
| 
 | ||||
|         process.stdin.setRawMode(true); | ||||
|         process.stdin.resume(); | ||||
|         process.stdin.on('data', onAny); | ||||
|       } | ||||
|     , removeChallenge: function (hostname, key, cb) { | ||||
|         console.log('[DEBUG] remove challenge', hostname, key); | ||||
|         setTimeout(cb, 1 * 1000); | ||||
|       } | ||||
|     , challengeType: chType | ||||
|     , email: email | ||||
|     , accountKeypair: accountKeypair | ||||
|     , domainKeypair: domainKeypair | ||||
|     , domains: web | ||||
|     }; | ||||
| 				process.stdin.setRawMode(true); | ||||
| 				process.stdin.resume(); | ||||
| 				process.stdin.on('data', onAny); | ||||
| 			}, | ||||
| 			removeChallenge: function(hostname, key, cb) { | ||||
| 				console.log('[DEBUG] remove challenge', hostname, key); | ||||
| 				setTimeout(cb, 1 * 1000); | ||||
| 			}, | ||||
| 			challengeType: chType, | ||||
| 			email: email, | ||||
| 			accountKeypair: accountKeypair, | ||||
| 			domainKeypair: domainKeypair, | ||||
| 			domains: web | ||||
| 		}; | ||||
| 
 | ||||
|     acme2.registerNewAccount(options, function (err, account) { | ||||
|       if (err) { console.log('err 2'); throw err; } | ||||
|       if (options.debug) console.debug('account:'); | ||||
|       if (options.debug) console.log(account); | ||||
| 		acme2.registerNewAccount(options, function(err, account) { | ||||
| 			if (err) { | ||||
| 				console.log('err 2'); | ||||
| 				throw err; | ||||
| 			} | ||||
| 			if (options.debug) console.debug('account:'); | ||||
| 			if (options.debug) console.log(account); | ||||
| 
 | ||||
|       acme2.getCertificate(options, function (err, fullchainPem) { | ||||
|         if (err) { console.log('err 3'); throw err; } | ||||
|         console.log('[acme-v2] A fullchain.pem:'); | ||||
|         console.log(fullchainPem); | ||||
|       }); | ||||
|     }); | ||||
|   }); | ||||
| 			acme2.getCertificate(options, function(err, fullchainPem) { | ||||
| 				if (err) { | ||||
| 					console.log('err 3'); | ||||
| 					throw err; | ||||
| 				} | ||||
| 				console.log('[acme-v2] A fullchain.pem:'); | ||||
| 				console.log(fullchainPem); | ||||
| 			}); | ||||
| 		}); | ||||
| 	}); | ||||
| }; | ||||
|  | ||||
| @ -23,59 +23,67 @@ Rules | ||||
| */ | ||||
| 
 | ||||
| // https://github.com/certbot/certbot/issues/5721#issuecomment-402362709
 | ||||
| var expected = "----\nxxxx\nyyyy\n----\n\n----\nxxxx\nyyyy\n----\n"; | ||||
| var expected = '----\nxxxx\nyyyy\n----\n\n----\nxxxx\nyyyy\n----\n'; | ||||
| var tests = [ | ||||
|   "----\r\nxxxx\r\nyyyy\r\n----\r\n\r\n----\r\nxxxx\r\nyyyy\r\n----\r\n" | ||||
| , "----\r\nxxxx\r\nyyyy\r\n----\r\n----\r\nxxxx\r\nyyyy\r\n----\r\n" | ||||
| , "----\nxxxx\nyyyy\n----\n\n----\r\nxxxx\r\nyyyy\r\n----" | ||||
| , "----\nxxxx\nyyyy\n----\n----\r\nxxxx\r\nyyyy\r\n----" | ||||
| , "----\nxxxx\nyyyy\n----\n----\nxxxx\nyyyy\n----" | ||||
| , "----\nxxxx\nyyyy\n----\n----\nxxxx\nyyyy\n----\n" | ||||
| , "----\nxxxx\nyyyy\n----\n\n----\nxxxx\nyyyy\n----\n" | ||||
| , "----\nxxxx\nyyyy\n----\r\n----\nxxxx\ryyyy\n----\n" | ||||
| 	'----\r\nxxxx\r\nyyyy\r\n----\r\n\r\n----\r\nxxxx\r\nyyyy\r\n----\r\n', | ||||
| 	'----\r\nxxxx\r\nyyyy\r\n----\r\n----\r\nxxxx\r\nyyyy\r\n----\r\n', | ||||
| 	'----\nxxxx\nyyyy\n----\n\n----\r\nxxxx\r\nyyyy\r\n----', | ||||
| 	'----\nxxxx\nyyyy\n----\n----\r\nxxxx\r\nyyyy\r\n----', | ||||
| 	'----\nxxxx\nyyyy\n----\n----\nxxxx\nyyyy\n----', | ||||
| 	'----\nxxxx\nyyyy\n----\n----\nxxxx\nyyyy\n----\n', | ||||
| 	'----\nxxxx\nyyyy\n----\n\n----\nxxxx\nyyyy\n----\n', | ||||
| 	'----\nxxxx\nyyyy\n----\r\n----\nxxxx\ryyyy\n----\n' | ||||
| ]; | ||||
| 
 | ||||
| function formatPemChain(str) { | ||||
|   return str.trim().replace(/[\r\n]+/g, '\n').replace(/\-\n\-/g, '-\n\n-') + '\n'; | ||||
| 	return ( | ||||
| 		str | ||||
| 			.trim() | ||||
| 			.replace(/[\r\n]+/g, '\n') | ||||
| 			.replace(/\-\n\-/g, '-\n\n-') + '\n' | ||||
| 	); | ||||
| } | ||||
| function splitPemChain(str) { | ||||
|   return str.trim().split(/[\r\n]{2,}/g).map(function (str) { | ||||
|     return str + '\n'; | ||||
|   }); | ||||
| 	return str | ||||
| 		.trim() | ||||
| 		.split(/[\r\n]{2,}/g) | ||||
| 		.map(function(str) { | ||||
| 			return str + '\n'; | ||||
| 		}); | ||||
| } | ||||
| 
 | ||||
| tests.forEach(function (str) { | ||||
|   var actual = formatPemChain(str); | ||||
|   if (expected !== actual) { | ||||
|     console.error('input:   ', JSON.stringify(str)); | ||||
|     console.error('expected:', JSON.stringify(expected)); | ||||
|     console.error('actual:  ', JSON.stringify(actual)); | ||||
|     throw new Error("did not pass"); | ||||
|   } | ||||
| tests.forEach(function(str) { | ||||
| 	var actual = formatPemChain(str); | ||||
| 	if (expected !== actual) { | ||||
| 		console.error('input:   ', JSON.stringify(str)); | ||||
| 		console.error('expected:', JSON.stringify(expected)); | ||||
| 		console.error('actual:  ', JSON.stringify(actual)); | ||||
| 		throw new Error('did not pass'); | ||||
| 	} | ||||
| }); | ||||
| 
 | ||||
| if ( | ||||
|   "----\nxxxx\nyyyy\n----\n" | ||||
|   !== | ||||
|   formatPemChain("\n\n----\r\nxxxx\r\nyyyy\r\n----\n\n") | ||||
| 	'----\nxxxx\nyyyy\n----\n' !== | ||||
| 	formatPemChain('\n\n----\r\nxxxx\r\nyyyy\r\n----\n\n') | ||||
| ) { | ||||
|   throw new Error("Not proper for single cert in chain"); | ||||
| 	throw new Error('Not proper for single cert in chain'); | ||||
| } | ||||
| 
 | ||||
| if ( | ||||
|   "--B--\nxxxx\nyyyy\n--E--\n\n--B--\nxxxx\nyyyy\n--E--\n\n--B--\nxxxx\nyyyy\n--E--\n" | ||||
|   !== | ||||
|   formatPemChain("\n\n\n--B--\nxxxx\nyyyy\n--E--\n\n\n\n--B--\nxxxx\nyyyy\n--E--\n\n\n--B--\nxxxx\nyyyy\n--E--\n\n\n") | ||||
| 	'--B--\nxxxx\nyyyy\n--E--\n\n--B--\nxxxx\nyyyy\n--E--\n\n--B--\nxxxx\nyyyy\n--E--\n' !== | ||||
| 	formatPemChain( | ||||
| 		'\n\n\n--B--\nxxxx\nyyyy\n--E--\n\n\n\n--B--\nxxxx\nyyyy\n--E--\n\n\n--B--\nxxxx\nyyyy\n--E--\n\n\n' | ||||
| 	) | ||||
| ) { | ||||
|   throw new Error("Not proper for three certs in chain"); | ||||
| 	throw new Error('Not proper for three certs in chain'); | ||||
| } | ||||
| 
 | ||||
| splitPemChain( | ||||
|   "--B--\nxxxx\nyyyy\n--E--\n\n--B--\nxxxx\nyyyy\n--E--\n\n--B--\nxxxx\nyyyy\n--E--\n" | ||||
| ).forEach(function (str) { | ||||
|   if ("--B--\nxxxx\nyyyy\n--E--\n" !== str) { | ||||
|     throw new Error("bad thingy"); | ||||
|   } | ||||
| 	'--B--\nxxxx\nyyyy\n--E--\n\n--B--\nxxxx\nyyyy\n--E--\n\n--B--\nxxxx\nyyyy\n--E--\n' | ||||
| ).forEach(function(str) { | ||||
| 	if ('--B--\nxxxx\nyyyy\n--E--\n' !== str) { | ||||
| 		throw new Error('bad thingy'); | ||||
| 	} | ||||
| }); | ||||
| 
 | ||||
| console.info('PASS'); | ||||
|  | ||||
							
								
								
									
										185
									
								
								tests/promise.js
									
									
									
									
									
								
							
							
						
						
									
										185
									
								
								tests/promise.js
									
									
									
									
									
								
							| @ -5,85 +5,120 @@ | ||||
| 'use strict'; | ||||
| 
 | ||||
| /* global Promise */ | ||||
| module.exports.run = function run(directoryUrl, RSA, web, chType, email, accountKeypair, domainKeypair) { | ||||
|   var acme2 = require('../').ACME.create({ RSA: RSA }); | ||||
|   // [ 'test.ppl.family' ] 'coolaj86@gmail.com''http-01'
 | ||||
|   acme2.init(directoryUrl).then(function () { | ||||
|     var options = { | ||||
|       agreeToTerms: function (tosUrl) { | ||||
|         return Promise.resolve(tosUrl); | ||||
|       } | ||||
|     , setChallenge: function (opts) { | ||||
|         return new Promise(function (resolve, reject) { | ||||
|           var pathname; | ||||
| module.exports.run = function run( | ||||
| 	directoryUrl, | ||||
| 	RSA, | ||||
| 	web, | ||||
| 	chType, | ||||
| 	email, | ||||
| 	accountKeypair, | ||||
| 	domainKeypair | ||||
| ) { | ||||
| 	var acme2 = require('../').ACME.create({ RSA: RSA }); | ||||
| 	// [ 'test.ppl.family' ] 'coolaj86@gmail.com''http-01'
 | ||||
| 	acme2.init(directoryUrl).then(function() { | ||||
| 		var options = { | ||||
| 			agreeToTerms: function(tosUrl) { | ||||
| 				return Promise.resolve(tosUrl); | ||||
| 			}, | ||||
| 			setChallenge: function(opts) { | ||||
| 				return new Promise(function(resolve, reject) { | ||||
| 					var pathname; | ||||
| 
 | ||||
|           console.log(""); | ||||
|           console.log('identifier:'); | ||||
|           console.log(opts.identifier); | ||||
|           console.log('hostname:'); | ||||
|           console.log(opts.hostname); | ||||
|           console.log('type:'); | ||||
|           console.log(opts.type); | ||||
|           console.log('token:'); | ||||
|           console.log(opts.token); | ||||
|           console.log('thumbprint:'); | ||||
|           console.log(opts.thumbprint); | ||||
|           console.log('keyAuthorization:'); | ||||
|           console.log(opts.keyAuthorization); | ||||
|           console.log('dnsAuthorization:'); | ||||
|           console.log(opts.dnsAuthorization); | ||||
|           console.log(""); | ||||
| 					console.log(''); | ||||
| 					console.log('identifier:'); | ||||
| 					console.log(opts.identifier); | ||||
| 					console.log('hostname:'); | ||||
| 					console.log(opts.hostname); | ||||
| 					console.log('type:'); | ||||
| 					console.log(opts.type); | ||||
| 					console.log('token:'); | ||||
| 					console.log(opts.token); | ||||
| 					console.log('thumbprint:'); | ||||
| 					console.log(opts.thumbprint); | ||||
| 					console.log('keyAuthorization:'); | ||||
| 					console.log(opts.keyAuthorization); | ||||
| 					console.log('dnsAuthorization:'); | ||||
| 					console.log(opts.dnsAuthorization); | ||||
| 					console.log(''); | ||||
| 
 | ||||
|           if ('http-01' === opts.type) { | ||||
|             pathname = opts.hostname + acme2.challengePrefixes['http-01'] + "/" + opts.token; | ||||
|             console.log("Put the string '" + opts.keyAuthorization + "' into a file at '" + pathname + "'"); | ||||
|             console.log("echo '" + opts.keyAuthorization + "' > '" + pathname + "'"); | ||||
|           } else if ('dns-01' === opts.type) { | ||||
|             pathname = acme2.challengePrefixes['dns-01'] + "." + opts.hostname.replace(/^\*\./, ''); | ||||
|             console.log("Put the string '" + opts.dnsAuthorization + "' into the TXT record '" + pathname + "'"); | ||||
|             console.log("dig TXT " + pathname + " '" + opts.dnsAuthorization + "'"); | ||||
|           } else { | ||||
|             reject(new Error("[acme-v2] unrecognized challenge type")); | ||||
|             return; | ||||
|           } | ||||
|           console.log("\nThen hit the 'any' key to continue..."); | ||||
| 					if ('http-01' === opts.type) { | ||||
| 						pathname = | ||||
| 							opts.hostname + | ||||
| 							acme2.challengePrefixes['http-01'] + | ||||
| 							'/' + | ||||
| 							opts.token; | ||||
| 						console.log( | ||||
| 							"Put the string '" + | ||||
| 								opts.keyAuthorization + | ||||
| 								"' into a file at '" + | ||||
| 								pathname + | ||||
| 								"'" | ||||
| 						); | ||||
| 						console.log( | ||||
| 							"echo '" + opts.keyAuthorization + "' > '" + pathname + "'" | ||||
| 						); | ||||
| 					} else if ('dns-01' === opts.type) { | ||||
| 						pathname = | ||||
| 							acme2.challengePrefixes['dns-01'] + | ||||
| 							'.' + | ||||
| 							opts.hostname.replace(/^\*\./, ''); | ||||
| 						console.log( | ||||
| 							"Put the string '" + | ||||
| 								opts.dnsAuthorization + | ||||
| 								"' into the TXT record '" + | ||||
| 								pathname + | ||||
| 								"'" | ||||
| 						); | ||||
| 						console.log( | ||||
| 							'dig TXT ' + pathname + " '" + opts.dnsAuthorization + "'" | ||||
| 						); | ||||
| 					} else { | ||||
| 						reject(new Error('[acme-v2] unrecognized challenge type')); | ||||
| 						return; | ||||
| 					} | ||||
| 					console.log("\nThen hit the 'any' key to continue..."); | ||||
| 
 | ||||
|           function onAny() { | ||||
|             console.log("'any' key was hit"); | ||||
|             process.stdin.pause(); | ||||
|             process.stdin.removeListener('data', onAny); | ||||
|             process.stdin.setRawMode(false); | ||||
|             resolve(); | ||||
|             return; | ||||
|           } | ||||
| 					function onAny() { | ||||
| 						console.log("'any' key was hit"); | ||||
| 						process.stdin.pause(); | ||||
| 						process.stdin.removeListener('data', onAny); | ||||
| 						process.stdin.setRawMode(false); | ||||
| 						resolve(); | ||||
| 						return; | ||||
| 					} | ||||
| 
 | ||||
|           process.stdin.setRawMode(true); | ||||
|           process.stdin.resume(); | ||||
|           process.stdin.on('data', onAny); | ||||
|         }); | ||||
|       } | ||||
|     , removeChallenge: function (opts) { | ||||
|         console.log('[acme-v2] remove challenge', opts.hostname, opts.keyAuthorization); | ||||
|         return new Promise(function (resolve) { | ||||
|           // hostname, key
 | ||||
|           setTimeout(resolve, 1 * 1000); | ||||
|         }); | ||||
|       } | ||||
|     , challengeType: chType | ||||
|     , email: email | ||||
|     , accountKeypair: accountKeypair | ||||
|     , domainKeypair: domainKeypair | ||||
|     , domains: web | ||||
|     }; | ||||
| 					process.stdin.setRawMode(true); | ||||
| 					process.stdin.resume(); | ||||
| 					process.stdin.on('data', onAny); | ||||
| 				}); | ||||
| 			}, | ||||
| 			removeChallenge: function(opts) { | ||||
| 				console.log( | ||||
| 					'[acme-v2] remove challenge', | ||||
| 					opts.hostname, | ||||
| 					opts.keyAuthorization | ||||
| 				); | ||||
| 				return new Promise(function(resolve) { | ||||
| 					// hostname, key
 | ||||
| 					setTimeout(resolve, 1 * 1000); | ||||
| 				}); | ||||
| 			}, | ||||
| 			challengeType: chType, | ||||
| 			email: email, | ||||
| 			accountKeypair: accountKeypair, | ||||
| 			domainKeypair: domainKeypair, | ||||
| 			domains: web | ||||
| 		}; | ||||
| 
 | ||||
|     acme2.accounts.create(options).then(function (account) { | ||||
|       console.log('[acme-v2] account:'); | ||||
|       console.log(account); | ||||
| 		acme2.accounts.create(options).then(function(account) { | ||||
| 			console.log('[acme-v2] account:'); | ||||
| 			console.log(account); | ||||
| 
 | ||||
|       acme2.certificates.create(options).then(function (fullchainPem) { | ||||
|         console.log('[acme-v2] fullchain.pem:'); | ||||
|         console.log(fullchainPem); | ||||
|       }); | ||||
|     }); | ||||
|   }); | ||||
| 			acme2.certificates.create(options).then(function(fullchainPem) { | ||||
| 				console.log('[acme-v2] fullchain.pem:'); | ||||
| 				console.log(fullchainPem); | ||||
| 			}); | ||||
| 		}); | ||||
| 	}); | ||||
| }; | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user