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 leCore = require('letiny-core'); | ||||
| var merge = require('./lib/common').merge; | ||||
| var tplHostname = require('./lib/common').tplHostname; | ||||
| var tplCopy = require('./lib/common').tplCopy; | ||||
| 
 | ||||
| var LE = module.exports; | ||||
| LE.productionServerUrl = leCore.productionServerUrl; | ||||
| @ -58,7 +58,7 @@ LE.create = function (defaults, handlers, backend) { | ||||
|       var getChallenge = require('./lib/default-handlers').getChallenge; | ||||
|       var copy = merge(defaults, { domains: [hostname] }); | ||||
| 
 | ||||
|       tplHostname(hostname, copy); | ||||
|       tplCopy(copy); | ||||
|       defaultos.domains = [hostname]; | ||||
| 
 | ||||
|       if (3 === getChallenge.length) { | ||||
| @ -158,9 +158,13 @@ LE.create = function (defaults, handlers, backend) { | ||||
|           return; | ||||
|         } | ||||
| 
 | ||||
|         //console.log("[NLE]: begin registration");
 | ||||
|         if (args.debug) { | ||||
|           console.log("[NLE]: begin registration"); | ||||
|         } | ||||
|         return backend.registerAsync(copy).then(function (pems) { | ||||
|           //console.log("[NLE]: end registration");
 | ||||
|           if (args.debug) { | ||||
|             console.log("[NLE]: end registration"); | ||||
|           } | ||||
|           cb(null, pems); | ||||
|           //return le.fetch(args, cb);
 | ||||
|         }, cb); | ||||
|  | ||||
| @ -13,7 +13,7 @@ function createAccount(args, handlers) { | ||||
| 
 | ||||
|   // TODO support ECDSA
 | ||||
|   // 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 } */ | ||||
| 
 | ||||
|     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
 | ||||
|   // just one email address, that could get crazy.
 | ||||
|   // We should have a folder per email and list
 | ||||
|   // each account as a file in the folder
 | ||||
|   // 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.createAccount = createAccount; | ||||
|  | ||||
| @ -45,12 +45,23 @@ module.exports.merge = function merge(defaults, args) { | ||||
|   return copy; | ||||
| }; | ||||
| 
 | ||||
| module.exports.tplHostname = function merge(hostname, copy) { | ||||
| module.exports.tplCopy = function merge(copy) { | ||||
|   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) { | ||||
|     if ('string' === typeof copy[key]) { | ||||
|       copy[key] = copy[key].replace(':hostname', hostname).replace(':host', hostname); | ||||
|       copy[key] = copy[key].replace(homeRe, homedir + path.sep); | ||||
|       Object.keys(tpls).sort(function (a, b) { | ||||
|         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 merge = require('./common').merge; | ||||
| var tplHostname = require('./common').tplHostname; | ||||
| var tplCopy = require('./common').tplCopy; | ||||
| var fetchFromConfigLiveDir = require('./common').fetchFromDisk; | ||||
| 
 | ||||
| var ipc = {}; // in-process cache
 | ||||
| @ -34,7 +34,7 @@ function getAcmeUrls(args) { | ||||
| 
 | ||||
| 
 | ||||
| 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) { | ||||
|       console.log("get certificate"); | ||||
|     } | ||||
| @ -58,7 +58,7 @@ function getCertificateAsync(account, args, defaults, handlers) { | ||||
|       //
 | ||||
|     , setChallenge: function (domain, key, value, done) { | ||||
|         var copy = merge(defaults, { domains: [domain] }); | ||||
|         tplHostname(domain, copy); | ||||
|         tplCopy(copy); | ||||
| 
 | ||||
|         args.domains = [domain]; | ||||
|         args.webrootPath = args.webrootPath; | ||||
| @ -74,7 +74,7 @@ function getCertificateAsync(account, args, defaults, handlers) { | ||||
|       } | ||||
|     , removeChallenge: function (domain, key, done) { | ||||
|         var copy = merge(defaults, { domains: [domain] }); | ||||
|         tplHostname(domain, copy); | ||||
|         tplCopy(copy); | ||||
| 
 | ||||
|         if (3 === handlers.removeChallenge.length) { | ||||
|           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 server = args.server; | ||||
|   var acmeHostname = require('url').parse(server).hostname; | ||||
| @ -220,18 +248,28 @@ function registerWithAcme(args, defaults, handlers) { | ||||
|     return accountId; | ||||
|   }, function (err) { | ||||
|     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); | ||||
|   }).then(function (accountId) { | ||||
| 
 | ||||
|     // Note: the ACME urls are always fetched fresh on purpose
 | ||||
|     return getAcmeUrls(args).then(function (urls) { | ||||
|       args._acmeUrls = urls; | ||||
| 
 | ||||
|       if (accountId) { | ||||
|         if (args.debug) { | ||||
|           console.log('[LE] use account'); | ||||
|         } | ||||
|         return Accounts.getAccount(accountId, args, handlers); | ||||
|       } else { | ||||
|         if (args.debug) { | ||||
|           console.log('[LE] create account'); | ||||
|         } | ||||
|         return Accounts.createAccount(args, handlers); | ||||
|       } | ||||
|     }); | ||||
| @ -242,33 +280,6 @@ function registerWithAcme(args, defaults, handlers) { | ||||
|       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) { | ||||
| @ -293,16 +304,18 @@ module.exports.create = function (defaults, handlers) { | ||||
|       // So :config/accounts/:server/directory is *incorrect*, but the following *is* correct:
 | ||||
|       args.accountsDir = args.accountsDir || ':config/accounts/:server'; | ||||
|       copy = merge(args, defaults); | ||||
|       tplHostname(args.domains[0], copy); | ||||
|       tplCopy(copy); | ||||
| 
 | ||||
|       if (args.debug) { | ||||
|         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) { | ||||
|       var copy = merge(args, defaults); | ||||
|       tplHostname(args.domains[0], copy); | ||||
|       tplCopy(copy); | ||||
| 
 | ||||
|       if (args.debug) { | ||||
|         console.log('[LE DEBUG] fetch domains', copy); | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user