roster-server 2.2.10 → 2.2.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/package.json +12 -3
  2. package/tasks/lessons.md +1 -0
  3. package/vendor/greenlock/.prettierrc +8 -0
  4. package/vendor/greenlock/LICENSE +312 -0
  5. package/vendor/greenlock/MIGRATION_GUIDE.md +403 -0
  6. package/vendor/greenlock/README.md +667 -0
  7. package/vendor/greenlock/accounts.js +218 -0
  8. package/vendor/greenlock/bin/add.js +72 -0
  9. package/vendor/greenlock/bin/certonly.js +368 -0
  10. package/vendor/greenlock/bin/config.js +77 -0
  11. package/vendor/greenlock/bin/defaults.js +58 -0
  12. package/vendor/greenlock/bin/greenlock.js +26 -0
  13. package/vendor/greenlock/bin/init.js +159 -0
  14. package/vendor/greenlock/bin/lib/cli.js +230 -0
  15. package/vendor/greenlock/bin/lib/flags.js +385 -0
  16. package/vendor/greenlock/bin/remove.js +46 -0
  17. package/vendor/greenlock/bin/tmpl/app.tmpl.js +9 -0
  18. package/vendor/greenlock/bin/tmpl/cluster.tmpl.js +30 -0
  19. package/vendor/greenlock/bin/tmpl/greenlock.tmpl.js +13 -0
  20. package/vendor/greenlock/bin/tmpl/server.tmpl.js +20 -0
  21. package/vendor/greenlock/bin/update.js +62 -0
  22. package/vendor/greenlock/certificates.js +324 -0
  23. package/vendor/greenlock/errors.js +58 -0
  24. package/vendor/greenlock/greenlock.js +621 -0
  25. package/vendor/greenlock/greenlockrc.js +169 -0
  26. package/vendor/greenlock/lib/challenges-wrapper.js +88 -0
  27. package/vendor/greenlock/lib/directory-url.js +44 -0
  28. package/vendor/greenlock/lib/init.js +191 -0
  29. package/vendor/greenlock/lib/manager-wrapper.js +625 -0
  30. package/vendor/greenlock/lib/rc.js +70 -0
  31. package/vendor/greenlock/logo/beaker-browser-301x112.png +0 -0
  32. package/vendor/greenlock/logo/from-not-secure-to-secure-url-bar.png +0 -0
  33. package/vendor/greenlock/logo/greenlock-1063x250.png +0 -0
  34. package/vendor/greenlock/logo/greenlock-850x200.png +0 -0
  35. package/vendor/greenlock/logo/ibm-301x112.png +0 -0
  36. package/vendor/greenlock/logo/telebit-301x112.png +0 -0
  37. package/vendor/greenlock/order.js +63 -0
  38. package/vendor/greenlock/package-lock.json +140 -0
  39. package/vendor/greenlock/package.json +56 -0
  40. package/vendor/greenlock/plugins.js +270 -0
  41. package/vendor/greenlock/tests/cli.sh +31 -0
  42. package/vendor/greenlock/tests/index.js +53 -0
  43. package/vendor/greenlock/user-events.js +7 -0
  44. package/vendor/greenlock/utils.js +281 -0
  45. package/vendor/greenlock-express/greenlock-shim.js +3 -1
  46. package/vendor/greenlock-express/package.json +0 -1
