mirror of
				https://github.com/therootcompany/greenlock.js.git
				synced 2024-11-16 17:29:00 +00:00 
			
		
		
		
	multiple bugfixes and enhancements for accounts
This commit is contained in:
		
							parent
							
								
									3a1f66f9e2
								
							
						
					
					
						commit
						dad8249d5f
					
				
							
								
								
									
										12
									
								
								index.js
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								index.js
									
									
									
									
									
								
							| @ -5,7 +5,7 @@ | |||||||
| var PromiseA = require('bluebird'); | var PromiseA = require('bluebird'); | ||||||
| var leCore = require('letiny-core'); | var leCore = require('letiny-core'); | ||||||
| var merge = require('./lib/common').merge; | var merge = require('./lib/common').merge; | ||||||
| var tplHostname = require('./lib/common').tplHostname; | var tplCopy = require('./lib/common').tplCopy; | ||||||
| 
 | 
 | ||||||
| var LE = module.exports; | var LE = module.exports; | ||||||
| LE.productionServerUrl = leCore.productionServerUrl; | LE.productionServerUrl = leCore.productionServerUrl; | ||||||
| @ -58,7 +58,7 @@ LE.create = function (defaults, handlers, backend) { | |||||||
|       var getChallenge = require('./lib/default-handlers').getChallenge; |       var getChallenge = require('./lib/default-handlers').getChallenge; | ||||||
|       var copy = merge(defaults, { domains: [hostname] }); |       var copy = merge(defaults, { domains: [hostname] }); | ||||||
| 
 | 
 | ||||||
|       tplHostname(hostname, copy); |       tplCopy(copy); | ||||||
|       defaultos.domains = [hostname]; |       defaultos.domains = [hostname]; | ||||||
| 
 | 
 | ||||||
|       if (3 === getChallenge.length) { |       if (3 === getChallenge.length) { | ||||||
| @ -158,9 +158,13 @@ LE.create = function (defaults, handlers, backend) { | |||||||
|           return; |           return; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         //console.log("[NLE]: begin registration");
 |         if (args.debug) { | ||||||
|  |           console.log("[NLE]: begin registration"); | ||||||
|  |         } | ||||||
|         return backend.registerAsync(copy).then(function (pems) { |         return backend.registerAsync(copy).then(function (pems) { | ||||||
|           //console.log("[NLE]: end registration");
 |           if (args.debug) { | ||||||
|  |             console.log("[NLE]: end registration"); | ||||||
|  |           } | ||||||
|           cb(null, pems); |           cb(null, pems); | ||||||
|           //return le.fetch(args, cb);
 |           //return le.fetch(args, cb);
 | ||||||
|         }, cb); |         }, cb); | ||||||
|  | |||||||
| @ -13,7 +13,7 @@ function createAccount(args, handlers) { | |||||||
| 
 | 
 | ||||||
|   // TODO support ECDSA
 |   // TODO support ECDSA
 | ||||||
|   // arg.rsaBitLength args.rsaExponent
 |   // arg.rsaBitLength args.rsaExponent
 | ||||||
|   return leCrypto.generateRsaKeypairAsync(args.rsaBitLength, args.rsaExponent).then(function (pems) { |   return leCrypto.generateRsaKeypairAsync(args.rsaKeySize, 65537).then(function (pems) { | ||||||
|     /* pems = { privateKeyPem, privateKeyJwk, publicKeyPem, publicKeyMd5, publicKeySha256 } */ |     /* pems = { privateKeyPem, privateKeyJwk, publicKeyPem, publicKeyMd5, publicKeySha256 } */ | ||||||
| 
 | 
 | ||||||
|     return LeCore.registerNewAccountAsync({ |     return LeCore.registerNewAccountAsync({ | ||||||
| @ -117,15 +117,69 @@ function getAccount(accountId, args, handlers) { | |||||||
|   }); |   }); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| function getAccountByEmail(/*args*/) { | function getAccountIdByEmail(args, handlers) { | ||||||
|   // If we read 10,000 account directories looking for
 |   // If we read 10,000 account directories looking for
 | ||||||
|   // just one email address, that could get crazy.
 |   // just one email address, that could get crazy.
 | ||||||
|   // We should have a folder per email and list
 |   // We should have a folder per email and list
 | ||||||
|   // each account as a file in the folder
 |   // each account as a file in the folder
 | ||||||
|   // TODO
 |   // TODO
 | ||||||
|   return PromiseA.resolve(null); |   var email = args.email; | ||||||
|  |   if ('string' !== typeof email) { | ||||||
|  |     if (args.debug) { | ||||||
|  |       console.log("[LE] No email given"); | ||||||
|  |     } | ||||||
|  |     return PromiseA.resolve(null); | ||||||
|  |   } | ||||||
|  |   return fs.readdirAsync(args.accountsDir).then(function (nodes) { | ||||||
|  |     if (args.debug) { | ||||||
|  |       console.log("[LE] arg.accountsDir success"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return PromiseA.all(nodes.map(function (node) { | ||||||
|  |       return fs.readFileAsync(path.join(args.accountsDir, node, 'regr.json'), 'utf8').then(function (text) { | ||||||
|  |         var regr = JSON.parse(text); | ||||||
|  |         regr.__accountId = node; | ||||||
|  | 
 | ||||||
|  |         return regr; | ||||||
|  |       }); | ||||||
|  |     })).then(function (regrs) { | ||||||
|  |       var accountId; | ||||||
|  | 
 | ||||||
|  |       /* | ||||||
|  |       if (args.debug) { | ||||||
|  |         console.log('read many regrs'); | ||||||
|  |         console.log('regrs', regrs); | ||||||
|  |       } | ||||||
|  |       */ | ||||||
|  | 
 | ||||||
|  |       regrs.some(function (regr) { | ||||||
|  |         return regr.body.contact.some(function (contact) { | ||||||
|  |           var match = contact.toLowerCase() === 'mailto:' + email.toLowerCase(); | ||||||
|  |           if (match) { | ||||||
|  |             accountId = regr.__accountId; | ||||||
|  |             return true; | ||||||
|  |           } | ||||||
|  |         }); | ||||||
|  |       }); | ||||||
|  | 
 | ||||||
|  |       if (!accountId) { | ||||||
|  |         return null; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       return accountId; | ||||||
|  |     }); | ||||||
|  |   }).then(function (accountId) { | ||||||
|  |     return accountId; | ||||||
|  |   }, function (err) { | ||||||
|  |     if ('ENOENT' == err.code) { | ||||||
|  |       // ignore error
 | ||||||
|  |       return null; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return PromiseA.reject(err); | ||||||
|  |   }); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| module.exports.getAccountByEmail = getAccountByEmail; | module.exports.getAccountIdByEmail = getAccountIdByEmail; | ||||||
| module.exports.getAccount = getAccount; | module.exports.getAccount = getAccount; | ||||||
| module.exports.createAccount = createAccount; | module.exports.createAccount = createAccount; | ||||||
|  | |||||||
| @ -45,12 +45,23 @@ module.exports.merge = function merge(defaults, args) { | |||||||
|   return copy; |   return copy; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| module.exports.tplHostname = function merge(hostname, copy) { | module.exports.tplCopy = function merge(copy) { | ||||||
|   var homedir = require('homedir')(); |   var homedir = require('homedir')(); | ||||||
|  |   var tpls = { | ||||||
|  |     hostname: (copy.domains || [])[0] | ||||||
|  |   , server: (copy.server || '').replace('https://', '').replace(/(\/)$/, '') | ||||||
|  |   , conf: copy.configDir | ||||||
|  |   , config: copy.configDir | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|   Object.keys(copy).forEach(function (key) { |   Object.keys(copy).forEach(function (key) { | ||||||
|     if ('string' === typeof copy[key]) { |     if ('string' === typeof copy[key]) { | ||||||
|       copy[key] = copy[key].replace(':hostname', hostname).replace(':host', hostname); |       Object.keys(tpls).sort(function (a, b) { | ||||||
|       copy[key] = copy[key].replace(homeRe, homedir + path.sep); |         return b.length - a.length; | ||||||
|  |       }).forEach(function (tplname) { | ||||||
|  |         copy[key] = copy[key].replace(':' + tplname, tpls[tplname]); | ||||||
|  |         copy[key] = copy[key].replace(homeRe, homedir + path.sep); | ||||||
|  |       }); | ||||||
|     } |     } | ||||||
|   }); |   }); | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										85
									
								
								lib/core.js
									
									
									
									
									
								
							
							
						
						
									
										85
									
								
								lib/core.js
									
									
									
									
									
								
							| @ -10,7 +10,7 @@ var leCrypto = PromiseA.promisifyAll(LeCore.leCrypto); | |||||||
| var Accounts = require('./accounts'); | var Accounts = require('./accounts'); | ||||||
| 
 | 
 | ||||||
| var merge = require('./common').merge; | var merge = require('./common').merge; | ||||||
| var tplHostname = require('./common').tplHostname; | var tplCopy = require('./common').tplCopy; | ||||||
| var fetchFromConfigLiveDir = require('./common').fetchFromDisk; | var fetchFromConfigLiveDir = require('./common').fetchFromDisk; | ||||||
| 
 | 
 | ||||||
| var ipc = {}; // in-process cache
 | var ipc = {}; // in-process cache
 | ||||||
| @ -34,7 +34,7 @@ function getAcmeUrls(args) { | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| function getCertificateAsync(account, args, defaults, handlers) { | function getCertificateAsync(account, args, defaults, handlers) { | ||||||
|   return leCrypto.generateRsaKeypairAsync(args.rsaKeySize, args.rsaExponent).then(function (domainKey) { |   return leCrypto.generateRsaKeypairAsync(args.rsaKeySize, 65537).then(function (domainKey) { | ||||||
|     if (args.debug) { |     if (args.debug) { | ||||||
|       console.log("get certificate"); |       console.log("get certificate"); | ||||||
|     } |     } | ||||||
| @ -58,7 +58,7 @@ function getCertificateAsync(account, args, defaults, handlers) { | |||||||
|       //
 |       //
 | ||||||
|     , setChallenge: function (domain, key, value, done) { |     , setChallenge: function (domain, key, value, done) { | ||||||
|         var copy = merge(defaults, { domains: [domain] }); |         var copy = merge(defaults, { domains: [domain] }); | ||||||
|         tplHostname(domain, copy); |         tplCopy(copy); | ||||||
| 
 | 
 | ||||||
|         args.domains = [domain]; |         args.domains = [domain]; | ||||||
|         args.webrootPath = args.webrootPath; |         args.webrootPath = args.webrootPath; | ||||||
| @ -74,7 +74,7 @@ function getCertificateAsync(account, args, defaults, handlers) { | |||||||
|       } |       } | ||||||
|     , removeChallenge: function (domain, key, done) { |     , removeChallenge: function (domain, key, done) { | ||||||
|         var copy = merge(defaults, { domains: [domain] }); |         var copy = merge(defaults, { domains: [domain] }); | ||||||
|         tplHostname(domain, copy); |         tplCopy(copy); | ||||||
| 
 | 
 | ||||||
|         if (3 === handlers.removeChallenge.length) { |         if (3 === handlers.removeChallenge.length) { | ||||||
|           handlers.removeChallenge(copy, key, done); |           handlers.removeChallenge(copy, key, done); | ||||||
| @ -204,7 +204,35 @@ function getCertificateAsync(account, args, defaults, handlers) { | |||||||
|   }); |   }); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| function registerWithAcme(args, defaults, handlers) { | function getOrCreateDomainCertificate(account, args, defaults, hanlers) { | ||||||
|  |   return fetchFromConfigLiveDir(args).then(function (certs) { | ||||||
|  |     // if nothing, register and save
 | ||||||
|  |     // if something, check date (don't register unless 30+ days)
 | ||||||
|  |     // if good, don't bother registering
 | ||||||
|  |     // (but if we get to the point that we're actually calling
 | ||||||
|  |     // this function, that shouldn't be the case, right?)
 | ||||||
|  |     //console.log(certs);
 | ||||||
|  |     if (!certs) { | ||||||
|  |       // no certs, seems like a good time to get some
 | ||||||
|  |       return getCertificateAsync(account, args, defaults, handlers); | ||||||
|  |     } | ||||||
|  |     else if (certs.issuedAt > (27 * 24 * 60 * 60 * 1000)) { | ||||||
|  |       // cert is at least 27 days old we can renew that
 | ||||||
|  |       return getCertificateAsync(account, args, defaults, handlers); | ||||||
|  |     } | ||||||
|  |     else if (args.duplicate) { | ||||||
|  |       // YOLO! I be gettin' fresh certs 'erday! Yo!
 | ||||||
|  |       return getCertificateAsync(account, args, defaults, handlers); | ||||||
|  |     } | ||||||
|  |     else { | ||||||
|  |       console.warn('[WARN] Ignoring renewal attempt for certificate less than 27 days old. Use args.duplicate to force.'); | ||||||
|  |       // We're happy with what we have
 | ||||||
|  |       return certs; | ||||||
|  |     } | ||||||
|  |   }); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | function getOrCreateAcmeAccount(args, defaults, handlers) { | ||||||
|   var pyconf = PromiseA.promisifyAll(require('pyconf')); |   var pyconf = PromiseA.promisifyAll(require('pyconf')); | ||||||
|   var server = args.server; |   var server = args.server; | ||||||
|   var acmeHostname = require('url').parse(server).hostname; |   var acmeHostname = require('url').parse(server).hostname; | ||||||
| @ -220,18 +248,28 @@ function registerWithAcme(args, defaults, handlers) { | |||||||
|     return accountId; |     return accountId; | ||||||
|   }, function (err) { |   }, function (err) { | ||||||
|     if ("ENOENT" === err.code) { |     if ("ENOENT" === err.code) { | ||||||
|       return Accounts.getAccountByEmail(args, handlers); |       if (args.debug) { | ||||||
|  |         console.log("[LE] try email"); | ||||||
|  |       } | ||||||
|  |       return Accounts.getAccountIdByEmail(args, handlers); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     return PromiseA.reject(err); |     return PromiseA.reject(err); | ||||||
|   }).then(function (accountId) { |   }).then(function (accountId) { | ||||||
|  | 
 | ||||||
|     // Note: the ACME urls are always fetched fresh on purpose
 |     // Note: the ACME urls are always fetched fresh on purpose
 | ||||||
|     return getAcmeUrls(args).then(function (urls) { |     return getAcmeUrls(args).then(function (urls) { | ||||||
|       args._acmeUrls = urls; |       args._acmeUrls = urls; | ||||||
| 
 | 
 | ||||||
|       if (accountId) { |       if (accountId) { | ||||||
|  |         if (args.debug) { | ||||||
|  |           console.log('[LE] use account'); | ||||||
|  |         } | ||||||
|         return Accounts.getAccount(accountId, args, handlers); |         return Accounts.getAccount(accountId, args, handlers); | ||||||
|       } else { |       } else { | ||||||
|  |         if (args.debug) { | ||||||
|  |           console.log('[LE] create account'); | ||||||
|  |         } | ||||||
|         return Accounts.createAccount(args, handlers); |         return Accounts.createAccount(args, handlers); | ||||||
|       } |       } | ||||||
|     }); |     }); | ||||||
| @ -242,33 +280,6 @@ function registerWithAcme(args, defaults, handlers) { | |||||||
|       return; |       return; | ||||||
|     } |     } | ||||||
|     */ |     */ | ||||||
| 
 |  | ||||||
|     //console.log(account);
 |  | ||||||
|     return fetchFromConfigLiveDir(args).then(function (certs) { |  | ||||||
|       // if nothing, register and save
 |  | ||||||
|       // if something, check date (don't register unless 30+ days)
 |  | ||||||
|       // if good, don't bother registering
 |  | ||||||
|       // (but if we get to the point that we're actually calling
 |  | ||||||
|       // this function, that shouldn't be the case, right?)
 |  | ||||||
|       //console.log(certs);
 |  | ||||||
|       if (!certs) { |  | ||||||
|         // no certs, seems like a good time to get some
 |  | ||||||
|         return getCertificateAsync(account, args, defaults, handlers); |  | ||||||
|       } |  | ||||||
|       else if (certs.issuedAt > (27 * 24 * 60 * 60 * 1000)) { |  | ||||||
|         // cert is at least 27 days old we can renew that
 |  | ||||||
|         return getCertificateAsync(account, args, defaults, handlers); |  | ||||||
|       } |  | ||||||
|       else if (args.duplicate) { |  | ||||||
|         // YOLO! I be gettin' fresh certs 'erday! Yo!
 |  | ||||||
|         return getCertificateAsync(account, args, defaults, handlers); |  | ||||||
|       } |  | ||||||
|       else { |  | ||||||
|         console.warn('[WARN] Ignoring renewal attempt for certificate less than 27 days old. Use args.duplicate to force.'); |  | ||||||
|         // We're happy with what we have
 |  | ||||||
|         return certs; |  | ||||||
|       } |  | ||||||
|     }); |  | ||||||
|   }); |   }); | ||||||
| /* | /* | ||||||
|   return fs.readdirAsync(accountsDir, function (nodes) { |   return fs.readdirAsync(accountsDir, function (nodes) { | ||||||
| @ -293,16 +304,18 @@ module.exports.create = function (defaults, handlers) { | |||||||
|       // So :config/accounts/:server/directory is *incorrect*, but the following *is* correct:
 |       // So :config/accounts/:server/directory is *incorrect*, but the following *is* correct:
 | ||||||
|       args.accountsDir = args.accountsDir || ':config/accounts/:server'; |       args.accountsDir = args.accountsDir || ':config/accounts/:server'; | ||||||
|       copy = merge(args, defaults); |       copy = merge(args, defaults); | ||||||
|       tplHostname(args.domains[0], copy); |       tplCopy(copy); | ||||||
| 
 | 
 | ||||||
|       if (args.debug) { |       if (args.debug) { | ||||||
|         console.log('[LE DEBUG] reg domains', args.domains); |         console.log('[LE DEBUG] reg domains', args.domains); | ||||||
|       } |       } | ||||||
|       return registerWithAcme(copy, defaults, handlers); |       return getOrCreateAcmeAccount(copy, defaults, handlers).then(function (account) { | ||||||
|  |         return getOrCreateDomainCertificate(account, copy, defaults, handlers); | ||||||
|  |       }); | ||||||
|     } |     } | ||||||
|   , fetchAsync: function (args) { |   , fetchAsync: function (args) { | ||||||
|       var copy = merge(args, defaults); |       var copy = merge(args, defaults); | ||||||
|       tplHostname(args.domains[0], copy); |       tplCopy(copy); | ||||||
| 
 | 
 | ||||||
|       if (args.debug) { |       if (args.debug) { | ||||||
|         console.log('[LE DEBUG] fetch domains', copy); |         console.log('[LE DEBUG] fetch domains', copy); | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user