mirror of
				https://git.coolaj86.com/coolaj86/greenlock-store-fs.js.git
				synced 2025-11-04 11:02:47 +00:00 
			
		
		
		
	v0.9.2: add comments, tame wild domains (use '_')
This commit is contained in:
		
							parent
							
								
									cfb335902c
								
							
						
					
					
						commit
						9f61e34a8a
					
				
							
								
								
									
										67
									
								
								index.js
									
									
									
									
									
								
							
							
						
						
									
										67
									
								
								index.js
									
									
									
									
									
								
							@ -31,12 +31,22 @@ var os = require("os");
 | 
				
			|||||||
module.exports.create = function (config) {
 | 
					module.exports.create = function (config) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // This file has been laid out in the order that options are used and calls are made
 | 
					  // This file has been laid out in the order that options are used and calls are made
 | 
				
			||||||
  // greenlock.approveDomains)
 | 
					  // SNICallback() // le-sni-auto has a cache
 | 
				
			||||||
  //   greenlock.store.certificates.checkAsync()
 | 
					  //   greenlock.approveDomains()
 | 
				
			||||||
  //   greenlock.store.accounts.checkAsync()
 | 
					  //        // you get opts.domain passed to you from SNI
 | 
				
			||||||
  //   greenlock.store.accounts.setKeypairAsync()
 | 
					  //        // you should set opts.subject as the cert "id" domain
 | 
				
			||||||
  //   greenlock.store.accounts.setAsync()
 | 
					  //        // you should set opts.domains as all domains on the cert
 | 
				
			||||||
 | 
					  //        // you should set opts.account.id, otherwise opts.email will be used
 | 
				
			||||||
 | 
					  //     greenlock.store.certificates.checkAsync() // on success -> SNI cache, on fail \/
 | 
				
			||||||
 | 
					  //     greenlock.store.accounts.checkAsync()     // optional (you can always return null)
 | 
				
			||||||
 | 
					  //     greenlock.store.accounts.checkKeypairAsync()
 | 
				
			||||||
 | 
					  //       greenlock.core.RSA.generateKeypair() // TODO double check name
 | 
				
			||||||
 | 
					  //       greenlock.core.accounts.register() // TODO double check name
 | 
				
			||||||
 | 
					  //     greenlock.store.accounts.setKeypairAsync() // TODO make sure this only happens on generate
 | 
				
			||||||
 | 
					  //     greenlock.store.accounts.setAsync() // optional
 | 
				
			||||||
  //     greenlock.store.certificates.checkKeypairAsync()
 | 
					  //     greenlock.store.certificates.checkKeypairAsync()
 | 
				
			||||||
 | 
					  //       greenlock.core.RSA.generateKeypair() // TODO double check name
 | 
				
			||||||
 | 
					  //       greenlock.core.certificates.register() // TODO double check name
 | 
				
			||||||
  //     greenlock.store.certificates.setKeypairAsync()
 | 
					  //     greenlock.store.certificates.setKeypairAsync()
 | 
				
			||||||
  //     greenlock.store.certificates.setAsync()
 | 
					  //     greenlock.store.certificates.setAsync()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -100,9 +110,9 @@ module.exports.create = function (config) {
 | 
				
			|||||||
    var chainPath = opts.chainPath || path.join(liveDir, 'chain.pem');
 | 
					    var chainPath = opts.chainPath || path.join(liveDir, 'chain.pem');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return PromiseA.all([
 | 
					    return PromiseA.all([
 | 
				
			||||||
      readFileAsync(privkeyPath, 'ascii')   // 0
 | 
					      readFileAsync(tameWild(privkeyPath, opts.subject), 'ascii')   // 0
 | 
				
			||||||
    , readFileAsync(certPath, 'ascii')      // 1
 | 
					    , readFileAsync(tameWild(certPath, opts.subject), 'ascii')      // 1
 | 
				
			||||||
    , readFileAsync(chainPath, 'ascii')     // 2
 | 
					    , readFileAsync(tameWild(chainPath, opts.subject), 'ascii')     // 2
 | 
				
			||||||
    ]).then(function (all) {
 | 
					    ]).then(function (all) {
 | 
				
			||||||
      return {
 | 
					      return {
 | 
				
			||||||
        privkey: all[0]
 | 
					        privkey: all[0]
 | 
				
			||||||
@ -154,7 +164,8 @@ module.exports.create = function (config) {
 | 
				
			|||||||
    console.log('accounts.checkKeypairAsync for', id);
 | 
					    console.log('accounts.checkKeypairAsync for', id);
 | 
				
			||||||
    if (!opts.account.id) { return Promise.reject(new Error("'account.id' should have been set in approveDomains()")); }
 | 
					    if (!opts.account.id) { return Promise.reject(new Error("'account.id' should have been set in approveDomains()")); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return readFileAsync(path.join(opts.accountsDir, sanitizeFilename(id) + '.json'), 'utf8').then(function (blob) {
 | 
					    var pathname = path.join(tameWild(opts.accountsDir, opts.subject), sanitizeFilename(id) + '.json');
 | 
				
			||||||
 | 
					    return readFileAsync(tameWild(pathname, opts.subject), 'utf8').then(function (blob) {
 | 
				
			||||||
      // keypair is an opaque object that should be treated as blob
 | 
					      // keypair is an opaque object that should be treated as blob
 | 
				
			||||||
      return JSON.parse(blob);
 | 
					      return JSON.parse(blob);
 | 
				
			||||||
    }).catch(function (err) {
 | 
					    }).catch(function (err) {
 | 
				
			||||||
@ -175,9 +186,10 @@ module.exports.create = function (config) {
 | 
				
			|||||||
    console.log('accounts.setKeypairAsync for', id);
 | 
					    console.log('accounts.setKeypairAsync for', id);
 | 
				
			||||||
    keypair = opts.keypair || keypair;
 | 
					    keypair = opts.keypair || keypair;
 | 
				
			||||||
    if (!opts.account.id) { return Promise.reject(new Error("'account.id' should have been set in approveDomains()")); }
 | 
					    if (!opts.account.id) { return Promise.reject(new Error("'account.id' should have been set in approveDomains()")); }
 | 
				
			||||||
    return mkdirpAsync(opts.accountsDir).then(function () {
 | 
					    return mkdirpAsync(tameWild(opts.accountsDir, opts.subject)).then(function () {
 | 
				
			||||||
      // keypair is an opaque object that should be treated as blob
 | 
					      // keypair is an opaque object that should be treated as blob
 | 
				
			||||||
      return writeFileAsync(path.join(opts.accountsDir, sanitizeFilename(id) + '.json'), JSON.stringify(keypair), 'utf8');
 | 
					      var pathname = tameWild(path.join(opts.accountsDir, sanitizeFilename(id) + '.json'), opts.subject);
 | 
				
			||||||
 | 
					      return writeFileAsync(tameWild(pathname, opts.subject), JSON.stringify(keypair), 'utf8');
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -200,7 +212,7 @@ module.exports.create = function (config) {
 | 
				
			|||||||
    console.log('certificates.checkKeypairAsync:');
 | 
					    console.log('certificates.checkKeypairAsync:');
 | 
				
			||||||
    var liveDir = opts.liveDir || path.join(opts.configDir, 'live', opts.subject);
 | 
					    var liveDir = opts.liveDir || path.join(opts.configDir, 'live', opts.subject);
 | 
				
			||||||
    var privkeyPath = opts.privkeyPath || opts.domainKeyPath || path.join(liveDir, 'privkey.pem');
 | 
					    var privkeyPath = opts.privkeyPath || opts.domainKeyPath || path.join(liveDir, 'privkey.pem');
 | 
				
			||||||
    return readFileAsync(privkeyPath, 'ascii').then(function (key) {
 | 
					    return readFileAsync(tameWild(privkeyPath, opts.subject), 'ascii').then(function (key) {
 | 
				
			||||||
      // keypair is normally an opaque object, but here it's a pem for the filesystem
 | 
					      // keypair is normally an opaque object, but here it's a pem for the filesystem
 | 
				
			||||||
      return { privateKeyPem: key };
 | 
					      return { privateKeyPem: key };
 | 
				
			||||||
    }).catch(function (err) {
 | 
					    }).catch(function (err) {
 | 
				
			||||||
@ -217,8 +229,8 @@ module.exports.create = function (config) {
 | 
				
			|||||||
    var liveDir = opts.liveDir || path.join(opts.configDir, 'live', opts.subject);
 | 
					    var liveDir = opts.liveDir || path.join(opts.configDir, 'live', opts.subject);
 | 
				
			||||||
    var privkeyPath = opts.privkeyPath || opts.domainKeyPath || path.join(liveDir, 'privkey.pem');
 | 
					    var privkeyPath = opts.privkeyPath || opts.domainKeyPath || path.join(liveDir, 'privkey.pem');
 | 
				
			||||||
    // keypair is normally an opaque object, but here it's a PEM for the FS
 | 
					    // keypair is normally an opaque object, but here it's a PEM for the FS
 | 
				
			||||||
    return mkdirpAsync(path.dirname(privkeyPath)).then(function () {
 | 
					    return mkdirpAsync(tameWild(path.dirname(privkeyPath), opts.subject)).then(function () {
 | 
				
			||||||
      return writeFileAsync(privkeyPath, keypair.privateKeyPem, 'ascii').then(function () {
 | 
					      return writeFileAsync(tameWild(privkeyPath, opts.subject), keypair.privateKeyPem, 'ascii').then(function () {
 | 
				
			||||||
        return null;
 | 
					        return null;
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
@ -242,18 +254,19 @@ module.exports.create = function (config) {
 | 
				
			|||||||
    //var privkeyPath = opts.privkeyPath || opts.domainKeyPath || path.join(liveDir, 'privkey.pem');
 | 
					    //var privkeyPath = opts.privkeyPath || opts.domainKeyPath || path.join(liveDir, 'privkey.pem');
 | 
				
			||||||
    var bundlePath = opts.bundlePath || path.join(liveDir, 'bundle.pem');
 | 
					    var bundlePath = opts.bundlePath || path.join(liveDir, 'bundle.pem');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return mkdirpAsync(path.dirname(certPath)).then(function () {
 | 
					    return mkdirpAsync(path.dirname(tameWild(certPath, opts.subject))).then(function () {
 | 
				
			||||||
      return mkdirpAsync(path.dirname(chainPath)).then(function () {
 | 
					      return mkdirpAsync(path.dirname(tameWild(chainPath, opts.subject))).then(function () {
 | 
				
			||||||
        return mkdirpAsync(path.dirname(fullchainPath)).then(function () {
 | 
					        return mkdirpAsync(path.dirname(tameWild(fullchainPath, opts.subject))).then(function () {
 | 
				
			||||||
          return mkdirpAsync(path.dirname(bundlePath)).then(function () {
 | 
					          return mkdirpAsync(path.dirname(tameWild(bundlePath, opts.subject))).then(function () {
 | 
				
			||||||
 | 
					            var fullchainPem = [ pems.cert, pems.chain ].join('\n'); // for Apache, Nginx, etc
 | 
				
			||||||
 | 
					            var bundlePem = [ pems.privkey, pems.cert, pems.chain ].join('\n'); // for HAProxy
 | 
				
			||||||
            return PromiseA.all([
 | 
					            return PromiseA.all([
 | 
				
			||||||
              sfs.writeFileAsync(certPath, pems.cert, 'ascii')
 | 
					              sfs.writeFileAsync(tameWild(certPath, opts.subject), pems.cert, 'ascii')
 | 
				
			||||||
            , sfs.writeFileAsync(chainPath, pems.chain, 'ascii')
 | 
					            , sfs.writeFileAsync(tameWild(chainPath, opts.subject), pems.chain, 'ascii')
 | 
				
			||||||
              // Most platforms need these two
 | 
					              // Most web servers need these two
 | 
				
			||||||
            , sfs.writeFileAsync(fullchainPath, [ pems.cert, pems.chain ].join('\n'), 'ascii')
 | 
					            , sfs.writeFileAsync(tameWild(fullchainPath, opts.subject), fullchainPem, 'ascii')
 | 
				
			||||||
            //, sfs.writeFileAsync(privkeyPath, pems.privkey, 'ascii')
 | 
					 | 
				
			||||||
              // HAProxy needs "bundle.pem" aka "combined.pem"
 | 
					              // HAProxy needs "bundle.pem" aka "combined.pem"
 | 
				
			||||||
            , sfs.writeFileAsync(bundlePath, [ pems.privkey, pems.cert, pems.chain ].join('\n'), 'ascii')
 | 
					            , sfs.writeFileAsync(tameWild(bundlePath, opts.subject), bundlePem, 'ascii')
 | 
				
			||||||
            ]);
 | 
					            ]);
 | 
				
			||||||
          });
 | 
					          });
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
@ -297,3 +310,9 @@ function mergeOptions(configs) {
 | 
				
			|||||||
function sanitizeFilename(id) {
 | 
					function sanitizeFilename(id) {
 | 
				
			||||||
  return id.replace(/(\.\.)|\\|\//g, '_').replace(/[^!-~]/g, '_');
 | 
					  return id.replace(/(\.\.)|\\|\//g, '_').replace(/[^!-~]/g, '_');
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// because not all file systems like '*' in a name (and they're scary)
 | 
				
			||||||
 | 
					function tameWild(path, wild) {
 | 
				
			||||||
 | 
					  var tame = wild.replace(/\*/g, '_');
 | 
				
			||||||
 | 
					  return path.replace(wild, tame);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,6 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
  "name": "le-store-fs",
 | 
					  "name": "le-store-fs",
 | 
				
			||||||
  "version": "0.9.1",
 | 
					  "version": "0.9.2",
 | 
				
			||||||
  "description": "A file-based certificate store for greenlock that supports wildcards.",
 | 
					  "description": "A file-based certificate store for greenlock that supports wildcards.",
 | 
				
			||||||
  "homepage": "https://git.coolaj86.com/coolaj86/le-store-fs.js",
 | 
					  "homepage": "https://git.coolaj86.com/coolaj86/le-store-fs.js",
 | 
				
			||||||
  "main": "index.js",
 | 
					  "main": "index.js",
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user