template improvements

This commit is contained in:
AJ ONeal 2019-11-05 02:50:27 -07:00
parent 4dc324f26f
commit 8f3872e82e
11 changed files with 286 additions and 211 deletions

View File

@ -464,7 +464,7 @@ This is what keeps the mapping of domains <-> certificates.
In many cases it will interact with the same database as the Key & Cert Store, and probably the code as well.
- set({ subject, altnames, renewAt })
- find({ altnames, renewBefore })
- find({ servernames, renewBefore })
```js
// should return a list of site configs:
[

View File

@ -117,7 +117,7 @@ A._newAccount = function(gnlck, mconf, db, acme, args, email, fullAccount) {
/^https?:\/\//i,
''
);
*/
*/
keyP = db.setKeypair(query, keypair);
}
@ -145,7 +145,7 @@ A._newAccount = function(gnlck, mconf, db, acme, args, email, fullAccount) {
/^https?:\/\//i,
''
)
*/
*/
},
reg
);

View File

@ -49,7 +49,7 @@ cli.main(async function(argList, flags) {
}
}
var GreenlockRc = require('./lib/greenlockrc.js');
var GreenlockRc = require('../greenlockrc.js');
//var rc = await GreenlockRc(pkgpath, manager, flags.manager);
await GreenlockRc(pkgpath, manager, flags.manager);
writeGreenlockJs(pkgdir, flags);

View File

@ -5,7 +5,7 @@ var Flags = module.exports;
var path = require('path');
//var pkgpath = path.join(__dirname, '..', 'package.json');
var pkgpath = path.join(process.cwd(), 'package.json');
var GreenlockRc = require('./greenlockrc.js');
var GreenlockRc = require('../../greenlockrc.js');
// These are ALL options
// The individual CLI files each select a subset of them
@ -168,21 +168,21 @@ Flags.flags = function(mconf, myOpts) {
};
};
Flags.init = function(myOpts) {
return GreenlockRc(pkgpath).then(async function(rc) {
rc._bin_mode = true;
var Greenlock = require('../../');
// this is a copy, so it's safe to modify
var greenlock = Greenlock.create(rc);
var mconf = await greenlock.manager.defaults();
var flagOptions = Flags.flags(mconf, myOpts);
return {
flagOptions,
rc,
greenlock,
mconf
};
});
Flags.init = async function(myOpts) {
var rc = await GreenlockRc(pkgpath);
rc._bin_mode = true;
var Greenlock = require('../../');
// this is a copy, so it's safe to modify
rc.packageRoot = path.dirname(pkgpath);
var greenlock = Greenlock.create(rc);
var mconf = await greenlock.manager.defaults();
var flagOptions = Flags.flags(mconf, myOpts);
return {
flagOptions,
rc,
greenlock,
mconf
};
};
Flags.mangleFlags = function(flags, mconf, sconf, extras) {

View File

@ -1,114 +0,0 @@
'use strict';
// TODO how to handle path differences when run from npx vs when required by greenlock?
var promisify = require('util').promisify;
var fs = require('fs');
var readFile = promisify(fs.readFile);
var writeFile = promisify(fs.writeFile);
var chmodFile = promisify(fs.chmod);
var path = require('path');
function saveFile(rcpath, data, enc) {
// because this may have a database url or some such
return writeFile(rcpath, data, enc).then(function() {
return chmodFile(rcpath, parseInt('0600', 8));
});
}
module.exports = async function(pkgpath, manager, rc) {
// TODO when run from package
// Run from the package root (assumed) or exit
var pkgdir = path.dirname(pkgpath);
var rcpath = path.join(pkgdir, '.greenlockrc');
var created = false;
try {
require(pkgpath);
} catch (e) {
console.error(
'npx greenlock must be run from the package root (where package.json is)'
);
process.exit(1);
}
if (manager) {
if ('.' === manager[0]) {
manager = path.resolve(pkgdir, manager);
}
try {
require(manager);
} catch (e) {
console.error('npx greenlock must be run from the package root');
process.exit(1);
}
}
var _data = await readFile(rcpath, 'utf8').catch(function(err) {
if ('ENOENT' !== err.code) {
throw err;
}
console.info('Creating ' + rcpath);
created = true;
var data = '{}';
return saveFile(rcpath, data, 'utf8').then(function() {
return data;
});
});
var changed;
var _rc;
try {
_rc = JSON.parse(_data);
} catch (e) {
console.error("couldn't parse " + rcpath, _data);
console.error('(perhaps you should just delete it and try again?)');
process.exit(1);
}
if (manager) {
if (!_rc.manager) {
_rc.manager = manager;
}
if (_rc.manager !== manager) {
console.info('Switching manager:');
var older = _rc.manager;
var newer = manager;
if ('/' === older[0]) {
older = path.relative(pkgdir, older);
}
if ('/' === newer[0]) {
newer = path.relative(pkgdir, newer);
}
console.info('\told: ' + older);
console.info('\tnew: ' + newer);
changed = true;
}
}
if (rc) {
changed = true;
Object.keys(rc).forEach(function(k) {
_rc[k] = rc[k];
});
}
if (['@greenlock/manager', 'greenlock-manager-fs'].includes(_rc.manager)) {
if (!_rc.configFile) {
changed = true;
_rc.configFile = path.join(pkgdir, 'greenlock.json');
}
}
if (!changed) {
return _rc;
}
var data = JSON.stringify(_rc, null, 2);
if (created) {
console.info('Wrote ' + rcpath);
}
return saveFile(rcpath, data, 'utf8').then(function() {
return _rc;
});
};

View File

@ -1,29 +1,13 @@
'use strict';
module.exports = require('greenlock').create(init());
function init() {
// .greenlockrc defines which manager to use
// (i.e. greenlock-manager-fs or greenlock-manager-cloud)
var options = getGreenlockRc() || {};
var pkg = require('./package.json');
module.exports = require('@root/greenlock').create({
// name & version for ACME client user agent
var pkg = require('./package.json');
options.packageAgent = pkg.name + '/' + pkg.version;
packageAgent: pkg.name + '/' + pkg.version,
// contact for security and critical bug notices
options.maintainerEmail = pkg.author;
maintainerEmail: pkg.author,
return options;
}
function getGreenlockRc() {
// The RC file is also used by the (optional) CLI and (optional) Web GUI.
// You are free to forego CLI and GUI support.
var fs = require('fs');
var path = require('path');
var rcPath = path.join(__dirname, '.greenlockrc');
var rc = fs.readFileSync(rcPath, 'utf8');
rc = JSON.parse(rc);
rc.packageRoot = __dirname;
}
// where to find .greenlockrc and set default paths
packageRoot: __dirname
});

View File

@ -2,21 +2,12 @@
require('greenlock-express')
.init(function() {
// .greenlockrc defines which manager to use
// (i.e. greenlock-manager-fs or greenlock-manager-cloud)
var options = getGreenlockRc() || {};
return {
greenlock: require('./greenlock.js'),
// name & version for ACME client user agent
var pkg = require('./package.json');
options.packageAgent = pkg.name + '/' + pkg.version;
// contact for security and critical bug notices
options.maintainerEmail = pkg.author;
// whether or not to run at cloudscale
options.cluster = false;
return options;
// whether or not to run at cloudscale
cluster: false
};
})
.ready(function(glx) {
var app = require('./app.js');
@ -25,14 +16,3 @@ require('greenlock-express')
// Get's SSL certificates magically!
glx.serveApp(app);
});
function getGreenlockRc() {
// The RC file is also used by the (optional) CLI and (optional) Web GUI.
// You are free to forego CLI and GUI support.
var fs = require('fs');
var path = require('path');
var rcPath = path.join(__dirname, '.greenlockrc');
var rc = fs.readFileSync(rcPath, 'utf8');
rc = JSON.parse(rc);
rc.packageRoot = __dirname;
}

View File

@ -127,7 +127,10 @@ C._rawOrder = function(gnlck, mconf, db, acme, chs, acc, email, args) {
var query = {
subject: args.subject,
certificate: args.certificate || {},
directoryUrl: args.directoryUrl || gnlck._defaults.directoryUrl
directoryUrl:
args.directoryUrl ||
mconf.directoryUrl ||
gnlck._defaults.directoryUrl
};
rawPending[id] = U._getOrCreateKeypair(db, args.subject, query, keyType)
.then(function(kresult) {
@ -208,7 +211,10 @@ C._check = function(gnlck, mconf, db, args) {
subject: args.subject,
// may contain certificate.id
certificate: args.certificate,
directoryUrl: args.directoryUrl || gnlck._defaults.directoryUrl
directoryUrl:
args.directoryUrl ||
mconf.directoryUrl ||
gnlck._defaults.directoryUrl
};
return db.check(query).then(function(pems) {
if (!pems) {

View File

@ -13,6 +13,7 @@ var P = require('./plugins.js');
var A = require('./accounts.js');
var C = require('./certificates.js');
var UserEvents = require('./user-events.js');
var GreenlockRc = require('./greenlockrc.js');
var caches = {};
@ -42,27 +43,21 @@ G.create = function(gconf) {
});
}
if (!gconf.packageRoot) {
gconf.packageRoot = process.cwd();
console.warn(
'`packageRoot` not defined, trying ' + gconf.packageRoot
);
}
if ('function' === typeof gconf.notify) {
gdefaults.notify = gconf.notify;
} else {
gdefaults.notify = _notify;
}
if (gconf.directoryUrl) {
gdefaults = gconf.directoryUrl;
if (gconf.staging) {
throw new Error(
'supply `directoryUrl` or `staging`, but not both'
);
}
} else if (gconf.staging) {
gdefaults.directoryUrl =
'https://acme-staging-v02.api.letsencrypt.org/directory';
} else {
gdefaults.directoryUrl =
'https://acme-v02.api.letsencrypt.org/directory';
}
console.info('ACME Directory URL:', gdefaults.directoryUrl);
var rc = GreenlockRc.resolve(gconf);
gconf = Object.assign(rc, gconf);
// Wraps each of the following with appropriate error checking
// greenlock.manager.defaults
@ -83,10 +78,31 @@ G.create = function(gconf) {
// greenlock.challenges.get
require('./challenges-underlay.js').wrap(greenlock);
if (gconf.directoryUrl) {
gdefaults.directoryUrl = gconf.directoryUrl;
if (gconf.staging) {
throw new Error(
'supply `directoryUrl` or `staging`, but not both'
);
}
} else if (
gconf.staging ||
process.argv.includes('--staging') ||
/DEV|STAG/i.test(process.env.ENV)
) {
greenlock.staging = true;
gdefaults.directoryUrl =
'https://acme-staging-v02.api.letsencrypt.org/directory';
} else {
greenlock.live = true;
gdefaults.directoryUrl =
'https://acme-v02.api.letsencrypt.org/directory';
}
greenlock._defaults = gdefaults;
greenlock._defaults.debug = gconf.debug;
if (!gconf._bin_mode) {
if (!gconf._bin_mode && false !== gconf.renew) {
// renew every 90-ish minutes (random for staggering)
// the weak setTimeout (unref) means that when run as a CLI process this
// will still finish as expected, and not wait on the timeout
@ -371,7 +387,7 @@ G.create = function(gconf) {
});
};
greenlock._acme = function(args) {
greenlock._acme = function(mconf, args) {
var packageAgent = gconf.packageAgent || '';
// because Greenlock_Express/v3.x Greenlock/v3 is redundant
if (!/greenlock/i.test(packageAgent)) {
@ -383,7 +399,15 @@ G.create = function(gconf) {
notify: greenlock._notify,
debug: greenlock._defaults.debug || args.debug
});
var dirUrl = args.directoryUrl || greenlock._defaults.directoryUrl;
var dirUrl = args.directoryUrl || mconf.directoryUrl;
var showDir = false;
if (!dirUrl) {
showDir = true;
dirUrl = greenlock._defaults.directoryUrl;
}
if (showDir || /staging/.test(dirUrl)) {
console.info('ACME Directory URL:', gdefaults.directoryUrl);
}
var dir = caches[dirUrl];
@ -409,17 +433,17 @@ G.create = function(gconf) {
});
};
greenlock.order = function(args) {
greenlock.order = function(siteConf) {
return greenlock._init().then(function() {
return greenlock.manager._defaults().then(function(mconf) {
return greenlock._order(mconf, args);
return greenlock._order(mconf, siteConf);
});
});
};
greenlock._order = function(mconf, args) {
greenlock._order = function(mconf, siteConf) {
// packageAgent, maintainerEmail
return greenlock._acme(args).then(function(acme) {
var storeConf = args.store || mconf.store;
return greenlock._acme(mconf, siteConf).then(function(acme) {
var storeConf = siteConf.store || mconf.store;
storeConf = JSON.parse(JSON.stringify(storeConf));
storeConf.packageRoot = gconf.packageRoot;
if (storeConf.basePath) {
@ -435,9 +459,10 @@ G.create = function(gconf) {
mconf,
store.accounts,
acme,
args
siteConf
).then(function(account) {
var challengeConfs = args.challenges || mconf.challenges;
var challengeConfs =
siteConf.challenges || mconf.challenges;
return Promise.all(
Object.keys(challengeConfs).map(function(typ01) {
return P._loadChallenge(challengeConfs, typ01);
@ -454,7 +479,7 @@ G.create = function(gconf) {
acme,
challenges,
account,
args
siteConf
).then(function(pems) {
if (!pems) {
throw new Error('no order result');

191
greenlockrc.js Normal file
View File

@ -0,0 +1,191 @@
'use strict';
// TODO how to handle path differences when run from npx vs when required by greenlock?
var fs = require('fs');
var path = require('path');
function saveFile(rcpath, data, enc) {
// because this may have a database url or some such
fs.writeFileSync(rcpath, data, enc);
return fs.chmodSync(rcpath, parseInt('0600', 8));
}
var GRC = (module.exports = function(pkgpath, manager, rc) {
// TODO when run from package
// Run from the package root (assumed) or exit
var pkgdir = path.dirname(pkgpath);
try {
require(pkgpath);
} catch (e) {
console.error(
'npx greenlock must be run from the package root (where package.json is)'
);
process.exit(1);
}
try {
return module.exports._defaults(pkgdir, manager, rc);
} catch (e) {
if ('package.json' === e.context) {
console.error(e.desc);
process.exit(1);
}
console.error(e.message);
process.exit(1);
}
});
// Figure out what to do between what's hard-coded,
// what's in the config file, and what's left unset
module.exports.resolve = function(gconf) {
var rc = GRC.read(gconf.packageRoot);
if (gconf.configFile) {
rc = { configFile: gconf.configFile };
}
var manager;
var updates;
if (rc.manager) {
if (gconf.manager && rc.manager !== gconf.manager) {
console.warn(
'warn: ignoring hard-coded ' +
gconf.manager +
' in favor of ' +
rc.manager
);
}
gconf.manager = rc.manager;
} else if (gconf.manager) {
manager = gconf.manager;
}
if (rc.configFile) {
if (gconf.configFile && rc.configFile !== gconf.configFile) {
console.warn(
'warn: ignoring hard-coded ' +
gconf.configFile +
' in favor of ' +
rc.configFile
);
}
gconf.configFile = rc.configFile;
} else if (gconf.manager) {
updates = { configFile: gconf.configFile };
}
return GRC._defaults(gconf.packageRoot, manager, rc);
};
module.exports._defaults = function(pkgdir, manager, rc) {
var rcpath = path.join(pkgdir, '.greenlockrc');
var _rc;
var created = false;
if (manager) {
if ('.' === manager[0]) {
manager = path.resolve(pkgdir, manager);
}
try {
require(manager);
} catch (e) {
console.error('could not load ' + manager + ' from ' + pkgdir);
throw e;
}
}
var stuff = module.exports._read(pkgdir);
_rc = stuff.rc;
created = stuff.created;
var changed;
if (manager) {
if (!_rc.manager) {
_rc.manager = manager;
}
if (_rc.manager !== manager) {
console.info('Switching manager:');
var older = _rc.manager;
var newer = manager;
if ('/' === older[0]) {
older = path.relative(pkgdir, older);
}
if ('/' === newer[0]) {
newer = path.relative(pkgdir, newer);
}
console.info('\told: ' + older);
console.info('\tnew: ' + newer);
changed = true;
}
}
if (rc) {
changed = true;
Object.keys(rc).forEach(function(k) {
_rc[k] = rc[k];
});
}
if (['@greenlock/manager', 'greenlock-manager-fs'].includes(_rc.manager)) {
if (!_rc.configFile) {
changed = true;
_rc.configFile = path.join(pkgdir, 'greenlock.json');
}
}
if (!changed) {
return _rc;
}
var data = JSON.stringify(_rc, null, 2);
if (created) {
console.info('Wrote ' + rcpath);
}
saveFile(rcpath, data, 'utf8');
return _rc;
};
module.exports.read = function(pkgdir) {
return module.exports._read(pkgdir).rc;
};
module.exports._read = function(pkgdir) {
var created;
var rcpath = path.join(pkgdir, '.greenlockrc');
var _data;
try {
_data = fs.readFileSync(rcpath, 'utf8');
} catch (err) {
if ('ENOENT' !== err.code) {
throw err;
}
try {
require(path.join(pkgdir, 'package.json'));
} catch (e) {
e.context = 'package.json';
e.desc =
'run `greenlock` from the same directory as `package.json`, or specify `packageRoot` of `.greenlockrc`';
throw e;
}
console.info('Creating ' + rcpath);
created = true;
_data = '{}';
saveFile(rcpath, _data, 'utf8');
}
var rc;
try {
rc = JSON.parse(_data);
} catch (e) {
console.error("couldn't parse " + rcpath, _data);
console.error('(perhaps you should just delete it and try again?)');
process.exit(1);
}
return {
created: created,
rc: rc
};
};

View File

@ -94,7 +94,10 @@ module.exports.wrap = function(greenlock, gconf) {
return mega.defaults(conf);
});
};
greenlock.manager._defaults = mega.defaults;
greenlock.manager._defaults = function(opts) {
return mega.defaults(opts);
};
greenlock.manager.add = function(args) {
if (!args || !Array.isArray(args.altnames) || !args.altnames.length) {