@abtnode/certificate-manager 1.6.8 → 1.6.9
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/libs/acme-manager.js +14 -9
- package/libs/util.js +1 -22
- package/package.json +8 -7
- package/sdk/manager.js +16 -13
- package/states/certificate.js +17 -7
package/libs/acme-manager.js
CHANGED
|
@@ -3,12 +3,12 @@ const fs = require('fs');
|
|
|
3
3
|
const path = require('path');
|
|
4
4
|
const { Certificate } = require('@fidm/x509');
|
|
5
5
|
const moment = require('moment');
|
|
6
|
+
const md5 = require('@abtnode/util/lib/md5');
|
|
6
7
|
|
|
7
8
|
const pkg = require('../package.json');
|
|
8
9
|
const AcmeWrapper = require('./acme-wrapper');
|
|
9
10
|
const { CERT_STATUS, CERT_SOURCE } = require('./constant');
|
|
10
11
|
const createQueue = require('./queue');
|
|
11
|
-
const { md5 } = require('./util');
|
|
12
12
|
const logger = require('./logger');
|
|
13
13
|
const states = require('../states');
|
|
14
14
|
|
|
@@ -45,9 +45,9 @@ class Manager extends EventEmitter {
|
|
|
45
45
|
}
|
|
46
46
|
},
|
|
47
47
|
options: {
|
|
48
|
-
maxRetries:
|
|
48
|
+
maxRetries: 3,
|
|
49
49
|
retryDelay: 60 * 1000,
|
|
50
|
-
maxTimeout: 60 * 1000
|
|
50
|
+
maxTimeout: 60 * 1000, // throw timeout error after 1 minutes
|
|
51
51
|
id: (job) => (job ? md5(`${job.domain}-${job.challenge}`) : ''),
|
|
52
52
|
},
|
|
53
53
|
});
|
|
@@ -56,8 +56,9 @@ class Manager extends EventEmitter {
|
|
|
56
56
|
getJobSchedular() {
|
|
57
57
|
return {
|
|
58
58
|
name: 'check-renewal-cert-job',
|
|
59
|
-
time: process.env.NODE_ENV === 'development' ? '0 * * * * *' : '0 */
|
|
59
|
+
time: process.env.NODE_ENV === 'development' ? '0 * * * * *' : '0 */10 * * * *', // every 3 minutes
|
|
60
60
|
fn: this.checkRenewalCerts.bind(this),
|
|
61
|
+
options: { runOnInit: false },
|
|
61
62
|
};
|
|
62
63
|
}
|
|
63
64
|
|
|
@@ -66,6 +67,11 @@ class Manager extends EventEmitter {
|
|
|
66
67
|
throw new Error('domain is required when add domain');
|
|
67
68
|
}
|
|
68
69
|
|
|
70
|
+
const existed = await states.certificate.findOne({ domain });
|
|
71
|
+
if (existed) {
|
|
72
|
+
return existed;
|
|
73
|
+
}
|
|
74
|
+
|
|
69
75
|
const result = await states.certificate.insert({
|
|
70
76
|
domain,
|
|
71
77
|
source: CERT_SOURCE.letsEncrypt,
|
|
@@ -116,7 +122,7 @@ class Manager extends EventEmitter {
|
|
|
116
122
|
let status = CERT_STATUS.creating;
|
|
117
123
|
|
|
118
124
|
if (cert.certificate) {
|
|
119
|
-
const info = Certificate.fromPEM(cert.
|
|
125
|
+
const info = Certificate.fromPEM(cert.certificate);
|
|
120
126
|
const days = moment(info.validTo).diff(moment(), 'days');
|
|
121
127
|
|
|
122
128
|
if (force === false && days > this.renewalOffsetInDay) {
|
|
@@ -150,14 +156,12 @@ class Manager extends EventEmitter {
|
|
|
150
156
|
{
|
|
151
157
|
source: CERT_SOURCE.letsEncrypt,
|
|
152
158
|
status: CERT_STATUS.generated,
|
|
153
|
-
validTo: { $lte: moment().add(this.renewalOffsetInDay, 'days') },
|
|
159
|
+
'meta.validTo': { $lte: moment().add(this.renewalOffsetInDay, 'days').unix() * 1000 },
|
|
154
160
|
},
|
|
155
161
|
],
|
|
156
162
|
});
|
|
157
163
|
|
|
158
|
-
|
|
159
|
-
certs.forEach(({ domain }) => this.queue.push({ domain }));
|
|
160
|
-
}
|
|
164
|
+
certs.forEach(({ domain }) => this.queue.push({ domain }));
|
|
161
165
|
}
|
|
162
166
|
}
|
|
163
167
|
|
|
@@ -184,6 +188,7 @@ Manager.getInstance = async ({ maintainerEmail, baseDataDir }) => {
|
|
|
184
188
|
{ domain: data.subject },
|
|
185
189
|
{
|
|
186
190
|
$set: {
|
|
191
|
+
domain: data.subject,
|
|
187
192
|
status: CERT_STATUS.generated,
|
|
188
193
|
certificate: data.fullchain,
|
|
189
194
|
privateKey: data.privkey,
|
package/libs/util.js
CHANGED
|
@@ -3,8 +3,6 @@ const fs = require('fs');
|
|
|
3
3
|
const get = require('lodash.get');
|
|
4
4
|
const { Certificate, PrivateKey } = require('@fidm/x509');
|
|
5
5
|
|
|
6
|
-
const md5 = (str) => crypto.createHash('md5').update(str).digest('hex');
|
|
7
|
-
|
|
8
6
|
const ensureDir = (dir) => {
|
|
9
7
|
if (fs.existsSync(dir)) {
|
|
10
8
|
return dir;
|
|
@@ -49,7 +47,6 @@ const validateCertificate = (cert, domain) => {
|
|
|
49
47
|
const getCertInfo = (certificate) => {
|
|
50
48
|
const info = Certificate.fromPEM(certificate);
|
|
51
49
|
|
|
52
|
-
const domain = info.subject.commonName.valueOf();
|
|
53
50
|
const validFrom = info.validFrom.valueOf();
|
|
54
51
|
const validTo = info.validTo.valueOf();
|
|
55
52
|
const issuer = {
|
|
@@ -59,11 +56,9 @@ const getCertInfo = (certificate) => {
|
|
|
59
56
|
};
|
|
60
57
|
|
|
61
58
|
return {
|
|
62
|
-
domain,
|
|
63
59
|
validFrom,
|
|
64
60
|
validTo,
|
|
65
61
|
issuer,
|
|
66
|
-
serialNumber: info.serialNumber,
|
|
67
62
|
sans: info.dnsNames,
|
|
68
63
|
validityPeriod: info.validTo - info.validFrom,
|
|
69
64
|
fingerprintAlg: 'SHA256',
|
|
@@ -71,20 +66,4 @@ const getCertInfo = (certificate) => {
|
|
|
71
66
|
};
|
|
72
67
|
};
|
|
73
68
|
|
|
74
|
-
|
|
75
|
-
if (!certificates) {
|
|
76
|
-
return null;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
if (Array.isArray(certificates)) {
|
|
80
|
-
return certificates.map((cert) => {
|
|
81
|
-
const info = cert.certificate ? getCertInfo(cert.certificate) : {};
|
|
82
|
-
return { ...cert, ...info };
|
|
83
|
-
});
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
const info = certificates.certificate ? getCertInfo(certificates.certificate) : {};
|
|
87
|
-
return { ...certificates, ...info };
|
|
88
|
-
};
|
|
89
|
-
|
|
90
|
-
module.exports = { md5, ensureDir, getFingerprint, validateCertificate, attachCertInfo };
|
|
69
|
+
module.exports = { ensureDir, getFingerprint, validateCertificate, getCertInfo };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@abtnode/certificate-manager",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.9",
|
|
4
4
|
"description": "Manage ABT Node SSL certificates",
|
|
5
5
|
"author": "polunzh <polunzh@gmail.com>",
|
|
6
6
|
"homepage": "https://github.com/ArcBlock/blocklet-server#readme",
|
|
@@ -24,17 +24,18 @@
|
|
|
24
24
|
},
|
|
25
25
|
"scripts": {
|
|
26
26
|
"test": "echo \"Error: run tests from root\"",
|
|
27
|
-
"lint": "eslint libs routes states index.js",
|
|
27
|
+
"lint": "eslint libs routes sdk states validators index.js",
|
|
28
28
|
"lint:fix": "eslint --fix tests lib"
|
|
29
29
|
},
|
|
30
30
|
"bugs": {
|
|
31
31
|
"url": "https://github.com/ArcBlock/blocklet-server/issues"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@abtnode/cron": "1.6.
|
|
35
|
-
"@abtnode/db": "1.6.
|
|
36
|
-
"@abtnode/logger": "1.6.
|
|
37
|
-
"@abtnode/queue": "1.6.
|
|
34
|
+
"@abtnode/cron": "1.6.9",
|
|
35
|
+
"@abtnode/db": "1.6.9",
|
|
36
|
+
"@abtnode/logger": "1.6.9",
|
|
37
|
+
"@abtnode/queue": "1.6.9",
|
|
38
|
+
"@abtnode/util": "1.6.9",
|
|
38
39
|
"@fidm/x509": "^1.2.1",
|
|
39
40
|
"@greenlock/manager": "^3.1.0",
|
|
40
41
|
"@nedb/core": "^1.1.0",
|
|
@@ -54,5 +55,5 @@
|
|
|
54
55
|
"punycode": "^2.1.1",
|
|
55
56
|
"ursa-optional": "^0.10.2"
|
|
56
57
|
},
|
|
57
|
-
"gitHead": "
|
|
58
|
+
"gitHead": "372e95513bd9a510702d93650c0c004589579cb3"
|
|
58
59
|
}
|
package/sdk/manager.js
CHANGED
|
@@ -4,7 +4,7 @@ const get = require('lodash.get');
|
|
|
4
4
|
const Cron = require('@abtnode/cron');
|
|
5
5
|
|
|
6
6
|
const AcmeManager = require('../libs/acme-manager');
|
|
7
|
-
const { CERT_SOURCE
|
|
7
|
+
const { CERT_SOURCE } = require('../libs/constant');
|
|
8
8
|
const states = require('../states');
|
|
9
9
|
const { validateAdd, validateUpdate, validateUpsertByDomain } = require('../validators/cert');
|
|
10
10
|
const logger = require('../libs/logger');
|
|
@@ -49,7 +49,7 @@ class Manager extends EventEmitter {
|
|
|
49
49
|
name: 'check-expired-certificates',
|
|
50
50
|
time: '0 0 9 * * *', // check on 09:00 every day
|
|
51
51
|
fn: this.checkCertificatesExpiration.bind(this),
|
|
52
|
-
options: { runOnInit:
|
|
52
|
+
options: { runOnInit: false },
|
|
53
53
|
},
|
|
54
54
|
],
|
|
55
55
|
});
|
|
@@ -86,12 +86,16 @@ class Manager extends EventEmitter {
|
|
|
86
86
|
|
|
87
87
|
getAllNormal() {
|
|
88
88
|
return states.certificate.find({
|
|
89
|
-
$
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
89
|
+
certificate: { $exists: true },
|
|
90
|
+
privateKey: { $exists: true },
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
getNormalByDomain(domain) {
|
|
95
|
+
return states.certificate.findOne({
|
|
96
|
+
domain,
|
|
97
|
+
certificate: { $exists: true },
|
|
98
|
+
privateKey: { $exists: true },
|
|
95
99
|
});
|
|
96
100
|
}
|
|
97
101
|
|
|
@@ -130,11 +134,6 @@ class Manager extends EventEmitter {
|
|
|
130
134
|
throw new Error('domain is required');
|
|
131
135
|
}
|
|
132
136
|
|
|
133
|
-
const existed = await states.certificate.findOne({ domain });
|
|
134
|
-
if (existed) {
|
|
135
|
-
throw new Error(`The name ${domain} already exists!`);
|
|
136
|
-
}
|
|
137
|
-
|
|
138
137
|
return this.acmeManager.add(domain);
|
|
139
138
|
}
|
|
140
139
|
|
|
@@ -175,6 +174,10 @@ class Manager extends EventEmitter {
|
|
|
175
174
|
addWithoutValidations(data) {
|
|
176
175
|
return states.certificate.insert(data);
|
|
177
176
|
}
|
|
177
|
+
|
|
178
|
+
updateWithoutValidations(id, data) {
|
|
179
|
+
return states.certificate.update({ _id: id }, { $set: data });
|
|
180
|
+
}
|
|
178
181
|
}
|
|
179
182
|
|
|
180
183
|
module.exports = Manager;
|
package/states/certificate.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
const get = require('lodash.get');
|
|
2
|
+
|
|
1
3
|
const { CERT_STATUS } = require('../libs/constant');
|
|
2
4
|
const BaseSate = require('./base');
|
|
3
|
-
const {
|
|
5
|
+
const { getCertInfo } = require('../libs/util');
|
|
4
6
|
|
|
5
7
|
class Certificate extends BaseSate {
|
|
6
8
|
constructor(dataDir) {
|
|
@@ -15,14 +17,22 @@ class Certificate extends BaseSate {
|
|
|
15
17
|
return super.update({ domain }, { $set: { status } });
|
|
16
18
|
}
|
|
17
19
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
20
|
+
insert(data) {
|
|
21
|
+
if (data.certificate) {
|
|
22
|
+
data.meta = getCertInfo(data.certificate);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return super.insert(data);
|
|
21
26
|
}
|
|
22
27
|
|
|
23
|
-
async
|
|
24
|
-
|
|
25
|
-
|
|
28
|
+
async update(condition, data, options) {
|
|
29
|
+
if (data.certificate) {
|
|
30
|
+
data.meta = getCertInfo(data.certificate);
|
|
31
|
+
} else if (get(data, '$set.certificate')) {
|
|
32
|
+
data.$set.meta = getCertInfo(get(data, '$set.certificate'));
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return super.update(condition, data, options);
|
|
26
36
|
}
|
|
27
37
|
}
|
|
28
38
|
|