@certd/plugin-lib 1.41.3 → 1.42.0
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/.mocharc.json +1 -1
- package/CHANGELOG.md +19 -0
- package/dist/cert/cert-reader.d.ts +4 -2
- package/dist/cert/cert-reader.d.ts.map +1 -1
- package/dist/cert/cert-reader.js +66 -3
- package/dist/cert/convert.js +1 -1
- package/dist/cert/dns-provider/api.d.ts +4 -1
- package/dist/cert/dns-provider/api.d.ts.map +1 -1
- package/dist/cert/dns-provider/base.d.ts +4 -2
- package/dist/cert/dns-provider/base.d.ts.map +1 -1
- package/dist/cert/dns-provider/base.js +16 -2
- package/package.json +21 -37
- package/test/cert-reader.test.ts +109 -0
package/.mocharc.json
CHANGED
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,25 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
# [1.42.0](https://github.com/certd/certd/compare/v1.41.4...v1.42.0) (2026-07-05)
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
* 修复jdk证书格式的问题 ([260f5ae](https://github.com/certd/certd/commit/260f5ae777b83493b0c578fe30fd00ec0c873226))
|
|
11
|
+
|
|
12
|
+
### Features
|
|
13
|
+
|
|
14
|
+
* 通过插件配置懒加载依赖,动态加载第三方依赖包,精简安装镜像大小 ([01568ca](https://github.com/certd/certd/commit/01568ca1489069046b5a89ebdd4ced2f7f6ddf93))
|
|
15
|
+
|
|
16
|
+
### Performance Improvements
|
|
17
|
+
|
|
18
|
+
* 【破坏性更新】 证书压缩包不再生成文件存储,而是实时打包下载,证书申请插件不再输出certZip ([7cff1a9](https://github.com/certd/certd/commit/7cff1a98424120585205889874b3ef4956a30583))
|
|
19
|
+
* 新增橙域网络(asia-isp) CDN证书部署插件 ([b48831e](https://github.com/certd/certd/commit/b48831e60b0059bef7ef9a34ab61c9dd2f684641))
|
|
20
|
+
|
|
21
|
+
## [1.41.4](https://github.com/certd/certd/compare/v1.41.3...v1.41.4) (2026-06-14)
|
|
22
|
+
|
|
23
|
+
**Note:** Version bump only for package @certd/plugin-lib
|
|
24
|
+
|
|
6
25
|
## [1.41.3](https://github.com/certd/certd/compare/v1.41.2...v1.41.3) (2026-06-11)
|
|
7
26
|
|
|
8
27
|
**Note:** Version bump only for package @certd/plugin-lib
|
|
@@ -74,8 +74,10 @@ export declare class CertReader {
|
|
|
74
74
|
saveToFile(type: "crt" | "key" | "pfx" | "der" | "oc" | "one" | "ic" | "jks" | "p7b", filepath?: string): string;
|
|
75
75
|
readCertFile(opts: HandleOpts): Promise<void>;
|
|
76
76
|
buildCertFileName(suffix: string, applyTime: any, prefix?: string): string;
|
|
77
|
-
buildCertName(prefix?: string): string;
|
|
77
|
+
buildCertName(prefix?: string, useHash?: boolean): string;
|
|
78
78
|
static appendTimeSuffix(name?: string): string;
|
|
79
|
-
static buildCertName(cert: CertInfo): string;
|
|
79
|
+
static buildCertName(cert: CertInfo, useHash?: boolean): string;
|
|
80
|
+
buildZip(): Promise<Buffer>;
|
|
81
|
+
buildZipFilename(prefix?: string): string;
|
|
80
82
|
}
|
|
81
83
|
//# sourceMappingURL=cert-reader.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cert-reader.d.ts","sourceRoot":"","sources":["../../src/cert/cert-reader.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,eAAe,EAAU,MAAM,oBAAoB,CAAC;AAE7D,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"cert-reader.d.ts","sourceRoot":"","sources":["../../src/cert/cert-reader.ts"],"names":[],"mappings":"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"}
|
package/dist/cert/cert-reader.js
CHANGED
|
@@ -5,6 +5,7 @@ import { crypto } from "@certd/acme-client";
|
|
|
5
5
|
import cryptoLib from "crypto";
|
|
6
6
|
import dayjs from "dayjs";
|
|
7
7
|
import { uniq } from "lodash-es";
|
|
8
|
+
import JSZip from "jszip";
|
|
8
9
|
const formats = {
|
|
9
10
|
pem: ["crt", "key", "ic"],
|
|
10
11
|
one: ["one"],
|
|
@@ -222,9 +223,14 @@ export class CertReader {
|
|
|
222
223
|
const timeStr = dayjs(applyTime).format("YYYYMMDDHHmmss");
|
|
223
224
|
return `${prefix}_${domain}_${timeStr}.${suffix}`;
|
|
224
225
|
}
|
|
225
|
-
buildCertName(prefix = "") {
|
|
226
|
+
buildCertName(prefix = "", useHash = false) {
|
|
226
227
|
let domain = this.getMainDomain();
|
|
227
228
|
domain = domain.replaceAll(".", "_").replaceAll("*", "_");
|
|
229
|
+
if (useHash) {
|
|
230
|
+
const domains = JSON.stringify(this.getAllDomains());
|
|
231
|
+
const hash = cryptoLib.createHash("md5").update(domains).digest("hex").slice(0, 16);
|
|
232
|
+
return `${prefix}_${domain}_${hash}`;
|
|
233
|
+
}
|
|
228
234
|
return `${prefix}_${domain}_${dayjs().format("YYYYMMDDHHmmssSSS")}`;
|
|
229
235
|
}
|
|
230
236
|
static appendTimeSuffix(name) {
|
|
@@ -233,7 +239,64 @@ export class CertReader {
|
|
|
233
239
|
}
|
|
234
240
|
return name + "_" + dayjs().format("YYYYMMDDHHmmssSSS");
|
|
235
241
|
}
|
|
236
|
-
static buildCertName(cert) {
|
|
237
|
-
return new CertReader(cert).buildCertName();
|
|
242
|
+
static buildCertName(cert, useHash = false) {
|
|
243
|
+
return new CertReader(cert).buildCertName("", useHash);
|
|
244
|
+
}
|
|
245
|
+
async buildZip() {
|
|
246
|
+
const cert = this.cert;
|
|
247
|
+
const zip = new JSZip();
|
|
248
|
+
if (cert.crt) {
|
|
249
|
+
zip.file("证书.pem", cert.crt);
|
|
250
|
+
}
|
|
251
|
+
if (cert.key) {
|
|
252
|
+
zip.file("私钥.pem", cert.key);
|
|
253
|
+
}
|
|
254
|
+
if (cert.ic) {
|
|
255
|
+
zip.file("中间证书.pem", cert.ic);
|
|
256
|
+
}
|
|
257
|
+
if (cert.crt) {
|
|
258
|
+
zip.file("cert.crt", cert.crt);
|
|
259
|
+
}
|
|
260
|
+
if (cert.key) {
|
|
261
|
+
zip.file("cert.key", cert.key);
|
|
262
|
+
}
|
|
263
|
+
if (cert.ic) {
|
|
264
|
+
zip.file("intermediate.crt", cert.ic);
|
|
265
|
+
}
|
|
266
|
+
if (cert.oc) {
|
|
267
|
+
zip.file("origin.crt", cert.oc);
|
|
268
|
+
}
|
|
269
|
+
if (cert.one) {
|
|
270
|
+
zip.file("one.pem", cert.one);
|
|
271
|
+
}
|
|
272
|
+
if (cert.p7b) {
|
|
273
|
+
zip.file("cert.p7b", cert.p7b);
|
|
274
|
+
}
|
|
275
|
+
if (cert.pfx) {
|
|
276
|
+
zip.file("cert.pfx", Buffer.from(cert.pfx, "base64"));
|
|
277
|
+
}
|
|
278
|
+
if (cert.der) {
|
|
279
|
+
zip.file("cert.der", Buffer.from(cert.der, "base64"));
|
|
280
|
+
}
|
|
281
|
+
if (cert.jks) {
|
|
282
|
+
zip.file("cert.jks", Buffer.from(cert.jks, "base64"));
|
|
283
|
+
}
|
|
284
|
+
zip.file("说明.txt", `证书文件说明
|
|
285
|
+
cert.crt:证书文件,包含证书链,pem格式
|
|
286
|
+
cert.key:私钥文件,pem格式
|
|
287
|
+
intermediate.crt:中间证书文件,pem格式
|
|
288
|
+
origin.crt:原始证书文件,不含证书链,pem格式
|
|
289
|
+
one.pem: 证书和私钥简单合并成一个文件,pem格式,crt正文+key正文
|
|
290
|
+
cert.pfx:pfx格式证书文件,iis服务器使用
|
|
291
|
+
cert.der:der格式证书文件
|
|
292
|
+
cert.jks:jks格式证书文件,java服务器使用
|
|
293
|
+
`);
|
|
294
|
+
return zip.generateAsync({ type: "nodebuffer" });
|
|
295
|
+
}
|
|
296
|
+
buildZipFilename(prefix = "cert") {
|
|
297
|
+
let domain = this.getMainDomain();
|
|
298
|
+
domain = domain.replaceAll(".", "_").replaceAll("*", "_");
|
|
299
|
+
const timeStr = dayjs().format("YYYYMMDDHHmmss");
|
|
300
|
+
return `${prefix}_${domain}_${timeStr}.zip`;
|
|
238
301
|
}
|
|
239
302
|
}
|
package/dist/cert/convert.js
CHANGED
|
@@ -107,7 +107,7 @@ export class CertConverter {
|
|
|
107
107
|
if (!fs.existsSync(dir)) {
|
|
108
108
|
fs.mkdirSync(dir, { recursive: true });
|
|
109
109
|
}
|
|
110
|
-
await this.exec(`keytool -importkeystore -srckeystore ${p12Path} -srcstoretype PKCS12 -srcstorepass "${jksPassword}" -destkeystore ${jksPath} -deststoretype
|
|
110
|
+
await this.exec(`keytool -importkeystore -srckeystore ${p12Path} -srcstoretype PKCS12 -srcstorepass "${jksPassword}" -destkeystore ${jksPath} -deststoretype JKS -deststorepass "${jksPassword}" `);
|
|
111
111
|
fs.unlinkSync(p12Path);
|
|
112
112
|
const fileBuffer = fs.readFileSync(jksPath);
|
|
113
113
|
const certBase64 = fileBuffer.toString("base64");
|
|
@@ -3,6 +3,8 @@ import { IAccess, IAccessService, IServiceGetter, PageRes, PageSearch, Registrab
|
|
|
3
3
|
export type DnsProviderDefine = Registrable & {
|
|
4
4
|
accessType: string;
|
|
5
5
|
icon?: string;
|
|
6
|
+
dependPlugins?: Record<string, string>;
|
|
7
|
+
dependPackages?: Record<string, string>;
|
|
6
8
|
};
|
|
7
9
|
export type CreateRecordOptions = {
|
|
8
10
|
domain: string;
|
|
@@ -23,6 +25,7 @@ export type DnsProviderContext = {
|
|
|
23
25
|
domainParser: IDomainParser;
|
|
24
26
|
serviceGetter: IServiceGetter;
|
|
25
27
|
accessGetter?: IAccessService;
|
|
28
|
+
define?: DnsProviderDefine;
|
|
26
29
|
};
|
|
27
30
|
export type DomainRecord = {
|
|
28
31
|
id: string;
|
|
@@ -49,7 +52,7 @@ export interface IDnsProvider<T = any> {
|
|
|
49
52
|
punyCodeDecode(domain: string): string;
|
|
50
53
|
createRecord(options: CreateRecordOptions): Promise<T>;
|
|
51
54
|
removeRecord(options: RemoveRecordOptions<T>): Promise<void>;
|
|
52
|
-
setCtx(ctx: DnsProviderContext): void
|
|
55
|
+
setCtx(ctx: DnsProviderContext): Promise<void>;
|
|
53
56
|
usePunyCode(): boolean;
|
|
54
57
|
getDomainListPage(pager: PageSearch): Promise<PageRes<DomainRecord>>;
|
|
55
58
|
getRecordListPage?(domain: string, pager: PageSearch): Promise<PageRes<DnsResolveRecord>>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../../src/cert/dns-provider/api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAE5G,MAAM,MAAM,iBAAiB,GAAG,WAAW,GAAG;IAC5C,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../../src/cert/dns-provider/api.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { HttpClient, ILogger } from "@certd/basic";
|
|
2
|
-
import { PageRes, PageSearch } from "@certd/pipeline";
|
|
2
|
+
import { IRuntimeDepsService, PageRes, PageSearch } from "@certd/pipeline";
|
|
3
3
|
import { CreateRecordOptions, DnsProviderContext, DnsResolveRecord, DomainRecord, IDnsProvider, RemoveRecordOptions } from "./api.js";
|
|
4
4
|
export declare abstract class AbstractDnsProvider<T = any> implements IDnsProvider<T> {
|
|
5
5
|
ctx: DnsProviderContext;
|
|
6
6
|
http: HttpClient;
|
|
7
7
|
logger: ILogger;
|
|
8
|
+
runtimeDepsService?: IRuntimeDepsService;
|
|
9
|
+
importRuntime(specifier: string): Promise<any>;
|
|
8
10
|
usePunyCode(): boolean;
|
|
9
11
|
/**
|
|
10
12
|
* 中文转英文
|
|
@@ -16,7 +18,7 @@ export declare abstract class AbstractDnsProvider<T = any> implements IDnsProvid
|
|
|
16
18
|
* @param domain
|
|
17
19
|
*/
|
|
18
20
|
punyCodeDecode(domain: string): any;
|
|
19
|
-
setCtx(ctx: DnsProviderContext): void
|
|
21
|
+
setCtx(ctx: DnsProviderContext): Promise<void>;
|
|
20
22
|
parseDomain(fullDomain: string): Promise<string>;
|
|
21
23
|
abstract createRecord(options: CreateRecordOptions): Promise<T>;
|
|
22
24
|
abstract onInstance(): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../../src/cert/dns-provider/base.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAkB,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../../src/cert/dns-provider/base.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAkB,mBAAmB,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE3F,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAqB,gBAAgB,EAAE,YAAY,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAEzJ,8BAAsB,mBAAmB,CAAC,CAAC,GAAG,GAAG,CAAE,YAAW,YAAY,CAAC,CAAC,CAAC;IAC3E,GAAG,EAAG,kBAAkB,CAAC;IACzB,IAAI,EAAG,UAAU,CAAC;IAClB,MAAM,EAAG,OAAO,CAAC;IACjB,kBAAkB,CAAC,EAAE,mBAAmB,CAAC;IAEnC,aAAa,CAAC,SAAS,EAAE,MAAM;IAOrC,WAAW,IAAI,OAAO;IAMtB;;;OAGG;IACH,cAAc,CAAC,MAAM,EAAE,MAAM;IAI7B;;;OAGG;IACH,cAAc,CAAC,MAAM,EAAE,MAAM;IAIvB,MAAM,CAAC,GAAG,EAAE,kBAAkB;IAY9B,WAAW,CAAC,UAAU,EAAE,MAAM;IAIpC,QAAQ,CAAC,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,CAAC,CAAC;IAE/D,QAAQ,CAAC,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAEpC,QAAQ,CAAC,YAAY,CAAC,OAAO,EAAE,mBAAmB,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAE/D,iBAAiB,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IAIlE,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;CAG7F;AAED,wBAAsB,iBAAiB,CAAC,IAAI,EAAE;IAAE,eAAe,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,kBAAkB,CAAA;CAAE,GAAG,OAAO,CAAC,YAAY,CAAC,CAmB7H"}
|
|
@@ -4,6 +4,13 @@ export class AbstractDnsProvider {
|
|
|
4
4
|
ctx;
|
|
5
5
|
http;
|
|
6
6
|
logger;
|
|
7
|
+
runtimeDepsService;
|
|
8
|
+
async importRuntime(specifier) {
|
|
9
|
+
if (!this.runtimeDepsService) {
|
|
10
|
+
throw new Error("runtimeDepsService 未初始化");
|
|
11
|
+
}
|
|
12
|
+
return await this.runtimeDepsService.importRuntime(specifier, this.logger);
|
|
13
|
+
}
|
|
7
14
|
usePunyCode() {
|
|
8
15
|
//是否使用punycode来添加解析记录
|
|
9
16
|
//默认都使用原始中文域名来添加
|
|
@@ -23,10 +30,16 @@ export class AbstractDnsProvider {
|
|
|
23
30
|
punyCodeDecode(domain) {
|
|
24
31
|
return punycode.toUnicode(domain);
|
|
25
32
|
}
|
|
26
|
-
setCtx(ctx) {
|
|
33
|
+
async setCtx(ctx) {
|
|
27
34
|
this.ctx = ctx;
|
|
28
35
|
this.logger = ctx.logger;
|
|
29
36
|
this.http = ctx.http;
|
|
37
|
+
if (!this.runtimeDepsService && this.ctx.serviceGetter) {
|
|
38
|
+
this.runtimeDepsService = await this.ctx.serviceGetter.get("runtimeDepsService");
|
|
39
|
+
}
|
|
40
|
+
if (this.runtimeDepsService && this.ctx.define?.name) {
|
|
41
|
+
await this.runtimeDepsService.ensureRuntimeDependencies({ pluginKeys: `dnsProvider:${this.ctx.define.name}`, logger: this.logger });
|
|
42
|
+
}
|
|
30
43
|
}
|
|
31
44
|
async parseDomain(fullDomain) {
|
|
32
45
|
return await this.ctx.domainParser.parse(fullDomain);
|
|
@@ -50,9 +63,10 @@ export async function createDnsProvider(opts) {
|
|
|
50
63
|
const accessGetter = await context.serviceGetter.get("accessService");
|
|
51
64
|
context.accessGetter = accessGetter;
|
|
52
65
|
}
|
|
66
|
+
context.define = dnsProviderDefine;
|
|
53
67
|
// @ts-ignore
|
|
54
68
|
const dnsProvider = new DnsProviderClass();
|
|
55
|
-
dnsProvider.setCtx(context);
|
|
69
|
+
await dnsProvider.setCtx(context);
|
|
56
70
|
await dnsProvider.onInstance();
|
|
57
71
|
return dnsProvider;
|
|
58
72
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@certd/plugin-lib",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.42.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
7
7
|
"types": "./dist/index.d.ts",
|
|
@@ -10,56 +10,40 @@
|
|
|
10
10
|
"before-build": "rimraf dist && rimraf tsconfig.tsbuildinfo && rimraf .rollup.cache",
|
|
11
11
|
"build": "npm run before-build && tsc -p tsconfig.build.json --skipLibCheck",
|
|
12
12
|
"dev-build": "npm run build",
|
|
13
|
-
"
|
|
14
|
-
"build2": "vue-tsc --noEmit && vite build",
|
|
15
|
-
"preview": "vite preview",
|
|
16
|
-
"test:unit": "cross-env NODE_ENV=unittest mocha --no-config --node-option no-warnings --node-option loader=ts-node/esm \"src/**/*.test.ts\"",
|
|
13
|
+
"test:unit": "cross-env NODE_ENV=unittest mocha",
|
|
17
14
|
"pub": "npm publish",
|
|
18
|
-
"compile": "tsc --skipLibCheck --watch"
|
|
15
|
+
"compile": "tsc --skipLibCheck --watch",
|
|
16
|
+
"format": "prettier --write src",
|
|
17
|
+
"lint": "eslint --fix"
|
|
19
18
|
},
|
|
20
19
|
"dependencies": {
|
|
21
|
-
"@
|
|
22
|
-
"@
|
|
23
|
-
"@
|
|
24
|
-
"@alicloud/tea-util": "^1.4.11",
|
|
25
|
-
"@aws-sdk/client-s3": "^3.964.0",
|
|
26
|
-
"@certd/acme-client": "^1.41.3",
|
|
27
|
-
"@certd/basic": "^1.41.3",
|
|
28
|
-
"@certd/pipeline": "^1.41.3",
|
|
29
|
-
"@certd/plus-core": "^1.41.3",
|
|
30
|
-
"@kubernetes/client-node": "0.21.0",
|
|
31
|
-
"ali-oss": "^6.22.0",
|
|
32
|
-
"basic-ftp": "^5.0.5",
|
|
33
|
-
"cos-nodejs-sdk-v5": "^2.15.4",
|
|
20
|
+
"@certd/acme-client": "^1.42.0",
|
|
21
|
+
"@certd/basic": "^1.42.0",
|
|
22
|
+
"@certd/pipeline": "^1.42.0",
|
|
34
23
|
"dayjs": "^1.11.7",
|
|
35
|
-
"
|
|
24
|
+
"jszip": "^3.10.1",
|
|
36
25
|
"lodash-es": "^4.17.21",
|
|
37
26
|
"psl": "^1.15.0",
|
|
38
|
-
"punycode.js": "^2.3.1"
|
|
39
|
-
"qiniu": "^7.12.0",
|
|
40
|
-
"rimraf": "^5.0.5",
|
|
41
|
-
"socks": "^2.8.3",
|
|
42
|
-
"socks-proxy-agent": "^8.0.4",
|
|
43
|
-
"ssh2": "1.17.0",
|
|
44
|
-
"strip-ansi": "^7.1.0",
|
|
45
|
-
"tencentcloud-sdk-nodejs": "^4.1.166"
|
|
27
|
+
"punycode.js": "^2.3.1"
|
|
46
28
|
},
|
|
47
29
|
"devDependencies": {
|
|
48
|
-
"@types/chai": "^4.3.
|
|
49
|
-
"@types/mocha": "^10.0.
|
|
30
|
+
"@types/chai": "^4.3.12",
|
|
31
|
+
"@types/mocha": "^10.0.6",
|
|
50
32
|
"@typescript-eslint/eslint-plugin": "^8.26.1",
|
|
51
33
|
"@typescript-eslint/parser": "^8.26.1",
|
|
52
|
-
"chai": "^
|
|
34
|
+
"chai": "^5.1.0",
|
|
53
35
|
"cross-env": "^7.0.3",
|
|
54
|
-
"eslint": "^8.
|
|
55
|
-
"eslint-config-prettier": "^
|
|
56
|
-
"eslint-plugin-prettier": "^
|
|
36
|
+
"eslint": "^8.57.0",
|
|
37
|
+
"eslint-config-prettier": "^9.1.0",
|
|
38
|
+
"eslint-plugin-prettier": "^5.1.3",
|
|
57
39
|
"esmock": "^2.7.5",
|
|
58
|
-
"mocha": "^10.
|
|
59
|
-
"
|
|
40
|
+
"mocha": "^10.6.0",
|
|
41
|
+
"node-forge": "^1.3.1",
|
|
42
|
+
"prettier": "3.3.3",
|
|
43
|
+
"rimraf": "^5.0.5",
|
|
60
44
|
"ts-node": "^10.9.2",
|
|
61
45
|
"tslib": "^2.8.1",
|
|
62
46
|
"typescript": "^5.4.2"
|
|
63
47
|
},
|
|
64
|
-
"gitHead": "
|
|
48
|
+
"gitHead": "b46948c0ba67069ebcd2bb71b21b6c289d99f1b8"
|
|
65
49
|
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/// <reference types="mocha" />
|
|
2
|
+
/// <reference types="node" />
|
|
3
|
+
|
|
4
|
+
import assert from "node:assert/strict";
|
|
5
|
+
|
|
6
|
+
import { CertReader } from "../src/cert/cert-reader.js";
|
|
7
|
+
import type { CertInfo } from "../src/cert/cert-reader.js";
|
|
8
|
+
|
|
9
|
+
// @ts-ignore
|
|
10
|
+
import forge from "node-forge";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Generate a minimal self-signed X.509 cert + key in PEM format for testing.
|
|
14
|
+
*/
|
|
15
|
+
function createSelfSignedCert(commonName: string): { crt: string; key: string } {
|
|
16
|
+
const keypair = forge.pki.rsa.generateKeyPair(2048);
|
|
17
|
+
|
|
18
|
+
const cert = forge.pki.createCertificate();
|
|
19
|
+
cert.publicKey = keypair.publicKey;
|
|
20
|
+
cert.serialNumber = "01";
|
|
21
|
+
cert.validFrom = new Date("2025-01-01").toISOString();
|
|
22
|
+
cert.validTo = new Date("2026-01-01").toISOString();
|
|
23
|
+
|
|
24
|
+
const attrs = [{ name: "commonName", value: commonName }];
|
|
25
|
+
cert.setSubject(attrs);
|
|
26
|
+
cert.setIssuer(attrs);
|
|
27
|
+
cert.sign(keypair.privateKey, forge.md.sha256.create());
|
|
28
|
+
|
|
29
|
+
return {
|
|
30
|
+
crt: forge.pki.certificateToPem(cert),
|
|
31
|
+
key: forge.pki.privateKeyToPem(keypair.privateKey),
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const testCert = createSelfSignedCert("example.com");
|
|
36
|
+
const testCertIc = createSelfSignedCert("intermediate.ca");
|
|
37
|
+
const mockCertInfo: CertInfo = {
|
|
38
|
+
crt: testCert.crt + "\n" + testCertIc.crt,
|
|
39
|
+
key: testCert.key,
|
|
40
|
+
oc: testCert.crt,
|
|
41
|
+
ic: testCertIc.crt,
|
|
42
|
+
one: testCert.crt + "\n" + testCert.key,
|
|
43
|
+
p7b: "PKCS7 test content",
|
|
44
|
+
pfx: Buffer.from("fake-pfx-data").toString("base64"),
|
|
45
|
+
der: Buffer.from("fake-der-data").toString("base64"),
|
|
46
|
+
jks: Buffer.from("fake-jks-data").toString("base64"),
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
describe("CertReader.buildZip", () => {
|
|
50
|
+
it("returns a non-empty Buffer", async () => {
|
|
51
|
+
const reader = new CertReader(mockCertInfo);
|
|
52
|
+
const buf = await reader.buildZip();
|
|
53
|
+
assert.ok(Buffer.isBuffer(buf));
|
|
54
|
+
assert.ok(buf.length > 0);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it("produces a valid zip containing expected files", async () => {
|
|
58
|
+
const reader = new CertReader(mockCertInfo);
|
|
59
|
+
const buf = await reader.buildZip();
|
|
60
|
+
const { default: JSZip } = await import("jszip");
|
|
61
|
+
const zip = await JSZip.loadAsync(buf);
|
|
62
|
+
|
|
63
|
+
assert.ok(zip.file("证书.pem"), "should contain 证书.pem");
|
|
64
|
+
assert.ok(zip.file("私钥.pem"), "should contain 私钥.pem");
|
|
65
|
+
assert.ok(zip.file("中间证书.pem"), "should contain 中间证书.pem");
|
|
66
|
+
assert.ok(zip.file("cert.crt"), "should contain cert.crt");
|
|
67
|
+
assert.ok(zip.file("cert.key"), "should contain cert.key");
|
|
68
|
+
assert.ok(zip.file("intermediate.crt"), "should contain intermediate.crt");
|
|
69
|
+
assert.ok(zip.file("origin.crt"), "should contain origin.crt");
|
|
70
|
+
assert.ok(zip.file("one.pem"), "should contain one.pem");
|
|
71
|
+
assert.ok(zip.file("cert.p7b"), "should contain cert.p7b");
|
|
72
|
+
assert.ok(zip.file("cert.pfx"), "should contain cert.pfx");
|
|
73
|
+
assert.ok(zip.file("cert.der"), "should contain cert.der");
|
|
74
|
+
assert.ok(zip.file("cert.jks"), "should contain cert.jks");
|
|
75
|
+
assert.ok(zip.file("说明.txt"), "should contain 说明.txt");
|
|
76
|
+
|
|
77
|
+
const pemContent = await zip.file("证书.pem").async("string");
|
|
78
|
+
assert.ok(pemContent.includes("-----BEGIN CERTIFICATE-----"));
|
|
79
|
+
|
|
80
|
+
const pfx = await zip.file("cert.pfx").async("nodebuffer");
|
|
81
|
+
assert.equal(pfx.toString(), "fake-pfx-data");
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
describe("CertReader.buildZipFilename", () => {
|
|
86
|
+
it("includes the main domain and timestamp", () => {
|
|
87
|
+
const reader = new CertReader(mockCertInfo);
|
|
88
|
+
const name = reader.buildZipFilename("cert");
|
|
89
|
+
assert.ok(name.startsWith("cert_example_com_"));
|
|
90
|
+
assert.ok(name.endsWith(".zip"));
|
|
91
|
+
const tsPart = name.replace("cert_example_com_", "").replace(".zip", "");
|
|
92
|
+
assert.match(tsPart, /^\d{14}$/);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it("uses the default prefix when not provided", () => {
|
|
96
|
+
const reader = new CertReader(mockCertInfo);
|
|
97
|
+
const name = reader.buildZipFilename();
|
|
98
|
+
assert.ok(name.startsWith("cert_example_com_"));
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
it("wildcard domain replaces asterisk", () => {
|
|
102
|
+
const wildcardCert = createSelfSignedCert("*.example.com");
|
|
103
|
+
const wcInfo: CertInfo = { crt: wildcardCert.crt, key: wildcardCert.key };
|
|
104
|
+
const reader = new CertReader(wcInfo);
|
|
105
|
+
const name = reader.buildZipFilename("cert");
|
|
106
|
+
assert.ok(name.startsWith("cert___example_com_"), "asterisk should be replaced, got: " + name);
|
|
107
|
+
assert.ok(!name.includes("*"));
|
|
108
|
+
});
|
|
109
|
+
});
|