Compare commits
150 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a1e504c138 | ||
|
|
4cc413047c | ||
|
|
2397097e4d | ||
|
|
c88f959ec9 | ||
|
|
0b2e28b62d | ||
|
|
c7f2ead696 | ||
|
|
b454e02d01 | ||
|
|
47df2ffc3e | ||
|
|
d18e431e2f | ||
|
|
0a147d2db7 | ||
|
|
ccdc933064 | ||
|
|
023f2d4569 | ||
|
|
06a7371d2b | ||
|
|
626f5d3487 | ||
|
|
8cd3b9fe2e | ||
|
|
716c35d52a | ||
|
|
8cc0f3918b | ||
|
|
98b51f0799 | ||
|
|
81d6dad548 | ||
|
|
41bc11cf96 | ||
|
|
721dbe415a | ||
|
|
f5c0b51428 | ||
|
|
892c6ad80c | ||
|
|
a47805e494 | ||
|
|
9dd49054d1 | ||
|
|
f5d1d1a0b7 | ||
|
|
d75fcb7fec | ||
|
|
826be45b6a | ||
|
|
d35d9c17c5 | ||
|
|
638c9720cf | ||
|
|
08a190882f | ||
|
|
bfa7530a39 | ||
|
|
6c74148c27 | ||
|
|
480cad0fed | ||
|
|
32be489136 | ||
|
|
11801d8e2e | ||
|
|
1b280a2940 | ||
|
|
424890a1e1 | ||
|
|
5f85219495 | ||
|
|
a63d687f1c | ||
|
|
f2d6c3ad83 | ||
|
|
0b6941d5ce | ||
|
|
048696ee93 | ||
|
|
27a405fb1d | ||
|
|
e2cf65b591 | ||
|
|
9749fc817d | ||
|
|
e6600f2c43 | ||
|
|
a664931e7a | ||
|
|
a2ba965600 | ||
|
|
65255dbb50 | ||
|
|
a5cb8761a5 | ||
|
|
e3930e0717 | ||
|
|
afd59e9933 | ||
|
|
8087524bef | ||
|
|
605440812f | ||
|
|
b10c6eb615 | ||
|
|
a96264ff6a | ||
|
|
deb3893820 | ||
|
|
9b1d822b5b | ||
|
|
5cd61c4c02 | ||
|
|
586fa70eac | ||
|
|
9b420ad33f | ||
|
|
5891290672 | ||
|
|
72a7b51d47 | ||
|
|
2943e0e58d | ||
|
|
5abce916a8 | ||
|
|
89d4be8a0a | ||
|
|
b7113bda23 | ||
|
|
0088929622 | ||
|
|
b3468cf7f2 | ||
|
|
f88c5c8528 | ||
|
|
687fdda7f7 | ||
|
|
aec51e514c | ||
|
|
308d4600ef | ||
|
|
50a5fa15bb | ||
|
|
7d96a57d73 | ||
|
|
162ebfd4e0 | ||
|
|
a586a92d5e | ||
|
|
3df20a924f | ||
|
|
ddcf466e4e | ||
|
|
5d10cbf18d | ||
|
|
8d9afa7592 | ||
|
|
95e05336c2 | ||
|
|
a188385817 | ||
|
|
0a6baf331b | ||
|
|
0e29e052d5 | ||
|
|
d8d255980e | ||
|
|
dc5a5fa543 | ||
|
|
8638fc91ff | ||
|
|
96a0900edc | ||
|
|
abea80e3ab | ||
|
|
42dfe936b7 | ||
|
|
8385bcc2d7 | ||
|
|
9b8f60b64b | ||
|
|
474114236e | ||
|
|
238b0b421a | ||
|
|
8abe62886a | ||
|
|
78cc9cffe4 | ||
|
|
59a5dd713f | ||
|
|
a39024ff03 | ||
|
|
72bfbd93a8 | ||
|
|
c9a3e3d9d2 | ||
|
|
8387708901 | ||
|
|
b565b4b3b9 | ||
|
|
893dcd4f24 | ||
|
|
d613aa8f3e | ||
|
|
5750bb7067 | ||
|
|
0e07ae6ce8 | ||
|
|
02b6351e13 | ||
|
|
78367af830 | ||
|
|
dc05cd481f | ||
|
|
7daad5477a | ||
|
|
45cdfbfae8 | ||
|
|
3fb5c38571 | ||
|
|
59f80ebc47 | ||
|
|
198a97b00c | ||
|
|
3ea4e917e8 | ||
|
|
60ad077172 | ||
|
|
356ad28e41 | ||
|
|
e241141220 | ||
|
|
14bb1b467a | ||
|
|
2bbea6fd3f | ||
|
|
48aef25b3f | ||
|
|
8e50e5dee3 | ||
|
|
d5d54d4d3b | ||
|
|
412e8a32dd | ||
|
|
0f82cf409b | ||
|
|
79df39acab | ||
|
|
8786bae7dc | ||
|
|
4b3f8ca361 | ||
|
|
03183218f7 | ||
|
|
95b6db57e1 | ||
|
|
bbe0c2457b | ||
|
|
c894c53e69 | ||
|
|
5b3fb7387d | ||
|
|
feac310caf | ||
|
|
d67ec3feb3 | ||
|
|
cf8abb4528 | ||
|
|
d66de26de4 | ||
|
|
e5a7ada3cf | ||
|
|
b76fdd7fe4 | ||
|
|
7edf3f6147 | ||
|
|
2143dff2ae | ||
|
|
32c714d1b6 | ||
|
|
84e699ee24 | ||
|
|
7fdb572b8b | ||
|
|
91ffb0820a | ||
|
|
cfd3b66be9 | ||
|
|
75c4f9dea8 | ||
|
|
a76a32230d |
104
CHANGELOG.md
@@ -3,6 +3,110 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.34.2](https://github.com/certd/certd/compare/v1.34.1...v1.34.2) (2025-05-11)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 修复部署到又拍云强制https无效的bug ([2397097](https://github.com/certd/certd/commit/2397097e4ddcb6f593210598e8779ffd44ac3f8f))
|
||||
* 修复刷新流水线页面后,日志不自动更新的bug ([0b2e28b](https://github.com/certd/certd/commit/0b2e28b62dd5eb6804c602083e65c87a9d1d72d2))
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 集成智能问答机器人 ([9dd4905](https://github.com/certd/certd/commit/9dd49054d18ec436a5029444ca55a38adc682933))
|
||||
* 支持设置网安备案号 ([d18e431](https://github.com/certd/certd/commit/d18e431e2f08e6b37704032c4ea6fbdd8e971442))
|
||||
* http方式支持校验443端口 ([d75fcb7](https://github.com/certd/certd/commit/d75fcb7fec421a9a638eaa27fe9378c84b5e0f19))
|
||||
|
||||
## [1.34.1](https://github.com/certd/certd/compare/v1.34.0...v1.34.1) (2025-05-05)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 根据SOA记录判断子域名托管有缺陷,改回手动配置子域名托管记录的方式 ([1b280a2](https://github.com/certd/certd/commit/1b280a2940f9e2d919b0bf23b89cc185be1fa498))
|
||||
* 修复宝塔授权测试按钮显示错误的bug ([048696e](https://github.com/certd/certd/commit/048696ee9386491bb68592fb3a47d1c900bb68bf))
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 支持部署证书到火山dcdn ([5f85219](https://github.com/certd/certd/commit/5f852194953dc1b4e6336770f417507b8f5a33ad))
|
||||
* 支持部署证书到unicloud ([a63d687](https://github.com/certd/certd/commit/a63d687f1c573159f0857693f37602b0e1e44072))
|
||||
|
||||
# [1.34.0](https://github.com/certd/certd/compare/v1.33.8...v1.34.0) (2025-04-28)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 修复二次认证登录进入错误账号的bug ([e3930e0](https://github.com/certd/certd/commit/e3930e07172dd7903cb0f6ff26e0e3e828ba3e77))
|
||||
|
||||
### Features
|
||||
|
||||
* 从yaml文件注册插件 ([deb3893](https://github.com/certd/certd/commit/deb38938204b29543f36d3266249958faaaa6b66))
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 优化cdnfly插件,支持自动匹配域名部署 ([afd59e9](https://github.com/certd/certd/commit/afd59e9933b2650f41c5d47684c171b93b962065))
|
||||
|
||||
## [1.33.8](https://github.com/certd/certd/compare/v1.33.7...v1.33.8) (2025-04-26)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 服务器时间获取不准确的bug ([5d10cbf](https://github.com/certd/certd/commit/5d10cbf18daf94a90a7551641a3b13e3c5fec611))
|
||||
* 修复复制流水线无效的bug ([3df20a9](https://github.com/certd/certd/commit/3df20a924f32970b052e2588ea20de095f0ea693))
|
||||
* 修复http上传方式无法清除记录文件的bug ([72a7b51](https://github.com/certd/certd/commit/72a7b51d479602b2c54c6c3ac8d8a0dcb9664e73))
|
||||
* 修复token过期后,疯狂打印token过期信息的bug ([50a5fa1](https://github.com/certd/certd/commit/50a5fa15bb240a125bbc91d2ce1ff3c835888a77))
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 从域名的soa获取主域名,子域名托管无需额外配置 ([a586a92](https://github.com/certd/certd/commit/a586a92d5e32ea846ac37be52a7ad8c328d89966))
|
||||
* 七牛oss支持删除过期备份 ([b7113bd](https://github.com/certd/certd/commit/b7113bda2378116d6c116dc583f563cce7cf9f00))
|
||||
* 数据库备份支持oss ([308d460](https://github.com/certd/certd/commit/308d4600efe2002f199c33b4594d3071784e58ea))
|
||||
* 支持阿里云中文域名申请 ([b3468cf](https://github.com/certd/certd/commit/b3468cf7f28228d7c9cf68de6b5a9bbeb67f2c6d))
|
||||
* 支持反向代理增加contextPath路径 ([0088929](https://github.com/certd/certd/commit/0088929622160cc922995de9a563e8061686ff34))
|
||||
* 支持中文域名 ([162ebfd](https://github.com/certd/certd/commit/162ebfd4e0c25727efb33952d3bbf7420a02e2c3))
|
||||
|
||||
## [1.33.7](https://github.com/certd/certd/compare/v1.33.6...v1.33.7) (2025-04-22)
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 添加部署证书至火山 Live ([abea80e](https://github.com/certd/certd/commit/abea80e3ab9b1672aebe1c5d5e856693b29931a8))
|
||||
* 优化首页插件列表展示 ([9b8f60b](https://github.com/certd/certd/commit/9b8f60b64b5f9a3db7dfa9b3dcbd9201984358d0))
|
||||
* 证书申请支持51dns ([8638fc9](https://github.com/certd/certd/commit/8638fc91ff34fccaf12ff9874fd3fa9d2a8c18b7))
|
||||
* 支持51dns ([96a0900](https://github.com/certd/certd/commit/96a0900edc95dcfd9acccf9d13592f12f5a09b3d))
|
||||
* ssh PTY模式登录设置 ([8385bcc](https://github.com/certd/certd/commit/8385bcc2d7f2411a07748bb5c53f9eaf4d38d7cc))
|
||||
* ssh伪终端模式优化,windows下不开启 ([42dfe93](https://github.com/certd/certd/commit/42dfe936b773b7bdd82ca3378363252ffffd7b71))
|
||||
|
||||
## [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
|
||||
|
||||
* 登录支持双重认证 ([48aef25](https://github.com/certd/certd/commit/48aef25b3f6499d674ca4e4ef16f4c62399fb735))
|
||||
* 多重认证登录 ([0f82cf4](https://github.com/certd/certd/commit/0f82cf409bc60706ab07e4ca4f272b9a1ca7eecb))
|
||||
* 优化部署到华为云CDN,支持先上传到ccm,再使用证书id部署,修复offline状态下导致部署报错的bug ([79df39a](https://github.com/certd/certd/commit/79df39acabab10ae7e1864dadcdc186bb007a3c5))
|
||||
|
||||
## [1.33.4](https://github.com/certd/certd/compare/v1.33.3...v1.33.4) (2025-04-15)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 补充类型断言 ([2143dff](https://github.com/certd/certd/commit/2143dff2ae96e6a78bef9f0498e36f8cd9e6941f))
|
||||
* 修复腾讯云部署到任意资源插件,无法使用之前已上传的腾讯云证书问题 ([32c714d](https://github.com/certd/certd/commit/32c714d1b6e68c71a74a7452115040c87ac4bfdc))
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 插件支持导入导出 ([cf8abb4](https://github.com/certd/certd/commit/cf8abb45282070c8ba91469f93fd379fabf1f74a))
|
||||
* 支持上传证书到华为云CCM ([cfd3b66](https://github.com/certd/certd/commit/cfd3b66be9ebf53a26693057e70ed60c3f116be9))
|
||||
|
||||
## [1.33.3](https://github.com/certd/certd/compare/v1.33.2...v1.33.3) (2025-04-14)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
144
README.md
@@ -5,24 +5,34 @@ Certd 是一个免费全自动申请和自动部署更新SSL证书的管理系
|
||||
|
||||
关键字:证书自动申请、证书自动更新、证书自动续期、证书自动续签、证书管理工具
|
||||
|
||||
> 关于证书续期:
|
||||
>* 实际上没有办法不改变证书文件本身情况下直接续期或者续签。
|
||||
>* 我们所说的续期,其实就是按照全套流程重新申请一份新证书,然后重新部署上去。
|
||||
>* 免费证书过期时间90天,以后可能还会缩短,所以自动化部署必不可少
|
||||
|
||||
|
||||
> 流水线数量现已调整为无限制,欢迎大家使用
|
||||
|
||||
## 一、特性
|
||||
本项目不仅支持证书申请过程自动化,还可以自动化部署更新证书,让你的证书永不过期。
|
||||
|
||||
* 全自动申请证书(支持所有注册商注册的域名)
|
||||
* 全自动部署更新证书(目前支持部署到主机、阿里云、腾讯云等,目前已支持60+部署插件)
|
||||
* 支持DNS-01、HTTP-01、CNAME代理等多种域名验证方式
|
||||
* 全自动申请证书(支持所有注册商注册的域名,支持DNS-01、HTTP-01、CNAME代理等多种域名验证方式)
|
||||
* 全自动部署更新证书(目前支持部署到主机、阿里云、腾讯云等70+部署插件)
|
||||
* 支持通配符域名/泛域名,支持多个域名打到一个证书上,支持pem、pfx、der、jks等多种证书格式
|
||||
* 邮件通知、webhook通知
|
||||
* 私有化部署,数据保存本地,授权信息加密存储,镜像由Github Actions构建,过程公开透明
|
||||
* 支持SQLite,PostgreSQL、MySQL数据库
|
||||
* 邮件通知、webhook通知、企微、钉钉、飞书、anpush等多种通知方式
|
||||
* 私有化部署,数据保存本地,安装升级非常简单快捷
|
||||
* 镜像由Github Actions构建,过程公开透明
|
||||
* 授权加密,站点隐藏,2FA,密码防爆破等多重安全保障
|
||||
* 支持SQLite,PostgreSQL、MySQL多种数据库
|
||||
* 开放接口支持
|
||||
* 站点证书监控
|
||||
* 多用户管理
|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
>
|
||||
> 流水线数量现已调整为无限制,欢迎大家使用
|
||||
>
|
||||
|
||||
> 关于证书续期:
|
||||
>* 实际上没有办法不改变证书文件本身情况下直接续期或者续签。
|
||||
>* 我们所说的续期,其实就是按照全套流程重新申请一份新证书,然后重新部署上去。
|
||||
|
||||
|
||||
## 二、在线体验
|
||||
@@ -62,7 +72,7 @@ https://certd.handfree.work/
|
||||
-------> [点我查看详细使用步骤演示](./step.md) <--------
|
||||
↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
|
||||
|
||||
更多教程请访问文档网站 [certd.docmirror.cn](https://certd.docmirror.cn/)
|
||||
更多教程请访问官方文档 [certd.docmirror.cn](https://certd.docmirror.cn/guide/)
|
||||
|
||||
|
||||
|
||||
@@ -72,10 +82,10 @@ https://certd.handfree.work/
|
||||
|
||||
您可以根据实际情况从如下方式中选择一种方式进行私有化部署:
|
||||
|
||||
1. [宝塔面板方式部署](https://certd.docmirror.cn/guide/install/docker/)
|
||||
2. [1Panel面板方式部署](https://certd.docmirror.cn/guide/install/1panel/)
|
||||
3. [Docker方式部署](https://certd.docmirror.cn/guide/install/docker/)
|
||||
4. [源码方式部署](https://certd.docmirror.cn/guide/install/source/)
|
||||
1. [宝塔面板方式部署 推荐](https://certd.docmirror.cn/guide/install/docker/)
|
||||
2. [1Panel面板方式部署 推荐](https://certd.docmirror.cn/guide/install/1panel/)
|
||||
3. [Docker方式部署 推荐](https://certd.docmirror.cn/guide/install/docker/)
|
||||
4. [源码方式部署 不建议](https://certd.docmirror.cn/guide/install/source/)
|
||||
|
||||
#### Docker镜像说明:
|
||||
* 国内镜像地址:
|
||||
@@ -101,86 +111,20 @@ https://certd.handfree.work/
|
||||
> * 请务必做好服务器本身的安全防护,防止数据库泄露
|
||||
> * 请务必做好数据备份,避免数据丢失
|
||||
|
||||
## 五、 升级
|
||||
|
||||
### docker-compose方式部署
|
||||
#### 1. 如果使用固定版本号
|
||||
1. 修改`docker-compose.yaml`中的镜像版本号
|
||||
2. 运行`docker compose up -d` 即可
|
||||
|
||||
#### 2. 如果需要使用最新版本
|
||||
```shell
|
||||
#重新拉取镜像
|
||||
docker pull registry.cn-shenzhen.aliyuncs.com/handsfree/certd:latest
|
||||
# 重新启动容器
|
||||
docker compose down
|
||||
docker compose up -d
|
||||
```
|
||||
> 数据默认存在`/data/certd`目录下,不用担心数据丢失
|
||||
|
||||
### 自动升级(仅限尝鲜建议非生产使用)
|
||||
```yaml
|
||||
version: '3.3'
|
||||
services:
|
||||
certd:
|
||||
image: registry.cn-shenzhen.aliyuncs.com/handsfree/certd:latest
|
||||
container_name: certd
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- /data/certd:/app/data
|
||||
ports:
|
||||
- "7001:7001"
|
||||
- "7002:7002"
|
||||
environment:
|
||||
- certd_system_resetAdminPasswd=false
|
||||
labels:
|
||||
com.centurylinklabs.watchtower.enable: "true"
|
||||
|
||||
certd-updater: # 添加 Watchtower 服务
|
||||
image: containrrr/watchtower:latest
|
||||
container_name: certd-updater
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
# 配置 自动更新
|
||||
environment:
|
||||
- WATCHTOWER_CLEANUP=true # 自动清理旧版本容器
|
||||
- WATCHTOWER_INCLUDE_STOPPED=false # 不更新已停止的容器
|
||||
- WATCHTOWER_LABEL_ENABLE=true # 根据容器标签进行更新
|
||||
- WATCHTOWER_POLL_INTERVAL=300 # 每 5 分钟检查一次更新
|
||||
|
||||
```
|
||||
|
||||
### 其他部署方式升级方法
|
||||
请参考 https://certd.docmirror.cn/guide/install/upgrade.html
|
||||
|
||||
|
||||
|
||||
### 更新日志:
|
||||
## 五、更多帮助
|
||||
请访问官方文档:[https://certd.docmirror.cn/](https://certd.docmirror.cn/guide/)
|
||||
|
||||
[CHANGELOG](./CHANGELOG.md)
|
||||
* 升级方法:[升级方法](https://certd.docmirror.cn/guide/install/upgrade/)
|
||||
* 常见问题:[忘记密码](https://certd.docmirror.cn/guide/use/forgotpasswd/)
|
||||
* 多数据库:[多数据库配置](https://certd.docmirror.cn/guide/install/database/)
|
||||
* 站点安全:[站点安全特性](https://certd.docmirror.cn/guide/feature/safe/)
|
||||
* 更新日志:[CHANGELOG](./CHANGELOG.md)
|
||||
|
||||
|
||||
## 六、一些说明
|
||||
* 本项目ssl证书提供商为letencrypt/Google/ZeroSSL
|
||||
* 申请过程遵循acme协议
|
||||
* 证书续期:
|
||||
* 实际上没有办法不改变证书文件本身情况下直接续期或者续签。
|
||||
* 我们所说的续期,其实就是按照全套流程重新申请一份新证书,然后重新部署上去。
|
||||
* 免费证书过期时间90天,以后可能还会缩短,所以自动化部署必不可少
|
||||
* 设置每天自动运行,当证书过期前35天,会自动重新申请证书并部署
|
||||
|
||||
|
||||
## 七、不同平台的设置说明
|
||||
|
||||
* 已迁移到新的文档网站,请到常见问题章节查看
|
||||
* [最新文档站链接 https://certd.docmirror.cn](https://certd.docmirror.cn/)
|
||||
|
||||
## 八、问题处理
|
||||
### 7.1 忘记管理员密码
|
||||
[重置管理员密码方法](https://certd.docmirror.cn/guide/use/forgotpasswd/)
|
||||
|
||||
## 九、联系作者
|
||||
## 六、联系作者
|
||||
如有疑问,欢迎加入群聊(请备注certd)
|
||||
|
||||
| 加群 | 微信群 | QQ群 |
|
||||
@@ -194,7 +138,7 @@ services:
|
||||
| 二维码 | <img height="230" src="./docs/guide/contact/images/me.png"> |
|
||||
|
||||
|
||||
## 十、捐赠
|
||||
## 七、捐赠
|
||||
************************
|
||||
支持开源,为爱发电,我已入驻爱发电
|
||||
https://afdian.com/a/greper
|
||||
@@ -218,34 +162,26 @@ https://afdian.com/a/greper
|
||||
|
||||
************************
|
||||
|
||||
## 十一、贡献代码
|
||||
## 八、贡献代码
|
||||
|
||||
1. 本地开发 [贡献插件](https://certd.docmirror.cn/guide/development/)
|
||||
1. 本地开发请参考 [贡献插件向导](https://certd.docmirror.cn/guide/development/)
|
||||
2. 作为贡献者,代表您同意您贡献的代码如下许可:
|
||||
1. 可以调整开源协议以使其更严格或更宽松。
|
||||
2. 可以用于商业用途。
|
||||
|
||||
|
||||
|
||||
## 十二、 开源许可
|
||||
## 九、 开源许可
|
||||
* 本项目遵循 GNU Affero General Public License(AGPL)开源协议。
|
||||
* 允许个人和公司内部自由使用、复制、修改和分发本项目,未获得商业授权情况下禁止任何形式的商业用途
|
||||
* 未获得商业授权情况下,禁止任何对logo、版权信息及授权许可相关代码的修改。
|
||||
* 如需商业授权,请联系作者。
|
||||
|
||||
|
||||
## 十三、我的其他项目(求Star)
|
||||
## 十、我的其他项目(求Star)
|
||||
|
||||
| 项目名称 | stars | 项目描述 |
|
||||
|---------------------------------------------------------|-------------------------------------------------------------------------------------------------------|-----------------------------------|
|
||||
| [袖手AI](https://ai.handsfree.work/) | | 袖手GPT,国内可用,无需FQ,每日免费额度 |
|
||||
| [fast-crud](https://gitee.com/fast-crud/fast-crud/) | <img alt="GitHub stars" src="https://img.shields.io/github/stars/fast-crud/fast-crud?logo=github"/> | 基于vue3的crud快速开发框架 |
|
||||
| [dev-sidecar](https://github.com/docmirror/dev-sidecar/) | <img alt="GitHub stars" src="https://img.shields.io/github/stars/docmirror/dev-sidecar?logo=github"/> | 直连访问github工具,无需FQ,解决github无法访问的问题 |
|
||||
|
||||
|
||||
|
||||
## 十四、更新日志
|
||||
|
||||
更新日志:[CHANGELOG](./CHANGELOG.md)
|
||||
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
01:33
|
||||
00:32
|
||||
|
||||
@@ -3,6 +3,8 @@ services:
|
||||
certd:
|
||||
# 镜像 # ↓↓↓↓↓ ---- 镜像版本号,建议改成固定版本号,例如:certd:1.29.0
|
||||
image: registry.cn-shenzhen.aliyuncs.com/handsfree/certd:latest
|
||||
# image: ghcr.io/certd/certd:latest # --------- 如果 报镜像not found,可以尝试其他镜像源
|
||||
# image: greper/certd:latest
|
||||
container_name: certd # 容器名
|
||||
restart: unless-stopped # 自动重启
|
||||
volumes:
|
||||
@@ -35,6 +37,8 @@ services:
|
||||
# networks:
|
||||
# - ip6net
|
||||
environment:
|
||||
# ↓↓↓↓ ----------------------------------------------------- 使用上海东八时区
|
||||
# - TZ=Asia/Shanghai
|
||||
# 设置环境变量即可自定义certd配置
|
||||
# 配置项见: packages/ui/certd-server/src/config/config.default.ts
|
||||
# 配置规则: certd_ + 配置项, 点号用_代替
|
||||
|
||||
@@ -88,22 +88,25 @@ export default defineConfig({
|
||||
text: "特性",
|
||||
items: [
|
||||
{text: "CNAME代理校验", link: "/guide/feature/cname/index.md"},
|
||||
{text: "插件列表", link: "/guide/plugins.md"},
|
||||
{text: "多数据库支持", link: "/guide/install/database.md"},
|
||||
{text: "开放接口", link: "/guide/open/index.md"},
|
||||
{
|
||||
text: "站点安全", items: [
|
||||
{text: "安全特性", link: "/guide/feature/safe"},
|
||||
{text: "站点隐藏", link: "/guide/feature/safe/hidden"},
|
||||
{text: "安全生产建议", link: "/guide/feature/safe/suggest"},
|
||||
text: "站点安全", link: "/guide/feature/safe"
|
||||
},
|
||||
{
|
||||
text: "插件列表", items: [
|
||||
{text: "授权提供商", link: "/guide/plugins/access"},
|
||||
{text: "DNS提供商", link: "/guide/plugins/dns-provider"},
|
||||
{text: "任务插件", link: "/guide/plugins/deploy"},
|
||||
{text: "通知插件", link: "/guide/plugins/notification"},
|
||||
]
|
||||
},
|
||||
|
||||
]
|
||||
},
|
||||
{
|
||||
text: "常见问题",
|
||||
items: [
|
||||
{text: "常见报错处理", link: "/guide/qa/"},
|
||||
{text: "群晖证书部署", link: "/guide/use/synology/"},
|
||||
{text: "腾讯云密钥获取", link: "/guide/use/tencent/"},
|
||||
{text: "连接windows主机", link: "/guide/use/host/windows.md"},
|
||||
@@ -115,8 +118,14 @@ export default defineConfig({
|
||||
{text: "js脚本插件使用", link: "/guide/use/custom-script/index.md"},
|
||||
{text: "邮箱配置", link: "/guide/use/email/index.md"},
|
||||
{text: "IPv6支持", link: "/guide/use/setting/ipv6.md"},
|
||||
{text: "其他插件使用", link: "/deploy/"},
|
||||
{text: "商业版说明", link: "/comm/"},
|
||||
{text: "ESXi", link: "/guide/use/ESXi/index.md"},
|
||||
]
|
||||
},
|
||||
{
|
||||
text: "商业版配置", link: "/guide/use/comm/", items: [
|
||||
{text: "支付宝配置", link: "/guide/use/comm/payments/alipay.md"},
|
||||
{text: "微信支付配置", link: "/guide/use/comm/payments/wxpay.md"},
|
||||
{text: "彩虹易支付配置", link: "/guide/use/comm/payments/yizhifu.md"},
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -133,26 +142,6 @@ export default defineConfig({
|
||||
]
|
||||
}
|
||||
],
|
||||
"/deploy/": [
|
||||
{
|
||||
text: "部署证书插件",
|
||||
items: [
|
||||
{text: "插件说明", link: "/deploy/index.md"},
|
||||
{text: "部署到ESXi", link: "/deploy/ESXi/index.md"},
|
||||
]
|
||||
}
|
||||
],
|
||||
"/comm/": [
|
||||
{
|
||||
text: "商业版",
|
||||
items: [
|
||||
{text: "支付宝配置", link: "/comm/payments/alipay.md"},
|
||||
{text: "微信支付配置", link: "/comm/payments/wxpay.md"},
|
||||
{text: "彩虹易支付配置", link: "/comm/payments/yizhifu.md"},
|
||||
]
|
||||
}
|
||||
]
|
||||
,
|
||||
},
|
||||
|
||||
socialLinks: [
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
# 部署插件说明
|
||||
|
||||
## 待完善
|
||||
|
||||
@@ -3,6 +3,103 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.34.1](https://github.com/certd/certd/compare/v1.34.0...v1.34.1) (2025-05-05)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 根据SOA记录判断子域名托管有缺陷,改回手动配置子域名托管记录的方式 ([1b280a2](https://github.com/certd/certd/commit/1b280a2940f9e2d919b0bf23b89cc185be1fa498))
|
||||
* 修复宝塔授权测试按钮显示错误的bug ([048696e](https://github.com/certd/certd/commit/048696ee9386491bb68592fb3a47d1c900bb68bf))
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 支持部署证书到火山dcdn ([5f85219](https://github.com/certd/certd/commit/5f852194953dc1b4e6336770f417507b8f5a33ad))
|
||||
* 支持部署证书到unicloud ([a63d687](https://github.com/certd/certd/commit/a63d687f1c573159f0857693f37602b0e1e44072))
|
||||
|
||||
# [1.34.0](https://github.com/certd/certd/compare/v1.33.8...v1.34.0) (2025-04-28)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 修复二次认证登录进入错误账号的bug ([e3930e0](https://github.com/certd/certd/commit/e3930e07172dd7903cb0f6ff26e0e3e828ba3e77))
|
||||
|
||||
### Features
|
||||
|
||||
* 从yaml文件注册插件 ([deb3893](https://github.com/certd/certd/commit/deb38938204b29543f36d3266249958faaaa6b66))
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 优化cdnfly插件,支持自动匹配域名部署 ([afd59e9](https://github.com/certd/certd/commit/afd59e9933b2650f41c5d47684c171b93b962065))
|
||||
|
||||
## [1.33.8](https://github.com/certd/certd/compare/v1.33.7...v1.33.8) (2025-04-26)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 服务器时间获取不准确的bug ([5d10cbf](https://github.com/certd/certd/commit/5d10cbf18daf94a90a7551641a3b13e3c5fec611))
|
||||
* 修复复制流水线无效的bug ([3df20a9](https://github.com/certd/certd/commit/3df20a924f32970b052e2588ea20de095f0ea693))
|
||||
* 修复http上传方式无法清除记录文件的bug ([72a7b51](https://github.com/certd/certd/commit/72a7b51d479602b2c54c6c3ac8d8a0dcb9664e73))
|
||||
* 修复token过期后,疯狂打印token过期信息的bug ([50a5fa1](https://github.com/certd/certd/commit/50a5fa15bb240a125bbc91d2ce1ff3c835888a77))
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 从域名的soa获取主域名,子域名托管无需额外配置 ([a586a92](https://github.com/certd/certd/commit/a586a92d5e32ea846ac37be52a7ad8c328d89966))
|
||||
* 七牛oss支持删除过期备份 ([b7113bd](https://github.com/certd/certd/commit/b7113bda2378116d6c116dc583f563cce7cf9f00))
|
||||
* 数据库备份支持oss ([308d460](https://github.com/certd/certd/commit/308d4600efe2002f199c33b4594d3071784e58ea))
|
||||
* 支持阿里云中文域名申请 ([b3468cf](https://github.com/certd/certd/commit/b3468cf7f28228d7c9cf68de6b5a9bbeb67f2c6d))
|
||||
* 支持反向代理增加contextPath路径 ([0088929](https://github.com/certd/certd/commit/0088929622160cc922995de9a563e8061686ff34))
|
||||
* 支持中文域名 ([162ebfd](https://github.com/certd/certd/commit/162ebfd4e0c25727efb33952d3bbf7420a02e2c3))
|
||||
|
||||
## [1.33.7](https://github.com/certd/certd/compare/v1.33.6...v1.33.7) (2025-04-22)
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 添加部署证书至火山 Live ([abea80e](https://github.com/certd/certd/commit/abea80e3ab9b1672aebe1c5d5e856693b29931a8))
|
||||
* 优化首页插件列表展示 ([9b8f60b](https://github.com/certd/certd/commit/9b8f60b64b5f9a3db7dfa9b3dcbd9201984358d0))
|
||||
* 证书申请支持51dns ([8638fc9](https://github.com/certd/certd/commit/8638fc91ff34fccaf12ff9874fd3fa9d2a8c18b7))
|
||||
* 支持51dns ([96a0900](https://github.com/certd/certd/commit/96a0900edc95dcfd9acccf9d13592f12f5a09b3d))
|
||||
* ssh PTY模式登录设置 ([8385bcc](https://github.com/certd/certd/commit/8385bcc2d7f2411a07748bb5c53f9eaf4d38d7cc))
|
||||
* ssh伪终端模式优化,windows下不开启 ([42dfe93](https://github.com/certd/certd/commit/42dfe936b773b7bdd82ca3378363252ffffd7b71))
|
||||
|
||||
## [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
|
||||
|
||||
* 登录支持双重认证 ([48aef25](https://github.com/certd/certd/commit/48aef25b3f6499d674ca4e4ef16f4c62399fb735))
|
||||
* 多重认证登录 ([0f82cf4](https://github.com/certd/certd/commit/0f82cf409bc60706ab07e4ca4f272b9a1ca7eecb))
|
||||
* 优化部署到华为云CDN,支持先上传到ccm,再使用证书id部署,修复offline状态下导致部署报错的bug ([79df39a](https://github.com/certd/certd/commit/79df39acabab10ae7e1864dadcdc186bb007a3c5))
|
||||
|
||||
## [1.33.4](https://github.com/certd/certd/compare/v1.33.3...v1.33.4) (2025-04-15)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 补充类型断言 ([2143dff](https://github.com/certd/certd/commit/2143dff2ae96e6a78bef9f0498e36f8cd9e6941f))
|
||||
* 修复腾讯云部署到任意资源插件,无法使用之前已上传的腾讯云证书问题 ([32c714d](https://github.com/certd/certd/commit/32c714d1b6e68c71a74a7452115040c87ac4bfdc))
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 插件支持导入导出 ([cf8abb4](https://github.com/certd/certd/commit/cf8abb45282070c8ba91469f93fd379fabf1f74a))
|
||||
* 支持上传证书到华为云CCM ([cfd3b66](https://github.com/certd/certd/commit/cfd3b66be9ebf53a26693057e70ed60c3f116be9))
|
||||
|
||||
## [1.33.3](https://github.com/certd/certd/compare/v1.33.2...v1.33.3) (2025-04-14)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 修复登录错误次数过多阻止再次登录逻辑 ([bf4d191](https://github.com/certd/certd/commit/bf4d191c8bd2f9209eb6768f662b9c77de99e998))
|
||||
|
||||
## [1.33.2](https://github.com/certd/certd/compare/v1.33.1...v1.33.2) (2025-04-12)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
@@ -22,4 +22,6 @@
|
||||

|
||||
|
||||
## 3、忘记解除地址和解除密码怎么办
|
||||
登录服务器,在数据库平级的目录下创建`.unhidden`文件即可`临时解除`站点隐藏
|
||||
登录服务器,在数据库平级的目录下创建`.unhidden`命名的空白文件,即可临时解除站点隐藏
|
||||
临时解除后会自动删除`.unhidden`文件,请尽快设置好新的`解除地址`和`解除密码`,并记住
|
||||
|
||||
|
||||
BIN
docs/guide/feature/safe/images/2fa.png
Normal file
|
After Width: | Height: | Size: 70 KiB |
@@ -1,34 +1,48 @@
|
||||
# 站点安全特性
|
||||
# 安全特性
|
||||
|
||||
Certd 存储了证书以及授权等敏感数据,所以需要严格保障安全。
|
||||
我们非常重视您的数据安全,提供了以下安全特性
|
||||
Certd 存储了证书以及授权等敏感数据,所以需要严格保障安全。
|
||||
我们提供了以下安全特性,以及安全生产建议(请遵照建议进行生产部署以保障数据安全)
|
||||
|
||||
## 1、 授权数据加密存储【默认开启】
|
||||
## 一、站点安全特性
|
||||
|
||||
### 1、 授权数据加密存储【默认开启】
|
||||
* 所有的授权敏感字段会加密后存储
|
||||
* 每个用户独立维护授权数据,连管理员都无权查看
|
||||
|
||||

|
||||
星号部分为加密数据
|
||||
|
||||
## 2、 密码防爆破【默认开启】
|
||||
### 2、 密码防爆破【默认开启】
|
||||
* 登录失败次数过多,账号将被锁定,最高24小时(重启服务可解除锁定)
|
||||
* 用户登录密码加密hash后存储,无法计算出密码明文
|
||||

|
||||
|
||||
## 3、站点隐藏【建议开启】
|
||||
### 3、站点隐藏【建议开启】
|
||||
* 一般来说Certd设置好之后,后续很少需要访问修改。
|
||||
* 所以我们平时可以把站点访问关闭,需要的时候再打开,减少站点被攻击的风险
|
||||
* 请前往 `系统管理->系统设置->安全设置->开启站点隐藏`
|
||||
* [站点隐藏设置说明](./hidden/)
|
||||

|
||||
|
||||
## 4、登录二次验证
|
||||
点击查看 [站点隐藏功能详细使用说明](./hidden/)
|
||||
|
||||
待实现
|
||||
|
||||
## 5、数据库自动备份【建议开启】
|
||||
### 4、登录双重验证
|
||||
|
||||
支持2FA双重认证
|
||||
|
||||

|
||||
|
||||
### 5、数据库自动备份【建议开启】
|
||||
* [自动备份设置说明](../../use/backup/)
|
||||
|
||||
|
||||
## 更多安全生产建议
|
||||
[安全生产建议](./suggest.md)
|
||||
## 二、安全生产建议
|
||||
|
||||
尽管`Cert`本身实现了很多安全特性,但`外部环境的安全`仍需要您来确保。
|
||||
请`务必`遵循如下建议做好安全防护
|
||||
|
||||
* 请`务必`使用`HTTPS协议`访问本应用,避免被中间人攻击
|
||||
* 请`务必`使用`web应用防火墙`防护本应用,防止XSS、SQL注入等攻击
|
||||
* 请`务必`做好`服务器本身`的安全防护,防止数据库泄露
|
||||
* 请`务必`做好[`数据备份`](../../use/backup/),避免数据丢失
|
||||
* 建议开启[`站点隐藏`](./hidden/)功能
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
# 安全生产建议
|
||||
|
||||
尽管`Cert`本身实现了很多安全特性,但`外部环境的安全`仍需要您来确保。
|
||||
请`务必`遵循如下建议做好安全防护
|
||||
|
||||
* 请`务必`使用`HTTPS协议`访问本应用,避免被中间人攻击
|
||||
* 请`务必`使用`web应用防火墙`防护本应用,防止XSS、SQL注入等攻击
|
||||
* 请`务必`做好`服务器本身`的安全防护,防止数据库泄露
|
||||
* 请`务必`做好[`数据备份`](../../use/backup/),避免数据丢失
|
||||
* 建议开启[`站点隐藏`](./hidden/)功能
|
||||
|
||||
@@ -5,30 +5,28 @@ Certd 是一款开源、免费、全自动申请和部署更新SSL证书的工
|
||||
|
||||
关键字:证书自动申请、证书自动更新、证书自动续期、证书自动续签、证书管理工具
|
||||
|
||||
## 1、关于证书续期
|
||||
>* 实际上没有办法不改变证书文件本身情况下直接续期或者续签。
|
||||
>* 我们所说的续期,其实就是按照全套流程重新申请一份新证书,然后重新部署上去。
|
||||
>* 免费证书过期时间90天,以后可能还会缩短,所以自动化部署必不可少
|
||||
|
||||
## 一、特性
|
||||
|
||||
## 2、项目特性
|
||||
本项目不仅支持证书申请过程自动化,还可以自动化部署更新证书,让你的证书永不过期。
|
||||
|
||||
* 全自动申请证书(支持所有注册商注册的域名)
|
||||
* 全自动部署更新证书(目前支持部署到主机、部署到阿里云、腾讯云等,目前已支持60+部署插件)
|
||||
* 支持通配符域名/泛域名,支持多个域名打到一个证书上
|
||||
* 邮件通知
|
||||
* 私有化部署,保障数据安全
|
||||
* 支持SQLite、Postgresql、MySQL数据库
|
||||
* 全自动申请证书(支持所有注册商注册的域名,支持DNS-01、HTTP-01、CNAME代理等多种域名验证方式)
|
||||
* 全自动部署更新证书(目前支持部署到主机、阿里云、腾讯云等70+部署插件)
|
||||
* 支持通配符域名/泛域名,支持多个域名打到一个证书上,支持pem、pfx、der、jks等多种证书格式
|
||||
* 邮件通知、webhook通知、企微、钉钉、飞书、anpush等多种通知方式
|
||||
* 私有化部署,数据保存本地,安装升级非常简单快捷
|
||||
* 镜像由Github Actions构建,过程公开透明
|
||||
* 授权加密,站点隐藏,2FA,密码防爆破等多重安全保障
|
||||
* 支持SQLite,PostgreSQL、MySQL多种数据库
|
||||
* 开放接口支持
|
||||
* 站点证书监控
|
||||
* 多用户管理
|
||||
|
||||
|
||||
## 二、一些说明
|
||||
* 本项目申请证书过程遵循acme协议
|
||||
* 需要验证域名所有权,一般有两种方式
|
||||
* http-01: 在网站根目录下放置一份txt文件
|
||||
* dns-01: 需要给域名添加txt解析记录,通配符域名只能用这种方式(本项目仅支持dns-01)
|
||||
* 证书续期:
|
||||
* 实际上没有办法不改变证书文件本身情况下直接续期或者续签。
|
||||
* 我们所说的续期,其实就是按照全套流程重新申请一份新证书,然后重新部署上去。
|
||||
* 免费证书过期时间90天,以后可能还会缩短,所以自动化部署必不可少
|
||||
* 设置每天自动运行,当证书过期前35天,会自动重新申请证书并部署
|
||||

|
||||
|
||||
|
||||
## 三、证书颁发机构对比
|
||||
* Let's Encrypt:申请最简单。
|
||||
* Google: 大厂光环,兼容性好,首次需要翻墙获取EAB。
|
||||
* ZeroSSL: 需要EAB,获取EAB无需翻墙。
|
||||
BIN
docs/guide/install/baota/images/network.png
Normal file
|
After Width: | Height: | Size: 82 KiB |
@@ -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`网络
|
||||

|
||||
@@ -55,6 +55,11 @@ https://your_server_ip:7002
|
||||
|
||||
## 二、升级
|
||||
|
||||
::: warning
|
||||
如果您是第一次升级certd版本,切记切记先备份一下数据
|
||||
:::
|
||||
|
||||
|
||||
### 如果使用固定版本号
|
||||
1. 修改`docker-compose.yaml`中的镜像版本号
|
||||
2. 运行`docker compose up -d` 即可
|
||||
|
||||
@@ -44,6 +44,11 @@ kill -9 $(lsof -t -i:7001)
|
||||
./start.sh
|
||||
```
|
||||
|
||||
::: warning
|
||||
升级certd版本前,切记切记先备份一下数据
|
||||
:::
|
||||
|
||||
|
||||
## 三、数据备份
|
||||
> 数据默认保存在 `./packages/ui/certd-server/data` 目录下
|
||||
> 建议配置一条[数据库备份流水线](../../use/backup/) 自动备份
|
||||
|
||||
@@ -8,5 +8,9 @@
|
||||
3. [1Panel面板方式部署升级](./1panel/#三、升级)
|
||||
4. [源码方式部署](./source/#二、升级)
|
||||
|
||||
::: warning
|
||||
如果您是第一次升级certd版本,切记切记先备份一下数据
|
||||
:::
|
||||
|
||||
## 升级日志
|
||||
[CHANGELOG](../changelogs/CHANGELOG.md)
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
# 插件列表
|
||||
|
||||

|
||||
|
||||
|
||||
58
docs/guide/plugins/access.md
Normal file
@@ -0,0 +1,58 @@
|
||||
# 授权列表
|
||||
|
||||
| 序号 | 名称 | 说明 |
|
||||
|-----|-----|-----|
|
||||
| 1.| **阿里云授权** | |
|
||||
| 2.| **EAB授权** | ZeroSSL证书申请需要EAB授权 |
|
||||
| 3.| **google cloud** | 谷歌云授权 |
|
||||
| 4.| **主机登录授权** | |
|
||||
| 5.| **SFTP授权** | |
|
||||
| 6.| **阿里云OSS授权** | 包含地域和Bucket |
|
||||
| 7.| **FTP授权** | |
|
||||
| 8.| **腾讯云** | |
|
||||
| 9.| **腾讯云COS授权** | 腾讯云对象存储授权,包含地域和存储桶 |
|
||||
| 10.| **七牛云授权** | |
|
||||
| 11.| **七牛OSS授权** | |
|
||||
| 12.| **天翼云授权** | |
|
||||
| 13.| **s3/minio授权** | S3/minio oss授权 |
|
||||
| 14.| **baota授权** | |
|
||||
| 15.| **易盾DCDN授权** | https://user.yiduncdn.com |
|
||||
| 16.| **易盾rcdn授权** | 易盾CDN,每月免费30G,[注册即领](https://rhcdn.yiduncdn.com/register?code=8mn536rrzfbf8) |
|
||||
| 17.| **易发云短信** | sms.yfyidc.cn/ |
|
||||
| 18.| **cdnfly授权** | |
|
||||
| 19.| **群晖登录授权** | |
|
||||
| 20.| **k8s授权** | |
|
||||
| 21.| **1panel授权** | 账号和密码 |
|
||||
| 22.| **百度云授权** | |
|
||||
| 23.| **LeCDN授权** | |
|
||||
| 24.| **白山云授权** | |
|
||||
| 25.| **plesk授权** | |
|
||||
| 26.| **易支付** | |
|
||||
| 27.| **支付宝** | |
|
||||
| 28.| **微信支付** | |
|
||||
| 29.| **长亭雷池授权** | |
|
||||
| 30.| **lucky** | |
|
||||
| 31.| **括彩云cdn授权** | 括彩云CDN,每月免费30G,[注册即领](https://kuocaicdn.com/register?code=8mn536rrzfbf8) |
|
||||
| 32.| **uniCloud** | unicloud授权 |
|
||||
| 33.| **华为云授权** | |
|
||||
| 34.| **西部数码授权** | |
|
||||
| 35.| **多吉云** | |
|
||||
| 36.| **我爱云授权** | 我爱云CDN |
|
||||
| 37.| **CacheFly** | CacheFly |
|
||||
| 38.| **Gcore** | Gcore |
|
||||
| 39.| **亚马逊云aws授权** | |
|
||||
| 40.| **dns.la授权** | |
|
||||
| 41.| **又拍云** | |
|
||||
| 42.| **火山引擎** | |
|
||||
| 43.| **京东云** | |
|
||||
| 44.| **51dns授权** | |
|
||||
|
||||
<style module>
|
||||
table th:first-of-type {
|
||||
width: 65px;
|
||||
}
|
||||
table th:nth-of-type(2) {
|
||||
width: 240px;
|
||||
}
|
||||
</style>
|
||||
|
||||
130
docs/guide/plugins/deploy.md
Normal file
@@ -0,0 +1,130 @@
|
||||
# 任务插件
|
||||
共 `70` 款任务插件
|
||||
## 1. 证书申请
|
||||
|
||||
| 序号 | 名称 | 说明 |
|
||||
|-----|-----|-----|
|
||||
| 1.| **证书申请(JS版)** | 免费通配符域名证书申请,支持多个域名打到同一个证书上 |
|
||||
| 2.| **证书申请(Lego)** | 支持海量DNS解析提供商,推荐使用,一样的免费通配符域名证书申请,支持多个域名打到同一个证书上 |
|
||||
| 3.| **商用证书托管** | 手动上传自定义证书后,自动部署(每次证书有更新,都需要手动上传一次) |
|
||||
## 2. 主机
|
||||
|
||||
| 序号 | 名称 | 说明 |
|
||||
|-----|-----|-----|
|
||||
| 1.| **FTP-上传证书到FTP** | 将证书上传到FTP服务器 |
|
||||
| 2.| **IIS-部署到IIS站点** | |
|
||||
| 3.| **主机-执行远程主机脚本命令** | 可以执行重启nginx等操作让证书生效 |
|
||||
| 4.| **主机-部署证书到SSH主机** | SFTP上传证书到主机,然后SSH执行部署脚本命令 |
|
||||
## 3. CDN
|
||||
|
||||
| 序号 | 名称 | 说明 |
|
||||
|-----|-----|-----|
|
||||
| 1.| **易盾-部署到易盾DCDN** | 主要是防御,http://user.yiduncdn.com/ |
|
||||
| 2.| **易盾-部署到易盾RCDN** | 易盾CDN,每月免费30G,[注册即领](https://rhcdn.yiduncdn.com/register?code=8mn536rrzfbf8) |
|
||||
| 3.| **cdnfly-部署证书到cdnfly** | cdnfly |
|
||||
| 4.| **百度云-部署证书到CDN** | 部署到百度云CDN |
|
||||
| 5.| **LeCDN-更新证书** | |
|
||||
| 6.| **LeCDN-更新证书V2** | 支持新版本LeCDN |
|
||||
| 7.| **白山云-更新证书** | |
|
||||
| 8.| **天翼云-部署证书到CDN** | 部署证书到天翼云CDN和全站加速 |
|
||||
| 9.| **括彩云-部署到括彩云CDN** | 括彩云CDN,每月免费30G,[注册即领](https://kuocaicdn.com/register?code=8mn536rrzfbf8) |
|
||||
| 10.| **多吉云-部署到多吉云CDN** | |
|
||||
| 11.| **我爱云-部署证书到我爱云CDN** | 部署证书到我爱云CDN |
|
||||
| 12.| **CacheFly-部署证书到CacheFly** | 部署证书到 CacheFly |
|
||||
| 13.| **Gcore-部署证书到Gcore** | 仅上传 并不会部署到cdn |
|
||||
| 14.| **Gcore-刷新Gcore证书** | 刷新现有的证书 |
|
||||
| 15.| **又拍云-部署证书到CDN/USS** | 支持又拍云CDN,又拍云云存储USS |
|
||||
## 4. 面板
|
||||
|
||||
| 序号 | 名称 | 说明 |
|
||||
|-----|-----|-----|
|
||||
| 1.| **宝塔-面板证书部署** | 部署宝塔面板本身的ssl证书 |
|
||||
| 2.| **宝塔-网站证书部署** | 部署宝塔管理的站点的ssl证书,目前支持网站站点、docker站点等 |
|
||||
| 3.| **群晖-部署证书到群晖面板** | Synology,支持6.x以上版本 |
|
||||
| 4.| **K8S-部署证书到Secret** | 部署证书到k8s的secret |
|
||||
| 5.| **K8S-Ingress 证书部署** | 部署证书到k8s的Ingress |
|
||||
| 6.| **1Panel-部署证书到1Panel** | 更新1Panel的证书 |
|
||||
| 7.| **Plesk-部署Plesk网站证书** | |
|
||||
| 8.| **雷池-更新证书** | 更新长亭雷池WAF的证书 |
|
||||
| 9.| **lucky-更新Lucky证书** | |
|
||||
| 10.| **uniCloud-部署到服务空间** | 部署到服务空间 |
|
||||
| 11.| **威联通-部署证书到威联通** | 部署证书到qnap |
|
||||
## 5. 阿里云
|
||||
|
||||
| 序号 | 名称 | 说明 |
|
||||
|-----|-----|-----|
|
||||
| 1.| **阿里云-部署到Ack** | 部署到阿里云Ack集群Ingress等通过Secret管理证书的应用 |
|
||||
| 2.| **阿里云-部署至任意云资源** | 【不建议使用】需要消耗阿里云自动部署次数,支持SLB、LIVE、webHosting、VOD、CR、DCDN、DDoS、CDN、ALB、APIGateway、FC、GA、MSE、NLB、OSS、SAE、WAF等云产品 |
|
||||
| 3.| **阿里云-部署证书至CDN** | 自动部署域名证书至阿里云CDN |
|
||||
| 4.| **阿里云-部署证书至DCDN** | 依赖证书申请前置任务,自动部署域名证书至阿里云DCDN |
|
||||
| 5.| **阿里云-部署证书至OSS** | 自动部署域名证书至阿里云OSS |
|
||||
| 6.| **阿里云-上传证书到阿里云** | 如果不想在阿里云上同一份证书上传多次,可以把此任务作为前置任务,其他阿里云任务证书那一项选择此任务的输出 |
|
||||
| 7.| **阿里云-部署至阿里云WAF** | 部署证书到阿里云WAF |
|
||||
| 8.| **阿里云-部署至ALB(应用负载均衡)** | ALB,更新监听器的默认证书 |
|
||||
| 9.| **阿里云-部署至NLB(网络负载均衡)** | NLB,网络负载均衡,更新监听器的默认证书 |
|
||||
| 10.| **阿里云-部署至SLB(传统负载均衡)** | 部署证书到阿里云SLB(传统负载均衡) |
|
||||
| 11.| **阿里云-部署至阿里云FC(3.0)** | 部署证书到阿里云函数计算(FC3.0),【注意】证书的加密算法必须选择【pkcs1旧版】 |
|
||||
## 6. 华为云
|
||||
|
||||
| 序号 | 名称 | 说明 |
|
||||
|-----|-----|-----|
|
||||
| 1.| **华为云-部署证书至CDN** | |
|
||||
## 7. 腾讯云
|
||||
|
||||
| 序号 | 名称 | 说明 |
|
||||
|-----|-----|-----|
|
||||
| 1.| **腾讯云-部署证书到任意云资源** | 支持负载均衡、CDN、DDoS、直播、点播、Web应用防火墙、API网关、TEO、容器服务、对象存储、轻应用服务器、云原生微服务、云开发 |
|
||||
| 2.| **腾讯云-部署到CLB** | 暂时只支持单向认证证书,暂时只支持通用负载均衡 |
|
||||
| 3.| **腾讯云-部署到CDN(废弃)** | 已废弃,请使用v2版 |
|
||||
| 4.| **腾讯云-部署到CDN-v2** | 推荐使用 |
|
||||
| 5.| **腾讯云-上传证书到腾讯云** | 上传成功后输出:tencentCertId |
|
||||
| 6.| **腾讯云-部署证书到COS** | 部署到腾讯云COS源站域名证书【注意:很不稳定,需要重试很多次偶尔才能成功一次】 |
|
||||
| 7.| **腾讯云-部署到腾讯云EO** | 腾讯云边缘安全加速平台EO,必须配置上传证书到腾讯云任务 |
|
||||
| 8.| **腾讯云-删除即将过期证书** | 仅删除未使用的证书 |
|
||||
| 9.| **腾讯云-部署到TKE-ingress** | serverless集群请使用K8S部署插件;Qcloud类型需要【上传到腾讯云】作为前置任务;ApiServer未开启外网访问则需要做域名的内网IP映射 |
|
||||
## 8. 火山引擎
|
||||
|
||||
| 序号 | 名称 | 说明 |
|
||||
|-----|-----|-----|
|
||||
| 1.| **火山引擎-部署证书至CDN** | 支持网页,文件下载,音视频点播 |
|
||||
| 2.| **火山引擎-部署证书至CLB** | 部署至火山引擎负载均衡 |
|
||||
| 3.| **火山引擎-上传证书至证书中心** | 上传证书至火山引擎证书中心 |
|
||||
| 4.| **火山引擎-部署证书至ALB** | 部署至火山引擎应用负载均衡 |
|
||||
| 5.| **火山引擎-部署证书至Live** | 部署至火山引擎视频直播 |
|
||||
## 9. 京东云
|
||||
|
||||
| 序号 | 名称 | 说明 |
|
||||
|-----|-----|-----|
|
||||
| 1.| **京东云-部署证书至CDN** | 京东云内容分发网络 |
|
||||
| 2.| **京东云-更新已有证书** | 更新SSL数字证书中的证书 |
|
||||
| 3.| **京东云-上传新证书** | 上传证书到SSL数字证书中心 |
|
||||
## 10. 七牛云
|
||||
|
||||
| 序号 | 名称 | 说明 |
|
||||
|-----|-----|-----|
|
||||
| 1.| **七牛云-部署证书至OSS** | 自动部署域名证书至七牛云KODO,注意是自定义源站域名,不是CDN域名 |
|
||||
| 2.| **七牛云-部署证书至CDN** | 自动部署域名证书至七牛云CDN |
|
||||
## 11. 亚马逊云
|
||||
|
||||
| 序号 | 名称 | 说明 |
|
||||
|-----|-----|-----|
|
||||
| 1.| **AWS-部署证书到CloudFront** | 部署证书到 AWS CloudFront |
|
||||
## 12. 其他
|
||||
|
||||
| 序号 | 名称 | 说明 |
|
||||
|-----|-----|-----|
|
||||
| 1.| **Demo-测试插件** | |
|
||||
| 2.| **重启 Certd** | 【仅管理员可用】 重启 certd的https服务,用于更新 Certd 的 ssl 证书 |
|
||||
| 3.| **自定义js脚本** | 【仅管理员】运行自定义js脚本执行 |
|
||||
| 4.| **等待** | 等待一段时间 |
|
||||
| 5.| **数据库备份** | 仅支持备份SQLite数据库 |
|
||||
|
||||
<style module>
|
||||
table th:first-of-type {
|
||||
width: 65px;
|
||||
}
|
||||
table th:nth-of-type(2) {
|
||||
width: 240px;
|
||||
}
|
||||
</style>
|
||||
|
||||
22
docs/guide/plugins/dns-provider.md
Normal file
@@ -0,0 +1,22 @@
|
||||
# DNS提供商
|
||||
|
||||
| 序号 | 名称 | 说明 |
|
||||
|-----|-----|-----|
|
||||
| 1.| **阿里云** | 阿里云DNS解析提供商 |
|
||||
| 2.| **腾讯云** | 腾讯云域名DNS解析提供者 |
|
||||
| 3.| **华为云** | 华为云DNS解析提供商 |
|
||||
| 4.| **西部数码** | west dns provider |
|
||||
| 5.| **dns.la** | dns.la |
|
||||
| 6.| **火山引擎** | 火山引擎DNS解析提供商 |
|
||||
| 7.| **京东云** | 京东云DNS解析提供商 |
|
||||
| 8.| **51dns** | 51DNS |
|
||||
|
||||
<style module>
|
||||
table th:first-of-type {
|
||||
width: 65px;
|
||||
}
|
||||
table th:nth-of-type(2) {
|
||||
width: 240px;
|
||||
}
|
||||
</style>
|
||||
|
||||
26
docs/guide/plugins/notification.md
Normal file
@@ -0,0 +1,26 @@
|
||||
# 通知插件
|
||||
|
||||
| 序号 | 名称 | 说明 |
|
||||
|-----|-----|-----|
|
||||
| 1.| **企业微信通知** | 企业微信群聊机器人通知 |
|
||||
| 2.| **电子邮件** | 电子邮件通知 |
|
||||
| 3.| **爱语飞飞微信通知(iyuu)** | https://iyuu.cn/ |
|
||||
| 4.| **自定义webhook** | 根据模版自定义http请求 |
|
||||
| 5.| **Server酱ᵀ** | https://sct.ftqq.com/ |
|
||||
| 6.| **Server酱³** | https://doc.sc3.ft07.com/serverchan3 |
|
||||
| 7.| **AnPush** | https://anpush.com |
|
||||
| 8.| **Telegram通知** | Telegram Bot推送通知 |
|
||||
| 9.| **Discord 通知** | Discord 机器人通知 |
|
||||
| 10.| **Slack通知** | Slack消息推送通知 |
|
||||
| 11.| **Bark 通知** | Bark 推送通知插件 |
|
||||
| 12.| **飞书通知** | 飞书群聊webhook通知 |
|
||||
|
||||
<style module>
|
||||
table th:first-of-type {
|
||||
width: 65px;
|
||||
}
|
||||
table th:nth-of-type(2) {
|
||||
width: 240px;
|
||||
}
|
||||
</style>
|
||||
|
||||
19
docs/guide/qa/index.md
Normal file
@@ -0,0 +1,19 @@
|
||||
# 常见报错解决
|
||||
|
||||
## 1. getaddrinfo ENOTFOUND错误
|
||||
如果出现`getaddrinfo ENOTFOUND`错误,可以尝试在`docker-compose.yaml`中设置dns
|
||||
```yaml
|
||||
version: '3.3' # 兼容旧版docker-compose
|
||||
services:
|
||||
certd:
|
||||
#↓↓↓↓ ------------ # 如果出现getaddrinfo ENOTFOUND错误,可以尝试设置dns
|
||||
dns:
|
||||
- 223.5.5.5 # 阿里云公共dns
|
||||
- 223.6.6.6
|
||||
# # ↓↓↓↓ ------- # 如果你服务器在腾讯云,可以用这个替换上面阿里云的公共dns
|
||||
# - 119.29.29.29 # 腾讯云公共dns
|
||||
# - 182.254.116.116
|
||||
# # ↓↓↓↓ ------- # 如果你服务器部署在国外,可以用这个替换上面阿里云的公共dns
|
||||
# - 8.8.8.8 # 谷歌公共dns
|
||||
# - 8.8.4.4
|
||||
```
|
||||
|
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 47 KiB |
@@ -1,5 +1,6 @@
|
||||
# 数据库自动备份
|
||||
|
||||
# 数据库备份
|
||||
* 两种备份方法: 1、手动备份 2、自动备份
|
||||
* 本文仅限sqlite数据库。
|
||||
## 一、手动备份
|
||||
数据库文件根据不同的部署方式保存的位置不一样,您可以手动复制出来进行备份
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 165 KiB After Width: | Height: | Size: 165 KiB |
BIN
docs/guide/use/pretask/images/pretask1.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
docs/guide/use/pretask/images/pretask2.png
Normal file
|
After Width: | Height: | Size: 25 KiB |
13
docs/guide/use/pretask/index.md
Normal file
@@ -0,0 +1,13 @@
|
||||
# 带输出的前置任务
|
||||
|
||||
前置任务输出可以在后续任务中使用
|
||||
|
||||
比如上传证书到阿里云,会返回阿里云的CertId,之后其他阿里云的部署任务可以选择复用这个证书
|
||||
|
||||
## 复用证书
|
||||
|
||||

|
||||
|
||||
在后续任务中可以选择前置任务的输出
|
||||
|
||||

|
||||
1
docs/images/intro/intro.svg
Normal file
|
After Width: | Height: | Size: 60 KiB |
@@ -9,5 +9,5 @@
|
||||
}
|
||||
},
|
||||
"npmClient": "pnpm",
|
||||
"version": "1.33.3"
|
||||
"version": "1.34.2"
|
||||
}
|
||||
|
||||
@@ -30,7 +30,8 @@
|
||||
"init": "lerna run build",
|
||||
"docs:dev": "vitepress dev docs",
|
||||
"docs:build": "vitepress build docs",
|
||||
"docs:preview": "vitepress preview docs"
|
||||
"docs:preview": "vitepress preview docs",
|
||||
"pub": "echo 1"
|
||||
},
|
||||
"license": "AGPL-3.0",
|
||||
"dependencies": {
|
||||
|
||||
@@ -3,6 +3,49 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.34.2](https://github.com/publishlab/node-acme-client/compare/v1.34.1...v1.34.2) (2025-05-11)
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* http方式支持校验443端口 ([d75fcb7](https://github.com/publishlab/node-acme-client/commit/d75fcb7fec421a9a638eaa27fe9378c84b5e0f19))
|
||||
|
||||
## [1.34.1](https://github.com/publishlab/node-acme-client/compare/v1.34.0...v1.34.1) (2025-05-05)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 根据SOA记录判断子域名托管有缺陷,改回手动配置子域名托管记录的方式 ([1b280a2](https://github.com/publishlab/node-acme-client/commit/1b280a2940f9e2d919b0bf23b89cc185be1fa498))
|
||||
|
||||
# [1.34.0](https://github.com/publishlab/node-acme-client/compare/v1.33.8...v1.34.0) (2025-04-28)
|
||||
|
||||
**Note:** Version bump only for package @certd/acme-client
|
||||
|
||||
## [1.33.8](https://github.com/publishlab/node-acme-client/compare/v1.33.7...v1.33.8) (2025-04-26)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 修复http上传方式无法清除记录文件的bug ([72a7b51](https://github.com/publishlab/node-acme-client/commit/72a7b51d479602b2c54c6c3ac8d8a0dcb9664e73))
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 从域名的soa获取主域名,子域名托管无需额外配置 ([a586a92](https://github.com/publishlab/node-acme-client/commit/a586a92d5e32ea846ac37be52a7ad8c328d89966))
|
||||
* 七牛oss支持删除过期备份 ([b7113bd](https://github.com/publishlab/node-acme-client/commit/b7113bda2378116d6c116dc583f563cce7cf9f00))
|
||||
|
||||
## [1.33.7](https://github.com/publishlab/node-acme-client/compare/v1.33.6...v1.33.7) (2025-04-22)
|
||||
|
||||
**Note:** Version bump only for package @certd/acme-client
|
||||
|
||||
## [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
|
||||
|
||||
## [1.33.4](https://github.com/publishlab/node-acme-client/compare/v1.33.3...v1.33.4) (2025-04-15)
|
||||
|
||||
**Note:** Version bump only for package @certd/acme-client
|
||||
|
||||
## [1.33.3](https://github.com/publishlab/node-acme-client/compare/v1.33.2...v1.33.3) (2025-04-14)
|
||||
|
||||
**Note:** Version bump only for package @certd/acme-client
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"description": "Simple and unopinionated ACME client",
|
||||
"private": false,
|
||||
"author": "nmorsman",
|
||||
"version": "1.33.3",
|
||||
"version": "1.34.2",
|
||||
"type": "module",
|
||||
"module": "scr/index.js",
|
||||
"main": "src/index.js",
|
||||
@@ -18,7 +18,7 @@
|
||||
"types"
|
||||
],
|
||||
"dependencies": {
|
||||
"@certd/basic": "^1.33.3",
|
||||
"@certd/basic": "^1.34.2",
|
||||
"@peculiar/x509": "^1.11.0",
|
||||
"asn1js": "^3.0.5",
|
||||
"axios": "^1.7.2",
|
||||
@@ -26,7 +26,8 @@
|
||||
"http-proxy-agent": "^7.0.2",
|
||||
"https-proxy-agent": "^7.0.5",
|
||||
"lodash-es": "^4.17.21",
|
||||
"node-forge": "^1.3.1"
|
||||
"node-forge": "^1.3.1",
|
||||
"punycode": "^2.3.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.14.10",
|
||||
@@ -50,7 +51,8 @@
|
||||
"lint": "eslint .",
|
||||
"lint-types": "tsd",
|
||||
"prepublishOnly": "npm run build-docs",
|
||||
"test": "mocha -t 60000 \"test/setup.js\" \"test/**/*.spec.js\""
|
||||
"test": "mocha -t 60000 \"test/setup.js\" \"test/**/*.spec.js\"",
|
||||
"pub": "npm publish"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -67,5 +69,5 @@
|
||||
"bugs": {
|
||||
"url": "https://github.com/publishlab/node-acme-client/issues"
|
||||
},
|
||||
"gitHead": "be69244e8ddb757de45c7e2b6033195c1f5a6910"
|
||||
"gitHead": "6c74148c277432f91014bf1eebd824e7423c6f4b"
|
||||
}
|
||||
|
||||
@@ -117,12 +117,12 @@ export default async (client, userOpts) => {
|
||||
|
||||
log(`[auto] [${d}] Trigger challengeCreateFn()`);
|
||||
try {
|
||||
const { recordReq, recordRes, dnsProvider, challenge, keyAuthorization } = await opts.challengeCreateFn(authz, keyAuthorizationGetter);
|
||||
const { recordReq, recordRes, dnsProvider, challenge, keyAuthorization ,httpUploader} = await opts.challengeCreateFn(authz, keyAuthorizationGetter);
|
||||
clearTasks.push(async () => {
|
||||
/* Trigger challengeRemoveFn(), suppress errors */
|
||||
log(`[auto] [${d}] Trigger challengeRemoveFn()`);
|
||||
try {
|
||||
await opts.challengeRemoveFn(authz, challenge, keyAuthorization, recordReq, recordRes, dnsProvider);
|
||||
await opts.challengeRemoveFn(authz, challenge, keyAuthorization, recordReq, recordRes, dnsProvider,httpUploader);
|
||||
} catch (e) {
|
||||
log(`[auto] [${d}] challengeRemoveFn threw error: ${e.message}`);
|
||||
}
|
||||
@@ -234,6 +234,7 @@ export default async (client, userOpts) => {
|
||||
throw new CancelError("用户取消");
|
||||
}
|
||||
|
||||
const waitDnsDiffuseTime = opts.waitDnsDiffuseTime || 30;
|
||||
try {
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
await runPromisePa(challengePromises);
|
||||
@@ -242,8 +243,8 @@ export default async (client, userOpts) => {
|
||||
await wait(60 * 1000);
|
||||
} else {
|
||||
await runPromisePa(localVerifyTasks, 1000);
|
||||
log("本地校验完成,等待30s")
|
||||
await wait(30 * 1000)
|
||||
log(`本地校验完成,等待${waitDnsDiffuseTime}s`)
|
||||
await wait(waitDnsDiffuseTime * 1000)
|
||||
}
|
||||
|
||||
log("开始向提供商请求挑战验证");
|
||||
|
||||
@@ -46,3 +46,5 @@ export * from './axios.js'
|
||||
export * from './logger.js'
|
||||
export * from './verify.js'
|
||||
export * from './error.js'
|
||||
|
||||
export * from './util.js'
|
||||
@@ -340,5 +340,6 @@ export {
|
||||
formatResponseError,
|
||||
getAuthoritativeDnsResolver,
|
||||
retrieveTlsAlpnCertificate,
|
||||
resolveDomainBySoaRecord
|
||||
};
|
||||
|
||||
|
||||
@@ -24,22 +24,46 @@ const dns = dnsSdk.promises
|
||||
*/
|
||||
|
||||
async function verifyHttpChallenge(authz, challenge, keyAuthorization, suffix = `/.well-known/acme-challenge/${challenge.token}`) {
|
||||
|
||||
async function doQuery(challengeUrl){
|
||||
log(`正在测试请求 ${challengeUrl} `)
|
||||
// const httpsPort = axios.defaults.acmeSettings.httpsChallengePort || 443;
|
||||
// const challengeUrl = `https://${authz.identifier.value}:${httpsPort}${suffix}`;
|
||||
|
||||
/* May redirect to HTTPS with invalid/self-signed cert - https://letsencrypt.org/docs/challenge-types/#http-01-challenge */
|
||||
const httpsAgent = new https.Agent({ rejectUnauthorized: false });
|
||||
|
||||
log(`Sending HTTP query to ${authz.identifier.value}, suffix: ${suffix}, port: ${httpPort}`);
|
||||
let data = ""
|
||||
try{
|
||||
const resp = await axios.get(challengeUrl, { httpsAgent });
|
||||
data = (resp.data || '').replace(/\s+$/, '');
|
||||
}catch (e) {
|
||||
log(`[error] HTTP request error from ${authz.identifier.value}`,e.message);
|
||||
return false
|
||||
}
|
||||
|
||||
if (!data || (data !== keyAuthorization)) {
|
||||
log(`[error] Authorization not found in HTTP response from ${authz.identifier.value}`);
|
||||
return false
|
||||
}
|
||||
return true
|
||||
|
||||
}
|
||||
|
||||
const httpPort = axios.defaults.acmeSettings.httpChallengePort || 80;
|
||||
const challengeUrl = `http://${authz.identifier.value}:${httpPort}${suffix}`;
|
||||
|
||||
/* May redirect to HTTPS with invalid/self-signed cert - https://letsencrypt.org/docs/challenge-types/#http-01-challenge */
|
||||
const httpsAgent = new https.Agent({ rejectUnauthorized: false });
|
||||
|
||||
log(`Sending HTTP query to ${authz.identifier.value}, suffix: ${suffix}, port: ${httpPort}`);
|
||||
const resp = await axios.get(challengeUrl, { httpsAgent });
|
||||
const data = (resp.data || '').replace(/\s+$/, '');
|
||||
|
||||
log(`Query successful, HTTP status code: ${resp.status}`);
|
||||
|
||||
if (!data || (data !== keyAuthorization)) {
|
||||
throw new Error(`Authorization not found in HTTP response from ${authz.identifier.value}`);
|
||||
if (!await doQuery(challengeUrl)) {
|
||||
const httpsPort = axios.defaults.acmeSettings.httpsChallengePort || 443;
|
||||
const httpsChallengeUrl = `https://${authz.identifier.value}:${httpsPort}${suffix}`;
|
||||
const res = await doQuery(httpsChallengeUrl)
|
||||
if (!res) {
|
||||
throw new Error(`[error] 验证失败,请检查以上测试url是否可以正常访问`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
log(`Key authorization match for ${challenge.type}/${authz.identifier.value}, ACME challenge verified`);
|
||||
return true;
|
||||
}
|
||||
|
||||
11
packages/core/acme-client/test/soa.spec.mjs
Normal file
@@ -0,0 +1,11 @@
|
||||
import {assert} from 'chai'
|
||||
import {resolveDomainBySoaRecord} from "../src/util.js"
|
||||
describe('dns', () => {
|
||||
it('resolveDomainBySoaRecord', async () => {
|
||||
const resp = await resolveDomainBySoaRecord("a.corp.smartdeer.com")
|
||||
|
||||
assert.equal(resp, "smartdeer.com")
|
||||
|
||||
});
|
||||
|
||||
})
|
||||
6
packages/core/acme-client/types/index.d.ts
vendored
@@ -59,7 +59,7 @@ export interface ClientExternalAccountBindingOptions {
|
||||
export interface ClientAutoOptions {
|
||||
csr: CsrBuffer | CsrString;
|
||||
challengeCreateFn: (authz: Authorization, keyAuthorization: (challenge:rfc8555.Challenge)=>Promise<string>) => Promise<{recordReq?:any,recordRes?:any,dnsProvider?:any,challenge: rfc8555.Challenge,keyAuthorization:string}>;
|
||||
challengeRemoveFn: (authz: Authorization, challenge: rfc8555.Challenge, keyAuthorization: string,recordReq:any, recordRes:any,dnsProvider:any) => Promise<any>;
|
||||
challengeRemoveFn: (authz: Authorization, challenge: rfc8555.Challenge, keyAuthorization: string,recordReq:any, recordRes:any,dnsProvider:any,httpUploader:any) => Promise<any>;
|
||||
email?: string;
|
||||
termsOfServiceAgreed?: boolean;
|
||||
skipChallengeVerification?: boolean;
|
||||
@@ -204,4 +204,6 @@ export function setLogger(fn: (message: any, ...args: any[]) => void): void;
|
||||
|
||||
export function walkTxtRecord(record: any): Promise<string[]>;
|
||||
|
||||
export const CancelError: typeof CancelError;
|
||||
export const CancelError: typeof CancelError;
|
||||
|
||||
export function resolveDomainBySoaRecord(domain: string): Promise<string>;
|
||||
@@ -1,137 +0,0 @@
|
||||
"use strict";
|
||||
/**
|
||||
* acme-client type definition tests
|
||||
*/
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
var __generator = (this && this.__generator) || function (thisArg, body) {
|
||||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
||||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
||||
function verb(n) { return function (v) { return step([n, v]); }; }
|
||||
function step(op) {
|
||||
if (f) throw new TypeError("Generator is already executing.");
|
||||
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
||||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
||||
if (y = 0, t) op = [op[0] & 2, t.value];
|
||||
switch (op[0]) {
|
||||
case 0: case 1: t = op; break;
|
||||
case 4: _.label++; return { value: op[1], done: false };
|
||||
case 5: _.label++; y = op[1]; op = [0]; continue;
|
||||
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
||||
default:
|
||||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
||||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
||||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
||||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
||||
if (t[2]) _.ops.pop();
|
||||
_.trys.pop(); continue;
|
||||
}
|
||||
op = body.call(thisArg, _);
|
||||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
||||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
||||
}
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var acme = require("acme-client");
|
||||
(function () { return __awaiter(void 0, void 0, void 0, function () {
|
||||
var accountKey, client, order, authorizations, authorization, challenge, _a, certKey, certCsr;
|
||||
return __generator(this, function (_b) {
|
||||
switch (_b.label) {
|
||||
case 0: return [4 /*yield*/, acme.crypto.createPrivateKey()];
|
||||
case 1:
|
||||
accountKey = _b.sent();
|
||||
client = new acme.Client({
|
||||
accountKey: accountKey,
|
||||
directoryUrl: acme.directory.letsencrypt.staging
|
||||
});
|
||||
/* Account */
|
||||
return [4 /*yield*/, client.createAccount({
|
||||
termsOfServiceAgreed: true,
|
||||
contact: ['mailto:test@example.com']
|
||||
})];
|
||||
case 2:
|
||||
/* Account */
|
||||
_b.sent();
|
||||
return [4 /*yield*/, client.createOrder({
|
||||
identifiers: [
|
||||
{ type: 'dns', value: 'example.com' },
|
||||
{ type: 'dns', value: '*.example.com' },
|
||||
]
|
||||
})];
|
||||
case 3:
|
||||
order = _b.sent();
|
||||
return [4 /*yield*/, client.getOrder(order)];
|
||||
case 4:
|
||||
_b.sent();
|
||||
return [4 /*yield*/, client.getAuthorizations(order)];
|
||||
case 5:
|
||||
authorizations = _b.sent();
|
||||
authorization = authorizations[0];
|
||||
challenge = authorization.challenges[0];
|
||||
return [4 /*yield*/, client.getChallengeKeyAuthorization(challenge)];
|
||||
case 6:
|
||||
_b.sent();
|
||||
return [4 /*yield*/, client.verifyChallenge(authorization, challenge)];
|
||||
case 7:
|
||||
_b.sent();
|
||||
return [4 /*yield*/, client.completeChallenge(challenge)];
|
||||
case 8:
|
||||
_b.sent();
|
||||
return [4 /*yield*/, client.waitForValidStatus(challenge)];
|
||||
case 9:
|
||||
_b.sent();
|
||||
return [4 /*yield*/, acme.crypto.createCsr({
|
||||
commonName: 'example.com',
|
||||
altNames: ['example.com', '*.example.com']
|
||||
})];
|
||||
case 10:
|
||||
_a = _b.sent(), certKey = _a[0], certCsr = _a[1];
|
||||
return [4 /*yield*/, client.finalizeOrder(order, certCsr)];
|
||||
case 11:
|
||||
_b.sent();
|
||||
return [4 /*yield*/, client.getCertificate(order)];
|
||||
case 12:
|
||||
_b.sent();
|
||||
return [4 /*yield*/, client.getCertificate(order, 'DST Root CA X3')];
|
||||
case 13:
|
||||
_b.sent();
|
||||
/* Auto */
|
||||
return [4 /*yield*/, client.auto({
|
||||
csr: certCsr,
|
||||
challengeCreateFn: function (authz, challenge, keyAuthorization) { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) {
|
||||
return [2 /*return*/];
|
||||
}); }); },
|
||||
challengeRemoveFn: function (authz, challenge, keyAuthorization) { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) {
|
||||
return [2 /*return*/];
|
||||
}); }); }
|
||||
})];
|
||||
case 14:
|
||||
/* Auto */
|
||||
_b.sent();
|
||||
return [4 /*yield*/, client.auto({
|
||||
csr: certCsr,
|
||||
email: 'test@example.com',
|
||||
termsOfServiceAgreed: false,
|
||||
skipChallengeVerification: false,
|
||||
challengePriority: ['http-01', 'dns-01'],
|
||||
preferredChain: 'DST Root CA X3',
|
||||
challengeCreateFn: function (authz, challenge, keyAuthorization) { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) {
|
||||
return [2 /*return*/];
|
||||
}); }); },
|
||||
challengeRemoveFn: function (authz, challenge, keyAuthorization) { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) {
|
||||
return [2 /*return*/];
|
||||
}); }); }
|
||||
})];
|
||||
case 15:
|
||||
_b.sent();
|
||||
return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
}); })();
|
||||
@@ -3,6 +3,44 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.34.2](https://github.com/certd/certd/compare/v1.34.1...v1.34.2) (2025-05-11)
|
||||
|
||||
**Note:** Version bump only for package @certd/basic
|
||||
|
||||
## [1.34.1](https://github.com/certd/certd/compare/v1.34.0...v1.34.1) (2025-05-05)
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 支持部署证书到火山dcdn ([5f85219](https://github.com/certd/certd/commit/5f852194953dc1b4e6336770f417507b8f5a33ad))
|
||||
|
||||
# [1.34.0](https://github.com/certd/certd/compare/v1.33.8...v1.34.0) (2025-04-28)
|
||||
|
||||
**Note:** Version bump only for package @certd/basic
|
||||
|
||||
## [1.33.8](https://github.com/certd/certd/compare/v1.33.7...v1.33.8) (2025-04-26)
|
||||
|
||||
**Note:** Version bump only for package @certd/basic
|
||||
|
||||
## [1.33.7](https://github.com/certd/certd/compare/v1.33.6...v1.33.7) (2025-04-22)
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 支持51dns ([96a0900](https://github.com/certd/certd/commit/96a0900edc95dcfd9acccf9d13592f12f5a09b3d))
|
||||
|
||||
## [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
|
||||
|
||||
* 多重认证登录 ([0f82cf4](https://github.com/certd/certd/commit/0f82cf409bc60706ab07e4ca4f272b9a1ca7eecb))
|
||||
|
||||
## [1.33.4](https://github.com/certd/certd/compare/v1.33.3...v1.33.4) (2025-04-15)
|
||||
|
||||
**Note:** Version bump only for package @certd/basic
|
||||
|
||||
## [1.33.3](https://github.com/certd/certd/compare/v1.33.2...v1.33.3) (2025-04-14)
|
||||
|
||||
**Note:** Version bump only for package @certd/basic
|
||||
|
||||
@@ -1 +1 @@
|
||||
22:22
|
||||
20:23
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@certd/basic",
|
||||
"private": false,
|
||||
"version": "1.33.3",
|
||||
"version": "1.34.2",
|
||||
"type": "module",
|
||||
"main": "./dist/index.js",
|
||||
"module": "./dist/index.js",
|
||||
@@ -12,7 +12,8 @@
|
||||
"build": "npm run before-build && tsc --skipLibCheck",
|
||||
"dev-build": "npm run build",
|
||||
"preview": "vite preview",
|
||||
"test": "mocha --loader=ts-node/esm"
|
||||
"test": "mocha --loader=ts-node/esm",
|
||||
"pub": "npm publish"
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "^1.7.2",
|
||||
@@ -44,5 +45,5 @@
|
||||
"tslib": "^2.8.1",
|
||||
"typescript": "^5.4.2"
|
||||
},
|
||||
"gitHead": "be69244e8ddb757de45c7e2b6033195c1f5a6910"
|
||||
"gitHead": "6c74148c277432f91014bf1eebd824e7423c6f4b"
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { customAlphabet } from "nanoid";
|
||||
|
||||
export const randomNumber = customAlphabet("1234567890", 4);
|
||||
export const simpleNanoId = customAlphabet("1234567890abcdefghijklmopqrstuvwxyz", 12);
|
||||
export const simpleNanoId = customAlphabet("1234567890abcdefghijklmopqrstuvwxyzABCDEFGHIJKLMOPQRSTUVWXYZ", 12);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { domainUtils } from './util.domain.js';
|
||||
import { domainUtils } from "./util.domain.js";
|
||||
|
||||
function groupByDomain(options: any[], inDomains: string[]) {
|
||||
const matched = [];
|
||||
@@ -19,16 +19,16 @@ function groupByDomain(options: any[], inDomains: string[]) {
|
||||
function buildGroupOptions(options: any[], inDomains: string[]) {
|
||||
const grouped = groupByDomain(options, inDomains);
|
||||
const groupOptions = [];
|
||||
groupOptions.push({ value: 'matched', disabled: true, label: '----已匹配----' });
|
||||
groupOptions.push({ value: "matched", disabled: true, label: "----已匹配----" });
|
||||
if (grouped.matched.length === 0) {
|
||||
options.push({ value: '', disabled: true, label: '没有可以匹配的域名' });
|
||||
options.push({ value: "", disabled: true, label: "没有可以匹配的域名" });
|
||||
} else {
|
||||
for (const matched of grouped.matched) {
|
||||
groupOptions.push(matched);
|
||||
}
|
||||
}
|
||||
if (grouped.notMatched.length > 0) {
|
||||
groupOptions.push({ value: 'unmatched', disabled: true, label: '----未匹配----' });
|
||||
groupOptions.push({ value: "unmatched", disabled: true, label: "----未匹配----" });
|
||||
for (const notMatched of grouped.notMatched) {
|
||||
groupOptions.push(notMatched);
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import axios, { AxiosHeaders, AxiosRequestConfig } from 'axios';
|
||||
import { ILogger, logger } from './util.log.js';
|
||||
import { Logger } from 'log4js';
|
||||
import { HttpProxyAgent } from 'http-proxy-agent';
|
||||
import { HttpsProxyAgent } from 'https-proxy-agent';
|
||||
import nodeHttp from 'http';
|
||||
import * as https from 'node:https';
|
||||
import { merge } from 'lodash-es';
|
||||
import { safePromise } from './util.promise.js';
|
||||
import fs from 'fs';
|
||||
import axios, { AxiosHeaders, AxiosRequestConfig } from "axios";
|
||||
import { ILogger, logger } from "./util.log.js";
|
||||
import { Logger } from "log4js";
|
||||
import { HttpProxyAgent } from "http-proxy-agent";
|
||||
import { HttpsProxyAgent } from "https-proxy-agent";
|
||||
import nodeHttp from "http";
|
||||
import * as https from "node:https";
|
||||
import { merge } from "lodash-es";
|
||||
import { safePromise } from "./util.promise.js";
|
||||
import fs from "fs";
|
||||
export class HttpError extends Error {
|
||||
status?: number;
|
||||
statusText?: string;
|
||||
@@ -22,10 +22,10 @@ export class HttpError extends Error {
|
||||
super(error.message || error.response?.statusText);
|
||||
|
||||
const message = error?.message;
|
||||
if (message && typeof message === 'string') {
|
||||
if (message.indexOf && message.indexOf('ssl3_get_record:wrong version number') >= 0) {
|
||||
if (message && typeof message === "string") {
|
||||
if (message.indexOf && message.indexOf("ssl3_get_record:wrong version number") >= 0) {
|
||||
this.message = `${message}(http协议错误,服务端要求http协议,请检查是否使用了https请求)`;
|
||||
} else if (message.indexOf('getaddrinfo EAI_AGAIN') >= 0) {
|
||||
} else if (message.indexOf("getaddrinfo EAI_AGAIN") >= 0) {
|
||||
this.message = `${message}(无法解析域名,请检查网络连接或dns配置,更换docker-compose.yaml中dns配置)`;
|
||||
}
|
||||
}
|
||||
@@ -47,7 +47,7 @@ export class HttpError extends Error {
|
||||
};
|
||||
let url = error.config?.url;
|
||||
if (error.config?.baseURL) {
|
||||
url = (error.config?.baseURL || '') + url;
|
||||
url = (error.config?.baseURL || "") + url;
|
||||
}
|
||||
if (url) {
|
||||
this.message = `${this.message} 【${url}】`;
|
||||
@@ -73,7 +73,7 @@ export const HttpCommonError = HttpError;
|
||||
let defaultAgents = createAgent();
|
||||
|
||||
export function setGlobalProxy(opts: { httpProxy?: string; httpsProxy?: string }) {
|
||||
logger.info('setGlobalProxy:', opts);
|
||||
logger.info("setGlobalProxy:", opts);
|
||||
defaultAgents = createAgent(opts);
|
||||
}
|
||||
|
||||
@@ -102,12 +102,12 @@ export function createAxiosService({ logger }: { logger: Logger }) {
|
||||
if (config.skipSslVerify || config.httpProxy) {
|
||||
let rejectUnauthorized = true;
|
||||
if (config.skipSslVerify) {
|
||||
logger.info('跳过SSL验证');
|
||||
logger.info("跳过SSL验证");
|
||||
rejectUnauthorized = false;
|
||||
}
|
||||
const proxy: any = {};
|
||||
if (config.httpProxy) {
|
||||
logger.info('使用自定义http代理:', config.httpProxy);
|
||||
logger.info("使用自定义http代理:", config.httpProxy);
|
||||
proxy.httpProxy = config.httpProxy;
|
||||
proxy.httpsProxy = config.httpProxy;
|
||||
}
|
||||
@@ -128,7 +128,7 @@ export function createAxiosService({ logger }: { logger: Logger }) {
|
||||
},
|
||||
(error: Error) => {
|
||||
// 发送失败
|
||||
logger.error('接口请求失败:', error);
|
||||
logger.error("接口请求失败:", error);
|
||||
return Promise.reject(error);
|
||||
}
|
||||
);
|
||||
@@ -143,9 +143,10 @@ export function createAxiosService({ logger }: { logger: Logger }) {
|
||||
|
||||
logger.info(`http response : status=${response?.status},data=${resData}`);
|
||||
} else {
|
||||
logger.info('http response status:', response?.status);
|
||||
logger.info("http response status:", response?.status);
|
||||
}
|
||||
if (response?.config?.returnResponse) {
|
||||
|
||||
if (response?.config?.returnOriginRes) {
|
||||
return response;
|
||||
}
|
||||
return response.data;
|
||||
@@ -154,53 +155,51 @@ export function createAxiosService({ logger }: { logger: Logger }) {
|
||||
const status = error.response?.status;
|
||||
switch (status) {
|
||||
case 400:
|
||||
error.message = '请求错误';
|
||||
error.message = "请求错误";
|
||||
break;
|
||||
case 401:
|
||||
error.message = '认证/登录失败';
|
||||
error.message = "认证/登录失败";
|
||||
break;
|
||||
case 403:
|
||||
error.message = '拒绝访问';
|
||||
error.message = "拒绝访问";
|
||||
break;
|
||||
case 404:
|
||||
error.message = `请求地址出错`;
|
||||
break;
|
||||
case 408:
|
||||
error.message = '请求超时';
|
||||
error.message = "请求超时";
|
||||
break;
|
||||
case 500:
|
||||
error.message = '服务器内部错误';
|
||||
error.message = "服务器内部错误";
|
||||
break;
|
||||
case 501:
|
||||
error.message = '服务未实现';
|
||||
error.message = "服务未实现";
|
||||
break;
|
||||
case 502:
|
||||
error.message = '网关错误';
|
||||
error.message = "网关错误";
|
||||
break;
|
||||
case 503:
|
||||
error.message = '服务不可用';
|
||||
error.message = "服务不可用";
|
||||
break;
|
||||
case 504:
|
||||
error.message = '网关超时';
|
||||
error.message = "网关超时";
|
||||
break;
|
||||
case 505:
|
||||
error.message = 'HTTP版本不受支持';
|
||||
error.message = "HTTP版本不受支持";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
logger.error(
|
||||
`请求出错:status:${error.response?.status},statusText:${error.response?.statusText},url:${error.config?.url},method:${error.config?.method}。`
|
||||
);
|
||||
logger.error('返回数据:', JSON.stringify(error.response?.data));
|
||||
logger.error(`请求出错:status:${error.response?.status},statusText:${error.response?.statusText},url:${error.config?.url},method:${error.config?.method}。`);
|
||||
logger.error("返回数据:", JSON.stringify(error.response?.data));
|
||||
if (error.response?.data) {
|
||||
const message = error.response.data.message || error.response.data.msg || error.response.data.error;
|
||||
if (typeof message === 'string') {
|
||||
if (typeof message === "string") {
|
||||
error.message = message;
|
||||
}
|
||||
}
|
||||
if (error instanceof AggregateError) {
|
||||
logger.error('AggregateError', error);
|
||||
logger.error("AggregateError", error);
|
||||
}
|
||||
const err = new HttpError(error);
|
||||
return Promise.reject(err);
|
||||
@@ -217,7 +216,7 @@ export type HttpRequestConfig<D = any> = {
|
||||
logParams?: boolean;
|
||||
logRes?: boolean;
|
||||
httpProxy?: string;
|
||||
returnResponse?: boolean;
|
||||
returnOriginRes?: boolean;
|
||||
} & AxiosRequestConfig<D>;
|
||||
export type HttpClient = {
|
||||
request<D = any, R = any>(config: HttpRequestConfig<D>): Promise<HttpClientResponse<R>>;
|
||||
@@ -244,24 +243,24 @@ export function createAgent(opts: CreateAgentOptions = {}) {
|
||||
if (httpProxy) {
|
||||
process.env.HTTP_PROXY = httpProxy;
|
||||
process.env.http_proxy = httpProxy;
|
||||
logger.info('use httpProxy:', httpProxy);
|
||||
logger.info("use httpProxy:", httpProxy);
|
||||
httpAgent = new HttpProxyAgent(httpProxy, opts as any);
|
||||
merge(httpAgent.options, opts);
|
||||
} else {
|
||||
process.env.HTTP_PROXY = '';
|
||||
process.env.http_proxy = '';
|
||||
process.env.HTTP_PROXY = "";
|
||||
process.env.http_proxy = "";
|
||||
httpAgent = new nodeHttp.Agent(opts);
|
||||
}
|
||||
const httpsProxy = opts.httpsProxy;
|
||||
if (httpsProxy) {
|
||||
process.env.HTTPS_PROXY = httpsProxy;
|
||||
process.env.https_proxy = httpsProxy;
|
||||
logger.info('use httpsProxy:', httpsProxy);
|
||||
logger.info("use httpsProxy:", httpsProxy);
|
||||
httpsAgent = new HttpsProxyAgent(httpsProxy, opts as any);
|
||||
merge(httpsAgent.options, opts);
|
||||
} else {
|
||||
process.env.HTTPS_PROXY = '';
|
||||
process.env.https_proxy = '';
|
||||
process.env.HTTPS_PROXY = "";
|
||||
process.env.https_proxy = "";
|
||||
httpsAgent = new https.Agent(opts);
|
||||
}
|
||||
return {
|
||||
@@ -276,27 +275,27 @@ export async function download(req: { http: HttpClient; config: HttpRequestConfi
|
||||
http
|
||||
.request({
|
||||
logRes: false,
|
||||
responseType: 'stream',
|
||||
responseType: "stream",
|
||||
...config,
|
||||
})
|
||||
.then(res => {
|
||||
const writer = fs.createWriteStream(savePath);
|
||||
res.pipe(writer);
|
||||
writer.on('close', () => {
|
||||
logger.info('文件下载成功');
|
||||
writer.on("close", () => {
|
||||
logger.info("文件下载成功");
|
||||
resolve(true);
|
||||
});
|
||||
//error
|
||||
writer.on('error', err => {
|
||||
logger.error('下载失败', err);
|
||||
writer.on("error", err => {
|
||||
logger.error("下载失败", err);
|
||||
reject(err);
|
||||
});
|
||||
//进度条打印
|
||||
const totalLength = res.headers['content-length'];
|
||||
const totalLength = res.headers["content-length"];
|
||||
let currentLength = 0;
|
||||
// 每5%打印一次
|
||||
const step = (totalLength / 100) * 5;
|
||||
res.on('data', (chunk: any) => {
|
||||
res.on("data", (chunk: any) => {
|
||||
currentLength += chunk.length;
|
||||
if (currentLength % step < chunk.length) {
|
||||
const percent = ((currentLength / totalLength) * 100).toFixed(2);
|
||||
@@ -305,19 +304,19 @@ export async function download(req: { http: HttpClient; config: HttpRequestConfi
|
||||
});
|
||||
})
|
||||
.catch(err => {
|
||||
logger.info('下载失败', err);
|
||||
logger.info("下载失败", err);
|
||||
reject(err);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export function getCookie(response: any, name: string) {
|
||||
const cookies = response.headers['set-cookie'];
|
||||
const cookies = response.headers["set-cookie"];
|
||||
//根据name 返回对应的cookie
|
||||
const found = cookies.find((cookie: any) => cookie.includes(name));
|
||||
if (!found) {
|
||||
return null;
|
||||
}
|
||||
const cookie = found.split(';')[0];
|
||||
return cookie.substring(cookie.indexOf('=') + 1);
|
||||
const cookie = found.split(";")[0];
|
||||
return cookie.substring(cookie.indexOf("=") + 1);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,38 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.34.2](https://github.com/certd/certd/compare/v1.34.1...v1.34.2) (2025-05-11)
|
||||
|
||||
**Note:** Version bump only for package @certd/pipeline
|
||||
|
||||
## [1.34.1](https://github.com/certd/certd/compare/v1.34.0...v1.34.1) (2025-05-05)
|
||||
|
||||
**Note:** Version bump only for package @certd/pipeline
|
||||
|
||||
# [1.34.0](https://github.com/certd/certd/compare/v1.33.8...v1.34.0) (2025-04-28)
|
||||
|
||||
**Note:** Version bump only for package @certd/pipeline
|
||||
|
||||
## [1.33.8](https://github.com/certd/certd/compare/v1.33.7...v1.33.8) (2025-04-26)
|
||||
|
||||
**Note:** Version bump only for package @certd/pipeline
|
||||
|
||||
## [1.33.7](https://github.com/certd/certd/compare/v1.33.6...v1.33.7) (2025-04-22)
|
||||
|
||||
**Note:** Version bump only for package @certd/pipeline
|
||||
|
||||
## [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
|
||||
|
||||
## [1.33.4](https://github.com/certd/certd/compare/v1.33.3...v1.33.4) (2025-04-15)
|
||||
|
||||
**Note:** Version bump only for package @certd/pipeline
|
||||
|
||||
## [1.33.3](https://github.com/certd/certd/compare/v1.33.2...v1.33.3) (2025-04-14)
|
||||
|
||||
**Note:** Version bump only for package @certd/pipeline
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@certd/pipeline",
|
||||
"private": false,
|
||||
"version": "1.33.3",
|
||||
"version": "1.34.2",
|
||||
"type": "module",
|
||||
"main": "./dist/index.js",
|
||||
"module": "./dist/index.js",
|
||||
@@ -13,11 +13,12 @@
|
||||
"dev-build": "npm run build",
|
||||
"build3": "rollup -c",
|
||||
"preview": "vite preview",
|
||||
"test": "mocha --loader=ts-node/esm"
|
||||
"test": "mocha --loader=ts-node/esm",
|
||||
"pub": "npm publish"
|
||||
},
|
||||
"dependencies": {
|
||||
"@certd/basic": "^1.33.3",
|
||||
"@certd/plus-core": "^1.33.3",
|
||||
"@certd/basic": "^1.34.2",
|
||||
"@certd/plus-core": "^1.34.2",
|
||||
"dayjs": "^1.11.7",
|
||||
"lodash-es": "^4.17.21",
|
||||
"reflect-metadata": "^0.1.13"
|
||||
@@ -43,5 +44,5 @@
|
||||
"tslib": "^2.8.1",
|
||||
"typescript": "^5.4.2"
|
||||
},
|
||||
"gitHead": "be69244e8ddb757de45c7e2b6033195c1f5a6910"
|
||||
"gitHead": "6c74148c277432f91014bf1eebd824e7423c6f4b"
|
||||
}
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
import { Decorator } from "./index.js";
|
||||
|
||||
export type AutowireProp = {
|
||||
name?: string;
|
||||
type?: any;
|
||||
};
|
||||
export const AUTOWIRE_KEY = "pipeline:autowire";
|
||||
|
||||
export function Autowire(props?: AutowireProp): PropertyDecorator {
|
||||
return (target, propertyKey) => {
|
||||
const _type = Reflect.getMetadata("design:type", target, propertyKey);
|
||||
target = Decorator.target(target, propertyKey);
|
||||
props = props || {};
|
||||
props.type = _type;
|
||||
Reflect.defineMetadata(AUTOWIRE_KEY, props || {}, target, propertyKey);
|
||||
};
|
||||
}
|
||||
@@ -1,2 +1 @@
|
||||
export * from "./utils.js";
|
||||
export * from "./common.js";
|
||||
|
||||
@@ -51,10 +51,6 @@ export type PluginDefine = Registrable & {
|
||||
[key: string]: TaskOutputDefine;
|
||||
};
|
||||
|
||||
autowire?: {
|
||||
[key: string]: any;
|
||||
};
|
||||
|
||||
shortcut?: {
|
||||
[key: string]: {
|
||||
title: string;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { pluginRegistry } from "./registry.js";
|
||||
import { PluginDefine, TaskInputDefine, TaskOutputDefine } from "./api.js";
|
||||
import { Decorator } from "../decorator/index.js";
|
||||
import { AUTOWIRE_KEY } from "../decorator/index.js";
|
||||
import "reflect-metadata";
|
||||
import { merge, sortBy } from "lodash-es";
|
||||
// 提供一个唯一 key
|
||||
@@ -12,7 +11,6 @@ export function IsTaskPlugin(define: PluginDefine): ClassDecorator {
|
||||
target = Decorator.target(target);
|
||||
|
||||
const inputs: any = {};
|
||||
const autowires: any = {};
|
||||
const outputs: any = {};
|
||||
const properties = Decorator.getClassProperties(target);
|
||||
for (const property in properties) {
|
||||
@@ -21,11 +19,6 @@ export function IsTaskPlugin(define: PluginDefine): ClassDecorator {
|
||||
inputs[property] = input;
|
||||
}
|
||||
|
||||
const autowire = Reflect.getMetadata(AUTOWIRE_KEY, target, property);
|
||||
if (autowire) {
|
||||
autowires[property] = autowire;
|
||||
}
|
||||
|
||||
const output = Reflect.getMetadata(PLUGIN_OUTPUT_KEY, target, property);
|
||||
if (output) {
|
||||
outputs[property] = output;
|
||||
@@ -57,7 +50,7 @@ export function IsTaskPlugin(define: PluginDefine): ClassDecorator {
|
||||
},
|
||||
};
|
||||
|
||||
define = merge(defaultConfig, define, { input: inputMap, autowire: autowires, output: outputs });
|
||||
define = merge(defaultConfig, define, { input: inputMap, output: outputs });
|
||||
|
||||
Reflect.defineMetadata(PLUGIN_CLASS_KEY, define, target);
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ export class Registry<T = any> {
|
||||
}
|
||||
|
||||
getDefineList() {
|
||||
const list = [];
|
||||
let list = [];
|
||||
for (const key in this.storage) {
|
||||
const define = this.getDefine(key);
|
||||
if (define) {
|
||||
@@ -78,6 +78,10 @@ export class Registry<T = any> {
|
||||
list.push({ ...define, key });
|
||||
}
|
||||
}
|
||||
|
||||
list = list.sort((a, b) => {
|
||||
return (a.order ?? 10) - (b?.order ?? 10);
|
||||
});
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,38 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.34.2](https://github.com/certd/certd/compare/v1.34.1...v1.34.2) (2025-05-11)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-huawei
|
||||
|
||||
## [1.34.1](https://github.com/certd/certd/compare/v1.34.0...v1.34.1) (2025-05-05)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-huawei
|
||||
|
||||
# [1.34.0](https://github.com/certd/certd/compare/v1.33.8...v1.34.0) (2025-04-28)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-huawei
|
||||
|
||||
## [1.33.8](https://github.com/certd/certd/compare/v1.33.7...v1.33.8) (2025-04-26)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-huawei
|
||||
|
||||
## [1.33.7](https://github.com/certd/certd/compare/v1.33.6...v1.33.7) (2025-04-22)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-huawei
|
||||
|
||||
## [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
|
||||
|
||||
## [1.33.4](https://github.com/certd/certd/compare/v1.33.3...v1.33.4) (2025-04-15)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-huawei
|
||||
|
||||
## [1.33.3](https://github.com/certd/certd/compare/v1.33.2...v1.33.3) (2025-04-14)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-huawei
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@certd/lib-huawei",
|
||||
"private": false,
|
||||
"version": "1.33.3",
|
||||
"version": "1.34.2",
|
||||
"main": "./dist/bundle.js",
|
||||
"module": "./dist/bundle.js",
|
||||
"types": "./dist/d/index.d.ts",
|
||||
@@ -10,7 +10,8 @@
|
||||
"before-build": "rimraf dist && rimraf tsconfig.tsbuildinfo && rimraf .rollup.cache",
|
||||
"build": "npm run before-build && rollup -c ",
|
||||
"dev-build": "npm run build",
|
||||
"preview": "vite preview"
|
||||
"preview": "vite preview",
|
||||
"pub": "npm publish"
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "^1.7.2",
|
||||
@@ -23,5 +24,5 @@
|
||||
"prettier": "^2.8.8",
|
||||
"tslib": "^2.8.1"
|
||||
},
|
||||
"gitHead": "be69244e8ddb757de45c7e2b6033195c1f5a6910"
|
||||
"gitHead": "6c74148c277432f91014bf1eebd824e7423c6f4b"
|
||||
}
|
||||
|
||||
@@ -3,6 +3,40 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.34.2](https://github.com/certd/certd/compare/v1.34.1...v1.34.2) (2025-05-11)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-iframe
|
||||
|
||||
## [1.34.1](https://github.com/certd/certd/compare/v1.34.0...v1.34.1) (2025-05-05)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-iframe
|
||||
|
||||
# [1.34.0](https://github.com/certd/certd/compare/v1.33.8...v1.34.0) (2025-04-28)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-iframe
|
||||
|
||||
## [1.33.8](https://github.com/certd/certd/compare/v1.33.7...v1.33.8) (2025-04-26)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-iframe
|
||||
|
||||
## [1.33.7](https://github.com/certd/certd/compare/v1.33.6...v1.33.7) (2025-04-22)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-iframe
|
||||
|
||||
## [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
|
||||
|
||||
## [1.33.4](https://github.com/certd/certd/compare/v1.33.3...v1.33.4) (2025-04-15)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-iframe
|
||||
|
||||
## [1.33.3](https://github.com/certd/certd/compare/v1.33.2...v1.33.3) (2025-04-14)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-iframe
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@certd/lib-iframe",
|
||||
"private": false,
|
||||
"version": "1.33.3",
|
||||
"version": "1.34.2",
|
||||
"type": "module",
|
||||
"main": "./dist/index.js",
|
||||
"module": "./dist/index.js",
|
||||
@@ -13,7 +13,8 @@
|
||||
"dev-build": "npm run build",
|
||||
"build3": "rollup -c",
|
||||
"build2": "vue-tsc --noEmit && vite build",
|
||||
"preview": "vite preview"
|
||||
"preview": "vite preview",
|
||||
"pub": "npm publish"
|
||||
},
|
||||
"dependencies": {
|
||||
"nanoid": "^4.0.0"
|
||||
@@ -30,5 +31,5 @@
|
||||
"tslib": "^2.8.1",
|
||||
"typescript": "^5.4.2"
|
||||
},
|
||||
"gitHead": "be69244e8ddb757de45c7e2b6033195c1f5a6910"
|
||||
"gitHead": "6c74148c277432f91014bf1eebd824e7423c6f4b"
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ export class IframeClient {
|
||||
return window.self !== window.top;
|
||||
}
|
||||
|
||||
register<T = any>(action: string, handler: (data: IframeMessageData<T>) => Promise<void>) {
|
||||
register<T = any>(action: string, handler: (data: IframeMessageData<T>) => Promise<any>) {
|
||||
this.handlers[action] = handler;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,38 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.34.2](https://github.com/certd/certd/compare/v1.34.1...v1.34.2) (2025-05-11)
|
||||
|
||||
**Note:** Version bump only for package @certd/jdcloud
|
||||
|
||||
## [1.34.1](https://github.com/certd/certd/compare/v1.34.0...v1.34.1) (2025-05-05)
|
||||
|
||||
**Note:** Version bump only for package @certd/jdcloud
|
||||
|
||||
# [1.34.0](https://github.com/certd/certd/compare/v1.33.8...v1.34.0) (2025-04-28)
|
||||
|
||||
**Note:** Version bump only for package @certd/jdcloud
|
||||
|
||||
## [1.33.8](https://github.com/certd/certd/compare/v1.33.7...v1.33.8) (2025-04-26)
|
||||
|
||||
**Note:** Version bump only for package @certd/jdcloud
|
||||
|
||||
## [1.33.7](https://github.com/certd/certd/compare/v1.33.6...v1.33.7) (2025-04-22)
|
||||
|
||||
**Note:** Version bump only for package @certd/jdcloud
|
||||
|
||||
## [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
|
||||
|
||||
## [1.33.4](https://github.com/certd/certd/compare/v1.33.3...v1.33.4) (2025-04-15)
|
||||
|
||||
**Note:** Version bump only for package @certd/jdcloud
|
||||
|
||||
## [1.33.3](https://github.com/certd/certd/compare/v1.33.2...v1.33.3) (2025-04-14)
|
||||
|
||||
**Note:** Version bump only for package @certd/jdcloud
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@certd/jdcloud",
|
||||
"version": "1.33.3",
|
||||
"version": "1.34.2",
|
||||
"description": "jdcloud openApi sdk",
|
||||
"main": "./dist/bundle.js",
|
||||
"module": "./dist/bundle.js",
|
||||
@@ -9,7 +9,8 @@
|
||||
"test": "cross-env NODE_CONFIG_DIR=./test/config mocha --recursive --require babel-register",
|
||||
"dev": "babel src --out-dir babel -w",
|
||||
"build": "rollup -c ",
|
||||
"dev-build": "npm run build"
|
||||
"dev-build": "npm run build",
|
||||
"pub": "npm publish"
|
||||
},
|
||||
"author": "",
|
||||
"license": "Apache",
|
||||
@@ -60,5 +61,5 @@
|
||||
"fetch"
|
||||
]
|
||||
},
|
||||
"gitHead": "be69244e8ddb757de45c7e2b6033195c1f5a6910"
|
||||
"gitHead": "6c74148c277432f91014bf1eebd824e7423c6f4b"
|
||||
}
|
||||
|
||||
@@ -3,6 +3,38 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.34.2](https://github.com/certd/certd/compare/v1.34.1...v1.34.2) (2025-05-11)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-k8s
|
||||
|
||||
## [1.34.1](https://github.com/certd/certd/compare/v1.34.0...v1.34.1) (2025-05-05)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-k8s
|
||||
|
||||
# [1.34.0](https://github.com/certd/certd/compare/v1.33.8...v1.34.0) (2025-04-28)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-k8s
|
||||
|
||||
## [1.33.8](https://github.com/certd/certd/compare/v1.33.7...v1.33.8) (2025-04-26)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-k8s
|
||||
|
||||
## [1.33.7](https://github.com/certd/certd/compare/v1.33.6...v1.33.7) (2025-04-22)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-k8s
|
||||
|
||||
## [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
|
||||
|
||||
## [1.33.4](https://github.com/certd/certd/compare/v1.33.3...v1.33.4) (2025-04-15)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-k8s
|
||||
|
||||
## [1.33.3](https://github.com/certd/certd/compare/v1.33.2...v1.33.3) (2025-04-14)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-k8s
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@certd/lib-k8s",
|
||||
"private": false,
|
||||
"version": "1.33.3",
|
||||
"version": "1.34.2",
|
||||
"type": "module",
|
||||
"main": "./dist/index.js",
|
||||
"module": "./dist/index.js",
|
||||
@@ -13,10 +13,11 @@
|
||||
"dev-build": "npm run build",
|
||||
"build3": "rollup -c",
|
||||
"build2": "vue-tsc --noEmit && vite build",
|
||||
"preview": "vite preview"
|
||||
"preview": "vite preview",
|
||||
"pub": "npm publish"
|
||||
},
|
||||
"dependencies": {
|
||||
"@certd/basic": "^1.33.3",
|
||||
"@certd/basic": "^1.34.2",
|
||||
"@kubernetes/client-node": "0.21.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -31,5 +32,5 @@
|
||||
"tslib": "^2.8.1",
|
||||
"typescript": "^5.4.2"
|
||||
},
|
||||
"gitHead": "be69244e8ddb757de45c7e2b6033195c1f5a6910"
|
||||
"gitHead": "6c74148c277432f91014bf1eebd824e7423c6f4b"
|
||||
}
|
||||
|
||||
@@ -3,6 +3,42 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.34.2](https://github.com/certd/certd/compare/v1.34.1...v1.34.2) (2025-05-11)
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 支持设置网安备案号 ([d18e431](https://github.com/certd/certd/commit/d18e431e2f08e6b37704032c4ea6fbdd8e971442))
|
||||
|
||||
## [1.34.1](https://github.com/certd/certd/compare/v1.34.0...v1.34.1) (2025-05-05)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-server
|
||||
|
||||
# [1.34.0](https://github.com/certd/certd/compare/v1.33.8...v1.34.0) (2025-04-28)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-server
|
||||
|
||||
## [1.33.8](https://github.com/certd/certd/compare/v1.33.7...v1.33.8) (2025-04-26)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-server
|
||||
|
||||
## [1.33.7](https://github.com/certd/certd/compare/v1.33.6...v1.33.7) (2025-04-22)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-server
|
||||
|
||||
## [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
|
||||
|
||||
* 登录支持双重认证 ([48aef25](https://github.com/certd/certd/commit/48aef25b3f6499d674ca4e4ef16f4c62399fb735))
|
||||
|
||||
## [1.33.4](https://github.com/certd/certd/compare/v1.33.3...v1.33.4) (2025-04-15)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-server
|
||||
|
||||
## [1.33.3](https://github.com/certd/certd/compare/v1.33.2...v1.33.3) (2025-04-14)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-server
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@certd/lib-server",
|
||||
"version": "1.33.3",
|
||||
"version": "1.34.2",
|
||||
"description": "midway with flyway, sql upgrade way ",
|
||||
"private": false,
|
||||
"type": "module",
|
||||
@@ -27,10 +27,10 @@
|
||||
],
|
||||
"license": "AGPL",
|
||||
"dependencies": {
|
||||
"@certd/acme-client": "^1.33.3",
|
||||
"@certd/basic": "^1.33.3",
|
||||
"@certd/pipeline": "^1.33.3",
|
||||
"@certd/plus-core": "^1.33.3",
|
||||
"@certd/acme-client": "^1.34.2",
|
||||
"@certd/basic": "^1.34.2",
|
||||
"@certd/pipeline": "^1.34.2",
|
||||
"@certd/plus-core": "^1.34.2",
|
||||
"@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": "be69244e8ddb757de45c7e2b6033195c1f5a6910"
|
||||
"gitHead": "6c74148c277432f91014bf1eebd824e7423c6f4b"
|
||||
}
|
||||
|
||||
@@ -75,6 +75,10 @@ export const Constants = {
|
||||
code: 10010,
|
||||
message: '站点已关闭',
|
||||
},
|
||||
need2fa:{
|
||||
code: 10020,
|
||||
message: '需要2FA认证',
|
||||
},
|
||||
openKeyError: {
|
||||
code: 20000,
|
||||
message: 'ApiToken错误',
|
||||
|
||||
@@ -1,10 +1,19 @@
|
||||
import { Constants } from '../constants.js';
|
||||
import { BaseException } from './base-exception.js';
|
||||
import { TextException } from "./common-exception.js";
|
||||
/**
|
||||
* 授权异常
|
||||
*/
|
||||
export class AuthException extends BaseException {
|
||||
constructor(message) {
|
||||
constructor(message?:string) {
|
||||
super('AuthException', Constants.res.auth.code, message ? message : Constants.res.auth.message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export class Need2FAException extends TextException {
|
||||
constructor(message:string,data:any) {
|
||||
super('Need2FAException', Constants.res.need2fa.code, message ? message : Constants.res.need2fa.message,data);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,9 +3,11 @@
|
||||
*/
|
||||
export class BaseException extends Error {
|
||||
code: number;
|
||||
constructor(name, code, message) {
|
||||
data?:any
|
||||
constructor(name, code, message,data?:any) {
|
||||
super(message);
|
||||
this.name = name;
|
||||
this.code = code;
|
||||
this.data = data;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,23 @@
|
||||
import { Constants } from '../constants.js';
|
||||
import { BaseException } from './base-exception.js';
|
||||
import { Constants } from "../constants.js";
|
||||
import { BaseException } from "./base-exception.js";
|
||||
|
||||
/**
|
||||
* 通用异常
|
||||
*/
|
||||
export class CommonException extends BaseException {
|
||||
constructor(message) {
|
||||
super('CommonException', Constants.res.error.code, message ? message : Constants.res.error.message);
|
||||
super("CommonException", Constants.res.error.code, message ? message : Constants.res.error.message);
|
||||
}
|
||||
}
|
||||
|
||||
export class CodeException extends BaseException {
|
||||
constructor(res: { code: number; message: string }) {
|
||||
super('CodeException', res.code, res.message);
|
||||
super("CodeException", res.code, res.message);
|
||||
}
|
||||
}
|
||||
|
||||
export class TextException extends BaseException {
|
||||
constructor(name, code,message, data?) {
|
||||
super(name, code, message, data);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,14 +2,15 @@ export class Result<T> {
|
||||
code: number;
|
||||
msg: string;
|
||||
data: T;
|
||||
|
||||
constructor(code, msg, data?) {
|
||||
this.code = code;
|
||||
this.msg = msg;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
static error(code = 1, msg) {
|
||||
return new Result(code, msg);
|
||||
static error(code = 1, msg, data?: any) {
|
||||
return new Result(code, msg, data);
|
||||
}
|
||||
|
||||
static success(msg, data?) {
|
||||
|
||||
@@ -25,6 +25,7 @@ export class SysPublicSettings extends BaseSettings {
|
||||
limitUserPipelineCount = 0;
|
||||
managerOtherUserPipeline = false;
|
||||
icpNo?: string;
|
||||
mpsNo?: string;
|
||||
robots?: boolean = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,38 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.34.2](https://github.com/certd/certd/compare/v1.34.1...v1.34.2) (2025-05-11)
|
||||
|
||||
**Note:** Version bump only for package @certd/midway-flyway-js
|
||||
|
||||
## [1.34.1](https://github.com/certd/certd/compare/v1.34.0...v1.34.1) (2025-05-05)
|
||||
|
||||
**Note:** Version bump only for package @certd/midway-flyway-js
|
||||
|
||||
# [1.34.0](https://github.com/certd/certd/compare/v1.33.8...v1.34.0) (2025-04-28)
|
||||
|
||||
**Note:** Version bump only for package @certd/midway-flyway-js
|
||||
|
||||
## [1.33.8](https://github.com/certd/certd/compare/v1.33.7...v1.33.8) (2025-04-26)
|
||||
|
||||
**Note:** Version bump only for package @certd/midway-flyway-js
|
||||
|
||||
## [1.33.7](https://github.com/certd/certd/compare/v1.33.6...v1.33.7) (2025-04-22)
|
||||
|
||||
**Note:** Version bump only for package @certd/midway-flyway-js
|
||||
|
||||
## [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
|
||||
|
||||
## [1.33.4](https://github.com/certd/certd/compare/v1.33.3...v1.33.4) (2025-04-15)
|
||||
|
||||
**Note:** Version bump only for package @certd/midway-flyway-js
|
||||
|
||||
## [1.33.3](https://github.com/certd/certd/compare/v1.33.2...v1.33.3) (2025-04-14)
|
||||
|
||||
**Note:** Version bump only for package @certd/midway-flyway-js
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@certd/midway-flyway-js",
|
||||
"version": "1.33.3",
|
||||
"version": "1.34.2",
|
||||
"description": "midway with flyway, sql upgrade way ",
|
||||
"private": false,
|
||||
"type": "module",
|
||||
@@ -46,5 +46,5 @@
|
||||
"typeorm": "^0.3.11",
|
||||
"typescript": "^5.4.2"
|
||||
},
|
||||
"gitHead": "be69244e8ddb757de45c7e2b6033195c1f5a6910"
|
||||
"gitHead": "6c74148c277432f91014bf1eebd824e7423c6f4b"
|
||||
}
|
||||
|
||||
@@ -3,6 +3,49 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.34.2](https://github.com/certd/certd/compare/v1.34.1...v1.34.2) (2025-05-11)
|
||||
|
||||
**Note:** Version bump only for package @certd/plugin-cert
|
||||
|
||||
## [1.34.1](https://github.com/certd/certd/compare/v1.34.0...v1.34.1) (2025-05-05)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 根据SOA记录判断子域名托管有缺陷,改回手动配置子域名托管记录的方式 ([1b280a2](https://github.com/certd/certd/commit/1b280a2940f9e2d919b0bf23b89cc185be1fa498))
|
||||
|
||||
# [1.34.0](https://github.com/certd/certd/compare/v1.33.8...v1.34.0) (2025-04-28)
|
||||
|
||||
**Note:** Version bump only for package @certd/plugin-cert
|
||||
|
||||
## [1.33.8](https://github.com/certd/certd/compare/v1.33.7...v1.33.8) (2025-04-26)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 修复http上传方式无法清除记录文件的bug ([72a7b51](https://github.com/certd/certd/commit/72a7b51d479602b2c54c6c3ac8d8a0dcb9664e73))
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 从域名的soa获取主域名,子域名托管无需额外配置 ([a586a92](https://github.com/certd/certd/commit/a586a92d5e32ea846ac37be52a7ad8c328d89966))
|
||||
* 数据库备份支持oss ([308d460](https://github.com/certd/certd/commit/308d4600efe2002f199c33b4594d3071784e58ea))
|
||||
* 支持阿里云中文域名申请 ([b3468cf](https://github.com/certd/certd/commit/b3468cf7f28228d7c9cf68de6b5a9bbeb67f2c6d))
|
||||
* 支持中文域名 ([162ebfd](https://github.com/certd/certd/commit/162ebfd4e0c25727efb33952d3bbf7420a02e2c3))
|
||||
|
||||
## [1.33.7](https://github.com/certd/certd/compare/v1.33.6...v1.33.7) (2025-04-22)
|
||||
|
||||
**Note:** Version bump only for package @certd/plugin-cert
|
||||
|
||||
## [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
|
||||
|
||||
## [1.33.4](https://github.com/certd/certd/compare/v1.33.3...v1.33.4) (2025-04-15)
|
||||
|
||||
**Note:** Version bump only for package @certd/plugin-cert
|
||||
|
||||
## [1.33.3](https://github.com/certd/certd/compare/v1.33.2...v1.33.3) (2025-04-14)
|
||||
|
||||
**Note:** Version bump only for package @certd/plugin-cert
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@certd/plugin-cert",
|
||||
"private": false,
|
||||
"version": "1.33.3",
|
||||
"version": "1.34.2",
|
||||
"type": "module",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
@@ -12,18 +12,20 @@
|
||||
"dev-build": "npm run build",
|
||||
"build3": "rollup -c",
|
||||
"build2": "vue-tsc --noEmit && vite build",
|
||||
"preview": "vite preview"
|
||||
"preview": "vite preview",
|
||||
"pub": "npm publish"
|
||||
},
|
||||
"dependencies": {
|
||||
"@certd/acme-client": "^1.33.3",
|
||||
"@certd/basic": "^1.33.3",
|
||||
"@certd/pipeline": "^1.33.3",
|
||||
"@certd/plugin-lib": "^1.33.3",
|
||||
"@certd/acme-client": "^1.34.2",
|
||||
"@certd/basic": "^1.34.2",
|
||||
"@certd/pipeline": "^1.34.2",
|
||||
"@certd/plugin-lib": "^1.34.2",
|
||||
"@google-cloud/publicca": "^1.3.0",
|
||||
"dayjs": "^1.11.7",
|
||||
"jszip": "^3.10.1",
|
||||
"lodash-es": "^4.17.21",
|
||||
"psl": "^1.9.0",
|
||||
"punycode": "^2.3.1",
|
||||
"rimraf": "^5.0.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -41,5 +43,5 @@
|
||||
"tslib": "^2.8.1",
|
||||
"typescript": "^5.4.2"
|
||||
},
|
||||
"gitHead": "be69244e8ddb757de45c7e2b6033195c1f5a6910"
|
||||
"gitHead": "6c74148c277432f91014bf1eebd824e7423c6f4b"
|
||||
}
|
||||
|
||||
@@ -4,9 +4,6 @@ import { IAccess, Registrable } from "@certd/pipeline";
|
||||
export type DnsProviderDefine = Registrable & {
|
||||
accessType: string;
|
||||
icon?: string;
|
||||
autowire?: {
|
||||
[key: string]: any;
|
||||
};
|
||||
};
|
||||
|
||||
export type CreateRecordOptions = {
|
||||
@@ -35,6 +32,8 @@ export interface IDnsProvider<T = any> {
|
||||
createRecord(options: CreateRecordOptions): Promise<T>;
|
||||
removeRecord(options: RemoveRecordOptions<T>): Promise<void>;
|
||||
setCtx(ctx: DnsProviderContext): void;
|
||||
//中文域名是否需要punycode转码,如果返回True,则使用punycode来添加解析记录,否则使用中文域名添加解析记录
|
||||
usePunyCode(): boolean;
|
||||
}
|
||||
|
||||
export interface ISubDomainsGetter {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { CreateRecordOptions, DnsProviderContext, DnsProviderDefine, IDnsProvider, RemoveRecordOptions } from "./api.js";
|
||||
import { dnsProviderRegistry } from "./registry.js";
|
||||
import { Decorator } from "@certd/pipeline";
|
||||
import { HttpClient, ILogger } from "@certd/basic";
|
||||
|
||||
export abstract class AbstractDnsProvider<T = any> implements IDnsProvider<T> {
|
||||
@@ -8,6 +7,12 @@ export abstract class AbstractDnsProvider<T = any> implements IDnsProvider<T> {
|
||||
http!: HttpClient;
|
||||
logger!: ILogger;
|
||||
|
||||
usePunyCode(): boolean {
|
||||
//是否使用punycode来添加解析记录
|
||||
//默认都使用原始中文域名来添加
|
||||
return false;
|
||||
}
|
||||
|
||||
setCtx(ctx: DnsProviderContext) {
|
||||
this.ctx = ctx;
|
||||
this.logger = ctx.logger;
|
||||
@@ -28,15 +33,13 @@ export abstract class AbstractDnsProvider<T = any> implements IDnsProvider<T> {
|
||||
export async function createDnsProvider(opts: { dnsProviderType: string; context: DnsProviderContext }): Promise<IDnsProvider> {
|
||||
const { dnsProviderType, context } = opts;
|
||||
const dnsProviderPlugin = dnsProviderRegistry.get(dnsProviderType);
|
||||
const DnsProviderClass = dnsProviderPlugin.target;
|
||||
const DnsProviderClass = await dnsProviderPlugin.target();
|
||||
const dnsProviderDefine = dnsProviderPlugin.define as DnsProviderDefine;
|
||||
if (dnsProviderDefine.deprecated) {
|
||||
context.logger.warn(dnsProviderDefine.deprecated);
|
||||
}
|
||||
// @ts-ignore
|
||||
const dnsProvider: IDnsProvider = new DnsProviderClass();
|
||||
|
||||
Decorator.inject(dnsProviderDefine.autowire, dnsProvider, context);
|
||||
dnsProvider.setCtx(context);
|
||||
await dnsProvider.onInstance();
|
||||
return dnsProvider;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { dnsProviderRegistry } from "./registry.js";
|
||||
import { DnsProviderDefine } from "./api.js";
|
||||
import { Decorator, AUTOWIRE_KEY } from "@certd/pipeline";
|
||||
import { Decorator } from "@certd/pipeline";
|
||||
import * as _ from "lodash-es";
|
||||
|
||||
// 提供一个唯一 key
|
||||
@@ -9,22 +9,15 @@ export const DNS_PROVIDER_CLASS_KEY = "pipeline:dns-provider";
|
||||
export function IsDnsProvider(define: DnsProviderDefine): ClassDecorator {
|
||||
return (target: any) => {
|
||||
target = Decorator.target(target);
|
||||
const autowires: any = {};
|
||||
const properties = Decorator.getClassProperties(target);
|
||||
for (const property in properties) {
|
||||
const autowire = Reflect.getMetadata(AUTOWIRE_KEY, target, property);
|
||||
if (autowire) {
|
||||
autowires[property] = autowire;
|
||||
}
|
||||
}
|
||||
_.merge(define, { autowire: autowires });
|
||||
|
||||
Reflect.defineMetadata(DNS_PROVIDER_CLASS_KEY, define, target);
|
||||
|
||||
target.define = define;
|
||||
dnsProviderRegistry.register(define.name, {
|
||||
define,
|
||||
target,
|
||||
target: async () => {
|
||||
return target;
|
||||
},
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,14 +1,18 @@
|
||||
import { IDomainParser, ISubDomainsGetter } from "./api";
|
||||
//@ts-ignore
|
||||
import psl from "psl";
|
||||
import { ILogger, utils, logger as globalLogger } from "@certd/basic";
|
||||
import { resolveDomainBySoaRecord } from "@certd/acme-client";
|
||||
|
||||
export class DomainParser implements IDomainParser {
|
||||
subDomainsGetter: ISubDomainsGetter;
|
||||
constructor(subDomainsGetter: ISubDomainsGetter) {
|
||||
logger: ILogger;
|
||||
constructor(subDomainsGetter: ISubDomainsGetter, logger?: ILogger) {
|
||||
this.subDomainsGetter = subDomainsGetter;
|
||||
this.logger = logger || globalLogger;
|
||||
}
|
||||
|
||||
parseDomain(fullDomain: string) {
|
||||
parseDomainByPsl(fullDomain: string) {
|
||||
const parsed = psl.parse(fullDomain) as psl.ParsedDomain;
|
||||
if (parsed.error) {
|
||||
throw new Error(`解析${fullDomain}域名失败:` + JSON.stringify(parsed.error));
|
||||
@@ -17,16 +21,46 @@ export class DomainParser implements IDomainParser {
|
||||
}
|
||||
|
||||
async parse(fullDomain: string) {
|
||||
this.logger.info(`查找主域名:${fullDomain}`);
|
||||
const cacheKey = `domain_parse:${fullDomain}`;
|
||||
const value = utils.cache.get(cacheKey);
|
||||
if (value) {
|
||||
this.logger.info(`从缓存获取到主域名:${fullDomain}->${value}`);
|
||||
return value;
|
||||
}
|
||||
|
||||
const subDomains = await this.subDomainsGetter.getSubDomains();
|
||||
if (subDomains && subDomains.length > 0) {
|
||||
const fullDomainDot = "." + fullDomain;
|
||||
for (const subDomain of subDomains) {
|
||||
if (fullDomain.endsWith(subDomain)) {
|
||||
if (fullDomainDot.endsWith("." + subDomain)) {
|
||||
//找到子域名托管
|
||||
utils.cache.set(cacheKey, subDomain, {
|
||||
ttl: 60 * 1000,
|
||||
});
|
||||
this.logger.info(`获取到子域名托管域名:${fullDomain}->${subDomain}`);
|
||||
return subDomain;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return this.parseDomain(fullDomain);
|
||||
const res = this.parseDomainByPsl(fullDomain);
|
||||
this.logger.info(`从psl获取主域名:${fullDomain}->${res}`);
|
||||
|
||||
let soaManDomain = null;
|
||||
try {
|
||||
const mainDomain = await resolveDomainBySoaRecord(fullDomain);
|
||||
if (mainDomain) {
|
||||
this.logger.info(`从SOA获取到主域名:${fullDomain}->${mainDomain}`);
|
||||
soaManDomain = mainDomain;
|
||||
}
|
||||
} catch (e) {
|
||||
this.logger.error("从SOA获取主域名失败", e.message);
|
||||
}
|
||||
if (soaManDomain && soaManDomain !== res) {
|
||||
this.logger.warn(`SOA获取的主域名(${soaManDomain})和psl获取的主域名(${res})不一致,请确认是否有设置子域名托管`);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,8 +6,8 @@ import { Challenge } from "@certd/acme-client/types/rfc8555";
|
||||
import { IContext } from "@certd/pipeline";
|
||||
import { ILogger, utils } from "@certd/basic";
|
||||
import { IDnsProvider, IDomainParser } from "../../dns-provider/index.js";
|
||||
import { HttpChallengeUploader } from "./uploads/api.js";
|
||||
|
||||
import punycode from "node:punycode";
|
||||
import { IOssClient } from "@certd/plugin-lib";
|
||||
export type CnameVerifyPlan = {
|
||||
type?: string;
|
||||
domain: string;
|
||||
@@ -18,7 +18,7 @@ export type CnameVerifyPlan = {
|
||||
export type HttpVerifyPlan = {
|
||||
type: string;
|
||||
domain: string;
|
||||
httpUploader: HttpChallengeUploader;
|
||||
httpUploader: IOssClient;
|
||||
};
|
||||
|
||||
export type DomainVerifyPlan = {
|
||||
@@ -35,7 +35,6 @@ export type DomainsVerifyPlan = {
|
||||
export type Providers = {
|
||||
dnsProvider?: IDnsProvider;
|
||||
domainsVerifyPlan?: DomainsVerifyPlan;
|
||||
httpUploader?: HttpChallengeUploader;
|
||||
};
|
||||
|
||||
export type CertInfo = {
|
||||
@@ -64,6 +63,7 @@ type AcmeServiceOptions = {
|
||||
maxCheckRetryCount?: number;
|
||||
userId: number;
|
||||
domainParser: IDomainParser;
|
||||
waitDnsDiffuseTime?: number;
|
||||
};
|
||||
|
||||
export class AcmeService {
|
||||
@@ -184,7 +184,7 @@ export class AcmeService {
|
||||
return authz.challenges.find((c: any) => c.type === type);
|
||||
};
|
||||
|
||||
const doHttpVerify = async (challenge: any, httpUploader: HttpChallengeUploader) => {
|
||||
const doHttpVerify = async (challenge: any, httpUploader: IOssClient) => {
|
||||
const keyAuthorization = await keyAuthorizationGetter(challenge);
|
||||
this.logger.info("http校验");
|
||||
const filePath = `.well-known/acme-challenge/${challenge.token}`;
|
||||
@@ -203,14 +203,16 @@ export class AcmeService {
|
||||
this.logger.info("dns校验");
|
||||
const keyAuthorization = await keyAuthorizationGetter(challenge);
|
||||
|
||||
const mainDomain = dnsProvider.usePunyCode() ? domain : punycode.toUnicode(domain);
|
||||
fullRecord = dnsProvider.usePunyCode() ? fullRecord : punycode.toUnicode(fullRecord);
|
||||
const recordValue = keyAuthorization;
|
||||
let hostRecord = fullRecord.replace(`${domain}`, "");
|
||||
let hostRecord = fullRecord.replace(`${mainDomain}`, "");
|
||||
if (hostRecord.endsWith(".")) {
|
||||
hostRecord = hostRecord.substring(0, hostRecord.length - 1);
|
||||
}
|
||||
|
||||
const recordReq = {
|
||||
domain,
|
||||
domain: mainDomain,
|
||||
fullRecord,
|
||||
hostRecord,
|
||||
type: "TXT",
|
||||
@@ -247,7 +249,10 @@ export class AcmeService {
|
||||
fullRecord = cname.fullRecord;
|
||||
}
|
||||
} else {
|
||||
this.logger.error("未找到域名Cname校验计划,使用默认的dnsProvider");
|
||||
this.logger.error(`未找到域名${fullDomain}的CNAME校验计划,请修改证书申请配置`);
|
||||
}
|
||||
if (dnsProvider == null) {
|
||||
throw new Error(`未找到域名${fullDomain}CNAME校验计划的DnsProvider,请修改证书申请配置`);
|
||||
}
|
||||
} else if (domainVerifyPlan.type === "http") {
|
||||
const httpVerifyPlan = domainVerifyPlan.httpVerifyPlan;
|
||||
@@ -286,7 +291,7 @@ export class AcmeService {
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
async challengeRemoveFn(authz: any, challenge: any, keyAuthorization: string, recordReq: any, recordRes: any, dnsProvider?: IDnsProvider, httpUploader?: HttpChallengeUploader) {
|
||||
async challengeRemoveFn(authz: any, challenge: any, keyAuthorization: string, recordReq: any, recordRes: any, dnsProvider?: IDnsProvider, httpUploader?: IOssClient) {
|
||||
this.logger.info("执行清理");
|
||||
|
||||
/* http-01 */
|
||||
@@ -321,9 +326,16 @@ export class AcmeService {
|
||||
isTest?: boolean;
|
||||
privateKeyType?: string;
|
||||
}): Promise<CertInfo> {
|
||||
const { email, isTest, domains, csrInfo, dnsProvider, domainsVerifyPlan, httpUploader } = options;
|
||||
const { email, isTest, csrInfo, dnsProvider, domainsVerifyPlan } = options;
|
||||
const client: acme.Client = await this.getAcmeClient(email, isTest);
|
||||
|
||||
let domains = options.domains;
|
||||
const encodingDomains = [];
|
||||
for (const domain of domains) {
|
||||
encodingDomains.push(punycode.toASCII(domain));
|
||||
}
|
||||
domains = encodingDomains;
|
||||
|
||||
/* Create CSR */
|
||||
const { commonName, altNames } = this.buildCommonNameByDomains(domains);
|
||||
let privateKey = null;
|
||||
@@ -361,14 +373,13 @@ export class AcmeService {
|
||||
privateKey
|
||||
);
|
||||
|
||||
if (dnsProvider == null && domainsVerifyPlan == null && httpUploader == null) {
|
||||
throw new Error("dnsProvider 、 domainsVerifyPlan 、 httpUploader不能都为空");
|
||||
if (dnsProvider == null && domainsVerifyPlan == null) {
|
||||
throw new Error("dnsProvider 、 domainsVerifyPlan不能都为空");
|
||||
}
|
||||
|
||||
const providers: Providers = {
|
||||
dnsProvider,
|
||||
domainsVerifyPlan,
|
||||
httpUploader,
|
||||
};
|
||||
/* 自动申请证书 */
|
||||
const crt = await client.auto({
|
||||
@@ -383,7 +394,7 @@ export class AcmeService {
|
||||
): Promise<{ recordReq?: any; recordRes?: any; dnsProvider?: any; challenge: Challenge; keyAuthorization: string }> => {
|
||||
return await this.challengeCreateFn(authz, keyAuthorizationGetter, providers);
|
||||
},
|
||||
challengeRemoveFn: async (authz: acme.Authorization, challenge: Challenge, keyAuthorization: string, recordReq: any, recordRes: any, dnsProvider: IDnsProvider): Promise<any> => {
|
||||
challengeRemoveFn: async (authz: acme.Authorization, challenge: Challenge, keyAuthorization: string, recordReq: any, recordRes: any, dnsProvider: IDnsProvider, httpUploader: IOssClient): Promise<any> => {
|
||||
return await this.challengeRemoveFn(authz, challenge, keyAuthorization, recordReq, recordRes, dnsProvider, httpUploader);
|
||||
},
|
||||
signal: this.options.signal,
|
||||
|
||||
@@ -27,8 +27,8 @@ export abstract class CertApplyBaseConvertPlugin extends AbstractTaskPlugin {
|
||||
"1、支持多个域名打到一个证书上,例如: foo.com,*.foo.com,*.bar.com\n" +
|
||||
"2、子域名被通配符包含的不要填写,例如:www.foo.com已经被*.foo.com包含,不要填写www.foo.com\n" +
|
||||
"3、泛域名只能通配*号那一级(*.foo.com的证书不能用于xxx.yyy.foo.com、不能用于foo.com)\n" +
|
||||
"4、输入一个,空格之后,再输入下一个\n" +
|
||||
"5、如果你配置了子域托管解析,请先[设置托管子域名](#/certd/pipeline/subDomain)",
|
||||
"4、输入一个,空格之后,再输入下一个 \n" +
|
||||
"5、如果您配置了子域托管解析,请先[设置托管子域名](#/certd/pipeline/subDomain)",
|
||||
})
|
||||
domains!: string[];
|
||||
|
||||
|
||||
@@ -9,8 +9,8 @@ import { CertReader } from "./cert-reader.js";
|
||||
import { CertApplyBasePlugin } from "./base.js";
|
||||
import { GoogleClient } from "../../libs/google.js";
|
||||
import { EabAccess } from "../../access";
|
||||
import { httpChallengeUploaderFactory } from "./uploads/factory.js";
|
||||
import { DomainParser } from "../../dns-provider/domain-parser.js";
|
||||
import { ossClientFactory } from "@certd/plugin-lib";
|
||||
export * from "./base.js";
|
||||
export type { CertInfo };
|
||||
export * from "./cert-reader.js";
|
||||
@@ -68,9 +68,9 @@ export class CertApplyPlugin extends CertApplyBasePlugin {
|
||||
],
|
||||
},
|
||||
required: true,
|
||||
helper: `DNS直接验证:域名是在阿里云/腾讯云/华为云/Cloudflare/NameSilo/西数/火山/dns.la/京东云注册的,选它;
|
||||
CNAME代理验证:支持任何注册商注册的域名,但第一次需要手动添加CNAME记录;
|
||||
HTTP文件验证:不支持泛域名,需要配置网站文件上传`,
|
||||
helper: `1. <b>DNS直接验证</b>:域名dns解析是在阿里云/腾讯云/华为云/CF/NameSilo/西数/火山/dns.la/京东云/51dns的,选它
|
||||
2. <b>CNAME代理验证</b>:支持任何注册商的域名,第一次需要手动添加CNAME记录(建议将DNS服务器修改为阿里云/腾讯云的,然后使用DNS直接验证)
|
||||
3. <b>HTTP文件验证</b>:不支持泛域名,需要配置网站文件上传`,
|
||||
})
|
||||
challengeType!: string;
|
||||
|
||||
@@ -115,6 +115,7 @@ HTTP文件验证:不支持泛域名,需要配置网站文件上传`,
|
||||
})
|
||||
dnsProviderType!: string;
|
||||
|
||||
// dns解析授权类型,勿删
|
||||
dnsProviderAccessType!: string;
|
||||
|
||||
@TaskInput({
|
||||
@@ -289,6 +290,17 @@ HTTP文件验证:不支持泛域名,需要配置网站文件上传`,
|
||||
})
|
||||
maxCheckRetryCount = 20;
|
||||
|
||||
@TaskInput({
|
||||
title: "等待解析生效时长",
|
||||
value: 30,
|
||||
component: {
|
||||
name: "a-input-number",
|
||||
vModel: "value",
|
||||
},
|
||||
helper: "等待解析生效时长(秒)",
|
||||
})
|
||||
waitDnsDiffuseTime = 30;
|
||||
|
||||
acme!: AcmeService;
|
||||
|
||||
eab!: EabAccess;
|
||||
@@ -326,7 +338,7 @@ HTTP文件验证:不支持泛域名,需要配置网站文件上传`,
|
||||
}
|
||||
this.eab = eab;
|
||||
const subDomainsGetter = await this.ctx.serviceGetter.get<ISubDomainsGetter>("subDomainsGetter");
|
||||
const domainParser = new DomainParser(subDomainsGetter);
|
||||
const domainParser = new DomainParser(subDomainsGetter, this.logger);
|
||||
this.acme = new AcmeService({
|
||||
userId: this.ctx.user.id,
|
||||
userContext: this.userContext,
|
||||
@@ -340,6 +352,7 @@ HTTP文件验证:不支持泛域名,需要配置网站文件上传`,
|
||||
signal: this.ctx.signal,
|
||||
maxCheckRetryCount: this.maxCheckRetryCount,
|
||||
domainParser,
|
||||
waitDnsDiffuseTime: this.waitDnsDiffuseTime,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -446,7 +459,7 @@ HTTP文件验证:不支持泛域名,需要配置网站文件上传`,
|
||||
rootDir = rootDir + "/";
|
||||
}
|
||||
this.logger.info("上传方式", httpRecord.httpUploaderType);
|
||||
const httpUploader = await httpChallengeUploaderFactory.createUploaderByType(httpRecord.httpUploaderType, {
|
||||
const httpUploader = await ossClientFactory.createOssClientByType(httpRecord.httpUploaderType, {
|
||||
access,
|
||||
rootDir: rootDir,
|
||||
ctx: httpUploaderContext,
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
import { IAccessService } from "@certd/pipeline";
|
||||
import { ILogger, utils } from "@certd/basic";
|
||||
|
||||
export type HttpChallengeUploader = {
|
||||
upload: (fileName: string, fileContent: Buffer) => Promise<void>;
|
||||
remove: (fileName: string) => Promise<void>;
|
||||
};
|
||||
|
||||
export type HttpChallengeUploadContext = {
|
||||
accessService: IAccessService;
|
||||
logger: ILogger;
|
||||
utils: typeof utils;
|
||||
};
|
||||
|
||||
export abstract class BaseHttpChallengeUploader<A> implements HttpChallengeUploader {
|
||||
rootDir: string;
|
||||
access: A = null;
|
||||
logger: ILogger;
|
||||
utils: typeof utils;
|
||||
ctx: HttpChallengeUploadContext;
|
||||
protected constructor(opts: { rootDir: string; access: A }) {
|
||||
this.rootDir = opts.rootDir;
|
||||
this.access = opts.access;
|
||||
}
|
||||
|
||||
async setCtx(ctx: any) {
|
||||
// set context
|
||||
this.ctx = ctx;
|
||||
this.logger = ctx.logger;
|
||||
this.utils = ctx.utils;
|
||||
}
|
||||
|
||||
abstract remove(fileName: string): Promise<void>;
|
||||
abstract upload(fileName: string, fileContent: Buffer): Promise<void>;
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
import { BaseHttpChallengeUploader } from "../api.js";
|
||||
import { AliossAccess, AliyunAccess } from "@certd/plugin-lib";
|
||||
import { AliossClient } from "@certd/plugin-lib";
|
||||
|
||||
export class AliossHttpChallengeUploader extends BaseHttpChallengeUploader<AliossAccess> {
|
||||
async upload(filePath: string, fileContent: Buffer) {
|
||||
const aliyunAccess = await this.ctx.accessService.getById<AliyunAccess>(this.access.accessId);
|
||||
const client = new AliossClient({
|
||||
access: aliyunAccess,
|
||||
bucket: this.access.bucket,
|
||||
region: this.access.region,
|
||||
});
|
||||
|
||||
const key = this.rootDir + filePath;
|
||||
this.logger.info(`开始上传文件: ${key}`);
|
||||
await client.uploadFile(key, fileContent);
|
||||
|
||||
this.logger.info(`校验文件上传成功: ${filePath}`);
|
||||
}
|
||||
|
||||
async remove(filePath: string) {
|
||||
const key = this.rootDir + filePath;
|
||||
// remove file from alioss
|
||||
const client = await this.getAliossClient();
|
||||
await client.removeFile(key);
|
||||
this.logger.info(`文件删除成功: ${key}`);
|
||||
}
|
||||
|
||||
private async getAliossClient() {
|
||||
const aliyunAccess = await this.ctx.accessService.getById<AliyunAccess>(this.access.accessId);
|
||||
const client = new AliossClient({
|
||||
access: aliyunAccess,
|
||||
bucket: this.access.bucket,
|
||||
region: this.access.region,
|
||||
});
|
||||
await client.init();
|
||||
return client;
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
import { BaseHttpChallengeUploader } from "../api.js";
|
||||
import { FtpAccess, FtpClient } from "@certd/plugin-lib";
|
||||
import path from "path";
|
||||
import os from "os";
|
||||
import fs from "fs";
|
||||
|
||||
export class FtpHttpChallengeUploader extends BaseHttpChallengeUploader<FtpAccess> {
|
||||
async upload(filePath: string, fileContent: Buffer) {
|
||||
const client = new FtpClient({
|
||||
access: this.access,
|
||||
logger: this.logger,
|
||||
});
|
||||
await client.connect(async (client) => {
|
||||
const tmpFilePath = path.join(os.tmpdir(), "cert", "http", filePath);
|
||||
const dir = path.dirname(tmpFilePath);
|
||||
if (!fs.existsSync(dir)) {
|
||||
fs.mkdirSync(dir, { recursive: true });
|
||||
}
|
||||
fs.writeFileSync(tmpFilePath, fileContent);
|
||||
try {
|
||||
// Write file to temp path
|
||||
const path = this.rootDir + filePath;
|
||||
await client.upload(path, tmpFilePath);
|
||||
} finally {
|
||||
// Remove temp file
|
||||
fs.unlinkSync(tmpFilePath);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async remove(filePath: string) {
|
||||
const client = new FtpClient({
|
||||
access: this.access,
|
||||
logger: this.logger,
|
||||
});
|
||||
await client.connect(async (client) => {
|
||||
const path = this.rootDir + filePath;
|
||||
await client.client.remove(path);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
import { BaseHttpChallengeUploader } from "../api.js";
|
||||
import { QiniuOssAccess, QiniuClient, QiniuAccess } from "@certd/plugin-lib";
|
||||
|
||||
export class QiniuOssHttpChallengeUploader extends BaseHttpChallengeUploader<QiniuOssAccess> {
|
||||
async upload(filePath: string, fileContent: Buffer) {
|
||||
const qiniuAccess = await this.ctx.accessService.getById<QiniuAccess>(this.access.accessId);
|
||||
const client = new QiniuClient({
|
||||
access: qiniuAccess,
|
||||
logger: this.logger,
|
||||
http: this.ctx.utils.http,
|
||||
});
|
||||
if (this.rootDir.endsWith("/")) {
|
||||
this.rootDir = this.rootDir.slice(0, -1);
|
||||
}
|
||||
await client.uploadFile(this.access.bucket, this.rootDir + filePath, fileContent);
|
||||
}
|
||||
|
||||
async remove(filePath: string) {
|
||||
const qiniuAccess = await this.ctx.accessService.getById<QiniuAccess>(this.access.accessId);
|
||||
const client = new QiniuClient({
|
||||
access: qiniuAccess,
|
||||
logger: this.logger,
|
||||
http: this.ctx.utils.http,
|
||||
});
|
||||
|
||||
if (this.rootDir.endsWith("/")) {
|
||||
this.rootDir = this.rootDir.slice(0, -1);
|
||||
}
|
||||
await client.removeFile(this.access.bucket, this.rootDir + filePath);
|
||||
}
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
import { BaseHttpChallengeUploader } from "../api.js";
|
||||
import { SshAccess, SshClient } from "@certd/plugin-lib";
|
||||
import path from "path";
|
||||
import os from "os";
|
||||
import fs from "fs";
|
||||
import { SftpAccess } from "@certd/plugin-lib";
|
||||
|
||||
export class SftpHttpChallengeUploader extends BaseHttpChallengeUploader<SftpAccess> {
|
||||
async upload(filePath: string, fileContent: Buffer) {
|
||||
const tmpFilePath = path.join(os.tmpdir(), "cert", "http", filePath);
|
||||
|
||||
// Write file to temp path
|
||||
const dir = path.dirname(tmpFilePath);
|
||||
if (!fs.existsSync(dir)) {
|
||||
fs.mkdirSync(dir, { recursive: true });
|
||||
}
|
||||
fs.writeFileSync(tmpFilePath, fileContent);
|
||||
|
||||
const access = await this.ctx.accessService.getById<SshAccess>(this.access.sshAccess);
|
||||
const key = this.rootDir + filePath;
|
||||
try {
|
||||
const client = new SshClient(this.logger);
|
||||
await client.uploadFiles({
|
||||
connectConf: access,
|
||||
mkdirs: true,
|
||||
transports: [
|
||||
{
|
||||
localPath: tmpFilePath,
|
||||
remotePath: key,
|
||||
},
|
||||
],
|
||||
opts: {
|
||||
mode: this.access?.fileMode ?? undefined,
|
||||
},
|
||||
});
|
||||
} finally {
|
||||
// Remove temp file
|
||||
fs.unlinkSync(tmpFilePath);
|
||||
}
|
||||
}
|
||||
|
||||
async remove(filePath: string) {
|
||||
const access = await this.ctx.accessService.getById<SshAccess>(this.access.sshAccess);
|
||||
const client = new SshClient(this.logger);
|
||||
const key = this.rootDir + filePath;
|
||||
await client.removeFiles({
|
||||
connectConf: access,
|
||||
files: [key],
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
import { BaseHttpChallengeUploader } from "../api.js";
|
||||
import { TencentAccess, TencentCosAccess, TencentCosClient } from "@certd/plugin-lib";
|
||||
|
||||
export class TencentCosHttpChallengeUploader extends BaseHttpChallengeUploader<TencentCosAccess> {
|
||||
async upload(filePath: string, fileContent: Buffer) {
|
||||
const access = await this.ctx.accessService.getById<TencentAccess>(this.access.accessId);
|
||||
const client = new TencentCosClient({
|
||||
access: access,
|
||||
logger: this.logger,
|
||||
region: this.access.region,
|
||||
bucket: this.access.bucket,
|
||||
});
|
||||
const key = this.rootDir + filePath;
|
||||
await client.uploadFile(key, fileContent);
|
||||
}
|
||||
|
||||
async remove(filePath: string) {
|
||||
const access = await this.ctx.accessService.getById<TencentAccess>(this.access.accessId);
|
||||
const client = new TencentCosClient({
|
||||
access: access,
|
||||
logger: this.logger,
|
||||
region: this.access.region,
|
||||
bucket: this.access.bucket,
|
||||
});
|
||||
const key = this.rootDir + filePath;
|
||||
await client.removeFile(key);
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,56 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.34.2](https://github.com/certd/certd/compare/v1.34.1...v1.34.2) (2025-05-11)
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* http方式支持校验443端口 ([d75fcb7](https://github.com/certd/certd/commit/d75fcb7fec421a9a638eaa27fe9378c84b5e0f19))
|
||||
|
||||
## [1.34.1](https://github.com/certd/certd/compare/v1.34.0...v1.34.1) (2025-05-05)
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 支持部署证书到火山dcdn ([5f85219](https://github.com/certd/certd/commit/5f852194953dc1b4e6336770f417507b8f5a33ad))
|
||||
|
||||
# [1.34.0](https://github.com/certd/certd/compare/v1.33.8...v1.34.0) (2025-04-28)
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 优化cdnfly插件,支持自动匹配域名部署 ([afd59e9](https://github.com/certd/certd/commit/afd59e9933b2650f41c5d47684c171b93b962065))
|
||||
|
||||
## [1.33.8](https://github.com/certd/certd/compare/v1.33.7...v1.33.8) (2025-04-26)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 修复http上传方式无法清除记录文件的bug ([72a7b51](https://github.com/certd/certd/commit/72a7b51d479602b2c54c6c3ac8d8a0dcb9664e73))
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 七牛oss支持删除过期备份 ([b7113bd](https://github.com/certd/certd/commit/b7113bda2378116d6c116dc583f563cce7cf9f00))
|
||||
* 数据库备份支持oss ([308d460](https://github.com/certd/certd/commit/308d4600efe2002f199c33b4594d3071784e58ea))
|
||||
|
||||
## [1.33.7](https://github.com/certd/certd/compare/v1.33.6...v1.33.7) (2025-04-22)
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* ssh PTY模式登录设置 ([8385bcc](https://github.com/certd/certd/commit/8385bcc2d7f2411a07748bb5c53f9eaf4d38d7cc))
|
||||
* ssh伪终端模式优化,windows下不开启 ([42dfe93](https://github.com/certd/certd/commit/42dfe936b773b7bdd82ca3378363252ffffd7b71))
|
||||
|
||||
## [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
|
||||
|
||||
## [1.33.4](https://github.com/certd/certd/compare/v1.33.3...v1.33.4) (2025-04-15)
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 插件支持导入导出 ([cf8abb4](https://github.com/certd/certd/commit/cf8abb45282070c8ba91469f93fd379fabf1f74a))
|
||||
|
||||
## [1.33.3](https://github.com/certd/certd/compare/v1.33.2...v1.33.3) (2025-04-14)
|
||||
|
||||
**Note:** Version bump only for package @certd/plugin-lib
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@certd/plugin-lib",
|
||||
"private": false,
|
||||
"version": "1.33.3",
|
||||
"version": "1.34.2",
|
||||
"type": "module",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
@@ -12,14 +12,16 @@
|
||||
"dev-build": "npm run build",
|
||||
"build3": "rollup -c",
|
||||
"build2": "vue-tsc --noEmit && vite build",
|
||||
"preview": "vite preview"
|
||||
"preview": "vite preview",
|
||||
"pub": "npm publish"
|
||||
},
|
||||
"dependencies": {
|
||||
"@alicloud/pop-core": "^1.7.10",
|
||||
"@certd/basic": "^1.33.3",
|
||||
"@certd/pipeline": "^1.33.3",
|
||||
"@aws-sdk/client-s3": "^3.787.0",
|
||||
"@certd/basic": "^1.34.2",
|
||||
"@certd/pipeline": "^1.34.2",
|
||||
"@kubernetes/client-node": "0.21.0",
|
||||
"ali-oss": "^6.21.0",
|
||||
"ali-oss": "^6.22.0",
|
||||
"basic-ftp": "^5.0.5",
|
||||
"cos-nodejs-sdk-v5": "^2.14.6",
|
||||
"dayjs": "^1.11.7",
|
||||
@@ -48,5 +50,5 @@
|
||||
"tslib": "^2.8.1",
|
||||
"typescript": "^5.4.2"
|
||||
},
|
||||
"gitHead": "be69244e8ddb757de45c7e2b6033195c1f5a6910"
|
||||
"gitHead": "6c74148c277432f91014bf1eebd824e7423c6f4b"
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import { IsAccess, AccessInput, BaseAccess } from "@certd/pipeline";
|
||||
title: "阿里云授权",
|
||||
desc: "",
|
||||
icon: "ant-design:aliyun-outlined",
|
||||
order: 0,
|
||||
})
|
||||
export class AliyunAccess extends BaseAccess {
|
||||
@AccessInput({
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { AliyunAccess } from "../access";
|
||||
import { AliyunAccess } from "../access/index.js";
|
||||
|
||||
export class AliossClient {
|
||||
access: AliyunAccess;
|
||||
@@ -52,13 +52,36 @@ export class AliossClient {
|
||||
}
|
||||
}
|
||||
|
||||
async uploadFile(filePath: string, content: Buffer) {
|
||||
async uploadFile(filePath: string, content: Buffer | string, timeout = 1000 * 60 * 60) {
|
||||
await this.init();
|
||||
return await this.client.put(filePath, content);
|
||||
return await this.client.put(filePath, content, {
|
||||
timeout,
|
||||
});
|
||||
}
|
||||
|
||||
async removeFile(filePath: string) {
|
||||
await this.init();
|
||||
return await this.client.delete(filePath);
|
||||
}
|
||||
|
||||
async downloadFile(key: string, savePath: string, timeout = 1000 * 60 * 60) {
|
||||
await this.init();
|
||||
return await this.client.get(key, savePath, {
|
||||
timeout,
|
||||
});
|
||||
}
|
||||
|
||||
async listDir(dirKey: string) {
|
||||
await this.init();
|
||||
const res = await this.client.listV2({
|
||||
prefix: dirKey,
|
||||
// max-keys: 100,
|
||||
// continuation-token: "token",
|
||||
// delimiter: "/",
|
||||
// marker: "marker",
|
||||
// encoding-type: "url",
|
||||
});
|
||||
|
||||
return res.objects;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,6 +37,7 @@ export function createRemoteSelectInputDefine(opts?: {
|
||||
multi?: boolean;
|
||||
required?: boolean;
|
||||
rules?: any;
|
||||
mergeScript?: string;
|
||||
}) {
|
||||
const title = opts?.title || "请选择";
|
||||
const certDomainsInputKey = opts?.certDomainsInputKey || "certDomains";
|
||||
@@ -65,8 +66,10 @@ export function createRemoteSelectInputDefine(opts?: {
|
||||
watches: [certDomainsInputKey, accessIdInputKey, ...watches],
|
||||
},
|
||||
rules: opts?.rules,
|
||||
required: true,
|
||||
mergeScript: `
|
||||
required: opts.required ?? true,
|
||||
mergeScript:
|
||||
opts.mergeScript ??
|
||||
`
|
||||
return {
|
||||
component:{
|
||||
form: ctx.compute(({form})=>{
|
||||
@@ -80,3 +83,5 @@ export function createRemoteSelectInputDefine(opts?: {
|
||||
|
||||
return merge(item, opts?.formItem);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ export class FtpClient {
|
||||
this.logger = opts.logger;
|
||||
}
|
||||
|
||||
async connect(callback: (client: FtpClient) => Promise<void>) {
|
||||
async connect(callback: (client: FtpClient) => Promise<any>) {
|
||||
const ftp = await import("basic-ftp");
|
||||
const Client = ftp.Client;
|
||||
const client = new Client();
|
||||
@@ -21,7 +21,7 @@ export class FtpClient {
|
||||
this.logger.info("FTP连接成功");
|
||||
this.client = client;
|
||||
try {
|
||||
await callback(this);
|
||||
return await callback(this);
|
||||
} finally {
|
||||
if (client) {
|
||||
client.close();
|
||||
@@ -44,4 +44,20 @@ export class FtpClient {
|
||||
this.logger.info(`开始删除文件${filePath}`);
|
||||
await this.client.remove(filePath, true);
|
||||
}
|
||||
|
||||
async listDir(dir: string): Promise<any[]> {
|
||||
if (!dir) {
|
||||
return [];
|
||||
}
|
||||
if (!dir.endsWith("/")) {
|
||||
dir = dir + "/";
|
||||
}
|
||||
this.logger.info(`开始列出目录${dir}`);
|
||||
return await this.client.list(dir);
|
||||
}
|
||||
|
||||
async download(filePath: string, savePath: string): Promise<void> {
|
||||
this.logger.info(`开始下载文件${filePath} -> ${savePath}`);
|
||||
await this.client.downloadTo(savePath, filePath);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,3 +5,5 @@ export * from "./ftp/index.js";
|
||||
export * from "./tencent/index.js";
|
||||
export * from "./qiniu/index.js";
|
||||
export * from "./ctyun/index.js";
|
||||
export * from "./oss/index.js";
|
||||
export * from "./s3/index.js";
|
||||
|
||||