@certd/acme-client 1.39.12 → 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 -78
- package/dist/verify.d.ts +14 -0
- package/{src → dist}/verify.js +46 -78
- package/dist/wait.d.ts +1 -0
- package/{src → dist}/wait.js +1 -0
- package/package.json +18 -12
- package/types/index.d.ts +14 -5
- package/types/index.test-d.ts +10 -3
- package/src/index.js +0 -106
- package/src/logs/app.log +0 -0
package/{src → dist}/verify.js
RENAMED
|
@@ -1,28 +1,24 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
1
2
|
/**
|
|
2
3
|
* ACME challenge verification
|
|
3
4
|
*/
|
|
4
|
-
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
import
|
|
9
|
-
import
|
|
10
|
-
import {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
const dns = dnsSdk.promises
|
|
14
|
-
|
|
15
|
-
let walkFromAuthoritative = true
|
|
5
|
+
import dnsSdk from "dns";
|
|
6
|
+
import https from 'https';
|
|
7
|
+
import { log as defaultLog } from './logger.js';
|
|
8
|
+
import axios from './axios.js';
|
|
9
|
+
import * as util from './util.js';
|
|
10
|
+
import { isAlpnCertificateAuthorizationValid } from './crypto/index.js';
|
|
11
|
+
import { utils } from '@certd/basic';
|
|
12
|
+
const dns = dnsSdk.promises;
|
|
13
|
+
let walkFromAuthoritative = true;
|
|
16
14
|
export function setWalkFromAuthoritative(value = true) {
|
|
17
|
-
walkFromAuthoritative = value
|
|
15
|
+
walkFromAuthoritative = value;
|
|
18
16
|
}
|
|
19
|
-
|
|
20
17
|
export function createChallengeFn(opts = {}) {
|
|
21
|
-
const logger = opts?.logger || { info: defaultLog, error: defaultLog, warn: defaultLog, debug: defaultLog }
|
|
22
|
-
|
|
18
|
+
const logger = opts?.logger || { info: defaultLog, error: defaultLog, warn: defaultLog, debug: defaultLog };
|
|
23
19
|
const log = function (...args) {
|
|
24
|
-
logger.info(...args)
|
|
25
|
-
}
|
|
20
|
+
logger.info(...args);
|
|
21
|
+
};
|
|
26
22
|
/**
|
|
27
23
|
* Verify ACME HTTP challenge
|
|
28
24
|
*
|
|
@@ -34,65 +30,52 @@ export function createChallengeFn(opts = {}) {
|
|
|
34
30
|
* @param {string} [suffix] URL suffix
|
|
35
31
|
* @returns {Promise<boolean>}
|
|
36
32
|
*/
|
|
37
|
-
|
|
38
33
|
async function verifyHttpChallenge(authz, challenge, keyAuthorization, suffix = `/.well-known/acme-challenge/${challenge.token}`) {
|
|
39
|
-
|
|
40
34
|
async function doQuery(challengeUrl) {
|
|
41
|
-
log(`正在测试请求 ${challengeUrl} `)
|
|
35
|
+
log(`正在测试请求 ${challengeUrl} `);
|
|
42
36
|
// const httpsPort = axios.defaults.acmeSettings.httpsChallengePort || 443;
|
|
43
37
|
// const challengeUrl = `https://${authz.identifier.value}:${httpsPort}${suffix}`;
|
|
44
|
-
|
|
45
38
|
/* May redirect to HTTPS with invalid/self-signed cert - https://letsencrypt.org/docs/challenge-types/#http-01-challenge */
|
|
46
39
|
const httpsAgent = new https.Agent({ rejectUnauthorized: false });
|
|
47
|
-
|
|
48
40
|
log(`Sending HTTP query to ${authz.identifier.value}, suffix: ${suffix}, port: ${httpPort}`);
|
|
49
|
-
let data = ""
|
|
41
|
+
let data = "";
|
|
50
42
|
try {
|
|
51
43
|
const resp = await axios.get(challengeUrl, { httpsAgent });
|
|
52
44
|
data = (resp.data || '').replace(/\s+$/, '');
|
|
53
|
-
}
|
|
45
|
+
}
|
|
46
|
+
catch (e) {
|
|
54
47
|
log(`[error] HTTP request error from ${authz.identifier.value}`, e.message);
|
|
55
|
-
return false
|
|
48
|
+
return false;
|
|
56
49
|
}
|
|
57
|
-
|
|
58
50
|
if (!data || (data !== keyAuthorization)) {
|
|
59
51
|
log(`[error] Authorization not found in HTTP response from ${authz.identifier.value}`);
|
|
60
|
-
return false
|
|
52
|
+
return false;
|
|
61
53
|
}
|
|
62
|
-
return true
|
|
63
|
-
|
|
54
|
+
return true;
|
|
64
55
|
}
|
|
65
|
-
|
|
66
56
|
const httpPort = axios.defaults.acmeSettings.httpChallengePort || 80;
|
|
67
57
|
let host = authz.identifier.value;
|
|
68
58
|
if (utils.domain.isIpv6(host)) {
|
|
69
59
|
host = `[${host}]`;
|
|
70
60
|
}
|
|
71
61
|
const challengeUrl = `http://${host}:${httpPort}${suffix}`;
|
|
72
|
-
|
|
73
62
|
if (!await doQuery(challengeUrl)) {
|
|
74
63
|
const httpsPort = axios.defaults.acmeSettings.httpsChallengePort || 443;
|
|
75
64
|
const httpsChallengeUrl = `https://${host}:${httpsPort}${suffix}`;
|
|
76
|
-
const res = await doQuery(httpsChallengeUrl)
|
|
65
|
+
const res = await doQuery(httpsChallengeUrl);
|
|
77
66
|
if (!res) {
|
|
78
67
|
throw new Error(`[error] 验证失败,请检查以上测试url是否可以正常访问`);
|
|
79
68
|
}
|
|
80
69
|
}
|
|
81
|
-
|
|
82
|
-
|
|
83
70
|
log(`Key authorization match for ${challenge.type}/${authz.identifier.value}, ACME challenge verified`);
|
|
84
71
|
return true;
|
|
85
72
|
}
|
|
86
|
-
|
|
87
73
|
/**
|
|
88
74
|
* Walk DNS until TXT records are found
|
|
89
75
|
*/
|
|
90
|
-
|
|
91
76
|
async function walkDnsChallengeRecord(recordName, resolver = dns, deep = 0) {
|
|
92
|
-
|
|
93
77
|
let records = [];
|
|
94
|
-
|
|
95
|
-
const isAuthoritative = resolver === dns
|
|
78
|
+
const isAuthoritative = resolver === dns;
|
|
96
79
|
/* Resolve TXT records */
|
|
97
80
|
try {
|
|
98
81
|
log(`检查域名 ${recordName} 的TXT记录(from ${isAuthoritative ? '本地DNS' : '权威DNS服务器'})`);
|
|
@@ -102,15 +85,14 @@ export function createChallengeFn(opts = {}) {
|
|
|
102
85
|
log(`TXT records: ${JSON.stringify(txtRecords)}`);
|
|
103
86
|
records = records.concat(...txtRecords);
|
|
104
87
|
}
|
|
105
|
-
}
|
|
88
|
+
}
|
|
89
|
+
catch (e) {
|
|
106
90
|
log(`解析 TXT 记录出错, ${recordName} :${e.message}`);
|
|
107
91
|
}
|
|
108
|
-
|
|
109
92
|
/* Resolve CNAME record first */
|
|
110
93
|
try {
|
|
111
94
|
log(`检查是否存在CNAME映射: ${recordName}`);
|
|
112
95
|
const cnameRecords = await resolver.resolveCname(recordName);
|
|
113
|
-
|
|
114
96
|
if (cnameRecords.length) {
|
|
115
97
|
const cnameRecord = cnameRecords[0];
|
|
116
98
|
log(`已找到${recordName}的CNAME记录,将检查: ${cnameRecord}`);
|
|
@@ -119,37 +101,36 @@ export function createChallengeFn(opts = {}) {
|
|
|
119
101
|
log(`从CNAME中找到TXT记录: ${JSON.stringify(res)}`);
|
|
120
102
|
records = records.concat(...res);
|
|
121
103
|
}
|
|
122
|
-
}
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
123
106
|
log(`没有CNAME映射(${recordName})`);
|
|
124
107
|
}
|
|
125
|
-
}
|
|
108
|
+
}
|
|
109
|
+
catch (e) {
|
|
126
110
|
log(`检查CNAME出错(${recordName}) :${e.message}`);
|
|
127
111
|
}
|
|
128
|
-
return records
|
|
112
|
+
return records;
|
|
129
113
|
}
|
|
130
|
-
|
|
131
114
|
async function walkTxtRecord(recordName, deep = 0) {
|
|
132
115
|
if (deep > 5) {
|
|
133
|
-
log(`walkTxtRecord too deep (#${deep}) , skip walk`)
|
|
134
|
-
return []
|
|
116
|
+
log(`walkTxtRecord too deep (#${deep}) , skip walk`);
|
|
117
|
+
return [];
|
|
135
118
|
}
|
|
136
|
-
|
|
137
|
-
const txtRecords = []
|
|
119
|
+
const txtRecords = [];
|
|
138
120
|
try {
|
|
139
121
|
/* Default DNS resolver first */
|
|
140
122
|
log('从本地DNS服务器获取TXT解析记录');
|
|
141
123
|
const res = await walkDnsChallengeRecord(recordName, dns, deep);
|
|
142
124
|
if (res && res.length > 0) {
|
|
143
125
|
for (const item of res) {
|
|
144
|
-
txtRecords.push(item)
|
|
126
|
+
txtRecords.push(item);
|
|
145
127
|
}
|
|
146
128
|
}
|
|
147
|
-
|
|
148
|
-
} catch (e) {
|
|
149
|
-
log(`本地获取TXT解析记录失败:${e.message}`)
|
|
150
129
|
}
|
|
151
|
-
|
|
152
|
-
|
|
130
|
+
catch (e) {
|
|
131
|
+
log(`本地获取TXT解析记录失败:${e.message}`);
|
|
132
|
+
}
|
|
133
|
+
if (walkFromAuthoritative !== false) {
|
|
153
134
|
try {
|
|
154
135
|
/* Authoritative DNS resolver */
|
|
155
136
|
log(`从域名权威服务器获取TXT解析记录`);
|
|
@@ -157,23 +138,22 @@ export function createChallengeFn(opts = {}) {
|
|
|
157
138
|
const res = await walkDnsChallengeRecord(recordName, authoritativeResolver, deep);
|
|
158
139
|
if (res && res.length > 0) {
|
|
159
140
|
for (const item of res) {
|
|
160
|
-
txtRecords.push(item)
|
|
141
|
+
txtRecords.push(item);
|
|
161
142
|
}
|
|
162
143
|
}
|
|
163
|
-
} catch (e) {
|
|
164
|
-
log(`权威服务器获取TXT解析记录失败:${e.message}`)
|
|
165
144
|
}
|
|
166
|
-
|
|
145
|
+
catch (e) {
|
|
146
|
+
log(`权威服务器获取TXT解析记录失败:${e.message}`);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
167
150
|
log(`跳过从权威服务器获取TXT解析记录`);
|
|
168
151
|
}
|
|
169
|
-
|
|
170
|
-
|
|
171
152
|
if (txtRecords.length === 0) {
|
|
172
153
|
throw new Error(`没有找到TXT解析记录(${recordName})`);
|
|
173
154
|
}
|
|
174
155
|
return txtRecords;
|
|
175
156
|
}
|
|
176
|
-
|
|
177
157
|
/**
|
|
178
158
|
* Verify ACME DNS challenge
|
|
179
159
|
*
|
|
@@ -185,7 +165,6 @@ export function createChallengeFn(opts = {}) {
|
|
|
185
165
|
* @param {string} [prefix] DNS prefix
|
|
186
166
|
* @returns {Promise<boolean>}
|
|
187
167
|
*/
|
|
188
|
-
|
|
189
168
|
async function verifyDnsChallenge(authz, challenge, keyAuthorization, prefix = '_acme-challenge.') {
|
|
190
169
|
const recordName = `${prefix}${authz.identifier.value}`;
|
|
191
170
|
log(`本地校验TXT记录): ${recordName}`);
|
|
@@ -194,14 +173,12 @@ export function createChallengeFn(opts = {}) {
|
|
|
194
173
|
recordValues = [...new Set(recordValues)];
|
|
195
174
|
log(`DNS查询成功, 找到 ${recordValues.length} 条TXT记录:${recordValues}`);
|
|
196
175
|
if (!recordValues.length || !recordValues.includes(keyAuthorization)) {
|
|
197
|
-
const err = `没有找到需要的DNS TXT记录: ${recordName},期望:${keyAuthorization},结果:${recordValues}
|
|
176
|
+
const err = `没有找到需要的DNS TXT记录: ${recordName},期望:${keyAuthorization},结果:${recordValues}`;
|
|
198
177
|
throw new Error(err);
|
|
199
178
|
}
|
|
200
|
-
|
|
201
179
|
log(`关键授权匹配成功(${challenge.type}/${recordName}):${keyAuthorization},校验成功, ACME challenge verified`);
|
|
202
180
|
return true;
|
|
203
181
|
}
|
|
204
|
-
|
|
205
182
|
/**
|
|
206
183
|
* Verify ACME TLS ALPN challenge
|
|
207
184
|
*
|
|
@@ -212,23 +189,18 @@ export function createChallengeFn(opts = {}) {
|
|
|
212
189
|
* @param {string} keyAuthorization Challenge key authorization
|
|
213
190
|
* @returns {Promise<boolean>}
|
|
214
191
|
*/
|
|
215
|
-
|
|
216
192
|
async function verifyTlsAlpnChallenge(authz, challenge, keyAuthorization) {
|
|
217
193
|
const tlsAlpnPort = axios.defaults.acmeSettings.tlsAlpnChallengePort || 443;
|
|
218
194
|
const host = authz.identifier.value;
|
|
219
195
|
log(`Establishing TLS connection with host: ${host}:${tlsAlpnPort}`);
|
|
220
|
-
|
|
221
196
|
const certificate = await util.retrieveTlsAlpnCertificate(host, tlsAlpnPort);
|
|
222
197
|
log('Certificate received from server successfully, matching key authorization in ALPN');
|
|
223
|
-
|
|
224
198
|
if (!isAlpnCertificateAuthorizationValid(certificate, keyAuthorization)) {
|
|
225
199
|
throw new Error(`Authorization not found in certificate from ${authz.identifier.value}`);
|
|
226
200
|
}
|
|
227
|
-
|
|
228
201
|
log(`Key authorization match for ${challenge.type}/${authz.identifier.value}, ACME challenge verified`);
|
|
229
202
|
return true;
|
|
230
203
|
}
|
|
231
|
-
|
|
232
204
|
return {
|
|
233
205
|
challenges: {
|
|
234
206
|
'http-01': verifyHttpChallenge,
|
|
@@ -237,10 +209,6 @@ export function createChallengeFn(opts = {}) {
|
|
|
237
209
|
},
|
|
238
210
|
walkTxtRecord,
|
|
239
211
|
walkDnsChallengeRecord,
|
|
240
|
-
}
|
|
241
|
-
|
|
212
|
+
};
|
|
242
213
|
}
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
214
|
// createChallengeFn({logger:{info:console.log}}).walkDnsChallengeRecord("handsfree.work")
|
package/dist/wait.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function wait(ms: any): Promise<unknown>;
|
package/{src → dist}/wait.js
RENAMED
package/package.json
CHANGED
|
@@ -3,22 +3,22 @@
|
|
|
3
3
|
"description": "Simple and unopinionated ACME client",
|
|
4
4
|
"private": false,
|
|
5
5
|
"author": "nmorsman",
|
|
6
|
-
"version": "1.39.
|
|
6
|
+
"version": "1.39.13",
|
|
7
7
|
"type": "module",
|
|
8
|
-
"module": "
|
|
9
|
-
"main": "
|
|
10
|
-
"types": "
|
|
8
|
+
"module": "./dist/index.js",
|
|
9
|
+
"main": "./dist/index.js",
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
11
|
"license": "MIT",
|
|
12
12
|
"homepage": "https://github.com/publishlab/node-acme-client",
|
|
13
13
|
"engines": {
|
|
14
14
|
"node": ">= 18"
|
|
15
15
|
},
|
|
16
16
|
"files": [
|
|
17
|
-
"
|
|
17
|
+
"dist",
|
|
18
18
|
"types"
|
|
19
19
|
],
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"@certd/basic": "^1.39.
|
|
21
|
+
"@certd/basic": "^1.39.13",
|
|
22
22
|
"@peculiar/x509": "^1.11.0",
|
|
23
23
|
"asn1js": "^3.0.5",
|
|
24
24
|
"axios": "^1.9.0",
|
|
@@ -35,10 +35,12 @@
|
|
|
35
35
|
"@typescript-eslint/parser": "^8.26.1",
|
|
36
36
|
"chai": "^4.4.1",
|
|
37
37
|
"chai-as-promised": "^7.1.2",
|
|
38
|
+
"cross-env": "^7.0.3",
|
|
38
39
|
"eslint": "^8.57.0",
|
|
39
40
|
"eslint-config-prettier": "^8.5.0",
|
|
40
41
|
"eslint-plugin-import": "^2.29.1",
|
|
41
42
|
"eslint-plugin-prettier": "^4.2.1",
|
|
43
|
+
"esmock": "^2.7.5",
|
|
42
44
|
"jsdoc-to-markdown": "^8.0.1",
|
|
43
45
|
"mocha": "^10.6.0",
|
|
44
46
|
"nock": "^13.5.4",
|
|
@@ -47,13 +49,17 @@
|
|
|
47
49
|
"typescript": "^5.4.2"
|
|
48
50
|
},
|
|
49
51
|
"scripts": {
|
|
50
|
-
"build
|
|
51
|
-
"
|
|
52
|
-
"
|
|
53
|
-
"
|
|
52
|
+
"before-build": "node -e \"const fs=require('fs');fs.rmSync('dist',{recursive:true,force:true});fs.rmSync('tsconfig.tsbuildinfo',{force:true});\"",
|
|
53
|
+
"build": "npm run before-build && tsc --skipLibCheck",
|
|
54
|
+
"build-docs": "jsdoc2md dist/client.js > docs/client.md && jsdoc2md dist/crypto/index.js > docs/crypto.md && jsdoc2md dist/crypto/forge.js > docs/forge.md",
|
|
55
|
+
"lint": "eslint \"src/**/*.ts\" \"types/**/*.ts\"",
|
|
56
|
+
"lint-types": "tsd --files \"types/index.test-d.ts\"",
|
|
57
|
+
"prepublishOnly": "npm run build && npm run build-docs",
|
|
54
58
|
"test": "mocha -t 60000 \"test/setup.js\" \"test/**/*.spec.js\"",
|
|
59
|
+
"before-test:unit": "node -e \"const fs=require('fs');fs.rmSync('dist-test',{recursive:true,force:true});fs.rmSync('tsconfig.test.tsbuildinfo',{force:true});\"",
|
|
60
|
+
"test:unit": "cross-env NODE_ENV=unittest npm run before-test:unit && cross-env NODE_ENV=unittest tsc -p tsconfig.test.json --skipLibCheck && cross-env NODE_ENV=unittest mocha -t 60000 \"dist-test/**/*.test.js\"",
|
|
55
61
|
"pub": "npm publish",
|
|
56
|
-
"compile": "
|
|
62
|
+
"compile": "tsc --skipLibCheck --watch"
|
|
57
63
|
},
|
|
58
64
|
"repository": {
|
|
59
65
|
"type": "git",
|
|
@@ -70,5 +76,5 @@
|
|
|
70
76
|
"bugs": {
|
|
71
77
|
"url": "https://github.com/publishlab/node-acme-client/issues"
|
|
72
78
|
},
|
|
73
|
-
"gitHead": "
|
|
79
|
+
"gitHead": "9f7d766cb386b299d4098141f4a47d23e16975e3"
|
|
74
80
|
}
|
package/types/index.d.ts
CHANGED
|
@@ -4,8 +4,6 @@
|
|
|
4
4
|
|
|
5
5
|
import { AxiosInstance } from 'axios';
|
|
6
6
|
import * as rfc8555 from './rfc8555';
|
|
7
|
-
import {CancelError} from '../src/error.js'
|
|
8
|
-
export * from '../src/error.js'
|
|
9
7
|
|
|
10
8
|
export type PrivateKeyBuffer = Buffer;
|
|
11
9
|
export type PublicKeyBuffer = Buffer;
|
|
@@ -115,6 +113,15 @@ export const directory: {
|
|
|
115
113
|
zerossl: {
|
|
116
114
|
staging: string,
|
|
117
115
|
production: string
|
|
116
|
+
},
|
|
117
|
+
sslcom: {
|
|
118
|
+
staging: string,
|
|
119
|
+
production: string,
|
|
120
|
+
ec: string
|
|
121
|
+
},
|
|
122
|
+
litessl: {
|
|
123
|
+
staging: string,
|
|
124
|
+
production: string
|
|
118
125
|
}
|
|
119
126
|
};
|
|
120
127
|
|
|
@@ -211,14 +218,16 @@ export const agents: any;
|
|
|
211
218
|
* Logger
|
|
212
219
|
*/
|
|
213
220
|
|
|
221
|
+
export class CancelError extends Error {
|
|
222
|
+
constructor(message?: string);
|
|
223
|
+
}
|
|
224
|
+
|
|
214
225
|
export function setLogger(fn: (message: any, ...args: any[]) => void): void;
|
|
215
226
|
|
|
216
227
|
export function createChallengeFn(opts?: {logger?:any}): any;
|
|
217
228
|
// export function walkTxtRecord(record: any): Promise<string[]>;
|
|
218
229
|
export function getAuthoritativeDnsResolver(record:string): Promise<any>;
|
|
219
230
|
|
|
220
|
-
export const CancelError: typeof CancelError;
|
|
221
|
-
|
|
222
231
|
export function resolveDomainBySoaRecord(domain: string): Promise<string>;
|
|
223
232
|
|
|
224
|
-
export function setWalkFromAuthoritative(value
|
|
233
|
+
export function setWalkFromAuthoritative(value?: boolean): void;
|
package/types/index.test-d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* acme-client type definition tests
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import * as acme from '
|
|
5
|
+
import * as acme from '..';
|
|
6
6
|
|
|
7
7
|
(async () => {
|
|
8
8
|
/* Client */
|
|
@@ -10,6 +10,7 @@ import * as acme from 'acme-client';
|
|
|
10
10
|
|
|
11
11
|
const client = new acme.Client({
|
|
12
12
|
accountKey,
|
|
13
|
+
sslProvider: 'letsencrypt',
|
|
13
14
|
directoryUrl: acme.directory.letsencrypt.staging
|
|
14
15
|
});
|
|
15
16
|
|
|
@@ -52,7 +53,10 @@ import * as acme from 'acme-client';
|
|
|
52
53
|
/* Auto */
|
|
53
54
|
await client.auto({
|
|
54
55
|
csr: certCsr,
|
|
55
|
-
challengeCreateFn: async (authz,
|
|
56
|
+
challengeCreateFn: async (authz, keyAuthorization) => ({
|
|
57
|
+
challenge: authz.challenges[0],
|
|
58
|
+
keyAuthorization: await keyAuthorization(authz.challenges[0])
|
|
59
|
+
}),
|
|
56
60
|
challengeRemoveFn: async (authz, challenge, keyAuthorization) => {}
|
|
57
61
|
});
|
|
58
62
|
|
|
@@ -63,7 +67,10 @@ import * as acme from 'acme-client';
|
|
|
63
67
|
skipChallengeVerification: false,
|
|
64
68
|
challengePriority: ['http-01', 'dns-01'],
|
|
65
69
|
preferredChain: 'DST Root CA X3',
|
|
66
|
-
challengeCreateFn: async (authz,
|
|
70
|
+
challengeCreateFn: async (authz, keyAuthorization) => ({
|
|
71
|
+
challenge: authz.challenges[0],
|
|
72
|
+
keyAuthorization: await keyAuthorization(authz.challenges[0])
|
|
73
|
+
}),
|
|
67
74
|
challengeRemoveFn: async (authz, challenge, keyAuthorization) => {}
|
|
68
75
|
});
|
|
69
76
|
})();
|
package/src/index.js
DELETED
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* acme-client
|
|
3
|
-
*/
|
|
4
|
-
import AcmeClinet from './client.js'
|
|
5
|
-
export const Client = AcmeClinet
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Directory URLs
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
export const directory = {
|
|
12
|
-
buypass: {
|
|
13
|
-
staging: 'https://api.test4.buypass.no/acme/directory',
|
|
14
|
-
production: 'https://api.buypass.com/acme/directory',
|
|
15
|
-
},
|
|
16
|
-
google: {
|
|
17
|
-
staging: 'https://dv.acme-v02.test-api.pki.goog/directory',
|
|
18
|
-
production: 'https://dv.acme-v02.api.pki.goog/directory',
|
|
19
|
-
},
|
|
20
|
-
letsencrypt: {
|
|
21
|
-
staging: 'https://acme-staging-v02.api.letsencrypt.org/directory',
|
|
22
|
-
production: 'https://acme-v02.api.letsencrypt.org/directory',
|
|
23
|
-
},
|
|
24
|
-
letsencrypt_staging: {
|
|
25
|
-
production: 'https://acme-staging-v02.api.letsencrypt.org/directory',
|
|
26
|
-
},
|
|
27
|
-
zerossl: {
|
|
28
|
-
staging: 'https://acme.zerossl.com/v2/DV90',
|
|
29
|
-
production: 'https://acme.zerossl.com/v2/DV90',
|
|
30
|
-
},
|
|
31
|
-
sslcom:{
|
|
32
|
-
staging: 'https://acme.ssl.com/sslcom-dv-rsa',
|
|
33
|
-
production: 'https://acme.ssl.com/sslcom-dv-rsa',
|
|
34
|
-
ec: 'https://acme.ssl.com/sslcom-dv-ecc',
|
|
35
|
-
},
|
|
36
|
-
litessl: {
|
|
37
|
-
staging: 'https://acme.litessl.com/acme/v2/directory',
|
|
38
|
-
production: 'https://acme.litessl.com/acme/v2/directory',
|
|
39
|
-
},
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
export function getDirectoryUrl(opts) {
|
|
43
|
-
const {sslProvider, pkType} = opts
|
|
44
|
-
const list= directory[sslProvider]
|
|
45
|
-
if (!list) {
|
|
46
|
-
throw new Error(`sslProvider ${sslProvider} not found`)
|
|
47
|
-
}
|
|
48
|
-
let pkTypePrefix = pkType || 'rsa'
|
|
49
|
-
if (pkType) {
|
|
50
|
-
pkTypePrefix = pkType.toLowerCase().split("_")[0]
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
if (pkTypePrefix && list[pkTypePrefix]) {
|
|
54
|
-
return list[pkTypePrefix]
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
return list.production
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
export function getAllSslProviderDomains() {
|
|
62
|
-
const list = Object.values(directory).map((item) => {
|
|
63
|
-
let url = item.production.replace('https://', '')
|
|
64
|
-
url = url.substring(0, url.indexOf('/'))
|
|
65
|
-
return url
|
|
66
|
-
})
|
|
67
|
-
return list
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
let sslProviderReverseProxies = {}
|
|
71
|
-
|
|
72
|
-
function initSslProviderReverseProxies() {
|
|
73
|
-
for (const sslProvider of getAllSslProviderDomains()) {
|
|
74
|
-
sslProviderReverseProxies[sslProvider] = ""
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
initSslProviderReverseProxies()
|
|
78
|
-
|
|
79
|
-
export function getSslProviderReverseProxies() {
|
|
80
|
-
return sslProviderReverseProxies
|
|
81
|
-
}
|
|
82
|
-
export function setSslProviderReverseProxies(reverseProxies) {
|
|
83
|
-
Object.assign(sslProviderReverseProxies, reverseProxies)
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* Crypto
|
|
88
|
-
*/
|
|
89
|
-
|
|
90
|
-
export * as crypto from './crypto/index.js'
|
|
91
|
-
export * as forge from './crypto/forge.js'
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* Axios
|
|
95
|
-
*/
|
|
96
|
-
|
|
97
|
-
export * from './axios.js'
|
|
98
|
-
/**
|
|
99
|
-
* Logger
|
|
100
|
-
*/
|
|
101
|
-
|
|
102
|
-
export * from './logger.js'
|
|
103
|
-
export * from './verify.js'
|
|
104
|
-
export * from './error.js'
|
|
105
|
-
|
|
106
|
-
export * from './util.js'
|
package/src/logs/app.log
DELETED
|
File without changes
|