mirror of
https://github.com/certd/certd.git
synced 2026-04-07 08:20:54 +08:00
Compare commits
51 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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
|
||||
25
CHANGELOG.md
25
CHANGELOG.md
@@ -3,6 +3,31 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [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
|
||||
|
||||
@@ -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. 定时运行
|
||||

|
||||
|
||||
@@ -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. 可以用于商业用途。
|
||||
|
||||
@@ -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,36 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [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,6 +1,8 @@
|
||||
# 本地开发
|
||||
欢迎贡献插件
|
||||
|
||||
建议nodejs版本 `20.x` 及以上
|
||||
|
||||
## 1.本地调试运行
|
||||
|
||||
### 克隆代码
|
||||
|
||||
@@ -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记录。
|
||||
|
||||
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.4"
|
||||
}
|
||||
|
||||
@@ -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,14 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [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.4",
|
||||
"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.4",
|
||||
"@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": "1eb70d4cfd1ed2f746369658db2559fe01718324"
|
||||
}
|
||||
|
||||
@@ -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": ["."] }
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,16 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [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
|
||||
21:51
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@certd/basic",
|
||||
"private": false,
|
||||
"version": "1.27.2",
|
||||
"version": "1.27.4",
|
||||
"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": "1eb70d4cfd1ed2f746369658db2559fe01718324"
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
@@ -204,6 +207,14 @@ export type CreateAgentOptions = {
|
||||
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;
|
||||
if (httpProxy) {
|
||||
|
||||
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 '';
|
||||
},
|
||||
};
|
||||
@@ -3,6 +3,14 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [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.4",
|
||||
"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.4",
|
||||
"@certd/plus-core": "^1.27.4",
|
||||
"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": "1eb70d4cfd1ed2f746369658db2559fe01718324"
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -3,6 +3,14 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [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.4",
|
||||
"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": "1eb70d4cfd1ed2f746369658db2559fe01718324"
|
||||
}
|
||||
|
||||
@@ -3,6 +3,14 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [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.4",
|
||||
"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": "1eb70d4cfd1ed2f746369658db2559fe01718324"
|
||||
}
|
||||
|
||||
@@ -3,6 +3,14 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [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.4",
|
||||
"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.4",
|
||||
"@kubernetes/client-node": "0.21.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -30,5 +31,5 @@
|
||||
"tslib": "^2.8.1",
|
||||
"typescript": "^5.4.2"
|
||||
},
|
||||
"gitHead": "1d8515bce0b3ce5ece84db53ca57cfbd0c3f4d5a"
|
||||
"gitHead": "1eb70d4cfd1ed2f746369658db2559fe01718324"
|
||||
}
|
||||
|
||||
@@ -3,6 +3,18 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [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.4",
|
||||
"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.4",
|
||||
"@certd/basic": "^1.27.4",
|
||||
"@certd/pipeline": "^1.27.4",
|
||||
"@certd/plus-core": "^1.27.4",
|
||||
"@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": "1eb70d4cfd1ed2f746369658db2559fe01718324"
|
||||
}
|
||||
|
||||
@@ -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,14 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [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.4",
|
||||
"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": "1eb70d4cfd1ed2f746369658db2559fe01718324"
|
||||
}
|
||||
|
||||
@@ -3,6 +3,18 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [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.4",
|
||||
"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.4",
|
||||
"@certd/basic": "^1.27.4",
|
||||
"@certd/pipeline": "^1.27.4",
|
||||
"@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": "1eb70d4cfd1ed2f746369658db2559fe01718324"
|
||||
}
|
||||
|
||||
@@ -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,16 +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: "成功后邮件通知",
|
||||
@@ -152,28 +141,28 @@ export abstract class CertApplyBasePlugin extends AbstractTaskPlugin {
|
||||
}
|
||||
this._result.pipelinePrivateVars.cert = cert;
|
||||
|
||||
if (cert.pfx == null || cert.der == null) {
|
||||
if (cert.pfx == null || cert.der == null || cert.jks == null) {
|
||||
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);
|
||||
@@ -221,11 +210,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) {
|
||||
|
||||
@@ -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"]
|
||||
|
||||
|
||||
|
||||
@@ -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.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.4",
|
||||
"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.4",
|
||||
"@certd/pipeline": "^1.27.4",
|
||||
"@rollup/plugin-commonjs": "^25.0.7",
|
||||
"@rollup/plugin-node-resolve": "^15.2.3",
|
||||
"@types/chai": "^4.3.12",
|
||||
|
||||
@@ -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}` : ""}`;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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>
|
||||
@@ -39,6 +40,20 @@
|
||||
</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
|
||||
|
||||
@@ -3,6 +3,23 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [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
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@certd/ui-server",
|
||||
"version": "1.27.2",
|
||||
"version": "1.27.4",
|
||||
"description": "fast-server base midway",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
@@ -29,17 +29,17 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@alicloud/pop-core": "^1.7.10",
|
||||
"@certd/acme-client": "^1.27.2",
|
||||
"@certd/basic": "^1.27.2",
|
||||
"@certd/commercial-core": "^1.27.2",
|
||||
"@certd/lib-huawei": "^1.27.2",
|
||||
"@certd/lib-k8s": "^1.27.2",
|
||||
"@certd/lib-server": "^1.27.2",
|
||||
"@certd/midway-flyway-js": "^1.27.2",
|
||||
"@certd/pipeline": "^1.27.2",
|
||||
"@certd/plugin-cert": "^1.27.2",
|
||||
"@certd/plugin-plus": "^1.27.2",
|
||||
"@certd/plus-core": "^1.27.2",
|
||||
"@certd/acme-client": "^1.27.4",
|
||||
"@certd/basic": "^1.27.4",
|
||||
"@certd/commercial-core": "^1.27.4",
|
||||
"@certd/lib-huawei": "^1.27.4",
|
||||
"@certd/lib-k8s": "^1.27.4",
|
||||
"@certd/lib-server": "^1.27.4",
|
||||
"@certd/midway-flyway-js": "^1.27.4",
|
||||
"@certd/pipeline": "^1.27.4",
|
||||
"@certd/plugin-cert": "^1.27.4",
|
||||
"@certd/plugin-plus": "^1.27.4",
|
||||
"@certd/plus-core": "^1.27.4",
|
||||
"@huaweicloud/huaweicloud-sdk-cdn": "^3.1.120",
|
||||
"@huaweicloud/huaweicloud-sdk-core": "^3.1.120",
|
||||
"@koa/cors": "^5.0.0",
|
||||
|
||||
@@ -5,6 +5,7 @@ import { PipelineService } from '../../../modules/pipeline/service/pipeline-serv
|
||||
import { UserSettingsService } from '../../../modules/mine/service/user-settings-service.js';
|
||||
import { getEmailSettings } from '../../../modules/sys/settings/fix.js';
|
||||
import { http, logger } from '@certd/basic';
|
||||
import { merge } from 'lodash-es';
|
||||
|
||||
/**
|
||||
*/
|
||||
@@ -77,6 +78,14 @@ export class SysSettingsController extends CrudController<SysSettingsService> {
|
||||
return this.ok(conf);
|
||||
}
|
||||
|
||||
@Post('/saveEmailSettings', { summary: 'sys:settings:edit' })
|
||||
async saveEmailSettings(@Body(ALL) body) {
|
||||
const conf = await getEmailSettings(this.service, this.userSettingsService);
|
||||
merge(conf, body);
|
||||
await this.service.saveSetting(conf);
|
||||
return this.ok(conf);
|
||||
}
|
||||
|
||||
@Post('/getSysSettings', { summary: 'sys:settings:edit' })
|
||||
async getSysSettings() {
|
||||
const publicSettings = await this.service.getPublicSettings();
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Provide, Scope, ScopeEnum } from '@midwayjs/core';
|
||||
import { Inject, Provide, Scope, ScopeEnum } from '@midwayjs/core';
|
||||
import { InjectEntityModel } from '@midwayjs/typeorm';
|
||||
import { Repository } from 'typeorm';
|
||||
import { BaseService, ListReq, ValidateException } from '@certd/lib-server';
|
||||
import { BaseService, ListReq, SysPrivateSettings, SysSettingsService, ValidateException } from '@certd/lib-server';
|
||||
import { CnameProviderEntity } from '../entity/cname-provider.js';
|
||||
import { CommonProviders } from './common-provider.js';
|
||||
|
||||
@@ -14,6 +14,9 @@ export class CnameProviderService extends BaseService<CnameProviderEntity> {
|
||||
@InjectEntityModel(CnameProviderEntity)
|
||||
repository: Repository<CnameProviderEntity>;
|
||||
|
||||
@Inject()
|
||||
settingsService: SysSettingsService;
|
||||
|
||||
//@ts-ignore
|
||||
getRepository() {
|
||||
return this.repository;
|
||||
@@ -85,7 +88,10 @@ export class CnameProviderService extends BaseService<CnameProviderEntity> {
|
||||
if (founds && founds.length > 0) {
|
||||
return founds[0];
|
||||
}
|
||||
if (CommonProviders.length > 0) {
|
||||
|
||||
const sysPrivateSettings = await this.settingsService.getSetting<SysPrivateSettings>(SysPrivateSettings);
|
||||
|
||||
if (sysPrivateSettings.commonCnameEnabled !== false && CommonProviders.length > 0) {
|
||||
return CommonProviders[0] as CnameProviderEntity;
|
||||
}
|
||||
return null;
|
||||
@@ -93,8 +99,12 @@ export class CnameProviderService extends BaseService<CnameProviderEntity> {
|
||||
|
||||
async list(req: ListReq): Promise<any[]> {
|
||||
const list = await super.list(req);
|
||||
const sysPrivateSettings = await this.settingsService.getSetting<SysPrivateSettings>(SysPrivateSettings);
|
||||
|
||||
return [...list, ...CommonProviders];
|
||||
if (sysPrivateSettings.commonCnameEnabled !== false) {
|
||||
return [...list, ...CommonProviders];
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
async info(id: any, infoIgnoreProperty?: any): Promise<any | null> {
|
||||
|
||||
@@ -193,7 +193,7 @@ export class CnameRecordService extends BaseService<CnameRecordEntity> {
|
||||
startTime: new Date().getTime(),
|
||||
};
|
||||
}
|
||||
let ttl = 15 * 60 * 1000;
|
||||
let ttl = 5 * 60 * 1000;
|
||||
if (isDev()) {
|
||||
ttl = 30 * 1000;
|
||||
}
|
||||
@@ -233,6 +233,7 @@ export class CnameRecordService extends BaseService<CnameRecordEntity> {
|
||||
logger.warn(`cname验证超时,停止检查,${bean.domain} ${testRecordValue}`);
|
||||
clearInterval(value.intervalId);
|
||||
await this.updateStatus(bean.id, 'timeout');
|
||||
cache.delete(cacheKey);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,12 +17,47 @@ import path from 'path';
|
||||
},
|
||||
})
|
||||
export class CopyCertToLocalPlugin extends AbstractTaskPlugin {
|
||||
@TaskInput({
|
||||
title: '域名证书',
|
||||
helper: '请选择前置任务输出的域名证书',
|
||||
component: {
|
||||
name: 'output-selector',
|
||||
from: ['CertApply', 'CertApplyLego'],
|
||||
},
|
||||
required: true,
|
||||
})
|
||||
cert!: CertInfo;
|
||||
|
||||
@TaskInput({
|
||||
title: '证书类型',
|
||||
helper: '要部署的证书格式,支持pem、pfx、der、jks格式',
|
||||
component: {
|
||||
name: 'a-select',
|
||||
options: [
|
||||
{ value: 'pem', label: 'pem,用于Nginx等大部分应用' },
|
||||
{ value: 'pfx', label: 'pfx,一般用于IIS' },
|
||||
{ value: 'der', label: 'der,一般用于Apache' },
|
||||
{ value: 'jks', label: 'jks,一般用于JAVA应用' },
|
||||
],
|
||||
},
|
||||
required: true,
|
||||
})
|
||||
certType!: string;
|
||||
|
||||
@TaskInput({
|
||||
title: '证书保存路径',
|
||||
helper: '全链证书,路径要包含文件名' + '\n推荐使用相对路径,将写入与数据库同级目录,无需映射,例如:tmp/cert.pem',
|
||||
component: {
|
||||
placeholder: 'tmp/full_chain.pem',
|
||||
},
|
||||
mergeScript: `
|
||||
return {
|
||||
show: ctx.compute(({form})=>{
|
||||
return form.certType === 'pem';
|
||||
})
|
||||
}
|
||||
`,
|
||||
required: true,
|
||||
rules: [{ type: 'filepath' }],
|
||||
})
|
||||
crtPath!: string;
|
||||
@@ -32,6 +67,14 @@ export class CopyCertToLocalPlugin extends AbstractTaskPlugin {
|
||||
component: {
|
||||
placeholder: 'tmp/cert.key',
|
||||
},
|
||||
mergeScript: `
|
||||
return {
|
||||
show: ctx.compute(({form})=>{
|
||||
return form.certType === 'pem';
|
||||
})
|
||||
}
|
||||
`,
|
||||
required: true,
|
||||
rules: [{ type: 'filepath' }],
|
||||
})
|
||||
keyPath!: string;
|
||||
@@ -42,6 +85,13 @@ export class CopyCertToLocalPlugin extends AbstractTaskPlugin {
|
||||
component: {
|
||||
placeholder: '/root/deploy/nginx/intermediate.pem',
|
||||
},
|
||||
mergeScript: `
|
||||
return {
|
||||
show: ctx.compute(({form})=>{
|
||||
return form.certType === 'pem';
|
||||
})
|
||||
}
|
||||
`,
|
||||
rules: [{ type: 'filepath' }],
|
||||
})
|
||||
icPath!: string;
|
||||
@@ -52,6 +102,14 @@ export class CopyCertToLocalPlugin extends AbstractTaskPlugin {
|
||||
component: {
|
||||
placeholder: 'tmp/cert.pfx',
|
||||
},
|
||||
mergeScript: `
|
||||
return {
|
||||
show: ctx.compute(({form})=>{
|
||||
return form.certType === 'pfx';
|
||||
})
|
||||
}
|
||||
`,
|
||||
required: true,
|
||||
rules: [{ type: 'filepath' }],
|
||||
})
|
||||
pfxPath!: string;
|
||||
@@ -63,30 +121,35 @@ export class CopyCertToLocalPlugin extends AbstractTaskPlugin {
|
||||
component: {
|
||||
placeholder: 'tmp/cert.der 或 tmp/cert.cer',
|
||||
},
|
||||
mergeScript: `
|
||||
return {
|
||||
show: ctx.compute(({form})=>{
|
||||
return form.certType === 'der';
|
||||
})
|
||||
}
|
||||
`,
|
||||
required: true,
|
||||
rules: [{ type: 'filepath' }],
|
||||
})
|
||||
derPath!: string;
|
||||
|
||||
// @TaskInput({
|
||||
// title: 'jks证书保存路径',
|
||||
// helper: '用于java,路径要包含文件名,例如:tmp/cert.jks',
|
||||
// component: {
|
||||
// placeholder: 'tmp/cert.jks',
|
||||
// },
|
||||
// rules: [{ type: 'filepath' }],
|
||||
// })
|
||||
jksPath!: string;
|
||||
|
||||
@TaskInput({
|
||||
title: '域名证书',
|
||||
helper: '请选择前置任务输出的域名证书',
|
||||
title: 'jks证书保存路径',
|
||||
helper: '用于java,路径要包含文件名,例如:tmp/cert.jks',
|
||||
component: {
|
||||
name: 'output-selector',
|
||||
from: ['CertApply', 'CertApplyLego'],
|
||||
placeholder: 'tmp/cert.jks',
|
||||
},
|
||||
mergeScript: `
|
||||
return {
|
||||
show: ctx.compute(({form})=>{
|
||||
return form.certType === 'jks';
|
||||
})
|
||||
}
|
||||
`,
|
||||
required: true,
|
||||
rules: [{ type: 'filepath' }],
|
||||
})
|
||||
cert!: CertInfo;
|
||||
jksPath!: string;
|
||||
|
||||
@TaskOutput({
|
||||
title: '证书保存路径',
|
||||
|
||||
@@ -18,12 +18,47 @@ import dayjs from 'dayjs';
|
||||
},
|
||||
})
|
||||
export class UploadCertToHostPlugin extends AbstractTaskPlugin {
|
||||
@TaskInput({
|
||||
title: '域名证书',
|
||||
helper: '请选择前置任务输出的域名证书',
|
||||
component: {
|
||||
name: 'output-selector',
|
||||
from: ['CertApply', 'CertApplyLego'],
|
||||
},
|
||||
required: true,
|
||||
})
|
||||
cert!: CertInfo;
|
||||
|
||||
@TaskInput({
|
||||
title: '证书格式',
|
||||
helper: '要部署的证书格式,支持pem、pfx、der、jks',
|
||||
component: {
|
||||
name: 'a-select',
|
||||
options: [
|
||||
{ value: 'pem', label: 'pem,Nginx等大部分应用' },
|
||||
{ value: 'pfx', label: 'pfx,一般用于IIS' },
|
||||
{ value: 'der', label: 'der,一般用于Apache' },
|
||||
{ value: 'jks', label: 'jks,一般用于JAVA应用' },
|
||||
],
|
||||
},
|
||||
required: true,
|
||||
})
|
||||
certType!: string;
|
||||
|
||||
@TaskInput({
|
||||
title: '证书保存路径',
|
||||
helper: '全链证书,需要有写入权限,路径要包含证书文件名,例如:/tmp/cert.pem',
|
||||
helper: '填写应用原本的证书保存路径,路径要包含证书文件名,例如:/tmp/cert.pem',
|
||||
component: {
|
||||
placeholder: '/root/deploy/nginx/full_chain.pem',
|
||||
},
|
||||
mergeScript: `
|
||||
return {
|
||||
show: ctx.compute(({form})=>{
|
||||
return form.certType === 'pem';
|
||||
})
|
||||
}
|
||||
`,
|
||||
required: true,
|
||||
rules: [{ type: 'filepath' }],
|
||||
})
|
||||
crtPath!: string;
|
||||
@@ -33,6 +68,14 @@ export class UploadCertToHostPlugin extends AbstractTaskPlugin {
|
||||
component: {
|
||||
placeholder: '/root/deploy/nginx/cert.key',
|
||||
},
|
||||
mergeScript: `
|
||||
return {
|
||||
show: ctx.compute(({form})=>{
|
||||
return form.certType === 'pem';
|
||||
})
|
||||
}
|
||||
`,
|
||||
required: true,
|
||||
rules: [{ type: 'filepath' }],
|
||||
})
|
||||
keyPath!: string;
|
||||
@@ -43,50 +86,70 @@ export class UploadCertToHostPlugin extends AbstractTaskPlugin {
|
||||
component: {
|
||||
placeholder: '/root/deploy/nginx/intermediate.pem',
|
||||
},
|
||||
mergeScript: `
|
||||
return {
|
||||
show: ctx.compute(({form})=>{
|
||||
return form.certType === 'pem';
|
||||
})
|
||||
}
|
||||
`,
|
||||
rules: [{ type: 'filepath' }],
|
||||
})
|
||||
icPath!: string;
|
||||
|
||||
@TaskInput({
|
||||
title: 'PFX证书保存路径',
|
||||
helper: '用于IIS证书部署,需要有写入权限,路径要包含证书文件名,例如:/tmp/cert.pfx',
|
||||
helper: '填写应用原本的证书保存路径,路径要包含证书文件名,例如:D:\\iis\\cert.pfx',
|
||||
component: {
|
||||
placeholder: '/root/deploy/nginx/cert.pfx',
|
||||
placeholder: 'D:\\iis\\cert.pfx',
|
||||
},
|
||||
mergeScript: `
|
||||
return {
|
||||
show: ctx.compute(({form})=>{
|
||||
return form.certType === 'pfx';
|
||||
})
|
||||
}
|
||||
`,
|
||||
required: true,
|
||||
rules: [{ type: 'filepath' }],
|
||||
})
|
||||
pfxPath!: string;
|
||||
|
||||
@TaskInput({
|
||||
title: 'DER证书保存路径',
|
||||
helper: '用于Apache证书部署,需要有写入权限,路径要包含证书文件名,例如:/tmp/cert.der',
|
||||
helper: '填写应用原本的证书保存路径,路径要包含证书文件名,例如:/tmp/cert.der',
|
||||
component: {
|
||||
placeholder: '/root/deploy/nginx/cert.der',
|
||||
placeholder: '/root/deploy/apache/cert.der',
|
||||
},
|
||||
mergeScript: `
|
||||
return {
|
||||
show: ctx.compute(({form})=>{
|
||||
return form.certType === 'der';
|
||||
})
|
||||
}
|
||||
`,
|
||||
required: true,
|
||||
rules: [{ type: 'filepath' }],
|
||||
})
|
||||
derPath!: string;
|
||||
|
||||
// @TaskInput({
|
||||
// title: 'jks证书保存路径',
|
||||
// helper: '需要有写入权限,路径要包含证书文件名,例如:/tmp/cert.jks',
|
||||
// component: {
|
||||
// placeholder: '/root/deploy/nginx/cert.jks',
|
||||
// },
|
||||
// rules: [{ type: 'filepath' }],
|
||||
// })
|
||||
jksPath!: string;
|
||||
|
||||
@TaskInput({
|
||||
title: '域名证书',
|
||||
helper: '请选择前置任务输出的域名证书',
|
||||
title: 'jks证书保存路径',
|
||||
helper: '填写应用原本的证书保存路径,路径要包含证书文件名,例如:/tmp/cert.jks',
|
||||
component: {
|
||||
name: 'output-selector',
|
||||
from: ['CertApply', 'CertApplyLego'],
|
||||
placeholder: '/root/deploy/java_app/cert.jks',
|
||||
},
|
||||
mergeScript: `
|
||||
return {
|
||||
show: ctx.compute(({form})=>{
|
||||
return form.certType === 'jks';
|
||||
})
|
||||
}
|
||||
`,
|
||||
required: true,
|
||||
rules: [{ type: 'filepath' }],
|
||||
})
|
||||
cert!: CertInfo;
|
||||
jksPath!: string;
|
||||
|
||||
@TaskInput({
|
||||
title: '主机登录配置',
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from '@certd/pipeline';
|
||||
import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from '@certd/pipeline';
|
||||
import { CertInfo } from '@certd/plugin-cert';
|
||||
import { AbstractPlusTaskPlugin, createRemoteSelectInputDefine } from '@certd/plugin-plus';
|
||||
import { createRemoteSelectInputDefine } from '@certd/plugin-plus';
|
||||
import { TencentSslClient } from '../../lib/index.js';
|
||||
|
||||
@IsTaskPlugin({
|
||||
name: 'DeployCertToTencentCosPlugin',
|
||||
title: '部署证书到腾讯云COS',
|
||||
needPlus: true,
|
||||
needPlus: false,
|
||||
icon: 'svg:icon-tencentcloud',
|
||||
group: pluginGroups.tencent.key,
|
||||
desc: '部署到腾讯云COS源站域名证书【注意:很不稳定,需要重试很多次偶尔才能成功一次】',
|
||||
@@ -16,7 +16,7 @@ import { TencentSslClient } from '../../lib/index.js';
|
||||
},
|
||||
},
|
||||
})
|
||||
export class DeployCertToTencentCosPlugin extends AbstractPlusTaskPlugin {
|
||||
export class DeployCertToTencentCosPlugin extends AbstractTaskPlugin {
|
||||
/**
|
||||
* AccessProvider的id
|
||||
*/
|
||||
|
||||
5
step.md
5
step.md
@@ -5,7 +5,7 @@
|
||||
> 申请证书->部署证书->设置定时执行->设置邮件通知
|
||||
|
||||
## 准备工作
|
||||
1. 已部署CertD服务(可官方Demo自助注册体验 https://certd.handsfree.work/ )
|
||||
1. 已部署CertD服务(可官方Demo自助注册体验 https://certd.handfree.work/ )
|
||||
2. 注册一个域名(支持阿里云万网、腾讯云DnsPod、华为云)
|
||||
3. 准备好以上DNS解析服务商的AccessKey 和 AccessSecret
|
||||
4. 证书要部署的目标(可选,单纯当成证书申请工具用也不错)
|
||||
@@ -18,10 +18,7 @@
|
||||
需要添加域名的DNS解析服务商的授权
|
||||

|
||||
|
||||
填写accessKey和accessSecret
|
||||

|
||||
流水线创建成功
|
||||

|
||||
|
||||
### 2. 流水线详情界面
|
||||
|
||||
|
||||
Reference in New Issue
Block a user