@certd/plugin-cert 1.0.2 → 1.0.3

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/package.json CHANGED
@@ -1,18 +1,19 @@
1
1
  {
2
2
  "name": "@certd/plugin-cert",
3
3
  "private": false,
4
- "version": "1.0.2",
5
- "main": "./dist/plugin-cert.umd.js",
4
+ "version": "1.0.3",
5
+ "main": "./dist/bundle.js",
6
6
  "module": "./dist/plugin-cert.mjs",
7
7
  "types": "./dist/es/plugin-cert.d.ts",
8
8
  "scripts": {
9
9
  "dev": "vite",
10
- "build": "vue-tsc --noEmit && vite build",
10
+ "build": "rollup -c",
11
+ "build2": "vue-tsc --noEmit && vite build",
11
12
  "preview": "vite preview"
12
13
  },
13
14
  "dependencies": {
14
- "@certd/acme-client": "^1.0.2",
15
- "@certd/pipeline": "^1.0.2",
15
+ "@certd/acme-client": "^1.0.3",
16
+ "@certd/pipeline": "^1.0.3",
16
17
  "node-forge": "^0.10.0"
17
18
  },
18
19
  "devDependencies": {
@@ -21,6 +22,11 @@
21
22
  "@alicloud/pop-core": "^1.7.10",
22
23
  "@midwayjs/core": "^3.0.0",
23
24
  "@midwayjs/decorator": "^3.0.0",
25
+ "@rollup/plugin-commonjs": "^23.0.4",
26
+ "@rollup/plugin-json": "^6.0.0",
27
+ "@rollup/plugin-node-resolve": "^15.0.1",
28
+ "@rollup/plugin-terser": "^0.4.3",
29
+ "@rollup/plugin-typescript": "^11.0.0",
24
30
  "@types/chai": "^4.3.3",
25
31
  "@types/lodash": "^4.14.186",
26
32
  "@types/mocha": "^10.0.0",
@@ -37,10 +43,13 @@
37
43
  "lodash": "^4.17.21",
38
44
  "log4js": "^6.7.1",
39
45
  "mocha": "^10.1.0",
46
+ "rollup": "^3.7.4",
47
+ "rollup-plugin-visualizer": "^5.8.2",
40
48
  "ts-node": "^10.9.1",
49
+ "tslib": "^2.5.2",
41
50
  "typescript": "^4.8.4",
42
51
  "vite": "^3.1.0",
43
52
  "vue-tsc": "^0.38.9"
44
53
  },
45
- "gitHead": "1a738403fcb2732c0797b51cba15ad2b18b66523"
54
+ "gitHead": "a43c5b0824d2cb19a731c16f62c5e7464f6635d6"
46
55
  }
