v0.7.0: reduce scope of find()
This commit is contained in:
		
							parent
							
								
									0ebc958305
								
							
						
					
					
						commit
						116b4925e7
					
				
							
								
								
									
										119
									
								
								manager.js
									
									
									
									
									
								
							
							
						
						
									
										119
									
								
								manager.js
									
									
									
									
									
								
							@ -11,15 +11,15 @@ var homedir = require('os').homedir();
 | 
			
		||||
var path = require('path');
 | 
			
		||||
var mkdirp = promisify(require('@root/mkdirp'));
 | 
			
		||||
 | 
			
		||||
Manage.create = function(opts) {
 | 
			
		||||
	if (!opts) {
 | 
			
		||||
		opts = {};
 | 
			
		||||
Manage.create = function(CONF) {
 | 
			
		||||
	if (!CONF) {
 | 
			
		||||
		CONF = {};
 | 
			
		||||
	}
 | 
			
		||||
	if (!opts.configFile) {
 | 
			
		||||
		opts.configFile = '~/.config/greenlock/manager.json';
 | 
			
		||||
		console.info('Greenlock Manager Config File: ' + opts.configFile);
 | 
			
		||||
	if (!CONF.configFile) {
 | 
			
		||||
		CONF.configFile = '~/.config/greenlock/manager.json';
 | 
			
		||||
		console.info('Greenlock Manager Config File: ' + CONF.configFile);
 | 
			
		||||
	}
 | 
			
		||||
	opts.configFile = opts.configFile.replace('~/', homedir + '/');
 | 
			
		||||
	CONF.configFile = CONF.configFile.replace('~/', homedir + '/');
 | 
			
		||||
 | 
			
		||||
	var manage = {};
 | 
			
		||||
 | 
			
		||||
@ -28,7 +28,7 @@ Manage.create = function(opts) {
 | 
			
		||||
	manage.defaults = manage.config = function(conf) {
 | 
			
		||||
		// get / set default site settings such as
 | 
			
		||||
		// subscriberEmail, store, challenges, renewOffset, renewStagger
 | 
			
		||||
		return Manage._getLatest(manage, opts).then(function(config) {
 | 
			
		||||
		return Manage._getLatest(manage, CONF).then(function(config) {
 | 
			
		||||
			if (!conf) {
 | 
			
		||||
				conf = JSON.parse(JSON.stringify(config));
 | 
			
		||||
				delete conf.sites;
 | 
			
		||||
@ -86,7 +86,7 @@ Manage.create = function(opts) {
 | 
			
		||||
	manage.add = function(args) {
 | 
			
		||||
		manage._txPromise = manage._txPromise.then(function() {
 | 
			
		||||
			// if the fs has changed since we last wrote, get the lastest from disk
 | 
			
		||||
			return Manage._getLatest(manage, opts).then(function(config) {
 | 
			
		||||
			return Manage._getLatest(manage, CONF).then(function(config) {
 | 
			
		||||
				// TODO move to Greenlock.add
 | 
			
		||||
				var subscriberEmail = args.subscriberEmail;
 | 
			
		||||
				var subject = args.subject || args.domain;
 | 
			
		||||
@ -131,7 +131,11 @@ Manage.create = function(opts) {
 | 
			
		||||
					altnames
 | 
			
		||||
						.slice(0)
 | 
			
		||||
						.sort()
 | 
			
		||||
						.join(' ') !== site.altnames.slice(0).sort().join(' ')
 | 
			
		||||
						.join(' ') !==
 | 
			
		||||
					site.altnames
 | 
			
		||||
						.slice(0)
 | 
			
		||||
						.sort()
 | 
			
		||||
						.join(' ')
 | 
			
		||||
				) {
 | 
			
		||||
					// TODO signal to wait for renewal?
 | 
			
		||||
					// it will definitely be renewed on the first request anyway
 | 
			
		||||
@ -180,11 +184,11 @@ Manage.create = function(opts) {
 | 
			
		||||
 | 
			
		||||
	manage.find = function(args) {
 | 
			
		||||
		return _find(args).then(function(existing) {
 | 
			
		||||
			if (!opts.find) {
 | 
			
		||||
			if (!CONF.find) {
 | 
			
		||||
				return existing;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			return Promise.resolve(opts.find(args)).then(function(results) {
 | 
			
		||||
			return Promise.resolve(CONF.find(args)).then(function(results) {
 | 
			
		||||
				// TODO also detect and delete stale (just ignoring them for now)
 | 
			
		||||
				var changed = [];
 | 
			
		||||
				var same = [];
 | 
			
		||||
@ -192,7 +196,7 @@ Manage.create = function(opts) {
 | 
			
		||||
					// Check lowercase subject names
 | 
			
		||||
					var subject = (_newer.subject || '').toLowerCase();
 | 
			
		||||
					// Set the default altnames to the subject, just in case
 | 
			
		||||
					var altnames = _newer.altnames || [];
 | 
			
		||||
					var altnames = (_newer.altnames || []).slice(0);
 | 
			
		||||
					if (!altnames.includes(subject)) {
 | 
			
		||||
						console.warn(
 | 
			
		||||
							"all site configs should include 'subject' and 'altnames': " +
 | 
			
		||||
@ -220,7 +224,6 @@ Manage.create = function(opts) {
 | 
			
		||||
						) {
 | 
			
		||||
							_older.renewAt = 0;
 | 
			
		||||
							_older.altnames = altnames;
 | 
			
		||||
							// TODO signal waitForRenewal (although it'll update on the first access automatically)
 | 
			
		||||
							changed.push(_older);
 | 
			
		||||
						} else {
 | 
			
		||||
							same.push(_older);
 | 
			
		||||
@ -243,7 +246,7 @@ Manage.create = function(opts) {
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				// kinda redundant to pull again, but whatever...
 | 
			
		||||
				return Manage._getLatest(manage, opts).then(function(config) {
 | 
			
		||||
				return Manage._getLatest(manage, CONF).then(function(config) {
 | 
			
		||||
					changed.forEach(function(site) {
 | 
			
		||||
						config.sites[site.subject] = site;
 | 
			
		||||
					});
 | 
			
		||||
@ -259,27 +262,27 @@ Manage.create = function(opts) {
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	function _find(args) {
 | 
			
		||||
		return Manage._getLatest(manage, opts).then(function(config) {
 | 
			
		||||
		return Manage._getLatest(manage, CONF).then(function(config) {
 | 
			
		||||
			// i.e. find certs more than 30 days old
 | 
			
		||||
			//args.issuedBefore = Date.now() - 30 * 24 * 60 * 60 * 1000;
 | 
			
		||||
			// i.e. find certs more that will expire in less than 45 days
 | 
			
		||||
			//args.expiresBefore = Date.now() + 45 * 24 * 60 * 60 * 1000;
 | 
			
		||||
			var issuedBefore = args.issuedBefore || Infinity;
 | 
			
		||||
			var expiresBefore = args.expiresBefore || Infinity; //Date.now() + 21 * 24 * 60 * 60 * 1000;
 | 
			
		||||
			var all = !args.altnames;
 | 
			
		||||
			var nameKeys = ['subject', 'altnames'];
 | 
			
		||||
 | 
			
		||||
			var altnames = (args.altnames || args.domains || []).slice(0);
 | 
			
		||||
			if (args.servername && !altnames.includes(args.servername)) {
 | 
			
		||||
				altnames.push(args.servername);
 | 
			
		||||
			}
 | 
			
		||||
			if (args.wildname && !altnames.includes(args.wildname)) {
 | 
			
		||||
				altnames.push(args.wildname);
 | 
			
		||||
			}
 | 
			
		||||
			// if there's anything to match, only return matches
 | 
			
		||||
			// if there's nothing to match, return everything
 | 
			
		||||
			var matchAll = !nameKeys.some(function(k) {
 | 
			
		||||
				return k in args;
 | 
			
		||||
			});
 | 
			
		||||
 | 
			
		||||
			var querynames = (args.altnames || []).slice(0);
 | 
			
		||||
 | 
			
		||||
			// TODO match ANY domain on any cert
 | 
			
		||||
			var sites = Object.keys(config.sites || {})
 | 
			
		||||
				.filter(function(sub) {
 | 
			
		||||
					var site = config.sites[sub];
 | 
			
		||||
				.filter(function(subject) {
 | 
			
		||||
					var site = doctor.site(config.sites, subject);
 | 
			
		||||
					if (site.deletedAt) {
 | 
			
		||||
						return false;
 | 
			
		||||
					}
 | 
			
		||||
@ -290,20 +293,20 @@ Manage.create = function(opts) {
 | 
			
		||||
						return false;
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					// after attribute filtering, before cert filtering
 | 
			
		||||
					if (matchAll) {
 | 
			
		||||
						return true;
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					// if subject is specified, don't return anything else
 | 
			
		||||
					if (args.subject) {
 | 
			
		||||
						if (site.subject === args.subject) {
 | 
			
		||||
							return true;
 | 
			
		||||
						}
 | 
			
		||||
					if (site.subject === args.subject) {
 | 
			
		||||
						return true;
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					// altnames, servername, and wildname all get rolled into one
 | 
			
		||||
					return (
 | 
			
		||||
						all ||
 | 
			
		||||
						(site.altnames || []).some(function(name) {
 | 
			
		||||
							return altnames.includes(name);
 | 
			
		||||
						})
 | 
			
		||||
					);
 | 
			
		||||
					return site.altnames.some(function(altname) {
 | 
			
		||||
						return querynames.includes(altname);
 | 
			
		||||
					});
 | 
			
		||||
				})
 | 
			
		||||
				.map(function(name) {
 | 
			
		||||
					var site = config.sites[name];
 | 
			
		||||
@ -326,7 +329,7 @@ Manage.create = function(opts) {
 | 
			
		||||
		});
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	manage.notify = opts.notify || _notify;
 | 
			
		||||
	manage.notify = CONF.notify || _notify;
 | 
			
		||||
	function _notify(ev, args) {
 | 
			
		||||
		if (!args) {
 | 
			
		||||
			args = ev;
 | 
			
		||||
@ -378,7 +381,7 @@ Manage.create = function(opts) {
 | 
			
		||||
 | 
			
		||||
	manage.update = function(args) {
 | 
			
		||||
		manage._txPromise = manage._txPromise.then(function() {
 | 
			
		||||
			return Manage._getLatest(manage, opts).then(function(config) {
 | 
			
		||||
			return Manage._getLatest(manage, CONF).then(function(config) {
 | 
			
		||||
				var site = config.sites[args.subject];
 | 
			
		||||
				//site.issuedAt = args.issuedAt;
 | 
			
		||||
				//site.expiresAt = args.expiresAt;
 | 
			
		||||
@ -394,7 +397,7 @@ Manage.create = function(opts) {
 | 
			
		||||
			throw new Error('should have a subject for sites to remove');
 | 
			
		||||
		}
 | 
			
		||||
		manage._txPromise = manage._txPromise.then(function() {
 | 
			
		||||
			return Manage._getLatest(manage, opts).then(function(config) {
 | 
			
		||||
			return Manage._getLatest(manage, CONF).then(function(config) {
 | 
			
		||||
				var site = config.sites[args.subject];
 | 
			
		||||
				if (!site) {
 | 
			
		||||
					return {};
 | 
			
		||||
@ -414,22 +417,22 @@ Manage.create = function(opts) {
 | 
			
		||||
	manage._config = {};
 | 
			
		||||
 | 
			
		||||
	manage._save = function(config) {
 | 
			
		||||
		return mkdirp(path.dirname(opts.configFile)).then(function() {
 | 
			
		||||
		return mkdirp(path.dirname(CONF.configFile)).then(function() {
 | 
			
		||||
			return sfs
 | 
			
		||||
				.writeFileAsync(
 | 
			
		||||
					opts.configFile,
 | 
			
		||||
					CONF.configFile,
 | 
			
		||||
					// pretty-print the config file
 | 
			
		||||
					JSON.stringify(config, null, 2),
 | 
			
		||||
					'utf8'
 | 
			
		||||
				)
 | 
			
		||||
				.then(function() {
 | 
			
		||||
					// this file may contain secrets, so keep it safe
 | 
			
		||||
					return chmodFile(opts.configFile, parseInt('0600', 8))
 | 
			
		||||
					return chmodFile(CONF.configFile, parseInt('0600', 8))
 | 
			
		||||
						.catch(function() {
 | 
			
		||||
							/*ignore for Windows */
 | 
			
		||||
						})
 | 
			
		||||
						.then(function() {
 | 
			
		||||
							return statFile(opts.configFile).then(function(
 | 
			
		||||
							return statFile(CONF.configFile).then(function(
 | 
			
		||||
								stat
 | 
			
		||||
							) {
 | 
			
		||||
								manage._lastStat.size = stat.size;
 | 
			
		||||
@ -443,8 +446,8 @@ Manage.create = function(opts) {
 | 
			
		||||
	return manage;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
Manage._getLatest = function(mng, opts) {
 | 
			
		||||
	return statFile(opts.configFile)
 | 
			
		||||
Manage._getLatest = function(mng, CONF) {
 | 
			
		||||
	return statFile(CONF.configFile)
 | 
			
		||||
		.catch(function(err) {
 | 
			
		||||
			if ('ENOENT' === err.code) {
 | 
			
		||||
				return {
 | 
			
		||||
@ -462,10 +465,34 @@ Manage._getLatest = function(mng, opts) {
 | 
			
		||||
			) {
 | 
			
		||||
				return mng._config;
 | 
			
		||||
			}
 | 
			
		||||
			return readFile(opts.configFile, 'utf8').then(function(data) {
 | 
			
		||||
			return readFile(CONF.configFile, 'utf8').then(function(data) {
 | 
			
		||||
				mng._lastStat = stat;
 | 
			
		||||
				mng._config = JSON.parse(data);
 | 
			
		||||
				return mng._config;
 | 
			
		||||
			});
 | 
			
		||||
		});
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var doctor = {};
 | 
			
		||||
// users muck up config files, so we try to handle it gracefully.
 | 
			
		||||
doctor.site = function(sconfs, subject) {
 | 
			
		||||
	var site = sconfs[subject];
 | 
			
		||||
	if (!site) {
 | 
			
		||||
		delete sconfs[subject];
 | 
			
		||||
		site = {};
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// TODO notify on any changes
 | 
			
		||||
	if ('string' !== typeof site.subject) {
 | 
			
		||||
		delete sconfs[subject];
 | 
			
		||||
		site.subject = 'greenlock-error.example.com';
 | 
			
		||||
	}
 | 
			
		||||
	if (!Array.isArray(site.altnames)) {
 | 
			
		||||
		site.altnames = [site.subject];
 | 
			
		||||
	}
 | 
			
		||||
	if (!site.renewAt) {
 | 
			
		||||
		site.renewAt = 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return site;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										2
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										2
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							@ -1,6 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
	"name": "greenlock-manager-fs",
 | 
			
		||||
	"version": "0.6.3",
 | 
			
		||||
	"version": "0.7.0",
 | 
			
		||||
	"lockfileVersion": 1,
 | 
			
		||||
	"requires": true,
 | 
			
		||||
	"dependencies": {
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
	"name": "greenlock-manager-fs",
 | 
			
		||||
	"version": "0.6.5",
 | 
			
		||||
	"version": "0.7.0",
 | 
			
		||||
	"description": "A simple file-based management strategy for Greenlock",
 | 
			
		||||
	"main": "manager.js",
 | 
			
		||||
	"scripts": {
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										52
									
								
								test.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								test.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,52 @@
 | 
			
		||||
'use strict';
 | 
			
		||||
 | 
			
		||||
var Manager = require('./');
 | 
			
		||||
var manager = Manager.create({
 | 
			
		||||
	configFile: 'greenlock-manager-test.delete-me.json'
 | 
			
		||||
});
 | 
			
		||||
var domains = ['example.com', 'www.example.com'];
 | 
			
		||||
 | 
			
		||||
async function run() {
 | 
			
		||||
	await manager.add({
 | 
			
		||||
		subject: domains[0],
 | 
			
		||||
		altnames: domains
 | 
			
		||||
	});
 | 
			
		||||
 | 
			
		||||
	await manager.find({}).then(function(results) {
 | 
			
		||||
		if (!results.length) {
 | 
			
		||||
			console.log(results);
 | 
			
		||||
			throw new Error('should have found all managed sites');
 | 
			
		||||
		}
 | 
			
		||||
	});
 | 
			
		||||
 | 
			
		||||
	await manager.find({ subject: 'www.example.com' }).then(function(results) {
 | 
			
		||||
		if (results.length) {
 | 
			
		||||
			console.log(results);
 | 
			
		||||
			throw new Error(
 | 
			
		||||
				"shouldn't find what doesn't exist, exactly, by subject"
 | 
			
		||||
			);
 | 
			
		||||
		}
 | 
			
		||||
	});
 | 
			
		||||
 | 
			
		||||
	await manager
 | 
			
		||||
		.find({ altnames: ['www.example.com'] })
 | 
			
		||||
		.then(function(results) {
 | 
			
		||||
			if (!results.length) {
 | 
			
		||||
				console.log(results);
 | 
			
		||||
				throw new Error('should have found sites matching altname');
 | 
			
		||||
			}
 | 
			
		||||
		});
 | 
			
		||||
 | 
			
		||||
	await manager.find({ altnames: ['*.example.com'] }).then(function(results) {
 | 
			
		||||
		if (results.length) {
 | 
			
		||||
			console.log(results);
 | 
			
		||||
			throw new Error(
 | 
			
		||||
				'should only find an exact (literal) wildcard match'
 | 
			
		||||
			);
 | 
			
		||||
		}
 | 
			
		||||
	});
 | 
			
		||||
 | 
			
		||||
  console.log("PASS");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
run();
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user