diff --git a/CHANGELOG.md b/CHANGELOG.md index 83dfbcfb..2c323ded 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,22 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.33.6](https://github.com/certd/certd/compare/v1.33.5...v1.33.6) (2025-04-20) + +### Bug Fixes + +* 上传商用证书,直接粘贴文本报错的问题;修复无法上传ec加密证书的bug ([5750bb7](https://github.com/certd/certd/commit/5750bb706779da274d8e7a87e71416cb64d2df79)) +* 修复下载证书时提示token已过期的问题 ([0e07ae6](https://github.com/certd/certd/commit/0e07ae6ce84dcb9279d3c44060d621566afa593c)) + +### Performance Improvements + +* 更新license时同时绑定url ([78367af](https://github.com/certd/certd/commit/78367af8307f801e778c76d49f0918c21ffe032f)) +* 切换到不同的分组后再打开创建对话框,会自动选择分组 ([893dcd4](https://github.com/certd/certd/commit/893dcd4f2487891199ed3e5a3d47a79a75efc942)) +* 新增部署到火山引擎ALB/CLB、上传到证书中心 ([c9a3e3d](https://github.com/certd/certd/commit/c9a3e3d9d26f964c7af7b56667936f1414fbf42a)) +* 优化/api缓存为0 ([dc05cd4](https://github.com/certd/certd/commit/dc05cd481f186b13375192be965000e6b4b429a5)) +* 优化华为cdn插件引用ccm证书 ([b565b4b](https://github.com/certd/certd/commit/b565b4b3b919b71b98ea2517670bc1ef00e00dc9)) +* 优化证书流水线创建,支持选择分组 ([d613aa8](https://github.com/certd/certd/commit/d613aa8f3e85d8dc475ef1b62d49394ce7fd7d24)) + ## [1.33.5](https://github.com/certd/certd/compare/v1.33.4...v1.33.5) (2025-04-17) ### Performance Improvements diff --git a/build.trigger b/build.trigger index 09cda20d..225578b6 100644 --- a/build.trigger +++ b/build.trigger @@ -1 +1 @@ -23:37 +00:08 diff --git a/docs/guide/changelogs/CHANGELOG.md b/docs/guide/changelogs/CHANGELOG.md index 83dfbcfb..2c323ded 100644 --- a/docs/guide/changelogs/CHANGELOG.md +++ b/docs/guide/changelogs/CHANGELOG.md @@ -3,6 +3,22 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.33.6](https://github.com/certd/certd/compare/v1.33.5...v1.33.6) (2025-04-20) + +### Bug Fixes + +* 上传商用证书,直接粘贴文本报错的问题;修复无法上传ec加密证书的bug ([5750bb7](https://github.com/certd/certd/commit/5750bb706779da274d8e7a87e71416cb64d2df79)) +* 修复下载证书时提示token已过期的问题 ([0e07ae6](https://github.com/certd/certd/commit/0e07ae6ce84dcb9279d3c44060d621566afa593c)) + +### Performance Improvements + +* 更新license时同时绑定url ([78367af](https://github.com/certd/certd/commit/78367af8307f801e778c76d49f0918c21ffe032f)) +* 切换到不同的分组后再打开创建对话框,会自动选择分组 ([893dcd4](https://github.com/certd/certd/commit/893dcd4f2487891199ed3e5a3d47a79a75efc942)) +* 新增部署到火山引擎ALB/CLB、上传到证书中心 ([c9a3e3d](https://github.com/certd/certd/commit/c9a3e3d9d26f964c7af7b56667936f1414fbf42a)) +* 优化/api缓存为0 ([dc05cd4](https://github.com/certd/certd/commit/dc05cd481f186b13375192be965000e6b4b429a5)) +* 优化华为cdn插件引用ccm证书 ([b565b4b](https://github.com/certd/certd/commit/b565b4b3b919b71b98ea2517670bc1ef00e00dc9)) +* 优化证书流水线创建,支持选择分组 ([d613aa8](https://github.com/certd/certd/commit/d613aa8f3e85d8dc475ef1b62d49394ce7fd7d24)) + ## [1.33.5](https://github.com/certd/certd/compare/v1.33.4...v1.33.5) (2025-04-17) ### Performance Improvements diff --git a/docs/guide/install/baota/images/network.png b/docs/guide/install/baota/images/network.png new file mode 100644 index 00000000..f21da36c Binary files /dev/null and b/docs/guide/install/baota/images/network.png differ diff --git a/docs/guide/install/baota/index.md b/docs/guide/install/baota/index.md index a518f1c9..31e6a4a8 100644 --- a/docs/guide/install/baota/index.md +++ b/docs/guide/install/baota/index.md @@ -13,7 +13,7 @@ #### 2.1 应用商店一键部署【推荐】 -* 在应用商店中找到`certd`(要先点右上角更新应用) +* 在宝塔Docker应用商店中找到`certd`(要先点右上角更新应用) * 点击安装,配置域名等基本信息即可完成安装 > 需要宝塔9.2.0及以上版本才支持 @@ -70,3 +70,12 @@ admin/123456 ## 五、备份恢复 将备份的`db.sqlite`及同目录下的其他文件一起覆盖到原来的位置,重启certd即可 + + +## 六、宝塔部署相关问题排查 + +### 1. 无法访问Certd +1. 确认服务器的安全规则,是否放开了对应端口 +2. 确认宝塔防火墙是否放开对应端口 +3. 尝试将Certd容器加入宝塔的`bridge`网络 +![](./images/network.png) \ No newline at end of file diff --git a/docs/guide/use/backup/index.md b/docs/guide/use/backup/index.md index 86ff93b4..7cc61231 100644 --- a/docs/guide/use/backup/index.md +++ b/docs/guide/use/backup/index.md @@ -1,5 +1,6 @@ -# 数据库自动备份 - +# 数据库备份 +* 两种备份方法: 1、手动备份 2、自动备份 +* 本文仅限sqlite数据库。 ## 一、手动备份 数据库文件根据不同的部署方式保存的位置不一样,您可以手动复制出来进行备份 diff --git a/lerna.json b/lerna.json index b25a3c25..f8702d59 100644 --- a/lerna.json +++ b/lerna.json @@ -9,5 +9,5 @@ } }, "npmClient": "pnpm", - "version": "1.33.5" + "version": "1.33.6" } diff --git a/packages/core/acme-client/CHANGELOG.md b/packages/core/acme-client/CHANGELOG.md index b64cc3c9..fe16363c 100644 --- a/packages/core/acme-client/CHANGELOG.md +++ b/packages/core/acme-client/CHANGELOG.md @@ -3,6 +3,10 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.33.6](https://github.com/publishlab/node-acme-client/compare/v1.33.5...v1.33.6) (2025-04-20) + +**Note:** Version bump only for package @certd/acme-client + ## [1.33.5](https://github.com/publishlab/node-acme-client/compare/v1.33.4...v1.33.5) (2025-04-17) **Note:** Version bump only for package @certd/acme-client diff --git a/packages/core/acme-client/package.json b/packages/core/acme-client/package.json index 7bcab8a9..5474eb03 100644 --- a/packages/core/acme-client/package.json +++ b/packages/core/acme-client/package.json @@ -3,7 +3,7 @@ "description": "Simple and unopinionated ACME client", "private": false, "author": "nmorsman", - "version": "1.33.5", + "version": "1.33.6", "type": "module", "module": "scr/index.js", "main": "src/index.js", @@ -18,7 +18,7 @@ "types" ], "dependencies": { - "@certd/basic": "^1.33.5", + "@certd/basic": "^1.33.6", "@peculiar/x509": "^1.11.0", "asn1js": "^3.0.5", "axios": "^1.7.2", @@ -67,5 +67,5 @@ "bugs": { "url": "https://github.com/publishlab/node-acme-client/issues" }, - "gitHead": "198a97b00c75219ea8efdc6db4676158506a07c1" + "gitHead": "8abe62886ab50634b4b05abedd2981ec8ee0422e" } diff --git a/packages/core/basic/CHANGELOG.md b/packages/core/basic/CHANGELOG.md index 570a5cf7..a5f97dc4 100644 --- a/packages/core/basic/CHANGELOG.md +++ b/packages/core/basic/CHANGELOG.md @@ -3,6 +3,10 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.33.6](https://github.com/certd/certd/compare/v1.33.5...v1.33.6) (2025-04-20) + +**Note:** Version bump only for package @certd/basic + ## [1.33.5](https://github.com/certd/certd/compare/v1.33.4...v1.33.5) (2025-04-17) ### Performance Improvements diff --git a/packages/core/basic/build.md b/packages/core/basic/build.md index c0b0ad71..0b792c13 100644 --- a/packages/core/basic/build.md +++ b/packages/core/basic/build.md @@ -1 +1 @@ -23:32 +00:04 diff --git a/packages/core/basic/package.json b/packages/core/basic/package.json index e8bb745a..87de0d49 100644 --- a/packages/core/basic/package.json +++ b/packages/core/basic/package.json @@ -1,7 +1,7 @@ { "name": "@certd/basic", "private": false, - "version": "1.33.5", + "version": "1.33.6", "type": "module", "main": "./dist/index.js", "module": "./dist/index.js", @@ -44,5 +44,5 @@ "tslib": "^2.8.1", "typescript": "^5.4.2" }, - "gitHead": "198a97b00c75219ea8efdc6db4676158506a07c1" + "gitHead": "8abe62886ab50634b4b05abedd2981ec8ee0422e" } diff --git a/packages/core/pipeline/CHANGELOG.md b/packages/core/pipeline/CHANGELOG.md index 88668f1a..51af93af 100644 --- a/packages/core/pipeline/CHANGELOG.md +++ b/packages/core/pipeline/CHANGELOG.md @@ -3,6 +3,10 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.33.6](https://github.com/certd/certd/compare/v1.33.5...v1.33.6) (2025-04-20) + +**Note:** Version bump only for package @certd/pipeline + ## [1.33.5](https://github.com/certd/certd/compare/v1.33.4...v1.33.5) (2025-04-17) **Note:** Version bump only for package @certd/pipeline diff --git a/packages/core/pipeline/package.json b/packages/core/pipeline/package.json index aa3136a6..373405fd 100644 --- a/packages/core/pipeline/package.json +++ b/packages/core/pipeline/package.json @@ -1,7 +1,7 @@ { "name": "@certd/pipeline", "private": false, - "version": "1.33.5", + "version": "1.33.6", "type": "module", "main": "./dist/index.js", "module": "./dist/index.js", @@ -16,8 +16,8 @@ "test": "mocha --loader=ts-node/esm" }, "dependencies": { - "@certd/basic": "^1.33.5", - "@certd/plus-core": "^1.33.5", + "@certd/basic": "^1.33.6", + "@certd/plus-core": "^1.33.6", "dayjs": "^1.11.7", "lodash-es": "^4.17.21", "reflect-metadata": "^0.1.13" @@ -43,5 +43,5 @@ "tslib": "^2.8.1", "typescript": "^5.4.2" }, - "gitHead": "198a97b00c75219ea8efdc6db4676158506a07c1" + "gitHead": "8abe62886ab50634b4b05abedd2981ec8ee0422e" } diff --git a/packages/libs/lib-huawei/CHANGELOG.md b/packages/libs/lib-huawei/CHANGELOG.md index 4c522d7a..d6b06ca4 100644 --- a/packages/libs/lib-huawei/CHANGELOG.md +++ b/packages/libs/lib-huawei/CHANGELOG.md @@ -3,6 +3,10 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.33.6](https://github.com/certd/certd/compare/v1.33.5...v1.33.6) (2025-04-20) + +**Note:** Version bump only for package @certd/lib-huawei + ## [1.33.5](https://github.com/certd/certd/compare/v1.33.4...v1.33.5) (2025-04-17) **Note:** Version bump only for package @certd/lib-huawei diff --git a/packages/libs/lib-huawei/package.json b/packages/libs/lib-huawei/package.json index 96b44579..ef233272 100644 --- a/packages/libs/lib-huawei/package.json +++ b/packages/libs/lib-huawei/package.json @@ -1,7 +1,7 @@ { "name": "@certd/lib-huawei", "private": false, - "version": "1.33.5", + "version": "1.33.6", "main": "./dist/bundle.js", "module": "./dist/bundle.js", "types": "./dist/d/index.d.ts", @@ -23,5 +23,5 @@ "prettier": "^2.8.8", "tslib": "^2.8.1" }, - "gitHead": "198a97b00c75219ea8efdc6db4676158506a07c1" + "gitHead": "8abe62886ab50634b4b05abedd2981ec8ee0422e" } diff --git a/packages/libs/lib-iframe/CHANGELOG.md b/packages/libs/lib-iframe/CHANGELOG.md index 2ece0a50..2af7a119 100644 --- a/packages/libs/lib-iframe/CHANGELOG.md +++ b/packages/libs/lib-iframe/CHANGELOG.md @@ -3,6 +3,12 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.33.6](https://github.com/certd/certd/compare/v1.33.5...v1.33.6) (2025-04-20) + +### Performance Improvements + +* 更新license时同时绑定url ([78367af](https://github.com/certd/certd/commit/78367af8307f801e778c76d49f0918c21ffe032f)) + ## [1.33.5](https://github.com/certd/certd/compare/v1.33.4...v1.33.5) (2025-04-17) **Note:** Version bump only for package @certd/lib-iframe diff --git a/packages/libs/lib-iframe/package.json b/packages/libs/lib-iframe/package.json index f5023c17..c9843cf9 100644 --- a/packages/libs/lib-iframe/package.json +++ b/packages/libs/lib-iframe/package.json @@ -1,7 +1,7 @@ { "name": "@certd/lib-iframe", "private": false, - "version": "1.33.5", + "version": "1.33.6", "type": "module", "main": "./dist/index.js", "module": "./dist/index.js", @@ -30,5 +30,5 @@ "tslib": "^2.8.1", "typescript": "^5.4.2" }, - "gitHead": "198a97b00c75219ea8efdc6db4676158506a07c1" + "gitHead": "8abe62886ab50634b4b05abedd2981ec8ee0422e" } diff --git a/packages/libs/lib-iframe/src/lib/iframe.client.ts b/packages/libs/lib-iframe/src/lib/iframe.client.ts index 527f8dcd..f2d90a5f 100644 --- a/packages/libs/lib-iframe/src/lib/iframe.client.ts +++ b/packages/libs/lib-iframe/src/lib/iframe.client.ts @@ -65,7 +65,7 @@ export class IframeClient { return window.self !== window.top; } - register(action: string, handler: (data: IframeMessageData) => Promise) { + register(action: string, handler: (data: IframeMessageData) => Promise) { this.handlers[action] = handler; } diff --git a/packages/libs/lib-jdcloud/CHANGELOG.md b/packages/libs/lib-jdcloud/CHANGELOG.md index 667da009..f11d1082 100644 --- a/packages/libs/lib-jdcloud/CHANGELOG.md +++ b/packages/libs/lib-jdcloud/CHANGELOG.md @@ -3,6 +3,10 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.33.6](https://github.com/certd/certd/compare/v1.33.5...v1.33.6) (2025-04-20) + +**Note:** Version bump only for package @certd/jdcloud + ## [1.33.5](https://github.com/certd/certd/compare/v1.33.4...v1.33.5) (2025-04-17) **Note:** Version bump only for package @certd/jdcloud diff --git a/packages/libs/lib-jdcloud/package.json b/packages/libs/lib-jdcloud/package.json index 9d3e31b4..110a26b3 100644 --- a/packages/libs/lib-jdcloud/package.json +++ b/packages/libs/lib-jdcloud/package.json @@ -1,6 +1,6 @@ { "name": "@certd/jdcloud", - "version": "1.33.5", + "version": "1.33.6", "description": "jdcloud openApi sdk", "main": "./dist/bundle.js", "module": "./dist/bundle.js", @@ -60,5 +60,5 @@ "fetch" ] }, - "gitHead": "198a97b00c75219ea8efdc6db4676158506a07c1" + "gitHead": "8abe62886ab50634b4b05abedd2981ec8ee0422e" } diff --git a/packages/libs/lib-k8s/CHANGELOG.md b/packages/libs/lib-k8s/CHANGELOG.md index 0ccce9a5..dd2f7f7c 100644 --- a/packages/libs/lib-k8s/CHANGELOG.md +++ b/packages/libs/lib-k8s/CHANGELOG.md @@ -3,6 +3,10 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.33.6](https://github.com/certd/certd/compare/v1.33.5...v1.33.6) (2025-04-20) + +**Note:** Version bump only for package @certd/lib-k8s + ## [1.33.5](https://github.com/certd/certd/compare/v1.33.4...v1.33.5) (2025-04-17) **Note:** Version bump only for package @certd/lib-k8s diff --git a/packages/libs/lib-k8s/package.json b/packages/libs/lib-k8s/package.json index 8218721d..d7d25b93 100644 --- a/packages/libs/lib-k8s/package.json +++ b/packages/libs/lib-k8s/package.json @@ -1,7 +1,7 @@ { "name": "@certd/lib-k8s", "private": false, - "version": "1.33.5", + "version": "1.33.6", "type": "module", "main": "./dist/index.js", "module": "./dist/index.js", @@ -16,7 +16,7 @@ "preview": "vite preview" }, "dependencies": { - "@certd/basic": "^1.33.5", + "@certd/basic": "^1.33.6", "@kubernetes/client-node": "0.21.0" }, "devDependencies": { @@ -31,5 +31,5 @@ "tslib": "^2.8.1", "typescript": "^5.4.2" }, - "gitHead": "198a97b00c75219ea8efdc6db4676158506a07c1" + "gitHead": "8abe62886ab50634b4b05abedd2981ec8ee0422e" } diff --git a/packages/libs/lib-server/CHANGELOG.md b/packages/libs/lib-server/CHANGELOG.md index 8515b7f9..759e632a 100644 --- a/packages/libs/lib-server/CHANGELOG.md +++ b/packages/libs/lib-server/CHANGELOG.md @@ -3,6 +3,10 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.33.6](https://github.com/certd/certd/compare/v1.33.5...v1.33.6) (2025-04-20) + +**Note:** Version bump only for package @certd/lib-server + ## [1.33.5](https://github.com/certd/certd/compare/v1.33.4...v1.33.5) (2025-04-17) ### Performance Improvements diff --git a/packages/libs/lib-server/package.json b/packages/libs/lib-server/package.json index 573b2313..a89374de 100644 --- a/packages/libs/lib-server/package.json +++ b/packages/libs/lib-server/package.json @@ -1,6 +1,6 @@ { "name": "@certd/lib-server", - "version": "1.33.5", + "version": "1.33.6", "description": "midway with flyway, sql upgrade way ", "private": false, "type": "module", @@ -27,10 +27,10 @@ ], "license": "AGPL", "dependencies": { - "@certd/acme-client": "^1.33.5", - "@certd/basic": "^1.33.5", - "@certd/pipeline": "^1.33.5", - "@certd/plus-core": "^1.33.5", + "@certd/acme-client": "^1.33.6", + "@certd/basic": "^1.33.6", + "@certd/pipeline": "^1.33.6", + "@certd/plus-core": "^1.33.6", "@midwayjs/cache": "~3.14.0", "@midwayjs/core": "~3.20.3", "@midwayjs/i18n": "~3.20.3", @@ -61,5 +61,5 @@ "typeorm": "^0.3.11", "typescript": "^5.4.2" }, - "gitHead": "198a97b00c75219ea8efdc6db4676158506a07c1" + "gitHead": "8abe62886ab50634b4b05abedd2981ec8ee0422e" } diff --git a/packages/libs/midway-flyway-js/CHANGELOG.md b/packages/libs/midway-flyway-js/CHANGELOG.md index 783e0747..14af9698 100644 --- a/packages/libs/midway-flyway-js/CHANGELOG.md +++ b/packages/libs/midway-flyway-js/CHANGELOG.md @@ -3,6 +3,10 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.33.6](https://github.com/certd/certd/compare/v1.33.5...v1.33.6) (2025-04-20) + +**Note:** Version bump only for package @certd/midway-flyway-js + ## [1.33.5](https://github.com/certd/certd/compare/v1.33.4...v1.33.5) (2025-04-17) **Note:** Version bump only for package @certd/midway-flyway-js diff --git a/packages/libs/midway-flyway-js/package.json b/packages/libs/midway-flyway-js/package.json index 3ebe7a10..0c07f198 100644 --- a/packages/libs/midway-flyway-js/package.json +++ b/packages/libs/midway-flyway-js/package.json @@ -1,6 +1,6 @@ { "name": "@certd/midway-flyway-js", - "version": "1.33.5", + "version": "1.33.6", "description": "midway with flyway, sql upgrade way ", "private": false, "type": "module", @@ -46,5 +46,5 @@ "typeorm": "^0.3.11", "typescript": "^5.4.2" }, - "gitHead": "198a97b00c75219ea8efdc6db4676158506a07c1" + "gitHead": "8abe62886ab50634b4b05abedd2981ec8ee0422e" } diff --git a/packages/plugins/plugin-cert/CHANGELOG.md b/packages/plugins/plugin-cert/CHANGELOG.md index 51fbcff5..efe587a9 100644 --- a/packages/plugins/plugin-cert/CHANGELOG.md +++ b/packages/plugins/plugin-cert/CHANGELOG.md @@ -3,6 +3,10 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.33.6](https://github.com/certd/certd/compare/v1.33.5...v1.33.6) (2025-04-20) + +**Note:** Version bump only for package @certd/plugin-cert + ## [1.33.5](https://github.com/certd/certd/compare/v1.33.4...v1.33.5) (2025-04-17) **Note:** Version bump only for package @certd/plugin-cert diff --git a/packages/plugins/plugin-cert/package.json b/packages/plugins/plugin-cert/package.json index 6b4a2345..074cb4b5 100644 --- a/packages/plugins/plugin-cert/package.json +++ b/packages/plugins/plugin-cert/package.json @@ -1,7 +1,7 @@ { "name": "@certd/plugin-cert", "private": false, - "version": "1.33.5", + "version": "1.33.6", "type": "module", "main": "./dist/index.js", "types": "./dist/index.d.ts", @@ -15,10 +15,10 @@ "preview": "vite preview" }, "dependencies": { - "@certd/acme-client": "^1.33.5", - "@certd/basic": "^1.33.5", - "@certd/pipeline": "^1.33.5", - "@certd/plugin-lib": "^1.33.5", + "@certd/acme-client": "^1.33.6", + "@certd/basic": "^1.33.6", + "@certd/pipeline": "^1.33.6", + "@certd/plugin-lib": "^1.33.6", "@google-cloud/publicca": "^1.3.0", "dayjs": "^1.11.7", "jszip": "^3.10.1", @@ -41,5 +41,5 @@ "tslib": "^2.8.1", "typescript": "^5.4.2" }, - "gitHead": "198a97b00c75219ea8efdc6db4676158506a07c1" + "gitHead": "8abe62886ab50634b4b05abedd2981ec8ee0422e" } diff --git a/packages/plugins/plugin-lib/CHANGELOG.md b/packages/plugins/plugin-lib/CHANGELOG.md index e2bf134c..28c312c8 100644 --- a/packages/plugins/plugin-lib/CHANGELOG.md +++ b/packages/plugins/plugin-lib/CHANGELOG.md @@ -3,6 +3,10 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.33.6](https://github.com/certd/certd/compare/v1.33.5...v1.33.6) (2025-04-20) + +**Note:** Version bump only for package @certd/plugin-lib + ## [1.33.5](https://github.com/certd/certd/compare/v1.33.4...v1.33.5) (2025-04-17) **Note:** Version bump only for package @certd/plugin-lib diff --git a/packages/plugins/plugin-lib/package.json b/packages/plugins/plugin-lib/package.json index 731df87d..625e36ef 100644 --- a/packages/plugins/plugin-lib/package.json +++ b/packages/plugins/plugin-lib/package.json @@ -1,7 +1,7 @@ { "name": "@certd/plugin-lib", "private": false, - "version": "1.33.5", + "version": "1.33.6", "type": "module", "main": "./dist/index.js", "types": "./dist/index.d.ts", @@ -16,8 +16,8 @@ }, "dependencies": { "@alicloud/pop-core": "^1.7.10", - "@certd/basic": "^1.33.5", - "@certd/pipeline": "^1.33.5", + "@certd/basic": "^1.33.6", + "@certd/pipeline": "^1.33.6", "@kubernetes/client-node": "0.21.0", "ali-oss": "^6.21.0", "basic-ftp": "^5.0.5", @@ -48,5 +48,5 @@ "tslib": "^2.8.1", "typescript": "^5.4.2" }, - "gitHead": "198a97b00c75219ea8efdc6db4676158506a07c1" + "gitHead": "8abe62886ab50634b4b05abedd2981ec8ee0422e" } diff --git a/packages/ui/certd-client/CHANGELOG.md b/packages/ui/certd-client/CHANGELOG.md index 2d4a0e5d..7b624c67 100644 --- a/packages/ui/certd-client/CHANGELOG.md +++ b/packages/ui/certd-client/CHANGELOG.md @@ -3,6 +3,20 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.33.6](https://github.com/certd/certd/compare/v1.33.5...v1.33.6) (2025-04-20) + +### Bug Fixes + +* 上传商用证书,直接粘贴文本报错的问题;修复无法上传ec加密证书的bug ([5750bb7](https://github.com/certd/certd/commit/5750bb706779da274d8e7a87e71416cb64d2df79)) +* 修复下载证书时提示token已过期的问题 ([0e07ae6](https://github.com/certd/certd/commit/0e07ae6ce84dcb9279d3c44060d621566afa593c)) + +### Performance Improvements + +* 更新license时同时绑定url ([78367af](https://github.com/certd/certd/commit/78367af8307f801e778c76d49f0918c21ffe032f)) +* 切换到不同的分组后再打开创建对话框,会自动选择分组 ([893dcd4](https://github.com/certd/certd/commit/893dcd4f2487891199ed3e5a3d47a79a75efc942)) +* 优化/api缓存为0 ([dc05cd4](https://github.com/certd/certd/commit/dc05cd481f186b13375192be965000e6b4b429a5)) +* 优化证书流水线创建,支持选择分组 ([d613aa8](https://github.com/certd/certd/commit/d613aa8f3e85d8dc475ef1b62d49394ce7fd7d24)) + ## [1.33.5](https://github.com/certd/certd/compare/v1.33.4...v1.33.5) (2025-04-17) ### Performance Improvements diff --git a/packages/ui/certd-client/package.json b/packages/ui/certd-client/package.json index f9f1904b..c562afb7 100644 --- a/packages/ui/certd-client/package.json +++ b/packages/ui/certd-client/package.json @@ -1,6 +1,6 @@ { "name": "@certd/ui-client", - "version": "1.33.5", + "version": "1.33.6", "private": true, "scripts": { "dev": "vite --open", @@ -101,8 +101,8 @@ "zod-defaults": "^0.1.3" }, "devDependencies": { - "@certd/lib-iframe": "^1.33.5", - "@certd/pipeline": "^1.33.5", + "@certd/lib-iframe": "^1.33.6", + "@certd/pipeline": "^1.33.6", "@rollup/plugin-commonjs": "^25.0.7", "@rollup/plugin-node-resolve": "^15.2.3", "@types/chai": "^4.3.12", diff --git a/packages/ui/certd-client/src/api/service.ts b/packages/ui/certd-client/src/api/service.ts index fd108aa0..3fe0d4ca 100644 --- a/packages/ui/certd-client/src/api/service.ts +++ b/packages/ui/certd-client/src/api/service.ts @@ -49,33 +49,32 @@ function createService() { } // 这个状态码是和后端约定的 - const { code } = dataAxios; - // 根据 code 进行判断 - if (code === undefined) { + if (dataAxios?.code === undefined) { // 如果没有 code 代表这不是项目后端开发的接口 errorCreate(`非标准返回:${dataAxios}, ${response.config.url}`); return dataAxios; - } else { - // 有 code 代表这是一个后端接口 可以进行进一步的判断 - switch (code) { - case 0: - // [ 示例 ] code === 0 代表没有错误 + } + const { code } = dataAxios; + // 有 code 代表这是一个后端接口 可以进行进一步的判断 + switch (code) { + case 0: + // [ 示例 ] code === 0 代表没有错误 + // @ts-ignore + return dataAxios?.data; + default: + // 不是正确的 code + const errorMessage = dataAxios.msg || dataAxios.message || "未知错误"; + // @ts-ignore + if (response?.config?.onError) { + const err = new CodeError(errorMessage, dataAxios.code, dataAxios.data); // @ts-ignore - return dataAxios.data; - default: - // 不是正确的 code - const errorMessage = dataAxios.msg || dataAxios.message || "未知错误"; - // @ts-ignore - if (response?.config?.onError) { - const err = new CodeError(errorMessage, dataAxios.code, dataAxios.data); - response.config.onError(err); - return; - } - //@ts-ignore - const showErrorNotify = response?.config?.showErrorNotify; - errorCreate(`${errorMessage}: ${response.config.url}`, showErrorNotify, dataAxios); - return dataAxios; - } + response.config.onError(err); + return; + } + //@ts-ignore + const showErrorNotify = response?.config?.showErrorNotify; + errorCreate(`${errorMessage}: ${response.config.url}`, showErrorNotify, dataAxios); + return dataAxios; } }, error => { diff --git a/packages/ui/certd-client/src/components/pem-input.vue b/packages/ui/certd-client/src/components/pem-input.vue index fed8c308..ec0ac685 100644 --- a/packages/ui/certd-client/src/components/pem-input.vue +++ b/packages/ui/certd-client/src/components/pem-input.vue @@ -1,7 +1,7 @@ @@ -17,7 +17,6 @@ const props = defineProps<{ }>(); const emit = defineEmits(["update:modelValue"]); -const textRef = ref(); function emitValue(value: string) { emit("update:modelValue", value); @@ -39,16 +38,6 @@ function onChange(e: any) { }; fileReader.readAsText(file); // 以文本形式读取文件 } - -watch( - () => props.modelValue, - value => { - textRef.value = value; - }, - { - immediate: true, - } -); diff --git a/packages/ui/certd-client/src/views/certd/pipeline/certd-form/use.ts b/packages/ui/certd-client/src/views/certd/pipeline/certd-form/use.ts deleted file mode 100644 index 69b1a1ea..00000000 --- a/packages/ui/certd-client/src/views/certd/pipeline/certd-form/use.ts +++ /dev/null @@ -1,126 +0,0 @@ -import { checkPipelineLimit, readCertDetail } from "/@/views/certd/pipeline/utils"; -import { omit } from "lodash-es"; -import * as api from "/@/views/certd/pipeline/api"; -import { message } from "ant-design-vue"; -import { nanoid } from "nanoid"; -import { useRouter } from "vue-router"; - -export function setRunnableIds(pipeline: any) { - const idMap: any = {}; - function createId(oldId: any) { - if (oldId == null) { - return nanoid(); - } - const newId = nanoid(); - idMap[oldId] = newId; - return newId; - } - if (pipeline.stages) { - for (const stage of pipeline.stages) { - stage.id = createId(stage.id); - if (stage.tasks) { - for (const task of stage.tasks) { - task.id = createId(task.id); - if (task.steps) { - for (const step of task.steps) { - step.id = createId(step.id); - } - } - } - } - } - } - - for (const trigger of pipeline.triggers) { - trigger.id = nanoid(); - } - for (const notification of pipeline.notifications) { - notification.id = nanoid(); - } - - let content = JSON.stringify(pipeline); - for (const key in idMap) { - content = content.replaceAll(key, idMap[key]); - } - return JSON.parse(content); -} - -export function useCertd(certdFormRef: any) { - const router = useRouter(); - async function openAddCertdPipelineDialog() { - //检查是否流水线数量超出限制 - await checkPipelineLimit(); - - certdFormRef.value.open(async ({ form }: any) => { - // const certDetail = readCertDetail(form.cert.crt); - // 添加certd pipeline - const triggers = []; - if (form.triggerCron) { - triggers.push({ title: "定时触发", type: "timer", props: { cron: form.triggerCron } }); - } - const notifications = []; - if (form.notification != null) { - notifications.push({ - type: "custom", - when: ["error", "turnToSuccess", "success"], - notificationId: form.notification, - title: form.notificationTarget?.name || "自定义通知", - }); - } - const pluginInput = omit(form, ["triggerCron", "notification", "notificationTarget", "certApplyPlugin"]); - let pipeline = { - title: form.domains[0] + "证书自动化", - runnableType: "pipeline", - stages: [ - { - title: "证书申请阶段", - maxTaskCount: 1, - runnableType: "stage", - tasks: [ - { - title: "证书申请任务", - runnableType: "task", - steps: [ - { - title: "申请证书", - runnableType: "step", - input: { - renewDays: 35, - ...pluginInput, - }, - strategy: { - runStrategy: 0, // 正常执行 - }, - type: form.certApplyPlugin, - }, - ], - }, - ], - }, - ], - triggers, - notifications, - }; - pipeline = setRunnableIds(pipeline); - - /** - * // cert: 证书; backup: 备份; custom:自定义; - * type: string; - * // custom: 自定义; monitor: 监控; - * from: string; - */ - const id = await api.Save({ - title: pipeline.title, - content: JSON.stringify(pipeline), - keepHistoryCount: 30, - type: "cert", - }); - message.success("创建成功,请添加证书部署任务"); - router.push({ path: "/certd/pipeline/detail", query: { id, editMode: "true" } }); - }); - } - - return { - openAddCertdPipelineDialog, - }; -} diff --git a/packages/ui/certd-client/src/views/certd/pipeline/certd-form/use.tsx b/packages/ui/certd-client/src/views/certd/pipeline/certd-form/use.tsx new file mode 100644 index 00000000..508175d6 --- /dev/null +++ b/packages/ui/certd-client/src/views/certd/pipeline/certd-form/use.tsx @@ -0,0 +1,333 @@ +import { checkPipelineLimit } from "/@/views/certd/pipeline/utils"; +import { cloneDeep, merge, omit } from "lodash-es"; +import { message } from "ant-design-vue"; +import { nanoid } from "nanoid"; +import { useRouter } from "vue-router"; +import { compute, CreateCrudOptionsRet, dict, useFormWrapper } from "@fast-crud/fast-crud"; +import NotificationSelector from "/@/views/certd/notification/notification-selector/index.vue"; +import { useReference } from "/@/use/use-refrence"; +import { ref } from "vue"; +import * as api from "../api"; +import { PluginGroup, usePluginStore } from "/@/store/plugin"; +import { createNotificationApi } from "/@/views/certd/notification/api"; +import GroupSelector from "../group/group-selector.vue"; + +export function setRunnableIds(pipeline: any) { + const idMap: any = {}; + function createId(oldId: any) { + if (oldId == null) { + return nanoid(); + } + const newId = nanoid(); + idMap[oldId] = newId; + return newId; + } + if (pipeline.stages) { + for (const stage of pipeline.stages) { + stage.id = createId(stage.id); + if (stage.tasks) { + for (const task of stage.tasks) { + task.id = createId(task.id); + if (task.steps) { + for (const step of task.steps) { + step.id = createId(step.id); + } + } + } + } + } + } + + for (const trigger of pipeline.triggers) { + trigger.id = nanoid(); + } + for (const notification of pipeline.notifications) { + notification.id = nanoid(); + } + + let content = JSON.stringify(pipeline); + for (const key in idMap) { + content = content.replaceAll(key, idMap[key]); + } + return JSON.parse(content); +} + +export function useCertPipelineCreator() { + const { openCrudFormDialog } = useFormWrapper(); + + const pluginStore = usePluginStore(); + const router = useRouter(); + + function createCrudOptions(certPlugins: any[], getFormData: any, doSubmit: any): CreateCrudOptionsRet { + const inputs: any = {}; + const moreParams = []; + for (const plugin of certPlugins) { + for (const inputKey in plugin.input) { + if (inputs[inputKey]) { + //如果两个插件有的字段,直接显示 + inputs[inputKey].form.show = true; + continue; + } + const inputDefine = cloneDeep(plugin.input[inputKey]); + if (!inputDefine.required && !inputDefine.maybeNeed) { + moreParams.push(inputKey); + // continue; + } + useReference(inputDefine); + inputs[inputKey] = { + title: inputDefine.title, + form: { + ...inputDefine, + show: compute(ctx => { + const form = getFormData(); + if (!form) { + return false; + } + + let inputDefineShow = true; + if (inputDefine.show != null) { + const computeShow = inputDefine.show as any; + if (computeShow === false) { + inputDefineShow = false; + } else if (computeShow && computeShow.computeFn) { + inputDefineShow = computeShow.computeFn({ form }); + } + } + return form?.certApplyPlugin === plugin.name && inputDefineShow; + }), + }, + }; + } + } + + const pluginStore = usePluginStore(); + const randomHour = Math.floor(Math.random() * 6); + const randomMin = Math.floor(Math.random() * 60); + + const groupDictRef = dict({ + url: "/pi/pipeline/group/all", + value: "id", + label: "name", + }); + + return { + crudOptions: { + form: { + doSubmit, + wrapper: { + width: 1350, + saveRemind: false, + title: "创建证书流水线", + }, + group: { + groups: { + more: { + header: "更多参数", + columns: moreParams, + collapsed: true, + }, + }, + }, + }, + columns: { + certApplyPlugin: { + title: "证书申请插件", + type: "dict-select", + dict: dict({ + data: [ + { value: "CertApply", label: "JS-ACME" }, + { value: "CertApplyLego", label: "Lego-ACME" }, + ], + }), + form: { + order: 0, + value: "CertApply", + helper: { + render: () => { + return ( +
    +
  • JS-ACME:使用简单方便,功能强大【推荐】
  • +
  • Lego-ACME:基于Lego实现,支持海量DNS提供商,熟悉LEGO的用户可以使用
  • +
+ ); + }, + }, + valueChange: { + handle: async ({ form, value }) => { + const config = await pluginStore.getPluginConfig({ + name: value, + type: "builtIn", + }); + if (config.sysSetting?.input) { + merge(form, config.sysSetting.input); + } + }, + immediate: true, + }, + }, + }, + ...inputs, + triggerCron: { + title: "定时触发", + type: "text", + form: { + value: `0 ${randomMin} ${randomHour} * * *`, + component: { + name: "cron-editor", + vModel: "modelValue", + placeholder: "0 0 4 * * *", + }, + helper: "点击上面的按钮,选择每天几点定时执行。\n建议设置为每天触发一次,证书未到期之前任务会跳过,不会重复执行", + order: 100, + }, + }, + notification: { + title: "失败通知", + type: "text", + form: { + value: 0, + component: { + name: NotificationSelector, + vModel: "modelValue", + on: { + selectedChange({ $event, form }) { + form.notificationTarget = $event; + }, + }, + }, + order: 101, + helper: "任务执行失败实时提醒", + }, + }, + groupId: { + title: "流水线分组", + type: "dict-select", + dict: groupDictRef, + form: { + component: { + name: GroupSelector, + vModel: "modelValue", + }, + order: 9999, + }, + }, + }, + }, + }; + } + + async function getCertPlugins() { + const pluginGroup = await pluginStore.getGroups(); + const pluginGroups: { [key: string]: PluginGroup } = pluginGroup.groups; + const certPluginGroup = pluginGroups.cert; + + const certPlugins = []; + for (const plugin of certPluginGroup.plugins) { + const detail: any = await pluginStore.getPluginDefine(plugin.name); + certPlugins.push(detail); + } + return certPlugins; + } + + async function openAddCertdPipelineDialog(req: { defaultGroupId?: number }) { + //检查是否流水线数量超出限制 + await checkPipelineLimit(); + + const wrapperRef = ref(); + function getFormData() { + if (!wrapperRef.value) { + return null; + } + return wrapperRef.value.getFormData(); + } + + async function doSubmit({ form }: any) { + // const certDetail = readCertDetail(form.cert.crt); + // 添加certd pipeline + const triggers = []; + if (form.triggerCron) { + triggers.push({ title: "定时触发", type: "timer", props: { cron: form.triggerCron } }); + } + const notifications = []; + if (form.notification != null) { + notifications.push({ + type: "custom", + when: ["error", "turnToSuccess", "success"], + notificationId: form.notification, + title: form.notificationTarget?.name || "自定义通知", + }); + } + const pluginInput = omit(form, ["triggerCron", "notification", "notificationTarget", "certApplyPlugin", "groupId"]); + let pipeline = { + title: form.domains[0] + "证书自动化", + runnableType: "pipeline", + stages: [ + { + title: "证书申请阶段", + maxTaskCount: 1, + runnableType: "stage", + tasks: [ + { + title: "证书申请任务", + runnableType: "task", + steps: [ + { + title: "申请证书", + runnableType: "step", + input: { + renewDays: 35, + ...pluginInput, + }, + strategy: { + runStrategy: 0, // 正常执行 + }, + type: form.certApplyPlugin, + }, + ], + }, + ], + }, + ], + triggers, + notifications, + }; + pipeline = setRunnableIds(pipeline); + + /** + * // cert: 证书; backup: 备份; custom:自定义; + * type: string; + * // custom: 自定义; monitor: 监控; + * from: string; + */ + const groupId = form.groupId; + const id = await api.Save({ + title: pipeline.title, + content: JSON.stringify(pipeline), + keepHistoryCount: 30, + type: "cert", + groupId, + }); + if (form.email) { + try { + //创建一个默认的邮件通知 + const notificationApi = createNotificationApi(); + await notificationApi.GetOrCreateDefault({ email: form.email }); + } catch (e) { + console.error(e); + } + } + message.success("创建成功,请添加证书部署任务"); + router.push({ path: "/certd/pipeline/detail", query: { id, editMode: "true" } }); + } + const certPlugins = await getCertPlugins(); + const { crudOptions } = createCrudOptions(certPlugins, getFormData, doSubmit); + //@ts-ignore + crudOptions.columns.groupId.form.value = req.defaultGroupId || undefined; + const wrapper = await openCrudFormDialog({ crudOptions }); + wrapperRef.value = wrapper; + } + + return { + openAddCertdPipelineDialog, + }; +} diff --git a/packages/ui/certd-client/src/views/certd/pipeline/crud.tsx b/packages/ui/certd-client/src/views/certd/pipeline/crud.tsx index c710d8b8..d16b388e 100644 --- a/packages/ui/certd-client/src/views/certd/pipeline/crud.tsx +++ b/packages/ui/certd-client/src/views/certd/pipeline/crud.tsx @@ -13,15 +13,16 @@ import { cloneDeep } from "lodash-es"; import { useModal } from "/@/use/use-modal"; import CertView from "./cert-view.vue"; import { eachStages } from "./utils"; -import { setRunnableIds, useCertd } from "/@/views/certd/pipeline/certd-form/use"; +import { setRunnableIds, useCertPipelineCreator } from "/@/views/certd/pipeline/certd-form/use"; import { useCertUpload } from "/@/views/certd/pipeline/cert-upload/use"; +import GroupSelector from "/@/views/certd/pipeline/group/group-selector.vue"; -export default function ({ crudExpose, context: { certdFormRef, groupDictRef, selectedRowKeys } }: CreateCrudOptionsProps): CreateCrudOptionsRet { +export default function ({ crudExpose, context: { groupDictRef, selectedRowKeys } }: CreateCrudOptionsProps): CreateCrudOptionsRet { const router = useRouter(); const { t } = useI18n(); const lastResRef = ref(); - const { openAddCertdPipelineDialog } = useCertd(certdFormRef); + const { openAddCertdPipelineDialog } = useCertPipelineCreator(); const { openUploadCreateDialog } = useCertUpload(); const pageRequest = async (query: UserPageQuery): Promise => { @@ -116,6 +117,13 @@ export default function ({ crudExpose, context: { certdFormRef, groupDictRef, se const userStore = useUserStore(); const settingStore = useSettingStore(); + function onDialogOpen(opt: any) { + const searchForm = crudExpose.getSearchValidatedFormData(); + opt.initialForm = { + groupId: searchForm.groupId, + }; + } + return { crudOptions: { request: { @@ -157,7 +165,9 @@ export default function ({ crudExpose, context: { certdFormRef, groupDictRef, se type: "primary", icon: "ion:ios-add-circle-outline", click() { - openAddCertdPipelineDialog(); + const searchForm = crudExpose.getSearchValidatedFormData(); + const defaultGroupId = searchForm.groupId; + openAddCertdPipelineDialog({ defaultGroupId }); }, }, uploadCert: { @@ -179,7 +189,8 @@ export default function ({ crudExpose, context: { certdFormRef, groupDictRef, se }, icon: "ion:cloud-upload-outline", click() { - openUploadCreateDialog(); + const searchForm = crudExpose.getSearchValidatedFormData(); + openUploadCreateDialog({ defaultGroupId: searchForm.groupId }); }, }, }, @@ -190,6 +201,9 @@ export default function ({ crudExpose, context: { certdFormRef, groupDictRef, se router.push({ path: "/certd/pipeline/detail", query: { id: res.id, editMode: "true" } }); } }, + wrapper: { + onOpen: onDialogOpen, + }, }, table: { scroll: { x: 1500 }, @@ -418,7 +432,7 @@ export default function ({ crudExpose, context: { certdFormRef, groupDictRef, se show: false, }, column: { - sorter: true, + sorter: false, width: 150, align: "center", }, @@ -489,6 +503,12 @@ export default function ({ crudExpose, context: { certdFormRef, groupDictRef, se show: true, }, dict: groupDictRef, + form: { + component: { + name: GroupSelector, + vModel: "modelValue", + }, + }, column: { width: 130, align: "center", diff --git a/packages/ui/certd-client/src/views/certd/pipeline/group/crud.tsx b/packages/ui/certd-client/src/views/certd/pipeline/group/crud.tsx index c8f53a6c..225b1b42 100644 --- a/packages/ui/certd-client/src/views/certd/pipeline/group/crud.tsx +++ b/packages/ui/certd-client/src/views/certd/pipeline/group/crud.tsx @@ -5,7 +5,6 @@ import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, Edi import { pipelineGroupApi } from "./api"; export default function ({ crudExpose, context }: CreateCrudOptionsProps): CreateCrudOptionsRet { - const { t } = useI18n(); const api = pipelineGroupApi; const pageRequest = async (query: UserPageQuery): Promise => { return await api.GetList(query); @@ -34,32 +33,32 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat mobile: { props: { rowHandle: { - width: 160 - } - } - } - } + width: 160, + }, + }, + }, + }, }, request: { pageRequest, addRequest, editRequest, - delRequest + delRequest, }, form: { labelCol: { //固定label宽度 span: null, style: { - width: "100px" - } + width: "100px", + }, }, col: { - span: 22 + span: 22, }, wrapper: { - width: 600 - } + width: 600, + }, }, rowHandle: { width: 200, @@ -72,12 +71,12 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat click({ row, index }) { crudExpose.openEdit({ index, - row + row, }); - } - } - } - } + }, + }, + }, + }, }, table: { editable: { @@ -90,8 +89,8 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat const { row, key, value } = opts; //如果是添加,需要返回{[rowKey]:xxx},比如:{id:2} return await api.UpdateObj({ id: row.id, [key]: value }); - } - } + }, + }, }, columns: { id: { @@ -99,37 +98,37 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat key: "id", type: "number", search: { - show: true + show: true, }, column: { width: 100, editable: { - disabled: true - } + disabled: true, + }, }, form: { - show: false - } + show: false, + }, }, name: { title: "分组名称", search: { - show: true + show: true, }, type: "text", form: { rules: [ { required: true, - message: "请输入分组名称" - } - ] + message: "请输入分组名称", + }, + ], }, column: { - width: 400 - } - } - } - } + width: 400, + }, + }, + }, + }, }; } diff --git a/packages/ui/certd-client/src/views/certd/pipeline/group/group-selector.vue b/packages/ui/certd-client/src/views/certd/pipeline/group/group-selector.vue new file mode 100644 index 00000000..48cd2e8b --- /dev/null +++ b/packages/ui/certd-client/src/views/certd/pipeline/group/group-selector.vue @@ -0,0 +1,60 @@ + + + diff --git a/packages/ui/certd-client/src/views/certd/pipeline/index.vue b/packages/ui/certd-client/src/views/certd/pipeline/index.vue index 0c9f240f..e1cc401a 100644 --- a/packages/ui/certd-client/src/views/certd/pipeline/index.vue +++ b/packages/ui/certd-client/src/views/certd/pipeline/index.vue @@ -15,7 +15,6 @@ - @@ -33,7 +32,6 @@ defineOptions({ name: "PipelineManager", }); -const certdFormRef = ref(); const groupDictRef = dict({ url: "/pi/pipeline/group/all", value: "id", @@ -41,7 +39,6 @@ const groupDictRef = dict({ }); const selectedRowKeys = ref([]); const context: any = { - certdFormRef, groupDictRef, selectedRowKeys, }; diff --git a/packages/ui/certd-client/src/views/certd/pipeline/utils.ts b/packages/ui/certd-client/src/views/certd/pipeline/utils.ts index b8b5bcfe..7e5ad599 100644 --- a/packages/ui/certd-client/src/views/certd/pipeline/utils.ts +++ b/packages/ui/certd-client/src/views/certd/pipeline/utils.ts @@ -2,8 +2,8 @@ import { forEach } from "lodash-es"; import { mySuiteApi } from "/@/views/certd/suite/mine/api"; import { notification } from "ant-design-vue"; import { useSettingStore } from "/@/store/settings"; -//@ts-ignore -import forge from "node-forge"; +import { ReadCertDetail } from "./api"; +import { util } from "/@/utils"; export function eachStages(list: any[], exec: (item: any, runnableType: string) => void, runnableType: string = "stage") { if (!list || list.length <= 0) { return; @@ -70,33 +70,22 @@ export async function checkPipelineLimit() { } } -export function readCertDetail(crt: string) { - const detail = forge.pki.certificateFromPem(crt); - const expires = detail.notAfter; - return { detail, expires }; +export async function readCertDetail(crt: string) { + const cached = await util.cache.get(crt); + if (cached) { + return cached; + } + const res = await ReadCertDetail(crt); + await util.cache.set(crt, res); + return res; } -export function getAllDomainsFromCrt(crt: string) { - const { detail } = readCertDetail(crt); - const domains = []; - - // 1. 提取SAN中的DNS名称 - const sanExtension = detail.extensions.find((ext: any) => ext.name === "subjectAltName"); - if (sanExtension) { - sanExtension.altNames.forEach((altName: any) => { - if (altName.type === 2) { - // type=2 表示DNS名称 - domains.push(altName.value); - } - }); +export async function getAllDomainsFromCrt(crt: string) { + const { detail } = await readCertDetail(crt); + const altNames = detail.domains.altNames; + const commonName = detail.domains.commonName; + if (altNames.includes(commonName)) { + return altNames; } - - // 2. 如果没有SAN,回退到CN(通用名称) - if (domains.length === 0) { - const cnAttr = detail.subject.attributes.find((attr: any) => attr.name === "commonName"); - if (cnAttr) { - domains.push(cnAttr.value); - } - } - return domains; + return [commonName, ...altNames]; } diff --git a/packages/ui/certd-client/src/views/sys/account/index.vue b/packages/ui/certd-client/src/views/sys/account/index.vue index 400f0e44..635c3327 100644 --- a/packages/ui/certd-client/src/views/sys/account/index.vue +++ b/packages/ui/certd-client/src/views/sys/account/index.vue @@ -76,6 +76,7 @@ onMounted(() => { iframeClient.register("updateLicense", async req => { await api.UpdateLicense(req.data); await settingStore.init(); + await settingStore.doBindUrl(); notification.success({ message: "更新成功", description: "专业版/商业版已激活", diff --git a/packages/ui/certd-server/CHANGELOG.md b/packages/ui/certd-server/CHANGELOG.md index a495765e..988e5790 100644 --- a/packages/ui/certd-server/CHANGELOG.md +++ b/packages/ui/certd-server/CHANGELOG.md @@ -3,6 +3,19 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.33.6](https://github.com/certd/certd/compare/v1.33.5...v1.33.6) (2025-04-20) + +### Bug Fixes + +* 上传商用证书,直接粘贴文本报错的问题;修复无法上传ec加密证书的bug ([5750bb7](https://github.com/certd/certd/commit/5750bb706779da274d8e7a87e71416cb64d2df79)) +* 修复下载证书时提示token已过期的问题 ([0e07ae6](https://github.com/certd/certd/commit/0e07ae6ce84dcb9279d3c44060d621566afa593c)) + +### Performance Improvements + +* 新增部署到火山引擎ALB/CLB、上传到证书中心 ([c9a3e3d](https://github.com/certd/certd/commit/c9a3e3d9d26f964c7af7b56667936f1414fbf42a)) +* 优化/api缓存为0 ([dc05cd4](https://github.com/certd/certd/commit/dc05cd481f186b13375192be965000e6b4b429a5)) +* 优化华为cdn插件引用ccm证书 ([b565b4b](https://github.com/certd/certd/commit/b565b4b3b919b71b98ea2517670bc1ef00e00dc9)) + ## [1.33.5](https://github.com/certd/certd/compare/v1.33.4...v1.33.5) (2025-04-17) ### Performance Improvements diff --git a/packages/ui/certd-server/package.json b/packages/ui/certd-server/package.json index 41b1c0f6..3cbcb858 100644 --- a/packages/ui/certd-server/package.json +++ b/packages/ui/certd-server/package.json @@ -1,6 +1,6 @@ { "name": "@certd/ui-server", - "version": "1.33.5", + "version": "1.33.6", "description": "fast-server base midway", "private": true, "type": "module", @@ -38,19 +38,19 @@ "@aws-sdk/client-acm": "^3.699.0", "@aws-sdk/client-cloudfront": "^3.699.0", "@aws-sdk/client-s3": "^3.705.0", - "@certd/acme-client": "^1.33.5", - "@certd/basic": "^1.33.5", - "@certd/commercial-core": "^1.33.5", - "@certd/jdcloud": "^1.33.5", - "@certd/lib-huawei": "^1.33.5", - "@certd/lib-k8s": "^1.33.5", - "@certd/lib-server": "^1.33.5", - "@certd/midway-flyway-js": "^1.33.5", - "@certd/pipeline": "^1.33.5", - "@certd/plugin-cert": "^1.33.5", - "@certd/plugin-lib": "^1.33.5", - "@certd/plugin-plus": "^1.33.5", - "@certd/plus-core": "^1.33.5", + "@certd/acme-client": "^1.33.6", + "@certd/basic": "^1.33.6", + "@certd/commercial-core": "^1.33.6", + "@certd/jdcloud": "^1.33.6", + "@certd/lib-huawei": "^1.33.6", + "@certd/lib-k8s": "^1.33.6", + "@certd/lib-server": "^1.33.6", + "@certd/midway-flyway-js": "^1.33.6", + "@certd/pipeline": "^1.33.6", + "@certd/plugin-cert": "^1.33.6", + "@certd/plugin-lib": "^1.33.6", + "@certd/plugin-plus": "^1.33.6", + "@certd/plus-core": "^1.33.6", "@corsinvest/cv4pve-api-javascript": "^8.3.0", "@huaweicloud/huaweicloud-sdk-cdn": "^3.1.120", "@huaweicloud/huaweicloud-sdk-core": "^3.1.120", diff --git a/packages/ui/certd-server/plugin-doc-gen.mjs b/packages/ui/certd-server/plugin-doc-gen.mjs new file mode 100644 index 00000000..f9b885ab --- /dev/null +++ b/packages/ui/certd-server/plugin-doc-gen.mjs @@ -0,0 +1,53 @@ +// 扫描目录,列出文件,然后加载为模块 + +import { join } from 'path'; +import fs from 'fs' +import { pathToFileURL } from "node:url"; +import path from 'path' +function scanDir(dir) { + const files = fs.readdirSync(dir); + const result = []; + // 扫描目录及子目录 + for (const file of files) { + if (file.includes("index.js")) { + continue; + } + + const filePath = join(dir, file); + const stat = fs.statSync(filePath); + if (stat.isDirectory()) { + result.push(...scanDir(filePath)); + } else { + if (!file.endsWith(".js")) { + continue; + } + result.push(filePath); + } + } + return result +} + +export default async function loadModules(dir) { + const files = scanDir(dir); + const modules = {} + for (const file of files) { + + try { + // 转换为 file:// URL(Windows 必需) + const moduleUrl = pathToFileURL(file).href + const module = await import(moduleUrl) + + // 如果模块有默认导出,优先使用 + modules[file] = module.default || module + } catch (err) { + console.error(`加载模块 ${file} 失败:`, err) + } + } + return modules; +} + +const modules = await loadModules('./dist/plugins'); + +for (const key in modules) { + console.log(key) +} diff --git a/packages/ui/certd-server/src/configuration.ts b/packages/ui/certd-server/src/configuration.ts index ebf6aa08..00d4ddff 100644 --- a/packages/ui/certd-server/src/configuration.ts +++ b/packages/ui/certd-server/src/configuration.ts @@ -96,7 +96,7 @@ export class MainConfiguration { this.app.getMiddleware().insertFirst(async (ctx: IMidwayKoaContext, next: NextFunction) => { await next(); - if (ctx.path === '/' || ctx.path === '/index.html') { + if (ctx.path === '/' || ctx.path === '/index.html' || ctx.path.startsWith("/api")) { ctx.response.set('Cache-Control', 'public,max-age=0'); } }); diff --git a/packages/ui/certd-server/src/controller/user/login/login-controller.ts b/packages/ui/certd-server/src/controller/user/login/login-controller.ts index 90bbae8d..2877c257 100644 --- a/packages/ui/certd-server/src/controller/user/login/login-controller.ts +++ b/packages/ui/certd-server/src/controller/user/login/login-controller.ts @@ -28,7 +28,7 @@ export class LoginController extends BaseController { } private writeTokenCookie(token: { expire: any; token: any }) { - this.ctx.cookies.set("token", token.token, { + this.ctx.cookies.set("certd_token", token.token, { maxAge: 1000 * token.expire }); } @@ -72,5 +72,10 @@ export class LoginController extends BaseController { } @Post('/logout', { summary: Constants.per.authOnly }) - public logout() {} + public logout() { + this.ctx.cookies.set("certd_token", "", { + maxAge: 0 + }); + return this.ok(); + } } diff --git a/packages/ui/certd-server/src/controller/user/pipeline/cert-controller.ts b/packages/ui/certd-server/src/controller/user/pipeline/cert-controller.ts index 7cc6c1f8..200c550d 100644 --- a/packages/ui/certd-server/src/controller/user/pipeline/cert-controller.ts +++ b/packages/ui/certd-server/src/controller/user/pipeline/cert-controller.ts @@ -1,7 +1,8 @@ -import { Controller, Inject, Post, Provide, Query } from '@midwayjs/core'; +import {Body, Controller, Inject, Post, Provide, Query} from '@midwayjs/core'; import { PipelineService } from '../../../modules/pipeline/service/pipeline-service.js'; import { BaseController, Constants } from '@certd/lib-server'; import { StorageService } from '../../../modules/pipeline/service/storage-service.js'; +import {CertReader} from "@certd/plugin-cert"; @Provide() @Controller('/api/pi/cert') @@ -18,4 +19,14 @@ export class CertController extends BaseController { const privateVars = await this.storeService.getPipelinePrivateVars(id); return this.ok(privateVars.cert); } + + + @Post('/readCertDetail', { summary: Constants.per.authOnly }) + async readCertDetail(@Body('crt') crt: string) { + if (!crt) { + throw new Error('crt is required'); + } + const certDetail = CertReader.readCertDetail(crt) + return this.ok(certDetail); + } } diff --git a/packages/ui/certd-server/src/middleware/authority.ts b/packages/ui/certd-server/src/middleware/authority.ts index a5252882..e5a8e56c 100644 --- a/packages/ui/certd-server/src/middleware/authority.ts +++ b/packages/ui/certd-server/src/middleware/authority.ts @@ -56,7 +56,20 @@ export class AuthorityMiddleware implements IWebMiddleware { token = token.replace('Bearer ', '').trim(); if (!token) { //尝试从cookie中获取token - token = ctx.cookies.get('token') || ''; + const cookie = ctx.headers.cookie; + if (cookie) { + const items = cookie.split(';'); + for (const item of items) { + if (!item || !item.trim()) { + continue; + } + const [key, value] = item.split('='); + if (key.trim() === 'certd_token') { + token = value.trim(); + break; + } + } + } } if (!token) { //尝试从query中获取token diff --git a/packages/ui/certd-server/src/plugins/plugin-huawei/plugins/deploy-to-cdn/index.ts b/packages/ui/certd-server/src/plugins/plugin-huawei/plugins/deploy-to-cdn/index.ts index 32a916ef..de14af20 100644 --- a/packages/ui/certd-server/src/plugins/plugin-huawei/plugins/deploy-to-cdn/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-huawei/plugins/deploy-to-cdn/index.ts @@ -19,7 +19,7 @@ import { CertApplyPluginNames} from '@certd/plugin-cert'; export class HauweiDeployCertToCDN extends AbstractTaskPlugin { @TaskInput({ title: '域名证书', - helper: '请选择前置任务输出的域名证书', + helper: '请选择前置任务输出的域名证书\n如果你选择使用ccm证书ID,则需要在[域名管理页面右上角开启SCM授权](https://console.huaweicloud.com/cdn/#/cdn/domain)', component: { name: 'output-selector', from: [...CertApplyPluginNames,'HauweiUploadToCCM'], @@ -62,16 +62,17 @@ export class HauweiDeployCertToCDN extends AbstractTaskPlugin { .withHttpsStatus('on') .withCertificateType('server') - if(typeof this.cert === 'object'){ - httpsConfig= httpsConfig.withCertificateSource(0) - .withCertificateName(this.appendTimeSuffix('certd')) - .withCertificateValue(this.cert.crt) - .withPrivateKey(this.cert.key); - }else{ - this.logger.info('使用已有域名证书:', this.cert); - httpsConfig= httpsConfig.withCertificateSource(2)//scm证书 - .withScmCertificateId(this.cert) - } + if(typeof this.cert === 'object'){ + httpsConfig= httpsConfig.withCertificateSource(0) + .withCertificateName(this.appendTimeSuffix('certd')) + .withCertificateValue(this.cert.crt) + .withPrivateKey(this.cert.key); + }else{ + this.logger.info('使用已有域名证书:', this.cert); + httpsConfig= httpsConfig.withCertificateSource(2)//scm证书 + .withCertificateName(this.appendTimeSuffix('certd')) + .withScmCertificateId(this.cert) + } const config = new cdn.Configs().withHttps(httpsConfig); const body = new cdn.ModifyDomainConfigRequestBody().withConfigs(config); diff --git a/packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/index.ts b/packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/index.ts index 74f66650..f1fe8c1e 100644 --- a/packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/index.ts @@ -1 +1,4 @@ export * from './plugin-deploy-to-cdn.js' +export * from './plugin-deploy-to-clb.js' +export * from './plugin-upload-to-cert-center.js' +export * from './plugin-deploy-to-alb.js' diff --git a/packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/plugin-deploy-to-alb.ts b/packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/plugin-deploy-to-alb.ts new file mode 100644 index 00000000..5fdc0136 --- /dev/null +++ b/packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/plugin-deploy-to-alb.ts @@ -0,0 +1,220 @@ +import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from "@certd/pipeline"; +import { createCertDomainGetterInputDefine, createRemoteSelectInputDefine } from "@certd/plugin-lib"; +import { CertApplyPluginNames, CertInfo } from "@certd/plugin-cert"; +import { VolcengineAccess } from "../access.js"; +import { VolcengineClient } from "../ve-client.js"; + +@IsTaskPlugin({ + name: "VolcengineDeployToALB", + title: "火山引擎-部署证书至ALB", + icon: "svg:icon-volcengine", + group: pluginGroups.volcengine.key, + desc: "部署至火山引擎应用负载均衡", + default: { + strategy: { + runStrategy: RunStrategy.SkipWhenSucceed + } + } +}) +export class VolcengineDeployToALB extends AbstractTaskPlugin { + @TaskInput({ + title: "域名证书", + helper: "请选择前置任务输出的域名证书", + component: { + name: "output-selector", + from: [...CertApplyPluginNames, "VolcengineUploadToCertCenter"] + }, + required: true + }) + cert!: CertInfo | string; + + @TaskInput(createCertDomainGetterInputDefine({ props: { required: false } })) + certDomains!: string[]; + + + @TaskInput({ + title: "Access授权", + helper: "火山引擎AccessKeyId、AccessKeySecret", + component: { + name: "access-selector", + type: "volcengine" + }, + required: true + }) + accessId!: string; + + @TaskInput({ + title: "Region", + helper: "地区选择", + component: { + name: "a-select", + options: [ + /** + * 中国地区 + * 华北2 + * 北京 + * cn-beijing + * 4 + * 可用区A:cn-beijing-a + * 可用区B:cn-beijing-b + * 可用区C:cn-beijing-c + * 可用区D:cn-beijing-d + * 商用 + * 华东2 + * 上海 + * cn-shanghai + * 4 + * 可用区A:cn-shanghai-a + * 可用区B:cn-shanghai-b + * 可用区C:cn-shanghai-c + * 可用区E:cn-shanghai-e + * 商用 + * 华南1 + * 广州 + * cn-guangzhou + * 3 + * 可用区A:cn-guangzhou-a + * 可用区B:cn-guangzhou-b + * 可用区C:cn-guangzhou-c + * 商用 + * 中国香港 + * 香港 + * cn-hongkong + * 2 + * 可用区A:cn-hongkong-a + * 可用区B:cn-hongkong-b + * 商用 + * 其他国家和地区 + * 亚太东南 + * 柔佛 + * ap-southeast-1 + * 2 + * 可用区A:ap-southeast-1a + * 可用区B:ap-southeast-1b + * 商用 + * 雅加达 + * ap-southeast-3 + * 2 + * 可用区A:ap-southeast-3a + * 可用区B:ap-southeast-3b + * 商用 + */ + { label: "北京", value: "cn-beijing" }, + { label: "上海", value: "cn-shanghai" }, + { label: "广州", value: "cn-guangzhou" }, + { label: "香港", value: "cn-hongkong" }, + { label: "柔佛", value: "ap-southeast-1" }, + { label: "雅加达", value: "ap-southeast-3" } + + ] + }, + value: "cn-beijing", + required: true + }) + regionId!: string; + + + @TaskInput( + createRemoteSelectInputDefine({ + title: "监听器列表", + helper: "选择要部署证书的监听器\n需要在监听器中选择证书中心,进行跨服务访问授权", + action: VolcengineDeployToALB.prototype.onGetListenerList.name, + watches: ["certDomains", "accessId", "regionId"], + required: true + }) + ) + listenerList!: string | string[]; + + + async onInstance() { + } + + async execute(): Promise { + this.logger.info("开始部署证书到火山引擎ALB"); + const access = await this.getAccess(this.accessId); + const certService = await this.getCertService(access); + let certId = this.cert; + if (typeof certId !== "string") { + const certInfo = this.cert as CertInfo; + this.logger.info(`开始上传证书`); + certId = await certService.ImportCertificate({ + certName:this.appendTimeSuffix("certd"), + cert:certInfo + }); + this.logger.info(`上传证书成功:${certId}`); + } else { + this.logger.info(`使用已有证书ID:${certId}`); + } + + const service = await this.getAlbService(); + for (const listener of this.listenerList) { + this.logger.info(`开始部署监听器${listener}证书`); + await service.request({ + action: "ModifyListenerAttributes", + query: { + ListenerId: listener, + CertificateSource: "cert_center", + CertCenterCertificateId: certId + } + }); + this.logger.info(`部署监听器${listener}证书成功`); + } + + this.logger.info("部署完成"); + } + + + private async getCertService(access: VolcengineAccess) { + const client = new VolcengineClient({ + logger: this.logger, + access, + http: this.http + }); + + return await client.getCertCenterService(); + } + + private async getAlbService() { + const access = await this.getAccess(this.accessId); + + const client = new VolcengineClient({ + logger: this.logger, + access, + http: this.http + }); + + const service = await client.getAlbService({ + region: this.regionId + }); + return service; + } + + async onGetListenerList(data: any) { + if (!this.accessId) { + throw new Error("请选择Access授权"); + } + const service = await this.getAlbService(); + + const res = await service.request({ + action: "DescribeListeners", + method: "GET", + query: { + PageSize: 100, + Protocol: "HTTPS" + }, + }); + + const list = res.Result.Listeners; + if (!list || list.length === 0) { + throw new Error("找不到HTTPS类型的负载均衡监听器,您也可以手动输入监听器ID"); + } + return list.map((item: any) => { + return { + value: item.ListenerId, + label: `${item.ListenerName}<${item.Description}:${item.ListenerId}>` + }; + }); + } +} + +new VolcengineDeployToALB(); diff --git a/packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/plugin-deploy-to-cdn.ts b/packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/plugin-deploy-to-cdn.ts index b16b34ff..c16411c0 100644 --- a/packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/plugin-deploy-to-cdn.ts +++ b/packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/plugin-deploy-to-cdn.ts @@ -23,7 +23,7 @@ export class VolcengineDeployToCDN extends AbstractTaskPlugin { helper: '请选择前置任务输出的域名证书', component: { name: 'output-selector', - from: [...CertApplyPluginNames, 'VolcengineUploadCert'], + from: [...CertApplyPluginNames, 'VolcengineUploadToCertCenter'], }, required: true, }) @@ -82,11 +82,17 @@ export class VolcengineDeployToCDN extends AbstractTaskPlugin { const client = await this.getClient(access) const service = await client.getCdnClient() + if (!this.cert) { + throw new Error('你还未选择证书'); + } let certId = this.cert if (typeof certId !== 'string') { const certInfo = this.cert as CertInfo this.logger.info(`开始上传证书`) certId = await client.uploadCert(certInfo, this.appendTimeSuffix('certd')) + this.logger.info(`上传证书成功:${certId}`); + }else{ + this.logger.info(`使用已有证书ID:${certId}`); } for (const domain of this.domainName) { diff --git a/packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/plugin-deploy-to-clb.ts b/packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/plugin-deploy-to-clb.ts new file mode 100644 index 00000000..d870803f --- /dev/null +++ b/packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/plugin-deploy-to-clb.ts @@ -0,0 +1,248 @@ +import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from "@certd/pipeline"; +import { createCertDomainGetterInputDefine, createRemoteSelectInputDefine } from "@certd/plugin-lib"; +import { CertApplyPluginNames, CertInfo } from "@certd/plugin-cert"; +import { VolcengineAccess } from "../access.js"; +import { VolcengineClient } from "../ve-client.js"; + +@IsTaskPlugin({ + name: "VolcengineDeployToCLB", + title: "火山引擎-部署证书至CLB", + icon: "svg:icon-volcengine", + group: pluginGroups.volcengine.key, + desc: "部署至火山引擎负载均衡", + default: { + strategy: { + runStrategy: RunStrategy.SkipWhenSucceed + } + } +}) +export class VolcengineDeployToCLB extends AbstractTaskPlugin { + @TaskInput({ + title: "域名证书", + helper: "请选择前置任务输出的域名证书", + component: { + name: "output-selector", + from: [...CertApplyPluginNames, "VolcengineUploadToCertCenter"] + }, + required: true + }) + cert!: CertInfo | string; + + @TaskInput(createCertDomainGetterInputDefine({ props: { required: false } })) + certDomains!: string[]; + + + @TaskInput({ + title: "Access授权", + helper: "火山引擎AccessKeyId、AccessKeySecret", + component: { + name: "access-selector", + type: "volcengine" + }, + required: true + }) + accessId!: string; + + @TaskInput({ + title: "Region", + helper: "地区选择", + component: { + name: "a-select", + options: [ + /** + * 中国地区 + * 华北2 + * 北京 + * cn-beijing + * 4 + * 可用区A:cn-beijing-a + * 可用区B:cn-beijing-b + * 可用区C:cn-beijing-c + * 可用区D:cn-beijing-d + * 商用 + * 华东2 + * 上海 + * cn-shanghai + * 4 + * 可用区A:cn-shanghai-a + * 可用区B:cn-shanghai-b + * 可用区C:cn-shanghai-c + * 可用区E:cn-shanghai-e + * 商用 + * 华南1 + * 广州 + * cn-guangzhou + * 3 + * 可用区A:cn-guangzhou-a + * 可用区B:cn-guangzhou-b + * 可用区C:cn-guangzhou-c + * 商用 + * 中国香港 + * 香港 + * cn-hongkong + * 2 + * 可用区A:cn-hongkong-a + * 可用区B:cn-hongkong-b + * 商用 + * 其他国家和地区 + * 亚太东南 + * 柔佛 + * ap-southeast-1 + * 2 + * 可用区A:ap-southeast-1a + * 可用区B:ap-southeast-1b + * 商用 + * 雅加达 + * ap-southeast-3 + * 2 + * 可用区A:ap-southeast-3a + * 可用区B:ap-southeast-3b + * 商用 + */ + { label: "北京", value: "cn-beijing" }, + { label: "上海", value: "cn-shanghai" }, + { label: "广州", value: "cn-guangzhou" }, + { label: "深圳", value: "cn-shenzhen" }, + { label: "杭州", value: "cn-hangzhou" }, + { label: "南京", value: "cn-north-1" }, + { label: "青岛", value: "cn-qingdao" }, + { label: "重庆", value: "cn-chengdu" }, + { label: "香港", value: "cn-hongkong" }, + { label: "柔佛", value: "ap-southeast-1" }, + { label: "雅加达", value: "ap-southeast-3" } + + ] + }, + value: "cn-beijing", + required: true + }) + regionId!: string; + + + @TaskInput( + createRemoteSelectInputDefine({ + title: "监听器列表", + helper: "选择要部署证书的监听器\n需要在监听器中选择证书中心,进行跨服务访问授权", + action: VolcengineDeployToCLB.prototype.onGetListenerList.name, + watches: ["certDomains", "accessId", "regionId"], + required: true + }) + ) + listenerList!: string | string[]; + + + async onInstance() { + } + + async execute(): Promise { + this.logger.info("开始部署证书到火山引擎CLB"); + const access = await this.getAccess(this.accessId); + const certService = await this.getCertService(access); + let certId = this.cert; + if (typeof certId !== "string") { + const certInfo = this.cert as CertInfo; + this.logger.info(`开始上传证书`); + certId = await certService.ImportCertificate({ + certName:this.appendTimeSuffix("certd"), + cert:certInfo + }); + this.logger.info(`上传证书成功:${certId}`); + } else { + this.logger.info(`使用已有证书ID:${certId}`); + } + + const service = await this.getClbService(); + for (const listener of this.listenerList) { + this.logger.info(`开始部署监听器${listener}证书`); + await service.request({ + action: "ModifyListenerAttributes", + query: { + ListenerId: listener, + CertificateSource: "cert_center", + CertCenterCertificateId: certId + } + }); + this.logger.info(`部署监听器${listener}证书成功`); + } + + this.logger.info("部署完成"); + } + + + private async getCertService(access: VolcengineAccess) { + const client = new VolcengineClient({ + logger: this.logger, + access, + http: this.http + }); + + return await client.getCertCenterService(); + } + + async onGetClbList(data: any) { + if (!this.accessId) { + throw new Error("请选择Access授权"); + } + const service = await this.getClbService(); + const res = await service.request({ + action: "DescribeLoadBalancers", + method: "GET", + query: { + PageSize: 100 + }, + }); + + const list = res.Result.LoadBalancers; + + return list.map((item: any) => { + return { + value: item.LoadBalancerId, + label: `${item.LoadBalancerName}<${item.Description}>` + }; + }); + } + + private async getClbService() { + const access = await this.getAccess(this.accessId); + + const client = new VolcengineClient({ + logger: this.logger, + access, + http: this.http + }); + + const service = await client.getClbService({ + region: this.regionId + }); + return service; + } + + async onGetListenerList(data: any) { + if (!this.accessId) { + throw new Error("请选择Access授权"); + } + const service = await this.getClbService(); + + const res = await service.request({ + action: "DescribeListeners", + method: "GET", + query: { + PageSize: 100, + Protocol: "HTTPS" + }, + }); + + const list = res.Result.Listeners; + if (!list || list.length === 0) { + throw new Error("找不到HTTPS类型的负载均衡监听器,您也可以手动输入监听器ID"); + } + return list.map((item: any) => { + return { + value: item.ListenerId, + label: `${item.ListenerName}<${item.Description}:${item.ListenerId}>` + }; + }); + } +} + +new VolcengineDeployToCLB(); diff --git a/packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/plugin-upload-to-cert-center.ts b/packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/plugin-upload-to-cert-center.ts new file mode 100644 index 00000000..b289ae70 --- /dev/null +++ b/packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/plugin-upload-to-cert-center.ts @@ -0,0 +1,77 @@ +import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput, TaskOutput } from "@certd/pipeline"; +import { createCertDomainGetterInputDefine } from "@certd/plugin-lib"; +import { CertApplyPluginNames, CertInfo } from "@certd/plugin-cert"; +import { VolcengineAccess } from "../access.js"; +import { VolcengineClient } from "../ve-client.js"; + +@IsTaskPlugin({ + name: 'VolcengineUploadToCertCenter', + title: '火山引擎-上传证书至证书中心', + icon: 'svg:icon-volcengine', + group: pluginGroups.volcengine.key, + desc: '上传证书至火山引擎证书中心', + default: { + strategy: { + runStrategy: RunStrategy.SkipWhenSucceed, + }, + }, +}) +export class VolcengineUploadToCertCenter extends AbstractTaskPlugin { + @TaskInput({ + title: '域名证书', + helper: '请选择前置任务输出的域名证书', + component: { + name: 'output-selector', + from: [...CertApplyPluginNames], + }, + required: true, + }) + cert!: CertInfo; + + @TaskInput(createCertDomainGetterInputDefine({ props: { required: false } })) + certDomains!: string[]; + + + @TaskInput({ + title: 'Access授权', + helper: '火山引擎AccessKeyId、AccessKeySecret', + component: { + name: 'access-selector', + type: 'volcengine', + }, + required: true, + }) + accessId!: string; + + + @TaskOutput({ + title: '上传成功后的火山引擎证书Id', + }) + volcengineCertId?: string; + + async onInstance() {} + async execute(): Promise { + this.logger.info('开始上传证书到证书中心'); + const access = await this.getAccess(this.accessId); + + const client = await this.getClient(access) + const service = await client.getCertCenterService() + const certInfo = this.cert + this.logger.info(`开始上传证书`) + this.volcengineCertId = await service.ImportCertificate({ + certName: this.appendTimeSuffix('certd'), + cert: certInfo + }) + this.logger.info(`上传完成:${this.volcengineCertId}`); + } + + + async getClient(access: VolcengineAccess) { + return new VolcengineClient({ + logger: this.logger, + access, + http:this.http + }) + } +} +new VolcengineUploadToCertCenter(); diff --git a/packages/ui/certd-server/src/plugins/plugin-volcengine/ve-client.ts b/packages/ui/certd-server/src/plugins/plugin-volcengine/ve-client.ts new file mode 100644 index 00000000..445340df --- /dev/null +++ b/packages/ui/certd-server/src/plugins/plugin-volcengine/ve-client.ts @@ -0,0 +1,122 @@ +import { VolcengineAccess } from "./access.js"; +import { HttpClient, ILogger } from "@certd/basic"; + +export type VolcengineOpts = { + access: VolcengineAccess + logger: ILogger + http: HttpClient +} + +export class VolcengineClient { + opts: VolcengineOpts; + CommonService: any; + + constructor(opts: VolcengineOpts) { + this.opts = opts; + } + + async getCertCenterService() { + const CommonService = await this.getServiceCls(); + + const service = new CommonService({ + serviceName: "certificate_service", + defaultVersion: "2024-10-01" + }); + service.setAccessKeyId(this.opts.access.accessKeyId); + service.setSecretKey(this.opts.access.secretAccessKey); + service.setRegion("cn-beijing"); + + service.ImportCertificate = async (body: { certName: string, cert: any }) => { + const { certName, cert } = body; + const res = await service.request({ + action: "ImportCertificate", + method: "POST", + body: { + Tag: certName, + Repeatable: false, + CertificateInfo: { + CertificateChain: cert.crt, + PrivateKey: cert.key + } + } + }); + return res.Result.InstanceId || res.Result.RepeatId + }; + return service; + } + + async getClbService(opts: { region?: string }) { + const CommonService = await this.getServiceCls(); + + const service = new CommonService({ + serviceName: "clb", + defaultVersion: "2020-04-01" + }); + service.setAccessKeyId(this.opts.access.accessKeyId); + service.setSecretKey(this.opts.access.secretAccessKey); + service.setRegion(opts.region); + + return service; + } + + async getAlbService(opts: { region?: string }) { + const CommonService = await this.getServiceCls(); + + const service = new CommonService({ + serviceName: "alb", + defaultVersion: "2020-04-01" + }); + service.setAccessKeyId(this.opts.access.accessKeyId); + service.setSecretKey(this.opts.access.secretAccessKey); + service.setRegion(opts.region); + + return service; + } + + async getServiceCls() { + if (this.CommonService) { + return this.CommonService; + } + const { Service } = await import("@volcengine/openapi"); + + class CommonService extends Service { + Generic: any; + + constructor(options: { + serviceName: string; + defaultVersion: string; + }) { + super(Object.assign({ host: "open.volcengineapi.com" }, options)); + this.Generic = async (req: { action: string, body?: any, method?: string, query?: any }) => { + const { action, method, body, query } = req; + return await this.fetchOpenAPI({ + Action: action, + Version: options.defaultVersion, + method: method as any, + headers: { + "content-type": "application/json" + }, + query: query || {}, + data: body + }); + }; + } + + async request(req: { action: string, body?: any, method?: string, query?: any }) { + const res = await this.Generic(req); + if (res.errorcode) { + throw new Error(`${res.errorcode}:${res.message}`); + } + if (res.ResponseMetadata?.Error) { + throw new Error(res.ResponseMetadata?.Error?.Message); + } + return res; + } + } + + this.CommonService = CommonService; + return CommonService; + } + + +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ceafc151..e5dfa03a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -46,7 +46,7 @@ importers: packages/core/acme-client: dependencies: '@certd/basic': - specifier: ^1.33.4 + specifier: ^1.33.5 version: link:../basic '@peculiar/x509': specifier: ^1.11.0 @@ -204,10 +204,10 @@ importers: packages/core/pipeline: dependencies: '@certd/basic': - specifier: ^1.33.4 + specifier: ^1.33.5 version: link:../basic '@certd/plus-core': - specifier: ^1.33.4 + specifier: ^1.33.5 version: link:../../pro/plus-core dayjs: specifier: ^1.11.7 @@ -412,7 +412,7 @@ importers: packages/libs/lib-k8s: dependencies: '@certd/basic': - specifier: ^1.33.4 + specifier: ^1.33.5 version: link:../../core/basic '@kubernetes/client-node': specifier: 0.21.0 @@ -452,16 +452,16 @@ importers: packages/libs/lib-server: dependencies: '@certd/acme-client': - specifier: ^1.33.4 + specifier: ^1.33.5 version: link:../../core/acme-client '@certd/basic': - specifier: ^1.33.4 + specifier: ^1.33.5 version: link:../../core/basic '@certd/pipeline': - specifier: ^1.33.4 + specifier: ^1.33.5 version: link:../../core/pipeline '@certd/plus-core': - specifier: ^1.33.4 + specifier: ^1.33.5 version: link:../../pro/plus-core '@midwayjs/cache': specifier: ~3.14.0 @@ -604,16 +604,16 @@ importers: packages/plugins/plugin-cert: dependencies: '@certd/acme-client': - specifier: ^1.33.4 + specifier: ^1.33.5 version: link:../../core/acme-client '@certd/basic': - specifier: ^1.33.4 + specifier: ^1.33.5 version: link:../../core/basic '@certd/pipeline': - specifier: ^1.33.4 + specifier: ^1.33.5 version: link:../../core/pipeline '@certd/plugin-lib': - specifier: ^1.33.4 + specifier: ^1.33.5 version: link:../plugin-lib '@google-cloud/publicca': specifier: ^1.3.0 @@ -680,10 +680,10 @@ importers: specifier: ^1.7.10 version: 1.8.0 '@certd/basic': - specifier: ^1.33.4 + specifier: ^1.33.5 version: link:../../core/basic '@certd/pipeline': - specifier: ^1.33.4 + specifier: ^1.33.5 version: link:../../core/pipeline '@kubernetes/client-node': specifier: 0.21.0 @@ -771,19 +771,19 @@ importers: packages/pro/commercial-core: dependencies: '@certd/basic': - specifier: ^1.33.4 + specifier: ^1.33.5 version: link:../../core/basic '@certd/lib-server': - specifier: ^1.33.4 + specifier: ^1.33.5 version: link:../../libs/lib-server '@certd/pipeline': - specifier: ^1.33.4 + specifier: ^1.33.5 version: link:../../core/pipeline '@certd/plugin-plus': - specifier: ^1.33.4 + specifier: ^1.33.5 version: link:../plugin-plus '@certd/plus-core': - specifier: ^1.33.4 + specifier: ^1.33.5 version: link:../plus-core '@midwayjs/core': specifier: ~3.20.3 @@ -868,22 +868,22 @@ importers: specifier: ^1.0.2 version: 1.0.2 '@certd/basic': - specifier: ^1.33.4 + specifier: ^1.33.5 version: link:../../core/basic '@certd/lib-k8s': - specifier: ^1.33.4 + specifier: ^1.33.5 version: link:../../libs/lib-k8s '@certd/pipeline': - specifier: ^1.33.4 + specifier: ^1.33.5 version: link:../../core/pipeline '@certd/plugin-cert': - specifier: ^1.33.4 + specifier: ^1.33.5 version: link:../../plugins/plugin-cert '@certd/plugin-lib': - specifier: ^1.33.4 + specifier: ^1.33.5 version: link:../../plugins/plugin-lib '@certd/plus-core': - specifier: ^1.33.4 + specifier: ^1.33.5 version: link:../plus-core ali-oss: specifier: ^6.21.0 @@ -980,7 +980,7 @@ importers: packages/pro/plus-core: dependencies: '@certd/basic': - specifier: ^1.33.4 + specifier: ^1.33.5 version: link:../../core/basic dayjs: specifier: ^1.11.7 @@ -1270,10 +1270,10 @@ importers: version: 0.1.3(zod@3.24.2) devDependencies: '@certd/lib-iframe': - specifier: ^1.33.4 + specifier: ^1.33.5 version: link:../../libs/lib-iframe '@certd/pipeline': - specifier: ^1.33.4 + specifier: ^1.33.5 version: link:../../core/pipeline '@rollup/plugin-commonjs': specifier: ^25.0.7 @@ -1453,43 +1453,43 @@ importers: specifier: ^3.705.0 version: 3.758.0(aws-crt@1.25.3) '@certd/acme-client': - specifier: ^1.33.4 + specifier: ^1.33.5 version: link:../../core/acme-client '@certd/basic': - specifier: ^1.33.4 + specifier: ^1.33.5 version: link:../../core/basic '@certd/commercial-core': - specifier: ^1.33.4 + specifier: ^1.33.5 version: link:../../pro/commercial-core '@certd/jdcloud': - specifier: ^1.33.4 + specifier: ^1.33.5 version: link:../../libs/lib-jdcloud '@certd/lib-huawei': - specifier: ^1.33.4 + specifier: ^1.33.5 version: link:../../libs/lib-huawei '@certd/lib-k8s': - specifier: ^1.33.4 + specifier: ^1.33.5 version: link:../../libs/lib-k8s '@certd/lib-server': - specifier: ^1.33.4 + specifier: ^1.33.5 version: link:../../libs/lib-server '@certd/midway-flyway-js': - specifier: ^1.33.4 + specifier: ^1.33.5 version: link:../../libs/midway-flyway-js '@certd/pipeline': - specifier: ^1.33.4 + specifier: ^1.33.5 version: link:../../core/pipeline '@certd/plugin-cert': - specifier: ^1.33.4 + specifier: ^1.33.5 version: link:../../plugins/plugin-cert '@certd/plugin-lib': - specifier: ^1.33.4 + specifier: ^1.33.5 version: link:../../plugins/plugin-lib '@certd/plugin-plus': - specifier: ^1.33.4 + specifier: ^1.33.5 version: link:../../pro/plugin-plus '@certd/plus-core': - specifier: ^1.33.4 + specifier: ^1.33.5 version: link:../../pro/plus-core '@corsinvest/cv4pve-api-javascript': specifier: ^8.3.0 @@ -20673,13 +20673,13 @@ snapshots: resolve: 1.22.10 semver: 6.3.1 - eslint-plugin-prettier@3.4.1(eslint-config-prettier@8.10.0(eslint@7.32.0))(eslint@7.32.0)(prettier@2.8.8): + eslint-plugin-prettier@3.4.1(eslint-config-prettier@8.10.0(eslint@8.57.0))(eslint@7.32.0)(prettier@2.8.8): dependencies: eslint: 7.32.0 prettier: 2.8.8 prettier-linter-helpers: 1.0.0 optionalDependencies: - eslint-config-prettier: 8.10.0(eslint@7.32.0) + eslint-config-prettier: 8.10.0(eslint@8.57.0) eslint-plugin-prettier@4.2.1(eslint-config-prettier@8.10.0(eslint@8.57.0))(eslint@8.57.0)(prettier@2.8.8): dependencies: @@ -23393,7 +23393,7 @@ snapshots: eslint: 7.32.0 eslint-config-prettier: 8.10.0(eslint@7.32.0) eslint-plugin-node: 11.1.0(eslint@7.32.0) - eslint-plugin-prettier: 3.4.1(eslint-config-prettier@8.10.0(eslint@7.32.0))(eslint@7.32.0)(prettier@2.8.8) + eslint-plugin-prettier: 3.4.1(eslint-config-prettier@8.10.0(eslint@8.57.0))(eslint@7.32.0)(prettier@2.8.8) execa: 5.1.1 inquirer: 7.3.3 json5: 2.2.3