mirror of
				https://git.coolaj86.com/coolaj86/greenlock-store-fs.js.git
				synced 2025-11-04 11:02:47 +00:00 
			
		
		
		
	make Prettier
This commit is contained in:
		
							parent
							
								
									de0f4d25b4
								
							
						
					
					
						commit
						e0a9fff07d
					
				
							
								
								
									
										7
									
								
								.prettierrc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								.prettierrc
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					  "bracketSpacing": true,
 | 
				
			||||||
 | 
					  "printWidth": 80,
 | 
				
			||||||
 | 
					  "tabWidth": 4,
 | 
				
			||||||
 | 
					  "trailingComma": "none",
 | 
				
			||||||
 | 
					  "useTabs": false
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										82
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										82
									
								
								README.md
									
									
									
									
									
								
							@ -4,10 +4,11 @@ A keypair and certificate storage strategy for Greenlock v2.7+ (and v3).
 | 
				
			|||||||
The (much simpler) successor to le-store-certbot.
 | 
					The (much simpler) successor to le-store-certbot.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Works with all ACME (Let's Encrypt) SSL certificate sytles:
 | 
					Works with all ACME (Let's Encrypt) SSL certificate sytles:
 | 
				
			||||||
* [x] single domains
 | 
					
 | 
				
			||||||
* [x] multiple domains (SANs, AltNames)
 | 
					-   [x] single domains
 | 
				
			||||||
* [x] wildcards
 | 
					-   [x] multiple domains (SANs, AltNames)
 | 
				
			||||||
* [x] private / localhost domains
 | 
					-   [x] wildcards
 | 
				
			||||||
 | 
					-   [x] private / localhost domains
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Usage
 | 
					# Usage
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -65,17 +66,25 @@ The subject and the first altname must be an exact match: `subject === altnames[
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
```js
 | 
					```js
 | 
				
			||||||
function approveDomains(opts) {
 | 
					function approveDomains(opts) {
 | 
				
			||||||
  // Allow only example.com and *.example.com (such as foo.example.com)
 | 
					    // Allow only example.com and *.example.com (such as foo.example.com)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // foo.example.com => *.example.com
 | 
					    // foo.example.com => *.example.com
 | 
				
			||||||
  var wild = '*.' + opts.domain.split('.').slice(1).join('.');
 | 
					    var wild =
 | 
				
			||||||
 | 
					        "*." +
 | 
				
			||||||
 | 
					        opts.domain
 | 
				
			||||||
 | 
					            .split(".")
 | 
				
			||||||
 | 
					            .slice(1)
 | 
				
			||||||
 | 
					            .join(".");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if ('example.com' !== opts.domain && '*.example.com' !== wild) {
 | 
					    if ("example.com" !== opts.domain && "*.example.com" !== wild) {
 | 
				
			||||||
    cb(new Error(opts.domain + " is not allowed"));
 | 
					        cb(new Error(opts.domain + " is not allowed"));
 | 
				
			||||||
  }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  var result = { subject: 'example.com', altnames: [ 'example.com', '*.example.com' ] };
 | 
					    var result = {
 | 
				
			||||||
  return Promise.resolve(result);
 | 
					        subject: "example.com",
 | 
				
			||||||
 | 
					        altnames: ["example.com", "*.example.com"]
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    return Promise.resolve(result);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -83,36 +92,45 @@ function approveDomains(opts) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
```js
 | 
					```js
 | 
				
			||||||
function approveDomains(opts, certs, cb) {
 | 
					function approveDomains(opts, certs, cb) {
 | 
				
			||||||
  var related = getRelated(opts.domain);
 | 
					    var related = getRelated(opts.domain);
 | 
				
			||||||
  if (!related) { cb(new Error(opts.domain + " is not allowed")); };
 | 
					    if (!related) {
 | 
				
			||||||
 | 
					        cb(new Error(opts.domain + " is not allowed"));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  opts.subject = related.subject;
 | 
					    opts.subject = related.subject;
 | 
				
			||||||
  opts.domains = related.domains;
 | 
					    opts.domains = related.domains;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  cb({ options: opts, certs: certs });
 | 
					    cb({ options: opts, certs: certs });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```js
 | 
					```js
 | 
				
			||||||
function getRelated(domain) {
 | 
					function getRelated(domain) {
 | 
				
			||||||
  var related;
 | 
					    var related;
 | 
				
			||||||
  var wild = '*.' + domain.split('.').slice(1).join('.');
 | 
					    var wild =
 | 
				
			||||||
  if (Object.keys(allAllowedDomains).some(function (k) {
 | 
					        "*." +
 | 
				
			||||||
    return allAllowedDomains[k].some(function (name) {
 | 
					        domain
 | 
				
			||||||
      if (domain === name || wild === name) {
 | 
					            .split(".")
 | 
				
			||||||
        related = { subject: k, altnames: allAllowedDomains[k] };
 | 
					            .slice(1)
 | 
				
			||||||
        return true;
 | 
					            .join(".");
 | 
				
			||||||
      }
 | 
					    if (
 | 
				
			||||||
    });
 | 
					        Object.keys(allAllowedDomains).some(function(k) {
 | 
				
			||||||
  })) {
 | 
					            return allAllowedDomains[k].some(function(name) {
 | 
				
			||||||
    return related;
 | 
					                if (domain === name || wild === name) {
 | 
				
			||||||
  }
 | 
					                    related = { subject: k, altnames: allAllowedDomains[k] };
 | 
				
			||||||
 | 
					                    return true;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					    ) {
 | 
				
			||||||
 | 
					        return related;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```js
 | 
					```js
 | 
				
			||||||
var allAllowedDomains = {
 | 
					var allAllowedDomains = {
 | 
				
			||||||
  'example.com': ['example.com', '*.example.com']
 | 
					    "example.com": ["example.com", "*.example.com"],
 | 
				
			||||||
, 'example.net': ['example.net', '*.example.net']
 | 
					    "example.net": ["example.net", "*.example.net"]
 | 
				
			||||||
}
 | 
					};
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										118
									
								
								accounts.js
									
									
									
									
									
								
							
							
						
						
									
										118
									
								
								accounts.js
									
									
									
									
									
								
							@ -1,15 +1,15 @@
 | 
				
			|||||||
'use strict';
 | 
					"use strict";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var accounts = module.exports;
 | 
					var accounts = module.exports;
 | 
				
			||||||
var store = accounts;
 | 
					var store = accounts;
 | 
				
			||||||
var U = require('./utils.js');
 | 
					var U = require("./utils.js");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var fs = require('fs');
 | 
					var fs = require("fs");
 | 
				
			||||||
var path = require('path');
 | 
					var path = require("path");
 | 
				
			||||||
var PromiseA = require('./promise.js');
 | 
					var PromiseA = require("./promise.js");
 | 
				
			||||||
var readFileAsync = PromiseA.promisify(fs.readFile);
 | 
					var readFileAsync = PromiseA.promisify(fs.readFile);
 | 
				
			||||||
var writeFileAsync = PromiseA.promisify(fs.writeFile);
 | 
					var writeFileAsync = PromiseA.promisify(fs.writeFile);
 | 
				
			||||||
var mkdirpAsync = PromiseA.promisify(require('@root/mkdirp'));
 | 
					var mkdirpAsync = PromiseA.promisify(require("@root/mkdirp"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Implement if you need the ACME account metadata elsewhere in the chain of events
 | 
					// Implement if you need the ACME account metadata elsewhere in the chain of events
 | 
				
			||||||
//store.accounts.check = function (opts) {
 | 
					//store.accounts.check = function (opts) {
 | 
				
			||||||
@ -22,23 +22,23 @@ var mkdirpAsync = PromiseA.promisify(require('@root/mkdirp'));
 | 
				
			|||||||
// Use account.id, or email, if id hasn't been set, to find an account keypair.
 | 
					// Use account.id, or email, if id hasn't been set, to find an account keypair.
 | 
				
			||||||
// Return an object with string privateKeyPem and/or object privateKeyJwk (or null, not undefined)
 | 
					// Return an object with string privateKeyPem and/or object privateKeyJwk (or null, not undefined)
 | 
				
			||||||
accounts.checkKeypair = function(opts) {
 | 
					accounts.checkKeypair = function(opts) {
 | 
				
			||||||
	var id =
 | 
					    var id =
 | 
				
			||||||
		(opts.account && opts.account.id) ||
 | 
					        (opts.account && opts.account.id) ||
 | 
				
			||||||
		(opts.subscriberEmail || opts.email) ||
 | 
					        (opts.subscriberEmail || opts.email) ||
 | 
				
			||||||
		'single-user';
 | 
					        "single-user";
 | 
				
			||||||
	//console.log('accounts.checkKeypair for', id);
 | 
					    //console.log('accounts.checkKeypair for', id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var pathname = path.join(
 | 
					    var pathname = path.join(
 | 
				
			||||||
		accountsDir(store, opts),
 | 
					        accountsDir(store, opts),
 | 
				
			||||||
		sanitizeFilename(id) + '.json'
 | 
					        sanitizeFilename(id) + ".json"
 | 
				
			||||||
	);
 | 
					    );
 | 
				
			||||||
	return readFileAsync(U._tameWild(pathname, opts.subject), 'utf8')
 | 
					    return readFileAsync(U._tameWild(pathname, opts.subject), "utf8")
 | 
				
			||||||
		.then(function(blob) {
 | 
					        .then(function(blob) {
 | 
				
			||||||
			// keypair can treated as an opaque object and just passed along,
 | 
					            // keypair can treated as an opaque object and just passed along,
 | 
				
			||||||
			// but just to show you what it is...
 | 
					            // but just to show you what it is...
 | 
				
			||||||
			var keypair = JSON.parse(blob);
 | 
					            var keypair = JSON.parse(blob);
 | 
				
			||||||
			return keypair;
 | 
					            return keypair;
 | 
				
			||||||
			/*
 | 
					            /*
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
				privateKeyPem: keypair.privateKeyPem, // string PEM private key
 | 
									privateKeyPem: keypair.privateKeyPem, // string PEM private key
 | 
				
			||||||
				privateKeyJwk: keypair.privateKeyJwk, // object JWK private key
 | 
									privateKeyJwk: keypair.privateKeyJwk, // object JWK private key
 | 
				
			||||||
@ -46,13 +46,13 @@ accounts.checkKeypair = function(opts) {
 | 
				
			|||||||
				public: keypair.public
 | 
									public: keypair.public
 | 
				
			||||||
			};
 | 
								};
 | 
				
			||||||
      */
 | 
					      */
 | 
				
			||||||
		})
 | 
					        })
 | 
				
			||||||
		.catch(function(err) {
 | 
					        .catch(function(err) {
 | 
				
			||||||
			if ('ENOENT' === err.code) {
 | 
					            if ("ENOENT" === err.code) {
 | 
				
			||||||
				return null;
 | 
					                return null;
 | 
				
			||||||
			}
 | 
					            }
 | 
				
			||||||
			throw err;
 | 
					            throw err;
 | 
				
			||||||
		});
 | 
					        });
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Accounts.setKeypair({ account, email, keypair, ... }):
 | 
					// Accounts.setKeypair({ account, email, keypair, ... }):
 | 
				
			||||||
@ -60,12 +60,12 @@ accounts.checkKeypair = function(opts) {
 | 
				
			|||||||
// Use account.id (or email if no id is present) to save an account keypair
 | 
					// Use account.id (or email if no id is present) to save an account keypair
 | 
				
			||||||
// Return null (not undefined) on success, or throw on error
 | 
					// Return null (not undefined) on success, or throw on error
 | 
				
			||||||
accounts.setKeypair = function(opts) {
 | 
					accounts.setKeypair = function(opts) {
 | 
				
			||||||
	//console.log('accounts.setKeypair for', opts.account, opts.email, opts.keypair);
 | 
					    //console.log('accounts.setKeypair for', opts.account, opts.email, opts.keypair);
 | 
				
			||||||
	var id = opts.account.id || opts.email || 'single-user';
 | 
					    var id = opts.account.id || opts.email || "single-user";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// you can just treat the keypair as opaque and save and retrieve it as JSON
 | 
					    // you can just treat the keypair as opaque and save and retrieve it as JSON
 | 
				
			||||||
	var keyblob = JSON.stringify(opts.keypair);
 | 
					    var keyblob = JSON.stringify(opts.keypair);
 | 
				
			||||||
	/*
 | 
					    /*
 | 
				
			||||||
	var keyblob = JSON.stringify({
 | 
						var keyblob = JSON.stringify({
 | 
				
			||||||
		privateKeyPem: opts.keypair.privateKeyPem, // string PEM
 | 
							privateKeyPem: opts.keypair.privateKeyPem, // string PEM
 | 
				
			||||||
		privateKeyJwk: opts.keypair.privateKeyJwk, // object JWK
 | 
							privateKeyJwk: opts.keypair.privateKeyJwk, // object JWK
 | 
				
			||||||
@ -73,24 +73,24 @@ accounts.setKeypair = function(opts) {
 | 
				
			|||||||
	});
 | 
						});
 | 
				
			||||||
  */
 | 
					  */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Ignore.
 | 
					    // Ignore.
 | 
				
			||||||
	// Just implementation specific details here.
 | 
					    // Just implementation specific details here.
 | 
				
			||||||
	return mkdirpAsync(accountsDir(store, opts))
 | 
					    return mkdirpAsync(accountsDir(store, opts))
 | 
				
			||||||
		.then(function() {
 | 
					        .then(function() {
 | 
				
			||||||
			var pathname = path.join(
 | 
					            var pathname = path.join(
 | 
				
			||||||
				accountsDir(store, opts),
 | 
					                accountsDir(store, opts),
 | 
				
			||||||
				sanitizeFilename(id) + '.json'
 | 
					                sanitizeFilename(id) + ".json"
 | 
				
			||||||
			);
 | 
					            );
 | 
				
			||||||
			return writeFileAsync(
 | 
					            return writeFileAsync(
 | 
				
			||||||
				U._tameWild(pathname, opts.subject),
 | 
					                U._tameWild(pathname, opts.subject),
 | 
				
			||||||
				keyblob,
 | 
					                keyblob,
 | 
				
			||||||
				'utf8'
 | 
					                "utf8"
 | 
				
			||||||
			);
 | 
					            );
 | 
				
			||||||
		})
 | 
					        })
 | 
				
			||||||
		.then(function() {
 | 
					        .then(function() {
 | 
				
			||||||
			// This is your job: return null, not undefined
 | 
					            // This is your job: return null, not undefined
 | 
				
			||||||
			return null;
 | 
					            return null;
 | 
				
			||||||
		});
 | 
					        });
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Implement if you need the ACME account metadata elsewhere in the chain of events
 | 
					// Implement if you need the ACME account metadata elsewhere in the chain of events
 | 
				
			||||||
@ -100,14 +100,14 @@ accounts.setKeypair = function(opts) {
 | 
				
			|||||||
//};
 | 
					//};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function sanitizeFilename(id) {
 | 
					function sanitizeFilename(id) {
 | 
				
			||||||
	return id.replace(/(\.\.)|\\|\//g, '_').replace(/[^!-~]/g, '_');
 | 
					    return id.replace(/(\.\.)|\\|\//g, "_").replace(/[^!-~]/g, "_");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function accountsDir(store, opts) {
 | 
					function accountsDir(store, opts) {
 | 
				
			||||||
	var dir = U._tpl(
 | 
					    var dir = U._tpl(
 | 
				
			||||||
		store,
 | 
					        store,
 | 
				
			||||||
		opts,
 | 
					        opts,
 | 
				
			||||||
		opts.accountsDir || store.options.accountsDir
 | 
					        opts.accountsDir || store.options.accountsDir
 | 
				
			||||||
	);
 | 
					    );
 | 
				
			||||||
	return U._tameWild(dir, opts.subject || '');
 | 
					    return U._tameWild(dir, opts.subject || "");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										412
									
								
								certificates.js
									
									
									
									
									
								
							
							
						
						
									
										412
									
								
								certificates.js
									
									
									
									
									
								
							@ -1,70 +1,70 @@
 | 
				
			|||||||
'use strict';
 | 
					"use strict";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var certificates = module.exports;
 | 
					var certificates = module.exports;
 | 
				
			||||||
var store = certificates;
 | 
					var store = certificates;
 | 
				
			||||||
var U = require('./utils.js');
 | 
					var U = require("./utils.js");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var fs = require('fs');
 | 
					var fs = require("fs");
 | 
				
			||||||
var path = require('path');
 | 
					var path = require("path");
 | 
				
			||||||
var PromiseA = require('./promise.js');
 | 
					var PromiseA = require("./promise.js");
 | 
				
			||||||
var sfs = require('safe-replace');
 | 
					var sfs = require("safe-replace");
 | 
				
			||||||
var readFileAsync = PromiseA.promisify(fs.readFile);
 | 
					var readFileAsync = PromiseA.promisify(fs.readFile);
 | 
				
			||||||
var writeFileAsync = PromiseA.promisify(fs.writeFile);
 | 
					var writeFileAsync = PromiseA.promisify(fs.writeFile);
 | 
				
			||||||
var mkdirpAsync = PromiseA.promisify(require('@root/mkdirp'));
 | 
					var mkdirpAsync = PromiseA.promisify(require("@root/mkdirp"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Certificates.check
 | 
					// Certificates.check
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
// Use certificate.id, or subject, if id hasn't been set, to find a certificate.
 | 
					// Use certificate.id, or subject, if id hasn't been set, to find a certificate.
 | 
				
			||||||
// Return an object with string PEMs for cert and chain (or null, not undefined)
 | 
					// Return an object with string PEMs for cert and chain (or null, not undefined)
 | 
				
			||||||
certificates.check = function(opts) {
 | 
					certificates.check = function(opts) {
 | 
				
			||||||
	// { certificate.id, subject, ... }
 | 
					    // { certificate.id, subject, ... }
 | 
				
			||||||
	var id = (opts.certificate && opts.certificate.id) || opts.subject;
 | 
					    var id = (opts.certificate && opts.certificate.id) || opts.subject;
 | 
				
			||||||
	//console.log('certificates.check for', opts);
 | 
					    //console.log('certificates.check for', opts);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// For advanced use cases:
 | 
					    // For advanced use cases:
 | 
				
			||||||
	// This just goes to show that any options set in approveDomains() will be available here
 | 
					    // This just goes to show that any options set in approveDomains() will be available here
 | 
				
			||||||
	// (the same is true for all of the hooks in this file)
 | 
					    // (the same is true for all of the hooks in this file)
 | 
				
			||||||
	if (opts.exampleThrowError) {
 | 
					    if (opts.exampleThrowError) {
 | 
				
			||||||
		return Promise.reject(new Error('You want an error? You got it!'));
 | 
					        return Promise.reject(new Error("You want an error? You got it!"));
 | 
				
			||||||
	}
 | 
					    }
 | 
				
			||||||
	if (opts.exampleReturnNull) {
 | 
					    if (opts.exampleReturnNull) {
 | 
				
			||||||
		return Promise.resolve(null);
 | 
					        return Promise.resolve(null);
 | 
				
			||||||
	}
 | 
					    }
 | 
				
			||||||
	if (opts.exampleReturnCerts) {
 | 
					    if (opts.exampleReturnCerts) {
 | 
				
			||||||
		return Promise.resolve(opts.exampleReturnCerts);
 | 
					        return Promise.resolve(opts.exampleReturnCerts);
 | 
				
			||||||
	}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return Promise.all([
 | 
					    return Promise.all([
 | 
				
			||||||
		readFileAsync(U._tameWild(privkeyPath(store, opts), id), 'ascii'), // 0 // all other PEM types are just
 | 
					        readFileAsync(U._tameWild(privkeyPath(store, opts), id), "ascii"), // 0 // all other PEM types are just
 | 
				
			||||||
		readFileAsync(U._tameWild(certPath(store, opts), id), 'ascii'), // 1 // some arrangement of these 3
 | 
					        readFileAsync(U._tameWild(certPath(store, opts), id), "ascii"), // 1 // some arrangement of these 3
 | 
				
			||||||
		readFileAsync(U._tameWild(chainPath(store, opts), id), 'ascii') // 2 // (bundle, combined, fullchain, etc)
 | 
					        readFileAsync(U._tameWild(chainPath(store, opts), id), "ascii") // 2 // (bundle, combined, fullchain, etc)
 | 
				
			||||||
	])
 | 
					    ])
 | 
				
			||||||
		.then(function(all) {
 | 
					        .then(function(all) {
 | 
				
			||||||
			////////////////////////
 | 
					            ////////////////////////
 | 
				
			||||||
			// PAY ATTENTION HERE //
 | 
					            // PAY ATTENTION HERE //
 | 
				
			||||||
			////////////////////////
 | 
					            ////////////////////////
 | 
				
			||||||
			// This is all you have to return: cert, chain
 | 
					            // This is all you have to return: cert, chain
 | 
				
			||||||
			return {
 | 
					            return {
 | 
				
			||||||
				cert: all[1], // string PEM. the bare cert, half of the concatonated fullchain.pem you need
 | 
					                cert: all[1], // string PEM. the bare cert, half of the concatonated fullchain.pem you need
 | 
				
			||||||
				chain: all[2], // string PEM. the bare chain, the second half of the fullchain.pem
 | 
					                chain: all[2], // string PEM. the bare chain, the second half of the fullchain.pem
 | 
				
			||||||
				privkey: all[0] // string PEM. optional, allows checkKeypair to be skipped
 | 
					                privkey: all[0] // string PEM. optional, allows checkKeypair to be skipped
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				// These can be useful to store in your database,
 | 
					                // These can be useful to store in your database,
 | 
				
			||||||
				// but otherwise they're easy to derive from the cert.
 | 
					                // but otherwise they're easy to derive from the cert.
 | 
				
			||||||
				// (when not available they'll be generated from cert-info)
 | 
					                // (when not available they'll be generated from cert-info)
 | 
				
			||||||
				//, subject: certinfo.subject     // string domain name
 | 
					                //, subject: certinfo.subject     // string domain name
 | 
				
			||||||
				//, altnames: certinfo.altnames   // array of domain name strings
 | 
					                //, altnames: certinfo.altnames   // array of domain name strings
 | 
				
			||||||
				//, issuedAt: certinfo.issuedAt   // number in ms (a.k.a. NotBefore)
 | 
					                //, issuedAt: certinfo.issuedAt   // number in ms (a.k.a. NotBefore)
 | 
				
			||||||
				//, expiresAt: certinfo.expiresAt // number in ms (a.k.a. NotAfter)
 | 
					                //, expiresAt: certinfo.expiresAt // number in ms (a.k.a. NotAfter)
 | 
				
			||||||
			};
 | 
					            };
 | 
				
			||||||
		})
 | 
					        })
 | 
				
			||||||
		.catch(function(err) {
 | 
					        .catch(function(err) {
 | 
				
			||||||
			// Treat non-exceptional failures as null returns (not undefined)
 | 
					            // Treat non-exceptional failures as null returns (not undefined)
 | 
				
			||||||
			if ('ENOENT' === err.code) {
 | 
					            if ("ENOENT" === err.code) {
 | 
				
			||||||
				return null;
 | 
					                return null;
 | 
				
			||||||
			}
 | 
					            }
 | 
				
			||||||
			throw err; // True exceptions should be thrown
 | 
					            throw err; // True exceptions should be thrown
 | 
				
			||||||
		});
 | 
					        });
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Certificates.checkKeypair
 | 
					// Certificates.checkKeypair
 | 
				
			||||||
@ -72,27 +72,27 @@ certificates.check = function(opts) {
 | 
				
			|||||||
// Use certificate.kid, certificate.id, or subject to find a certificate keypair
 | 
					// Use certificate.kid, certificate.id, or subject to find a certificate keypair
 | 
				
			||||||
// Return an object with string privateKeyPem and/or object privateKeyJwk (or null, not undefined)
 | 
					// Return an object with string privateKeyPem and/or object privateKeyJwk (or null, not undefined)
 | 
				
			||||||
certificates.checkKeypair = function(opts) {
 | 
					certificates.checkKeypair = function(opts) {
 | 
				
			||||||
	//console.log('certificates.checkKeypair:', opts);
 | 
					    //console.log('certificates.checkKeypair:', opts);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return readFileAsync(
 | 
					    return readFileAsync(
 | 
				
			||||||
		U._tameWild(privkeyPath(store, opts), opts.subject),
 | 
					        U._tameWild(privkeyPath(store, opts), opts.subject),
 | 
				
			||||||
		'ascii'
 | 
					        "ascii"
 | 
				
			||||||
	)
 | 
					    )
 | 
				
			||||||
		.then(function(key) {
 | 
					        .then(function(key) {
 | 
				
			||||||
			////////////////////////
 | 
					            ////////////////////////
 | 
				
			||||||
			// PAY ATTENTION HERE //
 | 
					            // PAY ATTENTION HERE //
 | 
				
			||||||
			////////////////////////
 | 
					            ////////////////////////
 | 
				
			||||||
			return {
 | 
					            return {
 | 
				
			||||||
				privateKeyPem: key // In this case we only saved privateKeyPem, so we only return it
 | 
					                privateKeyPem: key // In this case we only saved privateKeyPem, so we only return it
 | 
				
			||||||
				//privateKeyJwk: null     // (but it's fine, just different encodings of the same thing)
 | 
					                //privateKeyJwk: null     // (but it's fine, just different encodings of the same thing)
 | 
				
			||||||
			};
 | 
					            };
 | 
				
			||||||
		})
 | 
					        })
 | 
				
			||||||
		.catch(function(err) {
 | 
					        .catch(function(err) {
 | 
				
			||||||
			if ('ENOENT' === err.code) {
 | 
					            if ("ENOENT" === err.code) {
 | 
				
			||||||
				return null;
 | 
					                return null;
 | 
				
			||||||
			}
 | 
					            }
 | 
				
			||||||
			throw err;
 | 
					            throw err;
 | 
				
			||||||
		});
 | 
					        });
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Certificates.setKeypair({ certificate, subject, keypair, ... }):
 | 
					// Certificates.setKeypair({ certificate, subject, keypair, ... }):
 | 
				
			||||||
@ -100,22 +100,22 @@ certificates.checkKeypair = function(opts) {
 | 
				
			|||||||
// Use certificate.kid (or certificate.id or subject if no kid is present) to find a certificate keypair
 | 
					// Use certificate.kid (or certificate.id or subject if no kid is present) to find a certificate keypair
 | 
				
			||||||
// Return null (not undefined) on success, or throw on error
 | 
					// Return null (not undefined) on success, or throw on error
 | 
				
			||||||
certificates.setKeypair = function(opts) {
 | 
					certificates.setKeypair = function(opts) {
 | 
				
			||||||
	var keypair = opts.keypair || keypair;
 | 
					    var keypair = opts.keypair || keypair;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Ignore.
 | 
					    // Ignore.
 | 
				
			||||||
	// Just specific implementation details.
 | 
					    // Just specific implementation details.
 | 
				
			||||||
	return mkdirpAsync(
 | 
					    return mkdirpAsync(
 | 
				
			||||||
		U._tameWild(path.dirname(privkeyPath(store, opts)), opts.subject)
 | 
					        U._tameWild(path.dirname(privkeyPath(store, opts)), opts.subject)
 | 
				
			||||||
	).then(function() {
 | 
					    ).then(function() {
 | 
				
			||||||
		// keypair is normally an opaque object, but here it's a PEM for the FS (for things like Apache and Nginx)
 | 
					        // keypair is normally an opaque object, but here it's a PEM for the FS (for things like Apache and Nginx)
 | 
				
			||||||
		return writeFileAsync(
 | 
					        return writeFileAsync(
 | 
				
			||||||
			U._tameWild(privkeyPath(store, opts), opts.subject),
 | 
					            U._tameWild(privkeyPath(store, opts), opts.subject),
 | 
				
			||||||
			keypair.privateKeyPem,
 | 
					            keypair.privateKeyPem,
 | 
				
			||||||
			'ascii'
 | 
					            "ascii"
 | 
				
			||||||
		).then(function() {
 | 
					        ).then(function() {
 | 
				
			||||||
			return null;
 | 
					            return null;
 | 
				
			||||||
		});
 | 
					        });
 | 
				
			||||||
	});
 | 
					    });
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Certificates.set({ subject, pems, ... }):
 | 
					// Certificates.set({ subject, pems, ... }):
 | 
				
			||||||
@ -123,143 +123,143 @@ certificates.setKeypair = function(opts) {
 | 
				
			|||||||
// Use certificate.id (or subject if no ki is present) to save a certificate
 | 
					// Use certificate.id (or subject if no ki is present) to save a certificate
 | 
				
			||||||
// Return null (not undefined) on success, or throw on error
 | 
					// Return null (not undefined) on success, or throw on error
 | 
				
			||||||
certificates.set = function(opts) {
 | 
					certificates.set = function(opts) {
 | 
				
			||||||
	//console.log('certificates.set:', opts);
 | 
					    //console.log('certificates.set:', opts);
 | 
				
			||||||
	var pems = {
 | 
					    var pems = {
 | 
				
			||||||
		cert: opts.pems.cert, // string PEM the first half of the concatonated fullchain.pem cert
 | 
					        cert: opts.pems.cert, // string PEM the first half of the concatonated fullchain.pem cert
 | 
				
			||||||
		chain: opts.pems.chain, // string PEM the second half (yes, you need this too)
 | 
					        chain: opts.pems.chain, // string PEM the second half (yes, you need this too)
 | 
				
			||||||
		privkey: opts.pems.privkey // Ignore. string PEM, useful if you have to create bundle.pem
 | 
					        privkey: opts.pems.privkey // Ignore. string PEM, useful if you have to create bundle.pem
 | 
				
			||||||
	};
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Ignore
 | 
					    // Ignore
 | 
				
			||||||
	// Just implementation specific details (writing lots of combinatons of files)
 | 
					    // Just implementation specific details (writing lots of combinatons of files)
 | 
				
			||||||
	return mkdirpAsync(path.dirname(certPath(store, opts)))
 | 
					    return mkdirpAsync(path.dirname(certPath(store, opts)))
 | 
				
			||||||
		.then(function() {
 | 
					        .then(function() {
 | 
				
			||||||
			return mkdirpAsync(
 | 
					            return mkdirpAsync(
 | 
				
			||||||
				path.dirname(U._tameWild(chainPath(store, opts), opts.subject))
 | 
					                path.dirname(U._tameWild(chainPath(store, opts), opts.subject))
 | 
				
			||||||
			).then(function() {
 | 
					            ).then(function() {
 | 
				
			||||||
				return mkdirpAsync(
 | 
					                return mkdirpAsync(
 | 
				
			||||||
					path.dirname(
 | 
					                    path.dirname(
 | 
				
			||||||
						U._tameWild(fullchainPath(store, opts), opts.subject)
 | 
					                        U._tameWild(fullchainPath(store, opts), opts.subject)
 | 
				
			||||||
					)
 | 
					                    )
 | 
				
			||||||
				).then(function() {
 | 
					                ).then(function() {
 | 
				
			||||||
					return mkdirpAsync(
 | 
					                    return mkdirpAsync(
 | 
				
			||||||
						path.dirname(
 | 
					                        path.dirname(
 | 
				
			||||||
							U._tameWild(bundlePath(store, opts), opts.subject)
 | 
					                            U._tameWild(bundlePath(store, opts), opts.subject)
 | 
				
			||||||
						)
 | 
					                        )
 | 
				
			||||||
					).then(function() {
 | 
					                    ).then(function() {
 | 
				
			||||||
						var fullchainPem = [
 | 
					                        var fullchainPem = [
 | 
				
			||||||
							pems.cert.trim() + '\n',
 | 
					                            pems.cert.trim() + "\n",
 | 
				
			||||||
							pems.chain.trim() + '\n'
 | 
					                            pems.chain.trim() + "\n"
 | 
				
			||||||
						].join('\n'); // for Apache, Nginx, etc
 | 
					                        ].join("\n"); // for Apache, Nginx, etc
 | 
				
			||||||
						var bundlePem = [
 | 
					                        var bundlePem = [
 | 
				
			||||||
							pems.privkey,
 | 
					                            pems.privkey,
 | 
				
			||||||
							pems.cert,
 | 
					                            pems.cert,
 | 
				
			||||||
							pems.chain
 | 
					                            pems.chain
 | 
				
			||||||
						].join('\n'); // for HAProxy
 | 
					                        ].join("\n"); // for HAProxy
 | 
				
			||||||
						return PromiseA.all([
 | 
					                        return PromiseA.all([
 | 
				
			||||||
							sfs.writeFileAsync(
 | 
					                            sfs.writeFileAsync(
 | 
				
			||||||
								U._tameWild(
 | 
					                                U._tameWild(
 | 
				
			||||||
									certPath(store, opts),
 | 
					                                    certPath(store, opts),
 | 
				
			||||||
									opts.subject
 | 
					                                    opts.subject
 | 
				
			||||||
								),
 | 
					                                ),
 | 
				
			||||||
								pems.cert,
 | 
					                                pems.cert,
 | 
				
			||||||
								'ascii'
 | 
					                                "ascii"
 | 
				
			||||||
							),
 | 
					                            ),
 | 
				
			||||||
							sfs.writeFileAsync(
 | 
					                            sfs.writeFileAsync(
 | 
				
			||||||
								U._tameWild(
 | 
					                                U._tameWild(
 | 
				
			||||||
									chainPath(store, opts),
 | 
					                                    chainPath(store, opts),
 | 
				
			||||||
									opts.subject
 | 
					                                    opts.subject
 | 
				
			||||||
								),
 | 
					                                ),
 | 
				
			||||||
								pems.chain,
 | 
					                                pems.chain,
 | 
				
			||||||
								'ascii'
 | 
					                                "ascii"
 | 
				
			||||||
							),
 | 
					                            ),
 | 
				
			||||||
							// Most web servers need these two
 | 
					                            // Most web servers need these two
 | 
				
			||||||
							sfs.writeFileAsync(
 | 
					                            sfs.writeFileAsync(
 | 
				
			||||||
								U._tameWild(
 | 
					                                U._tameWild(
 | 
				
			||||||
									fullchainPath(store, opts),
 | 
					                                    fullchainPath(store, opts),
 | 
				
			||||||
									opts.subject
 | 
					                                    opts.subject
 | 
				
			||||||
								),
 | 
					                                ),
 | 
				
			||||||
								fullchainPem,
 | 
					                                fullchainPem,
 | 
				
			||||||
								'ascii'
 | 
					                                "ascii"
 | 
				
			||||||
							),
 | 
					                            ),
 | 
				
			||||||
							// HAProxy needs "bundle.pem" aka "combined.pem"
 | 
					                            // HAProxy needs "bundle.pem" aka "combined.pem"
 | 
				
			||||||
							sfs.writeFileAsync(
 | 
					                            sfs.writeFileAsync(
 | 
				
			||||||
								U._tameWild(
 | 
					                                U._tameWild(
 | 
				
			||||||
									bundlePath(store, opts),
 | 
					                                    bundlePath(store, opts),
 | 
				
			||||||
									opts.subject
 | 
					                                    opts.subject
 | 
				
			||||||
								),
 | 
					                                ),
 | 
				
			||||||
								bundlePem,
 | 
					                                bundlePem,
 | 
				
			||||||
								'ascii'
 | 
					                                "ascii"
 | 
				
			||||||
							)
 | 
					                            )
 | 
				
			||||||
						]);
 | 
					                        ]);
 | 
				
			||||||
					});
 | 
					                    });
 | 
				
			||||||
				});
 | 
					                });
 | 
				
			||||||
			});
 | 
					            });
 | 
				
			||||||
		})
 | 
					        })
 | 
				
			||||||
		.then(function() {
 | 
					        .then(function() {
 | 
				
			||||||
			// That's your job: return null
 | 
					            // That's your job: return null
 | 
				
			||||||
			return null;
 | 
					            return null;
 | 
				
			||||||
		});
 | 
					        });
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function liveDir(store, opts) {
 | 
					function liveDir(store, opts) {
 | 
				
			||||||
	return opts.liveDir || path.join(opts.configDir, 'live', opts.subject);
 | 
					    return opts.liveDir || path.join(opts.configDir, "live", opts.subject);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function privkeyPath(store, opts) {
 | 
					function privkeyPath(store, opts) {
 | 
				
			||||||
	var dir = U._tpl(
 | 
					    var dir = U._tpl(
 | 
				
			||||||
		store,
 | 
					        store,
 | 
				
			||||||
		opts,
 | 
					        opts,
 | 
				
			||||||
		opts.serverKeyPath ||
 | 
					        opts.serverKeyPath ||
 | 
				
			||||||
			opts.privkeyPath ||
 | 
					            opts.privkeyPath ||
 | 
				
			||||||
			opts.domainKeyPath ||
 | 
					            opts.domainKeyPath ||
 | 
				
			||||||
			store.options.serverKeyPath ||
 | 
					            store.options.serverKeyPath ||
 | 
				
			||||||
			store.options.privkeyPath ||
 | 
					            store.options.privkeyPath ||
 | 
				
			||||||
			store.options.domainKeyPath ||
 | 
					            store.options.domainKeyPath ||
 | 
				
			||||||
			path.join(liveDir(), 'privkey.pem')
 | 
					            path.join(liveDir(), "privkey.pem")
 | 
				
			||||||
	);
 | 
					    );
 | 
				
			||||||
	return U._tameWild(dir, opts.subject || '');
 | 
					    return U._tameWild(dir, opts.subject || "");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function certPath(store, opts) {
 | 
					function certPath(store, opts) {
 | 
				
			||||||
	var pathname =
 | 
					    var pathname =
 | 
				
			||||||
		opts.certPath ||
 | 
					        opts.certPath ||
 | 
				
			||||||
		store.options.certPath ||
 | 
					        store.options.certPath ||
 | 
				
			||||||
		path.join(liveDir(), 'cert.pem');
 | 
					        path.join(liveDir(), "cert.pem");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var dir = U._tpl(store, opts, pathname);
 | 
					    var dir = U._tpl(store, opts, pathname);
 | 
				
			||||||
	return U._tameWild(dir, opts.subject || '');
 | 
					    return U._tameWild(dir, opts.subject || "");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function fullchainPath(store, opts) {
 | 
					function fullchainPath(store, opts) {
 | 
				
			||||||
	var dir = U._tpl(
 | 
					    var dir = U._tpl(
 | 
				
			||||||
		store,
 | 
					        store,
 | 
				
			||||||
		opts,
 | 
					        opts,
 | 
				
			||||||
		opts.fullchainPath ||
 | 
					        opts.fullchainPath ||
 | 
				
			||||||
			store.options.fullchainPath ||
 | 
					            store.options.fullchainPath ||
 | 
				
			||||||
			path.join(liveDir(), 'fullchain.pem')
 | 
					            path.join(liveDir(), "fullchain.pem")
 | 
				
			||||||
	);
 | 
					    );
 | 
				
			||||||
	return U._tameWild(dir, opts.subject || '');
 | 
					    return U._tameWild(dir, opts.subject || "");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function chainPath(store, opts) {
 | 
					function chainPath(store, opts) {
 | 
				
			||||||
	var dir = U._tpl(
 | 
					    var dir = U._tpl(
 | 
				
			||||||
		store,
 | 
					        store,
 | 
				
			||||||
		opts,
 | 
					        opts,
 | 
				
			||||||
		opts.chainPath ||
 | 
					        opts.chainPath ||
 | 
				
			||||||
			store.options.chainPath ||
 | 
					            store.options.chainPath ||
 | 
				
			||||||
			path.join(liveDir(), 'chain.pem')
 | 
					            path.join(liveDir(), "chain.pem")
 | 
				
			||||||
	);
 | 
					    );
 | 
				
			||||||
	return U._tameWild(dir, opts.subject || '');
 | 
					    return U._tameWild(dir, opts.subject || "");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function bundlePath(store, opts) {
 | 
					function bundlePath(store, opts) {
 | 
				
			||||||
	var dir = U._tpl(
 | 
					    var dir = U._tpl(
 | 
				
			||||||
		store,
 | 
					        store,
 | 
				
			||||||
		opts,
 | 
					        opts,
 | 
				
			||||||
		opts.bundlePath ||
 | 
					        opts.bundlePath ||
 | 
				
			||||||
			store.options.bundlePath ||
 | 
					            store.options.bundlePath ||
 | 
				
			||||||
			path.join(liveDir(), 'bundle.pem')
 | 
					            path.join(liveDir(), "bundle.pem")
 | 
				
			||||||
	);
 | 
					    );
 | 
				
			||||||
	return U._tameWild(dir, opts.subject || '');
 | 
					    return U._tameWild(dir, opts.subject || "");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										98
									
								
								index.js
									
									
									
									
									
								
							
							
						
						
									
										98
									
								
								index.js
									
									
									
									
									
								
							@ -1,7 +1,7 @@
 | 
				
			|||||||
'use strict';
 | 
					"use strict";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var os = require('os');
 | 
					var os = require("os");
 | 
				
			||||||
var path = require('path');
 | 
					var path = require("path");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// How Storage Works in Greenlock: High-Level Call Stack
 | 
					// How Storage Works in Greenlock: High-Level Call Stack
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
@ -50,32 +50,32 @@ var path = require('path');
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// Either your user calls create with specific options, or greenlock calls it for you with a big options blob
 | 
					// Either your user calls create with specific options, or greenlock calls it for you with a big options blob
 | 
				
			||||||
module.exports.create = function(config) {
 | 
					module.exports.create = function(config) {
 | 
				
			||||||
	// Bear in mind that the only time any of this gets called is on first access after startup, new registration, and
 | 
					    // Bear in mind that the only time any of this gets called is on first access after startup, new registration, and
 | 
				
			||||||
	// renewal - so none of this needs to be particularly fast. It may need to be memory efficient, however - if you have
 | 
					    // renewal - so none of this needs to be particularly fast. It may need to be memory efficient, however - if you have
 | 
				
			||||||
	// more than 10,000 domains, for example.
 | 
					    // more than 10,000 domains, for example.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// basic setup
 | 
					    // basic setup
 | 
				
			||||||
	var store = {
 | 
					    var store = {
 | 
				
			||||||
		accounts: require('./accounts.js'),
 | 
					        accounts: require("./accounts.js"),
 | 
				
			||||||
		certificates: require('./certificates.js')
 | 
					        certificates: require("./certificates.js")
 | 
				
			||||||
	};
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// For you store.options should probably start empty and get a minimal set of options copied from `config` above.
 | 
					    // For you store.options should probably start empty and get a minimal set of options copied from `config` above.
 | 
				
			||||||
	// Example:
 | 
					    // Example:
 | 
				
			||||||
	//store.options = {};
 | 
					    //store.options = {};
 | 
				
			||||||
	//store.options.databaseUrl = config.databaseUrl;
 | 
					    //store.options.databaseUrl = config.databaseUrl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// In the case of greenlock-store-fs there's a bunch of legacy stuff that goes on, so we just clobber it all on.
 | 
					    // In the case of greenlock-store-fs there's a bunch of legacy stuff that goes on, so we just clobber it all on.
 | 
				
			||||||
	// Don't be like greenlock-store-fs (see note above).
 | 
					    // Don't be like greenlock-store-fs (see note above).
 | 
				
			||||||
	store.options = mergeOptions(config);
 | 
					    store.options = mergeOptions(config);
 | 
				
			||||||
	store.accounts.options = store.options;
 | 
					    store.accounts.options = store.options;
 | 
				
			||||||
	store.certificates.options = store.options;
 | 
					    store.certificates.options = store.options;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!config.basePath && !config.configDir) {
 | 
					    if (!config.basePath && !config.configDir) {
 | 
				
			||||||
		console.info('Greenlock Store FS Path:', store.options.configDir);
 | 
					        console.info("Greenlock Store FS Path:", store.options.configDir);
 | 
				
			||||||
	}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return store;
 | 
					    return store;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
///////////////////////////////////////////////////////////////////////////////
 | 
					///////////////////////////////////////////////////////////////////////////////
 | 
				
			||||||
@ -84,36 +84,36 @@ module.exports.create = function(config) {
 | 
				
			|||||||
//
 | 
					//
 | 
				
			||||||
// Everything below this line is just implementation specific
 | 
					// Everything below this line is just implementation specific
 | 
				
			||||||
var defaults = {
 | 
					var defaults = {
 | 
				
			||||||
	basePath: path.join(os.homedir(), '.config', 'greenlock'),
 | 
					    basePath: path.join(os.homedir(), ".config", "greenlock"),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	accountsDir: path.join(':basePath', 'accounts', ':directoryUrl'),
 | 
					    accountsDir: path.join(":basePath", "accounts", ":directoryUrl"),
 | 
				
			||||||
	serverDirGet: function(copy) {
 | 
					    serverDirGet: function(copy) {
 | 
				
			||||||
		return (copy.directoryUrl || copy.server || '')
 | 
					        return (copy.directoryUrl || copy.server || "")
 | 
				
			||||||
			.replace('https://', '')
 | 
					            .replace("https://", "")
 | 
				
			||||||
			.replace(/(\/)$/, '')
 | 
					            .replace(/(\/)$/, "")
 | 
				
			||||||
			.replace(/\//g, path.sep);
 | 
					            .replace(/\//g, path.sep);
 | 
				
			||||||
	},
 | 
					    },
 | 
				
			||||||
  privkeyPath: path.join(':basePath', ':env', ':subject', 'privkey.pem'),
 | 
					    privkeyPath: path.join(":basePath", ":env", ":subject", "privkey.pem"),
 | 
				
			||||||
	fullchainPath: path.join(':basePath', ':env', ':subject', 'fullchain.pem'),
 | 
					    fullchainPath: path.join(":basePath", ":env", ":subject", "fullchain.pem"),
 | 
				
			||||||
	certPath: path.join(':basePath', ':env', ':subject', 'cert.pem'),
 | 
					    certPath: path.join(":basePath", ":env", ":subject", "cert.pem"),
 | 
				
			||||||
	chainPath: path.join(':basePath', ':env', ':subject', 'chain.pem'),
 | 
					    chainPath: path.join(":basePath", ":env", ":subject", "chain.pem"),
 | 
				
			||||||
	bundlePath: path.join(':basePath', ':env', ':subject', 'bundle.pem')
 | 
					    bundlePath: path.join(":basePath", ":env", ":subject", "bundle.pem")
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
defaults.configDir = defaults.basePath;
 | 
					defaults.configDir = defaults.basePath;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function mergeOptions(configs) {
 | 
					function mergeOptions(configs) {
 | 
				
			||||||
	if (!configs.serverKeyPath) {
 | 
					    if (!configs.serverKeyPath) {
 | 
				
			||||||
		configs.serverKeyPath =
 | 
					        configs.serverKeyPath =
 | 
				
			||||||
			configs.domainKeyPath ||
 | 
					            configs.domainKeyPath ||
 | 
				
			||||||
			configs.privkeyPath ||
 | 
					            configs.privkeyPath ||
 | 
				
			||||||
			defaults.privkeyPath;
 | 
					            defaults.privkeyPath;
 | 
				
			||||||
	}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	Object.keys(defaults).forEach(function(key) {
 | 
					    Object.keys(defaults).forEach(function(key) {
 | 
				
			||||||
		if (!configs[key]) {
 | 
					        if (!configs[key]) {
 | 
				
			||||||
			configs[key] = defaults[key];
 | 
					            configs[key] = defaults[key];
 | 
				
			||||||
		}
 | 
					        }
 | 
				
			||||||
	});
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return configs;
 | 
					    return configs;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										30
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										30
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							@ -1,18 +1,18 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
  "name": "greenlock-store-fs",
 | 
					    "name": "greenlock-store-fs",
 | 
				
			||||||
  "version": "3.0.1",
 | 
					    "version": "3.2.0",
 | 
				
			||||||
  "lockfileVersion": 1,
 | 
					    "lockfileVersion": 1,
 | 
				
			||||||
  "requires": true,
 | 
					    "requires": true,
 | 
				
			||||||
  "dependencies": {
 | 
					    "dependencies": {
 | 
				
			||||||
    "@root/mkdirp": {
 | 
					        "@root/mkdirp": {
 | 
				
			||||||
      "version": "1.0.0",
 | 
					            "version": "1.0.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/@root/mkdirp/-/mkdirp-1.0.0.tgz",
 | 
					            "resolved": "https://registry.npmjs.org/@root/mkdirp/-/mkdirp-1.0.0.tgz",
 | 
				
			||||||
      "integrity": "sha512-hxGAYUx5029VggfG+U9naAhQkoMSXtOeXtbql97m3Hi6/sQSRL/4khKZPyOF6w11glyCOU38WCNLu9nUcSjOfA=="
 | 
					            "integrity": "sha512-hxGAYUx5029VggfG+U9naAhQkoMSXtOeXtbql97m3Hi6/sQSRL/4khKZPyOF6w11glyCOU38WCNLu9nUcSjOfA=="
 | 
				
			||||||
    },
 | 
					        },
 | 
				
			||||||
    "safe-replace": {
 | 
					        "safe-replace": {
 | 
				
			||||||
      "version": "1.1.0",
 | 
					            "version": "1.1.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/safe-replace/-/safe-replace-1.1.0.tgz",
 | 
					            "resolved": "https://registry.npmjs.org/safe-replace/-/safe-replace-1.1.0.tgz",
 | 
				
			||||||
      "integrity": "sha512-9/V2E0CDsKs9DWOOwJH7jYpSl9S3N05uyevNjvsnDauBqRowBPOyot1fIvV5N2IuZAbYyvrTXrYFVG0RZInfFw=="
 | 
					            "integrity": "sha512-9/V2E0CDsKs9DWOOwJH7jYpSl9S3N05uyevNjvsnDauBqRowBPOyot1fIvV5N2IuZAbYyvrTXrYFVG0RZInfFw=="
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										58
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										58
									
								
								package.json
									
									
									
									
									
								
							@ -1,31 +1,31 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
	"name": "greenlock-store-fs",
 | 
					    "name": "greenlock-store-fs",
 | 
				
			||||||
	"version": "3.2.0",
 | 
					    "version": "3.2.1",
 | 
				
			||||||
	"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.rootprojects.org/root/greenlock-store-fs.js",
 | 
					    "homepage": "https://git.rootprojects.org/root/greenlock-store-fs.js",
 | 
				
			||||||
	"main": "index.js",
 | 
					    "main": "index.js",
 | 
				
			||||||
	"directories": {
 | 
					    "directories": {
 | 
				
			||||||
		"test": "tests"
 | 
					        "test": "tests"
 | 
				
			||||||
	},
 | 
					    },
 | 
				
			||||||
	"scripts": {
 | 
					    "scripts": {
 | 
				
			||||||
		"test": "node tests"
 | 
					        "test": "node tests"
 | 
				
			||||||
	},
 | 
					    },
 | 
				
			||||||
	"repository": {
 | 
					    "repository": {
 | 
				
			||||||
		"type": "git",
 | 
					        "type": "git",
 | 
				
			||||||
		"url": "https://git.rootprojects.org/root/greenlock-store-fs.js.git"
 | 
					        "url": "https://git.rootprojects.org/root/greenlock-store-fs.js.git"
 | 
				
			||||||
	},
 | 
					    },
 | 
				
			||||||
	"keywords": [
 | 
					    "keywords": [
 | 
				
			||||||
		"greenlock",
 | 
					        "greenlock",
 | 
				
			||||||
		"json",
 | 
					        "json",
 | 
				
			||||||
		"keypairs",
 | 
					        "keypairs",
 | 
				
			||||||
		"certificates",
 | 
					        "certificates",
 | 
				
			||||||
		"store",
 | 
					        "store",
 | 
				
			||||||
		"database"
 | 
					        "database"
 | 
				
			||||||
	],
 | 
					    ],
 | 
				
			||||||
	"author": "AJ ONeal <solderjs@gmail.com> (https://solderjs.com/)",
 | 
					    "author": "AJ ONeal <solderjs@gmail.com> (https://solderjs.com/)",
 | 
				
			||||||
	"license": "MPL-2.0",
 | 
					    "license": "MPL-2.0",
 | 
				
			||||||
	"dependencies": {
 | 
					    "dependencies": {
 | 
				
			||||||
		"@root/mkdirp": "^1.0.0",
 | 
					        "@root/mkdirp": "^1.0.0",
 | 
				
			||||||
		"safe-replace": "^1.1.0"
 | 
					        "safe-replace": "^1.1.0"
 | 
				
			||||||
	}
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										34
									
								
								promise.js
									
									
									
									
									
								
							
							
						
						
									
										34
									
								
								promise.js
									
									
									
									
									
								
							@ -1,22 +1,22 @@
 | 
				
			|||||||
'use strict';
 | 
					"use strict";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function getPromise() {
 | 
					function getPromise() {
 | 
				
			||||||
	var util = require('util');
 | 
					    var util = require("util");
 | 
				
			||||||
	var PromiseA;
 | 
					    var PromiseA;
 | 
				
			||||||
	if (util.promisify && global.Promise) {
 | 
					    if (util.promisify && global.Promise) {
 | 
				
			||||||
		PromiseA = global.Promise;
 | 
					        PromiseA = global.Promise;
 | 
				
			||||||
		PromiseA.promisify = util.promisify;
 | 
					        PromiseA.promisify = util.promisify;
 | 
				
			||||||
	} else {
 | 
					    } else {
 | 
				
			||||||
		try {
 | 
					        try {
 | 
				
			||||||
			PromiseA = require('bluebird');
 | 
					            PromiseA = require("bluebird");
 | 
				
			||||||
		} catch (e) {
 | 
					        } catch (e) {
 | 
				
			||||||
			console.error(
 | 
					            console.error(
 | 
				
			||||||
				'Your version of node is missing Promise. Please run `npm install --save bluebird` in your project to fix'
 | 
					                "Your version of node is missing Promise. Please run `npm install --save bluebird` in your project to fix"
 | 
				
			||||||
			);
 | 
					            );
 | 
				
			||||||
			process.exit(10);
 | 
					            process.exit(10);
 | 
				
			||||||
		}
 | 
					        }
 | 
				
			||||||
	}
 | 
					    }
 | 
				
			||||||
	return PromiseA;
 | 
					    return PromiseA;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module.exports = getPromise();
 | 
					module.exports = getPromise();
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										52
									
								
								test.js
									
									
									
									
									
								
							
							
						
						
									
										52
									
								
								test.js
									
									
									
									
									
								
							@ -1,27 +1,33 @@
 | 
				
			|||||||
'use strict';
 | 
					"use strict";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var tester = require('greenlock-store-test');
 | 
					var tester = require("greenlock-store-test");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var crypto = require('crypto');
 | 
					var crypto = require("crypto");
 | 
				
			||||||
var os = require('os');
 | 
					var os = require("os");
 | 
				
			||||||
var path = require('path');
 | 
					var path = require("path");
 | 
				
			||||||
var basedir = path.join(os.tmpdir(), 'greenlock-store-fs-test-' + crypto.randomBytes(4).toString('hex'));
 | 
					var basedir = path.join(
 | 
				
			||||||
var domain = '*.example.com';
 | 
					    os.tmpdir(),
 | 
				
			||||||
var store = require('./').create({
 | 
					    "greenlock-store-fs-test-" + crypto.randomBytes(4).toString("hex")
 | 
				
			||||||
  configDir: basedir
 | 
					);
 | 
				
			||||||
, accountsDir: path.join(basedir, 'accounts')
 | 
					var domain = "*.example.com";
 | 
				
			||||||
, privkeyPath: path.join(basedir, 'live', domain, 'privkey.pem')
 | 
					var store = require("./").create({
 | 
				
			||||||
, fullchainPath: path.join(basedir, 'live', domain, 'fullchain.pem')
 | 
					    configDir: basedir,
 | 
				
			||||||
, certPath: path.join(basedir, 'live', domain, 'cert.pem')
 | 
					    accountsDir: path.join(basedir, "accounts"),
 | 
				
			||||||
, chainPath: path.join(basedir, 'live', domain, 'chain.pem')
 | 
					    privkeyPath: path.join(basedir, "live", domain, "privkey.pem"),
 | 
				
			||||||
, bundlePath: path.join(basedir, 'live', domain, 'bundle.pem')
 | 
					    fullchainPath: path.join(basedir, "live", domain, "fullchain.pem"),
 | 
				
			||||||
 | 
					    certPath: path.join(basedir, "live", domain, "cert.pem"),
 | 
				
			||||||
 | 
					    chainPath: path.join(basedir, "live", domain, "chain.pem"),
 | 
				
			||||||
 | 
					    bundlePath: path.join(basedir, "live", domain, "bundle.pem")
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
console.info('Test Dir:', basedir);
 | 
					console.info("Test Dir:", basedir);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
tester.test(store).then(function () {
 | 
					tester
 | 
				
			||||||
  console.info("PASS");
 | 
					    .test(store)
 | 
				
			||||||
}).catch(function (err) {
 | 
					    .then(function() {
 | 
				
			||||||
  console.error("FAIL");
 | 
					        console.info("PASS");
 | 
				
			||||||
  console.error(err);
 | 
					    })
 | 
				
			||||||
  process.exit(20);
 | 
					    .catch(function(err) {
 | 
				
			||||||
});
 | 
					        console.error("FAIL");
 | 
				
			||||||
 | 
					        console.error(err);
 | 
				
			||||||
 | 
					        process.exit(20);
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										80
									
								
								utils.js
									
									
									
									
									
								
							
							
						
						
									
										80
									
								
								utils.js
									
									
									
									
									
								
							@ -1,51 +1,51 @@
 | 
				
			|||||||
'use strict';
 | 
					"use strict";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var U = module.exports;
 | 
					var U = module.exports;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// because not all file systems like '*' in a name (and they're scary)
 | 
					// because not all file systems like '*' in a name (and they're scary)
 | 
				
			||||||
U._tameWild = function tameWild(pathname, wild) {
 | 
					U._tameWild = function tameWild(pathname, wild) {
 | 
				
			||||||
	if (!wild) {
 | 
					    if (!wild) {
 | 
				
			||||||
		return pathname;
 | 
					        return pathname;
 | 
				
			||||||
	}
 | 
					    }
 | 
				
			||||||
	var tame = wild.replace(/\*/g, '_');
 | 
					    var tame = wild.replace(/\*/g, "_");
 | 
				
			||||||
	return pathname.replace(wild, tame);
 | 
					    return pathname.replace(wild, tame);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
U._tpl = function tpl(store, opts, str) {
 | 
					U._tpl = function tpl(store, opts, str) {
 | 
				
			||||||
	var server = ['directoryUrl', 'serverDir', 'server'];
 | 
					    var server = ["directoryUrl", "serverDir", "server"];
 | 
				
			||||||
	var env = ['env', 'directoryUrl'];
 | 
					    var env = ["env", "directoryUrl"];
 | 
				
			||||||
	[
 | 
					    [
 | 
				
			||||||
		['basePath', 'configDir'],
 | 
					        ["basePath", "configDir"],
 | 
				
			||||||
		server,
 | 
					        server,
 | 
				
			||||||
		['subject', 'hostname', 'domain'],
 | 
					        ["subject", "hostname", "domain"],
 | 
				
			||||||
		env
 | 
					        env
 | 
				
			||||||
	].forEach(function(group) {
 | 
					    ].forEach(function(group) {
 | 
				
			||||||
		group.forEach(function(tmpl) {
 | 
					        group.forEach(function(tmpl) {
 | 
				
			||||||
			group.forEach(function(key) {
 | 
					            group.forEach(function(key) {
 | 
				
			||||||
				var item = opts[key] || store.options[key];
 | 
					                var item = opts[key] || store.options[key];
 | 
				
			||||||
				if ('string' !== typeof item) {
 | 
					                if ("string" !== typeof item) {
 | 
				
			||||||
					return;
 | 
					                    return;
 | 
				
			||||||
				}
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				if ('directoryUrl' === key) {
 | 
					                if ("directoryUrl" === key) {
 | 
				
			||||||
					item = item.replace(/^https?:\/\//i, '');
 | 
					                    item = item.replace(/^https?:\/\//i, "");
 | 
				
			||||||
				}
 | 
					                }
 | 
				
			||||||
				if ('env' === tmpl) {
 | 
					                if ("env" === tmpl) {
 | 
				
			||||||
					if (/staging/.test(item)) {
 | 
					                    if (/staging/.test(item)) {
 | 
				
			||||||
						item = 'staging';
 | 
					                        item = "staging";
 | 
				
			||||||
					} else if (/acme-v02/.test(item)) {
 | 
					                    } else if (/acme-v02/.test(item)) {
 | 
				
			||||||
						item = 'live';
 | 
					                        item = "live";
 | 
				
			||||||
					} else {
 | 
					                    } else {
 | 
				
			||||||
						// item = item;
 | 
					                        // item = item;
 | 
				
			||||||
					}
 | 
					                    }
 | 
				
			||||||
				}
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				if (-1 === str.indexOf(':' + tmpl)) {
 | 
					                if (-1 === str.indexOf(":" + tmpl)) {
 | 
				
			||||||
					return;
 | 
					                    return;
 | 
				
			||||||
				}
 | 
					                }
 | 
				
			||||||
				str = str.replace(':' + tmpl, item);
 | 
					                str = str.replace(":" + tmpl, item);
 | 
				
			||||||
			});
 | 
					            });
 | 
				
			||||||
		});
 | 
					        });
 | 
				
			||||||
	});
 | 
					    });
 | 
				
			||||||
	return str;
 | 
					    return str;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user