mirror of
https://github.com/certd/certd.git
synced 2026-04-04 15:00:54 +08:00
Compare commits
85 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
85ca850453 | ||
|
|
3baefb2b60 | ||
|
|
ffea5a0e02 | ||
|
|
be55695691 | ||
|
|
ea27c96362 | ||
|
|
7a73a01999 | ||
|
|
018dee6c38 | ||
|
|
c7cf2e6f16 | ||
|
|
9ab9a6e8b0 | ||
|
|
67ccff3e86 | ||
|
|
40c09ce26a | ||
|
|
3e0d4a0bed | ||
|
|
e8a6d38ac6 | ||
|
|
80159ecca8 | ||
|
|
c82bb730b2 | ||
|
|
26dad399d5 | ||
|
|
2689e6d6c0 | ||
|
|
90d1b68bd6 | ||
|
|
c7c4318c11 | ||
|
|
c6488b58f5 | ||
|
|
18bfcc24ad | ||
|
|
d8a134fe7e | ||
|
|
989f48c47a | ||
|
|
111a32b5e8 | ||
|
|
993ca754b5 | ||
|
|
381a37fbaa | ||
|
|
0ca61b4d99 | ||
|
|
16748a75d5 | ||
|
|
0e33dfa019 | ||
|
|
4a2f7ebf87 | ||
|
|
e9f18b79ea | ||
|
|
66629a591a | ||
|
|
8f22a358cf | ||
|
|
1f5f1596e5 | ||
|
|
339554bdbf | ||
|
|
9b6b614857 | ||
|
|
e6e99d4239 | ||
|
|
f4ae5125dc | ||
|
|
c3cfbd8474 | ||
|
|
86dd03c917 | ||
|
|
6410e34bf3 | ||
|
|
2db7fee745 | ||
|
|
4e8908e715 | ||
|
|
67d8020147 | ||
|
|
b4b9f33b2c | ||
|
|
d091703dc0 | ||
|
|
509b5291c3 | ||
|
|
111a0823e9 | ||
|
|
48bc7a45a9 | ||
|
|
1eb70d4cfd | ||
|
|
eae63b7c57 | ||
|
|
ec0862f99e | ||
|
|
79ca6f4acb | ||
|
|
66a9690dc9 | ||
|
|
01c65578b0 | ||
|
|
dd462989b5 | ||
|
|
da6ac1626b | ||
|
|
a38ff69cbd | ||
|
|
70db327eda | ||
|
|
8c3f86c690 | ||
|
|
b66542cb40 | ||
|
|
873ad871da | ||
|
|
889eaaea92 | ||
|
|
d2ce72e4aa | ||
|
|
bcfac02c96 | ||
|
|
60a2ed48c2 | ||
|
|
087c0b8253 | ||
|
|
a9a0967a6f | ||
|
|
7bbaa3806b | ||
|
|
7f910a13d5 | ||
|
|
6841c2328e | ||
|
|
ae072929df | ||
|
|
5d756eb54b | ||
|
|
9fe5d6655c | ||
|
|
37b5b22713 | ||
|
|
ee731e4759 | ||
|
|
0dbe3133cf | ||
|
|
843219c38b | ||
|
|
810d5f3c1f | ||
|
|
4a5bd0db05 | ||
|
|
0120e4d1f5 | ||
|
|
d199a18a91 | ||
|
|
ffc0981fbc | ||
|
|
27ca9b027b | ||
|
|
b0ff699b31 |
22
.github/workflows/build-image.yml
vendored
22
.github/workflows/build-image.yml
vendored
@@ -79,17 +79,17 @@ jobs:
|
||||
greper/certd:latest
|
||||
greper/certd:${{steps.get_certd_version.outputs.result}}
|
||||
|
||||
- name: Build armv7
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
platforms: linux/arm/v7
|
||||
push: true
|
||||
context: ./packages/ui/
|
||||
tags: |
|
||||
registry.cn-shenzhen.aliyuncs.com/handsfree/certd:armv7
|
||||
registry.cn-shenzhen.aliyuncs.com/handsfree/certd:${{steps.get_certd_version.outputs.result}}-armv7
|
||||
greper/certd:armv7
|
||||
greper/certd:${{steps.get_certd_version.outputs.result}}-armv7
|
||||
# - name: Build armv7
|
||||
# uses: docker/build-push-action@v6
|
||||
# with:
|
||||
# platforms: linux/arm/v7
|
||||
# push: true
|
||||
# context: ./packages/ui/
|
||||
# tags: |
|
||||
# registry.cn-shenzhen.aliyuncs.com/handsfree/certd:armv7
|
||||
# registry.cn-shenzhen.aliyuncs.com/handsfree/certd:${{steps.get_certd_version.outputs.result}}-armv7
|
||||
# greper/certd:armv7
|
||||
# greper/certd:${{steps.get_certd_version.outputs.result}}-armv7
|
||||
|
||||
- name: Build agent
|
||||
uses: docker/build-push-action@v6
|
||||
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -29,3 +29,5 @@ test/**/*.js
|
||||
/packages/ui/certd-server/data/db.sqlite
|
||||
/packages/ui/certd-server/data/keys.yaml
|
||||
/packages/pro/
|
||||
|
||||
test.js
|
||||
2
.npmrc
2
.npmrc
@@ -1,2 +1,2 @@
|
||||
link-workspace-packages=true
|
||||
link-workspace-packages=deep
|
||||
prefer-workspace-packages=true
|
||||
|
||||
53
CHANGELOG.md
53
CHANGELOG.md
@@ -3,6 +3,59 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.27.6](https://github.com/certd/certd/compare/v1.27.5...v1.27.6) (2024-11-19)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* .env 读取 \r 问题 ([0e33dfa](https://github.com/certd/certd/commit/0e33dfa019a55ea76193c428ec756af386adeb9d))
|
||||
* 修复vip试用secret报错的bug ([018dee6](https://github.com/certd/certd/commit/018dee6c383233560f078dfd30f6c2857a7e15ee))
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 当步骤全部都禁用时,任务本身显示删除线 ([9ab9a6e](https://github.com/certd/certd/commit/9ab9a6e8b083e19793894f23e59f29c604ec98e5))
|
||||
|
||||
## [1.27.5](https://github.com/certd/certd/compare/v1.27.4...v1.27.5) (2024-11-18)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 修复1Panel面板本身证书更新导致判定执行失败的问题 ([2689e6d](https://github.com/certd/certd/commit/2689e6d6c03aba21da90d5d45232c6ba08696be1))
|
||||
* 修复角色无法删除的bug ([66629a5](https://github.com/certd/certd/commit/66629a591aecc2d8364ea415c7afc3f9d0406562))
|
||||
* 修复Cname情况下,无法使用DNS类型的bug ([26dad39](https://github.com/certd/certd/commit/26dad399d5768b3205da099ddc11809aef7d6224))
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 日志查看自动滚动到底部 ([4a2f7eb](https://github.com/certd/certd/commit/4a2f7ebf87b7c027cebff7cb763f8f35f6d2aa36))
|
||||
* 系统设置中的代理设置优化为可全局生效,环境变量中的https_proxy设置将无效 ([381a37f](https://github.com/certd/certd/commit/381a37fbaa6b61c887eda743897ae00afb825bdf))
|
||||
* 新手导航在非编辑模式下不显示 ([18bfcc2](https://github.com/certd/certd/commit/18bfcc24ad0bde57bb04db8a4209861ec6b8ff1d))
|
||||
* 优化腾讯云 cloudflare 重复解析记录时的返回值 ([90d1b68](https://github.com/certd/certd/commit/90d1b68bd6cf232fbe085234efe07d29b7690044))
|
||||
* 支持namesilo ([80159ec](https://github.com/certd/certd/commit/80159ecca895103d0495f3217311199e66056572))
|
||||
* 专业版试用,无需绑定账号 ([c7c4318](https://github.com/certd/certd/commit/c7c4318c11b65a76089787aa58939832d338a232))
|
||||
|
||||
## [1.27.4](https://github.com/certd/certd/compare/v1.27.3...v1.27.4) (2024-11-14)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 修复未设置pfx密码,导致jks转换报错的bug ([c3cfbd8](https://github.com/certd/certd/commit/c3cfbd8474155aed4379f91075de37d5d8c73ef0))
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 公共cname服务支持关闭 ([f4ae512](https://github.com/certd/certd/commit/f4ae5125dc4cd97816976779cb3586b5ee78947e))
|
||||
|
||||
## [1.27.3](https://github.com/certd/certd/compare/v1.27.2...v1.27.3) (2024-11-13)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 修复偶发性cname一直验证超时的bug ([d2ce72e](https://github.com/certd/certd/commit/d2ce72e4aaacdf726ba8b91fcd71db40a27714ba))
|
||||
* 修复邮件配置,忽略证书校验设置不生效的bug ([66a9690](https://github.com/certd/certd/commit/66a9690dc958732e1b3c672d965db502296446f9))
|
||||
* 修复ipv6未开启情况下,请求带有ipv6地址域名报ETIMEDOUT的bug ([a9a0967](https://github.com/certd/certd/commit/a9a0967a6f1d0bd27e69f3ec52c31d90d470bc23))
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 修复站点个性化,浏览器标题没有生效的bug ([bcfac02](https://github.com/certd/certd/commit/bcfac02c96ceaf23d1a0b05b48d8047da933beaf))
|
||||
* 优化上传到主机插 路径选择,根据证书格式显示 ([8c3f86c](https://github.com/certd/certd/commit/8c3f86c6909ed91f48bb2880e78834e22f6f6a29))
|
||||
* 支持jks ([889eaae](https://github.com/certd/certd/commit/889eaaea92818f628b922dae540c026630611707))
|
||||
* ipv6支持 ([da6ac16](https://github.com/certd/certd/commit/da6ac1626b3574be2fabeeb18a1f10d60bdcbe49))
|
||||
|
||||
## [1.27.2](https://github.com/certd/certd/compare/v1.27.1...v1.27.2) (2024-11-08)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
13
README.md
13
README.md
@@ -10,7 +10,7 @@ Certd 是一个免费全自动申请和自动部署更新SSL证书的管理系
|
||||
|
||||
* 全自动申请证书(支持所有注册商注册的域名)
|
||||
* 全自动部署更新证书(目前支持部署到主机、部署到阿里云、腾讯云等,目前已支持30+部署插件)
|
||||
* 支持通配符域名/泛域名,支持多个域名打到一个证书上
|
||||
* 支持通配符域名/泛域名,支持多个域名打到一个证书上,支持pem、pfx、der、jks等多种证书格式
|
||||
* 邮件通知
|
||||
* 私有化部署,数据保存本地,镜像由Github Actions构建,过程公开透明
|
||||
* 支持sqlite,postgresql数据库
|
||||
@@ -22,7 +22,7 @@ Certd 是一个免费全自动申请和自动部署更新SSL证书的管理系
|
||||
|
||||
官方Demo地址,自助注册后体验
|
||||
|
||||
https://certd.handsfree.work/
|
||||
https://certd.handfree.work/
|
||||
|
||||
> 注意数据将不定期清理,不定期停止定时任务,生产使用请自行部署
|
||||
> 包含敏感信息,务必自己本地部署进行生产使用
|
||||
@@ -41,9 +41,12 @@ https://certd.handsfree.work/
|
||||
### 2. 添加部署任务
|
||||
当然我们一般需要把证书部署到应用上,certd支持海量的部署插件,您可以根据自身实际情况进行选择,比如部署到Nginx、阿里云、腾讯云、K8S、CDN、宝塔、1Panel等等
|
||||
|
||||
此处演示部署证书到主机的nginx上
|
||||
此处演示部署证书到主机的nginx上
|
||||

|
||||
|
||||
如果目前的部署插件都无法满足,您也可以手动下载,然后自行部署
|
||||

|
||||
|
||||
### 3. 定时运行
|
||||

|
||||
|
||||
@@ -112,7 +115,7 @@ docker compose up -d
|
||||
* 实际上没有办法不改变证书文件本身情况下直接续期或者续签。
|
||||
* 我们所说的续期,其实就是按照全套流程重新申请一份新证书,然后重新部署上去。
|
||||
* 免费证书过期时间90天,以后可能还会缩短,所以自动化部署必不可少
|
||||
* 设置每天自动运行,当证书过期前20天,会自动重新申请证书并部署
|
||||
* 设置每天自动运行,当证书过期前35天,会自动重新申请证书并部署
|
||||
|
||||
|
||||
## 七、不同平台的设置说明
|
||||
@@ -163,7 +166,7 @@ https://afdian.com/a/greper
|
||||
|
||||
## 十一、贡献代码
|
||||
|
||||
1. 本地开发 [贡献插件教程](https://certd.docmirror.cn/guide/development/)
|
||||
1. 本地开发 [贡献插件](https://certd.docmirror.cn/guide/development/)
|
||||
2. 作为贡献者,代表您同意您贡献的代码如下许可:
|
||||
1. 可以调整开源协议以使其更严格或更宽松。
|
||||
2. 可以用于商业用途。
|
||||
|
||||
@@ -1 +1 @@
|
||||
1
|
||||
22:02
|
||||
|
||||
@@ -11,35 +11,44 @@ services:
|
||||
ports: # 端口映射
|
||||
# ↓↓↓↓ ---------------------------------------------------------- 如果端口有冲突,可以修改第一个7001为其他不冲突的端口号
|
||||
- "7001:7001"
|
||||
# ↓↓↓↓ ---------------------------------------------------------- https端口,可以根据实际情况,是否暴露相关服务端口
|
||||
# ↓↓↓↓ ---------------------------------------------------------- https端口,可以根据实际情况,是否暴露该端口
|
||||
- "7002:7002"
|
||||
#↓↓↓↓ -------------------------------------------------------------- 如果出现getaddrinfo ENOTFOUND错误,可以尝试设置dns
|
||||
dns:
|
||||
# ↓↓↓↓ ---------------------------------------------------------- 如果出现getaddrinfo ENOTFOUND等错误,可以尝试修改或注释dns配置
|
||||
- 223.5.5.5
|
||||
- 223.5.5.5 # 阿里云公共dns
|
||||
- 223.6.6.6
|
||||
# ↓↓↓↓ ---------------------------------------------------------- 如果你服务器在腾讯云,可以用这个dns地址
|
||||
# - 119.29.29.29
|
||||
# - 182.254.116.116
|
||||
# ↓↓↓↓ ---------------------------------------------------------- 如果你服务器部署在国外,可以用8.8.8.8替换上面的dns
|
||||
# - 8.8.8.8
|
||||
# - 8.8.4.4
|
||||
# # ↓↓↓↓ --------------------------------------------------------- 如果你服务器在腾讯云,可以用这个替换上面阿里云的公共dns
|
||||
# - 119.29.29.29 # 腾讯云公共dns
|
||||
# - 182.254.116.116
|
||||
# # ↓↓↓↓ --------------------------------------------------------- 如果你服务器部署在国外,可以用这个替换上面阿里云的公共dns
|
||||
# - 8.8.8.8 # 谷歌公共dns
|
||||
# - 8.8.4.4
|
||||
|
||||
# extra_hosts:
|
||||
# ↓↓↓↓ ---------------------------------------------------------- 这里可以配置自定义hosts,外网域名可以指向本地局域网ip地址
|
||||
# # ↓↓↓↓ -------------------------------------------------------- 这里可以配置自定义hosts,外网域名可以指向本地局域网ip地址
|
||||
# - "localdomain.comm:192.168.1.3"
|
||||
|
||||
environment:
|
||||
- TZ=Asia/Shanghai
|
||||
# 设置环境变量即可自定义certd配置
|
||||
# 配置项见: packages/ui/certd-server/src/config/config.default.ts
|
||||
# 配置规则: certd_ + 配置项, 点号用_代替
|
||||
# ↓↓↓↓ ----------------------------- 如果忘记管理员密码,可以设置为true,重启之后,管理员密码将改成123456,然后请及时修改回false
|
||||
# 设置环境变量即可自定义certd配置
|
||||
# 配置项见: packages/ui/certd-server/src/config/config.default.ts
|
||||
# 配置规则: certd_ + 配置项, 点号用_代替
|
||||
# #↓↓↓↓ ----------------------------- 如果忘记管理员密码,可以设置为true,重启之后,管理员密码将改成123456,然后请及时修改回false
|
||||
- certd_system_resetAdminPasswd=false
|
||||
# ↓↓↓↓ ------------------------------- 使用postgresql数据库
|
||||
# - certd_flyway_scriptDir=./db/migration-pg # 升级脚本目录
|
||||
# - certd_typeorm_dataSource_default_type=postgres # 数据库类型
|
||||
# - certd_typeorm_dataSource_default_host=localhost # 数据库地址
|
||||
# - certd_typeorm_dataSource_default_port=5433 # 数据库端口
|
||||
# - certd_typeorm_dataSource_default_username=postgres # 用户名
|
||||
# - certd_typeorm_dataSource_default_password=yourpasswd # 密码
|
||||
# - certd_typeorm_dataSource_default_database=certd # 数据库名
|
||||
|
||||
# #↓↓↓↓ ----------------------------- 使用postgresql数据库
|
||||
# - certd_flyway_scriptDir=./db/migration-pg # 升级脚本目录
|
||||
# - certd_typeorm_dataSource_default_type=postgres # 数据库类型
|
||||
# - certd_typeorm_dataSource_default_host=localhost # 数据库地址
|
||||
# - certd_typeorm_dataSource_default_port=5433 # 数据库端口
|
||||
# - certd_typeorm_dataSource_default_username=postgres # 用户名
|
||||
# - certd_typeorm_dataSource_default_password=yourpasswd # 密码
|
||||
# - certd_typeorm_dataSource_default_database=certd # 数据库名
|
||||
|
||||
# #↓↓↓↓ ------------------------------------------------------------- 启用ipv6网络
|
||||
# networks:
|
||||
# - ip6net
|
||||
#networks:
|
||||
# ip6net:
|
||||
# enable_ipv6: true
|
||||
# ipam:
|
||||
# config:
|
||||
# - subnet: 2001:db8::/64
|
||||
|
||||
@@ -57,7 +57,7 @@ export default defineConfig({
|
||||
nav: [
|
||||
{ text: "首页", link: "/" },
|
||||
{ text: "指南", link: "/guide/" },
|
||||
{ text: "Demo体验", link: "https://certd.handsfree.work" }
|
||||
{ text: "Demo体验", link: "https://certd.handfree.work" }
|
||||
],
|
||||
sidebar: {
|
||||
"/guide/": [
|
||||
@@ -100,6 +100,7 @@ export default defineConfig({
|
||||
{ text: "Certd本身的证书更新", link: "/guide/use/https/index.md" },
|
||||
{ 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: "/guide/development/index.md" },
|
||||
]
|
||||
},
|
||||
|
||||
@@ -3,6 +3,63 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.27.5](https://github.com/certd/certd/compare/v1.27.4...v1.27.5) (2024-11-18)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 修复1Panel面板本身证书更新导致判定执行失败的问题 ([2689e6d](https://github.com/certd/certd/commit/2689e6d6c03aba21da90d5d45232c6ba08696be1))
|
||||
* 修复角色无法删除的bug ([66629a5](https://github.com/certd/certd/commit/66629a591aecc2d8364ea415c7afc3f9d0406562))
|
||||
* 修复Cname情况下,无法使用DNS类型的bug ([26dad39](https://github.com/certd/certd/commit/26dad399d5768b3205da099ddc11809aef7d6224))
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 日志查看自动滚动到底部 ([4a2f7eb](https://github.com/certd/certd/commit/4a2f7ebf87b7c027cebff7cb763f8f35f6d2aa36))
|
||||
* 系统设置中的代理设置优化为可全局生效,环境变量中的https_proxy设置将无效 ([381a37f](https://github.com/certd/certd/commit/381a37fbaa6b61c887eda743897ae00afb825bdf))
|
||||
* 新手导航在非编辑模式下不显示 ([18bfcc2](https://github.com/certd/certd/commit/18bfcc24ad0bde57bb04db8a4209861ec6b8ff1d))
|
||||
* 优化腾讯云 cloudflare 重复解析记录时的返回值 ([90d1b68](https://github.com/certd/certd/commit/90d1b68bd6cf232fbe085234efe07d29b7690044))
|
||||
* 支持namesilo ([80159ec](https://github.com/certd/certd/commit/80159ecca895103d0495f3217311199e66056572))
|
||||
* 专业版试用,无需绑定账号 ([c7c4318](https://github.com/certd/certd/commit/c7c4318c11b65a76089787aa58939832d338a232))
|
||||
|
||||
## [1.27.4](https://github.com/certd/certd/compare/v1.27.3...v1.27.4) (2024-11-14)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 修复未设置pfx密码,导致jks转换报错的bug ([c3cfbd8](https://github.com/certd/certd/commit/c3cfbd8474155aed4379f91075de37d5d8c73ef0))
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 公共cname服务支持关闭 ([f4ae512](https://github.com/certd/certd/commit/f4ae5125dc4cd97816976779cb3586b5ee78947e))
|
||||
|
||||
## [1.27.3](https://github.com/certd/certd/compare/v1.27.2...v1.27.3) (2024-11-13)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 修复偶发性cname一直验证超时的bug ([d2ce72e](https://github.com/certd/certd/commit/d2ce72e4aaacdf726ba8b91fcd71db40a27714ba))
|
||||
* 修复邮件配置,忽略证书校验设置不生效的bug ([66a9690](https://github.com/certd/certd/commit/66a9690dc958732e1b3c672d965db502296446f9))
|
||||
* 修复ipv6未开启情况下,请求带有ipv6地址域名报ETIMEDOUT的bug ([a9a0967](https://github.com/certd/certd/commit/a9a0967a6f1d0bd27e69f3ec52c31d90d470bc23))
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 修复站点个性化,浏览器标题没有生效的bug ([bcfac02](https://github.com/certd/certd/commit/bcfac02c96ceaf23d1a0b05b48d8047da933beaf))
|
||||
* 优化上传到主机插 路径选择,根据证书格式显示 ([8c3f86c](https://github.com/certd/certd/commit/8c3f86c6909ed91f48bb2880e78834e22f6f6a29))
|
||||
* 支持jks ([889eaae](https://github.com/certd/certd/commit/889eaaea92818f628b922dae540c026630611707))
|
||||
* ipv6支持 ([da6ac16](https://github.com/certd/certd/commit/da6ac1626b3574be2fabeeb18a1f10d60bdcbe49))
|
||||
|
||||
## [1.27.2](https://github.com/certd/certd/compare/v1.27.1...v1.27.2) (2024-11-08)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 修复某些容器管理ui无法识别端口列表的bug ([576e60a](https://github.com/certd/certd/commit/576e60a2b52315909e659d2a58cf98b130e69e6f))
|
||||
* 修复删除腾讯云过期证书时间判断上的bug,导致已过期仍然没有删除证书 ([1ba1007](https://github.com/certd/certd/commit/1ba10072615015d91b81fc56a3b01dae6a2ae9d1))
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 优化部署到阿里云CDN插件,支持多域名,更易用 ([80c500f](https://github.com/certd/certd/commit/80c500f618b169a1f64c57fe442242a4d0d9d833))
|
||||
* 优化流水线页面切换回来不丢失查询条件 ([4dcf6e8](https://github.com/certd/certd/commit/4dcf6e87bc5f7657ce8a56c5331e8723a0fee8ee))
|
||||
* 支持公共cname服务 ([3c919ee](https://github.com/certd/certd/commit/3c919ee5d1aef5d26cf3620a7c49d920786bc941))
|
||||
* 执行历史支持点击查看流水线详情 ([8968639](https://github.com/certd/certd/commit/89686399f90058835435b92872fc236fac990148))
|
||||
* 专业版7天试用 ([c58250e](https://github.com/certd/certd/commit/c58250e1f065a9bd8b4e82acc1df754504c0010c))
|
||||
|
||||
## [1.27.1](https://github.com/certd/certd/compare/v1.27.0...v1.27.1) (2024-11-04)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
# 本地开发
|
||||
欢迎贡献插件
|
||||
|
||||
## 1.本地调试运行
|
||||
建议nodejs版本 `20.x` 及以上
|
||||
|
||||
## 一、本地调试运行
|
||||
|
||||
### 克隆代码
|
||||
```shell
|
||||
@@ -55,7 +57,7 @@ npm run dev
|
||||
|
||||
```
|
||||
|
||||
## 开发插件
|
||||
## 二、开发插件
|
||||
进入 `packages/ui/certd-server/src/plugins`
|
||||
|
||||
### 1.复制`plugin-demo`目录作为你的插件目录
|
||||
@@ -89,8 +91,22 @@ export * from './plugins/plugin-deploy-to-xx'
|
||||
export * from "./plugin-cloudflare.js"
|
||||
```
|
||||
|
||||
## 重启服务进行调试
|
||||
### 6. 重启服务进行调试
|
||||
刷新浏览器,检查你的插件是否工作正常, 确保能够正常进行证书申请和部署
|
||||
|
||||
## 提交PR
|
||||
## 三、提交PR
|
||||
我们将尽快审核PR
|
||||
|
||||
## 四、 注意事项
|
||||
### 1. 如何让任务报错停止
|
||||
|
||||
```js
|
||||
// 抛出异常即可使任务停止,否则会判定为成功
|
||||
throw new Error("错误信息")
|
||||
```
|
||||
|
||||
|
||||
## 五、贡献插件送激活码
|
||||
|
||||
- PR要求,插件功能完整,代码规范
|
||||
- PR通过后,联系我们,送您一个专业版激活码
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
## 2. 原理
|
||||
* 假设你要申请证书的域名叫:`cert.com` ,它是在`Certd`不支持的服务商注册的
|
||||
* 假设你还有另外一个域名叫:`proxy.com`,它是在`Certd`支持的服务商注册的。
|
||||
* 假设我们还有另外一个域名叫:`proxy.com`,它是在`Certd`支持的服务商注册的。
|
||||
* 当我们按照如下进行配置时
|
||||
```
|
||||
CNAME记录(手动、固定) TXT记录(自动、随机)
|
||||
@@ -19,20 +19,17 @@ _acme-challenge.cert.com ---> xxxxx.cname.proxy.com ----> txt-record-abcdefg
|
||||
|
||||
```
|
||||
* 证书颁发机构就可以从`_acme-challenge.cert.com`查到TXT记录 `txt-record-abcdefg`,从而完成域名所有权校验。
|
||||
* 以上可以看出 `xxxxx.cname.proxy.com ----> txt-record-abcdefg` 这一段`Certd`可以自动添加的。
|
||||
* 以上可以看出 `xxxxx.cname.proxy.com ----> txt-record-abcdefg` 这一段`Certd` 是可以自动添加的。
|
||||
* 剩下的只需要在你的`cert.com`域名中手动添加一条固定的`CNAME解析`即可
|
||||
|
||||
|
||||
## 3. Certd CNAME使用步骤
|
||||
|
||||
1. 准备`一个`支持的服务商的注册的域名(`proxy.com`),或者将你众多域名其中`一个`的`DNS服务器`转到这几家服务商。
|
||||
2. 然后到`Certd`的 `CNAME服务管理`界面,用`cname.proxy.com`创建一条默认的CNAME服务,提供DNS提供商授权。
|
||||

|
||||
2. 然后创建证书流水线,输入`cert.com`,选择`CNAME`校验方式
|
||||
|
||||
3. 此时需要配置验证计划,Certd会生成一个随机的CNAME记录,例如:`_acme-challenge`->`xxxxxx.cname.proxy.com`
|
||||
|
||||
1. 创建证书流水线,输入你要申请证书的域名,假设就是`cert.com`,然后选择`CNAME`校验方式
|
||||
2. 此时需要配置验证计划,Certd会生成一个随机的CNAME记录模版,例如:`_acme-challenge`->`xxxxxx.cname.proxy.com`
|
||||

|
||||
3. 您需要手动在你的`cert.com`域名中添加CNAME解析,点击校验,校验成功后就可以开始申请证书了 (此操作每个域名只需要做一次,后续可以重复使用,注意不要删除添加的CNAME记录)
|
||||
3. 您需要手动在你的`cert.com`域名中添加CNAME解析,点击验证,校验成功后就可以开始申请证书了 (此操作每个域名只需要做一次,后续可以重复使用,注意不要删除添加的CNAME记录)
|
||||

|
||||

|
||||
4. 申请过程中,Certd会在`xxxxxx.cname.proxy.com`下自动添加TXT记录。
|
||||
|
||||
@@ -26,7 +26,7 @@ Certd 是一款开源、免费、全自动申请和部署更新SSL证书的工
|
||||
* 实际上没有办法不改变证书文件本身情况下直接续期或者续签。
|
||||
* 我们所说的续期,其实就是按照全套流程重新申请一份新证书,然后重新部署上去。
|
||||
* 免费证书过期时间90天,以后可能还会缩短,所以自动化部署必不可少
|
||||
* 设置每天自动运行,当证书过期前20天,会自动重新申请证书并部署
|
||||
* 设置每天自动运行,当证书过期前35天,会自动重新申请证书并部署
|
||||
|
||||
## 三、证书颁发机构对比
|
||||
* Let's Encrypt:申请最简单。
|
||||
|
||||
@@ -18,6 +18,10 @@ const res = await ctx.http.request({
|
||||
key : certKey
|
||||
}
|
||||
})
|
||||
if(!res || res.code !== 0){
|
||||
//抛异常才能让任务失败
|
||||
throw new Error("上传失败")
|
||||
}
|
||||
//不能用console.log,需要用ctx.logger 才能把日志打印在ui上
|
||||
ctx.logger.info("上传成功",res.data)
|
||||
|
||||
@@ -79,3 +83,4 @@ type CustomScriptPlugin = {
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
BIN
docs/guide/use/setting/images/ipv6.png
Normal file
BIN
docs/guide/use/setting/images/ipv6.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 39 KiB |
21
docs/guide/use/setting/ipv6.md
Normal file
21
docs/guide/use/setting/ipv6.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# IPv6支持
|
||||
|
||||
## 启用IPv6
|
||||
在`docker-compose.yaml`中启用IPv6支持,放开如下注释:
|
||||
```yaml
|
||||
# #↓↓↓↓ ------------------------------------------------------------- 启用ipv6网络
|
||||
networks:
|
||||
- ip6net
|
||||
networks:
|
||||
ip6net:
|
||||
enable_ipv6: true
|
||||
ipam:
|
||||
config:
|
||||
- subnet: 2001:db8::/64
|
||||
|
||||
```
|
||||
|
||||
## 设置双栈网络优先级
|
||||
可根据实际情况设置
|
||||
|
||||

|
||||
@@ -18,7 +18,7 @@ hero:
|
||||
link: /guide/tutorial.md
|
||||
- theme: alt
|
||||
text: demo体验
|
||||
link: https://certd.handsfree.work
|
||||
link: https://certd.handfree.work
|
||||
|
||||
features:
|
||||
- title: 全自动申请证书
|
||||
|
||||
@@ -9,5 +9,5 @@
|
||||
}
|
||||
},
|
||||
"npmClient": "pnpm",
|
||||
"version": "1.27.2"
|
||||
"version": "1.27.6"
|
||||
}
|
||||
|
||||
@@ -14,13 +14,14 @@
|
||||
},
|
||||
"scripts": {
|
||||
"start": "lerna bootstrap --hoist",
|
||||
"devb": "lerna run dev-build",
|
||||
"i-all": "lerna link && lerna exec npm install ",
|
||||
"publish": "npm run prepublishOnly2 && lerna publish --force-publish=pro/plus-core --conventional-commits --create-release github && npm run afterpublishOnly && npm run commitAll",
|
||||
"afterpublishOnly": "npm run copylogs && time /t >build.trigger && git add ./build.trigger && git commit -m \"build: trigger build image\" && TIMEOUT /T 10 && git push",
|
||||
"transform-sql": "cd ./packages/ui/certd-server/db/ && node --experimental-json-modules transform.js",
|
||||
"commitAll": "git add . && git commit -m \"build: publish\" && git push && npm run commitPro",
|
||||
"commitPro": "cd ./packages/core/ && git add . && git commit -m \"build: publish\" && git push",
|
||||
"copylogs": "copyfiles \"CHANGELOG.md\" ./docs/guide/other/changelogs/",
|
||||
"copylogs": "copyfiles \"CHANGELOG.md\" ./docs/guide/changelogs/",
|
||||
"prepublishOnly1": "npm run check && lerna run build ",
|
||||
"prepublishOnly2": "npm run check && npm run before-build && lerna run build ",
|
||||
"before-build": "npm run transform-sql && cd ./packages/core/basic && time /t >build.md && git add ./build.md && git commit -m \"build: prepare to build\"",
|
||||
@@ -34,6 +35,7 @@
|
||||
"license": "AGPL-3.0",
|
||||
"dependencies": {
|
||||
"axios": "^1.7.7",
|
||||
"copyfiles": "^2.4.1",
|
||||
"lodash-es": "^4.17.21",
|
||||
"typescript": "^5.4.2"
|
||||
},
|
||||
|
||||
28
packages/core/acme-client/.eslintrc
Normal file
28
packages/core/acme-client/.eslintrc
Normal file
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"extends": [
|
||||
"plugin:prettier/recommended",
|
||||
"prettier"
|
||||
],
|
||||
"plugins": [
|
||||
"eslint-plugin-import"
|
||||
],
|
||||
"env": {
|
||||
"mocha": true
|
||||
},
|
||||
"rules": {
|
||||
"@typescript-eslint/no-var-requires": "off",
|
||||
"@typescript-eslint/ban-ts-comment": "off",
|
||||
"@typescript-eslint/ban-ts-ignore": "off",
|
||||
"@typescript-eslint/no-explicit-any": "off",
|
||||
"@typescript-eslint/no-empty-function": "off",
|
||||
// "no-unused-expressions": "off",
|
||||
"max-len": [
|
||||
0,
|
||||
160,
|
||||
2,
|
||||
{
|
||||
"ignoreUrls": true
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
extends:
|
||||
- 'airbnb-base'
|
||||
|
||||
env:
|
||||
browser: false
|
||||
node: true
|
||||
mocha: true
|
||||
|
||||
rules:
|
||||
indent: [2, 4, { SwitchCase: 1, VariableDeclarator: 1 }]
|
||||
brace-style: [2, 'stroustrup', { allowSingleLine: true }]
|
||||
func-names: 0
|
||||
class-methods-use-this: 0
|
||||
no-param-reassign: 0
|
||||
max-len: [1, 200, 2, { ignoreUrls: true, ignoreComments: false }]
|
||||
import/no-useless-path-segments: 0
|
||||
@@ -3,6 +3,22 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.27.6](https://github.com/publishlab/node-acme-client/compare/v1.27.5...v1.27.6) (2024-11-19)
|
||||
|
||||
**Note:** Version bump only for package @certd/acme-client
|
||||
|
||||
## [1.27.5](https://github.com/publishlab/node-acme-client/compare/v1.27.4...v1.27.5) (2024-11-18)
|
||||
|
||||
**Note:** Version bump only for package @certd/acme-client
|
||||
|
||||
## [1.27.4](https://github.com/publishlab/node-acme-client/compare/v1.27.3...v1.27.4) (2024-11-14)
|
||||
|
||||
**Note:** Version bump only for package @certd/acme-client
|
||||
|
||||
## [1.27.3](https://github.com/publishlab/node-acme-client/compare/v1.27.2...v1.27.3) (2024-11-13)
|
||||
|
||||
**Note:** Version bump only for package @certd/acme-client
|
||||
|
||||
## [1.27.2](https://github.com/publishlab/node-acme-client/compare/v1.27.1...v1.27.2) (2024-11-08)
|
||||
|
||||
**Note:** Version bump only for package @certd/acme-client
|
||||
|
||||
@@ -6,6 +6,38 @@
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
## Constants
|
||||
|
||||
<dl>
|
||||
<dt><a href="#createPrivateEcdsaKey">createPrivateEcdsaKey</a> ⇒ <code>Promise.<buffer></code></dt>
|
||||
<dd><p>Generate a private ECDSA key</p>
|
||||
</dd>
|
||||
<dt><a href="#getPublicKey">getPublicKey</a> ⇒ <code>buffer</code></dt>
|
||||
<dd><p>Get a public key derived from a RSA or ECDSA key</p>
|
||||
</dd>
|
||||
<dt><a href="#getPemBodyAsB64u">getPemBodyAsB64u</a> ⇒ <code>string</code></dt>
|
||||
<dd><p>Parse body of PEM encoded object and return a Base64URL string
|
||||
If multiple objects are chained, the first body will be returned</p>
|
||||
</dd>
|
||||
<dt><a href="#readCsrDomains">readCsrDomains</a> ⇒ <code>object</code></dt>
|
||||
<dd><p>Read domains from a Certificate Signing Request</p>
|
||||
</dd>
|
||||
<dt><a href="#readCertificateInfo">readCertificateInfo</a> ⇒ <code>object</code></dt>
|
||||
<dd><p>Read information from a certificate
|
||||
If multiple certificates are chained, the first will be read</p>
|
||||
</dd>
|
||||
<dt><a href="#createCsr">createCsr</a> ⇒ <code>Promise.<Array.<buffer>></code></dt>
|
||||
<dd><p>Create a Certificate Signing Request</p>
|
||||
</dd>
|
||||
<dt><a href="#createAlpnCertificate">createAlpnCertificate</a> ⇒ <code>Promise.<Array.<buffer>></code></dt>
|
||||
<dd><p>Create a self-signed ALPN certificate for TLS-ALPN-01 challenges</p>
|
||||
<p><a href="https://datatracker.ietf.org/doc/html/rfc8737">https://datatracker.ietf.org/doc/html/rfc8737</a></p>
|
||||
</dd>
|
||||
<dt><a href="#isAlpnCertificateAuthorizationValid">isAlpnCertificateAuthorizationValid</a> ⇒ <code>boolean</code></dt>
|
||||
<dd><p>Validate that a ALPN certificate contains the expected key authorization</p>
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
## Functions
|
||||
|
||||
<dl>
|
||||
@@ -15,12 +47,6 @@
|
||||
<dt><a href="#createPrivateKey">createPrivateKey()</a></dt>
|
||||
<dd><p>Alias of <code>createPrivateRsaKey()</code></p>
|
||||
</dd>
|
||||
<dt><a href="#createPrivateEcdsaKey">createPrivateEcdsaKey([namedCurve])</a> ⇒ <code>Promise.<buffer></code></dt>
|
||||
<dd><p>Generate a private ECDSA key</p>
|
||||
</dd>
|
||||
<dt><a href="#getPublicKey">getPublicKey(keyPem)</a> ⇒ <code>buffer</code></dt>
|
||||
<dd><p>Get a public key derived from a RSA or ECDSA key</p>
|
||||
</dd>
|
||||
<dt><a href="#getJwk">getJwk(keyPem)</a> ⇒ <code>object</code></dt>
|
||||
<dd><p>Get a JSON Web Key derived from a RSA or ECDSA key</p>
|
||||
<p><a href="https://datatracker.ietf.org/doc/html/rfc7517">https://datatracker.ietf.org/doc/html/rfc7517</a></p>
|
||||
@@ -28,27 +54,6 @@
|
||||
<dt><a href="#splitPemChain">splitPemChain(chainPem)</a> ⇒ <code>Array.<string></code></dt>
|
||||
<dd><p>Split chain of PEM encoded objects from string into array</p>
|
||||
</dd>
|
||||
<dt><a href="#getPemBodyAsB64u">getPemBodyAsB64u(pem)</a> ⇒ <code>string</code></dt>
|
||||
<dd><p>Parse body of PEM encoded object and return a Base64URL string
|
||||
If multiple objects are chained, the first body will be returned</p>
|
||||
</dd>
|
||||
<dt><a href="#readCsrDomains">readCsrDomains(csrPem)</a> ⇒ <code>object</code></dt>
|
||||
<dd><p>Read domains from a Certificate Signing Request</p>
|
||||
</dd>
|
||||
<dt><a href="#readCertificateInfo">readCertificateInfo(certPem)</a> ⇒ <code>object</code></dt>
|
||||
<dd><p>Read information from a certificate
|
||||
If multiple certificates are chained, the first will be read</p>
|
||||
</dd>
|
||||
<dt><a href="#createCsr">createCsr(data, [keyPem])</a> ⇒ <code>Promise.<Array.<buffer>></code></dt>
|
||||
<dd><p>Create a Certificate Signing Request</p>
|
||||
</dd>
|
||||
<dt><a href="#createAlpnCertificate">createAlpnCertificate(authz, keyAuthorization, [keyPem])</a> ⇒ <code>Promise.<Array.<buffer>></code></dt>
|
||||
<dd><p>Create a self-signed ALPN certificate for TLS-ALPN-01 challenges</p>
|
||||
<p><a href="https://datatracker.ietf.org/doc/html/rfc8737">https://datatracker.ietf.org/doc/html/rfc8737</a></p>
|
||||
</dd>
|
||||
<dt><a href="#isAlpnCertificateAuthorizationValid">isAlpnCertificateAuthorizationValid(certPem, keyAuthorization)</a> ⇒ <code>boolean</code></dt>
|
||||
<dd><p>Validate that a ALPN certificate contains the expected key authorization</p>
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<a name="crypto"></a>
|
||||
@@ -57,40 +62,12 @@ If multiple certificates are chained, the first will be read</p>
|
||||
Native Node.js crypto interface
|
||||
|
||||
**Kind**: global namespace
|
||||
<a name="createPrivateRsaKey"></a>
|
||||
|
||||
## createPrivateRsaKey([modulusLength]) ⇒ <code>Promise.<buffer></code>
|
||||
Generate a private RSA key
|
||||
|
||||
**Kind**: global function
|
||||
**Returns**: <code>Promise.<buffer></code> - PEM encoded private RSA key
|
||||
|
||||
| Param | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| [modulusLength] | <code>number</code> | <code>2048</code> | Size of the keys modulus in bits, default: `2048` |
|
||||
|
||||
**Example**
|
||||
Generate private RSA key
|
||||
```js
|
||||
const privateKey = await acme.crypto.createPrivateRsaKey();
|
||||
```
|
||||
**Example**
|
||||
Private RSA key with modulus size 4096
|
||||
```js
|
||||
const privateKey = await acme.crypto.createPrivateRsaKey(4096);
|
||||
```
|
||||
<a name="createPrivateKey"></a>
|
||||
|
||||
## createPrivateKey()
|
||||
Alias of `createPrivateRsaKey()`
|
||||
|
||||
**Kind**: global function
|
||||
<a name="createPrivateEcdsaKey"></a>
|
||||
|
||||
## createPrivateEcdsaKey([namedCurve]) ⇒ <code>Promise.<buffer></code>
|
||||
## createPrivateEcdsaKey ⇒ <code>Promise.<buffer></code>
|
||||
Generate a private ECDSA key
|
||||
|
||||
**Kind**: global function
|
||||
**Kind**: global constant
|
||||
**Returns**: <code>Promise.<buffer></code> - PEM encoded private ECDSA key
|
||||
|
||||
| Param | Type | Description |
|
||||
@@ -109,10 +86,10 @@ const privateKey = await acme.crypto.createPrivateEcdsaKey('P-384');
|
||||
```
|
||||
<a name="getPublicKey"></a>
|
||||
|
||||
## getPublicKey(keyPem) ⇒ <code>buffer</code>
|
||||
## getPublicKey ⇒ <code>buffer</code>
|
||||
Get a public key derived from a RSA or ECDSA key
|
||||
|
||||
**Kind**: global function
|
||||
**Kind**: global constant
|
||||
**Returns**: <code>buffer</code> - PEM encoded public key
|
||||
|
||||
| Param | Type | Description |
|
||||
@@ -124,44 +101,13 @@ Get public key
|
||||
```js
|
||||
const publicKey = acme.crypto.getPublicKey(privateKey);
|
||||
```
|
||||
<a name="getJwk"></a>
|
||||
|
||||
## getJwk(keyPem) ⇒ <code>object</code>
|
||||
Get a JSON Web Key derived from a RSA or ECDSA key
|
||||
|
||||
https://datatracker.ietf.org/doc/html/rfc7517
|
||||
|
||||
**Kind**: global function
|
||||
**Returns**: <code>object</code> - JSON Web Key
|
||||
|
||||
| Param | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| keyPem | <code>buffer</code> \| <code>string</code> | PEM encoded private or public key |
|
||||
|
||||
**Example**
|
||||
Get JWK
|
||||
```js
|
||||
const jwk = acme.crypto.getJwk(privateKey);
|
||||
```
|
||||
<a name="splitPemChain"></a>
|
||||
|
||||
## splitPemChain(chainPem) ⇒ <code>Array.<string></code>
|
||||
Split chain of PEM encoded objects from string into array
|
||||
|
||||
**Kind**: global function
|
||||
**Returns**: <code>Array.<string></code> - Array of PEM objects including headers
|
||||
|
||||
| Param | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| chainPem | <code>buffer</code> \| <code>string</code> | PEM encoded object chain |
|
||||
|
||||
<a name="getPemBodyAsB64u"></a>
|
||||
|
||||
## getPemBodyAsB64u(pem) ⇒ <code>string</code>
|
||||
## getPemBodyAsB64u ⇒ <code>string</code>
|
||||
Parse body of PEM encoded object and return a Base64URL string
|
||||
If multiple objects are chained, the first body will be returned
|
||||
|
||||
**Kind**: global function
|
||||
**Kind**: global constant
|
||||
**Returns**: <code>string</code> - Base64URL-encoded body
|
||||
|
||||
| Param | Type | Description |
|
||||
@@ -170,10 +116,10 @@ If multiple objects are chained, the first body will be returned
|
||||
|
||||
<a name="readCsrDomains"></a>
|
||||
|
||||
## readCsrDomains(csrPem) ⇒ <code>object</code>
|
||||
## readCsrDomains ⇒ <code>object</code>
|
||||
Read domains from a Certificate Signing Request
|
||||
|
||||
**Kind**: global function
|
||||
**Kind**: global constant
|
||||
**Returns**: <code>object</code> - {commonName, altNames}
|
||||
|
||||
| Param | Type | Description |
|
||||
@@ -190,11 +136,11 @@ console.log(`Alt names: ${altNames.join(', ')}`);
|
||||
```
|
||||
<a name="readCertificateInfo"></a>
|
||||
|
||||
## readCertificateInfo(certPem) ⇒ <code>object</code>
|
||||
## readCertificateInfo ⇒ <code>object</code>
|
||||
Read information from a certificate
|
||||
If multiple certificates are chained, the first will be read
|
||||
|
||||
**Kind**: global function
|
||||
**Kind**: global constant
|
||||
**Returns**: <code>object</code> - Certificate info
|
||||
|
||||
| Param | Type | Description |
|
||||
@@ -215,10 +161,10 @@ console.log(`Alt names: ${altNames.join(', ')}`);
|
||||
```
|
||||
<a name="createCsr"></a>
|
||||
|
||||
## createCsr(data, [keyPem]) ⇒ <code>Promise.<Array.<buffer>></code>
|
||||
## createCsr ⇒ <code>Promise.<Array.<buffer>></code>
|
||||
Create a Certificate Signing Request
|
||||
|
||||
**Kind**: global function
|
||||
**Kind**: global constant
|
||||
**Returns**: <code>Promise.<Array.<buffer>></code> - [privateKey, certificateSigningRequest]
|
||||
|
||||
| Param | Type | Description |
|
||||
@@ -276,12 +222,12 @@ const [, certificateRequest] = await acme.crypto.createCsr({
|
||||
```
|
||||
<a name="createAlpnCertificate"></a>
|
||||
|
||||
## createAlpnCertificate(authz, keyAuthorization, [keyPem]) ⇒ <code>Promise.<Array.<buffer>></code>
|
||||
## createAlpnCertificate ⇒ <code>Promise.<Array.<buffer>></code>
|
||||
Create a self-signed ALPN certificate for TLS-ALPN-01 challenges
|
||||
|
||||
https://datatracker.ietf.org/doc/html/rfc8737
|
||||
|
||||
**Kind**: global function
|
||||
**Kind**: global constant
|
||||
**Returns**: <code>Promise.<Array.<buffer>></code> - [privateKey, certificate]
|
||||
|
||||
| Param | Type | Description |
|
||||
@@ -303,10 +249,10 @@ const [, alpnCertificate] = await acme.crypto.createAlpnCertificate(authz, keyAu
|
||||
```
|
||||
<a name="isAlpnCertificateAuthorizationValid"></a>
|
||||
|
||||
## isAlpnCertificateAuthorizationValid(certPem, keyAuthorization) ⇒ <code>boolean</code>
|
||||
## isAlpnCertificateAuthorizationValid ⇒ <code>boolean</code>
|
||||
Validate that a ALPN certificate contains the expected key authorization
|
||||
|
||||
**Kind**: global function
|
||||
**Kind**: global constant
|
||||
**Returns**: <code>boolean</code> - True when valid
|
||||
|
||||
| Param | Type | Description |
|
||||
@@ -314,3 +260,62 @@ Validate that a ALPN certificate contains the expected key authorization
|
||||
| certPem | <code>buffer</code> \| <code>string</code> | PEM encoded certificate |
|
||||
| keyAuthorization | <code>string</code> | Expected challenge key authorization |
|
||||
|
||||
<a name="createPrivateRsaKey"></a>
|
||||
|
||||
## createPrivateRsaKey([modulusLength]) ⇒ <code>Promise.<buffer></code>
|
||||
Generate a private RSA key
|
||||
|
||||
**Kind**: global function
|
||||
**Returns**: <code>Promise.<buffer></code> - PEM encoded private RSA key
|
||||
|
||||
| Param | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| [modulusLength] | <code>number</code> | Size of the keys modulus in bits, default: `2048` |
|
||||
|
||||
**Example**
|
||||
Generate private RSA key
|
||||
```js
|
||||
const privateKey = await acme.crypto.createPrivateRsaKey();
|
||||
```
|
||||
**Example**
|
||||
Private RSA key with modulus size 4096
|
||||
```js
|
||||
const privateKey = await acme.crypto.createPrivateRsaKey(4096);
|
||||
```
|
||||
<a name="createPrivateKey"></a>
|
||||
|
||||
## createPrivateKey()
|
||||
Alias of `createPrivateRsaKey()`
|
||||
|
||||
**Kind**: global function
|
||||
<a name="getJwk"></a>
|
||||
|
||||
## getJwk(keyPem) ⇒ <code>object</code>
|
||||
Get a JSON Web Key derived from a RSA or ECDSA key
|
||||
|
||||
https://datatracker.ietf.org/doc/html/rfc7517
|
||||
|
||||
**Kind**: global function
|
||||
**Returns**: <code>object</code> - JSON Web Key
|
||||
|
||||
| Param | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| keyPem | <code>buffer</code> \| <code>string</code> | PEM encoded private or public key |
|
||||
|
||||
**Example**
|
||||
Get JWK
|
||||
```js
|
||||
const jwk = acme.crypto.getJwk(privateKey);
|
||||
```
|
||||
<a name="splitPemChain"></a>
|
||||
|
||||
## splitPemChain(chainPem) ⇒ <code>Array.<string></code>
|
||||
Split chain of PEM encoded objects from string into array
|
||||
|
||||
**Kind**: global function
|
||||
**Returns**: <code>Array.<string></code> - Array of PEM objects including headers
|
||||
|
||||
| Param | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| chainPem | <code>buffer</code> \| <code>string</code> | PEM encoded object chain |
|
||||
|
||||
|
||||
@@ -8,37 +8,42 @@ major release. Please migrate to the new <code>acme.crypto</code> interface at y
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
## Constants
|
||||
|
||||
<dl>
|
||||
<dt><a href="#createPublicKey">createPublicKey</a> ⇒ <code>Promise.<buffer></code></dt>
|
||||
<dd><p>Create public key from a private RSA key</p>
|
||||
</dd>
|
||||
<dt><a href="#getPemBody">getPemBody</a> ⇒ <code>string</code></dt>
|
||||
<dd><p>Parse body of PEM encoded object from buffer or string
|
||||
If multiple objects are chained, the first body will be returned</p>
|
||||
</dd>
|
||||
<dt><a href="#splitPemChain">splitPemChain</a> ⇒ <code>Array.<string></code></dt>
|
||||
<dd><p>Split chain of PEM encoded objects from buffer or string into array</p>
|
||||
</dd>
|
||||
<dt><a href="#getModulus">getModulus</a> ⇒ <code>Promise.<buffer></code></dt>
|
||||
<dd><p>Get modulus</p>
|
||||
</dd>
|
||||
<dt><a href="#getPublicExponent">getPublicExponent</a> ⇒ <code>Promise.<buffer></code></dt>
|
||||
<dd><p>Get public exponent</p>
|
||||
</dd>
|
||||
<dt><a href="#readCsrDomains">readCsrDomains</a> ⇒ <code>Promise.<object></code></dt>
|
||||
<dd><p>Read domains from a Certificate Signing Request</p>
|
||||
</dd>
|
||||
<dt><a href="#readCertificateInfo">readCertificateInfo</a> ⇒ <code>Promise.<object></code></dt>
|
||||
<dd><p>Read information from a certificate</p>
|
||||
</dd>
|
||||
<dt><a href="#createCsr">createCsr</a> ⇒ <code>Promise.<Array.<buffer>></code></dt>
|
||||
<dd><p>Create a Certificate Signing Request</p>
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
## Functions
|
||||
|
||||
<dl>
|
||||
<dt><a href="#createPrivateKey">createPrivateKey([size])</a> ⇒ <code>Promise.<buffer></code></dt>
|
||||
<dd><p>Generate a private RSA key</p>
|
||||
</dd>
|
||||
<dt><a href="#createPublicKey">createPublicKey(key)</a> ⇒ <code>Promise.<buffer></code></dt>
|
||||
<dd><p>Create public key from a private RSA key</p>
|
||||
</dd>
|
||||
<dt><a href="#getPemBody">getPemBody(str)</a> ⇒ <code>string</code></dt>
|
||||
<dd><p>Parse body of PEM encoded object from buffer or string
|
||||
If multiple objects are chained, the first body will be returned</p>
|
||||
</dd>
|
||||
<dt><a href="#splitPemChain">splitPemChain(str)</a> ⇒ <code>Array.<string></code></dt>
|
||||
<dd><p>Split chain of PEM encoded objects from buffer or string into array</p>
|
||||
</dd>
|
||||
<dt><a href="#getModulus">getModulus(input)</a> ⇒ <code>Promise.<buffer></code></dt>
|
||||
<dd><p>Get modulus</p>
|
||||
</dd>
|
||||
<dt><a href="#getPublicExponent">getPublicExponent(input)</a> ⇒ <code>Promise.<buffer></code></dt>
|
||||
<dd><p>Get public exponent</p>
|
||||
</dd>
|
||||
<dt><a href="#readCsrDomains">readCsrDomains(csr)</a> ⇒ <code>Promise.<object></code></dt>
|
||||
<dd><p>Read domains from a Certificate Signing Request</p>
|
||||
</dd>
|
||||
<dt><a href="#readCertificateInfo">readCertificateInfo(cert)</a> ⇒ <code>Promise.<object></code></dt>
|
||||
<dd><p>Read information from a certificate</p>
|
||||
</dd>
|
||||
<dt><a href="#createCsr">createCsr(data, [key])</a> ⇒ <code>Promise.<Array.<buffer>></code></dt>
|
||||
<dd><p>Create a Certificate Signing Request</p>
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<a name="forge"></a>
|
||||
@@ -50,34 +55,12 @@ DEPRECATION WARNING: This crypto interface is deprecated and will be removed fro
|
||||
major release. Please migrate to the new `acme.crypto` interface at your earliest convenience.
|
||||
|
||||
**Kind**: global namespace
|
||||
<a name="createPrivateKey"></a>
|
||||
|
||||
## createPrivateKey([size]) ⇒ <code>Promise.<buffer></code>
|
||||
Generate a private RSA key
|
||||
|
||||
**Kind**: global function
|
||||
**Returns**: <code>Promise.<buffer></code> - PEM encoded private RSA key
|
||||
|
||||
| Param | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| [size] | <code>number</code> | <code>2048</code> | Size of the key, default: `2048` |
|
||||
|
||||
**Example**
|
||||
Generate private RSA key
|
||||
```js
|
||||
const privateKey = await acme.forge.createPrivateKey();
|
||||
```
|
||||
**Example**
|
||||
Private RSA key with defined size
|
||||
```js
|
||||
const privateKey = await acme.forge.createPrivateKey(4096);
|
||||
```
|
||||
<a name="createPublicKey"></a>
|
||||
|
||||
## createPublicKey(key) ⇒ <code>Promise.<buffer></code>
|
||||
## createPublicKey ⇒ <code>Promise.<buffer></code>
|
||||
Create public key from a private RSA key
|
||||
|
||||
**Kind**: global function
|
||||
**Kind**: global constant
|
||||
**Returns**: <code>Promise.<buffer></code> - PEM encoded public RSA key
|
||||
|
||||
| Param | Type | Description |
|
||||
@@ -91,11 +74,11 @@ const publicKey = await acme.forge.createPublicKey(privateKey);
|
||||
```
|
||||
<a name="getPemBody"></a>
|
||||
|
||||
## getPemBody(str) ⇒ <code>string</code>
|
||||
## getPemBody ⇒ <code>string</code>
|
||||
Parse body of PEM encoded object from buffer or string
|
||||
If multiple objects are chained, the first body will be returned
|
||||
|
||||
**Kind**: global function
|
||||
**Kind**: global constant
|
||||
**Returns**: <code>string</code> - PEM body
|
||||
|
||||
| Param | Type | Description |
|
||||
@@ -104,10 +87,10 @@ If multiple objects are chained, the first body will be returned
|
||||
|
||||
<a name="splitPemChain"></a>
|
||||
|
||||
## splitPemChain(str) ⇒ <code>Array.<string></code>
|
||||
## splitPemChain ⇒ <code>Array.<string></code>
|
||||
Split chain of PEM encoded objects from buffer or string into array
|
||||
|
||||
**Kind**: global function
|
||||
**Kind**: global constant
|
||||
**Returns**: <code>Array.<string></code> - Array of PEM bodies
|
||||
|
||||
| Param | Type | Description |
|
||||
@@ -116,10 +99,10 @@ Split chain of PEM encoded objects from buffer or string into array
|
||||
|
||||
<a name="getModulus"></a>
|
||||
|
||||
## getModulus(input) ⇒ <code>Promise.<buffer></code>
|
||||
## getModulus ⇒ <code>Promise.<buffer></code>
|
||||
Get modulus
|
||||
|
||||
**Kind**: global function
|
||||
**Kind**: global constant
|
||||
**Returns**: <code>Promise.<buffer></code> - Modulus
|
||||
|
||||
| Param | Type | Description |
|
||||
@@ -135,10 +118,10 @@ const m3 = await acme.forge.getModulus(certificateRequest);
|
||||
```
|
||||
<a name="getPublicExponent"></a>
|
||||
|
||||
## getPublicExponent(input) ⇒ <code>Promise.<buffer></code>
|
||||
## getPublicExponent ⇒ <code>Promise.<buffer></code>
|
||||
Get public exponent
|
||||
|
||||
**Kind**: global function
|
||||
**Kind**: global constant
|
||||
**Returns**: <code>Promise.<buffer></code> - Exponent
|
||||
|
||||
| Param | Type | Description |
|
||||
@@ -154,10 +137,10 @@ const e3 = await acme.forge.getPublicExponent(certificateRequest);
|
||||
```
|
||||
<a name="readCsrDomains"></a>
|
||||
|
||||
## readCsrDomains(csr) ⇒ <code>Promise.<object></code>
|
||||
## readCsrDomains ⇒ <code>Promise.<object></code>
|
||||
Read domains from a Certificate Signing Request
|
||||
|
||||
**Kind**: global function
|
||||
**Kind**: global constant
|
||||
**Returns**: <code>Promise.<object></code> - {commonName, altNames}
|
||||
|
||||
| Param | Type | Description |
|
||||
@@ -174,10 +157,10 @@ console.log(`Alt names: ${altNames.join(', ')}`);
|
||||
```
|
||||
<a name="readCertificateInfo"></a>
|
||||
|
||||
## readCertificateInfo(cert) ⇒ <code>Promise.<object></code>
|
||||
## readCertificateInfo ⇒ <code>Promise.<object></code>
|
||||
Read information from a certificate
|
||||
|
||||
**Kind**: global function
|
||||
**Kind**: global constant
|
||||
**Returns**: <code>Promise.<object></code> - Certificate info
|
||||
|
||||
| Param | Type | Description |
|
||||
@@ -198,10 +181,10 @@ console.log(`Alt names: ${altNames.join(', ')}`);
|
||||
```
|
||||
<a name="createCsr"></a>
|
||||
|
||||
## createCsr(data, [key]) ⇒ <code>Promise.<Array.<buffer>></code>
|
||||
## createCsr ⇒ <code>Promise.<Array.<buffer>></code>
|
||||
Create a Certificate Signing Request
|
||||
|
||||
**Kind**: global function
|
||||
**Kind**: global constant
|
||||
**Returns**: <code>Promise.<Array.<buffer>></code> - [privateKey, certificateSigningRequest]
|
||||
|
||||
| Param | Type | Description |
|
||||
@@ -256,3 +239,25 @@ const certificateKey = await acme.forge.createPrivateKey();
|
||||
const [, certificateRequest] = await acme.forge.createCsr({
|
||||
altNames: ['test.example.com'],
|
||||
}, certificateKey);
|
||||
<a name="createPrivateKey"></a>
|
||||
|
||||
## createPrivateKey([size]) ⇒ <code>Promise.<buffer></code>
|
||||
Generate a private RSA key
|
||||
|
||||
**Kind**: global function
|
||||
**Returns**: <code>Promise.<buffer></code> - PEM encoded private RSA key
|
||||
|
||||
| Param | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| [size] | <code>number</code> | Size of the key, default: `2048` |
|
||||
|
||||
**Example**
|
||||
Generate private RSA key
|
||||
```js
|
||||
const privateKey = await acme.forge.createPrivateKey();
|
||||
```
|
||||
**Example**
|
||||
Private RSA key with defined size
|
||||
```js
|
||||
const privateKey = await acme.forge.createPrivateKey(4096);
|
||||
```
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
"description": "Simple and unopinionated ACME client",
|
||||
"private": false,
|
||||
"author": "nmorsman",
|
||||
"version": "1.27.2",
|
||||
"version": "1.27.6",
|
||||
"type": "module",
|
||||
"module": "scr/index.js",
|
||||
"main": "src/index.js",
|
||||
"types": "types/index.d.ts",
|
||||
"license": "MIT",
|
||||
@@ -16,12 +18,14 @@
|
||||
"types"
|
||||
],
|
||||
"dependencies": {
|
||||
"@certd/basic": "^1.27.6",
|
||||
"@peculiar/x509": "^1.11.0",
|
||||
"asn1js": "^3.0.5",
|
||||
"axios": "^1.7.2",
|
||||
"debug": "^4.3.5",
|
||||
"http-proxy-agent": "^7.0.2",
|
||||
"https-proxy-agent": "^7.0.5",
|
||||
"lodash-es": "^4.17.21",
|
||||
"node-forge": "^1.3.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -29,8 +33,9 @@
|
||||
"chai": "^4.4.1",
|
||||
"chai-as-promised": "^7.1.2",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-config-airbnb-base": "^15.0.0",
|
||||
"eslint-config-prettier": "^8.5.0",
|
||||
"eslint-plugin-import": "^2.29.1",
|
||||
"eslint-plugin-prettier": "^4.2.1",
|
||||
"jsdoc-to-markdown": "^8.0.1",
|
||||
"mocha": "^10.6.0",
|
||||
"nock": "^13.5.4",
|
||||
@@ -60,5 +65,5 @@
|
||||
"bugs": {
|
||||
"url": "https://github.com/publishlab/node-acme-client/issues"
|
||||
},
|
||||
"gitHead": "1d8515bce0b3ce5ece84db53ca57cfbd0c3f4d5a"
|
||||
"gitHead": "3e0d4a0bede5f7353b9b7ff74d9883b59c05510c"
|
||||
}
|
||||
|
||||
@@ -1,110 +0,0 @@
|
||||
const nodeHttp = require('node:http');
|
||||
const https = require('node:https');
|
||||
const { HttpProxyAgent } = require('http-proxy-agent');
|
||||
const { HttpsProxyAgent } = require('https-proxy-agent');
|
||||
const { log } = require('./logger');
|
||||
|
||||
function createAgent(opts = {}) {
|
||||
let httpAgent;
|
||||
let
|
||||
httpsAgent;
|
||||
const httpProxy = opts.httpProxy || process.env.HTTP_PROXY || process.env.http_proxy;
|
||||
if (httpProxy) {
|
||||
log(`acme use httpProxy:${httpProxy}`);
|
||||
httpAgent = new HttpProxyAgent(httpProxy, opts);
|
||||
}
|
||||
else {
|
||||
httpAgent = new nodeHttp.Agent(opts);
|
||||
}
|
||||
const httpsProxy = opts.httpsProxy || process.env.HTTPS_PROXY || process.env.https_proxy;
|
||||
if (httpsProxy) {
|
||||
log(`acme use httpsProxy:${httpsProxy}`);
|
||||
httpsAgent = new HttpsProxyAgent(httpsProxy, opts);
|
||||
}
|
||||
else {
|
||||
httpsAgent = new https.Agent(opts);
|
||||
}
|
||||
return {
|
||||
httpAgent,
|
||||
httpsAgent,
|
||||
};
|
||||
}
|
||||
|
||||
let defaultAgents = createAgent();
|
||||
|
||||
function getGlobalAgents() {
|
||||
return defaultAgents;
|
||||
}
|
||||
|
||||
function setGlobalProxy(opts) {
|
||||
log('acme setGlobalProxy:', opts);
|
||||
defaultAgents = createAgent(opts);
|
||||
}
|
||||
|
||||
class HttpError extends Error {
|
||||
// eslint-disable-next-line constructor-super
|
||||
constructor(error) {
|
||||
if (!error) {
|
||||
return;
|
||||
}
|
||||
super(error.message);
|
||||
|
||||
this.message = error.message;
|
||||
const { message } = error;
|
||||
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')) {
|
||||
this.message = `${message}(无法解析域名,请检查网络连接或dns配置)`;
|
||||
}
|
||||
}
|
||||
|
||||
this.name = error.name;
|
||||
this.code = error.code;
|
||||
|
||||
if (error.response) {
|
||||
this.status = error.response.status;
|
||||
this.statusText = error.response.statusText;
|
||||
this.response = {
|
||||
data: error.response.data,
|
||||
};
|
||||
if (!this.message) {
|
||||
this.message = this.statusText;
|
||||
}
|
||||
}
|
||||
|
||||
let url = '';
|
||||
if (error.config) {
|
||||
this.request = {
|
||||
baseURL: error.config.baseURL,
|
||||
url: error.config.url,
|
||||
method: error.config.method,
|
||||
params: error.config.params,
|
||||
data: error.config.data,
|
||||
};
|
||||
url = (error.config.baseURL || '') + error.config.url;
|
||||
}
|
||||
if (url) {
|
||||
this.message = `${this.message}:${url}`;
|
||||
}
|
||||
// const { stack, cause } = error;
|
||||
delete this.cause;
|
||||
delete this.stack;
|
||||
// this.cause = cause;
|
||||
// this.stack = stack;
|
||||
delete error.stack;
|
||||
delete error.cause;
|
||||
delete error.response;
|
||||
delete error.config;
|
||||
delete error.request;
|
||||
// logger.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
setGlobalProxy,
|
||||
createAgent,
|
||||
getGlobalAgents,
|
||||
HttpError,
|
||||
};
|
||||
@@ -1,9 +1,7 @@
|
||||
/**
|
||||
* ACME API client
|
||||
*/
|
||||
|
||||
const util = require('./util');
|
||||
const { log } = require('./logger');
|
||||
import * as util from './util.js';
|
||||
|
||||
/**
|
||||
* AcmeApi
|
||||
@@ -248,4 +246,4 @@ class AcmeApi {
|
||||
}
|
||||
|
||||
/* Export API */
|
||||
module.exports = AcmeApi;
|
||||
export default AcmeApi;
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/**
|
||||
* ACME auto helper
|
||||
*/
|
||||
import { readCsrDomains } from './crypto/index.js';
|
||||
import { log } from './logger.js';
|
||||
import { wait } from './wait.js';
|
||||
import { CancelError } from './error.js';
|
||||
|
||||
const { readCsrDomains } = require('./crypto');
|
||||
const { log } = require('./logger');
|
||||
const { wait } = require('./wait');
|
||||
const { CancelError } = require('./error');
|
||||
|
||||
const defaultOpts = {
|
||||
csr: null,
|
||||
@@ -30,7 +30,7 @@ const defaultOpts = {
|
||||
* @returns {Promise<buffer>} Certificate
|
||||
*/
|
||||
|
||||
module.exports = async (client, userOpts) => {
|
||||
export default async (client, userOpts) => {
|
||||
const opts = { ...defaultOpts, ...userOpts };
|
||||
const accountPayload = { termsOfServiceAgreed: opts.termsOfServiceAgreed };
|
||||
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
/**
|
||||
* Axios instance
|
||||
*/
|
||||
const axios = require('axios');
|
||||
const { parseRetryAfterHeader } = require('./util');
|
||||
const { log } = require('./logger');
|
||||
const pkg = require('./../package.json');
|
||||
const Agents = require('./agents');
|
||||
|
||||
import axios from 'axios';
|
||||
import { parseRetryAfterHeader } from './util.js';
|
||||
import { log } from './logger.js';
|
||||
const { AxiosError } = axios;
|
||||
|
||||
import {getGlobalAgents, HttpError} from '@certd/basic'
|
||||
/**
|
||||
* Defaults
|
||||
*/
|
||||
@@ -16,7 +13,7 @@ const { AxiosError } = axios;
|
||||
const instance = axios.create();
|
||||
|
||||
/* Default User-Agent */
|
||||
instance.defaults.headers.common['User-Agent'] = `node-${pkg.name}/${pkg.version}`;
|
||||
instance.defaults.headers.common['User-Agent'] = `@certd/acme-client`;
|
||||
|
||||
/* Default ACME settings */
|
||||
instance.defaults.acmeSettings = {
|
||||
@@ -75,7 +72,7 @@ function validateStatus(response) {
|
||||
response,
|
||||
);
|
||||
|
||||
throw new Agents.HttpError(err);
|
||||
throw new HttpError(err);
|
||||
}
|
||||
|
||||
/* Pass all responses through the error interceptor */
|
||||
@@ -85,7 +82,7 @@ instance.interceptors.request.use((config) => {
|
||||
}
|
||||
config.validateStatus = () => false;
|
||||
|
||||
const agents = Agents.getGlobalAgents();
|
||||
const agents = getGlobalAgents();
|
||||
// if (config.skipSslVerify) {
|
||||
// logger.info('跳过SSL验证');
|
||||
// agents = createAgent({ rejectUnauthorized: false } as any);
|
||||
@@ -102,7 +99,7 @@ instance.interceptors.response.use(null, async (error) => {
|
||||
const { config, response } = error;
|
||||
|
||||
if (!config) {
|
||||
return Promise.reject(new Agents.HttpError(error));
|
||||
return Promise.reject(new HttpError(error));
|
||||
}
|
||||
|
||||
/* Pick up errors we want to retry */
|
||||
@@ -122,7 +119,7 @@ instance.interceptors.response.use(null, async (error) => {
|
||||
const waitMinutes = (headerRetryAfter / 60).toFixed(1);
|
||||
log(`Found retry-after response header with value: ${response.headers['retry-after']}, waiting ${waitMinutes} minutes`);
|
||||
log(JSON.stringify(response.data));
|
||||
return Promise.reject(new Agents.HttpError(error));
|
||||
return Promise.reject(new HttpError(error));
|
||||
}
|
||||
|
||||
log(`waiting ${retryAfter} seconds`);
|
||||
@@ -134,7 +131,7 @@ instance.interceptors.response.use(null, async (error) => {
|
||||
}
|
||||
|
||||
if (!response) {
|
||||
return Promise.reject(new Agents.HttpError(error));
|
||||
return Promise.reject(new HttpError(error));
|
||||
}
|
||||
/* Validate and return response */
|
||||
return validateStatus(response);
|
||||
@@ -144,4 +141,4 @@ instance.interceptors.response.use(null, async (error) => {
|
||||
* Export instance
|
||||
*/
|
||||
|
||||
module.exports = instance;
|
||||
export default instance;
|
||||
|
||||
@@ -3,16 +3,17 @@
|
||||
*
|
||||
* @namespace Client
|
||||
*/
|
||||
import { createHash } from 'crypto';
|
||||
import { getPemBodyAsB64u } from './crypto/index.js';
|
||||
import { log } from './logger.js';
|
||||
import HttpClient from './http.js';
|
||||
import AcmeApi from './api.js';
|
||||
import verify from './verify.js';
|
||||
import * as util from './util.js';
|
||||
import auto from './auto.js';
|
||||
import { CancelError } from './error.js';
|
||||
|
||||
|
||||
const { createHash } = require('crypto');
|
||||
const { getPemBodyAsB64u } = require('./crypto');
|
||||
const { log } = require('./logger');
|
||||
const HttpClient = require('./http');
|
||||
const AcmeApi = require('./api');
|
||||
const verify = require('./verify');
|
||||
const util = require('./util');
|
||||
const auto = require('./auto');
|
||||
const { CancelError } = require('./error');
|
||||
|
||||
/**
|
||||
* ACME states
|
||||
@@ -719,4 +720,4 @@ class AcmeClient {
|
||||
}
|
||||
|
||||
/* Export client */
|
||||
module.exports = AcmeClient;
|
||||
export default AcmeClient;
|
||||
|
||||
@@ -6,11 +6,10 @@
|
||||
*
|
||||
* @namespace forge
|
||||
*/
|
||||
|
||||
const net = require('net');
|
||||
const { promisify } = require('util');
|
||||
const forge = require('node-forge');
|
||||
const { createPrivateEcdsaKey, getPublicKey } = require('./index');
|
||||
import net from 'net';
|
||||
import { promisify } from 'util';
|
||||
import forge from 'node-forge';
|
||||
import { createPrivateEcdsaKey } from './index.js';
|
||||
|
||||
const generateKeyPair = promisify(forge.pki.rsa.generateKeyPair);
|
||||
|
||||
@@ -113,13 +112,12 @@ function parseDomains(obj) {
|
||||
* ```
|
||||
*/
|
||||
|
||||
async function createPrivateKey(size = 2048) {
|
||||
export async function createPrivateKey(size = 2048) {
|
||||
const keyPair = await generateKeyPair({ bits: size });
|
||||
const pemKey = forge.pki.privateKeyToPem(keyPair.privateKey);
|
||||
return Buffer.from(pemKey);
|
||||
}
|
||||
|
||||
exports.createPrivateKey = createPrivateKey;
|
||||
|
||||
/**
|
||||
* Create public key from a private RSA key
|
||||
@@ -133,7 +131,7 @@ exports.createPrivateKey = createPrivateKey;
|
||||
* ```
|
||||
*/
|
||||
|
||||
exports.createPublicKey = async (key) => {
|
||||
export const createPublicKey = async (key) => {
|
||||
const privateKey = forge.pki.privateKeyFromPem(key);
|
||||
const publicKey = forge.pki.rsa.setPublicKey(privateKey.n, privateKey.e);
|
||||
const pemKey = forge.pki.publicKeyToPem(publicKey);
|
||||
@@ -148,7 +146,7 @@ exports.createPublicKey = async (key) => {
|
||||
* @returns {string} PEM body
|
||||
*/
|
||||
|
||||
exports.getPemBody = (str) => {
|
||||
export const getPemBody = (str) => {
|
||||
const msg = forge.pem.decode(str)[0];
|
||||
return forge.util.encode64(msg.body);
|
||||
};
|
||||
@@ -160,7 +158,7 @@ exports.getPemBody = (str) => {
|
||||
* @returns {string[]} Array of PEM bodies
|
||||
*/
|
||||
|
||||
exports.splitPemChain = (str) => forge.pem.decode(str).map(forge.pem.encode);
|
||||
export const splitPemChain = (str) => forge.pem.decode(str).map(forge.pem.encode);
|
||||
|
||||
/**
|
||||
* Get modulus
|
||||
@@ -176,7 +174,7 @@ exports.splitPemChain = (str) => forge.pem.decode(str).map(forge.pem.encode);
|
||||
* ```
|
||||
*/
|
||||
|
||||
exports.getModulus = async (input) => {
|
||||
export const getModulus = async (input) => {
|
||||
if (!Buffer.isBuffer(input)) {
|
||||
input = Buffer.from(input);
|
||||
}
|
||||
@@ -199,7 +197,7 @@ exports.getModulus = async (input) => {
|
||||
* ```
|
||||
*/
|
||||
|
||||
exports.getPublicExponent = async (input) => {
|
||||
export const getPublicExponent = async (input) => {
|
||||
if (!Buffer.isBuffer(input)) {
|
||||
input = Buffer.from(input);
|
||||
}
|
||||
@@ -223,7 +221,7 @@ exports.getPublicExponent = async (input) => {
|
||||
* ```
|
||||
*/
|
||||
|
||||
exports.readCsrDomains = async (csr) => {
|
||||
export const readCsrDomains = async (csr) => {
|
||||
if (!Buffer.isBuffer(csr)) {
|
||||
csr = Buffer.from(csr);
|
||||
}
|
||||
@@ -251,7 +249,7 @@ exports.readCsrDomains = async (csr) => {
|
||||
* ```
|
||||
*/
|
||||
|
||||
exports.readCertificateInfo = async (cert) => {
|
||||
export const readCertificateInfo = async (cert) => {
|
||||
if (!Buffer.isBuffer(cert)) {
|
||||
cert = Buffer.from(cert);
|
||||
}
|
||||
@@ -379,7 +377,7 @@ function formatCsrAltNames(altNames) {
|
||||
* }, certificateKey);
|
||||
*/
|
||||
|
||||
exports.createCsr = async (data, keyType = null) => {
|
||||
export const createCsr = async (data, keyType = null) => {
|
||||
let key = null;
|
||||
if (keyType === 'ec') {
|
||||
key = await createPrivateEcdsaKey();
|
||||
|
||||
@@ -3,12 +3,12 @@
|
||||
*
|
||||
* @namespace crypto
|
||||
*/
|
||||
import net from 'net';
|
||||
import { promisify } from 'util';
|
||||
import crypto from 'crypto';
|
||||
import asn1js from 'asn1js';
|
||||
import x509 from '@peculiar/x509';
|
||||
|
||||
const net = require('net');
|
||||
const { promisify } = require('util');
|
||||
const crypto = require('crypto');
|
||||
const asn1js = require('asn1js');
|
||||
const x509 = require('@peculiar/x509');
|
||||
|
||||
const randomInt = promisify(crypto.randomInt);
|
||||
const generateKeyPair = promisify(crypto.generateKeyPair);
|
||||
@@ -67,7 +67,7 @@ function getKeyInfo(keyPem) {
|
||||
* ```
|
||||
*/
|
||||
|
||||
async function createPrivateRsaKey(modulusLength = 2048, encodingType = 'pkcs8') {
|
||||
export async function createPrivateRsaKey(modulusLength = 2048, encodingType = 'pkcs8') {
|
||||
const pair = await generateKeyPair('rsa', {
|
||||
modulusLength,
|
||||
privateKeyEncoding: {
|
||||
@@ -79,7 +79,6 @@ async function createPrivateRsaKey(modulusLength = 2048, encodingType = 'pkcs8')
|
||||
return Buffer.from(pair.privateKey);
|
||||
}
|
||||
|
||||
exports.createPrivateRsaKey = createPrivateRsaKey;
|
||||
|
||||
/**
|
||||
* Alias of `createPrivateRsaKey()`
|
||||
@@ -87,7 +86,7 @@ exports.createPrivateRsaKey = createPrivateRsaKey;
|
||||
* @function
|
||||
*/
|
||||
|
||||
exports.createPrivateKey = createPrivateRsaKey;
|
||||
export const createPrivateKey = createPrivateRsaKey;
|
||||
|
||||
/**
|
||||
* Generate a private ECDSA key
|
||||
@@ -106,7 +105,7 @@ exports.createPrivateKey = createPrivateRsaKey;
|
||||
* ```
|
||||
*/
|
||||
|
||||
exports.createPrivateEcdsaKey = async (namedCurve = 'P-256', encodingType = 'pkcs8') => {
|
||||
export const createPrivateEcdsaKey = async (namedCurve = 'P-256', encodingType = 'pkcs8') => {
|
||||
const pair = await generateKeyPair('ec', {
|
||||
namedCurve,
|
||||
privateKeyEncoding: {
|
||||
@@ -130,7 +129,7 @@ exports.createPrivateEcdsaKey = async (namedCurve = 'P-256', encodingType = 'pkc
|
||||
* ```
|
||||
*/
|
||||
|
||||
exports.getPublicKey = (keyPem) => {
|
||||
export const getPublicKey = (keyPem) => {
|
||||
const info = getKeyInfo(keyPem);
|
||||
|
||||
const publicKey = info.publicKey.export({
|
||||
@@ -155,7 +154,7 @@ exports.getPublicKey = (keyPem) => {
|
||||
* ```
|
||||
*/
|
||||
|
||||
function getJwk(keyPem) {
|
||||
export function getJwk(keyPem) {
|
||||
const jwk = crypto.createPublicKey(keyPem).export({
|
||||
format: 'jwk',
|
||||
});
|
||||
@@ -167,7 +166,6 @@ function getJwk(keyPem) {
|
||||
}, {});
|
||||
}
|
||||
|
||||
exports.getJwk = getJwk;
|
||||
|
||||
/**
|
||||
* Produce CryptoKeyPair and signing algorithm from a PEM encoded private key
|
||||
@@ -215,7 +213,7 @@ async function getWebCryptoKeyPair(keyPem) {
|
||||
* @returns {string[]} Array of PEM objects including headers
|
||||
*/
|
||||
|
||||
function splitPemChain(chainPem) {
|
||||
export function splitPemChain(chainPem) {
|
||||
if (Buffer.isBuffer(chainPem)) {
|
||||
chainPem = chainPem.toString();
|
||||
}
|
||||
@@ -225,7 +223,6 @@ function splitPemChain(chainPem) {
|
||||
.map((params) => x509.PemConverter.encode([params]));
|
||||
}
|
||||
|
||||
exports.splitPemChain = splitPemChain;
|
||||
|
||||
/**
|
||||
* Parse body of PEM encoded object and return a Base64URL string
|
||||
@@ -235,7 +232,7 @@ exports.splitPemChain = splitPemChain;
|
||||
* @returns {string} Base64URL-encoded body
|
||||
*/
|
||||
|
||||
exports.getPemBodyAsB64u = (pem) => {
|
||||
export const getPemBodyAsB64u = (pem) => {
|
||||
const chain = splitPemChain(pem);
|
||||
|
||||
if (!chain.length) {
|
||||
@@ -286,7 +283,7 @@ function parseDomains(input) {
|
||||
* ```
|
||||
*/
|
||||
|
||||
exports.readCsrDomains = (csrPem) => {
|
||||
export const readCsrDomains = (csrPem) => {
|
||||
if (Buffer.isBuffer(csrPem)) {
|
||||
csrPem = csrPem.toString();
|
||||
}
|
||||
@@ -315,7 +312,7 @@ exports.readCsrDomains = (csrPem) => {
|
||||
* ```
|
||||
*/
|
||||
|
||||
exports.readCertificateInfo = (certPem) => {
|
||||
export const readCertificateInfo = (certPem) => {
|
||||
if (Buffer.isBuffer(certPem)) {
|
||||
certPem = certPem.toString();
|
||||
}
|
||||
@@ -449,7 +446,7 @@ function createSubjectAltNameExtension(altNames) {
|
||||
* ```
|
||||
*/
|
||||
|
||||
exports.createCsr = async (data, keyPem = null) => {
|
||||
export const createCsr = async (data, keyPem = null) => {
|
||||
if (!keyPem) {
|
||||
keyPem = await createPrivateRsaKey(data.keySize);
|
||||
}
|
||||
@@ -520,7 +517,7 @@ exports.createCsr = async (data, keyPem = null) => {
|
||||
* ```
|
||||
*/
|
||||
|
||||
exports.createAlpnCertificate = async (authz, keyAuthorization, keyPem = null) => {
|
||||
export const createAlpnCertificate = async (authz, keyAuthorization, keyPem = null) => {
|
||||
if (!keyPem) {
|
||||
keyPem = await createPrivateRsaKey();
|
||||
}
|
||||
@@ -583,7 +580,7 @@ exports.createAlpnCertificate = async (authz, keyAuthorization, keyPem = null) =
|
||||
* @returns {boolean} True when valid
|
||||
*/
|
||||
|
||||
exports.isAlpnCertificateAuthorizationValid = (certPem, keyAuthorization) => {
|
||||
export const isAlpnCertificateAuthorizationValid = (certPem, keyAuthorization) => {
|
||||
const expected = crypto.createHash('sha256').update(keyAuthorization).digest('hex');
|
||||
|
||||
/* Attempt to locate ALPN extension */
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
class CancelError extends Error {
|
||||
export class CancelError extends Error {
|
||||
constructor(message) {
|
||||
super(message);
|
||||
this.name = 'CancelError';
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
CancelError,
|
||||
};
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/**
|
||||
* ACME HTTP client
|
||||
*/
|
||||
|
||||
const { createHmac, createSign, constants: { RSA_PKCS1_PADDING } } = require('crypto');
|
||||
const { getJwk } = require('./crypto');
|
||||
const { log } = require('./logger');
|
||||
const axios = require('./axios');
|
||||
import { createHmac, createSign, constants } from 'crypto';
|
||||
const { RSA_PKCS1_PADDING } = constants;
|
||||
import axios from './axios.js';
|
||||
import { log } from './logger.js';
|
||||
import { getJwk } from './crypto/index.js';
|
||||
|
||||
/**
|
||||
* ACME HTTP client
|
||||
@@ -324,4 +324,4 @@ class HttpClient {
|
||||
}
|
||||
|
||||
/* Export client */
|
||||
module.exports = HttpClient;
|
||||
export default HttpClient;
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
/**
|
||||
* acme-client
|
||||
*/
|
||||
|
||||
exports.Client = require('./client');
|
||||
import AcmeClinet from './client.js'
|
||||
export const Client = AcmeClinet
|
||||
|
||||
/**
|
||||
* Directory URLs
|
||||
*/
|
||||
|
||||
exports.directory = {
|
||||
export const directory = {
|
||||
buypass: {
|
||||
staging: 'https://api.test4.buypass.no/acme/directory',
|
||||
production: 'https://api.buypass.com/acme/directory',
|
||||
@@ -31,21 +31,18 @@ exports.directory = {
|
||||
* Crypto
|
||||
*/
|
||||
|
||||
exports.crypto = require('./crypto');
|
||||
exports.forge = require('./crypto/forge');
|
||||
export * as crypto from './crypto/index.js'
|
||||
export * as forge from './crypto/forge.js'
|
||||
|
||||
/**
|
||||
* Axios
|
||||
*/
|
||||
|
||||
exports.axios = require('./axios');
|
||||
exports.agents = require('./agents');
|
||||
|
||||
export * from './axios.js'
|
||||
/**
|
||||
* Logger
|
||||
*/
|
||||
|
||||
exports.setLogger = require('./logger').setLogger;
|
||||
|
||||
exports.walkTxtRecord = require('./verify').walkTxtRecord;
|
||||
exports.CancelError = require('./error').CancelError;
|
||||
export * from './logger.js'
|
||||
export * from './verify.js'
|
||||
export * from './error.js'
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
* ACME logger
|
||||
*/
|
||||
|
||||
const debug = require('debug')('acme-client');
|
||||
import debugg from 'debug'
|
||||
const debug = debugg('acme-client');
|
||||
|
||||
let logger = () => {};
|
||||
|
||||
@@ -12,7 +13,7 @@ let logger = () => {};
|
||||
* @param {function} fn Logger function
|
||||
*/
|
||||
|
||||
exports.setLogger = (fn) => {
|
||||
export const setLogger = (fn) => {
|
||||
logger = fn;
|
||||
};
|
||||
|
||||
@@ -22,7 +23,7 @@ exports.setLogger = (fn) => {
|
||||
* @param {string} msg Message
|
||||
*/
|
||||
|
||||
exports.log = (...msg) => {
|
||||
export const log = (...msg) => {
|
||||
debug(...msg);
|
||||
logger(...msg);
|
||||
};
|
||||
|
||||
@@ -2,11 +2,12 @@
|
||||
* Utility methods
|
||||
*/
|
||||
|
||||
const tls = require('tls');
|
||||
const dns = require('dns').promises;
|
||||
const { readCertificateInfo, splitPemChain } = require('./crypto');
|
||||
const { log } = require('./logger');
|
||||
import tls from 'tls';
|
||||
import dnsSdk from 'dns';
|
||||
import { readCertificateInfo, splitPemChain }from './crypto/index.js'
|
||||
import { log } from './logger.js'
|
||||
|
||||
const dns = dnsSdk.promises;
|
||||
/**
|
||||
* Exponential backoff
|
||||
*
|
||||
@@ -329,7 +330,7 @@ async function retrieveTlsAlpnCertificate(host, port, timeout = 30000) {
|
||||
* Export utils
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
export {
|
||||
retry,
|
||||
parseLinkHeader,
|
||||
parseRetryAfterHeader,
|
||||
@@ -338,3 +339,4 @@ module.exports = {
|
||||
getAuthoritativeDnsResolver,
|
||||
retrieveTlsAlpnCertificate,
|
||||
};
|
||||
|
||||
|
||||
@@ -2,13 +2,15 @@
|
||||
* ACME challenge verification
|
||||
*/
|
||||
|
||||
const dns = require('dns').promises;
|
||||
const https = require('https');
|
||||
const { log } = require('./logger');
|
||||
const axios = require('./axios');
|
||||
const util = require('./util');
|
||||
const { isAlpnCertificateAuthorizationValid } = require('./crypto');
|
||||
import dnsSdk from "dns"
|
||||
import https from 'https'
|
||||
import {log} from './logger.js'
|
||||
import axios from './axios.js'
|
||||
import * as util from './util.js'
|
||||
import {isAlpnCertificateAuthorizationValid} from './crypto/index.js'
|
||||
|
||||
|
||||
const dns = dnsSdk.promises
|
||||
/**
|
||||
* Verify ACME HTTP challenge
|
||||
*
|
||||
@@ -79,7 +81,7 @@ async function walkDnsChallengeRecord(recordName, resolver = dns) {
|
||||
}
|
||||
}
|
||||
|
||||
async function walkTxtRecord(recordName) {
|
||||
export async function walkTxtRecord(recordName) {
|
||||
try {
|
||||
/* Default DNS resolver first */
|
||||
log('Attempting to resolve TXT with default DNS resolver first');
|
||||
@@ -153,9 +155,8 @@ async function verifyTlsAlpnChallenge(authz, challenge, keyAuthorization) {
|
||||
* Export API
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
export default {
|
||||
'http-01': verifyHttpChallenge,
|
||||
'dns-01': verifyDnsChallenge,
|
||||
'tls-alpn-01': verifyTlsAlpnChallenge,
|
||||
walkTxtRecord,
|
||||
};
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
async function wait(ms) {
|
||||
export async function wait(ms) {
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(resolve, ms);
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
wait,
|
||||
};
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
{
|
||||
"compileOnSave": true,
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"lib": ["es6"],
|
||||
"strict": true,
|
||||
"noEmit": false,
|
||||
"esModuleInterop": true,
|
||||
"baseUrl": ".",
|
||||
"composite": false,
|
||||
"paths": { "acme-client": ["."] }
|
||||
}
|
||||
}
|
||||
@@ -1,2 +1,2 @@
|
||||
link-workspace-packages=true
|
||||
link-workspace-packages=deep
|
||||
prefer-workspace-packages=true
|
||||
|
||||
@@ -3,6 +3,28 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.27.6](https://github.com/certd/certd/compare/v1.27.5...v1.27.6) (2024-11-19)
|
||||
|
||||
**Note:** Version bump only for package @certd/basic
|
||||
|
||||
## [1.27.5](https://github.com/certd/certd/compare/v1.27.4...v1.27.5) (2024-11-18)
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 系统设置中的代理设置优化为可全局生效,环境变量中的https_proxy设置将无效 ([381a37f](https://github.com/certd/certd/commit/381a37fbaa6b61c887eda743897ae00afb825bdf))
|
||||
* 新手导航在非编辑模式下不显示 ([18bfcc2](https://github.com/certd/certd/commit/18bfcc24ad0bde57bb04db8a4209861ec6b8ff1d))
|
||||
* 优化腾讯云 cloudflare 重复解析记录时的返回值 ([90d1b68](https://github.com/certd/certd/commit/90d1b68bd6cf232fbe085234efe07d29b7690044))
|
||||
|
||||
## [1.27.4](https://github.com/certd/certd/compare/v1.27.3...v1.27.4) (2024-11-14)
|
||||
|
||||
**Note:** Version bump only for package @certd/basic
|
||||
|
||||
## [1.27.3](https://github.com/certd/certd/compare/v1.27.2...v1.27.3) (2024-11-13)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 修复ipv6未开启情况下,请求带有ipv6地址域名报ETIMEDOUT的bug ([a9a0967](https://github.com/certd/certd/commit/a9a0967a6f1d0bd27e69f3ec52c31d90d470bc23))
|
||||
|
||||
## [1.27.2](https://github.com/certd/certd/compare/v1.27.1...v1.27.2) (2024-11-08)
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
@@ -1 +1 @@
|
||||
23:43
|
||||
18:10
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@certd/basic",
|
||||
"private": false,
|
||||
"version": "1.27.2",
|
||||
"version": "1.27.6",
|
||||
"type": "module",
|
||||
"main": "./dist/index.js",
|
||||
"module": "./dist/index.js",
|
||||
@@ -43,5 +43,5 @@
|
||||
"tslib": "^2.8.1",
|
||||
"typescript": "^5.4.2"
|
||||
},
|
||||
"gitHead": "1d8515bce0b3ce5ece84db53ca57cfbd0c3f4d5a"
|
||||
"gitHead": "3e0d4a0bede5f7353b9b7ff74d9883b59c05510c"
|
||||
}
|
||||
|
||||
@@ -7,6 +7,8 @@ export * from './util.promise.js';
|
||||
export * from './util.hash.js';
|
||||
export * from './util.merge.js';
|
||||
export * from './util.cache.js';
|
||||
export * from './util.string.js';
|
||||
import { stringUtils } from './util.string.js';
|
||||
import sleep from './util.sleep.js';
|
||||
import { http, download } from './util.request.js';
|
||||
|
||||
@@ -38,4 +40,5 @@ export const utils = {
|
||||
dayjs,
|
||||
domain: domainUtils,
|
||||
options: optionsUtils,
|
||||
string: stringUtils,
|
||||
};
|
||||
|
||||
@@ -34,7 +34,10 @@ export class HttpError extends Error {
|
||||
this.code = error.code;
|
||||
|
||||
this.status = error.response?.status;
|
||||
this.statusText = error.response?.statusText;
|
||||
this.statusText = error.response?.statusText || error.code;
|
||||
if (!this.message) {
|
||||
this.message = error.code;
|
||||
}
|
||||
this.request = {
|
||||
baseURL: error.config?.baseURL,
|
||||
url: error.config?.url,
|
||||
@@ -47,16 +50,16 @@ export class HttpError extends Error {
|
||||
url = (error.config?.baseURL || '') + url;
|
||||
}
|
||||
if (url) {
|
||||
this.message = `${this.message} : url=${url}`;
|
||||
this.message = `${this.message} 【${url}】`;
|
||||
}
|
||||
|
||||
this.response = {
|
||||
data: error.response?.data,
|
||||
};
|
||||
|
||||
// const { stack, cause } = error;
|
||||
// this.cause = cause;
|
||||
// this.stack = stack;
|
||||
const { stack, cause } = error;
|
||||
this.cause = cause;
|
||||
this.stack = stack;
|
||||
delete error.response;
|
||||
delete error.config;
|
||||
delete error.request;
|
||||
@@ -175,7 +178,10 @@ export function createAxiosService({ logger }: { logger: Logger }) {
|
||||
);
|
||||
logger.error('返回数据:', JSON.stringify(error.response?.data));
|
||||
if (error.response?.data) {
|
||||
error.message = error.response.data.message || error.response.data.msg || error.response.data.error || error.response.data;
|
||||
const message = error.response.data.message || error.response.data.msg || error.response.data.error;
|
||||
if (typeof message === 'string') {
|
||||
error.message = message;
|
||||
}
|
||||
}
|
||||
if (error instanceof AggregateError) {
|
||||
logger.error('AggregateError', error);
|
||||
@@ -199,26 +205,45 @@ export type HttpClient = {
|
||||
request<D = any, R = any>(config: HttpRequestConfig<D>): Promise<HttpClientResponse<R>>;
|
||||
};
|
||||
|
||||
// const http_proxy_backup = process.env.HTTP_PROXY || process.env.http_proxy;
|
||||
// const https_proxy_backup = process.env.HTTPS_PROXY || process.env.https_proxy;
|
||||
|
||||
export type CreateAgentOptions = {
|
||||
httpProxy?: string;
|
||||
httpsProxy?: string;
|
||||
} & nodeHttp.AgentOptions;
|
||||
export function createAgent(opts: CreateAgentOptions = {}) {
|
||||
opts = merge(
|
||||
{
|
||||
autoSelectFamily: true,
|
||||
autoSelectFamilyAttemptTimeout: 1000,
|
||||
},
|
||||
opts
|
||||
);
|
||||
|
||||
let httpAgent, httpsAgent;
|
||||
const httpProxy = opts.httpProxy || process.env.HTTP_PROXY || process.env.http_proxy;
|
||||
const httpProxy = opts.httpProxy;
|
||||
if (httpProxy) {
|
||||
process.env.HTTP_PROXY = httpProxy;
|
||||
process.env.http_proxy = 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 = '';
|
||||
httpAgent = new nodeHttp.Agent(opts);
|
||||
}
|
||||
const httpsProxy = opts.httpsProxy || process.env.HTTPS_PROXY || process.env.https_proxy;
|
||||
const httpsProxy = opts.httpsProxy;
|
||||
if (httpsProxy) {
|
||||
process.env.HTTPS_PROXY = httpProxy;
|
||||
process.env.https_proxy = httpProxy;
|
||||
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 = '';
|
||||
httpsAgent = new https.Agent(opts);
|
||||
}
|
||||
return {
|
||||
|
||||
8
packages/core/basic/src/utils/util.string.ts
Normal file
8
packages/core/basic/src/utils/util.string.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
export const stringUtils = {
|
||||
maxLength(str?: string, length = 100) {
|
||||
if (str) {
|
||||
return str.length > length ? str.slice(0, length) + '...' : str;
|
||||
}
|
||||
return '';
|
||||
},
|
||||
};
|
||||
@@ -1,2 +1,2 @@
|
||||
link-workspace-packages=true
|
||||
link-workspace-packages=deep
|
||||
prefer-workspace-packages=true
|
||||
|
||||
@@ -3,6 +3,24 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.27.6](https://github.com/certd/certd/compare/v1.27.5...v1.27.6) (2024-11-19)
|
||||
|
||||
**Note:** Version bump only for package @certd/pipeline
|
||||
|
||||
## [1.27.5](https://github.com/certd/certd/compare/v1.27.4...v1.27.5) (2024-11-18)
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 新手导航在非编辑模式下不显示 ([18bfcc2](https://github.com/certd/certd/commit/18bfcc24ad0bde57bb04db8a4209861ec6b8ff1d))
|
||||
|
||||
## [1.27.4](https://github.com/certd/certd/compare/v1.27.3...v1.27.4) (2024-11-14)
|
||||
|
||||
**Note:** Version bump only for package @certd/pipeline
|
||||
|
||||
## [1.27.3](https://github.com/certd/certd/compare/v1.27.2...v1.27.3) (2024-11-13)
|
||||
|
||||
**Note:** Version bump only for package @certd/pipeline
|
||||
|
||||
## [1.27.2](https://github.com/certd/certd/compare/v1.27.1...v1.27.2) (2024-11-08)
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@certd/pipeline",
|
||||
"private": false,
|
||||
"version": "1.27.2",
|
||||
"version": "1.27.6",
|
||||
"type": "module",
|
||||
"main": "./dist/index.js",
|
||||
"module": "./dist/index.js",
|
||||
@@ -16,8 +16,8 @@
|
||||
"test": "mocha --loader=ts-node/esm"
|
||||
},
|
||||
"dependencies": {
|
||||
"@certd/basic": "^1.27.2",
|
||||
"@certd/plus-core": "^1.27.2",
|
||||
"@certd/basic": "^1.27.6",
|
||||
"@certd/plus-core": "^1.27.6",
|
||||
"dayjs": "^1.11.7",
|
||||
"lodash-es": "^4.17.21",
|
||||
"reflect-metadata": "^0.1.13"
|
||||
@@ -43,5 +43,5 @@
|
||||
"tslib": "^2.8.1",
|
||||
"typescript": "^5.4.2"
|
||||
},
|
||||
"gitHead": "1d8515bce0b3ce5ece84db53ca57cfbd0c3f4d5a"
|
||||
"gitHead": "3e0d4a0bede5f7353b9b7ff74d9883b59c05510c"
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Registry } from "../registry/index.js";
|
||||
import { createRegistry } from "../registry/index.js";
|
||||
|
||||
// @ts-ignore
|
||||
export const accessRegistry = new Registry("access");
|
||||
export const accessRegistry = createRegistry("access");
|
||||
|
||||
@@ -116,10 +116,14 @@ export class RunHistory {
|
||||
}
|
||||
|
||||
logError(runnable: Runnable, e: Error) {
|
||||
// delete e.stack;
|
||||
// delete e.cause;
|
||||
const errorInfo = runnable.runnableType === "step" ? e : e.message;
|
||||
this._loggers[runnable.id].error(`[${runnable.runnableType}] [${runnable.title}]<id:${runnable.id}> :`, errorInfo);
|
||||
const { cause, stack } = e;
|
||||
delete e.stack;
|
||||
delete e.cause;
|
||||
if (runnable.runnableType === "step") {
|
||||
this._loggers[runnable.id].error(`[${runnable.runnableType}] [${runnable.title}]<id:${runnable.id}> :`, e, stack, cause);
|
||||
} else {
|
||||
this._loggers[runnable.id].error(`[${runnable.runnableType}] [${runnable.title}]<id:${runnable.id}> :`, e.message);
|
||||
}
|
||||
}
|
||||
|
||||
finally(runnable: Runnable) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { OnRegisterContext, Registry } from "../registry/index.js";
|
||||
import { createRegistry, OnRegisterContext } from "../registry/index.js";
|
||||
import { AbstractTaskPlugin } from "./api.js";
|
||||
import { pluginGroups } from "./group.js";
|
||||
|
||||
@@ -13,4 +13,4 @@ const onRegister = ({ key, value }: OnRegisterContext<AbstractTaskPlugin>) => {
|
||||
}
|
||||
}
|
||||
};
|
||||
export const pluginRegistry = new Registry<AbstractTaskPlugin>("plugin", onRegister);
|
||||
export const pluginRegistry = createRegistry<AbstractTaskPlugin>("plugin", onRegister);
|
||||
|
||||
@@ -88,3 +88,21 @@ export class Registry<T> {
|
||||
return item.define;
|
||||
}
|
||||
}
|
||||
|
||||
export function createRegistry<T>(type: string, onRegister?: OnRegister<T>) {
|
||||
const pipelineregistrycacheKey = "PIPELINE_REGISTRY_CACHE";
|
||||
// @ts-ignore
|
||||
let cached: any = global[pipelineregistrycacheKey];
|
||||
if (!cached) {
|
||||
cached = {};
|
||||
// @ts-ignore
|
||||
global[pipelineregistrycacheKey] = cached;
|
||||
}
|
||||
|
||||
if (cached[type]) {
|
||||
return cached[type];
|
||||
}
|
||||
const newRegistry = new Registry<T>(type, onRegister);
|
||||
cached[type] = newRegistry;
|
||||
return newRegistry;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,22 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.27.6](https://github.com/certd/certd/compare/v1.27.5...v1.27.6) (2024-11-19)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-huawei
|
||||
|
||||
## [1.27.5](https://github.com/certd/certd/compare/v1.27.4...v1.27.5) (2024-11-18)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-huawei
|
||||
|
||||
## [1.27.4](https://github.com/certd/certd/compare/v1.27.3...v1.27.4) (2024-11-14)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-huawei
|
||||
|
||||
## [1.27.3](https://github.com/certd/certd/compare/v1.27.2...v1.27.3) (2024-11-13)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-huawei
|
||||
|
||||
## [1.27.2](https://github.com/certd/certd/compare/v1.27.1...v1.27.2) (2024-11-08)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-huawei
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@certd/lib-huawei",
|
||||
"private": false,
|
||||
"version": "1.27.2",
|
||||
"version": "1.27.6",
|
||||
"main": "./dist/bundle.js",
|
||||
"module": "./dist/bundle.js",
|
||||
"types": "./dist/d/index.d.ts",
|
||||
@@ -21,5 +21,5 @@
|
||||
"prettier": "^2.8.8",
|
||||
"tslib": "^2.8.1"
|
||||
},
|
||||
"gitHead": "1d8515bce0b3ce5ece84db53ca57cfbd0c3f4d5a"
|
||||
"gitHead": "3e0d4a0bede5f7353b9b7ff74d9883b59c05510c"
|
||||
}
|
||||
|
||||
@@ -3,6 +3,22 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.27.6](https://github.com/certd/certd/compare/v1.27.5...v1.27.6) (2024-11-19)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-iframe
|
||||
|
||||
## [1.27.5](https://github.com/certd/certd/compare/v1.27.4...v1.27.5) (2024-11-18)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-iframe
|
||||
|
||||
## [1.27.4](https://github.com/certd/certd/compare/v1.27.3...v1.27.4) (2024-11-14)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-iframe
|
||||
|
||||
## [1.27.3](https://github.com/certd/certd/compare/v1.27.2...v1.27.3) (2024-11-13)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-iframe
|
||||
|
||||
## [1.27.2](https://github.com/certd/certd/compare/v1.27.1...v1.27.2) (2024-11-08)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-iframe
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
{
|
||||
"name": "@certd/lib-iframe",
|
||||
"private": false,
|
||||
"version": "1.27.2",
|
||||
"version": "1.27.6",
|
||||
"type": "module",
|
||||
"main": "./dist/index.js",
|
||||
"module": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
@@ -29,5 +30,5 @@
|
||||
"tslib": "^2.8.1",
|
||||
"typescript": "^5.4.2"
|
||||
},
|
||||
"gitHead": "1d8515bce0b3ce5ece84db53ca57cfbd0c3f4d5a"
|
||||
"gitHead": "3e0d4a0bede5f7353b9b7ff74d9883b59c05510c"
|
||||
}
|
||||
|
||||
@@ -3,6 +3,22 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.27.6](https://github.com/certd/certd/compare/v1.27.5...v1.27.6) (2024-11-19)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-k8s
|
||||
|
||||
## [1.27.5](https://github.com/certd/certd/compare/v1.27.4...v1.27.5) (2024-11-18)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-k8s
|
||||
|
||||
## [1.27.4](https://github.com/certd/certd/compare/v1.27.3...v1.27.4) (2024-11-14)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-k8s
|
||||
|
||||
## [1.27.3](https://github.com/certd/certd/compare/v1.27.2...v1.27.3) (2024-11-13)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-k8s
|
||||
|
||||
## [1.27.2](https://github.com/certd/certd/compare/v1.27.1...v1.27.2) (2024-11-08)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-k8s
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
{
|
||||
"name": "@certd/lib-k8s",
|
||||
"private": false,
|
||||
"version": "1.27.2",
|
||||
"version": "1.27.6",
|
||||
"type": "module",
|
||||
"main": "./dist/index.js",
|
||||
"module": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
@@ -15,7 +16,7 @@
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@certd/basic": "^1.27.2",
|
||||
"@certd/basic": "^1.27.6",
|
||||
"@kubernetes/client-node": "0.21.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -30,5 +31,5 @@
|
||||
"tslib": "^2.8.1",
|
||||
"typescript": "^5.4.2"
|
||||
},
|
||||
"gitHead": "1d8515bce0b3ce5ece84db53ca57cfbd0c3f4d5a"
|
||||
"gitHead": "3e0d4a0bede5f7353b9b7ff74d9883b59c05510c"
|
||||
}
|
||||
|
||||
@@ -3,6 +3,30 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.27.6](https://github.com/certd/certd/compare/v1.27.5...v1.27.6) (2024-11-19)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 修复vip试用secret报错的bug ([018dee6](https://github.com/certd/certd/commit/018dee6c383233560f078dfd30f6c2857a7e15ee))
|
||||
|
||||
## [1.27.5](https://github.com/certd/certd/compare/v1.27.4...v1.27.5) (2024-11-18)
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 专业版试用,无需绑定账号 ([c7c4318](https://github.com/certd/certd/commit/c7c4318c11b65a76089787aa58939832d338a232))
|
||||
|
||||
## [1.27.4](https://github.com/certd/certd/compare/v1.27.3...v1.27.4) (2024-11-14)
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 公共cname服务支持关闭 ([f4ae512](https://github.com/certd/certd/commit/f4ae5125dc4cd97816976779cb3586b5ee78947e))
|
||||
|
||||
## [1.27.3](https://github.com/certd/certd/compare/v1.27.2...v1.27.3) (2024-11-13)
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* ipv6支持 ([da6ac16](https://github.com/certd/certd/commit/da6ac1626b3574be2fabeeb18a1f10d60bdcbe49))
|
||||
|
||||
## [1.27.2](https://github.com/certd/certd/compare/v1.27.1...v1.27.2) (2024-11-08)
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@certd/lib-server",
|
||||
"version": "1.27.2",
|
||||
"version": "1.27.6",
|
||||
"description": "midway with flyway, sql upgrade way ",
|
||||
"private": false,
|
||||
"type": "module",
|
||||
@@ -27,10 +27,10 @@
|
||||
],
|
||||
"license": "AGPL",
|
||||
"dependencies": {
|
||||
"@certd/acme-client": "^1.27.2",
|
||||
"@certd/basic": "^1.27.2",
|
||||
"@certd/pipeline": "^1.27.2",
|
||||
"@certd/plus-core": "^1.27.2",
|
||||
"@certd/acme-client": "^1.27.6",
|
||||
"@certd/basic": "^1.27.6",
|
||||
"@certd/pipeline": "^1.27.6",
|
||||
"@certd/plus-core": "^1.27.6",
|
||||
"@midwayjs/cache": "~3.14.0",
|
||||
"@midwayjs/core": "~3.17.1",
|
||||
"@midwayjs/i18n": "~3.17.3",
|
||||
@@ -61,5 +61,5 @@
|
||||
"typeorm": "^0.3.11",
|
||||
"typescript": "^5.4.2"
|
||||
},
|
||||
"gitHead": "1d8515bce0b3ce5ece84db53ca57cfbd0c3f4d5a"
|
||||
"gitHead": "3e0d4a0bede5f7353b9b7ff74d9883b59c05510c"
|
||||
}
|
||||
|
||||
@@ -55,7 +55,9 @@ export class PlusService {
|
||||
|
||||
async bindUrl(url: string) {
|
||||
const plusRequestService = await this.getPlusRequestService();
|
||||
return await plusRequestService.bindUrl(url);
|
||||
const res = await plusRequestService.bindUrl(url);
|
||||
this.plusRequestService = null;
|
||||
return res;
|
||||
}
|
||||
|
||||
async register() {
|
||||
@@ -64,6 +66,7 @@ export class PlusService {
|
||||
if (!licenseInfo.license) {
|
||||
await plusRequestService.register();
|
||||
logger.info('站点注册成功');
|
||||
this.plusRequestService = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,6 +111,23 @@ export class PlusService {
|
||||
return res.accessToken;
|
||||
}
|
||||
|
||||
async getVipTrial() {
|
||||
await this.register();
|
||||
const plusRequestService = await this.getPlusRequestService();
|
||||
const res = await plusRequestService.request({
|
||||
url: '/activation/subject/vip/trialGet',
|
||||
method: 'POST',
|
||||
});
|
||||
if (res.license) {
|
||||
await this.updateLicense(res.license);
|
||||
return {
|
||||
duration: res.duration,
|
||||
};
|
||||
} else {
|
||||
throw new Error('您已经领取过VIP试用了');
|
||||
}
|
||||
}
|
||||
|
||||
async requestWithToken(config: HttpRequestConfig) {
|
||||
const plusRequestService = await this.getPlusRequestService();
|
||||
const token = await this.getAccessToken();
|
||||
|
||||
@@ -30,6 +30,8 @@ export class SysPrivateSettings extends BaseSettings {
|
||||
|
||||
httpsProxy? = '';
|
||||
httpProxy? = '';
|
||||
dnsResultOrder? = '';
|
||||
commonCnameEnabled?: boolean = true;
|
||||
|
||||
removeSecret() {
|
||||
const clone = cloneDeep(this);
|
||||
|
||||
@@ -7,7 +7,7 @@ import { BaseSettings, SysInstallInfo, SysPrivateSettings, SysPublicSettings, Sy
|
||||
import * as _ from 'lodash-es';
|
||||
import { BaseService } from '../../../basic/index.js';
|
||||
import { logger, setGlobalProxy } from '@certd/basic';
|
||||
import { agents } from '@certd/acme-client';
|
||||
import * as dns from 'node:dns';
|
||||
/**
|
||||
* 设置
|
||||
*/
|
||||
@@ -132,7 +132,10 @@ export class SysSettingsService extends BaseService<SysSettingsEntity> {
|
||||
httpsProxy: bean.httpsProxy,
|
||||
};
|
||||
setGlobalProxy(opts);
|
||||
agents.setGlobalProxy(opts);
|
||||
|
||||
if (bean.dnsResultOrder) {
|
||||
dns.setDefaultResultOrder(bean.dnsResultOrder as any);
|
||||
}
|
||||
}
|
||||
|
||||
async updateByKey(key: string, setting: any) {
|
||||
|
||||
@@ -3,6 +3,22 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.27.6](https://github.com/certd/certd/compare/v1.27.5...v1.27.6) (2024-11-19)
|
||||
|
||||
**Note:** Version bump only for package @certd/midway-flyway-js
|
||||
|
||||
## [1.27.5](https://github.com/certd/certd/compare/v1.27.4...v1.27.5) (2024-11-18)
|
||||
|
||||
**Note:** Version bump only for package @certd/midway-flyway-js
|
||||
|
||||
## [1.27.4](https://github.com/certd/certd/compare/v1.27.3...v1.27.4) (2024-11-14)
|
||||
|
||||
**Note:** Version bump only for package @certd/midway-flyway-js
|
||||
|
||||
## [1.27.3](https://github.com/certd/certd/compare/v1.27.2...v1.27.3) (2024-11-13)
|
||||
|
||||
**Note:** Version bump only for package @certd/midway-flyway-js
|
||||
|
||||
## [1.27.2](https://github.com/certd/certd/compare/v1.27.1...v1.27.2) (2024-11-08)
|
||||
|
||||
**Note:** Version bump only for package @certd/midway-flyway-js
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
{
|
||||
"name": "@certd/midway-flyway-js",
|
||||
"version": "1.27.2",
|
||||
"version": "1.27.6",
|
||||
"description": "midway with flyway, sql upgrade way ",
|
||||
"private": false,
|
||||
"type": "module",
|
||||
"module": "./dist/index.js",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
"scripts": {
|
||||
@@ -45,5 +46,5 @@
|
||||
"typeorm": "^0.3.11",
|
||||
"typescript": "^5.4.2"
|
||||
},
|
||||
"gitHead": "1d8515bce0b3ce5ece84db53ca57cfbd0c3f4d5a"
|
||||
"gitHead": "3e0d4a0bede5f7353b9b7ff74d9883b59c05510c"
|
||||
}
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
link-workspace-packages=true
|
||||
link-workspace-packages=deep
|
||||
prefer-workspace-packages=true
|
||||
|
||||
@@ -3,6 +3,34 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.27.6](https://github.com/certd/certd/compare/v1.27.5...v1.27.6) (2024-11-19)
|
||||
|
||||
**Note:** Version bump only for package @certd/plugin-cert
|
||||
|
||||
## [1.27.5](https://github.com/certd/certd/compare/v1.27.4...v1.27.5) (2024-11-18)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 修复1Panel面板本身证书更新导致判定执行失败的问题 ([2689e6d](https://github.com/certd/certd/commit/2689e6d6c03aba21da90d5d45232c6ba08696be1))
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 新手导航在非编辑模式下不显示 ([18bfcc2](https://github.com/certd/certd/commit/18bfcc24ad0bde57bb04db8a4209861ec6b8ff1d))
|
||||
* 支持namesilo ([80159ec](https://github.com/certd/certd/commit/80159ecca895103d0495f3217311199e66056572))
|
||||
* 专业版试用,无需绑定账号 ([c7c4318](https://github.com/certd/certd/commit/c7c4318c11b65a76089787aa58939832d338a232))
|
||||
|
||||
## [1.27.4](https://github.com/certd/certd/compare/v1.27.3...v1.27.4) (2024-11-14)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 修复未设置pfx密码,导致jks转换报错的bug ([c3cfbd8](https://github.com/certd/certd/commit/c3cfbd8474155aed4379f91075de37d5d8c73ef0))
|
||||
|
||||
## [1.27.3](https://github.com/certd/certd/compare/v1.27.2...v1.27.3) (2024-11-13)
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 支持jks ([889eaae](https://github.com/certd/certd/commit/889eaaea92818f628b922dae540c026630611707))
|
||||
|
||||
## [1.27.2](https://github.com/certd/certd/compare/v1.27.1...v1.27.2) (2024-11-08)
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@certd/plugin-cert",
|
||||
"private": false,
|
||||
"version": "1.27.2",
|
||||
"version": "1.27.6",
|
||||
"type": "module",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
@@ -15,9 +15,9 @@
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@certd/acme-client": "^1.27.2",
|
||||
"@certd/basic": "^1.27.2",
|
||||
"@certd/pipeline": "^1.27.2",
|
||||
"@certd/acme-client": "^1.27.6",
|
||||
"@certd/basic": "^1.27.6",
|
||||
"@certd/pipeline": "^1.27.6",
|
||||
"@google-cloud/publicca": "^1.3.0",
|
||||
"dayjs": "^1.11.7",
|
||||
"jszip": "^3.10.1",
|
||||
@@ -40,5 +40,5 @@
|
||||
"tslib": "^2.8.1",
|
||||
"typescript": "^5.4.2"
|
||||
},
|
||||
"gitHead": "1d8515bce0b3ce5ece84db53ca57cfbd0c3f4d5a"
|
||||
"gitHead": "3e0d4a0bede5f7353b9b7ff74d9883b59c05510c"
|
||||
}
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
import { Registry } from "@certd/pipeline";
|
||||
import { createRegistry } from "@certd/pipeline";
|
||||
|
||||
export const dnsProviderRegistry = new Registry("dnsProvider");
|
||||
export const dnsProviderRegistry = createRegistry("dnsProvider");
|
||||
|
||||
@@ -49,15 +49,14 @@ export abstract class CertApplyBasePlugin extends AbstractTaskPlugin {
|
||||
email!: string;
|
||||
|
||||
@TaskInput({
|
||||
title: "PFX证书密码",
|
||||
title: "证书密码",
|
||||
component: {
|
||||
name: "input-password",
|
||||
vModel: "value",
|
||||
},
|
||||
required: false,
|
||||
order: 100,
|
||||
// helper: "PFX、jks格式证书是否加密;jks必须设置密码,不传则默认123456",
|
||||
helper: "PFX证书是否加密",
|
||||
helper: "PFX、jks格式证书是否加密;jks必须设置密码,不传则默认123456",
|
||||
})
|
||||
pfxPassword!: string;
|
||||
|
||||
@@ -74,17 +73,6 @@ export abstract class CertApplyBasePlugin extends AbstractTaskPlugin {
|
||||
})
|
||||
renewDays!: number;
|
||||
|
||||
@TaskInput({
|
||||
title: "强制更新",
|
||||
component: {
|
||||
name: "a-switch",
|
||||
vModel: "checked",
|
||||
},
|
||||
order: 100,
|
||||
helper: "是否强制重新申请证书",
|
||||
})
|
||||
forceUpdate!: string;
|
||||
|
||||
@TaskInput({
|
||||
title: "成功后邮件通知",
|
||||
value: true,
|
||||
@@ -152,32 +140,29 @@ export abstract class CertApplyBasePlugin extends AbstractTaskPlugin {
|
||||
}
|
||||
this._result.pipelinePrivateVars.cert = cert;
|
||||
|
||||
if (cert.pfx == null || cert.der == null) {
|
||||
if (isNew) {
|
||||
try {
|
||||
const converter = new CertConverter({ logger: this.logger });
|
||||
const res = await converter.convert({
|
||||
cert,
|
||||
pfxPassword: this.pfxPassword,
|
||||
});
|
||||
if (res.pfxPath) {
|
||||
if (cert.pfx == null && res.pfxPath) {
|
||||
const pfxBuffer = fs.readFileSync(res.pfxPath);
|
||||
cert.pfx = pfxBuffer.toString("base64");
|
||||
fs.unlinkSync(res.pfxPath);
|
||||
isNew = true;
|
||||
}
|
||||
|
||||
if (res.derPath) {
|
||||
if (cert.der == null && res.derPath) {
|
||||
const derBuffer = fs.readFileSync(res.derPath);
|
||||
cert.der = derBuffer.toString("base64");
|
||||
fs.unlinkSync(res.derPath);
|
||||
isNew = true;
|
||||
}
|
||||
|
||||
if (res.jksPath) {
|
||||
if (cert.jks == null && res.jksPath) {
|
||||
const jksBuffer = fs.readFileSync(res.jksPath);
|
||||
cert.jks = jksBuffer.toString("base64");
|
||||
fs.unlinkSync(res.jksPath);
|
||||
isNew = true;
|
||||
}
|
||||
|
||||
this.logger.info("转换证书格式成功");
|
||||
@@ -221,11 +206,11 @@ export abstract class CertApplyBasePlugin extends AbstractTaskPlugin {
|
||||
* 是否更新证书
|
||||
*/
|
||||
async condition() {
|
||||
if (this.forceUpdate) {
|
||||
this.logger.info("强制更新证书选项已勾选,准备申请新证书");
|
||||
this.logger.warn("申请完之后,切记取消强制更新,避免申请过多证书。");
|
||||
return null;
|
||||
}
|
||||
// if (this.forceUpdate) {
|
||||
// this.logger.info("强制更新证书选项已勾选,准备申请新证书");
|
||||
// this.logger.warn("申请完之后,切记取消强制更新,避免申请过多证书。");
|
||||
// return null;
|
||||
// }
|
||||
|
||||
let inputChanged = this.ctx.inputChanged;
|
||||
if (inputChanged) {
|
||||
@@ -303,7 +288,7 @@ export abstract class CertApplyBasePlugin extends AbstractTaskPlugin {
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否过期,默认提前20天
|
||||
* 检查是否过期,默认提前35天
|
||||
* @param expires
|
||||
* @param maxDays
|
||||
* @returns {boolean}
|
||||
|
||||
@@ -30,7 +30,7 @@ export class CertConverter {
|
||||
// 转der
|
||||
derPath = await this.convertDer(ctx);
|
||||
|
||||
//jksPath = await this.convertJks(ctx, opts.pfxPassword);
|
||||
jksPath = await this.convertJks(ctx, opts.pfxPassword);
|
||||
};
|
||||
|
||||
await certReader.readCertFile({ logger: this.logger, handle });
|
||||
@@ -106,8 +106,8 @@ export class CertConverter {
|
||||
const p12Path = path.join(os.tmpdir(), "/certd/tmp/", randomStr + `_cert.p12`);
|
||||
const { tmpCrtPath, tmpKeyPath } = opts;
|
||||
let passwordArg = "-passout pass:";
|
||||
if (pfxPassword) {
|
||||
passwordArg = `-password pass:${pfxPassword}`;
|
||||
if (jksPassword) {
|
||||
passwordArg = `-password pass:${jksPassword}`;
|
||||
}
|
||||
await this.exec(`openssl pkcs12 -export -in ${tmpCrtPath} -inkey ${tmpKeyPath} -out ${p12Path} -name certd ${passwordArg}`);
|
||||
|
||||
@@ -117,7 +117,7 @@ export class CertConverter {
|
||||
fs.mkdirSync(dir, { recursive: true });
|
||||
}
|
||||
await this.exec(
|
||||
`keytool -importkeystore -srckeystore ${p12Path} -srcstoretype PKCS12 -srcstorepass "${pfxPassword}" -destkeystore ${jksPath} -deststoretype PKCS12 -deststorepass "${jksPassword}" `
|
||||
`keytool -importkeystore -srckeystore ${p12Path} -srcstoretype PKCS12 -srcstorepass "${jksPassword}" -destkeystore ${jksPath} -deststoretype PKCS12 -deststorepass "${jksPassword}" `
|
||||
);
|
||||
fs.unlinkSync(p12Path);
|
||||
return jksPath;
|
||||
|
||||
@@ -17,7 +17,7 @@ RUN apk add --no-cache openjdk8
|
||||
WORKDIR /app/
|
||||
COPY --from=builder /workspace/certd-server/ /app/
|
||||
|
||||
ENV LEGO_VERSION=4.19.2
|
||||
ENV LEGO_VERSION 4.19.2
|
||||
ENV LEGO_DOWNLOAD_DIR /app/tools/lego
|
||||
RUN mkdir -p $LEGO_DOWNLOAD_DIR
|
||||
|
||||
@@ -31,9 +31,9 @@ RUN ARCH=$(uname -m) && \
|
||||
echo "Unsupported architecture: $ARCH"; \
|
||||
fi
|
||||
|
||||
ENV TZ=Asia/Shanghai
|
||||
ENV NODE_ENV=production
|
||||
ENV MIDWAY_SERVER_ENV=production
|
||||
ENV TZ Asia/Shanghai
|
||||
ENV NODE_ENV production
|
||||
ENV MIDWAY_SERVER_ENV production
|
||||
CMD ["npm", "run","start"]
|
||||
|
||||
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
link-workspace-packages=true
|
||||
link-workspace-packages=deep
|
||||
prefer-workspace-packages=true
|
||||
|
||||
@@ -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.27.6](https://github.com/certd/certd/compare/v1.27.5...v1.27.6) (2024-11-19)
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 当步骤全部都禁用时,任务本身显示删除线 ([9ab9a6e](https://github.com/certd/certd/commit/9ab9a6e8b083e19793894f23e59f29c604ec98e5))
|
||||
|
||||
## [1.27.5](https://github.com/certd/certd/compare/v1.27.4...v1.27.5) (2024-11-18)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 修复1Panel面板本身证书更新导致判定执行失败的问题 ([2689e6d](https://github.com/certd/certd/commit/2689e6d6c03aba21da90d5d45232c6ba08696be1))
|
||||
* 修复Cname情况下,无法使用DNS类型的bug ([26dad39](https://github.com/certd/certd/commit/26dad399d5768b3205da099ddc11809aef7d6224))
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 日志查看自动滚动到底部 ([4a2f7eb](https://github.com/certd/certd/commit/4a2f7ebf87b7c027cebff7cb763f8f35f6d2aa36))
|
||||
* 系统设置中的代理设置优化为可全局生效,环境变量中的https_proxy设置将无效 ([381a37f](https://github.com/certd/certd/commit/381a37fbaa6b61c887eda743897ae00afb825bdf))
|
||||
* 新手导航在非编辑模式下不显示 ([18bfcc2](https://github.com/certd/certd/commit/18bfcc24ad0bde57bb04db8a4209861ec6b8ff1d))
|
||||
* 专业版试用,无需绑定账号 ([c7c4318](https://github.com/certd/certd/commit/c7c4318c11b65a76089787aa58939832d338a232))
|
||||
|
||||
## [1.27.4](https://github.com/certd/certd/compare/v1.27.3...v1.27.4) (2024-11-14)
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 公共cname服务支持关闭 ([f4ae512](https://github.com/certd/certd/commit/f4ae5125dc4cd97816976779cb3586b5ee78947e))
|
||||
|
||||
## [1.27.3](https://github.com/certd/certd/compare/v1.27.2...v1.27.3) (2024-11-13)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 修复邮件配置,忽略证书校验设置不生效的bug ([66a9690](https://github.com/certd/certd/commit/66a9690dc958732e1b3c672d965db502296446f9))
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 修复站点个性化,浏览器标题没有生效的bug ([bcfac02](https://github.com/certd/certd/commit/bcfac02c96ceaf23d1a0b05b48d8047da933beaf))
|
||||
* 优化上传到主机插 路径选择,根据证书格式显示 ([8c3f86c](https://github.com/certd/certd/commit/8c3f86c6909ed91f48bb2880e78834e22f6f6a29))
|
||||
* ipv6支持 ([da6ac16](https://github.com/certd/certd/commit/da6ac1626b3574be2fabeeb18a1f10d60bdcbe49))
|
||||
|
||||
## [1.27.2](https://github.com/certd/certd/compare/v1.27.1...v1.27.2) (2024-11-08)
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@certd/ui-client",
|
||||
"version": "1.27.2",
|
||||
"version": "1.27.6",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "vite --open",
|
||||
@@ -26,10 +26,10 @@
|
||||
"dependencies": {
|
||||
"@ant-design/colors": "^7.0.2",
|
||||
"@ant-design/icons-vue": "^6.1.0",
|
||||
"@fast-crud/fast-crud": "^1.22.3",
|
||||
"@fast-crud/fast-extends": "^1.22.3",
|
||||
"@fast-crud/ui-antdv4": "^1.22.3",
|
||||
"@fast-crud/ui-interface": "^1.22.3",
|
||||
"@fast-crud/fast-crud": "^1.23.1",
|
||||
"@fast-crud/fast-extends": "^1.23.1",
|
||||
"@fast-crud/ui-antdv4": "^1.23.1",
|
||||
"@fast-crud/ui-interface": "^1.23.1",
|
||||
"@iconify/vue": "^4.1.1",
|
||||
"@soerenmartius/vue3-clipboard": "^0.1.2",
|
||||
"@vue-js-cron/light": "^4.0.5",
|
||||
@@ -65,8 +65,8 @@
|
||||
"vuedraggable": "^4.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@certd/lib-iframe": "^1.27.2",
|
||||
"@certd/pipeline": "^1.27.2",
|
||||
"@certd/lib-iframe": "^1.27.6",
|
||||
"@certd/pipeline": "^1.27.6",
|
||||
"@rollup/plugin-commonjs": "^25.0.7",
|
||||
"@rollup/plugin-node-resolve": "^15.2.3",
|
||||
"@types/chai": "^4.3.12",
|
||||
|
||||
@@ -40,6 +40,7 @@ if (props.modelValue == null) {
|
||||
}
|
||||
const emit = defineEmits<{
|
||||
"update:modelValue": any;
|
||||
change: any;
|
||||
}>();
|
||||
|
||||
const errorMessage = ref<string | null>(null);
|
||||
|
||||
@@ -6,6 +6,9 @@
|
||||
<div>1. 解析记录应该添加在{{ record.domain }}域名下</div>
|
||||
<div>2. 要添加的是CNAME类型的记录,不是TXT</div>
|
||||
<div>3. 核对记录值是否是:{{ record.recordValue }}</div>
|
||||
<div>
|
||||
4. 运行命令 <a-tag>nslookup -qa=txt {{ record.hostRecord }}{{ record.domain }}</a-tag> 查看解析配置是否正确
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<fs-icon class="ml-5 pointer" icon="mingcute:question-line"></fs-icon>
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
<span class="label">DNS类型:</span>
|
||||
<span class="input">
|
||||
<fs-dict-select
|
||||
v-model="item.dnsProviderType"
|
||||
v-model:value="item.dnsProviderType"
|
||||
size="small"
|
||||
:dict="dnsProviderTypeDict"
|
||||
placeholder="DNS提供商"
|
||||
@@ -79,6 +79,7 @@ import CnameVerifyPlan from "./cname-verify-plan.vue";
|
||||
import psl from "psl";
|
||||
import { Form } from "ant-design-vue";
|
||||
import { DomainsVerifyPlanInput } from "./type";
|
||||
import { CnameRecord } from "./api";
|
||||
defineOptions({
|
||||
name: "DomainsVerifyPlanEditor"
|
||||
});
|
||||
|
||||
@@ -158,7 +158,7 @@ const steps = ref<Step[]>([
|
||||
title: "设置定时执行",
|
||||
descriptions: [
|
||||
"流水线测试成功,接下来配置定时触发,以后每天定时执行就不用管了",
|
||||
"推荐配置每天运行一次,在到期前20天才会重新申请新证书并部署,没到期前会自动跳过,不会重复申请。"
|
||||
"推荐配置每天运行一次,在到期前35天才会重新申请新证书并部署,没到期前会自动跳过,不会重复申请。"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -7,3 +7,11 @@ export async function doActive(form: any) {
|
||||
data: form
|
||||
});
|
||||
}
|
||||
|
||||
export async function getVipTrial() {
|
||||
return await request({
|
||||
url: "/sys/plus/getVipTrial",
|
||||
method: "post",
|
||||
data: {}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -12,13 +12,14 @@
|
||||
</div>
|
||||
</template>
|
||||
<script lang="tsx" setup>
|
||||
import { computed, reactive, ref } from "vue";
|
||||
import { computed, reactive } from "vue";
|
||||
import dayjs from "dayjs";
|
||||
import { message, Modal } from "ant-design-vue";
|
||||
import * as api from "./api";
|
||||
import { useSettingStore } from "/@/store/modules/settings";
|
||||
import { useRouter } from "vue-router";
|
||||
import { useUserStore } from "/@/store/modules/user";
|
||||
|
||||
const settingStore = useSettingStore();
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
@@ -129,21 +130,27 @@ function goAccount() {
|
||||
router.push("/sys/account");
|
||||
}
|
||||
|
||||
async function getVipTrial() {
|
||||
const res = await api.getVipTrial();
|
||||
message.success(`恭喜,您已获得专业版${res.duration}天试用`);
|
||||
await settingStore.init();
|
||||
}
|
||||
|
||||
function openTrialModal() {
|
||||
Modal.destroyAll();
|
||||
|
||||
modal.confirm({
|
||||
title: "7天专业版试用获取",
|
||||
okText: "立即去绑定账号",
|
||||
okText: "立即获取",
|
||||
onOk() {
|
||||
goAccount();
|
||||
getVipTrial();
|
||||
},
|
||||
width: 600,
|
||||
content: () => {
|
||||
return (
|
||||
<div class="flex-col mt-10 mb-10">
|
||||
<div>感谢您对开源项目的支持</div>
|
||||
<div>绑定袖手账号后,即可获取7天专业版试用</div>
|
||||
<div>点击确认,即可获取7天专业版试用</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -69,7 +69,8 @@ router.afterEach((to: any) => {
|
||||
// }
|
||||
pageStore.open(to);
|
||||
// 更改标题
|
||||
site.title(to.meta.title);
|
||||
const settingStore = useSettingStore();
|
||||
site.title(to.meta.title, settingStore.siteInfo.title);
|
||||
|
||||
//修改左侧边栏
|
||||
const matched = to.matched;
|
||||
|
||||
@@ -3,7 +3,7 @@ import * as sites from "./util.site";
|
||||
import * as storages from "./util.storage";
|
||||
import commons from "./util.common";
|
||||
import * as mitt from "./util.mitt";
|
||||
import router from "/util.router";
|
||||
import { routerUtils } from "./util.router";
|
||||
import { treeUtils } from "./util.tree";
|
||||
export const util = {
|
||||
...envs,
|
||||
@@ -11,6 +11,6 @@ export const util = {
|
||||
...storages,
|
||||
...commons,
|
||||
...mitt,
|
||||
...router,
|
||||
router: routerUtils,
|
||||
tree: treeUtils
|
||||
};
|
||||
|
||||
@@ -33,5 +33,12 @@ export default {
|
||||
|
||||
async sleep(ms: number) {
|
||||
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||
},
|
||||
|
||||
maxLength(str?: string, length = 100) {
|
||||
if (str) {
|
||||
return str.length > length ? str.slice(0, length) + "..." : str;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
};
|
||||
|
||||
@@ -4,8 +4,8 @@ export const site = {
|
||||
* @description 更新标题
|
||||
* @param titleText
|
||||
*/
|
||||
title: function (titleText: string) {
|
||||
const processTitle = env.TITLE || "FsAdmin";
|
||||
title: function (titleText: string, baseTitle?: string) {
|
||||
const processTitle = baseTitle || env.TITLE || "Certd";
|
||||
window.document.title = `${processTitle}${titleText ? ` | ${titleText}` : ""}`;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -108,6 +108,7 @@ export default defineComponent({
|
||||
chooseForm.show = false;
|
||||
console.log("choose ok:", selectedId.value);
|
||||
refreshTarget(selectedId.value);
|
||||
ctx.emit("change", selectedId.value);
|
||||
ctx.emit("update:modelValue", selectedId.value);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -139,7 +139,9 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||
width: 300,
|
||||
cellRender: ({ row, value }) => {
|
||||
debugger;
|
||||
return <router-link to={{ path: "/certd/pipeline/detail", query: { id: row.pipelineId } }}>{value}</router-link>;
|
||||
return (
|
||||
<router-link to={{ path: "/certd/pipeline/detail", query: { id: row.pipelineId, editMode: false, historyId: row.id } }}>{value}</router-link>
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -348,6 +348,7 @@ export default function ({ crudExpose, context: { certdFormRef } }: CreateCrudOp
|
||||
type: "link",
|
||||
search: {
|
||||
show: true,
|
||||
title: "关键字",
|
||||
component: {
|
||||
name: "a-input"
|
||||
}
|
||||
|
||||
@@ -140,7 +140,7 @@ async function onLoaded(pipeline: PipelineDetail) {
|
||||
}
|
||||
const res = await api.GetCount();
|
||||
LocalStorage.set("pipeline-count", res.count);
|
||||
if (res.count <= 1) {
|
||||
if (res.count <= 1 && editMode.value === true) {
|
||||
await nextTick();
|
||||
tourHandleOpen(true);
|
||||
}
|
||||
|
||||
@@ -230,7 +230,7 @@ export default {
|
||||
}
|
||||
const { doComputed } = useCompute();
|
||||
const currentPlugin = doComputed(() => {
|
||||
return currentPluginDefine.value;
|
||||
return currentPluginDefine.value || {};
|
||||
}, getContext);
|
||||
const changeCurrentPlugin = async (step: any) => {
|
||||
const stepType = step.type;
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
<a key="edit" @click="stepEdit(currentTask, element, index)">编辑</a>
|
||||
<a key="edit" @click="stepCopy(currentTask, element, index)">复制</a>
|
||||
<a key="remove" @click="stepDelete(currentTask, index)">删除</a>
|
||||
<a key="disabled" @click="element.disabled = !!!element.disabled">{{ element.disabled ? "启用" : "禁用" }}</a>
|
||||
<a key="disabled" @click="toggleDisabled(currentTask, element)">{{ element.disabled ? "启用" : "禁用" }}</a>
|
||||
<fs-icon v-plus class="icon-button handle cursor-move" title="拖动排序" icon="ion:move-outline"></fs-icon>
|
||||
</div>
|
||||
</div>
|
||||
@@ -88,6 +88,7 @@ import { CopyOutlined } from "@ant-design/icons-vue";
|
||||
import VDraggable from "vuedraggable";
|
||||
import { useUserStore } from "/@/store/modules/user";
|
||||
import { useSettingStore } from "/@/store/modules/settings";
|
||||
import { filter } from "lodash-es";
|
||||
export default {
|
||||
name: "PiTaskForm",
|
||||
components: { CopyOutlined, PiStepForm, VDraggable },
|
||||
@@ -152,7 +153,11 @@ export default {
|
||||
});
|
||||
};
|
||||
|
||||
return { stepAdd, stepEdit, stepCopy, stepDelete, stepFormRef };
|
||||
const toggleDisabled = (task: any, step: any) => {
|
||||
step.disabled = !!!step.disabled;
|
||||
};
|
||||
|
||||
return { stepAdd, stepEdit, stepCopy, stepDelete, toggleDisabled, stepFormRef };
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -162,7 +167,7 @@ export default {
|
||||
function useTaskForm() {
|
||||
const mode = ref("add");
|
||||
const callback = ref();
|
||||
const currentTask = ref({ title: undefined, steps: [] });
|
||||
const currentTask = ref({ title: undefined, steps: [], disabled: false });
|
||||
provide("currentTask", currentTask);
|
||||
const taskFormRef: Ref<any> = ref(null);
|
||||
const taskDrawerVisible = ref(false);
|
||||
@@ -219,6 +224,15 @@ export default {
|
||||
console.error("表单验证失败:", e);
|
||||
return;
|
||||
}
|
||||
const task: any = currentTask.value;
|
||||
const allDisabled = filter(task.steps, (item: any) => {
|
||||
return item.disabled;
|
||||
});
|
||||
if (task.steps.length > 0 && task.steps.length === allDisabled.length) {
|
||||
task.disabled = true;
|
||||
} else {
|
||||
task.disabled = false;
|
||||
}
|
||||
|
||||
callback.value("save", currentTask.value);
|
||||
taskDrawerClose();
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<pi-status-show :status="item.node.status?.result" type="icon"></pi-status-show>
|
||||
</div>
|
||||
</template>
|
||||
<div class="pi-task-view-logs" style="overflow: auto">
|
||||
<div class="pi-task-view-logs" :class="item.node.id" style="overflow: auto">
|
||||
<template v-for="(logItem, index) of item.logs" :key="index">
|
||||
<span :class="logItem.color"> {{ logItem.time }}</span> <span>{{ logItem.content }}</span>
|
||||
</template>
|
||||
@@ -19,7 +19,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { computed, inject, Ref, ref } from "vue";
|
||||
import { computed, inject, nextTick, Ref, ref, watch } from "vue";
|
||||
import { RunHistory } from "../../type";
|
||||
import PiStatusShow from "/@/views/certd/pipeline/pipeline/component/status-show.vue";
|
||||
|
||||
@@ -78,6 +78,29 @@ export default {
|
||||
}
|
||||
return [];
|
||||
});
|
||||
|
||||
watch(
|
||||
() => {
|
||||
return node.logs.value.length;
|
||||
},
|
||||
async () => {
|
||||
let el = document.querySelector(`.pi-task-view-logs.${node.node.id}`);
|
||||
//判断当前是否在底部
|
||||
const isBottom = el ? el.scrollHeight - el.scrollTop === el.clientHeight : true;
|
||||
await nextTick();
|
||||
el = document.querySelector(`.pi-task-view-logs.${node.node.id}`);
|
||||
//如果在底部则滚动到底部
|
||||
if (isBottom && el) {
|
||||
el?.scrollTo({
|
||||
top: el.scrollHeight,
|
||||
behavior: "smooth"
|
||||
});
|
||||
}
|
||||
},
|
||||
{
|
||||
immediate: true
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -109,7 +109,7 @@
|
||||
</div>
|
||||
</template>
|
||||
<span class="flex-o w-100">
|
||||
<span class="ellipsis flex-1 task-title" :class="{ 'in-edit': editMode }">{{ task.title }}</span>
|
||||
<span class="ellipsis flex-1 task-title" :class="{ 'in-edit': editMode, deleted: task.disabled }">{{ task.title }}</span>
|
||||
<pi-status-show :status="task.status?.result"></pi-status-show>
|
||||
</span>
|
||||
</a-popover>
|
||||
@@ -304,7 +304,6 @@ export default defineComponent({
|
||||
}
|
||||
|
||||
const loadCurrentHistoryDetail = async () => {
|
||||
console.log("load history logs");
|
||||
const detail: RunHistory = await props.options?.getHistoryDetail({ historyId: currentHistory.value.id });
|
||||
currentHistory.value.logs = detail.logs;
|
||||
_.merge(currentHistory.value.pipeline, detail.pipeline);
|
||||
@@ -329,7 +328,6 @@ export default defineComponent({
|
||||
if (reload) {
|
||||
histories.value = [];
|
||||
}
|
||||
console.log("load history list");
|
||||
const historyList = await props.options.getHistoryList({ pipelineId: pipeline.value.id });
|
||||
if (!historyList) {
|
||||
return;
|
||||
@@ -885,6 +883,9 @@ export default defineComponent({
|
||||
&.in-edit {
|
||||
margin-right: 28px;
|
||||
}
|
||||
&.disabled{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
.action {
|
||||
|
||||
@@ -5,6 +5,7 @@ export type StatusEnumItem = {
|
||||
icon: string;
|
||||
spin?: boolean;
|
||||
iconSpin?: boolean;
|
||||
iconColor?: string;
|
||||
};
|
||||
export type StatusEnumType = {
|
||||
[key: string]: StatusEnumItem;
|
||||
|
||||
@@ -13,6 +13,8 @@ export type SysPublicSetting = {
|
||||
export type SysPrivateSetting = {
|
||||
httpProxy?: string;
|
||||
httpsProxy?: string;
|
||||
dnsResultOrder?: string;
|
||||
commonCnameEnabled?: boolean;
|
||||
};
|
||||
|
||||
export const SettingKeys = {
|
||||
@@ -52,6 +54,14 @@ export async function EmailSettingsGet() {
|
||||
});
|
||||
}
|
||||
|
||||
export async function EmailSettingsSave(setting: any) {
|
||||
return await request({
|
||||
url: apiPrefix + "/saveEmailSettings",
|
||||
method: "post",
|
||||
data: setting
|
||||
});
|
||||
}
|
||||
|
||||
export async function stopOtherUserTimer() {
|
||||
return await request({
|
||||
url: apiPrefix + "/stopOtherUserTimer",
|
||||
|
||||
@@ -8,16 +8,17 @@
|
||||
</template>
|
||||
|
||||
<div class="flex-o">
|
||||
<div v-if="!formState.usePlus" class="email-form">
|
||||
<a-form
|
||||
:model="formState"
|
||||
name="basic"
|
||||
:label-col="{ span: 8 }"
|
||||
:wrapper-col="{ span: 16 }"
|
||||
autocomplete="off"
|
||||
@finish="onFinish"
|
||||
@finish-failed="onFinishFailed"
|
||||
>
|
||||
<a-form
|
||||
:model="formState"
|
||||
name="basic"
|
||||
:label-col="{ span: 8 }"
|
||||
:wrapper-col="{ span: 16 }"
|
||||
autocomplete="off"
|
||||
class="email-form-box"
|
||||
@finish="onFinish"
|
||||
@finish-failed="onFinishFailed"
|
||||
>
|
||||
<div v-if="!formState.usePlus" class="email-form">
|
||||
<a-form-item label="使用自定义邮件服务器"> </a-form-item>
|
||||
<a-form-item label="SMTP域名" name="host" :rules="[{ required: true, message: '请输入smtp域名或ip' }]">
|
||||
<a-input v-model:value="formState.host" />
|
||||
@@ -41,32 +42,31 @@
|
||||
<a-switch v-model:checked="formState.secure" />
|
||||
<div class="helper">ssl和非ssl的smtp端口是不一样的,注意修改端口</div>
|
||||
</a-form-item>
|
||||
<a-form-item label="忽略证书校验" name="tls.rejectUnauthorized">
|
||||
<a-form-item label="忽略证书校验" :name="['tls', 'rejectUnauthorized']">
|
||||
<a-switch v-model:checked="formState.tls.rejectUnauthorized" />
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item :wrapper-col="{ offset: 8, span: 16 }">
|
||||
<a-button type="primary" html-type="submit">保存</a-button>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</div>
|
||||
<div class="email-form">
|
||||
<a-form :label-col="{ span: 8 }" :wrapper-col="{ span: 16 }">
|
||||
<a-form-item label="使用官方邮件服务器">
|
||||
</div>
|
||||
<div class="email-form">
|
||||
<a-form-item label="使用官方邮件服务器" name="usePlus">
|
||||
<div class="flex-o">
|
||||
<a-switch v-model:checked="formState.usePlus" :disabled="!settingStore.isPlus" @change="onUsePlusChanged" />
|
||||
<vip-button class="ml-5" mode="button"></vip-button>
|
||||
</div>
|
||||
<div class="helper">使用官方邮箱服务器直接发邮件,免除繁琐的配置</div>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</div>
|
||||
</div>
|
||||
</a-form>
|
||||
</div>
|
||||
<div class="email-form">
|
||||
<a-form :model="testFormState" name="basic" :label-col="{ span: 8 }" :wrapper-col="{ span: 16 }" autocomplete="off" @finish="onTestSend">
|
||||
<a-form-item label="测试收件邮箱" name="receiver" :rules="[{ required: true, message: '请输入测试收件邮箱' }]">
|
||||
<a-input v-model:value="testFormState.receiver" />
|
||||
<div class="helper">发送失败???可以试试使用官方邮件服务器↗↗↗↗↗↗↗↗</div>
|
||||
<div class="helper">发送失败???<a href="https://certd.docmirror.cn/guide/use/email/" target="_blank">邮件配置帮助文档</a></div>
|
||||
<div class="helper">您还可以试试使用官方邮件服务器↗↗↗↗↗↗↗↗</div>
|
||||
</a-form-item>
|
||||
<a-form-item :wrapper-col="{ offset: 8, span: 16 }">
|
||||
<a-button type="primary" :loading="testFormState.loading" html-type="submit">测试</a-button>
|
||||
@@ -79,7 +79,7 @@
|
||||
<script setup lang="ts">
|
||||
import { reactive } from "vue";
|
||||
import * as api from "../api";
|
||||
import { SettingKeys } from "../api";
|
||||
import { EmailSettingsSave, SettingKeys } from "../api";
|
||||
import * as emailApi from "./api.email";
|
||||
import { notification } from "ant-design-vue";
|
||||
import { useSettingStore } from "/src/store/modules/settings";
|
||||
@@ -122,7 +122,7 @@ load();
|
||||
|
||||
const onFinish = async (form: any) => {
|
||||
console.log("Success:", form);
|
||||
await api.SettingsSave(SettingKeys.SysEmail, form);
|
||||
await api.EmailSettingsSave(form);
|
||||
notification.success({
|
||||
message: "保存成功"
|
||||
});
|
||||
@@ -133,7 +133,7 @@ const onFinishFailed = (errorInfo: any) => {
|
||||
};
|
||||
|
||||
async function onUsePlusChanged() {
|
||||
await api.SettingsSave(SettingKeys.SysEmail, formState);
|
||||
await api.EmailSettingsSave(formState);
|
||||
}
|
||||
|
||||
interface TestFormState {
|
||||
@@ -161,6 +161,9 @@ const settingStore = useSettingStore();
|
||||
|
||||
<style lang="less">
|
||||
.page-setting-email {
|
||||
.email-form-box {
|
||||
display: flex;
|
||||
}
|
||||
.email-form {
|
||||
width: 500px;
|
||||
margin: 20px;
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
<a-form-item label="管理其他用户流水线" :name="['public', 'managerOtherUserPipeline']">
|
||||
<a-switch v-model:checked="formState.public.managerOtherUserPipeline" />
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item label="ICP备案号" :name="['public', 'icpNo']">
|
||||
<a-input v-model:value="formState.public.icpNo" placeholder="粤ICP备xxxxxxx号" />
|
||||
</a-form-item>
|
||||
@@ -37,8 +38,22 @@
|
||||
<a-input v-model:value="formState.private.httpsProxy" placeholder="http://192.168.1.2:18010/" />
|
||||
<a-button class="ml-5" type="primary" :loading="testProxyLoading" title="保存后,再点击测试" @click="testProxy">测试</a-button>
|
||||
</div>
|
||||
<div class="helper">一般这两个代理填一样的</div>
|
||||
<div class="helper">一般这两个代理填一样的,保存后再测试</div>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item label="双栈网络" :name="['private', 'dnsResultOrder']">
|
||||
<a-select v-model:value="formState.private.dnsResultOrder">
|
||||
<a-select-option value="verbatim">默认</a-select-option>
|
||||
<a-select-option value="ipv4first">IPV4优先</a-select-option>
|
||||
<a-select-option value="ipv6first">IPV6优先</a-select-option>
|
||||
</a-select>
|
||||
<div class="helper">如果选择IPv6优先,需要在docker-compose.yaml中启用ipv6</div>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item label="启用公共CNAME服务" :name="['private', 'commonCnameEnabled']">
|
||||
<a-switch v-model:checked="formState.private.commonCnameEnabled" />
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item :wrapper-col="{ offset: 8, span: 16 }">
|
||||
<a-button :loading="saveLoading" type="primary" html-type="submit">保存</a-button>
|
||||
</a-form-item>
|
||||
@@ -47,13 +62,14 @@
|
||||
</fs-page>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
<script setup lang="tsx">
|
||||
import { reactive, ref } from "vue";
|
||||
import * as api from "./api";
|
||||
import { SysSettings } from "./api";
|
||||
import { notification } from "ant-design-vue";
|
||||
import { useSettingStore } from "/@/store/modules/settings";
|
||||
import { merge } from "lodash-es";
|
||||
import { util } from "/@/utils";
|
||||
|
||||
defineOptions({
|
||||
name: "SysSettings"
|
||||
@@ -111,7 +127,25 @@ async function testProxy() {
|
||||
testProxyLoading.value = true;
|
||||
try {
|
||||
const res = await api.TestProxy();
|
||||
const content = `测试google:${res.google === true ? "成功" : "失败" + res.google},测试百度:${res.baidu === true ? "成功" : "失败:" + res.baidu}`;
|
||||
let success = true;
|
||||
if (res.google !== true || res.baidu !== true) {
|
||||
success = false;
|
||||
}
|
||||
const content = () => {
|
||||
return (
|
||||
<div>
|
||||
<div>Google: {res.google === true ? "成功" : util.maxLength(res.google)}</div>
|
||||
<div>Baidu: {res.baidu === true ? "成功" : util.maxLength(res.google)}</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
if (!success) {
|
||||
notification.error({
|
||||
message: "测试失败",
|
||||
description: content
|
||||
});
|
||||
return;
|
||||
}
|
||||
notification.success({
|
||||
message: "测试完成",
|
||||
description: content
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
link-workspace-packages=true
|
||||
link-workspace-packages=deep
|
||||
prefer-workspace-packages=true
|
||||
|
||||
@@ -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.27.6](https://github.com/certd/certd/compare/v1.27.5...v1.27.6) (2024-11-19)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* .env 读取 \r 问题 ([0e33dfa](https://github.com/certd/certd/commit/0e33dfa019a55ea76193c428ec756af386adeb9d))
|
||||
|
||||
## [1.27.5](https://github.com/certd/certd/compare/v1.27.4...v1.27.5) (2024-11-18)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 修复角色无法删除的bug ([66629a5](https://github.com/certd/certd/commit/66629a591aecc2d8364ea415c7afc3f9d0406562))
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 新手导航在非编辑模式下不显示 ([18bfcc2](https://github.com/certd/certd/commit/18bfcc24ad0bde57bb04db8a4209861ec6b8ff1d))
|
||||
* 优化腾讯云 cloudflare 重复解析记录时的返回值 ([90d1b68](https://github.com/certd/certd/commit/90d1b68bd6cf232fbe085234efe07d29b7690044))
|
||||
* 支持namesilo ([80159ec](https://github.com/certd/certd/commit/80159ecca895103d0495f3217311199e66056572))
|
||||
* 专业版试用,无需绑定账号 ([c7c4318](https://github.com/certd/certd/commit/c7c4318c11b65a76089787aa58939832d338a232))
|
||||
|
||||
## [1.27.4](https://github.com/certd/certd/compare/v1.27.3...v1.27.4) (2024-11-14)
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 公共cname服务支持关闭 ([f4ae512](https://github.com/certd/certd/commit/f4ae5125dc4cd97816976779cb3586b5ee78947e))
|
||||
|
||||
## [1.27.3](https://github.com/certd/certd/compare/v1.27.2...v1.27.3) (2024-11-13)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 修复偶发性cname一直验证超时的bug ([d2ce72e](https://github.com/certd/certd/commit/d2ce72e4aaacdf726ba8b91fcd71db40a27714ba))
|
||||
* 修复邮件配置,忽略证书校验设置不生效的bug ([66a9690](https://github.com/certd/certd/commit/66a9690dc958732e1b3c672d965db502296446f9))
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 优化上传到主机插 路径选择,根据证书格式显示 ([8c3f86c](https://github.com/certd/certd/commit/8c3f86c6909ed91f48bb2880e78834e22f6f6a29))
|
||||
|
||||
## [1.27.2](https://github.com/certd/certd/compare/v1.27.1...v1.27.2) (2024-11-08)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user