@certd/acme-client 1.20.2 → 1.20.5
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/LICENSE +1 -1
- package/README.md +13 -36
- package/package.json +17 -16
- package/src/api.js +13 -13
- package/src/auto.js +30 -10
- package/src/axios.js +7 -4
- package/src/client.js +22 -25
- package/src/crypto/forge.js +2 -2
- package/src/crypto/index.js +216 -123
- package/src/http.js +15 -5
- package/src/util.js +59 -3
- package/src/verify.js +38 -4
- package/types/index.d.ts +2 -0
- package/types/rfc8555.d.ts +10 -10
- package/types/tsconfig.json +0 -11
- package/types/tslint.json +0 -6
- /package/types/{test.ts → index.test-d.ts} +0 -0
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -1,21 +1,13 @@
|
|
|
1
|
-
# acme-client [](https://github.com/publishlab/node-acme-client/actions/workflows/tests.yml)
|
|
2
2
|
|
|
3
3
|
*A simple and unopinionated ACME client.*
|
|
4
4
|
|
|
5
5
|
This module is written to handle communication with a Boulder/Let's Encrypt-style ACME API.
|
|
6
6
|
|
|
7
|
-
* RFC 8555 - Automatic Certificate Management Environment (ACME): [https://
|
|
7
|
+
* RFC 8555 - Automatic Certificate Management Environment (ACME): [https://datatracker.ietf.org/doc/html/rfc8555](https://datatracker.ietf.org/doc/html/rfc8555)
|
|
8
8
|
* Boulder divergences from ACME: [https://github.com/letsencrypt/boulder/blob/master/docs/acme-divergences.md](https://github.com/letsencrypt/boulder/blob/master/docs/acme-divergences.md)
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
## Important upgrade notice
|
|
12
|
-
|
|
13
|
-
On September 15, 2022, Let's Encrypt will stop accepting Certificate Signing Requests signed using the obsolete SHA-1 hash. This change affects all `acme-client` versions lower than `3.3.2` and `4.2.4`. Please upgrade ASAP to ensure that your certificates can still be issued following this date.
|
|
14
|
-
|
|
15
|
-
A more detailed explanation can be found [at the Let's Encrypt forums](https://community.letsencrypt.org/t/rejecting-sha-1-csrs-and-validation-using-tls-1-0-1-1-urls/175144).
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
### Compatibility
|
|
10
|
+
## Compatibility
|
|
19
11
|
|
|
20
12
|
| acme-client | Node.js | |
|
|
21
13
|
| ------------- | --------- | ----------------------------------------- |
|
|
@@ -25,8 +17,7 @@ A more detailed explanation can be found [at the Let's Encrypt forums](https://c
|
|
|
25
17
|
| v2.x | >= v4 | [Changelog](CHANGELOG.md#v200-2018-04-02) |
|
|
26
18
|
| v1.x | >= v4 | [Changelog](CHANGELOG.md#v100-2017-10-20) |
|
|
27
19
|
|
|
28
|
-
|
|
29
|
-
### Table of contents
|
|
20
|
+
## Table of contents
|
|
30
21
|
|
|
31
22
|
* [Installation](#installation)
|
|
32
23
|
* [Usage](#usage)
|
|
@@ -43,14 +34,12 @@ A more detailed explanation can be found [at the Let's Encrypt forums](https://c
|
|
|
43
34
|
* [Debugging](#debugging)
|
|
44
35
|
* [License](#license)
|
|
45
36
|
|
|
46
|
-
|
|
47
37
|
## Installation
|
|
48
38
|
|
|
49
39
|
```bash
|
|
50
40
|
$ npm install acme-client
|
|
51
41
|
```
|
|
52
42
|
|
|
53
|
-
|
|
54
43
|
## Usage
|
|
55
44
|
|
|
56
45
|
```js
|
|
@@ -64,7 +53,6 @@ const client = new acme.Client({
|
|
|
64
53
|
});
|
|
65
54
|
```
|
|
66
55
|
|
|
67
|
-
|
|
68
56
|
### Directory URLs
|
|
69
57
|
|
|
70
58
|
```js
|
|
@@ -77,10 +65,9 @@ acme.directory.letsencrypt.production;
|
|
|
77
65
|
acme.directory.zerossl.production;
|
|
78
66
|
```
|
|
79
67
|
|
|
80
|
-
|
|
81
68
|
### External account binding
|
|
82
69
|
|
|
83
|
-
To enable [external account binding](https://
|
|
70
|
+
To enable [external account binding](https://datatracker.ietf.org/doc/html/rfc8555#section-7.3.4) when creating your ACME account, provide your KID and HMAC key to the client constructor.
|
|
84
71
|
|
|
85
72
|
```js
|
|
86
73
|
const client = new acme.Client({
|
|
@@ -93,7 +80,6 @@ const client = new acme.Client({
|
|
|
93
80
|
});
|
|
94
81
|
```
|
|
95
82
|
|
|
96
|
-
|
|
97
83
|
### Specifying the account URL
|
|
98
84
|
|
|
99
85
|
During the ACME account creation process, the server will check the supplied account key and either create a new account if the key is unused, or return the existing ACME account bound to that key.
|
|
@@ -114,14 +100,13 @@ You can fetch the clients current account URL, either after creating an account
|
|
|
114
100
|
const myAccountUrl = client.getAccountUrl();
|
|
115
101
|
```
|
|
116
102
|
|
|
117
|
-
|
|
118
103
|
## Cryptography
|
|
119
104
|
|
|
120
|
-
For key pairs `acme-client` utilizes native Node.js cryptography APIs, supporting signing and generation of both RSA and ECDSA keys. The module [
|
|
105
|
+
For key pairs `acme-client` utilizes native Node.js cryptography APIs, supporting signing and generation of both RSA and ECDSA keys. The module [@peculiar/x509](https://www.npmjs.com/package/@peculiar/x509) is used to generate and parse Certificate Signing Requests.
|
|
121
106
|
|
|
122
107
|
These utility methods are exposed through `.crypto`.
|
|
123
108
|
|
|
124
|
-
*
|
|
109
|
+
* **Documentation: [docs/crypto.md](docs/crypto.md)**
|
|
125
110
|
|
|
126
111
|
```js
|
|
127
112
|
const privateRsaKey = await acme.crypto.createPrivateRsaKey();
|
|
@@ -133,22 +118,20 @@ const [certificateKey, certificateCsr] = await acme.crypto.createCsr({
|
|
|
133
118
|
});
|
|
134
119
|
```
|
|
135
120
|
|
|
136
|
-
|
|
137
121
|
### Legacy `.forge` interface
|
|
138
122
|
|
|
139
123
|
The legacy `node-forge` crypto interface is still available for backward compatibility, however this interface is now considered deprecated and will be removed in a future major version of `acme-client`.
|
|
140
124
|
|
|
141
125
|
You should consider migrating to the new `.crypto` API at your earliest convenience. More details can be found in the [acme-client v5 upgrade guide](docs/upgrade-v5.md).
|
|
142
126
|
|
|
143
|
-
*
|
|
144
|
-
|
|
127
|
+
* **Documentation: [docs/forge.md](docs/forge.md)**
|
|
145
128
|
|
|
146
129
|
## Auto mode
|
|
147
130
|
|
|
148
131
|
For convenience an `auto()` method is included in the client that takes a single config object. This method will handle the entire process of getting a certificate for one or multiple domains.
|
|
149
132
|
|
|
150
|
-
*
|
|
151
|
-
*
|
|
133
|
+
* **Documentation: [docs/client.md#AcmeClient+auto](docs/client.md#AcmeClient+auto)**
|
|
134
|
+
* **Full example: [examples/auto.js](examples/auto.js)**
|
|
152
135
|
|
|
153
136
|
```js
|
|
154
137
|
const autoOpts = {
|
|
@@ -162,12 +145,11 @@ const autoOpts = {
|
|
|
162
145
|
const certificate = await client.auto(autoOpts);
|
|
163
146
|
```
|
|
164
147
|
|
|
165
|
-
|
|
166
148
|
### Challenge priority
|
|
167
149
|
|
|
168
150
|
When ordering a certificate using auto mode, `acme-client` uses a priority list when selecting challenges to respond to. Its default value is `['http-01', 'dns-01']` which translates to "use `http-01` if any challenges exist, otherwise fall back to `dns-01`".
|
|
169
151
|
|
|
170
|
-
While most challenges can be validated using the method of your choosing, please note that
|
|
152
|
+
While most challenges can be validated using the method of your choosing, please note that **wildcard certificates can only be validated through `dns-01`**. More information regarding Let's Encrypt challenge types [can be found here](https://letsencrypt.org/docs/challenge-types/).
|
|
171
153
|
|
|
172
154
|
To modify challenge priority, provide a list of challenge types in `challengePriority`:
|
|
173
155
|
|
|
@@ -178,7 +160,6 @@ await client.auto({
|
|
|
178
160
|
});
|
|
179
161
|
```
|
|
180
162
|
|
|
181
|
-
|
|
182
163
|
### Internal challenge verification
|
|
183
164
|
|
|
184
165
|
When using auto mode, `acme-client` will first validate that challenges are satisfied internally before completing the challenge at the ACME provider. In some cases (firewalls, etc) this internal challenge verification might not be possible to complete.
|
|
@@ -194,13 +175,12 @@ await client.auto({
|
|
|
194
175
|
});
|
|
195
176
|
```
|
|
196
177
|
|
|
197
|
-
|
|
198
178
|
## API
|
|
199
179
|
|
|
200
180
|
For more fine-grained control you can interact with the ACME API using the methods documented below.
|
|
201
181
|
|
|
202
|
-
*
|
|
203
|
-
*
|
|
182
|
+
* **Documentation: [docs/client.md](docs/client.md)**
|
|
183
|
+
* **Full example: [examples/api.js](examples/api.js)**
|
|
204
184
|
|
|
205
185
|
```js
|
|
206
186
|
const account = await client.createAccount({
|
|
@@ -216,7 +196,6 @@ const order = await client.createOrder({
|
|
|
216
196
|
});
|
|
217
197
|
```
|
|
218
198
|
|
|
219
|
-
|
|
220
199
|
## HTTP client defaults
|
|
221
200
|
|
|
222
201
|
This module uses [axios](https://github.com/axios/axios) when communicating with the ACME HTTP API, and exposes the client instance through `.axios`.
|
|
@@ -237,7 +216,6 @@ A complete list of axios options and documentation can be found at:
|
|
|
237
216
|
* [https://github.com/axios/axios#request-config](https://github.com/axios/axios#request-config)
|
|
238
217
|
* [https://github.com/axios/axios#custom-instance-defaults](https://github.com/axios/axios#custom-instance-defaults)
|
|
239
218
|
|
|
240
|
-
|
|
241
219
|
## Debugging
|
|
242
220
|
|
|
243
221
|
To get a better grasp of what `acme-client` is doing behind the scenes, you can either pass it a logger function, or enable debugging through an environment variable.
|
|
@@ -256,7 +234,6 @@ Debugging to the console can also be enabled through [debug](https://www.npmjs.c
|
|
|
256
234
|
DEBUG=acme-client node index.js
|
|
257
235
|
```
|
|
258
236
|
|
|
259
|
-
|
|
260
237
|
## License
|
|
261
238
|
|
|
262
239
|
[MIT](LICENSE)
|
package/package.json
CHANGED
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
"description": "Simple and unopinionated ACME client",
|
|
4
4
|
"private": false,
|
|
5
5
|
"author": "nmorsman",
|
|
6
|
-
"version": "1.20.
|
|
6
|
+
"version": "1.20.5",
|
|
7
7
|
"main": "src/index.js",
|
|
8
|
-
"types": "types",
|
|
8
|
+
"types": "types/index.d.ts",
|
|
9
9
|
"license": "MIT",
|
|
10
10
|
"homepage": "https://github.com/publishlab/node-acme-client",
|
|
11
11
|
"engines": {
|
|
@@ -16,32 +16,33 @@
|
|
|
16
16
|
"types"
|
|
17
17
|
],
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"
|
|
19
|
+
"@peculiar/x509": "^1.9.7",
|
|
20
|
+
"asn1js": "^3.0.5",
|
|
21
|
+
"axios": "^1.6.5",
|
|
20
22
|
"debug": "^4.1.1",
|
|
21
|
-
"
|
|
23
|
+
"https-proxy-agent": "^7.0.4",
|
|
22
24
|
"node-forge": "^1.3.1"
|
|
23
25
|
},
|
|
24
26
|
"devDependencies": {
|
|
25
|
-
"@types/node": "^
|
|
26
|
-
"chai": "^4.
|
|
27
|
+
"@types/node": "^20.11.5",
|
|
28
|
+
"chai": "^4.4.1",
|
|
27
29
|
"chai-as-promised": "^7.1.1",
|
|
28
|
-
"
|
|
29
|
-
"eslint": "^8.11.0",
|
|
30
|
+
"eslint": "^8.56.0",
|
|
30
31
|
"eslint-config-airbnb-base": "^15.0.0",
|
|
31
|
-
"eslint-plugin-import": "^2.
|
|
32
|
-
"jsdoc-to-markdown": "^
|
|
33
|
-
"mocha": "^10.
|
|
34
|
-
"nock": "^13.
|
|
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",
|
|
35
37
|
"typescript": "^4.8.4",
|
|
36
38
|
"uuid": "^8.3.2"
|
|
37
39
|
},
|
|
38
40
|
"scripts": {
|
|
39
41
|
"build-docs": "jsdoc2md src/client.js > docs/client.md && jsdoc2md src/crypto/index.js > docs/crypto.md && jsdoc2md src/crypto/forge.js > docs/forge.md",
|
|
40
42
|
"lint": "eslint .",
|
|
41
|
-
"lint-types": "
|
|
43
|
+
"lint-types": "tsd",
|
|
42
44
|
"prepublishOnly": "npm run build-docs",
|
|
43
|
-
"test": "mocha -t 60000 \"test/setup.js\" \"test/**/*.spec.js\""
|
|
44
|
-
"test-local": "/bin/bash scripts/run-tests.sh"
|
|
45
|
+
"test": "mocha -t 60000 \"test/setup.js\" \"test/**/*.spec.js\""
|
|
45
46
|
},
|
|
46
47
|
"repository": {
|
|
47
48
|
"type": "git",
|
|
@@ -58,5 +59,5 @@
|
|
|
58
59
|
"bugs": {
|
|
59
60
|
"url": "https://github.com/publishlab/node-acme-client/issues"
|
|
60
61
|
},
|
|
61
|
-
"gitHead": "
|
|
62
|
+
"gitHead": "485ae3514cf0983715464d02d0ddbaf271f52189"
|
|
62
63
|
}
|
package/src/api.js
CHANGED
|
@@ -41,7 +41,7 @@ class AcmeApi {
|
|
|
41
41
|
* @private
|
|
42
42
|
* @param {string} url Request URL
|
|
43
43
|
* @param {object} [payload] Request payload, default: `null`
|
|
44
|
-
* @param {
|
|
44
|
+
* @param {number[]} [validStatusCodes] Array of valid HTTP response status codes, default: `[]`
|
|
45
45
|
* @param {object} [opts]
|
|
46
46
|
* @param {boolean} [opts.includeJwsKid] Include KID instead of JWK in JWS header, default: `true`
|
|
47
47
|
* @param {boolean} [opts.includeExternalAccountBinding] Include EAB in request, default: `false`
|
|
@@ -66,7 +66,7 @@ class AcmeApi {
|
|
|
66
66
|
* @private
|
|
67
67
|
* @param {string} resource Request resource name
|
|
68
68
|
* @param {object} [payload] Request payload, default: `null`
|
|
69
|
-
* @param {
|
|
69
|
+
* @param {number[]} [validStatusCodes] Array of valid HTTP response status codes, default: `[]`
|
|
70
70
|
* @param {object} [opts]
|
|
71
71
|
* @param {boolean} [opts.includeJwsKid] Include KID instead of JWK in JWS header, default: `true`
|
|
72
72
|
* @param {boolean} [opts.includeExternalAccountBinding] Include EAB in request, default: `false`
|
|
@@ -82,7 +82,7 @@ class AcmeApi {
|
|
|
82
82
|
/**
|
|
83
83
|
* Get Terms of Service URL if available
|
|
84
84
|
*
|
|
85
|
-
* https://
|
|
85
|
+
* https://datatracker.ietf.org/doc/html/rfc8555#section-7.1.1
|
|
86
86
|
*
|
|
87
87
|
* @returns {Promise<string|null>} ToS URL
|
|
88
88
|
*/
|
|
@@ -95,7 +95,7 @@ class AcmeApi {
|
|
|
95
95
|
/**
|
|
96
96
|
* Create new account
|
|
97
97
|
*
|
|
98
|
-
* https://
|
|
98
|
+
* https://datatracker.ietf.org/doc/html/rfc8555#section-7.3
|
|
99
99
|
*
|
|
100
100
|
* @param {object} data Request payload
|
|
101
101
|
* @returns {Promise<object>} HTTP response
|
|
@@ -119,7 +119,7 @@ class AcmeApi {
|
|
|
119
119
|
/**
|
|
120
120
|
* Update account
|
|
121
121
|
*
|
|
122
|
-
* https://
|
|
122
|
+
* https://datatracker.ietf.org/doc/html/rfc8555#section-7.3.2
|
|
123
123
|
*
|
|
124
124
|
* @param {object} data Request payload
|
|
125
125
|
* @returns {Promise<object>} HTTP response
|
|
@@ -133,7 +133,7 @@ class AcmeApi {
|
|
|
133
133
|
/**
|
|
134
134
|
* Update account key
|
|
135
135
|
*
|
|
136
|
-
* https://
|
|
136
|
+
* https://datatracker.ietf.org/doc/html/rfc8555#section-7.3.5
|
|
137
137
|
*
|
|
138
138
|
* @param {object} data Request payload
|
|
139
139
|
* @returns {Promise<object>} HTTP response
|
|
@@ -147,7 +147,7 @@ class AcmeApi {
|
|
|
147
147
|
/**
|
|
148
148
|
* Create new order
|
|
149
149
|
*
|
|
150
|
-
* https://
|
|
150
|
+
* https://datatracker.ietf.org/doc/html/rfc8555#section-7.4
|
|
151
151
|
*
|
|
152
152
|
* @param {object} data Request payload
|
|
153
153
|
* @returns {Promise<object>} HTTP response
|
|
@@ -161,7 +161,7 @@ class AcmeApi {
|
|
|
161
161
|
/**
|
|
162
162
|
* Get order
|
|
163
163
|
*
|
|
164
|
-
* https://
|
|
164
|
+
* https://datatracker.ietf.org/doc/html/rfc8555#section-7.4
|
|
165
165
|
*
|
|
166
166
|
* @param {string} url Order URL
|
|
167
167
|
* @returns {Promise<object>} HTTP response
|
|
@@ -175,7 +175,7 @@ class AcmeApi {
|
|
|
175
175
|
/**
|
|
176
176
|
* Finalize order
|
|
177
177
|
*
|
|
178
|
-
* https://
|
|
178
|
+
* https://datatracker.ietf.org/doc/html/rfc8555#section-7.4
|
|
179
179
|
*
|
|
180
180
|
* @param {string} url Finalization URL
|
|
181
181
|
* @param {object} data Request payload
|
|
@@ -190,7 +190,7 @@ class AcmeApi {
|
|
|
190
190
|
/**
|
|
191
191
|
* Get identifier authorization
|
|
192
192
|
*
|
|
193
|
-
* https://
|
|
193
|
+
* https://datatracker.ietf.org/doc/html/rfc8555#section-7.5
|
|
194
194
|
*
|
|
195
195
|
* @param {string} url Authorization URL
|
|
196
196
|
* @returns {Promise<object>} HTTP response
|
|
@@ -204,7 +204,7 @@ class AcmeApi {
|
|
|
204
204
|
/**
|
|
205
205
|
* Update identifier authorization
|
|
206
206
|
*
|
|
207
|
-
* https://
|
|
207
|
+
* https://datatracker.ietf.org/doc/html/rfc8555#section-7.5.2
|
|
208
208
|
*
|
|
209
209
|
* @param {string} url Authorization URL
|
|
210
210
|
* @param {object} data Request payload
|
|
@@ -219,7 +219,7 @@ class AcmeApi {
|
|
|
219
219
|
/**
|
|
220
220
|
* Complete challenge
|
|
221
221
|
*
|
|
222
|
-
* https://
|
|
222
|
+
* https://datatracker.ietf.org/doc/html/rfc8555#section-7.5.1
|
|
223
223
|
*
|
|
224
224
|
* @param {string} url Challenge URL
|
|
225
225
|
* @param {object} data Request payload
|
|
@@ -234,7 +234,7 @@ class AcmeApi {
|
|
|
234
234
|
/**
|
|
235
235
|
* Revoke certificate
|
|
236
236
|
*
|
|
237
|
-
* https://
|
|
237
|
+
* https://datatracker.ietf.org/doc/html/rfc8555#section-7.6
|
|
238
238
|
*
|
|
239
239
|
* @param {object} data Request payload
|
|
240
240
|
* @returns {Promise<object>} HTTP response
|
package/src/auto.js
CHANGED
|
@@ -84,6 +84,8 @@ module.exports = async function(client, userOpts) {
|
|
|
84
84
|
|
|
85
85
|
log('[auto] Resolving and satisfying authorization challenges');
|
|
86
86
|
|
|
87
|
+
const clearTasks = [];
|
|
88
|
+
|
|
87
89
|
const challengeFunc = async (authz) => {
|
|
88
90
|
const d = authz.identifier.value;
|
|
89
91
|
let challengeCompleted = false;
|
|
@@ -139,15 +141,17 @@ module.exports = async function(client, userOpts) {
|
|
|
139
141
|
throw e;
|
|
140
142
|
}
|
|
141
143
|
finally {
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
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
|
+
});
|
|
151
155
|
}
|
|
152
156
|
}
|
|
153
157
|
catch (e) {
|
|
@@ -182,7 +186,23 @@ module.exports = async function(client, userOpts) {
|
|
|
182
186
|
return promise;
|
|
183
187
|
}
|
|
184
188
|
|
|
185
|
-
|
|
189
|
+
|
|
190
|
+
try {
|
|
191
|
+
await runPromisesSerially(challengePromises);
|
|
192
|
+
}
|
|
193
|
+
finally {
|
|
194
|
+
await runPromisesSerially(clearTasks);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// try {
|
|
198
|
+
// await Promise.allSettled(challengePromises);
|
|
199
|
+
// }
|
|
200
|
+
// finally {
|
|
201
|
+
// log('清理challenge');
|
|
202
|
+
// await Promise.allSettled(clearTasks);
|
|
203
|
+
// }
|
|
204
|
+
|
|
205
|
+
|
|
186
206
|
log('challenge结束');
|
|
187
207
|
|
|
188
208
|
// log('[auto] Waiting for challenge valid status');
|
package/src/axios.js
CHANGED
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
const axios = require('axios');
|
|
6
|
-
const adapter = require('axios/lib/adapters/http');
|
|
7
6
|
const pkg = require('./../package.json');
|
|
8
7
|
|
|
9
8
|
|
|
@@ -19,10 +18,14 @@ instance.defaults.headers.common['User-Agent'] = `node-${pkg.name}/${pkg.version
|
|
|
19
18
|
/* Default ACME settings */
|
|
20
19
|
instance.defaults.acmeSettings = {
|
|
21
20
|
httpChallengePort: 80,
|
|
22
|
-
|
|
21
|
+
httpsChallengePort: 443,
|
|
22
|
+
tlsAlpnChallengePort: 443
|
|
23
23
|
};
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
// instance.defaults.proxy = {
|
|
26
|
+
// host: '192.168.34.139',
|
|
27
|
+
// port: 10811
|
|
28
|
+
// };
|
|
26
29
|
/**
|
|
27
30
|
* Explicitly set Node as default HTTP adapter
|
|
28
31
|
*
|
|
@@ -30,7 +33,7 @@ instance.defaults.acmeSettings = {
|
|
|
30
33
|
* https://stackoverflow.com/questions/42677387
|
|
31
34
|
*/
|
|
32
35
|
|
|
33
|
-
instance.defaults.adapter =
|
|
36
|
+
instance.defaults.adapter = 'http';
|
|
34
37
|
|
|
35
38
|
|
|
36
39
|
/**
|
package/src/client.js
CHANGED
|
@@ -154,7 +154,7 @@ class AcmeClient {
|
|
|
154
154
|
/**
|
|
155
155
|
* Create a new account
|
|
156
156
|
*
|
|
157
|
-
* https://
|
|
157
|
+
* https://datatracker.ietf.org/doc/html/rfc8555#section-7.3
|
|
158
158
|
*
|
|
159
159
|
* @param {object} [data] Request data
|
|
160
160
|
* @returns {Promise<object>} Account
|
|
@@ -200,7 +200,7 @@ class AcmeClient {
|
|
|
200
200
|
/**
|
|
201
201
|
* Update existing account
|
|
202
202
|
*
|
|
203
|
-
* https://
|
|
203
|
+
* https://datatracker.ietf.org/doc/html/rfc8555#section-7.3.2
|
|
204
204
|
*
|
|
205
205
|
* @param {object} [data] Request data
|
|
206
206
|
* @returns {Promise<object>} Account
|
|
@@ -240,7 +240,7 @@ class AcmeClient {
|
|
|
240
240
|
/**
|
|
241
241
|
* Update account private key
|
|
242
242
|
*
|
|
243
|
-
* https://
|
|
243
|
+
* https://datatracker.ietf.org/doc/html/rfc8555#section-7.3.5
|
|
244
244
|
*
|
|
245
245
|
* @param {buffer|string} newAccountKey New PEM encoded private key
|
|
246
246
|
* @param {object} [data] Additional request data
|
|
@@ -286,7 +286,7 @@ class AcmeClient {
|
|
|
286
286
|
/**
|
|
287
287
|
* Create a new order
|
|
288
288
|
*
|
|
289
|
-
* https://
|
|
289
|
+
* https://datatracker.ietf.org/doc/html/rfc8555#section-7.4
|
|
290
290
|
*
|
|
291
291
|
* @param {object} data Request data
|
|
292
292
|
* @returns {Promise<object>} Order
|
|
@@ -318,7 +318,7 @@ class AcmeClient {
|
|
|
318
318
|
/**
|
|
319
319
|
* Refresh order object from CA
|
|
320
320
|
*
|
|
321
|
-
* https://
|
|
321
|
+
* https://datatracker.ietf.org/doc/html/rfc8555#section-7.4
|
|
322
322
|
*
|
|
323
323
|
* @param {object} order Order object
|
|
324
324
|
* @returns {Promise<object>} Order
|
|
@@ -345,7 +345,7 @@ class AcmeClient {
|
|
|
345
345
|
/**
|
|
346
346
|
* Finalize order
|
|
347
347
|
*
|
|
348
|
-
* https://
|
|
348
|
+
* https://datatracker.ietf.org/doc/html/rfc8555#section-7.4
|
|
349
349
|
*
|
|
350
350
|
* @param {object} order Order object
|
|
351
351
|
* @param {buffer|string} csr PEM encoded Certificate Signing Request
|
|
@@ -380,7 +380,7 @@ class AcmeClient {
|
|
|
380
380
|
/**
|
|
381
381
|
* Get identifier authorizations from order
|
|
382
382
|
*
|
|
383
|
-
* https://
|
|
383
|
+
* https://datatracker.ietf.org/doc/html/rfc8555#section-7.5
|
|
384
384
|
*
|
|
385
385
|
* @param {object} order Order
|
|
386
386
|
* @returns {Promise<object[]>} Authorizations
|
|
@@ -410,7 +410,7 @@ class AcmeClient {
|
|
|
410
410
|
/**
|
|
411
411
|
* Deactivate identifier authorization
|
|
412
412
|
*
|
|
413
|
-
* https://
|
|
413
|
+
* https://datatracker.ietf.org/doc/html/rfc8555#section-7.5.2
|
|
414
414
|
*
|
|
415
415
|
* @param {object} authz Identifier authorization
|
|
416
416
|
* @returns {Promise<object>} Authorization
|
|
@@ -442,7 +442,7 @@ class AcmeClient {
|
|
|
442
442
|
/**
|
|
443
443
|
* Get key authorization for ACME challenge
|
|
444
444
|
*
|
|
445
|
-
* https://
|
|
445
|
+
* https://datatracker.ietf.org/doc/html/rfc8555#section-8.1
|
|
446
446
|
*
|
|
447
447
|
* @param {object} challenge Challenge object returned by API
|
|
448
448
|
* @returns {Promise<string>} Key authorization
|
|
@@ -462,22 +462,19 @@ class AcmeClient {
|
|
|
462
462
|
const thumbprint = keysum.digest('base64url');
|
|
463
463
|
const result = `${challenge.token}.${thumbprint}`;
|
|
464
464
|
|
|
465
|
-
|
|
466
|
-
* https://tools.ietf.org/html/rfc8555#section-8.3
|
|
467
|
-
*/
|
|
468
|
-
|
|
465
|
+
/* https://datatracker.ietf.org/doc/html/rfc8555#section-8.3 */
|
|
469
466
|
if (challenge.type === 'http-01') {
|
|
470
467
|
return result;
|
|
471
468
|
}
|
|
472
469
|
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
470
|
+
/* https://datatracker.ietf.org/doc/html/rfc8555#section-8.4 */
|
|
471
|
+
if (challenge.type === 'dns-01') {
|
|
472
|
+
return createHash('sha256').update(result).digest('base64url');
|
|
473
|
+
}
|
|
477
474
|
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
return
|
|
475
|
+
/* https://datatracker.ietf.org/doc/html/rfc8737 */
|
|
476
|
+
if (challenge.type === 'tls-alpn-01') {
|
|
477
|
+
return result;
|
|
481
478
|
}
|
|
482
479
|
|
|
483
480
|
throw new Error(`Unable to produce key authorization, unknown challenge type: ${challenge.type}`);
|
|
@@ -522,7 +519,7 @@ class AcmeClient {
|
|
|
522
519
|
/**
|
|
523
520
|
* Notify CA that challenge has been completed
|
|
524
521
|
*
|
|
525
|
-
* https://
|
|
522
|
+
* https://datatracker.ietf.org/doc/html/rfc8555#section-7.5.1
|
|
526
523
|
*
|
|
527
524
|
* @param {object} challenge Challenge object returned by API
|
|
528
525
|
* @returns {Promise<object>} Challenge
|
|
@@ -543,7 +540,7 @@ class AcmeClient {
|
|
|
543
540
|
/**
|
|
544
541
|
* Wait for ACME provider to verify status on a order, authorization or challenge
|
|
545
542
|
*
|
|
546
|
-
* https://
|
|
543
|
+
* https://datatracker.ietf.org/doc/html/rfc8555#section-7.5.1
|
|
547
544
|
*
|
|
548
545
|
* @param {object} item An order, authorization or challenge object
|
|
549
546
|
* @returns {Promise<object>} Valid order, authorization or challenge
|
|
@@ -554,7 +551,7 @@ class AcmeClient {
|
|
|
554
551
|
* await client.waitForValidStatus(challenge);
|
|
555
552
|
* ```
|
|
556
553
|
*
|
|
557
|
-
* @example Wait for valid
|
|
554
|
+
* @example Wait for valid authorization status
|
|
558
555
|
* ```js
|
|
559
556
|
* const authz = { ... };
|
|
560
557
|
* await client.waitForValidStatus(authz);
|
|
@@ -600,7 +597,7 @@ class AcmeClient {
|
|
|
600
597
|
/**
|
|
601
598
|
* Get certificate from ACME order
|
|
602
599
|
*
|
|
603
|
-
* https://
|
|
600
|
+
* https://datatracker.ietf.org/doc/html/rfc8555#section-7.4.2
|
|
604
601
|
*
|
|
605
602
|
* @param {object} order Order object
|
|
606
603
|
* @param {string} [preferredChain] Indicate which certificate chain is preferred if a CA offers multiple, by exact issuer common name, default: `null`
|
|
@@ -647,7 +644,7 @@ class AcmeClient {
|
|
|
647
644
|
/**
|
|
648
645
|
* Revoke certificate
|
|
649
646
|
*
|
|
650
|
-
* https://
|
|
647
|
+
* https://datatracker.ietf.org/doc/html/rfc8555#section-7.6
|
|
651
648
|
*
|
|
652
649
|
* @param {buffer|string} cert PEM encoded certificate
|
|
653
650
|
* @param {object} [data] Additional request data
|
package/src/crypto/forge.js
CHANGED
|
@@ -281,7 +281,7 @@ exports.readCertificateInfo = async function(cert) {
|
|
|
281
281
|
|
|
282
282
|
/**
|
|
283
283
|
* Determine ASN.1 type for CSR subject short name
|
|
284
|
-
* Note: https://
|
|
284
|
+
* Note: https://datatracker.ietf.org/doc/html/rfc5280
|
|
285
285
|
*
|
|
286
286
|
* @private
|
|
287
287
|
* @param {string} shortName CSR subject short name
|
|
@@ -343,7 +343,7 @@ function formatCsrAltNames(altNames) {
|
|
|
343
343
|
* @param {object} data
|
|
344
344
|
* @param {number} [data.keySize] Size of newly created private key, default: `2048`
|
|
345
345
|
* @param {string} [data.commonName]
|
|
346
|
-
* @param {
|
|
346
|
+
* @param {string[]} [data.altNames] default: `[]`
|
|
347
347
|
* @param {string} [data.country]
|
|
348
348
|
* @param {string} [data.state]
|
|
349
349
|
* @param {string} [data.locality]
|