close #9 write rewenal config files
This commit is contained in:
		
							parent
							
								
									873e8ea89f
								
							
						
					
					
						commit
						77f54981c5
					
				| @ -14,7 +14,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.rsaBitLength, args.rsaExponent).then(function (pems) { | ||||||
|     /* pems = { privateKeyPem, privateKeyJwk, publicKeyPem, publicKeyMd5 } */ |     /* pems = { privateKeyPem, privateKeyJwk, publicKeyPem, publicKeyMd5, publicKeySha256 } */ | ||||||
| 
 | 
 | ||||||
|     return LeCore.registerNewAccountAsync({ |     return LeCore.registerNewAccountAsync({ | ||||||
|       email: args.email |       email: args.email | ||||||
| @ -28,7 +28,13 @@ function createAccount(args, handlers) { | |||||||
| 
 | 
 | ||||||
|     , debug: args.debug || handlers.debug |     , debug: args.debug || handlers.debug | ||||||
|     }).then(function (body) { |     }).then(function (body) { | ||||||
|       var accountDir = path.join(args.accountsDir, pems.publicKeyMd5); |       // TODO XXX use sha256
 | ||||||
|  |       var accountId = pems.publicKeyMd5; | ||||||
|  |       var accountDir = path.join(args.accountsDir, accountId); | ||||||
|  |       var regr = { body: body }; | ||||||
|  | 
 | ||||||
|  |       args.accountId = accountId; | ||||||
|  |       args.accountDir = accountDir; | ||||||
| 
 | 
 | ||||||
|       return mkdirpAsync(accountDir).then(function () { |       return mkdirpAsync(accountDir).then(function () { | ||||||
| 
 | 
 | ||||||
| @ -52,8 +58,12 @@ function createAccount(args, handlers) { | |||||||
|             new_authzr_uri: 'https://acme-v01.api.letsencrypt.org/acme/new-authz', |             new_authzr_uri: 'https://acme-v01.api.letsencrypt.org/acme/new-authz', | ||||||
|             terms_of_service: 'https://letsencrypt.org/documents/LE-SA-v1.0.1-July-27-2015.pdf' } |             terms_of_service: 'https://letsencrypt.org/documents/LE-SA-v1.0.1-July-27-2015.pdf' } | ||||||
|            */ |            */ | ||||||
|         , fs.writeFileAsync(path.join(accountDir, 'regr.json'), JSON.stringify({ body: body }), 'utf8') |         , fs.writeFileAsync(path.join(accountDir, 'regr.json'), JSON.stringify(regr), 'utf8') | ||||||
|         ]).then(function () { |         ]).then(function () { | ||||||
|  |           pems.meta = accountMeta; | ||||||
|  |           pems.privateKey = pems.privateKeyJwk; | ||||||
|  |           pems.regr = regr; | ||||||
|  |           pems.accountId = accountId; | ||||||
|           return pems; |           return pems; | ||||||
|         }); |         }); | ||||||
|       }); |       }); | ||||||
| @ -94,11 +104,13 @@ function getAccount(accountId, args, handlers) { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     return leCrypto.parseAccountPrivateKeyAsync(files.private_key).then(function (keypair) { |     return leCrypto.parseAccountPrivateKeyAsync(files.private_key).then(function (keypair) { | ||||||
|       files.accountId = accountId;                  // md5sum(publicKeyPem)
 |       files.accountId = accountId;                  // preserve current account id
 | ||||||
|       files.publicKeyMd5 = accountId;               // md5sum(publicKeyPem)
 |       files.publicKeySha256 = keypair.publicKeySha256; | ||||||
|  |       files.publicKeyMd5 = keypair.publicKeyMd5; | ||||||
|       files.publicKeyPem = keypair.publicKeyPem;    // ascii PEM: ----BEGIN...
 |       files.publicKeyPem = keypair.publicKeyPem;    // ascii PEM: ----BEGIN...
 | ||||||
|       files.privateKeyPem = keypair.privateKeyPem;  // ascii PEM: ----BEGIN...
 |       files.privateKeyPem = keypair.privateKeyPem;  // ascii PEM: ----BEGIN...
 | ||||||
|       files.privateKeyJson = keypair.private_key;   // json { n: ..., e: ..., iq: ..., etc }
 |       files.privateKeyJson = keypair.private_key;   // json { n: ..., e: ..., iq: ..., etc }
 | ||||||
|  |       files.privateKeyJwk = keypair.private_key;    // json { n: ..., e: ..., iq: ..., etc }
 | ||||||
| 
 | 
 | ||||||
|       return files; |       return files; | ||||||
|     }); |     }); | ||||||
|  | |||||||
							
								
								
									
										178
									
								
								lib/core.js
									
									
									
									
									
								
							
							
						
						
									
										178
									
								
								lib/core.js
									
									
									
									
									
								
							| @ -34,13 +34,13 @@ function getAcmeUrls(args) { | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| function getCertificateAsync(account, args, defaults, handlers) { | function getCertificateAsync(account, args, defaults, handlers) { | ||||||
|   return leCrypto.generateRsaKeypairAsync(args.rsaBitLength, args.rsaExponent).then(function (domain) { |   return leCrypto.generateRsaKeypairAsync(args.rsaKeySize, args.rsaExponent).then(function (domainKey) { | ||||||
|     return LeCore.getCertificateAsync({ |     return LeCore.getCertificateAsync({ | ||||||
|       newAuthzUrl: args._acmeUrls.newAuthz |       newAuthzUrl: args._acmeUrls.newAuthz | ||||||
|     , newCertUrl: args._acmeUrls.newCert |     , newCertUrl: args._acmeUrls.newCert | ||||||
| 
 | 
 | ||||||
|     , accountPrivateKeyPem: account.privateKeyPem |     , accountPrivateKeyPem: account.privateKeyPem | ||||||
|     , domainPrivateKeyPem: domain.privateKeyPem |     , domainPrivateKeyPem: domainKey.privateKeyPem | ||||||
|     , domains: args.domains |     , domains: args.domains | ||||||
| 
 | 
 | ||||||
|       //
 |       //
 | ||||||
| @ -82,31 +82,97 @@ function getCertificateAsync(account, args, defaults, handlers) { | |||||||
|         } |         } | ||||||
|       } |       } | ||||||
|     }).then(function (result) { |     }).then(function (result) { | ||||||
|       var liveDir = path.join(args.configDir, 'live', args.domains[0]); |  | ||||||
|       var certPath = path.join(liveDir, 'cert.pem'); |  | ||||||
|       var fullchainPath = path.join(liveDir, 'fullchain.pem'); |  | ||||||
|       var chainPath = path.join(liveDir, 'chain.pem'); |  | ||||||
|       var privkeyPath = path.join(liveDir, 'privkey.pem'); |  | ||||||
| 
 |  | ||||||
|       result.fullchain = result.cert + '\n' + result.ca; |       result.fullchain = result.cert + '\n' + result.ca; | ||||||
| 
 | 
 | ||||||
|       // TODO write to archive first, then write to live
 |       var pyconf = PromiseA.promisifyAll(require('pyconf')); | ||||||
| 
 | 
 | ||||||
|       // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
 |       return pyconf.readFileAsync(args.renewalPath, function (obj) { | ||||||
|       // TODO read renewal.conf.default, write renewal.conf
 |         return obj; | ||||||
|       // var pyconf = PromiseA.promisifyAll(require('pyconf'));
 |       }, function () { | ||||||
|       // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
 |         return pyconf.readFileAsync(path.join(__dirname, 'lib', 'renewal.conf.tpl')).then(function (obj) { | ||||||
|  |           return obj; | ||||||
|  |         }); | ||||||
|  |       }).then(function (obj) { | ||||||
|  |         obj.checkpoint = parseInt(obj.checkpoint, 10) || 0; | ||||||
| 
 | 
 | ||||||
|       return mkdirpAsync(liveDir).then(function () { |         var liveDir = args.liveDir || path.join(args.configDir, 'live', args.domains[0]); | ||||||
|  | 
 | ||||||
|  |         var certPath = args.certPath || obj.cert || path.join(liveDir, 'cert.pem'); | ||||||
|  |         var fullchainPath = args.fullchainPath || obj.fullchain || path.join(liveDir, 'fullchain.pem'); | ||||||
|  |         var chainPath = args.chainPath || obj.chain || path.join(liveDir, 'chain.pem'); | ||||||
|  |         var privkeyPath = args.domainPrivateKeyPath || args.domainKeyPath | ||||||
|  |           || obj.privkey || obj.keyPath | ||||||
|  |           || path.join(liveDir, 'privkey.pem'); | ||||||
|  | 
 | ||||||
|  |         var archiveDir = args.archiveDir || path.join(args.configDir, 'live', args.domains[0]); | ||||||
|  | 
 | ||||||
|  |         var checkpoint = obj.checkpoint.toString(); | ||||||
|  |         var certArchive = path.join(archiveDir, 'cert' + checkpoint + '.pem'); | ||||||
|  |         var fullchainArchive = path.join(archiveDir, 'fullchain' + checkpoint + '.pem'); | ||||||
|  |         var chainArchive = path.join(archiveDir, 'chain'+ checkpoint + '.pem'); | ||||||
|  |         var privkeyArchive = path.join(archiveDir, 'privkey' + checkpoint + '.pem'); | ||||||
|  | 
 | ||||||
|  |         return mkdirpAsync(archiveDir).then(function () { | ||||||
|  |           return PromiseA.all([ | ||||||
|  |             sfs.writeFileAsync(certArchive, result.cert, 'ascii') | ||||||
|  |           , sfs.writeFileAsync(chainArchive, result.ca || result.chain, 'ascii') | ||||||
|  |           , sfs.writeFileAsync(fullchainArchive, result.fullchain, 'ascii') | ||||||
|  |           , sfs.writeFileAsync(privkeyArchive, result.key || result.privkey, 'ascii') | ||||||
|  |           ]); | ||||||
|  |         }).then(function () { | ||||||
|  |           return mkdirpAsync(liveDir); | ||||||
|  |         }).then(function () { | ||||||
|           return PromiseA.all([ |           return PromiseA.all([ | ||||||
|             sfs.writeFileAsync(certPath, result.cert, 'ascii') |             sfs.writeFileAsync(certPath, result.cert, 'ascii') | ||||||
|           , sfs.writeFileAsync(chainPath, result.ca || result.chain, 'ascii') |           , sfs.writeFileAsync(chainPath, result.ca || result.chain, 'ascii') | ||||||
|           , sfs.writeFileAsync(fullchainPath, result.fullchain, 'ascii') |           , sfs.writeFileAsync(fullchainPath, result.fullchain, 'ascii') | ||||||
|           , sfs.writeFileAsync(privkeyPath, result.key || result.privkey, 'ascii') |           , sfs.writeFileAsync(privkeyPath, result.key || result.privkey, 'ascii') | ||||||
|         ]).then(function () { |           ]); | ||||||
|         // TODO format result licesy
 |         }).then(function () { | ||||||
|           //console.log(liveDir);
 |           obj.checkpoint += 1; | ||||||
|           //console.log(result);
 | 
 | ||||||
|  |           var updates = { | ||||||
|  |             cert: certPath | ||||||
|  |           , privkey: privkeyPath | ||||||
|  |           , chain: chainPath | ||||||
|  |           , fullchain: fullchainPath | ||||||
|  |           , configDir: args.configDir | ||||||
|  |           , workDir: args.workDir | ||||||
|  |           , tos: args.agreeTos && true | ||||||
|  |           , http01Port: args.http01Port | ||||||
|  |           , keyPath: args.domainPrivateKeyPath || args.privkeyPath | ||||||
|  |           , email: args.email | ||||||
|  |           , domains: args.domains | ||||||
|  |           , rsaKeySize: args.rsaKeySize | ||||||
|  |           , checkpoints: obj.checkpoint | ||||||
|  |             // TODO XXX what's the deal with these? they don't make sense
 | ||||||
|  |             // are they just old junk? or do they have a meaning that I don't know about?
 | ||||||
|  |           , fullchainPath: path.join(args.configDir, 'chain.pem') | ||||||
|  |           , certPath: path.join(args.configDir, 'cert.pem') | ||||||
|  |           , chainPath: path.join(args.configDir, 'chain.pem') | ||||||
|  |             // TODO XXX end
 | ||||||
|  |             // yes, it's an array. weird, right?
 | ||||||
|  |           , webrootPath: args.webrootPath && [args.webrootPath] || [] | ||||||
|  |           , account: account.accountId | ||||||
|  |           , server: args.server || args.acmeDiscoveryUrl | ||||||
|  |           , logsDir: args.logsDir | ||||||
|  |           }; | ||||||
|  | 
 | ||||||
|  |           // final section is completely dynamic
 | ||||||
|  |           // :hostname = :webroot_path
 | ||||||
|  |           args.domains.forEach(function (hostname) { | ||||||
|  |             updates[hostname] = args.webrootPath; | ||||||
|  |           }); | ||||||
|  | 
 | ||||||
|  |           // must write back to the original object or
 | ||||||
|  |           // annotations will be lost
 | ||||||
|  |           Object.keys(updates).forEach(function (key) { | ||||||
|  |             obj[key] = updates[key]; | ||||||
|  |           }); | ||||||
|  | 
 | ||||||
|  |           return pyconf.writeFile(args.renewalPath, obj); | ||||||
|  |         }).then(function () { | ||||||
|  | 
 | ||||||
|           return { |           return { | ||||||
|             certPath: certPath |             certPath: certPath | ||||||
|           , chainPath: chainPath |           , chainPath: chainPath | ||||||
| @ -135,8 +201,7 @@ function registerWithAcme(args, defaults, handlers) { | |||||||
|   var acmeHostname = require('url').parse(server).hostname; |   var acmeHostname = require('url').parse(server).hostname; | ||||||
|   var configDir = args.configDir; |   var configDir = args.configDir; | ||||||
| 
 | 
 | ||||||
|   args.server = server; |   args.renewalPath = args.renewalPath || path.join(configDir, 'renewal', args.domains[0] + '.conf'); | ||||||
|   args.renewalDir = args.renewalDir || path.join(configDir, 'renewal', args.domains[0] + '.conf'); |  | ||||||
|   args.accountsDir = args.accountsDir || path.join(configDir, 'accounts', acmeHostname, 'directory'); |   args.accountsDir = args.accountsDir || path.join(configDir, 'accounts', acmeHostname, 'directory'); | ||||||
| 
 | 
 | ||||||
|   return pyconf.readFileAsync(args.renewalDir).then(function (renewal) { |   return pyconf.readFileAsync(args.renewalDir).then(function (renewal) { | ||||||
| @ -195,71 +260,6 @@ function registerWithAcme(args, defaults, handlers) { | |||||||
|         return certs; |         return certs; | ||||||
|       } |       } | ||||||
|     }); |     }); | ||||||
| 
 |  | ||||||
|     /* |  | ||||||
|     cert = /home/aj/node-letsencrypt/tests/letsencrypt.config/live/lds.io/cert.pem |  | ||||||
|     privkey = /home/aj/node-letsencrypt/tests/letsencrypt.config/live/lds.io/privkey.pem |  | ||||||
|     chain = /home/aj/node-letsencrypt/tests/letsencrypt.config/live/lds.io/chain.pem |  | ||||||
|     fullchain = /home/aj/node-letsencrypt/tests/letsencrypt.config/live/lds.io/fullchain.pem |  | ||||||
| 
 |  | ||||||
|     # Options and defaults used in the renewal process |  | ||||||
|     [renewalparams] |  | ||||||
|     apache_enmod = a2enmod |  | ||||||
|     no_verify_ssl = False |  | ||||||
|     ifaces = None |  | ||||||
|     apache_dismod = a2dismod |  | ||||||
|     register_unsafely_without_email = False |  | ||||||
|     uir = None |  | ||||||
|     installer = none |  | ||||||
|     config_dir = /home/aj/node-letsencrypt/tests/letsencrypt.config |  | ||||||
|     text_mode = True |  | ||||||
|     func = <function obtain_cert at 0x7f46af0f02a8> |  | ||||||
|     prepare = False |  | ||||||
|     work_dir = /home/aj/node-letsencrypt/tests/letsencrypt.work |  | ||||||
|     tos = True |  | ||||||
|     init = False |  | ||||||
|     http01_port = 80 |  | ||||||
|     duplicate = False |  | ||||||
|     key_path = None |  | ||||||
|     nginx = False |  | ||||||
|     fullchain_path = /home/aj/node-letsencrypt/chain.pem |  | ||||||
|     email = coolaj86@gmail.com |  | ||||||
|     csr = None |  | ||||||
|     agree_dev_preview = None |  | ||||||
|     redirect = None |  | ||||||
|     verbose_count = -3 |  | ||||||
|     config_file = None |  | ||||||
|     renew_by_default = True |  | ||||||
|     hsts = False |  | ||||||
|     authenticator = webroot |  | ||||||
|     domains = lds.io, |  | ||||||
|     rsa_key_size = 2048 |  | ||||||
|     checkpoints = 1 |  | ||||||
|     manual_test_mode = False |  | ||||||
|     apache = False |  | ||||||
|     cert_path = /home/aj/node-letsencrypt/cert.pem |  | ||||||
|     webroot_path = /home/aj/node-letsencrypt/examples/../tests/acme-challenge, |  | ||||||
|     strict_permissions = False |  | ||||||
|     apache_server_root = /etc/apache2 |  | ||||||
|     account = 1c41c64dfaf10d511db8aef0cc33b27f |  | ||||||
|     manual_public_ip_logging_ok = False |  | ||||||
|     chain_path = /home/aj/node-letsencrypt/chain.pem |  | ||||||
|     standalone = False |  | ||||||
|     manual = False |  | ||||||
|     server = https://acme-staging.api.letsencrypt.org/directory
 |  | ||||||
|     standalone_supported_challenges = "http-01,tls-sni-01" |  | ||||||
|     webroot = True |  | ||||||
|     apache_init_script = None |  | ||||||
|     user_agent = None |  | ||||||
|     apache_ctl = apache2ctl |  | ||||||
|     apache_le_vhost_ext = -le-ssl.conf |  | ||||||
|     debug = False |  | ||||||
|     tls_sni_01_port = 443 |  | ||||||
|     logs_dir = /home/aj/node-letsencrypt/tests/letsencrypt.logs |  | ||||||
|     configurator = None |  | ||||||
|     [[webroot_map]] |  | ||||||
|     lds.io = /home/aj/node-letsencrypt/examples/../tests/acme-challenge |  | ||||||
|     */ |  | ||||||
|   }); |   }); | ||||||
| /* | /* | ||||||
|   return fs.readdirAsync(accountsDir, function (nodes) { |   return fs.readdirAsync(accountsDir, function (nodes) { | ||||||
| @ -277,7 +277,13 @@ module.exports.create = function (defaults, handlers) { | |||||||
| 
 | 
 | ||||||
|   var wrapped = { |   var wrapped = { | ||||||
|     registerAsync: function (args) { |     registerAsync: function (args) { | ||||||
|       var copy = merge(args, defaults); |       var copy; | ||||||
|  |       // TODO move these defaults elsewhere?
 | ||||||
|  |       args.renewalPath = args.renewalPath || ':config/renewal/:hostname.conf'; | ||||||
|  |       // Note: the /directory is part of the server url and, as such, bleeds into the pathname
 | ||||||
|  |       // 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); |       tplHostname(args.domains[0], copy); | ||||||
| 
 | 
 | ||||||
|       if (args.debug) { |       if (args.debug) { | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user