@@ -0,0 +1,218 @@
1
+ 'use strict';
2
+
3
+ var A = module.exports;
4
+ var log = require('lemonlog')('greenlock-accounts');
5
+ var U = require('./utils.js');
6
+ var E = require('./errors.js');
7
+
8
+ var pending = {};
9
+
10
+ A._getOrCreate = function(gnlck, mconf, db, acme, args) {
11
+ var email = args.subscriberEmail || mconf.subscriberEmail;
12
+
13
+ if (!email) {
14
+ throw E.NO_SUBSCRIBER('get account', args.subject);
15
+ }
16
+
17
+ // TODO send welcome message with benefit info
18
+ return U._validMx(email)
19
+ .catch(function() {
20
+ throw E.NO_SUBSCRIBER('get account', args.subcriberEmail);
21
+ })
22
+ .then(function() {
23
+ if (pending[email]) {
24
+ return pending[email];
25
+ }
26
+
27
+ pending[email] = A._rawGetOrCreate(
28
+ gnlck,
29
+ mconf,
30
+ db,
31
+ acme,
32
+ args,
33
+ email
34
+ )
35
+ .catch(function(e) {
36
+ delete pending[email];
37
+ throw e;
38
+ })
39
+ .then(function(result) {
40
+ delete pending[email];
41
+ return result;
42
+ });
43
+
44
+ return pending[email];
45
+ });
46
+ };
47
+
48
+ // What we really need out of this is the private key and the ACME "key" id
49
+ A._rawGetOrCreate = function(gnlck, mconf, db, acme, args, email) {
50
+ var p;
51
+ if (db.check) {
52
+ p = A._checkStore(gnlck, mconf, db, acme, args, email);
53
+ } else {
54
+ p = Promise.resolve(null);
55
+ }
56
+
57
+ return p.then(function(fullAccount) {
58
+ if (!fullAccount) {
59
+ return A._newAccount(gnlck, mconf, db, acme, args, email, null);
60
+ }
61
+
62
+ if (fullAccount.keypair && fullAccount.key && fullAccount.key.kid) {
63
+ return fullAccount;
64
+ }
65
+
66
+ return A._newAccount(gnlck, mconf, db, acme, args, email, fullAccount);
67
+ });
68
+ };
69
+
70
+ A._newAccount = function(gnlck, mconf, db, acme, args, email, fullAccount) {
71
+ var keyType = args.accountKeyType || mconf.accountKeyType;
72
+ var query = {
73
+ subject: args.subject,
74
+ email: email,
75
+ subscriberEmail: email,
76
+ customerEmail: args.customerEmail,
77
+ account: fullAccount || {},
78
+ directoryUrl:
79
+ args.directoryUrl ||
80
+ mconf.directoryUrl ||
81
+ gnlck._defaults.directoryUrl
82
+ };
83
+
84
+ return U._getOrCreateKeypair(db, args.subject, query, keyType).then(
85
+ function(kresult) {
86
+ var keypair = kresult.keypair;
87
+ var accReg = {
88
+ subscriberEmail: email,
89
+ agreeToTerms:
90
+ args.agreeToTerms ||
91
+ mconf.agreeToTerms ||
92
+ gnlck._defaults.agreeToTerms,
93
+ accountKey: keypair.privateKeyJwk || keypair.private,
94
+ debug: args.debug
95
+ };
96
+ return acme.accounts.create(accReg).then(function(receipt) {
97
+ var reg = {
98
+ keypair: keypair,
99
+ receipt: receipt,
100
+ // shudder... not actually a KeyID... but so it is called anyway...
101
+ kid:
102
+ receipt &&
103
+ receipt.key &&
104
+ (receipt.key.kid || receipt.kid),
105
+ email: args.email,
106
+ subscriberEmail: email,
107
+ customerEmail: args.customerEmail
108
+ };
109
+
110
+ var keyP;
111
+ if (kresult.exists) {
112
+ keyP = Promise.resolve();
113
+ } else {
114
+ query.keypair = keypair;
115
+ query.receipt = receipt;
116
+ /*
117
+ query.server = gnlck._defaults.directoryUrl.replace(
118
+ /^https?:\/\//i,
119
+ ''
120
+ );
121
+ */
122
+ keyP = db.setKeypair(query, keypair);
123
+ }
124
+
125
+ return keyP
126
+ .then(function() {
127
+ if (!db.set) {
128
+ return Promise.resolve({
129
+ keypair: keypair
130
+ });
131
+ }
132
+ return db.set(
133
+ {
134
+ // id to be set by Store
135
+ email: email,
136
+ subscriberEmail: email,
137
+ customerEmail: args.customerEmail,
138
+ agreeTos: true,
139
+ agreeToTerms: true,
140
+ directoryUrl:
141
+ args.directoryUrl ||
142
+ mconf.directoryUrl ||
143
+ gnlck._defaults.directoryUrl
144
+ /*
145
+ server: gnlck._defaults.directoryUrl.replace(
146
+ /^https?:\/\//i,
147
+ ''
148
+ )
149
+ */
150
+ },
151
+ reg
152
+ );
153
+ })
154
+ .then(function(fullAccount) {
155
+ if (fullAccount && 'object' !== typeof fullAccount) {
156
+ throw new Error(
157
+ "accounts.set should either return 'null' or an object with an 'id' string"
158
+ );
159
+ }
160
+
161
+ if (!fullAccount) {
162
+ fullAccount = {};
163
+ }
164
+ fullAccount.keypair = keypair;
165
+ if (!fullAccount.key) {
166
+ fullAccount.key = {};
167
+ }
168
+ fullAccount.key.kid = reg.kid;
169
+
170
+ return fullAccount;
171
+ });
172
+ });
173
+ }
174
+ );
175
+ };
176
+
177
+ A._checkStore = function(gnlck, mconf, db, acme, args, email) {
178
+ if ((args.domain || args.domains) && !args.subject) {
179
+ log.warn("Use 'subject' instead of 'domain'");
180
+ args.subject = args.domain;
181
+ }
182
+
183
+ var account = args.account;
184
+ if (!account) {
185
+ account = {};
186
+ }
187
+
188
+ if (args.accountKey) {
189
+ log.warn('Prefer storing accountKey in your account key store instead of passing it');
190
+ // TODO we probably don't need this
191
+ return U._importKeypair(args.accountKey);
192
+ }
193
+
194
+ if (!db.check) {
195
+ return Promise.resolve(null);
196
+ }
197
+
198
+ return db
199
+ .check({
200
+ //keypair: undefined,
201
+ //receipt: undefined,
202
+ email: email,
203
+ subscriberEmail: email,
204
+ customerEmail: args.customerEmail || mconf.customerEmail,
205
+ account: account,
206
+ directoryUrl:
207
+ args.directoryUrl ||
208
+ mconf.directoryUrl ||
209
+ gnlck._defaults.directoryUrl
210
+ })
211
+ .then(function(fullAccount) {
212
+ if (!fullAccount) {
213
+ return null;
214
+ }
215
+
216
+ return fullAccount;
217
+ });
218
+ };
@@ -0,0 +1,72 @@
1
+ 'use strict';
2
+
3
+ var log = require('lemonlog')('greenlock-add');
4
+ var args = process.argv.slice(3);
5
+ var cli = require('./lib/cli.js');
6
+ //var path = require('path');
7
+ //var pkgpath = path.join(__dirname, '..', 'package.json');
8
+ //var pkgpath = path.join(process.cwd(), 'package.json');
9
+
10
+ var Flags = require('./lib/flags.js');
11
+
12
+ Flags.init().then(function({ flagOptions, greenlock, mconf }) {
13
+ var myFlags = {};
14
+ [
15
+ 'subject',
16
+ 'altnames',
17
+ 'renew-offset',
18
+ 'subscriber-email',
19
+ 'customer-email',
20
+ 'server-key-type',
21
+ 'challenge-http-01',
22
+ 'challenge-http-01-xxxx',
23
+ 'challenge-dns-01',
24
+ 'challenge-dns-01-xxxx',
25
+ 'challenge-tls-alpn-01',
26
+ 'challenge-tls-alpn-01-xxxx',
27
+ 'challenge',
28
+ 'challenge-xxxx',
29
+ 'challenge-json',
30
+ 'force-save'
31
+ ].forEach(function(k) {
32
+ myFlags[k] = flagOptions[k];
33
+ });
34
+
35
+ cli.parse(myFlags);
36
+ cli.main(function(argList, flags) {
37
+ Flags.mangleFlags(flags, mconf);
38
+ main(argList, flags, greenlock);
39
+ }, args);
40
+ });
41
+
42
+ async function main(_, flags, greenlock) {
43
+ if (!flags.subject || !flags.altnames) {
44
+ log.error('Provide --subject and --altnames (valid domains)');
45
+ process.exit(1);
46
+ return;
47
+ }
48
+
49
+ greenlock
50
+ .add(flags)
51
+ .catch(function(err) {
52
+ log.error('Add failed:', err.message);
53
+ process.exit(1);
54
+ })
55
+ .then(function() {
56
+ return greenlock
57
+ ._config({
58
+ servername:
59
+ flags.altnames[
60
+ Math.floor(Math.random() * flags.altnames.length)
61
+ ]
62
+ })
63
+ .then(function(site) {
64
+ if (!site) {
65
+ log.error('No config found after add (internal mismatch)');
66
+ process.exit(1);
67
+ return;
68
+ }
69
+ log.info('Site config:', site);
70
+ });
71
+ });
72
+ }
@@ -0,0 +1,368 @@
1
+ 'use strict';
2
+
3
+ var log = require('lemonlog')('greenlock-certonly');
4
+ var mkdirp = require('@root/mkdirp');
5
+ var cli = require('./cli.js');
6
+
7
+ cli.parse({
8
+ 'directory-url': [
9
+ false,
10
+ ' ACME Directory Resource URL',
11
+ 'string',
12
+ 'https://acme-v02.api.letsencrypt.org/directory',
13
+ 'server,acme-url'
14
+ ],
15
+ email: [
16
+ false,
17
+ ' Email used for registration and recovery contact. (default: null)',
18
+ 'email'
19
+ ],
20
+ 'agree-tos': [
21
+ false,
22
+ " Agree to the Greenlock and Let's Encrypt Subscriber Agreements",
23
+ 'boolean',
24
+ false
25
+ ],
26
+ 'community-member': [
27
+ false,
28
+ ' Submit stats to and get updates from Greenlock',
29
+ 'boolean',
30
+ false
31
+ ],
32
+ domains: [
33
+ false,
34
+ ' Domain names to apply. For multiple domains you can enter a comma separated list of domains as a parameter. (default: [])',
35
+ 'string'
36
+ ],
37
+ 'renew-offset': [
38
+ false,
39
+ ' Positive (time after issue) or negative (time before expiry) offset, such as 30d or -45d',
40
+ 'string',
41
+ '45d'
42
+ ],
43
+ 'renew-within': [
44
+ false,
45
+ ' (ignored) use renew-offset instead',
46
+ 'ignore',
47
+ undefined
48
+ ],
49
+ 'cert-path': [
50
+ false,
51
+ ' Path to where new cert.pem is saved',
52
+ 'string',
53
+ ':configDir/live/:hostname/cert.pem'
54
+ ],
55
+ 'fullchain-path': [
56
+ false,
57
+ ' Path to where new fullchain.pem (cert + chain) is saved',
58
+ 'string',
59
+ ':configDir/live/:hostname/fullchain.pem'
60
+ ],
61
+ 'bundle-path': [
62
+ false,
63
+ ' Path to where new bundle.pem (fullchain + privkey) is saved',
64
+ 'string',
65
+ ':configDir/live/:hostname/bundle.pem'
66
+ ],
67
+ 'chain-path': [
68
+ false,
69
+ ' Path to where new chain.pem is saved',
70
+ 'string',
71
+ ':configDir/live/:hostname/chain.pem'
72
+ ],
73
+ 'privkey-path': [
74
+ false,
75
+ ' Path to where privkey.pem is saved',
76
+ 'string',
77
+ ':configDir/live/:hostname/privkey.pem'
78
+ ],
79
+ 'config-dir': [
80
+ false,
81
+ ' Configuration directory.',
82
+ 'string',
83
+ '~/letsencrypt/etc/'
84
+ ],
85
+ store: [
86
+ false,
87
+ ' The name of the storage module to use',
88
+ 'string',
89
+ 'greenlock-store-fs'
90
+ ],
91
+ 'store-xxxx': [
92
+ false,
93
+ ' An option for the chosen storage module, such as --store-apikey or --store-bucket',
94
+ 'bag'
95
+ ],
96
+ 'store-json': [
97
+ false,
98
+ ' A JSON string containing all option for the chosen store module (instead of --store-xxxx)',
99
+ 'json',
100
+ '{}'
101
+ ],
102
+ challenge: [
103
+ false,
104
+ ' The name of the HTTP-01, DNS-01, or TLS-ALPN-01 challenge module to use',
105
+ 'string',
106
+ '@greenlock/acme-http-01-fs'
107
+ ],
108
+ 'challenge-xxxx': [
109
+ false,
110
+ ' An option for the chosen challenge module, such as --challenge-apikey or --challenge-bucket',
111
+ 'bag'
112
+ ],
113
+ 'challenge-json': [
114
+ false,
115
+ ' A JSON string containing all option for the chosen challenge module (instead of --challenge-xxxx)',
116
+ 'json',
117
+ '{}'
118
+ ],
119
+ 'skip-dry-run': [
120
+ false,
121
+ ' Use with caution (and test with the staging url first). Creates an Order on the ACME server without a self-test.',
122
+ 'boolean'
123
+ ],
124
+ 'skip-challenge-tests': [
125
+ false,
126
+ ' Use with caution (and with the staging url first). Presents challenges to the ACME server without first testing locally.',
127
+ 'boolean'
128
+ ],
129
+ 'http-01-port': [
130
+ false,
131
+ ' Required to be 80 for live servers. Do not use. For special test environments only.',
132
+ 'int'
133
+ ],
134
+ 'dns-01': [false, ' Use DNS-01 challange type', 'boolean', false],
135
+ standalone: [
136
+ false,
137
+ ' Obtain certs using a "standalone" webserver.',
138
+ 'boolean',
139
+ false
140
+ ],
141
+ manual: [
142
+ false,
143
+ ' Print the token and key to the screen and wait for you to hit enter, giving you time to copy it somewhere before continuing (uses acme-http-01-cli or acme-dns-01-cli)',
144
+ 'boolean',
145
+ false
146
+ ],
147
+ debug: [false, ' show traces and logs', 'boolean', false],
148
+ root: [
149
+ false,
150
+ ' public_html / webroot path (may use the :hostname template such as /srv/www/:hostname)',
151
+ 'string',
152
+ undefined,
153
+ 'webroot-path'
154
+ ],
155
+
156
+ //
157
+ // backwards compat
158
+ //
159
+ duplicate: [
160
+ false,
161
+ ' Allow getting a certificate that duplicates an existing one/is an early renewal',
162
+ 'boolean',
163
+ false
164
+ ],
165
+ 'rsa-key-size': [
166
+ false,
167
+ ' (ignored) use server-key-type or account-key-type instead',
168
+ 'ignore',
169
+ 2048
170
+ ],
171
+ 'server-key-path': [
172
+ false,
173
+ ' Path to privkey.pem to use for certificate (default: generate new)',
174
+ 'string',
175
+ undefined,
176
+ 'domain-key-path'
177
+ ],
178
+ 'server-key-type': [
179
+ false,
180
+ " One of 'RSA' (2048), 'RSA-3084', 'RSA-4096', 'ECDSA' (P-256), or 'P-384'. For best compatibility, security, and efficiency use the default (More bits != More security)",
181
+ 'string',
182
+ 'RSA'
183
+ ],
184
+ 'account-key-path': [
185
+ false,
186
+ ' Path to privkey.pem to use for account (default: generate new)',
187
+ 'string'
188
+ ],
189
+ 'account-key-type': [
190
+ false,
191
+ " One of 'ECDSA' (P-256), 'P-384', 'RSA', 'RSA-3084', or 'RSA-4096'. Stick with 'ECDSA' (P-256) unless you need 'RSA' (2048) for legacy compatibility. (More bits != More security)",
192
+ 'string',
193
+ 'P-256'
194
+ ],
195
+ webroot: [false, ' (ignored) for certbot compatibility', 'ignore', false],
196
+ //, 'standalone-supported-challenges': [ false, " Supported challenges, order preferences are randomly chosen. (default: http-01,tls-alpn-01)", 'string', 'http-01']
197
+ 'work-dir': [
198
+ false,
199
+ ' for certbot compatibility (ignored)',
200
+ 'string',
201
+ '~/letsencrypt/var/lib/'
202
+ ],
203
+ 'logs-dir': [
204
+ false,
205
+ ' for certbot compatibility (ignored)',
206
+ 'string',
207
+ '~/letsencrypt/var/log/'
208
+ ],
209
+ 'acme-version': [
210
+ false,
211
+ ' (ignored) ACME is now RFC 8555 and prior drafts are no longer supported',
212
+ 'ignore',
213
+ 'rfc8555'
214
+ ]
215
+ });
216
+
217
+ // ignore certonly and extraneous arguments
218
+ cli.main(function(_, options) {
219
+
220
+ [
221
+ 'configDir',
222
+ 'privkeyPath',
223
+ 'certPath',
224
+ 'chainPath',
225
+ 'fullchainPath',
226
+ 'bundlePath'
227
+ ].forEach(function(k) {
228
+ if (options[k]) {
229
+ options.storeOpts[k] = options[k];
230
+ }
231
+ delete options[k];
232
+ });
233
+
234
+ if (options.workDir) {
235
+ options.challengeOpts.workDir = options.workDir;
236
+ delete options.workDir;
237
+ }
238
+
239
+ if (options.debug) log.debug('certonly options', options);
240
+
241
+ var args = {};
242
+ var homedir = require('os').homedir();
243
+
244
+ Object.keys(options).forEach(function(key) {
245
+ var val = options[key];
246
+
247
+ if ('string' === typeof val) {
248
+ val = val.replace(/^~/, homedir);
249
+ }
250
+
251
+ key = key.replace(/\-([a-z0-9A-Z])/g, function(c) {
252
+ return c[1].toUpperCase();
253
+ });
254
+ args[key] = val;
255
+ });
256
+
257
+ Object.keys(args).forEach(function(key) {
258
+ var val = args[key];
259
+
260
+ if ('string' === typeof val) {
261
+ val = val.replace(/(\:configDir)|(\:config)/, args.configDir);
262
+ }
263
+
264
+ args[key] = val;
265
+ });
266
+
267
+ if (args.domains) {
268
+ args.domains = args.domains.split(',');
269
+ }
270
+
271
+ if (
272
+ !(Array.isArray(args.domains) && args.domains.length) ||
273
+ !args.email ||
274
+ !args.agreeTos ||
275
+ (!args.server && !args.directoryUrl)
276
+ ) {
277
+ log.error(
278
+ 'Usage: greenlock certonly --standalone --agree-tos --email user@example.com --domains example.com --config-dir ~/acme/etc (see greenlock --help)'
279
+ );
280
+ return;
281
+ }
282
+
283
+ if (args.http01Port) {
284
+ // [@agnat]: Coerce to string. cli returns a number although we request a string.
285
+ args.http01Port = '' + args.http01Port;
286
+ args.http01Port = args.http01Port.split(',').map(function(port) {
287
+ return parseInt(port, 10);
288
+ });
289
+ }
290
+
291
+ function run() {
292
+ var challenges = {};
293
+ if (/http.?01/i.test(args.challenge)) {
294
+ challenges['http-01'] = args.challengeOpts;
295
+ }
296
+ if (/dns.?01/i.test(args.challenge)) {
297
+ challenges['dns-01'] = args.challengeOpts;
298
+ }
299
+ if (/alpn.?01/i.test(args.challenge)) {
300
+ challenges['tls-alpn-01'] = args.challengeOpts;
301
+ }
302
+ if (!Object.keys(challenges).length) {
303
+ throw new Error(
304
+ "Could not determine the challenge type for '" +
305
+ args.challengeOpts.module +
306
+ "'. Expected a name like @you/acme-xxxx-01-foo. Please name the module with http-01, dns-01, or tls-alpn-01."
307
+ );
308
+ }
309
+ args.challengeOpts.module = args.challenge;
310
+ args.storeOpts.module = args.store;
311
+
312
+ require(args.challenge);
313
+ require(args.store);
314
+
315
+ var greenlock = require('../').create({
316
+ maintainerEmail: args.maintainerEmail || 'coolaj86@gmail.com',
317
+ manager: './manager.js',
318
+ configFile: '~/.config/greenlock/certs.json',
319
+ challenges: challenges,
320
+ store: args.storeOpts,
321
+ renewOffset: args.renewOffset || '30d',
322
+ renewStagger: '1d'
323
+ });
324
+
325
+ // for long-running processes
326
+ if (args.renewEvery) {
327
+ setInterval(function() {
328
+ greenlock.renew({
329
+ period: args.renewEvery
330
+ });
331
+ }, args.renewEvery);
332
+ }
333
+
334
+ // TODO should greenlock.add simply always include greenlock.renew?
335
+ // the concern is conflating error events
336
+ return greenlock
337
+ .add({
338
+ subject: args.subject,
339
+ altnames: args.altnames,
340
+ subscriberEmail: args.subscriberEmail || args.email
341
+ })
342
+ .then(function(changes) {
343
+ log.info('Certificate order result:', changes);
344
+ // renew should always
345
+ return greenlock
346
+ .renew({
347
+ subject: args.subject,
348
+ force: false
349
+ })
350
+ .then(function() {});
351
+ });
352
+ }
353
+
354
+ if ('greenlock-store-fs' !== args.store) {
355
+ run();
356
+ return;
357
+ }
358
+
359
+ // TODO remove mkdirp and let greenlock-store-fs do this?
360
+ mkdirp(args.storeOpts.configDir, function(err) {
361
+ if (!err) {
362
+ run();
363
+ }
364
+
365
+ log.error("Could not create config dir '%s': %s. Try --config-dir '/tmp'", args.configDir, err.code);
366
+ return;
367
+ });
368
+ }, process.argv.slice(3));