@postalsys/certs 1.0.1 → 1.0.3
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.
- package/lib/certs.js +60 -16
- package/lib/settings.js +20 -0
- package/package.json +7 -7
package/lib/certs.js
CHANGED
|
@@ -274,13 +274,43 @@ class Certs {
|
|
|
274
274
|
values[dataKey] = Object.assign(currendData || {}, updates);
|
|
275
275
|
}
|
|
276
276
|
|
|
277
|
+
let run = this.redis.multi();
|
|
278
|
+
|
|
279
|
+
if ('cert' in updates) {
|
|
280
|
+
run = run.sadd(this.getKey('certlist'), domain);
|
|
281
|
+
}
|
|
282
|
+
|
|
277
283
|
if (incrVersion) {
|
|
278
|
-
|
|
284
|
+
run = run.hincrby(this.settings.getKey('settings'), versionKey, 1);
|
|
279
285
|
}
|
|
280
286
|
|
|
281
287
|
if (Object.keys(values).length) {
|
|
282
|
-
|
|
288
|
+
run = this.settings.getSet(run, values);
|
|
283
289
|
}
|
|
290
|
+
|
|
291
|
+
await run.exec();
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
async deleteCertificateData(domain) {
|
|
295
|
+
let dataKey = `domain:${domain}:data`;
|
|
296
|
+
let lastCheckKey = `domain:${domain}:lastCheck`;
|
|
297
|
+
let privateKeyKey = `domain:${domain}:privateKey`;
|
|
298
|
+
let lastErrorKey = `domain:${domain}:lastError`;
|
|
299
|
+
let versionKey = `domain:${domain}:certVersion`;
|
|
300
|
+
|
|
301
|
+
return await this.redis
|
|
302
|
+
.multi()
|
|
303
|
+
.hdel(this.settings.getKey('settings'), dataKey)
|
|
304
|
+
.hdel(this.settings.getKey('settings'), lastCheckKey)
|
|
305
|
+
.hdel(this.settings.getKey('settings'), privateKeyKey)
|
|
306
|
+
.hdel(this.settings.getKey('settings'), lastErrorKey)
|
|
307
|
+
.hdel(this.settings.getKey('settings'), versionKey)
|
|
308
|
+
.srem(this.getKey('certlist'), domain)
|
|
309
|
+
.exec();
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
async listCertificateDomains() {
|
|
313
|
+
return (await this.redis.smembers(this.getKey('certlist'))).sort((a, b) => a.toLowerCase().trim().localeCompare(b.toLowerCase().trim()));
|
|
284
314
|
}
|
|
285
315
|
|
|
286
316
|
async acquireCert(domain) {
|
|
@@ -313,21 +343,21 @@ class Certs {
|
|
|
313
343
|
return existingCertificateData;
|
|
314
344
|
}
|
|
315
345
|
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
}
|
|
346
|
+
// reload from db, maybe already renewed
|
|
347
|
+
if (existingCertificateData && existingCertificateData.validTo && existingCertificateData.validTo > new Date(Date.now() + RENEW_AFTER_REMAINING)) {
|
|
348
|
+
// no need to renew
|
|
349
|
+
return existingCertificateData;
|
|
350
|
+
}
|
|
322
351
|
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
352
|
+
let privateKey = existingCertificateData && existingCertificateData.privateKey;
|
|
353
|
+
if (!privateKey) {
|
|
354
|
+
// generate new key
|
|
355
|
+
this.logger.trace({ msg: 'Provision new private key', domain });
|
|
356
|
+
privateKey = await generateKey(this.acmeOptions.keyBits, this.acmeOptions.keyExponent);
|
|
357
|
+
await this.setCertificateData(domain, { domain, privateKey, status: 'pending', lastError: null });
|
|
358
|
+
}
|
|
330
359
|
|
|
360
|
+
try {
|
|
331
361
|
const jwkPrivateKey = pem2jwk(privateKey);
|
|
332
362
|
const csr = await CSR.csr({
|
|
333
363
|
jwk: jwkPrivateKey,
|
|
@@ -397,6 +427,19 @@ class Certs {
|
|
|
397
427
|
} catch (err) {
|
|
398
428
|
this.logger.error({ msg: 'Failed to update certificate record', domain, err });
|
|
399
429
|
}
|
|
430
|
+
} else if (privateKey) {
|
|
431
|
+
try {
|
|
432
|
+
await this.setCertificateData(domain, {
|
|
433
|
+
status: 'failed',
|
|
434
|
+
lastError: {
|
|
435
|
+
err: err.message,
|
|
436
|
+
code: err.code,
|
|
437
|
+
time: new Date()
|
|
438
|
+
}
|
|
439
|
+
});
|
|
440
|
+
} catch (err) {
|
|
441
|
+
this.logger.error({ msg: 'Failed to update certificate record', domain, err });
|
|
442
|
+
}
|
|
400
443
|
}
|
|
401
444
|
|
|
402
445
|
if (existingCertificateData && existingCertificateData.cert) {
|
|
@@ -471,12 +514,13 @@ class Certs {
|
|
|
471
514
|
async getCertificate(domain, skipAcquire) {
|
|
472
515
|
domain = normalizeDomain(domain);
|
|
473
516
|
let certificateData = await this.loadCertificateData(domain);
|
|
517
|
+
|
|
474
518
|
if (certificateData && certificateData.status === 'valid' && certificateData.validTo && certificateData.validTo >= new Date()) {
|
|
475
519
|
return certificateData;
|
|
476
520
|
}
|
|
477
521
|
|
|
478
522
|
if (skipAcquire) {
|
|
479
|
-
return false;
|
|
523
|
+
return certificateData || false;
|
|
480
524
|
}
|
|
481
525
|
|
|
482
526
|
return await this.acquireCert(domain);
|
package/lib/settings.js
CHANGED
|
@@ -20,6 +20,26 @@ class Settings {
|
|
|
20
20
|
return `${this.ns}certs:${name}`;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
+
getSet(run, ...args) {
|
|
24
|
+
let settingsKey = this.getKey('settings');
|
|
25
|
+
|
|
26
|
+
let props = false;
|
|
27
|
+
|
|
28
|
+
if (args.length === 1 && typeof args[0] === 'object' && args[0]) {
|
|
29
|
+
props = {};
|
|
30
|
+
for (let key of Object.keys(args[0])) {
|
|
31
|
+
props[key] = msgpack.encode(args[0][key]);
|
|
32
|
+
}
|
|
33
|
+
} else if (args.length === 2 && typeof args[0] === 'string') {
|
|
34
|
+
props = {
|
|
35
|
+
[args[0]]: msgpack.encode(args[1])
|
|
36
|
+
};
|
|
37
|
+
} else {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
return run.hmset(settingsKey, props);
|
|
41
|
+
}
|
|
42
|
+
|
|
23
43
|
async set(...args) {
|
|
24
44
|
let settingsKey = this.getKey('settings');
|
|
25
45
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@postalsys/certs",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
4
4
|
"description": "Manage Let's Encrypt certificates",
|
|
5
5
|
"main": "lib/certs.js",
|
|
6
6
|
"scripts": {
|
|
@@ -15,17 +15,17 @@
|
|
|
15
15
|
"devDependencies": {
|
|
16
16
|
"eslint-config-nodemailer": "1.2.0",
|
|
17
17
|
"eslint-config-prettier": "8.5.0",
|
|
18
|
-
"express": "4.18.
|
|
19
|
-
"ioredis": "5.
|
|
18
|
+
"express": "4.18.2",
|
|
19
|
+
"ioredis": "5.2.4"
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
22
|
"@root/acme": "3.1.0",
|
|
23
23
|
"ioredfour": "1.2.0-ioredis-06",
|
|
24
|
-
"joi": "17.
|
|
25
|
-
"msgpack5": "6.0.
|
|
24
|
+
"joi": "17.7.0",
|
|
25
|
+
"msgpack5": "6.0.2",
|
|
26
26
|
"pem-jwk": "2.0.0",
|
|
27
|
-
"pino": "8.
|
|
27
|
+
"pino": "8.7.0",
|
|
28
28
|
"punycode": "2.1.1",
|
|
29
|
-
"uuid": "
|
|
29
|
+
"uuid": "9.0.0"
|
|
30
30
|
}
|
|
31
31
|
}
|