@certd/plugin-cert 1.22.0 → 1.22.1
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/CHANGELOG.md +6 -0
- package/LICENSE +661 -0
- package/dist/access/eab-access.d.ts +4 -4
- package/dist/access/eab-access.js +46 -46
- package/dist/access/index.d.ts +1 -1
- package/dist/access/index.js +1 -1
- package/dist/bundle.js +1 -1
- package/dist/d/plugin/cert-plugin/acme.d.ts +0 -2
- package/dist/d/plugin/cert-plugin/index.d.ts +0 -1
- package/dist/dns-provider/api.d.ts +27 -27
- package/dist/dns-provider/api.js +1 -1
- package/dist/dns-provider/base.d.ts +8 -8
- package/dist/dns-provider/base.js +6 -6
- package/dist/dns-provider/decorator.d.ts +3 -3
- package/dist/dns-provider/decorator.js +26 -26
- package/dist/dns-provider/index.d.ts +4 -4
- package/dist/dns-provider/index.js +4 -4
- package/dist/dns-provider/registry.d.ts +2 -2
- package/dist/dns-provider/registry.js +2 -2
- package/dist/index.d.ts +3 -3
- package/dist/plugin/cert-plugin/acme.d.ts +54 -54
- package/dist/plugin/cert-plugin/acme.js +203 -203
- package/dist/plugin/cert-plugin/base.d.ts +49 -49
- package/dist/plugin/cert-plugin/base.js +4 -1
- package/dist/plugin/cert-plugin/cert-reader.d.ts +16 -16
- package/dist/plugin/cert-plugin/cert-reader.js +45 -45
- package/dist/plugin/cert-plugin/index.d.ts +16 -16
- package/dist/plugin/cert-plugin/index.js +5 -3
- package/dist/plugin/cert-plugin/lego.d.ts +1 -1
- package/dist/plugin/cert-plugin/lego.js +17 -9
- package/dist/plugin-cert.mjs +11786 -0
- package/dist/plugin-cert.umd.js +28 -0
- package/package.json +4 -4
- package/stats.html +6177 -0
- package/test/user.secret.js +7 -0
- package/test/user.secret.ts +4 -0
- package/tsconfig.tsbuildinfo +1 -0
|
@@ -1,203 +1,203 @@
|
|
|
1
|
-
// @ts-ignore
|
|
2
|
-
import * as acme from "@certd/acme-client";
|
|
3
|
-
import _ from "lodash-es";
|
|
4
|
-
import psl from "psl";
|
|
5
|
-
export class AcmeService {
|
|
6
|
-
userContext;
|
|
7
|
-
logger;
|
|
8
|
-
sslProvider;
|
|
9
|
-
skipLocalVerify = true;
|
|
10
|
-
eab;
|
|
11
|
-
constructor(options) {
|
|
12
|
-
this.userContext = options.userContext;
|
|
13
|
-
this.logger = options.logger;
|
|
14
|
-
this.sslProvider = options.sslProvider || "letsencrypt";
|
|
15
|
-
this.eab = options.eab;
|
|
16
|
-
this.skipLocalVerify = options.skipLocalVerify ?? false;
|
|
17
|
-
acme.setLogger((text) => {
|
|
18
|
-
this.logger.info(text);
|
|
19
|
-
});
|
|
20
|
-
}
|
|
21
|
-
async getAccountConfig(email) {
|
|
22
|
-
return (await this.userContext.getObj(this.buildAccountKey(email))) || {};
|
|
23
|
-
}
|
|
24
|
-
buildAccountKey(email) {
|
|
25
|
-
return `acme.config.${this.sslProvider}.${email}`;
|
|
26
|
-
}
|
|
27
|
-
async saveAccountConfig(email, conf) {
|
|
28
|
-
await this.userContext.setObj(this.buildAccountKey(email), conf);
|
|
29
|
-
}
|
|
30
|
-
async getAcmeClient(email, isTest = false) {
|
|
31
|
-
const conf = await this.getAccountConfig(email);
|
|
32
|
-
if (conf.key == null) {
|
|
33
|
-
conf.key = await this.createNewKey();
|
|
34
|
-
await this.saveAccountConfig(email, conf);
|
|
35
|
-
}
|
|
36
|
-
let directoryUrl = "";
|
|
37
|
-
if (isTest) {
|
|
38
|
-
directoryUrl = acme.directory[this.sslProvider].staging;
|
|
39
|
-
}
|
|
40
|
-
else {
|
|
41
|
-
directoryUrl = acme.directory[this.sslProvider].production;
|
|
42
|
-
}
|
|
43
|
-
const client = new acme.Client({
|
|
44
|
-
directoryUrl: directoryUrl,
|
|
45
|
-
accountKey: conf.key,
|
|
46
|
-
accountUrl: conf.accountUrl,
|
|
47
|
-
externalAccountBinding: this.eab,
|
|
48
|
-
backoffAttempts: 30,
|
|
49
|
-
backoffMin: 5000,
|
|
50
|
-
backoffMax: 10000,
|
|
51
|
-
});
|
|
52
|
-
if (conf.accountUrl == null) {
|
|
53
|
-
const accountPayload = {
|
|
54
|
-
termsOfServiceAgreed: true,
|
|
55
|
-
contact: [`mailto:${email}`],
|
|
56
|
-
externalAccountBinding: this.eab,
|
|
57
|
-
};
|
|
58
|
-
await client.createAccount(accountPayload);
|
|
59
|
-
conf.accountUrl = client.getAccountUrl();
|
|
60
|
-
await this.saveAccountConfig(email, conf);
|
|
61
|
-
}
|
|
62
|
-
return client;
|
|
63
|
-
}
|
|
64
|
-
async createNewKey() {
|
|
65
|
-
const key = await acme.forge.createPrivateKey();
|
|
66
|
-
return key.toString();
|
|
67
|
-
}
|
|
68
|
-
parseDomain(fullDomain) {
|
|
69
|
-
const parsed = psl.parse(fullDomain);
|
|
70
|
-
if (parsed.error) {
|
|
71
|
-
throw new Error(`解析${fullDomain}域名失败:` + JSON.stringify(parsed.error));
|
|
72
|
-
}
|
|
73
|
-
return parsed.domain;
|
|
74
|
-
}
|
|
75
|
-
async challengeCreateFn(authz, challenge, keyAuthorization, dnsProvider) {
|
|
76
|
-
this.logger.info("Triggered challengeCreateFn()");
|
|
77
|
-
/* http-01 */
|
|
78
|
-
const fullDomain = authz.identifier.value;
|
|
79
|
-
if (challenge.type === "http-01") {
|
|
80
|
-
const filePath = `/var/www/html/.well-known/acme-challenge/${challenge.token}`;
|
|
81
|
-
const fileContents = keyAuthorization;
|
|
82
|
-
this.logger.info(`Creating challenge response for ${fullDomain} at path: ${filePath}`);
|
|
83
|
-
/* Replace this */
|
|
84
|
-
this.logger.info(`Would write "${fileContents}" to path "${filePath}"`);
|
|
85
|
-
// await fs.writeFileAsync(filePath, fileContents);
|
|
86
|
-
}
|
|
87
|
-
else if (challenge.type === "dns-01") {
|
|
88
|
-
/* dns-01 */
|
|
89
|
-
const dnsRecord = `_acme-challenge.${fullDomain}`;
|
|
90
|
-
const recordValue = keyAuthorization;
|
|
91
|
-
this.logger.info(`Creating TXT record for ${fullDomain}: ${dnsRecord}`);
|
|
92
|
-
/* Replace this */
|
|
93
|
-
this.logger.info(`Would create TXT record "${dnsRecord}" with value "${recordValue}"`);
|
|
94
|
-
const domain = this.parseDomain(fullDomain);
|
|
95
|
-
this.logger.info("解析到域名domain=", domain);
|
|
96
|
-
return await dnsProvider.createRecord({
|
|
97
|
-
fullRecord: dnsRecord,
|
|
98
|
-
type: "TXT",
|
|
99
|
-
value: recordValue,
|
|
100
|
-
domain,
|
|
101
|
-
});
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
/**
|
|
105
|
-
* Function used to remove an ACME challenge response
|
|
106
|
-
*
|
|
107
|
-
* @param {object} authz Authorization object
|
|
108
|
-
* @param {object} challenge Selected challenge
|
|
109
|
-
* @param {string} keyAuthorization Authorization key
|
|
110
|
-
* @param recordItem challengeCreateFn create record item
|
|
111
|
-
* @param dnsProvider dnsProvider
|
|
112
|
-
* @returns {Promise}
|
|
113
|
-
*/
|
|
114
|
-
async challengeRemoveFn(authz, challenge, keyAuthorization, recordItem, dnsProvider) {
|
|
115
|
-
this.logger.info("Triggered challengeRemoveFn()");
|
|
116
|
-
/* http-01 */
|
|
117
|
-
const fullDomain = authz.identifier.value;
|
|
118
|
-
if (challenge.type === "http-01") {
|
|
119
|
-
const filePath = `/var/www/html/.well-known/acme-challenge/${challenge.token}`;
|
|
120
|
-
this.logger.info(`Removing challenge response for ${fullDomain} at path: ${filePath}`);
|
|
121
|
-
/* Replace this */
|
|
122
|
-
this.logger.info(`Would remove file on path "${filePath}"`);
|
|
123
|
-
// await fs.unlinkAsync(filePath);
|
|
124
|
-
}
|
|
125
|
-
else if (challenge.type === "dns-01") {
|
|
126
|
-
const dnsRecord = `_acme-challenge.${fullDomain}`;
|
|
127
|
-
const recordValue = keyAuthorization;
|
|
128
|
-
this.logger.info(`Removing TXT record for ${fullDomain}: ${dnsRecord}`);
|
|
129
|
-
/* Replace this */
|
|
130
|
-
this.logger.info(`Would remove TXT record "${dnsRecord}" with value "${recordValue}"`);
|
|
131
|
-
const domain = this.parseDomain(fullDomain);
|
|
132
|
-
try {
|
|
133
|
-
await dnsProvider.removeRecord({
|
|
134
|
-
fullRecord: dnsRecord,
|
|
135
|
-
type: "TXT",
|
|
136
|
-
value: keyAuthorization,
|
|
137
|
-
record: recordItem,
|
|
138
|
-
domain,
|
|
139
|
-
});
|
|
140
|
-
}
|
|
141
|
-
catch (e) {
|
|
142
|
-
this.logger.error("删除解析记录出错:", e);
|
|
143
|
-
throw e;
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
async order(options) {
|
|
148
|
-
const { email, isTest, domains, csrInfo, dnsProvider } = options;
|
|
149
|
-
const client = await this.getAcmeClient(email, isTest);
|
|
150
|
-
/* Create CSR */
|
|
151
|
-
const { commonName, altNames } = this.buildCommonNameByDomains(domains);
|
|
152
|
-
const [key, csr] = await acme.forge.createCsr({
|
|
153
|
-
commonName,
|
|
154
|
-
...csrInfo,
|
|
155
|
-
altNames,
|
|
156
|
-
});
|
|
157
|
-
if (dnsProvider == null) {
|
|
158
|
-
throw new Error("dnsProvider 不能为空");
|
|
159
|
-
}
|
|
160
|
-
/* 自动申请证书 */
|
|
161
|
-
const crt = await client.auto({
|
|
162
|
-
csr,
|
|
163
|
-
email: email,
|
|
164
|
-
termsOfServiceAgreed: true,
|
|
165
|
-
skipChallengeVerification: this.skipLocalVerify,
|
|
166
|
-
challengePriority: ["dns-01"],
|
|
167
|
-
challengeCreateFn: async (authz, challenge, keyAuthorization) => {
|
|
168
|
-
return await this.challengeCreateFn(authz, challenge, keyAuthorization, dnsProvider);
|
|
169
|
-
},
|
|
170
|
-
challengeRemoveFn: async (authz, challenge, keyAuthorization, recordItem) => {
|
|
171
|
-
return await this.challengeRemoveFn(authz, challenge, keyAuthorization, recordItem, dnsProvider);
|
|
172
|
-
},
|
|
173
|
-
});
|
|
174
|
-
const cert = {
|
|
175
|
-
crt: crt.toString(),
|
|
176
|
-
key: key.toString(),
|
|
177
|
-
csr: csr.toString(),
|
|
178
|
-
};
|
|
179
|
-
/* Done */
|
|
180
|
-
this.logger.debug(`CSR:\n${cert.csr}`);
|
|
181
|
-
this.logger.debug(`Certificate:\n${cert.crt}`);
|
|
182
|
-
this.logger.info("证书申请成功");
|
|
183
|
-
return cert;
|
|
184
|
-
}
|
|
185
|
-
buildCommonNameByDomains(domains) {
|
|
186
|
-
if (typeof domains === "string") {
|
|
187
|
-
domains = domains.split(",");
|
|
188
|
-
}
|
|
189
|
-
if (domains.length === 0) {
|
|
190
|
-
throw new Error("domain can not be empty");
|
|
191
|
-
}
|
|
192
|
-
const commonName = domains[0];
|
|
193
|
-
let altNames = undefined;
|
|
194
|
-
if (domains.length > 1) {
|
|
195
|
-
altNames = _.slice(domains, 1);
|
|
196
|
-
}
|
|
197
|
-
return {
|
|
198
|
-
commonName,
|
|
199
|
-
altNames,
|
|
200
|
-
};
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
1
|
+
// @ts-ignore
|
|
2
|
+
import * as acme from "@certd/acme-client";
|
|
3
|
+
import _ from "lodash-es";
|
|
4
|
+
import psl from "psl";
|
|
5
|
+
export class AcmeService {
|
|
6
|
+
userContext;
|
|
7
|
+
logger;
|
|
8
|
+
sslProvider;
|
|
9
|
+
skipLocalVerify = true;
|
|
10
|
+
eab;
|
|
11
|
+
constructor(options) {
|
|
12
|
+
this.userContext = options.userContext;
|
|
13
|
+
this.logger = options.logger;
|
|
14
|
+
this.sslProvider = options.sslProvider || "letsencrypt";
|
|
15
|
+
this.eab = options.eab;
|
|
16
|
+
this.skipLocalVerify = options.skipLocalVerify ?? false;
|
|
17
|
+
acme.setLogger((text) => {
|
|
18
|
+
this.logger.info(text);
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
async getAccountConfig(email) {
|
|
22
|
+
return (await this.userContext.getObj(this.buildAccountKey(email))) || {};
|
|
23
|
+
}
|
|
24
|
+
buildAccountKey(email) {
|
|
25
|
+
return `acme.config.${this.sslProvider}.${email}`;
|
|
26
|
+
}
|
|
27
|
+
async saveAccountConfig(email, conf) {
|
|
28
|
+
await this.userContext.setObj(this.buildAccountKey(email), conf);
|
|
29
|
+
}
|
|
30
|
+
async getAcmeClient(email, isTest = false) {
|
|
31
|
+
const conf = await this.getAccountConfig(email);
|
|
32
|
+
if (conf.key == null) {
|
|
33
|
+
conf.key = await this.createNewKey();
|
|
34
|
+
await this.saveAccountConfig(email, conf);
|
|
35
|
+
}
|
|
36
|
+
let directoryUrl = "";
|
|
37
|
+
if (isTest) {
|
|
38
|
+
directoryUrl = acme.directory[this.sslProvider].staging;
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
directoryUrl = acme.directory[this.sslProvider].production;
|
|
42
|
+
}
|
|
43
|
+
const client = new acme.Client({
|
|
44
|
+
directoryUrl: directoryUrl,
|
|
45
|
+
accountKey: conf.key,
|
|
46
|
+
accountUrl: conf.accountUrl,
|
|
47
|
+
externalAccountBinding: this.eab,
|
|
48
|
+
backoffAttempts: 30,
|
|
49
|
+
backoffMin: 5000,
|
|
50
|
+
backoffMax: 10000,
|
|
51
|
+
});
|
|
52
|
+
if (conf.accountUrl == null) {
|
|
53
|
+
const accountPayload = {
|
|
54
|
+
termsOfServiceAgreed: true,
|
|
55
|
+
contact: [`mailto:${email}`],
|
|
56
|
+
externalAccountBinding: this.eab,
|
|
57
|
+
};
|
|
58
|
+
await client.createAccount(accountPayload);
|
|
59
|
+
conf.accountUrl = client.getAccountUrl();
|
|
60
|
+
await this.saveAccountConfig(email, conf);
|
|
61
|
+
}
|
|
62
|
+
return client;
|
|
63
|
+
}
|
|
64
|
+
async createNewKey() {
|
|
65
|
+
const key = await acme.forge.createPrivateKey();
|
|
66
|
+
return key.toString();
|
|
67
|
+
}
|
|
68
|
+
parseDomain(fullDomain) {
|
|
69
|
+
const parsed = psl.parse(fullDomain);
|
|
70
|
+
if (parsed.error) {
|
|
71
|
+
throw new Error(`解析${fullDomain}域名失败:` + JSON.stringify(parsed.error));
|
|
72
|
+
}
|
|
73
|
+
return parsed.domain;
|
|
74
|
+
}
|
|
75
|
+
async challengeCreateFn(authz, challenge, keyAuthorization, dnsProvider) {
|
|
76
|
+
this.logger.info("Triggered challengeCreateFn()");
|
|
77
|
+
/* http-01 */
|
|
78
|
+
const fullDomain = authz.identifier.value;
|
|
79
|
+
if (challenge.type === "http-01") {
|
|
80
|
+
const filePath = `/var/www/html/.well-known/acme-challenge/${challenge.token}`;
|
|
81
|
+
const fileContents = keyAuthorization;
|
|
82
|
+
this.logger.info(`Creating challenge response for ${fullDomain} at path: ${filePath}`);
|
|
83
|
+
/* Replace this */
|
|
84
|
+
this.logger.info(`Would write "${fileContents}" to path "${filePath}"`);
|
|
85
|
+
// await fs.writeFileAsync(filePath, fileContents);
|
|
86
|
+
}
|
|
87
|
+
else if (challenge.type === "dns-01") {
|
|
88
|
+
/* dns-01 */
|
|
89
|
+
const dnsRecord = `_acme-challenge.${fullDomain}`;
|
|
90
|
+
const recordValue = keyAuthorization;
|
|
91
|
+
this.logger.info(`Creating TXT record for ${fullDomain}: ${dnsRecord}`);
|
|
92
|
+
/* Replace this */
|
|
93
|
+
this.logger.info(`Would create TXT record "${dnsRecord}" with value "${recordValue}"`);
|
|
94
|
+
const domain = this.parseDomain(fullDomain);
|
|
95
|
+
this.logger.info("解析到域名domain=", domain);
|
|
96
|
+
return await dnsProvider.createRecord({
|
|
97
|
+
fullRecord: dnsRecord,
|
|
98
|
+
type: "TXT",
|
|
99
|
+
value: recordValue,
|
|
100
|
+
domain,
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Function used to remove an ACME challenge response
|
|
106
|
+
*
|
|
107
|
+
* @param {object} authz Authorization object
|
|
108
|
+
* @param {object} challenge Selected challenge
|
|
109
|
+
* @param {string} keyAuthorization Authorization key
|
|
110
|
+
* @param recordItem challengeCreateFn create record item
|
|
111
|
+
* @param dnsProvider dnsProvider
|
|
112
|
+
* @returns {Promise}
|
|
113
|
+
*/
|
|
114
|
+
async challengeRemoveFn(authz, challenge, keyAuthorization, recordItem, dnsProvider) {
|
|
115
|
+
this.logger.info("Triggered challengeRemoveFn()");
|
|
116
|
+
/* http-01 */
|
|
117
|
+
const fullDomain = authz.identifier.value;
|
|
118
|
+
if (challenge.type === "http-01") {
|
|
119
|
+
const filePath = `/var/www/html/.well-known/acme-challenge/${challenge.token}`;
|
|
120
|
+
this.logger.info(`Removing challenge response for ${fullDomain} at path: ${filePath}`);
|
|
121
|
+
/* Replace this */
|
|
122
|
+
this.logger.info(`Would remove file on path "${filePath}"`);
|
|
123
|
+
// await fs.unlinkAsync(filePath);
|
|
124
|
+
}
|
|
125
|
+
else if (challenge.type === "dns-01") {
|
|
126
|
+
const dnsRecord = `_acme-challenge.${fullDomain}`;
|
|
127
|
+
const recordValue = keyAuthorization;
|
|
128
|
+
this.logger.info(`Removing TXT record for ${fullDomain}: ${dnsRecord}`);
|
|
129
|
+
/* Replace this */
|
|
130
|
+
this.logger.info(`Would remove TXT record "${dnsRecord}" with value "${recordValue}"`);
|
|
131
|
+
const domain = this.parseDomain(fullDomain);
|
|
132
|
+
try {
|
|
133
|
+
await dnsProvider.removeRecord({
|
|
134
|
+
fullRecord: dnsRecord,
|
|
135
|
+
type: "TXT",
|
|
136
|
+
value: keyAuthorization,
|
|
137
|
+
record: recordItem,
|
|
138
|
+
domain,
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
catch (e) {
|
|
142
|
+
this.logger.error("删除解析记录出错:", e);
|
|
143
|
+
throw e;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
async order(options) {
|
|
148
|
+
const { email, isTest, domains, csrInfo, dnsProvider } = options;
|
|
149
|
+
const client = await this.getAcmeClient(email, isTest);
|
|
150
|
+
/* Create CSR */
|
|
151
|
+
const { commonName, altNames } = this.buildCommonNameByDomains(domains);
|
|
152
|
+
const [key, csr] = await acme.forge.createCsr({
|
|
153
|
+
commonName,
|
|
154
|
+
...csrInfo,
|
|
155
|
+
altNames,
|
|
156
|
+
});
|
|
157
|
+
if (dnsProvider == null) {
|
|
158
|
+
throw new Error("dnsProvider 不能为空");
|
|
159
|
+
}
|
|
160
|
+
/* 自动申请证书 */
|
|
161
|
+
const crt = await client.auto({
|
|
162
|
+
csr,
|
|
163
|
+
email: email,
|
|
164
|
+
termsOfServiceAgreed: true,
|
|
165
|
+
skipChallengeVerification: this.skipLocalVerify,
|
|
166
|
+
challengePriority: ["dns-01"],
|
|
167
|
+
challengeCreateFn: async (authz, challenge, keyAuthorization) => {
|
|
168
|
+
return await this.challengeCreateFn(authz, challenge, keyAuthorization, dnsProvider);
|
|
169
|
+
},
|
|
170
|
+
challengeRemoveFn: async (authz, challenge, keyAuthorization, recordItem) => {
|
|
171
|
+
return await this.challengeRemoveFn(authz, challenge, keyAuthorization, recordItem, dnsProvider);
|
|
172
|
+
},
|
|
173
|
+
});
|
|
174
|
+
const cert = {
|
|
175
|
+
crt: crt.toString(),
|
|
176
|
+
key: key.toString(),
|
|
177
|
+
csr: csr.toString(),
|
|
178
|
+
};
|
|
179
|
+
/* Done */
|
|
180
|
+
this.logger.debug(`CSR:\n${cert.csr}`);
|
|
181
|
+
this.logger.debug(`Certificate:\n${cert.crt}`);
|
|
182
|
+
this.logger.info("证书申请成功");
|
|
183
|
+
return cert;
|
|
184
|
+
}
|
|
185
|
+
buildCommonNameByDomains(domains) {
|
|
186
|
+
if (typeof domains === "string") {
|
|
187
|
+
domains = domains.split(",");
|
|
188
|
+
}
|
|
189
|
+
if (domains.length === 0) {
|
|
190
|
+
throw new Error("domain can not be empty");
|
|
191
|
+
}
|
|
192
|
+
const commonName = domains[0];
|
|
193
|
+
let altNames = undefined;
|
|
194
|
+
if (domains.length > 1) {
|
|
195
|
+
altNames = _.slice(domains, 1);
|
|
196
|
+
}
|
|
197
|
+
return {
|
|
198
|
+
commonName,
|
|
199
|
+
altNames,
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWNtZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9wbHVnaW4vY2VydC1wbHVnaW4vYWNtZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxhQUFhO0FBQ2IsT0FBTyxLQUFLLElBQUksTUFBTSxvQkFBb0IsQ0FBQztBQUMzQyxPQUFPLENBQUMsTUFBTSxXQUFXLENBQUM7QUFLMUIsT0FBTyxHQUFHLE1BQU0sS0FBSyxDQUFDO0FBU3RCLE1BQU0sT0FBTyxXQUFXO0lBQ3RCLFdBQVcsQ0FBVztJQUN0QixNQUFNLENBQVM7SUFDZixXQUFXLENBQWM7SUFDekIsZUFBZSxHQUFHLElBQUksQ0FBQztJQUN2QixHQUFHLENBQXVDO0lBQzFDLFlBQVksT0FNWDtRQUNDLElBQUksQ0FBQyxXQUFXLEdBQUcsT0FBTyxDQUFDLFdBQVcsQ0FBQztRQUN2QyxJQUFJLENBQUMsTUFBTSxHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUM7UUFDN0IsSUFBSSxDQUFDLFdBQVcsR0FBRyxPQUFPLENBQUMsV0FBVyxJQUFJLGFBQWEsQ0FBQztRQUN4RCxJQUFJLENBQUMsR0FBRyxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUM7UUFDdkIsSUFBSSxDQUFDLGVBQWUsR0FBRyxPQUFPLENBQUMsZUFBZSxJQUFJLEtBQUssQ0FBQztRQUN4RCxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsSUFBWSxFQUFFLEVBQUU7WUFDOUIsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDekIsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQsS0FBSyxDQUFDLGdCQUFnQixDQUFDLEtBQWE7UUFDbEMsT0FBTyxDQUFDLE1BQU0sSUFBSSxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLGVBQWUsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLElBQUksRUFBRSxDQUFDO0lBQzVFLENBQUM7SUFFRCxlQUFlLENBQUMs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
|
|
@@ -1,49 +1,49 @@
|
|
|
1
|
-
import { AbstractTaskPlugin, HttpClient, IAccessService, IContext, Step } from "@certd/pipeline";
|
|
2
|
-
import type { CertInfo } from "./acme.js";
|
|
3
|
-
import { Logger } from "log4js";
|
|
4
|
-
import { CertReader } from "./cert-reader.js";
|
|
5
|
-
export { CertReader };
|
|
6
|
-
export type { CertInfo };
|
|
7
|
-
export declare abstract class CertApplyBasePlugin extends AbstractTaskPlugin {
|
|
8
|
-
domains: string[];
|
|
9
|
-
email: string;
|
|
10
|
-
renewDays: number;
|
|
11
|
-
forceUpdate: string;
|
|
12
|
-
successNotify: boolean;
|
|
13
|
-
intro: string;
|
|
14
|
-
csrInfo: string;
|
|
15
|
-
logger: Logger;
|
|
16
|
-
userContext: IContext;
|
|
17
|
-
accessService: IAccessService;
|
|
18
|
-
http: HttpClient;
|
|
19
|
-
lastStatus: Step;
|
|
20
|
-
cert?: CertInfo;
|
|
21
|
-
onInstance(): Promise<void>;
|
|
22
|
-
abstract onInit(): Promise<void>;
|
|
23
|
-
abstract doCertApply(): Promise<any>;
|
|
24
|
-
execute(): Promise<void>;
|
|
25
|
-
output(certReader: CertReader, isNew: boolean): Promise<void>;
|
|
26
|
-
zipCert(cert: CertInfo, applyTime: string): Promise<void>;
|
|
27
|
-
/**
|
|
28
|
-
* 是否更新证书
|
|
29
|
-
*/
|
|
30
|
-
condition(): Promise<CertReader>;
|
|
31
|
-
formatCert(pem: string): string;
|
|
32
|
-
formatCerts(cert: {
|
|
33
|
-
crt: string;
|
|
34
|
-
key: string;
|
|
35
|
-
csr: string;
|
|
36
|
-
}): CertInfo;
|
|
37
|
-
readLastCert(): Promise<CertReader | undefined>;
|
|
38
|
-
/**
|
|
39
|
-
* 检查是否过期,默认提前20天
|
|
40
|
-
* @param expires
|
|
41
|
-
* @param maxDays
|
|
42
|
-
* @returns {boolean}
|
|
43
|
-
*/
|
|
44
|
-
isWillExpire(expires: number, maxDays?: number): {
|
|
45
|
-
isWillExpire: boolean;
|
|
46
|
-
leftDays: number;
|
|
47
|
-
};
|
|
48
|
-
private sendSuccessEmail;
|
|
49
|
-
}
|
|
1
|
+
import { AbstractTaskPlugin, HttpClient, IAccessService, IContext, Step } from "@certd/pipeline";
|
|
2
|
+
import type { CertInfo } from "./acme.js";
|
|
3
|
+
import { Logger } from "log4js";
|
|
4
|
+
import { CertReader } from "./cert-reader.js";
|
|
5
|
+
export { CertReader };
|
|
6
|
+
export type { CertInfo };
|
|
7
|
+
export declare abstract class CertApplyBasePlugin extends AbstractTaskPlugin {
|
|
8
|
+
domains: string[];
|
|
9
|
+
email: string;
|
|
10
|
+
renewDays: number;
|
|
11
|
+
forceUpdate: string;
|
|
12
|
+
successNotify: boolean;
|
|
13
|
+
intro: string;
|
|
14
|
+
csrInfo: string;
|
|
15
|
+
logger: Logger;
|
|
16
|
+
userContext: IContext;
|
|
17
|
+
accessService: IAccessService;
|
|
18
|
+
http: HttpClient;
|
|
19
|
+
lastStatus: Step;
|
|
20
|
+
cert?: CertInfo;
|
|
21
|
+
onInstance(): Promise<void>;
|
|
22
|
+
abstract onInit(): Promise<void>;
|
|
23
|
+
abstract doCertApply(): Promise<any>;
|
|
24
|
+
execute(): Promise<void>;
|
|
25
|
+
output(certReader: CertReader, isNew: boolean): Promise<void>;
|
|
26
|
+
zipCert(cert: CertInfo, applyTime: string): Promise<void>;
|
|
27
|
+
/**
|
|
28
|
+
* 是否更新证书
|
|
29
|
+
*/
|
|
30
|
+
condition(): Promise<CertReader>;
|
|
31
|
+
formatCert(pem: string): string;
|
|
32
|
+
formatCerts(cert: {
|
|
33
|
+
crt: string;
|
|
34
|
+
key: string;
|
|
35
|
+
csr: string;
|
|
36
|
+
}): CertInfo;
|
|
37
|
+
readLastCert(): Promise<CertReader | undefined>;
|
|
38
|
+
/**
|
|
39
|
+
* 检查是否过期,默认提前20天
|
|
40
|
+
* @param expires
|
|
41
|
+
* @param maxDays
|
|
42
|
+
* @returns {boolean}
|
|
43
|
+
*/
|
|
44
|
+
isWillExpire(expires: number, maxDays?: number): {
|
|
45
|
+
isWillExpire: boolean;
|
|
46
|
+
leftDays: number;
|
|
47
|
+
};
|
|
48
|
+
private sendSuccessEmail;
|
|
49
|
+
}
|
|
@@ -182,6 +182,7 @@ __decorate([
|
|
|
182
182
|
col: {
|
|
183
183
|
span: 24,
|
|
184
184
|
},
|
|
185
|
+
order: -1,
|
|
185
186
|
helper: "1、支持通配符域名,例如: *.foo.com、foo.com、*.test.handsfree.work\n" +
|
|
186
187
|
"2、支持多个域名、多个子域名、多个通配符域名打到一个证书上(域名必须是在同一个DNS提供商解析)\n" +
|
|
187
188
|
"3、多级子域名要分成多个域名输入(*.foo.com的证书不能用于xxx.yyy.foo.com、foo.com)\n" +
|
|
@@ -197,6 +198,7 @@ __decorate([
|
|
|
197
198
|
vModel: "value",
|
|
198
199
|
},
|
|
199
200
|
required: true,
|
|
201
|
+
order: -1,
|
|
200
202
|
helper: "请输入邮箱",
|
|
201
203
|
}),
|
|
202
204
|
__metadata("design:type", String)
|
|
@@ -204,6 +206,7 @@ __decorate([
|
|
|
204
206
|
__decorate([
|
|
205
207
|
TaskInput({
|
|
206
208
|
title: "更新天数",
|
|
209
|
+
value: 20,
|
|
207
210
|
component: {
|
|
208
211
|
name: "a-input-number",
|
|
209
212
|
vModel: "value",
|
|
@@ -253,4 +256,4 @@ __decorate([
|
|
|
253
256
|
}),
|
|
254
257
|
__metadata("design:type", Object)
|
|
255
258
|
], CertApplyBasePlugin.prototype, "cert", void 0);
|
|
256
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
259
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFzZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9wbHVnaW4vY2VydC1wbHVnaW4vYmFzZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7QUFBQSxPQUFPLEVBQUUsa0JBQWtCLEVBQThDLFNBQVMsRUFBRSxVQUFVLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUN4SCxPQUFPLEtBQUssTUFBTSxPQUFPLENBQUM7QUFHMUIsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBQzlDLE9BQU8sS0FBSyxNQUFNLE9BQU8sQ0FBQztBQUUxQixPQUFPLEVBQUUsVUFBVSxFQUFFLENBQUM7QUFHdEIsTUFBTSxPQUFnQixtQkFBb0IsU0FBUSxrQkFBa0I7SUFvQmxFLE9BQU8sQ0FBWTtJQVluQixLQUFLLENBQVU7SUFhZixTQUFTLENBQVU7SUFXbkIsV0FBVyxDQUFVO0lBWXJCLGFBQWEsR0FBRyxJQUFJLENBQUM7SUFPckIsS0FBSyxDQUFVO0lBRWYsZUFBZTtJQUNmLHNCQUFzQjtJQUN0QixxQkFBcUI7SUFDckIsS0FBSztJQUNMLE9BQU8sQ0FBVTtJQUVqQixNQUFNLENBQVU7SUFDaEIsV0FBVyxDQUFZO0lBQ3ZCLGFBQWEsQ0FBa0I7SUFDL0IsSUFBSSxDQUFjO0lBQ2xCLFVBQVUsQ0FBUTtJQUtsQixJQUFJLENBQVk7SUFFaEIsS0FBSyxDQUFDLFVBQVU7UUFDZCxJQUFJLENBQUMsYUFBYSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsYUFBYSxDQUFDO1FBQzVDLElBQUksQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUM7UUFDOUIsSUFBSSxDQUFDLFdBQVcsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLFdBQVcsQ0FBQztRQUN4QyxJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDO1FBQzFCLElBQUksQ0FBQyxVQUFVLEdB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
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import { CertInfo } from "./acme.js";
|
|
2
|
-
import forge from "node-forge";
|
|
3
|
-
export declare class CertReader implements CertInfo {
|
|
4
|
-
crt: string;
|
|
5
|
-
key: string;
|
|
6
|
-
csr: string;
|
|
7
|
-
detail: any;
|
|
8
|
-
expires: number;
|
|
9
|
-
constructor(certInfo: CertInfo);
|
|
10
|
-
toCertInfo(): CertInfo;
|
|
11
|
-
getCrtDetail(crt: string): {
|
|
12
|
-
detail: forge.pki.Certificate;
|
|
13
|
-
expires: Date;
|
|
14
|
-
};
|
|
15
|
-
saveToFile(type: "crt" | "key", filepath?: string): string;
|
|
16
|
-
}
|
|
1
|
+
import { CertInfo } from "./acme.js";
|
|
2
|
+
import forge from "node-forge";
|
|
3
|
+
export declare class CertReader implements CertInfo {
|
|
4
|
+
crt: string;
|
|
5
|
+
key: string;
|
|
6
|
+
csr: string;
|
|
7
|
+
detail: any;
|
|
8
|
+
expires: number;
|
|
9
|
+
constructor(certInfo: CertInfo);
|
|
10
|
+
toCertInfo(): CertInfo;
|
|
11
|
+
getCrtDetail(crt: string): {
|
|
12
|
+
detail: forge.pki.Certificate;
|
|
13
|
+
expires: Date;
|
|
14
|
+
};
|
|
15
|
+
saveToFile(type: "crt" | "key", filepath?: string): string;
|
|
16
|
+
}
|