@certd/acme-client 1.39.11 → 1.39.13
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/dist/api.d.ts +151 -0
- package/{src → dist}/api.js +2 -38
- package/dist/auto.d.ts +9 -0
- package/{src → dist}/auto.js +45 -79
- package/dist/axios.d.ts +8 -0
- package/{src → dist}/axios.js +3 -31
- package/dist/client.d.ts +396 -0
- package/{src → dist}/client.js +16 -108
- package/dist/crypto/forge.d.ts +174 -0
- package/{src → dist}/crypto/forge.js +7 -63
- package/dist/crypto/index.d.ts +215 -0
- package/{src → dist}/crypto/index.js +2 -87
- package/dist/error.d.ts +3 -0
- package/{src → dist}/error.js +1 -3
- package/dist/http.d.ts +135 -0
- package/{src → dist}/http.js +3 -65
- package/dist/index.d.ts +58 -0
- package/dist/index.js +90 -0
- package/dist/logger.d.ts +15 -0
- package/{src → dist}/logger.js +4 -9
- package/dist/rfc8555.d.ts +106 -0
- package/dist/rfc8555.js +25 -0
- package/dist/types.d.ts +117 -0
- package/dist/types.js +1 -0
- package/dist/util.d.ts +85 -0
- package/{src → dist}/util.js +11 -76
- package/dist/verify.d.ts +14 -0
- package/dist/verify.js +214 -0
- package/dist/wait.d.ts +1 -0
- package/{src → dist}/wait.js +1 -0
- package/package.json +18 -12
- package/types/index.d.ts +15 -4
- package/types/index.test-d.ts +10 -3
- package/src/index.js +0 -106
- package/src/verify.js +0 -231
package/dist/api.d.ts
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AcmeApi
|
|
3
|
+
*
|
|
4
|
+
* @class
|
|
5
|
+
* @param {HttpClient} httpClient
|
|
6
|
+
*/
|
|
7
|
+
declare class AcmeApi {
|
|
8
|
+
constructor(httpClient: any, accountUrl?: any);
|
|
9
|
+
getLocationFromHeader(resp: any): any;
|
|
10
|
+
/**
|
|
11
|
+
* Get account URL
|
|
12
|
+
*
|
|
13
|
+
* @private
|
|
14
|
+
* @returns {string} Account URL
|
|
15
|
+
*/
|
|
16
|
+
getAccountUrl(): any;
|
|
17
|
+
/**
|
|
18
|
+
* ACME API request
|
|
19
|
+
*
|
|
20
|
+
* @private
|
|
21
|
+
* @param {string} url Request URL
|
|
22
|
+
* @param {object} [payload] Request payload, default: `null`
|
|
23
|
+
* @param {number[]} [validStatusCodes] Array of valid HTTP response status codes, default: `[]`
|
|
24
|
+
* @param {object} [opts]
|
|
25
|
+
* @param {boolean} [opts.includeJwsKid] Include KID instead of JWK in JWS header, default: `true`
|
|
26
|
+
* @param {boolean} [opts.includeExternalAccountBinding] Include EAB in request, default: `false`
|
|
27
|
+
* @returns {Promise<object>} HTTP response
|
|
28
|
+
*/
|
|
29
|
+
apiRequest(url: any, payload?: any, validStatusCodes?: any[], { includeJwsKid, includeExternalAccountBinding }?: {
|
|
30
|
+
includeJwsKid?: boolean;
|
|
31
|
+
includeExternalAccountBinding?: boolean;
|
|
32
|
+
}): Promise<any>;
|
|
33
|
+
/**
|
|
34
|
+
* ACME API request by resource name helper
|
|
35
|
+
*
|
|
36
|
+
* @private
|
|
37
|
+
* @param {string} resource Request resource name
|
|
38
|
+
* @param {object} [payload] Request payload, default: `null`
|
|
39
|
+
* @param {number[]} [validStatusCodes] Array of valid HTTP response status codes, default: `[]`
|
|
40
|
+
* @param {object} [opts]
|
|
41
|
+
* @param {boolean} [opts.includeJwsKid] Include KID instead of JWK in JWS header, default: `true`
|
|
42
|
+
* @param {boolean} [opts.includeExternalAccountBinding] Include EAB in request, default: `false`
|
|
43
|
+
* @returns {Promise<object>} HTTP response
|
|
44
|
+
*/
|
|
45
|
+
apiResourceRequest(resource: any, payload?: any, validStatusCodes?: any[], { includeJwsKid, includeExternalAccountBinding }?: {
|
|
46
|
+
includeJwsKid?: boolean;
|
|
47
|
+
includeExternalAccountBinding?: boolean;
|
|
48
|
+
}): Promise<any>;
|
|
49
|
+
/**
|
|
50
|
+
* Get Terms of Service URL if available
|
|
51
|
+
*
|
|
52
|
+
* https://datatracker.ietf.org/doc/html/rfc8555#section-7.1.1
|
|
53
|
+
*
|
|
54
|
+
* @returns {Promise<string|null>} ToS URL
|
|
55
|
+
*/
|
|
56
|
+
getTermsOfServiceUrl(): Promise<any>;
|
|
57
|
+
/**
|
|
58
|
+
* Create new account
|
|
59
|
+
*
|
|
60
|
+
* https://datatracker.ietf.org/doc/html/rfc8555#section-7.3
|
|
61
|
+
*
|
|
62
|
+
* @param {object} data Request payload
|
|
63
|
+
* @returns {Promise<object>} HTTP response
|
|
64
|
+
*/
|
|
65
|
+
createAccount(data: any): Promise<any>;
|
|
66
|
+
/**
|
|
67
|
+
* Update account
|
|
68
|
+
*
|
|
69
|
+
* https://datatracker.ietf.org/doc/html/rfc8555#section-7.3.2
|
|
70
|
+
*
|
|
71
|
+
* @param {object} data Request payload
|
|
72
|
+
* @returns {Promise<object>} HTTP response
|
|
73
|
+
*/
|
|
74
|
+
updateAccount(data: any): Promise<any>;
|
|
75
|
+
/**
|
|
76
|
+
* Update account key
|
|
77
|
+
*
|
|
78
|
+
* https://datatracker.ietf.org/doc/html/rfc8555#section-7.3.5
|
|
79
|
+
*
|
|
80
|
+
* @param {object} data Request payload
|
|
81
|
+
* @returns {Promise<object>} HTTP response
|
|
82
|
+
*/
|
|
83
|
+
updateAccountKey(data: any): Promise<any>;
|
|
84
|
+
/**
|
|
85
|
+
* Create new order
|
|
86
|
+
*
|
|
87
|
+
* https://datatracker.ietf.org/doc/html/rfc8555#section-7.4
|
|
88
|
+
*
|
|
89
|
+
* @param {object} data Request payload
|
|
90
|
+
* @returns {Promise<object>} HTTP response
|
|
91
|
+
*/
|
|
92
|
+
createOrder(data: any): Promise<any>;
|
|
93
|
+
/**
|
|
94
|
+
* Get order
|
|
95
|
+
*
|
|
96
|
+
* https://datatracker.ietf.org/doc/html/rfc8555#section-7.4
|
|
97
|
+
*
|
|
98
|
+
* @param {string} url Order URL
|
|
99
|
+
* @returns {Promise<object>} HTTP response
|
|
100
|
+
*/
|
|
101
|
+
getOrder(url: any): Promise<any>;
|
|
102
|
+
/**
|
|
103
|
+
* Finalize order
|
|
104
|
+
*
|
|
105
|
+
* https://datatracker.ietf.org/doc/html/rfc8555#section-7.4
|
|
106
|
+
*
|
|
107
|
+
* @param {string} url Finalization URL
|
|
108
|
+
* @param {object} data Request payload
|
|
109
|
+
* @returns {Promise<object>} HTTP response
|
|
110
|
+
*/
|
|
111
|
+
finalizeOrder(url: any, data: any): Promise<any>;
|
|
112
|
+
/**
|
|
113
|
+
* Get identifier authorization
|
|
114
|
+
*
|
|
115
|
+
* https://datatracker.ietf.org/doc/html/rfc8555#section-7.5
|
|
116
|
+
*
|
|
117
|
+
* @param {string} url Authorization URL
|
|
118
|
+
* @returns {Promise<object>} HTTP response
|
|
119
|
+
*/
|
|
120
|
+
getAuthorization(url: any): Promise<any>;
|
|
121
|
+
/**
|
|
122
|
+
* Update identifier authorization
|
|
123
|
+
*
|
|
124
|
+
* https://datatracker.ietf.org/doc/html/rfc8555#section-7.5.2
|
|
125
|
+
*
|
|
126
|
+
* @param {string} url Authorization URL
|
|
127
|
+
* @param {object} data Request payload
|
|
128
|
+
* @returns {Promise<object>} HTTP response
|
|
129
|
+
*/
|
|
130
|
+
updateAuthorization(url: any, data: any): Promise<any>;
|
|
131
|
+
/**
|
|
132
|
+
* Complete challenge
|
|
133
|
+
*
|
|
134
|
+
* https://datatracker.ietf.org/doc/html/rfc8555#section-7.5.1
|
|
135
|
+
*
|
|
136
|
+
* @param {string} url Challenge URL
|
|
137
|
+
* @param {object} data Request payload
|
|
138
|
+
* @returns {Promise<object>} HTTP response
|
|
139
|
+
*/
|
|
140
|
+
completeChallenge(url: any, data: any): Promise<any>;
|
|
141
|
+
/**
|
|
142
|
+
* Revoke certificate
|
|
143
|
+
*
|
|
144
|
+
* https://datatracker.ietf.org/doc/html/rfc8555#section-7.6
|
|
145
|
+
*
|
|
146
|
+
* @param {object} data Request payload
|
|
147
|
+
* @returns {Promise<object>} HTTP response
|
|
148
|
+
*/
|
|
149
|
+
revokeCert(data: any): Promise<any>;
|
|
150
|
+
}
|
|
151
|
+
export default AcmeApi;
|
package/{src → dist}/api.js
RENAMED
|
@@ -1,21 +1,19 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
1
2
|
/**
|
|
2
3
|
* ACME API client
|
|
3
4
|
*/
|
|
4
|
-
import
|
|
5
|
-
|
|
5
|
+
import * as util from './util.js';
|
|
6
6
|
/**
|
|
7
7
|
* AcmeApi
|
|
8
8
|
*
|
|
9
9
|
* @class
|
|
10
10
|
* @param {HttpClient} httpClient
|
|
11
11
|
*/
|
|
12
|
-
|
|
13
12
|
class AcmeApi {
|
|
14
13
|
constructor(httpClient, accountUrl = null) {
|
|
15
14
|
this.http = httpClient;
|
|
16
15
|
this.accountUrl = accountUrl;
|
|
17
16
|
}
|
|
18
|
-
|
|
19
17
|
getLocationFromHeader(resp) {
|
|
20
18
|
let locationUrl = resp.headers.location;
|
|
21
19
|
const mapping = this.http.urlMapping;
|
|
@@ -30,22 +28,18 @@ class AcmeApi {
|
|
|
30
28
|
}
|
|
31
29
|
return locationUrl;
|
|
32
30
|
}
|
|
33
|
-
|
|
34
31
|
/**
|
|
35
32
|
* Get account URL
|
|
36
33
|
*
|
|
37
34
|
* @private
|
|
38
35
|
* @returns {string} Account URL
|
|
39
36
|
*/
|
|
40
|
-
|
|
41
37
|
getAccountUrl() {
|
|
42
38
|
if (!this.accountUrl) {
|
|
43
39
|
throw new Error('No account URL found, register account first');
|
|
44
40
|
}
|
|
45
|
-
|
|
46
41
|
return this.accountUrl;
|
|
47
42
|
}
|
|
48
|
-
|
|
49
43
|
/**
|
|
50
44
|
* ACME API request
|
|
51
45
|
*
|
|
@@ -58,18 +52,14 @@ class AcmeApi {
|
|
|
58
52
|
* @param {boolean} [opts.includeExternalAccountBinding] Include EAB in request, default: `false`
|
|
59
53
|
* @returns {Promise<object>} HTTP response
|
|
60
54
|
*/
|
|
61
|
-
|
|
62
55
|
async apiRequest(url, payload = null, validStatusCodes = [], { includeJwsKid = true, includeExternalAccountBinding = false } = {}) {
|
|
63
56
|
const kid = includeJwsKid ? this.getAccountUrl() : null;
|
|
64
57
|
const resp = await this.http.signedRequest(url, payload, { kid, includeExternalAccountBinding });
|
|
65
|
-
|
|
66
58
|
if (validStatusCodes.length && (validStatusCodes.indexOf(resp.status) === -1)) {
|
|
67
59
|
throw new Error(util.formatResponseError(resp));
|
|
68
60
|
}
|
|
69
|
-
|
|
70
61
|
return resp;
|
|
71
62
|
}
|
|
72
|
-
|
|
73
63
|
/**
|
|
74
64
|
* ACME API request by resource name helper
|
|
75
65
|
*
|
|
@@ -82,12 +72,10 @@ class AcmeApi {
|
|
|
82
72
|
* @param {boolean} [opts.includeExternalAccountBinding] Include EAB in request, default: `false`
|
|
83
73
|
* @returns {Promise<object>} HTTP response
|
|
84
74
|
*/
|
|
85
|
-
|
|
86
75
|
async apiResourceRequest(resource, payload = null, validStatusCodes = [], { includeJwsKid = true, includeExternalAccountBinding = false } = {}) {
|
|
87
76
|
const resourceUrl = await this.http.getResourceUrl(resource);
|
|
88
77
|
return this.apiRequest(resourceUrl, payload, validStatusCodes, { includeJwsKid, includeExternalAccountBinding });
|
|
89
78
|
}
|
|
90
|
-
|
|
91
79
|
/**
|
|
92
80
|
* Get Terms of Service URL if available
|
|
93
81
|
*
|
|
@@ -95,11 +83,9 @@ class AcmeApi {
|
|
|
95
83
|
*
|
|
96
84
|
* @returns {Promise<string|null>} ToS URL
|
|
97
85
|
*/
|
|
98
|
-
|
|
99
86
|
async getTermsOfServiceUrl() {
|
|
100
87
|
return this.http.getMetaField('termsOfService');
|
|
101
88
|
}
|
|
102
|
-
|
|
103
89
|
/**
|
|
104
90
|
* Create new account
|
|
105
91
|
*
|
|
@@ -108,21 +94,17 @@ class AcmeApi {
|
|
|
108
94
|
* @param {object} data Request payload
|
|
109
95
|
* @returns {Promise<object>} HTTP response
|
|
110
96
|
*/
|
|
111
|
-
|
|
112
97
|
async createAccount(data) {
|
|
113
98
|
const resp = await this.apiResourceRequest('newAccount', data, [200, 201], {
|
|
114
99
|
includeJwsKid: false,
|
|
115
100
|
includeExternalAccountBinding: (data.onlyReturnExisting !== true),
|
|
116
101
|
});
|
|
117
|
-
|
|
118
102
|
/* Set account URL */
|
|
119
103
|
if (resp.headers.location) {
|
|
120
104
|
this.accountUrl = this.getLocationFromHeader(resp);
|
|
121
105
|
}
|
|
122
|
-
|
|
123
106
|
return resp;
|
|
124
107
|
}
|
|
125
|
-
|
|
126
108
|
/**
|
|
127
109
|
* Update account
|
|
128
110
|
*
|
|
@@ -131,11 +113,9 @@ class AcmeApi {
|
|
|
131
113
|
* @param {object} data Request payload
|
|
132
114
|
* @returns {Promise<object>} HTTP response
|
|
133
115
|
*/
|
|
134
|
-
|
|
135
116
|
updateAccount(data) {
|
|
136
117
|
return this.apiRequest(this.getAccountUrl(), data, [200, 202]);
|
|
137
118
|
}
|
|
138
|
-
|
|
139
119
|
/**
|
|
140
120
|
* Update account key
|
|
141
121
|
*
|
|
@@ -144,11 +124,9 @@ class AcmeApi {
|
|
|
144
124
|
* @param {object} data Request payload
|
|
145
125
|
* @returns {Promise<object>} HTTP response
|
|
146
126
|
*/
|
|
147
|
-
|
|
148
127
|
updateAccountKey(data) {
|
|
149
128
|
return this.apiResourceRequest('keyChange', data, [200]);
|
|
150
129
|
}
|
|
151
|
-
|
|
152
130
|
/**
|
|
153
131
|
* Create new order
|
|
154
132
|
*
|
|
@@ -157,11 +135,9 @@ class AcmeApi {
|
|
|
157
135
|
* @param {object} data Request payload
|
|
158
136
|
* @returns {Promise<object>} HTTP response
|
|
159
137
|
*/
|
|
160
|
-
|
|
161
138
|
createOrder(data) {
|
|
162
139
|
return this.apiResourceRequest('newOrder', data, [201]);
|
|
163
140
|
}
|
|
164
|
-
|
|
165
141
|
/**
|
|
166
142
|
* Get order
|
|
167
143
|
*
|
|
@@ -170,11 +146,9 @@ class AcmeApi {
|
|
|
170
146
|
* @param {string} url Order URL
|
|
171
147
|
* @returns {Promise<object>} HTTP response
|
|
172
148
|
*/
|
|
173
|
-
|
|
174
149
|
getOrder(url) {
|
|
175
150
|
return this.apiRequest(url, null, [200]);
|
|
176
151
|
}
|
|
177
|
-
|
|
178
152
|
/**
|
|
179
153
|
* Finalize order
|
|
180
154
|
*
|
|
@@ -184,11 +158,9 @@ class AcmeApi {
|
|
|
184
158
|
* @param {object} data Request payload
|
|
185
159
|
* @returns {Promise<object>} HTTP response
|
|
186
160
|
*/
|
|
187
|
-
|
|
188
161
|
finalizeOrder(url, data) {
|
|
189
162
|
return this.apiRequest(url, data, [200]);
|
|
190
163
|
}
|
|
191
|
-
|
|
192
164
|
/**
|
|
193
165
|
* Get identifier authorization
|
|
194
166
|
*
|
|
@@ -197,11 +169,9 @@ class AcmeApi {
|
|
|
197
169
|
* @param {string} url Authorization URL
|
|
198
170
|
* @returns {Promise<object>} HTTP response
|
|
199
171
|
*/
|
|
200
|
-
|
|
201
172
|
getAuthorization(url) {
|
|
202
173
|
return this.apiRequest(url, null, [200]);
|
|
203
174
|
}
|
|
204
|
-
|
|
205
175
|
/**
|
|
206
176
|
* Update identifier authorization
|
|
207
177
|
*
|
|
@@ -211,11 +181,9 @@ class AcmeApi {
|
|
|
211
181
|
* @param {object} data Request payload
|
|
212
182
|
* @returns {Promise<object>} HTTP response
|
|
213
183
|
*/
|
|
214
|
-
|
|
215
184
|
updateAuthorization(url, data) {
|
|
216
185
|
return this.apiRequest(url, data, [200]);
|
|
217
186
|
}
|
|
218
|
-
|
|
219
187
|
/**
|
|
220
188
|
* Complete challenge
|
|
221
189
|
*
|
|
@@ -225,11 +193,9 @@ class AcmeApi {
|
|
|
225
193
|
* @param {object} data Request payload
|
|
226
194
|
* @returns {Promise<object>} HTTP response
|
|
227
195
|
*/
|
|
228
|
-
|
|
229
196
|
completeChallenge(url, data) {
|
|
230
197
|
return this.apiRequest(url, data, [200]);
|
|
231
198
|
}
|
|
232
|
-
|
|
233
199
|
/**
|
|
234
200
|
* Revoke certificate
|
|
235
201
|
*
|
|
@@ -238,11 +204,9 @@ class AcmeApi {
|
|
|
238
204
|
* @param {object} data Request payload
|
|
239
205
|
* @returns {Promise<object>} HTTP response
|
|
240
206
|
*/
|
|
241
|
-
|
|
242
207
|
revokeCert(data) {
|
|
243
208
|
return this.apiResourceRequest('revokeCert', data, [200]);
|
|
244
209
|
}
|
|
245
210
|
}
|
|
246
|
-
|
|
247
211
|
/* Export API */
|
|
248
212
|
export default AcmeApi;
|
package/dist/auto.d.ts
ADDED
package/{src → dist}/auto.js
RENAMED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
1
2
|
/**
|
|
2
3
|
* ACME auto helper
|
|
3
4
|
*/
|
|
@@ -5,10 +6,6 @@ import { readCsrDomains } from "./crypto/index.js";
|
|
|
5
6
|
import { wait } from "./wait.js";
|
|
6
7
|
import { CancelError } from "./error.js";
|
|
7
8
|
import { domainUtils } from '@certd/basic';
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
9
|
const defaultOpts = {
|
|
13
10
|
csr: null,
|
|
14
11
|
email: null,
|
|
@@ -24,7 +21,6 @@ const defaultOpts = {
|
|
|
24
21
|
},
|
|
25
22
|
waitDnsDiffuseTime: 30,
|
|
26
23
|
};
|
|
27
|
-
|
|
28
24
|
/**
|
|
29
25
|
* ACME client auto mode
|
|
30
26
|
*
|
|
@@ -32,161 +28,139 @@ const defaultOpts = {
|
|
|
32
28
|
* @param {object} userOpts Options
|
|
33
29
|
* @returns {Promise<buffer>} Certificate
|
|
34
30
|
*/
|
|
35
|
-
|
|
36
31
|
export default async (client, userOpts) => {
|
|
37
32
|
const opts = { ...defaultOpts, ...userOpts };
|
|
38
33
|
const accountPayload = { termsOfServiceAgreed: opts.termsOfServiceAgreed };
|
|
39
|
-
|
|
40
34
|
if (!Buffer.isBuffer(opts.csr)) {
|
|
41
35
|
opts.csr = Buffer.from(opts.csr);
|
|
42
36
|
}
|
|
43
|
-
|
|
44
37
|
if (opts.email) {
|
|
45
38
|
accountPayload.contact = [`mailto:${opts.email}`];
|
|
46
39
|
}
|
|
47
40
|
if (opts.externalAccountBinding) {
|
|
48
41
|
accountPayload.externalAccountBinding = opts.externalAccountBinding;
|
|
49
42
|
}
|
|
50
|
-
|
|
51
|
-
const log = (...args)=>{
|
|
43
|
+
const log = (...args) => {
|
|
52
44
|
return client.logger.info(...args);
|
|
53
|
-
}
|
|
45
|
+
};
|
|
54
46
|
/**
|
|
55
47
|
* Register account
|
|
56
48
|
*/
|
|
57
|
-
|
|
58
49
|
log("[auto] Checking account");
|
|
59
|
-
|
|
60
50
|
try {
|
|
61
51
|
client.getAccountUrl();
|
|
62
52
|
log("[auto] Account URL already exists, skipping account registration( 证书申请账户已存在,跳过注册 )");
|
|
63
|
-
}
|
|
53
|
+
}
|
|
54
|
+
catch (e) {
|
|
64
55
|
log("[auto] Registering account (注册证书申请账户)");
|
|
65
56
|
await client.createAccount(accountPayload);
|
|
66
57
|
}
|
|
67
|
-
|
|
68
58
|
/**
|
|
69
59
|
* Parse domains from CSR
|
|
70
60
|
*/
|
|
71
|
-
|
|
72
61
|
log("[auto] Parsing domains from Certificate Signing Request");
|
|
73
62
|
const { commonName, altNames } = readCsrDomains(opts.csr);
|
|
74
63
|
const uniqueDomains = Array.from(new Set([commonName].concat(altNames).filter((d) => d)));
|
|
75
|
-
|
|
76
64
|
log(`[auto] Resolved ${uniqueDomains.length} unique domains from parsing the Certificate Signing Request`);
|
|
77
|
-
|
|
78
65
|
/**
|
|
79
66
|
* Place order
|
|
80
67
|
*/
|
|
81
|
-
|
|
82
68
|
log("[auto] Placing new certificate order with ACME provider");
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
if (opts.profile && client.sslProvider.startsWith("letsencrypt") ){
|
|
69
|
+
let hasIp = false;
|
|
70
|
+
const orderPayload = { identifiers: uniqueDomains.map((d) => {
|
|
71
|
+
// 判断是否为IP(v4或v6),否则按域名处理
|
|
72
|
+
const type = domainUtils.isIp(d) ? 'ip' : 'dns';
|
|
73
|
+
if (type === 'ip') {
|
|
74
|
+
hasIp = true;
|
|
75
|
+
}
|
|
76
|
+
return { type, value: d };
|
|
77
|
+
}) };
|
|
78
|
+
if (opts.profile && client.sslProvider.startsWith("letsencrypt")) {
|
|
94
79
|
orderPayload.profile = opts.profile;
|
|
95
|
-
if(hasIp){
|
|
96
|
-
orderPayload.profile = "shortlived"
|
|
80
|
+
if (hasIp) {
|
|
81
|
+
orderPayload.profile = "shortlived";
|
|
97
82
|
}
|
|
98
83
|
}
|
|
99
84
|
const order = await client.createOrder(orderPayload);
|
|
100
85
|
const authorizations = await client.getAuthorizations(order);
|
|
101
|
-
|
|
102
86
|
log(`[auto] Placed certificate order successfully, received ${authorizations.length} identity authorizations`);
|
|
103
|
-
|
|
104
87
|
/**
|
|
105
88
|
* Resolve and satisfy challenges
|
|
106
89
|
*/
|
|
107
|
-
|
|
108
90
|
log("[auto] Resolving and satisfying authorization challenges");
|
|
109
|
-
|
|
110
91
|
const clearTasks = [];
|
|
111
92
|
const localVerifyTasks = [];
|
|
112
93
|
const completeChallengeTasks = [];
|
|
113
|
-
|
|
114
94
|
const challengeFunc = async (authz) => {
|
|
115
95
|
const d = authz.identifier.value;
|
|
116
96
|
let challengeCompleted = false;
|
|
117
|
-
|
|
118
97
|
/* Skip authz that already has valid status */
|
|
119
98
|
if (authz.status === "valid") {
|
|
120
99
|
log(`[auto] [${d}] Authorization already has valid status, no need to complete challenges`);
|
|
121
100
|
return;
|
|
122
101
|
}
|
|
123
|
-
|
|
124
102
|
const keyAuthorizationGetter = async (challenge) => {
|
|
125
103
|
return await client.getChallengeKeyAuthorization(challenge);
|
|
126
104
|
};
|
|
127
|
-
|
|
128
105
|
async function deactivateAuth(e) {
|
|
129
106
|
log(`[auto] [${d}] Unable to complete challenge: ${e.message}`);
|
|
130
107
|
try {
|
|
131
108
|
log(`[auto] [${d}] Deactivating failed authorization`);
|
|
132
109
|
await client.deactivateAuthorization(authz);
|
|
133
|
-
}
|
|
110
|
+
}
|
|
111
|
+
catch (f) {
|
|
134
112
|
/* Suppress deactivateAuthorization() errors */
|
|
135
113
|
log(`[auto] [${d}] Authorization deactivation threw error: ${f.message}`);
|
|
136
114
|
}
|
|
137
115
|
}
|
|
138
|
-
|
|
139
116
|
log(`[auto] [${d}] Trigger challengeCreateFn()`);
|
|
140
117
|
try {
|
|
141
|
-
const { recordReq, recordRes, dnsProvider, challenge, keyAuthorization
|
|
118
|
+
const { recordReq, recordRes, dnsProvider, challenge, keyAuthorization, httpUploader } = await opts.challengeCreateFn(authz, keyAuthorizationGetter);
|
|
142
119
|
clearTasks.push(async () => {
|
|
143
120
|
/* Trigger challengeRemoveFn(), suppress errors */
|
|
144
121
|
log(`[auto] [${d}] Trigger challengeRemoveFn()`);
|
|
145
122
|
try {
|
|
146
|
-
await opts.challengeRemoveFn(authz, challenge, keyAuthorization, recordReq, recordRes, dnsProvider,httpUploader);
|
|
147
|
-
}
|
|
123
|
+
await opts.challengeRemoveFn(authz, challenge, keyAuthorization, recordReq, recordRes, dnsProvider, httpUploader);
|
|
124
|
+
}
|
|
125
|
+
catch (e) {
|
|
148
126
|
log(`[auto] [${d}] challengeRemoveFn threw error: ${e.message}`);
|
|
149
127
|
}
|
|
150
128
|
});
|
|
151
|
-
|
|
152
129
|
localVerifyTasks.push(async () => {
|
|
153
130
|
/* Challenge verification */
|
|
154
131
|
log(`[auto] [${d}] 开始本地验证, type = ${challenge.type}`);
|
|
155
132
|
try {
|
|
156
133
|
await client.verifyChallenge(authz, challenge);
|
|
157
|
-
}
|
|
134
|
+
}
|
|
135
|
+
catch (e) {
|
|
158
136
|
log(`[auto] [${d}] 本地验证失败,尝试请求ACME提供商获取状态: ${e.message}`);
|
|
159
137
|
}
|
|
160
138
|
});
|
|
161
|
-
|
|
162
139
|
completeChallengeTasks.push(async () => {
|
|
163
140
|
/* Complete challenge and wait for valid status */
|
|
164
141
|
log(`[auto] [${d}] 请求ACME提供商完成验证`);
|
|
165
|
-
try{
|
|
142
|
+
try {
|
|
166
143
|
await client.completeChallenge(challenge);
|
|
167
|
-
}
|
|
144
|
+
}
|
|
145
|
+
catch (e) {
|
|
168
146
|
await deactivateAuth(e);
|
|
169
147
|
throw e;
|
|
170
148
|
}
|
|
171
149
|
challengeCompleted = true;
|
|
172
150
|
log(`[auto] [${d}] 等待返回valid状态`);
|
|
173
|
-
await client.waitForValidStatus(challenge,d);
|
|
151
|
+
await client.waitForValidStatus(challenge, d);
|
|
174
152
|
});
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
} catch (e) {
|
|
153
|
+
}
|
|
154
|
+
catch (e) {
|
|
178
155
|
log(`[auto] [${d}] challengeCreateFn threw error: ${e.message || e}`);
|
|
179
156
|
await deactivateAuth(e);
|
|
180
157
|
throw e;
|
|
181
158
|
}
|
|
182
|
-
|
|
183
159
|
};
|
|
184
160
|
const domainSets = [];
|
|
185
|
-
|
|
186
161
|
authorizations.forEach((authz) => {
|
|
187
162
|
const d = authz.identifier.value;
|
|
188
163
|
log(`authorization:domain = ${d}, value = ${JSON.stringify(authz)}`);
|
|
189
|
-
|
|
190
164
|
if (authz.status === "valid") {
|
|
191
165
|
log(`[auto] [${d}] Authorization already has valid status, no need to complete challenges`);
|
|
192
166
|
return;
|
|
@@ -206,9 +180,7 @@ export default async (client, userOpts) => {
|
|
|
206
180
|
domainSets.push(group);
|
|
207
181
|
}
|
|
208
182
|
});
|
|
209
|
-
|
|
210
183
|
// log(`domainSets:${JSON.stringify(domainSets)}`);
|
|
211
|
-
|
|
212
184
|
const allChallengePromises = [];
|
|
213
185
|
// eslint-disable-next-line no-restricted-syntax
|
|
214
186
|
const challengePromises = [];
|
|
@@ -223,9 +195,7 @@ export default async (client, userOpts) => {
|
|
|
223
195
|
});
|
|
224
196
|
}
|
|
225
197
|
}
|
|
226
|
-
|
|
227
198
|
log(`[auto] challengeGroups:${allChallengePromises.length}`);
|
|
228
|
-
|
|
229
199
|
async function runAllPromise(tasks) {
|
|
230
200
|
let promise = Promise.resolve();
|
|
231
201
|
tasks.forEach((task) => {
|
|
@@ -233,22 +203,20 @@ export default async (client, userOpts) => {
|
|
|
233
203
|
});
|
|
234
204
|
return promise;
|
|
235
205
|
}
|
|
236
|
-
|
|
237
206
|
async function runPromisePa(tasks, waitTime = 8000) {
|
|
238
207
|
const results = [];
|
|
239
|
-
let j = 0
|
|
208
|
+
let j = 0;
|
|
240
209
|
// eslint-disable-next-line no-await-in-loop,no-restricted-syntax
|
|
241
210
|
for (const task of tasks) {
|
|
242
|
-
j
|
|
211
|
+
j++;
|
|
243
212
|
log(`开始第${j}个任务`);
|
|
244
213
|
results.push(task());
|
|
245
214
|
// eslint-disable-next-line no-await-in-loop
|
|
246
|
-
log(`wait ${Math.floor(waitTime/1000)}s`)
|
|
215
|
+
log(`wait ${Math.floor(waitTime / 1000)}s`);
|
|
247
216
|
await wait(waitTime);
|
|
248
217
|
}
|
|
249
218
|
return Promise.all(results);
|
|
250
219
|
}
|
|
251
|
-
|
|
252
220
|
log(`开始challenge,共${allChallengePromises.length}组`);
|
|
253
221
|
let i = 0;
|
|
254
222
|
// eslint-disable-next-line no-restricted-syntax
|
|
@@ -258,7 +226,6 @@ export default async (client, userOpts) => {
|
|
|
258
226
|
if (opts.signal && opts.signal.aborted) {
|
|
259
227
|
throw new CancelError("用户取消");
|
|
260
228
|
}
|
|
261
|
-
|
|
262
229
|
const waitDnsDiffuseTime = opts.waitDnsDiffuseTime || 30;
|
|
263
230
|
try {
|
|
264
231
|
// eslint-disable-next-line no-await-in-loop
|
|
@@ -266,41 +233,40 @@ export default async (client, userOpts) => {
|
|
|
266
233
|
if (opts.skipChallengeVerification === true) {
|
|
267
234
|
log(`跳过本地验证(skipChallengeVerification=true),等待 60s`);
|
|
268
235
|
await wait(60 * 1000);
|
|
269
|
-
}
|
|
270
|
-
|
|
236
|
+
}
|
|
237
|
+
else {
|
|
238
|
+
log("开始本地校验");
|
|
271
239
|
await runPromisePa(localVerifyTasks, 1000);
|
|
272
|
-
log(`本地校验完成,等待${waitDnsDiffuseTime}s`)
|
|
273
|
-
await wait(waitDnsDiffuseTime * 1000)
|
|
240
|
+
log(`本地校验完成,等待${waitDnsDiffuseTime}s`);
|
|
241
|
+
await wait(waitDnsDiffuseTime * 1000);
|
|
274
242
|
}
|
|
275
|
-
|
|
276
243
|
log("开始向提供商请求检查验证");
|
|
277
244
|
await runPromisePa(completeChallengeTasks, 1000);
|
|
278
|
-
}
|
|
245
|
+
}
|
|
246
|
+
catch (e) {
|
|
279
247
|
log(`证书申请失败${e.message}`);
|
|
280
248
|
throw e;
|
|
281
|
-
}
|
|
249
|
+
}
|
|
250
|
+
finally {
|
|
282
251
|
// letsencrypt 如果同时检出两个TXT记录,会以第一个为准,就会校验失败,所以需要提前删除
|
|
283
252
|
// zerossl 此方式测试无问题
|
|
284
253
|
log(`清理challenge痕迹,length:${clearTasks.length}`);
|
|
285
254
|
try {
|
|
286
255
|
// eslint-disable-next-line no-await-in-loop
|
|
287
256
|
await runAllPromise(clearTasks);
|
|
288
|
-
}
|
|
257
|
+
}
|
|
258
|
+
catch (e) {
|
|
289
259
|
log("清理challenge失败");
|
|
290
260
|
log(e);
|
|
291
261
|
}
|
|
292
262
|
}
|
|
293
263
|
}
|
|
294
|
-
|
|
295
|
-
|
|
296
264
|
log("challenge结束");
|
|
297
|
-
|
|
298
265
|
// log('[auto] Waiting for challenge valid status');
|
|
299
266
|
// await Promise.all(challengePromises);
|
|
300
267
|
/**
|
|
301
268
|
* Finalize order and download certificate
|
|
302
269
|
*/
|
|
303
|
-
|
|
304
270
|
log("[auto] Finalizing order and downloading certificate");
|
|
305
271
|
const finalized = await client.finalizeOrder(order, opts.csr);
|
|
306
272
|
const res = await client.getCertificate(finalized, opts.preferredChain);
|