CLI: add, update, config, defaults, remove
This commit is contained in:
parent
2dbd61158f
commit
5b38fe7fcd
29
bin/add.js
29
bin/add.js
|
@ -1,12 +1,12 @@
|
|||
'use strict';
|
||||
|
||||
var args = process.argv.slice(3);
|
||||
var cli = require('./cli.js');
|
||||
var cli = require('./lib/cli.js');
|
||||
//var path = require('path');
|
||||
//var pkgpath = path.join(__dirname, '..', 'package.json');
|
||||
//var pkgpath = path.join(process.cwd(), 'package.json');
|
||||
|
||||
var Flags = require('./flags.js');
|
||||
var Flags = require('./lib/flags.js');
|
||||
|
||||
Flags.init().then(function({ flagOptions, rc, greenlock, mconf }) {
|
||||
var myFlags = {};
|
||||
|
@ -14,7 +14,15 @@ Flags.init().then(function({ flagOptions, rc, greenlock, mconf }) {
|
|||
'subject',
|
||||
'altnames',
|
||||
'renew-offset',
|
||||
'subscriber-email',
|
||||
'customer-email',
|
||||
'server-key-type',
|
||||
'challenge-http-01',
|
||||
'challenge-http-01-xxxx',
|
||||
'challenge-dns-01',
|
||||
'challenge-dns-01-xxxx',
|
||||
'challenge-tls-alpn-01',
|
||||
'challenge-tls-alpn-01-xxxx',
|
||||
'challenge',
|
||||
'challenge-xxxx',
|
||||
'challenge-json',
|
||||
|
@ -25,27 +33,27 @@ Flags.init().then(function({ flagOptions, rc, greenlock, mconf }) {
|
|||
|
||||
cli.parse(myFlags);
|
||||
cli.main(function(argList, flags) {
|
||||
main(argList, flags, rc, greenlock, mconf);
|
||||
Flags.mangleFlags(flags, mconf);
|
||||
main(argList, flags, rc, greenlock);
|
||||
}, args);
|
||||
});
|
||||
|
||||
async function main(_, flags, rc, greenlock, mconf) {
|
||||
if (!flags.subject) {
|
||||
async function main(_, flags, rc, greenlock) {
|
||||
if (!flags.subject || !flags.altnames) {
|
||||
console.error(
|
||||
'--subject must be provided as the id of the site/certificate'
|
||||
'--subject and --altnames must be provided and should be valid domains'
|
||||
);
|
||||
process.exit(1);
|
||||
return;
|
||||
}
|
||||
|
||||
Flags.mangleFlags(flags, mconf);
|
||||
|
||||
greenlock
|
||||
.add(flags)
|
||||
.catch(function(err) {
|
||||
console.error();
|
||||
console.error('error:', err.message);
|
||||
console.error();
|
||||
process.exit(1);
|
||||
})
|
||||
.then(function() {
|
||||
return greenlock
|
||||
|
@ -65,10 +73,8 @@ async function main(_, flags, rc, greenlock, mconf) {
|
|||
process.exit(1);
|
||||
return;
|
||||
}
|
||||
console.info();
|
||||
console.info('Created config!');
|
||||
console.info();
|
||||
|
||||
console.info();
|
||||
Object.keys(site).forEach(function(k) {
|
||||
if ('defaults' === k) {
|
||||
console.info(k + ':');
|
||||
|
@ -80,7 +86,6 @@ async function main(_, flags, rc, greenlock, mconf) {
|
|||
console.info(k + ': ' + JSON.stringify(site[k]));
|
||||
}
|
||||
});
|
||||
console.info();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
'use strict';
|
||||
|
||||
var args = process.argv.slice(3);
|
||||
var cli = require('./cli.js');
|
||||
var cli = require('./lib/cli.js');
|
||||
//var path = require('path');
|
||||
//var pkgpath = path.join(__dirname, '..', 'package.json');
|
||||
//var pkgpath = path.join(process.cwd(), 'package.json');
|
||||
|
||||
var Flags = require('./flags.js');
|
||||
var Flags = require('./lib/flags.js');
|
||||
|
||||
Flags.init().then(function({ flagOptions, rc, greenlock, mconf }) {
|
||||
var myFlags = {};
|
||||
|
@ -19,11 +19,11 @@ Flags.init().then(function({ flagOptions, rc, greenlock, mconf }) {
|
|||
cli.parse(myFlags);
|
||||
cli.main(function(argList, flags) {
|
||||
Flags.mangleFlags(flags, mconf);
|
||||
main(argList, flags, rc, greenlock, mconf);
|
||||
main(argList, flags, rc, greenlock);
|
||||
}, args);
|
||||
});
|
||||
|
||||
async function main(_, flags, rc, greenlock /*, mconf */) {
|
||||
async function main(_, flags, rc, greenlock) {
|
||||
var servernames = [flags.subject]
|
||||
.concat([flags.servername])
|
||||
//.concat(flags.servernames)
|
||||
|
@ -49,22 +49,23 @@ async function main(_, flags, rc, greenlock /*, mconf */) {
|
|||
.catch(function(err) {
|
||||
console.error();
|
||||
console.error('error:', err.message);
|
||||
console.log(err.stack);
|
||||
//console.log(err.stack);
|
||||
console.error();
|
||||
process.exit(1);
|
||||
})
|
||||
.then(function(site) {
|
||||
if (!site) {
|
||||
console.info();
|
||||
console.info('No config found for ');
|
||||
console.info('No config found for', flags.servername);
|
||||
console.info();
|
||||
process.exit(1);
|
||||
return;
|
||||
}
|
||||
|
||||
console.info();
|
||||
console.info(
|
||||
'Config for ' + JSON.stringify(flags.servername) + ':'
|
||||
);
|
||||
console.info(JSON.stringify(site, null, 2));
|
||||
console.info();
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,17 +1,62 @@
|
|||
store: [
|
||||
false,
|
||||
'the npm name or path of the storage module or callbacks file',
|
||||
'string',
|
||||
'greenlock-store-fs'
|
||||
],
|
||||
'store-xxxx': [
|
||||
false,
|
||||
'an option for the chosen storage module, such as --store-apikey or --store-bucket',
|
||||
'bag'
|
||||
],
|
||||
'store-json': [
|
||||
false,
|
||||
'a JSON string containing all option for the chosen store module (instead of --store-xxxx)',
|
||||
'json',
|
||||
'{}'
|
||||
],
|
||||
'use strict';
|
||||
|
||||
var args = process.argv.slice(3);
|
||||
var cli = require('./lib/cli.js');
|
||||
//var path = require('path');
|
||||
//var pkgpath = path.join(__dirname, '..', 'package.json');
|
||||
//var pkgpath = path.join(process.cwd(), 'package.json');
|
||||
|
||||
var Flags = require('./lib/flags.js');
|
||||
|
||||
Flags.init({ forceSave: true }).then(function({
|
||||
flagOptions,
|
||||
rc,
|
||||
greenlock,
|
||||
mconf
|
||||
}) {
|
||||
var myFlags = {};
|
||||
[
|
||||
'account-key-type',
|
||||
'server-key-type',
|
||||
'subscriber-email',
|
||||
'renew-offset',
|
||||
'store',
|
||||
'store-xxxx',
|
||||
'challenge-http-01-xxxx',
|
||||
'challenge-dns-01',
|
||||
'challenge-dns-01-xxxx',
|
||||
'challenge-tls-alpn-01',
|
||||
'challenge-tls-alpn-01-xxxx',
|
||||
'challenge',
|
||||
'challenge-xxxx',
|
||||
'challenge-http-01',
|
||||
].forEach(function(k) {
|
||||
myFlags[k] = flagOptions[k];
|
||||
});
|
||||
|
||||
cli.parse(myFlags);
|
||||
cli.main(function(argList, flags) {
|
||||
Flags.mangleFlags(flags, mconf, null, { forceSave: true });
|
||||
main(argList, flags, rc, greenlock);
|
||||
}, args);
|
||||
});
|
||||
|
||||
async function main(_, flags, rc, greenlock) {
|
||||
greenlock.manager
|
||||
.defaults(flags)
|
||||
.catch(function(err) {
|
||||
console.error();
|
||||
console.error('error:', err.message);
|
||||
//console.log(err.stack);
|
||||
console.error();
|
||||
process.exit(1);
|
||||
})
|
||||
.then(function() {
|
||||
return greenlock.manager.defaults();
|
||||
})
|
||||
.then(function(dconf) {
|
||||
console.info();
|
||||
console.info('Global config');
|
||||
console.info(JSON.stringify(dconf, null, 2));
|
||||
});
|
||||
}
|
||||
|
|
138
bin/flags.js
138
bin/flags.js
|
@ -1,138 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
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');
|
||||
|
||||
Flags.init = function() {
|
||||
return GreenlockRc(pkgpath).then(async function(rc) {
|
||||
var Greenlock = require('../');
|
||||
// this is a copy, so it's safe to modify
|
||||
rc._bin_mode = true;
|
||||
var greenlock = Greenlock.create(rc);
|
||||
var mconf = await greenlock.manager.defaults();
|
||||
|
||||
var flagOptions = {
|
||||
subject: [
|
||||
false,
|
||||
'the "subject" (primary domain) of the certificate',
|
||||
'string'
|
||||
],
|
||||
altnames: [
|
||||
false,
|
||||
'the "subject alternative names" (additional domains) on the certificate, the first of which MUST be the subject',
|
||||
'string'
|
||||
],
|
||||
servername: [
|
||||
false,
|
||||
'a name that matches a subject or altname',
|
||||
'string'
|
||||
],
|
||||
servernames: [
|
||||
false,
|
||||
'a list of names that matches a subject or altname',
|
||||
'string'
|
||||
],
|
||||
'renew-offset': [
|
||||
false,
|
||||
"time to wait until renewing the cert such as '45d' (45 days after being issued) or '-3w' (3 weeks before expiration date)",
|
||||
'string',
|
||||
mconf.renewOffset
|
||||
],
|
||||
'server-key-type': [
|
||||
false,
|
||||
"either 'RSA-2048' or 'P-256' (ECDSA) - although other values are technically supported, they don't make sense and won't work with many services (More bits != More security)",
|
||||
'string',
|
||||
mconf.serverKeyType
|
||||
],
|
||||
challenge: [
|
||||
false,
|
||||
'the name name of file path of the HTTP-01, DNS-01, or TLS-ALPN-01 challenge module to use',
|
||||
'string',
|
||||
Object.keys(mconf.challenges)
|
||||
.map(function(typ) {
|
||||
return mconf.challenges[typ].module;
|
||||
})
|
||||
.join(',')
|
||||
],
|
||||
'challenge-xxxx': [
|
||||
false,
|
||||
'an option for the chosen challenge module, such as --challenge-apikey or --challenge-bucket',
|
||||
'bag'
|
||||
],
|
||||
'challenge-json': [
|
||||
false,
|
||||
'a JSON string containing all option for the chosen challenge module (instead of --challenge-xxxx)',
|
||||
'json',
|
||||
'{}'
|
||||
],
|
||||
'force-save': [
|
||||
false,
|
||||
"save all options for this site, even if it's the same as the defaults",
|
||||
'boolean',
|
||||
false
|
||||
]
|
||||
};
|
||||
|
||||
return {
|
||||
flagOptions,
|
||||
rc,
|
||||
greenlock,
|
||||
mconf
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
Flags.mangleFlags = function(flags, mconf) {
|
||||
if ('altnames' in flags) {
|
||||
flags.altnames = (flags.altnames || '').split(/[,\s]+/).filter(Boolean);
|
||||
}
|
||||
if ('servernames' in flags) {
|
||||
flags.servernames = (flags.servernames || '')
|
||||
.split(/[,\s]+/)
|
||||
.filter(Boolean);
|
||||
}
|
||||
|
||||
Object.keys(flags).forEach(function(k) {
|
||||
if (flags[k] === mconf[k] && !flags.forceSave) {
|
||||
delete flags[k];
|
||||
}
|
||||
});
|
||||
|
||||
var typ;
|
||||
var challenge;
|
||||
if (flags.challenge) {
|
||||
if (/http-01/.test(flags.challenge)) {
|
||||
typ = 'http-01';
|
||||
} else if (/dns-01/.test(flags.challenge)) {
|
||||
typ = 'dns-01';
|
||||
} else if (/tls-alpn-01/.test(flags.challenge)) {
|
||||
typ = 'tls-alpn-01';
|
||||
}
|
||||
|
||||
challenge = flags.challengeOpts;
|
||||
challenge.module = flags.challenge;
|
||||
flags.challenges = {};
|
||||
flags.challenges[typ] = challenge;
|
||||
delete flags.challengeOpts;
|
||||
delete flags.challenge;
|
||||
|
||||
var chall = mconf.challenges[typ];
|
||||
if (challenge.module === chall.module) {
|
||||
var keys = Object.keys(challenge);
|
||||
var same =
|
||||
!keys.length ||
|
||||
keys.every(function(k) {
|
||||
return chall[k] === challenge[k];
|
||||
});
|
||||
if (same && !flags.forceSave) {
|
||||
delete flags.challenges;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delete flags.forceSave;
|
||||
};
|
|
@ -5,14 +5,14 @@ var args = process.argv.slice(2);
|
|||
var arg0 = args[0];
|
||||
//console.log(args);
|
||||
|
||||
var found = ['certonly', 'add', 'update', 'config', 'defaults', 'remove'].some(function(
|
||||
k
|
||||
) {
|
||||
var found = ['certonly', 'add', 'update', 'config', 'defaults', 'remove'].some(
|
||||
function(k) {
|
||||
if (k === arg0) {
|
||||
require('./' + k);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
if (!found) {
|
||||
console.error(arg0 + ': command not yet implemented');
|
||||
|
|
|
@ -12,6 +12,13 @@ CLI.parse = function(conf) {
|
|||
|
||||
Object.keys(conf).forEach(function(k) {
|
||||
var v = conf[k];
|
||||
if (!v) {
|
||||
console.error(
|
||||
'Developer Error: missing config value for',
|
||||
JSON.stringify(k)
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
var aliases = v[5];
|
||||
var bag;
|
||||
var bagName;
|
||||
|
@ -85,7 +92,6 @@ CLI.main = function(cb, args) {
|
|||
if (bag !== flag.slice(0, bag.length)) {
|
||||
return false;
|
||||
}
|
||||
console.log(bagName, toCamel(flag.slice(bag.length)));
|
||||
opts[bagName][toCamel(flag.slice(bag.length))] = args.shift();
|
||||
return true;
|
||||
}
|
|
@ -0,0 +1,356 @@
|
|||
'use strict';
|
||||
|
||||
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');
|
||||
|
||||
Flags.init = function(myOpts) {
|
||||
if (!myOpts) {
|
||||
myOpts = {};
|
||||
}
|
||||
return GreenlockRc(pkgpath).then(async function(rc) {
|
||||
var Greenlock = require('../../');
|
||||
// this is a copy, so it's safe to modify
|
||||
rc._bin_mode = true;
|
||||
var greenlock = Greenlock.create(rc);
|
||||
var mconf = await greenlock.manager.defaults();
|
||||
|
||||
var flagOptions = {
|
||||
subject: [
|
||||
false,
|
||||
'the "subject" (primary domain) of the certificate',
|
||||
'string'
|
||||
],
|
||||
altnames: [
|
||||
false,
|
||||
'the "subject alternative names" (additional domains) on the certificate, the first of which MUST be the subject',
|
||||
'string'
|
||||
],
|
||||
servername: [
|
||||
false,
|
||||
'a name that matches a subject or altname',
|
||||
'string'
|
||||
],
|
||||
servernames: [
|
||||
false,
|
||||
'a list of names that matches a subject or altname',
|
||||
'string'
|
||||
],
|
||||
'renew-offset': [
|
||||
false,
|
||||
"time to wait until renewing the cert such as '45d' (45 days after being issued) or '-3w' (3 weeks before expiration date)",
|
||||
'string',
|
||||
mconf.renewOffset
|
||||
],
|
||||
'customer-email': [
|
||||
false,
|
||||
"the email address of the owner of the domain or site (not necessarily the Let's Encrypt or ACME subscriber)",
|
||||
'string'
|
||||
],
|
||||
'subscriber-email': [
|
||||
false,
|
||||
"the email address of the Let's Encrypt or ACME Account subscriber (not necessarily the domain owner)",
|
||||
'string'
|
||||
],
|
||||
'account-key-type': [
|
||||
false,
|
||||
"either 'P-256' (ECDSA) or 'RSA-2048' - although other values are technically supported, they don't make sense and won't work with many services (More bits != More security)",
|
||||
'string',
|
||||
mconf.accountKeyType
|
||||
],
|
||||
'server-key-type': [
|
||||
false,
|
||||
"either 'RSA-2048' or 'P-256' (ECDSA) - although other values are technically supported, they don't make sense and won't work with many services (More bits != More security)",
|
||||
'string',
|
||||
mconf.serverKeyType
|
||||
],
|
||||
store: [
|
||||
false,
|
||||
'the module name or file path of the store module to use',
|
||||
'string'
|
||||
//mconf.store.module
|
||||
],
|
||||
'store-xxxx': [
|
||||
false,
|
||||
'an option for the chosen store module, such as --store-apikey or --store-bucket',
|
||||
'bag'
|
||||
],
|
||||
challenge: [
|
||||
false,
|
||||
'the module name or file path of the HTTP-01, DNS-01, or TLS-ALPN-01 challenge module to use',
|
||||
'string',
|
||||
''
|
||||
/*
|
||||
Object.keys(mconf.challenges)
|
||||
.map(function(typ) {
|
||||
return mconf.challenges[typ].module;
|
||||
})
|
||||
.join(',')
|
||||
*/
|
||||
],
|
||||
'challenge-xxxx': [
|
||||
false,
|
||||
'an option for the chosen challenge module, such as --challenge-apikey or --challenge-bucket',
|
||||
'bag'
|
||||
],
|
||||
'challenge-json': [
|
||||
false,
|
||||
'a JSON string containing all option for the chosen challenge module (instead of --challenge-xxxx)',
|
||||
'json',
|
||||
'{}'
|
||||
],
|
||||
'challenge-http-01': [
|
||||
false,
|
||||
'the module name or file path of the HTTP-01 to add',
|
||||
'string'
|
||||
//(mconf.challenges['http-01'] || {}).module
|
||||
],
|
||||
'challenge-http-01-xxxx': [
|
||||
false,
|
||||
'an option for the chosen challenge module, such as --challenge-http-01-apikey or --challenge-http-01-bucket',
|
||||
'bag'
|
||||
],
|
||||
'challenge-dns-01': [
|
||||
false,
|
||||
'the module name or file path of the DNS-01 to add',
|
||||
'string'
|
||||
//(mconf.challenges['dns-01'] || {}).module
|
||||
],
|
||||
'challenge-dns-01-xxxx': [
|
||||
false,
|
||||
'an option for the chosen challenge module, such as --challenge-dns-01-apikey or --challenge-dns-01-bucket',
|
||||
'bag'
|
||||
],
|
||||
'challenge-tls-alpn-01': [
|
||||
false,
|
||||
'the module name or file path of the DNS-01 to add',
|
||||
'string'
|
||||
//(mconf.challenges['tls-alpn-01'] || {}).module
|
||||
],
|
||||
'challenge-tls-alpn-01-xxxx': [
|
||||
false,
|
||||
'an option for the chosen challenge module, such as --challenge-tls-alpn-01-apikey or --challenge-tls-alpn-01-bucket',
|
||||
'bag'
|
||||
],
|
||||
'force-save': [
|
||||
false,
|
||||
"save all options for this site, even if it's the same as the defaults",
|
||||
'boolean',
|
||||
myOpts.forceSave || false
|
||||
]
|
||||
};
|
||||
|
||||
return {
|
||||
flagOptions,
|
||||
rc,
|
||||
greenlock,
|
||||
mconf
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
Flags.mangleFlags = function(flags, mconf, sconf, extras) {
|
||||
if (extras) {
|
||||
if (extras.forceSave) {
|
||||
flags.forceSave = true;
|
||||
}
|
||||
}
|
||||
//console.log('debug a:', flags);
|
||||
|
||||
if ('altnames' in flags) {
|
||||
flags.altnames = (flags.altnames || '').split(/[,\s]+/).filter(Boolean);
|
||||
}
|
||||
if ('servernames' in flags) {
|
||||
flags.servernames = (flags.servernames || '')
|
||||
.split(/[,\s]+/)
|
||||
.filter(Boolean);
|
||||
}
|
||||
|
||||
var store;
|
||||
if (flags.store) {
|
||||
store = flags.storeOpts;
|
||||
store.module = flags.store;
|
||||
flags.store = store;
|
||||
} else {
|
||||
delete flags.store;
|
||||
}
|
||||
delete flags.storeOpts;
|
||||
|
||||
// If this is additive, make an object to hold all values
|
||||
var isAdditive = [
|
||||
['http-01', 'Http01'],
|
||||
['dns-01', 'Dns01'],
|
||||
['tls-alpn-01', 'TlsAlpn01']
|
||||
].some(function(types) {
|
||||
var typCamel = types[1];
|
||||
var modname = 'challenge' + typCamel;
|
||||
if (flags[modname]) {
|
||||
if (!flags.challenges) {
|
||||
flags.challenges = {};
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
if (isAdditive && sconf) {
|
||||
// copy over the old
|
||||
var schallenges = sconf.challenges || {};
|
||||
Object.keys(schallenges).forEach(function(k) {
|
||||
if (!flags.challenges[k]) {
|
||||
flags.challenges[k] = schallenges[k];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var typ;
|
||||
var challenge;
|
||||
if (flags.challenge) {
|
||||
// this varient of the flag is exclusive
|
||||
flags.challenges = {};
|
||||
isAdditive = false;
|
||||
|
||||
if (/http-01/.test(flags.challenge)) {
|
||||
typ = 'http-01';
|
||||
} else if (/dns-01/.test(flags.challenge)) {
|
||||
typ = 'dns-01';
|
||||
} else if (/tls-alpn-01/.test(flags.challenge)) {
|
||||
typ = 'tls-alpn-01';
|
||||
}
|
||||
|
||||
var modname = 'challenge';
|
||||
var optsname = 'challengeOpts';
|
||||
challenge = flags[optsname];
|
||||
// JSON may already have module name
|
||||
if (challenge.module) {
|
||||
if (flags[modname] && challenge.module !== flags[modname]) {
|
||||
console.error(
|
||||
'module names do not match:',
|
||||
JSON.stringify(challenge.module),
|
||||
JSON.stringify(flags[modname])
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
} else {
|
||||
challenge.module = flags[modname];
|
||||
}
|
||||
flags.challenges[typ] = challenge;
|
||||
|
||||
var chall = mconf.challenges[typ];
|
||||
if (chall && challenge.module === chall.module) {
|
||||
var keys = Object.keys(challenge);
|
||||
var same =
|
||||
!keys.length ||
|
||||
keys.every(function(k) {
|
||||
return chall[k] === challenge[k];
|
||||
});
|
||||
if (same && !flags.forceSave) {
|
||||
delete flags.challenges;
|
||||
}
|
||||
}
|
||||
}
|
||||
delete flags.challenge;
|
||||
delete flags.challengeOpts;
|
||||
|
||||
// Add each of the values, including the existing
|
||||
[
|
||||
['http-01', 'Http01'],
|
||||
['dns-01', 'Dns01'],
|
||||
['tls-alpn-01', 'TlsAlpn01']
|
||||
].forEach(function(types) {
|
||||
var typ = types[0];
|
||||
var typCamel = types[1];
|
||||
var modname = 'challenge' + typCamel;
|
||||
var optsname = 'challenge' + typCamel + 'Opts';
|
||||
var chall = mconf.challenges[typ];
|
||||
var challenge = flags[optsname];
|
||||
|
||||
// this variant of the flag is additive
|
||||
if (isAdditive && chall && flags.forceSave) {
|
||||
if (flags.challenges && !flags.challenges[typ]) {
|
||||
flags.challenges[typ] = chall;
|
||||
}
|
||||
}
|
||||
|
||||
if (!flags[modname]) {
|
||||
delete flags[modname];
|
||||
delete flags[optsname];
|
||||
return;
|
||||
}
|
||||
|
||||
// JSON may already have module name
|
||||
if (challenge.module) {
|
||||
if (flags[modname] && challenge.module !== flags[modname]) {
|
||||
console.error(
|
||||
'module names do not match:',
|
||||
JSON.stringify(challenge.module),
|
||||
JSON.stringify(flags[modname])
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
} else {
|
||||
challenge.module = flags[modname];
|
||||
}
|
||||
if (flags[modname]) {
|
||||
if (!flags.challenges) {
|
||||
flags.challenges = {};
|
||||
}
|
||||
flags.challenges[typ] = challenge;
|
||||
}
|
||||
|
||||
// Check to see if this is already what's set in the defaults
|
||||
if (chall && challenge.module === chall.module) {
|
||||
var keys = Object.keys(challenge);
|
||||
// Check if all of the options are also the same
|
||||
var same =
|
||||
!keys.length ||
|
||||
keys.every(function(k) {
|
||||
return chall[k] === challenge[k];
|
||||
});
|
||||
if (same && !flags.forceSave) {
|
||||
// If it's already the global, don't make it the per-site
|
||||
delete flags[modname];
|
||||
delete flags[optsname];
|
||||
}
|
||||
}
|
||||
|
||||
delete flags[modname];
|
||||
delete flags[optsname];
|
||||
});
|
||||
|
||||
[
|
||||
['accountKeyType', [/256/, /384/, /EC/], 'EC-P256'],
|
||||
['serverKeyType', [/RSA/], 'RSA-2048']
|
||||
].forEach(function(k) {
|
||||
var key = k[0];
|
||||
var vals = k[1];
|
||||
var val = flags[key];
|
||||
if (val) {
|
||||
if (
|
||||
!vals.some(function(v) {
|
||||
return v.test(val);
|
||||
})
|
||||
) {
|
||||
flags[key] = k[2];
|
||||
console.warn(
|
||||
key,
|
||||
"does not allow the value '",
|
||||
val,
|
||||
"' using the default '",
|
||||
k[2],
|
||||
"' instead."
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Object.keys(flags).forEach(function(k) {
|
||||
if (flags[k] === mconf[k] && !flags.forceSave) {
|
||||
delete flags[k];
|
||||
}
|
||||
});
|
||||
|
||||
//console.log('debug z:', flags);
|
||||
delete flags.forceSave;
|
||||
};
|
|
@ -0,0 +1,55 @@
|
|||
'use strict';
|
||||
|
||||
var args = process.argv.slice(3);
|
||||
var cli = require('./lib/cli.js');
|
||||
//var path = require('path');
|
||||
//var pkgpath = path.join(__dirname, '..', 'package.json');
|
||||
//var pkgpath = path.join(process.cwd(), 'package.json');
|
||||
|
||||
var Flags = require('./lib/flags.js');
|
||||
|
||||
Flags.init().then(function({ flagOptions, rc, greenlock, mconf }) {
|
||||
var myFlags = {};
|
||||
['subject'].forEach(function(k) {
|
||||
myFlags[k] = flagOptions[k];
|
||||
});
|
||||
|
||||
cli.parse(myFlags);
|
||||
cli.main(function(argList, flags) {
|
||||
Flags.mangleFlags(flags, mconf);
|
||||
main(argList, flags, rc, greenlock);
|
||||
}, args);
|
||||
});
|
||||
|
||||
async function main(_, flags, rc, greenlock) {
|
||||
if (!flags.subject) {
|
||||
console.error('--subject must be provided as a valid domain');
|
||||
process.exit(1);
|
||||
return;
|
||||
}
|
||||
|
||||
greenlock
|
||||
.remove(flags)
|
||||
.catch(function(err) {
|
||||
console.error();
|
||||
console.error('error:', err.message);
|
||||
//console.log(err.stack);
|
||||
console.error();
|
||||
process.exit(1);
|
||||
})
|
||||
.then(function(site) {
|
||||
if (!site) {
|
||||
console.info();
|
||||
console.info('No config found for', flags.subject);
|
||||
console.info();
|
||||
process.exit(1);
|
||||
return;
|
||||
}
|
||||
console.info();
|
||||
console.info(
|
||||
'Deleted config for ' + JSON.stringify(flags.subject) + ':'
|
||||
);
|
||||
console.info(JSON.stringify(site, null, 2));
|
||||
console.info();
|
||||
});
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
'use strict';
|
||||
|
||||
var args = process.argv.slice(3);
|
||||
var cli = require('./cli.js');
|
||||
var Flags = require('./flags.js');
|
||||
var cli = require('./lib/cli.js');
|
||||
var Flags = require('./lib/flags.js');
|
||||
|
||||
Flags.init().then(function({ flagOptions, rc, greenlock, mconf }) {
|
||||
var myFlags = {};
|
||||
|
@ -10,7 +10,15 @@ Flags.init().then(function({ flagOptions, rc, greenlock, mconf }) {
|
|||
'subject',
|
||||
'altnames',
|
||||
'renew-offset',
|
||||
'subscriber-email',
|
||||
'customer-email',
|
||||
'server-key-type',
|
||||
'challenge-http-01',
|
||||
'challenge-http-01-xxxx',
|
||||
'challenge-dns-01',
|
||||
'challenge-dns-01-xxxx',
|
||||
'challenge-tls-alpn-01',
|
||||
'challenge-tls-alpn-01-xxxx',
|
||||
'challenge',
|
||||
'challenge-xxxx',
|
||||
'challenge-json',
|
||||
|
@ -20,41 +28,41 @@ Flags.init().then(function({ flagOptions, rc, greenlock, mconf }) {
|
|||
});
|
||||
|
||||
cli.parse(myFlags);
|
||||
cli.main(function(argList, flags) {
|
||||
main(argList, flags, rc, greenlock, mconf);
|
||||
cli.main(async function(argList, flags) {
|
||||
var sconf = await greenlock._config({ servername: flags.subject });
|
||||
Flags.mangleFlags(flags, mconf, sconf);
|
||||
main(argList, flags, rc, greenlock);
|
||||
}, args);
|
||||
});
|
||||
|
||||
async function main(_, flags, rc, greenlock, mconf) {
|
||||
if (!flags.subject || !flags.altnames) {
|
||||
console.error(
|
||||
'--subject and --altnames must be provided and should be valid domains'
|
||||
);
|
||||
async function main(_, flags, rc, greenlock) {
|
||||
if (!flags.subject) {
|
||||
console.error('--subject must be provided as a valid domain');
|
||||
process.exit(1);
|
||||
return;
|
||||
}
|
||||
|
||||
Flags.mangleFlags(flags, mconf);
|
||||
|
||||
greenlock.update(flags).catch(function(err) {
|
||||
greenlock
|
||||
.update(flags)
|
||||
.catch(function(err) {
|
||||
console.error();
|
||||
console.error('error:', err.message);
|
||||
console.error();
|
||||
}) .then(function() {
|
||||
process.exit(1);
|
||||
})
|
||||
.then(function() {
|
||||
return greenlock
|
||||
._config({ servername: flags.subject })
|
||||
.then(function(site) {
|
||||
if (!site) {
|
||||
console.info();
|
||||
console.info('No config found for ');
|
||||
console.info('No config found for', flags.subject);
|
||||
console.info();
|
||||
process.exit(1);
|
||||
return;
|
||||
}
|
||||
console.info();
|
||||
console.info("Updated config!");
|
||||
console.info();
|
||||
|
||||
console.info();
|
||||
Object.keys(site).forEach(function(k) {
|
||||
if ('defaults' === k) {
|
||||
console.info(k + ':');
|
||||
|
@ -66,7 +74,6 @@ async function main(_, flags, rc, greenlock, mconf) {
|
|||
console.info(k + ': ' + JSON.stringify(site[k]));
|
||||
}
|
||||
});
|
||||
console.info();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -77,6 +77,8 @@ G.create = function(gconf) {
|
|||
// The goal here is to reduce boilerplate, such as error checking
|
||||
// and duration parsing, that a manager must implement
|
||||
greenlock.sites.add = greenlock.add = greenlock.manager.add;
|
||||
greenlock.sites.update = greenlock.update = greenlock.manager.update;
|
||||
greenlock.sites.remove = greenlock.remove = greenlock.manager.remove;
|
||||
|
||||
// Exports challenges.get for Greenlock Express HTTP-01,
|
||||
// and whatever odd use case pops up, I suppose
|
||||
|
|
|
@ -87,7 +87,7 @@ module.exports.wrap = function(greenlock, manager, gconf) {
|
|||
});
|
||||
};
|
||||
|
||||
greenlock.add = greenlock.manager.add = function(args) {
|
||||
greenlock.manager.add = function(args) {
|
||||
if (!args || !Array.isArray(args.altnames) || !args.altnames.length) {
|
||||
throw new Error(
|
||||
'you must specify `altnames` when adding a new site'
|
||||
|
@ -158,9 +158,21 @@ module.exports.wrap = function(greenlock, manager, gconf) {
|
|||
};
|
||||
|
||||
greenlock.manager.remove = function(args) {
|
||||
return Promise.resolve().then(function() {
|
||||
args.subject = checkSubject(args);
|
||||
if (args.servername) {
|
||||
throw new Error(
|
||||
'remove() should be called with `subject` only, if you wish to remove altnames use `update()`'
|
||||
);
|
||||
}
|
||||
if (args.altnames) {
|
||||
throw new Error(
|
||||
'remove() should be called with `subject` only, not `altnames`'
|
||||
);
|
||||
}
|
||||
// TODO check no altnames
|
||||
return manager.remove(args);
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@root/greenlock",
|
||||
"version": "3.1.0-wip",
|
||||
"version": "3.1.0",
|
||||
"description": "The easiest Let's Encrypt client for Node.js and Browsers",
|
||||
"homepage": "https://rootprojects.org/greenlock/",
|
||||
"main": "greenlock.js",
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
# TODO notify if wildcard is selected and no dns challenge is present
|
||||
node bin/greenlock.js add --subject example.com --altnames 'example.com,*.example.com'
|
||||
node bin/greenlock.js update --subject example.com
|
||||
node bin/greenlock.js config --subject example.com
|
||||
node bin/greenlock.js config --subject *.example.com
|
||||
node bin/greenlock.js defaults
|
||||
node bin/greenlock.js defaults --account-key-type
|
||||
node bin/greenlock.js defaults
|
||||
# using --challenge-xx-xx-xxx is additive
|
||||
node bin/greenlock.js defaults --challenge-dns-01 foo-http-01-bar --challenge-dns-01-token BIG_TOKEN
|
||||
# using --challenge is exclusive (will delete things not mentioned)
|
||||
node bin/greenlock.js defaults --challenge acme-http-01-standalone
|
||||
node bin/greenlock.js remove --subject example.com
|
||||
# should delete all and add just this one anew
|
||||
node bin/greenlock.js update --subject example.com --challenge bar-http-01-baz
|
||||
# should add, leaving the existing
|
||||
node bin/greenlock.js update --subject example.com --challenge-dns-01 baz-dns-01-qux --challenge-dns-01-token BIG_TOKEN
|
||||
# should delete all and add just this one anew
|
||||
node bin/greenlock.js update --subject example.com --challenge bar-http-01-baz
|
||||
|
||||
# TODO test for failure
|
||||
# node bin/greenlock.js add --subject example.com
|
||||
# node bin/greenlock.js add --subject example --altnames example
|
||||
# node bin/greenlock.js add --subject example.com --altnames '*.example.com'
|
||||
# node bin/greenlock.js add --subject example.com --altnames '*.example.com,example.com'
|
||||
# node bin/greenlock.js update --altnames example.com
|
||||
# node bin/greenlock.js config foo.example.com
|
Loading…
Reference in New Issue