@certd/acme-client 1.20.14 → 1.20.16

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/README.md CHANGED
@@ -9,13 +9,13 @@ This module is written to handle communication with a Boulder/Let's Encrypt-styl
9
9
 
10
10
  ## Compatibility
11
11
 
12
- | acme-client | Node.js | |
13
- | ------------- | --------- | ----------------------------------------- |
14
- | v5.x | >= v16 | [Upgrade guide](docs/upgrade-v5.md) |
15
- | v4.x | >= v10 | [Changelog](CHANGELOG.md#v400-2020-05-29) |
16
- | v3.x | >= v8 | [Changelog](CHANGELOG.md#v300-2019-07-13) |
17
- | v2.x | >= v4 | [Changelog](CHANGELOG.md#v200-2018-04-02) |
18
- | v1.x | >= v4 | [Changelog](CHANGELOG.md#v100-2017-10-20) |
12
+ | acme-client | Node.js | |
13
+ | ----------- | ------- | ----------------------------------------- |
14
+ | v5.x | >= v16 | [Upgrade guide](docs/upgrade-v5.md) |
15
+ | v4.x | >= v10 | [Changelog](CHANGELOG.md#v400-2020-05-29) |
16
+ | v3.x | >= v8 | [Changelog](CHANGELOG.md#v300-2019-07-13) |
17
+ | v2.x | >= v4 | [Changelog](CHANGELOG.md#v200-2018-04-02) |
18
+ | v1.x | >= v4 | [Changelog](CHANGELOG.md#v100-2017-10-20) |
19
19
 
20
20
  ## Table of contents
21
21
 
@@ -49,7 +49,7 @@ const accountPrivateKey = '<PEM encoded private key>';
49
49
 
50
50
  const client = new acme.Client({
51
51
  directoryUrl: acme.directory.letsencrypt.staging,
52
- accountKey: accountPrivateKey
52
+ accountKey: accountPrivateKey,
53
53
  });
54
54
  ```
55
55
 
@@ -75,8 +75,8 @@ const client = new acme.Client({
75
75
  accountKey: accountPrivateKey,
76
76
  externalAccountBinding: {
77
77
  kid: 'YOUR-EAB-KID',
78
- hmacKey: 'YOUR-EAB-HMAC-KEY'
79
- }
78
+ hmacKey: 'YOUR-EAB-HMAC-KEY',
79
+ },
80
80
  });
81
81
  ```
82
82
 
@@ -90,7 +90,7 @@ In some cases, for example with some EAB providers, this account creation step m
90
90
  const client = new acme.Client({
91
91
  directoryUrl: acme.directory.letsencrypt.staging,
92
92
  accountKey: accountPrivateKey,
93
- accountUrl: 'https://acme-v02.api.letsencrypt.org/acme/acct/12345678'
93
+ accountUrl: 'https://acme-v02.api.letsencrypt.org/acme/acct/12345678',
94
94
  });
95
95
  ```
96
96
 
@@ -113,8 +113,7 @@ const privateRsaKey = await acme.crypto.createPrivateRsaKey();
113
113
  const privateEcdsaKey = await acme.crypto.createPrivateEcdsaKey();
114
114
 
115
115
  const [certificateKey, certificateCsr] = await acme.crypto.createCsr({
116
- commonName: '*.example.com',
117
- altNames: ['example.com']
116
+ altNames: ['example.com', '*.example.com'],
118
117
  });
119
118
  ```
120
119
 
@@ -139,7 +138,7 @@ const autoOpts = {
139
138
  email: 'test@example.com',
140
139
  termsOfServiceAgreed: true,
141
140
  challengeCreateFn: async (authz, challenge, keyAuthorization) => {},
142
- challengeRemoveFn: async (authz, challenge, keyAuthorization) => {}
141
+ challengeRemoveFn: async (authz, challenge, keyAuthorization) => {},
143
142
  };
144
143
 
145
144
  const certificate = await client.auto(autoOpts);
@@ -156,7 +155,7 @@ To modify challenge priority, provide a list of challenge types in `challengePri
156
155
  ```js
157
156
  await client.auto({
158
157
  ...,
159
- challengePriority: ['http-01', 'dns-01']
158
+ challengePriority: ['http-01', 'dns-01'],
160
159
  });
161
160
  ```
162
161
 
@@ -171,7 +170,7 @@ To completely disable `acme-client`s internal challenge verification, enable `sk
171
170
  ```js
172
171
  await client.auto({
173
172
  ...,
174
- skipChallengeVerification: true
173
+ skipChallengeVerification: true,
175
174
  });
176
175
  ```
177
176
 
@@ -185,14 +184,14 @@ For more fine-grained control you can interact with the ACME API using the metho
185
184
  ```js
186
185
  const account = await client.createAccount({
187
186
  termsOfServiceAgreed: true,
188
- contact: ['mailto:test@example.com']
187
+ contact: ['mailto:test@example.com'],
189
188
  });
190
189
 
191
190
  const order = await client.createOrder({
192
191
  identifiers: [
193
192
  { type: 'dns', value: 'example.com' },
194
- { type: 'dns', value: '*.example.com' }
195
- ]
193
+ { type: 'dns', value: '*.example.com' },
194
+ ],
196
195
  });
197
196
  ```
198
197
 
@@ -207,7 +206,7 @@ const acme = require('acme-client');
207
206
 
208
207
  acme.axios.defaults.proxy = {
209
208
  host: '127.0.0.1',
210
- port: 9000
209
+ port: 9000,
211
210
  };
212
211
  ```
213
212
 
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "description": "Simple and unopinionated ACME client",
4
4
  "private": false,
5
5
  "author": "nmorsman",
6
- "version": "1.20.14",
6
+ "version": "1.20.16",
7
7
  "main": "src/index.js",
8
8
  "types": "types/index.d.ts",
9
9
  "license": "MIT",
@@ -16,24 +16,24 @@
16
16
  "types"
17
17
  ],
18
18
  "dependencies": {
19
- "@peculiar/x509": "^1.9.7",
19
+ "@peculiar/x509": "^1.10.0",
20
20
  "asn1js": "^3.0.5",
21
- "axios": "^1.6.5",
21
+ "axios": "^1.7.2",
22
22
  "debug": "^4.1.1",
23
23
  "https-proxy-agent": "^7.0.4",
24
24
  "node-forge": "^1.3.1"
25
25
  },
26
26
  "devDependencies": {
27
- "@types/node": "^20.11.5",
27
+ "@types/node": "^20.12.12",
28
28
  "chai": "^4.4.1",
29
- "chai-as-promised": "^7.1.1",
30
- "eslint": "^8.56.0",
29
+ "chai-as-promised": "^7.1.2",
30
+ "eslint": "^8.57.0",
31
31
  "eslint-config-airbnb-base": "^15.0.0",
32
32
  "eslint-plugin-import": "^2.29.1",
33
- "jsdoc-to-markdown": "^8.0.0",
34
- "mocha": "^10.2.0",
35
- "nock": "^13.5.0",
36
- "tsd": "^0.30.4",
33
+ "jsdoc-to-markdown": "^8.0.1",
34
+ "mocha": "^10.4.0",
35
+ "nock": "^13.5.4",
36
+ "tsd": "^0.31.0",
37
37
  "typescript": "^4.8.4",
38
38
  "uuid": "^8.3.2"
39
39
  },
@@ -59,5 +59,5 @@
59
59
  "bugs": {
60
60
  "url": "https://github.com/publishlab/node-acme-client/issues"
61
61
  },
62
- "gitHead": "6900452b49a312d04c1a4b070e8004db7746105f"
62
+ "gitHead": "d46dab4fdda738fac0be87a60a3af6037feb42d4"
63
63
  }
package/src/api.js CHANGED
@@ -4,7 +4,6 @@
4
4
 
5
5
  const util = require('./util');
6
6
 
7
-
8
7
  /**
9
8
  * AcmeApi
10
9
  *
@@ -18,7 +17,6 @@ class AcmeApi {
18
17
  this.accountUrl = accountUrl;
19
18
  }
20
19
 
21
-
22
20
  /**
23
21
  * Get account URL
24
22
  *
@@ -34,7 +32,6 @@ class AcmeApi {
34
32
  return this.accountUrl;
35
33
  }
36
34
 
37
-
38
35
  /**
39
36
  * ACME API request
40
37
  *
@@ -59,7 +56,6 @@ class AcmeApi {
59
56
  return resp;
60
57
  }
61
58
 
62
-
63
59
  /**
64
60
  * ACME API request by resource name helper
65
61
  *
@@ -78,7 +74,6 @@ class AcmeApi {
78
74
  return this.apiRequest(resourceUrl, payload, validStatusCodes, { includeJwsKid, includeExternalAccountBinding });
79
75
  }
80
76
 
81
-
82
77
  /**
83
78
  * Get Terms of Service URL if available
84
79
  *
@@ -91,7 +86,6 @@ class AcmeApi {
91
86
  return this.http.getMetaField('termsOfService');
92
87
  }
93
88
 
94
-
95
89
  /**
96
90
  * Create new account
97
91
  *
@@ -104,7 +98,7 @@ class AcmeApi {
104
98
  async createAccount(data) {
105
99
  const resp = await this.apiResourceRequest('newAccount', data, [200, 201], {
106
100
  includeJwsKid: false,
107
- includeExternalAccountBinding: (data.onlyReturnExisting !== true)
101
+ includeExternalAccountBinding: (data.onlyReturnExisting !== true),
108
102
  });
109
103
 
110
104
  /* Set account URL */
@@ -115,7 +109,6 @@ class AcmeApi {
115
109
  return resp;
116
110
  }
117
111
 
118
-
119
112
  /**
120
113
  * Update account
121
114
  *
@@ -129,7 +122,6 @@ class AcmeApi {
129
122
  return this.apiRequest(this.getAccountUrl(), data, [200, 202]);
130
123
  }
131
124
 
132
-
133
125
  /**
134
126
  * Update account key
135
127
  *
@@ -143,7 +135,6 @@ class AcmeApi {
143
135
  return this.apiResourceRequest('keyChange', data, [200]);
144
136
  }
145
137
 
146
-
147
138
  /**
148
139
  * Create new order
149
140
  *
@@ -157,7 +148,6 @@ class AcmeApi {
157
148
  return this.apiResourceRequest('newOrder', data, [201]);
158
149
  }
159
150
 
160
-
161
151
  /**
162
152
  * Get order
163
153
  *
@@ -171,7 +161,6 @@ class AcmeApi {
171
161
  return this.apiRequest(url, null, [200]);
172
162
  }
173
163
 
174
-
175
164
  /**
176
165
  * Finalize order
177
166
  *
@@ -186,7 +175,6 @@ class AcmeApi {
186
175
  return this.apiRequest(url, data, [200]);
187
176
  }
188
177
 
189
-
190
178
  /**
191
179
  * Get identifier authorization
192
180
  *
@@ -200,7 +188,6 @@ class AcmeApi {
200
188
  return this.apiRequest(url, null, [200]);
201
189
  }
202
190
 
203
-
204
191
  /**
205
192
  * Update identifier authorization
206
193
  *
@@ -215,7 +202,6 @@ class AcmeApi {
215
202
  return this.apiRequest(url, data, [200]);
216
203
  }
217
204
 
218
-
219
205
  /**
220
206
  * Complete challenge
221
207
  *
@@ -230,7 +216,6 @@ class AcmeApi {
230
216
  return this.apiRequest(url, data, [200]);
231
217
  }
232
218
 
233
-
234
219
  /**
235
220
  * Revoke certificate
236
221
  *
@@ -245,6 +230,5 @@ class AcmeApi {
245
230
  }
246
231
  }
247
232
 
248
-
249
233
  /* Export API */
250
234
  module.exports = AcmeApi;
package/src/auto.js CHANGED
@@ -4,6 +4,7 @@
4
4
 
5
5
  const { readCsrDomains } = require('./crypto');
6
6
  const { log } = require('./logger');
7
+ const { wait } = require('./wait');
7
8
 
8
9
  const defaultOpts = {
9
10
  csr: null,
@@ -13,10 +14,9 @@ const defaultOpts = {
13
14
  skipChallengeVerification: false,
14
15
  challengePriority: ['http-01', 'dns-01'],
15
16
  challengeCreateFn: async () => { throw new Error('Missing challengeCreateFn()'); },
16
- challengeRemoveFn: async () => { throw new Error('Missing challengeRemoveFn()'); }
17
+ challengeRemoveFn: async () => { throw new Error('Missing challengeRemoveFn()'); },
17
18
  };
18
19
 
19
-
20
20
  /**
21
21
  * ACME client auto mode
22
22
  *
@@ -25,8 +25,8 @@ const defaultOpts = {
25
25
  * @returns {Promise<buffer>} Certificate
26
26
  */
27
27
 
28
- module.exports = async function(client, userOpts) {
29
- const opts = Object.assign({}, defaultOpts, userOpts);
28
+ module.exports = async (client, userOpts) => {
29
+ const opts = { ...defaultOpts, ...userOpts };
30
30
  const accountPayload = { termsOfServiceAgreed: opts.termsOfServiceAgreed };
31
31
 
32
32
  if (!Buffer.isBuffer(opts.csr)) {
@@ -37,7 +37,6 @@ module.exports = async function(client, userOpts) {
37
37
  accountPayload.contact = [`mailto:${opts.email}`];
38
38
  }
39
39
 
40
-
41
40
  /**
42
41
  * Register account
43
42
  */
@@ -53,7 +52,6 @@ module.exports = async function(client, userOpts) {
53
52
  await client.createAccount(accountPayload);
54
53
  }
55
54
 
56
-
57
55
  /**
58
56
  * Parse domains from CSR
59
57
  */
@@ -64,7 +62,6 @@ module.exports = async function(client, userOpts) {
64
62
 
65
63
  log(`[auto] Resolved ${uniqueDomains.length} unique domains from parsing the Certificate Signing Request`);
66
64
 
67
-
68
65
  /**
69
66
  * Place order
70
67
  */
@@ -76,7 +73,6 @@ module.exports = async function(client, userOpts) {
76
73
 
77
74
  log(`[auto] Placed certificate order successfully, received ${authorizations.length} identity authorizations`);
78
75
 
79
-
80
76
  /**
81
77
  * Resolve and satisfy challenges
82
78
  */
@@ -118,7 +114,18 @@ module.exports = async function(client, userOpts) {
118
114
  let recordItem = null;
119
115
  try {
120
116
  recordItem = await opts.challengeCreateFn(authz, challenge, keyAuthorization);
121
-
117
+ log(`[auto] [${d}] challengeCreateFn success`);
118
+ log(`[auto] [${d}] add challengeRemoveFn()`);
119
+ clearTasks.push(async () => {
120
+ /* Trigger challengeRemoveFn(), suppress errors */
121
+ log(`[auto] [${d}] Trigger challengeRemoveFn()`);
122
+ try {
123
+ await opts.challengeRemoveFn(authz, challenge, keyAuthorization, recordItem);
124
+ }
125
+ catch (e) {
126
+ log(`[auto] [${d}] challengeRemoveFn threw error: ${e.message}`);
127
+ }
128
+ });
122
129
  // throw new Error('测试异常');
123
130
  /* Challenge verification */
124
131
  if (opts.skipChallengeVerification === true) {
@@ -140,19 +147,6 @@ module.exports = async function(client, userOpts) {
140
147
  log(`[auto] [${d}] challengeCreateFn threw error: ${e.message}`);
141
148
  throw e;
142
149
  }
143
- finally {
144
- log(`[auto] [${d}] add challengeRemoveFn()`);
145
- clearTasks.push(async () => {
146
- /* Trigger challengeRemoveFn(), suppress errors */
147
- log(`[auto] [${d}] Trigger challengeRemoveFn()`);
148
- try {
149
- await opts.challengeRemoveFn(authz, challenge, keyAuthorization, recordItem);
150
- }
151
- catch (e) {
152
- log(`[auto] [${d}] challengeRemoveFn threw error: ${e.message}`);
153
- }
154
- });
155
- }
156
150
  }
157
151
  catch (e) {
158
152
  /* Deactivate pending authz when unable to complete challenge */
@@ -177,7 +171,6 @@ module.exports = async function(client, userOpts) {
177
171
  await challengeFunc(authz);
178
172
  });
179
173
 
180
-
181
174
  function runAllPromise(tasks) {
182
175
  let promise = Promise.resolve();
183
176
  tasks.forEach((task) => {
@@ -186,14 +179,20 @@ module.exports = async function(client, userOpts) {
186
179
  return promise;
187
180
  }
188
181
 
189
- // function runPromisePa(tasks) {
190
- // return Promise.all(tasks.map((task) => task()));
191
- // }
192
-
182
+ async function runPromisePa(tasks) {
183
+ const results = [];
184
+ // eslint-disable-next-line no-await-in-loop,no-restricted-syntax
185
+ for (const task of tasks) {
186
+ results.push(task());
187
+ // eslint-disable-next-line no-await-in-loop
188
+ await wait(10000);
189
+ }
190
+ return Promise.all(results);
191
+ }
193
192
 
194
193
  try {
195
194
  log('开始challenge');
196
- await runAllPromise(challengePromises);
195
+ await runPromisePa(challengePromises);
197
196
 
198
197
  log('challenge结束');
199
198
 
@@ -210,11 +209,18 @@ module.exports = async function(client, userOpts) {
210
209
  }
211
210
  catch (e) {
212
211
  log('证书申请失败');
213
- throw e;
212
+ log(e);
213
+ throw new Error(`证书申请失败:${e.message}`);
214
214
  }
215
215
  finally {
216
216
  log(`清理challenge痕迹,length:${clearTasks.length}`);
217
- await runAllPromise(clearTasks);
217
+ try {
218
+ await runAllPromise(clearTasks);
219
+ }
220
+ catch (e) {
221
+ log('清理challenge失败');
222
+ log(e);
223
+ }
218
224
  }
219
225
 
220
226
  // try {
package/src/axios.js CHANGED
@@ -5,7 +5,6 @@
5
5
  const axios = require('axios');
6
6
  const pkg = require('./../package.json');
7
7
 
8
-
9
8
  /**
10
9
  * Instance
11
10
  */
@@ -19,9 +18,8 @@ instance.defaults.headers.common['User-Agent'] = `node-${pkg.name}/${pkg.version
19
18
  instance.defaults.acmeSettings = {
20
19
  httpChallengePort: 80,
21
20
  httpsChallengePort: 443,
22
- tlsAlpnChallengePort: 443
21
+ tlsAlpnChallengePort: 443,
23
22
  };
24
-
25
23
  // instance.defaults.proxy = {
26
24
  // host: '192.168.34.139',
27
25
  // port: 10811
@@ -35,7 +33,6 @@ instance.defaults.acmeSettings = {
35
33
 
36
34
  instance.defaults.adapter = 'http';
37
35
 
38
-
39
36
  /**
40
37
  * Export instance
41
38
  */