mirror of
https://github.com/woodchen-ink/certimate.git
synced 2025-07-18 01:11:55 +08:00
Merge branch 'main' of https://github.com/certimate-go/certimate into certimate-go-main
This commit is contained in:
commit
926fc3da95
6
.github/ISSUE_TEMPLATE/1-bug_report.yml
vendored
6
.github/ISSUE_TEMPLATE/1-bug_report.yml
vendored
@ -11,14 +11,14 @@ body:
|
|||||||
|
|
||||||
**在提交 Issue 之前,请确认以下事项**:
|
**在提交 Issue 之前,请确认以下事项**:
|
||||||
1. 我**确认**已尝试过使用当前最新版本,并能复现问题。由于开发者精力有限,非当前最新版本的问题将被直接关闭,感谢理解。
|
1. 我**确认**已尝试过使用当前最新版本,并能复现问题。由于开发者精力有限,非当前最新版本的问题将被直接关闭,感谢理解。
|
||||||
2. 我**确认**已搜索过[已有的 Issues](https://github.com/usual2970/certimate/issues)(包括已关闭的),没有类似的问题。
|
2. 我**确认**已搜索过[已有的 Issues](https://github.com/certimate-go/certimate/issues)(包括已关闭的),没有类似的问题。
|
||||||
3. 我**确认**已阅读过[文档](https://docs.certimate.me/),没有类似的问题。
|
3. 我**确认**已阅读过[文档](https://docs.certimate.me/),没有类似的问题。
|
||||||
4. 请**务必**按照模板规范详细描述问题,否则 Issue 将会被直接关闭。
|
4. 请**务必**按照模板规范详细描述问题,否则 Issue 将会被直接关闭。
|
||||||
5. 请保持每个 Issue 只包含一个缺陷报告。如果有多个缺陷,请分别提交 Issue。
|
5. 请保持每个 Issue 只包含一个缺陷报告。如果有多个缺陷,请分别提交 Issue。
|
||||||
|
|
||||||
**Before you submit the issue, please make sure of the following checklist**:
|
**Before you submit the issue, please make sure of the following checklist**:
|
||||||
1. Yes, I'm using the latest release and can reproduce the issue. Issues that are not in the latest version will be closed directly.
|
1. Yes, I'm using the latest release and can reproduce the issue. Issues that are not in the latest version will be closed directly.
|
||||||
2. Yes, I've searched for [existing issues](https://github.com/usual2970/certimate/issues) (including closed ones) on GitHub and didn't find any similar.
|
2. Yes, I've searched for [existing issues](https://github.com/certimate-go/certimate/issues) (including closed ones) on GitHub and didn't find any similar.
|
||||||
3. Yes, I've read the [documentation](https://docs.certimate.me/en/) and didn't find any similar.
|
3. Yes, I've read the [documentation](https://docs.certimate.me/en/) and didn't find any similar.
|
||||||
4. Please describe the problem in detail according to the template specification, otherwise the issue will be closed directly.
|
4. Please describe the problem in detail according to the template specification, otherwise the issue will be closed directly.
|
||||||
5. Please limit one report per issue.
|
5. Please limit one report per issue.
|
||||||
@ -76,5 +76,5 @@ body:
|
|||||||
attributes:
|
attributes:
|
||||||
label: 贡献 / Contribution
|
label: 贡献 / Contribution
|
||||||
options:
|
options:
|
||||||
- label: 我乐意为此贡献代码! / I am interested in contributing to this issue!
|
- label: 我乐意为此贡献 PR! / I am interested in contributing a PR for this!
|
||||||
required: false
|
required: false
|
||||||
|
6
.github/ISSUE_TEMPLATE/2-feature_request.yml
vendored
6
.github/ISSUE_TEMPLATE/2-feature_request.yml
vendored
@ -11,14 +11,14 @@ body:
|
|||||||
|
|
||||||
**在提交 Issue 之前,请确认以下事项**:
|
**在提交 Issue 之前,请确认以下事项**:
|
||||||
1. 我**确认**是基于当前最新大版本而提出的新功能请求或改进意见。
|
1. 我**确认**是基于当前最新大版本而提出的新功能请求或改进意见。
|
||||||
2. 我**确认**已搜索过[已有的 Issues](https://github.com/usual2970/certimate/issues)(包括已关闭的),没有类似的问题。
|
2. 我**确认**已搜索过[已有的 Issues](https://github.com/certimate-go/certimate/issues)(包括已关闭的),没有类似的问题。
|
||||||
3. 我**确认**已阅读过[文档](https://docs.certimate.me/),没有类似的问题。
|
3. 我**确认**已阅读过[文档](https://docs.certimate.me/),没有类似的问题。
|
||||||
4. 请**务必**按照模板规范详细描述问题,否则 Issue 将会被直接关闭。
|
4. 请**务必**按照模板规范详细描述问题,否则 Issue 将会被直接关闭。
|
||||||
5. 请保持每个 Issue 只包含一个功能请求。如果有多个需求,请分别提交 Issue。
|
5. 请保持每个 Issue 只包含一个功能请求。如果有多个需求,请分别提交 Issue。
|
||||||
|
|
||||||
**Before you submit the issue, please make sure of the following checklist**:
|
**Before you submit the issue, please make sure of the following checklist**:
|
||||||
1. Yes, I'm using the latest release.
|
1. Yes, I'm using the latest release.
|
||||||
2. Yes, I've searched for [existing issues](https://github.com/usual2970/certimate/issues) (including closed ones) on GitHub and didn't find any similar.
|
2. Yes, I've searched for [existing issues](https://github.com/certimate-go/certimate/issues) (including closed ones) on GitHub and didn't find any similar.
|
||||||
3. Yes, I've read the [documentation](https://docs.certimate.me/en/) and didn't find any similar.
|
3. Yes, I've read the [documentation](https://docs.certimate.me/en/) and didn't find any similar.
|
||||||
4. Please describe the problem in detail according to the template specification, otherwise the issue will be closed directly.
|
4. Please describe the problem in detail according to the template specification, otherwise the issue will be closed directly.
|
||||||
5. Please limit one request per issue.
|
5. Please limit one request per issue.
|
||||||
@ -48,5 +48,5 @@ body:
|
|||||||
attributes:
|
attributes:
|
||||||
label: 贡献 / Contribution
|
label: 贡献 / Contribution
|
||||||
options:
|
options:
|
||||||
- label: 我乐意为此贡献代码! / I am interested in contributing to this issue!
|
- label: 我乐意为此贡献 PR! / I am interested in contributing a PR for this!
|
||||||
required: false
|
required: false
|
||||||
|
4
.github/ISSUE_TEMPLATE/3-questions.yml
vendored
4
.github/ISSUE_TEMPLATE/3-questions.yml
vendored
@ -9,14 +9,14 @@ body:
|
|||||||
|
|
||||||
**在提交 Issue 之前,请确认以下事项**:
|
**在提交 Issue 之前,请确认以下事项**:
|
||||||
1. 我**确认**正在使用的是当前最新版本。
|
1. 我**确认**正在使用的是当前最新版本。
|
||||||
2. 我**确认**已搜索过[已有的 Issues](https://github.com/usual2970/certimate/issues)(包括已关闭的),没有类似的问题。
|
2. 我**确认**已搜索过[已有的 Issues](https://github.com/certimate-go/certimate/issues)(包括已关闭的),没有类似的问题。
|
||||||
3. 我**确认**已阅读过[文档](https://docs.certimate.me/),没有类似的问题。
|
3. 我**确认**已阅读过[文档](https://docs.certimate.me/),没有类似的问题。
|
||||||
4. 请**务必**按照模板规范详细描述问题,否则 Issue 将会被直接关闭。
|
4. 请**务必**按照模板规范详细描述问题,否则 Issue 将会被直接关闭。
|
||||||
5. 请保持每个 Issue 只包含一个问题求助。如果有多个问题,请分别提交 Issue。
|
5. 请保持每个 Issue 只包含一个问题求助。如果有多个问题,请分别提交 Issue。
|
||||||
|
|
||||||
**Before you submit the issue, please make sure of the following checklist**:
|
**Before you submit the issue, please make sure of the following checklist**:
|
||||||
1. Yes, I'm using the latest release.
|
1. Yes, I'm using the latest release.
|
||||||
2. Yes, I've searched for [existing issues](https://github.com/usual2970/certimate/issues) (including closed ones) on GitHub and didn't find any similar.
|
2. Yes, I've searched for [existing issues](https://github.com/certimate-go/certimate/issues) (including closed ones) on GitHub and didn't find any similar.
|
||||||
3. Yes, I've read the [documentation](https://docs.certimate.me/en/) and didn't find any similar.
|
3. Yes, I've read the [documentation](https://docs.certimate.me/en/) and didn't find any similar.
|
||||||
4. Please describe the problem in detail according to the template specification, otherwise the issue will be closed directly.
|
4. Please describe the problem in detail according to the template specification, otherwise the issue will be closed directly.
|
||||||
5. Please limit one question per issue.
|
5. Please limit one question per issue.
|
||||||
|
@ -1,52 +0,0 @@
|
|||||||
# .goreleaser.linux.yml
|
|
||||||
project_name: certimate
|
|
||||||
|
|
||||||
dist: .builds/linux
|
|
||||||
|
|
||||||
before:
|
|
||||||
hooks:
|
|
||||||
- go mod tidy
|
|
||||||
|
|
||||||
builds:
|
|
||||||
- id: build_linux
|
|
||||||
main: ./
|
|
||||||
binary: certimate
|
|
||||||
ldflags:
|
|
||||||
- -s -w -X github.com/usual2970/certimate.Version={{ .Version }}
|
|
||||||
env:
|
|
||||||
- CGO_ENABLED=0
|
|
||||||
goos:
|
|
||||||
- linux
|
|
||||||
goarch:
|
|
||||||
- amd64
|
|
||||||
- arm64
|
|
||||||
- arm
|
|
||||||
goarm:
|
|
||||||
- 7
|
|
||||||
|
|
||||||
release:
|
|
||||||
draft: true
|
|
||||||
ids:
|
|
||||||
- linux
|
|
||||||
|
|
||||||
archives:
|
|
||||||
- id: archive_linux
|
|
||||||
builds: [build_linux]
|
|
||||||
format: "zip"
|
|
||||||
name_template: "{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}"
|
|
||||||
files:
|
|
||||||
- CHANGELOG.md
|
|
||||||
- LICENSE.md
|
|
||||||
- README.md
|
|
||||||
|
|
||||||
checksum:
|
|
||||||
name_template: "checksums_linux.txt"
|
|
||||||
|
|
||||||
snapshot:
|
|
||||||
name_template: "{{ incpatch .Version }}-next"
|
|
||||||
|
|
||||||
changelog:
|
|
||||||
sort: asc
|
|
||||||
filters:
|
|
||||||
exclude:
|
|
||||||
- "^ui:"
|
|
@ -1,49 +0,0 @@
|
|||||||
# .goreleaser.macos.yml
|
|
||||||
project_name: certimate
|
|
||||||
|
|
||||||
dist: .builds/macos
|
|
||||||
|
|
||||||
before:
|
|
||||||
hooks:
|
|
||||||
- go mod tidy
|
|
||||||
|
|
||||||
builds:
|
|
||||||
- id: build_macos
|
|
||||||
main: ./
|
|
||||||
binary: certimate
|
|
||||||
ldflags:
|
|
||||||
- -s -w -X github.com/usual2970/certimate.Version={{ .Version }}
|
|
||||||
env:
|
|
||||||
- CGO_ENABLED=0
|
|
||||||
goos:
|
|
||||||
- darwin
|
|
||||||
goarch:
|
|
||||||
- amd64
|
|
||||||
- arm64
|
|
||||||
|
|
||||||
release:
|
|
||||||
draft: true
|
|
||||||
ids:
|
|
||||||
- macos
|
|
||||||
|
|
||||||
archives:
|
|
||||||
- id: archive_macos
|
|
||||||
builds: [build_macos]
|
|
||||||
format: "zip"
|
|
||||||
name_template: "{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}"
|
|
||||||
files:
|
|
||||||
- CHANGELOG.md
|
|
||||||
- LICENSE.md
|
|
||||||
- README.md
|
|
||||||
|
|
||||||
checksum:
|
|
||||||
name_template: "checksums_macos.txt"
|
|
||||||
|
|
||||||
snapshot:
|
|
||||||
name_template: "{{ incpatch .Version }}-next"
|
|
||||||
|
|
||||||
changelog:
|
|
||||||
sort: asc
|
|
||||||
filters:
|
|
||||||
exclude:
|
|
||||||
- "^ui:"
|
|
@ -1,52 +0,0 @@
|
|||||||
# .goreleaser.windows.yml
|
|
||||||
project_name: certimate
|
|
||||||
|
|
||||||
dist: .builds/windows
|
|
||||||
|
|
||||||
before:
|
|
||||||
hooks:
|
|
||||||
- go mod tidy
|
|
||||||
|
|
||||||
builds:
|
|
||||||
- id: build_windows
|
|
||||||
main: ./
|
|
||||||
binary: certimate
|
|
||||||
ldflags:
|
|
||||||
- -s -w -X github.com/usual2970/certimate.Version={{ .Version }}
|
|
||||||
env:
|
|
||||||
- CGO_ENABLED=0
|
|
||||||
goos:
|
|
||||||
- windows
|
|
||||||
goarch:
|
|
||||||
- amd64
|
|
||||||
- arm64
|
|
||||||
ignore:
|
|
||||||
- goos: windows
|
|
||||||
goarch: arm
|
|
||||||
|
|
||||||
release:
|
|
||||||
draft: true
|
|
||||||
ids:
|
|
||||||
- windows
|
|
||||||
|
|
||||||
archives:
|
|
||||||
- id: archive_windows
|
|
||||||
builds: [build_windows]
|
|
||||||
format: "zip"
|
|
||||||
name_template: "{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}"
|
|
||||||
files:
|
|
||||||
- CHANGELOG.md
|
|
||||||
- LICENSE.md
|
|
||||||
- README.md
|
|
||||||
|
|
||||||
checksum:
|
|
||||||
name_template: "checksums_windows.txt"
|
|
||||||
|
|
||||||
snapshot:
|
|
||||||
name_template: "{{ incpatch .Version }}-next"
|
|
||||||
|
|
||||||
changelog:
|
|
||||||
sort: asc
|
|
||||||
filters:
|
|
||||||
exclude:
|
|
||||||
- "^ui:"
|
|
@ -11,7 +11,7 @@ builds:
|
|||||||
main: ./
|
main: ./
|
||||||
binary: certimate
|
binary: certimate
|
||||||
ldflags:
|
ldflags:
|
||||||
- -s -w -X github.com/usual2970/certimate.Version={{ .Version }}
|
- -s -w -X github.com/certimate-go/certimate.Version={{ .Version }}
|
||||||
env:
|
env:
|
||||||
- CGO_ENABLED=0
|
- CGO_ENABLED=0
|
||||||
goos:
|
goos:
|
||||||
@ -41,9 +41,9 @@ archives:
|
|||||||
builds: [build_noncgo]
|
builds: [build_noncgo]
|
||||||
format: "zip"
|
format: "zip"
|
||||||
files:
|
files:
|
||||||
- CHANGELOG.md
|
- LICENSE
|
||||||
- LICENSE.md
|
|
||||||
- README.md
|
- README.md
|
||||||
|
- CHANGELOG.md
|
||||||
|
|
||||||
checksum:
|
checksum:
|
||||||
name_template: "checksums.txt"
|
name_template: "checksums.txt"
|
||||||
|
@ -1 +1 @@
|
|||||||
A full changelog of past releases is available on [GitHub Releases](https://github.com/usual2970/certimate/releases) page.
|
A full changelog of past releases is available on [GitHub Releases](https://github.com/certimate-go/certimate/releases) page.
|
||||||
|
116
CONTRIBUTING.md
116
CONTRIBUTING.md
@ -1,76 +1,106 @@
|
|||||||
# 向 Certimate 贡献代码
|
# 贡献指南
|
||||||
|
|
||||||
感谢你抽出时间来改进 Certimate!以下是向 Certimate 主仓库提交 PR(Pull Request)时的操作指南。
|
非常感谢你抽出时间来帮助改进 Certimate!以下是向 Certimate 提交 Pull Request 时的操作指南。
|
||||||
|
|
||||||
- [向 Certimate 贡献代码](#向-certimate-贡献代码)
|
我们需要保持敏捷和快速迭代,同时也希望确保贡献者能获得尽可能流畅的参与体验。这份贡献指南旨在帮助你熟悉代码库和我们的工作方式,让你可以尽快进入有趣的开发环节。
|
||||||
- [前提条件](#前提条件)
|
|
||||||
- [修改 Go 代码](#修改-go-代码)
|
|
||||||
- [修改管理页面 (Admin UI)](#修改管理页面-admin-ui)
|
|
||||||
|
|
||||||
## 前提条件
|
索引:
|
||||||
|
|
||||||
- Go 1.24+ (用于修改 Go 代码)
|
- [开发](#开发)
|
||||||
- Node 20+ (用于修改 UI)
|
- [要求](#要求)
|
||||||
|
- [后端代码](#后端代码)
|
||||||
|
- [前端代码](#前端代码)
|
||||||
|
- [提交 PR](#提交-pr)
|
||||||
|
- [提交流程](#提交流程)
|
||||||
|
- [获取帮助](#获取帮助)
|
||||||
|
|
||||||
如果还没有这样做,你可以 fork Certimate 的主仓库,并克隆到本地以便进行修改:
|
---
|
||||||
|
|
||||||
```bash
|
## 开发
|
||||||
git clone https://github.com/your_username/certimate.git
|
|
||||||
```
|
|
||||||
|
|
||||||
> **重要提示:**
|
### 要求
|
||||||
> 建议为每个 Bug 修复或新功能创建一个从 `main` 分支派生的新分支。如果你计划提交多个 PR,请保持不同的改动在独立分支中,以便更容易进行代码审查并最终合并。
|
|
||||||
> 保持一个 PR 只实现一个功能。
|
|
||||||
|
|
||||||
## 修改 Go 代码
|
- Go 1.24+(用于修改后端代码)
|
||||||
|
- Node.js 22.0+(用于修改前端代码)
|
||||||
|
|
||||||
假设你已经对 Certimate 的 Go 代码做了一些修改,现在你想要运行它:
|
### 后端代码
|
||||||
|
|
||||||
1. 进入根目录
|
Certimate 的后端代码是使用 Golang 开发的,是一个基于 [Pocketbase](https://github.com/pocketbase/pocketbase) 构建的单体应用。
|
||||||
2. 运行以下命令启动服务:
|
|
||||||
|
|
||||||
|
假设你已经对 Certimate 的后端代码做出了一些修改,现在你想要运行它,请遵循以下步骤:
|
||||||
|
|
||||||
|
1. 进入根目录;
|
||||||
|
2. 安装依赖:
|
||||||
|
```bash
|
||||||
|
go mod vendor
|
||||||
|
```
|
||||||
|
3. 启动本地开发服务:
|
||||||
```bash
|
```bash
|
||||||
go run main.go serve
|
go run main.go serve
|
||||||
```
|
```
|
||||||
|
|
||||||
这将启动一个 Web 服务器,默认运行在 `http://localhost:8090`,并使用来自 `ui/dist` 的预构建管理页面。
|
这将启动一个 Web 服务器,默认运行在 `http://localhost:8090`,并使用来自 `/ui/dist` 的预构建管理页面。
|
||||||
|
|
||||||
**在向主仓库提交 PR 之前,建议你:**
|
> 如果你遇到报错 `ui/embed.go: pattern all:dist: no matching files found`,请参考“[前端代码](#前端代码)”这一小节构建 WebUI。
|
||||||
|
|
||||||
- 使用 [gofumpt](https://github.com/mvdan/gofumpt) 对你的代码进行格式化。
|
**在向主仓库提交 PR 之前,你应该:**
|
||||||
|
|
||||||
- 为你的改动添加单元测试或集成测试(Certimate 使用 Go 的标准 `testing` 包)。你可以通过以下命令运行测试(在项目根目录下):
|
- 使用 [gofumpt](https://github.com/mvdan/gofumpt) 格式化你的代码。推荐使用 VSCode,并安装 gofumpt 插件,以便在保存时自动格式化。
|
||||||
|
- 为你的改动添加单元测试或集成测试(使用 Go 标准库中的 `testing` 包)。
|
||||||
|
|
||||||
```bash
|
### 前端代码
|
||||||
go test ./...
|
|
||||||
```
|
|
||||||
|
|
||||||
## 修改管理页面 (Admin UI)
|
Certimate 的前端代码是使用 TypeScript 开发的,是一个基于 [React](https://github.com/facebook/react) 和 [Vite](https://github.com/vitejs/vite) 构建的单页应用。
|
||||||
|
|
||||||
Certimate 的管理页面是一个基于 React 和 Vite 构建的单页应用(SPA)。
|
假设你已经对 Certimate 的前端代码做出了一些修改,现在你想要运行它,请遵循以下步骤:
|
||||||
|
|
||||||
要启动 Admin UI:
|
|
||||||
|
|
||||||
1. 进入 `ui` 项目目录。
|
|
||||||
|
|
||||||
2. 运行 `npm install` 安装依赖。
|
|
||||||
|
|
||||||
|
1. 进入 `/ui` 目录;
|
||||||
|
2. 安装依赖:
|
||||||
|
```bash
|
||||||
|
npm install
|
||||||
|
```
|
||||||
3. 启动 Vite 开发服务器:
|
3. 启动 Vite 开发服务器:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm run dev
|
npm run dev
|
||||||
```
|
```
|
||||||
|
|
||||||
你可以通过浏览器访问 `http://localhost:5173` 来查看运行中的管理页面。
|
这将启动一个 Web 服务器,默认运行在 `http://localhost:5173`,你可以通过浏览器访问来查看运行中的 WebUI。
|
||||||
|
|
||||||
由于 Admin UI 只是一个客户端应用,运行时需要 Certimate 的后端服务作为支撑。你可以手动运行 Certimate,或者使用预构建的可执行文件。
|
完成修改后,运行以下命令来构建 WebUI,以便它能被嵌入到 Go 包中:
|
||||||
|
|
||||||
所有对 Admin UI 的修改将会自动反映在浏览器中,无需手动刷新页面。
|
|
||||||
|
|
||||||
完成修改后,运行以下命令来构建 Admin UI,以便它能被嵌入到 Go 包中:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm run build
|
npm run build
|
||||||
```
|
```
|
||||||
|
|
||||||
完成所有步骤后,你可以将改动提交 PR 到 Certimate 主仓库。
|
**在向主仓库提交 PR 之前,你应该:**
|
||||||
|
|
||||||
|
- 使用 [ESLint](https://github.com/eslint/eslint) 格式化你的代码。推荐使用 VSCode,并安装 ESLint+Prettier 插件,以便在保存时自动格式化。
|
||||||
|
|
||||||
|
## 提交 PR
|
||||||
|
|
||||||
|
在提交 PR 之前,请先创建一个 Issue 来讨论你的修改方案,并等待来自项目维护者的反馈。这样做有助于:
|
||||||
|
|
||||||
|
- 让我们充分理解你的修改内容;
|
||||||
|
- 评估修改是否符合项目路线图;
|
||||||
|
- 避免重复工作;
|
||||||
|
- 防止你投入时间到可能无法被合并的修改中。
|
||||||
|
|
||||||
|
### 提交流程
|
||||||
|
|
||||||
|
1. Fork 本仓库;
|
||||||
|
2. 在提交 PR 之前,请先发起 Issue 讨论你想要做的修改;
|
||||||
|
3. 为你的修改创建一个新的分支;
|
||||||
|
4. 请为你的修改添加相应的测试;
|
||||||
|
5. 确保你的代码能通过现有的测试;
|
||||||
|
6. 请在 PR 描述中关联相关 Issue;
|
||||||
|
7. 等待合并!
|
||||||
|
|
||||||
|
> [!IMPORTANT]
|
||||||
|
>
|
||||||
|
> 建议为每个新功能或 Bug 修复创建一个从 `main` 分支派生的新分支。如果你计划提交多个 PR,请保持不同的改动在独立分支中,以便更容易进行代码审查并最终合并。
|
||||||
|
>
|
||||||
|
> 保持一个 PR 只实现一个功能或修复。
|
||||||
|
|
||||||
|
## 获取帮助
|
||||||
|
|
||||||
|
如果你在贡献过程中遇到困难或问题,可以通过 GitHub Issues 向我们提问。
|
||||||
|
@ -1,81 +1,106 @@
|
|||||||
# Contributing to Certimate
|
# Contribution Guide
|
||||||
|
|
||||||
Thank you for taking the time to improve Certimate! Below is a guide for submitting a PR (Pull Request) to the main Certimate repository.
|
Thank you for taking the time to improve Certimate! Below is a guide for submitting a PR (Pull Request) to the Certimate repository.
|
||||||
|
|
||||||
- [Contributing to Certimate](#contributing-to-certimate)
|
We need to be nimble and ship fast given where we are, but we also want to make sure that contributors like you get as smooth an experience at contributing as possible. We've assembled this contribution guide for that purpose, aiming at getting you familiarized with the codebase & how we work with contributors, so you could quickly jump to the fun part.
|
||||||
|
|
||||||
|
Index:
|
||||||
|
|
||||||
|
- [Development](#development)
|
||||||
- [Prerequisites](#prerequisites)
|
- [Prerequisites](#prerequisites)
|
||||||
- [Making Changes in the Go Code](#making-changes-in-the-go-code)
|
- [Backend Code](#backend-code)
|
||||||
- [Making Changes in the Admin UI](#making-changes-in-the-admin-ui)
|
- [Frontend Code](#frontend-code)
|
||||||
|
- [Submitting PR](#submitting-pr)
|
||||||
|
- [Pull Request Process](#pull-request-process)
|
||||||
|
- [Getting Help](#getting-help)
|
||||||
|
|
||||||
## Prerequisites
|
---
|
||||||
|
|
||||||
- Go 1.24+ (for Go code changes)
|
## Development
|
||||||
- Node 20+ (for Admin UI changes)
|
|
||||||
|
|
||||||
If you haven't done so already, you can fork the Certimate repository and clone your fork to work locally:
|
### Prerequisites
|
||||||
|
|
||||||
```bash
|
- Go 1.24+ (for backend code changes)
|
||||||
git clone https://github.com/your_username/certimate.git
|
- Node.js 22.0+ (for frontend code changes)
|
||||||
```
|
|
||||||
|
|
||||||
> **Important:**
|
### Backend Code
|
||||||
> It is recommended to create a new branch from `main` for each bug fix or feature. If you plan to submit multiple PRs, ensure the changes are in separate branches for easier review and eventual merge.
|
|
||||||
> Keep each PR focused on a single feature or fix.
|
|
||||||
|
|
||||||
## Making Changes in the Go Code
|
The backend code of Certimate is developed using Golang. It is a monolithic application based on [Pocketbase](https://github.com/pocketbase/pocketbase).
|
||||||
|
|
||||||
Once you have made changes to the Go code in Certimate, follow these steps to run the project:
|
Once you have made changes to the backend code in Certimate, follow these steps to run the project:
|
||||||
|
|
||||||
1. Navigate to the root directory.
|
1. Navigate to the root directory.
|
||||||
|
2. Install dependencies:
|
||||||
2. Start the service by running:
|
```bash
|
||||||
|
go mod vendor
|
||||||
|
```
|
||||||
|
3. Start the local development server:
|
||||||
```bash
|
```bash
|
||||||
go run main.go serve
|
go run main.go serve
|
||||||
```
|
```
|
||||||
|
|
||||||
This will start a web server at `http://localhost:8090` using the prebuilt Admin UI located in `ui/dist`.
|
This will start a web server at `http://localhost:8090` using the prebuilt WebUI located in `/ui/dist`.
|
||||||
|
|
||||||
**Before submitting a PR to the main repository, consider:**
|
> If you encounter an error `ui/embed.go: pattern all:dist: no matching files found`, please refer to _[Frontend Code](#frontend-code)_ and build WebUI first.
|
||||||
|
|
||||||
- Format your source code by using [gofumpt](https://github.com/mvdan/gofumpt).
|
**Before submitting a PR to the main repository, you should:**
|
||||||
|
|
||||||
- Adding unit or integration tests for your changes. Certimate uses Go’s standard `testing` package. You can run tests using the following command (while in the root project directory):
|
- Format your source code by using [gofumpt](https://github.com/mvdan/gofumpt). Recommended using VSCode and installing the gofumpt plugin to automatically format when saving.
|
||||||
|
- Adding unit or integration tests for your changes (with go standard library `testing` package).
|
||||||
|
|
||||||
```bash
|
### Frontend Code
|
||||||
go test ./...
|
|
||||||
```
|
|
||||||
|
|
||||||
## Making Changes in the Admin UI
|
The frontend code of Certimate is developed using TypeScript. It is a SPA based on [React](https://github.com/facebook/react) and [Vite](https://github.com/vitejs/vite).
|
||||||
|
|
||||||
Certimate’s Admin UI is a single-page application (SPA) built using React and Vite.
|
Once you have made changes to the backend code in Certimate, follow these steps to run the project:
|
||||||
|
|
||||||
To start the Admin UI:
|
|
||||||
|
|
||||||
1. Navigate to the `ui` project directory.
|
|
||||||
|
|
||||||
2. Install the necessary dependencies by running:
|
|
||||||
|
|
||||||
|
1. Navigate to the `/ui` directory.
|
||||||
|
2. Install dependencies:
|
||||||
```bash
|
```bash
|
||||||
npm install
|
npm install
|
||||||
```
|
```
|
||||||
|
3. Start the local development server:
|
||||||
3. Start the Vite development server:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm run dev
|
npm run dev
|
||||||
```
|
```
|
||||||
|
|
||||||
You can now access the running Admin UI at `http://localhost:5173` in your browser.
|
This will start a web server at `http://localhost:5173`. You can now access the WebUI in your browser.
|
||||||
|
|
||||||
Since the Admin UI is a client-side application, you will also need to have the Certimate backend running. You can either manually run Certimate or use a prebuilt executable.
|
After completing your changes, build the WebUI so it can be embedded into the Go package:
|
||||||
|
|
||||||
Any changes you make in the Admin UI will be automatically reflected in the browser without requiring a page reload.
|
|
||||||
|
|
||||||
After completing your changes, build the Admin UI so it can be embedded into the Go package:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm run build
|
npm run build
|
||||||
```
|
```
|
||||||
|
|
||||||
Once all steps are completed, you are ready to submit a PR to the main Certimate repository.
|
**Before submitting a PR to the main repository, you should:**
|
||||||
|
|
||||||
|
- Format your source code by using [ESLint](https://github.com/eslint/eslint). Recommended using VSCode and installing the ESLint plugin to automatically format when saving.
|
||||||
|
|
||||||
|
## Submitting PR
|
||||||
|
|
||||||
|
Before opening a Pull Request, please open an issue to discuss the change and get feedback from the maintainers. This will helps us:
|
||||||
|
|
||||||
|
- To understand the context of the change.
|
||||||
|
- To ensure it fits into Certimate's roadmap.
|
||||||
|
- To prevent us from duplicating work.
|
||||||
|
- To prevent you from spending time on a change that we may not be able to accept.
|
||||||
|
|
||||||
|
### Pull Request Process
|
||||||
|
|
||||||
|
1. Fork the repository.
|
||||||
|
2. Before you draft a PR, please open an issue to discuss the changes you want to make.
|
||||||
|
3. Create a new branch for your changes.
|
||||||
|
4. Please add tests for your changes accordingly.
|
||||||
|
5. Ensure your code passes the existing tests.
|
||||||
|
6. Please link the issue in the PR description.
|
||||||
|
7. Get merged!
|
||||||
|
|
||||||
|
> [!IMPORTANT]
|
||||||
|
>
|
||||||
|
> It is recommended to create a new branch from `main` for each bug fix or feature. If you plan to submit multiple PRs, ensure the changes are in separate branches for easier review and eventual merge.
|
||||||
|
>
|
||||||
|
> Keep each PR focused on a single feature or fix.
|
||||||
|
|
||||||
|
## Getting Help
|
||||||
|
|
||||||
|
If you ever get stuck or get a burning question while contributing, simply shoot your queries our way via the GitHub issues.
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2025 certimate-go
|
||||||
Copyright (c) 2024 Yoan.Liu
|
Copyright (c) 2024 Yoan.Liu
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
39
README.md
39
README.md
@ -2,11 +2,11 @@
|
|||||||
|
|
||||||
<div align="center">
|
<div align="center">
|
||||||
|
|
||||||
[](https://github.com/usual2970/certimate)
|
[](https://github.com/certimate-go/certimate)
|
||||||
[](https://github.com/usual2970/certimate)
|
[](https://github.com/certimate-go/certimate)
|
||||||
[](https://hub.docker.com/r/usual2970/certimate)
|
[](https://hub.docker.com/r/certimate/certimate)
|
||||||
[](https://github.com/usual2970/certimate/releases)
|
[](https://github.com/certimate-go/certimate/releases)
|
||||||
[](https://mit-license.org/)
|
[](https://mit-license.org/)
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -49,7 +49,7 @@ Certimate 旨在为用户提供一个安全、简便的 SSL 证书管理解决
|
|||||||
- 支持单域名、多域名、泛域名证书,可选 RSA、ECC 签名算法;
|
- 支持单域名、多域名、泛域名证书,可选 RSA、ECC 签名算法;
|
||||||
- 支持 PEM、PFX、JKS 等多种格式输出证书;
|
- 支持 PEM、PFX、JKS 等多种格式输出证书;
|
||||||
- 支持 30+ 域名托管商(如阿里云、腾讯云、Cloudflare 等,[点此查看完整清单](https://docs.certimate.me/docs/reference/providers#supported-dns-providers));
|
- 支持 30+ 域名托管商(如阿里云、腾讯云、Cloudflare 等,[点此查看完整清单](https://docs.certimate.me/docs/reference/providers#supported-dns-providers));
|
||||||
- 支持 90+ 部署目标(如 Kubernetes、CDN、WAF、负载均衡等,[点此查看完整清单](https://docs.certimate.me/docs/reference/providers#supported-hosting-providers));
|
- 支持 100+ 部署目标(如 Kubernetes、CDN、WAF、负载均衡等,[点此查看完整清单](https://docs.certimate.me/docs/reference/providers#supported-hosting-providers));
|
||||||
- 支持邮件、钉钉、飞书、企业微信、Webhook 等多种通知渠道;
|
- 支持邮件、钉钉、飞书、企业微信、Webhook 等多种通知渠道;
|
||||||
- 支持 Let's Encrypt、Buypass、Google Trust Services、SSL.com、ZeroSSL 等多种 ACME 证书颁发机构;
|
- 支持 Let's Encrypt、Buypass、Google Trust Services、SSL.com、ZeroSSL 等多种 ACME 证书颁发机构;
|
||||||
- 更多特性等待探索。
|
- 更多特性等待探索。
|
||||||
@ -58,7 +58,7 @@ Certimate 旨在为用户提供一个安全、简便的 SSL 证书管理解决
|
|||||||
|
|
||||||
**5 分钟部署 Certimate!**
|
**5 分钟部署 Certimate!**
|
||||||
|
|
||||||
以二进制部署为例,从 [GitHub Releases](https://github.com/usual2970/certimate/releases) 页面下载预先编译好的二进制可执行文件压缩包,解压缩后在终端中执行:
|
以二进制部署为例,从 [GitHub Releases](https://github.com/certimate-go/certimate/releases) 页面下载预先编译好的二进制可执行文件压缩包,解压缩后在终端中执行:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
./certimate serve
|
./certimate serve
|
||||||
@ -81,10 +81,10 @@ Certimate 旨在为用户提供一个安全、简便的 SSL 证书管理解决
|
|||||||
|
|
||||||
相关文章:
|
相关文章:
|
||||||
|
|
||||||
- [使用 CNAME 完成 ACME DNS-01 质询](https://docs.certimate.me/blog/cname)
|
- [《使用 CNAME 完成 ACME DNS-01 质询》](https://docs.certimate.me/blog/cname)
|
||||||
- [v0.3.0:第二个不向后兼容的大版本](https://docs.certimate.me/blog/v0.3.0)
|
- [《v0.3.0:第二个不向后兼容的大版本》](https://docs.certimate.me/blog/v0.3.0)
|
||||||
- [v0.2.0:第一个不向后兼容的大版本](https://docs.certimate.me/blog/v0.2.0)
|
- [《v0.2.0:第一个不向后兼容的大版本》](https://docs.certimate.me/blog/v0.2.0)
|
||||||
- [Why Certimate?](https://docs.certimate.me/blog/why-certimate)
|
- [《Why Certimate?》](https://docs.certimate.me/blog/why-certimate)
|
||||||
|
|
||||||
## ⭐ 运行界面
|
## ⭐ 运行界面
|
||||||
|
|
||||||
@ -92,18 +92,19 @@ Certimate 旨在为用户提供一个安全、简便的 SSL 证书管理解决
|
|||||||
|
|
||||||
## 🤝 参与贡献
|
## 🤝 参与贡献
|
||||||
|
|
||||||
Certimate 是一个免费且开源的项目,采用 [MIT License](./LICENSE.md)。你可以使用它做任何你想做的事,甚至把它当作一个付费服务提供给用户。
|
Certimate 是一个免费且开源的项目。我们欢迎任何人为 Certimate 做出贡献,以帮助改善 Certimate。包括但不限于:提交代码、反馈缺陷、交流想法,或分享你基于 Certimate 的使用案例。同时,我们也欢迎用户在个人博客或社交媒体上分享 Certimate。
|
||||||
|
|
||||||
你可以通过以下方式来支持 Certimate 的开发:
|
如果你想要贡献代码,请先阅读我们的[贡献指南](./CONTRIBUTING.md)。
|
||||||
|
|
||||||
- 提交代码:如果你发现了 Bug 或有新的功能需求,而你又有相关经验,可以[提交代码](CONTRIBUTING.md)给我们。
|
请在 https://github.com/certimate-go/certimate 提交 [Issues](https://github.com/certimate-go/certimate/issues) 和 [Pull Requests](https://github.com/certimate-go/certimate/pulls)。
|
||||||
- 提交 Issue:功能建议或者 Bug 可以[提交 Issue](https://github.com/usual2970/certimate/issues) 给我们。
|
|
||||||
|
|
||||||
支持更多提供商、UI 的优化改进、Bug 修复、文档完善等,欢迎大家参与贡献。
|
#### 感谢以下贡献者对 Certimate 做出的贡献:
|
||||||
|
|
||||||
|
[](https://github.com/certimate-go/certimate/graphs/contributors)
|
||||||
|
|
||||||
## ⛔ 免责声明
|
## ⛔ 免责声明
|
||||||
|
|
||||||
Certimate 基于 [MIT License](https://opensource.org/licenses/MIT) 发布,完全免费提供,旨在“按现状”供用户使用。作者及贡献者不对使用本软件所产生的任何直接或间接后果承担责任,包括但不限于性能下降、数据丢失、服务中断、或任何其他类型的损害。
|
Certimate 遵循 [MIT License](https://opensource.org/licenses/MIT) 开源协议,完全免费提供,旨在“按现状”供用户使用。作者及贡献者不对使用本软件所产生的任何直接或间接后果承担责任,包括但不限于性能下降、数据丢失、服务中断、或任何其他类型的损害。
|
||||||
|
|
||||||
**无任何保证**:本软件不提供任何明示或暗示的保证,包括但不限于对特定用途的适用性、无侵权性、商用性及可靠性的保证。
|
**无任何保证**:本软件不提供任何明示或暗示的保证,包括但不限于对特定用途的适用性、无侵权性、商用性及可靠性的保证。
|
||||||
|
|
||||||
@ -114,8 +115,8 @@ Certimate 基于 [MIT License](https://opensource.org/licenses/MIT) 发布,完
|
|||||||
- [Telegram](https://t.me/+ZXphsppxUg41YmVl)
|
- [Telegram](https://t.me/+ZXphsppxUg41YmVl)
|
||||||
- 微信群聊(超 200 人需邀请入群,可先加作者好友)
|
- 微信群聊(超 200 人需邀请入群,可先加作者好友)
|
||||||
|
|
||||||
<img src="https://i.imgur.com/8xwsLTA.png" width="240"/>
|
<img src="https://i.imgur.com/8xwsLTA.png" width="200"/>
|
||||||
|
|
||||||
## 🚀 Star 趋势图
|
## 🚀 Star 趋势图
|
||||||
|
|
||||||
[](https://starchart.cc/usual2970/certimate)
|
[](https://starchart.cc/certimate-go/certimate)
|
||||||
|
41
README_EN.md
41
README_EN.md
@ -2,11 +2,11 @@
|
|||||||
|
|
||||||
<div align="center">
|
<div align="center">
|
||||||
|
|
||||||
[](https://github.com/usual2970/certimate)
|
[](https://github.com/certimate-go/certimate)
|
||||||
[](https://github.com/usual2970/certimate)
|
[](https://github.com/certimate-go/certimate)
|
||||||
[](https://hub.docker.com/r/usual2970/certimate)
|
[](https://hub.docker.com/r/certimate/certimate)
|
||||||
[](https://github.com/usual2970/certimate/releases)
|
[](https://github.com/certimate-go/certimate/releases)
|
||||||
[](https://mit-license.org/)
|
[](https://mit-license.org/)
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -39,7 +39,7 @@ Certimate aims to provide users with a secure and user-friendly SSL certificate
|
|||||||
- Supports single-domain, multi-domain, wildcard certificates, with options for RSA or ECC.
|
- Supports single-domain, multi-domain, wildcard certificates, with options for RSA or ECC.
|
||||||
- Supports various certificate formats such as PEM, PFX, JKS.
|
- Supports various certificate formats such as PEM, PFX, JKS.
|
||||||
- Supports more than 30+ domain registrars (e.g., Alibaba Cloud, Tencent Cloud, Cloudflare, etc. [Check out this link](https://docs.certimate.me/en/docs/reference/providers#supported-dns-providers));
|
- Supports more than 30+ domain registrars (e.g., Alibaba Cloud, Tencent Cloud, Cloudflare, etc. [Check out this link](https://docs.certimate.me/en/docs/reference/providers#supported-dns-providers));
|
||||||
- Supports more than 90+ deployment targets (e.g., Kubernetes, CDN, WAF, load balancers, etc. [Check out this link](https://docs.certimate.me/en/docs/reference/providers#supported-hosting-providers));
|
- Supports more than 100+ deployment targets (e.g., Kubernetes, CDN, WAF, load balancers, etc. [Check out this link](https://docs.certimate.me/en/docs/reference/providers#supported-hosting-providers));
|
||||||
- Supports multiple notification channels including email, DingTalk, Feishu, WeCom, Webhook, and more;
|
- Supports multiple notification channels including email, DingTalk, Feishu, WeCom, Webhook, and more;
|
||||||
- Supports multiple ACME CAs including Let's Encrypt, Buypass, Google Trust Services,SSL.com, ZeroSSL, and more;
|
- Supports multiple ACME CAs including Let's Encrypt, Buypass, Google Trust Services,SSL.com, ZeroSSL, and more;
|
||||||
- More features waiting to be discovered.
|
- More features waiting to be discovered.
|
||||||
@ -48,7 +48,7 @@ Certimate aims to provide users with a secure and user-friendly SSL certificate
|
|||||||
|
|
||||||
**Deploy Certimate in 5 minutes!**
|
**Deploy Certimate in 5 minutes!**
|
||||||
|
|
||||||
Download the archived package of precompiled binary files directly from [GitHub Releases](https://github.com/usual2970/certimate/releases), extract and then execute:
|
Download the archived package of precompiled binary files directly from [GitHub Releases](https://github.com/certimate-go/certimate/releases), extract and then execute:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
./certimate serve
|
./certimate serve
|
||||||
@ -65,14 +65,14 @@ Work with Certimate right now. Or read other content in the documentation to lea
|
|||||||
|
|
||||||
## 📄 Documentation
|
## 📄 Documentation
|
||||||
|
|
||||||
Please visit the documentation site [docs.certimate.me](https://docs.certimate.me/en/).
|
For full documentation, please visit [docs.certimate.me](https://docs.certimate.me/en/).
|
||||||
|
|
||||||
Related articles:
|
Related articles:
|
||||||
|
|
||||||
- [使用 CNAME 完成 ACME DNS-01 质询](https://docs.certimate.me/blog/cname)
|
- [_使用 CNAME 完成 ACME DNS-01 质询_](https://docs.certimate.me/blog/cname)
|
||||||
- [v0.3.0:第二个不向后兼容的大版本](https://docs.certimate.me/blog/v0.3.0)
|
- [_v0.3.0:第二个不向后兼容的大版本_](https://docs.certimate.me/blog/v0.3.0)
|
||||||
- [v0.2.0:第一个不向后兼容的大版本](https://docs.certimate.me/blog/v0.2.0)
|
- [_v0.2.0:第一个不向后兼容的大版本_](https://docs.certimate.me/blog/v0.2.0)
|
||||||
- [Why Certimate?](https://docs.certimate.me/blog/why-certimate)
|
- [_Why Certimate?_](https://docs.certimate.me/blog/why-certimate)
|
||||||
|
|
||||||
## ⭐ Screenshot
|
## ⭐ Screenshot
|
||||||
|
|
||||||
@ -80,18 +80,19 @@ Related articles:
|
|||||||
|
|
||||||
## 🤝 Contributing
|
## 🤝 Contributing
|
||||||
|
|
||||||
Certimate is a free and open-source project, licensed under the [MIT License](./LICENSE.md). You can use it for anything you want, even offering it as a paid service to users.
|
Certimate is a free and open-source project, and your feedback and contributions are needed and always welcome. Contributions include but are not limited to: submitting code, reporting bugs, sharing ideas, or showcasing your use cases based on Certimate. We also encourage users to share Certimate on personal blogs or social media.
|
||||||
|
|
||||||
You can support the development of Certimate in the following ways:
|
For those who'd like to contribute code, see our [Contribution Guide](./CONTRIBUTING_EN.md).
|
||||||
|
|
||||||
- **Submit Code**: If you find a bug or have new feature requests, and you have relevant experience, [you can submit code to us](CONTRIBUTING_EN.md).
|
[Issues](https://github.com/certimate-go/certimate/issues) and [Pull Requests](https://github.com/certimate-go/certimate/pulls) are opened at https://github.com/certimate-go/certimate.
|
||||||
- **Submit an Issue**: For feature suggestions or bugs, you can [submit an issue](https://github.com/usual2970/certimate/issues) to us.
|
|
||||||
|
|
||||||
Support for more service providers, UI enhancements, bug fixes, and documentation improvements are all welcome. We encourage everyone to contribute.
|
#### Contributors
|
||||||
|
|
||||||
|
[](https://github.com/certimate-go/certimate/graphs/contributors)
|
||||||
|
|
||||||
## ⛔ Disclaimer
|
## ⛔ Disclaimer
|
||||||
|
|
||||||
This software is provided under the [MIT License](https://opensource.org/licenses/MIT) and distributed “as-is” without any warranty of any kind. The authors and contributors are not responsible for any damages or losses resulting from the use or inability to use this software, including but not limited to data loss, business interruption, or any other potential harm.
|
This repository is available under the [MIT License](https://opensource.org/licenses/MIT), and distributed “as-is” without any warranty of any kind. The authors and contributors are not responsible for any damages or losses resulting from the use or inability to use this software, including but not limited to data loss, business interruption, or any other potential harm.
|
||||||
|
|
||||||
**No Warranties**: This software comes without any express or implied warranties, including but not limited to implied warranties of merchantability, fitness for a particular purpose, and non-infringement.
|
**No Warranties**: This software comes without any express or implied warranties, including but not limited to implied warranties of merchantability, fitness for a particular purpose, and non-infringement.
|
||||||
|
|
||||||
@ -102,8 +103,8 @@ This software is provided under the [MIT License](https://opensource.org/license
|
|||||||
- [Telegram](https://t.me/+ZXphsppxUg41YmVl)
|
- [Telegram](https://t.me/+ZXphsppxUg41YmVl)
|
||||||
- Wechat Group
|
- Wechat Group
|
||||||
|
|
||||||
<img src="https://i.imgur.com/zSHEoIm.png" width="240"/>
|
<img src="https://i.imgur.com/zSHEoIm.png" width="200"/>
|
||||||
|
|
||||||
## 🚀 Star History
|
## 🚀 Star History
|
||||||
|
|
||||||
[](https://starchart.cc/usual2970/certimate)
|
[](https://starchart.cc/certimate-go/certimate)
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
version: "3.0"
|
version: "3.0"
|
||||||
services:
|
services:
|
||||||
certimate:
|
certimate:
|
||||||
image: registry.cn-shanghai.aliyuncs.com/usual2970/certimate:latest
|
image: certimate/certimate:latest
|
||||||
container_name: certimate_server
|
container_name: certimate
|
||||||
ports:
|
ports:
|
||||||
- 8090:8090
|
- 8090:8090
|
||||||
volumes:
|
volumes:
|
||||||
|
11
go.mod
11
go.mod
@ -1,4 +1,4 @@
|
|||||||
module github.com/usual2970/certimate
|
module github.com/certimate-go/certimate
|
||||||
|
|
||||||
go 1.24.0
|
go 1.24.0
|
||||||
|
|
||||||
@ -30,6 +30,7 @@ require (
|
|||||||
github.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible
|
github.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible
|
||||||
github.com/aws/aws-sdk-go-v2/service/acm v1.32.0
|
github.com/aws/aws-sdk-go-v2/service/acm v1.32.0
|
||||||
github.com/aws/aws-sdk-go-v2/service/cloudfront v1.46.1
|
github.com/aws/aws-sdk-go-v2/service/cloudfront v1.46.1
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/iam v1.42.0
|
||||||
github.com/baidubce/bce-sdk-go v0.9.228
|
github.com/baidubce/bce-sdk-go v0.9.228
|
||||||
github.com/blinkbean/dingtalk v1.1.3
|
github.com/blinkbean/dingtalk v1.1.3
|
||||||
github.com/byteplus-sdk/byteplus-sdk-golang v1.0.46
|
github.com/byteplus-sdk/byteplus-sdk-golang v1.0.46
|
||||||
@ -51,6 +52,7 @@ require (
|
|||||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cdn v1.0.1155
|
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cdn v1.0.1155
|
||||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/clb v1.0.1166
|
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/clb v1.0.1166
|
||||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1173
|
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1173
|
||||||
|
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/gaap v1.0.1163
|
||||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/live v1.0.1150
|
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/live v1.0.1150
|
||||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/scf v1.0.1172
|
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/scf v1.0.1172
|
||||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssl v1.0.1169
|
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssl v1.0.1169
|
||||||
@ -85,7 +87,6 @@ require (
|
|||||||
github.com/alibabacloud-go/tea-oss-utils v1.1.0 // indirect
|
github.com/alibabacloud-go/tea-oss-utils v1.1.0 // indirect
|
||||||
github.com/alibabacloud-go/tea-utils/v2 v2.0.7 // indirect
|
github.com/alibabacloud-go/tea-utils/v2 v2.0.7 // indirect
|
||||||
github.com/avast/retry-go v3.0.0+incompatible // indirect
|
github.com/avast/retry-go v3.0.0+incompatible // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/service/iam v1.42.0 // indirect
|
|
||||||
github.com/aws/aws-sdk-go-v2/service/route53 v1.50.0 // indirect
|
github.com/aws/aws-sdk-go-v2/service/route53 v1.50.0 // indirect
|
||||||
github.com/buger/goterm v1.0.4 // indirect
|
github.com/buger/goterm v1.0.4 // indirect
|
||||||
github.com/diskfs/go-diskfs v1.5.0 // indirect
|
github.com/diskfs/go-diskfs v1.5.0 // indirect
|
||||||
@ -218,8 +219,8 @@ require (
|
|||||||
modernc.org/sqlite v1.37.1 // indirect
|
modernc.org/sqlite v1.37.1 // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
replace github.com/Edgio/edgio-api v0.0.0-workspace => ./internal/pkg/sdk3rd/edgio/edgio-api@v0.0.0-workspace
|
replace github.com/Edgio/edgio-api v0.0.0-workspace => ./pkg/sdk3rd/edgio/edgio-api@v0.0.0-workspace
|
||||||
|
|
||||||
replace gitlab.ecloud.com/ecloud/ecloudsdkcore v1.0.0 => ./internal/pkg/sdk3rd/cmcc/ecloudsdkcore@v1.0.0
|
replace gitlab.ecloud.com/ecloud/ecloudsdkcore v1.0.0 => ./pkg/sdk3rd/cmcc/ecloudsdkcore@v1.0.0
|
||||||
|
|
||||||
replace gitlab.ecloud.com/ecloud/ecloudsdkclouddns v1.0.1 => ./internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1
|
replace gitlab.ecloud.com/ecloud/ecloudsdkclouddns v1.0.1 => ./pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1
|
||||||
|
3
go.sum
3
go.sum
@ -836,6 +836,7 @@ github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/clb v1.0.1166/go.mod h1
|
|||||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1128/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
|
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1128/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
|
||||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1150/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
|
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1150/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
|
||||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1155/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
|
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1155/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
|
||||||
|
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1163/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
|
||||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1164/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
|
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1164/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
|
||||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1166/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
|
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1166/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
|
||||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1169/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
|
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1169/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
|
||||||
@ -845,6 +846,8 @@ github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1173 h1:W5b
|
|||||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1173/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
|
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1173/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
|
||||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1128 h1:mrJ5Fbkd7sZIJ5F6oRfh5zebPQaudPH9Y0+GUmFytYU=
|
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1128 h1:mrJ5Fbkd7sZIJ5F6oRfh5zebPQaudPH9Y0+GUmFytYU=
|
||||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1128/go.mod h1:zbsYIBT+VTX4z4ocjTAdLBIWyNYj3z0BRqd0iPdnjsk=
|
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1128/go.mod h1:zbsYIBT+VTX4z4ocjTAdLBIWyNYj3z0BRqd0iPdnjsk=
|
||||||
|
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/gaap v1.0.1163 h1:putqrH5n1SVRqFWHOylVqYI5yLQUjRTkHqZPLT2yeVY=
|
||||||
|
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/gaap v1.0.1163/go.mod h1:aEWRXlAvovPUUoS3kVB/LVWEQ19WqzTj2lXGvR1YArY=
|
||||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/live v1.0.1150 h1:RQQYfZOFYlkxKR2+xp8el3+8xs9DhxBy+ajlHtapqtQ=
|
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/live v1.0.1150 h1:RQQYfZOFYlkxKR2+xp8el3+8xs9DhxBy+ajlHtapqtQ=
|
||||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/live v1.0.1150/go.mod h1:zpfr6EBWy7ClASTGUgIy01Gn4R79UXf+2QGQeyR124A=
|
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/live v1.0.1150/go.mod h1:zpfr6EBWy7ClASTGUgIy01Gn4R79UXf+2QGQeyR124A=
|
||||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/scf v1.0.1172 h1:6SUO0hTie3zxnUEMxmhnS1iRIXpAukSZV27Nrx4NwIk=
|
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/scf v1.0.1172 h1:6SUO0hTie3zxnUEMxmhnS1iRIXpAukSZV27Nrx4NwIk=
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package applicant
|
package applicant
|
||||||
|
|
||||||
import "github.com/usual2970/certimate/internal/domain"
|
import "github.com/certimate-go/certimate/internal/domain"
|
||||||
|
|
||||||
const (
|
const (
|
||||||
caLetsEncrypt = string(domain.CAProviderTypeLetsEncrypt)
|
caLetsEncrypt = string(domain.CAProviderTypeLetsEncrypt)
|
||||||
|
@ -13,10 +13,10 @@ import (
|
|||||||
"github.com/go-acme/lego/v4/registration"
|
"github.com/go-acme/lego/v4/registration"
|
||||||
"golang.org/x/sync/singleflight"
|
"golang.org/x/sync/singleflight"
|
||||||
|
|
||||||
"github.com/usual2970/certimate/internal/domain"
|
"github.com/certimate-go/certimate/internal/domain"
|
||||||
certutil "github.com/usual2970/certimate/internal/pkg/utils/cert"
|
"github.com/certimate-go/certimate/internal/repository"
|
||||||
maputil "github.com/usual2970/certimate/internal/pkg/utils/map"
|
xcert "github.com/certimate-go/certimate/pkg/utils/cert"
|
||||||
"github.com/usual2970/certimate/internal/repository"
|
xmaps "github.com/certimate-go/certimate/pkg/utils/maps"
|
||||||
)
|
)
|
||||||
|
|
||||||
type acmeUser struct {
|
type acmeUser struct {
|
||||||
@ -51,7 +51,7 @@ func newAcmeUser(ca, caAccessId, email string) (*acmeUser, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
keyPEM, err := certutil.ConvertECPrivateKeyToPEM(key)
|
keyPEM, err := xcert.ConvertECPrivateKeyToPEM(key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -75,7 +75,7 @@ func (u acmeUser) GetRegistration() *registration.Resource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (u *acmeUser) GetPrivateKey() crypto.PrivateKey {
|
func (u *acmeUser) GetPrivateKey() crypto.PrivateKey {
|
||||||
rs, _ := certutil.ParseECPrivateKeyFromPEM(u.privkey)
|
rs, _ := xcert.ParseECPrivateKeyFromPEM(u.privkey)
|
||||||
return rs
|
return rs
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,7 +120,7 @@ func registerAcmeUser(client *lego.Client, user *acmeUser, userRegisterOptions m
|
|||||||
case caGoogleTrustServices:
|
case caGoogleTrustServices:
|
||||||
{
|
{
|
||||||
access := domain.AccessConfigForGoogleTrustServices{}
|
access := domain.AccessConfigForGoogleTrustServices{}
|
||||||
if err := maputil.Populate(userRegisterOptions, &access); err != nil {
|
if err := xmaps.Populate(userRegisterOptions, &access); err != nil {
|
||||||
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -134,7 +134,7 @@ func registerAcmeUser(client *lego.Client, user *acmeUser, userRegisterOptions m
|
|||||||
case caSSLCom:
|
case caSSLCom:
|
||||||
{
|
{
|
||||||
access := domain.AccessConfigForSSLCom{}
|
access := domain.AccessConfigForSSLCom{}
|
||||||
if err := maputil.Populate(userRegisterOptions, &access); err != nil {
|
if err := xmaps.Populate(userRegisterOptions, &access); err != nil {
|
||||||
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -148,7 +148,7 @@ func registerAcmeUser(client *lego.Client, user *acmeUser, userRegisterOptions m
|
|||||||
case caZeroSSL:
|
case caZeroSSL:
|
||||||
{
|
{
|
||||||
access := domain.AccessConfigForZeroSSL{}
|
access := domain.AccessConfigForZeroSSL{}
|
||||||
if err := maputil.Populate(userRegisterOptions, &access); err != nil {
|
if err := xmaps.Populate(userRegisterOptions, &access); err != nil {
|
||||||
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -162,7 +162,7 @@ func registerAcmeUser(client *lego.Client, user *acmeUser, userRegisterOptions m
|
|||||||
case caCustom:
|
case caCustom:
|
||||||
{
|
{
|
||||||
access := domain.AccessConfigForACMECA{}
|
access := domain.AccessConfigForACMECA{}
|
||||||
if err := maputil.Populate(userRegisterOptions, &access); err != nil {
|
if err := xmaps.Populate(userRegisterOptions, &access); err != nil {
|
||||||
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,10 +19,10 @@ import (
|
|||||||
"golang.org/x/exp/slices"
|
"golang.org/x/exp/slices"
|
||||||
"golang.org/x/time/rate"
|
"golang.org/x/time/rate"
|
||||||
|
|
||||||
"github.com/usual2970/certimate/internal/domain"
|
"github.com/certimate-go/certimate/internal/domain"
|
||||||
maputil "github.com/usual2970/certimate/internal/pkg/utils/map"
|
"github.com/certimate-go/certimate/internal/repository"
|
||||||
sliceutil "github.com/usual2970/certimate/internal/pkg/utils/slice"
|
xmaps "github.com/certimate-go/certimate/pkg/utils/maps"
|
||||||
"github.com/usual2970/certimate/internal/repository"
|
xslices "github.com/certimate-go/certimate/pkg/utils/slices"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ApplyResult struct {
|
type ApplyResult struct {
|
||||||
@ -55,7 +55,7 @@ func NewWithWorkflowNode(config ApplicantWithWorkflowNodeConfig) (Applicant, err
|
|||||||
|
|
||||||
nodeCfg := config.Node.GetConfigForApply()
|
nodeCfg := config.Node.GetConfigForApply()
|
||||||
options := &applicantProviderOptions{
|
options := &applicantProviderOptions{
|
||||||
Domains: sliceutil.Filter(strings.Split(nodeCfg.Domains, ";"), func(s string) bool { return s != "" }),
|
Domains: xslices.Filter(strings.Split(nodeCfg.Domains, ";"), func(s string) bool { return s != "" }),
|
||||||
ContactEmail: nodeCfg.ContactEmail,
|
ContactEmail: nodeCfg.ContactEmail,
|
||||||
Provider: domain.ACMEDns01ProviderType(nodeCfg.Provider),
|
Provider: domain.ACMEDns01ProviderType(nodeCfg.Provider),
|
||||||
ProviderAccessConfig: make(map[string]any),
|
ProviderAccessConfig: make(map[string]any),
|
||||||
@ -64,7 +64,7 @@ func NewWithWorkflowNode(config ApplicantWithWorkflowNodeConfig) (Applicant, err
|
|||||||
CAProviderAccessConfig: make(map[string]any),
|
CAProviderAccessConfig: make(map[string]any),
|
||||||
CAProviderServiceConfig: nodeCfg.CAProviderConfig,
|
CAProviderServiceConfig: nodeCfg.CAProviderConfig,
|
||||||
KeyAlgorithm: nodeCfg.KeyAlgorithm,
|
KeyAlgorithm: nodeCfg.KeyAlgorithm,
|
||||||
Nameservers: sliceutil.Filter(strings.Split(nodeCfg.Nameservers, ";"), func(s string) bool { return s != "" }),
|
Nameservers: xslices.Filter(strings.Split(nodeCfg.Nameservers, ";"), func(s string) bool { return s != "" }),
|
||||||
DnsPropagationWait: nodeCfg.DnsPropagationWait,
|
DnsPropagationWait: nodeCfg.DnsPropagationWait,
|
||||||
DnsPropagationTimeout: nodeCfg.DnsPropagationTimeout,
|
DnsPropagationTimeout: nodeCfg.DnsPropagationTimeout,
|
||||||
DnsTTL: nodeCfg.DnsTTL,
|
DnsTTL: nodeCfg.DnsTTL,
|
||||||
@ -189,7 +189,7 @@ func applyUseLego(legoProvider challenge.Provider, options *applicantProviderOpt
|
|||||||
}
|
}
|
||||||
|
|
||||||
case caCustom:
|
case caCustom:
|
||||||
caDirURL := maputil.GetString(options.CAProviderAccessConfig, "endpoint")
|
caDirURL := xmaps.GetString(options.CAProviderAccessConfig, "endpoint")
|
||||||
if caDirURL != "" {
|
if caDirURL != "" {
|
||||||
config.CADirURL = caDirURL
|
config.CADirURL = caDirURL
|
||||||
} else {
|
} else {
|
||||||
|
@ -5,45 +5,46 @@ import (
|
|||||||
|
|
||||||
"github.com/go-acme/lego/v4/challenge"
|
"github.com/go-acme/lego/v4/challenge"
|
||||||
|
|
||||||
"github.com/usual2970/certimate/internal/domain"
|
"github.com/certimate-go/certimate/internal/domain"
|
||||||
pACMEHttpReq "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/acmehttpreq"
|
pACMEHttpReq "github.com/certimate-go/certimate/pkg/core/ssl-applicator/acme-dns01/providers/acmehttpreq"
|
||||||
pAliyun "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/aliyun"
|
pAliyun "github.com/certimate-go/certimate/pkg/core/ssl-applicator/acme-dns01/providers/aliyun"
|
||||||
pAliyunESA "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/aliyun-esa"
|
pAliyunESA "github.com/certimate-go/certimate/pkg/core/ssl-applicator/acme-dns01/providers/aliyun-esa"
|
||||||
pAWSRoute53 "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/aws-route53"
|
pAWSRoute53 "github.com/certimate-go/certimate/pkg/core/ssl-applicator/acme-dns01/providers/aws-route53"
|
||||||
pAzureDNS "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/azure-dns"
|
pAzureDNS "github.com/certimate-go/certimate/pkg/core/ssl-applicator/acme-dns01/providers/azure-dns"
|
||||||
pBaiduCloud "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/baiducloud"
|
pBaiduCloud "github.com/certimate-go/certimate/pkg/core/ssl-applicator/acme-dns01/providers/baiducloud"
|
||||||
pBunny "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/bunny"
|
pBunny "github.com/certimate-go/certimate/pkg/core/ssl-applicator/acme-dns01/providers/bunny"
|
||||||
pCloudflare "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/cloudflare"
|
pCloudflare "github.com/certimate-go/certimate/pkg/core/ssl-applicator/acme-dns01/providers/cloudflare"
|
||||||
pClouDNS "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/cloudns"
|
pClouDNS "github.com/certimate-go/certimate/pkg/core/ssl-applicator/acme-dns01/providers/cloudns"
|
||||||
pCMCCCloud "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/cmcccloud"
|
pCMCCCloud "github.com/certimate-go/certimate/pkg/core/ssl-applicator/acme-dns01/providers/cmcccloud"
|
||||||
pConstellix "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/constellix"
|
pConstellix "github.com/certimate-go/certimate/pkg/core/ssl-applicator/acme-dns01/providers/constellix"
|
||||||
pDeSEC "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/desec"
|
pCTCCCloud "github.com/certimate-go/certimate/pkg/core/ssl-applicator/acme-dns01/providers/ctcccloud"
|
||||||
pDigitalOcean "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/digitalocean"
|
pDeSEC "github.com/certimate-go/certimate/pkg/core/ssl-applicator/acme-dns01/providers/desec"
|
||||||
pDNSLA "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/dnsla"
|
pDigitalOcean "github.com/certimate-go/certimate/pkg/core/ssl-applicator/acme-dns01/providers/digitalocean"
|
||||||
pDuckDNS "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/duckdns"
|
pDNSLA "github.com/certimate-go/certimate/pkg/core/ssl-applicator/acme-dns01/providers/dnsla"
|
||||||
pDynv6 "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/dynv6"
|
pDuckDNS "github.com/certimate-go/certimate/pkg/core/ssl-applicator/acme-dns01/providers/duckdns"
|
||||||
pGcore "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/gcore"
|
pDynv6 "github.com/certimate-go/certimate/pkg/core/ssl-applicator/acme-dns01/providers/dynv6"
|
||||||
pGname "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/gname"
|
pGcore "github.com/certimate-go/certimate/pkg/core/ssl-applicator/acme-dns01/providers/gcore"
|
||||||
pGoDaddy "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/godaddy"
|
pGname "github.com/certimate-go/certimate/pkg/core/ssl-applicator/acme-dns01/providers/gname"
|
||||||
pHetzner "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/hetzner"
|
pGoDaddy "github.com/certimate-go/certimate/pkg/core/ssl-applicator/acme-dns01/providers/godaddy"
|
||||||
pHuaweiCloud "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/huaweicloud"
|
pHetzner "github.com/certimate-go/certimate/pkg/core/ssl-applicator/acme-dns01/providers/hetzner"
|
||||||
pJDCloud "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/jdcloud"
|
pHuaweiCloud "github.com/certimate-go/certimate/pkg/core/ssl-applicator/acme-dns01/providers/huaweicloud"
|
||||||
pNamecheap "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/namecheap"
|
pJDCloud "github.com/certimate-go/certimate/pkg/core/ssl-applicator/acme-dns01/providers/jdcloud"
|
||||||
pNameDotCom "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/namedotcom"
|
pNamecheap "github.com/certimate-go/certimate/pkg/core/ssl-applicator/acme-dns01/providers/namecheap"
|
||||||
pNameSilo "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/namesilo"
|
pNameDotCom "github.com/certimate-go/certimate/pkg/core/ssl-applicator/acme-dns01/providers/namedotcom"
|
||||||
pNetcup "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/netcup"
|
pNameSilo "github.com/certimate-go/certimate/pkg/core/ssl-applicator/acme-dns01/providers/namesilo"
|
||||||
pNetlify "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/netlify"
|
pNetcup "github.com/certimate-go/certimate/pkg/core/ssl-applicator/acme-dns01/providers/netcup"
|
||||||
pNS1 "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/ns1"
|
pNetlify "github.com/certimate-go/certimate/pkg/core/ssl-applicator/acme-dns01/providers/netlify"
|
||||||
pPorkbun "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/porkbun"
|
pNS1 "github.com/certimate-go/certimate/pkg/core/ssl-applicator/acme-dns01/providers/ns1"
|
||||||
pPowerDNS "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/powerdns"
|
pPorkbun "github.com/certimate-go/certimate/pkg/core/ssl-applicator/acme-dns01/providers/porkbun"
|
||||||
pRainYun "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/rainyun"
|
pPowerDNS "github.com/certimate-go/certimate/pkg/core/ssl-applicator/acme-dns01/providers/powerdns"
|
||||||
pTencentCloud "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/tencentcloud"
|
pRainYun "github.com/certimate-go/certimate/pkg/core/ssl-applicator/acme-dns01/providers/rainyun"
|
||||||
pTencentCloudEO "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/tencentcloud-eo"
|
pTencentCloud "github.com/certimate-go/certimate/pkg/core/ssl-applicator/acme-dns01/providers/tencentcloud"
|
||||||
pUCloudUDNR "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/ucloud-udnr"
|
pTencentCloudEO "github.com/certimate-go/certimate/pkg/core/ssl-applicator/acme-dns01/providers/tencentcloud-eo"
|
||||||
pVercel "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/vercel"
|
pUCloudUDNR "github.com/certimate-go/certimate/pkg/core/ssl-applicator/acme-dns01/providers/ucloud-udnr"
|
||||||
pVolcEngine "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/volcengine"
|
pVercel "github.com/certimate-go/certimate/pkg/core/ssl-applicator/acme-dns01/providers/vercel"
|
||||||
pWestcn "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/westcn"
|
pVolcEngine "github.com/certimate-go/certimate/pkg/core/ssl-applicator/acme-dns01/providers/volcengine"
|
||||||
maputil "github.com/usual2970/certimate/internal/pkg/utils/map"
|
pWestcn "github.com/certimate-go/certimate/pkg/core/ssl-applicator/acme-dns01/providers/westcn"
|
||||||
|
xmaps "github.com/certimate-go/certimate/pkg/utils/maps"
|
||||||
)
|
)
|
||||||
|
|
||||||
type applicantProviderOptions struct {
|
type applicantProviderOptions struct {
|
||||||
@ -75,7 +76,7 @@ func createApplicantProvider(options *applicantProviderOptions) (challenge.Provi
|
|||||||
case domain.ACMEDns01ProviderTypeACMEHttpReq:
|
case domain.ACMEDns01ProviderTypeACMEHttpReq:
|
||||||
{
|
{
|
||||||
access := domain.AccessConfigForACMEHttpReq{}
|
access := domain.AccessConfigForACMEHttpReq{}
|
||||||
if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil {
|
if err := xmaps.Populate(options.ProviderAccessConfig, &access); err != nil {
|
||||||
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,7 +93,7 @@ func createApplicantProvider(options *applicantProviderOptions) (challenge.Provi
|
|||||||
case domain.ACMEDns01ProviderTypeAliyun, domain.ACMEDns01ProviderTypeAliyunDNS, domain.ACMEDns01ProviderTypeAliyunESA:
|
case domain.ACMEDns01ProviderTypeAliyun, domain.ACMEDns01ProviderTypeAliyunDNS, domain.ACMEDns01ProviderTypeAliyunESA:
|
||||||
{
|
{
|
||||||
access := domain.AccessConfigForAliyun{}
|
access := domain.AccessConfigForAliyun{}
|
||||||
if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil {
|
if err := xmaps.Populate(options.ProviderAccessConfig, &access); err != nil {
|
||||||
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,7 +111,7 @@ func createApplicantProvider(options *applicantProviderOptions) (challenge.Provi
|
|||||||
applicant, err := pAliyunESA.NewChallengeProvider(&pAliyunESA.ChallengeProviderConfig{
|
applicant, err := pAliyunESA.NewChallengeProvider(&pAliyunESA.ChallengeProviderConfig{
|
||||||
AccessKeyId: access.AccessKeyId,
|
AccessKeyId: access.AccessKeyId,
|
||||||
AccessKeySecret: access.AccessKeySecret,
|
AccessKeySecret: access.AccessKeySecret,
|
||||||
Region: maputil.GetString(options.ProviderServiceConfig, "region"),
|
Region: xmaps.GetString(options.ProviderServiceConfig, "region"),
|
||||||
DnsPropagationTimeout: options.DnsPropagationTimeout,
|
DnsPropagationTimeout: options.DnsPropagationTimeout,
|
||||||
DnsTTL: options.DnsTTL,
|
DnsTTL: options.DnsTTL,
|
||||||
})
|
})
|
||||||
@ -124,15 +125,15 @@ func createApplicantProvider(options *applicantProviderOptions) (challenge.Provi
|
|||||||
case domain.ACMEDns01ProviderTypeAWS, domain.ACMEDns01ProviderTypeAWSRoute53:
|
case domain.ACMEDns01ProviderTypeAWS, domain.ACMEDns01ProviderTypeAWSRoute53:
|
||||||
{
|
{
|
||||||
access := domain.AccessConfigForAWS{}
|
access := domain.AccessConfigForAWS{}
|
||||||
if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil {
|
if err := xmaps.Populate(options.ProviderAccessConfig, &access); err != nil {
|
||||||
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
applicant, err := pAWSRoute53.NewChallengeProvider(&pAWSRoute53.ChallengeProviderConfig{
|
applicant, err := pAWSRoute53.NewChallengeProvider(&pAWSRoute53.ChallengeProviderConfig{
|
||||||
AccessKeyId: access.AccessKeyId,
|
AccessKeyId: access.AccessKeyId,
|
||||||
SecretAccessKey: access.SecretAccessKey,
|
SecretAccessKey: access.SecretAccessKey,
|
||||||
Region: maputil.GetString(options.ProviderServiceConfig, "region"),
|
Region: xmaps.GetString(options.ProviderServiceConfig, "region"),
|
||||||
HostedZoneId: maputil.GetString(options.ProviderServiceConfig, "hostedZoneId"),
|
HostedZoneId: xmaps.GetString(options.ProviderServiceConfig, "hostedZoneId"),
|
||||||
DnsPropagationTimeout: options.DnsPropagationTimeout,
|
DnsPropagationTimeout: options.DnsPropagationTimeout,
|
||||||
DnsTTL: options.DnsTTL,
|
DnsTTL: options.DnsTTL,
|
||||||
})
|
})
|
||||||
@ -142,7 +143,7 @@ func createApplicantProvider(options *applicantProviderOptions) (challenge.Provi
|
|||||||
case domain.ACMEDns01ProviderTypeAzure, domain.ACMEDns01ProviderTypeAzureDNS:
|
case domain.ACMEDns01ProviderTypeAzure, domain.ACMEDns01ProviderTypeAzureDNS:
|
||||||
{
|
{
|
||||||
access := domain.AccessConfigForAzure{}
|
access := domain.AccessConfigForAzure{}
|
||||||
if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil {
|
if err := xmaps.Populate(options.ProviderAccessConfig, &access); err != nil {
|
||||||
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -160,7 +161,7 @@ func createApplicantProvider(options *applicantProviderOptions) (challenge.Provi
|
|||||||
case domain.ACMEDns01ProviderTypeBaiduCloud, domain.ACMEDns01ProviderTypeBaiduCloudDNS:
|
case domain.ACMEDns01ProviderTypeBaiduCloud, domain.ACMEDns01ProviderTypeBaiduCloudDNS:
|
||||||
{
|
{
|
||||||
access := domain.AccessConfigForBaiduCloud{}
|
access := domain.AccessConfigForBaiduCloud{}
|
||||||
if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil {
|
if err := xmaps.Populate(options.ProviderAccessConfig, &access); err != nil {
|
||||||
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -176,7 +177,7 @@ func createApplicantProvider(options *applicantProviderOptions) (challenge.Provi
|
|||||||
case domain.ACMEDns01ProviderTypeBunny:
|
case domain.ACMEDns01ProviderTypeBunny:
|
||||||
{
|
{
|
||||||
access := domain.AccessConfigForBunny{}
|
access := domain.AccessConfigForBunny{}
|
||||||
if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil {
|
if err := xmaps.Populate(options.ProviderAccessConfig, &access); err != nil {
|
||||||
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,7 +192,7 @@ func createApplicantProvider(options *applicantProviderOptions) (challenge.Provi
|
|||||||
case domain.ACMEDns01ProviderTypeCloudflare:
|
case domain.ACMEDns01ProviderTypeCloudflare:
|
||||||
{
|
{
|
||||||
access := domain.AccessConfigForCloudflare{}
|
access := domain.AccessConfigForCloudflare{}
|
||||||
if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil {
|
if err := xmaps.Populate(options.ProviderAccessConfig, &access); err != nil {
|
||||||
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -207,7 +208,7 @@ func createApplicantProvider(options *applicantProviderOptions) (challenge.Provi
|
|||||||
case domain.ACMEDns01ProviderTypeClouDNS:
|
case domain.ACMEDns01ProviderTypeClouDNS:
|
||||||
{
|
{
|
||||||
access := domain.AccessConfigForClouDNS{}
|
access := domain.AccessConfigForClouDNS{}
|
||||||
if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil {
|
if err := xmaps.Populate(options.ProviderAccessConfig, &access); err != nil {
|
||||||
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -220,10 +221,10 @@ func createApplicantProvider(options *applicantProviderOptions) (challenge.Provi
|
|||||||
return applicant, err
|
return applicant, err
|
||||||
}
|
}
|
||||||
|
|
||||||
case domain.ACMEDns01ProviderTypeCMCCCloud:
|
case domain.ACMEDns01ProviderTypeCMCCCloud, domain.ACMEDns01ProviderTypeCMCCCloudDNS:
|
||||||
{
|
{
|
||||||
access := domain.AccessConfigForCMCCCloud{}
|
access := domain.AccessConfigForCMCCCloud{}
|
||||||
if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil {
|
if err := xmaps.Populate(options.ProviderAccessConfig, &access); err != nil {
|
||||||
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -239,7 +240,7 @@ func createApplicantProvider(options *applicantProviderOptions) (challenge.Provi
|
|||||||
case domain.ACMEDns01ProviderTypeConstellix:
|
case domain.ACMEDns01ProviderTypeConstellix:
|
||||||
{
|
{
|
||||||
access := domain.AccessConfigForConstellix{}
|
access := domain.AccessConfigForConstellix{}
|
||||||
if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil {
|
if err := xmaps.Populate(options.ProviderAccessConfig, &access); err != nil {
|
||||||
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -252,10 +253,26 @@ func createApplicantProvider(options *applicantProviderOptions) (challenge.Provi
|
|||||||
return applicant, err
|
return applicant, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case domain.ACMEDns01ProviderTypeCTCCCloud, domain.ACMEDns01ProviderTypeCTCCCloudSmartDNS:
|
||||||
|
{
|
||||||
|
access := domain.AccessConfigForCTCCCloud{}
|
||||||
|
if err := xmaps.Populate(options.ProviderAccessConfig, &access); err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
applicant, err := pCTCCCloud.NewChallengeProvider(&pCTCCCloud.ChallengeProviderConfig{
|
||||||
|
AccessKeyId: access.AccessKeyId,
|
||||||
|
SecretAccessKey: access.SecretAccessKey,
|
||||||
|
DnsPropagationTimeout: options.DnsPropagationTimeout,
|
||||||
|
DnsTTL: options.DnsTTL,
|
||||||
|
})
|
||||||
|
return applicant, err
|
||||||
|
}
|
||||||
|
|
||||||
case domain.ACMEDns01ProviderTypeDeSEC:
|
case domain.ACMEDns01ProviderTypeDeSEC:
|
||||||
{
|
{
|
||||||
access := domain.AccessConfigForDeSEC{}
|
access := domain.AccessConfigForDeSEC{}
|
||||||
if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil {
|
if err := xmaps.Populate(options.ProviderAccessConfig, &access); err != nil {
|
||||||
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -270,7 +287,7 @@ func createApplicantProvider(options *applicantProviderOptions) (challenge.Provi
|
|||||||
case domain.ACMEDns01ProviderTypeDigitalOcean:
|
case domain.ACMEDns01ProviderTypeDigitalOcean:
|
||||||
{
|
{
|
||||||
access := domain.AccessConfigForDigitalOcean{}
|
access := domain.AccessConfigForDigitalOcean{}
|
||||||
if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil {
|
if err := xmaps.Populate(options.ProviderAccessConfig, &access); err != nil {
|
||||||
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -285,7 +302,7 @@ func createApplicantProvider(options *applicantProviderOptions) (challenge.Provi
|
|||||||
case domain.ACMEDns01ProviderTypeDNSLA:
|
case domain.ACMEDns01ProviderTypeDNSLA:
|
||||||
{
|
{
|
||||||
access := domain.AccessConfigForDNSLA{}
|
access := domain.AccessConfigForDNSLA{}
|
||||||
if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil {
|
if err := xmaps.Populate(options.ProviderAccessConfig, &access); err != nil {
|
||||||
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -301,7 +318,7 @@ func createApplicantProvider(options *applicantProviderOptions) (challenge.Provi
|
|||||||
case domain.ACMEDns01ProviderTypeDuckDNS:
|
case domain.ACMEDns01ProviderTypeDuckDNS:
|
||||||
{
|
{
|
||||||
access := domain.AccessConfigForDuckDNS{}
|
access := domain.AccessConfigForDuckDNS{}
|
||||||
if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil {
|
if err := xmaps.Populate(options.ProviderAccessConfig, &access); err != nil {
|
||||||
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -315,7 +332,7 @@ func createApplicantProvider(options *applicantProviderOptions) (challenge.Provi
|
|||||||
case domain.ACMEDns01ProviderTypeDynv6:
|
case domain.ACMEDns01ProviderTypeDynv6:
|
||||||
{
|
{
|
||||||
access := domain.AccessConfigForDynv6{}
|
access := domain.AccessConfigForDynv6{}
|
||||||
if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil {
|
if err := xmaps.Populate(options.ProviderAccessConfig, &access); err != nil {
|
||||||
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -330,7 +347,7 @@ func createApplicantProvider(options *applicantProviderOptions) (challenge.Provi
|
|||||||
case domain.ACMEDns01ProviderTypeGcore:
|
case domain.ACMEDns01ProviderTypeGcore:
|
||||||
{
|
{
|
||||||
access := domain.AccessConfigForGcore{}
|
access := domain.AccessConfigForGcore{}
|
||||||
if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil {
|
if err := xmaps.Populate(options.ProviderAccessConfig, &access); err != nil {
|
||||||
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -345,7 +362,7 @@ func createApplicantProvider(options *applicantProviderOptions) (challenge.Provi
|
|||||||
case domain.ACMEDns01ProviderTypeGname:
|
case domain.ACMEDns01ProviderTypeGname:
|
||||||
{
|
{
|
||||||
access := domain.AccessConfigForGname{}
|
access := domain.AccessConfigForGname{}
|
||||||
if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil {
|
if err := xmaps.Populate(options.ProviderAccessConfig, &access); err != nil {
|
||||||
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -361,7 +378,7 @@ func createApplicantProvider(options *applicantProviderOptions) (challenge.Provi
|
|||||||
case domain.ACMEDns01ProviderTypeGoDaddy:
|
case domain.ACMEDns01ProviderTypeGoDaddy:
|
||||||
{
|
{
|
||||||
access := domain.AccessConfigForGoDaddy{}
|
access := domain.AccessConfigForGoDaddy{}
|
||||||
if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil {
|
if err := xmaps.Populate(options.ProviderAccessConfig, &access); err != nil {
|
||||||
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -377,7 +394,7 @@ func createApplicantProvider(options *applicantProviderOptions) (challenge.Provi
|
|||||||
case domain.ACMEDns01ProviderTypeHetzner:
|
case domain.ACMEDns01ProviderTypeHetzner:
|
||||||
{
|
{
|
||||||
access := domain.AccessConfigForHetzner{}
|
access := domain.AccessConfigForHetzner{}
|
||||||
if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil {
|
if err := xmaps.Populate(options.ProviderAccessConfig, &access); err != nil {
|
||||||
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -392,14 +409,14 @@ func createApplicantProvider(options *applicantProviderOptions) (challenge.Provi
|
|||||||
case domain.ACMEDns01ProviderTypeHuaweiCloud, domain.ACMEDns01ProviderTypeHuaweiCloudDNS:
|
case domain.ACMEDns01ProviderTypeHuaweiCloud, domain.ACMEDns01ProviderTypeHuaweiCloudDNS:
|
||||||
{
|
{
|
||||||
access := domain.AccessConfigForHuaweiCloud{}
|
access := domain.AccessConfigForHuaweiCloud{}
|
||||||
if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil {
|
if err := xmaps.Populate(options.ProviderAccessConfig, &access); err != nil {
|
||||||
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
applicant, err := pHuaweiCloud.NewChallengeProvider(&pHuaweiCloud.ChallengeProviderConfig{
|
applicant, err := pHuaweiCloud.NewChallengeProvider(&pHuaweiCloud.ChallengeProviderConfig{
|
||||||
AccessKeyId: access.AccessKeyId,
|
AccessKeyId: access.AccessKeyId,
|
||||||
SecretAccessKey: access.SecretAccessKey,
|
SecretAccessKey: access.SecretAccessKey,
|
||||||
Region: maputil.GetString(options.ProviderServiceConfig, "region"),
|
Region: xmaps.GetString(options.ProviderServiceConfig, "region"),
|
||||||
DnsPropagationTimeout: options.DnsPropagationTimeout,
|
DnsPropagationTimeout: options.DnsPropagationTimeout,
|
||||||
DnsTTL: options.DnsTTL,
|
DnsTTL: options.DnsTTL,
|
||||||
})
|
})
|
||||||
@ -409,14 +426,14 @@ func createApplicantProvider(options *applicantProviderOptions) (challenge.Provi
|
|||||||
case domain.ACMEDns01ProviderTypeJDCloud, domain.ACMEDns01ProviderTypeJDCloudDNS:
|
case domain.ACMEDns01ProviderTypeJDCloud, domain.ACMEDns01ProviderTypeJDCloudDNS:
|
||||||
{
|
{
|
||||||
access := domain.AccessConfigForJDCloud{}
|
access := domain.AccessConfigForJDCloud{}
|
||||||
if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil {
|
if err := xmaps.Populate(options.ProviderAccessConfig, &access); err != nil {
|
||||||
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
applicant, err := pJDCloud.NewChallengeProvider(&pJDCloud.ChallengeProviderConfig{
|
applicant, err := pJDCloud.NewChallengeProvider(&pJDCloud.ChallengeProviderConfig{
|
||||||
AccessKeyId: access.AccessKeyId,
|
AccessKeyId: access.AccessKeyId,
|
||||||
AccessKeySecret: access.AccessKeySecret,
|
AccessKeySecret: access.AccessKeySecret,
|
||||||
RegionId: maputil.GetString(options.ProviderServiceConfig, "regionId"),
|
RegionId: xmaps.GetString(options.ProviderServiceConfig, "regionId"),
|
||||||
DnsPropagationTimeout: options.DnsPropagationTimeout,
|
DnsPropagationTimeout: options.DnsPropagationTimeout,
|
||||||
DnsTTL: options.DnsTTL,
|
DnsTTL: options.DnsTTL,
|
||||||
})
|
})
|
||||||
@ -426,7 +443,7 @@ func createApplicantProvider(options *applicantProviderOptions) (challenge.Provi
|
|||||||
case domain.ACMEDns01ProviderTypeNamecheap:
|
case domain.ACMEDns01ProviderTypeNamecheap:
|
||||||
{
|
{
|
||||||
access := domain.AccessConfigForNamecheap{}
|
access := domain.AccessConfigForNamecheap{}
|
||||||
if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil {
|
if err := xmaps.Populate(options.ProviderAccessConfig, &access); err != nil {
|
||||||
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -442,7 +459,7 @@ func createApplicantProvider(options *applicantProviderOptions) (challenge.Provi
|
|||||||
case domain.ACMEDns01ProviderTypeNameDotCom:
|
case domain.ACMEDns01ProviderTypeNameDotCom:
|
||||||
{
|
{
|
||||||
access := domain.AccessConfigForNameDotCom{}
|
access := domain.AccessConfigForNameDotCom{}
|
||||||
if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil {
|
if err := xmaps.Populate(options.ProviderAccessConfig, &access); err != nil {
|
||||||
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -458,7 +475,7 @@ func createApplicantProvider(options *applicantProviderOptions) (challenge.Provi
|
|||||||
case domain.ACMEDns01ProviderTypeNameSilo:
|
case domain.ACMEDns01ProviderTypeNameSilo:
|
||||||
{
|
{
|
||||||
access := domain.AccessConfigForNameSilo{}
|
access := domain.AccessConfigForNameSilo{}
|
||||||
if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil {
|
if err := xmaps.Populate(options.ProviderAccessConfig, &access); err != nil {
|
||||||
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -473,7 +490,7 @@ func createApplicantProvider(options *applicantProviderOptions) (challenge.Provi
|
|||||||
case domain.ACMEDns01ProviderTypeNetcup:
|
case domain.ACMEDns01ProviderTypeNetcup:
|
||||||
{
|
{
|
||||||
access := domain.AccessConfigForNetcup{}
|
access := domain.AccessConfigForNetcup{}
|
||||||
if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil {
|
if err := xmaps.Populate(options.ProviderAccessConfig, &access); err != nil {
|
||||||
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -490,7 +507,7 @@ func createApplicantProvider(options *applicantProviderOptions) (challenge.Provi
|
|||||||
case domain.ACMEDns01ProviderTypeNetlify:
|
case domain.ACMEDns01ProviderTypeNetlify:
|
||||||
{
|
{
|
||||||
access := domain.AccessConfigForNetlify{}
|
access := domain.AccessConfigForNetlify{}
|
||||||
if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil {
|
if err := xmaps.Populate(options.ProviderAccessConfig, &access); err != nil {
|
||||||
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -505,7 +522,7 @@ func createApplicantProvider(options *applicantProviderOptions) (challenge.Provi
|
|||||||
case domain.ACMEDns01ProviderTypeNS1:
|
case domain.ACMEDns01ProviderTypeNS1:
|
||||||
{
|
{
|
||||||
access := domain.AccessConfigForNS1{}
|
access := domain.AccessConfigForNS1{}
|
||||||
if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil {
|
if err := xmaps.Populate(options.ProviderAccessConfig, &access); err != nil {
|
||||||
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -520,7 +537,7 @@ func createApplicantProvider(options *applicantProviderOptions) (challenge.Provi
|
|||||||
case domain.ACMEDns01ProviderTypePorkbun:
|
case domain.ACMEDns01ProviderTypePorkbun:
|
||||||
{
|
{
|
||||||
access := domain.AccessConfigForPorkbun{}
|
access := domain.AccessConfigForPorkbun{}
|
||||||
if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil {
|
if err := xmaps.Populate(options.ProviderAccessConfig, &access); err != nil {
|
||||||
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -536,7 +553,7 @@ func createApplicantProvider(options *applicantProviderOptions) (challenge.Provi
|
|||||||
case domain.ACMEDns01ProviderTypePowerDNS:
|
case domain.ACMEDns01ProviderTypePowerDNS:
|
||||||
{
|
{
|
||||||
access := domain.AccessConfigForPowerDNS{}
|
access := domain.AccessConfigForPowerDNS{}
|
||||||
if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil {
|
if err := xmaps.Populate(options.ProviderAccessConfig, &access); err != nil {
|
||||||
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -553,7 +570,7 @@ func createApplicantProvider(options *applicantProviderOptions) (challenge.Provi
|
|||||||
case domain.ACMEDns01ProviderTypeRainYun:
|
case domain.ACMEDns01ProviderTypeRainYun:
|
||||||
{
|
{
|
||||||
access := domain.AccessConfigForRainYun{}
|
access := domain.AccessConfigForRainYun{}
|
||||||
if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil {
|
if err := xmaps.Populate(options.ProviderAccessConfig, &access); err != nil {
|
||||||
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -568,7 +585,7 @@ func createApplicantProvider(options *applicantProviderOptions) (challenge.Provi
|
|||||||
case domain.ACMEDns01ProviderTypeTencentCloud, domain.ACMEDns01ProviderTypeTencentCloudDNS, domain.ACMEDns01ProviderTypeTencentCloudEO:
|
case domain.ACMEDns01ProviderTypeTencentCloud, domain.ACMEDns01ProviderTypeTencentCloudDNS, domain.ACMEDns01ProviderTypeTencentCloudEO:
|
||||||
{
|
{
|
||||||
access := domain.AccessConfigForTencentCloud{}
|
access := domain.AccessConfigForTencentCloud{}
|
||||||
if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil {
|
if err := xmaps.Populate(options.ProviderAccessConfig, &access); err != nil {
|
||||||
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -586,7 +603,7 @@ func createApplicantProvider(options *applicantProviderOptions) (challenge.Provi
|
|||||||
applicant, err := pTencentCloudEO.NewChallengeProvider(&pTencentCloudEO.ChallengeProviderConfig{
|
applicant, err := pTencentCloudEO.NewChallengeProvider(&pTencentCloudEO.ChallengeProviderConfig{
|
||||||
SecretId: access.SecretId,
|
SecretId: access.SecretId,
|
||||||
SecretKey: access.SecretKey,
|
SecretKey: access.SecretKey,
|
||||||
ZoneId: maputil.GetString(options.ProviderServiceConfig, "zoneId"),
|
ZoneId: xmaps.GetString(options.ProviderServiceConfig, "zoneId"),
|
||||||
DnsPropagationTimeout: options.DnsPropagationTimeout,
|
DnsPropagationTimeout: options.DnsPropagationTimeout,
|
||||||
DnsTTL: options.DnsTTL,
|
DnsTTL: options.DnsTTL,
|
||||||
})
|
})
|
||||||
@ -600,7 +617,7 @@ func createApplicantProvider(options *applicantProviderOptions) (challenge.Provi
|
|||||||
case domain.ACMEDns01ProviderTypeUCloudUDNR:
|
case domain.ACMEDns01ProviderTypeUCloudUDNR:
|
||||||
{
|
{
|
||||||
access := domain.AccessConfigForUCloud{}
|
access := domain.AccessConfigForUCloud{}
|
||||||
if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil {
|
if err := xmaps.Populate(options.ProviderAccessConfig, &access); err != nil {
|
||||||
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -616,7 +633,7 @@ func createApplicantProvider(options *applicantProviderOptions) (challenge.Provi
|
|||||||
case domain.ACMEDns01ProviderTypeVercel:
|
case domain.ACMEDns01ProviderTypeVercel:
|
||||||
{
|
{
|
||||||
access := domain.AccessConfigForVercel{}
|
access := domain.AccessConfigForVercel{}
|
||||||
if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil {
|
if err := xmaps.Populate(options.ProviderAccessConfig, &access); err != nil {
|
||||||
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -632,7 +649,7 @@ func createApplicantProvider(options *applicantProviderOptions) (challenge.Provi
|
|||||||
case domain.ACMEDns01ProviderTypeVolcEngine, domain.ACMEDns01ProviderTypeVolcEngineDNS:
|
case domain.ACMEDns01ProviderTypeVolcEngine, domain.ACMEDns01ProviderTypeVolcEngineDNS:
|
||||||
{
|
{
|
||||||
access := domain.AccessConfigForVolcEngine{}
|
access := domain.AccessConfigForVolcEngine{}
|
||||||
if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil {
|
if err := xmaps.Populate(options.ProviderAccessConfig, &access); err != nil {
|
||||||
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -648,7 +665,7 @@ func createApplicantProvider(options *applicantProviderOptions) (challenge.Provi
|
|||||||
case domain.ACMEDns01ProviderTypeWestcn:
|
case domain.ACMEDns01ProviderTypeWestcn:
|
||||||
{
|
{
|
||||||
access := domain.AccessConfigForWestcn{}
|
access := domain.AccessConfigForWestcn{}
|
||||||
if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil {
|
if err := xmaps.Populate(options.ProviderAccessConfig, &access); err != nil {
|
||||||
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,12 +13,12 @@ import (
|
|||||||
"github.com/go-acme/lego/v4/certcrypto"
|
"github.com/go-acme/lego/v4/certcrypto"
|
||||||
"github.com/pocketbase/dbx"
|
"github.com/pocketbase/dbx"
|
||||||
|
|
||||||
"github.com/usual2970/certimate/internal/app"
|
"github.com/certimate-go/certimate/internal/app"
|
||||||
"github.com/usual2970/certimate/internal/domain"
|
"github.com/certimate-go/certimate/internal/domain"
|
||||||
"github.com/usual2970/certimate/internal/domain/dtos"
|
"github.com/certimate-go/certimate/internal/domain/dtos"
|
||||||
"github.com/usual2970/certimate/internal/notify"
|
"github.com/certimate-go/certimate/internal/notify"
|
||||||
certutil "github.com/usual2970/certimate/internal/pkg/utils/cert"
|
"github.com/certimate-go/certimate/internal/repository"
|
||||||
"github.com/usual2970/certimate/internal/repository"
|
xcert "github.com/certimate-go/certimate/pkg/utils/cert"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -145,7 +145,7 @@ func (s *CertificateService) ArchiveFile(ctx context.Context, req *dtos.Certific
|
|||||||
{
|
{
|
||||||
const pfxPassword = "certimate"
|
const pfxPassword = "certimate"
|
||||||
|
|
||||||
certPFX, err := certutil.TransformCertificateFromPEMToPFX(certificate.Certificate, certificate.PrivateKey, pfxPassword)
|
certPFX, err := xcert.TransformCertificateFromPEMToPFX(certificate.Certificate, certificate.PrivateKey, pfxPassword)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -183,7 +183,7 @@ func (s *CertificateService) ArchiveFile(ctx context.Context, req *dtos.Certific
|
|||||||
{
|
{
|
||||||
const jksPassword = "certimate"
|
const jksPassword = "certimate"
|
||||||
|
|
||||||
certJKS, err := certutil.TransformCertificateFromPEMToJKS(certificate.Certificate, certificate.PrivateKey, jksPassword, jksPassword, jksPassword)
|
certJKS, err := xcert.TransformCertificateFromPEMToJKS(certificate.Certificate, certificate.PrivateKey, jksPassword, jksPassword, jksPassword)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -223,7 +223,7 @@ func (s *CertificateService) ArchiveFile(ctx context.Context, req *dtos.Certific
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *CertificateService) ValidateCertificate(ctx context.Context, req *dtos.CertificateValidateCertificateReq) (*dtos.CertificateValidateCertificateResp, error) {
|
func (s *CertificateService) ValidateCertificate(ctx context.Context, req *dtos.CertificateValidateCertificateReq) (*dtos.CertificateValidateCertificateResp, error) {
|
||||||
certX509, err := certutil.ParseCertificateFromPEM(req.Certificate)
|
certX509, err := xcert.ParseCertificateFromPEM(req.Certificate)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
} else if time.Now().After(certX509.NotAfter) {
|
} else if time.Now().After(certX509.NotAfter) {
|
||||||
|
@ -5,9 +5,9 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
|
|
||||||
"github.com/usual2970/certimate/internal/domain"
|
"github.com/certimate-go/certimate/internal/domain"
|
||||||
"github.com/usual2970/certimate/internal/pkg/core/deployer"
|
"github.com/certimate-go/certimate/internal/repository"
|
||||||
"github.com/usual2970/certimate/internal/repository"
|
"github.com/certimate-go/certimate/pkg/core"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Deployer interface {
|
type Deployer interface {
|
||||||
@ -46,20 +46,22 @@ func NewWithWorkflowNode(config DeployerWithWorkflowNodeConfig) (Deployer, error
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
deployerProvider, err := createDeployerProvider(options)
|
deployer, err := createSSLDeployerProvider(options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
} else {
|
||||||
|
deployer.SetLogger(config.Logger)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &deployerImpl{
|
return &deployerImpl{
|
||||||
provider: deployerProvider.WithLogger(config.Logger),
|
provider: deployer,
|
||||||
certPEM: config.CertificatePEM,
|
certPEM: config.CertificatePEM,
|
||||||
privkeyPEM: config.PrivateKeyPEM,
|
privkeyPEM: config.PrivateKeyPEM,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type deployerImpl struct {
|
type deployerImpl struct {
|
||||||
provider deployer.Deployer
|
provider core.SSLDeployer
|
||||||
certPEM string
|
certPEM string
|
||||||
privkeyPEM string
|
privkeyPEM string
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -41,6 +41,12 @@ type AccessConfigForAliyun struct {
|
|||||||
ResourceGroupId string `json:"resourceGroupId,omitempty"`
|
ResourceGroupId string `json:"resourceGroupId,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type AccessConfigForAPISIX struct {
|
||||||
|
ServerUrl string `json:"serverUrl"`
|
||||||
|
ApiKey string `json:"apiKey"`
|
||||||
|
AllowInsecureConnections bool `json:"allowInsecureConnections,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
type AccessConfigForAWS struct {
|
type AccessConfigForAWS struct {
|
||||||
AccessKeyId string `json:"accessKeyId"`
|
AccessKeyId string `json:"accessKeyId"`
|
||||||
SecretAccessKey string `json:"secretAccessKey"`
|
SecretAccessKey string `json:"secretAccessKey"`
|
||||||
@ -114,6 +120,11 @@ type AccessConfigForConstellix struct {
|
|||||||
SecretKey string `json:"secretKey"`
|
SecretKey string `json:"secretKey"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type AccessConfigForCTCCCloud struct {
|
||||||
|
AccessKeyId string `json:"accessKeyId"`
|
||||||
|
SecretAccessKey string `json:"secretAccessKey"`
|
||||||
|
}
|
||||||
|
|
||||||
type AccessConfigForDeSEC struct {
|
type AccessConfigForDeSEC struct {
|
||||||
Token string `json:"token"`
|
Token string `json:"token"`
|
||||||
}
|
}
|
||||||
@ -162,6 +173,7 @@ type AccessConfigForEmail struct {
|
|||||||
Username string `json:"username"`
|
Username string `json:"username"`
|
||||||
Password string `json:"password"`
|
Password string `json:"password"`
|
||||||
DefaultSenderAddress string `json:"defaultSenderAddress,omitempty"`
|
DefaultSenderAddress string `json:"defaultSenderAddress,omitempty"`
|
||||||
|
DefaultSenderName string `json:"defaultSenderName,omitempty"`
|
||||||
DefaultReceiverAddress string `json:"defaultReceiverAddress,omitempty"`
|
DefaultReceiverAddress string `json:"defaultReceiverAddress,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
certutil "github.com/usual2970/certimate/internal/pkg/utils/cert"
|
xcert "github.com/certimate-go/certimate/pkg/utils/cert"
|
||||||
)
|
)
|
||||||
|
|
||||||
const CollectionNameCertificate = "certificate"
|
const CollectionNameCertificate = "certificate"
|
||||||
@ -106,10 +106,10 @@ func (c *Certificate) PopulateFromPEM(certPEM, privkeyPEM string) *Certificate {
|
|||||||
c.Certificate = certPEM
|
c.Certificate = certPEM
|
||||||
c.PrivateKey = privkeyPEM
|
c.PrivateKey = privkeyPEM
|
||||||
|
|
||||||
_, issuerCertPEM, _ := certutil.ExtractCertificatesFromPEM(certPEM)
|
_, issuerCertPEM, _ := xcert.ExtractCertificatesFromPEM(certPEM)
|
||||||
c.IssuerCertificate = issuerCertPEM
|
c.IssuerCertificate = issuerCertPEM
|
||||||
|
|
||||||
certX509, _ := certutil.ParseCertificateFromPEM(certPEM)
|
certX509, _ := xcert.ParseCertificateFromPEM(certPEM)
|
||||||
if certX509 != nil {
|
if certX509 != nil {
|
||||||
c.PopulateFromX509(certX509)
|
c.PopulateFromX509(certX509)
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package dtos
|
package dtos
|
||||||
|
|
||||||
import "github.com/usual2970/certimate/internal/domain"
|
import "github.com/certimate-go/certimate/internal/domain"
|
||||||
|
|
||||||
type NotifyTestPushReq struct {
|
type NotifyTestPushReq struct {
|
||||||
Channel domain.NotifyChannelType `json:"channel"`
|
Channel domain.NotifyChannelType `json:"channel"`
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package dtos
|
package dtos
|
||||||
|
|
||||||
import "github.com/usual2970/certimate/internal/domain"
|
import "github.com/certimate-go/certimate/internal/domain"
|
||||||
|
|
||||||
type WorkflowStartRunReq struct {
|
type WorkflowStartRunReq struct {
|
||||||
WorkflowId string `json:"-"`
|
WorkflowId string `json:"-"`
|
||||||
|
@ -14,6 +14,7 @@ const (
|
|||||||
AccessProviderTypeACMEHttpReq = AccessProviderType("acmehttpreq")
|
AccessProviderTypeACMEHttpReq = AccessProviderType("acmehttpreq")
|
||||||
AccessProviderTypeAkamai = AccessProviderType("akamai") // Akamai(预留)
|
AccessProviderTypeAkamai = AccessProviderType("akamai") // Akamai(预留)
|
||||||
AccessProviderTypeAliyun = AccessProviderType("aliyun")
|
AccessProviderTypeAliyun = AccessProviderType("aliyun")
|
||||||
|
AccessProviderTypeAPISIX = AccessProviderType("apisix")
|
||||||
AccessProviderTypeAWS = AccessProviderType("aws")
|
AccessProviderTypeAWS = AccessProviderType("aws")
|
||||||
AccessProviderTypeAzure = AccessProviderType("azure")
|
AccessProviderTypeAzure = AccessProviderType("azure")
|
||||||
AccessProviderTypeBaiduCloud = AccessProviderType("baiducloud")
|
AccessProviderTypeBaiduCloud = AccessProviderType("baiducloud")
|
||||||
@ -29,7 +30,7 @@ const (
|
|||||||
AccessProviderTypeClouDNS = AccessProviderType("cloudns")
|
AccessProviderTypeClouDNS = AccessProviderType("cloudns")
|
||||||
AccessProviderTypeCMCCCloud = AccessProviderType("cmcccloud")
|
AccessProviderTypeCMCCCloud = AccessProviderType("cmcccloud")
|
||||||
AccessProviderTypeConstellix = AccessProviderType("constellix")
|
AccessProviderTypeConstellix = AccessProviderType("constellix")
|
||||||
AccessProviderTypeCTCCCloud = AccessProviderType("ctcccloud") // 天翼云(预留)
|
AccessProviderTypeCTCCCloud = AccessProviderType("ctcccloud")
|
||||||
AccessProviderTypeCUCCCloud = AccessProviderType("cucccloud") // 联通云(预留)
|
AccessProviderTypeCUCCCloud = AccessProviderType("cucccloud") // 联通云(预留)
|
||||||
AccessProviderTypeDeSEC = AccessProviderType("desec")
|
AccessProviderTypeDeSEC = AccessProviderType("desec")
|
||||||
AccessProviderTypeDigitalOcean = AccessProviderType("digitalocean")
|
AccessProviderTypeDigitalOcean = AccessProviderType("digitalocean")
|
||||||
@ -118,51 +119,54 @@ ACME DNS-01 提供商常量值。
|
|||||||
NOTICE: If you add new constant, please keep ASCII order.
|
NOTICE: If you add new constant, please keep ASCII order.
|
||||||
*/
|
*/
|
||||||
const (
|
const (
|
||||||
ACMEDns01ProviderTypeACMEHttpReq = ACMEDns01ProviderType(AccessProviderTypeACMEHttpReq)
|
ACMEDns01ProviderTypeACMEHttpReq = ACMEDns01ProviderType(AccessProviderTypeACMEHttpReq)
|
||||||
ACMEDns01ProviderTypeAliyun = ACMEDns01ProviderType(AccessProviderTypeAliyun) // 兼容旧值,等同于 [ACMEDns01ProviderTypeAliyunDNS]
|
ACMEDns01ProviderTypeAliyun = ACMEDns01ProviderType(AccessProviderTypeAliyun) // 兼容旧值,等同于 [ACMEDns01ProviderTypeAliyunDNS]
|
||||||
ACMEDns01ProviderTypeAliyunDNS = ACMEDns01ProviderType(AccessProviderTypeAliyun + "-dns")
|
ACMEDns01ProviderTypeAliyunDNS = ACMEDns01ProviderType(AccessProviderTypeAliyun + "-dns")
|
||||||
ACMEDns01ProviderTypeAliyunESA = ACMEDns01ProviderType(AccessProviderTypeAliyun + "-esa")
|
ACMEDns01ProviderTypeAliyunESA = ACMEDns01ProviderType(AccessProviderTypeAliyun + "-esa")
|
||||||
ACMEDns01ProviderTypeAWS = ACMEDns01ProviderType(AccessProviderTypeAWS) // 兼容旧值,等同于 [ACMEDns01ProviderTypeAWSRoute53]
|
ACMEDns01ProviderTypeAWS = ACMEDns01ProviderType(AccessProviderTypeAWS) // 兼容旧值,等同于 [ACMEDns01ProviderTypeAWSRoute53]
|
||||||
ACMEDns01ProviderTypeAWSRoute53 = ACMEDns01ProviderType(AccessProviderTypeAWS + "-route53")
|
ACMEDns01ProviderTypeAWSRoute53 = ACMEDns01ProviderType(AccessProviderTypeAWS + "-route53")
|
||||||
ACMEDns01ProviderTypeAzure = ACMEDns01ProviderType(AccessProviderTypeAzure) // 兼容旧值,等同于 [ACMEDns01ProviderTypeAzure]
|
ACMEDns01ProviderTypeAzure = ACMEDns01ProviderType(AccessProviderTypeAzure) // 兼容旧值,等同于 [ACMEDns01ProviderTypeAzure]
|
||||||
ACMEDns01ProviderTypeAzureDNS = ACMEDns01ProviderType(AccessProviderTypeAzure + "-dns")
|
ACMEDns01ProviderTypeAzureDNS = ACMEDns01ProviderType(AccessProviderTypeAzure + "-dns")
|
||||||
ACMEDns01ProviderTypeBaiduCloud = ACMEDns01ProviderType(AccessProviderTypeBaiduCloud) // 兼容旧值,等同于 [ACMEDns01ProviderTypeBaiduCloudDNS]
|
ACMEDns01ProviderTypeBaiduCloud = ACMEDns01ProviderType(AccessProviderTypeBaiduCloud) // 兼容旧值,等同于 [ACMEDns01ProviderTypeBaiduCloudDNS]
|
||||||
ACMEDns01ProviderTypeBaiduCloudDNS = ACMEDns01ProviderType(AccessProviderTypeBaiduCloud + "-dns")
|
ACMEDns01ProviderTypeBaiduCloudDNS = ACMEDns01ProviderType(AccessProviderTypeBaiduCloud + "-dns")
|
||||||
ACMEDns01ProviderTypeBunny = ACMEDns01ProviderType(AccessProviderTypeBunny)
|
ACMEDns01ProviderTypeBunny = ACMEDns01ProviderType(AccessProviderTypeBunny)
|
||||||
ACMEDns01ProviderTypeCloudflare = ACMEDns01ProviderType(AccessProviderTypeCloudflare)
|
ACMEDns01ProviderTypeCloudflare = ACMEDns01ProviderType(AccessProviderTypeCloudflare)
|
||||||
ACMEDns01ProviderTypeClouDNS = ACMEDns01ProviderType(AccessProviderTypeClouDNS)
|
ACMEDns01ProviderTypeClouDNS = ACMEDns01ProviderType(AccessProviderTypeClouDNS)
|
||||||
ACMEDns01ProviderTypeCMCCCloud = ACMEDns01ProviderType(AccessProviderTypeCMCCCloud)
|
ACMEDns01ProviderTypeCMCCCloud = ACMEDns01ProviderType(AccessProviderTypeCMCCCloud) // 兼容旧值,等同于 [ACMEDns01ProviderTypeCMCCCloudDNS]
|
||||||
ACMEDns01ProviderTypeConstellix = ACMEDns01ProviderType(AccessProviderTypeConstellix)
|
ACMEDns01ProviderTypeCMCCCloudDNS = ACMEDns01ProviderType(AccessProviderTypeCMCCCloud + "-dns")
|
||||||
ACMEDns01ProviderTypeDeSEC = ACMEDns01ProviderType(AccessProviderTypeDeSEC)
|
ACMEDns01ProviderTypeConstellix = ACMEDns01ProviderType(AccessProviderTypeConstellix)
|
||||||
ACMEDns01ProviderTypeDigitalOcean = ACMEDns01ProviderType(AccessProviderTypeDigitalOcean)
|
ACMEDns01ProviderTypeCTCCCloud = ACMEDns01ProviderType(AccessProviderTypeCTCCCloud) // 兼容旧值,等同于 [ACMEDns01ProviderTypeCTCCCloudSmartDNS]
|
||||||
ACMEDns01ProviderTypeDNSLA = ACMEDns01ProviderType(AccessProviderTypeDNSLA)
|
ACMEDns01ProviderTypeCTCCCloudSmartDNS = ACMEDns01ProviderType(AccessProviderTypeCTCCCloud + "-smartdns")
|
||||||
ACMEDns01ProviderTypeDuckDNS = ACMEDns01ProviderType(AccessProviderTypeDuckDNS)
|
ACMEDns01ProviderTypeDeSEC = ACMEDns01ProviderType(AccessProviderTypeDeSEC)
|
||||||
ACMEDns01ProviderTypeDynv6 = ACMEDns01ProviderType(AccessProviderTypeDynv6)
|
ACMEDns01ProviderTypeDigitalOcean = ACMEDns01ProviderType(AccessProviderTypeDigitalOcean)
|
||||||
ACMEDns01ProviderTypeGcore = ACMEDns01ProviderType(AccessProviderTypeGcore)
|
ACMEDns01ProviderTypeDNSLA = ACMEDns01ProviderType(AccessProviderTypeDNSLA)
|
||||||
ACMEDns01ProviderTypeGname = ACMEDns01ProviderType(AccessProviderTypeGname)
|
ACMEDns01ProviderTypeDuckDNS = ACMEDns01ProviderType(AccessProviderTypeDuckDNS)
|
||||||
ACMEDns01ProviderTypeGoDaddy = ACMEDns01ProviderType(AccessProviderTypeGoDaddy)
|
ACMEDns01ProviderTypeDynv6 = ACMEDns01ProviderType(AccessProviderTypeDynv6)
|
||||||
ACMEDns01ProviderTypeHetzner = ACMEDns01ProviderType(AccessProviderTypeHetzner)
|
ACMEDns01ProviderTypeGcore = ACMEDns01ProviderType(AccessProviderTypeGcore)
|
||||||
ACMEDns01ProviderTypeHuaweiCloud = ACMEDns01ProviderType(AccessProviderTypeHuaweiCloud) // 兼容旧值,等同于 [ACMEDns01ProviderTypeHuaweiCloudDNS]
|
ACMEDns01ProviderTypeGname = ACMEDns01ProviderType(AccessProviderTypeGname)
|
||||||
ACMEDns01ProviderTypeHuaweiCloudDNS = ACMEDns01ProviderType(AccessProviderTypeHuaweiCloud + "-dns")
|
ACMEDns01ProviderTypeGoDaddy = ACMEDns01ProviderType(AccessProviderTypeGoDaddy)
|
||||||
ACMEDns01ProviderTypeJDCloud = ACMEDns01ProviderType(AccessProviderTypeJDCloud) // 兼容旧值,等同于 [ACMEDns01ProviderTypeJDCloudDNS]
|
ACMEDns01ProviderTypeHetzner = ACMEDns01ProviderType(AccessProviderTypeHetzner)
|
||||||
ACMEDns01ProviderTypeJDCloudDNS = ACMEDns01ProviderType(AccessProviderTypeJDCloud + "-dns")
|
ACMEDns01ProviderTypeHuaweiCloud = ACMEDns01ProviderType(AccessProviderTypeHuaweiCloud) // 兼容旧值,等同于 [ACMEDns01ProviderTypeHuaweiCloudDNS]
|
||||||
ACMEDns01ProviderTypeNamecheap = ACMEDns01ProviderType(AccessProviderTypeNamecheap)
|
ACMEDns01ProviderTypeHuaweiCloudDNS = ACMEDns01ProviderType(AccessProviderTypeHuaweiCloud + "-dns")
|
||||||
ACMEDns01ProviderTypeNameDotCom = ACMEDns01ProviderType(AccessProviderTypeNameDotCom)
|
ACMEDns01ProviderTypeJDCloud = ACMEDns01ProviderType(AccessProviderTypeJDCloud) // 兼容旧值,等同于 [ACMEDns01ProviderTypeJDCloudDNS]
|
||||||
ACMEDns01ProviderTypeNameSilo = ACMEDns01ProviderType(AccessProviderTypeNameSilo)
|
ACMEDns01ProviderTypeJDCloudDNS = ACMEDns01ProviderType(AccessProviderTypeJDCloud + "-dns")
|
||||||
ACMEDns01ProviderTypeNetcup = ACMEDns01ProviderType(AccessProviderTypeNetcup)
|
ACMEDns01ProviderTypeNamecheap = ACMEDns01ProviderType(AccessProviderTypeNamecheap)
|
||||||
ACMEDns01ProviderTypeNetlify = ACMEDns01ProviderType(AccessProviderTypeNetlify)
|
ACMEDns01ProviderTypeNameDotCom = ACMEDns01ProviderType(AccessProviderTypeNameDotCom)
|
||||||
ACMEDns01ProviderTypeNS1 = ACMEDns01ProviderType(AccessProviderTypeNS1)
|
ACMEDns01ProviderTypeNameSilo = ACMEDns01ProviderType(AccessProviderTypeNameSilo)
|
||||||
ACMEDns01ProviderTypePorkbun = ACMEDns01ProviderType(AccessProviderTypePorkbun)
|
ACMEDns01ProviderTypeNetcup = ACMEDns01ProviderType(AccessProviderTypeNetcup)
|
||||||
ACMEDns01ProviderTypePowerDNS = ACMEDns01ProviderType(AccessProviderTypePowerDNS)
|
ACMEDns01ProviderTypeNetlify = ACMEDns01ProviderType(AccessProviderTypeNetlify)
|
||||||
ACMEDns01ProviderTypeRainYun = ACMEDns01ProviderType(AccessProviderTypeRainYun)
|
ACMEDns01ProviderTypeNS1 = ACMEDns01ProviderType(AccessProviderTypeNS1)
|
||||||
ACMEDns01ProviderTypeTencentCloud = ACMEDns01ProviderType(AccessProviderTypeTencentCloud) // 兼容旧值,等同于 [ACMEDns01ProviderTypeTencentCloudDNS]
|
ACMEDns01ProviderTypePorkbun = ACMEDns01ProviderType(AccessProviderTypePorkbun)
|
||||||
ACMEDns01ProviderTypeTencentCloudDNS = ACMEDns01ProviderType(AccessProviderTypeTencentCloud + "-dns")
|
ACMEDns01ProviderTypePowerDNS = ACMEDns01ProviderType(AccessProviderTypePowerDNS)
|
||||||
ACMEDns01ProviderTypeTencentCloudEO = ACMEDns01ProviderType(AccessProviderTypeTencentCloud + "-eo")
|
ACMEDns01ProviderTypeRainYun = ACMEDns01ProviderType(AccessProviderTypeRainYun)
|
||||||
ACMEDns01ProviderTypeUCloudUDNR = ACMEDns01ProviderType(AccessProviderTypeUCloud + "-udnr")
|
ACMEDns01ProviderTypeTencentCloud = ACMEDns01ProviderType(AccessProviderTypeTencentCloud) // 兼容旧值,等同于 [ACMEDns01ProviderTypeTencentCloudDNS]
|
||||||
ACMEDns01ProviderTypeVercel = ACMEDns01ProviderType(AccessProviderTypeVercel)
|
ACMEDns01ProviderTypeTencentCloudDNS = ACMEDns01ProviderType(AccessProviderTypeTencentCloud + "-dns")
|
||||||
ACMEDns01ProviderTypeVolcEngine = ACMEDns01ProviderType(AccessProviderTypeVolcEngine) // 兼容旧值,等同于 [ACMEDns01ProviderTypeVolcEngineDNS]
|
ACMEDns01ProviderTypeTencentCloudEO = ACMEDns01ProviderType(AccessProviderTypeTencentCloud + "-eo")
|
||||||
ACMEDns01ProviderTypeVolcEngineDNS = ACMEDns01ProviderType(AccessProviderTypeVolcEngine + "-dns")
|
ACMEDns01ProviderTypeUCloudUDNR = ACMEDns01ProviderType(AccessProviderTypeUCloud + "-udnr")
|
||||||
ACMEDns01ProviderTypeWestcn = ACMEDns01ProviderType(AccessProviderTypeWestcn)
|
ACMEDns01ProviderTypeVercel = ACMEDns01ProviderType(AccessProviderTypeVercel)
|
||||||
|
ACMEDns01ProviderTypeVolcEngine = ACMEDns01ProviderType(AccessProviderTypeVolcEngine) // 兼容旧值,等同于 [ACMEDns01ProviderTypeVolcEngineDNS]
|
||||||
|
ACMEDns01ProviderTypeVolcEngineDNS = ACMEDns01ProviderType(AccessProviderTypeVolcEngine + "-dns")
|
||||||
|
ACMEDns01ProviderTypeWestcn = ACMEDns01ProviderType(AccessProviderTypeWestcn)
|
||||||
)
|
)
|
||||||
|
|
||||||
type DeploymentProviderType string
|
type DeploymentProviderType string
|
||||||
@ -193,6 +197,7 @@ const (
|
|||||||
DeploymentProviderTypeAliyunOSS = DeploymentProviderType(AccessProviderTypeAliyun + "-oss")
|
DeploymentProviderTypeAliyunOSS = DeploymentProviderType(AccessProviderTypeAliyun + "-oss")
|
||||||
DeploymentProviderTypeAliyunVOD = DeploymentProviderType(AccessProviderTypeAliyun + "-vod")
|
DeploymentProviderTypeAliyunVOD = DeploymentProviderType(AccessProviderTypeAliyun + "-vod")
|
||||||
DeploymentProviderTypeAliyunWAF = DeploymentProviderType(AccessProviderTypeAliyun + "-waf")
|
DeploymentProviderTypeAliyunWAF = DeploymentProviderType(AccessProviderTypeAliyun + "-waf")
|
||||||
|
DeploymentProviderTypeAPISIX = DeploymentProviderType(AccessProviderTypeAWS + "-apisix")
|
||||||
DeploymentProviderTypeAWSACM = DeploymentProviderType(AccessProviderTypeAWS + "-acm")
|
DeploymentProviderTypeAWSACM = DeploymentProviderType(AccessProviderTypeAWS + "-acm")
|
||||||
DeploymentProviderTypeAWSCloudFront = DeploymentProviderType(AccessProviderTypeAWS + "-cloudfront")
|
DeploymentProviderTypeAWSCloudFront = DeploymentProviderType(AccessProviderTypeAWS + "-cloudfront")
|
||||||
DeploymentProviderTypeAWSIAM = DeploymentProviderType(AccessProviderTypeAWS + "-iam")
|
DeploymentProviderTypeAWSIAM = DeploymentProviderType(AccessProviderTypeAWS + "-iam")
|
||||||
@ -210,6 +215,12 @@ const (
|
|||||||
DeploymentProviderTypeBytePlusCDN = DeploymentProviderType(AccessProviderTypeBytePlus + "-cdn")
|
DeploymentProviderTypeBytePlusCDN = DeploymentProviderType(AccessProviderTypeBytePlus + "-cdn")
|
||||||
DeploymentProviderTypeCacheFly = DeploymentProviderType(AccessProviderTypeCacheFly)
|
DeploymentProviderTypeCacheFly = DeploymentProviderType(AccessProviderTypeCacheFly)
|
||||||
DeploymentProviderTypeCdnfly = DeploymentProviderType(AccessProviderTypeCdnfly)
|
DeploymentProviderTypeCdnfly = DeploymentProviderType(AccessProviderTypeCdnfly)
|
||||||
|
DeploymentProviderTypeCTCCCloudAO = DeploymentProviderType(AccessProviderTypeCTCCCloud + "-ao")
|
||||||
|
DeploymentProviderTypeCTCCCloudCDN = DeploymentProviderType(AccessProviderTypeCTCCCloud + "-cdn")
|
||||||
|
DeploymentProviderTypeCTCCCloudCMS = DeploymentProviderType(AccessProviderTypeCTCCCloud + "-cms")
|
||||||
|
DeploymentProviderTypeCTCCCloudELB = DeploymentProviderType(AccessProviderTypeCTCCCloud + "-elb")
|
||||||
|
DeploymentProviderTypeCTCCCloudICDN = DeploymentProviderType(AccessProviderTypeCTCCCloud + "-icdn")
|
||||||
|
DeploymentProviderTypeCTCCCloudLVDN = DeploymentProviderType(AccessProviderTypeCTCCCloud + "-ldvn")
|
||||||
DeploymentProviderTypeDogeCloudCDN = DeploymentProviderType(AccessProviderTypeDogeCloud + "-cdn")
|
DeploymentProviderTypeDogeCloudCDN = DeploymentProviderType(AccessProviderTypeDogeCloud + "-cdn")
|
||||||
DeploymentProviderTypeEdgioApplications = DeploymentProviderType(AccessProviderTypeEdgio + "-applications")
|
DeploymentProviderTypeEdgioApplications = DeploymentProviderType(AccessProviderTypeEdgio + "-applications")
|
||||||
DeploymentProviderTypeFlexCDN = DeploymentProviderType(AccessProviderTypeFlexCDN)
|
DeploymentProviderTypeFlexCDN = DeploymentProviderType(AccessProviderTypeFlexCDN)
|
||||||
@ -242,6 +253,7 @@ const (
|
|||||||
DeploymentProviderTypeTencentCloudCSS = DeploymentProviderType(AccessProviderTypeTencentCloud + "-css")
|
DeploymentProviderTypeTencentCloudCSS = DeploymentProviderType(AccessProviderTypeTencentCloud + "-css")
|
||||||
DeploymentProviderTypeTencentCloudECDN = DeploymentProviderType(AccessProviderTypeTencentCloud + "-ecdn")
|
DeploymentProviderTypeTencentCloudECDN = DeploymentProviderType(AccessProviderTypeTencentCloud + "-ecdn")
|
||||||
DeploymentProviderTypeTencentCloudEO = DeploymentProviderType(AccessProviderTypeTencentCloud + "-eo")
|
DeploymentProviderTypeTencentCloudEO = DeploymentProviderType(AccessProviderTypeTencentCloud + "-eo")
|
||||||
|
DeploymentProviderTypeTencentCloudGAAP = DeploymentProviderType(AccessProviderTypeTencentCloud + "-gaap")
|
||||||
DeploymentProviderTypeTencentCloudSCF = DeploymentProviderType(AccessProviderTypeTencentCloud + "-scf")
|
DeploymentProviderTypeTencentCloudSCF = DeploymentProviderType(AccessProviderTypeTencentCloud + "-scf")
|
||||||
DeploymentProviderTypeTencentCloudSSL = DeploymentProviderType(AccessProviderTypeTencentCloud + "-ssl")
|
DeploymentProviderTypeTencentCloudSSL = DeploymentProviderType(AccessProviderTypeTencentCloud + "-ssl")
|
||||||
DeploymentProviderTypeTencentCloudSSLDeploy = DeploymentProviderType(AccessProviderTypeTencentCloud + "-ssldeploy")
|
DeploymentProviderTypeTencentCloudSSLDeploy = DeploymentProviderType(AccessProviderTypeTencentCloud + "-ssldeploy")
|
||||||
|
@ -4,8 +4,8 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/usual2970/certimate/internal/domain/expr"
|
"github.com/certimate-go/certimate/internal/domain/expr"
|
||||||
maputil "github.com/usual2970/certimate/internal/pkg/utils/map"
|
xmaps "github.com/certimate-go/certimate/pkg/utils/maps"
|
||||||
)
|
)
|
||||||
|
|
||||||
const CollectionNameWorkflow = "workflow"
|
const CollectionNameWorkflow = "workflow"
|
||||||
@ -121,62 +121,62 @@ type WorkflowNodeConfigForCondition struct {
|
|||||||
|
|
||||||
func (n *WorkflowNode) GetConfigForApply() WorkflowNodeConfigForApply {
|
func (n *WorkflowNode) GetConfigForApply() WorkflowNodeConfigForApply {
|
||||||
return WorkflowNodeConfigForApply{
|
return WorkflowNodeConfigForApply{
|
||||||
Domains: maputil.GetString(n.Config, "domains"),
|
Domains: xmaps.GetString(n.Config, "domains"),
|
||||||
ContactEmail: maputil.GetString(n.Config, "contactEmail"),
|
ContactEmail: xmaps.GetString(n.Config, "contactEmail"),
|
||||||
Provider: maputil.GetString(n.Config, "provider"),
|
Provider: xmaps.GetString(n.Config, "provider"),
|
||||||
ProviderAccessId: maputil.GetString(n.Config, "providerAccessId"),
|
ProviderAccessId: xmaps.GetString(n.Config, "providerAccessId"),
|
||||||
ProviderConfig: maputil.GetKVMapAny(n.Config, "providerConfig"),
|
ProviderConfig: xmaps.GetKVMapAny(n.Config, "providerConfig"),
|
||||||
CAProvider: maputil.GetString(n.Config, "caProvider"),
|
CAProvider: xmaps.GetString(n.Config, "caProvider"),
|
||||||
CAProviderAccessId: maputil.GetString(n.Config, "caProviderAccessId"),
|
CAProviderAccessId: xmaps.GetString(n.Config, "caProviderAccessId"),
|
||||||
CAProviderConfig: maputil.GetKVMapAny(n.Config, "caProviderConfig"),
|
CAProviderConfig: xmaps.GetKVMapAny(n.Config, "caProviderConfig"),
|
||||||
KeyAlgorithm: maputil.GetOrDefaultString(n.Config, "keyAlgorithm", string(CertificateKeyAlgorithmTypeRSA2048)),
|
KeyAlgorithm: xmaps.GetOrDefaultString(n.Config, "keyAlgorithm", string(CertificateKeyAlgorithmTypeRSA2048)),
|
||||||
Nameservers: maputil.GetString(n.Config, "nameservers"),
|
Nameservers: xmaps.GetString(n.Config, "nameservers"),
|
||||||
DnsPropagationWait: maputil.GetInt32(n.Config, "dnsPropagationWait"),
|
DnsPropagationWait: xmaps.GetInt32(n.Config, "dnsPropagationWait"),
|
||||||
DnsPropagationTimeout: maputil.GetInt32(n.Config, "dnsPropagationTimeout"),
|
DnsPropagationTimeout: xmaps.GetInt32(n.Config, "dnsPropagationTimeout"),
|
||||||
DnsTTL: maputil.GetInt32(n.Config, "dnsTTL"),
|
DnsTTL: xmaps.GetInt32(n.Config, "dnsTTL"),
|
||||||
DisableFollowCNAME: maputil.GetBool(n.Config, "disableFollowCNAME"),
|
DisableFollowCNAME: xmaps.GetBool(n.Config, "disableFollowCNAME"),
|
||||||
DisableARI: maputil.GetBool(n.Config, "disableARI"),
|
DisableARI: xmaps.GetBool(n.Config, "disableARI"),
|
||||||
SkipBeforeExpiryDays: maputil.GetOrDefaultInt32(n.Config, "skipBeforeExpiryDays", 30),
|
SkipBeforeExpiryDays: xmaps.GetOrDefaultInt32(n.Config, "skipBeforeExpiryDays", 30),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *WorkflowNode) GetConfigForUpload() WorkflowNodeConfigForUpload {
|
func (n *WorkflowNode) GetConfigForUpload() WorkflowNodeConfigForUpload {
|
||||||
return WorkflowNodeConfigForUpload{
|
return WorkflowNodeConfigForUpload{
|
||||||
Certificate: maputil.GetString(n.Config, "certificate"),
|
Certificate: xmaps.GetString(n.Config, "certificate"),
|
||||||
PrivateKey: maputil.GetString(n.Config, "privateKey"),
|
PrivateKey: xmaps.GetString(n.Config, "privateKey"),
|
||||||
Domains: maputil.GetString(n.Config, "domains"),
|
Domains: xmaps.GetString(n.Config, "domains"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *WorkflowNode) GetConfigForMonitor() WorkflowNodeConfigForMonitor {
|
func (n *WorkflowNode) GetConfigForMonitor() WorkflowNodeConfigForMonitor {
|
||||||
host := maputil.GetString(n.Config, "host")
|
host := xmaps.GetString(n.Config, "host")
|
||||||
return WorkflowNodeConfigForMonitor{
|
return WorkflowNodeConfigForMonitor{
|
||||||
Host: host,
|
Host: host,
|
||||||
Port: maputil.GetOrDefaultInt32(n.Config, "port", 443),
|
Port: xmaps.GetOrDefaultInt32(n.Config, "port", 443),
|
||||||
Domain: maputil.GetOrDefaultString(n.Config, "domain", host),
|
Domain: xmaps.GetOrDefaultString(n.Config, "domain", host),
|
||||||
RequestPath: maputil.GetString(n.Config, "path"),
|
RequestPath: xmaps.GetString(n.Config, "path"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *WorkflowNode) GetConfigForDeploy() WorkflowNodeConfigForDeploy {
|
func (n *WorkflowNode) GetConfigForDeploy() WorkflowNodeConfigForDeploy {
|
||||||
return WorkflowNodeConfigForDeploy{
|
return WorkflowNodeConfigForDeploy{
|
||||||
Certificate: maputil.GetString(n.Config, "certificate"),
|
Certificate: xmaps.GetString(n.Config, "certificate"),
|
||||||
Provider: maputil.GetString(n.Config, "provider"),
|
Provider: xmaps.GetString(n.Config, "provider"),
|
||||||
ProviderAccessId: maputil.GetString(n.Config, "providerAccessId"),
|
ProviderAccessId: xmaps.GetString(n.Config, "providerAccessId"),
|
||||||
ProviderConfig: maputil.GetKVMapAny(n.Config, "providerConfig"),
|
ProviderConfig: xmaps.GetKVMapAny(n.Config, "providerConfig"),
|
||||||
SkipOnLastSucceeded: maputil.GetBool(n.Config, "skipOnLastSucceeded"),
|
SkipOnLastSucceeded: xmaps.GetBool(n.Config, "skipOnLastSucceeded"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *WorkflowNode) GetConfigForNotify() WorkflowNodeConfigForNotify {
|
func (n *WorkflowNode) GetConfigForNotify() WorkflowNodeConfigForNotify {
|
||||||
return WorkflowNodeConfigForNotify{
|
return WorkflowNodeConfigForNotify{
|
||||||
Channel: maputil.GetString(n.Config, "channel"),
|
Channel: xmaps.GetString(n.Config, "channel"),
|
||||||
Provider: maputil.GetString(n.Config, "provider"),
|
Provider: xmaps.GetString(n.Config, "provider"),
|
||||||
ProviderAccessId: maputil.GetString(n.Config, "providerAccessId"),
|
ProviderAccessId: xmaps.GetString(n.Config, "providerAccessId"),
|
||||||
ProviderConfig: maputil.GetKVMapAny(n.Config, "providerConfig"),
|
ProviderConfig: xmaps.GetKVMapAny(n.Config, "providerConfig"),
|
||||||
Subject: maputil.GetString(n.Config, "subject"),
|
Subject: xmaps.GetString(n.Config, "subject"),
|
||||||
Message: maputil.GetString(n.Config, "message"),
|
Message: xmaps.GetString(n.Config, "message"),
|
||||||
SkipOnAllPrevSkipped: maputil.GetBool(n.Config, "skipOnAllPrevSkipped"),
|
SkipOnAllPrevSkipped: xmaps.GetBool(n.Config, "skipOnAllPrevSkipped"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,9 +5,9 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
|
|
||||||
"github.com/usual2970/certimate/internal/domain"
|
"github.com/certimate-go/certimate/internal/domain"
|
||||||
"github.com/usual2970/certimate/internal/pkg/core/notifier"
|
"github.com/certimate-go/certimate/internal/repository"
|
||||||
"github.com/usual2970/certimate/internal/repository"
|
"github.com/certimate-go/certimate/pkg/core"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Notifier interface {
|
type Notifier interface {
|
||||||
@ -46,20 +46,22 @@ func NewWithWorkflowNode(config NotifierWithWorkflowNodeConfig) (Notifier, error
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
notifierProvider, err := createNotifierProvider(options)
|
notifier, err := createNotifierProvider(options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
} else {
|
||||||
|
notifier.SetLogger(config.Logger)
|
||||||
}
|
}
|
||||||
|
|
||||||
return ¬ifierImpl{
|
return ¬ifierImpl{
|
||||||
provider: notifierProvider.WithLogger(config.Logger),
|
provider: notifier,
|
||||||
subject: config.Subject,
|
subject: config.Subject,
|
||||||
message: config.Message,
|
message: config.Message,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type notifierImpl struct {
|
type notifierImpl struct {
|
||||||
provider notifier.Notifier
|
provider core.Notifier
|
||||||
subject string
|
subject string
|
||||||
message string
|
message string
|
||||||
}
|
}
|
||||||
|
@ -7,10 +7,10 @@ import (
|
|||||||
|
|
||||||
"golang.org/x/sync/errgroup"
|
"golang.org/x/sync/errgroup"
|
||||||
|
|
||||||
"github.com/usual2970/certimate/internal/domain"
|
"github.com/certimate-go/certimate/internal/domain"
|
||||||
"github.com/usual2970/certimate/internal/pkg/core/notifier"
|
"github.com/certimate-go/certimate/internal/repository"
|
||||||
maputil "github.com/usual2970/certimate/internal/pkg/utils/map"
|
"github.com/certimate-go/certimate/pkg/core"
|
||||||
"github.com/usual2970/certimate/internal/repository"
|
xmaps "github.com/certimate-go/certimate/pkg/utils/maps"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Deprecated: v0.4.x 将废弃
|
// Deprecated: v0.4.x 将废弃
|
||||||
@ -51,7 +51,7 @@ func SendToChannel(subject, message string, channel string, channelConfig map[st
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: v0.4.x 将废弃
|
// Deprecated: v0.4.x 将废弃
|
||||||
func getEnabledNotifiers() ([]notifier.Notifier, error) {
|
func getEnabledNotifiers() ([]core.Notifier, error) {
|
||||||
settingsRepo := repository.NewSettingsRepository()
|
settingsRepo := repository.NewSettingsRepository()
|
||||||
settings, err := settingsRepo.GetByName(context.Background(), "notifyChannels")
|
settings, err := settingsRepo.GetByName(context.Background(), "notifyChannels")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -63,9 +63,9 @@ func getEnabledNotifiers() ([]notifier.Notifier, error) {
|
|||||||
return nil, fmt.Errorf("unmarshal notifyChannels error: %w", err)
|
return nil, fmt.Errorf("unmarshal notifyChannels error: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
notifiers := make([]notifier.Notifier, 0)
|
notifiers := make([]core.Notifier, 0)
|
||||||
for k, v := range rs {
|
for k, v := range rs {
|
||||||
if !maputil.GetBool(v, "enabled") {
|
if !xmaps.GetBool(v, "enabled") {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,19 +4,19 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/usual2970/certimate/internal/domain"
|
"github.com/certimate-go/certimate/internal/domain"
|
||||||
"github.com/usual2970/certimate/internal/pkg/core/notifier"
|
"github.com/certimate-go/certimate/pkg/core"
|
||||||
pDingTalkBot "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/dingtalkbot"
|
pDingTalkBot "github.com/certimate-go/certimate/pkg/core/notifier/providers/dingtalkbot"
|
||||||
pDiscordBot "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/discordbot"
|
pDiscordBot "github.com/certimate-go/certimate/pkg/core/notifier/providers/discordbot"
|
||||||
pEmail "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/email"
|
pEmail "github.com/certimate-go/certimate/pkg/core/notifier/providers/email"
|
||||||
pLarkBot "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/larkbot"
|
pLarkBot "github.com/certimate-go/certimate/pkg/core/notifier/providers/larkbot"
|
||||||
pMattermost "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/mattermost"
|
pMattermost "github.com/certimate-go/certimate/pkg/core/notifier/providers/mattermost"
|
||||||
pSlackBot "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/slackbot"
|
pSlackBot "github.com/certimate-go/certimate/pkg/core/notifier/providers/slackbot"
|
||||||
pTelegramBot "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/telegrambot"
|
pTelegramBot "github.com/certimate-go/certimate/pkg/core/notifier/providers/telegrambot"
|
||||||
pWebhook "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/webhook"
|
pWebhook "github.com/certimate-go/certimate/pkg/core/notifier/providers/webhook"
|
||||||
pWeComBot "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/wecombot"
|
pWeComBot "github.com/certimate-go/certimate/pkg/core/notifier/providers/wecombot"
|
||||||
httputil "github.com/usual2970/certimate/internal/pkg/utils/http"
|
xhttp "github.com/certimate-go/certimate/pkg/utils/http"
|
||||||
maputil "github.com/usual2970/certimate/internal/pkg/utils/map"
|
xmaps "github.com/certimate-go/certimate/pkg/utils/maps"
|
||||||
)
|
)
|
||||||
|
|
||||||
type notifierProviderOptions struct {
|
type notifierProviderOptions struct {
|
||||||
@ -25,7 +25,7 @@ type notifierProviderOptions struct {
|
|||||||
ProviderServiceConfig map[string]any
|
ProviderServiceConfig map[string]any
|
||||||
}
|
}
|
||||||
|
|
||||||
func createNotifierProvider(options *notifierProviderOptions) (notifier.Notifier, error) {
|
func createNotifierProvider(options *notifierProviderOptions) (core.Notifier, error) {
|
||||||
/*
|
/*
|
||||||
注意:如果追加新的常量值,请保持以 ASCII 排序。
|
注意:如果追加新的常量值,请保持以 ASCII 排序。
|
||||||
NOTICE: If you add new constant, please keep ASCII order.
|
NOTICE: If you add new constant, please keep ASCII order.
|
||||||
@ -34,11 +34,11 @@ func createNotifierProvider(options *notifierProviderOptions) (notifier.Notifier
|
|||||||
case domain.NotificationProviderTypeDingTalkBot:
|
case domain.NotificationProviderTypeDingTalkBot:
|
||||||
{
|
{
|
||||||
access := domain.AccessConfigForDingTalkBot{}
|
access := domain.AccessConfigForDingTalkBot{}
|
||||||
if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil {
|
if err := xmaps.Populate(options.ProviderAccessConfig, &access); err != nil {
|
||||||
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return pDingTalkBot.NewNotifier(&pDingTalkBot.NotifierConfig{
|
return pDingTalkBot.NewNotifierProvider(&pDingTalkBot.NotifierProviderConfig{
|
||||||
WebhookUrl: access.WebhookUrl,
|
WebhookUrl: access.WebhookUrl,
|
||||||
Secret: access.Secret,
|
Secret: access.Secret,
|
||||||
})
|
})
|
||||||
@ -47,42 +47,43 @@ func createNotifierProvider(options *notifierProviderOptions) (notifier.Notifier
|
|||||||
case domain.NotificationProviderTypeDiscordBot:
|
case domain.NotificationProviderTypeDiscordBot:
|
||||||
{
|
{
|
||||||
access := domain.AccessConfigForDiscordBot{}
|
access := domain.AccessConfigForDiscordBot{}
|
||||||
if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil {
|
if err := xmaps.Populate(options.ProviderAccessConfig, &access); err != nil {
|
||||||
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return pDiscordBot.NewNotifier(&pDiscordBot.NotifierConfig{
|
return pDiscordBot.NewNotifierProvider(&pDiscordBot.NotifierProviderConfig{
|
||||||
BotToken: access.BotToken,
|
BotToken: access.BotToken,
|
||||||
ChannelId: maputil.GetOrDefaultString(options.ProviderServiceConfig, "channelId", access.DefaultChannelId),
|
ChannelId: xmaps.GetOrDefaultString(options.ProviderServiceConfig, "channelId", access.DefaultChannelId),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
case domain.NotificationProviderTypeEmail:
|
case domain.NotificationProviderTypeEmail:
|
||||||
{
|
{
|
||||||
access := domain.AccessConfigForEmail{}
|
access := domain.AccessConfigForEmail{}
|
||||||
if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil {
|
if err := xmaps.Populate(options.ProviderAccessConfig, &access); err != nil {
|
||||||
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return pEmail.NewNotifier(&pEmail.NotifierConfig{
|
return pEmail.NewNotifierProvider(&pEmail.NotifierProviderConfig{
|
||||||
SmtpHost: access.SmtpHost,
|
SmtpHost: access.SmtpHost,
|
||||||
SmtpPort: access.SmtpPort,
|
SmtpPort: access.SmtpPort,
|
||||||
SmtpTls: access.SmtpTls,
|
SmtpTls: access.SmtpTls,
|
||||||
Username: access.Username,
|
Username: access.Username,
|
||||||
Password: access.Password,
|
Password: access.Password,
|
||||||
SenderAddress: maputil.GetOrDefaultString(options.ProviderServiceConfig, "senderAddress", access.DefaultSenderAddress),
|
SenderAddress: xmaps.GetOrDefaultString(options.ProviderServiceConfig, "senderAddress", access.DefaultSenderAddress),
|
||||||
ReceiverAddress: maputil.GetOrDefaultString(options.ProviderServiceConfig, "receiverAddress", access.DefaultReceiverAddress),
|
SenderName: xmaps.GetOrDefaultString(options.ProviderServiceConfig, "senderName", access.DefaultSenderName),
|
||||||
|
ReceiverAddress: xmaps.GetOrDefaultString(options.ProviderServiceConfig, "receiverAddress", access.DefaultReceiverAddress),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
case domain.NotificationProviderTypeLarkBot:
|
case domain.NotificationProviderTypeLarkBot:
|
||||||
{
|
{
|
||||||
access := domain.AccessConfigForLarkBot{}
|
access := domain.AccessConfigForLarkBot{}
|
||||||
if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil {
|
if err := xmaps.Populate(options.ProviderAccessConfig, &access); err != nil {
|
||||||
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return pLarkBot.NewNotifier(&pLarkBot.NotifierConfig{
|
return pLarkBot.NewNotifierProvider(&pLarkBot.NotifierProviderConfig{
|
||||||
WebhookUrl: access.WebhookUrl,
|
WebhookUrl: access.WebhookUrl,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -90,54 +91,54 @@ func createNotifierProvider(options *notifierProviderOptions) (notifier.Notifier
|
|||||||
case domain.NotificationProviderTypeMattermost:
|
case domain.NotificationProviderTypeMattermost:
|
||||||
{
|
{
|
||||||
access := domain.AccessConfigForMattermost{}
|
access := domain.AccessConfigForMattermost{}
|
||||||
if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil {
|
if err := xmaps.Populate(options.ProviderAccessConfig, &access); err != nil {
|
||||||
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return pMattermost.NewNotifier(&pMattermost.NotifierConfig{
|
return pMattermost.NewNotifierProvider(&pMattermost.NotifierProviderConfig{
|
||||||
ServerUrl: access.ServerUrl,
|
ServerUrl: access.ServerUrl,
|
||||||
Username: access.Username,
|
Username: access.Username,
|
||||||
Password: access.Password,
|
Password: access.Password,
|
||||||
ChannelId: maputil.GetOrDefaultString(options.ProviderServiceConfig, "channelId", access.DefaultChannelId),
|
ChannelId: xmaps.GetOrDefaultString(options.ProviderServiceConfig, "channelId", access.DefaultChannelId),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
case domain.NotificationProviderTypeSlackBot:
|
case domain.NotificationProviderTypeSlackBot:
|
||||||
{
|
{
|
||||||
access := domain.AccessConfigForSlackBot{}
|
access := domain.AccessConfigForSlackBot{}
|
||||||
if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil {
|
if err := xmaps.Populate(options.ProviderAccessConfig, &access); err != nil {
|
||||||
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return pSlackBot.NewNotifier(&pSlackBot.NotifierConfig{
|
return pSlackBot.NewNotifierProvider(&pSlackBot.NotifierProviderConfig{
|
||||||
BotToken: access.BotToken,
|
BotToken: access.BotToken,
|
||||||
ChannelId: maputil.GetOrDefaultString(options.ProviderServiceConfig, "channelId", access.DefaultChannelId),
|
ChannelId: xmaps.GetOrDefaultString(options.ProviderServiceConfig, "channelId", access.DefaultChannelId),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
case domain.NotificationProviderTypeTelegramBot:
|
case domain.NotificationProviderTypeTelegramBot:
|
||||||
{
|
{
|
||||||
access := domain.AccessConfigForTelegramBot{}
|
access := domain.AccessConfigForTelegramBot{}
|
||||||
if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil {
|
if err := xmaps.Populate(options.ProviderAccessConfig, &access); err != nil {
|
||||||
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return pTelegramBot.NewNotifier(&pTelegramBot.NotifierConfig{
|
return pTelegramBot.NewNotifierProvider(&pTelegramBot.NotifierProviderConfig{
|
||||||
BotToken: access.BotToken,
|
BotToken: access.BotToken,
|
||||||
ChatId: maputil.GetOrDefaultInt64(options.ProviderServiceConfig, "chatId", access.DefaultChatId),
|
ChatId: xmaps.GetOrDefaultInt64(options.ProviderServiceConfig, "chatId", access.DefaultChatId),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
case domain.NotificationProviderTypeWebhook:
|
case domain.NotificationProviderTypeWebhook:
|
||||||
{
|
{
|
||||||
access := domain.AccessConfigForWebhook{}
|
access := domain.AccessConfigForWebhook{}
|
||||||
if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil {
|
if err := xmaps.Populate(options.ProviderAccessConfig, &access); err != nil {
|
||||||
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
mergedHeaders := make(map[string]string)
|
mergedHeaders := make(map[string]string)
|
||||||
if defaultHeadersString := access.HeadersString; defaultHeadersString != "" {
|
if defaultHeadersString := access.HeadersString; defaultHeadersString != "" {
|
||||||
h, err := httputil.ParseHeaders(defaultHeadersString)
|
h, err := xhttp.ParseHeaders(defaultHeadersString)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to parse webhook headers: %w", err)
|
return nil, fmt.Errorf("failed to parse webhook headers: %w", err)
|
||||||
}
|
}
|
||||||
@ -145,8 +146,8 @@ func createNotifierProvider(options *notifierProviderOptions) (notifier.Notifier
|
|||||||
mergedHeaders[http.CanonicalHeaderKey(key)] = h.Get(key)
|
mergedHeaders[http.CanonicalHeaderKey(key)] = h.Get(key)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if extendedHeadersString := maputil.GetString(options.ProviderServiceConfig, "headers"); extendedHeadersString != "" {
|
if extendedHeadersString := xmaps.GetString(options.ProviderServiceConfig, "headers"); extendedHeadersString != "" {
|
||||||
h, err := httputil.ParseHeaders(extendedHeadersString)
|
h, err := xhttp.ParseHeaders(extendedHeadersString)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to parse webhook headers: %w", err)
|
return nil, fmt.Errorf("failed to parse webhook headers: %w", err)
|
||||||
}
|
}
|
||||||
@ -155,9 +156,9 @@ func createNotifierProvider(options *notifierProviderOptions) (notifier.Notifier
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return pWebhook.NewNotifier(&pWebhook.NotifierConfig{
|
return pWebhook.NewNotifierProvider(&pWebhook.NotifierProviderConfig{
|
||||||
WebhookUrl: access.Url,
|
WebhookUrl: access.Url,
|
||||||
WebhookData: maputil.GetOrDefaultString(options.ProviderServiceConfig, "webhookData", access.DefaultDataForNotification),
|
WebhookData: xmaps.GetOrDefaultString(options.ProviderServiceConfig, "webhookData", access.DefaultDataForNotification),
|
||||||
Method: access.Method,
|
Method: access.Method,
|
||||||
Headers: mergedHeaders,
|
Headers: mergedHeaders,
|
||||||
AllowInsecureConnections: access.AllowInsecureConnections,
|
AllowInsecureConnections: access.AllowInsecureConnections,
|
||||||
@ -167,11 +168,11 @@ func createNotifierProvider(options *notifierProviderOptions) (notifier.Notifier
|
|||||||
case domain.NotificationProviderTypeWeComBot:
|
case domain.NotificationProviderTypeWeComBot:
|
||||||
{
|
{
|
||||||
access := domain.AccessConfigForWeComBot{}
|
access := domain.AccessConfigForWeComBot{}
|
||||||
if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil {
|
if err := xmaps.Populate(options.ProviderAccessConfig, &access); err != nil {
|
||||||
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return pWeComBot.NewNotifier(&pWeComBot.NotifierConfig{
|
return pWeComBot.NewNotifierProvider(&pWeComBot.NotifierProviderConfig{
|
||||||
WebhookUrl: access.WebhookUrl,
|
WebhookUrl: access.WebhookUrl,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -3,104 +3,104 @@ package notify
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/usual2970/certimate/internal/domain"
|
"github.com/certimate-go/certimate/internal/domain"
|
||||||
"github.com/usual2970/certimate/internal/pkg/core/notifier"
|
"github.com/certimate-go/certimate/pkg/core"
|
||||||
pBark "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/bark"
|
pBark "github.com/certimate-go/certimate/pkg/core/notifier/providers/bark"
|
||||||
pDingTalk "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/dingtalkbot"
|
pDingTalk "github.com/certimate-go/certimate/pkg/core/notifier/providers/dingtalkbot"
|
||||||
pEmail "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/email"
|
pEmail "github.com/certimate-go/certimate/pkg/core/notifier/providers/email"
|
||||||
pGotify "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/gotify"
|
pGotify "github.com/certimate-go/certimate/pkg/core/notifier/providers/gotify"
|
||||||
pLark "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/larkbot"
|
pLark "github.com/certimate-go/certimate/pkg/core/notifier/providers/larkbot"
|
||||||
pMattermost "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/mattermost"
|
pMattermost "github.com/certimate-go/certimate/pkg/core/notifier/providers/mattermost"
|
||||||
pPushover "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/pushover"
|
pPushover "github.com/certimate-go/certimate/pkg/core/notifier/providers/pushover"
|
||||||
pPushPlus "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/pushplus"
|
pPushPlus "github.com/certimate-go/certimate/pkg/core/notifier/providers/pushplus"
|
||||||
pServerChan "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/serverchan"
|
pServerChan "github.com/certimate-go/certimate/pkg/core/notifier/providers/serverchan"
|
||||||
pTelegram "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/telegrambot"
|
pTelegram "github.com/certimate-go/certimate/pkg/core/notifier/providers/telegrambot"
|
||||||
pWebhook "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/webhook"
|
pWebhook "github.com/certimate-go/certimate/pkg/core/notifier/providers/webhook"
|
||||||
pWeCom "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/wecombot"
|
pWeCom "github.com/certimate-go/certimate/pkg/core/notifier/providers/wecombot"
|
||||||
maputil "github.com/usual2970/certimate/internal/pkg/utils/map"
|
xmaps "github.com/certimate-go/certimate/pkg/utils/maps"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Deprecated: v0.4.x 将废弃
|
// Deprecated: v0.4.x 将废弃
|
||||||
func createNotifierProviderUseGlobalSettings(channel domain.NotifyChannelType, channelConfig map[string]any) (notifier.Notifier, error) {
|
func createNotifierProviderUseGlobalSettings(channel domain.NotifyChannelType, channelConfig map[string]any) (core.Notifier, error) {
|
||||||
/*
|
/*
|
||||||
注意:如果追加新的常量值,请保持以 ASCII 排序。
|
注意:如果追加新的常量值,请保持以 ASCII 排序。
|
||||||
NOTICE: If you add new constant, please keep ASCII order.
|
NOTICE: If you add new constant, please keep ASCII order.
|
||||||
*/
|
*/
|
||||||
switch channel {
|
switch channel {
|
||||||
case domain.NotifyChannelTypeBark:
|
case domain.NotifyChannelTypeBark:
|
||||||
return pBark.NewNotifier(&pBark.NotifierConfig{
|
return pBark.NewNotifierProvider(&pBark.NotifierProviderConfig{
|
||||||
DeviceKey: maputil.GetString(channelConfig, "deviceKey"),
|
DeviceKey: xmaps.GetString(channelConfig, "deviceKey"),
|
||||||
ServerUrl: maputil.GetString(channelConfig, "serverUrl"),
|
ServerUrl: xmaps.GetString(channelConfig, "serverUrl"),
|
||||||
})
|
})
|
||||||
|
|
||||||
case domain.NotifyChannelTypeDingTalk:
|
case domain.NotifyChannelTypeDingTalk:
|
||||||
return pDingTalk.NewNotifier(&pDingTalk.NotifierConfig{
|
return pDingTalk.NewNotifierProvider(&pDingTalk.NotifierProviderConfig{
|
||||||
WebhookUrl: "https://oapi.dingtalk.com/robot/send?access_token=" + maputil.GetString(channelConfig, "accessToken"),
|
WebhookUrl: "https://oapi.dingtalk.com/robot/send?access_token=" + xmaps.GetString(channelConfig, "accessToken"),
|
||||||
Secret: maputil.GetString(channelConfig, "secret"),
|
Secret: xmaps.GetString(channelConfig, "secret"),
|
||||||
})
|
})
|
||||||
|
|
||||||
case domain.NotifyChannelTypeEmail:
|
case domain.NotifyChannelTypeEmail:
|
||||||
return pEmail.NewNotifier(&pEmail.NotifierConfig{
|
return pEmail.NewNotifierProvider(&pEmail.NotifierProviderConfig{
|
||||||
SmtpHost: maputil.GetString(channelConfig, "smtpHost"),
|
SmtpHost: xmaps.GetString(channelConfig, "smtpHost"),
|
||||||
SmtpPort: maputil.GetInt32(channelConfig, "smtpPort"),
|
SmtpPort: xmaps.GetInt32(channelConfig, "smtpPort"),
|
||||||
SmtpTls: maputil.GetOrDefaultBool(channelConfig, "smtpTLS", true),
|
SmtpTls: xmaps.GetOrDefaultBool(channelConfig, "smtpTLS", true),
|
||||||
Username: maputil.GetOrDefaultString(channelConfig, "username", maputil.GetString(channelConfig, "senderAddress")),
|
Username: xmaps.GetOrDefaultString(channelConfig, "username", xmaps.GetString(channelConfig, "senderAddress")),
|
||||||
Password: maputil.GetString(channelConfig, "password"),
|
Password: xmaps.GetString(channelConfig, "password"),
|
||||||
SenderAddress: maputil.GetString(channelConfig, "senderAddress"),
|
SenderAddress: xmaps.GetString(channelConfig, "senderAddress"),
|
||||||
ReceiverAddress: maputil.GetString(channelConfig, "receiverAddress"),
|
ReceiverAddress: xmaps.GetString(channelConfig, "receiverAddress"),
|
||||||
})
|
})
|
||||||
|
|
||||||
case domain.NotifyChannelTypeGotify:
|
case domain.NotifyChannelTypeGotify:
|
||||||
return pGotify.NewNotifier(&pGotify.NotifierConfig{
|
return pGotify.NewNotifierProvider(&pGotify.NotifierProviderConfig{
|
||||||
ServerUrl: maputil.GetString(channelConfig, "url"),
|
ServerUrl: xmaps.GetString(channelConfig, "url"),
|
||||||
Token: maputil.GetString(channelConfig, "token"),
|
Token: xmaps.GetString(channelConfig, "token"),
|
||||||
Priority: maputil.GetOrDefaultInt64(channelConfig, "priority", 1),
|
Priority: xmaps.GetOrDefaultInt64(channelConfig, "priority", 1),
|
||||||
})
|
})
|
||||||
|
|
||||||
case domain.NotifyChannelTypeLark:
|
case domain.NotifyChannelTypeLark:
|
||||||
return pLark.NewNotifier(&pLark.NotifierConfig{
|
return pLark.NewNotifierProvider(&pLark.NotifierProviderConfig{
|
||||||
WebhookUrl: maputil.GetString(channelConfig, "webhookUrl"),
|
WebhookUrl: xmaps.GetString(channelConfig, "webhookUrl"),
|
||||||
})
|
})
|
||||||
|
|
||||||
case domain.NotifyChannelTypeMattermost:
|
case domain.NotifyChannelTypeMattermost:
|
||||||
return pMattermost.NewNotifier(&pMattermost.NotifierConfig{
|
return pMattermost.NewNotifierProvider(&pMattermost.NotifierProviderConfig{
|
||||||
ServerUrl: maputil.GetString(channelConfig, "serverUrl"),
|
ServerUrl: xmaps.GetString(channelConfig, "serverUrl"),
|
||||||
ChannelId: maputil.GetString(channelConfig, "channelId"),
|
ChannelId: xmaps.GetString(channelConfig, "channelId"),
|
||||||
Username: maputil.GetString(channelConfig, "username"),
|
Username: xmaps.GetString(channelConfig, "username"),
|
||||||
Password: maputil.GetString(channelConfig, "password"),
|
Password: xmaps.GetString(channelConfig, "password"),
|
||||||
})
|
})
|
||||||
|
|
||||||
case domain.NotifyChannelTypePushover:
|
case domain.NotifyChannelTypePushover:
|
||||||
return pPushover.NewNotifier(&pPushover.NotifierConfig{
|
return pPushover.NewNotifierProvider(&pPushover.NotifierProviderConfig{
|
||||||
Token: maputil.GetString(channelConfig, "token"),
|
Token: xmaps.GetString(channelConfig, "token"),
|
||||||
User: maputil.GetString(channelConfig, "user"),
|
User: xmaps.GetString(channelConfig, "user"),
|
||||||
})
|
})
|
||||||
|
|
||||||
case domain.NotifyChannelTypePushPlus:
|
case domain.NotifyChannelTypePushPlus:
|
||||||
return pPushPlus.NewNotifier(&pPushPlus.NotifierConfig{
|
return pPushPlus.NewNotifierProvider(&pPushPlus.NotifierProviderConfig{
|
||||||
Token: maputil.GetString(channelConfig, "token"),
|
Token: xmaps.GetString(channelConfig, "token"),
|
||||||
})
|
})
|
||||||
|
|
||||||
case domain.NotifyChannelTypeServerChan:
|
case domain.NotifyChannelTypeServerChan:
|
||||||
return pServerChan.NewNotifier(&pServerChan.NotifierConfig{
|
return pServerChan.NewNotifierProvider(&pServerChan.NotifierProviderConfig{
|
||||||
ServerUrl: maputil.GetString(channelConfig, "url"),
|
ServerUrl: xmaps.GetString(channelConfig, "url"),
|
||||||
})
|
})
|
||||||
|
|
||||||
case domain.NotifyChannelTypeTelegram:
|
case domain.NotifyChannelTypeTelegram:
|
||||||
return pTelegram.NewNotifier(&pTelegram.NotifierConfig{
|
return pTelegram.NewNotifierProvider(&pTelegram.NotifierProviderConfig{
|
||||||
BotToken: maputil.GetString(channelConfig, "apiToken"),
|
BotToken: xmaps.GetString(channelConfig, "apiToken"),
|
||||||
ChatId: maputil.GetInt64(channelConfig, "chatId"),
|
ChatId: xmaps.GetInt64(channelConfig, "chatId"),
|
||||||
})
|
})
|
||||||
|
|
||||||
case domain.NotifyChannelTypeWebhook:
|
case domain.NotifyChannelTypeWebhook:
|
||||||
return pWebhook.NewNotifier(&pWebhook.NotifierConfig{
|
return pWebhook.NewNotifierProvider(&pWebhook.NotifierProviderConfig{
|
||||||
WebhookUrl: maputil.GetString(channelConfig, "url"),
|
WebhookUrl: xmaps.GetString(channelConfig, "url"),
|
||||||
AllowInsecureConnections: maputil.GetBool(channelConfig, "allowInsecureConnections"),
|
AllowInsecureConnections: xmaps.GetBool(channelConfig, "allowInsecureConnections"),
|
||||||
})
|
})
|
||||||
|
|
||||||
case domain.NotifyChannelTypeWeCom:
|
case domain.NotifyChannelTypeWeCom:
|
||||||
return pWeCom.NewNotifier(&pWeCom.NotifierConfig{
|
return pWeCom.NewNotifierProvider(&pWeCom.NotifierProviderConfig{
|
||||||
WebhookUrl: maputil.GetString(channelConfig, "webhookUrl"),
|
WebhookUrl: xmaps.GetString(channelConfig, "webhookUrl"),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,8 +4,8 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/usual2970/certimate/internal/domain"
|
"github.com/certimate-go/certimate/internal/domain"
|
||||||
"github.com/usual2970/certimate/internal/domain/dtos"
|
"github.com/certimate-go/certimate/internal/domain/dtos"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Deprecated: v0.4.x 将废弃
|
// Deprecated: v0.4.x 将废弃
|
||||||
|
@ -1,104 +0,0 @@
|
|||||||
package onepanelconsole
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"crypto/tls"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"log/slog"
|
|
||||||
"net/url"
|
|
||||||
|
|
||||||
"github.com/usual2970/certimate/internal/pkg/core/deployer"
|
|
||||||
onepanelsdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/1panel"
|
|
||||||
)
|
|
||||||
|
|
||||||
type DeployerConfig struct {
|
|
||||||
// 1Panel 服务地址。
|
|
||||||
ServerUrl string `json:"serverUrl"`
|
|
||||||
// 1Panel 版本。
|
|
||||||
// 可取值 "v1"、"v2"。
|
|
||||||
ApiVersion string `json:"apiVersion"`
|
|
||||||
// 1Panel 接口密钥。
|
|
||||||
ApiKey string `json:"apiKey"`
|
|
||||||
// 是否允许不安全的连接。
|
|
||||||
AllowInsecureConnections bool `json:"allowInsecureConnections,omitempty"`
|
|
||||||
// 是否自动重启。
|
|
||||||
AutoRestart bool `json:"autoRestart"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type DeployerProvider struct {
|
|
||||||
config *DeployerConfig
|
|
||||||
logger *slog.Logger
|
|
||||||
sdkClient *onepanelsdk.Client
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ deployer.Deployer = (*DeployerProvider)(nil)
|
|
||||||
|
|
||||||
func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
|
|
||||||
if config == nil {
|
|
||||||
panic("config is nil")
|
|
||||||
}
|
|
||||||
|
|
||||||
client, err := createSdkClient(config.ServerUrl, config.ApiVersion, config.ApiKey, config.AllowInsecureConnections)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to create sdk client: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &DeployerProvider{
|
|
||||||
config: config,
|
|
||||||
logger: slog.Default(),
|
|
||||||
sdkClient: client,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer {
|
|
||||||
if logger == nil {
|
|
||||||
d.logger = slog.New(slog.DiscardHandler)
|
|
||||||
} else {
|
|
||||||
d.logger = logger
|
|
||||||
}
|
|
||||||
return d
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) {
|
|
||||||
// 设置面板 SSL 证书
|
|
||||||
updateSystemSSLReq := &onepanelsdk.UpdateSystemSSLRequest{
|
|
||||||
Cert: certPEM,
|
|
||||||
Key: privkeyPEM,
|
|
||||||
SSL: "enable",
|
|
||||||
SSLType: "import-paste",
|
|
||||||
}
|
|
||||||
if d.config.AutoRestart {
|
|
||||||
updateSystemSSLReq.AutoRestart = "true"
|
|
||||||
} else {
|
|
||||||
updateSystemSSLReq.AutoRestart = "false"
|
|
||||||
}
|
|
||||||
updateSystemSSLResp, err := d.sdkClient.UpdateSystemSSL(updateSystemSSLReq)
|
|
||||||
d.logger.Debug("sdk request '1panel.UpdateSystemSSL'", slog.Any("request", updateSystemSSLReq), slog.Any("response", updateSystemSSLResp))
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to execute sdk request '1panel.UpdateSystemSSL': %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &deployer.DeployResult{}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func createSdkClient(serverUrl, apiVersion, apiKey string, skipTlsVerify bool) (*onepanelsdk.Client, error) {
|
|
||||||
if _, err := url.Parse(serverUrl); err != nil {
|
|
||||||
return nil, errors.New("invalid 1panel server url")
|
|
||||||
}
|
|
||||||
|
|
||||||
if apiVersion == "" {
|
|
||||||
return nil, errors.New("invalid 1panel api version")
|
|
||||||
}
|
|
||||||
|
|
||||||
if apiKey == "" {
|
|
||||||
return nil, errors.New("invalid 1panel api key")
|
|
||||||
}
|
|
||||||
|
|
||||||
client := onepanelsdk.NewClient(serverUrl, apiVersion, apiKey)
|
|
||||||
if skipTlsVerify {
|
|
||||||
client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true})
|
|
||||||
}
|
|
||||||
|
|
||||||
return client, nil
|
|
||||||
}
|
|
@ -1,200 +0,0 @@
|
|||||||
package onepanelsite
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"crypto/tls"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"log/slog"
|
|
||||||
"net/url"
|
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/usual2970/certimate/internal/pkg/core/deployer"
|
|
||||||
"github.com/usual2970/certimate/internal/pkg/core/uploader"
|
|
||||||
uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/1panel-ssl"
|
|
||||||
onepanelsdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/1panel"
|
|
||||||
)
|
|
||||||
|
|
||||||
type DeployerConfig struct {
|
|
||||||
// 1Panel 服务地址。
|
|
||||||
ServerUrl string `json:"serverUrl"`
|
|
||||||
// 1Panel 版本。
|
|
||||||
// 可取值 "v1"、"v2"。
|
|
||||||
ApiVersion string `json:"apiVersion"`
|
|
||||||
// 1Panel 接口密钥。
|
|
||||||
ApiKey string `json:"apiKey"`
|
|
||||||
// 是否允许不安全的连接。
|
|
||||||
AllowInsecureConnections bool `json:"allowInsecureConnections,omitempty"`
|
|
||||||
// 部署资源类型。
|
|
||||||
ResourceType ResourceType `json:"resourceType"`
|
|
||||||
// 网站 ID。
|
|
||||||
// 部署资源类型为 [RESOURCE_TYPE_WEBSITE] 时必填。
|
|
||||||
WebsiteId int64 `json:"websiteId,omitempty"`
|
|
||||||
// 证书 ID。
|
|
||||||
// 部署资源类型为 [RESOURCE_TYPE_CERTIFICATE] 时必填。
|
|
||||||
CertificateId int64 `json:"certificateId,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type DeployerProvider struct {
|
|
||||||
config *DeployerConfig
|
|
||||||
logger *slog.Logger
|
|
||||||
sdkClient *onepanelsdk.Client
|
|
||||||
sslUploader uploader.Uploader
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ deployer.Deployer = (*DeployerProvider)(nil)
|
|
||||||
|
|
||||||
func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
|
|
||||||
if config == nil {
|
|
||||||
panic("config is nil")
|
|
||||||
}
|
|
||||||
|
|
||||||
client, err := createSdkClient(config.ServerUrl, config.ApiVersion, config.ApiKey, config.AllowInsecureConnections)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to create sdk client: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{
|
|
||||||
ServerUrl: config.ServerUrl,
|
|
||||||
ApiVersion: config.ApiVersion,
|
|
||||||
ApiKey: config.ApiKey,
|
|
||||||
AllowInsecureConnections: config.AllowInsecureConnections,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to create ssl uploader: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &DeployerProvider{
|
|
||||||
config: config,
|
|
||||||
logger: slog.Default(),
|
|
||||||
sdkClient: client,
|
|
||||||
sslUploader: uploader,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer {
|
|
||||||
if logger == nil {
|
|
||||||
d.logger = slog.New(slog.DiscardHandler)
|
|
||||||
} else {
|
|
||||||
d.logger = logger
|
|
||||||
}
|
|
||||||
d.sslUploader.WithLogger(logger)
|
|
||||||
return d
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) {
|
|
||||||
// 根据部署资源类型决定部署方式
|
|
||||||
switch d.config.ResourceType {
|
|
||||||
case RESOURCE_TYPE_WEBSITE:
|
|
||||||
if err := d.deployToWebsite(ctx, certPEM, privkeyPEM); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
case RESOURCE_TYPE_CERTIFICATE:
|
|
||||||
if err := d.deployToCertificate(ctx, certPEM, privkeyPEM); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
return nil, fmt.Errorf("unsupported resource type '%s'", d.config.ResourceType)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &deployer.DeployResult{}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *DeployerProvider) deployToWebsite(ctx context.Context, certPEM string, privkeyPEM string) error {
|
|
||||||
if d.config.WebsiteId == 0 {
|
|
||||||
return errors.New("config `websiteId` is required")
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取网站 HTTPS 配置
|
|
||||||
getHttpsConfReq := &onepanelsdk.GetHttpsConfRequest{
|
|
||||||
WebsiteID: d.config.WebsiteId,
|
|
||||||
}
|
|
||||||
getHttpsConfResp, err := d.sdkClient.GetHttpsConf(getHttpsConfReq)
|
|
||||||
d.logger.Debug("sdk request '1panel.GetHttpsConf'", slog.Any("request", getHttpsConfReq), slog.Any("response", getHttpsConfResp))
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to execute sdk request '1panel.GetHttpsConf': %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 上传证书到面板
|
|
||||||
upres, err := d.sslUploader.Upload(ctx, certPEM, privkeyPEM)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to upload certificate file: %w", err)
|
|
||||||
} else {
|
|
||||||
d.logger.Info("ssl certificate uploaded", slog.Any("result", upres))
|
|
||||||
}
|
|
||||||
|
|
||||||
// 修改网站 HTTPS 配置
|
|
||||||
certId, _ := strconv.ParseInt(upres.CertId, 10, 64)
|
|
||||||
updateHttpsConfReq := &onepanelsdk.UpdateHttpsConfRequest{
|
|
||||||
WebsiteID: d.config.WebsiteId,
|
|
||||||
Type: "existed",
|
|
||||||
WebsiteSSLID: certId,
|
|
||||||
Enable: getHttpsConfResp.Data.Enable,
|
|
||||||
HttpConfig: getHttpsConfResp.Data.HttpConfig,
|
|
||||||
SSLProtocol: getHttpsConfResp.Data.SSLProtocol,
|
|
||||||
Algorithm: getHttpsConfResp.Data.Algorithm,
|
|
||||||
Hsts: getHttpsConfResp.Data.Hsts,
|
|
||||||
}
|
|
||||||
updateHttpsConfResp, err := d.sdkClient.UpdateHttpsConf(updateHttpsConfReq)
|
|
||||||
d.logger.Debug("sdk request '1panel.UpdateHttpsConf'", slog.Any("request", updateHttpsConfReq), slog.Any("response", updateHttpsConfResp))
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to execute sdk request '1panel.UpdateHttpsConf': %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *DeployerProvider) deployToCertificate(ctx context.Context, certPEM string, privkeyPEM string) error {
|
|
||||||
if d.config.CertificateId == 0 {
|
|
||||||
return errors.New("config `certificateId` is required")
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取证书详情
|
|
||||||
getWebsiteSSLReq := &onepanelsdk.GetWebsiteSSLRequest{
|
|
||||||
SSLID: d.config.CertificateId,
|
|
||||||
}
|
|
||||||
getWebsiteSSLResp, err := d.sdkClient.GetWebsiteSSL(getWebsiteSSLReq)
|
|
||||||
d.logger.Debug("sdk request '1panel.GetWebsiteSSL'", slog.Any("request", getWebsiteSSLReq), slog.Any("response", getWebsiteSSLResp))
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to execute sdk request '1panel.GetWebsiteSSL': %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 更新证书
|
|
||||||
uploadWebsiteSSLReq := &onepanelsdk.UploadWebsiteSSLRequest{
|
|
||||||
Type: "paste",
|
|
||||||
SSLID: d.config.CertificateId,
|
|
||||||
Description: getWebsiteSSLResp.Data.Description,
|
|
||||||
Certificate: certPEM,
|
|
||||||
PrivateKey: privkeyPEM,
|
|
||||||
}
|
|
||||||
uploadWebsiteSSLResp, err := d.sdkClient.UploadWebsiteSSL(uploadWebsiteSSLReq)
|
|
||||||
d.logger.Debug("sdk request '1panel.UploadWebsiteSSL'", slog.Any("request", uploadWebsiteSSLReq), slog.Any("response", uploadWebsiteSSLResp))
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to execute sdk request '1panel.UploadWebsiteSSL': %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func createSdkClient(serverUrl, apiVersion, apiKey string, skipTlsVerify bool) (*onepanelsdk.Client, error) {
|
|
||||||
if _, err := url.Parse(serverUrl); err != nil {
|
|
||||||
return nil, errors.New("invalid 1panel server url")
|
|
||||||
}
|
|
||||||
|
|
||||||
if apiVersion == "" {
|
|
||||||
return nil, errors.New("invalid 1panel api version")
|
|
||||||
}
|
|
||||||
|
|
||||||
if apiKey == "" {
|
|
||||||
return nil, errors.New("invalid 1panel api key")
|
|
||||||
}
|
|
||||||
|
|
||||||
client := onepanelsdk.NewClient(serverUrl, apiVersion, apiKey)
|
|
||||||
if skipTlsVerify {
|
|
||||||
client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true})
|
|
||||||
}
|
|
||||||
|
|
||||||
return client, nil
|
|
||||||
}
|
|
@ -1,74 +0,0 @@
|
|||||||
package aliyuncas
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"log/slog"
|
|
||||||
|
|
||||||
"github.com/usual2970/certimate/internal/pkg/core/deployer"
|
|
||||||
"github.com/usual2970/certimate/internal/pkg/core/uploader"
|
|
||||||
uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/aliyun-cas"
|
|
||||||
)
|
|
||||||
|
|
||||||
type DeployerConfig struct {
|
|
||||||
// 阿里云 AccessKeyId。
|
|
||||||
AccessKeyId string `json:"accessKeyId"`
|
|
||||||
// 阿里云 AccessKeySecret。
|
|
||||||
AccessKeySecret string `json:"accessKeySecret"`
|
|
||||||
// 阿里云资源组 ID。
|
|
||||||
ResourceGroupId string `json:"resourceGroupId,omitempty"`
|
|
||||||
// 阿里云地域。
|
|
||||||
Region string `json:"region"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type DeployerProvider struct {
|
|
||||||
config *DeployerConfig
|
|
||||||
logger *slog.Logger
|
|
||||||
sslUploader uploader.Uploader
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ deployer.Deployer = (*DeployerProvider)(nil)
|
|
||||||
|
|
||||||
func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
|
|
||||||
if config == nil {
|
|
||||||
panic("config is nil")
|
|
||||||
}
|
|
||||||
|
|
||||||
uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{
|
|
||||||
AccessKeyId: config.AccessKeyId,
|
|
||||||
AccessKeySecret: config.AccessKeySecret,
|
|
||||||
ResourceGroupId: config.ResourceGroupId,
|
|
||||||
Region: config.Region,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to create ssl uploader: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &DeployerProvider{
|
|
||||||
config: config,
|
|
||||||
logger: slog.Default(),
|
|
||||||
sslUploader: uploader,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer {
|
|
||||||
if logger == nil {
|
|
||||||
d.logger = slog.New(slog.DiscardHandler)
|
|
||||||
} else {
|
|
||||||
d.logger = logger
|
|
||||||
}
|
|
||||||
d.sslUploader.WithLogger(logger)
|
|
||||||
return d
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) {
|
|
||||||
// 上传证书到 CAS
|
|
||||||
upres, err := d.sslUploader.Upload(ctx, certPEM, privkeyPEM)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to upload certificate file: %w", err)
|
|
||||||
} else {
|
|
||||||
d.logger.Info("ssl certificate uploaded", slog.Any("result", upres))
|
|
||||||
}
|
|
||||||
|
|
||||||
return &deployer.DeployResult{}, nil
|
|
||||||
}
|
|
@ -1,75 +0,0 @@
|
|||||||
package awsiam
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"log/slog"
|
|
||||||
|
|
||||||
"github.com/usual2970/certimate/internal/pkg/core/deployer"
|
|
||||||
"github.com/usual2970/certimate/internal/pkg/core/uploader"
|
|
||||||
uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/aws-iam"
|
|
||||||
)
|
|
||||||
|
|
||||||
type DeployerConfig struct {
|
|
||||||
// AWS AccessKeyId。
|
|
||||||
AccessKeyId string `json:"accessKeyId"`
|
|
||||||
// AWS SecretAccessKey。
|
|
||||||
SecretAccessKey string `json:"secretAccessKey"`
|
|
||||||
// AWS 区域。
|
|
||||||
Region string `json:"region"`
|
|
||||||
// IAM 证书路径。
|
|
||||||
// 选填。
|
|
||||||
CertificatePath string `json:"certificatePath,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type DeployerProvider struct {
|
|
||||||
config *DeployerConfig
|
|
||||||
logger *slog.Logger
|
|
||||||
sslUploader uploader.Uploader
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ deployer.Deployer = (*DeployerProvider)(nil)
|
|
||||||
|
|
||||||
func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
|
|
||||||
if config == nil {
|
|
||||||
panic("config is nil")
|
|
||||||
}
|
|
||||||
|
|
||||||
uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{
|
|
||||||
AccessKeyId: config.AccessKeyId,
|
|
||||||
SecretAccessKey: config.SecretAccessKey,
|
|
||||||
Region: config.Region,
|
|
||||||
CertificatePath: config.CertificatePath,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to create ssl uploader: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &DeployerProvider{
|
|
||||||
config: config,
|
|
||||||
logger: slog.Default(),
|
|
||||||
sslUploader: uploader,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer {
|
|
||||||
if logger == nil {
|
|
||||||
d.logger = slog.New(slog.DiscardHandler)
|
|
||||||
} else {
|
|
||||||
d.logger = logger
|
|
||||||
}
|
|
||||||
d.sslUploader.WithLogger(logger)
|
|
||||||
return d
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) {
|
|
||||||
// 上传证书到 IAM
|
|
||||||
upres, err := d.sslUploader.Upload(ctx, certPEM, privkeyPEM)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to upload certificate file: %w", err)
|
|
||||||
} else {
|
|
||||||
d.logger.Info("ssl certificate uploaded", slog.Any("result", upres))
|
|
||||||
}
|
|
||||||
|
|
||||||
return &deployer.DeployResult{}, nil
|
|
||||||
}
|
|
@ -1,67 +0,0 @@
|
|||||||
package baiducloudcert
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"log/slog"
|
|
||||||
|
|
||||||
"github.com/usual2970/certimate/internal/pkg/core/deployer"
|
|
||||||
"github.com/usual2970/certimate/internal/pkg/core/uploader"
|
|
||||||
uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/baiducloud-cert"
|
|
||||||
)
|
|
||||||
|
|
||||||
type DeployerConfig struct {
|
|
||||||
// 百度智能云 AccessKeyId。
|
|
||||||
AccessKeyId string `json:"accessKeyId"`
|
|
||||||
// 百度智能云 SecretAccessKey。
|
|
||||||
SecretAccessKey string `json:"secretAccessKey"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type DeployerProvider struct {
|
|
||||||
config *DeployerConfig
|
|
||||||
logger *slog.Logger
|
|
||||||
sslUploader uploader.Uploader
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ deployer.Deployer = (*DeployerProvider)(nil)
|
|
||||||
|
|
||||||
func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
|
|
||||||
if config == nil {
|
|
||||||
panic("config is nil")
|
|
||||||
}
|
|
||||||
|
|
||||||
uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{
|
|
||||||
AccessKeyId: config.AccessKeyId,
|
|
||||||
SecretAccessKey: config.SecretAccessKey,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to create ssl uploader: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &DeployerProvider{
|
|
||||||
config: config,
|
|
||||||
logger: slog.Default(),
|
|
||||||
sslUploader: uploader,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer {
|
|
||||||
if logger == nil {
|
|
||||||
d.logger = slog.New(slog.DiscardHandler)
|
|
||||||
} else {
|
|
||||||
d.logger = logger
|
|
||||||
}
|
|
||||||
return d
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) {
|
|
||||||
// 上传证书到 CAS
|
|
||||||
upres, err := d.sslUploader.Upload(ctx, certPEM, privkeyPEM)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to upload certificate file: %w", err)
|
|
||||||
} else {
|
|
||||||
d.logger.Info("ssl certificate uploaded", slog.Any("result", upres))
|
|
||||||
}
|
|
||||||
|
|
||||||
return &deployer.DeployResult{}, nil
|
|
||||||
}
|
|
@ -1,88 +0,0 @@
|
|||||||
package baotapanelconsole
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"crypto/tls"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"log/slog"
|
|
||||||
"net/url"
|
|
||||||
|
|
||||||
"github.com/usual2970/certimate/internal/pkg/core/deployer"
|
|
||||||
btsdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/btwaf"
|
|
||||||
)
|
|
||||||
|
|
||||||
type DeployerConfig struct {
|
|
||||||
// 堡塔云 WAF 服务地址。
|
|
||||||
ServerUrl string `json:"serverUrl"`
|
|
||||||
// 堡塔云 WAF 接口密钥。
|
|
||||||
ApiKey string `json:"apiKey"`
|
|
||||||
// 是否允许不安全的连接。
|
|
||||||
AllowInsecureConnections bool `json:"allowInsecureConnections,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type DeployerProvider struct {
|
|
||||||
config *DeployerConfig
|
|
||||||
logger *slog.Logger
|
|
||||||
sdkClient *btsdk.Client
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ deployer.Deployer = (*DeployerProvider)(nil)
|
|
||||||
|
|
||||||
func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
|
|
||||||
if config == nil {
|
|
||||||
panic("config is nil")
|
|
||||||
}
|
|
||||||
|
|
||||||
client, err := createSdkClient(config.ServerUrl, config.ApiKey, config.AllowInsecureConnections)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to create sdk client: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &DeployerProvider{
|
|
||||||
config: config,
|
|
||||||
logger: slog.Default(),
|
|
||||||
sdkClient: client,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer {
|
|
||||||
if logger == nil {
|
|
||||||
d.logger = slog.New(slog.DiscardHandler)
|
|
||||||
} else {
|
|
||||||
d.logger = logger
|
|
||||||
}
|
|
||||||
return d
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) {
|
|
||||||
// 设置面板 SSL
|
|
||||||
configSetSSLReq := &btsdk.ConfigSetSSLRequest{
|
|
||||||
CertContent: certPEM,
|
|
||||||
KeyContent: privkeyPEM,
|
|
||||||
}
|
|
||||||
configSetSSLResp, err := d.sdkClient.ConfigSetSSL(configSetSSLReq)
|
|
||||||
d.logger.Debug("sdk request 'bt.ConfigSetSSL'", slog.Any("request", configSetSSLReq), slog.Any("response", configSetSSLResp))
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to execute sdk request 'bt.ConfigSetSSL': %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &deployer.DeployResult{}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func createSdkClient(serverUrl, apiKey string, skipTlsVerify bool) (*btsdk.Client, error) {
|
|
||||||
if _, err := url.Parse(serverUrl); err != nil {
|
|
||||||
return nil, errors.New("invalid baota server url")
|
|
||||||
}
|
|
||||||
|
|
||||||
if apiKey == "" {
|
|
||||||
return nil, errors.New("invalid baota api key")
|
|
||||||
}
|
|
||||||
|
|
||||||
client := btsdk.NewClient(serverUrl, apiKey)
|
|
||||||
if skipTlsVerify {
|
|
||||||
client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true})
|
|
||||||
}
|
|
||||||
|
|
||||||
return client, nil
|
|
||||||
}
|
|
@ -1,66 +0,0 @@
|
|||||||
package bunnycdn
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"encoding/base64"
|
|
||||||
"fmt"
|
|
||||||
"log/slog"
|
|
||||||
|
|
||||||
"github.com/usual2970/certimate/internal/pkg/core/deployer"
|
|
||||||
bunnysdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/bunny"
|
|
||||||
)
|
|
||||||
|
|
||||||
type DeployerConfig struct {
|
|
||||||
// Bunny API Key。
|
|
||||||
ApiKey string `json:"apiKey"`
|
|
||||||
// Bunny Pull Zone ID。
|
|
||||||
PullZoneId string `json:"pullZoneId"`
|
|
||||||
// Bunny CDN Hostname(支持泛域名)。
|
|
||||||
Hostname string `json:"hostname"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type DeployerProvider struct {
|
|
||||||
config *DeployerConfig
|
|
||||||
logger *slog.Logger
|
|
||||||
sdkClient *bunnysdk.Client
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ deployer.Deployer = (*DeployerProvider)(nil)
|
|
||||||
|
|
||||||
func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
|
|
||||||
if config == nil {
|
|
||||||
panic("config is nil")
|
|
||||||
}
|
|
||||||
|
|
||||||
return &DeployerProvider{
|
|
||||||
config: config,
|
|
||||||
logger: slog.Default(),
|
|
||||||
sdkClient: bunnysdk.NewClient(config.ApiKey),
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer {
|
|
||||||
if logger == nil {
|
|
||||||
d.logger = slog.New(slog.DiscardHandler)
|
|
||||||
} else {
|
|
||||||
d.logger = logger
|
|
||||||
}
|
|
||||||
return d
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) {
|
|
||||||
// 上传证书
|
|
||||||
createCertificateReq := &bunnysdk.AddCustomCertificateRequest{
|
|
||||||
Hostname: d.config.Hostname,
|
|
||||||
PullZoneId: d.config.PullZoneId,
|
|
||||||
Certificate: base64.StdEncoding.EncodeToString([]byte(certPEM)),
|
|
||||||
CertificateKey: base64.StdEncoding.EncodeToString([]byte(privkeyPEM)),
|
|
||||||
}
|
|
||||||
createCertificateResp, err := d.sdkClient.AddCustomCertificate(createCertificateReq)
|
|
||||||
d.logger.Debug("sdk request 'bunny.AddCustomCertificate'", slog.Any("request", createCertificateReq), slog.Any("response", createCertificateResp))
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to execute sdk request 'bunny.AddCustomCertificate': %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &deployer.DeployResult{}, nil
|
|
||||||
}
|
|
@ -1,75 +0,0 @@
|
|||||||
package cachefly
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"log/slog"
|
|
||||||
|
|
||||||
"github.com/usual2970/certimate/internal/pkg/core/deployer"
|
|
||||||
cfsdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/cachefly"
|
|
||||||
)
|
|
||||||
|
|
||||||
type DeployerConfig struct {
|
|
||||||
// CacheFly API Token。
|
|
||||||
ApiToken string `json:"apiToken"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type DeployerProvider struct {
|
|
||||||
config *DeployerConfig
|
|
||||||
logger *slog.Logger
|
|
||||||
sdkClient *cfsdk.Client
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ deployer.Deployer = (*DeployerProvider)(nil)
|
|
||||||
|
|
||||||
func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
|
|
||||||
if config == nil {
|
|
||||||
panic("config is nil")
|
|
||||||
}
|
|
||||||
|
|
||||||
client, err := createSdkClient(config.ApiToken)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to create sdk client: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &DeployerProvider{
|
|
||||||
config: config,
|
|
||||||
logger: slog.Default(),
|
|
||||||
sdkClient: client,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer {
|
|
||||||
if logger == nil {
|
|
||||||
d.logger = slog.New(slog.DiscardHandler)
|
|
||||||
} else {
|
|
||||||
d.logger = logger
|
|
||||||
}
|
|
||||||
return d
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) {
|
|
||||||
// 上传证书
|
|
||||||
// REF: https://api.cachefly.com/api/2.5/docs#tag/Certificates/paths/~1certificates/post
|
|
||||||
createCertificateReq := &cfsdk.CreateCertificateRequest{
|
|
||||||
Certificate: certPEM,
|
|
||||||
CertificateKey: privkeyPEM,
|
|
||||||
}
|
|
||||||
createCertificateResp, err := d.sdkClient.CreateCertificate(createCertificateReq)
|
|
||||||
d.logger.Debug("sdk request 'cachefly.CreateCertificate'", slog.Any("request", createCertificateReq), slog.Any("response", createCertificateResp))
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to execute sdk request 'cachefly.CreateCertificate': %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &deployer.DeployResult{}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func createSdkClient(apiToken string) (*cfsdk.Client, error) {
|
|
||||||
if apiToken == "" {
|
|
||||||
return nil, errors.New("invalid cachefly api token")
|
|
||||||
}
|
|
||||||
|
|
||||||
client := cfsdk.NewClient(apiToken)
|
|
||||||
return client, nil
|
|
||||||
}
|
|
@ -1,85 +0,0 @@
|
|||||||
package dogecloudcdn
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"log/slog"
|
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/usual2970/certimate/internal/pkg/core/deployer"
|
|
||||||
"github.com/usual2970/certimate/internal/pkg/core/uploader"
|
|
||||||
uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/dogecloud"
|
|
||||||
dogesdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/dogecloud"
|
|
||||||
)
|
|
||||||
|
|
||||||
type DeployerConfig struct {
|
|
||||||
// 多吉云 AccessKey。
|
|
||||||
AccessKey string `json:"accessKey"`
|
|
||||||
// 多吉云 SecretKey。
|
|
||||||
SecretKey string `json:"secretKey"`
|
|
||||||
// 加速域名(不支持泛域名)。
|
|
||||||
Domain string `json:"domain"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type DeployerProvider struct {
|
|
||||||
config *DeployerConfig
|
|
||||||
logger *slog.Logger
|
|
||||||
sdkClient *dogesdk.Client
|
|
||||||
sslUploader uploader.Uploader
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ deployer.Deployer = (*DeployerProvider)(nil)
|
|
||||||
|
|
||||||
func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
|
|
||||||
if config == nil {
|
|
||||||
panic("config is nil")
|
|
||||||
}
|
|
||||||
|
|
||||||
client := dogesdk.NewClient(config.AccessKey, config.SecretKey)
|
|
||||||
|
|
||||||
uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{
|
|
||||||
AccessKey: config.AccessKey,
|
|
||||||
SecretKey: config.SecretKey,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to create ssl uploader: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &DeployerProvider{
|
|
||||||
config: config,
|
|
||||||
logger: slog.Default(),
|
|
||||||
sdkClient: client,
|
|
||||||
sslUploader: uploader,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer {
|
|
||||||
if logger == nil {
|
|
||||||
d.logger = slog.New(slog.DiscardHandler)
|
|
||||||
} else {
|
|
||||||
d.logger = logger
|
|
||||||
}
|
|
||||||
d.sslUploader.WithLogger(logger)
|
|
||||||
return d
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) {
|
|
||||||
// 上传证书到 CDN
|
|
||||||
upres, err := d.sslUploader.Upload(ctx, certPEM, privkeyPEM)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to upload certificate file: %w", err)
|
|
||||||
} else {
|
|
||||||
d.logger.Info("ssl certificate uploaded", slog.Any("result", upres))
|
|
||||||
}
|
|
||||||
|
|
||||||
// 绑定证书
|
|
||||||
// REF: https://docs.dogecloud.com/cdn/api-cert-bind
|
|
||||||
bindCdnCertId, _ := strconv.ParseInt(upres.CertId, 10, 64)
|
|
||||||
bindCdnCertResp, err := d.sdkClient.BindCdnCertWithDomain(bindCdnCertId, d.config.Domain)
|
|
||||||
d.logger.Debug("sdk request 'cdn.BindCdnCert'", slog.Int64("request.certId", bindCdnCertId), slog.String("request.domain", d.config.Domain), slog.Any("response", bindCdnCertResp))
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to execute sdk request 'cdn.BindCdnCert': %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &deployer.DeployResult{}, nil
|
|
||||||
}
|
|
@ -1,71 +0,0 @@
|
|||||||
package huaweicloudscm
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"log/slog"
|
|
||||||
|
|
||||||
"github.com/usual2970/certimate/internal/pkg/core/deployer"
|
|
||||||
"github.com/usual2970/certimate/internal/pkg/core/uploader"
|
|
||||||
uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/huaweicloud-scm"
|
|
||||||
)
|
|
||||||
|
|
||||||
type DeployerConfig struct {
|
|
||||||
// 华为云 AccessKeyId。
|
|
||||||
AccessKeyId string `json:"accessKeyId"`
|
|
||||||
// 华为云 SecretAccessKey。
|
|
||||||
SecretAccessKey string `json:"secretAccessKey"`
|
|
||||||
// 华为云企业项目 ID。
|
|
||||||
EnterpriseProjectId string `json:"enterpriseProjectId,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type DeployerProvider struct {
|
|
||||||
config *DeployerConfig
|
|
||||||
logger *slog.Logger
|
|
||||||
sslUploader uploader.Uploader
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ deployer.Deployer = (*DeployerProvider)(nil)
|
|
||||||
|
|
||||||
func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
|
|
||||||
if config == nil {
|
|
||||||
panic("config is nil")
|
|
||||||
}
|
|
||||||
|
|
||||||
uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{
|
|
||||||
AccessKeyId: config.AccessKeyId,
|
|
||||||
SecretAccessKey: config.SecretAccessKey,
|
|
||||||
EnterpriseProjectId: config.EnterpriseProjectId,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to create ssl uploader: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &DeployerProvider{
|
|
||||||
config: config,
|
|
||||||
logger: slog.Default(),
|
|
||||||
sslUploader: uploader,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer {
|
|
||||||
if logger == nil {
|
|
||||||
d.logger = slog.New(slog.DiscardHandler)
|
|
||||||
} else {
|
|
||||||
d.logger = logger
|
|
||||||
}
|
|
||||||
d.sslUploader.WithLogger(logger)
|
|
||||||
return d
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) {
|
|
||||||
// 上传证书到 SCM
|
|
||||||
upres, err := d.sslUploader.Upload(ctx, certPEM, privkeyPEM)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to upload certificate file: %w", err)
|
|
||||||
} else {
|
|
||||||
d.logger.Info("ssl certificate uploaded", slog.Any("result", upres))
|
|
||||||
}
|
|
||||||
|
|
||||||
return &deployer.DeployResult{}, nil
|
|
||||||
}
|
|
@ -1,176 +0,0 @@
|
|||||||
package lecdn
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"crypto/tls"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"log/slog"
|
|
||||||
"net/url"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/usual2970/certimate/internal/pkg/core/deployer"
|
|
||||||
leclientsdkv3 "github.com/usual2970/certimate/internal/pkg/sdk3rd/lecdn/v3/client"
|
|
||||||
lemastersdkv3 "github.com/usual2970/certimate/internal/pkg/sdk3rd/lecdn/v3/master"
|
|
||||||
)
|
|
||||||
|
|
||||||
type DeployerConfig struct {
|
|
||||||
// LeCDN 服务地址。
|
|
||||||
ServerUrl string `json:"serverUrl"`
|
|
||||||
// LeCDN 版本。
|
|
||||||
// 可取值 "v3"。
|
|
||||||
ApiVersion string `json:"apiVersion"`
|
|
||||||
// LeCDN 用户角色。
|
|
||||||
// 可取值 "client"、"master"。
|
|
||||||
ApiRole string `json:"apiRole"`
|
|
||||||
// LeCDN 用户名。
|
|
||||||
Username string `json:"accessKeyId"`
|
|
||||||
// LeCDN 用户密码。
|
|
||||||
Password string `json:"accessKey"`
|
|
||||||
// 是否允许不安全的连接。
|
|
||||||
AllowInsecureConnections bool `json:"allowInsecureConnections,omitempty"`
|
|
||||||
// 部署资源类型。
|
|
||||||
ResourceType ResourceType `json:"resourceType"`
|
|
||||||
// 证书 ID。
|
|
||||||
// 部署资源类型为 [RESOURCE_TYPE_CERTIFICATE] 时必填。
|
|
||||||
CertificateId int64 `json:"certificateId,omitempty"`
|
|
||||||
// 客户 ID。
|
|
||||||
// 部署资源类型为 [RESOURCE_TYPE_CERTIFICATE] 时选填。
|
|
||||||
ClientId int64 `json:"clientId,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type DeployerProvider struct {
|
|
||||||
config *DeployerConfig
|
|
||||||
logger *slog.Logger
|
|
||||||
sdkClient interface{}
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ deployer.Deployer = (*DeployerProvider)(nil)
|
|
||||||
|
|
||||||
const (
|
|
||||||
apiVersionV3 = "v3"
|
|
||||||
|
|
||||||
apiRoleClient = "client"
|
|
||||||
apiRoleMaster = "master"
|
|
||||||
)
|
|
||||||
|
|
||||||
func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
|
|
||||||
if config == nil {
|
|
||||||
panic("config is nil")
|
|
||||||
}
|
|
||||||
|
|
||||||
client, err := createSdkClient(config.ServerUrl, config.ApiVersion, config.ApiRole, config.Username, config.Password, config.AllowInsecureConnections)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to create sdk client: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &DeployerProvider{
|
|
||||||
config: config,
|
|
||||||
logger: slog.Default(),
|
|
||||||
sdkClient: client,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer {
|
|
||||||
if logger == nil {
|
|
||||||
d.logger = slog.New(slog.DiscardHandler)
|
|
||||||
} else {
|
|
||||||
d.logger = logger
|
|
||||||
}
|
|
||||||
return d
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) {
|
|
||||||
// 根据部署资源类型决定部署方式
|
|
||||||
switch d.config.ResourceType {
|
|
||||||
case RESOURCE_TYPE_CERTIFICATE:
|
|
||||||
if err := d.deployToCertificate(ctx, certPEM, privkeyPEM); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
return nil, fmt.Errorf("unsupported resource type '%s'", d.config.ResourceType)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &deployer.DeployResult{}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *DeployerProvider) deployToCertificate(ctx context.Context, certPEM string, privkeyPEM string) error {
|
|
||||||
if d.config.CertificateId == 0 {
|
|
||||||
return errors.New("config `certificateId` is required")
|
|
||||||
}
|
|
||||||
|
|
||||||
// 修改证书
|
|
||||||
// REF: https://wdk0pwf8ul.feishu.cn/wiki/YE1XwCRIHiLYeKkPupgcXrlgnDd
|
|
||||||
switch sdkClient := d.sdkClient.(type) {
|
|
||||||
case *leclientsdkv3.Client:
|
|
||||||
updateSSLCertReq := &leclientsdkv3.UpdateCertificateRequest{
|
|
||||||
Name: fmt.Sprintf("certimate-%d", time.Now().UnixMilli()),
|
|
||||||
Description: "upload from certimate",
|
|
||||||
Type: "upload",
|
|
||||||
SSLPEM: certPEM,
|
|
||||||
SSLKey: privkeyPEM,
|
|
||||||
AutoRenewal: false,
|
|
||||||
}
|
|
||||||
updateSSLCertResp, err := sdkClient.UpdateCertificate(d.config.CertificateId, updateSSLCertReq)
|
|
||||||
d.logger.Debug("sdk request 'lecdn.UpdateCertificate'", slog.Int64("certId", d.config.CertificateId), slog.Any("request", updateSSLCertReq), slog.Any("response", updateSSLCertResp))
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to execute sdk request 'lecdn.UpdateCertificate': %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
case *lemastersdkv3.Client:
|
|
||||||
updateSSLCertReq := &lemastersdkv3.UpdateCertificateRequest{
|
|
||||||
ClientId: d.config.ClientId,
|
|
||||||
Name: fmt.Sprintf("certimate-%d", time.Now().UnixMilli()),
|
|
||||||
Description: "upload from certimate",
|
|
||||||
Type: "upload",
|
|
||||||
SSLPEM: certPEM,
|
|
||||||
SSLKey: privkeyPEM,
|
|
||||||
AutoRenewal: false,
|
|
||||||
}
|
|
||||||
updateSSLCertResp, err := sdkClient.UpdateCertificate(d.config.CertificateId, updateSSLCertReq)
|
|
||||||
d.logger.Debug("sdk request 'lecdn.UpdateCertificate'", slog.Int64("certId", d.config.CertificateId), slog.Any("request", updateSSLCertReq), slog.Any("response", updateSSLCertResp))
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to execute sdk request 'lecdn.UpdateCertificate': %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
panic("sdk client is not implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func createSdkClient(serverUrl, apiVersion, apiRole, username, password string, skipTlsVerify bool) (interface{}, error) {
|
|
||||||
if _, err := url.Parse(serverUrl); err != nil {
|
|
||||||
return nil, errors.New("invalid lecdn server url")
|
|
||||||
}
|
|
||||||
|
|
||||||
if username == "" {
|
|
||||||
return nil, errors.New("invalid lecdn username")
|
|
||||||
}
|
|
||||||
|
|
||||||
if password == "" {
|
|
||||||
return nil, errors.New("invalid lecdn password")
|
|
||||||
}
|
|
||||||
|
|
||||||
if apiVersion == apiVersionV3 && apiRole == apiRoleClient {
|
|
||||||
// v3 版客户端
|
|
||||||
client := leclientsdkv3.NewClient(serverUrl, username, password)
|
|
||||||
if skipTlsVerify {
|
|
||||||
client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true})
|
|
||||||
}
|
|
||||||
|
|
||||||
return client, nil
|
|
||||||
} else if apiVersion == apiVersionV3 && apiRole == apiRoleMaster {
|
|
||||||
// v3 版主控端
|
|
||||||
client := lemastersdkv3.NewClient(serverUrl, username, password)
|
|
||||||
if skipTlsVerify {
|
|
||||||
client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true})
|
|
||||||
}
|
|
||||||
|
|
||||||
return client, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, fmt.Errorf("invalid lecdn api version or user role")
|
|
||||||
}
|
|
@ -1,101 +0,0 @@
|
|||||||
package rainyunrcdn
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"log/slog"
|
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/usual2970/certimate/internal/pkg/core/deployer"
|
|
||||||
"github.com/usual2970/certimate/internal/pkg/core/uploader"
|
|
||||||
uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/rainyun-sslcenter"
|
|
||||||
rainyunsdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/rainyun"
|
|
||||||
)
|
|
||||||
|
|
||||||
type DeployerConfig struct {
|
|
||||||
// 雨云 API 密钥。
|
|
||||||
ApiKey string `json:"apiKey"`
|
|
||||||
// RCDN 实例 ID。
|
|
||||||
InstanceId int32 `json:"instanceId"`
|
|
||||||
// 加速域名(支持泛域名)。
|
|
||||||
Domain string `json:"domain"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type DeployerProvider struct {
|
|
||||||
config *DeployerConfig
|
|
||||||
logger *slog.Logger
|
|
||||||
sdkClient *rainyunsdk.Client
|
|
||||||
sslUploader uploader.Uploader
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ deployer.Deployer = (*DeployerProvider)(nil)
|
|
||||||
|
|
||||||
func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
|
|
||||||
if config == nil {
|
|
||||||
panic("config is nil")
|
|
||||||
}
|
|
||||||
|
|
||||||
client, err := createSdkClient(config.ApiKey)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to create sdk client: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{
|
|
||||||
ApiKey: config.ApiKey,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to create ssl uploader: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &DeployerProvider{
|
|
||||||
config: config,
|
|
||||||
logger: slog.Default(),
|
|
||||||
sdkClient: client,
|
|
||||||
sslUploader: uploader,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer {
|
|
||||||
if logger == nil {
|
|
||||||
d.logger = slog.New(slog.DiscardHandler)
|
|
||||||
} else {
|
|
||||||
d.logger = logger
|
|
||||||
}
|
|
||||||
d.sslUploader.WithLogger(logger)
|
|
||||||
return d
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) {
|
|
||||||
// 上传证书到 SSL 证书
|
|
||||||
upres, err := d.sslUploader.Upload(ctx, certPEM, privkeyPEM)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to upload certificate file: %w", err)
|
|
||||||
} else {
|
|
||||||
d.logger.Info("ssl certificate uploaded", slog.Any("result", upres))
|
|
||||||
}
|
|
||||||
|
|
||||||
// RCDN SSL 绑定域名
|
|
||||||
// REF: https://apifox.com/apidoc/shared/a4595cc8-44c5-4678-a2a3-eed7738dab03/api-184214120
|
|
||||||
certId, _ := strconv.Atoi(upres.CertId)
|
|
||||||
rcdnInstanceSslBindReq := &rainyunsdk.RcdnInstanceSslBindRequest{
|
|
||||||
CertId: int32(certId),
|
|
||||||
Domains: []string{d.config.Domain},
|
|
||||||
}
|
|
||||||
rcdnInstanceSslBindResp, err := d.sdkClient.RcdnInstanceSslBind(d.config.InstanceId, rcdnInstanceSslBindReq)
|
|
||||||
d.logger.Debug("sdk request 'rcdn.InstanceSslBind'", slog.Any("instanceId", d.config.InstanceId), slog.Any("request", rcdnInstanceSslBindReq), slog.Any("response", rcdnInstanceSslBindResp))
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to execute sdk request 'rcdn.InstanceSslBind': %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &deployer.DeployResult{}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func createSdkClient(apiKey string) (*rainyunsdk.Client, error) {
|
|
||||||
if apiKey == "" {
|
|
||||||
return nil, errors.New("invalid rainyun api key")
|
|
||||||
}
|
|
||||||
|
|
||||||
client := rainyunsdk.NewClient(apiKey)
|
|
||||||
return client, nil
|
|
||||||
}
|
|
@ -1,94 +0,0 @@
|
|||||||
package ratpanelconsole
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"crypto/tls"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"log/slog"
|
|
||||||
"net/url"
|
|
||||||
|
|
||||||
"github.com/usual2970/certimate/internal/pkg/core/deployer"
|
|
||||||
rpsdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/ratpanel"
|
|
||||||
)
|
|
||||||
|
|
||||||
type DeployerConfig struct {
|
|
||||||
// 耗子面板服务地址。
|
|
||||||
ServerUrl string `json:"serverUrl"`
|
|
||||||
// 耗子面板访问令牌 ID。
|
|
||||||
AccessTokenId int32 `json:"accessTokenId"`
|
|
||||||
// 耗子面板访问令牌。
|
|
||||||
AccessToken string `json:"accessToken"`
|
|
||||||
// 是否允许不安全的连接。
|
|
||||||
AllowInsecureConnections bool `json:"allowInsecureConnections,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type DeployerProvider struct {
|
|
||||||
config *DeployerConfig
|
|
||||||
logger *slog.Logger
|
|
||||||
sdkClient *rpsdk.Client
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ deployer.Deployer = (*DeployerProvider)(nil)
|
|
||||||
|
|
||||||
func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
|
|
||||||
if config == nil {
|
|
||||||
panic("config is nil")
|
|
||||||
}
|
|
||||||
|
|
||||||
client, err := createSdkClient(config.ServerUrl, config.AccessTokenId, config.AccessToken, config.AllowInsecureConnections)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to create sdk client: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &DeployerProvider{
|
|
||||||
config: config,
|
|
||||||
logger: slog.Default(),
|
|
||||||
sdkClient: client,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer {
|
|
||||||
if logger == nil {
|
|
||||||
d.logger = slog.New(slog.DiscardHandler)
|
|
||||||
} else {
|
|
||||||
d.logger = logger
|
|
||||||
}
|
|
||||||
return d
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) {
|
|
||||||
// 设置面板 SSL 证书
|
|
||||||
settingCertReq := &rpsdk.SettingCertRequest{
|
|
||||||
Certificate: certPEM,
|
|
||||||
PrivateKey: privkeyPEM,
|
|
||||||
}
|
|
||||||
settingCertResp, err := d.sdkClient.SettingCert(settingCertReq)
|
|
||||||
d.logger.Debug("sdk request 'ratpanel.SettingCert'", slog.Any("request", settingCertReq), slog.Any("response", settingCertResp))
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to execute sdk request 'ratpanel.SettingCert': %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &deployer.DeployResult{}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func createSdkClient(serverUrl string, accessTokenId int32, accessToken string, skipTlsVerify bool) (*rpsdk.Client, error) {
|
|
||||||
if _, err := url.Parse(serverUrl); err != nil {
|
|
||||||
return nil, errors.New("invalid ratpanel server url")
|
|
||||||
}
|
|
||||||
|
|
||||||
if accessTokenId == 0 {
|
|
||||||
return nil, errors.New("invalid ratpanel access token id")
|
|
||||||
}
|
|
||||||
|
|
||||||
if accessToken == "" {
|
|
||||||
return nil, errors.New("invalid ratpanel access token")
|
|
||||||
}
|
|
||||||
|
|
||||||
client := rpsdk.NewClient(serverUrl, accessTokenId, accessToken)
|
|
||||||
if skipTlsVerify {
|
|
||||||
client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true})
|
|
||||||
}
|
|
||||||
|
|
||||||
return client, nil
|
|
||||||
}
|
|
@ -1,101 +0,0 @@
|
|||||||
package ratpanelsite
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"crypto/tls"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"log/slog"
|
|
||||||
"net/url"
|
|
||||||
|
|
||||||
"github.com/usual2970/certimate/internal/pkg/core/deployer"
|
|
||||||
rpsdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/ratpanel"
|
|
||||||
)
|
|
||||||
|
|
||||||
type DeployerConfig struct {
|
|
||||||
// 耗子面板服务地址。
|
|
||||||
ServerUrl string `json:"serverUrl"`
|
|
||||||
// 耗子面板访问令牌 ID。
|
|
||||||
AccessTokenId int32 `json:"accessTokenId"`
|
|
||||||
// 耗子面板访问令牌。
|
|
||||||
AccessToken string `json:"accessToken"`
|
|
||||||
// 是否允许不安全的连接。
|
|
||||||
AllowInsecureConnections bool `json:"allowInsecureConnections,omitempty"`
|
|
||||||
// 网站名称。
|
|
||||||
SiteName string `json:"siteName"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type DeployerProvider struct {
|
|
||||||
config *DeployerConfig
|
|
||||||
logger *slog.Logger
|
|
||||||
sdkClient *rpsdk.Client
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ deployer.Deployer = (*DeployerProvider)(nil)
|
|
||||||
|
|
||||||
func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
|
|
||||||
if config == nil {
|
|
||||||
panic("config is nil")
|
|
||||||
}
|
|
||||||
|
|
||||||
client, err := createSdkClient(config.ServerUrl, config.AccessTokenId, config.AccessToken, config.AllowInsecureConnections)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to create sdk client: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &DeployerProvider{
|
|
||||||
config: config,
|
|
||||||
logger: slog.Default(),
|
|
||||||
sdkClient: client,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer {
|
|
||||||
if logger == nil {
|
|
||||||
d.logger = slog.New(slog.DiscardHandler)
|
|
||||||
} else {
|
|
||||||
d.logger = logger
|
|
||||||
}
|
|
||||||
return d
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) {
|
|
||||||
if d.config.SiteName == "" {
|
|
||||||
return nil, errors.New("config `siteName` is required")
|
|
||||||
}
|
|
||||||
|
|
||||||
// 设置站点 SSL 证书
|
|
||||||
websiteCertReq := &rpsdk.WebsiteCertRequest{
|
|
||||||
SiteName: d.config.SiteName,
|
|
||||||
Certificate: certPEM,
|
|
||||||
PrivateKey: privkeyPEM,
|
|
||||||
}
|
|
||||||
websiteCertResp, err := d.sdkClient.WebsiteCert(websiteCertReq)
|
|
||||||
d.logger.Debug("sdk request 'ratpanel.WebsiteCert'", slog.Any("request", websiteCertReq), slog.Any("response", websiteCertResp))
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to execute sdk request 'ratpanel.WebsiteCert': %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &deployer.DeployResult{}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func createSdkClient(serverUrl string, accessTokenId int32, accessToken string, skipTlsVerify bool) (*rpsdk.Client, error) {
|
|
||||||
if _, err := url.Parse(serverUrl); err != nil {
|
|
||||||
return nil, errors.New("invalid ratpanel server url")
|
|
||||||
}
|
|
||||||
|
|
||||||
if accessTokenId == 0 {
|
|
||||||
return nil, errors.New("invalid ratpanel access token id")
|
|
||||||
}
|
|
||||||
|
|
||||||
if accessToken == "" {
|
|
||||||
return nil, errors.New("invalid ratpanel access token")
|
|
||||||
}
|
|
||||||
|
|
||||||
client := rpsdk.NewClient(serverUrl, accessTokenId, accessToken)
|
|
||||||
if skipTlsVerify {
|
|
||||||
client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true})
|
|
||||||
}
|
|
||||||
|
|
||||||
return client, nil
|
|
||||||
}
|
|
@ -1,68 +0,0 @@
|
|||||||
package tencentcloudssl
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"log/slog"
|
|
||||||
|
|
||||||
"github.com/usual2970/certimate/internal/pkg/core/deployer"
|
|
||||||
"github.com/usual2970/certimate/internal/pkg/core/uploader"
|
|
||||||
uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/tencentcloud-ssl"
|
|
||||||
)
|
|
||||||
|
|
||||||
type DeployerConfig struct {
|
|
||||||
// 腾讯云 SecretId。
|
|
||||||
SecretId string `json:"secretId"`
|
|
||||||
// 腾讯云 SecretKey。
|
|
||||||
SecretKey string `json:"secretKey"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type DeployerProvider struct {
|
|
||||||
config *DeployerConfig
|
|
||||||
logger *slog.Logger
|
|
||||||
sslUploader uploader.Uploader
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ deployer.Deployer = (*DeployerProvider)(nil)
|
|
||||||
|
|
||||||
func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
|
|
||||||
if config == nil {
|
|
||||||
panic("config is nil")
|
|
||||||
}
|
|
||||||
|
|
||||||
uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{
|
|
||||||
SecretId: config.SecretId,
|
|
||||||
SecretKey: config.SecretKey,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to create ssl uploader: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &DeployerProvider{
|
|
||||||
config: config,
|
|
||||||
logger: slog.Default(),
|
|
||||||
sslUploader: uploader,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer {
|
|
||||||
if logger == nil {
|
|
||||||
d.logger = slog.New(slog.DiscardHandler)
|
|
||||||
} else {
|
|
||||||
d.logger = logger
|
|
||||||
}
|
|
||||||
d.sslUploader.WithLogger(logger)
|
|
||||||
return d
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) {
|
|
||||||
// 上传证书到 SSL
|
|
||||||
upres, err := d.sslUploader.Upload(ctx, certPEM, privkeyPEM)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to upload certificate file: %w", err)
|
|
||||||
} else {
|
|
||||||
d.logger.Info("ssl certificate uploaded", slog.Any("result", upres))
|
|
||||||
}
|
|
||||||
|
|
||||||
return &deployer.DeployResult{}, nil
|
|
||||||
}
|
|
@ -1,71 +0,0 @@
|
|||||||
package volcenginecertcenter
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"log/slog"
|
|
||||||
|
|
||||||
"github.com/usual2970/certimate/internal/pkg/core/deployer"
|
|
||||||
"github.com/usual2970/certimate/internal/pkg/core/uploader"
|
|
||||||
uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/volcengine-certcenter"
|
|
||||||
)
|
|
||||||
|
|
||||||
type DeployerConfig struct {
|
|
||||||
// 火山引擎 AccessKeyId。
|
|
||||||
AccessKeyId string `json:"accessKeyId"`
|
|
||||||
// 火山引擎 AccessKeySecret。
|
|
||||||
AccessKeySecret string `json:"accessKeySecret"`
|
|
||||||
// 火山引擎地域。
|
|
||||||
Region string `json:"region"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type DeployerProvider struct {
|
|
||||||
config *DeployerConfig
|
|
||||||
logger *slog.Logger
|
|
||||||
sslUploader uploader.Uploader
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ deployer.Deployer = (*DeployerProvider)(nil)
|
|
||||||
|
|
||||||
func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
|
|
||||||
if config == nil {
|
|
||||||
panic("config is nil")
|
|
||||||
}
|
|
||||||
|
|
||||||
uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{
|
|
||||||
AccessKeyId: config.AccessKeyId,
|
|
||||||
AccessKeySecret: config.AccessKeySecret,
|
|
||||||
Region: config.Region,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to create ssl uploader: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &DeployerProvider{
|
|
||||||
config: config,
|
|
||||||
logger: slog.Default(),
|
|
||||||
sslUploader: uploader,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer {
|
|
||||||
if logger == nil {
|
|
||||||
d.logger = slog.New(slog.DiscardHandler)
|
|
||||||
} else {
|
|
||||||
d.logger = logger
|
|
||||||
}
|
|
||||||
d.sslUploader.WithLogger(logger)
|
|
||||||
return d
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) {
|
|
||||||
// 上传证书到证书中心
|
|
||||||
upres, err := d.sslUploader.Upload(ctx, certPEM, privkeyPEM)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to upload certificate file: %w", err)
|
|
||||||
} else {
|
|
||||||
d.logger.Info("ssl certificate uploaded", slog.Any("result", upres))
|
|
||||||
}
|
|
||||||
|
|
||||||
return &deployer.DeployResult{}, nil
|
|
||||||
}
|
|
@ -1,109 +0,0 @@
|
|||||||
package wangsucdn
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"log/slog"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/usual2970/certimate/internal/pkg/core/deployer"
|
|
||||||
"github.com/usual2970/certimate/internal/pkg/core/uploader"
|
|
||||||
uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/wangsu-certificate"
|
|
||||||
wangsusdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/wangsu/cdn"
|
|
||||||
sliceutil "github.com/usual2970/certimate/internal/pkg/utils/slice"
|
|
||||||
)
|
|
||||||
|
|
||||||
type DeployerConfig struct {
|
|
||||||
// 网宿云 AccessKeyId。
|
|
||||||
AccessKeyId string `json:"accessKeyId"`
|
|
||||||
// 网宿云 AccessKeySecret。
|
|
||||||
AccessKeySecret string `json:"accessKeySecret"`
|
|
||||||
// 加速域名数组(支持泛域名)。
|
|
||||||
Domains []string `json:"domains"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type DeployerProvider struct {
|
|
||||||
config *DeployerConfig
|
|
||||||
logger *slog.Logger
|
|
||||||
sdkClient *wangsusdk.Client
|
|
||||||
sslUploader uploader.Uploader
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ deployer.Deployer = (*DeployerProvider)(nil)
|
|
||||||
|
|
||||||
func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
|
|
||||||
if config == nil {
|
|
||||||
panic("config is nil")
|
|
||||||
}
|
|
||||||
|
|
||||||
client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to create sdk client: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{
|
|
||||||
AccessKeyId: config.AccessKeyId,
|
|
||||||
AccessKeySecret: config.AccessKeySecret,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to create ssl uploader: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &DeployerProvider{
|
|
||||||
config: config,
|
|
||||||
logger: slog.Default(),
|
|
||||||
sdkClient: client,
|
|
||||||
sslUploader: uploader,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer {
|
|
||||||
if logger == nil {
|
|
||||||
d.logger = slog.New(slog.DiscardHandler)
|
|
||||||
} else {
|
|
||||||
d.logger = logger
|
|
||||||
}
|
|
||||||
return d
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) {
|
|
||||||
// 上传证书到证书管理
|
|
||||||
upres, err := d.sslUploader.Upload(ctx, certPEM, privkeyPEM)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to upload certificate file: %w", err)
|
|
||||||
} else {
|
|
||||||
d.logger.Info("ssl certificate uploaded", slog.Any("result", upres))
|
|
||||||
}
|
|
||||||
|
|
||||||
// 批量修改域名证书配置
|
|
||||||
// REF: https://www.wangsu.com/document/api-doc/37447
|
|
||||||
certId, _ := strconv.ParseInt(upres.CertId, 10, 64)
|
|
||||||
batchUpdateCertificateConfigReq := &wangsusdk.BatchUpdateCertificateConfigRequest{
|
|
||||||
CertificateId: certId,
|
|
||||||
DomainNames: sliceutil.Map(d.config.Domains, func(domain string) string {
|
|
||||||
// "*.example.com" → ".example.com",适配网宿云 CDN 要求的泛域名格式
|
|
||||||
return strings.TrimPrefix(domain, "*")
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
batchUpdateCertificateConfigResp, err := d.sdkClient.BatchUpdateCertificateConfig(batchUpdateCertificateConfigReq)
|
|
||||||
d.logger.Debug("sdk request 'cdn.BatchUpdateCertificateConfig'", slog.Any("request", batchUpdateCertificateConfigReq), slog.Any("response", batchUpdateCertificateConfigResp))
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to execute sdk request 'cdn.BatchUpdateCertificateConfig': %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &deployer.DeployResult{}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func createSdkClient(accessKeyId, accessKeySecret string) (*wangsusdk.Client, error) {
|
|
||||||
if accessKeyId == "" {
|
|
||||||
return nil, errors.New("invalid wangsu access key id")
|
|
||||||
}
|
|
||||||
|
|
||||||
if accessKeySecret == "" {
|
|
||||||
return nil, errors.New("invalid wangsu access key secret")
|
|
||||||
}
|
|
||||||
|
|
||||||
return wangsusdk.NewClient(accessKeyId, accessKeySecret), nil
|
|
||||||
}
|
|
@ -1,109 +0,0 @@
|
|||||||
package wangsucertificate
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"log/slog"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/usual2970/certimate/internal/pkg/core/deployer"
|
|
||||||
"github.com/usual2970/certimate/internal/pkg/core/uploader"
|
|
||||||
uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/wangsu-certificate"
|
|
||||||
wangsusdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/wangsu/certificate"
|
|
||||||
typeutil "github.com/usual2970/certimate/internal/pkg/utils/type"
|
|
||||||
)
|
|
||||||
|
|
||||||
type DeployerConfig struct {
|
|
||||||
// 网宿云 AccessKeyId。
|
|
||||||
AccessKeyId string `json:"accessKeyId"`
|
|
||||||
// 网宿云 AccessKeySecret。
|
|
||||||
AccessKeySecret string `json:"accessKeySecret"`
|
|
||||||
// 证书 ID。
|
|
||||||
// 选填。零值时表示新建证书;否则表示更新证书。
|
|
||||||
CertificateId string `json:"certificateId,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type DeployerProvider struct {
|
|
||||||
config *DeployerConfig
|
|
||||||
logger *slog.Logger
|
|
||||||
sdkClient *wangsusdk.Client
|
|
||||||
sslUploader uploader.Uploader
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ deployer.Deployer = (*DeployerProvider)(nil)
|
|
||||||
|
|
||||||
func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
|
|
||||||
if config == nil {
|
|
||||||
panic("config is nil")
|
|
||||||
}
|
|
||||||
|
|
||||||
client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to create sdk client: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{
|
|
||||||
AccessKeyId: config.AccessKeyId,
|
|
||||||
AccessKeySecret: config.AccessKeySecret,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to create ssl uploader: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &DeployerProvider{
|
|
||||||
config: config,
|
|
||||||
logger: slog.Default(),
|
|
||||||
sdkClient: client,
|
|
||||||
sslUploader: uploader,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer {
|
|
||||||
if logger == nil {
|
|
||||||
d.logger = slog.New(slog.DiscardHandler)
|
|
||||||
} else {
|
|
||||||
d.logger = logger
|
|
||||||
}
|
|
||||||
return d
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) {
|
|
||||||
if d.config.CertificateId == "" {
|
|
||||||
// 上传证书到证书管理
|
|
||||||
upres, err := d.sslUploader.Upload(ctx, certPEM, privkeyPEM)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to upload certificate file: %w", err)
|
|
||||||
} else {
|
|
||||||
d.logger.Info("ssl certificate uploaded", slog.Any("result", upres))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// 修改证书
|
|
||||||
// REF: https://www.wangsu.com/document/api-doc/25568?productCode=certificatemanagement
|
|
||||||
updateCertificateReq := &wangsusdk.UpdateCertificateRequest{
|
|
||||||
Name: typeutil.ToPtr(fmt.Sprintf("certimate_%d", time.Now().UnixMilli())),
|
|
||||||
Certificate: typeutil.ToPtr(certPEM),
|
|
||||||
PrivateKey: typeutil.ToPtr(privkeyPEM),
|
|
||||||
Comment: typeutil.ToPtr("upload from certimate"),
|
|
||||||
}
|
|
||||||
updateCertificateResp, err := d.sdkClient.UpdateCertificate(d.config.CertificateId, updateCertificateReq)
|
|
||||||
d.logger.Debug("sdk request 'certificatemanagement.UpdateCertificate'", slog.Any("request", updateCertificateReq), slog.Any("response", updateCertificateResp))
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to execute sdk request 'certificatemanagement.CreateCertificate': %w", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return &deployer.DeployResult{}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func createSdkClient(accessKeyId, accessKeySecret string) (*wangsusdk.Client, error) {
|
|
||||||
if accessKeyId == "" {
|
|
||||||
return nil, errors.New("invalid wangsu access key id")
|
|
||||||
}
|
|
||||||
|
|
||||||
if accessKeySecret == "" {
|
|
||||||
return nil, errors.New("invalid wangsu access key secret")
|
|
||||||
}
|
|
||||||
|
|
||||||
return wangsusdk.NewClient(accessKeyId, accessKeySecret), nil
|
|
||||||
}
|
|
@ -1,157 +0,0 @@
|
|||||||
package onepanelssl
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"crypto/tls"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"log/slog"
|
|
||||||
"net/url"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/usual2970/certimate/internal/pkg/core/uploader"
|
|
||||||
onepanelsdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/1panel"
|
|
||||||
)
|
|
||||||
|
|
||||||
type UploaderConfig struct {
|
|
||||||
// 1Panel 服务地址。
|
|
||||||
ServerUrl string `json:"serverUrl"`
|
|
||||||
// 1Panel 版本。
|
|
||||||
ApiVersion string `json:"apiVersion"`
|
|
||||||
// 1Panel 接口密钥。
|
|
||||||
ApiKey string `json:"apiKey"`
|
|
||||||
// 是否允许不安全的连接。
|
|
||||||
AllowInsecureConnections bool `json:"allowInsecureConnections,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type UploaderProvider struct {
|
|
||||||
config *UploaderConfig
|
|
||||||
logger *slog.Logger
|
|
||||||
sdkClient *onepanelsdk.Client
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ uploader.Uploader = (*UploaderProvider)(nil)
|
|
||||||
|
|
||||||
func NewUploader(config *UploaderConfig) (*UploaderProvider, error) {
|
|
||||||
if config == nil {
|
|
||||||
panic("config is nil")
|
|
||||||
}
|
|
||||||
|
|
||||||
client, err := createSdkClient(config.ServerUrl, config.ApiVersion, config.ApiKey, config.AllowInsecureConnections)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to create sdk client: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &UploaderProvider{
|
|
||||||
config: config,
|
|
||||||
logger: slog.Default(),
|
|
||||||
sdkClient: client,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *UploaderProvider) WithLogger(logger *slog.Logger) uploader.Uploader {
|
|
||||||
if logger == nil {
|
|
||||||
u.logger = slog.New(slog.DiscardHandler)
|
|
||||||
} else {
|
|
||||||
u.logger = logger
|
|
||||||
}
|
|
||||||
return u
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *UploaderProvider) Upload(ctx context.Context, certPEM string, privkeyPEM string) (*uploader.UploadResult, error) {
|
|
||||||
// 遍历证书列表,避免重复上传
|
|
||||||
if res, err := u.getCertIfExists(ctx, certPEM, privkeyPEM); err != nil {
|
|
||||||
return nil, err
|
|
||||||
} else if res != nil {
|
|
||||||
u.logger.Info("ssl certificate already exists")
|
|
||||||
return res, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// 生成新证书名(需符合 1Panel 命名规则)
|
|
||||||
certName := fmt.Sprintf("certimate-%d", time.Now().UnixMilli())
|
|
||||||
|
|
||||||
// 上传证书
|
|
||||||
uploadWebsiteSSLReq := &onepanelsdk.UploadWebsiteSSLRequest{
|
|
||||||
Type: "paste",
|
|
||||||
Description: certName,
|
|
||||||
Certificate: certPEM,
|
|
||||||
PrivateKey: privkeyPEM,
|
|
||||||
}
|
|
||||||
uploadWebsiteSSLResp, err := u.sdkClient.UploadWebsiteSSL(uploadWebsiteSSLReq)
|
|
||||||
u.logger.Debug("sdk request '1panel.UploadWebsiteSSL'", slog.Any("request", uploadWebsiteSSLReq), slog.Any("response", uploadWebsiteSSLResp))
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to execute sdk request '1panel.UploadWebsiteSSL': %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 遍历证书列表,获取刚刚上传证书 ID
|
|
||||||
if res, err := u.getCertIfExists(ctx, certPEM, privkeyPEM); err != nil {
|
|
||||||
return nil, err
|
|
||||||
} else if res == nil {
|
|
||||||
return nil, fmt.Errorf("no ssl certificate found, may be upload failed (code: %d, message: %s)", uploadWebsiteSSLResp.GetCode(), uploadWebsiteSSLResp.GetMessage())
|
|
||||||
} else {
|
|
||||||
return res, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *UploaderProvider) getCertIfExists(ctx context.Context, certPEM string, privkeyPEM string) (*uploader.UploadResult, error) {
|
|
||||||
searchWebsiteSSLPageNumber := int32(1)
|
|
||||||
searchWebsiteSSLPageSize := int32(100)
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-ctx.Done():
|
|
||||||
return nil, ctx.Err()
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
|
|
||||||
searchWebsiteSSLReq := &onepanelsdk.SearchWebsiteSSLRequest{
|
|
||||||
Page: searchWebsiteSSLPageNumber,
|
|
||||||
PageSize: searchWebsiteSSLPageSize,
|
|
||||||
}
|
|
||||||
searchWebsiteSSLResp, err := u.sdkClient.SearchWebsiteSSL(searchWebsiteSSLReq)
|
|
||||||
u.logger.Debug("sdk request '1panel.SearchWebsiteSSL'", slog.Any("request", searchWebsiteSSLReq), slog.Any("response", searchWebsiteSSLResp))
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to execute sdk request '1panel.SearchWebsiteSSL': %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, sslItem := range searchWebsiteSSLResp.Data.Items {
|
|
||||||
if strings.TrimSpace(sslItem.PEM) == strings.TrimSpace(certPEM) &&
|
|
||||||
strings.TrimSpace(sslItem.PrivateKey) == strings.TrimSpace(privkeyPEM) {
|
|
||||||
// 如果已存在相同证书,直接返回
|
|
||||||
return &uploader.UploadResult{
|
|
||||||
CertId: fmt.Sprintf("%d", sslItem.ID),
|
|
||||||
CertName: sslItem.Description,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(searchWebsiteSSLResp.Data.Items) < int(searchWebsiteSSLPageSize) {
|
|
||||||
break
|
|
||||||
} else {
|
|
||||||
searchWebsiteSSLPageNumber++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func createSdkClient(serverUrl, apiVersion, apiKey string, skipTlsVerify bool) (*onepanelsdk.Client, error) {
|
|
||||||
if _, err := url.Parse(serverUrl); err != nil {
|
|
||||||
return nil, errors.New("invalid 1panel server url")
|
|
||||||
}
|
|
||||||
|
|
||||||
if apiVersion == "" {
|
|
||||||
return nil, errors.New("invalid 1panel api version")
|
|
||||||
}
|
|
||||||
|
|
||||||
if apiKey == "" {
|
|
||||||
return nil, errors.New("invalid 1panel api key")
|
|
||||||
}
|
|
||||||
|
|
||||||
client := onepanelsdk.NewClient(serverUrl, apiVersion, apiKey)
|
|
||||||
if skipTlsVerify {
|
|
||||||
client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true})
|
|
||||||
}
|
|
||||||
|
|
||||||
return client, nil
|
|
||||||
}
|
|
@ -1,77 +0,0 @@
|
|||||||
package dogecloud
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"log/slog"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/usual2970/certimate/internal/pkg/core/uploader"
|
|
||||||
dogesdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/dogecloud"
|
|
||||||
)
|
|
||||||
|
|
||||||
type UploaderConfig struct {
|
|
||||||
// 多吉云 AccessKey。
|
|
||||||
AccessKey string `json:"accessKey"`
|
|
||||||
// 多吉云 SecretKey。
|
|
||||||
SecretKey string `json:"secretKey"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type UploaderProvider struct {
|
|
||||||
config *UploaderConfig
|
|
||||||
logger *slog.Logger
|
|
||||||
sdkClient *dogesdk.Client
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ uploader.Uploader = (*UploaderProvider)(nil)
|
|
||||||
|
|
||||||
func NewUploader(config *UploaderConfig) (*UploaderProvider, error) {
|
|
||||||
if config == nil {
|
|
||||||
panic("config is nil")
|
|
||||||
}
|
|
||||||
|
|
||||||
client, err := createSdkClient(config.AccessKey, config.SecretKey)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to create sdk client: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &UploaderProvider{
|
|
||||||
config: config,
|
|
||||||
logger: slog.Default(),
|
|
||||||
sdkClient: client,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *UploaderProvider) WithLogger(logger *slog.Logger) uploader.Uploader {
|
|
||||||
if logger == nil {
|
|
||||||
u.logger = slog.New(slog.DiscardHandler)
|
|
||||||
} else {
|
|
||||||
u.logger = logger
|
|
||||||
}
|
|
||||||
return u
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *UploaderProvider) Upload(ctx context.Context, certPEM string, privkeyPEM string) (*uploader.UploadResult, error) {
|
|
||||||
// 生成新证书名(需符合多吉云命名规则)
|
|
||||||
var certId, certName string
|
|
||||||
certName = fmt.Sprintf("certimate-%d", time.Now().UnixMilli())
|
|
||||||
|
|
||||||
// 上传新证书
|
|
||||||
// REF: https://docs.dogecloud.com/cdn/api-cert-upload
|
|
||||||
uploadSslCertResp, err := u.sdkClient.UploadCdnCert(certName, certPEM, privkeyPEM)
|
|
||||||
u.logger.Debug("sdk request 'cdn.UploadCdnCert'", slog.Any("response", uploadSslCertResp))
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to execute sdk request 'cdn.UploadCdnCert': %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
certId = fmt.Sprintf("%d", uploadSslCertResp.Data.Id)
|
|
||||||
return &uploader.UploadResult{
|
|
||||||
CertId: certId,
|
|
||||||
CertName: certName,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func createSdkClient(accessKey, secretKey string) (*dogesdk.Client, error) {
|
|
||||||
client := dogesdk.NewClient(accessKey, secretKey)
|
|
||||||
return client, nil
|
|
||||||
}
|
|
@ -1,95 +0,0 @@
|
|||||||
package gcorecdn
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"log/slog"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/G-Core/gcorelabscdn-go/gcore/provider"
|
|
||||||
"github.com/G-Core/gcorelabscdn-go/sslcerts"
|
|
||||||
|
|
||||||
"github.com/usual2970/certimate/internal/pkg/core/uploader"
|
|
||||||
gcoresdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/gcore/common"
|
|
||||||
)
|
|
||||||
|
|
||||||
type UploaderConfig struct {
|
|
||||||
// Gcore API Token。
|
|
||||||
ApiToken string `json:"apiToken"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type UploaderProvider struct {
|
|
||||||
config *UploaderConfig
|
|
||||||
logger *slog.Logger
|
|
||||||
sdkClient *sslcerts.Service
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ uploader.Uploader = (*UploaderProvider)(nil)
|
|
||||||
|
|
||||||
func NewUploader(config *UploaderConfig) (*UploaderProvider, error) {
|
|
||||||
if config == nil {
|
|
||||||
panic("config is nil")
|
|
||||||
}
|
|
||||||
|
|
||||||
client, err := createSdkClient(config.ApiToken)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to create sdk client: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &UploaderProvider{
|
|
||||||
config: config,
|
|
||||||
logger: slog.Default(),
|
|
||||||
sdkClient: client,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *UploaderProvider) WithLogger(logger *slog.Logger) uploader.Uploader {
|
|
||||||
if logger == nil {
|
|
||||||
u.logger = slog.New(slog.DiscardHandler)
|
|
||||||
} else {
|
|
||||||
u.logger = logger
|
|
||||||
}
|
|
||||||
return u
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *UploaderProvider) Upload(ctx context.Context, certPEM string, privkeyPEM string) (*uploader.UploadResult, error) {
|
|
||||||
// 生成新证书名(需符合 Gcore 命名规则)
|
|
||||||
var certId, certName string
|
|
||||||
certName = fmt.Sprintf("certimate_%d", time.Now().UnixMilli())
|
|
||||||
|
|
||||||
// 新增证书
|
|
||||||
// REF: https://api.gcore.com/docs/cdn#tag/SSL-certificates/operation/add_ssl_certificates
|
|
||||||
createCertificateReq := &sslcerts.CreateRequest{
|
|
||||||
Name: certName,
|
|
||||||
Cert: certPEM,
|
|
||||||
PrivateKey: privkeyPEM,
|
|
||||||
Automated: false,
|
|
||||||
ValidateRootCA: false,
|
|
||||||
}
|
|
||||||
createCertificateResp, err := u.sdkClient.Create(context.TODO(), createCertificateReq)
|
|
||||||
u.logger.Debug("sdk request 'sslcerts.Create'", slog.Any("request", createCertificateReq), slog.Any("response", createCertificateResp))
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to execute sdk request 'sslcerts.Create': %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
certId = fmt.Sprintf("%d", createCertificateResp.ID)
|
|
||||||
certName = createCertificateResp.Name
|
|
||||||
return &uploader.UploadResult{
|
|
||||||
CertId: certId,
|
|
||||||
CertName: certName,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func createSdkClient(apiToken string) (*sslcerts.Service, error) {
|
|
||||||
if apiToken == "" {
|
|
||||||
return nil, errors.New("invalid gcore api token")
|
|
||||||
}
|
|
||||||
|
|
||||||
requester := provider.NewClient(
|
|
||||||
gcoresdk.BASE_URL,
|
|
||||||
provider.WithSigner(gcoresdk.NewAuthRequestSigner(apiToken)),
|
|
||||||
)
|
|
||||||
service := sslcerts.NewService(requester)
|
|
||||||
return service, nil
|
|
||||||
}
|
|
@ -1,96 +0,0 @@
|
|||||||
package qiniusslcert
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"log/slog"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/qiniu/go-sdk/v7/auth"
|
|
||||||
|
|
||||||
"github.com/usual2970/certimate/internal/pkg/core/uploader"
|
|
||||||
qiniusdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/qiniu"
|
|
||||||
certutil "github.com/usual2970/certimate/internal/pkg/utils/cert"
|
|
||||||
)
|
|
||||||
|
|
||||||
type UploaderConfig struct {
|
|
||||||
// 七牛云 AccessKey。
|
|
||||||
AccessKey string `json:"accessKey"`
|
|
||||||
// 七牛云 SecretKey。
|
|
||||||
SecretKey string `json:"secretKey"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type UploaderProvider struct {
|
|
||||||
config *UploaderConfig
|
|
||||||
logger *slog.Logger
|
|
||||||
sdkClient *qiniusdk.Client
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ uploader.Uploader = (*UploaderProvider)(nil)
|
|
||||||
|
|
||||||
func NewUploader(config *UploaderConfig) (*UploaderProvider, error) {
|
|
||||||
if config == nil {
|
|
||||||
panic("config is nil")
|
|
||||||
}
|
|
||||||
|
|
||||||
client, err := createSdkClient(config.AccessKey, config.SecretKey)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to create sdk client: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &UploaderProvider{
|
|
||||||
config: config,
|
|
||||||
logger: slog.Default(),
|
|
||||||
sdkClient: client,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *UploaderProvider) WithLogger(logger *slog.Logger) uploader.Uploader {
|
|
||||||
if logger == nil {
|
|
||||||
u.logger = slog.New(slog.DiscardHandler)
|
|
||||||
} else {
|
|
||||||
u.logger = logger
|
|
||||||
}
|
|
||||||
return u
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *UploaderProvider) Upload(ctx context.Context, certPEM string, privkeyPEM string) (*uploader.UploadResult, error) {
|
|
||||||
// 解析证书内容
|
|
||||||
certX509, err := certutil.ParseCertificateFromPEM(certPEM)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// 生成新证书名(需符合七牛云命名规则)
|
|
||||||
var certId, certName string
|
|
||||||
certName = fmt.Sprintf("certimate-%d", time.Now().UnixMilli())
|
|
||||||
|
|
||||||
// 上传新证书
|
|
||||||
// REF: https://developer.qiniu.com/fusion/8593/interface-related-certificate
|
|
||||||
uploadSslCertResp, err := u.sdkClient.UploadSslCert(context.TODO(), certName, certX509.Subject.CommonName, certPEM, privkeyPEM)
|
|
||||||
u.logger.Debug("sdk request 'cdn.UploadSslCert'", slog.Any("response", uploadSslCertResp))
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to execute sdk request 'cdn.UploadSslCert': %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
certId = uploadSslCertResp.CertID
|
|
||||||
return &uploader.UploadResult{
|
|
||||||
CertId: certId,
|
|
||||||
CertName: certName,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func createSdkClient(accessKey, secretKey string) (*qiniusdk.Client, error) {
|
|
||||||
if secretKey == "" {
|
|
||||||
return nil, errors.New("invalid qiniu access key")
|
|
||||||
}
|
|
||||||
|
|
||||||
if secretKey == "" {
|
|
||||||
return nil, errors.New("invalid qiniu secret key")
|
|
||||||
}
|
|
||||||
|
|
||||||
credential := auth.New(accessKey, secretKey)
|
|
||||||
client := qiniusdk.NewClient(credential)
|
|
||||||
return client, nil
|
|
||||||
}
|
|
@ -1,82 +0,0 @@
|
|||||||
package upyunssl
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"log/slog"
|
|
||||||
|
|
||||||
"github.com/usual2970/certimate/internal/pkg/core/uploader"
|
|
||||||
upyunsdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/upyun/console"
|
|
||||||
)
|
|
||||||
|
|
||||||
type UploaderConfig struct {
|
|
||||||
// 又拍云账号用户名。
|
|
||||||
Username string `json:"username"`
|
|
||||||
// 又拍云账号密码。
|
|
||||||
Password string `json:"password"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type UploaderProvider struct {
|
|
||||||
config *UploaderConfig
|
|
||||||
logger *slog.Logger
|
|
||||||
sdkClient *upyunsdk.Client
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ uploader.Uploader = (*UploaderProvider)(nil)
|
|
||||||
|
|
||||||
func NewUploader(config *UploaderConfig) (*UploaderProvider, error) {
|
|
||||||
if config == nil {
|
|
||||||
panic("config is nil")
|
|
||||||
}
|
|
||||||
|
|
||||||
client, err := createSdkClient(config.Username, config.Password)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to create sdk client: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &UploaderProvider{
|
|
||||||
config: config,
|
|
||||||
logger: slog.Default(),
|
|
||||||
sdkClient: client,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *UploaderProvider) WithLogger(logger *slog.Logger) uploader.Uploader {
|
|
||||||
if logger == nil {
|
|
||||||
u.logger = slog.New(slog.DiscardHandler)
|
|
||||||
} else {
|
|
||||||
u.logger = logger
|
|
||||||
}
|
|
||||||
return u
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *UploaderProvider) Upload(ctx context.Context, certPEM string, privkeyPEM string) (*uploader.UploadResult, error) {
|
|
||||||
// 上传证书
|
|
||||||
uploadHttpsCertificateReq := &upyunsdk.UploadHttpsCertificateRequest{
|
|
||||||
Certificate: certPEM,
|
|
||||||
PrivateKey: privkeyPEM,
|
|
||||||
}
|
|
||||||
uploadHttpsCertificateResp, err := u.sdkClient.UploadHttpsCertificate(uploadHttpsCertificateReq)
|
|
||||||
u.logger.Debug("sdk request 'console.UploadHttpsCertificate'", slog.Any("response", uploadHttpsCertificateResp))
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to execute sdk request 'console.UploadHttpsCertificate': %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &uploader.UploadResult{
|
|
||||||
CertId: uploadHttpsCertificateResp.Data.Result.CertificateId,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func createSdkClient(username, password string) (*upyunsdk.Client, error) {
|
|
||||||
if username == "" {
|
|
||||||
return nil, errors.New("invalid upyun username")
|
|
||||||
}
|
|
||||||
|
|
||||||
if password == "" {
|
|
||||||
return nil, errors.New("invalid upyun password")
|
|
||||||
}
|
|
||||||
|
|
||||||
client := upyunsdk.NewClient(username, password)
|
|
||||||
return client, nil
|
|
||||||
}
|
|
@ -1,32 +0,0 @@
|
|||||||
package uploader
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"log/slog"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 表示定义证书上传器的抽象类型接口。
|
|
||||||
// 云服务商通常会提供 SSL 证书管理服务,可供用户集中管理证书。
|
|
||||||
// 注意与 `Deployer` 区分,“上传”通常为“部署”的前置操作。
|
|
||||||
type Uploader interface {
|
|
||||||
WithLogger(logger *slog.Logger) Uploader
|
|
||||||
|
|
||||||
// 上传证书。
|
|
||||||
//
|
|
||||||
// 入参:
|
|
||||||
// - ctx:上下文。
|
|
||||||
// - certPEM:证书 PEM 内容。
|
|
||||||
// - privkeyPEM:私钥 PEM 内容。
|
|
||||||
//
|
|
||||||
// 出参:
|
|
||||||
// - res:上传结果。
|
|
||||||
// - err: 错误。
|
|
||||||
Upload(ctx context.Context, certPEM string, privkeyPEM string) (_res *UploadResult, _err error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 表示证书上传结果的数据结构,包含上传后的证书 ID、名称和其他数据。
|
|
||||||
type UploadResult struct {
|
|
||||||
CertId string `json:"certId"`
|
|
||||||
CertName string `json:"certName,omitzero"`
|
|
||||||
ExtendedData map[string]any `json:"extendedData,omitempty"`
|
|
||||||
}
|
|
@ -1,54 +0,0 @@
|
|||||||
package onepanel
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (c *Client) UpdateSystemSSL(req *UpdateSystemSSLRequest) (*UpdateSystemSSLResponse, error) {
|
|
||||||
resp := &UpdateSystemSSLResponse{}
|
|
||||||
err := c.sendRequestWithResult(http.MethodPost, "/settings/ssl/update", req, resp)
|
|
||||||
return resp, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) SearchWebsiteSSL(req *SearchWebsiteSSLRequest) (*SearchWebsiteSSLResponse, error) {
|
|
||||||
resp := &SearchWebsiteSSLResponse{}
|
|
||||||
err := c.sendRequestWithResult(http.MethodPost, "/websites/ssl/search", req, resp)
|
|
||||||
return resp, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) GetWebsiteSSL(req *GetWebsiteSSLRequest) (*GetWebsiteSSLResponse, error) {
|
|
||||||
if req.SSLID == 0 {
|
|
||||||
return nil, fmt.Errorf("1panel api error: invalid parameter: SSLID")
|
|
||||||
}
|
|
||||||
|
|
||||||
resp := &GetWebsiteSSLResponse{}
|
|
||||||
err := c.sendRequestWithResult(http.MethodGet, fmt.Sprintf("/websites/ssl/%d", req.SSLID), req, resp)
|
|
||||||
return resp, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) UploadWebsiteSSL(req *UploadWebsiteSSLRequest) (*UploadWebsiteSSLResponse, error) {
|
|
||||||
resp := &UploadWebsiteSSLResponse{}
|
|
||||||
err := c.sendRequestWithResult(http.MethodPost, "/websites/ssl/upload", req, resp)
|
|
||||||
return resp, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) GetHttpsConf(req *GetHttpsConfRequest) (*GetHttpsConfResponse, error) {
|
|
||||||
if req.WebsiteID == 0 {
|
|
||||||
return nil, fmt.Errorf("1panel api error: invalid parameter: WebsiteID")
|
|
||||||
}
|
|
||||||
|
|
||||||
resp := &GetHttpsConfResponse{}
|
|
||||||
err := c.sendRequestWithResult(http.MethodGet, fmt.Sprintf("/websites/%d/https", req.WebsiteID), req, resp)
|
|
||||||
return resp, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) UpdateHttpsConf(req *UpdateHttpsConfRequest) (*UpdateHttpsConfResponse, error) {
|
|
||||||
if req.WebsiteID == 0 {
|
|
||||||
return nil, fmt.Errorf("1panel api error: invalid parameter: WebsiteID")
|
|
||||||
}
|
|
||||||
|
|
||||||
resp := &UpdateHttpsConfResponse{}
|
|
||||||
err := c.sendRequestWithResult(http.MethodPost, fmt.Sprintf("/websites/%d/https", req.WebsiteID), req, resp)
|
|
||||||
return resp, err
|
|
||||||
}
|
|
@ -1,99 +0,0 @@
|
|||||||
package onepanel
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/md5"
|
|
||||||
"crypto/tls"
|
|
||||||
"encoding/hex"
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/go-resty/resty/v2"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Client struct {
|
|
||||||
client *resty.Client
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewClient(serverUrl, apiVersion, apiKey string) *Client {
|
|
||||||
if apiVersion == "" {
|
|
||||||
apiVersion = "v1"
|
|
||||||
}
|
|
||||||
|
|
||||||
client := resty.New().
|
|
||||||
SetBaseURL(strings.TrimRight(serverUrl, "/")+"/api/"+apiVersion).
|
|
||||||
SetHeader("User-Agent", "certimate").
|
|
||||||
SetPreRequestHook(func(c *resty.Client, req *http.Request) error {
|
|
||||||
timestamp := fmt.Sprintf("%d", time.Now().Unix())
|
|
||||||
tokenMd5 := md5.Sum([]byte("1panel" + apiKey + timestamp))
|
|
||||||
tokenMd5Hex := hex.EncodeToString(tokenMd5[:])
|
|
||||||
req.Header.Set("1Panel-Timestamp", timestamp)
|
|
||||||
req.Header.Set("1Panel-Token", tokenMd5Hex)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
|
|
||||||
return &Client{
|
|
||||||
client: client,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) WithTimeout(timeout time.Duration) *Client {
|
|
||||||
c.client.SetTimeout(timeout)
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) WithTLSConfig(config *tls.Config) *Client {
|
|
||||||
c.client.SetTLSClientConfig(config)
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) sendRequest(method string, path string, params interface{}) (*resty.Response, error) {
|
|
||||||
req := c.client.R()
|
|
||||||
if strings.EqualFold(method, http.MethodGet) {
|
|
||||||
qs := make(map[string]string)
|
|
||||||
if params != nil {
|
|
||||||
temp := make(map[string]any)
|
|
||||||
jsonb, _ := json.Marshal(params)
|
|
||||||
json.Unmarshal(jsonb, &temp)
|
|
||||||
for k, v := range temp {
|
|
||||||
if v != nil {
|
|
||||||
qs[k] = fmt.Sprintf("%v", v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
req = req.SetQueryParams(qs)
|
|
||||||
} else {
|
|
||||||
req = req.SetHeader("Content-Type", "application/json").SetBody(params)
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := req.Execute(method, path)
|
|
||||||
if err != nil {
|
|
||||||
return resp, fmt.Errorf("1panel api error: failed to send request: %w", err)
|
|
||||||
} else if resp.IsError() {
|
|
||||||
return resp, fmt.Errorf("1panel api error: unexpected status code: %d, resp: %s", resp.StatusCode(), resp.String())
|
|
||||||
}
|
|
||||||
|
|
||||||
return resp, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) sendRequestWithResult(method string, path string, params interface{}, result BaseResponse) error {
|
|
||||||
resp, err := c.sendRequest(method, path, params)
|
|
||||||
if err != nil {
|
|
||||||
if resp != nil {
|
|
||||||
json.Unmarshal(resp.Body(), &result)
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := json.Unmarshal(resp.Body(), &result); err != nil {
|
|
||||||
return fmt.Errorf("1panel api error: failed to unmarshal response: %w", err)
|
|
||||||
} else if errcode := result.GetCode(); errcode/100 != 2 {
|
|
||||||
return fmt.Errorf("1panel api error: code='%d', message='%s'", errcode, result.GetMessage())
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
@ -1,131 +0,0 @@
|
|||||||
package onepanel
|
|
||||||
|
|
||||||
type BaseResponse interface {
|
|
||||||
GetCode() int32
|
|
||||||
GetMessage() string
|
|
||||||
}
|
|
||||||
|
|
||||||
type baseResponse struct {
|
|
||||||
Code *int32 `json:"code,omitempty"`
|
|
||||||
Message *string `json:"message,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *baseResponse) GetCode() int32 {
|
|
||||||
if r.Code != nil {
|
|
||||||
return *r.Code
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *baseResponse) GetMessage() string {
|
|
||||||
if r.Message != nil {
|
|
||||||
return *r.Message
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
type UpdateSystemSSLRequest struct {
|
|
||||||
Cert string `json:"cert"`
|
|
||||||
Key string `json:"key"`
|
|
||||||
SSLType string `json:"sslType"`
|
|
||||||
SSL string `json:"ssl"`
|
|
||||||
SSLID int64 `json:"sslID"`
|
|
||||||
AutoRestart string `json:"autoRestart"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type UpdateSystemSSLResponse struct {
|
|
||||||
baseResponse
|
|
||||||
}
|
|
||||||
|
|
||||||
type SearchWebsiteSSLRequest struct {
|
|
||||||
Page int32 `json:"page"`
|
|
||||||
PageSize int32 `json:"pageSize"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type SearchWebsiteSSLResponse struct {
|
|
||||||
baseResponse
|
|
||||||
Data *struct {
|
|
||||||
Items []*struct {
|
|
||||||
ID int64 `json:"id"`
|
|
||||||
PEM string `json:"pem"`
|
|
||||||
PrivateKey string `json:"privateKey"`
|
|
||||||
Domains string `json:"domains"`
|
|
||||||
Description string `json:"description"`
|
|
||||||
Status string `json:"status"`
|
|
||||||
UpdatedAt string `json:"updatedAt"`
|
|
||||||
CreatedAt string `json:"createdAt"`
|
|
||||||
} `json:"items"`
|
|
||||||
Total int32 `json:"total"`
|
|
||||||
} `json:"data,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type GetWebsiteSSLRequest struct {
|
|
||||||
SSLID int64 `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type GetWebsiteSSLResponse struct {
|
|
||||||
baseResponse
|
|
||||||
Data *struct {
|
|
||||||
ID int64 `json:"id"`
|
|
||||||
Provider string `json:"provider"`
|
|
||||||
Description string `json:"description"`
|
|
||||||
PrimaryDomain string `json:"primaryDomain"`
|
|
||||||
Domains string `json:"domains"`
|
|
||||||
Type string `json:"type"`
|
|
||||||
Organization string `json:"organization"`
|
|
||||||
Status string `json:"status"`
|
|
||||||
StartDate string `json:"startDate"`
|
|
||||||
ExpireDate string `json:"expireDate"`
|
|
||||||
CreatedAt string `json:"createdAt"`
|
|
||||||
UpdatedAt string `json:"updatedAt"`
|
|
||||||
} `json:"data,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type UploadWebsiteSSLRequest struct {
|
|
||||||
Type string `json:"type"`
|
|
||||||
SSLID int64 `json:"sslID"`
|
|
||||||
Certificate string `json:"certificate"`
|
|
||||||
CertificatePath string `json:"certificatePath"`
|
|
||||||
PrivateKey string `json:"privateKey"`
|
|
||||||
PrivateKeyPath string `json:"privateKeyPath"`
|
|
||||||
Description string `json:"description"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type UploadWebsiteSSLResponse struct {
|
|
||||||
baseResponse
|
|
||||||
}
|
|
||||||
|
|
||||||
type GetHttpsConfRequest struct {
|
|
||||||
WebsiteID int64 `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type GetHttpsConfResponse struct {
|
|
||||||
baseResponse
|
|
||||||
Data *struct {
|
|
||||||
Enable bool `json:"enable"`
|
|
||||||
HttpConfig string `json:"httpConfig"`
|
|
||||||
SSLProtocol []string `json:"SSLProtocol"`
|
|
||||||
Algorithm string `json:"algorithm"`
|
|
||||||
Hsts bool `json:"hsts"`
|
|
||||||
} `json:"data,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type UpdateHttpsConfRequest struct {
|
|
||||||
WebsiteID int64 `json:"websiteId"`
|
|
||||||
Enable bool `json:"enable"`
|
|
||||||
Type string `json:"type"`
|
|
||||||
WebsiteSSLID int64 `json:"websiteSSLId"`
|
|
||||||
PrivateKey string `json:"privateKey"`
|
|
||||||
Certificate string `json:"certificate"`
|
|
||||||
PrivateKeyPath string `json:"privateKeyPath"`
|
|
||||||
CertificatePath string `json:"certificatePath"`
|
|
||||||
ImportType string `json:"importType"`
|
|
||||||
HttpConfig string `json:"httpConfig"`
|
|
||||||
SSLProtocol []string `json:"SSLProtocol"`
|
|
||||||
Algorithm string `json:"algorithm"`
|
|
||||||
Hsts bool `json:"hsts"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type UpdateHttpsConfResponse struct {
|
|
||||||
baseResponse
|
|
||||||
}
|
|
@ -1,23 +0,0 @@
|
|||||||
package baishan
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (c *Client) CreateCertificate(req *CreateCertificateRequest) (*CreateCertificateResponse, error) {
|
|
||||||
resp := &CreateCertificateResponse{}
|
|
||||||
err := c.sendRequestWithResult(http.MethodPost, "/v2/domain/certificate", req, resp)
|
|
||||||
return resp, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) GetDomainConfig(req *GetDomainConfigRequest) (*GetDomainConfigResponse, error) {
|
|
||||||
resp := &GetDomainConfigResponse{}
|
|
||||||
err := c.sendRequestWithResult(http.MethodGet, "/v2/domain/config", req, resp)
|
|
||||||
return resp, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) SetDomainConfig(req *SetDomainConfigRequest) (*SetDomainConfigResponse, error) {
|
|
||||||
resp := &SetDomainConfigResponse{}
|
|
||||||
err := c.sendRequestWithResult(http.MethodPost, "/v2/domain/config", req, resp)
|
|
||||||
return resp, err
|
|
||||||
}
|
|
@ -1,93 +0,0 @@
|
|||||||
package baishan
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"net/url"
|
|
||||||
"reflect"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/go-resty/resty/v2"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Client struct {
|
|
||||||
client *resty.Client
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewClient(apiToken string) *Client {
|
|
||||||
client := resty.New().
|
|
||||||
SetBaseURL("https://cdn.api.baishan.com").
|
|
||||||
SetHeader("User-Agent", "certimate").
|
|
||||||
SetHeader("Token", apiToken)
|
|
||||||
|
|
||||||
return &Client{
|
|
||||||
client: client,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) WithTimeout(timeout time.Duration) *Client {
|
|
||||||
c.client.SetTimeout(timeout)
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) sendRequest(method string, path string, params interface{}) (*resty.Response, error) {
|
|
||||||
req := c.client.R()
|
|
||||||
if strings.EqualFold(method, http.MethodGet) {
|
|
||||||
qs := url.Values{}
|
|
||||||
if params != nil {
|
|
||||||
temp := make(map[string]any)
|
|
||||||
jsonb, _ := json.Marshal(params)
|
|
||||||
json.Unmarshal(jsonb, &temp)
|
|
||||||
for k, v := range temp {
|
|
||||||
if v != nil {
|
|
||||||
rv := reflect.ValueOf(v)
|
|
||||||
switch rv.Kind() {
|
|
||||||
case reflect.Slice, reflect.Array:
|
|
||||||
for i := 0; i < rv.Len(); i++ {
|
|
||||||
qs.Add(fmt.Sprintf("%s[]", k), fmt.Sprintf("%v", rv.Index(i).Interface()))
|
|
||||||
}
|
|
||||||
case reflect.Map:
|
|
||||||
for _, rk := range rv.MapKeys() {
|
|
||||||
qs.Add(fmt.Sprintf("%s[%s]", k, rk.Interface()), fmt.Sprintf("%v", rv.MapIndex(rk).Interface()))
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
qs.Set(k, fmt.Sprintf("%v", v))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
req = req.SetQueryParamsFromValues(qs)
|
|
||||||
} else {
|
|
||||||
req = req.SetHeader("Content-Type", "application/json").SetBody(params)
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := req.Execute(method, path)
|
|
||||||
if err != nil {
|
|
||||||
return resp, fmt.Errorf("baishan api error: failed to send request: %w", err)
|
|
||||||
} else if resp.IsError() {
|
|
||||||
return resp, fmt.Errorf("baishan api error: unexpected status code: %d, resp: %s", resp.StatusCode(), resp.String())
|
|
||||||
}
|
|
||||||
|
|
||||||
return resp, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) sendRequestWithResult(method string, path string, params interface{}, result BaseResponse) error {
|
|
||||||
resp, err := c.sendRequest(method, path, params)
|
|
||||||
if err != nil {
|
|
||||||
if resp != nil {
|
|
||||||
json.Unmarshal(resp.Body(), &result)
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := json.Unmarshal(resp.Body(), &result); err != nil {
|
|
||||||
return fmt.Errorf("baishan api error: failed to unmarshal response: %w", err)
|
|
||||||
} else if errcode := result.GetCode(); errcode != 0 {
|
|
||||||
return fmt.Errorf("baishan api error: code='%d', message='%s'", errcode, result.GetMessage())
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
@ -1,82 +0,0 @@
|
|||||||
package baishan
|
|
||||||
|
|
||||||
import "encoding/json"
|
|
||||||
|
|
||||||
type BaseResponse interface {
|
|
||||||
GetCode() int32
|
|
||||||
GetMessage() string
|
|
||||||
}
|
|
||||||
|
|
||||||
type baseResponse struct {
|
|
||||||
Code *int32 `json:"code,omitempty"`
|
|
||||||
Message *string `json:"message,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *baseResponse) GetCode() int32 {
|
|
||||||
if r.Code != nil {
|
|
||||||
return *r.Code
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *baseResponse) GetMessage() string {
|
|
||||||
if r.Message != nil {
|
|
||||||
return *r.Message
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
type CreateCertificateRequest struct {
|
|
||||||
CertificateId *string `json:"cert_id,omitempty"`
|
|
||||||
Certificate string `json:"certificate"`
|
|
||||||
Key string `json:"key"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type CreateCertificateResponse struct {
|
|
||||||
baseResponse
|
|
||||||
Data *DomainCertificate `json:"data,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type GetDomainConfigRequest struct {
|
|
||||||
Domains string `json:"domains"`
|
|
||||||
Config []string `json:"config"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type GetDomainConfigResponse struct {
|
|
||||||
baseResponse
|
|
||||||
Data []*struct {
|
|
||||||
Domain string `json:"domain"`
|
|
||||||
Config *DomainConfig `json:"config"`
|
|
||||||
} `json:"data,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type SetDomainConfigRequest struct {
|
|
||||||
Domains string `json:"domains"`
|
|
||||||
Config *DomainConfig `json:"config"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type SetDomainConfigResponse struct {
|
|
||||||
baseResponse
|
|
||||||
Data *struct {
|
|
||||||
Config *DomainConfig `json:"config"`
|
|
||||||
} `json:"data,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type DomainCertificate struct {
|
|
||||||
CertId json.Number `json:"cert_id"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
CertStartTime string `json:"cert_start_time"`
|
|
||||||
CertExpireTime string `json:"cert_expire_time"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type DomainConfig struct {
|
|
||||||
Https *DomainConfigHttps `json:"https"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type DomainConfigHttps struct {
|
|
||||||
CertId json.Number `json:"cert_id"`
|
|
||||||
ForceHttps *string `json:"force_https,omitempty"`
|
|
||||||
EnableHttp2 *string `json:"http2,omitempty"`
|
|
||||||
EnableOcsp *string `json:"ocsp,omitempty"`
|
|
||||||
}
|
|
@ -1,31 +0,0 @@
|
|||||||
package btpanel
|
|
||||||
|
|
||||||
func (c *Client) ConfigSavePanelSSL(req *ConfigSavePanelSSLRequest) (*ConfigSavePanelSSLResponse, error) {
|
|
||||||
resp := &ConfigSavePanelSSLResponse{}
|
|
||||||
err := c.sendRequestWithResult("/config?action=SavePanelSSL", req, resp)
|
|
||||||
return resp, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) SiteSetSSL(req *SiteSetSSLRequest) (*SiteSetSSLResponse, error) {
|
|
||||||
resp := &SiteSetSSLResponse{}
|
|
||||||
err := c.sendRequestWithResult("/site?action=SetSSL", req, resp)
|
|
||||||
return resp, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) SystemServiceAdmin(req *SystemServiceAdminRequest) (*SystemServiceAdminResponse, error) {
|
|
||||||
resp := &SystemServiceAdminResponse{}
|
|
||||||
err := c.sendRequestWithResult("/system?action=ServiceAdmin", req, resp)
|
|
||||||
return resp, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) SSLCertSaveCert(req *SSLCertSaveCertRequest) (*SSLCertSaveCertResponse, error) {
|
|
||||||
resp := &SSLCertSaveCertResponse{}
|
|
||||||
err := c.sendRequestWithResult("/ssl/cert/save_cert", req, resp)
|
|
||||||
return resp, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) SSLSetBatchCertToSite(req *SSLSetBatchCertToSiteRequest) (*SSLSetBatchCertToSiteResponse, error) {
|
|
||||||
resp := &SSLSetBatchCertToSiteResponse{}
|
|
||||||
err := c.sendRequestWithResult("/ssl?action=SetBatchCertToSite", req, resp)
|
|
||||||
return resp, err
|
|
||||||
}
|
|
@ -1,110 +0,0 @@
|
|||||||
package btpanel
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/md5"
|
|
||||||
"crypto/tls"
|
|
||||||
"encoding/hex"
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"reflect"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/go-resty/resty/v2"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Client struct {
|
|
||||||
apiKey string
|
|
||||||
|
|
||||||
client *resty.Client
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewClient(serverUrl, apiKey string) *Client {
|
|
||||||
client := resty.New().
|
|
||||||
SetBaseURL(strings.TrimRight(serverUrl, "/")).
|
|
||||||
SetHeader("Content-Type", "application/x-www-form-urlencoded").
|
|
||||||
SetHeader("User-Agent", "certimate")
|
|
||||||
|
|
||||||
return &Client{
|
|
||||||
apiKey: apiKey,
|
|
||||||
client: client,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) WithTimeout(timeout time.Duration) *Client {
|
|
||||||
c.client.SetTimeout(timeout)
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) WithTLSConfig(config *tls.Config) *Client {
|
|
||||||
c.client.SetTLSClientConfig(config)
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) generateSignature(timestamp string) string {
|
|
||||||
keyMd5 := md5.Sum([]byte(c.apiKey))
|
|
||||||
keyMd5Hex := strings.ToLower(hex.EncodeToString(keyMd5[:]))
|
|
||||||
|
|
||||||
signMd5 := md5.Sum([]byte(timestamp + keyMd5Hex))
|
|
||||||
signMd5Hex := strings.ToLower(hex.EncodeToString(signMd5[:]))
|
|
||||||
return signMd5Hex
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) sendRequest(path string, params interface{}) (*resty.Response, error) {
|
|
||||||
timestamp := time.Now().Unix()
|
|
||||||
|
|
||||||
data := make(map[string]string)
|
|
||||||
if params != nil {
|
|
||||||
temp := make(map[string]any)
|
|
||||||
jsonb, _ := json.Marshal(params)
|
|
||||||
json.Unmarshal(jsonb, &temp)
|
|
||||||
for k, v := range temp {
|
|
||||||
if v != nil {
|
|
||||||
switch reflect.Indirect(reflect.ValueOf(v)).Kind() {
|
|
||||||
case reflect.String:
|
|
||||||
data[k] = v.(string)
|
|
||||||
case reflect.Bool, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Float32, reflect.Float64:
|
|
||||||
data[k] = fmt.Sprintf("%v", v)
|
|
||||||
default:
|
|
||||||
if t, ok := v.(time.Time); ok {
|
|
||||||
data[k] = t.Format(time.RFC3339)
|
|
||||||
} else {
|
|
||||||
jbytes, _ := json.Marshal(v)
|
|
||||||
data[k] = string(jbytes)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
data["request_time"] = fmt.Sprintf("%d", timestamp)
|
|
||||||
data["request_token"] = c.generateSignature(fmt.Sprintf("%d", timestamp))
|
|
||||||
|
|
||||||
req := c.client.R().SetFormData(data)
|
|
||||||
resp, err := req.Post(path)
|
|
||||||
if err != nil {
|
|
||||||
return resp, fmt.Errorf("baota api error: failed to send request: %w", err)
|
|
||||||
} else if resp.IsError() {
|
|
||||||
return resp, fmt.Errorf("baota api error: unexpected status code: %d, resp: %s", resp.StatusCode(), resp.String())
|
|
||||||
}
|
|
||||||
|
|
||||||
return resp, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) sendRequestWithResult(path string, params interface{}, result BaseResponse) error {
|
|
||||||
resp, err := c.sendRequest(path, params)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := json.Unmarshal(resp.Body(), &result); err != nil {
|
|
||||||
return fmt.Errorf("baota api error: failed to unmarshal response: %w", err)
|
|
||||||
} else if errstatus := result.GetStatus(); errstatus != nil && !*errstatus {
|
|
||||||
if result.GetMessage() == nil {
|
|
||||||
return fmt.Errorf("baota api error: unknown error")
|
|
||||||
} else {
|
|
||||||
return fmt.Errorf("baota api error: message='%s'", *result.GetMessage())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
@ -1,75 +0,0 @@
|
|||||||
package btpanel
|
|
||||||
|
|
||||||
type BaseResponse interface {
|
|
||||||
GetStatus() *bool
|
|
||||||
GetMessage() *string
|
|
||||||
}
|
|
||||||
|
|
||||||
type baseResponse struct {
|
|
||||||
Status *bool `json:"status,omitempty"`
|
|
||||||
Message *string `json:"msg,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *baseResponse) GetStatus() *bool {
|
|
||||||
return r.Status
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *baseResponse) GetMessage() *string {
|
|
||||||
return r.Message
|
|
||||||
}
|
|
||||||
|
|
||||||
type ConfigSavePanelSSLRequest struct {
|
|
||||||
PrivateKey string `json:"privateKey"`
|
|
||||||
Certificate string `json:"certPem"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type ConfigSavePanelSSLResponse struct {
|
|
||||||
baseResponse
|
|
||||||
}
|
|
||||||
|
|
||||||
type SiteSetSSLRequest struct {
|
|
||||||
Type string `json:"type"`
|
|
||||||
SiteName string `json:"siteName"`
|
|
||||||
PrivateKey string `json:"key"`
|
|
||||||
Certificate string `json:"csr"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type SiteSetSSLResponse struct {
|
|
||||||
baseResponse
|
|
||||||
}
|
|
||||||
|
|
||||||
type SystemServiceAdminRequest struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
Type string `json:"type"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type SystemServiceAdminResponse struct {
|
|
||||||
baseResponse
|
|
||||||
}
|
|
||||||
|
|
||||||
type SSLCertSaveCertRequest struct {
|
|
||||||
PrivateKey string `json:"key"`
|
|
||||||
Certificate string `json:"csr"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type SSLCertSaveCertResponse struct {
|
|
||||||
baseResponse
|
|
||||||
SSLHash string `json:"ssl_hash"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type SSLSetBatchCertToSiteRequest struct {
|
|
||||||
BatchInfo []*SSLSetBatchCertToSiteRequestBatchInfo `json:"BatchInfo"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type SSLSetBatchCertToSiteRequestBatchInfo struct {
|
|
||||||
SSLHash string `json:"ssl_hash"`
|
|
||||||
SiteName string `json:"siteName"`
|
|
||||||
CertName string `json:"certName"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type SSLSetBatchCertToSiteResponse struct {
|
|
||||||
baseResponse
|
|
||||||
TotalCount int32 `json:"total"`
|
|
||||||
SuccessCount int32 `json:"success"`
|
|
||||||
FailedCount int32 `json:"faild"`
|
|
||||||
}
|
|
@ -1,19 +0,0 @@
|
|||||||
package btwaf
|
|
||||||
|
|
||||||
func (c *Client) GetSiteList(req *GetSiteListRequest) (*GetSiteListResponse, error) {
|
|
||||||
resp := &GetSiteListResponse{}
|
|
||||||
err := c.sendRequestWithResult("/wafmastersite/get_site_list", req, resp)
|
|
||||||
return resp, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) ModifySite(req *ModifySiteRequest) (*ModifySiteResponse, error) {
|
|
||||||
resp := &ModifySiteResponse{}
|
|
||||||
err := c.sendRequestWithResult("/wafmastersite/modify_site", req, resp)
|
|
||||||
return resp, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) ConfigSetSSL(req *ConfigSetSSLRequest) (*ConfigSetSSLResponse, error) {
|
|
||||||
resp := &ConfigSetSSLResponse{}
|
|
||||||
err := c.sendRequestWithResult("/config/set_cert", req, resp)
|
|
||||||
return resp, err
|
|
||||||
}
|
|
@ -1,77 +0,0 @@
|
|||||||
package btwaf
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/md5"
|
|
||||||
"crypto/tls"
|
|
||||||
"encoding/hex"
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/go-resty/resty/v2"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Client struct {
|
|
||||||
client *resty.Client
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewClient(serverUrl, apiKey string) *Client {
|
|
||||||
client := resty.New().
|
|
||||||
SetBaseURL(strings.TrimRight(serverUrl, "/")+"/api").
|
|
||||||
SetHeader("Content-Type", "application/json").
|
|
||||||
SetHeader("User-Agent", "certimate").
|
|
||||||
SetPreRequestHook(func(c *resty.Client, req *http.Request) error {
|
|
||||||
timestamp := fmt.Sprintf("%d", time.Now().Unix())
|
|
||||||
keyMd5 := md5.Sum([]byte(apiKey))
|
|
||||||
keyMd5Hex := strings.ToLower(hex.EncodeToString(keyMd5[:]))
|
|
||||||
signMd5 := md5.Sum([]byte(timestamp + keyMd5Hex))
|
|
||||||
signMd5Hex := strings.ToLower(hex.EncodeToString(signMd5[:]))
|
|
||||||
req.Header.Set("waf_request_time", timestamp)
|
|
||||||
req.Header.Set("waf_request_token", signMd5Hex)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
|
|
||||||
return &Client{
|
|
||||||
client: client,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) WithTimeout(timeout time.Duration) *Client {
|
|
||||||
c.client.SetTimeout(timeout)
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) WithTLSConfig(config *tls.Config) *Client {
|
|
||||||
c.client.SetTLSClientConfig(config)
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) sendRequest(path string, params interface{}) (*resty.Response, error) {
|
|
||||||
req := c.client.R().SetBody(params)
|
|
||||||
resp, err := req.Post(path)
|
|
||||||
if err != nil {
|
|
||||||
return resp, fmt.Errorf("baota api error: failed to send request: %w", err)
|
|
||||||
} else if resp.IsError() {
|
|
||||||
return resp, fmt.Errorf("baota api error: unexpected status code: %d, resp: %s", resp.StatusCode(), resp.String())
|
|
||||||
}
|
|
||||||
|
|
||||||
return resp, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) sendRequestWithResult(path string, params interface{}, result BaseResponse) error {
|
|
||||||
resp, err := c.sendRequest(path, params)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := json.Unmarshal(resp.Body(), &result); err != nil {
|
|
||||||
return fmt.Errorf("baota api error: failed to unmarshal response: %w", err)
|
|
||||||
} else if errcode := result.GetCode(); errcode != 0 {
|
|
||||||
return fmt.Errorf("baota api error: code='%d'", errcode)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
@ -1,67 +0,0 @@
|
|||||||
package btwaf
|
|
||||||
|
|
||||||
type BaseResponse interface {
|
|
||||||
GetCode() int32
|
|
||||||
}
|
|
||||||
|
|
||||||
type baseResponse struct {
|
|
||||||
Code *int32 `json:"code,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *baseResponse) GetCode() int32 {
|
|
||||||
if r.Code != nil {
|
|
||||||
return *r.Code
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
type GetSiteListRequest struct {
|
|
||||||
Page *int32 `json:"p,omitempty"`
|
|
||||||
PageSize *int32 `json:"p_size,omitempty"`
|
|
||||||
SiteName *string `json:"site_name,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type GetSiteListResponse struct {
|
|
||||||
baseResponse
|
|
||||||
Result *struct {
|
|
||||||
List []*struct {
|
|
||||||
SiteId string `json:"site_id"`
|
|
||||||
SiteName string `json:"site_name"`
|
|
||||||
Type string `json:"types"`
|
|
||||||
Status int32 `json:"status"`
|
|
||||||
CreateTime int64 `json:"create_time"`
|
|
||||||
UpdateTime int64 `json:"update_time"`
|
|
||||||
} `json:"list"`
|
|
||||||
Total int32 `json:"total"`
|
|
||||||
} `json:"res,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type SiteServerInfo struct {
|
|
||||||
ListenSSLPorts *[]int32 `json:"listen_ssl_port,omitempty"`
|
|
||||||
SSL *SiteServerSSLInfo `json:"ssl,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type SiteServerSSLInfo struct {
|
|
||||||
IsSSL *int32 `json:"is_ssl,omitempty"`
|
|
||||||
FullChain *string `json:"full_chain,omitempty"`
|
|
||||||
PrivateKey *string `json:"private_key,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type ModifySiteRequest struct {
|
|
||||||
SiteId string `json:"site_id"`
|
|
||||||
Type *string `json:"types,omitempty"`
|
|
||||||
Server *SiteServerInfo `json:"server,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type ModifySiteResponse struct {
|
|
||||||
baseResponse
|
|
||||||
}
|
|
||||||
|
|
||||||
type ConfigSetSSLRequest struct {
|
|
||||||
CertContent string `json:"certContent"`
|
|
||||||
KeyContent string `json:"keyContent"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type ConfigSetSSLResponse struct {
|
|
||||||
baseResponse
|
|
||||||
}
|
|
@ -1,16 +0,0 @@
|
|||||||
package bunny
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"net/url"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (c *Client) AddCustomCertificate(req *AddCustomCertificateRequest) ([]byte, error) {
|
|
||||||
if req.PullZoneId == "" {
|
|
||||||
return nil, fmt.Errorf("bunny api error: invalid parameter: PullZoneId")
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := c.sendRequest(http.MethodPost, fmt.Sprintf("/pullzone/%s/addCertificate", url.PathEscape(req.PullZoneId)), req)
|
|
||||||
return resp.Body(), err
|
|
||||||
}
|
|
@ -1,61 +0,0 @@
|
|||||||
package bunny
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/go-resty/resty/v2"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Client struct {
|
|
||||||
client *resty.Client
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewClient(apiToken string) *Client {
|
|
||||||
client := resty.New().
|
|
||||||
SetBaseURL("https://api.bunny.net").
|
|
||||||
SetHeader("User-Agent", "certimate").
|
|
||||||
SetHeader("AccessKey", apiToken)
|
|
||||||
|
|
||||||
return &Client{
|
|
||||||
client: client,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) WithTimeout(timeout time.Duration) *Client {
|
|
||||||
c.client.SetTimeout(timeout)
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) sendRequest(method string, path string, params interface{}) (*resty.Response, error) {
|
|
||||||
req := c.client.R()
|
|
||||||
if strings.EqualFold(method, http.MethodGet) {
|
|
||||||
qs := make(map[string]string)
|
|
||||||
if params != nil {
|
|
||||||
temp := make(map[string]any)
|
|
||||||
jsonb, _ := json.Marshal(params)
|
|
||||||
json.Unmarshal(jsonb, &temp)
|
|
||||||
for k, v := range temp {
|
|
||||||
if v != nil {
|
|
||||||
qs[k] = fmt.Sprintf("%v", v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
req = req.SetQueryParams(qs)
|
|
||||||
} else {
|
|
||||||
req = req.SetHeader("Content-Type", "application/json").SetBody(params)
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := req.Execute(method, path)
|
|
||||||
if err != nil {
|
|
||||||
return resp, fmt.Errorf("bunny api error: failed to send request: %w", err)
|
|
||||||
} else if resp.IsError() {
|
|
||||||
return resp, fmt.Errorf("bunny api error: unexpected status code: %d, resp: %s", resp.StatusCode(), resp.String())
|
|
||||||
}
|
|
||||||
|
|
||||||
return resp, nil
|
|
||||||
}
|
|
@ -1,8 +0,0 @@
|
|||||||
package bunny
|
|
||||||
|
|
||||||
type AddCustomCertificateRequest struct {
|
|
||||||
Hostname string `json:"Hostname"`
|
|
||||||
PullZoneId string `json:"-"`
|
|
||||||
Certificate string `json:"Certificate"`
|
|
||||||
CertificateKey string `json:"CertificateKey"`
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
package cachefly
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (c *Client) CreateCertificate(req *CreateCertificateRequest) (*CreateCertificateResponse, error) {
|
|
||||||
resp := &CreateCertificateResponse{}
|
|
||||||
err := c.sendRequestWithResult(http.MethodPost, "/certificates", req, resp)
|
|
||||||
return resp, err
|
|
||||||
}
|
|
@ -1,76 +0,0 @@
|
|||||||
package cachefly
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/go-resty/resty/v2"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Client struct {
|
|
||||||
client *resty.Client
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewClient(apiToken string) *Client {
|
|
||||||
client := resty.New().
|
|
||||||
SetBaseURL("https://api.cachefly.com/api/2.5").
|
|
||||||
SetHeader("X-CF-Authorization", "Bearer "+apiToken)
|
|
||||||
|
|
||||||
return &Client{
|
|
||||||
client: client,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) WithTimeout(timeout time.Duration) *Client {
|
|
||||||
c.client.SetTimeout(timeout)
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) sendRequest(method string, path string, params interface{}) (*resty.Response, error) {
|
|
||||||
req := c.client.R()
|
|
||||||
if strings.EqualFold(method, http.MethodGet) {
|
|
||||||
qs := make(map[string]string)
|
|
||||||
if params != nil {
|
|
||||||
temp := make(map[string]any)
|
|
||||||
jsonb, _ := json.Marshal(params)
|
|
||||||
json.Unmarshal(jsonb, &temp)
|
|
||||||
for k, v := range temp {
|
|
||||||
if v != nil {
|
|
||||||
qs[k] = fmt.Sprintf("%v", v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
req = req.SetQueryParams(qs)
|
|
||||||
} else {
|
|
||||||
req = req.SetHeader("Content-Type", "application/json").SetBody(params)
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := req.Execute(method, path)
|
|
||||||
if err != nil {
|
|
||||||
return resp, fmt.Errorf("cachefly api error: failed to send request: %w", err)
|
|
||||||
} else if resp.IsError() {
|
|
||||||
return resp, fmt.Errorf("cachefly api error: unexpected status code: %d, resp: %s", resp.StatusCode(), resp.String())
|
|
||||||
}
|
|
||||||
|
|
||||||
return resp, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) sendRequestWithResult(method string, path string, params interface{}, result BaseResponse) error {
|
|
||||||
resp, err := c.sendRequest(method, path, params)
|
|
||||||
if err != nil {
|
|
||||||
if resp != nil {
|
|
||||||
json.Unmarshal(resp.Body(), &result)
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := json.Unmarshal(resp.Body(), &result); err != nil {
|
|
||||||
return fmt.Errorf("cachefly api error: failed to unmarshal response: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
@ -1,38 +0,0 @@
|
|||||||
package cachefly
|
|
||||||
|
|
||||||
type BaseResponse interface {
|
|
||||||
GetMessage() string
|
|
||||||
}
|
|
||||||
|
|
||||||
type baseResponse struct {
|
|
||||||
Message *string `json:"message,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *baseResponse) GetMessage() string {
|
|
||||||
if r.Message != nil {
|
|
||||||
return *r.Message
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
type CreateCertificateRequest struct {
|
|
||||||
Certificate string `json:"certificate"`
|
|
||||||
CertificateKey string `json:"certificateKey"`
|
|
||||||
Password *string `json:"password"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type CreateCertificateResponse struct {
|
|
||||||
baseResponse
|
|
||||||
Id string `json:"_id"`
|
|
||||||
SubjectCommonName string `json:"subjectCommonName"`
|
|
||||||
SubjectNames []string `json:"subjectNames"`
|
|
||||||
Expired bool `json:"expired"`
|
|
||||||
Expiring bool `json:"expiring"`
|
|
||||||
InUse bool `json:"inUse"`
|
|
||||||
Managed bool `json:"managed"`
|
|
||||||
Services []string `json:"services"`
|
|
||||||
Domains []string `json:"domains"`
|
|
||||||
NotBefore string `json:"notBefore"`
|
|
||||||
NotAfter string `json:"notAfter"`
|
|
||||||
CreatedAt string `json:"createdAt"`
|
|
||||||
}
|
|
@ -1,43 +0,0 @@
|
|||||||
package cdnfly
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"net/url"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (c *Client) GetSite(req *GetSiteRequest) (*GetSiteResponse, error) {
|
|
||||||
if req.Id == "" {
|
|
||||||
return nil, fmt.Errorf("cdnfly api error: invalid parameter: Id")
|
|
||||||
}
|
|
||||||
|
|
||||||
resp := &GetSiteResponse{}
|
|
||||||
err := c.sendRequestWithResult(http.MethodGet, fmt.Sprintf("/v1/sites/%s", url.PathEscape(req.Id)), req, resp)
|
|
||||||
return resp, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) UpdateSite(req *UpdateSiteRequest) (*UpdateSiteResponse, error) {
|
|
||||||
if req.Id == "" {
|
|
||||||
return nil, fmt.Errorf("cdnfly api error: invalid parameter: Id")
|
|
||||||
}
|
|
||||||
|
|
||||||
resp := &UpdateSiteResponse{}
|
|
||||||
err := c.sendRequestWithResult(http.MethodPut, fmt.Sprintf("/v1/sites/%s", url.PathEscape(req.Id)), req, resp)
|
|
||||||
return resp, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) CreateCertificate(req *CreateCertificateRequest) (*CreateCertificateResponse, error) {
|
|
||||||
resp := &CreateCertificateResponse{}
|
|
||||||
err := c.sendRequestWithResult(http.MethodPost, "/v1/certs", req, resp)
|
|
||||||
return resp, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) UpdateCertificate(req *UpdateCertificateRequest) (*UpdateCertificateResponse, error) {
|
|
||||||
if req.Id == "" {
|
|
||||||
return nil, fmt.Errorf("cdnfly api error: invalid parameter: Id")
|
|
||||||
}
|
|
||||||
|
|
||||||
resp := &UpdateCertificateResponse{}
|
|
||||||
err := c.sendRequestWithResult(http.MethodPut, fmt.Sprintf("/v1/certs/%s", url.PathEscape(req.Id)), req, resp)
|
|
||||||
return resp, err
|
|
||||||
}
|
|
@ -1,86 +0,0 @@
|
|||||||
package cdnfly
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/tls"
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/go-resty/resty/v2"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Client struct {
|
|
||||||
client *resty.Client
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewClient(serverUrl, apiKey, apiSecret string) *Client {
|
|
||||||
client := resty.New().
|
|
||||||
SetBaseURL(strings.TrimRight(serverUrl, "/")).
|
|
||||||
SetHeader("User-Agent", "certimate").
|
|
||||||
SetHeader("API-Key", apiKey).
|
|
||||||
SetHeader("API-Secret", apiSecret)
|
|
||||||
|
|
||||||
return &Client{
|
|
||||||
client: client,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) WithTimeout(timeout time.Duration) *Client {
|
|
||||||
c.client.SetTimeout(timeout)
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) WithTLSConfig(config *tls.Config) *Client {
|
|
||||||
c.client.SetTLSClientConfig(config)
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) sendRequest(method string, path string, params interface{}) (*resty.Response, error) {
|
|
||||||
req := c.client.R()
|
|
||||||
if strings.EqualFold(method, http.MethodGet) {
|
|
||||||
qs := make(map[string]string)
|
|
||||||
if params != nil {
|
|
||||||
temp := make(map[string]any)
|
|
||||||
jsonb, _ := json.Marshal(params)
|
|
||||||
json.Unmarshal(jsonb, &temp)
|
|
||||||
for k, v := range temp {
|
|
||||||
if v != nil {
|
|
||||||
qs[k] = fmt.Sprintf("%v", v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
req = req.SetQueryParams(qs)
|
|
||||||
} else {
|
|
||||||
req = req.SetHeader("Content-Type", "application/json").SetBody(params)
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := req.Execute(method, path)
|
|
||||||
if err != nil {
|
|
||||||
return resp, fmt.Errorf("cdnfly api error: failed to send request: %w", err)
|
|
||||||
} else if resp.IsError() {
|
|
||||||
return resp, fmt.Errorf("cdnfly api error: unexpected status code: %d, resp: %s", resp.StatusCode(), resp.String())
|
|
||||||
}
|
|
||||||
|
|
||||||
return resp, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) sendRequestWithResult(method string, path string, params interface{}, result BaseResponse) error {
|
|
||||||
resp, err := c.sendRequest(method, path, params)
|
|
||||||
if err != nil {
|
|
||||||
if resp != nil {
|
|
||||||
json.Unmarshal(resp.Body(), &result)
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := json.Unmarshal(resp.Body(), &result); err != nil {
|
|
||||||
return fmt.Errorf("cdnfly api error: failed to unmarshal response: %w", err)
|
|
||||||
} else if errcode := result.GetCode(); errcode != "" && errcode != "0" {
|
|
||||||
return fmt.Errorf("cdnfly api error: code='%s', message='%s'", errcode, result.GetMessage())
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
@ -1,84 +0,0 @@
|
|||||||
package cdnfly
|
|
||||||
|
|
||||||
import "fmt"
|
|
||||||
|
|
||||||
type BaseResponse interface {
|
|
||||||
GetCode() string
|
|
||||||
GetMessage() string
|
|
||||||
}
|
|
||||||
|
|
||||||
type baseResponse struct {
|
|
||||||
Code any `json:"code"`
|
|
||||||
Message string `json:"msg"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *baseResponse) GetCode() string {
|
|
||||||
if r.Code == nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
if code, ok := r.Code.(int); ok {
|
|
||||||
return fmt.Sprintf("%d", code)
|
|
||||||
}
|
|
||||||
|
|
||||||
if code, ok := r.Code.(string); ok {
|
|
||||||
return code
|
|
||||||
}
|
|
||||||
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *baseResponse) GetMessage() string {
|
|
||||||
return r.Message
|
|
||||||
}
|
|
||||||
|
|
||||||
type GetSiteRequest struct {
|
|
||||||
Id string `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type GetSiteResponse struct {
|
|
||||||
baseResponse
|
|
||||||
Data *struct {
|
|
||||||
Id int64 `json:"id"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
Domain string `json:"domain"`
|
|
||||||
HttpsListen string `json:"https_listen"`
|
|
||||||
} `json:"data,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type UpdateSiteRequest struct {
|
|
||||||
Id string `json:"-"`
|
|
||||||
HttpsListen *string `json:"https_listen,omitempty"`
|
|
||||||
Enable *bool `json:"enable,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type UpdateSiteResponse struct {
|
|
||||||
baseResponse
|
|
||||||
}
|
|
||||||
|
|
||||||
type CreateCertificateRequest struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
Description *string `json:"des,omitempty"`
|
|
||||||
Type string `json:"type"`
|
|
||||||
Cert string `json:"cert"`
|
|
||||||
Key string `json:"key"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type CreateCertificateResponse struct {
|
|
||||||
baseResponse
|
|
||||||
Data string `json:"data"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type UpdateCertificateRequest struct {
|
|
||||||
Id string `json:"-"`
|
|
||||||
Name *string `json:"name,omitempty"`
|
|
||||||
Description *string `json:"des,omitempty"`
|
|
||||||
Type *string `json:"type,omitempty"`
|
|
||||||
Cert *string `json:"cert,omitempty"`
|
|
||||||
Key *string `json:"key,omitempty"`
|
|
||||||
Enable *bool `json:"enable,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type UpdateCertificateResponse struct {
|
|
||||||
baseResponse
|
|
||||||
}
|
|
@ -1,78 +0,0 @@
|
|||||||
package unicloud
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"regexp"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (c *Client) ensureServerlessJwtTokenExists() error {
|
|
||||||
c.serverlessJwtTokenMtx.Lock()
|
|
||||||
defer c.serverlessJwtTokenMtx.Unlock()
|
|
||||||
if c.serverlessJwtToken != "" && c.serverlessJwtTokenExp.After(time.Now()) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
params := &loginParams{
|
|
||||||
Password: c.password,
|
|
||||||
}
|
|
||||||
if regexp.MustCompile("^1\\d{10}$").MatchString(c.username) {
|
|
||||||
params.Mobile = c.username
|
|
||||||
} else if regexp.MustCompile("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$").MatchString(c.username) {
|
|
||||||
params.Email = c.username
|
|
||||||
} else {
|
|
||||||
params.Username = c.username
|
|
||||||
}
|
|
||||||
|
|
||||||
resp := &loginResponse{}
|
|
||||||
if err := c.invokeServerlessWithResult(
|
|
||||||
uniIdentityEndpoint, uniIdentityClientSecret, uniIdentityAppId, uniIdentitySpaceId,
|
|
||||||
"uni-id-co", "login", "", params, nil,
|
|
||||||
resp); err != nil {
|
|
||||||
return err
|
|
||||||
} else if resp.Data == nil || resp.Data.NewToken == nil || resp.Data.NewToken.Token == "" {
|
|
||||||
return fmt.Errorf("unicloud api error: received empty token")
|
|
||||||
}
|
|
||||||
|
|
||||||
c.serverlessJwtToken = resp.Data.NewToken.Token
|
|
||||||
c.serverlessJwtTokenExp = time.UnixMilli(resp.Data.NewToken.TokenExpired)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) ensureApiUserTokenExists() error {
|
|
||||||
if err := c.ensureServerlessJwtTokenExists(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
c.apiUserTokenMtx.Lock()
|
|
||||||
defer c.apiUserTokenMtx.Unlock()
|
|
||||||
if c.apiUserToken != "" {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
resp := &getUserTokenResponse{}
|
|
||||||
if err := c.invokeServerlessWithResult(
|
|
||||||
uniConsoleEndpoint, uniConsoleClientSecret, uniConsoleAppId, uniConsoleSpaceId,
|
|
||||||
"uni-cloud-kernel", "", "user/getUserToken", nil, map[string]any{"isLogin": true},
|
|
||||||
resp); err != nil {
|
|
||||||
return err
|
|
||||||
} else if resp.Data == nil || resp.Data.Data == nil || resp.Data.Data.Data == nil || resp.Data.Data.Data.Token == "" {
|
|
||||||
return fmt.Errorf("unicloud api error: received empty user token")
|
|
||||||
}
|
|
||||||
|
|
||||||
c.apiUserToken = resp.Data.Data.Data.Token
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) CreateDomainWithCert(req *CreateDomainWithCertRequest) (*CreateDomainWithCertResponse, error) {
|
|
||||||
if err := c.ensureApiUserTokenExists(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
resp := &CreateDomainWithCertResponse{}
|
|
||||||
err := c.sendRequestWithResult(http.MethodPost, "/host/create-domain-with-cert", req, resp)
|
|
||||||
return resp, err
|
|
||||||
}
|
|
@ -1,103 +0,0 @@
|
|||||||
package unicloud
|
|
||||||
|
|
||||||
type BaseResponse interface {
|
|
||||||
GetSuccess() bool
|
|
||||||
GetErrorCode() string
|
|
||||||
GetErrorMessage() string
|
|
||||||
|
|
||||||
GetReturnCode() int32
|
|
||||||
GetReturnDesc() string
|
|
||||||
}
|
|
||||||
|
|
||||||
type baseResponse struct {
|
|
||||||
Success *bool `json:"success,omitempty"`
|
|
||||||
Header *map[string]string `json:"header,omitempty"`
|
|
||||||
Error *struct {
|
|
||||||
Code string `json:"code"`
|
|
||||||
Message string `json:"message"`
|
|
||||||
} `json:"error,omitempty"`
|
|
||||||
|
|
||||||
ReturnCode *int32 `json:"ret,omitempty"`
|
|
||||||
ReturnDesc *string `json:"desc,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *baseResponse) GetReturnCode() int32 {
|
|
||||||
if r.ReturnCode != nil {
|
|
||||||
return *r.ReturnCode
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *baseResponse) GetReturnDesc() string {
|
|
||||||
if r.ReturnDesc != nil {
|
|
||||||
return *r.ReturnDesc
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *baseResponse) GetSuccess() bool {
|
|
||||||
if r.Success != nil {
|
|
||||||
return *r.Success
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *baseResponse) GetErrorCode() string {
|
|
||||||
if r.Error != nil {
|
|
||||||
return r.Error.Code
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *baseResponse) GetErrorMessage() string {
|
|
||||||
if r.Error != nil {
|
|
||||||
return r.Error.Message
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
type loginParams struct {
|
|
||||||
Email string `json:"email,omitempty"`
|
|
||||||
Mobile string `json:"mobile,omitempty"`
|
|
||||||
Username string `json:"username,omitempty"`
|
|
||||||
Password string `json:"password"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type loginResponse struct {
|
|
||||||
baseResponse
|
|
||||||
Data *struct {
|
|
||||||
Code int32 `json:"errCode"`
|
|
||||||
UID string `json:"uid"`
|
|
||||||
NewToken *struct {
|
|
||||||
Token string `json:"token"`
|
|
||||||
TokenExpired int64 `json:"tokenExpired"`
|
|
||||||
} `json:"newToken,omitempty"`
|
|
||||||
} `json:"data,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type getUserTokenResponse struct {
|
|
||||||
baseResponse
|
|
||||||
Data *struct {
|
|
||||||
Code int32 `json:"code"`
|
|
||||||
Data *struct {
|
|
||||||
Result int32 `json:"ret"`
|
|
||||||
Description string `json:"desc"`
|
|
||||||
Data *struct {
|
|
||||||
Email string `json:"email"`
|
|
||||||
Token string `json:"token"`
|
|
||||||
} `json:"data,omitempty"`
|
|
||||||
} `json:"data,omitempty"`
|
|
||||||
} `json:"data,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type CreateDomainWithCertRequest struct {
|
|
||||||
Provider string `json:"provider"`
|
|
||||||
SpaceId string `json:"spaceId"`
|
|
||||||
Domain string `json:"domain"`
|
|
||||||
Cert string `json:"cert"`
|
|
||||||
Key string `json:"key"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type CreateDomainWithCertResponse struct {
|
|
||||||
baseResponse
|
|
||||||
}
|
|
@ -1,41 +0,0 @@
|
|||||||
package dnsla
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"net/url"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (c *Client) ListDomains(req *ListDomainsRequest) (*ListDomainsResponse, error) {
|
|
||||||
resp := &ListDomainsResponse{}
|
|
||||||
err := c.sendRequestWithResult(http.MethodGet, "/domainList", req, resp)
|
|
||||||
return resp, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) ListRecords(req *ListRecordsRequest) (*ListRecordsResponse, error) {
|
|
||||||
resp := &ListRecordsResponse{}
|
|
||||||
err := c.sendRequestWithResult(http.MethodGet, "/recordList", req, resp)
|
|
||||||
return resp, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) CreateRecord(req *CreateRecordRequest) (*CreateRecordResponse, error) {
|
|
||||||
resp := &CreateRecordResponse{}
|
|
||||||
err := c.sendRequestWithResult(http.MethodPost, "/record", req, resp)
|
|
||||||
return resp, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) UpdateRecord(req *UpdateRecordRequest) (*UpdateRecordResponse, error) {
|
|
||||||
resp := &UpdateRecordResponse{}
|
|
||||||
err := c.sendRequestWithResult(http.MethodPut, "/record", req, resp)
|
|
||||||
return resp, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) DeleteRecord(req *DeleteRecordRequest) (*DeleteRecordResponse, error) {
|
|
||||||
if req.Id == "" {
|
|
||||||
return nil, fmt.Errorf("dnsla api error: invalid parameter: Id")
|
|
||||||
}
|
|
||||||
|
|
||||||
resp := &DeleteRecordResponse{}
|
|
||||||
err := c.sendRequestWithResult(http.MethodDelete, fmt.Sprintf("/record?id=%s", url.QueryEscape(req.Id)), req, resp)
|
|
||||||
return resp, err
|
|
||||||
}
|
|
@ -1,79 +0,0 @@
|
|||||||
package dnsla
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/go-resty/resty/v2"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Client struct {
|
|
||||||
client *resty.Client
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewClient(apiId, apiSecret string) *Client {
|
|
||||||
client := resty.New().
|
|
||||||
SetBaseURL("https://api.dns.la/api").
|
|
||||||
SetBasicAuth(apiId, apiSecret).
|
|
||||||
SetHeader("User-Agent", "certimate")
|
|
||||||
|
|
||||||
return &Client{
|
|
||||||
client: client,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) WithTimeout(timeout time.Duration) *Client {
|
|
||||||
c.client.SetTimeout(timeout)
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) sendRequest(method string, path string, params interface{}) (*resty.Response, error) {
|
|
||||||
req := c.client.R()
|
|
||||||
if strings.EqualFold(method, http.MethodGet) {
|
|
||||||
qs := make(map[string]string)
|
|
||||||
if params != nil {
|
|
||||||
temp := make(map[string]any)
|
|
||||||
jsonb, _ := json.Marshal(params)
|
|
||||||
json.Unmarshal(jsonb, &temp)
|
|
||||||
for k, v := range temp {
|
|
||||||
if v != nil {
|
|
||||||
qs[k] = fmt.Sprintf("%v", v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
req = req.SetQueryParams(qs)
|
|
||||||
} else {
|
|
||||||
req = req.SetHeader("Content-Type", "application/json").SetBody(params)
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := req.Execute(method, path)
|
|
||||||
if err != nil {
|
|
||||||
return resp, fmt.Errorf("dnsla api error: failed to send request: %w", err)
|
|
||||||
} else if resp.IsError() {
|
|
||||||
return resp, fmt.Errorf("dnsla api error: unexpected status code: %d, resp: %s", resp.StatusCode(), resp.String())
|
|
||||||
}
|
|
||||||
|
|
||||||
return resp, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) sendRequestWithResult(method string, path string, params interface{}, result BaseResponse) error {
|
|
||||||
resp, err := c.sendRequest(method, path, params)
|
|
||||||
if err != nil {
|
|
||||||
if resp != nil {
|
|
||||||
json.Unmarshal(resp.Body(), &result)
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := json.Unmarshal(resp.Body(), &result); err != nil {
|
|
||||||
return fmt.Errorf("dnsla api error: failed to unmarshal response: %w", err)
|
|
||||||
} else if errcode := result.GetCode(); errcode/100 != 2 {
|
|
||||||
return fmt.Errorf("dnsla api error: code='%d', message='%s'", errcode, result.GetMessage())
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
@ -1,131 +0,0 @@
|
|||||||
package dnsla
|
|
||||||
|
|
||||||
type BaseResponse interface {
|
|
||||||
GetCode() int32
|
|
||||||
GetMessage() string
|
|
||||||
}
|
|
||||||
|
|
||||||
type baseResponse struct {
|
|
||||||
Code *int32 `json:"code,omitempty"`
|
|
||||||
Message *string `json:"message,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *baseResponse) GetCode() int32 {
|
|
||||||
if r.Code != nil {
|
|
||||||
return *r.Code
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *baseResponse) GetMessage() string {
|
|
||||||
if r.Message != nil {
|
|
||||||
return *r.Message
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
type DomainInfo struct {
|
|
||||||
Id string `json:"id"`
|
|
||||||
GroupId string `json:"groupId"`
|
|
||||||
GroupName string `json:"groupName"`
|
|
||||||
Domain string `json:"domain"`
|
|
||||||
DisplayDomain string `json:"displayDomain"`
|
|
||||||
CreatedAt int64 `json:"createdAt"`
|
|
||||||
UpdatedAt int64 `json:"updatedAt"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type RecordInfo struct {
|
|
||||||
Id string `json:"id"`
|
|
||||||
DomainId string `json:"domainId"`
|
|
||||||
GroupId string `json:"groupId"`
|
|
||||||
GroupName string `json:"groupName"`
|
|
||||||
LineId string `json:"lineId"`
|
|
||||||
LineCode string `json:"lineCode"`
|
|
||||||
LineName string `json:"lineName"`
|
|
||||||
Type int32 `json:"type"`
|
|
||||||
Host string `json:"host"`
|
|
||||||
DisplayHost string `json:"displayHost"`
|
|
||||||
Data string `json:"data"`
|
|
||||||
DisplayData string `json:"displayData"`
|
|
||||||
Ttl int32 `json:"ttl"`
|
|
||||||
Weight int32 `json:"weight"`
|
|
||||||
Preference int32 `json:"preference"`
|
|
||||||
CreatedAt int64 `json:"createdAt"`
|
|
||||||
UpdatedAt int64 `json:"updatedAt"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type ListDomainsRequest struct {
|
|
||||||
PageIndex int32 `json:"pageIndex"`
|
|
||||||
PageSize int32 `json:"pageSize"`
|
|
||||||
GroupId *string `json:"groupId,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type ListDomainsResponse struct {
|
|
||||||
baseResponse
|
|
||||||
Data *struct {
|
|
||||||
Total int32 `json:"total"`
|
|
||||||
Results []*DomainInfo `json:"results"`
|
|
||||||
} `json:"data,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type ListRecordsRequest struct {
|
|
||||||
PageIndex int32 `json:"pageIndex"`
|
|
||||||
PageSize int32 `json:"pageSize"`
|
|
||||||
DomainId string `json:"domainId"`
|
|
||||||
GroupId *string `json:"groupId,omitempty"`
|
|
||||||
LineId *string `json:"lineId,omitempty"`
|
|
||||||
Type *int32 `json:"type,omitempty"`
|
|
||||||
Host *string `json:"host,omitempty"`
|
|
||||||
Data *string `json:"data,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type ListRecordsResponse struct {
|
|
||||||
baseResponse
|
|
||||||
Data *struct {
|
|
||||||
Total int32 `json:"total"`
|
|
||||||
Results []*RecordInfo `json:"results"`
|
|
||||||
} `json:"data,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type CreateRecordRequest struct {
|
|
||||||
DomainId string `json:"domainId"`
|
|
||||||
GroupId *string `json:"groupId,omitempty"`
|
|
||||||
LineId *string `json:"lineId,omitempty"`
|
|
||||||
Type int32 `json:"type"`
|
|
||||||
Host string `json:"host"`
|
|
||||||
Data string `json:"data"`
|
|
||||||
Ttl int32 `json:"ttl"`
|
|
||||||
Weight *int32 `json:"weight,omitempty"`
|
|
||||||
Preference *int32 `json:"preference,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type CreateRecordResponse struct {
|
|
||||||
baseResponse
|
|
||||||
Data *struct {
|
|
||||||
Id string `json:"id"`
|
|
||||||
} `json:"data,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type UpdateRecordRequest struct {
|
|
||||||
Id string `json:"id"`
|
|
||||||
GroupId *string `json:"groupId,omitempty"`
|
|
||||||
LineId *string `json:"lineId,omitempty"`
|
|
||||||
Type *int32 `json:"type,omitempty"`
|
|
||||||
Host *string `json:"host,omitempty"`
|
|
||||||
Data *string `json:"data,omitempty"`
|
|
||||||
Ttl *int32 `json:"ttl,omitempty"`
|
|
||||||
Weight *int32 `json:"weight,omitempty"`
|
|
||||||
Preference *int32 `json:"preference,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type UpdateRecordResponse struct {
|
|
||||||
baseResponse
|
|
||||||
}
|
|
||||||
|
|
||||||
type DeleteRecordRequest struct {
|
|
||||||
Id string `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type DeleteRecordResponse struct {
|
|
||||||
baseResponse
|
|
||||||
}
|
|
@ -1,183 +0,0 @@
|
|||||||
package dogecloud
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/hmac"
|
|
||||||
"crypto/sha1"
|
|
||||||
"encoding/hex"
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"net/http"
|
|
||||||
"net/url"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
const dogeHost = "https://api.dogecloud.com"
|
|
||||||
|
|
||||||
type Client struct {
|
|
||||||
accessKey string
|
|
||||||
secretKey string
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewClient(accessKey, secretKey string) *Client {
|
|
||||||
return &Client{accessKey: accessKey, secretKey: secretKey}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) UploadCdnCert(note, cert, private string) (*UploadCdnCertResponse, error) {
|
|
||||||
req := &UploadCdnCertRequest{
|
|
||||||
Note: note,
|
|
||||||
Certificate: cert,
|
|
||||||
PrivateKey: private,
|
|
||||||
}
|
|
||||||
|
|
||||||
reqBts, err := json.Marshal(req)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
reqMap := make(map[string]interface{})
|
|
||||||
err = json.Unmarshal(reqBts, &reqMap)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
respBts, err := c.sendReq(http.MethodPost, "cdn/cert/upload.json", reqMap, true)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
resp := &UploadCdnCertResponse{}
|
|
||||||
err = json.Unmarshal(respBts, resp)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if resp.Code != nil && *resp.Code != 0 && *resp.Code != 200 {
|
|
||||||
return nil, fmt.Errorf("dogecloud api error, code: %d, msg: %s", *resp.Code, *resp.Message)
|
|
||||||
}
|
|
||||||
|
|
||||||
return resp, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) BindCdnCertWithDomain(certId int64, domain string) (*BindCdnCertResponse, error) {
|
|
||||||
req := &BindCdnCertRequest{
|
|
||||||
CertId: certId,
|
|
||||||
Domain: &domain,
|
|
||||||
}
|
|
||||||
|
|
||||||
reqBts, err := json.Marshal(req)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
reqMap := make(map[string]interface{})
|
|
||||||
err = json.Unmarshal(reqBts, &reqMap)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
respBts, err := c.sendReq(http.MethodPost, "cdn/cert/bind.json", reqMap, true)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
resp := &BindCdnCertResponse{}
|
|
||||||
err = json.Unmarshal(respBts, resp)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if resp.Code != nil && *resp.Code != 0 && *resp.Code != 200 {
|
|
||||||
return nil, fmt.Errorf("dogecloud api error, code: %d, msg: %s", *resp.Code, *resp.Message)
|
|
||||||
}
|
|
||||||
|
|
||||||
return resp, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) BindCdnCertWithDomainId(certId int64, domainId int64) (*BindCdnCertResponse, error) {
|
|
||||||
req := &BindCdnCertRequest{
|
|
||||||
CertId: certId,
|
|
||||||
DomainId: &domainId,
|
|
||||||
}
|
|
||||||
|
|
||||||
reqBts, err := json.Marshal(req)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
reqMap := make(map[string]interface{})
|
|
||||||
err = json.Unmarshal(reqBts, &reqMap)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
respBts, err := c.sendReq(http.MethodPost, "cdn/cert/bind.json", reqMap, true)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
resp := &BindCdnCertResponse{}
|
|
||||||
err = json.Unmarshal(respBts, resp)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if resp.Code != nil && *resp.Code != 0 && *resp.Code != 200 {
|
|
||||||
return nil, fmt.Errorf("dogecloud api error, code: %d, msg: %s", *resp.Code, *resp.Message)
|
|
||||||
}
|
|
||||||
|
|
||||||
return resp, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// 调用多吉云的 API。
|
|
||||||
// https://docs.dogecloud.com/cdn/api-access-token?id=go
|
|
||||||
//
|
|
||||||
// 入参:
|
|
||||||
// - method:GET 或 POST
|
|
||||||
// - path:是调用的 API 接口地址,包含 URL 请求参数 QueryString,例如:/console/vfetch/add.json?url=xxx&a=1&b=2
|
|
||||||
// - data:POST 的数据,对象,例如 {a: 1, b: 2},传递此参数表示不是 GET 请求而是 POST 请求
|
|
||||||
// - jsonMode:数据 data 是否以 JSON 格式请求,默认为 false 则使用表单形式(a=1&b=2)
|
|
||||||
func (c *Client) sendReq(method string, path string, data map[string]interface{}, jsonMode bool) ([]byte, error) {
|
|
||||||
body := ""
|
|
||||||
mime := ""
|
|
||||||
if jsonMode {
|
|
||||||
_body, err := json.Marshal(data)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
body = string(_body)
|
|
||||||
mime = "application/json"
|
|
||||||
} else {
|
|
||||||
values := url.Values{}
|
|
||||||
for k, v := range data {
|
|
||||||
values.Set(k, v.(string))
|
|
||||||
}
|
|
||||||
body = values.Encode()
|
|
||||||
mime = "application/x-www-form-urlencoded"
|
|
||||||
}
|
|
||||||
|
|
||||||
path = strings.TrimPrefix(path, "/")
|
|
||||||
signStr := "/" + path + "\n" + body
|
|
||||||
hmacObj := hmac.New(sha1.New, []byte(c.secretKey))
|
|
||||||
hmacObj.Write([]byte(signStr))
|
|
||||||
sign := hex.EncodeToString(hmacObj.Sum(nil))
|
|
||||||
auth := fmt.Sprintf("TOKEN %s:%s", c.accessKey, sign)
|
|
||||||
|
|
||||||
req, err := http.NewRequest(method, fmt.Sprintf("%s/%s", dogeHost, path), strings.NewReader(body))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
req.Header.Set("Content-Type", mime)
|
|
||||||
req.Header.Set("Authorization", auth)
|
|
||||||
|
|
||||||
client := http.Client{}
|
|
||||||
resp, err := client.Do(req)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
bytes, err := io.ReadAll(resp.Body)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return bytes, nil
|
|
||||||
}
|
|
@ -1,31 +0,0 @@
|
|||||||
package dogecloud
|
|
||||||
|
|
||||||
type BaseResponse struct {
|
|
||||||
Code *int `json:"code,omitempty"`
|
|
||||||
Message *string `json:"msg,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type UploadCdnCertRequest struct {
|
|
||||||
Note string `json:"note"`
|
|
||||||
Certificate string `json:"cert"`
|
|
||||||
PrivateKey string `json:"private"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type UploadCdnCertResponseData struct {
|
|
||||||
Id int64 `json:"id"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type UploadCdnCertResponse struct {
|
|
||||||
BaseResponse
|
|
||||||
Data *UploadCdnCertResponseData `json:"data,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type BindCdnCertRequest struct {
|
|
||||||
CertId int64 `json:"id"`
|
|
||||||
DomainId *int64 `json:"did,omitempty"`
|
|
||||||
Domain *string `json:"domain,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type BindCdnCertResponse struct {
|
|
||||||
BaseResponse
|
|
||||||
}
|
|
@ -1,48 +0,0 @@
|
|||||||
package flexcdn
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (c *Client) ensureAccessTokenExists() error {
|
|
||||||
c.accessTokenMtx.Lock()
|
|
||||||
defer c.accessTokenMtx.Unlock()
|
|
||||||
if c.accessToken != "" && c.accessTokenExp.After(time.Now()) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
req := &getAPIAccessTokenRequest{
|
|
||||||
Type: c.apiRole,
|
|
||||||
AccessKeyId: c.accessKeyId,
|
|
||||||
AccessKey: c.accessKey,
|
|
||||||
}
|
|
||||||
res, err := c.sendRequest(http.MethodPost, "/APIAccessTokenService/getAPIAccessToken", req)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
resp := &getAPIAccessTokenResponse{}
|
|
||||||
if err := json.Unmarshal(res.Body(), &resp); err != nil {
|
|
||||||
return fmt.Errorf("flexcdn api error: failed to unmarshal response: %w", err)
|
|
||||||
} else if resp.GetCode() != 200 {
|
|
||||||
return fmt.Errorf("flexcdn get access token failed: code='%d', message='%s'", resp.GetCode(), resp.GetMessage())
|
|
||||||
}
|
|
||||||
|
|
||||||
c.accessToken = resp.Data.Token
|
|
||||||
c.accessTokenExp = time.Unix(resp.Data.ExpiresAt, 0)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) UpdateSSLCert(req *UpdateSSLCertRequest) (*UpdateSSLCertResponse, error) {
|
|
||||||
if err := c.ensureAccessTokenExists(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
resp := &UpdateSSLCertResponse{}
|
|
||||||
err := c.sendRequestWithResult(http.MethodPost, "/SSLCertService/updateSSLCert", req, resp)
|
|
||||||
return resp, err
|
|
||||||
}
|
|
@ -1,103 +0,0 @@
|
|||||||
package flexcdn
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/tls"
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"strings"
|
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/go-resty/resty/v2"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Client struct {
|
|
||||||
apiRole string
|
|
||||||
accessKeyId string
|
|
||||||
accessKey string
|
|
||||||
|
|
||||||
accessToken string
|
|
||||||
accessTokenExp time.Time
|
|
||||||
accessTokenMtx sync.Mutex
|
|
||||||
|
|
||||||
client *resty.Client
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewClient(serverUrl, apiRole, accessKeyId, accessKey string) *Client {
|
|
||||||
client := &Client{
|
|
||||||
apiRole: apiRole,
|
|
||||||
accessKeyId: accessKeyId,
|
|
||||||
accessKey: accessKey,
|
|
||||||
}
|
|
||||||
client.client = resty.New().
|
|
||||||
SetBaseURL(strings.TrimRight(serverUrl, "/")).
|
|
||||||
SetHeader("User-Agent", "certimate").
|
|
||||||
SetPreRequestHook(func(c *resty.Client, req *http.Request) error {
|
|
||||||
if client.accessToken != "" {
|
|
||||||
req.Header.Set("X-Cloud-Access-Token", client.accessToken)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
|
|
||||||
return client
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) WithTimeout(timeout time.Duration) *Client {
|
|
||||||
c.client.SetTimeout(timeout)
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) WithTLSConfig(config *tls.Config) *Client {
|
|
||||||
c.client.SetTLSClientConfig(config)
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) sendRequest(method string, path string, params interface{}) (*resty.Response, error) {
|
|
||||||
req := c.client.R()
|
|
||||||
if strings.EqualFold(method, http.MethodGet) {
|
|
||||||
qs := make(map[string]string)
|
|
||||||
if params != nil {
|
|
||||||
temp := make(map[string]any)
|
|
||||||
jsonb, _ := json.Marshal(params)
|
|
||||||
json.Unmarshal(jsonb, &temp)
|
|
||||||
for k, v := range temp {
|
|
||||||
if v != nil {
|
|
||||||
qs[k] = fmt.Sprintf("%v", v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
req = req.SetQueryParams(qs)
|
|
||||||
} else {
|
|
||||||
req = req.SetHeader("Content-Type", "application/json").SetBody(params)
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := req.Execute(method, path)
|
|
||||||
if err != nil {
|
|
||||||
return resp, fmt.Errorf("flexcdn api error: failed to send request: %w", err)
|
|
||||||
} else if resp.IsError() {
|
|
||||||
return resp, fmt.Errorf("flexcdn api error: unexpected status code: %d, resp: %s", resp.StatusCode(), resp.String())
|
|
||||||
}
|
|
||||||
|
|
||||||
return resp, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) sendRequestWithResult(method string, path string, params interface{}, result BaseResponse) error {
|
|
||||||
resp, err := c.sendRequest(method, path, params)
|
|
||||||
if err != nil {
|
|
||||||
if resp != nil {
|
|
||||||
json.Unmarshal(resp.Body(), &result)
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := json.Unmarshal(resp.Body(), &result); err != nil {
|
|
||||||
return fmt.Errorf("flexcdn api error: failed to unmarshal response: %w", err)
|
|
||||||
} else if errcode := result.GetCode(); errcode != 200 {
|
|
||||||
return fmt.Errorf("flexcdn api error: code='%d', message='%s'", errcode, result.GetMessage())
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
@ -1,52 +0,0 @@
|
|||||||
package flexcdn
|
|
||||||
|
|
||||||
type BaseResponse interface {
|
|
||||||
GetCode() int32
|
|
||||||
GetMessage() string
|
|
||||||
}
|
|
||||||
|
|
||||||
type baseResponse struct {
|
|
||||||
Code int32 `json:"code"`
|
|
||||||
Message string `json:"message"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *baseResponse) GetCode() int32 {
|
|
||||||
return r.Code
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *baseResponse) GetMessage() string {
|
|
||||||
return r.Message
|
|
||||||
}
|
|
||||||
|
|
||||||
type getAPIAccessTokenRequest struct {
|
|
||||||
Type string `json:"type"`
|
|
||||||
AccessKeyId string `json:"accessKeyId"`
|
|
||||||
AccessKey string `json:"accessKey"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type getAPIAccessTokenResponse struct {
|
|
||||||
baseResponse
|
|
||||||
Data *struct {
|
|
||||||
Token string `json:"token"`
|
|
||||||
ExpiresAt int64 `json:"expiresAt"`
|
|
||||||
} `json:"data,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type UpdateSSLCertRequest struct {
|
|
||||||
SSLCertId int64 `json:"sslCertId"`
|
|
||||||
IsOn bool `json:"isOn"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
Description string `json:"description"`
|
|
||||||
ServerName string `json:"serverName"`
|
|
||||||
IsCA bool `json:"isCA"`
|
|
||||||
CertData string `json:"certData"`
|
|
||||||
KeyData string `json:"keyData"`
|
|
||||||
TimeBeginAt int64 `json:"timeBeginAt"`
|
|
||||||
TimeEndAt int64 `json:"timeEndAt"`
|
|
||||||
DNSNames []string `json:"dnsNames"`
|
|
||||||
CommonNames []string `json:"commonNames"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type UpdateSSLCertResponse struct {
|
|
||||||
baseResponse
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
package gname
|
|
||||||
|
|
||||||
func (c *Client) AddDomainResolution(req *AddDomainResolutionRequest) (*AddDomainResolutionResponse, error) {
|
|
||||||
resp := &AddDomainResolutionResponse{}
|
|
||||||
err := c.sendRequestWithResult("/api/resolution/add", req, resp)
|
|
||||||
return resp, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) ModifyDomainResolution(req *ModifyDomainResolutionRequest) (*ModifyDomainResolutionResponse, error) {
|
|
||||||
resp := &ModifyDomainResolutionResponse{}
|
|
||||||
err := c.sendRequestWithResult("/api/resolution/edit", req, resp)
|
|
||||||
return resp, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) DeleteDomainResolution(req *DeleteDomainResolutionRequest) (*DeleteDomainResolutionResponse, error) {
|
|
||||||
resp := &DeleteDomainResolutionResponse{}
|
|
||||||
err := c.sendRequestWithResult("/api/resolution/delete", req, resp)
|
|
||||||
return resp, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) ListDomainResolution(req *ListDomainResolutionRequest) (*ListDomainResolutionResponse, error) {
|
|
||||||
resp := &ListDomainResolutionResponse{}
|
|
||||||
err := c.sendRequestWithResult("/api/resolution/list", req, resp)
|
|
||||||
return resp, err
|
|
||||||
}
|
|
@ -1,104 +0,0 @@
|
|||||||
package gname
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/md5"
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"net/url"
|
|
||||||
"sort"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/go-resty/resty/v2"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Client struct {
|
|
||||||
appId string
|
|
||||||
appKey string
|
|
||||||
|
|
||||||
client *resty.Client
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewClient(appId, appKey string) *Client {
|
|
||||||
client := resty.New().
|
|
||||||
SetBaseURL("http://api.gname.com").
|
|
||||||
SetHeader("Content-Type", "application/x-www-form-urlencoded").
|
|
||||||
SetHeader("User-Agent", "certimate")
|
|
||||||
|
|
||||||
return &Client{
|
|
||||||
appId: appId,
|
|
||||||
appKey: appKey,
|
|
||||||
client: client,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) WithTimeout(timeout time.Duration) *Client {
|
|
||||||
c.client.SetTimeout(timeout)
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) generateSignature(params map[string]string) string {
|
|
||||||
// Step 1: Sort parameters by ASCII order
|
|
||||||
var keys []string
|
|
||||||
for k := range params {
|
|
||||||
keys = append(keys, k)
|
|
||||||
}
|
|
||||||
sort.Strings(keys)
|
|
||||||
|
|
||||||
// Step 2: Create string A with URL-encoded values
|
|
||||||
var pairs []string
|
|
||||||
for _, k := range keys {
|
|
||||||
encodedValue := url.QueryEscape(params[k])
|
|
||||||
pairs = append(pairs, fmt.Sprintf("%s=%s", k, encodedValue))
|
|
||||||
}
|
|
||||||
stringA := strings.Join(pairs, "&")
|
|
||||||
|
|
||||||
// Step 3: Append appkey to create string B
|
|
||||||
stringB := stringA + c.appKey
|
|
||||||
|
|
||||||
// Step 4: Calculate MD5 and convert to uppercase
|
|
||||||
hash := md5.Sum([]byte(stringB))
|
|
||||||
return strings.ToUpper(fmt.Sprintf("%x", hash))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) sendRequest(path string, params interface{}) (*resty.Response, error) {
|
|
||||||
data := make(map[string]string)
|
|
||||||
if params != nil {
|
|
||||||
temp := make(map[string]any)
|
|
||||||
jsonb, _ := json.Marshal(params)
|
|
||||||
json.Unmarshal(jsonb, &temp)
|
|
||||||
for k, v := range temp {
|
|
||||||
if v != nil {
|
|
||||||
data[k] = fmt.Sprintf("%v", v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
data["appid"] = c.appId
|
|
||||||
data["gntime"] = fmt.Sprintf("%d", time.Now().Unix())
|
|
||||||
data["gntoken"] = c.generateSignature(data)
|
|
||||||
|
|
||||||
req := c.client.R().SetFormData(data)
|
|
||||||
resp, err := req.Post(path)
|
|
||||||
if err != nil {
|
|
||||||
return resp, fmt.Errorf("gname api error: failed to send request: %w", err)
|
|
||||||
} else if resp.IsError() {
|
|
||||||
return resp, fmt.Errorf("gname api error: unexpected status code: %d, resp: %s", resp.StatusCode(), resp.String())
|
|
||||||
}
|
|
||||||
|
|
||||||
return resp, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) sendRequestWithResult(path string, params interface{}, result BaseResponse) error {
|
|
||||||
resp, err := c.sendRequest(path, params)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := json.Unmarshal(resp.Body(), &result); err != nil {
|
|
||||||
return fmt.Errorf("gname api error: failed to unmarshal response: %w", err)
|
|
||||||
} else if errcode := result.GetCode(); errcode != 1 {
|
|
||||||
return fmt.Errorf("gname api error: code='%d', message='%s'", errcode, result.GetMessage())
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
@ -1,81 +0,0 @@
|
|||||||
package gname
|
|
||||||
|
|
||||||
import "encoding/json"
|
|
||||||
|
|
||||||
type BaseResponse interface {
|
|
||||||
GetCode() int32
|
|
||||||
GetMessage() string
|
|
||||||
}
|
|
||||||
|
|
||||||
type baseResponse struct {
|
|
||||||
Code int32 `json:"code"`
|
|
||||||
Message string `json:"msg"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *baseResponse) GetCode() int32 {
|
|
||||||
return r.Code
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *baseResponse) GetMessage() string {
|
|
||||||
return r.Message
|
|
||||||
}
|
|
||||||
|
|
||||||
type AddDomainResolutionRequest struct {
|
|
||||||
ZoneName string `json:"ym"`
|
|
||||||
RecordType string `json:"lx"`
|
|
||||||
RecordName string `json:"zj"`
|
|
||||||
RecordValue string `json:"jlz"`
|
|
||||||
MX int32 `json:"mx"`
|
|
||||||
TTL int32 `json:"ttl"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type AddDomainResolutionResponse struct {
|
|
||||||
baseResponse
|
|
||||||
Data json.Number `json:"data"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type ModifyDomainResolutionRequest struct {
|
|
||||||
ID int64 `json:"jxid"`
|
|
||||||
ZoneName string `json:"ym"`
|
|
||||||
RecordType string `json:"lx"`
|
|
||||||
RecordName string `json:"zj"`
|
|
||||||
RecordValue string `json:"jlz"`
|
|
||||||
MX int32 `json:"mx"`
|
|
||||||
TTL int32 `json:"ttl"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type ModifyDomainResolutionResponse struct {
|
|
||||||
baseResponse
|
|
||||||
}
|
|
||||||
|
|
||||||
type DeleteDomainResolutionRequest struct {
|
|
||||||
ZoneName string `json:"ym"`
|
|
||||||
RecordID int64 `json:"jxid"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type DeleteDomainResolutionResponse struct {
|
|
||||||
baseResponse
|
|
||||||
}
|
|
||||||
|
|
||||||
type ListDomainResolutionRequest struct {
|
|
||||||
ZoneName string `json:"ym"`
|
|
||||||
Page *int32 `json:"page,omitempty"`
|
|
||||||
PageSize *int32 `json:"limit,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type ListDomainResolutionResponse struct {
|
|
||||||
baseResponse
|
|
||||||
Count int32 `json:"count"`
|
|
||||||
Data []*ResolutionRecord `json:"data"`
|
|
||||||
Page int32 `json:"page"`
|
|
||||||
PageSize int32 `json:"pagesize"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type ResolutionRecord struct {
|
|
||||||
ID json.Number `json:"id"`
|
|
||||||
ZoneName string `json:"ym"`
|
|
||||||
RecordType string `json:"lx"`
|
|
||||||
RecordName string `json:"zjt"`
|
|
||||||
RecordValue string `json:"jxz"`
|
|
||||||
MX int32 `json:"mx"`
|
|
||||||
}
|
|
@ -1,48 +0,0 @@
|
|||||||
package goedge
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (c *Client) ensureAccessTokenExists() error {
|
|
||||||
c.accessTokenMtx.Lock()
|
|
||||||
defer c.accessTokenMtx.Unlock()
|
|
||||||
if c.accessToken != "" && c.accessTokenExp.After(time.Now()) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
req := &getAPIAccessTokenRequest{
|
|
||||||
Type: c.apiRole,
|
|
||||||
AccessKeyId: c.accessKeyId,
|
|
||||||
AccessKey: c.accessKey,
|
|
||||||
}
|
|
||||||
res, err := c.sendRequest(http.MethodPost, "/APIAccessTokenService/getAPIAccessToken", req)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
resp := &getAPIAccessTokenResponse{}
|
|
||||||
if err := json.Unmarshal(res.Body(), &resp); err != nil {
|
|
||||||
return fmt.Errorf("goedge api error: failed to unmarshal response: %w", err)
|
|
||||||
} else if resp.GetCode() != 200 {
|
|
||||||
return fmt.Errorf("goedge get access token failed: code='%d', message='%s'", resp.GetCode(), resp.GetMessage())
|
|
||||||
}
|
|
||||||
|
|
||||||
c.accessToken = resp.Data.Token
|
|
||||||
c.accessTokenExp = time.Unix(resp.Data.ExpiresAt, 0)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) UpdateSSLCert(req *UpdateSSLCertRequest) (*UpdateSSLCertResponse, error) {
|
|
||||||
if err := c.ensureAccessTokenExists(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
resp := &UpdateSSLCertResponse{}
|
|
||||||
err := c.sendRequestWithResult(http.MethodPost, "/SSLCertService/updateSSLCert", req, resp)
|
|
||||||
return resp, err
|
|
||||||
}
|
|
@ -1,103 +0,0 @@
|
|||||||
package goedge
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/tls"
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"strings"
|
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/go-resty/resty/v2"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Client struct {
|
|
||||||
apiRole string
|
|
||||||
accessKeyId string
|
|
||||||
accessKey string
|
|
||||||
|
|
||||||
accessToken string
|
|
||||||
accessTokenExp time.Time
|
|
||||||
accessTokenMtx sync.Mutex
|
|
||||||
|
|
||||||
client *resty.Client
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewClient(serverUrl, apiRole, accessKeyId, accessKey string) *Client {
|
|
||||||
client := &Client{
|
|
||||||
apiRole: apiRole,
|
|
||||||
accessKeyId: accessKeyId,
|
|
||||||
accessKey: accessKey,
|
|
||||||
}
|
|
||||||
client.client = resty.New().
|
|
||||||
SetBaseURL(strings.TrimRight(serverUrl, "/")).
|
|
||||||
SetHeader("User-Agent", "certimate").
|
|
||||||
SetPreRequestHook(func(c *resty.Client, req *http.Request) error {
|
|
||||||
if client.accessToken != "" {
|
|
||||||
req.Header.Set("X-Edge-Access-Token", client.accessToken)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
|
|
||||||
return client
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) WithTimeout(timeout time.Duration) *Client {
|
|
||||||
c.client.SetTimeout(timeout)
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) WithTLSConfig(config *tls.Config) *Client {
|
|
||||||
c.client.SetTLSClientConfig(config)
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) sendRequest(method string, path string, params interface{}) (*resty.Response, error) {
|
|
||||||
req := c.client.R()
|
|
||||||
if strings.EqualFold(method, http.MethodGet) {
|
|
||||||
qs := make(map[string]string)
|
|
||||||
if params != nil {
|
|
||||||
temp := make(map[string]any)
|
|
||||||
jsonb, _ := json.Marshal(params)
|
|
||||||
json.Unmarshal(jsonb, &temp)
|
|
||||||
for k, v := range temp {
|
|
||||||
if v != nil {
|
|
||||||
qs[k] = fmt.Sprintf("%v", v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
req = req.SetQueryParams(qs)
|
|
||||||
} else {
|
|
||||||
req = req.SetHeader("Content-Type", "application/json").SetBody(params)
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := req.Execute(method, path)
|
|
||||||
if err != nil {
|
|
||||||
return resp, fmt.Errorf("goedge api error: failed to send request: %w", err)
|
|
||||||
} else if resp.IsError() {
|
|
||||||
return resp, fmt.Errorf("goedge api error: unexpected status code: %d, resp: %s", resp.StatusCode(), resp.String())
|
|
||||||
}
|
|
||||||
|
|
||||||
return resp, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) sendRequestWithResult(method string, path string, params interface{}, result BaseResponse) error {
|
|
||||||
resp, err := c.sendRequest(method, path, params)
|
|
||||||
if err != nil {
|
|
||||||
if resp != nil {
|
|
||||||
json.Unmarshal(resp.Body(), &result)
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := json.Unmarshal(resp.Body(), &result); err != nil {
|
|
||||||
return fmt.Errorf("goedge api error: failed to unmarshal response: %w", err)
|
|
||||||
} else if errcode := result.GetCode(); errcode != 200 {
|
|
||||||
return fmt.Errorf("goedge api error: code='%d', message='%s'", errcode, result.GetMessage())
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
@ -1,52 +0,0 @@
|
|||||||
package goedge
|
|
||||||
|
|
||||||
type BaseResponse interface {
|
|
||||||
GetCode() int32
|
|
||||||
GetMessage() string
|
|
||||||
}
|
|
||||||
|
|
||||||
type baseResponse struct {
|
|
||||||
Code int32 `json:"code"`
|
|
||||||
Message string `json:"message"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *baseResponse) GetCode() int32 {
|
|
||||||
return r.Code
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *baseResponse) GetMessage() string {
|
|
||||||
return r.Message
|
|
||||||
}
|
|
||||||
|
|
||||||
type getAPIAccessTokenRequest struct {
|
|
||||||
Type string `json:"type"`
|
|
||||||
AccessKeyId string `json:"accessKeyId"`
|
|
||||||
AccessKey string `json:"accessKey"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type getAPIAccessTokenResponse struct {
|
|
||||||
baseResponse
|
|
||||||
Data *struct {
|
|
||||||
Token string `json:"token"`
|
|
||||||
ExpiresAt int64 `json:"expiresAt"`
|
|
||||||
} `json:"data,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type UpdateSSLCertRequest struct {
|
|
||||||
SSLCertId int64 `json:"sslCertId"`
|
|
||||||
IsOn bool `json:"isOn"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
Description string `json:"description"`
|
|
||||||
ServerName string `json:"serverName"`
|
|
||||||
IsCA bool `json:"isCA"`
|
|
||||||
CertData string `json:"certData"`
|
|
||||||
KeyData string `json:"keyData"`
|
|
||||||
TimeBeginAt int64 `json:"timeBeginAt"`
|
|
||||||
TimeEndAt int64 `json:"timeEndAt"`
|
|
||||||
DNSNames []string `json:"dnsNames"`
|
|
||||||
CommonNames []string `json:"commonNames"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type UpdateSSLCertResponse struct {
|
|
||||||
baseResponse
|
|
||||||
}
|
|
@ -1,50 +0,0 @@
|
|||||||
package client
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (c *Client) ensureAccessTokenExists() error {
|
|
||||||
c.accessTokenMtx.Lock()
|
|
||||||
defer c.accessTokenMtx.Unlock()
|
|
||||||
if c.accessToken != "" {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
req := &loginRequest{
|
|
||||||
Email: c.username,
|
|
||||||
Username: c.username,
|
|
||||||
Password: c.password,
|
|
||||||
}
|
|
||||||
res, err := c.sendRequest(http.MethodPost, "/login", req)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
resp := &loginResponse{}
|
|
||||||
if err := json.Unmarshal(res.Body(), &resp); err != nil {
|
|
||||||
return fmt.Errorf("lecdn api error: failed to unmarshal response: %w", err)
|
|
||||||
} else if resp.GetCode() != 200 {
|
|
||||||
return fmt.Errorf("lecdn get token failed: code='%d', message='%s'", resp.GetCode(), resp.GetMessage())
|
|
||||||
}
|
|
||||||
|
|
||||||
c.accessToken = resp.Data.Token
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) UpdateCertificate(certId int64, req *UpdateCertificateRequest) (*UpdateCertificateResponse, error) {
|
|
||||||
if certId == 0 {
|
|
||||||
return nil, fmt.Errorf("lecdn api error: invalid parameter: CertId")
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := c.ensureAccessTokenExists(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
resp := &UpdateCertificateResponse{}
|
|
||||||
err := c.sendRequestWithResult(http.MethodPut, fmt.Sprintf("/certificate/%d", certId), req, resp)
|
|
||||||
return resp, err
|
|
||||||
}
|
|
@ -1,100 +0,0 @@
|
|||||||
package client
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/tls"
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"strings"
|
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/go-resty/resty/v2"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Client struct {
|
|
||||||
username string
|
|
||||||
password string
|
|
||||||
|
|
||||||
accessToken string
|
|
||||||
accessTokenMtx sync.Mutex
|
|
||||||
|
|
||||||
client *resty.Client
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewClient(serverUrl, username, password string) *Client {
|
|
||||||
client := &Client{
|
|
||||||
username: username,
|
|
||||||
password: password,
|
|
||||||
}
|
|
||||||
client.client = resty.New().
|
|
||||||
SetBaseURL(strings.TrimRight(serverUrl, "/")+"/prod-api").
|
|
||||||
SetHeader("User-Agent", "certimate").
|
|
||||||
SetPreRequestHook(func(c *resty.Client, req *http.Request) error {
|
|
||||||
if client.accessToken != "" {
|
|
||||||
req.Header.Set("Authorization", "Bearer "+client.accessToken)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
|
|
||||||
return client
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) WithTimeout(timeout time.Duration) *Client {
|
|
||||||
c.client.SetTimeout(timeout)
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) WithTLSConfig(config *tls.Config) *Client {
|
|
||||||
c.client.SetTLSClientConfig(config)
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) sendRequest(method string, path string, params interface{}) (*resty.Response, error) {
|
|
||||||
req := c.client.R()
|
|
||||||
if strings.EqualFold(method, http.MethodGet) {
|
|
||||||
qs := make(map[string]string)
|
|
||||||
if params != nil {
|
|
||||||
temp := make(map[string]any)
|
|
||||||
jsonb, _ := json.Marshal(params)
|
|
||||||
json.Unmarshal(jsonb, &temp)
|
|
||||||
for k, v := range temp {
|
|
||||||
if v != nil {
|
|
||||||
qs[k] = fmt.Sprintf("%v", v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
req = req.SetQueryParams(qs)
|
|
||||||
} else {
|
|
||||||
req = req.SetHeader("Content-Type", "application/json").SetBody(params)
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := req.Execute(method, path)
|
|
||||||
if err != nil {
|
|
||||||
return resp, fmt.Errorf("lecdn api error: failed to send request: %w", err)
|
|
||||||
} else if resp.IsError() {
|
|
||||||
return resp, fmt.Errorf("lecdn api error: unexpected status code: %d, resp: %s", resp.StatusCode(), resp.String())
|
|
||||||
}
|
|
||||||
|
|
||||||
return resp, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) sendRequestWithResult(method string, path string, params interface{}, result BaseResponse) error {
|
|
||||||
resp, err := c.sendRequest(method, path, params)
|
|
||||||
if err != nil {
|
|
||||||
if resp != nil {
|
|
||||||
json.Unmarshal(resp.Body(), &result)
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := json.Unmarshal(resp.Body(), &result); err != nil {
|
|
||||||
return fmt.Errorf("lecdn api error: failed to unmarshal response: %w", err)
|
|
||||||
} else if errcode := result.GetCode(); errcode != 200 {
|
|
||||||
return fmt.Errorf("lecdn api error: code='%d', message='%s'", errcode, result.GetMessage())
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
@ -1,47 +0,0 @@
|
|||||||
package client
|
|
||||||
|
|
||||||
type BaseResponse interface {
|
|
||||||
GetCode() int32
|
|
||||||
GetMessage() string
|
|
||||||
}
|
|
||||||
|
|
||||||
type baseResponse struct {
|
|
||||||
Code int32 `json:"code"`
|
|
||||||
Message string `json:"msg"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *baseResponse) GetCode() int32 {
|
|
||||||
return r.Code
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *baseResponse) GetMessage() string {
|
|
||||||
return r.Message
|
|
||||||
}
|
|
||||||
|
|
||||||
type loginRequest struct {
|
|
||||||
Email string `json:"email"`
|
|
||||||
Username string `json:"username"`
|
|
||||||
Password string `json:"password"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type loginResponse struct {
|
|
||||||
baseResponse
|
|
||||||
Data *struct {
|
|
||||||
UserId int64 `json:"user_id"`
|
|
||||||
Username string `json:"username"`
|
|
||||||
Token string `json:"token"`
|
|
||||||
} `json:"data,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type UpdateCertificateRequest struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
Description string `json:"description"`
|
|
||||||
Type string `json:"type"`
|
|
||||||
SSLPEM string `json:"ssl_pem"`
|
|
||||||
SSLKey string `json:"ssl_key"`
|
|
||||||
AutoRenewal bool `json:"auto_renewal"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type UpdateCertificateResponse struct {
|
|
||||||
baseResponse
|
|
||||||
}
|
|
@ -1,49 +0,0 @@
|
|||||||
package master
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (c *Client) ensureAccessTokenExists() error {
|
|
||||||
c.accessTokenMtx.Lock()
|
|
||||||
defer c.accessTokenMtx.Unlock()
|
|
||||||
if c.accessToken != "" {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
req := &loginRequest{
|
|
||||||
Username: c.username,
|
|
||||||
Password: c.password,
|
|
||||||
}
|
|
||||||
res, err := c.sendRequest(http.MethodPost, "/auth/login", req)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
resp := &loginResponse{}
|
|
||||||
if err := json.Unmarshal(res.Body(), &resp); err != nil {
|
|
||||||
return fmt.Errorf("lecdn api error: failed to unmarshal response: %w", err)
|
|
||||||
} else if resp.GetCode() != 200 {
|
|
||||||
return fmt.Errorf("lecdn get token failed: code='%d', message='%s'", resp.GetCode(), resp.GetMessage())
|
|
||||||
}
|
|
||||||
|
|
||||||
c.accessToken = resp.Data.Token
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) UpdateCertificate(certId int64, req *UpdateCertificateRequest) (*UpdateCertificateResponse, error) {
|
|
||||||
if certId == 0 {
|
|
||||||
return nil, fmt.Errorf("lecdn api error: invalid parameter: CertId")
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := c.ensureAccessTokenExists(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
resp := &UpdateCertificateResponse{}
|
|
||||||
err := c.sendRequestWithResult(http.MethodPut, fmt.Sprintf("/certificate/%d", certId), req, resp)
|
|
||||||
return resp, err
|
|
||||||
}
|
|
@ -1,100 +0,0 @@
|
|||||||
package master
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/tls"
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"strings"
|
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/go-resty/resty/v2"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Client struct {
|
|
||||||
username string
|
|
||||||
password string
|
|
||||||
|
|
||||||
accessToken string
|
|
||||||
accessTokenMtx sync.Mutex
|
|
||||||
|
|
||||||
client *resty.Client
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewClient(serverUrl, username, password string) *Client {
|
|
||||||
client := &Client{
|
|
||||||
username: username,
|
|
||||||
password: password,
|
|
||||||
}
|
|
||||||
client.client = resty.New().
|
|
||||||
SetBaseURL(strings.TrimRight(serverUrl, "/")+"/prod-api").
|
|
||||||
SetHeader("User-Agent", "certimate").
|
|
||||||
SetPreRequestHook(func(c *resty.Client, req *http.Request) error {
|
|
||||||
if client.accessToken != "" {
|
|
||||||
req.Header.Set("Authorization", "Bearer "+client.accessToken)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
|
|
||||||
return client
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) WithTimeout(timeout time.Duration) *Client {
|
|
||||||
c.client.SetTimeout(timeout)
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) WithTLSConfig(config *tls.Config) *Client {
|
|
||||||
c.client.SetTLSClientConfig(config)
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) sendRequest(method string, path string, params interface{}) (*resty.Response, error) {
|
|
||||||
req := c.client.R()
|
|
||||||
if strings.EqualFold(method, http.MethodGet) {
|
|
||||||
qs := make(map[string]string)
|
|
||||||
if params != nil {
|
|
||||||
temp := make(map[string]any)
|
|
||||||
jsonb, _ := json.Marshal(params)
|
|
||||||
json.Unmarshal(jsonb, &temp)
|
|
||||||
for k, v := range temp {
|
|
||||||
if v != nil {
|
|
||||||
qs[k] = fmt.Sprintf("%v", v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
req = req.SetQueryParams(qs)
|
|
||||||
} else {
|
|
||||||
req = req.SetHeader("Content-Type", "application/json").SetBody(params)
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := req.Execute(method, path)
|
|
||||||
if err != nil {
|
|
||||||
return resp, fmt.Errorf("lecdn api error: failed to send request: %w", err)
|
|
||||||
} else if resp.IsError() {
|
|
||||||
return resp, fmt.Errorf("lecdn api error: unexpected status code: %d, resp: %s", resp.StatusCode(), resp.String())
|
|
||||||
}
|
|
||||||
|
|
||||||
return resp, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) sendRequestWithResult(method string, path string, params interface{}, result BaseResponse) error {
|
|
||||||
resp, err := c.sendRequest(method, path, params)
|
|
||||||
if err != nil {
|
|
||||||
if resp != nil {
|
|
||||||
json.Unmarshal(resp.Body(), &result)
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := json.Unmarshal(resp.Body(), &result); err != nil {
|
|
||||||
return fmt.Errorf("lecdn api error: failed to unmarshal response: %w", err)
|
|
||||||
} else if errcode := result.GetCode(); errcode != 200 {
|
|
||||||
return fmt.Errorf("lecdn api error: code='%d', message='%s'", errcode, result.GetMessage())
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user