@@ -0,0 +1,35 @@
1
+ const resolve = require("@rollup/plugin-node-resolve");
2
+ const commonjs = require("@rollup/plugin-commonjs");
3
+ const rollupTypescript = require("rollup-plugin-typescript2");
4
+ const json = require("@rollup/plugin-json");
5
+ const terser = require("@rollup/plugin-terser");
6
+ module.exports = {
7
+ input: "src/index.ts",
8
+ output: {
9
+ file: "dist/bundle.js",
10
+ format: "cjs",
11
+ },
12
+ plugins: [
13
+ // 解析第三方依赖
14
+ resolve(),
15
+ // 识别 commonjs 模式第三方依赖
16
+ commonjs(),
17
+ rollupTypescript(),
18
+ json(),
19
+ terser(),
20
+ ],
21
+ external: [
22
+ "vue",
23
+ "lodash",
24
+ "dayjs",
25
+ "@certd/acme-client",
26
+ "@certd/pipeline",
27
+ "@certd/plugin-cert",
28
+ "@certd/plugin-aliyun",
29
+ "@certd/plugin-tencent",
30
+ "@certd/plugin-huawei",
31
+ "@certd/plugin-host",
32
+ "@certd/plugin-tencent",
33
+ "@certd/plugin-util",
34
+ ],
35
+ };
package/tsconfig.json CHANGED
@@ -1,9 +1,8 @@
1
1
  {
2
2
  "compilerOptions": {
3
- "noImplicitAny": true,
4
3
  "target": "ESNext",
5
4
  "useDefineForClassFields": true,
6
- "module": "commonjs",
5
+ "module": "ESNext",
7
6
  "moduleResolution": "Node",
8
7
  "strict": true,
9
8
  "jsx": "preserve",
package/vite.config.ts CHANGED
@@ -1,22 +1,54 @@
1
1
  import { defineConfig } from "vite";
2
+ import visualizer from "rollup-plugin-visualizer";
3
+ import typescript from "@rollup/plugin-typescript";
2
4
  // https://vitejs.dev/config/
3
5
  export default defineConfig({
4
6
  plugins: [],
5
7
  build: {
6
8
  lib: {
7
9
  entry: "src/index.ts",
8
- name: "pipeline",
10
+ name: "CertdPluginCert",
9
11
  },
10
12
  rollupOptions: {
11
- external: ["vue", "lodash", "dayjs", "@fast-crud/fast-crud"],
13
+ plugins: [
14
+ // @ts-ignore
15
+ visualizer(),
16
+ // @ts-ignore
17
+ typescript({
18
+ target: "esnext",
19
+ rootDir: "src",
20
+ declaration: true,
21
+ declarationDir: "dist/d",
22
+ exclude: ["./node_modules/**", "./src/**/*.vue"],
23
+ allowSyntheticDefaultImports: true,
24
+ }),
25
+ ],
26
+ external: [
27
+ "vue",
28
+ "lodash",
29
+ "dayjs",
30
+ "@certd/acme-client",
31
+ "@certd/pipeline",
32
+ "@certd/plugin-cert",
33
+ "@certd/plugin-aliyun",
34
+ "@certd/plugin-tencent",
35
+ "@certd/plugin-huawei",
36
+ "@certd/plugin-host",
37
+ "@certd/plugin-tencent",
38
+ "@certd/plugin-util",
39
+ ],
12
40
  output: {
13
- // Provide global variables to use in the UMD build
14
- // for externalized deps
15
41
  globals: {
16
42
  vue: "Vue",
17
- "lodash": "_",
43
+ lodash: "_",
18
44
  dayjs: "dayjs",
19
- "@fast-crud/fast-crud": "FastCrud",
45
+ "@certd/plugin-cert": "CertdPluginCert",
46
+ "@certd/acme-client": "CertdAcmeClient",
47
+ "@certd/pipeline": "CertdPluginPipeline",
48
+ "@certd/plugin-aliyun": "CertdPluginAliyun",
49
+ "@certd/plugin-host": "CertdPluginHost",
50
+ "@certd/plugin-huawei": "CertdPluginHuawei",
51
+ "@certd/plugin-util": "CertdPluginUtil",
20
52
  },
21
53
  },
22
54
  },
@@ -1,23 +0,0 @@
1
- import { Registrable } from "@certd/pipeline";
2
-
3
- export type DnsProviderDefine = Registrable & {
4
- accessType: string;
5
- autowire?: {
6
- [key: string]: any;
7
- };
8
- };
9
-
10
- export type CreateRecordOptions = {
11
- fullRecord: string;
12
- type: string;
13
- value: any;
14
- };
15
- export type RemoveRecordOptions = CreateRecordOptions & {
16
- record: any;
17
- };
18
-
19
- export interface IDnsProvider {
20
- onInstance(): Promise<void>;
21
- createRecord(options: CreateRecordOptions): Promise<any>;
22
- removeRecord(options: RemoveRecordOptions): Promise<any>;
23
- }
@@ -1,30 +0,0 @@
1
- import { dnsProviderRegistry } from "./registry";
2
- import { DnsProviderDefine } from "./api";
3
- import { Decorator, AUTOWIRE_KEY } from "@certd/pipeline";
4
- import _ from "lodash";
5
-
6
- // 提供一个唯一 key
7
- export const DNS_PROVIDER_CLASS_KEY = "pipeline:dns-provider";
8
-
9
- export function IsDnsProvider(define: DnsProviderDefine): ClassDecorator {
10
- return (target: any) => {
11
- target = Decorator.target(target);
12
- const autowires: any = {};
13
- const properties = Decorator.getClassProperties(target);
14
- for (const property in properties) {
15
- const autowire = Reflect.getMetadata(AUTOWIRE_KEY, target, property);
16
- if (autowire) {
17
- autowires[property] = autowire;
18
- }
19
- }
20
- _.merge(define, { autowire: autowires });
21
-
22
- Reflect.defineMetadata(DNS_PROVIDER_CLASS_KEY, define, target);
23
-
24
- target.define = define;
25
- dnsProviderRegistry.register(define.name, {
26
- define,
27
- target,
28
- });
29
- };
30
- }
@@ -1,3 +0,0 @@
1
- export * from "./api";
2
- export * from "./registry";
3
- export * from "./decorator";
@@ -1,3 +0,0 @@
1
- import { Registry } from "@certd/pipeline";
2
-
3
- export const dnsProviderRegistry = new Registry();
package/src/index.ts DELETED
@@ -1,2 +0,0 @@
1
- export * from "./plugin";
2
- export * from "./dns-provider";
@@ -1,205 +0,0 @@
1
- // @ts-ignore
2
- import * as acme from "@certd/acme-client";
3
- import _ from "lodash";
4
- import { Challenge } from "@certd/acme-client/types/rfc8555";
5
- import { Logger } from "log4js";
6
- import { IContext } from "@certd/pipeline/src/core/context";
7
- import { IDnsProvider } from "../../dns-provider";
8
- export type CertInfo = {
9
- crt: string;
10
- key: string;
11
- csr: string;
12
- };
13
- export class AcmeService {
14
- userContext: IContext;
15
- logger: Logger;
16
- constructor(options: { userContext: IContext; logger: Logger }) {
17
- this.userContext = options.userContext;
18
- this.logger = options.logger;
19
- acme.setLogger((text: string) => {
20
- this.logger.info(text);
21
- });
22
- }
23
-
24
- async getAccountConfig(email: string): Promise<any> {
25
- return (await this.userContext.getObj(this.buildAccountKey(email))) || {};
26
- }
27
-
28
- buildAccountKey(email: string) {
29
- return "acme.config." + email;
30
- }
31
-
32
- async saveAccountConfig(email: string, conf: any) {
33
- await this.userContext.setObj(this.buildAccountKey(email), conf);
34
- }
35
-
36
- async getAcmeClient(email: string, isTest = false): Promise<acme.Client> {
37
- const conf = await this.getAccountConfig(email);
38
- if (conf.key == null) {
39
- conf.key = await this.createNewKey();
40
- await this.saveAccountConfig(email, conf);
41
- }
42
- const client = new acme.Client({
43
- directoryUrl: isTest ? acme.directory.letsencrypt.staging : acme.directory.letsencrypt.production,
44
- accountKey: conf.key,
45
- accountUrl: conf.accountUrl,
46
- backoffAttempts: 20,
47
- backoffMin: 5000,
48
- backoffMax: 10000,
49
- });
50
-
51
- if (conf.accountUrl == null) {
52
- const accountPayload = {
53
- termsOfServiceAgreed: true,
54
- contact: [`mailto:${email}`],
55
- };
56
- await client.createAccount(accountPayload);
57
- conf.accountUrl = client.getAccountUrl();
58
- await this.saveAccountConfig(email, conf);
59
- }
60
- return client;
61
- }
62
-
63
- async createNewKey() {
64
- const key = await acme.forge.createPrivateKey();
65
- return key.toString();
66
- }
67
-
68
- async challengeCreateFn(authz: any, challenge: any, keyAuthorization: string, dnsProvider: IDnsProvider) {
69
- this.logger.info("Triggered challengeCreateFn()");
70
-
71
- /* http-01 */
72
- if (challenge.type === "http-01") {
73
- const filePath = `/var/www/html/.well-known/acme-challenge/${challenge.token}`;
74
- const fileContents = keyAuthorization;
75
-
76
- this.logger.info(`Creating challenge response for ${authz.identifier.value} at path: ${filePath}`);
77
-
78
- /* Replace this */
79
- this.logger.info(`Would write "${fileContents}" to path "${filePath}"`);
80
- // await fs.writeFileAsync(filePath, fileContents);
81
- } else if (challenge.type === "dns-01") {
82
- /* dns-01 */
83
- const dnsRecord = `_acme-challenge.${authz.identifier.value}`;
84
- const recordValue = keyAuthorization;
85
-
86
- this.logger.info(`Creating TXT record for ${authz.identifier.value}: ${dnsRecord}`);
87
-
88
- /* Replace this */
89
- this.logger.info(`Would create TXT record "${dnsRecord}" with value "${recordValue}"`);
90
-
91
- return await dnsProvider.createRecord({
92
- fullRecord: dnsRecord,
93
- type: "TXT",
94
- value: recordValue,
95
- });
96
- }
97
- }
98
-
99
- /**
100
- * Function used to remove an ACME challenge response
101
- *
102
- * @param {object} authz Authorization object
103
- * @param {object} challenge Selected challenge
104
- * @param {string} keyAuthorization Authorization key
105
- * @param recordItem challengeCreateFn create record item
106
- * @param dnsProvider dnsProvider
107
- * @returns {Promise}
108
- */
109
-
110
- async challengeRemoveFn(authz: any, challenge: any, keyAuthorization: string, recordItem: any, dnsProvider: IDnsProvider) {
111
- this.logger.info("Triggered challengeRemoveFn()");
112
-
113
- /* http-01 */
114
- if (challenge.type === "http-01") {
115
- const filePath = `/var/www/html/.well-known/acme-challenge/${challenge.token}`;
116
-
117
- this.logger.info(`Removing challenge response for ${authz.identifier.value} at path: ${filePath}`);
118
-
119
- /* Replace this */
120
- this.logger.info(`Would remove file on path "${filePath}"`);
121
- // await fs.unlinkAsync(filePath);
122
- } else if (challenge.type === "dns-01") {
123
- const dnsRecord = `_acme-challenge.${authz.identifier.value}`;
124
- const recordValue = keyAuthorization;
125
-
126
- this.logger.info(`Removing TXT record for ${authz.identifier.value}: ${dnsRecord}`);
127
-
128
- /* Replace this */
129
- this.logger.info(`Would remove TXT record "${dnsRecord}" with value "${recordValue}"`);
130
- try {
131
- await dnsProvider.removeRecord({
132
- fullRecord: dnsRecord,
133
- type: "TXT",
134
- value: keyAuthorization,
135
- record: recordItem,
136
- });
137
- } catch (e) {
138
- this.logger.error("删除解析记录出错:", e);
139
- throw e;
140
- }
141
- }
142
- }
143
-
144
- async order(options: { email: string; domains: string | string[]; dnsProvider: any; csrInfo: any; isTest?: boolean }) {
145
- const { email, isTest, domains, csrInfo, dnsProvider } = options;
146
- const client: acme.Client = await this.getAcmeClient(email, isTest);
147
-
148
- /* Create CSR */
149
- const { commonName, altNames } = this.buildCommonNameByDomains(domains);
150
-
151
- const [key, csr] = await acme.forge.createCsr({
152
- commonName,
153
- ...csrInfo,
154
- altNames,
155
- });
156
- if (dnsProvider == null) {
157
- throw new Error("dnsProvider 不能为空");
158
- }
159
- /* 自动申请证书 */
160
- const crt = await client.auto({
161
- csr,
162
- email: email,
163
- termsOfServiceAgreed: true,
164
- challengePriority: ["dns-01"],
165
- challengeCreateFn: async (authz: acme.Authorization, challenge: Challenge, keyAuthorization: string): Promise<any> => {
166
- return await this.challengeCreateFn(authz, challenge, keyAuthorization, dnsProvider);
167
- },
168
- challengeRemoveFn: async (authz: acme.Authorization, challenge: Challenge, keyAuthorization: string, recordItem: any): Promise<any> => {
169
- return await this.challengeRemoveFn(authz, challenge, keyAuthorization, recordItem, dnsProvider);
170
- },
171
- });
172
-
173
- const cert: CertInfo = {
174
- crt: crt.toString(),
175
- key: key.toString(),
176
- csr: csr.toString(),
177
- };
178
- /* Done */
179
- this.logger.debug(`CSR:\n${cert.csr}`);
180
- this.logger.debug(`Certificate:\n${cert.crt}`);
181
- this.logger.info("证书申请成功");
182
- return cert;
183
- }
184
-
185
- buildCommonNameByDomains(domains: string | string[]): {
186
- commonName: string;
187
- altNames: string[] | undefined;
188
- } {
189
- if (typeof domains === "string") {
190
- domains = domains.split(",");
191
- }
192
- if (domains.length === 0) {
193
- throw new Error("domain can not be empty");
194
- }
195
- const commonName = domains[0];
196
- let altNames: undefined | string[] = undefined;
197
- if (domains.length > 1) {
198
- altNames = _.slice(domains, 1);
199
- }
200
- return {
201
- commonName,
202
- altNames,
203
- };
204
- }
205
- }
@@ -1,52 +0,0 @@
1
- import { CertInfo } from "./acme";
2
- import fs from "fs";
3
- import os from "os";
4
- import forge from "node-forge";
5
- import path from "path";
6
- export class CertReader implements CertInfo {
7
- crt: string;
8
- key: string;
9
- csr: string;
10
-
11
- detail: any;
12
- expires: number;
13
- constructor(certInfo: CertInfo) {
14
- this.crt = certInfo.crt;
15
- this.key = certInfo.key;
16
- this.csr = certInfo.csr;
17
-
18
- const { detail, expires } = this.getCrtDetail(this.crt);
19
- this.detail = detail;
20
- this.expires = expires.getTime();
21
- }
22
-
23
- toCertInfo(): CertInfo {
24
- return {
25
- crt: this.crt,
26
- key: this.key,
27
- csr: this.csr,
28
- };
29
- }
30
-
31
- getCrtDetail(crt: string) {
32
- const pki = forge.pki;
33
- const detail = pki.certificateFromPem(crt.toString());
34
- const expires = detail.validity.notAfter;
35
- return { detail, expires };
36
- }
37
-
38
- saveToFile(type: "crt" | "key", filepath?: string) {
39
- if (filepath == null) {
40
- //写入临时目录
41
- filepath = path.join(os.tmpdir(), "/certd/tmp/", Math.floor(Math.random() * 1000000) + "", `cert.${type}`);
42
- }
43
-
44
- const dir = path.dirname(filepath);
45
- if (!fs.existsSync(dir)) {
46
- fs.mkdirSync(dir, { recursive: true });
47
- }
48
-
49
- fs.writeFileSync(filepath, this[type]);
50
- return filepath;
51
- }
52
- }