diff --git a/.github/ISSUE_TEMPLATE/1-bug_report.yml b/.github/ISSUE_TEMPLATE/1-bug_report.yml new file mode 100644 index 00000000..9ae9301e --- /dev/null +++ b/.github/ISSUE_TEMPLATE/1-bug_report.yml @@ -0,0 +1,77 @@ +name: "🐞 Bug Report" +description: "报告缺陷来帮助我们完善。 / Create a report to help us improve." +title: "[Bug] 简要描述你发现的缺陷" +labels: + - bug +body: + - type: markdown + attributes: + value: | + ## Welcome! + + **在提交 Issue 之前,请确认以下事项**: + 1. 我**确认**已尝试过使用当前最新版本,并能复现问题。 + 2. 我**确认**已搜索过[已有的 Issues](https://github.com/usual2970/certimate/issues)(包括已关闭的),没有类似的问题。 + 3. 我**确认**已阅读过[文档](https://docs.certimate.me/),没有类似的问题。 + 4. 请**务必**按照模板规范详细描述问题,否则 Issue 将会被直接关闭。 + + **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. + 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. + 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. + + - type: input + attributes: + label: 软件版本 / Release Version + description: 请提供 Certimate 的具体版本。 / Please provide the specific version of Certimate. + placeholder: (e.g. v1.0.0) + validations: + required: true + + - type: textarea + attributes: + label: 缺陷描述 / Description + description: 请详细清晰地描述你发现的缺陷或故障,如果可能请上传截图。 / Describe the bug you found in detail and clearly, and upload screenshots if possible. + validations: + required: true + + - type: textarea + attributes: + label: 复现步骤 / Steps to reproduce + description: 请提供可复现的完整步骤。 / Please walk us through it step by step. + placeholder: | + 1. ... + 2. ... + 3. ... + ... + validations: + required: true + + - type: textarea + attributes: + label: 日志 / Logs + description: 在此处添加日志信息(如果有的话)。 / Add logs here if available. + value: |- +
+ + ```console + # 请在此粘贴日志 / Paste logs here + ``` + +
+ validations: + required: false + + - type: textarea + attributes: + label: 其他 / Miscellaneous + description: 在此处添加关于该 Issue 的任何其他信息。 / Add any other context about the issue here. + validations: + required: false + + - type: markdown + attributes: + value: | + 请保持每个 Issue 只包含一个缺陷报告。 + Please limit one report per issue. diff --git a/.github/ISSUE_TEMPLATE/2-feature_request.yml b/.github/ISSUE_TEMPLATE/2-feature_request.yml new file mode 100644 index 00000000..d16d76cb --- /dev/null +++ b/.github/ISSUE_TEMPLATE/2-feature_request.yml @@ -0,0 +1,56 @@ +name: "💡 Feature Request" +description: "提出新功能请求或改进意见。 / Suggest an idea for this project." +title: "[Feature] 简要描述你希望实现的功能" +labels: + - enhancement +body: + - type: markdown + attributes: + value: | + ## Welcome! + + **在提交 Issue 之前,请确认以下事项**: + 1. 我**确认**是基于当前最新大版本而提出的新功能请求或改进意见。 + 2. 我**确认**已搜索过[已有的 Issues](https://github.com/usual2970/certimate/issues)(包括已关闭的),没有类似的问题。 + 3. 我**确认**已阅读过[文档](https://docs.certimate.me/),没有类似的问题。 + 4. 请**务必**按照模板规范详细描述问题,否则 Issue 将会被直接关闭。 + + **Before you submit the issue, please make sure of the following checklist**: + 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. + 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. + + - type: textarea + attributes: + label: 功能描述 / Description + description: 请详细清晰地描述你希望添加的功能,如果可能请上传截图。 / Describe the feature you'd like to add in detail and clearly, and upload screenshots if possible. + validations: + required: true + + - type: textarea + attributes: + label: 请求动机 / Motivation + description: 为什么这个功能对项目有帮助? / Why is this feature helpful to the project? + validations: + required: true + + - type: textarea + attributes: + label: 其他 / Miscellaneous + description: 在此处添加关于该 Issue 的任何其他信息。 / Add any other context about the problem here. + validations: + required: false + + - type: checkboxes + attributes: + label: 贡献 / Contribution + options: + - label: 我乐意为此贡献代码! / I am interested in contributing to this feature! + required: false + + - type: markdown + attributes: + value: | + 请保持每个 Issue 只包含一个功能请求。 + Please limit one request per issue. diff --git a/.github/ISSUE_TEMPLATE/3-questions.yml b/.github/ISSUE_TEMPLATE/3-questions.yml new file mode 100644 index 00000000..fd847486 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/3-questions.yml @@ -0,0 +1,40 @@ +name: "❓ Questions" +description: "遇到了困难需要求助? / Have problem in use and need help?" +title: "[Feature] 简要描述你遇到的问题" +body: + - type: markdown + attributes: + value: | + ## Welcome! + + **在提交 Issue 之前,请确认以下事项**: + 1. 我**确认**正在使用的是当前最新版本。 + 2. 我**确认**已搜索过[已有的 Issues](https://github.com/usual2970/certimate/issues)(包括已关闭的),没有类似的问题。 + 3. 我**确认**已阅读过[文档](https://docs.certimate.me/),没有类似的问题。 + 4. 请**务必**按照模板规范详细描述问题,否则 Issue 将会被直接关闭。 + + **Before you submit the issue, please make sure of the following checklist**: + 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. + 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. + + - type: textarea + attributes: + label: 问题描述 / Description + description: 请详细清晰地描述你遇到的问题,如果可能请上传截图。 / Describe the problem you encountered in detail and clearly, and upload screenshots if possible. + validations: + required: true + + - type: textarea + attributes: + label: 其他 / Miscellaneous + description: 在此处添加关于该问题的任何其他信息。 / Add any other context about the problem here. + validations: + required: false + + - type: markdown + attributes: + value: | + 请保持每个 Issue 只包含一个问题求助。 + Please limit one question per issue. diff --git a/Dockerfile b/Dockerfile index 6968b448..d8b6a59c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,38 +1,28 @@ -FROM node:22-alpine3.19 AS front-builder - +FROM node:22-alpine3.19 AS webui-builder WORKDIR /app - COPY . /app/ - RUN \ cd /app/ui && \ npm install && \ npm run build -FROM golang:1.23-alpine AS builder +FROM golang:1.23-alpine AS builder WORKDIR /app RUN apk add --no-cache tzdata - COPY ../. /app/ - RUN rm -rf /app/ui/dist - -COPY --from=front-builder /app/ui/dist /app/ui/dist - +COPY --from=webui-builder /app/ui/dist /app/ui/dist RUN go build -o certimate FROM alpine:latest - WORKDIR /app RUN apk add --no-cache tzdata - COPY --from=builder /app/certimate . COPY --from=builder /usr/share/zoneinfo /usr/share/zoneinfo - -ENTRYPOINT ["./certimate", "serve", "--http", "0.0.0.0:8090"] \ No newline at end of file +ENTRYPOINT ["./certimate", "serve", "--http", "0.0.0.0:8090"] diff --git a/README.md b/README.md index dbad9bdb..0e32d29e 100644 --- a/README.md +++ b/README.md @@ -38,8 +38,8 @@ Certimate 旨在为用户提供一个安全、简便的 SSL 证书管理解决 - 灵活的工作流编排方式,证书从申请到部署完全自动化; - 支持单域名、多域名、泛域名证书,可选 RSA、ECC 签名算法; - 支持 PEM、PFX、JKS 等多种格式输出证书; -- 支持 20+ 域名托管商(如阿里云、腾讯云、Cloudflare 等,[点此查看](https://docs.certimate.me/docs/reference/providers#supported-dns-providers)完整提供商清单); -- 支持 60+ 部署目标(如 Kubernetes、CDN、WAF、负载均衡等,[点此查看](https://docs.certimate.me/docs/reference/providers#supported-host-providers)完整提供商清单); +- 支持 20+ 域名托管商(如阿里云、腾讯云、Cloudflare 等,[点此查看完整清单](https://docs.certimate.me/docs/reference/providers#supported-dns-providers)); +- 支持 70+ 部署目标(如 Kubernetes、CDN、WAF、负载均衡等,[点此查看完整清单](https://docs.certimate.me/docs/reference/providers#supported-host-providers)); - 支持邮件、钉钉、飞书、企业微信、Webhook 等多种通知渠道; - 支持 Let's Encrypt、ZeroSSL、Google Trust Services 等多种 ACME 证书颁发机构; - 更多特性等待探索。 @@ -71,7 +71,7 @@ Certimate 旨在为用户提供一个安全、简便的 SSL 证书管理解决 相关文章: -- [使用 CNAME 实现 DNS-01 challenge](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.2.0:第一个不向后兼容的大版本](https://docs.certimate.me/blog/v0.2.0) - [Why Certimate?](https://docs.certimate.me/blog/why-certimate) diff --git a/README_EN.md b/README_EN.md index 71472e08..55999bfc 100644 --- a/README_EN.md +++ b/README_EN.md @@ -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 various certificate formats such as PEM, PFX, JKS. - Supports more than 20+ 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 60+ deployment targets (e.g., Kubernetes, CDN, WAF, load balancers, etc. [Check out this link](https://docs.certimate.me/en/docs/reference/providers#supported-host-providers)); +- Supports more than 70+ deployment targets (e.g., Kubernetes, CDN, WAF, load balancers, etc. [Check out this link](https://docs.certimate.me/en/docs/reference/providers#supported-host-providers)); - Supports multiple notification channels including email, DingTalk, Feishu, WeCom, Webhook, and more; - Supports multiple ACME CAs including Let's Encrypt, ZeroSSL, Google Trust Services, and more; - More features waiting to be discovered. @@ -69,7 +69,7 @@ Please visit the documentation site [docs.certimate.me](https://docs.certimate.m Related articles: -- [使用 CNAME 实现 DNS-01 challenge](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.2.0:第一个不向后兼容的大版本](https://docs.certimate.me/blog/v0.2.0) - [Why Certimate?](https://docs.certimate.me/blog/why-certimate) diff --git a/go.mod b/go.mod index 190cc75c..7c8723af 100644 --- a/go.mod +++ b/go.mod @@ -99,13 +99,18 @@ require ( github.com/google/gnostic-models v0.6.9 // indirect github.com/google/go-cmp v0.6.0 // indirect github.com/google/gofuzz v1.2.0 // indirect + github.com/hashicorp/go-cleanhttp v0.5.2 // indirect + github.com/hashicorp/go-retryablehttp v0.7.7 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/kylelemons/godebug v1.1.0 // indirect github.com/leodido/go-urn v1.4.0 // indirect github.com/mailru/easyjson v0.9.0 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/namedotcom/go v0.0.0-20180403034216-08470befbe04 // indirect + github.com/nrdcg/desec v0.10.0 // indirect github.com/nrdcg/mailinabox v0.2.0 // indirect + github.com/nrdcg/porkbun v0.4.0 // indirect + github.com/peterhellberg/link v1.2.0 // indirect github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect github.com/qiniu/dyn v1.3.0 // indirect github.com/qiniu/x v1.10.5 // indirect diff --git a/go.sum b/go.sum index 8c79203b..98e8211f 100644 --- a/go.sum +++ b/go.sum @@ -494,6 +494,7 @@ github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOj github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-hclog v0.16.2/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= @@ -503,6 +504,8 @@ github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iP github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= +github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU= +github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk= github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= @@ -646,10 +649,14 @@ github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJm github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nikoksr/notify v1.3.0 h1:UxzfxzAYGQD9a5JYLBTVx0lFMxeHCke3rPCkfWdPgLs= github.com/nikoksr/notify v1.3.0/go.mod h1:Xor2hMmkvrCfkCKvXGbcrESez4brac2zQjhd6U2BbeM= +github.com/nrdcg/desec v0.10.0 h1:qrEDiqnsvNU9QE7lXIXi/tIHAfyaFXKxF2/8/52O8uM= +github.com/nrdcg/desec v0.10.0/go.mod h1:5+4vyhMRTs49V9CNoODF/HwT8Mwxv9DJ6j+7NekUnBs= github.com/nrdcg/mailinabox v0.2.0 h1:IKq8mfKiVwNW2hQii/ng1dJ4yYMMv3HAP3fMFIq2CFk= github.com/nrdcg/mailinabox v0.2.0/go.mod h1:0yxqeYOiGyxAu7Sb94eMxHPIOsPYXAjTeA9ZhePhGnc= github.com/nrdcg/namesilo v0.2.1 h1:kLjCjsufdW/IlC+iSfAqj0iQGgKjlbUUeDJio5Y6eMg= github.com/nrdcg/namesilo v0.2.1/go.mod h1:lwMvfQTyYq+BbjJd30ylEG4GPSS6PII0Tia4rRpRiyw= +github.com/nrdcg/porkbun v0.4.0 h1:rWweKlwo1PToQ3H+tEO9gPRW0wzzgmI/Ob3n2Guticw= +github.com/nrdcg/porkbun v0.4.0/go.mod h1:/QMskrHEIM0IhC/wY7iTCUgINsxdT2WcOphktJ9+Q54= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -675,6 +682,8 @@ github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144T github.com/pavlo-v-chernykh/keystore-go/v4 v4.5.0 h1:2nosf3P75OZv2/ZO/9Px5ZgZ5gbKrzA3joN1QMfOGMQ= github.com/pavlo-v-chernykh/keystore-go/v4 v4.5.0/go.mod h1:lAVhWwbNaveeJmxrxuSTxMgKpF6DjnuVpn6T8WiBwYQ= github.com/performancecopilot/speed/v4 v4.0.0/go.mod h1:qxrSyuDGrTOWfV+uKRFhfxw6h/4HXRGUiZiufxo49BM= +github.com/peterhellberg/link v1.2.0 h1:UA5pg3Gp/E0F2WdX7GERiNrPQrM1K6CVJUUWfHa4t6c= +github.com/peterhellberg/link v1.2.0/go.mod h1:gYfAh+oJgQu2SrZHg5hROVRQe1ICoK0/HHJTcE0edxc= github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= github.com/pierrec/lz4 v2.6.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= diff --git a/internal/applicant/applicant.go b/internal/applicant/applicant.go index ebe6208f..8cd8b6d0 100644 --- a/internal/applicant/applicant.go +++ b/internal/applicant/applicant.go @@ -73,12 +73,7 @@ func NewWithApplyNode(node *domain.WorkflowNode) (Applicant, error) { if access, err := accessRepo.GetById(context.Background(), nodeConfig.ProviderAccessId); err != nil { return nil, fmt.Errorf("failed to get access #%s record: %w", nodeConfig.ProviderAccessId, err) } else { - accessConfig, err := access.UnmarshalConfigToMap() - if err != nil { - return nil, fmt.Errorf("failed to unmarshal access config: %w", err) - } - - options.ProviderAccessConfig = accessConfig + options.ProviderAccessConfig = access.Config } certRepo := repository.NewCertificateRepository() diff --git a/internal/applicant/providers.go b/internal/applicant/providers.go index dcfc1dde..90e8a972 100644 --- a/internal/applicant/providers.go +++ b/internal/applicant/providers.go @@ -14,6 +14,7 @@ import ( pCloudflare "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/cloudflare" pClouDNS "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/cloudns" pCMCCCloud "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/cmcccloud" + pDeSEC "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/desec" pDNSLA "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/dnsla" pDynv6 "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/dynv6" pGcore "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/gcore" @@ -25,9 +26,12 @@ import ( pNameDotCom "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/namedotcom" pNameSilo "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/namesilo" pNS1 "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/ns1" + pPorkbun "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/porkbun" pPowerDNS "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/powerdns" pRainYun "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/rainyun" pTencentCloud "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/tencentcloud" + pTencentCloudEO "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/tencentcloud-eo" + pVercel "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/vercel" pVolcEngine "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/volcengine" pWestcn "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/westcn" "github.com/usual2970/certimate/internal/pkg/utils/maputil" @@ -171,6 +175,21 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { return applicant, err } + case domain.ApplyDNSProviderTypeDeSEC: + { + access := domain.AccessConfigForDeSEC{} + if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { + return nil, fmt.Errorf("failed to populate provider access config: %w", err) + } + + applicant, err := pDeSEC.NewChallengeProvider(&pDeSEC.ChallengeProviderConfig{ + Token: access.Token, + DnsPropagationTimeout: options.DnsPropagationTimeout, + DnsTTL: options.DnsTTL, + }) + return applicant, err + } + case domain.ApplyDNSProviderTypeDNSLA: { access := domain.AccessConfigForDNSLA{} @@ -276,7 +295,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { applicant, err := pJDCloud.NewChallengeProvider(&pJDCloud.ChallengeProviderConfig{ AccessKeyId: access.AccessKeyId, AccessKeySecret: access.AccessKeySecret, - RegionId: maputil.GetString(options.ProviderApplyConfig, "region_id"), + RegionId: maputil.GetString(options.ProviderApplyConfig, "regionId"), DnsPropagationTimeout: options.DnsPropagationTimeout, DnsTTL: options.DnsTTL, }) @@ -345,6 +364,22 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { return applicant, err } + case domain.ApplyDNSProviderTypePorkbun: + { + access := domain.AccessConfigForPorkbun{} + if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { + return nil, fmt.Errorf("failed to populate provider access config: %w", err) + } + + applicant, err := pPorkbun.NewChallengeProvider(&pPorkbun.ChallengeProviderConfig{ + ApiKey: access.ApiKey, + SecretApiKey: access.SecretApiKey, + DnsPropagationTimeout: options.DnsPropagationTimeout, + DnsTTL: options.DnsTTL, + }) + return applicant, err + } + case domain.ApplyDNSProviderTypePowerDNS: { access := domain.AccessConfigForPowerDNS{} @@ -376,16 +411,48 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { return applicant, err } - case domain.ApplyDNSProviderTypeTencentCloud, domain.ApplyDNSProviderTypeTencentCloudDNS: + case domain.ApplyDNSProviderTypeTencentCloud, domain.ApplyDNSProviderTypeTencentCloudDNS, domain.ApplyDNSProviderTypeTencentCloudEO: { access := domain.AccessConfigForTencentCloud{} if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { return nil, fmt.Errorf("failed to populate provider access config: %w", err) } - applicant, err := pTencentCloud.NewChallengeProvider(&pTencentCloud.ChallengeProviderConfig{ - SecretId: access.SecretId, - SecretKey: access.SecretKey, + switch options.Provider { + case domain.ApplyDNSProviderTypeTencentCloud, domain.ApplyDNSProviderTypeTencentCloudDNS: + applicant, err := pTencentCloud.NewChallengeProvider(&pTencentCloud.ChallengeProviderConfig{ + SecretId: access.SecretId, + SecretKey: access.SecretKey, + DnsPropagationTimeout: options.DnsPropagationTimeout, + DnsTTL: options.DnsTTL, + }) + return applicant, err + + case domain.ApplyDNSProviderTypeTencentCloudEO: + applicant, err := pTencentCloudEO.NewChallengeProvider(&pTencentCloudEO.ChallengeProviderConfig{ + SecretId: access.SecretId, + SecretKey: access.SecretKey, + ZoneId: maputil.GetString(options.ProviderApplyConfig, "zoneId"), + DnsPropagationTimeout: options.DnsPropagationTimeout, + DnsTTL: options.DnsTTL, + }) + return applicant, err + + default: + break + } + } + + case domain.ApplyDNSProviderTypeVercel: + { + access := domain.AccessConfigForVercel{} + if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { + return nil, fmt.Errorf("failed to populate provider access config: %w", err) + } + + applicant, err := pVercel.NewChallengeProvider(&pVercel.ChallengeProviderConfig{ + ApiAccessToken: access.ApiAccessToken, + TeamId: access.TeamId, DnsPropagationTimeout: options.DnsPropagationTimeout, DnsTTL: options.DnsTTL, }) diff --git a/internal/deployer/deployer.go b/internal/deployer/deployer.go index 36e92866..6efc001c 100644 --- a/internal/deployer/deployer.go +++ b/internal/deployer/deployer.go @@ -39,14 +39,9 @@ func NewWithDeployNode(node *domain.WorkflowNode, certdata struct { return nil, fmt.Errorf("failed to get access #%s record: %w", nodeConfig.ProviderAccessId, err) } - accessConfig, err := access.UnmarshalConfigToMap() - if err != nil { - return nil, fmt.Errorf("failed to unmarshal access config: %w", err) - } - deployer, err := createDeployer(&deployerOptions{ Provider: domain.DeployProviderType(nodeConfig.Provider), - ProviderAccessConfig: accessConfig, + ProviderAccessConfig: access.Config, ProviderDeployConfig: nodeConfig.ProviderConfig, }) if err != nil { diff --git a/internal/deployer/providers.go b/internal/deployer/providers.go index a83fb681..61d14613 100644 --- a/internal/deployer/providers.go +++ b/internal/deployer/providers.go @@ -24,7 +24,10 @@ import ( pAWSACM "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aws-acm" pAWSCloudFront "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aws-cloudfront" pAzureKeyVault "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/azure-keyvault" + pBaiduCloudAppBLB "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/baiducloud-appblb" + pBaiduCloudBLB "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/baiducloud-blb" pBaiduCloudCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/baiducloud-cdn" + pBaiduCloudCert "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/baiducloud-cert" pBaishanCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/baishan-cdn" pBaotaPanelConsole "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/baotapanel-console" pBaotaPanelSite "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/baotapanel-site" @@ -36,6 +39,7 @@ import ( pGcoreCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/gcore-cdn" pHuaweiCloudCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/huaweicloud-cdn" pHuaweiCloudELB "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/huaweicloud-elb" + pHuaweiCloudSCM "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/huaweicloud-scm" pHuaweiCloudWAF "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/huaweicloud-waf" pJDCloudALB "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/jdcloud-alb" pJDCloudCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/jdcloud-cdn" @@ -61,7 +65,9 @@ import ( pUCloudUCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/ucloud-ucdn" pUCloudUS3 "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/ucloud-us3" pUpyunCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/upyun-cdn" + pVolcEngineALB "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/volcengine-alb" pVolcEngineCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/volcengine-cdn" + pVolcEngineCertCenter "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/volcengine-certcenter" pVolcEngineCLB "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/volcengine-clb" pVolcEngineDCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/volcengine-dcdn" pVolcEngineImageX "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/volcengine-imagex" @@ -302,7 +308,7 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, error) { } } - case domain.DeployProviderTypeBaiduCloudCDN: + case domain.DeployProviderTypeBaiduCloudAppBLB, domain.DeployProviderTypeBaiduCloudBLB, domain.DeployProviderTypeBaiduCloudCDN, domain.DeployProviderTypeBaiduCloudCert: { access := domain.AccessConfigForBaiduCloud{} if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { @@ -310,6 +316,30 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, error) { } switch options.Provider { + case domain.DeployProviderTypeBaiduCloudAppBLB: + deployer, err := pBaiduCloudAppBLB.NewDeployer(&pBaiduCloudAppBLB.DeployerConfig{ + AccessKeyId: access.AccessKeyId, + SecretAccessKey: access.SecretAccessKey, + Region: maputil.GetString(options.ProviderDeployConfig, "region"), + ResourceType: pBaiduCloudAppBLB.ResourceType(maputil.GetString(options.ProviderDeployConfig, "resourceType")), + LoadbalancerId: maputil.GetString(options.ProviderDeployConfig, "loadbalancerId"), + ListenerPort: maputil.GetInt32(options.ProviderDeployConfig, "listenerPort"), + Domain: maputil.GetString(options.ProviderDeployConfig, "domain"), + }) + return deployer, err + + case domain.DeployProviderTypeBaiduCloudBLB: + deployer, err := pBaiduCloudBLB.NewDeployer(&pBaiduCloudBLB.DeployerConfig{ + AccessKeyId: access.AccessKeyId, + SecretAccessKey: access.SecretAccessKey, + Region: maputil.GetString(options.ProviderDeployConfig, "region"), + ResourceType: pBaiduCloudBLB.ResourceType(maputil.GetString(options.ProviderDeployConfig, "resourceType")), + LoadbalancerId: maputil.GetString(options.ProviderDeployConfig, "loadbalancerId"), + ListenerPort: maputil.GetInt32(options.ProviderDeployConfig, "listenerPort"), + Domain: maputil.GetString(options.ProviderDeployConfig, "domain"), + }) + return deployer, err + case domain.DeployProviderTypeBaiduCloudCDN: deployer, err := pBaiduCloudCDN.NewDeployer(&pBaiduCloudCDN.DeployerConfig{ AccessKeyId: access.AccessKeyId, @@ -318,6 +348,13 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, error) { }) return deployer, err + case domain.DeployProviderTypeBaiduCloudCert: + deployer, err := pBaiduCloudCert.NewDeployer(&pBaiduCloudCert.DeployerConfig{ + AccessKeyId: access.AccessKeyId, + SecretAccessKey: access.SecretAccessKey, + }) + return deployer, err + default: break } @@ -478,7 +515,7 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, error) { } } - case domain.DeployProviderTypeHuaweiCloudCDN, domain.DeployProviderTypeHuaweiCloudELB, domain.DeployProviderTypeHuaweiCloudWAF: + case domain.DeployProviderTypeHuaweiCloudCDN, domain.DeployProviderTypeHuaweiCloudELB, domain.DeployProviderTypeHuaweiCloudSCM, domain.DeployProviderTypeHuaweiCloudWAF: { access := domain.AccessConfigForHuaweiCloud{} if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { @@ -507,6 +544,13 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, error) { }) return deployer, err + case domain.DeployProviderTypeHuaweiCloudSCM: + deployer, err := pHuaweiCloudSCM.NewDeployer(&pHuaweiCloudSCM.DeployerConfig{ + AccessKeyId: access.AccessKeyId, + SecretAccessKey: access.SecretAccessKey, + }) + return deployer, err + case domain.DeployProviderTypeHuaweiCloudWAF: deployer, err := pHuaweiCloudWAF.NewDeployer(&pHuaweiCloudWAF.DeployerConfig{ AccessKeyId: access.AccessKeyId, @@ -848,7 +892,7 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, error) { } } - case domain.DeployProviderTypeVolcEngineCDN, domain.DeployProviderTypeVolcEngineCLB, domain.DeployProviderTypeVolcEngineDCDN, domain.DeployProviderTypeVolcEngineImageX, domain.DeployProviderTypeVolcEngineLive, domain.DeployProviderTypeVolcEngineTOS: + case domain.DeployProviderTypeVolcEngineALB, domain.DeployProviderTypeVolcEngineCDN, domain.DeployProviderTypeVolcEngineCertCenter, domain.DeployProviderTypeVolcEngineCLB, domain.DeployProviderTypeVolcEngineDCDN, domain.DeployProviderTypeVolcEngineImageX, domain.DeployProviderTypeVolcEngineLive, domain.DeployProviderTypeVolcEngineTOS: { access := domain.AccessConfigForVolcEngine{} if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { @@ -856,6 +900,18 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, error) { } switch options.Provider { + case domain.DeployProviderTypeVolcEngineALB: + deployer, err := pVolcEngineALB.NewDeployer(&pVolcEngineALB.DeployerConfig{ + AccessKeyId: access.AccessKeyId, + AccessKeySecret: access.SecretAccessKey, + Region: maputil.GetString(options.ProviderDeployConfig, "region"), + ResourceType: pVolcEngineALB.ResourceType(maputil.GetString(options.ProviderDeployConfig, "resourceType")), + LoadbalancerId: maputil.GetString(options.ProviderDeployConfig, "loadbalancerId"), + ListenerId: maputil.GetString(options.ProviderDeployConfig, "listenerId"), + Domain: maputil.GetString(options.ProviderDeployConfig, "domain"), + }) + return deployer, err + case domain.DeployProviderTypeVolcEngineCDN: deployer, err := pVolcEngineCDN.NewDeployer(&pVolcEngineCDN.DeployerConfig{ AccessKeyId: access.AccessKeyId, @@ -864,12 +920,21 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, error) { }) return deployer, err + case domain.DeployProviderTypeVolcEngineCertCenter: + deployer, err := pVolcEngineCertCenter.NewDeployer(&pVolcEngineCertCenter.DeployerConfig{ + AccessKeyId: access.AccessKeyId, + AccessKeySecret: access.SecretAccessKey, + Region: maputil.GetString(options.ProviderDeployConfig, "region"), + }) + return deployer, err + case domain.DeployProviderTypeVolcEngineCLB: deployer, err := pVolcEngineCLB.NewDeployer(&pVolcEngineCLB.DeployerConfig{ AccessKeyId: access.AccessKeyId, AccessKeySecret: access.SecretAccessKey, Region: maputil.GetString(options.ProviderDeployConfig, "region"), ResourceType: pVolcEngineCLB.ResourceType(maputil.GetString(options.ProviderDeployConfig, "resourceType")), + LoadbalancerId: maputil.GetString(options.ProviderDeployConfig, "loadbalancerId"), ListenerId: maputil.GetString(options.ProviderDeployConfig, "listenerId"), }) return deployer, err diff --git a/internal/domain/access.go b/internal/domain/access.go index f19a0871..dc796c83 100644 --- a/internal/domain/access.go +++ b/internal/domain/access.go @@ -1,7 +1,6 @@ package domain import ( - "encoding/json" "time" ) @@ -9,19 +8,10 @@ const CollectionNameAccess = "access" type Access struct { Meta - Name string `json:"name" db:"name"` - Provider string `json:"provider" db:"provider"` - Config string `json:"config" db:"config"` - DeletedAt *time.Time `json:"deleted" db:"deleted"` -} - -func (a *Access) UnmarshalConfigToMap() (map[string]any, error) { - config := make(map[string]any) - if err := json.Unmarshal([]byte(a.Config), &config); err != nil { - return nil, err - } - - return config, nil + Name string `json:"name" db:"name"` + Provider string `json:"provider" db:"provider"` + Config map[string]any `json:"config" db:"config"` + DeletedAt *time.Time `json:"deleted" db:"deleted"` } type AccessConfigFor1Panel struct { @@ -98,6 +88,10 @@ type AccessConfigForCMCCCloud struct { AccessKeySecret string `json:"accessKeySecret"` } +type AccessConfigForDeSEC struct { + Token string `json:"token"` +} + type AccessConfigForDNSLA struct { ApiId string `json:"apiId"` ApiSecret string `json:"apiSecret"` @@ -165,6 +159,11 @@ type AccessConfigForNS1 struct { ApiKey string `json:"apiKey"` } +type AccessConfigForPorkbun struct { + ApiKey string `json:"apiKey"` + SecretApiKey string `json:"secretApiKey"` +} + type AccessConfigForPowerDNS struct { ApiUrl string `json:"apiUrl"` ApiKey string `json:"apiKey"` @@ -210,6 +209,11 @@ type AccessConfigForUpyun struct { Password string `json:"password"` } +type AccessConfigForVercel struct { + ApiAccessToken string `json:"apiAccessToken"` + TeamId string `json:"teamId,omitempty"` +} + type AccessConfigForVolcEngine struct { AccessKeyId string `json:"accessKeyId"` SecretAccessKey string `json:"secretAccessKey"` diff --git a/internal/domain/provider.go b/internal/domain/provider.go index addb3c87..0e4bcce3 100644 --- a/internal/domain/provider.go +++ b/internal/domain/provider.go @@ -26,6 +26,7 @@ const ( AccessProviderTypeCMCCCloud = AccessProviderType("cmcccloud") AccessProviderTypeCTCCCloud = AccessProviderType("ctcccloud") // 联通云(预留) AccessProviderTypeCUCCCloud = AccessProviderType("cucccloud") // 天翼云(预留) + AccessProviderTypeDeSEC = AccessProviderType("desec") AccessProviderTypeDNSLA = AccessProviderType("dnsla") AccessProviderTypeDogeCloud = AccessProviderType("dogecloud") AccessProviderTypeDynv6 = AccessProviderType("dynv6") @@ -43,6 +44,7 @@ const ( AccessProviderTypeNameDotCom = AccessProviderType("namedotcom") AccessProviderTypeNameSilo = AccessProviderType("namesilo") AccessProviderTypeNS1 = AccessProviderType("ns1") + AccessProviderTypePorkbun = AccessProviderType("porkbun") AccessProviderTypePowerDNS = AccessProviderType("powerdns") AccessProviderTypeQiniu = AccessProviderType("qiniu") AccessProviderTypeQingCloud = AccessProviderType("qingcloud") // 青云(预留) @@ -52,6 +54,7 @@ const ( AccessProviderTypeTencentCloud = AccessProviderType("tencentcloud") AccessProviderTypeUCloud = AccessProviderType("ucloud") AccessProviderTypeUpyun = AccessProviderType("upyun") + AccessProviderTypeVercel = AccessProviderType("vercel") AccessProviderTypeVolcEngine = AccessProviderType("volcengine") AccessProviderTypeWebhook = AccessProviderType("webhook") AccessProviderTypeWestcn = AccessProviderType("westcn") @@ -79,6 +82,7 @@ const ( ApplyDNSProviderTypeCloudflare = ApplyDNSProviderType("cloudflare") ApplyDNSProviderTypeClouDNS = ApplyDNSProviderType("cloudns") ApplyDNSProviderTypeCMCCCloud = ApplyDNSProviderType("cmcccloud") + ApplyDNSProviderTypeDeSEC = ApplyDNSProviderType("desec") ApplyDNSProviderTypeDNSLA = ApplyDNSProviderType("dnsla") ApplyDNSProviderTypeDynv6 = ApplyDNSProviderType("dynv6") ApplyDNSProviderTypeGcore = ApplyDNSProviderType("gcore") @@ -92,10 +96,13 @@ const ( ApplyDNSProviderTypeNameDotCom = ApplyDNSProviderType("namedotcom") ApplyDNSProviderTypeNameSilo = ApplyDNSProviderType("namesilo") ApplyDNSProviderTypeNS1 = ApplyDNSProviderType("ns1") + ApplyDNSProviderTypePorkbun = ApplyDNSProviderType("porkbun") ApplyDNSProviderTypePowerDNS = ApplyDNSProviderType("powerdns") ApplyDNSProviderTypeRainYun = ApplyDNSProviderType("rainyun") ApplyDNSProviderTypeTencentCloud = ApplyDNSProviderType("tencentcloud") // 兼容旧值,等同于 [ApplyDNSProviderTypeTencentCloudDNS] ApplyDNSProviderTypeTencentCloudDNS = ApplyDNSProviderType("tencentcloud-dns") + ApplyDNSProviderTypeTencentCloudEO = ApplyDNSProviderType("tencentcloud-eo") + ApplyDNSProviderTypeVercel = ApplyDNSProviderType("vercel") ApplyDNSProviderTypeVolcEngine = ApplyDNSProviderType("volcengine") // 兼容旧值,等同于 [ApplyDNSProviderTypeVolcEngineDNS] ApplyDNSProviderTypeVolcEngineDNS = ApplyDNSProviderType("volcengine-dns") ApplyDNSProviderTypeWestcn = ApplyDNSProviderType("westcn") @@ -129,7 +136,10 @@ const ( DeployProviderTypeAWSACM = DeployProviderType("aws-acm") DeployProviderTypeAWSCloudFront = DeployProviderType("aws-cloudfront") DeployProviderTypeAzureKeyVault = DeployProviderType("azure-keyvault") + DeployProviderTypeBaiduCloudAppBLB = DeployProviderType("baiducloud-appblb") + DeployProviderTypeBaiduCloudBLB = DeployProviderType("baiducloud-blb") DeployProviderTypeBaiduCloudCDN = DeployProviderType("baiducloud-cdn") + DeployProviderTypeBaiduCloudCert = DeployProviderType("baiducloud-cert") DeployProviderTypeBaishanCDN = DeployProviderType("baishan-cdn") DeployProviderTypeBaotaPanelConsole = DeployProviderType("baotapanel-console") DeployProviderTypeBaotaPanelSite = DeployProviderType("baotapanel-site") @@ -141,6 +151,7 @@ const ( DeployProviderTypeGcoreCDN = DeployProviderType("gcore-cdn") DeployProviderTypeHuaweiCloudCDN = DeployProviderType("huaweicloud-cdn") DeployProviderTypeHuaweiCloudELB = DeployProviderType("huaweicloud-elb") + DeployProviderTypeHuaweiCloudSCM = DeployProviderType("huaweicloud-scm") DeployProviderTypeHuaweiCloudWAF = DeployProviderType("huaweicloud-waf") DeployProviderTypeJDCloudALB = DeployProviderType("jdcloud-alb") DeployProviderTypeJDCloudCDN = DeployProviderType("jdcloud-cdn") @@ -168,7 +179,9 @@ const ( DeployProviderTypeUCloudUS3 = DeployProviderType("ucloud-us3") DeployProviderTypeUpyunCDN = DeployProviderType("upyun-cdn") DeployProviderTypeUpyunFile = DeployProviderType("upyun-file") + DeployProviderTypeVolcEngineALB = DeployProviderType("volcengine-alb") DeployProviderTypeVolcEngineCDN = DeployProviderType("volcengine-cdn") + DeployProviderTypeVolcEngineCertCenter = DeployProviderType("volcengine-certcenter") DeployProviderTypeVolcEngineCLB = DeployProviderType("volcengine-clb") DeployProviderTypeVolcEngineDCDN = DeployProviderType("volcengine-dcdn") DeployProviderTypeVolcEngineImageX = DeployProviderType("volcengine-imagex") diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/baiducloud/internal/lego.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/baiducloud/internal/lego.go index 0d3f9c66..da157bd0 100644 --- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/baiducloud/internal/lego.go +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/baiducloud/internal/lego.go @@ -6,7 +6,7 @@ import ( "strings" "time" - bceDns "github.com/baidubce/bce-sdk-go/services/dns" + bcedns "github.com/baidubce/bce-sdk-go/services/dns" "github.com/go-acme/lego/v4/challenge" "github.com/go-acme/lego/v4/challenge/dns01" "github.com/go-acme/lego/v4/platform/config/env" @@ -38,7 +38,7 @@ type Config struct { } type DNSProvider struct { - client *bceDns.Client + client *bcedns.Client config *Config } @@ -69,7 +69,7 @@ func NewDNSProviderConfig(config *Config) (*DNSProvider, error) { return nil, errors.New("baiducloud: the configuration of the DNS provider is nil") } - client, err := bceDns.NewClient(config.AccessKeyID, config.SecretAccessKey, "") + client, err := bcedns.NewClient(config.AccessKeyID, config.SecretAccessKey, "") if err != nil { return nil, err } else { @@ -128,11 +128,11 @@ func (d *DNSProvider) Timeout() (timeout, interval time.Duration) { return d.config.PropagationTimeout, d.config.PollingInterval } -func (d *DNSProvider) getDNSRecord(zoneName, subDomain string) (*bceDns.Record, error) { +func (d *DNSProvider) getDNSRecord(zoneName, subDomain string) (*bcedns.Record, error) { pageMarker := "" pageSize := 1000 for { - request := &bceDns.ListRecordRequest{} + request := &bcedns.ListRecordRequest{} request.Rr = subDomain request.Marker = pageMarker request.MaxKeys = pageSize @@ -165,7 +165,7 @@ func (d *DNSProvider) addOrUpdateDNSRecord(zoneName, subDomain, value string) er } if record == nil { - request := &bceDns.CreateRecordRequest{ + request := &bcedns.CreateRecordRequest{ Type: "TXT", Rr: subDomain, Value: value, @@ -174,7 +174,7 @@ func (d *DNSProvider) addOrUpdateDNSRecord(zoneName, subDomain, value string) er err := d.client.CreateRecord(zoneName, request, d.generateClientToken()) return err } else { - request := &bceDns.UpdateRecordRequest{ + request := &bcedns.UpdateRecordRequest{ Type: "TXT", Rr: subDomain, Value: value, diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/cmcccloud/internal/lego.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/cmcccloud/internal/lego.go index 92ef6dfe..0329d18d 100644 --- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/cmcccloud/internal/lego.go +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/cmcccloud/internal/lego.go @@ -106,6 +106,7 @@ func (d *DNSProvider) Present(domain, token, keyAuth string) error { if err != nil { return err } + if record == nil { // add new record resp, err := d.client.CreateRecordOpenapi(&model.CreateRecordOpenapiRequest{ diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/desec/desec.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/desec/desec.go new file mode 100644 index 00000000..7a997117 --- /dev/null +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/desec/desec.go @@ -0,0 +1,36 @@ +package desec + +import ( + "time" + + "github.com/go-acme/lego/v4/challenge" + "github.com/go-acme/lego/v4/providers/dns/desec" +) + +type ChallengeProviderConfig struct { + Token string `json:"token"` + DnsPropagationTimeout int32 `json:"dnsPropagationTimeout,omitempty"` + DnsTTL int32 `json:"dnsTTL,omitempty"` +} + +func NewChallengeProvider(config *ChallengeProviderConfig) (challenge.Provider, error) { + if config == nil { + panic("config is nil") + } + + providerConfig := desec.NewDefaultConfig() + providerConfig.Token = config.Token + if config.DnsPropagationTimeout != 0 { + providerConfig.PropagationTimeout = time.Duration(config.DnsPropagationTimeout) * time.Second + } + if config.DnsTTL != 0 { + providerConfig.TTL = int(config.DnsTTL) + } + + provider, err := desec.NewDNSProviderConfig(providerConfig) + if err != nil { + return nil, err + } + + return provider, nil +} diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/gname/internal/lego.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/gname/internal/lego.go index 3d0f2e54..3c9b1b13 100644 --- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/gname/internal/lego.go +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/gname/internal/lego.go @@ -122,8 +122,8 @@ func (d *DNSProvider) Timeout() (timeout, interval time.Duration) { } func (d *DNSProvider) getDNSRecord(zoneName, subDomain string) (*gnamesdk.ResolutionRecord, error) { - page := 1 - pageSize := 20 + page := int32(1) + pageSize := int32(20) for { request := &gnamesdk.ListDomainResolutionRequest{} request.ZoneName = zoneName @@ -166,18 +166,19 @@ func (d *DNSProvider) addOrUpdateDNSRecord(zoneName, subDomain, value string) er RecordType: "TXT", RecordName: subDomain, RecordValue: value, - TTL: d.config.TTL, + TTL: int32(d.config.TTL), } _, err := d.client.AddDomainResolution(request) return err } else { + recordId, _ := record.ID.Int64() request := &gnamesdk.ModifyDomainResolutionRequest{ - ID: record.ID, + ID: recordId, ZoneName: zoneName, RecordType: "TXT", RecordName: subDomain, RecordValue: value, - TTL: d.config.TTL, + TTL: int32(d.config.TTL), } _, err := d.client.ModifyDomainResolution(request) return err @@ -194,9 +195,10 @@ func (d *DNSProvider) removeDNSRecord(zoneName, subDomain string) error { return nil } + recordId, _ := record.ID.Int64() request := &gnamesdk.DeleteDomainResolutionRequest{ ZoneName: zoneName, - RecordID: record.ID, + RecordID: recordId, } _, err = d.client.DeleteDomainResolution(request) return err diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/jdcloud/internal/lego.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/jdcloud/internal/lego.go index 68d81f7e..d5b5277b 100644 --- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/jdcloud/internal/lego.go +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/jdcloud/internal/lego.go @@ -8,10 +8,10 @@ import ( "github.com/go-acme/lego/v4/challenge" "github.com/go-acme/lego/v4/challenge/dns01" "github.com/go-acme/lego/v4/platform/config/env" - jdCore "github.com/jdcloud-api/jdcloud-sdk-go/core" - jdDnsApi "github.com/jdcloud-api/jdcloud-sdk-go/services/domainservice/apis" - jdDnsClient "github.com/jdcloud-api/jdcloud-sdk-go/services/domainservice/client" - jdDnsModel "github.com/jdcloud-api/jdcloud-sdk-go/services/domainservice/models" + jdcore "github.com/jdcloud-api/jdcloud-sdk-go/core" + jddnsapi "github.com/jdcloud-api/jdcloud-sdk-go/services/domainservice/apis" + jddnsclient "github.com/jdcloud-api/jdcloud-sdk-go/services/domainservice/client" + jddnsmodel "github.com/jdcloud-api/jdcloud-sdk-go/services/domainservice/models" ) const ( @@ -41,7 +41,7 @@ type Config struct { } type DNSProvider struct { - client *jdDnsClient.DomainserviceClient + client *jddnsclient.DomainserviceClient config *Config } @@ -73,12 +73,12 @@ func NewDNSProviderConfig(config *Config) (*DNSProvider, error) { return nil, errors.New("jdcloud: the configuration of the DNS provider is nil") } - clientCredentials := jdCore.NewCredentials(config.AccessKeyID, config.AccessKeySecret) - client := jdDnsClient.NewDomainserviceClient(clientCredentials) + clientCredentials := jdcore.NewCredentials(config.AccessKeyID, config.AccessKeySecret) + client := jddnsclient.NewDomainserviceClient(clientCredentials) clientConfig := &client.Config clientConfig.SetTimeout(config.HTTPTimeout) client.SetConfig(clientConfig) - client.SetLogger(jdCore.NewDefaultLogger(jdCore.LogWarn)) + client.SetLogger(jdcore.NewDefaultLogger(jdcore.LogWarn)) return &DNSProvider{ client: client, @@ -130,11 +130,11 @@ func (d *DNSProvider) Timeout() (timeout, interval time.Duration) { return d.config.PropagationTimeout, d.config.PollingInterval } -func (d *DNSProvider) getDNSZone(zoneName string) (*jdDnsModel.DomainInfo, error) { +func (d *DNSProvider) getDNSZone(zoneName string) (*jddnsmodel.DomainInfo, error) { pageNumber := 1 pageSize := 10 for { - request := jdDnsApi.NewDescribeDomainsRequest(d.config.RegionId, pageNumber, pageSize) + request := jddnsapi.NewDescribeDomainsRequest(d.config.RegionId, pageNumber, pageSize) request.SetDomainName(zoneName) response, err := d.client.DescribeDomains(request) @@ -158,7 +158,7 @@ func (d *DNSProvider) getDNSZone(zoneName string) (*jdDnsModel.DomainInfo, error return nil, fmt.Errorf("jdcloud: zone %s not found", zoneName) } -func (d *DNSProvider) getDNSZoneAndRecord(zoneName, subDomain string) (*jdDnsModel.DomainInfo, *jdDnsModel.RRInfo, error) { +func (d *DNSProvider) getDNSZoneAndRecord(zoneName, subDomain string) (*jddnsmodel.DomainInfo, *jddnsmodel.RRInfo, error) { zone, err := d.getDNSZone(zoneName) if err != nil { return nil, nil, err @@ -167,7 +167,7 @@ func (d *DNSProvider) getDNSZoneAndRecord(zoneName, subDomain string) (*jdDnsMod pageNumber := 1 pageSize := 10 for { - request := jdDnsApi.NewDescribeResourceRecordRequest(d.config.RegionId, fmt.Sprintf("%d", zone.Id)) + request := jddnsapi.NewDescribeResourceRecordRequest(d.config.RegionId, fmt.Sprintf("%d", zone.Id)) request.SetSearch(subDomain) request.SetPageNumber(pageNumber) request.SetPageSize(pageSize) @@ -200,7 +200,7 @@ func (d *DNSProvider) addOrUpdateDNSRecord(zoneName, subDomain, value string) er } if record == nil { - request := jdDnsApi.NewCreateResourceRecordRequest(d.config.RegionId, fmt.Sprintf("%d", zone.Id), &jdDnsModel.AddRR{ + request := jddnsapi.NewCreateResourceRecordRequest(d.config.RegionId, fmt.Sprintf("%d", zone.Id), &jddnsmodel.AddRR{ Type: "TXT", HostRecord: subDomain, HostValue: value, @@ -210,7 +210,7 @@ func (d *DNSProvider) addOrUpdateDNSRecord(zoneName, subDomain, value string) er _, err := d.client.CreateResourceRecord(request) return err } else { - request := jdDnsApi.NewModifyResourceRecordRequest(d.config.RegionId, fmt.Sprintf("%d", zone.Id), fmt.Sprintf("%d", record.Id), &jdDnsModel.UpdateRR{ + request := jddnsapi.NewModifyResourceRecordRequest(d.config.RegionId, fmt.Sprintf("%d", zone.Id), fmt.Sprintf("%d", record.Id), &jddnsmodel.UpdateRR{ Type: "TXT", HostRecord: subDomain, HostValue: value, @@ -231,7 +231,7 @@ func (d *DNSProvider) removeDNSRecord(zoneName, subDomain string) error { if record == nil { return nil } else { - request := jdDnsApi.NewDeleteResourceRecordRequest(d.config.RegionId, fmt.Sprintf("%d", zone.Id), fmt.Sprintf("%d", record.Id)) + request := jddnsapi.NewDeleteResourceRecordRequest(d.config.RegionId, fmt.Sprintf("%d", zone.Id), fmt.Sprintf("%d", record.Id)) _, err = d.client.DeleteResourceRecord(request) return err } diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/porkbun/porkbun.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/porkbun/porkbun.go new file mode 100644 index 00000000..ba60a791 --- /dev/null +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/porkbun/porkbun.go @@ -0,0 +1,38 @@ +package porkbun + +import ( + "time" + + "github.com/go-acme/lego/v4/challenge" + "github.com/go-acme/lego/v4/providers/dns/porkbun" +) + +type ChallengeProviderConfig struct { + ApiKey string `json:"apiKey"` + SecretApiKey string `json:"secretApiKey"` + DnsPropagationTimeout int32 `json:"dnsPropagationTimeout,omitempty"` + DnsTTL int32 `json:"dnsTTL,omitempty"` +} + +func NewChallengeProvider(config *ChallengeProviderConfig) (challenge.Provider, error) { + if config == nil { + panic("config is nil") + } + + providerConfig := porkbun.NewDefaultConfig() + providerConfig.APIKey = config.ApiKey + providerConfig.SecretAPIKey = config.SecretApiKey + if config.DnsPropagationTimeout != 0 { + providerConfig.PropagationTimeout = time.Duration(config.DnsPropagationTimeout) * time.Second + } + if config.DnsTTL != 0 { + providerConfig.TTL = int(config.DnsTTL) + } + + provider, err := porkbun.NewDNSProviderConfig(providerConfig) + if err != nil { + return nil, err + } + + return provider, nil +} diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/powerdns/powerdns.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/powerdns/powerdns.go index 3dc86d66..e5275efe 100644 --- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/powerdns/powerdns.go +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/powerdns/powerdns.go @@ -1,4 +1,4 @@ -package namesilo +package powerdns import ( "net/url" diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/tencentcloud-eo/internal/lego.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/tencentcloud-eo/internal/lego.go new file mode 100644 index 00000000..57f74193 --- /dev/null +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/tencentcloud-eo/internal/lego.go @@ -0,0 +1,207 @@ +package lego_tencentcloudeo + +import ( + "errors" + "fmt" + "math" + "strings" + "time" + + "github.com/go-acme/lego/v4/challenge" + "github.com/go-acme/lego/v4/challenge/dns01" + "github.com/go-acme/lego/v4/platform/config/env" + "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common" + "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile" + teo "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/teo/v20220901" +) + +const ( + envNamespace = "TENCENTCLOUDEO_" + + EnvSecretID = envNamespace + "SECRET_ID" + EnvSecretKey = envNamespace + "SECRET_KEY" + EnvZoneId = envNamespace + "ZONE_ID" + + EnvTTL = envNamespace + "TTL" + EnvPropagationTimeout = envNamespace + "PROPAGATION_TIMEOUT" + EnvPollingInterval = envNamespace + "POLLING_INTERVAL" + EnvHTTPTimeout = envNamespace + "HTTP_TIMEOUT" +) + +var _ challenge.ProviderTimeout = (*DNSProvider)(nil) + +type Config struct { + SecretID string + SecretKey string + ZoneId string + + PropagationTimeout time.Duration + PollingInterval time.Duration + TTL int32 + HTTPTimeout time.Duration +} + +type DNSProvider struct { + client *teo.Client + config *Config +} + +func NewDefaultConfig() *Config { + return &Config{ + TTL: int32(env.GetOrDefaultInt(EnvTTL, 300)), + PropagationTimeout: env.GetOrDefaultSecond(EnvPropagationTimeout, 2*time.Minute), + PollingInterval: env.GetOrDefaultSecond(EnvPollingInterval, dns01.DefaultPollingInterval), + HTTPTimeout: env.GetOrDefaultSecond(EnvHTTPTimeout, 30*time.Second), + } +} + +func NewDNSProvider() (*DNSProvider, error) { + values, err := env.Get(EnvSecretID, EnvSecretKey, EnvZoneId) + if err != nil { + return nil, fmt.Errorf("tencentcloud-eo: %w", err) + } + + config := NewDefaultConfig() + config.SecretID = values[EnvSecretID] + config.SecretKey = values[EnvSecretKey] + config.ZoneId = values[EnvSecretKey] + + return NewDNSProviderConfig(config) +} + +func NewDNSProviderConfig(config *Config) (*DNSProvider, error) { + if config == nil { + return nil, errors.New("tencentcloud-eo: the configuration of the DNS provider is nil") + } + + credential := common.NewCredential(config.SecretID, config.SecretKey) + cpf := profile.NewClientProfile() + cpf.HttpProfile.ReqTimeout = int(math.Round(config.HTTPTimeout.Seconds())) + client, err := teo.NewClient(credential, "", cpf) + if err != nil { + return nil, err + } + + return &DNSProvider{ + client: client, + config: config, + }, nil +} + +func (d *DNSProvider) Present(domain, token, keyAuth string) error { + info := dns01.GetChallengeInfo(domain, keyAuth) + + if err := d.addOrUpdateDNSRecord(strings.TrimRight(info.EffectiveFQDN, "."), info.Value); err != nil { + return fmt.Errorf("tencentcloud-eo: %w", err) + } + + return nil +} + +func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error { + info := dns01.GetChallengeInfo(domain, keyAuth) + + if err := d.removeDNSRecord(strings.TrimRight(info.EffectiveFQDN, ".")); err != nil { + return fmt.Errorf("tencentcloud-eo: %w", err) + } + + return nil +} + +func (d *DNSProvider) Timeout() (timeout, interval time.Duration) { + return d.config.PropagationTimeout, d.config.PollingInterval +} + +func (d *DNSProvider) getDNSRecord(effectiveFQDN string) (*teo.DnsRecord, error) { + pageOffset := 0 + pageLimit := 1000 + for { + request := teo.NewDescribeDnsRecordsRequest() + request.ZoneId = common.StringPtr(d.config.ZoneId) + request.Offset = common.Int64Ptr(int64(pageOffset)) + request.Limit = common.Int64Ptr(int64(pageLimit)) + request.Filters = []*teo.AdvancedFilter{ + { + Name: common.StringPtr("type"), + Values: []*string{common.StringPtr("TXT")}, + }, + } + + response, err := d.client.DescribeDnsRecords(request) + if err != nil { + return nil, err + } + + if response.Response == nil { + break + } else { + for _, record := range response.Response.DnsRecords { + if *record.Name == effectiveFQDN { + return record, nil + } + } + + if len(response.Response.DnsRecords) < int(pageLimit) { + break + } + + pageOffset += len(response.Response.DnsRecords) + } + } + + return nil, nil +} + +func (d *DNSProvider) addOrUpdateDNSRecord(effectiveFQDN, value string) error { + record, err := d.getDNSRecord(effectiveFQDN) + if err != nil { + return err + } + + if record == nil { + request := teo.NewCreateDnsRecordRequest() + request.ZoneId = common.StringPtr(d.config.ZoneId) + request.Name = common.StringPtr(effectiveFQDN) + request.Type = common.StringPtr("TXT") + request.Content = common.StringPtr(value) + request.TTL = common.Int64Ptr(int64(d.config.TTL)) + _, err := d.client.CreateDnsRecord(request) + return err + } else { + record.Content = common.StringPtr(value) + request := teo.NewModifyDnsRecordsRequest() + request.ZoneId = common.StringPtr(d.config.ZoneId) + request.DnsRecords = []*teo.DnsRecord{record} + if _, err := d.client.ModifyDnsRecords(request); err != nil { + return err + } + + if *record.Status == "disable" { + request := teo.NewModifyDnsRecordsStatusRequest() + request.ZoneId = common.StringPtr(d.config.ZoneId) + request.RecordsToEnable = []*string{record.RecordId} + if _, err = d.client.ModifyDnsRecordsStatus(request); err != nil { + return err + } + } + + return nil + } +} + +func (d *DNSProvider) removeDNSRecord(effectiveFQDN string) error { + record, err := d.getDNSRecord(effectiveFQDN) + if err != nil { + return err + } + + if record == nil { + return nil + } else { + request := teo.NewDeleteDnsRecordsRequest() + request.ZoneId = common.StringPtr(d.config.ZoneId) + request.RecordIds = []*string{record.RecordId} + _, err = d.client.DeleteDnsRecords(request) + return err + } +} diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/tencentcloud-eo/tencentcloud_eo.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/tencentcloud-eo/tencentcloud_eo.go new file mode 100644 index 00000000..33552ecf --- /dev/null +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/tencentcloud-eo/tencentcloud_eo.go @@ -0,0 +1,41 @@ +package tencentcloudeo + +import ( + "time" + + "github.com/go-acme/lego/v4/challenge" + + internal "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/tencentcloud-eo/internal" +) + +type ChallengeProviderConfig struct { + SecretId string `json:"secretId"` + SecretKey string `json:"secretKey"` + ZoneId string `json:"zoneId"` + DnsPropagationTimeout int32 `json:"dnsPropagationTimeout,omitempty"` + DnsTTL int32 `json:"dnsTTL,omitempty"` +} + +func NewChallengeProvider(config *ChallengeProviderConfig) (challenge.Provider, error) { + if config == nil { + panic("config is nil") + } + + providerConfig := internal.NewDefaultConfig() + providerConfig.SecretID = config.SecretId + providerConfig.SecretKey = config.SecretKey + providerConfig.ZoneId = config.ZoneId + if config.DnsPropagationTimeout != 0 { + providerConfig.PropagationTimeout = time.Duration(config.DnsPropagationTimeout) * time.Second + } + if config.DnsTTL != 0 { + providerConfig.TTL = config.DnsTTL + } + + provider, err := internal.NewDNSProviderConfig(providerConfig) + if err != nil { + return nil, err + } + + return provider, nil +} diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/vercel/vercel.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/vercel/vercel.go new file mode 100644 index 00000000..35fb5f02 --- /dev/null +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/vercel/vercel.go @@ -0,0 +1,38 @@ +package vercel + +import ( + "time" + + "github.com/go-acme/lego/v4/challenge" + "github.com/go-acme/lego/v4/providers/dns/vercel" +) + +type ChallengeProviderConfig struct { + ApiAccessToken string `json:"apiAccessToken"` + TeamId string `json:"teamId,omitempty"` + DnsPropagationTimeout int32 `json:"dnsPropagationTimeout,omitempty"` + DnsTTL int32 `json:"dnsTTL,omitempty"` +} + +func NewChallengeProvider(config *ChallengeProviderConfig) (challenge.Provider, error) { + if config == nil { + panic("config is nil") + } + + providerConfig := vercel.NewDefaultConfig() + providerConfig.AuthToken = config.ApiAccessToken + providerConfig.TeamID = config.TeamId + if config.DnsPropagationTimeout != 0 { + providerConfig.PropagationTimeout = time.Duration(config.DnsPropagationTimeout) * time.Second + } + if config.DnsTTL != 0 { + providerConfig.TTL = int(config.DnsTTL) + } + + provider, err := vercel.NewDNSProviderConfig(providerConfig) + if err != nil { + return nil, err + } + + return provider, nil +} diff --git a/internal/pkg/core/deployer/providers/aliyun-alb/aliyun_alb.go b/internal/pkg/core/deployer/providers/aliyun-alb/aliyun_alb.go index ae088602..a019917a 100644 --- a/internal/pkg/core/deployer/providers/aliyun-alb/aliyun_alb.go +++ b/internal/pkg/core/deployer/providers/aliyun-alb/aliyun_alb.go @@ -9,9 +9,9 @@ import ( "strings" "time" - aliyunAlb "github.com/alibabacloud-go/alb-20200616/v2/client" - aliyunCas "github.com/alibabacloud-go/cas-20200407/v3/client" - aliyunOpen "github.com/alibabacloud-go/darabonba-openapi/v2/client" + alialb "github.com/alibabacloud-go/alb-20200616/v2/client" + alicas "github.com/alibabacloud-go/cas-20200407/v3/client" + aliopen "github.com/alibabacloud-go/darabonba-openapi/v2/client" "github.com/alibabacloud-go/tea/tea" xerrors "github.com/pkg/errors" "golang.org/x/exp/slices" @@ -51,8 +51,8 @@ type DeployerProvider struct { var _ deployer.Deployer = (*DeployerProvider)(nil) type wSdkClients struct { - alb *aliyunAlb.Client - cas *aliyunCas.Client + ALB *alialb.Client + CAS *alicas.Client } func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { @@ -123,10 +123,10 @@ func (d *DeployerProvider) deployToLoadbalancer(ctx context.Context, cloudCertId // 查询负载均衡实例的详细信息 // REF: https://help.aliyun.com/zh/slb/application-load-balancer/developer-reference/api-alb-2020-06-16-getloadbalancerattribute - getLoadBalancerAttributeReq := &aliyunAlb.GetLoadBalancerAttributeRequest{ + getLoadBalancerAttributeReq := &alialb.GetLoadBalancerAttributeRequest{ LoadBalancerId: tea.String(d.config.LoadbalancerId), } - getLoadBalancerAttributeResp, err := d.sdkClients.alb.GetLoadBalancerAttribute(getLoadBalancerAttributeReq) + getLoadBalancerAttributeResp, err := d.sdkClients.ALB.GetLoadBalancerAttribute(getLoadBalancerAttributeReq) d.logger.Debug("sdk request 'alb.GetLoadBalancerAttribute'", slog.Any("request", getLoadBalancerAttributeReq), slog.Any("response", getLoadBalancerAttributeResp)) if err != nil { return xerrors.Wrap(err, "failed to execute sdk request 'alb.GetLoadBalancerAttribute'") @@ -138,13 +138,13 @@ func (d *DeployerProvider) deployToLoadbalancer(ctx context.Context, cloudCertId listListenersLimit := int32(100) var listListenersToken *string = nil for { - listListenersReq := &aliyunAlb.ListListenersRequest{ + listListenersReq := &alialb.ListListenersRequest{ MaxResults: tea.Int32(listListenersLimit), NextToken: listListenersToken, LoadBalancerIds: []*string{tea.String(d.config.LoadbalancerId)}, ListenerProtocol: tea.String("HTTPS"), } - listListenersResp, err := d.sdkClients.alb.ListListeners(listListenersReq) + listListenersResp, err := d.sdkClients.ALB.ListListeners(listListenersReq) d.logger.Debug("sdk request 'alb.ListListeners'", slog.Any("request", listListenersReq), slog.Any("response", listListenersResp)) if err != nil { return xerrors.Wrap(err, "failed to execute sdk request 'alb.ListListeners'") @@ -167,13 +167,13 @@ func (d *DeployerProvider) deployToLoadbalancer(ctx context.Context, cloudCertId // REF: https://help.aliyun.com/zh/slb/application-load-balancer/developer-reference/api-alb-2020-06-16-listlisteners listListenersToken = nil for { - listListenersReq := &aliyunAlb.ListListenersRequest{ + listListenersReq := &alialb.ListListenersRequest{ MaxResults: tea.Int32(listListenersLimit), NextToken: listListenersToken, LoadBalancerIds: []*string{tea.String(d.config.LoadbalancerId)}, ListenerProtocol: tea.String("QUIC"), } - listListenersResp, err := d.sdkClients.alb.ListListeners(listListenersReq) + listListenersResp, err := d.sdkClients.ALB.ListListeners(listListenersReq) d.logger.Debug("sdk request 'alb.ListListeners'", slog.Any("request", listListenersReq), slog.Any("response", listListenersResp)) if err != nil { return xerrors.Wrap(err, "failed to execute sdk request 'alb.ListListeners'") @@ -229,10 +229,10 @@ func (d *DeployerProvider) deployToListener(ctx context.Context, cloudCertId str func (d *DeployerProvider) updateListenerCertificate(ctx context.Context, cloudListenerId string, cloudCertId string) error { // 查询监听的属性 // REF: https://help.aliyun.com/zh/slb/application-load-balancer/developer-reference/api-alb-2020-06-16-getlistenerattribute - getListenerAttributeReq := &aliyunAlb.GetListenerAttributeRequest{ + getListenerAttributeReq := &alialb.GetListenerAttributeRequest{ ListenerId: tea.String(cloudListenerId), } - getListenerAttributeResp, err := d.sdkClients.alb.GetListenerAttribute(getListenerAttributeReq) + getListenerAttributeResp, err := d.sdkClients.ALB.GetListenerAttribute(getListenerAttributeReq) d.logger.Debug("sdk request 'alb.GetListenerAttribute'", slog.Any("request", getListenerAttributeReq), slog.Any("response", getListenerAttributeResp)) if err != nil { return xerrors.Wrap(err, "failed to execute sdk request 'alb.GetListenerAttribute'") @@ -243,13 +243,13 @@ func (d *DeployerProvider) updateListenerCertificate(ctx context.Context, cloudL // 修改监听的属性 // REF: https://help.aliyun.com/zh/slb/application-load-balancer/developer-reference/api-alb-2020-06-16-updatelistenerattribute - updateListenerAttributeReq := &aliyunAlb.UpdateListenerAttributeRequest{ + updateListenerAttributeReq := &alialb.UpdateListenerAttributeRequest{ ListenerId: tea.String(cloudListenerId), - Certificates: []*aliyunAlb.UpdateListenerAttributeRequestCertificates{{ + Certificates: []*alialb.UpdateListenerAttributeRequestCertificates{{ CertificateId: tea.String(cloudCertId), }}, } - updateListenerAttributeResp, err := d.sdkClients.alb.UpdateListenerAttribute(updateListenerAttributeReq) + updateListenerAttributeResp, err := d.sdkClients.ALB.UpdateListenerAttribute(updateListenerAttributeReq) d.logger.Debug("sdk request 'alb.UpdateListenerAttribute'", slog.Any("request", updateListenerAttributeReq), slog.Any("response", updateListenerAttributeResp)) if err != nil { return xerrors.Wrap(err, "failed to execute sdk request 'alb.UpdateListenerAttribute'") @@ -259,17 +259,17 @@ func (d *DeployerProvider) updateListenerCertificate(ctx context.Context, cloudL // 查询监听证书列表 // REF: https://help.aliyun.com/zh/slb/application-load-balancer/developer-reference/api-alb-2020-06-16-listlistenercertificates - listenerCertificates := make([]aliyunAlb.ListListenerCertificatesResponseBodyCertificates, 0) + listenerCertificates := make([]alialb.ListListenerCertificatesResponseBodyCertificates, 0) listListenerCertificatesLimit := int32(100) var listListenerCertificatesToken *string = nil for { - listListenerCertificatesReq := &aliyunAlb.ListListenerCertificatesRequest{ + listListenerCertificatesReq := &alialb.ListListenerCertificatesRequest{ NextToken: listListenerCertificatesToken, MaxResults: tea.Int32(listListenerCertificatesLimit), ListenerId: tea.String(cloudListenerId), CertificateType: tea.String("Server"), } - listListenerCertificatesResp, err := d.sdkClients.alb.ListListenerCertificates(listListenerCertificatesReq) + listListenerCertificatesResp, err := d.sdkClients.ALB.ListListenerCertificates(listListenerCertificatesReq) d.logger.Debug("sdk request 'alb.ListListenerCertificates'", slog.Any("request", listListenerCertificatesReq), slog.Any("response", listListenerCertificatesResp)) if err != nil { return xerrors.Wrap(err, "failed to execute sdk request 'alb.ListListenerCertificates'") @@ -291,52 +291,62 @@ func (d *DeployerProvider) updateListenerCertificate(ctx context.Context, cloudL // 遍历查询监听证书,并找出需要解除关联的证书 // REF: https://help.aliyun.com/zh/slb/application-load-balancer/developer-reference/api-alb-2020-06-16-listlistenercertificates // REF: https://help.aliyun.com/zh/ssl-certificate/developer-reference/api-cas-2020-04-07-getusercertificatedetail - certificateIsAssociated := false - certificateIdsExpired := make([]string, 0) + certificateIsAlreadyAssociated := false + certificateIdsToDissociate := make([]string, 0) if len(listenerCertificates) > 0 { d.logger.Info("found listener certificates to deploy", slog.Any("listenerCertificates", listenerCertificates)) var errs []error for _, listenerCertificate := range listenerCertificates { - // 监听证书 ID 格式:${证书 ID}-${地域} - certificateId := strings.Split(*listenerCertificate.CertificateId, "-")[0] - if certificateId == cloudCertId { - certificateIsAssociated = true + if tea.BoolValue(listenerCertificate.IsDefault) { continue } - if *listenerCertificate.IsDefault || !strings.EqualFold(*listenerCertificate.Status, "Associated") { + if !strings.EqualFold(tea.StringValue(listenerCertificate.Status), "Associated") { continue } + // 监听证书 ID 格式:${证书 ID}-${地域} + certificateId := strings.Split(tea.StringValue(listenerCertificate.CertificateId), "-")[0] + if certificateId == cloudCertId { + certificateIsAlreadyAssociated = true + break + } + certificateIdAsInt64, err := strconv.ParseInt(certificateId, 10, 64) if err != nil { errs = append(errs, err) continue } - getUserCertificateDetailReq := &aliyunCas.GetUserCertificateDetailRequest{ + getUserCertificateDetailReq := &alicas.GetUserCertificateDetailRequest{ CertId: tea.Int64(certificateIdAsInt64), } - getUserCertificateDetailResp, err := d.sdkClients.cas.GetUserCertificateDetail(getUserCertificateDetailReq) + getUserCertificateDetailResp, err := d.sdkClients.CAS.GetUserCertificateDetail(getUserCertificateDetailReq) d.logger.Debug("sdk request 'cas.GetUserCertificateDetail'", slog.Any("request", getUserCertificateDetailReq), slog.Any("response", getUserCertificateDetailResp)) if err != nil { + if sdkerr, ok := err.(*tea.SDKError); ok { + if tea.IntValue(sdkerr.StatusCode) == 400 && tea.StringValue(sdkerr.Code) == "NotFound" { + continue + } + } + errs = append(errs, xerrors.Wrap(err, "failed to execute sdk request 'cas.GetUserCertificateDetail'")) continue - } + } else { + certCNMatched := tea.StringValue(getUserCertificateDetailResp.Body.Common) == d.config.Domain + certSANMatched := slices.Contains(strings.Split(tea.StringValue(getUserCertificateDetailResp.Body.Sans), ","), d.config.Domain) + if !certCNMatched && !certSANMatched { + continue + } - certCnMatched := getUserCertificateDetailResp.Body.Common != nil && *getUserCertificateDetailResp.Body.Common == d.config.Domain - certSanMatched := getUserCertificateDetailResp.Body.Sans != nil && slices.Contains(strings.Split(*getUserCertificateDetailResp.Body.Sans, ","), d.config.Domain) - if !certCnMatched && !certSanMatched { - continue - } + certEndDate, _ := time.Parse("2006-01-02", tea.StringValue(getUserCertificateDetailResp.Body.EndDate)) + if time.Now().Before(certEndDate) { + continue + } - certEndDate, _ := time.Parse("2006-01-02", *getUserCertificateDetailResp.Body.EndDate) - if time.Now().Before(certEndDate) { - continue + certificateIdsToDissociate = append(certificateIdsToDissociate, certificateId) } - - certificateIdsExpired = append(certificateIdsExpired, certificateId) } if len(errs) > 0 { @@ -346,16 +356,16 @@ func (d *DeployerProvider) updateListenerCertificate(ctx context.Context, cloudL // 关联监听和扩展证书 // REF: https://help.aliyun.com/zh/slb/application-load-balancer/developer-reference/api-alb-2020-06-16-associateadditionalcertificateswithlistener - if !certificateIsAssociated { - associateAdditionalCertificatesFromListenerReq := &aliyunAlb.AssociateAdditionalCertificatesWithListenerRequest{ + if !certificateIsAlreadyAssociated { + associateAdditionalCertificatesFromListenerReq := &alialb.AssociateAdditionalCertificatesWithListenerRequest{ ListenerId: tea.String(cloudListenerId), - Certificates: []*aliyunAlb.AssociateAdditionalCertificatesWithListenerRequestCertificates{ + Certificates: []*alialb.AssociateAdditionalCertificatesWithListenerRequestCertificates{ { CertificateId: tea.String(cloudCertId), }, }, } - associateAdditionalCertificatesFromListenerResp, err := d.sdkClients.alb.AssociateAdditionalCertificatesWithListener(associateAdditionalCertificatesFromListenerReq) + associateAdditionalCertificatesFromListenerResp, err := d.sdkClients.ALB.AssociateAdditionalCertificatesWithListener(associateAdditionalCertificatesFromListenerReq) d.logger.Debug("sdk request 'alb.AssociateAdditionalCertificatesWithListener'", slog.Any("request", associateAdditionalCertificatesFromListenerReq), slog.Any("response", associateAdditionalCertificatesFromListenerResp)) if err != nil { return xerrors.Wrap(err, "failed to execute sdk request 'alb.AssociateAdditionalCertificatesWithListener'") @@ -364,19 +374,19 @@ func (d *DeployerProvider) updateListenerCertificate(ctx context.Context, cloudL // 解除关联监听和扩展证书 // REF: https://help.aliyun.com/zh/slb/application-load-balancer/developer-reference/api-alb-2020-06-16-dissociateadditionalcertificatesfromlistener - if len(certificateIdsExpired) > 0 { - dissociateAdditionalCertificates := make([]*aliyunAlb.DissociateAdditionalCertificatesFromListenerRequestCertificates, 0) - for _, certificateId := range certificateIdsExpired { - dissociateAdditionalCertificates = append(dissociateAdditionalCertificates, &aliyunAlb.DissociateAdditionalCertificatesFromListenerRequestCertificates{ + if !certificateIsAlreadyAssociated && len(certificateIdsToDissociate) > 0 { + dissociateAdditionalCertificates := make([]*alialb.DissociateAdditionalCertificatesFromListenerRequestCertificates, 0) + for _, certificateId := range certificateIdsToDissociate { + dissociateAdditionalCertificates = append(dissociateAdditionalCertificates, &alialb.DissociateAdditionalCertificatesFromListenerRequestCertificates{ CertificateId: tea.String(certificateId), }) } - dissociateAdditionalCertificatesFromListenerReq := &aliyunAlb.DissociateAdditionalCertificatesFromListenerRequest{ + dissociateAdditionalCertificatesFromListenerReq := &alialb.DissociateAdditionalCertificatesFromListenerRequest{ ListenerId: tea.String(cloudListenerId), Certificates: dissociateAdditionalCertificates, } - dissociateAdditionalCertificatesFromListenerResp, err := d.sdkClients.alb.DissociateAdditionalCertificatesFromListener(dissociateAdditionalCertificatesFromListenerReq) + dissociateAdditionalCertificatesFromListenerResp, err := d.sdkClients.ALB.DissociateAdditionalCertificatesFromListener(dissociateAdditionalCertificatesFromListenerReq) d.logger.Debug("sdk request 'alb.DissociateAdditionalCertificatesFromListener'", slog.Any("request", dissociateAdditionalCertificatesFromListenerReq), slog.Any("response", dissociateAdditionalCertificatesFromListenerResp)) if err != nil { return xerrors.Wrap(err, "failed to execute sdk request 'alb.DissociateAdditionalCertificatesFromListener'") @@ -397,12 +407,12 @@ func createSdkClients(accessKeyId, accessKeySecret, region string) (*wSdkClients albEndpoint = fmt.Sprintf("alb.%s.aliyuncs.com", region) } - albConfig := &aliyunOpen.Config{ + albConfig := &aliopen.Config{ AccessKeyId: tea.String(accessKeyId), AccessKeySecret: tea.String(accessKeySecret), Endpoint: tea.String(albEndpoint), } - albClient, err := aliyunAlb.NewClient(albConfig) + albClient, err := alialb.NewClient(albConfig) if err != nil { return nil, err } @@ -415,19 +425,19 @@ func createSdkClients(accessKeyId, accessKeySecret, region string) (*wSdkClients casEndpoint = "cas.aliyuncs.com" } - casConfig := &aliyunOpen.Config{ + casConfig := &aliopen.Config{ Endpoint: tea.String(casEndpoint), AccessKeyId: tea.String(accessKeyId), AccessKeySecret: tea.String(accessKeySecret), } - casClient, err := aliyunCas.NewClient(casConfig) + casClient, err := alicas.NewClient(casConfig) if err != nil { return nil, err } return &wSdkClients{ - alb: albClient, - cas: casClient, + ALB: albClient, + CAS: casClient, }, nil } diff --git a/internal/pkg/core/deployer/providers/aliyun-cas-deploy/aliyun_cas_deploy.go b/internal/pkg/core/deployer/providers/aliyun-cas-deploy/aliyun_cas_deploy.go index 7c53358d..b50e8c5d 100644 --- a/internal/pkg/core/deployer/providers/aliyun-cas-deploy/aliyun_cas_deploy.go +++ b/internal/pkg/core/deployer/providers/aliyun-cas-deploy/aliyun_cas_deploy.go @@ -8,8 +8,8 @@ import ( "strings" "time" - aliyunCas "github.com/alibabacloud-go/cas-20200407/v3/client" - aliyunOpen "github.com/alibabacloud-go/darabonba-openapi/v2/client" + alicas "github.com/alibabacloud-go/cas-20200407/v3/client" + aliopen "github.com/alibabacloud-go/darabonba-openapi/v2/client" "github.com/alibabacloud-go/tea/tea" xerrors "github.com/pkg/errors" @@ -35,7 +35,7 @@ type DeployerConfig struct { type DeployerProvider struct { config *DeployerConfig logger *slog.Logger - sdkClient *aliyunCas.Client + sdkClient *alicas.Client sslUploader uploader.Uploader } @@ -95,7 +95,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe if len(contactIds) == 0 { // 获取联系人列表 // REF: https://help.aliyun.com/zh/ssl-certificate/developer-reference/api-cas-2020-04-07-listcontact - listContactReq := &aliyunCas.ListContactRequest{} + listContactReq := &alicas.ListContactRequest{} listContactReq.ShowSize = tea.Int32(1) listContactReq.CurrentPage = tea.Int32(1) listContactResp, err := d.sdkClient.ListContact(listContactReq) @@ -111,7 +111,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe // 创建部署任务 // REF: https://help.aliyun.com/zh/ssl-certificate/developer-reference/api-cas-2020-04-07-createdeploymentjob - createDeploymentJobReq := &aliyunCas.CreateDeploymentJobRequest{ + createDeploymentJobReq := &alicas.CreateDeploymentJobRequest{ Name: tea.String(fmt.Sprintf("certimate-%d", time.Now().UnixMilli())), JobType: tea.String("user"), CertIds: tea.String(upres.CertId), @@ -131,7 +131,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe return nil, ctx.Err() } - describeDeploymentJobReq := &aliyunCas.DescribeDeploymentJobRequest{ + describeDeploymentJobReq := &alicas.DescribeDeploymentJobRequest{ JobId: createDeploymentJobResp.Body.JobId, } describeDeploymentJobResp, err := d.sdkClient.DescribeDeploymentJob(describeDeploymentJobReq) @@ -155,7 +155,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe return &deployer.DeployResult{}, nil } -func createSdkClient(accessKeyId, accessKeySecret, region string) (*aliyunCas.Client, error) { +func createSdkClient(accessKeyId, accessKeySecret, region string) (*alicas.Client, error) { if region == "" { region = "cn-hangzhou" // CAS 服务默认区域:华东一杭州 } @@ -169,13 +169,13 @@ func createSdkClient(accessKeyId, accessKeySecret, region string) (*aliyunCas.Cl endpoint = fmt.Sprintf("cas.%s.aliyuncs.com", region) } - config := &aliyunOpen.Config{ + config := &aliopen.Config{ AccessKeyId: tea.String(accessKeyId), AccessKeySecret: tea.String(accessKeySecret), Endpoint: tea.String(endpoint), } - client, err := aliyunCas.NewClient(config) + client, err := alicas.NewClient(config) if err != nil { return nil, err } diff --git a/internal/pkg/core/deployer/providers/aliyun-cdn/aliyun_cdn.go b/internal/pkg/core/deployer/providers/aliyun-cdn/aliyun_cdn.go index 8f61837f..2a9be884 100644 --- a/internal/pkg/core/deployer/providers/aliyun-cdn/aliyun_cdn.go +++ b/internal/pkg/core/deployer/providers/aliyun-cdn/aliyun_cdn.go @@ -7,8 +7,8 @@ import ( "strings" "time" - aliyunCdn "github.com/alibabacloud-go/cdn-20180510/v5/client" - aliyunOpen "github.com/alibabacloud-go/darabonba-openapi/v2/client" + alicdn "github.com/alibabacloud-go/cdn-20180510/v5/client" + aliopen "github.com/alibabacloud-go/darabonba-openapi/v2/client" "github.com/alibabacloud-go/tea/tea" xerrors "github.com/pkg/errors" @@ -27,7 +27,7 @@ type DeployerConfig struct { type DeployerProvider struct { config *DeployerConfig logger *slog.Logger - sdkClient *aliyunCdn.Client + sdkClient *alicdn.Client } var _ deployer.Deployer = (*DeployerProvider)(nil) @@ -64,7 +64,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe // 设置 CDN 域名域名证书 // REF: https://help.aliyun.com/zh/cdn/developer-reference/api-cdn-2018-05-10-setcdndomainsslcertificate - setCdnDomainSSLCertificateReq := &aliyunCdn.SetCdnDomainSSLCertificateRequest{ + setCdnDomainSSLCertificateReq := &alicdn.SetCdnDomainSSLCertificateRequest{ DomainName: tea.String(domain), CertName: tea.String(fmt.Sprintf("certimate-%d", time.Now().UnixMilli())), CertType: tea.String("upload"), @@ -81,14 +81,14 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe return &deployer.DeployResult{}, nil } -func createSdkClient(accessKeyId, accessKeySecret string) (*aliyunCdn.Client, error) { - config := &aliyunOpen.Config{ +func createSdkClient(accessKeyId, accessKeySecret string) (*alicdn.Client, error) { + config := &aliopen.Config{ AccessKeyId: tea.String(accessKeyId), AccessKeySecret: tea.String(accessKeySecret), Endpoint: tea.String("cdn.aliyuncs.com"), } - client, err := aliyunCdn.NewClient(config) + client, err := alicdn.NewClient(config) if err != nil { return nil, err } diff --git a/internal/pkg/core/deployer/providers/aliyun-clb/aliyun_clb.go b/internal/pkg/core/deployer/providers/aliyun-clb/aliyun_clb.go index fe0d3a44..2fcdd0f0 100644 --- a/internal/pkg/core/deployer/providers/aliyun-clb/aliyun_clb.go +++ b/internal/pkg/core/deployer/providers/aliyun-clb/aliyun_clb.go @@ -6,8 +6,8 @@ import ( "fmt" "log/slog" - aliyunOpen "github.com/alibabacloud-go/darabonba-openapi/v2/client" - aliyunSlb "github.com/alibabacloud-go/slb-20140515/v4/client" + aliopen "github.com/alibabacloud-go/darabonba-openapi/v2/client" + alislb "github.com/alibabacloud-go/slb-20140515/v4/client" "github.com/alibabacloud-go/tea/tea" xerrors "github.com/pkg/errors" @@ -39,7 +39,7 @@ type DeployerConfig struct { type DeployerProvider struct { config *DeployerConfig logger *slog.Logger - sdkClient *aliyunSlb.Client + sdkClient *alislb.Client sslUploader uploader.Uploader } @@ -117,7 +117,7 @@ func (d *DeployerProvider) deployToLoadbalancer(ctx context.Context, cloudCertId // 查询负载均衡实例的详细信息 // REF: https://help.aliyun.com/zh/slb/classic-load-balancer/developer-reference/api-slb-2014-05-15-describeloadbalancerattribute - describeLoadBalancerAttributeReq := &aliyunSlb.DescribeLoadBalancerAttributeRequest{ + describeLoadBalancerAttributeReq := &alislb.DescribeLoadBalancerAttributeRequest{ RegionId: tea.String(d.config.Region), LoadBalancerId: tea.String(d.config.LoadbalancerId), } @@ -133,7 +133,7 @@ func (d *DeployerProvider) deployToLoadbalancer(ctx context.Context, cloudCertId describeLoadBalancerListenersLimit := int32(100) var describeLoadBalancerListenersToken *string = nil for { - describeLoadBalancerListenersReq := &aliyunSlb.DescribeLoadBalancerListenersRequest{ + describeLoadBalancerListenersReq := &alislb.DescribeLoadBalancerListenersRequest{ RegionId: tea.String(d.config.Region), MaxResults: tea.Int32(describeLoadBalancerListenersLimit), NextToken: describeLoadBalancerListenersToken, @@ -199,7 +199,7 @@ func (d *DeployerProvider) deployToListener(ctx context.Context, cloudCertId str func (d *DeployerProvider) updateListenerCertificate(ctx context.Context, cloudLoadbalancerId string, cloudListenerPort int32, cloudCertId string) error { // 查询监听配置 // REF: https://help.aliyun.com/zh/slb/classic-load-balancer/developer-reference/api-slb-2014-05-15-describeloadbalancerhttpslistenerattribute - describeLoadBalancerHTTPSListenerAttributeReq := &aliyunSlb.DescribeLoadBalancerHTTPSListenerAttributeRequest{ + describeLoadBalancerHTTPSListenerAttributeReq := &alislb.DescribeLoadBalancerHTTPSListenerAttributeRequest{ LoadBalancerId: tea.String(cloudLoadbalancerId), ListenerPort: tea.Int32(cloudListenerPort), } @@ -214,7 +214,7 @@ func (d *DeployerProvider) updateListenerCertificate(ctx context.Context, cloudL // 修改监听配置 // REF: https://help.aliyun.com/zh/slb/classic-load-balancer/developer-reference/api-slb-2014-05-15-setloadbalancerhttpslistenerattribute - setLoadBalancerHTTPSListenerAttributeReq := &aliyunSlb.SetLoadBalancerHTTPSListenerAttributeRequest{ + setLoadBalancerHTTPSListenerAttributeReq := &alislb.SetLoadBalancerHTTPSListenerAttributeRequest{ RegionId: tea.String(d.config.Region), LoadBalancerId: tea.String(cloudLoadbalancerId), ListenerPort: tea.Int32(cloudListenerPort), @@ -230,7 +230,7 @@ func (d *DeployerProvider) updateListenerCertificate(ctx context.Context, cloudL // 查询扩展域名 // REF: https://help.aliyun.com/zh/slb/classic-load-balancer/developer-reference/api-slb-2014-05-15-describedomainextensions - describeDomainExtensionsReq := &aliyunSlb.DescribeDomainExtensionsRequest{ + describeDomainExtensionsReq := &alislb.DescribeDomainExtensionsRequest{ RegionId: tea.String(d.config.Region), LoadBalancerId: tea.String(cloudLoadbalancerId), ListenerPort: tea.Int32(cloudListenerPort), @@ -251,7 +251,7 @@ func (d *DeployerProvider) updateListenerCertificate(ctx context.Context, cloudL continue } - setDomainExtensionAttributeReq := &aliyunSlb.SetDomainExtensionAttributeRequest{ + setDomainExtensionAttributeReq := &alislb.SetDomainExtensionAttributeRequest{ RegionId: tea.String(d.config.Region), DomainExtensionId: tea.String(*domainExtension.DomainExtensionId), ServerCertificateId: tea.String(cloudCertId), @@ -273,7 +273,7 @@ func (d *DeployerProvider) updateListenerCertificate(ctx context.Context, cloudL return nil } -func createSdkClient(accessKeyId, accessKeySecret, region string) (*aliyunSlb.Client, error) { +func createSdkClient(accessKeyId, accessKeySecret, region string) (*alislb.Client, error) { // 接入点一览 https://api.aliyun.com/product/Slb var endpoint string switch region { @@ -287,13 +287,13 @@ func createSdkClient(accessKeyId, accessKeySecret, region string) (*aliyunSlb.Cl endpoint = fmt.Sprintf("slb.%s.aliyuncs.com", region) } - config := &aliyunOpen.Config{ + config := &aliopen.Config{ AccessKeyId: tea.String(accessKeyId), AccessKeySecret: tea.String(accessKeySecret), Endpoint: tea.String(endpoint), } - client, err := aliyunSlb.NewClient(config) + client, err := alislb.NewClient(config) if err != nil { return nil, err } diff --git a/internal/pkg/core/deployer/providers/aliyun-clb/aliyun_clb_test.go b/internal/pkg/core/deployer/providers/aliyun-clb/aliyun_clb_test.go index a845bf86..f688edf9 100644 --- a/internal/pkg/core/deployer/providers/aliyun-clb/aliyun_clb_test.go +++ b/internal/pkg/core/deployer/providers/aliyun-clb/aliyun_clb_test.go @@ -46,7 +46,7 @@ Shell command to run this test: --CERTIMATE_DEPLOYER_ALIYUNCLB_REGION="cn-hangzhou" \ --CERTIMATE_DEPLOYER_ALIYUNCLB_LOADBALANCERID="your-clb-instance-id" \ --CERTIMATE_DEPLOYER_ALIYUNCLB_LISTENERPORT=443 \ - --CERTIMATE_DEPLOYER_ALIYUNCLB_DOMAIN="your-alb-sni-domain" + --CERTIMATE_DEPLOYER_ALIYUNCLB_DOMAIN="your-clb-sni-domain" */ func TestDeploy(t *testing.T) { flag.Parse() diff --git a/internal/pkg/core/deployer/providers/aliyun-dcdn/aliyun_dcdn.go b/internal/pkg/core/deployer/providers/aliyun-dcdn/aliyun_dcdn.go index 0ca22a6e..b9ba9f23 100644 --- a/internal/pkg/core/deployer/providers/aliyun-dcdn/aliyun_dcdn.go +++ b/internal/pkg/core/deployer/providers/aliyun-dcdn/aliyun_dcdn.go @@ -7,8 +7,8 @@ import ( "strings" "time" - aliyunOpen "github.com/alibabacloud-go/darabonba-openapi/v2/client" - aliyunDcdn "github.com/alibabacloud-go/dcdn-20180115/v3/client" + aliopen "github.com/alibabacloud-go/darabonba-openapi/v2/client" + alidcdn "github.com/alibabacloud-go/dcdn-20180115/v3/client" "github.com/alibabacloud-go/tea/tea" xerrors "github.com/pkg/errors" @@ -27,7 +27,7 @@ type DeployerConfig struct { type DeployerProvider struct { config *DeployerConfig logger *slog.Logger - sdkClient *aliyunDcdn.Client + sdkClient *alidcdn.Client } var _ deployer.Deployer = (*DeployerProvider)(nil) @@ -64,7 +64,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe // 配置域名证书 // REF: https://help.aliyun.com/zh/edge-security-acceleration/dcdn/developer-reference/api-dcdn-2018-01-15-setdcdndomainsslcertificate - setDcdnDomainSSLCertificateReq := &aliyunDcdn.SetDcdnDomainSSLCertificateRequest{ + setDcdnDomainSSLCertificateReq := &alidcdn.SetDcdnDomainSSLCertificateRequest{ DomainName: tea.String(domain), CertName: tea.String(fmt.Sprintf("certimate-%d", time.Now().UnixMilli())), CertType: tea.String("upload"), @@ -81,14 +81,14 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe return &deployer.DeployResult{}, nil } -func createSdkClient(accessKeyId, accessKeySecret string) (*aliyunDcdn.Client, error) { - config := &aliyunOpen.Config{ +func createSdkClient(accessKeyId, accessKeySecret string) (*alidcdn.Client, error) { + config := &aliopen.Config{ AccessKeyId: tea.String(accessKeyId), AccessKeySecret: tea.String(accessKeySecret), Endpoint: tea.String("dcdn.aliyuncs.com"), } - client, err := aliyunDcdn.NewClient(config) + client, err := alidcdn.NewClient(config) if err != nil { return nil, err } diff --git a/internal/pkg/core/deployer/providers/aliyun-esa/aliyun_esa.go b/internal/pkg/core/deployer/providers/aliyun-esa/aliyun_esa.go index aa7e60c1..918ec095 100644 --- a/internal/pkg/core/deployer/providers/aliyun-esa/aliyun_esa.go +++ b/internal/pkg/core/deployer/providers/aliyun-esa/aliyun_esa.go @@ -8,8 +8,8 @@ import ( "strconv" "strings" - aliyunOpen "github.com/alibabacloud-go/darabonba-openapi/v2/client" - aliyunEsa "github.com/alibabacloud-go/esa-20240910/v2/client" + aliopen "github.com/alibabacloud-go/darabonba-openapi/v2/client" + aliesa "github.com/alibabacloud-go/esa-20240910/v2/client" "github.com/alibabacloud-go/tea/tea" xerrors "github.com/pkg/errors" @@ -32,7 +32,7 @@ type DeployerConfig struct { type DeployerProvider struct { config *DeployerConfig logger *slog.Logger - sdkClient *aliyunEsa.Client + sdkClient *aliesa.Client sslUploader uploader.Uploader } @@ -87,7 +87,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe // 配置站点证书 // REF: https://help.aliyun.com/zh/edge-security-acceleration/esa/api-esa-2024-09-10-setcertificate certId, _ := strconv.ParseInt(upres.CertId, 10, 64) - setCertificateReq := &aliyunEsa.SetCertificateRequest{ + setCertificateReq := &aliesa.SetCertificateRequest{ SiteId: tea.Int64(d.config.SiteId), Type: tea.String("cas"), CasId: tea.Int64(certId), @@ -101,15 +101,15 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe return &deployer.DeployResult{}, nil } -func createSdkClient(accessKeyId, accessKeySecret, region string) (*aliyunEsa.Client, error) { +func createSdkClient(accessKeyId, accessKeySecret, region string) (*aliesa.Client, error) { // 接入点一览 https://api.aliyun.com/product/ESA - config := &aliyunOpen.Config{ + config := &aliopen.Config{ AccessKeyId: tea.String(accessKeyId), AccessKeySecret: tea.String(accessKeySecret), Endpoint: tea.String(fmt.Sprintf("esa.%s.aliyuncs.com", region)), } - client, err := aliyunEsa.NewClient(config) + client, err := aliesa.NewClient(config) if err != nil { return nil, err } diff --git a/internal/pkg/core/deployer/providers/aliyun-fc/aliyun_fc.go b/internal/pkg/core/deployer/providers/aliyun-fc/aliyun_fc.go index d5450017..87f51130 100644 --- a/internal/pkg/core/deployer/providers/aliyun-fc/aliyun_fc.go +++ b/internal/pkg/core/deployer/providers/aliyun-fc/aliyun_fc.go @@ -6,9 +6,9 @@ import ( "log/slog" "time" - aliyunOpen "github.com/alibabacloud-go/darabonba-openapi/v2/client" - aliyunFc3 "github.com/alibabacloud-go/fc-20230330/v4/client" - aliyunFc2 "github.com/alibabacloud-go/fc-open-20210406/v2/client" + aliopen "github.com/alibabacloud-go/darabonba-openapi/v2/client" + alifc3 "github.com/alibabacloud-go/fc-20230330/v4/client" + alifc2 "github.com/alibabacloud-go/fc-open-20210406/v2/client" "github.com/alibabacloud-go/tea/tea" xerrors "github.com/pkg/errors" @@ -24,7 +24,7 @@ type DeployerConfig struct { Region string `json:"region"` // 服务版本。 ServiceVersion string `json:"serviceVersion"` - // 自定义域名(不支持泛域名)。 + // 自定义域名(支持泛域名)。 Domain string `json:"domain"` } @@ -37,8 +37,8 @@ type DeployerProvider struct { var _ deployer.Deployer = (*DeployerProvider)(nil) type wSdkClients struct { - fc2 *aliyunFc2.Client - fc3 *aliyunFc3.Client + FC2 *alifc2.Client + FC3 *alifc3.Client } func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { @@ -89,7 +89,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe func (d *DeployerProvider) deployToFC3(ctx context.Context, certPem string, privkeyPem string) error { // 获取自定义域名 // REF: https://help.aliyun.com/zh/functioncompute/fc-3-0/developer-reference/api-fc-2023-03-30-getcustomdomain - getCustomDomainResp, err := d.sdkClients.fc3.GetCustomDomain(tea.String(d.config.Domain)) + getCustomDomainResp, err := d.sdkClients.FC3.GetCustomDomain(tea.String(d.config.Domain)) d.logger.Debug("sdk request 'fc.GetCustomDomain'", slog.Any("response", getCustomDomainResp)) if err != nil { return xerrors.Wrap(err, "failed to execute sdk request 'fc.GetCustomDomain'") @@ -97,9 +97,9 @@ func (d *DeployerProvider) deployToFC3(ctx context.Context, certPem string, priv // 更新自定义域名 // REF: https://help.aliyun.com/zh/functioncompute/fc-3-0/developer-reference/api-fc-2023-03-30-updatecustomdomain - updateCustomDomainReq := &aliyunFc3.UpdateCustomDomainRequest{ - Body: &aliyunFc3.UpdateCustomDomainInput{ - CertConfig: &aliyunFc3.CertConfig{ + updateCustomDomainReq := &alifc3.UpdateCustomDomainRequest{ + Body: &alifc3.UpdateCustomDomainInput{ + CertConfig: &alifc3.CertConfig{ CertName: tea.String(fmt.Sprintf("certimate-%d", time.Now().UnixMilli())), Certificate: tea.String(certPem), PrivateKey: tea.String(privkeyPem), @@ -108,7 +108,7 @@ func (d *DeployerProvider) deployToFC3(ctx context.Context, certPem string, priv TlsConfig: getCustomDomainResp.Body.TlsConfig, }, } - updateCustomDomainResp, err := d.sdkClients.fc3.UpdateCustomDomain(tea.String(d.config.Domain), updateCustomDomainReq) + updateCustomDomainResp, err := d.sdkClients.FC3.UpdateCustomDomain(tea.String(d.config.Domain), updateCustomDomainReq) d.logger.Debug("sdk request 'fc.UpdateCustomDomain'", slog.Any("request", updateCustomDomainReq), slog.Any("response", updateCustomDomainResp)) if err != nil { return xerrors.Wrap(err, "failed to execute sdk request 'fc.UpdateCustomDomain'") @@ -120,7 +120,7 @@ func (d *DeployerProvider) deployToFC3(ctx context.Context, certPem string, priv func (d *DeployerProvider) deployToFC2(ctx context.Context, certPem string, privkeyPem string) error { // 获取自定义域名 // REF: https://help.aliyun.com/zh/functioncompute/fc-2-0/developer-reference/api-fc-open-2021-04-06-getcustomdomain - getCustomDomainResp, err := d.sdkClients.fc2.GetCustomDomain(tea.String(d.config.Domain)) + getCustomDomainResp, err := d.sdkClients.FC2.GetCustomDomain(tea.String(d.config.Domain)) d.logger.Debug("sdk request 'fc.GetCustomDomain'", slog.Any("response", getCustomDomainResp)) if err != nil { return xerrors.Wrap(err, "failed to execute sdk request 'fc.GetCustomDomain'") @@ -128,8 +128,8 @@ func (d *DeployerProvider) deployToFC2(ctx context.Context, certPem string, priv // 更新自定义域名 // REF: https://help.aliyun.com/zh/functioncompute/fc-2-0/developer-reference/api-fc-open-2021-04-06-updatecustomdomain - updateCustomDomainReq := &aliyunFc2.UpdateCustomDomainRequest{ - CertConfig: &aliyunFc2.CertConfig{ + updateCustomDomainReq := &alifc2.UpdateCustomDomainRequest{ + CertConfig: &alifc2.CertConfig{ CertName: tea.String(fmt.Sprintf("certimate-%d", time.Now().UnixMilli())), Certificate: tea.String(certPem), PrivateKey: tea.String(privkeyPem), @@ -137,7 +137,7 @@ func (d *DeployerProvider) deployToFC2(ctx context.Context, certPem string, priv Protocol: getCustomDomainResp.Body.Protocol, TlsConfig: getCustomDomainResp.Body.TlsConfig, } - updateCustomDomainResp, err := d.sdkClients.fc2.UpdateCustomDomain(tea.String(d.config.Domain), updateCustomDomainReq) + updateCustomDomainResp, err := d.sdkClients.FC2.UpdateCustomDomain(tea.String(d.config.Domain), updateCustomDomainReq) d.logger.Debug("sdk request 'fc.UpdateCustomDomain'", slog.Any("request", updateCustomDomainReq), slog.Any("response", updateCustomDomainResp)) if err != nil { return xerrors.Wrap(err, "failed to execute sdk request 'fc.UpdateCustomDomain'") @@ -156,30 +156,30 @@ func createSdkClients(accessKeyId, accessKeySecret, region string) (*wSdkClients fc2Endpoint = fmt.Sprintf("fc.%s.aliyuncs.com", region) } - fc2Config := &aliyunOpen.Config{ + fc2Config := &aliopen.Config{ AccessKeyId: tea.String(accessKeyId), AccessKeySecret: tea.String(accessKeySecret), Endpoint: tea.String(fc2Endpoint), } - fc2Client, err := aliyunFc2.NewClient(fc2Config) + fc2Client, err := alifc2.NewClient(fc2Config) if err != nil { return nil, err } // 接入点一览 https://api.aliyun.com/product/FC-Open fc3Endpoint := fmt.Sprintf("fcv3.%s.aliyuncs.com", region) - fc3Config := &aliyunOpen.Config{ + fc3Config := &aliopen.Config{ AccessKeyId: tea.String(accessKeyId), AccessKeySecret: tea.String(accessKeySecret), Endpoint: tea.String(fc3Endpoint), } - fc3Client, err := aliyunFc3.NewClient(fc3Config) + fc3Client, err := alifc3.NewClient(fc3Config) if err != nil { return nil, err } return &wSdkClients{ - fc2: fc2Client, - fc3: fc3Client, + FC2: fc2Client, + FC3: fc3Client, }, nil } diff --git a/internal/pkg/core/deployer/providers/aliyun-live/aliyun_live.go b/internal/pkg/core/deployer/providers/aliyun-live/aliyun_live.go index 4eacd077..e3f6a435 100644 --- a/internal/pkg/core/deployer/providers/aliyun-live/aliyun_live.go +++ b/internal/pkg/core/deployer/providers/aliyun-live/aliyun_live.go @@ -7,8 +7,8 @@ import ( "strings" "time" - aliyunOpen "github.com/alibabacloud-go/darabonba-openapi/v2/client" - aliyunLive "github.com/alibabacloud-go/live-20161101/client" + aliopen "github.com/alibabacloud-go/darabonba-openapi/v2/client" + alilive "github.com/alibabacloud-go/live-20161101/client" "github.com/alibabacloud-go/tea/tea" xerrors "github.com/pkg/errors" @@ -29,7 +29,7 @@ type DeployerConfig struct { type DeployerProvider struct { config *DeployerConfig logger *slog.Logger - sdkClient *aliyunLive.Client + sdkClient *alilive.Client } var _ deployer.Deployer = (*DeployerProvider)(nil) @@ -66,7 +66,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe // 设置域名证书 // REF: https://help.aliyun.com/zh/live/developer-reference/api-live-2016-11-01-setlivedomaincertificate - setLiveDomainSSLCertificateReq := &aliyunLive.SetLiveDomainCertificateRequest{ + setLiveDomainSSLCertificateReq := &alilive.SetLiveDomainCertificateRequest{ DomainName: tea.String(domain), CertName: tea.String(fmt.Sprintf("certimate-%d", time.Now().UnixMilli())), CertType: tea.String("upload"), @@ -83,7 +83,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe return &deployer.DeployResult{}, nil } -func createSdkClient(accessKeyId, accessKeySecret, region string) (*aliyunLive.Client, error) { +func createSdkClient(accessKeyId, accessKeySecret, region string) (*alilive.Client, error) { // 接入点一览 https://api.aliyun.com/product/live var endpoint string switch region { @@ -100,13 +100,13 @@ func createSdkClient(accessKeyId, accessKeySecret, region string) (*aliyunLive.C endpoint = fmt.Sprintf("live.%s.aliyuncs.com", region) } - config := &aliyunOpen.Config{ + config := &aliopen.Config{ AccessKeyId: tea.String(accessKeyId), AccessKeySecret: tea.String(accessKeySecret), Endpoint: tea.String(endpoint), } - client, err := aliyunLive.NewClient(config) + client, err := alilive.NewClient(config) if err != nil { return nil, err } diff --git a/internal/pkg/core/deployer/providers/aliyun-nlb/aliyun_nlb.go b/internal/pkg/core/deployer/providers/aliyun-nlb/aliyun_nlb.go index 98885d7d..f851fee8 100644 --- a/internal/pkg/core/deployer/providers/aliyun-nlb/aliyun_nlb.go +++ b/internal/pkg/core/deployer/providers/aliyun-nlb/aliyun_nlb.go @@ -7,8 +7,8 @@ import ( "log/slog" "strings" - aliyunOpen "github.com/alibabacloud-go/darabonba-openapi/v2/client" - aliyunNlb "github.com/alibabacloud-go/nlb-20220430/v2/client" + aliopen "github.com/alibabacloud-go/darabonba-openapi/v2/client" + alinlb "github.com/alibabacloud-go/nlb-20220430/v2/client" "github.com/alibabacloud-go/tea/tea" xerrors "github.com/pkg/errors" @@ -37,7 +37,7 @@ type DeployerConfig struct { type DeployerProvider struct { config *DeployerConfig logger *slog.Logger - sdkClient *aliyunNlb.Client + sdkClient *alinlb.Client sslUploader uploader.Uploader } @@ -111,7 +111,7 @@ func (d *DeployerProvider) deployToLoadbalancer(ctx context.Context, cloudCertId // 查询负载均衡实例的详细信息 // REF: https://help.aliyun.com/zh/slb/network-load-balancer/developer-reference/api-nlb-2022-04-30-getloadbalancerattribute - getLoadBalancerAttributeReq := &aliyunNlb.GetLoadBalancerAttributeRequest{ + getLoadBalancerAttributeReq := &alinlb.GetLoadBalancerAttributeRequest{ LoadBalancerId: tea.String(d.config.LoadbalancerId), } getLoadBalancerAttributeResp, err := d.sdkClient.GetLoadBalancerAttribute(getLoadBalancerAttributeReq) @@ -126,7 +126,7 @@ func (d *DeployerProvider) deployToLoadbalancer(ctx context.Context, cloudCertId listListenersLimit := int32(100) var listListenersToken *string = nil for { - listListenersReq := &aliyunNlb.ListListenersRequest{ + listListenersReq := &alinlb.ListListenersRequest{ MaxResults: tea.Int32(listListenersLimit), NextToken: listListenersToken, LoadBalancerIds: []*string{tea.String(d.config.LoadbalancerId)}, @@ -188,7 +188,7 @@ func (d *DeployerProvider) deployToListener(ctx context.Context, cloudCertId str func (d *DeployerProvider) updateListenerCertificate(ctx context.Context, cloudListenerId string, cloudCertId string) error { // 查询监听的属性 // REF: https://help.aliyun.com/zh/slb/network-load-balancer/developer-reference/api-nlb-2022-04-30-getlistenerattribute - getListenerAttributeReq := &aliyunNlb.GetListenerAttributeRequest{ + getListenerAttributeReq := &alinlb.GetListenerAttributeRequest{ ListenerId: tea.String(cloudListenerId), } getListenerAttributeResp, err := d.sdkClient.GetListenerAttribute(getListenerAttributeReq) @@ -199,7 +199,7 @@ func (d *DeployerProvider) updateListenerCertificate(ctx context.Context, cloudL // 修改监听的属性 // REF: https://help.aliyun.com/zh/slb/network-load-balancer/developer-reference/api-nlb-2022-04-30-updatelistenerattribute - updateListenerAttributeReq := &aliyunNlb.UpdateListenerAttributeRequest{ + updateListenerAttributeReq := &alinlb.UpdateListenerAttributeRequest{ ListenerId: tea.String(cloudListenerId), CertificateIds: []*string{tea.String(cloudCertId)}, } @@ -212,7 +212,7 @@ func (d *DeployerProvider) updateListenerCertificate(ctx context.Context, cloudL return nil } -func createSdkClient(accessKeyId, accessKeySecret, region string) (*aliyunNlb.Client, error) { +func createSdkClient(accessKeyId, accessKeySecret, region string) (*alinlb.Client, error) { // 接入点一览 https://api.aliyun.com/product/Nlb var endpoint string switch region { @@ -220,13 +220,13 @@ func createSdkClient(accessKeyId, accessKeySecret, region string) (*aliyunNlb.Cl endpoint = fmt.Sprintf("nlb.%s.aliyuncs.com", region) } - config := &aliyunOpen.Config{ + config := &aliopen.Config{ AccessKeyId: tea.String(accessKeyId), AccessKeySecret: tea.String(accessKeySecret), Endpoint: tea.String(endpoint), } - client, err := aliyunNlb.NewClient(config) + client, err := alinlb.NewClient(config) if err != nil { return nil, err } diff --git a/internal/pkg/core/deployer/providers/aliyun-vod/aliyun_vod.go b/internal/pkg/core/deployer/providers/aliyun-vod/aliyun_vod.go index 66dc188c..95d4f631 100644 --- a/internal/pkg/core/deployer/providers/aliyun-vod/aliyun_vod.go +++ b/internal/pkg/core/deployer/providers/aliyun-vod/aliyun_vod.go @@ -6,9 +6,9 @@ import ( "log/slog" "time" - aliyunOpen "github.com/alibabacloud-go/darabonba-openapi/v2/client" + aliopen "github.com/alibabacloud-go/darabonba-openapi/v2/client" "github.com/alibabacloud-go/tea/tea" - aliyunVod "github.com/alibabacloud-go/vod-20170321/v4/client" + alivod "github.com/alibabacloud-go/vod-20170321/v4/client" xerrors "github.com/pkg/errors" "github.com/usual2970/certimate/internal/pkg/core/deployer" @@ -28,7 +28,7 @@ type DeployerConfig struct { type DeployerProvider struct { config *DeployerConfig logger *slog.Logger - sdkClient *aliyunVod.Client + sdkClient *alivod.Client } var _ deployer.Deployer = (*DeployerProvider)(nil) @@ -62,7 +62,7 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { // 设置域名证书 // REF: https://help.aliyun.com/zh/vod/developer-reference/api-vod-2017-03-21-setvoddomainsslcertificate - setVodDomainSSLCertificateReq := &aliyunVod.SetVodDomainSSLCertificateRequest{ + setVodDomainSSLCertificateReq := &alivod.SetVodDomainSSLCertificateRequest{ DomainName: tea.String(d.config.Domain), CertName: tea.String(fmt.Sprintf("certimate-%d", time.Now().UnixMilli())), CertType: tea.String("upload"), @@ -79,17 +79,17 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe return &deployer.DeployResult{}, nil } -func createSdkClient(accessKeyId, accessKeySecret, region string) (*aliyunVod.Client, error) { +func createSdkClient(accessKeyId, accessKeySecret, region string) (*alivod.Client, error) { // 接入点一览 https://api.aliyun.com/product/vod endpoint := fmt.Sprintf("vod.%s.aliyuncs.com", region) - config := &aliyunOpen.Config{ + config := &aliopen.Config{ AccessKeyId: tea.String(accessKeyId), AccessKeySecret: tea.String(accessKeySecret), Endpoint: tea.String(endpoint), } - client, err := aliyunVod.NewClient(config) + client, err := alivod.NewClient(config) if err != nil { return nil, err } diff --git a/internal/pkg/core/deployer/providers/aliyun-waf/aliyun_waf.go b/internal/pkg/core/deployer/providers/aliyun-waf/aliyun_waf.go index 998ee7e7..cc179b34 100644 --- a/internal/pkg/core/deployer/providers/aliyun-waf/aliyun_waf.go +++ b/internal/pkg/core/deployer/providers/aliyun-waf/aliyun_waf.go @@ -7,14 +7,15 @@ import ( "log/slog" "strings" - aliyunOpen "github.com/alibabacloud-go/darabonba-openapi/v2/client" + aliopen "github.com/alibabacloud-go/darabonba-openapi/v2/client" "github.com/alibabacloud-go/tea/tea" - aliyunWaf "github.com/alibabacloud-go/waf-openapi-20211001/v5/client" + aliwaf "github.com/alibabacloud-go/waf-openapi-20211001/v5/client" xerrors "github.com/pkg/errors" "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" + "github.com/usual2970/certimate/internal/pkg/utils/sliceutil" ) type DeployerConfig struct { @@ -35,7 +36,7 @@ type DeployerConfig struct { type DeployerProvider struct { config *DeployerConfig logger *slog.Logger - sdkClient *aliyunWaf.Client + sdkClient *aliwaf.Client sslUploader uploader.Uploader } @@ -106,7 +107,7 @@ func (d *DeployerProvider) deployToWAF3(ctx context.Context, certPem string, pri // 查询默认 SSL/TLS 设置 // REF: https://help.aliyun.com/zh/waf/web-application-firewall-3-0/developer-reference/api-waf-openapi-2021-10-01-describedefaulthttps - describeDefaultHttpsReq := &aliyunWaf.DescribeDefaultHttpsRequest{ + describeDefaultHttpsReq := &aliwaf.DescribeDefaultHttpsRequest{ InstanceId: tea.String(d.config.InstanceId), RegionId: tea.String(d.config.Region), } @@ -118,7 +119,7 @@ func (d *DeployerProvider) deployToWAF3(ctx context.Context, certPem string, pri // 修改默认 SSL/TLS 设置 // REF: https://help.aliyun.com/zh/waf/web-application-firewall-3-0/developer-reference/api-waf-openapi-2021-10-01-modifydefaulthttps - modifyDefaultHttpsReq := &aliyunWaf.ModifyDefaultHttpsRequest{ + modifyDefaultHttpsReq := &aliwaf.ModifyDefaultHttpsRequest{ InstanceId: tea.String(d.config.InstanceId), RegionId: tea.String(d.config.Region), CertId: tea.String(upres.CertId), @@ -139,7 +140,7 @@ func (d *DeployerProvider) deployToWAF3(ctx context.Context, certPem string, pri // 查询 CNAME 接入详情 // REF: https://help.aliyun.com/zh/waf/web-application-firewall-3-0/developer-reference/api-waf-openapi-2021-10-01-describedomaindetail - describeDomainDetailReq := &aliyunWaf.DescribeDomainDetailRequest{ + describeDomainDetailReq := &aliwaf.DescribeDomainDetailRequest{ InstanceId: tea.String(d.config.InstanceId), RegionId: tea.String(d.config.Region), Domain: tea.String(d.config.Domain), @@ -152,30 +153,14 @@ func (d *DeployerProvider) deployToWAF3(ctx context.Context, certPem string, pri // 修改 CNAME 接入资源 // REF: https://help.aliyun.com/zh/waf/web-application-firewall-3-0/developer-reference/api-waf-openapi-2021-10-01-modifydomain - modifyDomainReq := &aliyunWaf.ModifyDomainRequest{ + modifyDomainReq := &aliwaf.ModifyDomainRequest{ InstanceId: tea.String(d.config.InstanceId), RegionId: tea.String(d.config.Region), Domain: tea.String(d.config.Domain), - Listen: &aliyunWaf.ModifyDomainRequestListen{ - CertId: tea.String(upres.CertId), - TLSVersion: tea.String("tlsv1"), - EnableTLSv3: tea.Bool(false), - }, - Redirect: &aliyunWaf.ModifyDomainRequestRedirect{ - Loadbalance: tea.String("iphash"), - }, - } - if describeDomainDetailResp.Body != nil && describeDomainDetailResp.Body.Listen != nil { - modifyDomainReq.Listen.TLSVersion = describeDomainDetailResp.Body.Listen.TLSVersion - modifyDomainReq.Listen.EnableTLSv3 = describeDomainDetailResp.Body.Listen.EnableTLSv3 - modifyDomainReq.Listen.FocusHttps = describeDomainDetailResp.Body.Listen.FocusHttps - } - if describeDomainDetailResp.Body != nil && describeDomainDetailResp.Body.Redirect != nil { - modifyDomainReq.Redirect.Loadbalance = describeDomainDetailResp.Body.Redirect.Loadbalance - modifyDomainReq.Redirect.FocusHttpBackend = describeDomainDetailResp.Body.Redirect.FocusHttpBackend - modifyDomainReq.Redirect.SniEnabled = describeDomainDetailResp.Body.Redirect.SniEnabled - modifyDomainReq.Redirect.SniHost = describeDomainDetailResp.Body.Redirect.SniHost + Listen: &aliwaf.ModifyDomainRequestListen{CertId: tea.String(upres.CertId)}, + Redirect: &aliwaf.ModifyDomainRequestRedirect{Loadbalance: tea.String("iphash")}, } + modifyDomainReq = assign(modifyDomainReq, describeDomainDetailResp.Body) modifyDomainResp, err := d.sdkClient.ModifyDomain(modifyDomainReq) d.logger.Debug("sdk request 'waf.ModifyDomain'", slog.Any("request", modifyDomainReq), slog.Any("response", modifyDomainResp)) if err != nil { @@ -186,15 +171,15 @@ func (d *DeployerProvider) deployToWAF3(ctx context.Context, certPem string, pri return nil } -func createSdkClient(accessKeyId, accessKeySecret, region string) (*aliyunWaf.Client, error) { +func createSdkClient(accessKeyId, accessKeySecret, region string) (*aliwaf.Client, error) { // 接入点一览:https://api.aliyun.com/product/waf-openapi - config := &aliyunOpen.Config{ + config := &aliopen.Config{ AccessKeyId: tea.String(accessKeyId), AccessKeySecret: tea.String(accessKeySecret), Endpoint: tea.String(fmt.Sprintf("wafopenapi.%s.aliyuncs.com", region)), } - client, err := aliyunWaf.NewClient(config) + client, err := aliwaf.NewClient(config) if err != nil { return nil, err } @@ -222,3 +207,166 @@ func createSslUploader(accessKeyId, accessKeySecret, region string) (uploader.Up }) return uploader, err } + +func assign(source *aliwaf.ModifyDomainRequest, target *aliwaf.DescribeDomainDetailResponseBody) *aliwaf.ModifyDomainRequest { + // `ModifyDomain` 中不传的字段表示使用默认值、而非保留原值, + // 因此这里需要把原配置中的参数重新赋值回去。 + + if target == nil { + return source + } + + if target.Listen != nil { + if source.Listen == nil { + source.Listen = &aliwaf.ModifyDomainRequestListen{} + } + + if target.Listen.CipherSuite != nil { + source.Listen.CipherSuite = tea.Int32(int32(*target.Listen.CipherSuite)) + } + + if target.Listen.CustomCiphers != nil { + source.Listen.CustomCiphers = target.Listen.CustomCiphers + } + + if target.Listen.EnableTLSv3 != nil { + source.Listen.EnableTLSv3 = target.Listen.EnableTLSv3 + } + + if target.Listen.ExclusiveIp != nil { + source.Listen.ExclusiveIp = target.Listen.ExclusiveIp + } + + if target.Listen.FocusHttps != nil { + source.Listen.FocusHttps = target.Listen.FocusHttps + } + + if target.Listen.Http2Enabled != nil { + source.Listen.Http2Enabled = target.Listen.Http2Enabled + } + + if target.Listen.HttpPorts != nil { + source.Listen.HttpPorts = sliceutil.Map(target.Listen.HttpPorts, func(v *int64) *int32 { + if v == nil { + return nil + } + return tea.Int32(int32(*v)) + }) + } + + if target.Listen.HttpsPorts != nil { + source.Listen.HttpsPorts = sliceutil.Map(target.Listen.HttpsPorts, func(v *int64) *int32 { + if v == nil { + return nil + } + return tea.Int32(int32(*v)) + }) + } + + if target.Listen.IPv6Enabled != nil { + source.Listen.IPv6Enabled = target.Listen.IPv6Enabled + } + + if target.Listen.ProtectionResource != nil { + source.Listen.ProtectionResource = target.Listen.ProtectionResource + } + + if target.Listen.TLSVersion != nil { + source.Listen.TLSVersion = target.Listen.TLSVersion + } + + if target.Listen.XffHeaderMode != nil { + source.Listen.XffHeaderMode = tea.Int32(int32(*target.Listen.XffHeaderMode)) + } + + if target.Listen.XffHeaders != nil { + source.Listen.XffHeaders = target.Listen.XffHeaders + } + } + + if target.Redirect != nil { + if source.Redirect == nil { + source.Redirect = &aliwaf.ModifyDomainRequestRedirect{} + } + + if target.Redirect.Backends != nil { + source.Redirect.Backends = sliceutil.Map(target.Redirect.Backends, func(v *aliwaf.DescribeDomainDetailResponseBodyRedirectBackends) *string { + if v == nil { + return nil + } + return v.Backend + }) + } + + if target.Redirect.BackupBackends != nil { + source.Redirect.BackupBackends = sliceutil.Map(target.Redirect.BackupBackends, func(v *aliwaf.DescribeDomainDetailResponseBodyRedirectBackupBackends) *string { + if v == nil { + return nil + } + return v.Backend + }) + } + + if target.Redirect.ConnectTimeout != nil { + source.Redirect.ConnectTimeout = target.Redirect.ConnectTimeout + } + + if target.Redirect.FocusHttpBackend != nil { + source.Redirect.FocusHttpBackend = target.Redirect.FocusHttpBackend + } + + if target.Redirect.Keepalive != nil { + source.Redirect.Keepalive = target.Redirect.Keepalive + } + + if target.Redirect.KeepaliveRequests != nil { + source.Redirect.KeepaliveRequests = target.Redirect.KeepaliveRequests + } + + if target.Redirect.KeepaliveTimeout != nil { + source.Redirect.KeepaliveTimeout = target.Redirect.KeepaliveTimeout + } + + if target.Redirect.Loadbalance != nil { + source.Redirect.Loadbalance = target.Redirect.Loadbalance + } + + if target.Redirect.ReadTimeout != nil { + source.Redirect.ReadTimeout = target.Redirect.ReadTimeout + } + + if target.Redirect.RequestHeaders != nil { + source.Redirect.RequestHeaders = sliceutil.Map(target.Redirect.RequestHeaders, func(v *aliwaf.DescribeDomainDetailResponseBodyRedirectRequestHeaders) *aliwaf.ModifyDomainRequestRedirectRequestHeaders { + if v == nil { + return nil + } + return &aliwaf.ModifyDomainRequestRedirectRequestHeaders{ + Key: v.Key, + Value: v.Value, + } + }) + } + + if target.Redirect.Retry != nil { + source.Redirect.Retry = target.Redirect.Retry + } + + if target.Redirect.SniEnabled != nil { + source.Redirect.SniEnabled = target.Redirect.SniEnabled + } + + if target.Redirect.SniHost != nil { + source.Redirect.SniHost = target.Redirect.SniHost + } + + if target.Redirect.WriteTimeout != nil { + source.Redirect.WriteTimeout = target.Redirect.WriteTimeout + } + + if target.Redirect.XffProto != nil { + source.Redirect.XffProto = target.Redirect.XffProto + } + } + + return source +} diff --git a/internal/pkg/core/deployer/providers/aws-cloudfront/aws_cloudfront.go b/internal/pkg/core/deployer/providers/aws-cloudfront/aws_cloudfront.go index 456799bd..6ebfaad2 100644 --- a/internal/pkg/core/deployer/providers/aws-cloudfront/aws_cloudfront.go +++ b/internal/pkg/core/deployer/providers/aws-cloudfront/aws_cloudfront.go @@ -6,10 +6,10 @@ import ( "log/slog" aws "github.com/aws/aws-sdk-go-v2/aws" - awsCfg "github.com/aws/aws-sdk-go-v2/config" - awsCred "github.com/aws/aws-sdk-go-v2/credentials" - awsCf "github.com/aws/aws-sdk-go-v2/service/cloudfront" - awsCfTypes "github.com/aws/aws-sdk-go-v2/service/cloudfront/types" + awscfg "github.com/aws/aws-sdk-go-v2/config" + awscred "github.com/aws/aws-sdk-go-v2/credentials" + "github.com/aws/aws-sdk-go-v2/service/cloudfront" + "github.com/aws/aws-sdk-go-v2/service/cloudfront/types" xerrors "github.com/pkg/errors" "github.com/usual2970/certimate/internal/pkg/core/deployer" @@ -31,7 +31,7 @@ type DeployerConfig struct { type DeployerProvider struct { config *DeployerConfig logger *slog.Logger - sdkClient *awsCf.Client + sdkClient *cloudfront.Client sslUploader uploader.Uploader } @@ -89,7 +89,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe // 获取分配配置 // REF: https://docs.aws.amazon.com/en_us/cloudfront/latest/APIReference/API_GetDistributionConfig.html - getDistributionConfigReq := &awsCf.GetDistributionConfigInput{ + getDistributionConfigReq := &cloudfront.GetDistributionConfigInput{ Id: aws.String(d.config.DistributionId), } getDistributionConfigResp, err := d.sdkClient.GetDistributionConfig(context.TODO(), getDistributionConfigReq) @@ -100,13 +100,13 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe // 更新分配配置 // REF: https://docs.aws.amazon.com/zh_cn/cloudfront/latest/APIReference/API_UpdateDistribution.html - updateDistributionReq := &awsCf.UpdateDistributionInput{ + updateDistributionReq := &cloudfront.UpdateDistributionInput{ Id: aws.String(d.config.DistributionId), DistributionConfig: getDistributionConfigResp.DistributionConfig, IfMatch: getDistributionConfigResp.ETag, } if updateDistributionReq.DistributionConfig.ViewerCertificate == nil { - updateDistributionReq.DistributionConfig.ViewerCertificate = &awsCfTypes.ViewerCertificate{} + updateDistributionReq.DistributionConfig.ViewerCertificate = &types.ViewerCertificate{} } updateDistributionReq.DistributionConfig.ViewerCertificate.CloudFrontDefaultCertificate = aws.Bool(false) updateDistributionReq.DistributionConfig.ViewerCertificate.ACMCertificateArn = aws.String(upres.CertId) @@ -119,15 +119,15 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe return &deployer.DeployResult{}, nil } -func createSdkClient(accessKeyId, secretAccessKey, region string) (*awsCf.Client, error) { - cfg, err := awsCfg.LoadDefaultConfig(context.TODO()) +func createSdkClient(accessKeyId, secretAccessKey, region string) (*cloudfront.Client, error) { + cfg, err := awscfg.LoadDefaultConfig(context.TODO()) if err != nil { return nil, err } - client := awsCf.NewFromConfig(cfg, func(o *awsCf.Options) { + client := cloudfront.NewFromConfig(cfg, func(o *cloudfront.Options) { o.Region = region - o.Credentials = aws.NewCredentialsCache(awsCred.NewStaticCredentialsProvider(accessKeyId, secretAccessKey, "")) + o.Credentials = aws.NewCredentialsCache(awscred.NewStaticCredentialsProvider(accessKeyId, secretAccessKey, "")) }) return client, nil } diff --git a/internal/pkg/core/deployer/providers/baiducloud-appblb/baiducloud_appblb.go b/internal/pkg/core/deployer/providers/baiducloud-appblb/baiducloud_appblb.go new file mode 100644 index 00000000..7a5f7ef2 --- /dev/null +++ b/internal/pkg/core/deployer/providers/baiducloud-appblb/baiducloud_appblb.go @@ -0,0 +1,332 @@ +package baiducloudappblb + +import ( + "context" + "errors" + "fmt" + "log/slog" + "strconv" + "strings" + + bceappblb "github.com/baidubce/bce-sdk-go/services/appblb" + "github.com/google/uuid" + xerrors "github.com/pkg/errors" + + "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" + "github.com/usual2970/certimate/internal/pkg/utils/sliceutil" +) + +type DeployerConfig struct { + // 百度智能云 AccessKeyId。 + AccessKeyId string `json:"accessKeyId"` + // 百度智能云 SecretAccessKey。 + SecretAccessKey string `json:"secretAccessKey"` + // 百度智能云区域。 + Region string `json:"region"` + // 部署资源类型。 + ResourceType ResourceType `json:"resourceType"` + // 负载均衡实例 ID。 + // 部署资源类型为 [RESOURCE_TYPE_LOADBALANCER]、[RESOURCE_TYPE_LISTENER] 时必填。 + LoadbalancerId string `json:"loadbalancerId,omitempty"` + // 负载均衡监听端口。 + // 部署资源类型为 [RESOURCE_TYPE_LISTENER] 时必填。 + ListenerPort int32 `json:"listenerPort,omitempty"` + // SNI 域名(支持泛域名)。 + // 部署资源类型为 [RESOURCE_TYPE_LOADBALANCER]、[RESOURCE_TYPE_LISTENER] 时选填。 + Domain string `json:"domain,omitempty"` +} + +type DeployerProvider struct { + config *DeployerConfig + logger *slog.Logger + sdkClient *bceappblb.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.SecretAccessKey, config.Region) + if err != nil { + return nil, xerrors.Wrap(err, "failed to create sdk client") + } + + uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ + AccessKeyId: config.AccessKeyId, + SecretAccessKey: config.SecretAccessKey, + }) + if err != nil { + return nil, xerrors.Wrap(err, "failed to create ssl uploader") + } + + 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.Default() + } 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, xerrors.Wrap(err, "failed to upload certificate file") + } else { + d.logger.Info("ssl certificate uploaded", slog.Any("result", upres)) + } + + // 根据部署资源类型决定部署方式 + switch d.config.ResourceType { + case RESOURCE_TYPE_LOADBALANCER: + if err := d.deployToLoadbalancer(ctx, upres.CertId); err != nil { + return nil, err + } + + case RESOURCE_TYPE_LISTENER: + if err := d.deployToListener(ctx, upres.CertId); err != nil { + return nil, err + } + + default: + return nil, fmt.Errorf("unsupported resource type: %s", d.config.ResourceType) + } + + return &deployer.DeployResult{}, nil +} + +func (d *DeployerProvider) deployToLoadbalancer(ctx context.Context, cloudCertId string) error { + if d.config.LoadbalancerId == "" { + return errors.New("config `loadbalancerId` is required") + } + + // 查询 BLB 实例详情 + // REF: https://cloud.baidu.com/doc/BLB/s/6jwvxnyhi#describeloadbalancerdetail%E6%9F%A5%E8%AF%A2blb%E5%AE%9E%E4%BE%8B%E8%AF%A6%E6%83%85 + describeLoadBalancerDetailResp, err := d.sdkClient.DescribeLoadBalancerDetail(d.config.LoadbalancerId) + d.logger.Debug("sdk request 'appblb.DescribeLoadBalancerAttribute'", slog.String("blbId", d.config.LoadbalancerId), slog.Any("response", describeLoadBalancerDetailResp)) + if err != nil { + return xerrors.Wrap(err, "failed to execute sdk request 'appblb.DescribeLoadBalancerDetail'") + } + + // 获取全部 HTTPS/SSL 监听端口 + listeners := make([]struct { + Type string + Port int32 + }, 0) + for _, listener := range describeLoadBalancerDetailResp.Listener { + if listener.Type == "HTTPS" || listener.Type == "SSL" { + listenerPort, err := strconv.Atoi(listener.Port) + if err != nil { + continue + } + + listeners = append(listeners, struct { + Type string + Port int32 + }{ + Type: listener.Type, + Port: int32(listenerPort), + }) + } + } + + // 遍历更新监听证书 + if len(listeners) == 0 { + d.logger.Info("no blb listeners to deploy") + } else { + d.logger.Info("found https/ssl listeners to deploy", slog.Any("listeners", listeners)) + var errs []error + + for _, listener := range listeners { + if err := d.updateListenerCertificate(ctx, d.config.LoadbalancerId, listener.Type, listener.Port, cloudCertId); err != nil { + errs = append(errs, err) + } + } + + if len(errs) > 0 { + return errors.Join(errs...) + } + } + + return nil +} + +func (d *DeployerProvider) deployToListener(ctx context.Context, cloudCertId string) error { + if d.config.LoadbalancerId == "" { + return errors.New("config `loadbalancerId` is required") + } + if d.config.ListenerPort == 0 { + return errors.New("config `listenerPort` is required") + } + + // 查询监听 + // REF: https://cloud.baidu.com/doc/BLB/s/ujwvxnyux#describeappalllisteners%E6%9F%A5%E8%AF%A2%E6%89%80%E6%9C%89%E7%9B%91%E5%90%AC + describeAppAllListenersRequest := &bceappblb.DescribeAppListenerArgs{ + ListenerPort: uint16(d.config.ListenerPort), + } + describeAppAllListenersResp, err := d.sdkClient.DescribeAppAllListeners(d.config.LoadbalancerId, describeAppAllListenersRequest) + d.logger.Debug("sdk request 'appblb.DescribeAppAllListeners'", slog.String("blbId", d.config.LoadbalancerId), slog.Any("request", describeAppAllListenersRequest), slog.Any("response", describeAppAllListenersResp)) + if err != nil { + return xerrors.Wrap(err, "failed to execute sdk request 'appblb.DescribeAppAllListeners'") + } + + // 获取全部 HTTPS/SSL 监听端口 + listeners := make([]struct { + Type string + Port int32 + }, 0) + for _, listener := range describeAppAllListenersResp.ListenerList { + if listener.ListenerType == "HTTPS" || listener.ListenerType == "SSL" { + listeners = append(listeners, struct { + Type string + Port int32 + }{ + Type: listener.ListenerType, + Port: int32(listener.ListenerPort), + }) + } + } + + // 遍历更新监听证书 + if len(listeners) == 0 { + d.logger.Info("no blb listeners to deploy") + } else { + d.logger.Info("found https/ssl listeners to deploy", slog.Any("listeners", listeners)) + var errs []error + + for _, listener := range listeners { + if err := d.updateListenerCertificate(ctx, d.config.LoadbalancerId, listener.Type, listener.Port, cloudCertId); err != nil { + errs = append(errs, err) + } + } + + if len(errs) > 0 { + return errors.Join(errs...) + } + } + + return nil +} + +func (d *DeployerProvider) updateListenerCertificate(ctx context.Context, cloudLoadbalancerId string, cloudListenerType string, cloudListenerPort int32, cloudCertId string) error { + switch strings.ToUpper(cloudListenerType) { + case "HTTPS": + return d.updateHttpsListenerCertificate(ctx, cloudLoadbalancerId, cloudListenerPort, cloudCertId) + case "SSL": + return d.updateSslListenerCertificate(ctx, cloudLoadbalancerId, cloudListenerPort, cloudCertId) + default: + return fmt.Errorf("unsupported listener type: %s", cloudListenerType) + } +} + +func (d *DeployerProvider) updateHttpsListenerCertificate(ctx context.Context, cloudLoadbalancerId string, cloudHttpsListenerPort int32, cloudCertId string) error { + // 查询 HTTPS 监听器 + // REF: https://cloud.baidu.com/doc/BLB/s/ujwvxnyux#describeapphttpslisteners%E6%9F%A5%E8%AF%A2https%E7%9B%91%E5%90%AC%E5%99%A8 + describeAppHTTPSListenersReq := &bceappblb.DescribeAppListenerArgs{ + ListenerPort: uint16(cloudHttpsListenerPort), + MaxKeys: 1, + } + describeAppHTTPSListenersResp, err := d.sdkClient.DescribeAppHTTPSListeners(cloudLoadbalancerId, describeAppHTTPSListenersReq) + d.logger.Debug("sdk request 'appblb.DescribeAppHTTPSListeners'", slog.String("blbId", cloudLoadbalancerId), slog.Any("request", describeAppHTTPSListenersReq), slog.Any("response", describeAppHTTPSListenersResp)) + if err != nil { + return xerrors.Wrap(err, "failed to execute sdk request 'appblb.DescribeAppHTTPSListeners'") + } else if len(describeAppHTTPSListenersResp.ListenerList) == 0 { + return fmt.Errorf("listener %s:%d not found", cloudLoadbalancerId, cloudHttpsListenerPort) + } + + if d.config.Domain == "" { + // 未指定 SNI,只需部署到监听器 + + // 更新 HTTPS 监听器 + // REF: https://cloud.baidu.com/doc/BLB/s/ujwvxnyux#updateapphttpslistener%E6%9B%B4%E6%96%B0https%E7%9B%91%E5%90%AC%E5%99%A8 + updateAppHTTPSListenerReq := &bceappblb.UpdateAppHTTPSListenerArgs{ + ClientToken: generateClientToken(), + ListenerPort: uint16(cloudHttpsListenerPort), + CertIds: []string{cloudCertId}, + } + err := d.sdkClient.UpdateAppHTTPSListener(cloudLoadbalancerId, updateAppHTTPSListenerReq) + d.logger.Debug("sdk request 'appblb.UpdateAppHTTPSListener'", slog.Any("request", updateAppHTTPSListenerReq)) + if err != nil { + return xerrors.Wrap(err, "failed to execute sdk request 'appblb.UpdateAppHTTPSListener'") + } + } else { + // 指定 SNI,需部署到扩展域名 + + // 更新 HTTPS 监听器 + // REF: https://cloud.baidu.com/doc/BLB/s/yjwvxnvl6#updatehttpslistener%E6%9B%B4%E6%96%B0https%E7%9B%91%E5%90%AC%E5%99%A8 + updateAppHTTPSListenerReq := &bceappblb.UpdateAppHTTPSListenerArgs{ + ClientToken: generateClientToken(), + ListenerPort: uint16(cloudHttpsListenerPort), + AdditionalCertDomains: sliceutil.Map(describeAppHTTPSListenersResp.ListenerList[0].AdditionalCertDomains, func(domain bceappblb.AdditionalCertDomainsModel) bceappblb.AdditionalCertDomainsModel { + if domain.Host == d.config.Domain { + return bceappblb.AdditionalCertDomainsModel{ + Host: domain.Host, + CertId: cloudCertId, + } + } + + return bceappblb.AdditionalCertDomainsModel{ + Host: domain.Host, + CertId: domain.CertId, + } + }), + } + err := d.sdkClient.UpdateAppHTTPSListener(cloudLoadbalancerId, updateAppHTTPSListenerReq) + d.logger.Debug("sdk request 'appblb.UpdateAppHTTPSListener'", slog.Any("request", updateAppHTTPSListenerReq)) + if err != nil { + return xerrors.Wrap(err, "failed to execute sdk request 'appblb.UpdateAppHTTPSListener'") + } + } + + return nil +} + +func (d *DeployerProvider) updateSslListenerCertificate(ctx context.Context, cloudLoadbalancerId string, cloudHttpsListenerPort int32, cloudCertId string) error { + // 更新 SSL 监听器 + // REF: https://cloud.baidu.com/doc/BLB/s/ujwvxnyux#updateappssllistener%E6%9B%B4%E6%96%B0ssl%E7%9B%91%E5%90%AC%E5%99%A8 + updateAppSSLListenerReq := &bceappblb.UpdateAppSSLListenerArgs{ + ClientToken: generateClientToken(), + ListenerPort: uint16(cloudHttpsListenerPort), + CertIds: []string{cloudCertId}, + } + err := d.sdkClient.UpdateAppSSLListener(cloudLoadbalancerId, updateAppSSLListenerReq) + d.logger.Debug("sdk request 'appblb.UpdateAppSSLListener'", slog.Any("request", updateAppSSLListenerReq)) + if err != nil { + return xerrors.Wrap(err, "failed to execute sdk request 'appblb.UpdateAppSSLListener'") + } + + return nil +} + +func createSdkClient(accessKeyId, secretAccessKey, region string) (*bceappblb.Client, error) { + endpoint := "" + if region != "" { + endpoint = fmt.Sprintf("blb.%s.baidubce.com", region) + } + + client, err := bceappblb.NewClient(accessKeyId, secretAccessKey, endpoint) + if err != nil { + return nil, err + } + + return client, nil +} + +func generateClientToken() string { + return strings.ReplaceAll(uuid.New().String(), "-", "") +} diff --git a/internal/pkg/core/deployer/providers/baiducloud-appblb/baiducloud_appblb_test.go b/internal/pkg/core/deployer/providers/baiducloud-appblb/baiducloud_appblb_test.go new file mode 100644 index 00000000..6753475c --- /dev/null +++ b/internal/pkg/core/deployer/providers/baiducloud-appblb/baiducloud_appblb_test.go @@ -0,0 +1,86 @@ +package baiducloudappblb_test + +import ( + "context" + "flag" + "fmt" + "os" + "strings" + "testing" + + provider "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/baiducloud-appblb" +) + +var ( + fInputCertPath string + fInputKeyPath string + fAccessKeyId string + fSecretAccessKey string + fRegion string + fLoadbalancerId string + fDomain string +) + +func init() { + argsPrefix := "CERTIMATE_DEPLOYER_BAIDUCLOUDAPPBLB_" + + flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "") + flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "") + flag.StringVar(&fAccessKeyId, argsPrefix+"ACCESSKEYID", "", "") + flag.StringVar(&fSecretAccessKey, argsPrefix+"SECRETACCESSKEY", "", "") + flag.StringVar(&fRegion, argsPrefix+"REGION", "", "") + flag.StringVar(&fLoadbalancerId, argsPrefix+"LOADBALANCERID", "", "") + flag.StringVar(&fDomain, argsPrefix+"DOMAIN", "", "") +} + +/* +Shell command to run this test: + + go test -v ./baiducloud_appblb_test.go -args \ + --CERTIMATE_DEPLOYER_BAIDUCLOUDAPPBLB_INPUTCERTPATH="/path/to/your-input-cert.pem" \ + --CERTIMATE_DEPLOYER_BAIDUCLOUDAPPBLB_INPUTKEYPATH="/path/to/your-input-key.pem" \ + --CERTIMATE_DEPLOYER_BAIDUCLOUDAPPBLB_ACCESSKEYID="your-access-key-id" \ + --CERTIMATE_DEPLOYER_BAIDUCLOUDAPPBLB_SECRETACCESSKEY="your-secret-access-key" \ + --CERTIMATE_DEPLOYER_BAIDUCLOUDAPPBLB_REGION="bj" \ + --CERTIMATE_DEPLOYER_BAIDUCLOUDAPPBLB_LOADBALANCERID="your-blb-loadbalancer-id" \ + --CERTIMATE_DEPLOYER_BAIDUCLOUDAPPBLB_DOMAIN="your-blb-sni-domain" +*/ +func TestDeploy(t *testing.T) { + flag.Parse() + + t.Run("Deploy", func(t *testing.T) { + t.Log(strings.Join([]string{ + "args:", + fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath), + fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath), + fmt.Sprintf("ACCESSKEYID: %v", fAccessKeyId), + fmt.Sprintf("SECRETACCESSKEY: %v", fSecretAccessKey), + fmt.Sprintf("REGION: %v", fRegion), + fmt.Sprintf("LOADBALANCERID: %v", fLoadbalancerId), + fmt.Sprintf("DOMAIN: %v", fDomain), + }, "\n")) + + deployer, err := provider.NewDeployer(&provider.DeployerConfig{ + AccessKeyId: fAccessKeyId, + SecretAccessKey: fSecretAccessKey, + ResourceType: provider.RESOURCE_TYPE_LOADBALANCER, + Region: fRegion, + LoadbalancerId: fLoadbalancerId, + Domain: fDomain, + }) + if err != nil { + t.Errorf("err: %+v", err) + return + } + + fInputCertData, _ := os.ReadFile(fInputCertPath) + fInputKeyData, _ := os.ReadFile(fInputKeyPath) + res, err := deployer.Deploy(context.Background(), string(fInputCertData), string(fInputKeyData)) + if err != nil { + t.Errorf("err: %+v", err) + return + } + + t.Logf("ok: %v", res) + }) +} diff --git a/internal/pkg/core/deployer/providers/baiducloud-appblb/consts.go b/internal/pkg/core/deployer/providers/baiducloud-appblb/consts.go new file mode 100644 index 00000000..3955f9a0 --- /dev/null +++ b/internal/pkg/core/deployer/providers/baiducloud-appblb/consts.go @@ -0,0 +1,10 @@ +package baiducloudappblb + +type ResourceType string + +const ( + // 资源类型:部署到指定负载均衡器。 + RESOURCE_TYPE_LOADBALANCER = ResourceType("loadbalancer") + // 资源类型:部署到指定监听器。 + RESOURCE_TYPE_LISTENER = ResourceType("listener") +) diff --git a/internal/pkg/core/deployer/providers/baiducloud-blb/baiducloud_blb.go b/internal/pkg/core/deployer/providers/baiducloud-blb/baiducloud_blb.go new file mode 100644 index 00000000..6be94e6d --- /dev/null +++ b/internal/pkg/core/deployer/providers/baiducloud-blb/baiducloud_blb.go @@ -0,0 +1,332 @@ +package baiducloudblb + +import ( + "context" + "errors" + "fmt" + "log/slog" + "strconv" + "strings" + + bceblb "github.com/baidubce/bce-sdk-go/services/blb" + "github.com/google/uuid" + xerrors "github.com/pkg/errors" + + "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" + "github.com/usual2970/certimate/internal/pkg/utils/sliceutil" +) + +type DeployerConfig struct { + // 百度智能云 AccessKeyId。 + AccessKeyId string `json:"accessKeyId"` + // 百度智能云 SecretAccessKey。 + SecretAccessKey string `json:"secretAccessKey"` + // 百度智能云区域。 + Region string `json:"region"` + // 部署资源类型。 + ResourceType ResourceType `json:"resourceType"` + // 负载均衡实例 ID。 + // 部署资源类型为 [RESOURCE_TYPE_LOADBALANCER]、[RESOURCE_TYPE_LISTENER] 时必填。 + LoadbalancerId string `json:"loadbalancerId,omitempty"` + // 负载均衡监听端口。 + // 部署资源类型为 [RESOURCE_TYPE_LISTENER] 时必填。 + ListenerPort int32 `json:"listenerPort,omitempty"` + // SNI 域名(支持泛域名)。 + // 部署资源类型为 [RESOURCE_TYPE_LOADBALANCER]、[RESOURCE_TYPE_LISTENER] 时选填。 + Domain string `json:"domain,omitempty"` +} + +type DeployerProvider struct { + config *DeployerConfig + logger *slog.Logger + sdkClient *bceblb.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.SecretAccessKey, config.Region) + if err != nil { + return nil, xerrors.Wrap(err, "failed to create sdk client") + } + + uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ + AccessKeyId: config.AccessKeyId, + SecretAccessKey: config.SecretAccessKey, + }) + if err != nil { + return nil, xerrors.Wrap(err, "failed to create ssl uploader") + } + + 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.Default() + } 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, xerrors.Wrap(err, "failed to upload certificate file") + } else { + d.logger.Info("ssl certificate uploaded", slog.Any("result", upres)) + } + + // 根据部署资源类型决定部署方式 + switch d.config.ResourceType { + case RESOURCE_TYPE_LOADBALANCER: + if err := d.deployToLoadbalancer(ctx, upres.CertId); err != nil { + return nil, err + } + + case RESOURCE_TYPE_LISTENER: + if err := d.deployToListener(ctx, upres.CertId); err != nil { + return nil, err + } + + default: + return nil, fmt.Errorf("unsupported resource type: %s", d.config.ResourceType) + } + + return &deployer.DeployResult{}, nil +} + +func (d *DeployerProvider) deployToLoadbalancer(ctx context.Context, cloudCertId string) error { + if d.config.LoadbalancerId == "" { + return errors.New("config `loadbalancerId` is required") + } + + // 查询 BLB 实例详情 + // REF: https://cloud.baidu.com/doc/BLB/s/njwvxnv79#describeloadbalancerdetail%E6%9F%A5%E8%AF%A2blb%E5%AE%9E%E4%BE%8B%E8%AF%A6%E6%83%85 + describeLoadBalancerDetailResp, err := d.sdkClient.DescribeLoadBalancerDetail(d.config.LoadbalancerId) + d.logger.Debug("sdk request 'blb.DescribeLoadBalancerAttribute'", slog.String("blbId", d.config.LoadbalancerId), slog.Any("response", describeLoadBalancerDetailResp)) + if err != nil { + return xerrors.Wrap(err, "failed to execute sdk request 'blb.DescribeLoadBalancerDetail'") + } + + // 获取全部 HTTPS/SSL 监听端口 + listeners := make([]struct { + Type string + Port int32 + }, 0) + for _, listener := range describeLoadBalancerDetailResp.Listener { + if listener.Type == "HTTPS" || listener.Type == "SSL" { + listenerPort, err := strconv.Atoi(listener.Port) + if err != nil { + continue + } + + listeners = append(listeners, struct { + Type string + Port int32 + }{ + Type: listener.Type, + Port: int32(listenerPort), + }) + } + } + + // 遍历更新监听证书 + if len(listeners) == 0 { + d.logger.Info("no blb listeners to deploy") + } else { + d.logger.Info("found https/ssl listeners to deploy", slog.Any("listeners", listeners)) + var errs []error + + for _, listener := range listeners { + if err := d.updateListenerCertificate(ctx, d.config.LoadbalancerId, listener.Type, listener.Port, cloudCertId); err != nil { + errs = append(errs, err) + } + } + + if len(errs) > 0 { + return errors.Join(errs...) + } + } + + return nil +} + +func (d *DeployerProvider) deployToListener(ctx context.Context, cloudCertId string) error { + if d.config.LoadbalancerId == "" { + return errors.New("config `loadbalancerId` is required") + } + if d.config.ListenerPort == 0 { + return errors.New("config `listenerPort` is required") + } + + // 查询监听 + // REF: https://cloud.baidu.com/doc/BLB/s/yjwvxnvl6#describealllisteners%E6%9F%A5%E8%AF%A2%E6%89%80%E6%9C%89%E7%9B%91%E5%90%AC + describeAllListenersRequest := &bceblb.DescribeListenerArgs{ + ListenerPort: uint16(d.config.ListenerPort), + } + describeAllListenersResp, err := d.sdkClient.DescribeAllListeners(d.config.LoadbalancerId, describeAllListenersRequest) + d.logger.Debug("sdk request 'blb.DescribeAllListeners'", slog.String("blbId", d.config.LoadbalancerId), slog.Any("request", describeAllListenersRequest), slog.Any("response", describeAllListenersResp)) + if err != nil { + return xerrors.Wrap(err, "failed to execute sdk request 'blb.DescribeAllListeners'") + } + + // 获取全部 HTTPS/SSL 监听端口 + listeners := make([]struct { + Type string + Port int32 + }, 0) + for _, listener := range describeAllListenersResp.AllListenerList { + if listener.ListenerType == "HTTPS" || listener.ListenerType == "SSL" { + listeners = append(listeners, struct { + Type string + Port int32 + }{ + Type: listener.ListenerType, + Port: int32(listener.ListenerPort), + }) + } + } + + // 遍历更新监听证书 + if len(listeners) == 0 { + d.logger.Info("no blb listeners to deploy") + } else { + d.logger.Info("found https/ssl listeners to deploy", slog.Any("listeners", listeners)) + var errs []error + + for _, listener := range listeners { + if err := d.updateListenerCertificate(ctx, d.config.LoadbalancerId, listener.Type, listener.Port, cloudCertId); err != nil { + errs = append(errs, err) + } + } + + if len(errs) > 0 { + return errors.Join(errs...) + } + } + + return nil +} + +func (d *DeployerProvider) updateListenerCertificate(ctx context.Context, cloudLoadbalancerId string, cloudListenerType string, cloudListenerPort int32, cloudCertId string) error { + switch strings.ToUpper(cloudListenerType) { + case "HTTPS": + return d.updateHttpsListenerCertificate(ctx, cloudLoadbalancerId, cloudListenerPort, cloudCertId) + case "SSL": + return d.updateSslListenerCertificate(ctx, cloudLoadbalancerId, cloudListenerPort, cloudCertId) + default: + return fmt.Errorf("unsupported listener type: %s", cloudListenerType) + } +} + +func (d *DeployerProvider) updateHttpsListenerCertificate(ctx context.Context, cloudLoadbalancerId string, cloudHttpsListenerPort int32, cloudCertId string) error { + // 查询 HTTPS 监听器 + // REF: https://cloud.baidu.com/doc/BLB/s/yjwvxnvl6#describehttpslisteners%E6%9F%A5%E8%AF%A2https%E7%9B%91%E5%90%AC%E5%99%A8 + describeHTTPSListenersReq := &bceblb.DescribeListenerArgs{ + ListenerPort: uint16(cloudHttpsListenerPort), + MaxKeys: 1, + } + describeHTTPSListenersResp, err := d.sdkClient.DescribeHTTPSListeners(cloudLoadbalancerId, describeHTTPSListenersReq) + d.logger.Debug("sdk request 'blb.DescribeHTTPSListeners'", slog.String("blbId", cloudLoadbalancerId), slog.Any("request", describeHTTPSListenersReq), slog.Any("response", describeHTTPSListenersResp)) + if err != nil { + return xerrors.Wrap(err, "failed to execute sdk request 'blb.DescribeHTTPSListeners'") + } else if len(describeHTTPSListenersResp.ListenerList) == 0 { + return fmt.Errorf("listener %s:%d not found", cloudLoadbalancerId, cloudHttpsListenerPort) + } + + if d.config.Domain == "" { + // 未指定 SNI,只需部署到监听器 + + // 更新 HTTPS 监听器 + // REF: https://cloud.baidu.com/doc/BLB/s/yjwvxnvl6#updatehttpslistener%E6%9B%B4%E6%96%B0https%E7%9B%91%E5%90%AC%E5%99%A8 + updateHTTPSListenerReq := &bceblb.UpdateHTTPSListenerArgs{ + ClientToken: generateClientToken(), + ListenerPort: uint16(cloudHttpsListenerPort), + CertIds: []string{cloudCertId}, + } + err := d.sdkClient.UpdateHTTPSListener(cloudLoadbalancerId, updateHTTPSListenerReq) + d.logger.Debug("sdk request 'blb.UpdateHTTPSListener'", slog.Any("request", updateHTTPSListenerReq)) + if err != nil { + return xerrors.Wrap(err, "failed to execute sdk request 'blb.UpdateHTTPSListener'") + } + } else { + // 指定 SNI,需部署到扩展域名 + + // 更新 HTTPS 监听器 + // REF: https://cloud.baidu.com/doc/BLB/s/yjwvxnvl6#updatehttpslistener%E6%9B%B4%E6%96%B0https%E7%9B%91%E5%90%AC%E5%99%A8 + updateHTTPSListenerReq := &bceblb.UpdateHTTPSListenerArgs{ + ClientToken: generateClientToken(), + ListenerPort: uint16(cloudHttpsListenerPort), + AdditionalCertDomains: sliceutil.Map(describeHTTPSListenersResp.ListenerList[0].AdditionalCertDomains, func(domain bceblb.AdditionalCertDomainsModel) bceblb.AdditionalCertDomainsModel { + if domain.Host == d.config.Domain { + return bceblb.AdditionalCertDomainsModel{ + Host: domain.Host, + CertId: cloudCertId, + } + } + + return bceblb.AdditionalCertDomainsModel{ + Host: domain.Host, + CertId: domain.CertId, + } + }), + } + err := d.sdkClient.UpdateHTTPSListener(cloudLoadbalancerId, updateHTTPSListenerReq) + d.logger.Debug("sdk request 'blb.UpdateHTTPSListener'", slog.Any("request", updateHTTPSListenerReq)) + if err != nil { + return xerrors.Wrap(err, "failed to execute sdk request 'blb.UpdateHTTPSListener'") + } + } + + return nil +} + +func (d *DeployerProvider) updateSslListenerCertificate(ctx context.Context, cloudLoadbalancerId string, cloudHttpsListenerPort int32, cloudCertId string) error { + // 更新 SSL 监听器 + // REF: https://cloud.baidu.com/doc/BLB/s/yjwvxnvl6#updatessllistener%E6%9B%B4%E6%96%B0ssl%E7%9B%91%E5%90%AC%E5%99%A8 + updateSSLListenerReq := &bceblb.UpdateSSLListenerArgs{ + ClientToken: generateClientToken(), + ListenerPort: uint16(cloudHttpsListenerPort), + CertIds: []string{cloudCertId}, + } + err := d.sdkClient.UpdateSSLListener(cloudLoadbalancerId, updateSSLListenerReq) + d.logger.Debug("sdk request 'blb.UpdateSSLListener'", slog.Any("request", updateSSLListenerReq)) + if err != nil { + return xerrors.Wrap(err, "failed to execute sdk request 'blb.UpdateSSLListener'") + } + + return nil +} + +func createSdkClient(accessKeyId, secretAccessKey, region string) (*bceblb.Client, error) { + endpoint := "" + if region != "" { + endpoint = fmt.Sprintf("blb.%s.baidubce.com", region) + } + + client, err := bceblb.NewClient(accessKeyId, secretAccessKey, endpoint) + if err != nil { + return nil, err + } + + return client, nil +} + +func generateClientToken() string { + return strings.ReplaceAll(uuid.New().String(), "-", "") +} diff --git a/internal/pkg/core/deployer/providers/baiducloud-blb/baiducloud_blb_test.go b/internal/pkg/core/deployer/providers/baiducloud-blb/baiducloud_blb_test.go new file mode 100644 index 00000000..756e6f8f --- /dev/null +++ b/internal/pkg/core/deployer/providers/baiducloud-blb/baiducloud_blb_test.go @@ -0,0 +1,86 @@ +package baiducloudblb_test + +import ( + "context" + "flag" + "fmt" + "os" + "strings" + "testing" + + provider "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/baiducloud-blb" +) + +var ( + fInputCertPath string + fInputKeyPath string + fAccessKeyId string + fSecretAccessKey string + fRegion string + fLoadbalancerId string + fDomain string +) + +func init() { + argsPrefix := "CERTIMATE_DEPLOYER_BAIDUCLOUDBLB_" + + flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "") + flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "") + flag.StringVar(&fAccessKeyId, argsPrefix+"ACCESSKEYID", "", "") + flag.StringVar(&fSecretAccessKey, argsPrefix+"SECRETACCESSKEY", "", "") + flag.StringVar(&fRegion, argsPrefix+"REGION", "", "") + flag.StringVar(&fLoadbalancerId, argsPrefix+"LOADBALANCERID", "", "") + flag.StringVar(&fDomain, argsPrefix+"DOMAIN", "", "") +} + +/* +Shell command to run this test: + + go test -v ./baiducloud_blb_test.go -args \ + --CERTIMATE_DEPLOYER_BAIDUCLOUDBLB_INPUTCERTPATH="/path/to/your-input-cert.pem" \ + --CERTIMATE_DEPLOYER_BAIDUCLOUDBLB_INPUTKEYPATH="/path/to/your-input-key.pem" \ + --CERTIMATE_DEPLOYER_BAIDUCLOUDBLB_ACCESSKEYID="your-access-key-id" \ + --CERTIMATE_DEPLOYER_BAIDUCLOUDBLB_SECRETACCESSKEY="your-secret-access-key" \ + --CERTIMATE_DEPLOYER_BAIDUCLOUDBLB_REGION="bj" \ + --CERTIMATE_DEPLOYER_BAIDUCLOUDBLB_LOADBALANCERID="your-blb-loadbalancer-id" \ + --CERTIMATE_DEPLOYER_BAIDUCLOUDBLB_DOMAIN="your-blb-sni-domain" +*/ +func TestDeploy(t *testing.T) { + flag.Parse() + + t.Run("Deploy", func(t *testing.T) { + t.Log(strings.Join([]string{ + "args:", + fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath), + fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath), + fmt.Sprintf("ACCESSKEYID: %v", fAccessKeyId), + fmt.Sprintf("SECRETACCESSKEY: %v", fSecretAccessKey), + fmt.Sprintf("REGION: %v", fRegion), + fmt.Sprintf("LOADBALANCERID: %v", fLoadbalancerId), + fmt.Sprintf("DOMAIN: %v", fDomain), + }, "\n")) + + deployer, err := provider.NewDeployer(&provider.DeployerConfig{ + AccessKeyId: fAccessKeyId, + SecretAccessKey: fSecretAccessKey, + ResourceType: provider.RESOURCE_TYPE_LOADBALANCER, + Region: fRegion, + LoadbalancerId: fLoadbalancerId, + Domain: fDomain, + }) + if err != nil { + t.Errorf("err: %+v", err) + return + } + + fInputCertData, _ := os.ReadFile(fInputCertPath) + fInputKeyData, _ := os.ReadFile(fInputKeyPath) + res, err := deployer.Deploy(context.Background(), string(fInputCertData), string(fInputKeyData)) + if err != nil { + t.Errorf("err: %+v", err) + return + } + + t.Logf("ok: %v", res) + }) +} diff --git a/internal/pkg/core/deployer/providers/baiducloud-blb/consts.go b/internal/pkg/core/deployer/providers/baiducloud-blb/consts.go new file mode 100644 index 00000000..52cb8804 --- /dev/null +++ b/internal/pkg/core/deployer/providers/baiducloud-blb/consts.go @@ -0,0 +1,10 @@ +package baiducloudblb + +type ResourceType string + +const ( + // 资源类型:部署到指定负载均衡器。 + RESOURCE_TYPE_LOADBALANCER = ResourceType("loadbalancer") + // 资源类型:部署到指定监听器。 + RESOURCE_TYPE_LISTENER = ResourceType("listener") +) diff --git a/internal/pkg/core/deployer/providers/baiducloud-cdn/baiducloud_cdn.go b/internal/pkg/core/deployer/providers/baiducloud-cdn/baiducloud_cdn.go index a31a21ec..87f5aa5c 100644 --- a/internal/pkg/core/deployer/providers/baiducloud-cdn/baiducloud_cdn.go +++ b/internal/pkg/core/deployer/providers/baiducloud-cdn/baiducloud_cdn.go @@ -6,8 +6,8 @@ import ( "log/slog" "time" - bceCdn "github.com/baidubce/bce-sdk-go/services/cdn" - bceCdnApi "github.com/baidubce/bce-sdk-go/services/cdn/api" + bcecdn "github.com/baidubce/bce-sdk-go/services/cdn" + bcecdnapi "github.com/baidubce/bce-sdk-go/services/cdn/api" xerrors "github.com/pkg/errors" "github.com/usual2970/certimate/internal/pkg/core/deployer" @@ -25,7 +25,7 @@ type DeployerConfig struct { type DeployerProvider struct { config *DeployerConfig logger *slog.Logger - sdkClient *bceCdn.Client + sdkClient *bcecdn.Client } var _ deployer.Deployer = (*DeployerProvider)(nil) @@ -61,7 +61,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe // REF: https://cloud.baidu.com/doc/CDN/s/qjzuz2hp8 putCertResp, err := d.sdkClient.PutCert( d.config.Domain, - &bceCdnApi.UserCertificate{ + &bcecdnapi.UserCertificate{ CertName: fmt.Sprintf("certimate-%d", time.Now().UnixMilli()), ServerData: certPem, PrivateData: privkeyPem, @@ -76,8 +76,8 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe return &deployer.DeployResult{}, nil } -func createSdkClient(accessKeyId, secretAccessKey string) (*bceCdn.Client, error) { - client, err := bceCdn.NewClient(accessKeyId, secretAccessKey, "") +func createSdkClient(accessKeyId, secretAccessKey string) (*bcecdn.Client, error) { + client, err := bcecdn.NewClient(accessKeyId, secretAccessKey, "") if err != nil { return nil, err } diff --git a/internal/pkg/core/deployer/providers/baiducloud-cert/baiducloud_cert.go b/internal/pkg/core/deployer/providers/baiducloud-cert/baiducloud_cert.go new file mode 100644 index 00000000..d51018f0 --- /dev/null +++ b/internal/pkg/core/deployer/providers/baiducloud-cert/baiducloud_cert.go @@ -0,0 +1,68 @@ +package baiducloudcert + +import ( + "context" + "log/slog" + + xerrors "github.com/pkg/errors" + + "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, xerrors.Wrap(err, "failed to create ssl uploader") + } + + 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.Default() + } 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, xerrors.Wrap(err, "failed to upload certificate file") + } else { + d.logger.Info("ssl certificate uploaded", slog.Any("result", upres)) + } + + return &deployer.DeployResult{}, nil +} diff --git a/internal/pkg/core/deployer/providers/baishan-cdn/baishan_cdn.go b/internal/pkg/core/deployer/providers/baishan-cdn/baishan_cdn.go index 3435b26e..e6aec2ab 100644 --- a/internal/pkg/core/deployer/providers/baishan-cdn/baishan_cdn.go +++ b/internal/pkg/core/deployer/providers/baishan-cdn/baishan_cdn.go @@ -2,9 +2,12 @@ import ( "context" + "encoding/json" "errors" "fmt" "log/slog" + "regexp" + "strings" "time" xerrors "github.com/pkg/errors" @@ -75,6 +78,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe // 新增证书 // REF: https://portal.baishancloud.com/track/document/downloadPdf/1441 + certificateId := "" createCertificateReq := &bssdk.CreateCertificateRequest{ Certificate: certPem, Key: privkeyPem, @@ -83,7 +87,19 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe createCertificateResp, err := d.sdkClient.CreateCertificate(createCertificateReq) d.logger.Debug("sdk request 'baishan.CreateCertificate'", slog.Any("request", createCertificateReq), slog.Any("response", createCertificateResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'baishan.CreateCertificate'") + if createCertificateResp != nil { + if createCertificateResp.GetCode() == 400699 && strings.Contains(createCertificateResp.GetMessage(), "this certificate is exists") { + // 证书已存在,忽略新增证书接口错误 + re := regexp.MustCompile(`\d+`) + certificateId = re.FindString(createCertificateResp.GetMessage()) + } + } + + if certificateId == "" { + return nil, xerrors.Wrap(err, "failed to execute sdk request 'baishan.CreateCertificate'") + } + } else { + certificateId = createCertificateResp.Data.CertId.String() } // 设置域名配置 @@ -92,7 +108,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe Domains: d.config.Domain, Config: &bssdk.DomainConfig{ Https: &bssdk.DomainConfigHttps{ - CertId: createCertificateResp.Data.CertId, + CertId: json.Number(certificateId), ForceHttps: getDomainConfigResp.Data[0].Config.Https.ForceHttps, EnableHttp2: getDomainConfigResp.Data[0].Config.Https.EnableHttp2, EnableOcsp: getDomainConfigResp.Data[0].Config.Https.EnableOcsp, diff --git a/internal/pkg/core/deployer/providers/byteplus-cdn/byteplus_cdn.go b/internal/pkg/core/deployer/providers/byteplus-cdn/byteplus_cdn.go index b8bd8856..7406f074 100644 --- a/internal/pkg/core/deployer/providers/byteplus-cdn/byteplus_cdn.go +++ b/internal/pkg/core/deployer/providers/byteplus-cdn/byteplus_cdn.go @@ -6,7 +6,7 @@ import ( "log/slog" "strings" - bpCdn "github.com/byteplus-sdk/byteplus-sdk-golang/service/cdn" + bpcdn "github.com/byteplus-sdk/byteplus-sdk-golang/service/cdn" xerrors "github.com/pkg/errors" "github.com/usual2970/certimate/internal/pkg/core/deployer" @@ -26,7 +26,7 @@ type DeployerConfig struct { type DeployerProvider struct { config *DeployerConfig logger *slog.Logger - sdkClient *bpCdn.CDN + sdkClient *bpcdn.CDN sslUploader uploader.Uploader } @@ -37,7 +37,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { panic("config is nil") } - client := bpCdn.NewInstance() + client := bpcdn.NewInstance() client.Client.SetAccessKey(config.AccessKey) client.Client.SetSecretKey(config.SecretKey) @@ -80,7 +80,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe if strings.HasPrefix(d.config.Domain, "*.") { // 获取指定证书可关联的域名 // REF: https://docs.byteplus.com/en/docs/byteplus-cdn/reference-describecertconfig-9ea17 - describeCertConfigReq := &bpCdn.DescribeCertConfigRequest{ + describeCertConfigReq := &bpcdn.DescribeCertConfigRequest{ CertId: upres.CertId, } describeCertConfigResp, err := d.sdkClient.DescribeCertConfig(describeCertConfigReq) @@ -119,7 +119,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe for _, domain := range domains { // 关联证书与加速域名 // REF: https://docs.byteplus.com/en/docs/byteplus-cdn/reference-batchdeploycert - batchDeployCertReq := &bpCdn.BatchDeployCertRequest{ + batchDeployCertReq := &bpcdn.BatchDeployCertRequest{ CertId: upres.CertId, Domain: domain, } diff --git a/internal/pkg/core/deployer/providers/edgio-applications/edgio_applications.go b/internal/pkg/core/deployer/providers/edgio-applications/edgio_applications.go index 6e21444c..8ce6c73d 100644 --- a/internal/pkg/core/deployer/providers/edgio-applications/edgio_applications.go +++ b/internal/pkg/core/deployer/providers/edgio-applications/edgio_applications.go @@ -9,7 +9,7 @@ import ( "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/utils/certutil" edgsdk "github.com/usual2970/certimate/internal/pkg/vendors/edgio-sdk/applications/v7" - edgsdkDtos "github.com/usual2970/certimate/internal/pkg/vendors/edgio-sdk/applications/v7/dtos" + edgsdkdtos "github.com/usual2970/certimate/internal/pkg/vendors/edgio-sdk/applications/v7/dtos" ) type DeployerConfig struct { @@ -64,7 +64,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe // 上传 TLS 证书 // REF: https://docs.edg.io/rest_api/#tag/tls-certs/operation/postConfigV01TlsCerts - uploadTlsCertReq := edgsdkDtos.UploadTlsCertRequest{ + uploadTlsCertReq := edgsdkdtos.UploadTlsCertRequest{ EnvironmentID: d.config.EnvironmentId, PrimaryCert: privateCertPem, IntermediateCert: intermediateCertPem, diff --git a/internal/pkg/core/deployer/providers/huaweicloud-cdn/huaweicloud_cdn.go b/internal/pkg/core/deployer/providers/huaweicloud-cdn/huaweicloud_cdn.go index d05d6503..048ccbd2 100644 --- a/internal/pkg/core/deployer/providers/huaweicloud-cdn/huaweicloud_cdn.go +++ b/internal/pkg/core/deployer/providers/huaweicloud-cdn/huaweicloud_cdn.go @@ -5,9 +5,9 @@ import ( "log/slog" "github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/global" - hcCdn "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/cdn/v2" - hcCdnModel "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/cdn/v2/model" - hcCdnRegion "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/cdn/v2/region" + hccdn "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/cdn/v2" + hccdnmodel "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/cdn/v2/model" + hccdnregion "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/cdn/v2/region" xerrors "github.com/pkg/errors" "github.com/usual2970/certimate/internal/pkg/core/deployer" @@ -30,7 +30,7 @@ type DeployerConfig struct { type DeployerProvider struct { config *DeployerConfig logger *slog.Logger - sdkClient *hcCdn.CdnClient + sdkClient *hccdn.CdnClient sslUploader uploader.Uploader } @@ -87,7 +87,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe // 查询加速域名配置 // REF: https://support.huaweicloud.com/api-cdn/ShowDomainFullConfig.html - showDomainFullConfigReq := &hcCdnModel.ShowDomainFullConfigRequest{ + showDomainFullConfigReq := &hccdnmodel.ShowDomainFullConfigRequest{ DomainName: d.config.Domain, } showDomainFullConfigResp, err := d.sdkClient.ShowDomainFullConfig(showDomainFullConfigReq) @@ -99,15 +99,15 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe // 更新加速域名配置 // REF: https://support.huaweicloud.com/api-cdn/UpdateDomainMultiCertificates.html // REF: https://support.huaweicloud.com/usermanual-cdn/cdn_01_0306.html - updateDomainMultiCertificatesReqBodyContent := &hcCdnModel.UpdateDomainMultiCertificatesRequestBodyContent{} + updateDomainMultiCertificatesReqBodyContent := &hccdnmodel.UpdateDomainMultiCertificatesRequestBodyContent{} updateDomainMultiCertificatesReqBodyContent.DomainName = d.config.Domain updateDomainMultiCertificatesReqBodyContent.HttpsSwitch = 1 updateDomainMultiCertificatesReqBodyContent.CertificateType = hwsdk.Int32Ptr(2) updateDomainMultiCertificatesReqBodyContent.ScmCertificateId = hwsdk.StringPtr(upres.CertId) updateDomainMultiCertificatesReqBodyContent.CertName = hwsdk.StringPtr(upres.CertName) updateDomainMultiCertificatesReqBodyContent = assign(updateDomainMultiCertificatesReqBodyContent, showDomainFullConfigResp.Configs) - updateDomainMultiCertificatesReq := &hcCdnModel.UpdateDomainMultiCertificatesRequest{ - Body: &hcCdnModel.UpdateDomainMultiCertificatesRequestBody{ + updateDomainMultiCertificatesReq := &hccdnmodel.UpdateDomainMultiCertificatesRequest{ + Body: &hccdnmodel.UpdateDomainMultiCertificatesRequestBody{ Https: updateDomainMultiCertificatesReqBodyContent, }, } @@ -120,7 +120,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe return &deployer.DeployResult{}, nil } -func createSdkClient(accessKeyId, secretAccessKey, region string) (*hcCdn.CdnClient, error) { +func createSdkClient(accessKeyId, secretAccessKey, region string) (*hccdn.CdnClient, error) { if region == "" { region = "cn-north-1" // CDN 服务默认区域:华北一北京 } @@ -133,12 +133,12 @@ func createSdkClient(accessKeyId, secretAccessKey, region string) (*hcCdn.CdnCli return nil, err } - hcRegion, err := hcCdnRegion.SafeValueOf(region) + hcRegion, err := hccdnregion.SafeValueOf(region) if err != nil { return nil, err } - hcClient, err := hcCdn.CdnClientBuilder(). + hcClient, err := hccdn.CdnClientBuilder(). WithRegion(hcRegion). WithCredential(auth). SafeBuild() @@ -146,42 +146,44 @@ func createSdkClient(accessKeyId, secretAccessKey, region string) (*hcCdn.CdnCli return nil, err } - client := hcCdn.NewCdnClient(hcClient) + client := hccdn.NewCdnClient(hcClient) return client, nil } -func assign(reqContent *hcCdnModel.UpdateDomainMultiCertificatesRequestBodyContent, target *hcCdnModel.ConfigsGetBody) *hcCdnModel.UpdateDomainMultiCertificatesRequestBodyContent { +func assign(source *hccdnmodel.UpdateDomainMultiCertificatesRequestBodyContent, target *hccdnmodel.ConfigsGetBody) *hccdnmodel.UpdateDomainMultiCertificatesRequestBodyContent { + // `UpdateDomainMultiCertificates` 中不传的字段表示使用默认值、而非保留原值, + // 因此这里需要把原配置中的参数重新赋值回去。 + if target == nil { - return reqContent + return source } - // 华为云 API 中不传的字段表示使用默认值、而非保留原值,因此这里需要把原配置中的参数重新赋值回去。 - // 而且蛋疼的是查询接口返回的数据结构和更新接口传入的参数结构不一致,需要做很多转化。 - if *target.OriginProtocol == "follow" { - reqContent.AccessOriginWay = hwsdk.Int32Ptr(1) + source.AccessOriginWay = hwsdk.Int32Ptr(1) } else if *target.OriginProtocol == "http" { - reqContent.AccessOriginWay = hwsdk.Int32Ptr(2) + source.AccessOriginWay = hwsdk.Int32Ptr(2) } else if *target.OriginProtocol == "https" { - reqContent.AccessOriginWay = hwsdk.Int32Ptr(3) + source.AccessOriginWay = hwsdk.Int32Ptr(3) } if target.ForceRedirect != nil { - reqContent.ForceRedirectConfig = &hcCdnModel.ForceRedirect{} + if source.ForceRedirectConfig == nil { + source.ForceRedirectConfig = &hccdnmodel.ForceRedirect{} + } if target.ForceRedirect.Status == "on" { - reqContent.ForceRedirectConfig.Switch = 1 - reqContent.ForceRedirectConfig.RedirectType = target.ForceRedirect.Type + source.ForceRedirectConfig.Switch = 1 + source.ForceRedirectConfig.RedirectType = target.ForceRedirect.Type } else { - reqContent.ForceRedirectConfig.Switch = 0 + source.ForceRedirectConfig.Switch = 0 } } if target.Https != nil { if *target.Https.Http2Status == "on" { - reqContent.Http2 = hwsdk.Int32Ptr(1) + source.Http2 = hwsdk.Int32Ptr(1) } } - return reqContent + return source } diff --git a/internal/pkg/core/deployer/providers/huaweicloud-elb/huaweicloud_elb.go b/internal/pkg/core/deployer/providers/huaweicloud-elb/huaweicloud_elb.go index 618af762..904c138f 100644 --- a/internal/pkg/core/deployer/providers/huaweicloud-elb/huaweicloud_elb.go +++ b/internal/pkg/core/deployer/providers/huaweicloud-elb/huaweicloud_elb.go @@ -8,12 +8,12 @@ import ( "github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/basic" "github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/global" - hcElb "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/elb/v3" - hcElbModel "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/elb/v3/model" - hcElbRegion "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/elb/v3/region" - hcIam "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/iam/v3" - hcIamModel "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/iam/v3/model" - hcIamRegion "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/iam/v3/region" + hcelb "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/elb/v3" + hcelbmodel "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/elb/v3/model" + hcelbregion "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/elb/v3/region" + hciam "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/iam/v3" + hciammodel "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/iam/v3/model" + hciamregion "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/iam/v3/region" xerrors "github.com/pkg/errors" "golang.org/x/exp/slices" @@ -46,7 +46,7 @@ type DeployerConfig struct { type DeployerProvider struct { config *DeployerConfig logger *slog.Logger - sdkClient *hcElb.ElbClient + sdkClient *hcelb.ElbClient sslUploader uploader.Uploader } @@ -121,10 +121,10 @@ func (d *DeployerProvider) deployToCertificate(ctx context.Context, certPem stri // 更新证书 // REF: https://support.huaweicloud.com/api-elb/UpdateCertificate.html - updateCertificateReq := &hcElbModel.UpdateCertificateRequest{ + updateCertificateReq := &hcelbmodel.UpdateCertificateRequest{ CertificateId: d.config.CertificateId, - Body: &hcElbModel.UpdateCertificateRequestBody{ - Certificate: &hcElbModel.UpdateCertificateOption{ + Body: &hcelbmodel.UpdateCertificateRequestBody{ + Certificate: &hcelbmodel.UpdateCertificateOption{ Certificate: hwsdk.StringPtr(certPem), PrivateKey: hwsdk.StringPtr(privkeyPem), }, @@ -146,7 +146,7 @@ func (d *DeployerProvider) deployToLoadbalancer(ctx context.Context, certPem str // 查询负载均衡器详情 // REF: https://support.huaweicloud.com/api-elb/ShowLoadBalancer.html - showLoadBalancerReq := &hcElbModel.ShowLoadBalancerRequest{ + showLoadBalancerReq := &hcelbmodel.ShowLoadBalancerRequest{ LoadbalancerId: d.config.LoadbalancerId, } showLoadBalancerResp, err := d.sdkClient.ShowLoadBalancer(showLoadBalancerReq) @@ -161,7 +161,7 @@ func (d *DeployerProvider) deployToLoadbalancer(ctx context.Context, certPem str listListenersLimit := int32(2000) var listListenersMarker *string = nil for { - listListenersReq := &hcElbModel.ListListenersRequest{ + listListenersReq := &hcelbmodel.ListListenersRequest{ Limit: hwsdk.Int32Ptr(listListenersLimit), Marker: listListenersMarker, Protocol: &[]string{"HTTPS", "TERMINATED_HTTPS"}, @@ -239,7 +239,7 @@ func (d *DeployerProvider) deployToListener(ctx context.Context, certPem string, func (d *DeployerProvider) modifyListenerCertificate(ctx context.Context, cloudListenerId string, cloudCertId string) error { // 查询监听器详情 // REF: https://support.huaweicloud.com/api-elb/ShowListener.html - showListenerReq := &hcElbModel.ShowListenerRequest{ + showListenerReq := &hcelbmodel.ShowListenerRequest{ ListenerId: cloudListenerId, } showListenerResp, err := d.sdkClient.ShowListener(showListenerReq) @@ -250,10 +250,10 @@ func (d *DeployerProvider) modifyListenerCertificate(ctx context.Context, cloudL // 更新监听器 // REF: https://support.huaweicloud.com/api-elb/UpdateListener.html - updateListenerReq := &hcElbModel.UpdateListenerRequest{ + updateListenerReq := &hcelbmodel.UpdateListenerRequest{ ListenerId: cloudListenerId, - Body: &hcElbModel.UpdateListenerRequestBody{ - Listener: &hcElbModel.UpdateListenerOption{ + Body: &hcelbmodel.UpdateListenerRequestBody{ + Listener: &hcelbmodel.UpdateListenerOption{ DefaultTlsContainerRef: hwsdk.StringPtr(cloudCertId), }, }, @@ -264,7 +264,7 @@ func (d *DeployerProvider) modifyListenerCertificate(ctx context.Context, cloudL sniCertIds := make([]string, 0) sniCertIds = append(sniCertIds, cloudCertId) - listOldCertificateReq := &hcElbModel.ListCertificatesRequest{ + listOldCertificateReq := &hcelbmodel.ListCertificatesRequest{ Id: &showListenerResp.Listener.SniContainerRefs, } listOldCertificateResp, err := d.sdkClient.ListCertificates(listOldCertificateReq) @@ -273,7 +273,7 @@ func (d *DeployerProvider) modifyListenerCertificate(ctx context.Context, cloudL return xerrors.Wrap(err, "failed to execute sdk request 'elb.ListCertificates'") } - showNewCertificateReq := &hcElbModel.ShowCertificateRequest{ + showNewCertificateReq := &hcelbmodel.ShowCertificateRequest{ CertificateId: cloudCertId, } showNewCertificateResp, err := d.sdkClient.ShowCertificate(showNewCertificateReq) @@ -315,7 +315,7 @@ func (d *DeployerProvider) modifyListenerCertificate(ctx context.Context, cloudL return nil } -func createSdkClient(accessKeyId, secretAccessKey, region string) (*hcElb.ElbClient, error) { +func createSdkClient(accessKeyId, secretAccessKey, region string) (*hcelb.ElbClient, error) { projectId, err := getSdkProjectId(accessKeyId, secretAccessKey, region) if err != nil { return nil, err @@ -330,12 +330,12 @@ func createSdkClient(accessKeyId, secretAccessKey, region string) (*hcElb.ElbCli return nil, err } - hcRegion, err := hcElbRegion.SafeValueOf(region) + hcRegion, err := hcelbregion.SafeValueOf(region) if err != nil { return nil, err } - hcClient, err := hcElb.ElbClientBuilder(). + hcClient, err := hcelb.ElbClientBuilder(). WithRegion(hcRegion). WithCredential(auth). SafeBuild() @@ -343,7 +343,7 @@ func createSdkClient(accessKeyId, secretAccessKey, region string) (*hcElb.ElbCli return nil, err } - client := hcElb.NewElbClient(hcClient) + client := hcelb.NewElbClient(hcClient) return client, nil } @@ -360,12 +360,12 @@ func getSdkProjectId(accessKeyId, secretAccessKey, region string) (string, error return "", err } - hcRegion, err := hcIamRegion.SafeValueOf(region) + hcRegion, err := hciamregion.SafeValueOf(region) if err != nil { return "", err } - hcClient, err := hcIam.IamClientBuilder(). + hcClient, err := hciam.IamClientBuilder(). WithRegion(hcRegion). WithCredential(auth). SafeBuild() @@ -373,9 +373,9 @@ func getSdkProjectId(accessKeyId, secretAccessKey, region string) (string, error return "", err } - client := hcIam.NewIamClient(hcClient) + client := hciam.NewIamClient(hcClient) - request := &hcIamModel.KeystoneListProjectsRequest{ + request := &hciammodel.KeystoneListProjectsRequest{ Name: ®ion, } response, err := client.KeystoneListProjects(request) diff --git a/internal/pkg/core/deployer/providers/huaweicloud-scm/huaweicloud_scm.go b/internal/pkg/core/deployer/providers/huaweicloud-scm/huaweicloud_scm.go new file mode 100644 index 00000000..69b75f2f --- /dev/null +++ b/internal/pkg/core/deployer/providers/huaweicloud-scm/huaweicloud_scm.go @@ -0,0 +1,69 @@ +package huaweicloudscm + +import ( + "context" + "log/slog" + + xerrors "github.com/pkg/errors" + + "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"` +} + +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, xerrors.Wrap(err, "failed to create ssl uploader") + } + + 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.Default() + } 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, xerrors.Wrap(err, "failed to upload certificate file") + } else { + d.logger.Info("ssl certificate uploaded", slog.Any("result", upres)) + } + + return &deployer.DeployResult{}, nil +} diff --git a/internal/pkg/core/deployer/providers/huaweicloud-waf/huaweicloud_waf.go b/internal/pkg/core/deployer/providers/huaweicloud-waf/huaweicloud_waf.go index 9d124191..0e29567c 100644 --- a/internal/pkg/core/deployer/providers/huaweicloud-waf/huaweicloud_waf.go +++ b/internal/pkg/core/deployer/providers/huaweicloud-waf/huaweicloud_waf.go @@ -9,12 +9,12 @@ import ( "github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/basic" "github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/global" - hcIam "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/iam/v3" - hcIamModel "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/iam/v3/model" - hcIamRegion "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/iam/v3/region" - hcWaf "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/waf/v1" - hcWafModel "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/waf/v1/model" - hcWafRegion "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/waf/v1/region" + hciam "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/iam/v3" + hciamModel "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/iam/v3/model" + hciamregion "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/iam/v3/region" + hcwaf "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/waf/v1" + hcwafmodel "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/waf/v1/model" + hcwafregion "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/waf/v1/region" xerrors "github.com/pkg/errors" "github.com/usual2970/certimate/internal/pkg/core/deployer" @@ -43,7 +43,7 @@ type DeployerConfig struct { type DeployerProvider struct { config *DeployerConfig logger *slog.Logger - sdkClient *hcWaf.WafClient + sdkClient *hcwaf.WafClient sslUploader uploader.Uploader } @@ -126,7 +126,7 @@ func (d *DeployerProvider) deployToCertificate(ctx context.Context, certPem stri // 查询证书 // REF: https://support.huaweicloud.com/api-waf/ShowCertificate.html - showCertificateReq := &hcWafModel.ShowCertificateRequest{ + showCertificateReq := &hcwafmodel.ShowCertificateRequest{ CertificateId: d.config.CertificateId, } showCertificateResp, err := d.sdkClient.ShowCertificate(showCertificateReq) @@ -137,9 +137,9 @@ func (d *DeployerProvider) deployToCertificate(ctx context.Context, certPem stri // 更新证书 // REF: https://support.huaweicloud.com/api-waf/UpdateCertificate.html - updateCertificateReq := &hcWafModel.UpdateCertificateRequest{ + updateCertificateReq := &hcwafmodel.UpdateCertificateRequest{ CertificateId: d.config.CertificateId, - Body: &hcWafModel.UpdateCertificateRequestBody{ + Body: &hcwafmodel.UpdateCertificateRequestBody{ Name: *showCertificateResp.Name, Content: hwsdk.StringPtr(certPem), Key: hwsdk.StringPtr(privkeyPem), @@ -173,7 +173,7 @@ func (d *DeployerProvider) deployToCloudServer(ctx context.Context, certPem stri listHostPage := int32(1) listHostPageSize := int32(100) for { - listHostReq := &hcWafModel.ListHostRequest{ + listHostReq := &hcwafmodel.ListHostRequest{ Hostname: hwsdk.StringPtr(strings.TrimPrefix(d.config.Domain, "*")), Page: hwsdk.Int32Ptr(listHostPage), Pagesize: hwsdk.Int32Ptr(listHostPageSize), @@ -205,9 +205,9 @@ func (d *DeployerProvider) deployToCloudServer(ctx context.Context, certPem stri // 更新云模式防护域名的配置 // REF: https://support.huaweicloud.com/api-waf/UpdateHost.html - updateHostReq := &hcWafModel.UpdateHostRequest{ + updateHostReq := &hcwafmodel.UpdateHostRequest{ InstanceId: hostId, - Body: &hcWafModel.UpdateHostRequestBody{ + Body: &hcwafmodel.UpdateHostRequestBody{ Certificateid: hwsdk.StringPtr(upres.CertId), Certificatename: hwsdk.StringPtr(upres.CertName), }, @@ -240,7 +240,7 @@ func (d *DeployerProvider) deployToPremiumHost(ctx context.Context, certPem stri listPremiumHostPage := int32(1) listPremiumHostPageSize := int32(100) for { - listPremiumHostReq := &hcWafModel.ListPremiumHostRequest{ + listPremiumHostReq := &hcwafmodel.ListPremiumHostRequest{ Hostname: hwsdk.StringPtr(strings.TrimPrefix(d.config.Domain, "*")), Page: hwsdk.StringPtr(fmt.Sprintf("%d", listPremiumHostPage)), Pagesize: hwsdk.StringPtr(fmt.Sprintf("%d", listPremiumHostPageSize)), @@ -272,9 +272,9 @@ func (d *DeployerProvider) deployToPremiumHost(ctx context.Context, certPem stri // 修改独享模式域名配置 // REF: https://support.huaweicloud.com/api-waf/UpdatePremiumHost.html - updatePremiumHostReq := &hcWafModel.UpdatePremiumHostRequest{ + updatePremiumHostReq := &hcwafmodel.UpdatePremiumHostRequest{ HostId: hostId, - Body: &hcWafModel.UpdatePremiumHostRequestBody{ + Body: &hcwafmodel.UpdatePremiumHostRequestBody{ Certificateid: hwsdk.StringPtr(upres.CertId), Certificatename: hwsdk.StringPtr(upres.CertName), }, @@ -288,7 +288,7 @@ func (d *DeployerProvider) deployToPremiumHost(ctx context.Context, certPem stri return nil } -func createSdkClient(accessKeyId, secretAccessKey, region string) (*hcWaf.WafClient, error) { +func createSdkClient(accessKeyId, secretAccessKey, region string) (*hcwaf.WafClient, error) { projectId, err := getSdkProjectId(accessKeyId, secretAccessKey, region) if err != nil { return nil, err @@ -303,12 +303,12 @@ func createSdkClient(accessKeyId, secretAccessKey, region string) (*hcWaf.WafCli return nil, err } - hcRegion, err := hcWafRegion.SafeValueOf(region) + hcRegion, err := hcwafregion.SafeValueOf(region) if err != nil { return nil, err } - hcClient, err := hcWaf.WafClientBuilder(). + hcClient, err := hcwaf.WafClientBuilder(). WithRegion(hcRegion). WithCredential(auth). SafeBuild() @@ -316,7 +316,7 @@ func createSdkClient(accessKeyId, secretAccessKey, region string) (*hcWaf.WafCli return nil, err } - client := hcWaf.NewWafClient(hcClient) + client := hcwaf.NewWafClient(hcClient) return client, nil } @@ -329,12 +329,12 @@ func getSdkProjectId(accessKeyId, secretAccessKey, region string) (string, error return "", err } - hcRegion, err := hcIamRegion.SafeValueOf(region) + hcRegion, err := hciamregion.SafeValueOf(region) if err != nil { return "", err } - hcClient, err := hcIam.IamClientBuilder(). + hcClient, err := hciam.IamClientBuilder(). WithRegion(hcRegion). WithCredential(auth). SafeBuild() @@ -342,9 +342,9 @@ func getSdkProjectId(accessKeyId, secretAccessKey, region string) (string, error return "", err } - client := hcIam.NewIamClient(hcClient) + client := hciam.NewIamClient(hcClient) - request := &hcIamModel.KeystoneListProjectsRequest{ + request := &hciamModel.KeystoneListProjectsRequest{ Name: ®ion, } response, err := client.KeystoneListProjects(request) diff --git a/internal/pkg/core/deployer/providers/jdcloud-alb/jdcloud_alb.go b/internal/pkg/core/deployer/providers/jdcloud-alb/jdcloud_alb.go index b1ab981f..d6c3f05a 100644 --- a/internal/pkg/core/deployer/providers/jdcloud-alb/jdcloud_alb.go +++ b/internal/pkg/core/deployer/providers/jdcloud-alb/jdcloud_alb.go @@ -7,11 +7,11 @@ import ( "log/slog" "strings" - jdCore "github.com/jdcloud-api/jdcloud-sdk-go/core" - jdCommon "github.com/jdcloud-api/jdcloud-sdk-go/services/common/models" - jdLbApi "github.com/jdcloud-api/jdcloud-sdk-go/services/lb/apis" - jdLbClient "github.com/jdcloud-api/jdcloud-sdk-go/services/lb/client" - jdLbModel "github.com/jdcloud-api/jdcloud-sdk-go/services/lb/models" + jdcore "github.com/jdcloud-api/jdcloud-sdk-go/core" + jdcommon "github.com/jdcloud-api/jdcloud-sdk-go/services/common/models" + jdlbapi "github.com/jdcloud-api/jdcloud-sdk-go/services/lb/apis" + jdlbclient "github.com/jdcloud-api/jdcloud-sdk-go/services/lb/client" + jdlbmodel "github.com/jdcloud-api/jdcloud-sdk-go/services/lb/models" xerrors "github.com/pkg/errors" "github.com/usual2970/certimate/internal/pkg/core/deployer" @@ -43,7 +43,7 @@ type DeployerConfig struct { type DeployerProvider struct { config *DeployerConfig logger *slog.Logger - sdkClient *jdLbClient.LbClient + sdkClient *jdlbclient.LbClient sslUploader uploader.Uploader } @@ -120,7 +120,7 @@ func (d *DeployerProvider) deployToLoadbalancer(ctx context.Context, cloudCertId // 查询负载均衡器详情 // REF: https://docs.jdcloud.com/cn/load-balancer/api/describeloadbalancer - describeLoadBalancerReq := jdLbApi.NewDescribeLoadBalancerRequest(d.config.RegionId, d.config.LoadbalancerId) + describeLoadBalancerReq := jdlbapi.NewDescribeLoadBalancerRequest(d.config.RegionId, d.config.LoadbalancerId) describeLoadBalancerResp, err := d.sdkClient.DescribeLoadBalancer(describeLoadBalancerReq) d.logger.Debug("sdk request 'lb.DescribeLoadBalancer'", slog.Any("request", describeLoadBalancerReq), slog.Any("response", describeLoadBalancerResp)) if err != nil { @@ -133,8 +133,8 @@ func (d *DeployerProvider) deployToLoadbalancer(ctx context.Context, cloudCertId describeListenersPageNumber := 1 describeListenersPageSize := 100 for { - describeListenersReq := jdLbApi.NewDescribeListenersRequest(d.config.RegionId) - describeListenersReq.SetFilters([]jdCommon.Filter{{Name: "loadBalancerId", Values: []string{d.config.LoadbalancerId}}}) + describeListenersReq := jdlbapi.NewDescribeListenersRequest(d.config.RegionId) + describeListenersReq.SetFilters([]jdcommon.Filter{{Name: "loadBalancerId", Values: []string{d.config.LoadbalancerId}}}) describeListenersReq.SetPageSize(describeListenersPageNumber) describeListenersReq.SetPageSize(describeListenersPageSize) describeListenersResp, err := d.sdkClient.DescribeListeners(describeListenersReq) @@ -194,7 +194,7 @@ func (d *DeployerProvider) deployToListener(ctx context.Context, cloudCertId str func (d *DeployerProvider) updateListenerCertificate(ctx context.Context, cloudListenerId string, cloudCertId string) error { // 查询监听器详情 // REF: https://docs.jdcloud.com/cn/load-balancer/api/describelistener - describeListenerReq := jdLbApi.NewDescribeListenerRequest(d.config.RegionId, cloudListenerId) + describeListenerReq := jdlbapi.NewDescribeListenerRequest(d.config.RegionId, cloudListenerId) describeListenerResp, err := d.sdkClient.DescribeListener(describeListenerReq) d.logger.Debug("sdk request 'lb.DescribeListener'", slog.Any("request", describeListenerReq), slog.Any("response", describeListenerResp)) if err != nil { @@ -206,8 +206,8 @@ func (d *DeployerProvider) updateListenerCertificate(ctx context.Context, cloudL // 修改监听器信息 // REF: https://docs.jdcloud.com/cn/load-balancer/api/updatelistener - updateListenerReq := jdLbApi.NewUpdateListenerRequest(d.config.RegionId, cloudListenerId) - updateListenerReq.SetCertificateSpecs([]jdLbModel.CertificateSpec{{CertificateId: cloudCertId}}) + updateListenerReq := jdlbapi.NewUpdateListenerRequest(d.config.RegionId, cloudListenerId) + updateListenerReq.SetCertificateSpecs([]jdlbmodel.CertificateSpec{{CertificateId: cloudCertId}}) updateListenerResp, err := d.sdkClient.UpdateListener(updateListenerReq) d.logger.Debug("sdk request 'lb.UpdateListener'", slog.Any("request", updateListenerReq), slog.Any("response", updateListenerResp)) if err != nil { @@ -216,7 +216,7 @@ func (d *DeployerProvider) updateListenerCertificate(ctx context.Context, cloudL } else { // 指定 SNI,需部署到扩展证书 - extCertSpecs := sliceutil.Filter(describeListenerResp.Result.Listener.ExtensionCertificateSpecs, func(extCertSpec jdLbModel.ExtensionCertificateSpec) bool { + extCertSpecs := sliceutil.Filter(describeListenerResp.Result.Listener.ExtensionCertificateSpecs, func(extCertSpec jdlbmodel.ExtensionCertificateSpec) bool { return extCertSpec.Domain == d.config.Domain }) if len(extCertSpecs) == 0 { @@ -225,11 +225,11 @@ func (d *DeployerProvider) updateListenerCertificate(ctx context.Context, cloudL // 批量修改扩展证书 // REF: https://docs.jdcloud.com/cn/load-balancer/api/updatelistenercertificates - updateListenerCertificatesReq := jdLbApi.NewUpdateListenerCertificatesRequest( + updateListenerCertificatesReq := jdlbapi.NewUpdateListenerCertificatesRequest( d.config.RegionId, cloudListenerId, - sliceutil.Map(extCertSpecs, func(extCertSpec jdLbModel.ExtensionCertificateSpec) jdLbModel.ExtCertificateUpdateSpec { - return jdLbModel.ExtCertificateUpdateSpec{ + sliceutil.Map(extCertSpecs, func(extCertSpec jdlbmodel.ExtensionCertificateSpec) jdlbmodel.ExtCertificateUpdateSpec { + return jdlbmodel.ExtCertificateUpdateSpec{ CertificateBindId: extCertSpec.CertificateBindId, CertificateId: &cloudCertId, Domain: &extCertSpec.Domain, @@ -246,9 +246,9 @@ func (d *DeployerProvider) updateListenerCertificate(ctx context.Context, cloudL return nil } -func createSdkClient(accessKeyId, accessKeySecret string) (*jdLbClient.LbClient, error) { - clientCredentials := jdCore.NewCredentials(accessKeyId, accessKeySecret) - client := jdLbClient.NewLbClient(clientCredentials) - client.SetLogger(jdCore.NewDefaultLogger(jdCore.LogWarn)) +func createSdkClient(accessKeyId, accessKeySecret string) (*jdlbclient.LbClient, error) { + clientCredentials := jdcore.NewCredentials(accessKeyId, accessKeySecret) + client := jdlbclient.NewLbClient(clientCredentials) + client.SetLogger(jdcore.NewDefaultLogger(jdcore.LogWarn)) return client, nil } diff --git a/internal/pkg/core/deployer/providers/jdcloud-cdn/jdcloud_cdn.go b/internal/pkg/core/deployer/providers/jdcloud-cdn/jdcloud_cdn.go index 3c473961..8fe7f6ea 100644 --- a/internal/pkg/core/deployer/providers/jdcloud-cdn/jdcloud_cdn.go +++ b/internal/pkg/core/deployer/providers/jdcloud-cdn/jdcloud_cdn.go @@ -4,9 +4,9 @@ import ( "context" "log/slog" - jdCore "github.com/jdcloud-api/jdcloud-sdk-go/core" - jdCdnApi "github.com/jdcloud-api/jdcloud-sdk-go/services/cdn/apis" - jdCdnClient "github.com/jdcloud-api/jdcloud-sdk-go/services/cdn/client" + jdcore "github.com/jdcloud-api/jdcloud-sdk-go/core" + jdcdnapi "github.com/jdcloud-api/jdcloud-sdk-go/services/cdn/apis" + jdcdnclient "github.com/jdcloud-api/jdcloud-sdk-go/services/cdn/client" xerrors "github.com/pkg/errors" "github.com/usual2970/certimate/internal/pkg/core/deployer" @@ -26,7 +26,7 @@ type DeployerConfig struct { type DeployerProvider struct { config *DeployerConfig logger *slog.Logger - sdkClient *jdCdnClient.CdnClient + sdkClient *jdcdnclient.CdnClient sslUploader uploader.Uploader } @@ -71,7 +71,7 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { // 查询域名配置信息 // REF: https://docs.jdcloud.com/cn/cdn/api/querydomainconfig - queryDomainConfigReq := jdCdnApi.NewQueryDomainConfigRequest(d.config.Domain) + queryDomainConfigReq := jdcdnapi.NewQueryDomainConfigRequest(d.config.Domain) queryDomainConfigResp, err := d.sdkClient.QueryDomainConfig(queryDomainConfigReq) d.logger.Debug("sdk request 'cdn.QueryDomainConfig'", slog.Any("request", queryDomainConfigReq), slog.Any("response", queryDomainConfigResp)) if err != nil { @@ -88,7 +88,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe // 设置通讯协议 // REF: https://docs.jdcloud.com/cn/cdn/api/sethttptype - setHttpTypeReq := jdCdnApi.NewSetHttpTypeRequest(d.config.Domain) + setHttpTypeReq := jdcdnapi.NewSetHttpTypeRequest(d.config.Domain) setHttpTypeReq.SetHttpType("https") setHttpTypeReq.SetCertificate(certPem) setHttpTypeReq.SetRsaKey(privkeyPem) @@ -104,9 +104,9 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe return &deployer.DeployResult{}, nil } -func createSdkClient(accessKeyId, accessKeySecret string) (*jdCdnClient.CdnClient, error) { - clientCredentials := jdCore.NewCredentials(accessKeyId, accessKeySecret) - client := jdCdnClient.NewCdnClient(clientCredentials) - client.SetLogger(jdCore.NewDefaultLogger(jdCore.LogWarn)) +func createSdkClient(accessKeyId, accessKeySecret string) (*jdcdnclient.CdnClient, error) { + clientCredentials := jdcore.NewCredentials(accessKeyId, accessKeySecret) + client := jdcdnclient.NewCdnClient(clientCredentials) + client.SetLogger(jdcore.NewDefaultLogger(jdcore.LogWarn)) return client, nil } diff --git a/internal/pkg/core/deployer/providers/jdcloud-live/jdcloud_live.go b/internal/pkg/core/deployer/providers/jdcloud-live/jdcloud_live.go index ea125408..c89a67b9 100644 --- a/internal/pkg/core/deployer/providers/jdcloud-live/jdcloud_live.go +++ b/internal/pkg/core/deployer/providers/jdcloud-live/jdcloud_live.go @@ -4,9 +4,9 @@ import ( "context" "log/slog" - jdCore "github.com/jdcloud-api/jdcloud-sdk-go/core" - jdLiveApi "github.com/jdcloud-api/jdcloud-sdk-go/services/live/apis" - jdLiveClient "github.com/jdcloud-api/jdcloud-sdk-go/services/live/client" + jdcore "github.com/jdcloud-api/jdcloud-sdk-go/core" + jdliveapi "github.com/jdcloud-api/jdcloud-sdk-go/services/live/apis" + jdliveclient "github.com/jdcloud-api/jdcloud-sdk-go/services/live/client" xerrors "github.com/pkg/errors" "github.com/usual2970/certimate/internal/pkg/core/deployer" @@ -24,7 +24,7 @@ type DeployerConfig struct { type DeployerProvider struct { config *DeployerConfig logger *slog.Logger - sdkClient *jdLiveClient.LiveClient + sdkClient *jdliveclient.LiveClient } var _ deployer.Deployer = (*DeployerProvider)(nil) @@ -58,7 +58,7 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { // 设置直播证书 // REF: https://docs.jdcloud.com/cn/live-video/api/setlivedomaincertificate - setLiveDomainCertificateReq := jdLiveApi.NewSetLiveDomainCertificateRequest(d.config.Domain, "on") + setLiveDomainCertificateReq := jdliveapi.NewSetLiveDomainCertificateRequest(d.config.Domain, "on") setLiveDomainCertificateReq.SetCert(certPem) setLiveDomainCertificateReq.SetKey(privkeyPem) setLiveDomainCertificateResp, err := d.sdkClient.SetLiveDomainCertificate(setLiveDomainCertificateReq) @@ -70,9 +70,9 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe return &deployer.DeployResult{}, nil } -func createSdkClient(accessKeyId, accessKeySecret string) (*jdLiveClient.LiveClient, error) { - clientCredentials := jdCore.NewCredentials(accessKeyId, accessKeySecret) - client := jdLiveClient.NewLiveClient(clientCredentials) - client.SetLogger(jdCore.NewDefaultLogger(jdCore.LogWarn)) +func createSdkClient(accessKeyId, accessKeySecret string) (*jdliveclient.LiveClient, error) { + clientCredentials := jdcore.NewCredentials(accessKeyId, accessKeySecret) + client := jdliveclient.NewLiveClient(clientCredentials) + client.SetLogger(jdcore.NewDefaultLogger(jdcore.LogWarn)) return client, nil } diff --git a/internal/pkg/core/deployer/providers/jdcloud-vod/jdcloud_vod.go b/internal/pkg/core/deployer/providers/jdcloud-vod/jdcloud_vod.go index 69410c78..95be5c15 100644 --- a/internal/pkg/core/deployer/providers/jdcloud-vod/jdcloud_vod.go +++ b/internal/pkg/core/deployer/providers/jdcloud-vod/jdcloud_vod.go @@ -7,9 +7,9 @@ import ( "strconv" "time" - jdCore "github.com/jdcloud-api/jdcloud-sdk-go/core" - jdVodApi "github.com/jdcloud-api/jdcloud-sdk-go/services/vod/apis" - jdVodClient "github.com/jdcloud-api/jdcloud-sdk-go/services/vod/client" + jdcore "github.com/jdcloud-api/jdcloud-sdk-go/core" + jdvodapi "github.com/jdcloud-api/jdcloud-sdk-go/services/vod/apis" + jdvodclient "github.com/jdcloud-api/jdcloud-sdk-go/services/vod/client" xerrors "github.com/pkg/errors" "github.com/usual2970/certimate/internal/pkg/core/deployer" @@ -27,7 +27,7 @@ type DeployerConfig struct { type DeployerProvider struct { config *DeployerConfig logger *slog.Logger - sdkClient *jdVodClient.VodClient + sdkClient *jdvodclient.VodClient } var _ deployer.Deployer = (*DeployerProvider)(nil) @@ -65,7 +65,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe listDomainsPageNumber := 1 listDomainsPageSize := 100 for { - listDomainsReq := jdVodApi.NewListDomainsRequest() + listDomainsReq := jdvodapi.NewListDomainsRequest() listDomainsReq.SetPageNumber(1) listDomainsReq.SetPageSize(100) listDomainsResp, err := d.sdkClient.ListDomains(listDomainsReq) @@ -93,7 +93,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe // 查询域名 SSL 配置 // REF: https://docs.jdcloud.com/cn/video-on-demand/api/gethttpssl - getHttpSslReq := jdVodApi.NewGetHttpSslRequest(domainId) + getHttpSslReq := jdvodapi.NewGetHttpSslRequest(domainId) getHttpSslResp, err := d.sdkClient.GetHttpSsl(getHttpSslReq) d.logger.Debug("sdk request 'vod.GetHttpSsl'", slog.Any("request", getHttpSslReq), slog.Any("response", getHttpSslResp)) if err != nil { @@ -102,7 +102,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe // 设置域名 SSL 配置 // REF: https://docs.jdcloud.com/cn/video-on-demand/api/sethttpssl - setHttpSslReq := jdVodApi.NewSetHttpSslRequest(domainId) + setHttpSslReq := jdvodapi.NewSetHttpSslRequest(domainId) setHttpSslReq.SetTitle(fmt.Sprintf("certimate-%d", time.Now().UnixMilli())) setHttpSslReq.SetSslCert(certPem) setHttpSslReq.SetSslKey(privkeyPem) @@ -118,9 +118,9 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe return &deployer.DeployResult{}, nil } -func createSdkClient(accessKeyId, accessKeySecret string) (*jdVodClient.VodClient, error) { - clientCredentials := jdCore.NewCredentials(accessKeyId, accessKeySecret) - client := jdVodClient.NewVodClient(clientCredentials) - client.SetLogger(jdCore.NewDefaultLogger(jdCore.LogWarn)) +func createSdkClient(accessKeyId, accessKeySecret string) (*jdvodclient.VodClient, error) { + clientCredentials := jdcore.NewCredentials(accessKeyId, accessKeySecret) + client := jdvodclient.NewVodClient(clientCredentials) + client.SetLogger(jdcore.NewDefaultLogger(jdcore.LogWarn)) return client, nil } diff --git a/internal/pkg/core/deployer/providers/k8s-secret/k8s_secret.go b/internal/pkg/core/deployer/providers/k8s-secret/k8s_secret.go index 7ca92e41..88b4b6a1 100644 --- a/internal/pkg/core/deployer/providers/k8s-secret/k8s_secret.go +++ b/internal/pkg/core/deployer/providers/k8s-secret/k8s_secret.go @@ -7,8 +7,8 @@ import ( "strings" xerrors "github.com/pkg/errors" - k8sCore "k8s.io/api/core/v1" - k8sMeta "k8s.io/apimachinery/pkg/apis/meta/v1" + k8score "k8s.io/api/core/v1" + k8smeta "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" "k8s.io/client-go/rest" "k8s.io/client-go/tools/clientcmd" @@ -87,7 +87,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe return nil, xerrors.Wrap(err, "failed to create k8s client") } - var secretPayload *k8sCore.Secret + var secretPayload *k8score.Secret secretAnnotations := map[string]string{ "certimate/common-name": certX509.Subject.CommonName, "certimate/subject-sn": certX509.Subject.SerialNumber, @@ -97,24 +97,24 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe } // 获取 Secret 实例,如果不存在则创建 - secretPayload, err = client.CoreV1().Secrets(d.config.Namespace).Get(context.TODO(), d.config.SecretName, k8sMeta.GetOptions{}) + secretPayload, err = client.CoreV1().Secrets(d.config.Namespace).Get(context.TODO(), d.config.SecretName, k8smeta.GetOptions{}) if err != nil { - secretPayload = &k8sCore.Secret{ - TypeMeta: k8sMeta.TypeMeta{ + secretPayload = &k8score.Secret{ + TypeMeta: k8smeta.TypeMeta{ Kind: "Secret", APIVersion: "v1", }, - ObjectMeta: k8sMeta.ObjectMeta{ + ObjectMeta: k8smeta.ObjectMeta{ Name: d.config.SecretName, Annotations: secretAnnotations, }, - Type: k8sCore.SecretType(d.config.SecretType), + Type: k8score.SecretType(d.config.SecretType), } secretPayload.Data = make(map[string][]byte) secretPayload.Data[d.config.SecretDataKeyForCrt] = []byte(certPem) secretPayload.Data[d.config.SecretDataKeyForKey] = []byte(privkeyPem) - secretPayload, err = client.CoreV1().Secrets(d.config.Namespace).Create(context.TODO(), secretPayload, k8sMeta.CreateOptions{}) + secretPayload, err = client.CoreV1().Secrets(d.config.Namespace).Create(context.TODO(), secretPayload, k8smeta.CreateOptions{}) d.logger.Debug("k8s operate 'Secrets.Create'", slog.String("namespace", d.config.Namespace), slog.Any("secret", secretPayload)) if err != nil { return nil, xerrors.Wrap(err, "failed to create k8s secret") @@ -124,7 +124,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe } // 更新 Secret 实例 - secretPayload.Type = k8sCore.SecretType(d.config.SecretType) + secretPayload.Type = k8score.SecretType(d.config.SecretType) if secretPayload.ObjectMeta.Annotations == nil { secretPayload.ObjectMeta.Annotations = secretAnnotations } else { @@ -137,7 +137,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe } secretPayload.Data[d.config.SecretDataKeyForCrt] = []byte(certPem) secretPayload.Data[d.config.SecretDataKeyForKey] = []byte(privkeyPem) - secretPayload, err = client.CoreV1().Secrets(d.config.Namespace).Update(context.TODO(), secretPayload, k8sMeta.UpdateOptions{}) + secretPayload, err = client.CoreV1().Secrets(d.config.Namespace).Update(context.TODO(), secretPayload, k8smeta.UpdateOptions{}) d.logger.Debug("k8s operate 'Secrets.Update'", slog.String("namespace", d.config.Namespace), slog.Any("secret", secretPayload)) if err != nil { return nil, xerrors.Wrap(err, "failed to update k8s secret") diff --git a/internal/pkg/core/deployer/providers/qiniu-cdn/qiniu_cdn_test.go b/internal/pkg/core/deployer/providers/qiniu-cdn/qiniu_cdn_test.go index eff0ab48..fffbfca5 100644 --- a/internal/pkg/core/deployer/providers/qiniu-cdn/qiniu_cdn_test.go +++ b/internal/pkg/core/deployer/providers/qiniu-cdn/qiniu_cdn_test.go @@ -37,7 +37,7 @@ Shell command to run this test: --CERTIMATE_DEPLOYER_QINIUCDN_INPUTKEYPATH="/path/to/your-input-key.pem" \ --CERTIMATE_DEPLOYER_QINIUCDN_ACCESSKEY="your-access-key" \ --CERTIMATE_DEPLOYER_QINIUCDN_SECRETKEY="your-secret-key" \ - --CERTIMATE_DEPLOYER_QINIUCDN_DOMAIN="example.com" \ + --CERTIMATE_DEPLOYER_QINIUCDN_DOMAIN="example.com" */ func TestDeploy(t *testing.T) { flag.Parse() diff --git a/internal/pkg/core/deployer/providers/qiniu-pili/qiniu_pili_test.go b/internal/pkg/core/deployer/providers/qiniu-pili/qiniu_pili_test.go index 1d307dda..73e69855 100644 --- a/internal/pkg/core/deployer/providers/qiniu-pili/qiniu_pili_test.go +++ b/internal/pkg/core/deployer/providers/qiniu-pili/qiniu_pili_test.go @@ -40,7 +40,7 @@ Shell command to run this test: --CERTIMATE_DEPLOYER_QINIUPILI_ACCESSKEY="your-access-key" \ --CERTIMATE_DEPLOYER_QINIUPILI_SECRETKEY="your-secret-key" \ --CERTIMATE_DEPLOYER_QINIUPILI_HUB="your-hub-name" \ - --CERTIMATE_DEPLOYER_QINIUPILI_DOMAIN="example.com" \ + --CERTIMATE_DEPLOYER_QINIUPILI_DOMAIN="example.com" */ func TestDeploy(t *testing.T) { flag.Parse() diff --git a/internal/pkg/core/deployer/providers/tencentcloud-cdn/tencentcloud_cdn.go b/internal/pkg/core/deployer/providers/tencentcloud-cdn/tencentcloud_cdn.go index da76c955..38e58c7b 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-cdn/tencentcloud_cdn.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-cdn/tencentcloud_cdn.go @@ -6,10 +6,10 @@ import ( "strings" xerrors "github.com/pkg/errors" - tcCdn "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cdn/v20180606" + tccdn "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cdn/v20180606" "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common" "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile" - tcSsl "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssl/v20191205" + tcssl "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssl/v20191205" "golang.org/x/exp/slices" "github.com/usual2970/certimate/internal/pkg/core/deployer" @@ -36,8 +36,8 @@ type DeployerProvider struct { var _ deployer.Deployer = (*DeployerProvider)(nil) type wSdkClients struct { - ssl *tcSsl.Client - cdn *tcCdn.Client + SSL *tcssl.Client + CDN *tccdn.Client } func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { @@ -122,12 +122,12 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe // 证书部署到 CDN 实例 // REF: https://cloud.tencent.com/document/product/400/91667 - deployCertificateInstanceReq := tcSsl.NewDeployCertificateInstanceRequest() + deployCertificateInstanceReq := tcssl.NewDeployCertificateInstanceRequest() deployCertificateInstanceReq.CertificateId = common.StringPtr(upres.CertId) deployCertificateInstanceReq.ResourceType = common.StringPtr("cdn") deployCertificateInstanceReq.Status = common.Int64Ptr(1) deployCertificateInstanceReq.InstanceIdList = common.StringPtrs(instanceIds) - deployCertificateInstanceResp, err := d.sdkClients.ssl.DeployCertificateInstance(deployCertificateInstanceReq) + deployCertificateInstanceResp, err := d.sdkClients.SSL.DeployCertificateInstance(deployCertificateInstanceReq) d.logger.Debug("sdk request 'ssl.DeployCertificateInstance'", slog.Any("request", deployCertificateInstanceReq), slog.Any("response", deployCertificateInstanceResp)) if err != nil { return nil, xerrors.Wrap(err, "failed to execute sdk request 'ssl.DeployCertificateInstance'") @@ -140,10 +140,10 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe func (d *DeployerProvider) getDomainsByCertificateId(cloudCertId string) ([]string, error) { // 获取证书中的可用域名 // REF: https://cloud.tencent.com/document/product/228/42491 - describeCertDomainsReq := tcCdn.NewDescribeCertDomainsRequest() + describeCertDomainsReq := tccdn.NewDescribeCertDomainsRequest() describeCertDomainsReq.CertId = common.StringPtr(cloudCertId) describeCertDomainsReq.Product = common.StringPtr("cdn") - describeCertDomainsResp, err := d.sdkClients.cdn.DescribeCertDomains(describeCertDomainsReq) + describeCertDomainsResp, err := d.sdkClients.CDN.DescribeCertDomains(describeCertDomainsReq) d.logger.Debug("sdk request 'cdn.DescribeCertDomains'", slog.Any("request", describeCertDomainsReq), slog.Any("response", describeCertDomainsResp)) if err != nil { return nil, xerrors.Wrap(err, "failed to execute sdk request 'cdn.DescribeCertDomains'") @@ -162,10 +162,10 @@ func (d *DeployerProvider) getDomainsByCertificateId(cloudCertId string) ([]stri func (d *DeployerProvider) getDeployedDomainsByCertificateId(cloudCertId string) ([]string, error) { // 根据证书查询关联 CDN 域名 // REF: https://cloud.tencent.com/document/product/400/62674 - describeDeployedResourcesReq := tcSsl.NewDescribeDeployedResourcesRequest() + describeDeployedResourcesReq := tcssl.NewDescribeDeployedResourcesRequest() describeDeployedResourcesReq.CertificateIds = common.StringPtrs([]string{cloudCertId}) describeDeployedResourcesReq.ResourceType = common.StringPtr("cdn") - describeDeployedResourcesResp, err := d.sdkClients.ssl.DescribeDeployedResources(describeDeployedResourcesReq) + describeDeployedResourcesResp, err := d.sdkClients.SSL.DescribeDeployedResources(describeDeployedResourcesReq) d.logger.Debug("sdk request 'cdn.DescribeDeployedResources'", slog.Any("request", describeDeployedResourcesReq), slog.Any("response", describeDeployedResourcesResp)) if err != nil { return nil, xerrors.Wrap(err, "failed to execute sdk request 'cdn.DescribeDeployedResources'") @@ -186,18 +186,18 @@ func (d *DeployerProvider) getDeployedDomainsByCertificateId(cloudCertId string) func createSdkClients(secretId, secretKey string) (*wSdkClients, error) { credential := common.NewCredential(secretId, secretKey) - sslClient, err := tcSsl.NewClient(credential, "", profile.NewClientProfile()) + sslClient, err := tcssl.NewClient(credential, "", profile.NewClientProfile()) if err != nil { return nil, err } - cdnClient, err := tcCdn.NewClient(credential, "", profile.NewClientProfile()) + cdnClient, err := tccdn.NewClient(credential, "", profile.NewClientProfile()) if err != nil { return nil, err } return &wSdkClients{ - ssl: sslClient, - cdn: cdnClient, + SSL: sslClient, + CDN: cdnClient, }, nil } diff --git a/internal/pkg/core/deployer/providers/tencentcloud-clb/tencentcloud_clb.go b/internal/pkg/core/deployer/providers/tencentcloud-clb/tencentcloud_clb.go index 3f4e6600..e8edb9cc 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-clb/tencentcloud_clb.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-clb/tencentcloud_clb.go @@ -7,10 +7,10 @@ import ( "log/slog" xerrors "github.com/pkg/errors" - tcClb "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/clb/v20180317" + tcclb "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/clb/v20180317" "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common" "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile" - tcSsl "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssl/v20191205" + tcssl "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssl/v20191205" "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/uploader" @@ -47,8 +47,8 @@ type DeployerProvider struct { var _ deployer.Deployer = (*DeployerProvider)(nil) type wSdkClients struct { - ssl *tcSsl.Client - clb *tcClb.Client + SSL *tcssl.Client + CLB *tcclb.Client } func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { @@ -135,7 +135,7 @@ func (d *DeployerProvider) deployViaSslService(ctx context.Context, cloudCertId // 证书部署到 CLB 实例 // REF: https://cloud.tencent.com/document/product/400/91667 - deployCertificateInstanceReq := tcSsl.NewDeployCertificateInstanceRequest() + deployCertificateInstanceReq := tcssl.NewDeployCertificateInstanceRequest() deployCertificateInstanceReq.CertificateId = common.StringPtr(cloudCertId) deployCertificateInstanceReq.ResourceType = common.StringPtr("clb") deployCertificateInstanceReq.Status = common.Int64Ptr(1) @@ -146,7 +146,7 @@ func (d *DeployerProvider) deployViaSslService(ctx context.Context, cloudCertId // 指定 SNI,需部署到域名 deployCertificateInstanceReq.InstanceIdList = common.StringPtrs([]string{fmt.Sprintf("%s|%s|%s", d.config.LoadbalancerId, d.config.ListenerId, d.config.Domain)}) } - deployCertificateInstanceResp, err := d.sdkClients.ssl.DeployCertificateInstance(deployCertificateInstanceReq) + deployCertificateInstanceResp, err := d.sdkClients.SSL.DeployCertificateInstance(deployCertificateInstanceReq) d.logger.Debug("sdk request 'ssl.DeployCertificateInstance'", slog.Any("request", deployCertificateInstanceReq), slog.Any("response", deployCertificateInstanceResp)) if err != nil { return xerrors.Wrap(err, "failed to execute sdk request 'ssl.DeployCertificateInstance'") @@ -163,9 +163,9 @@ func (d *DeployerProvider) deployToLoadbalancer(ctx context.Context, cloudCertId // 查询监听器列表 // REF: https://cloud.tencent.com/document/api/214/30686 listenerIds := make([]string, 0) - describeListenersReq := tcClb.NewDescribeListenersRequest() + describeListenersReq := tcclb.NewDescribeListenersRequest() describeListenersReq.LoadBalancerId = common.StringPtr(d.config.LoadbalancerId) - describeListenersResp, err := d.sdkClients.clb.DescribeListeners(describeListenersReq) + describeListenersResp, err := d.sdkClients.CLB.DescribeListeners(describeListenersReq) d.logger.Debug("sdk request 'clb.DescribeListeners'", slog.Any("request", describeListenersReq), slog.Any("response", describeListenersResp)) if err != nil { return xerrors.Wrap(err, "failed to execute sdk request 'clb.DescribeListeners'") @@ -231,15 +231,15 @@ func (d *DeployerProvider) deployToRuleDomain(ctx context.Context, cloudCertId s // 修改负载均衡七层监听器转发规则的域名级别属性 // REF: https://cloud.tencent.com/document/api/214/38092 - modifyDomainAttributesReq := tcClb.NewModifyDomainAttributesRequest() + modifyDomainAttributesReq := tcclb.NewModifyDomainAttributesRequest() modifyDomainAttributesReq.LoadBalancerId = common.StringPtr(d.config.LoadbalancerId) modifyDomainAttributesReq.ListenerId = common.StringPtr(d.config.ListenerId) modifyDomainAttributesReq.Domain = common.StringPtr(d.config.Domain) - modifyDomainAttributesReq.Certificate = &tcClb.CertificateInput{ + modifyDomainAttributesReq.Certificate = &tcclb.CertificateInput{ SSLMode: common.StringPtr("UNIDIRECTIONAL"), CertId: common.StringPtr(cloudCertId), } - modifyDomainAttributesResp, err := d.sdkClients.clb.ModifyDomainAttributes(modifyDomainAttributesReq) + modifyDomainAttributesResp, err := d.sdkClients.CLB.ModifyDomainAttributes(modifyDomainAttributesReq) d.logger.Debug("sdk request 'clb.ModifyDomainAttributes'", slog.Any("request", modifyDomainAttributesReq), slog.Any("response", modifyDomainAttributesResp)) if err != nil { return xerrors.Wrap(err, "failed to execute sdk request 'clb.ModifyDomainAttributes'") @@ -251,10 +251,10 @@ func (d *DeployerProvider) deployToRuleDomain(ctx context.Context, cloudCertId s func (d *DeployerProvider) modifyListenerCertificate(ctx context.Context, cloudLoadbalancerId, cloudListenerId, cloudCertId string) error { // 查询监听器列表 // REF: https://cloud.tencent.com/document/api/214/30686 - describeListenersReq := tcClb.NewDescribeListenersRequest() + describeListenersReq := tcclb.NewDescribeListenersRequest() describeListenersReq.LoadBalancerId = common.StringPtr(cloudLoadbalancerId) describeListenersReq.ListenerIds = common.StringPtrs([]string{cloudListenerId}) - describeListenersResp, err := d.sdkClients.clb.DescribeListeners(describeListenersReq) + describeListenersResp, err := d.sdkClients.CLB.DescribeListeners(describeListenersReq) d.logger.Debug("sdk request 'clb.DescribeListeners'", slog.Any("request", describeListenersReq), slog.Any("response", describeListenersResp)) if err != nil { return xerrors.Wrap(err, "failed to execute sdk request 'clb.DescribeListeners'") @@ -264,17 +264,17 @@ func (d *DeployerProvider) modifyListenerCertificate(ctx context.Context, cloudL // 修改监听器属性 // REF: https://cloud.tencent.com/document/product/214/30681 - modifyListenerReq := tcClb.NewModifyListenerRequest() + modifyListenerReq := tcclb.NewModifyListenerRequest() modifyListenerReq.LoadBalancerId = common.StringPtr(cloudLoadbalancerId) modifyListenerReq.ListenerId = common.StringPtr(cloudListenerId) - modifyListenerReq.Certificate = &tcClb.CertificateInput{CertId: common.StringPtr(cloudCertId)} + modifyListenerReq.Certificate = &tcclb.CertificateInput{CertId: common.StringPtr(cloudCertId)} if describeListenersResp.Response.Listeners[0].Certificate != nil && describeListenersResp.Response.Listeners[0].Certificate.SSLMode != nil { modifyListenerReq.Certificate.SSLMode = describeListenersResp.Response.Listeners[0].Certificate.SSLMode modifyListenerReq.Certificate.CertCaId = describeListenersResp.Response.Listeners[0].Certificate.CertCaId } else { modifyListenerReq.Certificate.SSLMode = common.StringPtr("UNIDIRECTIONAL") } - modifyListenerResp, err := d.sdkClients.clb.ModifyListener(modifyListenerReq) + modifyListenerResp, err := d.sdkClients.CLB.ModifyListener(modifyListenerReq) d.logger.Debug("sdk request 'clb.ModifyListener'", slog.Any("request", modifyListenerReq), slog.Any("response", modifyListenerResp)) if err != nil { return xerrors.Wrap(err, "failed to execute sdk request 'clb.ModifyListener'") @@ -287,18 +287,18 @@ func createSdkClients(secretId, secretKey, region string) (*wSdkClients, error) credential := common.NewCredential(secretId, secretKey) // 注意虽然官方文档中地域无需指定,但实际需要部署到 CLB 时必传 - sslClient, err := tcSsl.NewClient(credential, region, profile.NewClientProfile()) + sslClient, err := tcssl.NewClient(credential, region, profile.NewClientProfile()) if err != nil { return nil, err } - clbClient, err := tcClb.NewClient(credential, region, profile.NewClientProfile()) + clbClient, err := tcclb.NewClient(credential, region, profile.NewClientProfile()) if err != nil { return nil, err } return &wSdkClients{ - ssl: sslClient, - clb: clbClient, + SSL: sslClient, + CLB: clbClient, }, nil } diff --git a/internal/pkg/core/deployer/providers/tencentcloud-cos/tencentcloud_cos.go b/internal/pkg/core/deployer/providers/tencentcloud-cos/tencentcloud_cos.go index 6bfa5976..7f1992e9 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-cos/tencentcloud_cos.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-cos/tencentcloud_cos.go @@ -9,7 +9,7 @@ import ( xerrors "github.com/pkg/errors" "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common" "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile" - tcSsl "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssl/v20191205" + tcssl "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssl/v20191205" "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/uploader" @@ -32,7 +32,7 @@ type DeployerConfig struct { type DeployerProvider struct { config *DeployerConfig logger *slog.Logger - sdkClient *tcSsl.Client + sdkClient *tcssl.Client sslUploader uploader.Uploader } @@ -92,7 +92,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe // 证书部署到 COS 实例 // REF: https://cloud.tencent.com/document/product/400/91667 - deployCertificateInstanceReq := tcSsl.NewDeployCertificateInstanceRequest() + deployCertificateInstanceReq := tcssl.NewDeployCertificateInstanceRequest() deployCertificateInstanceReq.CertificateId = common.StringPtr(upres.CertId) deployCertificateInstanceReq.ResourceType = common.StringPtr("cos") deployCertificateInstanceReq.Status = common.Int64Ptr(1) @@ -106,9 +106,9 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe return &deployer.DeployResult{}, nil } -func createSdkClient(secretId, secretKey, region string) (*tcSsl.Client, error) { +func createSdkClient(secretId, secretKey, region string) (*tcssl.Client, error) { credential := common.NewCredential(secretId, secretKey) - client, err := tcSsl.NewClient(credential, region, profile.NewClientProfile()) + client, err := tcssl.NewClient(credential, region, profile.NewClientProfile()) if err != nil { return nil, err } diff --git a/internal/pkg/core/deployer/providers/tencentcloud-css/tencentcloud_css.go b/internal/pkg/core/deployer/providers/tencentcloud-css/tencentcloud_css.go index 66c6d57d..e29e25ea 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-css/tencentcloud_css.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-css/tencentcloud_css.go @@ -7,7 +7,7 @@ import ( xerrors "github.com/pkg/errors" "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common" "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile" - tcLive "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/live/v20180801" + tclive "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/live/v20180801" "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/uploader" @@ -26,7 +26,7 @@ type DeployerConfig struct { type DeployerProvider struct { config *DeployerConfig logger *slog.Logger - sdkClient *tcLive.Client + sdkClient *tclive.Client sslUploader uploader.Uploader } @@ -79,15 +79,14 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe // 绑定证书对应的播放域名 // REF: https://cloud.tencent.com/document/product/267/78655 - modifyLiveDomainCertBindingsReq := &tcLive.ModifyLiveDomainCertBindingsRequest{ - DomainInfos: []*tcLive.LiveCertDomainInfo{ - { - DomainName: common.StringPtr(d.config.Domain), - Status: common.Int64Ptr(1), - }, + modifyLiveDomainCertBindingsReq := tclive.NewModifyLiveDomainCertBindingsRequest() + modifyLiveDomainCertBindingsReq.DomainInfos = []*tclive.LiveCertDomainInfo{ + { + DomainName: common.StringPtr(d.config.Domain), + Status: common.Int64Ptr(1), }, - CloudCertId: common.StringPtr(upres.CertId), } + modifyLiveDomainCertBindingsReq.CloudCertId = common.StringPtr(upres.CertId) modifyLiveDomainCertBindingsResp, err := d.sdkClient.ModifyLiveDomainCertBindings(modifyLiveDomainCertBindingsReq) d.logger.Debug("sdk request 'live.ModifyLiveDomainCertBindings'", slog.Any("request", modifyLiveDomainCertBindingsReq), slog.Any("response", modifyLiveDomainCertBindingsResp)) if err != nil { @@ -97,10 +96,10 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe return &deployer.DeployResult{}, nil } -func createSdkClient(secretId, secretKey string) (*tcLive.Client, error) { +func createSdkClient(secretId, secretKey string) (*tclive.Client, error) { credential := common.NewCredential(secretId, secretKey) - client, err := tcLive.NewClient(credential, "", profile.NewClientProfile()) + client, err := tclive.NewClient(credential, "", profile.NewClientProfile()) if err != nil { return nil, err } diff --git a/internal/pkg/core/deployer/providers/tencentcloud-ecdn/tencentcloud_ecdn.go b/internal/pkg/core/deployer/providers/tencentcloud-ecdn/tencentcloud_ecdn.go index 3cfe70ff..bd2aebe2 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-ecdn/tencentcloud_ecdn.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-ecdn/tencentcloud_ecdn.go @@ -6,10 +6,10 @@ import ( "strings" xerrors "github.com/pkg/errors" - tcCdn "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cdn/v20180606" + tccdn "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cdn/v20180606" "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common" "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile" - tcSsl "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssl/v20191205" + tcssl "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssl/v20191205" "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/uploader" @@ -35,8 +35,8 @@ type DeployerProvider struct { var _ deployer.Deployer = (*DeployerProvider)(nil) type wSdkClients struct { - ssl *tcSsl.Client - cdn *tcCdn.Client + SSL *tcssl.Client + CDN *tccdn.Client } func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { @@ -105,12 +105,12 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe // 证书部署到 ECDN 实例 // REF: https://cloud.tencent.com/document/product/400/91667 - deployCertificateInstanceReq := tcSsl.NewDeployCertificateInstanceRequest() + deployCertificateInstanceReq := tcssl.NewDeployCertificateInstanceRequest() deployCertificateInstanceReq.CertificateId = common.StringPtr(upres.CertId) deployCertificateInstanceReq.ResourceType = common.StringPtr("ecdn") deployCertificateInstanceReq.Status = common.Int64Ptr(1) deployCertificateInstanceReq.InstanceIdList = common.StringPtrs(instanceIds) - deployCertificateInstanceResp, err := d.sdkClients.ssl.DeployCertificateInstance(deployCertificateInstanceReq) + deployCertificateInstanceResp, err := d.sdkClients.SSL.DeployCertificateInstance(deployCertificateInstanceReq) d.logger.Debug("sdk request 'ssl.DeployCertificateInstance'", slog.Any("request", deployCertificateInstanceReq), slog.Any("response", deployCertificateInstanceResp)) if err != nil { return nil, xerrors.Wrap(err, "failed to execute sdk request 'ssl.DeployCertificateInstance'") @@ -123,10 +123,10 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe func (d *DeployerProvider) getDomainsByCertificateId(cloudCertId string) ([]string, error) { // 获取证书中的可用域名 // REF: https://cloud.tencent.com/document/product/228/42491 - describeCertDomainsReq := tcCdn.NewDescribeCertDomainsRequest() + describeCertDomainsReq := tccdn.NewDescribeCertDomainsRequest() describeCertDomainsReq.CertId = common.StringPtr(cloudCertId) describeCertDomainsReq.Product = common.StringPtr("ecdn") - describeCertDomainsResp, err := d.sdkClients.cdn.DescribeCertDomains(describeCertDomainsReq) + describeCertDomainsResp, err := d.sdkClients.CDN.DescribeCertDomains(describeCertDomainsReq) d.logger.Debug("sdk request 'cdn.DescribeCertDomains'", slog.Any("request", describeCertDomainsReq), slog.Any("response", describeCertDomainsResp)) if err != nil { return nil, xerrors.Wrap(err, "failed to execute sdk request 'cdn.DescribeCertDomains'") @@ -145,18 +145,18 @@ func (d *DeployerProvider) getDomainsByCertificateId(cloudCertId string) ([]stri func createSdkClients(secretId, secretKey string) (*wSdkClients, error) { credential := common.NewCredential(secretId, secretKey) - sslClient, err := tcSsl.NewClient(credential, "", profile.NewClientProfile()) + sslClient, err := tcssl.NewClient(credential, "", profile.NewClientProfile()) if err != nil { return nil, err } - cdnClient, err := tcCdn.NewClient(credential, "", profile.NewClientProfile()) + cdnClient, err := tccdn.NewClient(credential, "", profile.NewClientProfile()) if err != nil { return nil, err } return &wSdkClients{ - ssl: sslClient, - cdn: cdnClient, + SSL: sslClient, + CDN: cdnClient, }, nil } diff --git a/internal/pkg/core/deployer/providers/tencentcloud-eo/tencentcloud_eo.go b/internal/pkg/core/deployer/providers/tencentcloud-eo/tencentcloud_eo.go index d28c7f5a..b6ebbf94 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-eo/tencentcloud_eo.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-eo/tencentcloud_eo.go @@ -8,8 +8,8 @@ import ( xerrors "github.com/pkg/errors" "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common" "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile" - tcSsl "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssl/v20191205" - tcTeo "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/teo/v20220901" + tcssl "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssl/v20191205" + tcteo "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/teo/v20220901" "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/uploader" @@ -37,8 +37,8 @@ type DeployerProvider struct { var _ deployer.Deployer = (*DeployerProvider)(nil) type wSdkClients struct { - ssl *tcSsl.Client - teo *tcTeo.Client + SSL *tcssl.Client + TEO *tcteo.Client } func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { @@ -92,12 +92,12 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe // 配置域名证书 // REF: https://cloud.tencent.com/document/product/1552/80764 - modifyHostsCertificateReq := tcTeo.NewModifyHostsCertificateRequest() + modifyHostsCertificateReq := tcteo.NewModifyHostsCertificateRequest() modifyHostsCertificateReq.ZoneId = common.StringPtr(d.config.ZoneId) modifyHostsCertificateReq.Mode = common.StringPtr("sslcert") modifyHostsCertificateReq.Hosts = common.StringPtrs([]string{d.config.Domain}) - modifyHostsCertificateReq.ServerCertInfo = []*tcTeo.ServerCertInfo{{CertId: common.StringPtr(upres.CertId)}} - modifyHostsCertificateResp, err := d.sdkClients.teo.ModifyHostsCertificate(modifyHostsCertificateReq) + modifyHostsCertificateReq.ServerCertInfo = []*tcteo.ServerCertInfo{{CertId: common.StringPtr(upres.CertId)}} + modifyHostsCertificateResp, err := d.sdkClients.TEO.ModifyHostsCertificate(modifyHostsCertificateReq) d.logger.Debug("sdk request 'teo.ModifyHostsCertificate'", slog.Any("request", modifyHostsCertificateReq), slog.Any("response", modifyHostsCertificateResp)) if err != nil { return nil, xerrors.Wrap(err, "failed to execute sdk request 'teo.ModifyHostsCertificate'") @@ -109,18 +109,18 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe func createSdkClients(secretId, secretKey string) (*wSdkClients, error) { credential := common.NewCredential(secretId, secretKey) - sslClient, err := tcSsl.NewClient(credential, "", profile.NewClientProfile()) + sslClient, err := tcssl.NewClient(credential, "", profile.NewClientProfile()) if err != nil { return nil, err } - teoClient, err := tcTeo.NewClient(credential, "", profile.NewClientProfile()) + teoClient, err := tcteo.NewClient(credential, "", profile.NewClientProfile()) if err != nil { return nil, err } return &wSdkClients{ - ssl: sslClient, - teo: teoClient, + SSL: sslClient, + TEO: teoClient, }, nil } diff --git a/internal/pkg/core/deployer/providers/tencentcloud-scf/tencentcloud_scf.go b/internal/pkg/core/deployer/providers/tencentcloud-scf/tencentcloud_scf.go index f136fa53..9d8512c2 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-scf/tencentcloud_scf.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-scf/tencentcloud_scf.go @@ -7,7 +7,7 @@ import ( xerrors "github.com/pkg/errors" "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common" "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile" - tcScf "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/scf/v20180416" + tcscf "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/scf/v20180416" "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/uploader" @@ -28,7 +28,7 @@ type DeployerConfig struct { type DeployerProvider struct { config *DeployerConfig logger *slog.Logger - sdkClient *tcScf.Client + sdkClient *tcscf.Client sslUploader uploader.Uploader } @@ -73,7 +73,7 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { // 查看云函数自定义域名详情 // REF: https://cloud.tencent.com/document/product/583/111924 - getCustomDomainReq := tcScf.NewGetCustomDomainRequest() + getCustomDomainReq := tcscf.NewGetCustomDomainRequest() getCustomDomainReq.Domain = common.StringPtr(d.config.Domain) getCustomDomainResp, err := d.sdkClient.GetCustomDomain(getCustomDomainReq) d.logger.Debug("sdk request 'scf.GetCustomDomain'", slog.Any("request", getCustomDomainReq), slog.Any("response", getCustomDomainResp)) @@ -91,9 +91,9 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe // 更新云函数自定义域名 // REF: https://cloud.tencent.com/document/product/583/111922 - updateCustomDomainReq := tcScf.NewUpdateCustomDomainRequest() + updateCustomDomainReq := tcscf.NewUpdateCustomDomainRequest() updateCustomDomainReq.Domain = common.StringPtr(d.config.Domain) - updateCustomDomainReq.CertConfig = &tcScf.CertConf{ + updateCustomDomainReq.CertConfig = &tcscf.CertConf{ CertificateId: common.StringPtr(upres.CertId), } updateCustomDomainReq.Protocol = getCustomDomainResp.Response.Protocol @@ -106,9 +106,9 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe return &deployer.DeployResult{}, nil } -func createSdkClient(secretId, secretKey, region string) (*tcScf.Client, error) { +func createSdkClient(secretId, secretKey, region string) (*tcscf.Client, error) { credential := common.NewCredential(secretId, secretKey) - client, err := tcScf.NewClient(credential, region, profile.NewClientProfile()) + client, err := tcscf.NewClient(credential, region, profile.NewClientProfile()) if err != nil { return nil, err } diff --git a/internal/pkg/core/deployer/providers/tencentcloud-ssl-deploy/tencentcloud_ssl_deploy.go b/internal/pkg/core/deployer/providers/tencentcloud-ssl-deploy/tencentcloud_ssl_deploy.go index acebc43e..8e06920a 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-ssl-deploy/tencentcloud_ssl_deploy.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-ssl-deploy/tencentcloud_ssl_deploy.go @@ -10,7 +10,7 @@ import ( xerrors "github.com/pkg/errors" "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common" "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile" - tcSsl "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssl/v20191205" + tcssl "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssl/v20191205" "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/uploader" @@ -33,7 +33,7 @@ type DeployerConfig struct { type DeployerProvider struct { config *DeployerConfig logger *slog.Logger - sdkClient *tcSsl.Client + sdkClient *tcssl.Client sslUploader uploader.Uploader } @@ -93,7 +93,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe // 证书部署到云资源实例列表 // REF: https://cloud.tencent.com/document/product/400/91667 - deployCertificateInstanceReq := tcSsl.NewDeployCertificateInstanceRequest() + deployCertificateInstanceReq := tcssl.NewDeployCertificateInstanceRequest() deployCertificateInstanceReq.CertificateId = common.StringPtr(upres.CertId) deployCertificateInstanceReq.ResourceType = common.StringPtr(d.config.ResourceType) deployCertificateInstanceReq.InstanceIdList = common.StringPtrs(d.config.ResourceIds) @@ -113,7 +113,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe return nil, ctx.Err() } - describeHostDeployRecordDetailReq := tcSsl.NewDescribeHostDeployRecordDetailRequest() + describeHostDeployRecordDetailReq := tcssl.NewDescribeHostDeployRecordDetailRequest() describeHostDeployRecordDetailReq.DeployRecordId = common.StringPtr(fmt.Sprintf("%d", *deployCertificateInstanceResp.Response.DeployRecordId)) describeHostDeployRecordDetailReq.Limit = common.Uint64Ptr(100) describeHostDeployRecordDetailResp, err := d.sdkClient.DescribeHostDeployRecordDetail(describeHostDeployRecordDetailReq) @@ -145,10 +145,10 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe return &deployer.DeployResult{}, nil } -func createSdkClient(secretId, secretKey, region string) (*tcSsl.Client, error) { +func createSdkClient(secretId, secretKey, region string) (*tcssl.Client, error) { credential := common.NewCredential(secretId, secretKey) - client, err := tcSsl.NewClient(credential, region, profile.NewClientProfile()) + client, err := tcssl.NewClient(credential, region, profile.NewClientProfile()) if err != nil { return nil, err } diff --git a/internal/pkg/core/deployer/providers/tencentcloud-vod/tencentcloud_vod.go b/internal/pkg/core/deployer/providers/tencentcloud-vod/tencentcloud_vod.go index 92469390..6a32eb62 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-vod/tencentcloud_vod.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-vod/tencentcloud_vod.go @@ -7,7 +7,7 @@ import ( xerrors "github.com/pkg/errors" "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common" "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile" - tcVod "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vod/v20180717" + tcvod "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vod/v20180717" "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/uploader" @@ -28,7 +28,7 @@ type DeployerConfig struct { type DeployerProvider struct { config *DeployerConfig logger *slog.Logger - sdkClient *tcVod.Client + sdkClient *tcvod.Client sslUploader uploader.Uploader } @@ -81,7 +81,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe // 设置点播域名 HTTPS 证书 // REF: https://cloud.tencent.com/document/api/266/102015 - setVodDomainCertificateReq := tcVod.NewSetVodDomainCertificateRequest() + setVodDomainCertificateReq := tcvod.NewSetVodDomainCertificateRequest() setVodDomainCertificateReq.Domain = common.StringPtr(d.config.Domain) setVodDomainCertificateReq.Operation = common.StringPtr("Set") setVodDomainCertificateReq.CertID = common.StringPtr(upres.CertId) @@ -97,9 +97,9 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe return &deployer.DeployResult{}, nil } -func createSdkClient(secretId, secretKey string) (*tcVod.Client, error) { +func createSdkClient(secretId, secretKey string) (*tcvod.Client, error) { credential := common.NewCredential(secretId, secretKey) - client, err := tcVod.NewClient(credential, "", profile.NewClientProfile()) + client, err := tcvod.NewClient(credential, "", profile.NewClientProfile()) if err != nil { return nil, err } diff --git a/internal/pkg/core/deployer/providers/tencentcloud-waf/tencentcloud_waf.go b/internal/pkg/core/deployer/providers/tencentcloud-waf/tencentcloud_waf.go index 400b96b8..2921fb84 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-waf/tencentcloud_waf.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-waf/tencentcloud_waf.go @@ -8,7 +8,7 @@ import ( xerrors "github.com/pkg/errors" "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common" "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile" - tcWaf "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/waf/v20180125" + tcwaf "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/waf/v20180125" "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/uploader" @@ -33,7 +33,7 @@ type DeployerConfig struct { type DeployerProvider struct { config *DeployerConfig logger *slog.Logger - sdkClient *tcWaf.Client + sdkClient *tcwaf.Client sslUploader uploader.Uploader } @@ -96,7 +96,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe // 查询单个 SaaS 型 WAF 域名详情 // REF: https://cloud.tencent.com/document/api/627/82938 - describeDomainDetailsSaasReq := tcWaf.NewDescribeDomainDetailsSaasRequest() + describeDomainDetailsSaasReq := tcwaf.NewDescribeDomainDetailsSaasRequest() describeDomainDetailsSaasReq.Domain = common.StringPtr(d.config.Domain) describeDomainDetailsSaasReq.DomainId = common.StringPtr(d.config.DomainId) describeDomainDetailsSaasReq.InstanceId = common.StringPtr(d.config.InstanceId) @@ -108,7 +108,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe // 编辑 SaaS 型 WAF 域名 // REF: https://cloud.tencent.com/document/api/627/94309 - modifySpartaProtectionReq := tcWaf.NewModifySpartaProtectionRequest() + modifySpartaProtectionReq := tcwaf.NewModifySpartaProtectionRequest() modifySpartaProtectionReq.Domain = common.StringPtr(d.config.Domain) modifySpartaProtectionReq.DomainId = common.StringPtr(d.config.DomainId) modifySpartaProtectionReq.InstanceID = common.StringPtr(d.config.InstanceId) @@ -123,9 +123,9 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe return &deployer.DeployResult{}, nil } -func createSdkClient(secretId, secretKey, region string) (*tcWaf.Client, error) { +func createSdkClient(secretId, secretKey, region string) (*tcwaf.Client, error) { credential := common.NewCredential(secretId, secretKey) - client, err := tcWaf.NewClient(credential, region, profile.NewClientProfile()) + client, err := tcwaf.NewClient(credential, region, profile.NewClientProfile()) if err != nil { return nil, err } diff --git a/internal/pkg/core/deployer/providers/ucloud-ucdn/ucloud_ucdn.go b/internal/pkg/core/deployer/providers/ucloud-ucdn/ucloud_ucdn.go index 117cf9fb..82be501c 100644 --- a/internal/pkg/core/deployer/providers/ucloud-ucdn/ucloud_ucdn.go +++ b/internal/pkg/core/deployer/providers/ucloud-ucdn/ucloud_ucdn.go @@ -7,9 +7,9 @@ import ( "strconv" xerrors "github.com/pkg/errors" - uCdn "github.com/ucloud/ucloud-sdk-go/services/ucdn" - usdk "github.com/ucloud/ucloud-sdk-go/ucloud" - uAuth "github.com/ucloud/ucloud-sdk-go/ucloud/auth" + "github.com/ucloud/ucloud-sdk-go/services/ucdn" + "github.com/ucloud/ucloud-sdk-go/ucloud" + "github.com/ucloud/ucloud-sdk-go/ucloud/auth" "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/uploader" @@ -30,7 +30,7 @@ type DeployerConfig struct { type DeployerProvider struct { config *DeployerConfig logger *slog.Logger - sdkClient *uCdn.UCDNClient + sdkClient *ucdn.UCDNClient sslUploader uploader.Uploader } @@ -87,7 +87,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe getUcdnDomainConfigReq := d.sdkClient.NewGetUcdnDomainConfigRequest() getUcdnDomainConfigReq.DomainId = []string{d.config.DomainId} if d.config.ProjectId != "" { - getUcdnDomainConfigReq.ProjectId = usdk.String(d.config.ProjectId) + getUcdnDomainConfigReq.ProjectId = ucloud.String(d.config.ProjectId) } getUcdnDomainConfigResp, err := d.sdkClient.GetUcdnDomainConfig(getUcdnDomainConfigReq) d.logger.Debug("sdk request 'ucdn.GetUcdnDomainConfig'", slog.Any("request", getUcdnDomainConfigReq), slog.Any("response", getUcdnDomainConfigResp)) @@ -101,15 +101,15 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe // REF: https://docs.ucloud.cn/api/ucdn-api/update_ucdn_domain_https_config_v2 certId, _ := strconv.Atoi(upres.CertId) updateUcdnDomainHttpsConfigV2Req := d.sdkClient.NewUpdateUcdnDomainHttpsConfigV2Request() - updateUcdnDomainHttpsConfigV2Req.DomainId = usdk.String(d.config.DomainId) - updateUcdnDomainHttpsConfigV2Req.HttpsStatusCn = usdk.String(getUcdnDomainConfigResp.DomainList[0].HttpsStatusCn) - updateUcdnDomainHttpsConfigV2Req.HttpsStatusAbroad = usdk.String(getUcdnDomainConfigResp.DomainList[0].HttpsStatusAbroad) - updateUcdnDomainHttpsConfigV2Req.HttpsStatusAbroad = usdk.String(getUcdnDomainConfigResp.DomainList[0].HttpsStatusAbroad) - updateUcdnDomainHttpsConfigV2Req.CertId = usdk.Int(certId) - updateUcdnDomainHttpsConfigV2Req.CertName = usdk.String(upres.CertName) - updateUcdnDomainHttpsConfigV2Req.CertType = usdk.String("ussl") + updateUcdnDomainHttpsConfigV2Req.DomainId = ucloud.String(d.config.DomainId) + updateUcdnDomainHttpsConfigV2Req.HttpsStatusCn = ucloud.String(getUcdnDomainConfigResp.DomainList[0].HttpsStatusCn) + updateUcdnDomainHttpsConfigV2Req.HttpsStatusAbroad = ucloud.String(getUcdnDomainConfigResp.DomainList[0].HttpsStatusAbroad) + updateUcdnDomainHttpsConfigV2Req.HttpsStatusAbroad = ucloud.String(getUcdnDomainConfigResp.DomainList[0].HttpsStatusAbroad) + updateUcdnDomainHttpsConfigV2Req.CertId = ucloud.Int(certId) + updateUcdnDomainHttpsConfigV2Req.CertName = ucloud.String(upres.CertName) + updateUcdnDomainHttpsConfigV2Req.CertType = ucloud.String("ussl") if d.config.ProjectId != "" { - updateUcdnDomainHttpsConfigV2Req.ProjectId = usdk.String(d.config.ProjectId) + updateUcdnDomainHttpsConfigV2Req.ProjectId = ucloud.String(d.config.ProjectId) } updateUcdnDomainHttpsConfigV2Resp, err := d.sdkClient.UpdateUcdnDomainHttpsConfigV2(updateUcdnDomainHttpsConfigV2Req) d.logger.Debug("sdk request 'ucdn.UpdateUcdnDomainHttpsConfigV2'", slog.Any("request", updateUcdnDomainHttpsConfigV2Req), slog.Any("response", updateUcdnDomainHttpsConfigV2Resp)) @@ -120,13 +120,13 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe return &deployer.DeployResult{}, nil } -func createSdkClient(privateKey, publicKey string) (*uCdn.UCDNClient, error) { - cfg := usdk.NewConfig() +func createSdkClient(privateKey, publicKey string) (*ucdn.UCDNClient, error) { + cfg := ucloud.NewConfig() - credential := uAuth.NewCredential() + credential := auth.NewCredential() credential.PrivateKey = privateKey credential.PublicKey = publicKey - client := uCdn.NewClient(&cfg, &credential) + client := ucdn.NewClient(&cfg, &credential) return client, nil } diff --git a/internal/pkg/core/deployer/providers/ucloud-us3/ucloud_us3.go b/internal/pkg/core/deployer/providers/ucloud-us3/ucloud_us3.go index 2d043a5d..d3a68868 100644 --- a/internal/pkg/core/deployer/providers/ucloud-us3/ucloud_us3.go +++ b/internal/pkg/core/deployer/providers/ucloud-us3/ucloud_us3.go @@ -5,8 +5,8 @@ import ( "log/slog" xerrors "github.com/pkg/errors" - usdk "github.com/ucloud/ucloud-sdk-go/ucloud" - uAuth "github.com/ucloud/ucloud-sdk-go/ucloud/auth" + "github.com/ucloud/ucloud-sdk-go/ucloud" + "github.com/ucloud/ucloud-sdk-go/ucloud/auth" "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/uploader" @@ -87,12 +87,12 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe // 添加 SSL 证书 // REF: https://docs.ucloud.cn/api/ufile-api/add_ufile_ssl_cert addUFileSSLCertReq := d.sdkClient.NewAddUFileSSLCertRequest() - addUFileSSLCertReq.BucketName = usdk.String(d.config.Bucket) - addUFileSSLCertReq.Domain = usdk.String(d.config.Domain) - addUFileSSLCertReq.USSLId = usdk.String(upres.CertId) - addUFileSSLCertReq.CertificateName = usdk.String(upres.CertName) + addUFileSSLCertReq.BucketName = ucloud.String(d.config.Bucket) + addUFileSSLCertReq.Domain = ucloud.String(d.config.Domain) + addUFileSSLCertReq.USSLId = ucloud.String(upres.CertId) + addUFileSSLCertReq.CertificateName = ucloud.String(upres.CertName) if d.config.ProjectId != "" { - addUFileSSLCertReq.ProjectId = usdk.String(d.config.ProjectId) + addUFileSSLCertReq.ProjectId = ucloud.String(d.config.ProjectId) } addUFileSSLCertResp, err := d.sdkClient.AddUFileSSLCert(addUFileSSLCertReq) d.logger.Debug("sdk request 'us3.AddUFileSSLCert'", slog.Any("request", addUFileSSLCertReq), slog.Any("response", addUFileSSLCertResp)) @@ -104,10 +104,10 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe } func createSdkClient(privateKey, publicKey, region string) (*usdkFile.UFileClient, error) { - cfg := usdk.NewConfig() + cfg := ucloud.NewConfig() cfg.Region = region - credential := uAuth.NewCredential() + credential := auth.NewCredential() credential.PrivateKey = privateKey credential.PublicKey = publicKey diff --git a/internal/pkg/core/deployer/providers/upyun-cdn/upyun_cdn_test.go b/internal/pkg/core/deployer/providers/upyun-cdn/upyun_cdn_test.go index 8a7b4485..7e9e16ff 100644 --- a/internal/pkg/core/deployer/providers/upyun-cdn/upyun_cdn_test.go +++ b/internal/pkg/core/deployer/providers/upyun-cdn/upyun_cdn_test.go @@ -37,7 +37,7 @@ Shell command to run this test: --CERTIMATE_DEPLOYER_UPYUNCDN_INPUTKEYPATH="/path/to/your-input-key.pem" \ --CERTIMATE_DEPLOYER_UPYUNCDN_USERNAME="your-username" \ --CERTIMATE_DEPLOYER_UPYUNCDN_PASSWORD="your-password" \ - --CERTIMATE_DEPLOYER_UPYUNCDN_DOMAIN="example.com" \ + --CERTIMATE_DEPLOYER_UPYUNCDN_DOMAIN="example.com" */ func TestDeploy(t *testing.T) { flag.Parse() diff --git a/internal/pkg/core/deployer/providers/volcengine-alb/consts.go b/internal/pkg/core/deployer/providers/volcengine-alb/consts.go new file mode 100644 index 00000000..aba1182c --- /dev/null +++ b/internal/pkg/core/deployer/providers/volcengine-alb/consts.go @@ -0,0 +1,10 @@ +package volcenginealb + +type ResourceType string + +const ( + // 资源类型:部署到指定负载均衡器。 + RESOURCE_TYPE_LOADBALANCER = ResourceType("loadbalancer") + // 资源类型:部署到指定监听器。 + RESOURCE_TYPE_LISTENER = ResourceType("listener") +) diff --git a/internal/pkg/core/deployer/providers/volcengine-alb/volcengine_alb.go b/internal/pkg/core/deployer/providers/volcengine-alb/volcengine_alb.go new file mode 100644 index 00000000..0c6ba1b4 --- /dev/null +++ b/internal/pkg/core/deployer/providers/volcengine-alb/volcengine_alb.go @@ -0,0 +1,263 @@ +package volcenginealb + +import ( + "context" + "errors" + "fmt" + "log/slog" + + xerrors "github.com/pkg/errors" + vealb "github.com/volcengine/volcengine-go-sdk/service/alb" + ve "github.com/volcengine/volcengine-go-sdk/volcengine" + vesession "github.com/volcengine/volcengine-go-sdk/volcengine/session" + + "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" + "github.com/usual2970/certimate/internal/pkg/utils/sliceutil" +) + +type DeployerConfig struct { + // 火山引擎 AccessKeyId。 + AccessKeyId string `json:"accessKeyId"` + // 火山引擎 AccessKeySecret。 + AccessKeySecret string `json:"accessKeySecret"` + // 火山引擎地域。 + Region string `json:"region"` + // 部署资源类型。 + ResourceType ResourceType `json:"resourceType"` + // 负载均衡实例 ID。 + // 部署资源类型为 [RESOURCE_TYPE_LOADBALANCER] 时必填。 + LoadbalancerId string `json:"loadbalancerId,omitempty"` + // 负载均衡监听器 ID。 + // 部署资源类型为 [RESOURCE_TYPE_LISTENER] 时必填。 + ListenerId string `json:"listenerId,omitempty"` + // SNI 域名(支持泛域名)。 + // 部署资源类型为 [RESOURCE_TYPE_LOADBALANCER]、[RESOURCE_TYPE_LISTENER] 时选填。 + Domain string `json:"domain,omitempty"` +} + +type DeployerProvider struct { + config *DeployerConfig + logger *slog.Logger + sdkClient *vealb.ALB + 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, config.Region) + if err != nil { + return nil, xerrors.Wrap(err, "failed to create sdk client") + } + + uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ + AccessKeyId: config.AccessKeyId, + AccessKeySecret: config.AccessKeySecret, + Region: config.Region, + }) + if err != nil { + return nil, xerrors.Wrap(err, "failed to create ssl uploader") + } + + 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.Default() + } 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, xerrors.Wrap(err, "failed to upload certificate file") + } else { + d.logger.Info("ssl certificate uploaded", slog.Any("result", upres)) + } + + // 根据部署资源类型决定部署方式 + switch d.config.ResourceType { + case RESOURCE_TYPE_LOADBALANCER: + if err := d.deployToLoadbalancer(ctx, upres.CertId); err != nil { + return nil, err + } + + case RESOURCE_TYPE_LISTENER: + if err := d.deployToListener(ctx, upres.CertId); err != nil { + return nil, err + } + + default: + return nil, fmt.Errorf("unsupported resource type: %s", d.config.ResourceType) + } + + return &deployer.DeployResult{}, nil +} + +func (d *DeployerProvider) deployToLoadbalancer(ctx context.Context, cloudCertId string) error { + if d.config.LoadbalancerId == "" { + return errors.New("config `loadbalancerId` is required") + } + + // 查询 ALB 实例的详细信息 + // REF: https://www.volcengine.com/docs/6767/113596 + describeLoadBalancerAttributesReq := &vealb.DescribeLoadBalancerAttributesInput{ + LoadBalancerId: ve.String(d.config.LoadbalancerId), + } + describeLoadBalancerAttributesResp, err := d.sdkClient.DescribeLoadBalancerAttributes(describeLoadBalancerAttributesReq) + d.logger.Debug("sdk request 'alb.DescribeLoadBalancerAttributes'", slog.Any("request", describeLoadBalancerAttributesReq), slog.Any("response", describeLoadBalancerAttributesResp)) + if err != nil { + return xerrors.Wrap(err, "failed to execute sdk request 'alb.DescribeLoadBalancerAttributes'") + } + + // 查询 HTTPS 监听器列表 + // REF: https://www.volcengine.com/docs/6767/113684 + listenerIds := make([]string, 0) + describeListenersPageSize := int64(100) + describeListenersPageNumber := int64(1) + for { + describeListenersReq := &vealb.DescribeListenersInput{ + LoadBalancerId: ve.String(d.config.LoadbalancerId), + Protocol: ve.String("HTTPS"), + PageNumber: ve.Int64(describeListenersPageNumber), + PageSize: ve.Int64(describeListenersPageSize), + } + describeListenersResp, err := d.sdkClient.DescribeListeners(describeListenersReq) + d.logger.Debug("sdk request 'alb.DescribeListeners'", slog.Any("request", describeListenersReq), slog.Any("response", describeListenersResp)) + if err != nil { + return xerrors.Wrap(err, "failed to execute sdk request 'alb.DescribeListeners'") + } + + for _, listener := range describeListenersResp.Listeners { + listenerIds = append(listenerIds, *listener.ListenerId) + } + + if len(describeListenersResp.Listeners) < int(describeListenersPageSize) { + break + } else { + describeListenersPageNumber++ + } + } + + // 遍历更新监听证书 + if len(listenerIds) == 0 { + d.logger.Info("no alb listeners to deploy") + } else { + d.logger.Info("found https listeners to deploy", slog.Any("listenerIds", listenerIds)) + var errs []error + + for _, listenerId := range listenerIds { + if err := d.updateListenerCertificate(ctx, listenerId, cloudCertId); err != nil { + errs = append(errs, err) + } + } + + if len(errs) > 0 { + return errors.Join(errs...) + } + } + + return nil +} + +func (d *DeployerProvider) deployToListener(ctx context.Context, cloudCertId string) error { + if d.config.ListenerId == "" { + return errors.New("config `listenerId` is required") + } + + if err := d.updateListenerCertificate(ctx, d.config.LoadbalancerId, cloudCertId); err != nil { + return err + } + + return nil +} + +func (d *DeployerProvider) updateListenerCertificate(ctx context.Context, cloudListenerId string, cloudCertId string) error { + // 查询指定监听器的详细信息 + // REF: https://www.volcengine.com/docs/6767/113686 + describeListenerAttributesReq := &vealb.DescribeListenerAttributesInput{ + ListenerId: ve.String(cloudListenerId), + } + describeListenerAttributesResp, err := d.sdkClient.DescribeListenerAttributes(describeListenerAttributesReq) + d.logger.Debug("sdk request 'alb.DescribeListenerAttributes'", slog.Any("request", describeListenerAttributesReq), slog.Any("response", describeListenerAttributesResp)) + if err != nil { + return xerrors.Wrap(err, "failed to execute sdk request 'alb.DescribeListenerAttributes'") + } + + if d.config.Domain == "" { + // 未指定 SNI,只需部署到监听器 + + // 修改指定监听器 + // REF: https://www.volcengine.com/docs/6767/113683 + modifyListenerAttributesReq := &vealb.ModifyListenerAttributesInput{ + ListenerId: ve.String(cloudListenerId), + CertificateSource: ve.String("cert_center"), + CertCenterCertificateId: ve.String(cloudCertId), + } + modifyListenerAttributesResp, err := d.sdkClient.ModifyListenerAttributes(modifyListenerAttributesReq) + d.logger.Debug("sdk request 'alb.ModifyListenerAttributes'", slog.Any("request", modifyListenerAttributesReq), slog.Any("response", modifyListenerAttributesResp)) + if err != nil { + return xerrors.Wrap(err, "failed to execute sdk request 'alb.ModifyListenerAttributes'") + } + } else { + // 指定 SNI,需部署到扩展域名 + + // 修改指定监听器 + // REF: https://www.volcengine.com/docs/6767/113683 + modifyListenerAttributesReq := &vealb.ModifyListenerAttributesInput{ + ListenerId: ve.String(cloudListenerId), + DomainExtensions: sliceutil.Map( + sliceutil.Filter( + describeListenerAttributesResp.DomainExtensions, + func(domain *vealb.DomainExtensionForDescribeListenerAttributesOutput) bool { + return *domain.Domain == d.config.Domain + }, + ), + func(domain *vealb.DomainExtensionForDescribeListenerAttributesOutput) *vealb.DomainExtensionForModifyListenerAttributesInput { + return &vealb.DomainExtensionForModifyListenerAttributesInput{ + DomainExtensionId: domain.DomainExtensionId, + Domain: domain.Domain, + CertificateSource: ve.String("cert_center"), + CertCenterCertificateId: ve.String(cloudCertId), + Action: ve.String("modify"), + } + }), + } + modifyListenerAttributesResp, err := d.sdkClient.ModifyListenerAttributes(modifyListenerAttributesReq) + d.logger.Debug("sdk request 'alb.ModifyListenerAttributes'", slog.Any("request", modifyListenerAttributesReq), slog.Any("response", modifyListenerAttributesResp)) + if err != nil { + return xerrors.Wrap(err, "failed to execute sdk request 'alb.ModifyListenerAttributes'") + } + } + + return nil +} + +func createSdkClient(accessKeyId, accessKeySecret, region string) (*vealb.ALB, error) { + config := ve.NewConfig().WithRegion(region).WithAkSk(accessKeyId, accessKeySecret) + + session, err := vesession.NewSession(config) + if err != nil { + return nil, err + } + + client := vealb.New(session) + return client, nil +} diff --git a/internal/pkg/core/deployer/providers/volcengine-alb/volcengine_alb_test.go b/internal/pkg/core/deployer/providers/volcengine-alb/volcengine_alb_test.go new file mode 100644 index 00000000..23a79200 --- /dev/null +++ b/internal/pkg/core/deployer/providers/volcengine-alb/volcengine_alb_test.go @@ -0,0 +1,81 @@ +package volcenginealb_test + +import ( + "context" + "flag" + "fmt" + "os" + "strings" + "testing" + + provider "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/volcengine-alb" +) + +var ( + fInputCertPath string + fInputKeyPath string + fAccessKeyId string + fAccessKeySecret string + fRegion string + fListenerId string +) + +func init() { + argsPrefix := "CERTIMATE_DEPLOYER_VOLCENGINEALB_" + + flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "") + flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "") + flag.StringVar(&fAccessKeyId, argsPrefix+"ACCESSKEYID", "", "") + flag.StringVar(&fAccessKeySecret, argsPrefix+"ACCESSKEYSECRET", "", "") + flag.StringVar(&fRegion, argsPrefix+"REGION", "", "") + flag.StringVar(&fListenerId, argsPrefix+"LISTENERID", "", "") +} + +/* +Shell command to run this test: + + go test -v ./volcengine_alb_test.go -args \ + --CERTIMATE_DEPLOYER_VOLCENGINEALB_INPUTCERTPATH="/path/to/your-input-cert.pem" \ + --CERTIMATE_DEPLOYER_VOLCENGINEALB_INPUTKEYPATH="/path/to/your-input-key.pem" \ + --CERTIMATE_DEPLOYER_VOLCENGINEALB_ACCESSKEYID="your-access-key-id" \ + --CERTIMATE_DEPLOYER_VOLCENGINEALB_ACCESSKEYSECRET="your-access-key-secret" \ + --CERTIMATE_DEPLOYER_VOLCENGINEALB_REGION="cn-beijing" \ + --CERTIMATE_DEPLOYER_VOLCENGINEALB_LISTENERID="your-listener-id" +*/ +func TestDeploy(t *testing.T) { + flag.Parse() + + t.Run("Deploy", func(t *testing.T) { + t.Log(strings.Join([]string{ + "args:", + fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath), + fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath), + fmt.Sprintf("ACCESSKEYID: %v", fAccessKeyId), + fmt.Sprintf("ACCESSKEYSECRET: %v", fAccessKeySecret), + fmt.Sprintf("REGION: %v", fRegion), + fmt.Sprintf("LISTENERID: %v", fListenerId), + }, "\n")) + + deployer, err := provider.NewDeployer(&provider.DeployerConfig{ + AccessKeyId: fAccessKeyId, + AccessKeySecret: fAccessKeySecret, + Region: fRegion, + ResourceType: provider.RESOURCE_TYPE_LISTENER, + ListenerId: fListenerId, + }) + if err != nil { + t.Errorf("err: %+v", err) + return + } + + fInputCertData, _ := os.ReadFile(fInputCertPath) + fInputKeyData, _ := os.ReadFile(fInputKeyPath) + res, err := deployer.Deploy(context.Background(), string(fInputCertData), string(fInputKeyData)) + if err != nil { + t.Errorf("err: %+v", err) + return + } + + t.Logf("ok: %v", res) + }) +} diff --git a/internal/pkg/core/deployer/providers/volcengine-cdn/volcengine_cdn.go b/internal/pkg/core/deployer/providers/volcengine-cdn/volcengine_cdn.go index 88f05415..fe0844d9 100644 --- a/internal/pkg/core/deployer/providers/volcengine-cdn/volcengine_cdn.go +++ b/internal/pkg/core/deployer/providers/volcengine-cdn/volcengine_cdn.go @@ -7,7 +7,7 @@ import ( "strings" xerrors "github.com/pkg/errors" - veCdn "github.com/volcengine/volc-sdk-golang/service/cdn" + vecdn "github.com/volcengine/volc-sdk-golang/service/cdn" "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/uploader" @@ -26,7 +26,7 @@ type DeployerConfig struct { type DeployerProvider struct { config *DeployerConfig logger *slog.Logger - sdkClient *veCdn.CDN + sdkClient *vecdn.CDN sslUploader uploader.Uploader } @@ -37,7 +37,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { panic("config is nil") } - client := veCdn.NewInstance() + client := vecdn.NewInstance() client.Client.SetAccessKey(config.AccessKeyId) client.Client.SetSecretKey(config.AccessKeySecret) @@ -80,7 +80,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe if strings.HasPrefix(d.config.Domain, "*.") { // 获取指定证书可关联的域名 // REF: https://www.volcengine.com/docs/6454/125711 - describeCertConfigReq := &veCdn.DescribeCertConfigRequest{ + describeCertConfigReq := &vecdn.DescribeCertConfigRequest{ CertId: upres.CertId, } describeCertConfigResp, err := d.sdkClient.DescribeCertConfig(describeCertConfigReq) @@ -119,7 +119,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe for _, domain := range domains { // 关联证书与加速域名 // REF: https://www.volcengine.com/docs/6454/125712 - batchDeployCertReq := &veCdn.BatchDeployCertRequest{ + batchDeployCertReq := &vecdn.BatchDeployCertRequest{ CertId: upres.CertId, Domain: domain, } diff --git a/internal/pkg/core/deployer/providers/volcengine-certcenter/volcengine_certcenter.go b/internal/pkg/core/deployer/providers/volcengine-certcenter/volcengine_certcenter.go new file mode 100644 index 00000000..a8062641 --- /dev/null +++ b/internal/pkg/core/deployer/providers/volcengine-certcenter/volcengine_certcenter.go @@ -0,0 +1,72 @@ +package volcenginecertcenter + +import ( + "context" + "log/slog" + + xerrors "github.com/pkg/errors" + + "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, xerrors.Wrap(err, "failed to create ssl uploader") + } + + 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.Default() + } 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, xerrors.Wrap(err, "failed to upload certificate file") + } else { + d.logger.Info("ssl certificate uploaded", slog.Any("result", upres)) + } + + return &deployer.DeployResult{}, nil +} diff --git a/internal/pkg/core/deployer/providers/volcengine-clb/consts.go b/internal/pkg/core/deployer/providers/volcengine-clb/consts.go index dc1e992b..4d9ab1e3 100644 --- a/internal/pkg/core/deployer/providers/volcengine-clb/consts.go +++ b/internal/pkg/core/deployer/providers/volcengine-clb/consts.go @@ -3,6 +3,8 @@ type ResourceType string const ( + // 资源类型:部署到指定负载均衡器。 + RESOURCE_TYPE_LOADBALANCER = ResourceType("loadbalancer") // 资源类型:部署到指定监听器。 RESOURCE_TYPE_LISTENER = ResourceType("listener") ) diff --git a/internal/pkg/core/deployer/providers/volcengine-clb/volcengine_clb.go b/internal/pkg/core/deployer/providers/volcengine-clb/volcengine_clb.go index b3ba7241..37481a3f 100644 --- a/internal/pkg/core/deployer/providers/volcengine-clb/volcengine_clb.go +++ b/internal/pkg/core/deployer/providers/volcengine-clb/volcengine_clb.go @@ -7,9 +7,9 @@ import ( "log/slog" xerrors "github.com/pkg/errors" - veClb "github.com/volcengine/volcengine-go-sdk/service/clb" + veclb "github.com/volcengine/volcengine-go-sdk/service/clb" ve "github.com/volcengine/volcengine-go-sdk/volcengine" - veSession "github.com/volcengine/volcengine-go-sdk/volcengine/session" + vesession "github.com/volcengine/volcengine-go-sdk/volcengine/session" "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/uploader" @@ -25,6 +25,9 @@ type DeployerConfig struct { Region string `json:"region"` // 部署资源类型。 ResourceType ResourceType `json:"resourceType"` + // 负载均衡实例 ID。 + // 部署资源类型为 [RESOURCE_TYPE_LOADBALANCER] 时必填。 + LoadbalancerId string `json:"loadbalancerId,omitempty"` // 负载均衡监听器 ID。 // 部署资源类型为 [RESOURCE_TYPE_LISTENER] 时必填。 ListenerId string `json:"listenerId,omitempty"` @@ -33,7 +36,7 @@ type DeployerConfig struct { type DeployerProvider struct { config *DeployerConfig logger *slog.Logger - sdkClient *veClb.CLB + sdkClient *veclb.CLB sslUploader uploader.Uploader } @@ -87,6 +90,11 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe // 根据部署资源类型决定部署方式 switch d.config.ResourceType { + case RESOURCE_TYPE_LOADBALANCER: + if err := d.deployToLoadbalancer(ctx, upres.CertId); err != nil { + return nil, err + } + case RESOURCE_TYPE_LISTENER: if err := d.deployToListener(ctx, upres.CertId); err != nil { return nil, err @@ -99,15 +107,89 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe return &deployer.DeployResult{}, nil } +func (d *DeployerProvider) deployToLoadbalancer(ctx context.Context, cloudCertId string) error { + if d.config.LoadbalancerId == "" { + return errors.New("config `loadbalancerId` is required") + } + + // 查看指定负载均衡实例的详情 + // REF: https://www.volcengine.com/docs/6406/71773 + describeLoadBalancerAttributesReq := &veclb.DescribeLoadBalancerAttributesInput{ + LoadBalancerId: ve.String(d.config.LoadbalancerId), + } + describeLoadBalancerAttributesResp, err := d.sdkClient.DescribeLoadBalancerAttributes(describeLoadBalancerAttributesReq) + d.logger.Debug("sdk request 'clb.DescribeLoadBalancerAttributes'", slog.Any("request", describeLoadBalancerAttributesReq), slog.Any("response", describeLoadBalancerAttributesResp)) + if err != nil { + return xerrors.Wrap(err, "failed to execute sdk request 'clb.DescribeLoadBalancerAttributes'") + } + + // 查询 HTTPS 监听器列表 + // REF: https://www.volcengine.com/docs/6406/71776 + listenerIds := make([]string, 0) + describeListenersPageSize := int64(100) + describeListenersPageNumber := int64(1) + for { + describeListenersReq := &veclb.DescribeListenersInput{ + LoadBalancerId: ve.String(d.config.LoadbalancerId), + Protocol: ve.String("HTTPS"), + PageNumber: ve.Int64(describeListenersPageNumber), + PageSize: ve.Int64(describeListenersPageSize), + } + describeListenersResp, err := d.sdkClient.DescribeListeners(describeListenersReq) + d.logger.Debug("sdk request 'clb.DescribeListeners'", slog.Any("request", describeListenersReq), slog.Any("response", describeListenersResp)) + if err != nil { + return xerrors.Wrap(err, "failed to execute sdk request 'clb.DescribeListeners'") + } + + for _, listener := range describeListenersResp.Listeners { + listenerIds = append(listenerIds, *listener.ListenerId) + } + + if len(describeListenersResp.Listeners) < int(describeListenersPageSize) { + break + } else { + describeListenersPageNumber++ + } + } + + // 遍历更新监听证书 + if len(listenerIds) == 0 { + d.logger.Info("no clb listeners to deploy") + } else { + d.logger.Info("found https listeners to deploy", slog.Any("listenerIds", listenerIds)) + var errs []error + + for _, listenerId := range listenerIds { + if err := d.updateListenerCertificate(ctx, listenerId, cloudCertId); err != nil { + errs = append(errs, err) + } + } + + if len(errs) > 0 { + return errors.Join(errs...) + } + } + + return nil +} + func (d *DeployerProvider) deployToListener(ctx context.Context, cloudCertId string) error { if d.config.ListenerId == "" { return errors.New("config `listenerId` is required") } - // 修改监听器 + if err := d.updateListenerCertificate(ctx, d.config.LoadbalancerId, cloudCertId); err != nil { + return err + } + + return nil +} + +func (d *DeployerProvider) updateListenerCertificate(ctx context.Context, cloudListenerId string, cloudCertId string) error { + // 修改指定监听器 // REF: https://www.volcengine.com/docs/6406/71775 - modifyListenerAttributesReq := &veClb.ModifyListenerAttributesInput{ - ListenerId: ve.String(d.config.ListenerId), + modifyListenerAttributesReq := &veclb.ModifyListenerAttributesInput{ + ListenerId: ve.String(cloudListenerId), CertificateSource: ve.String("cert_center"), CertCenterCertificateId: ve.String(cloudCertId), } @@ -120,14 +202,14 @@ func (d *DeployerProvider) deployToListener(ctx context.Context, cloudCertId str return nil } -func createSdkClient(accessKeyId, accessKeySecret, region string) (*veClb.CLB, error) { +func createSdkClient(accessKeyId, accessKeySecret, region string) (*veclb.CLB, error) { config := ve.NewConfig().WithRegion(region).WithAkSk(accessKeyId, accessKeySecret) - session, err := veSession.NewSession(config) + session, err := vesession.NewSession(config) if err != nil { return nil, err } - client := veClb.New(session) + client := veclb.New(session) return client, nil } diff --git a/internal/pkg/core/deployer/providers/volcengine-clb/volcengine_clb_test.go b/internal/pkg/core/deployer/providers/volcengine-clb/volcengine_clb_test.go index 0b589f88..9e9e63e2 100644 --- a/internal/pkg/core/deployer/providers/volcengine-clb/volcengine_clb_test.go +++ b/internal/pkg/core/deployer/providers/volcengine-clb/volcengine_clb_test.go @@ -40,7 +40,7 @@ Shell command to run this test: --CERTIMATE_DEPLOYER_VOLCENGINECLB_ACCESSKEYID="your-access-key-id" \ --CERTIMATE_DEPLOYER_VOLCENGINECLB_ACCESSKEYSECRET="your-access-key-secret" \ --CERTIMATE_DEPLOYER_VOLCENGINECLB_REGION="cn-beijing" \ - --CERTIMATE_DEPLOYER_VOLCENGINECLB_LISTENERID="cn-beijing" + --CERTIMATE_DEPLOYER_VOLCENGINECLB_LISTENERID="your-listener-id" */ func TestDeploy(t *testing.T) { flag.Parse() diff --git a/internal/pkg/core/deployer/providers/volcengine-dcdn/volcengine_dcdn.go b/internal/pkg/core/deployer/providers/volcengine-dcdn/volcengine_dcdn.go index 0b9de8a7..23af16e5 100644 --- a/internal/pkg/core/deployer/providers/volcengine-dcdn/volcengine_dcdn.go +++ b/internal/pkg/core/deployer/providers/volcengine-dcdn/volcengine_dcdn.go @@ -6,9 +6,9 @@ import ( "strings" xerrors "github.com/pkg/errors" - veDcdn "github.com/volcengine/volcengine-go-sdk/service/dcdn" + vedcdn "github.com/volcengine/volcengine-go-sdk/service/dcdn" ve "github.com/volcengine/volcengine-go-sdk/volcengine" - veSession "github.com/volcengine/volcengine-go-sdk/volcengine/session" + vesession "github.com/volcengine/volcengine-go-sdk/volcengine/session" "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/uploader" @@ -29,7 +29,7 @@ type DeployerConfig struct { type DeployerProvider struct { config *DeployerConfig logger *slog.Logger - sdkClient *veDcdn.DCDN + sdkClient *vedcdn.DCDN sslUploader uploader.Uploader } @@ -86,7 +86,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe // 绑定证书 // REF: https://www.volcengine.com/docs/6559/1250189 - createCertBindReq := &veDcdn.CreateCertBindInput{ + createCertBindReq := &vedcdn.CreateCertBindInput{ CertSource: ve.String("volc"), CertId: ve.String(upres.CertId), DomainNames: ve.StringSlice([]string{domain}), @@ -100,18 +100,18 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe return &deployer.DeployResult{}, nil } -func createSdkClient(accessKeyId, accessKeySecret, region string) (*veDcdn.DCDN, error) { +func createSdkClient(accessKeyId, accessKeySecret, region string) (*vedcdn.DCDN, error) { if region == "" { region = "cn-beijing" // DCDN 服务默认区域:北京 } config := ve.NewConfig().WithRegion(region).WithAkSk(accessKeyId, accessKeySecret) - session, err := veSession.NewSession(config) + session, err := vesession.NewSession(config) if err != nil { return nil, err } - client := veDcdn.New(session) + client := vedcdn.New(session) return client, nil } diff --git a/internal/pkg/core/deployer/providers/volcengine-imagex/volcengine_imagex.go b/internal/pkg/core/deployer/providers/volcengine-imagex/volcengine_imagex.go index f3ac68bf..26696d57 100644 --- a/internal/pkg/core/deployer/providers/volcengine-imagex/volcengine_imagex.go +++ b/internal/pkg/core/deployer/providers/volcengine-imagex/volcengine_imagex.go @@ -6,8 +6,8 @@ import ( "log/slog" xerrors "github.com/pkg/errors" - veBase "github.com/volcengine/volc-sdk-golang/base" - veImageX "github.com/volcengine/volc-sdk-golang/service/imagex/v2" + vebase "github.com/volcengine/volc-sdk-golang/base" + veimagex "github.com/volcengine/volc-sdk-golang/service/imagex/v2" "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/uploader" @@ -30,7 +30,7 @@ type DeployerConfig struct { type DeployerProvider struct { config *DeployerConfig logger *slog.Logger - sdkClient *veImageX.Imagex + sdkClient *veimagex.Imagex sslUploader uploader.Uploader } @@ -91,7 +91,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe // 获取域名配置 // REF: https://www.volcengine.com/docs/508/9366 - getDomainConfigReq := &veImageX.GetDomainConfigQuery{ + getDomainConfigReq := &veimagex.GetDomainConfigQuery{ ServiceID: d.config.ServiceId, DomainName: d.config.Domain, } @@ -103,13 +103,13 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe // 更新 HTTPS 配置 // REF: https://www.volcengine.com/docs/508/66012 - updateHttpsReq := &veImageX.UpdateHTTPSReq{ - UpdateHTTPSQuery: &veImageX.UpdateHTTPSQuery{ + updateHttpsReq := &veimagex.UpdateHTTPSReq{ + UpdateHTTPSQuery: &veimagex.UpdateHTTPSQuery{ ServiceID: d.config.ServiceId, }, - UpdateHTTPSBody: &veImageX.UpdateHTTPSBody{ + UpdateHTTPSBody: &veimagex.UpdateHTTPSBody{ Domain: d.config.Domain, - HTTPS: &veImageX.UpdateHTTPSBodyHTTPS{ + HTTPS: &veimagex.UpdateHTTPSBodyHTTPS{ CertID: upres.CertId, EnableHTTPS: true, }, @@ -133,15 +133,15 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe return &deployer.DeployResult{}, nil } -func createSdkClient(accessKeyId, accessKeySecret, region string) (*veImageX.Imagex, error) { - var instance *veImageX.Imagex +func createSdkClient(accessKeyId, accessKeySecret, region string) (*veimagex.Imagex, error) { + var instance *veimagex.Imagex if region == "" { - instance = veImageX.NewInstance() + instance = veimagex.NewInstance() } else { - instance = veImageX.NewInstanceWithRegion(region) + instance = veimagex.NewInstanceWithRegion(region) } - instance.SetCredential(veBase.Credentials{ + instance.SetCredential(vebase.Credentials{ AccessKeyID: accessKeyId, SecretAccessKey: accessKeySecret, }) diff --git a/internal/pkg/core/deployer/providers/volcengine-live/volcengine_live.go b/internal/pkg/core/deployer/providers/volcengine-live/volcengine_live.go index 15073743..a12df9f2 100644 --- a/internal/pkg/core/deployer/providers/volcengine-live/volcengine_live.go +++ b/internal/pkg/core/deployer/providers/volcengine-live/volcengine_live.go @@ -7,7 +7,7 @@ import ( "strings" xerrors "github.com/pkg/errors" - veLive "github.com/volcengine/volc-sdk-golang/service/live/v20230101" + velive "github.com/volcengine/volc-sdk-golang/service/live/v20230101" ve "github.com/volcengine/volcengine-go-sdk/volcengine" "github.com/usual2970/certimate/internal/pkg/core/deployer" @@ -27,7 +27,7 @@ type DeployerConfig struct { type DeployerProvider struct { config *DeployerConfig logger *slog.Logger - sdkClient *veLive.Live + sdkClient *velive.Live sslUploader uploader.Uploader } @@ -38,7 +38,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { panic("config is nil") } - client := veLive.NewInstance() + client := velive.NewInstance() client.SetAccessKey(config.AccessKeyId) client.SetSecretKey(config.AccessKeySecret) @@ -85,7 +85,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe for { // 查询域名列表 // REF: https://www.volcengine.com/docs/6469/1186277#%E6%9F%A5%E8%AF%A2%E5%9F%9F%E5%90%8D%E5%88%97%E8%A1%A8 - listDomainDetailReq := &veLive.ListDomainDetailBody{ + listDomainDetailReq := &velive.ListDomainDetailBody{ PageNum: listDomainDetailPageNum, PageSize: listDomainDetailPageSize, } @@ -127,7 +127,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe for _, domain := range domains { // 绑定证书 // REF: https://www.volcengine.com/docs/6469/1186278#%E7%BB%91%E5%AE%9A%E8%AF%81%E4%B9%A6 - bindCertReq := &veLive.BindCertBody{ + bindCertReq := &velive.BindCertBody{ ChainID: upres.CertId, Domain: domain, HTTPS: ve.Bool(true), diff --git a/internal/pkg/core/deployer/providers/volcengine-tos/volcengine_tos.go b/internal/pkg/core/deployer/providers/volcengine-tos/volcengine_tos.go index d4bd6e59..f2ac4128 100644 --- a/internal/pkg/core/deployer/providers/volcengine-tos/volcengine_tos.go +++ b/internal/pkg/core/deployer/providers/volcengine-tos/volcengine_tos.go @@ -7,7 +7,7 @@ import ( "log/slog" xerrors "github.com/pkg/errors" - veTos "github.com/volcengine/ve-tos-golang-sdk/v2/tos" + "github.com/volcengine/ve-tos-golang-sdk/v2/tos" "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/uploader" @@ -30,7 +30,7 @@ type DeployerConfig struct { type DeployerProvider struct { config *DeployerConfig logger *slog.Logger - sdkClient *veTos.ClientV2 + sdkClient *tos.ClientV2 sslUploader uploader.Uploader } @@ -91,9 +91,9 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe // 设置自定义域名 // REF: https://www.volcengine.com/docs/6559/1250189 - putBucketCustomDomainReq := &veTos.PutBucketCustomDomainInput{ + putBucketCustomDomainReq := &tos.PutBucketCustomDomainInput{ Bucket: d.config.Bucket, - Rule: veTos.CustomDomainRule{ + Rule: tos.CustomDomainRule{ Domain: d.config.Domain, CertID: upres.CertId, }, @@ -107,13 +107,13 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe return &deployer.DeployResult{}, nil } -func createSdkClient(accessKeyId, accessKeySecret, region string) (*veTos.ClientV2, error) { +func createSdkClient(accessKeyId, accessKeySecret, region string) (*tos.ClientV2, error) { endpoint := fmt.Sprintf("tos-%s.ivolces.com", region) - client, err := veTos.NewClientV2( + client, err := tos.NewClientV2( endpoint, - veTos.WithRegion(region), - veTos.WithCredentials(veTos.NewStaticCredentials(accessKeyId, accessKeySecret)), + tos.WithRegion(region), + tos.WithCredentials(tos.NewStaticCredentials(accessKeyId, accessKeySecret)), ) if err != nil { return nil, err diff --git a/internal/pkg/core/uploader/providers/aliyun-cas/aliyun_cas.go b/internal/pkg/core/uploader/providers/aliyun-cas/aliyun_cas.go index f7633cce..9f3e9212 100644 --- a/internal/pkg/core/uploader/providers/aliyun-cas/aliyun_cas.go +++ b/internal/pkg/core/uploader/providers/aliyun-cas/aliyun_cas.go @@ -85,36 +85,38 @@ func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPe if listUserCertificateOrderResp.Body.CertificateOrderList != nil { for _, certDetail := range listUserCertificateOrderResp.Body.CertificateOrderList { - if strings.EqualFold(certX509.SerialNumber.Text(16), *certDetail.SerialNo) { - getUserCertificateDetailReq := &alicas.GetUserCertificateDetailRequest{ - CertId: certDetail.CertificateId, - } - getUserCertificateDetailResp, err := u.sdkClient.GetUserCertificateDetail(getUserCertificateDetailReq) - u.logger.Debug("sdk request 'cas.GetUserCertificateDetail'", slog.Any("request", getUserCertificateDetailReq), slog.Any("response", getUserCertificateDetailResp)) + if !strings.EqualFold(certX509.SerialNumber.Text(16), *certDetail.SerialNo) { + continue + } + + getUserCertificateDetailReq := &alicas.GetUserCertificateDetailRequest{ + CertId: certDetail.CertificateId, + } + getUserCertificateDetailResp, err := u.sdkClient.GetUserCertificateDetail(getUserCertificateDetailReq) + u.logger.Debug("sdk request 'cas.GetUserCertificateDetail'", slog.Any("request", getUserCertificateDetailReq), slog.Any("response", getUserCertificateDetailResp)) + if err != nil { + return nil, xerrors.Wrap(err, "failed to execute sdk request 'cas.GetUserCertificateDetail'") + } + + var isSameCert bool + if *getUserCertificateDetailResp.Body.Cert == certPem { + isSameCert = true + } else { + oldCertX509, err := certutil.ParseCertificateFromPEM(*getUserCertificateDetailResp.Body.Cert) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'cas.GetUserCertificateDetail'") + continue } - var isSameCert bool - if *getUserCertificateDetailResp.Body.Cert == certPem { - isSameCert = true - } else { - oldCertX509, err := certutil.ParseCertificateFromPEM(*getUserCertificateDetailResp.Body.Cert) - if err != nil { - continue - } + isSameCert = certutil.EqualCertificate(certX509, oldCertX509) + } - isSameCert = certutil.EqualCertificate(certX509, oldCertX509) - } - - // 如果已存在相同证书,直接返回 - if isSameCert { - u.logger.Info("ssl certificate already exists") - return &uploader.UploadResult{ - CertId: fmt.Sprintf("%d", tea.Int64Value(certDetail.CertificateId)), - CertName: *certDetail.Name, - }, nil - } + // 如果已存在相同证书,直接返回 + if isSameCert { + u.logger.Info("ssl certificate already exists") + return &uploader.UploadResult{ + CertId: fmt.Sprintf("%d", tea.Int64Value(certDetail.CertificateId)), + CertName: *certDetail.Name, + }, nil } } } diff --git a/internal/pkg/core/uploader/providers/baiducloud-cert/baiducloud_cert.go b/internal/pkg/core/uploader/providers/baiducloud-cert/baiducloud_cert.go new file mode 100644 index 00000000..1f311f87 --- /dev/null +++ b/internal/pkg/core/uploader/providers/baiducloud-cert/baiducloud_cert.go @@ -0,0 +1,139 @@ +package baiducloudcert + +import ( + "context" + "fmt" + "log/slog" + "strings" + "time" + + xerrors "github.com/pkg/errors" + + "github.com/usual2970/certimate/internal/pkg/core/uploader" + "github.com/usual2970/certimate/internal/pkg/utils/certutil" + bdsdk "github.com/usual2970/certimate/internal/pkg/vendors/baiducloud-sdk/cert" +) + +type UploaderConfig struct { + // 百度智能云 AccessKeyId。 + AccessKeyId string `json:"accessKeyId"` + // 百度智能云 SecretAccessKey。 + SecretAccessKey string `json:"secretAccessKey"` +} + +type UploaderProvider struct { + config *UploaderConfig + logger *slog.Logger + sdkClient *bdsdk.Client +} + +var _ uploader.Uploader = (*UploaderProvider)(nil) + +func NewUploader(config *UploaderConfig) (*UploaderProvider, error) { + if config == nil { + panic("config is nil") + } + + client, err := createSdkClient(config.AccessKeyId, config.SecretAccessKey) + if err != nil { + return nil, xerrors.Wrap(err, "failed to create sdk client") + } + + 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.Default() + } else { + u.logger = logger + } + return u +} + +func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPem string) (res *uploader.UploadResult, err error) { + // 解析证书内容 + certX509, err := certutil.ParseCertificateFromPEM(certPem) + if err != nil { + return nil, err + } + + // 遍历证书列表,避免重复上传 + // REF: https://cloud.baidu.com/doc/Reference/s/Gjwvz27xu#35-%E6%9F%A5%E7%9C%8B%E8%AF%81%E4%B9%A6%E5%88%97%E8%A1%A8%E8%AF%A6%E6%83%85 + listCertDetail, err := u.sdkClient.ListCertDetail() + u.logger.Debug("sdk request 'cert.ListCertDetail'", slog.Any("response", listCertDetail)) + if err != nil { + return nil, xerrors.Wrap(err, "failed to execute sdk request 'cert.ListCertDetail'") + } else { + for _, certDetail := range listCertDetail.Certs { + // 先对比证书通用名称 + if !strings.EqualFold(certX509.Subject.CommonName, certDetail.CertCommonName) { + continue + } + + // 再对比证书有效期 + oldCertNotBefore, _ := time.Parse("2006-01-02T15:04:05Z", certDetail.CertStartTime) + oldCertNotAfter, _ := time.Parse("2006-01-02T15:04:05Z", certDetail.CertStopTime) + if !certX509.NotBefore.Equal(oldCertNotBefore) || !certX509.NotAfter.Equal(oldCertNotAfter) { + continue + } + + // 再对比证书多域名 + if certDetail.CertDNSNames != strings.Join(certX509.DNSNames, ",") { + continue + } + + // 最后对比证书内容 + getCertDetailResp, err := u.sdkClient.GetCertRawData(certDetail.CertId) + u.logger.Debug("sdk request 'cert.GetCertRawData'", slog.Any("certId", certDetail.CertId), slog.Any("response", getCertDetailResp)) + if err != nil { + return nil, xerrors.Wrap(err, "failed to execute sdk request 'cert.GetCertRawData'") + } else { + oldCertX509, err := certutil.ParseCertificateFromPEM(getCertDetailResp.CertServerData) + if err != nil { + continue + } + if !certutil.EqualCertificate(certX509, oldCertX509) { + continue + } + } + + // 如果以上信息都一致,则视为已存在相同证书,直接返回 + u.logger.Info("ssl certificate already exists") + return &uploader.UploadResult{ + CertId: certDetail.CertId, + CertName: certDetail.CertName, + }, nil + } + } + + // 创建证书 + // REF: https://cloud.baidu.com/doc/Reference/s/Gjwvz27xu#31-%E5%88%9B%E5%BB%BA%E8%AF%81%E4%B9%A6 + createCertReq := &bdsdk.CreateCertArgs{} + createCertReq.CertName = fmt.Sprintf("certimate-%d", time.Now().UnixMilli()) + createCertReq.CertServerData = certPem + createCertReq.CertPrivateData = privkeyPem + createCertResp, err := u.sdkClient.CreateCert(createCertReq) + u.logger.Debug("sdk request 'cert.CreateCert'", slog.Any("request", createCertReq), slog.Any("response", createCertResp)) + if err != nil { + return nil, xerrors.Wrap(err, "failed to execute sdk request 'cert.CreateCert'") + } + + return &uploader.UploadResult{ + CertId: createCertResp.CertId, + CertName: createCertResp.CertName, + }, nil +} + +func createSdkClient(accessKeyId, secretAccessKey string) (*bdsdk.Client, error) { + client, err := bdsdk.NewClient(accessKeyId, secretAccessKey, "") + if err != nil { + return nil, err + } + + return client, nil +} diff --git a/internal/pkg/core/uploader/providers/baiducloud-cert/baiducloud_cert_test.go b/internal/pkg/core/uploader/providers/baiducloud-cert/baiducloud_cert_test.go new file mode 100644 index 00000000..55de1576 --- /dev/null +++ b/internal/pkg/core/uploader/providers/baiducloud-cert/baiducloud_cert_test.go @@ -0,0 +1,72 @@ +package baiducloudcert_test + +import ( + "context" + "encoding/json" + "flag" + "fmt" + "os" + "strings" + "testing" + + provider "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/baiducloud-cert" +) + +var ( + fInputCertPath string + fInputKeyPath string + fAccessKeyId string + fSecretAccessKey string +) + +func init() { + argsPrefix := "CERTIMATE_UPLOADER_BAIDUCLOUDCAS_" + + flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "") + flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "") + flag.StringVar(&fAccessKeyId, argsPrefix+"ACCESSKEYID", "", "") + flag.StringVar(&fSecretAccessKey, argsPrefix+"SECRETACCESSKEY", "", "") +} + +/* +Shell command to run this test: + + go test -v ./baiducloud_cas_test.go -args \ + --CERTIMATE_UPLOADER_BAIDUCLOUDCAS_INPUTCERTPATH="/path/to/your-input-cert.pem" \ + --CERTIMATE_UPLOADER_BAIDUCLOUDCAS_INPUTKEYPATH="/path/to/your-input-key.pem" \ + --CERTIMATE_UPLOADER_BAIDUCLOUDCAS_ACCESSKEYID="your-access-key-id" \ + --CERTIMATE_UPLOADER_BAIDUCLOUDCAS_SECRETACCESSKEY="your-access-key-secret" +*/ +func TestDeploy(t *testing.T) { + flag.Parse() + + t.Run("Deploy", func(t *testing.T) { + t.Log(strings.Join([]string{ + "args:", + fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath), + fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath), + fmt.Sprintf("ACCESSKEYID: %v", fAccessKeyId), + fmt.Sprintf("SECRETACCESSKEY: %v", fSecretAccessKey), + }, "\n")) + + uploader, err := provider.NewUploader(&provider.UploaderConfig{ + AccessKeyId: fAccessKeyId, + SecretAccessKey: fSecretAccessKey, + }) + if err != nil { + t.Errorf("err: %+v", err) + return + } + + fInputCertData, _ := os.ReadFile(fInputCertPath) + fInputKeyData, _ := os.ReadFile(fInputKeyPath) + res, err := uploader.Upload(context.Background(), string(fInputCertData), string(fInputKeyData)) + if err != nil { + t.Errorf("err: %+v", err) + return + } + + sres, _ := json.Marshal(res) + t.Logf("ok: %s", string(sres)) + }) +} diff --git a/internal/pkg/core/uploader/providers/upyun-ssl/upyun_ssl.go b/internal/pkg/core/uploader/providers/upyun-ssl/upyun_ssl.go index 3e4d3c40..dbbe41fa 100644 --- a/internal/pkg/core/uploader/providers/upyun-ssl/upyun_ssl.go +++ b/internal/pkg/core/uploader/providers/upyun-ssl/upyun_ssl.go @@ -59,9 +59,9 @@ func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPe PrivateKey: privkeyPem, } uploadHttpsCertificateResp, err := u.sdkClient.UploadHttpsCertificate(uploadHttpsCertificateReq) - u.logger.Debug("sdk request 'ssl.UploadHttpsCertificate'", slog.Any("response", uploadHttpsCertificateResp)) + u.logger.Debug("sdk request 'console.UploadHttpsCertificate'", slog.Any("response", uploadHttpsCertificateResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'ssl.UploadHttpsCertificate'") + return nil, xerrors.Wrap(err, "failed to execute sdk request 'console.UploadHttpsCertificate'") } return &uploader.UploadResult{ diff --git a/internal/pkg/core/uploader/uploader.go b/internal/pkg/core/uploader/uploader.go index 06cecec0..5edcdce4 100644 --- a/internal/pkg/core/uploader/uploader.go +++ b/internal/pkg/core/uploader/uploader.go @@ -27,6 +27,6 @@ type Uploader interface { // 表示证书上传结果的数据结构,包含上传后的证书 ID、名称和其他数据。 type UploadResult struct { CertId string `json:"certId"` - CertName string `json:"certName"` + CertName string `json:"certName,omitzero"` ExtendedData map[string]any `json:"extendedData,omitempty"` } diff --git a/internal/pkg/vendors/1panel-sdk/api.go b/internal/pkg/vendors/1panel-sdk/api.go index a6390408..8b0a6d09 100644 --- a/internal/pkg/vendors/1panel-sdk/api.go +++ b/internal/pkg/vendors/1panel-sdk/api.go @@ -8,44 +8,29 @@ import ( func (c *Client) UpdateSystemSSL(req *UpdateSystemSSLRequest) (*UpdateSystemSSLResponse, error) { resp := &UpdateSystemSSLResponse{} err := c.sendRequestWithResult(http.MethodPost, "/settings/ssl/update", req, resp) - if err != nil { - return nil, err - } - return resp, nil + return resp, err } func (c *Client) SearchWebsiteSSL(req *SearchWebsiteSSLRequest) (*SearchWebsiteSSLResponse, error) { resp := &SearchWebsiteSSLResponse{} err := c.sendRequestWithResult(http.MethodPost, "/websites/ssl/search", req, resp) - if err != nil { - return nil, err - } - return resp, nil + return resp, err } func (c *Client) UploadWebsiteSSL(req *UploadWebsiteSSLRequest) (*UploadWebsiteSSLResponse, error) { resp := &UploadWebsiteSSLResponse{} err := c.sendRequestWithResult(http.MethodPost, "/websites/ssl/upload", req, resp) - if err != nil { - return nil, err - } - return resp, nil + return resp, err } func (c *Client) GetHttpsConf(req *GetHttpsConfRequest) (*GetHttpsConfResponse, error) { resp := &GetHttpsConfResponse{} err := c.sendRequestWithResult(http.MethodGet, fmt.Sprintf("/websites/%d/https", req.WebsiteID), req, resp) - if err != nil { - return nil, err - } - return resp, nil + return resp, err } func (c *Client) UpdateHttpsConf(req *UpdateHttpsConfRequest) (*UpdateHttpsConfResponse, error) { resp := &UpdateHttpsConfResponse{} err := c.sendRequestWithResult(http.MethodPost, fmt.Sprintf("/websites/%d/https", req.WebsiteID), req, resp) - if err != nil { - return nil, err - } - return resp, nil + return resp, err } diff --git a/internal/pkg/vendors/1panel-sdk/client.go b/internal/pkg/vendors/1panel-sdk/client.go index 9c424111..653e3a69 100644 --- a/internal/pkg/vendors/1panel-sdk/client.go +++ b/internal/pkg/vendors/1panel-sdk/client.go @@ -77,9 +77,9 @@ func (c *Client) sendRequest(method string, path string, params interface{}) (*r resp, err := req.Send() if err != nil { - return nil, fmt.Errorf("1panel api error: failed to send request: %w", err) + return resp, fmt.Errorf("1panel api error: failed to send request: %w", err) } else if resp.IsError() { - return nil, fmt.Errorf("1panel api error: unexpected status code: %d, %s", resp.StatusCode(), resp.Body()) + return resp, fmt.Errorf("1panel api error: unexpected status code: %d, %s", resp.StatusCode(), resp.Body()) } return resp, nil @@ -88,6 +88,9 @@ func (c *Client) sendRequest(method string, path string, params interface{}) (*r 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 } diff --git a/internal/pkg/vendors/1panel-sdk/models.go b/internal/pkg/vendors/1panel-sdk/models.go index 8510aefe..af1bdbe9 100644 --- a/internal/pkg/vendors/1panel-sdk/models.go +++ b/internal/pkg/vendors/1panel-sdk/models.go @@ -6,16 +6,22 @@ type BaseResponse interface { } type baseResponse struct { - Code int32 `json:"code"` - Message string `json:"message"` + Code *int32 `json:"code,omitempty"` + Message *string `json:"message,omitempty"` } func (r *baseResponse) GetCode() int32 { - return r.Code + if r.Code != nil { + return *r.Code + } + return 0 } func (r *baseResponse) GetMessage() string { - return r.Message + if r.Message != nil { + return *r.Message + } + return "" } type UpdateSystemSSLRequest struct { @@ -38,7 +44,7 @@ type SearchWebsiteSSLRequest struct { type SearchWebsiteSSLResponse struct { baseResponse - Data struct { + Data *struct { Items []*struct { ID int64 `json:"id"` PEM string `json:"pem"` @@ -50,7 +56,7 @@ type SearchWebsiteSSLResponse struct { CreatedAt string `json:"createdAt"` } `json:"items"` Total int32 `json:"total"` - } `json:"data"` + } `json:"data,omitempty"` } type UploadWebsiteSSLRequest struct { @@ -73,13 +79,13 @@ type GetHttpsConfRequest struct { type GetHttpsConfResponse struct { baseResponse - Data struct { + Data *struct { Enable bool `json:"enable"` HttpConfig string `json:"httpConfig"` SSLProtocol []string `json:"SSLProtocol"` Algorithm string `json:"algorithm"` Hsts bool `json:"hsts"` - } `json:"data"` + } `json:"data,omitempty"` } type UpdateHttpsConfRequest struct { diff --git a/internal/pkg/vendors/baiducloud-sdk/cert/api.go b/internal/pkg/vendors/baiducloud-sdk/cert/api.go new file mode 100644 index 00000000..78c6c26a --- /dev/null +++ b/internal/pkg/vendors/baiducloud-sdk/cert/api.go @@ -0,0 +1,93 @@ +package cert + +import ( + "errors" + "fmt" + + "github.com/baidubce/bce-sdk-go/bce" + "github.com/baidubce/bce-sdk-go/http" + "github.com/baidubce/bce-sdk-go/services/cert" +) + +func (c *Client) CreateCert(args *CreateCertArgs) (*CreateCertResult, error) { + if args == nil { + return nil, errors.New("unset args") + } + + result, err := c.Client.CreateCert(&args.CreateCertArgs) + if err != nil { + return nil, err + } + + return &CreateCertResult{CreateCertResult: *result}, nil +} + +func (c *Client) ListCerts() (*ListCertResult, error) { + result, err := c.Client.ListCerts() + if err != nil { + return nil, err + } + + return &ListCertResult{ListCertResult: *result}, nil +} + +func (c *Client) ListCertDetail() (*ListCertDetailResult, error) { + result, err := c.Client.ListCertDetail() + if err != nil { + return nil, err + } + + return &ListCertDetailResult{ListCertDetailResult: *result}, nil +} + +func (c *Client) GetCertMeta(id string) (*CertificateMeta, error) { + result, err := c.Client.GetCertMeta(id) + if err != nil { + return nil, err + } + + return &CertificateMeta{CertificateMeta: *result}, nil +} + +func (c *Client) GetCertDetail(id string) (*CertificateDetailMeta, error) { + result, err := c.Client.GetCertDetail(id) + if err != nil { + return nil, err + } + + return &CertificateDetailMeta{CertificateDetailMeta: *result}, nil +} + +func (c *Client) GetCertRawData(id string) (*CertificateRawData, error) { + result := &CertificateRawData{} + err := bce.NewRequestBuilder(c). + WithMethod(http.GET). + WithURL(cert.URI_PREFIX + cert.REQUEST_CERT_URL + "/" + id + "/rawData"). + WithResult(result). + Do() + + return result, err +} + +func (c *Client) UpdateCertName(id string, args *UpdateCertNameArgs) error { + if args == nil { + return errors.New("unset args") + } + + err := c.Client.UpdateCertName(id, &args.UpdateCertNameArgs) + return err +} + +func (c *Client) UpdateCertData(id string, args *UpdateCertDataArgs) error { + if args == nil { + return fmt.Errorf("unset args") + } + + err := c.Client.UpdateCertData(id, &args.UpdateCertDataArgs) + return err +} + +func (c *Client) DeleteCert(id string) error { + err := c.Client.DeleteCert(id) + return err +} diff --git a/internal/pkg/vendors/baiducloud-sdk/cert/client.go b/internal/pkg/vendors/baiducloud-sdk/cert/client.go new file mode 100644 index 00000000..02c4feff --- /dev/null +++ b/internal/pkg/vendors/baiducloud-sdk/cert/client.go @@ -0,0 +1,17 @@ +package cert + +import ( + "github.com/baidubce/bce-sdk-go/services/cert" +) + +type Client struct { + *cert.Client +} + +func NewClient(ak, sk, endPoint string) (*Client, error) { + client, err := cert.NewClient(ak, sk, endPoint) + if err != nil { + return nil, err + } + return &Client{client}, nil +} diff --git a/internal/pkg/vendors/baiducloud-sdk/cert/models.go b/internal/pkg/vendors/baiducloud-sdk/cert/models.go new file mode 100644 index 00000000..d3fe0449 --- /dev/null +++ b/internal/pkg/vendors/baiducloud-sdk/cert/models.go @@ -0,0 +1,48 @@ +package cert + +import "github.com/baidubce/bce-sdk-go/services/cert" + +type CreateCertArgs struct { + cert.CreateCertArgs +} + +type CreateCertResult struct { + cert.CreateCertResult +} + +type UpdateCertNameArgs struct { + cert.UpdateCertNameArgs +} + +type CertificateMeta struct { + cert.CertificateMeta +} + +type CertificateDetailMeta struct { + cert.CertificateDetailMeta +} + +type CertificateRawData struct { + CertId string `json:"certId"` + CertName string `json:"certName"` + CertServerData string `json:"certServerData"` + CertPrivateData string `json:"certPrivateKey"` + CertLinkData string `json:"certLinkData,omitempty"` + CertType int `json:"certType,omitempty"` +} + +type ListCertResult struct { + cert.ListCertResult +} + +type ListCertDetailResult struct { + cert.ListCertDetailResult +} + +type UpdateCertDataArgs struct { + cert.UpdateCertDataArgs +} + +type CertInServiceMeta struct { + cert.CertInServiceMeta +} diff --git a/internal/pkg/vendors/baishan-sdk/api.go b/internal/pkg/vendors/baishan-sdk/api.go index c2f76adc..9abc6427 100644 --- a/internal/pkg/vendors/baishan-sdk/api.go +++ b/internal/pkg/vendors/baishan-sdk/api.go @@ -5,28 +5,19 @@ import ( ) func (c *Client) CreateCertificate(req *CreateCertificateRequest) (*CreateCertificateResponse, error) { - resp := CreateCertificateResponse{} - err := c.sendRequestWithResult(http.MethodPost, "/v2/domain/certificate", req, &resp) - if err != nil { - return nil, err - } - return &resp, nil + 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) - if err != nil { - return nil, err - } - return &resp, nil + 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) - if err != nil { - return nil, err - } - return &resp, nil + resp := &SetDomainConfigResponse{} + err := c.sendRequestWithResult(http.MethodPost, "/v2/domain/config", req, resp) + return resp, err } diff --git a/internal/pkg/vendors/baishan-sdk/client.go b/internal/pkg/vendors/baishan-sdk/client.go index 44015b62..400e1ae1 100644 --- a/internal/pkg/vendors/baishan-sdk/client.go +++ b/internal/pkg/vendors/baishan-sdk/client.go @@ -4,6 +4,8 @@ import ( "encoding/json" "fmt" "net/http" + "net/url" + "reflect" "strings" "time" @@ -35,21 +37,33 @@ func (c *Client) sendRequest(method string, path string, params interface{}) (*r req.Method = method req.URL = "https://cdn.api.baishan.com" + path if strings.EqualFold(method, http.MethodGet) { - qs := make(map[string]string) + 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 { - qs[k] = fmt.Sprintf("%v", v) + 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. - SetQueryParams(qs). - SetQueryParam("token", c.apiToken) + SetQueryParam("token", c.apiToken). + SetQueryParamsFromValues(qs) } else { req = req. SetHeader("Content-Type", "application/json"). @@ -59,9 +73,9 @@ func (c *Client) sendRequest(method string, path string, params interface{}) (*r resp, err := req.Send() if err != nil { - return nil, fmt.Errorf("baishan api error: failed to send request: %w", err) + return resp, fmt.Errorf("baishan api error: failed to send request: %w", err) } else if resp.IsError() { - return nil, fmt.Errorf("baishan api error: unexpected status code: %d, %s", resp.StatusCode(), resp.Body()) + return resp, fmt.Errorf("baishan api error: unexpected status code: %d, %s", resp.StatusCode(), resp.Body()) } return resp, nil @@ -70,6 +84,9 @@ func (c *Client) sendRequest(method string, path string, params interface{}) (*r 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 } diff --git a/internal/pkg/vendors/baishan-sdk/models.go b/internal/pkg/vendors/baishan-sdk/models.go index e1c79c0e..b7dfd3f5 100644 --- a/internal/pkg/vendors/baishan-sdk/models.go +++ b/internal/pkg/vendors/baishan-sdk/models.go @@ -1,21 +1,29 @@ package baishansdk +import "encoding/json" + type BaseResponse interface { - GetCode() int + GetCode() int32 GetMessage() string } type baseResponse struct { - Code int `json:"code"` - Message string `json:"message"` + Code *int32 `json:"code,omitempty"` + Message *string `json:"message,omitempty"` } -func (r *baseResponse) GetCode() int { - return r.Code +func (r *baseResponse) GetCode() int32 { + if r.Code != nil { + return *r.Code + } + return 0 } func (r *baseResponse) GetMessage() string { - return r.Message + if r.Message != nil { + return *r.Message + } + return "" } type CreateCertificateRequest struct { @@ -26,11 +34,11 @@ type CreateCertificateRequest struct { type CreateCertificateResponse struct { baseResponse - Data *DomainCertificate `json:"data"` + Data *DomainCertificate `json:"data,omitempty"` } type GetDomainConfigRequest struct { - Domains string `json:"domains"` + Domains string `json:"domains"` Config []string `json:"config"` } @@ -39,7 +47,7 @@ type GetDomainConfigResponse struct { Data []*struct { Domain string `json:"domain"` Config *DomainConfig `json:"config"` - } `json:"data"` + } `json:"data,omitempty"` } type SetDomainConfigRequest struct { @@ -51,14 +59,14 @@ type SetDomainConfigResponse struct { baseResponse Data *struct { Config *DomainConfig `json:"config"` - } `json:"data"` + } `json:"data,omitempty"` } type DomainCertificate struct { - CertId int64 `json:"cert_id"` - Name string `json:"name"` - CertStartTime string `json:"cert_start_time"` - CertExpireTime string `json:"cert_expire_time"` + 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 { @@ -66,8 +74,8 @@ type DomainConfig struct { } type DomainConfigHttps struct { - CertId int64 `json:"cert_id"` - ForceHttps *string `json:"force_https,omitempty"` - EnableHttp2 *string `json:"http2,omitempty"` - EnableOcsp *string `json:"ocsp,omitempty"` + CertId json.Number `json:"cert_id"` + ForceHttps *string `json:"force_https,omitempty"` + EnableHttp2 *string `json:"http2,omitempty"` + EnableOcsp *string `json:"ocsp,omitempty"` } diff --git a/internal/pkg/vendors/btpanel-sdk/api.go b/internal/pkg/vendors/btpanel-sdk/api.go index 434e7f6e..a2b63127 100644 --- a/internal/pkg/vendors/btpanel-sdk/api.go +++ b/internal/pkg/vendors/btpanel-sdk/api.go @@ -1,46 +1,31 @@ package btpanelsdk func (c *Client) ConfigSavePanelSSL(req *ConfigSavePanelSSLRequest) (*ConfigSavePanelSSLResponse, error) { - resp := ConfigSavePanelSSLResponse{} - err := c.sendRequestWithResult("/config?action=SavePanelSSL", req, &resp) - if err != nil { - return nil, err - } - return &resp, nil + 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) - if err != nil { - return nil, err - } - return &resp, nil + 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) - if err != nil { - return nil, err - } - return &resp, nil + 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) - if err != nil { - return nil, err - } - return &resp, nil + 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) - if err != nil { - return nil, err - } - return &resp, nil + resp := &SSLSetBatchCertToSiteResponse{} + err := c.sendRequestWithResult("/ssl?action=SetBatchCertToSite", req, resp) + return resp, err } diff --git a/internal/pkg/vendors/btpanel-sdk/client.go b/internal/pkg/vendors/btpanel-sdk/client.go index 847a4387..8fb4ad32 100644 --- a/internal/pkg/vendors/btpanel-sdk/client.go +++ b/internal/pkg/vendors/btpanel-sdk/client.go @@ -84,9 +84,9 @@ func (c *Client) sendRequest(path string, params interface{}) (*resty.Response, SetFormData(data) resp, err := req.Post(url) if err != nil { - return nil, fmt.Errorf("baota api error: failed to send request: %w", err) + return resp, fmt.Errorf("baota api error: failed to send request: %w", err) } else if resp.IsError() { - return nil, fmt.Errorf("baota api error: unexpected status code: %d, %s", resp.StatusCode(), resp.Body()) + return resp, fmt.Errorf("baota api error: unexpected status code: %d, %s", resp.StatusCode(), resp.Body()) } return resp, nil diff --git a/internal/pkg/vendors/cachefly-sdk/api.go b/internal/pkg/vendors/cachefly-sdk/api.go index ad6e3b8d..b4219fa1 100644 --- a/internal/pkg/vendors/cachefly-sdk/api.go +++ b/internal/pkg/vendors/cachefly-sdk/api.go @@ -5,10 +5,7 @@ import ( ) func (c *Client) CreateCertificate(req *CreateCertificateRequest) (*CreateCertificateResponse, error) { - resp := CreateCertificateResponse{} - err := c.sendRequestWithResult(http.MethodPost, "/certificates", req, &resp) - if err != nil { - return nil, err - } - return &resp, nil + resp := &CreateCertificateResponse{} + err := c.sendRequestWithResult(http.MethodPost, "/certificates", req, resp) + return resp, err } diff --git a/internal/pkg/vendors/cachefly-sdk/client.go b/internal/pkg/vendors/cachefly-sdk/client.go index 505aafaf..0b11f6d2 100644 --- a/internal/pkg/vendors/cachefly-sdk/client.go +++ b/internal/pkg/vendors/cachefly-sdk/client.go @@ -57,9 +57,9 @@ func (c *Client) sendRequest(method string, path string, params interface{}) (*r resp, err := req.Send() if err != nil { - return nil, fmt.Errorf("cachefly api error: failed to send request: %w", err) + return resp, fmt.Errorf("cachefly api error: failed to send request: %w", err) } else if resp.IsError() { - return nil, fmt.Errorf("cachefly api error: unexpected status code: %d, %s", resp.StatusCode(), resp.Body()) + return resp, fmt.Errorf("cachefly api error: unexpected status code: %d, %s", resp.StatusCode(), resp.Body()) } return resp, nil @@ -68,6 +68,9 @@ func (c *Client) sendRequest(method string, path string, params interface{}) (*r 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 } diff --git a/internal/pkg/vendors/cachefly-sdk/models.go b/internal/pkg/vendors/cachefly-sdk/models.go index aaca7723..4026f2f6 100644 --- a/internal/pkg/vendors/cachefly-sdk/models.go +++ b/internal/pkg/vendors/cachefly-sdk/models.go @@ -1,15 +1,18 @@ package cacheflysdk type BaseResponse interface { - GetMessage() *string + GetMessage() string } type baseResponse struct { Message *string `json:"message,omitempty"` } -func (r *baseResponse) GetMessage() *string { - return r.Message +func (r *baseResponse) GetMessage() string { + if r.Message != nil { + return *r.Message + } + return "" } type CreateCertificateRequest struct { diff --git a/internal/pkg/vendors/cdnfly-sdk/api.go b/internal/pkg/vendors/cdnfly-sdk/api.go index 211baa33..2387f6d8 100644 --- a/internal/pkg/vendors/cdnfly-sdk/api.go +++ b/internal/pkg/vendors/cdnfly-sdk/api.go @@ -6,37 +6,25 @@ import ( ) func (c *Client) GetSite(req *GetSiteRequest) (*GetSiteResponse, error) { - resp := GetSiteResponse{} - err := c.sendRequestWithResult(http.MethodGet, fmt.Sprintf("/v1/sites/%s", req.Id), req, &resp) - if err != nil { - return nil, err - } - return &resp, nil + resp := &GetSiteResponse{} + err := c.sendRequestWithResult(http.MethodGet, fmt.Sprintf("/v1/sites/%s", req.Id), req, resp) + return resp, err } func (c *Client) UpdateSite(req *UpdateSiteRequest) (*UpdateSiteResponse, error) { - resp := UpdateSiteResponse{} - err := c.sendRequestWithResult(http.MethodPut, fmt.Sprintf("/v1/sites/%s", req.Id), req, &resp) - if err != nil { - return nil, err - } - return &resp, nil + resp := &UpdateSiteResponse{} + err := c.sendRequestWithResult(http.MethodPut, fmt.Sprintf("/v1/sites/%s", 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) - if err != nil { - return nil, err - } - return &resp, nil + resp := &CreateCertificateResponse{} + err := c.sendRequestWithResult(http.MethodPost, "/v1/certs", req, resp) + return resp, err } func (c *Client) UpdateCertificate(req *UpdateCertificateRequest) (*UpdateCertificateResponse, error) { - resp := UpdateCertificateResponse{} - err := c.sendRequestWithResult(http.MethodPut, fmt.Sprintf("/v1/certs/%s", req.Id), req, &resp) - if err != nil { - return nil, err - } - return &resp, nil + resp := &UpdateCertificateResponse{} + err := c.sendRequestWithResult(http.MethodPut, fmt.Sprintf("/v1/certs/%s", req.Id), req, resp) + return resp, err } diff --git a/internal/pkg/vendors/cdnfly-sdk/client.go b/internal/pkg/vendors/cdnfly-sdk/client.go index 7e2e93f4..b43a04db 100644 --- a/internal/pkg/vendors/cdnfly-sdk/client.go +++ b/internal/pkg/vendors/cdnfly-sdk/client.go @@ -63,9 +63,9 @@ func (c *Client) sendRequest(method string, path string, params interface{}) (*r resp, err := req.Send() if err != nil { - return nil, fmt.Errorf("cdnfly api error: failed to send request: %w", err) + return resp, fmt.Errorf("cdnfly api error: failed to send request: %w", err) } else if resp.IsError() { - return nil, fmt.Errorf("cdnfly api error: unexpected status code: %d, %s", resp.StatusCode(), resp.Body()) + return resp, fmt.Errorf("cdnfly api error: unexpected status code: %d, %s", resp.StatusCode(), resp.Body()) } return resp, nil @@ -74,6 +74,9 @@ func (c *Client) sendRequest(method string, path string, params interface{}) (*r 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 } diff --git a/internal/pkg/vendors/cdnfly-sdk/models.go b/internal/pkg/vendors/cdnfly-sdk/models.go index adaf3188..07497cd3 100644 --- a/internal/pkg/vendors/cdnfly-sdk/models.go +++ b/internal/pkg/vendors/cdnfly-sdk/models.go @@ -31,7 +31,7 @@ type GetSiteResponse struct { Name string `json:"name"` Domain string `json:"domain"` HttpsListen string `json:"https_listen"` - } `json:"data"` + } `json:"data,omitempty"` } type UpdateSiteRequest struct { diff --git a/internal/pkg/vendors/dnsla-sdk/api.go b/internal/pkg/vendors/dnsla-sdk/api.go index df8e6026..dae745c4 100644 --- a/internal/pkg/vendors/dnsla-sdk/api.go +++ b/internal/pkg/vendors/dnsla-sdk/api.go @@ -7,46 +7,31 @@ import ( ) func (c *Client) ListDomains(req *ListDomainsRequest) (*ListDomainsResponse, error) { - resp := ListDomainsResponse{} - err := c.sendRequestWithResult(http.MethodGet, "/domainList", req, &resp) - if err != nil { - return nil, err - } - return &resp, nil + 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) - if err != nil { - return nil, err - } - return &resp, nil + 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) - if err != nil { - return nil, err - } - return &resp, nil + 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) - if err != nil { - return nil, err - } - return &resp, nil + resp := &UpdateRecordResponse{} + err := c.sendRequestWithResult(http.MethodPut, "/record", req, resp) + return resp, err } func (c *Client) DeleteRecord(req *DeleteRecordRequest) (*DeleteRecordResponse, error) { - resp := DeleteRecordResponse{} - err := c.sendRequestWithResult(http.MethodDelete, fmt.Sprintf("/record?id=%s", url.QueryEscape(req.Id)), req, &resp) - if err != nil { - return nil, err - } - return &resp, nil + resp := &DeleteRecordResponse{} + err := c.sendRequestWithResult(http.MethodDelete, fmt.Sprintf("/record?id=%s", url.QueryEscape(req.Id)), req, resp) + return resp, err } diff --git a/internal/pkg/vendors/dnsla-sdk/client.go b/internal/pkg/vendors/dnsla-sdk/client.go index 60430fa1..72b0ed3d 100644 --- a/internal/pkg/vendors/dnsla-sdk/client.go +++ b/internal/pkg/vendors/dnsla-sdk/client.go @@ -58,9 +58,9 @@ func (c *Client) sendRequest(method string, path string, params interface{}) (*r resp, err := req.Send() if err != nil { - return nil, fmt.Errorf("dnsla api error: failed to send request: %w", err) + return resp, fmt.Errorf("dnsla api error: failed to send request: %w", err) } else if resp.IsError() { - return nil, fmt.Errorf("dnsla api error: unexpected status code: %d, %s", resp.StatusCode(), resp.Body()) + return resp, fmt.Errorf("dnsla api error: unexpected status code: %d, %s", resp.StatusCode(), resp.Body()) } return resp, nil @@ -69,6 +69,9 @@ func (c *Client) sendRequest(method string, path string, params interface{}) (*r 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 } diff --git a/internal/pkg/vendors/dnsla-sdk/models.go b/internal/pkg/vendors/dnsla-sdk/models.go index 85fe7978..701c7a83 100644 --- a/internal/pkg/vendors/dnsla-sdk/models.go +++ b/internal/pkg/vendors/dnsla-sdk/models.go @@ -1,21 +1,27 @@ package dnslasdk type BaseResponse interface { - GetCode() int + GetCode() int32 GetMessage() string } type baseResponse struct { - Code int `json:"code"` - Message string `json:"message"` + Code *int32 `json:"code,omitempty"` + Message *string `json:"message,omitempty"` } -func (r *baseResponse) GetCode() int { - return r.Code +func (r *baseResponse) GetCode() int32 { + if r.Code != nil { + return *r.Code + } + return 0 } func (r *baseResponse) GetMessage() string { - return r.Message + if r.Message != nil { + return *r.Message + } + return "" } type DomainInfo struct { diff --git a/internal/pkg/vendors/gname-sdk/api.go b/internal/pkg/vendors/gname-sdk/api.go index d01574c7..5a4c681f 100644 --- a/internal/pkg/vendors/gname-sdk/api.go +++ b/internal/pkg/vendors/gname-sdk/api.go @@ -1,37 +1,25 @@ package gnamesdk func (c *Client) AddDomainResolution(req *AddDomainResolutionRequest) (*AddDomainResolutionResponse, error) { - result := AddDomainResolutionResponse{} - err := c.sendRequestWithResult("/api/resolution/add", req, &result) - if err != nil { - return nil, err - } - return &result, nil + 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) - if err != nil { - return nil, err - } - return &resp, nil + 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) - if err != nil { - return nil, err - } - return &resp, nil + 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) - if err != nil { - return nil, err - } - return &resp, nil + resp := &ListDomainResolutionResponse{} + err := c.sendRequestWithResult("/api/resolution/list", req, resp) + return resp, err } diff --git a/internal/pkg/vendors/gname-sdk/client.go b/internal/pkg/vendors/gname-sdk/client.go index 8e2a2ba9..0a2238f2 100644 --- a/internal/pkg/vendors/gname-sdk/client.go +++ b/internal/pkg/vendors/gname-sdk/client.go @@ -80,9 +80,9 @@ func (c *Client) sendRequest(path string, params interface{}) (*resty.Response, SetFormData(data) resp, err := req.Post(url) if err != nil { - return nil, fmt.Errorf("gname api error: failed to send request: %w", err) + return resp, fmt.Errorf("gname api error: failed to send request: %w", err) } else if resp.IsError() { - return nil, fmt.Errorf("gname api error: unexpected status code: %d, %s", resp.StatusCode(), resp.Body()) + return resp, fmt.Errorf("gname api error: unexpected status code: %d, %s", resp.StatusCode(), resp.Body()) } return resp, nil diff --git a/internal/pkg/vendors/gname-sdk/models.go b/internal/pkg/vendors/gname-sdk/models.go index 997fb2c4..58283c50 100644 --- a/internal/pkg/vendors/gname-sdk/models.go +++ b/internal/pkg/vendors/gname-sdk/models.go @@ -1,16 +1,18 @@ package gnamesdk +import "encoding/json" + type BaseResponse interface { - GetCode() int + GetCode() int32 GetMessage() string } type baseResponse struct { - Code int `json:"code"` + Code int32 `json:"code"` Message string `json:"msg"` } -func (r *baseResponse) GetCode() int { +func (r *baseResponse) GetCode() int32 { return r.Code } @@ -23,23 +25,23 @@ type AddDomainResolutionRequest struct { RecordType string `json:"lx"` RecordName string `json:"zj"` RecordValue string `json:"jlz"` - MX int `json:"mx"` - TTL int `json:"ttl"` + MX int32 `json:"mx"` + TTL int32 `json:"ttl"` } type AddDomainResolutionResponse struct { baseResponse - Data string `json:"data"` + Data json.Number `json:"data"` } type ModifyDomainResolutionRequest struct { - ID string `json:"jxid"` + ID int64 `json:"jxid"` ZoneName string `json:"ym"` RecordType string `json:"lx"` RecordName string `json:"zj"` RecordValue string `json:"jlz"` - MX int `json:"mx"` - TTL int `json:"ttl"` + MX int32 `json:"mx"` + TTL int32 `json:"ttl"` } type ModifyDomainResolutionResponse struct { @@ -48,7 +50,7 @@ type ModifyDomainResolutionResponse struct { type DeleteDomainResolutionRequest struct { ZoneName string `json:"ym"` - RecordID string `json:"jxid"` + RecordID int64 `json:"jxid"` } type DeleteDomainResolutionResponse struct { @@ -57,23 +59,23 @@ type DeleteDomainResolutionResponse struct { type ListDomainResolutionRequest struct { ZoneName string `json:"ym"` - Page *int `json:"page,omitempty"` - PageSize *int `json:"limit,omitempty"` + Page *int32 `json:"page,omitempty"` + PageSize *int32 `json:"limit,omitempty"` } type ListDomainResolutionResponse struct { baseResponse - Count int `json:"count"` + Count int32 `json:"count"` Data []*ResolutionRecord `json:"data"` - Page int `json:"page"` - PageSize int `json:"pagesize"` + Page int32 `json:"page"` + PageSize int32 `json:"pagesize"` } type ResolutionRecord struct { - ID string `json:"id"` - ZoneName string `json:"ym"` - RecordType string `json:"lx"` - RecordName string `json:"zjt"` - RecordValue string `json:"jxz"` - MX int `json:"mx"` + 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"` } diff --git a/internal/pkg/vendors/safeline-sdk/api.go b/internal/pkg/vendors/safeline-sdk/api.go index 17af6c83..48ce1def 100644 --- a/internal/pkg/vendors/safeline-sdk/api.go +++ b/internal/pkg/vendors/safeline-sdk/api.go @@ -1,10 +1,7 @@ package safelinesdk func (c *Client) UpdateCertificate(req *UpdateCertificateRequest) (*UpdateCertificateResponse, error) { - resp := UpdateCertificateResponse{} - err := c.sendRequestWithResult("/api/open/cert", req, &resp) - if err != nil { - return nil, err - } - return &resp, nil + resp := &UpdateCertificateResponse{} + err := c.sendRequestWithResult("/api/open/cert", req, resp) + return resp, err } diff --git a/internal/pkg/vendors/safeline-sdk/client.go b/internal/pkg/vendors/safeline-sdk/client.go index 0d47c028..ade8acfa 100644 --- a/internal/pkg/vendors/safeline-sdk/client.go +++ b/internal/pkg/vendors/safeline-sdk/client.go @@ -45,9 +45,9 @@ func (c *Client) sendRequest(path string, params interface{}) (*resty.Response, SetBody(params) resp, err := req.Post(url) if err != nil { - return nil, fmt.Errorf("safeline api error: failed to send request: %w", err) + return resp, fmt.Errorf("safeline api error: failed to send request: %w", err) } else if resp.IsError() { - return nil, fmt.Errorf("safeline api error: unexpected status code: %d, %s", resp.StatusCode(), resp.Body()) + return resp, fmt.Errorf("safeline api error: unexpected status code: %d, %s", resp.StatusCode(), resp.Body()) } return resp, nil @@ -56,6 +56,9 @@ func (c *Client) sendRequest(path string, params interface{}) (*resty.Response, func (c *Client) sendRequestWithResult(path string, params interface{}, result BaseResponse) error { resp, err := c.sendRequest(path, params) if err != nil { + if resp != nil { + json.Unmarshal(resp.Body(), &result) + } return err } diff --git a/internal/pkg/vendors/upyun-sdk/console/api.go b/internal/pkg/vendors/upyun-sdk/console/api.go index afcb0b5b..28ccd734 100644 --- a/internal/pkg/vendors/upyun-sdk/console/api.go +++ b/internal/pkg/vendors/upyun-sdk/console/api.go @@ -33,12 +33,9 @@ func (c *Client) UploadHttpsCertificate(req *UploadHttpsCertificateRequest) (*Up } } - resp := UploadHttpsCertificateResponse{} - err := c.sendRequestWithResult(http.MethodPost, "/api/https/certificate/", req, &resp) - if err != nil { - return nil, err - } - return &resp, nil + resp := &UploadHttpsCertificateResponse{} + err := c.sendRequestWithResult(http.MethodPost, "/api/https/certificate/", req, resp) + return resp, err } func (c *Client) GetHttpsCertificateManager(certificateId string) (*GetHttpsCertificateManagerResponse, error) { @@ -48,13 +45,10 @@ func (c *Client) GetHttpsCertificateManager(certificateId string) (*GetHttpsCert } } - req := GetHttpsCertificateManagerRequest{CertificateId: certificateId} - resp := GetHttpsCertificateManagerResponse{} - err := c.sendRequestWithResult(http.MethodGet, "/api/https/certificate/manager/", &req, &resp) - if err != nil { - return nil, err - } - return &resp, nil + req := &GetHttpsCertificateManagerRequest{CertificateId: certificateId} + resp := &GetHttpsCertificateManagerResponse{} + err := c.sendRequestWithResult(http.MethodGet, "/api/https/certificate/manager/", req, resp) + return resp, err } func (c *Client) UpdateHttpsCertificateManager(req *UpdateHttpsCertificateManagerRequest) (*UpdateHttpsCertificateManagerResponse, error) { @@ -64,12 +58,9 @@ func (c *Client) UpdateHttpsCertificateManager(req *UpdateHttpsCertificateManage } } - resp := UpdateHttpsCertificateManagerResponse{} - err := c.sendRequestWithResult(http.MethodPost, "/api/https/certificate/manager", req, &resp) - if err != nil { - return nil, err - } - return &resp, nil + resp := &UpdateHttpsCertificateManagerResponse{} + err := c.sendRequestWithResult(http.MethodPost, "/api/https/certificate/manager", req, resp) + return resp, err } func (c *Client) GetHttpsServiceManager(domain string) (*GetHttpsServiceManagerResponse, error) { @@ -79,13 +70,10 @@ func (c *Client) GetHttpsServiceManager(domain string) (*GetHttpsServiceManagerR } } - req := GetHttpsServiceManagerRequest{Domain: domain} - resp := GetHttpsServiceManagerResponse{} - err := c.sendRequestWithResult(http.MethodGet, "/api/https/services/manager", &req, &resp) - if err != nil { - return nil, err - } - return &resp, nil + req := &GetHttpsServiceManagerRequest{Domain: domain} + resp := &GetHttpsServiceManagerResponse{} + err := c.sendRequestWithResult(http.MethodGet, "/api/https/services/manager", req, resp) + return resp, err } func (c *Client) MigrateHttpsDomain(req *MigrateHttpsDomainRequest) (*MigrateHttpsDomainResponse, error) { @@ -95,10 +83,7 @@ func (c *Client) MigrateHttpsDomain(req *MigrateHttpsDomainRequest) (*MigrateHtt } } - resp := MigrateHttpsDomainResponse{} - err := c.sendRequestWithResult(http.MethodPost, "/api/https/migrate/domain", req, &resp) - if err != nil { - return nil, err - } - return &resp, nil + resp := &MigrateHttpsDomainResponse{} + err := c.sendRequestWithResult(http.MethodPost, "/api/https/migrate/domain", req, resp) + return resp, err } diff --git a/internal/pkg/vendors/upyun-sdk/console/client.go b/internal/pkg/vendors/upyun-sdk/console/client.go index 74758b82..7b968f53 100644 --- a/internal/pkg/vendors/upyun-sdk/console/client.go +++ b/internal/pkg/vendors/upyun-sdk/console/client.go @@ -60,12 +60,11 @@ func (c *Client) sendRequest(method string, path string, params interface{}) (*r SetBody(params) } - req = req.SetDebug(true) resp, err := req.Send() if err != nil { - return nil, fmt.Errorf("upyun api error: failed to send request: %w", err) + return resp, fmt.Errorf("upyun api error: failed to send request: %w", err) } else if resp.IsError() { - return nil, fmt.Errorf("upyun api error: unexpected status code: %d, %s", resp.StatusCode(), resp.Body()) + return resp, fmt.Errorf("upyun api error: unexpected status code: %d, %s", resp.StatusCode(), resp.Body()) } return resp, nil @@ -74,6 +73,9 @@ func (c *Client) sendRequest(method string, path string, params interface{}) (*r func (c *Client) sendRequestWithResult(method string, path string, params interface{}, result interface{}) error { resp, err := c.sendRequest(method, path, params) if err != nil { + if resp != nil { + json.Unmarshal(resp.Body(), &result) + } return err } diff --git a/internal/pkg/vendors/upyun-sdk/console/models.go b/internal/pkg/vendors/upyun-sdk/console/models.go index 982993fe..12f2ab34 100644 --- a/internal/pkg/vendors/upyun-sdk/console/models.go +++ b/internal/pkg/vendors/upyun-sdk/console/models.go @@ -17,7 +17,7 @@ type baseResponseData struct { ErrorMessage string `json:"message"` } -func (r *baseResponseData) GetErrorCode() int { +func (r *baseResponseData) GetErrorCode() int32 { if r.ErrorCode.String() == "" { return 0 } @@ -27,7 +27,7 @@ func (r *baseResponseData) GetErrorCode() int { return -1 } - return int(errcode) + return int32(errcode) } func (r *baseResponseData) GetErrorMessage() string { @@ -41,10 +41,10 @@ type signinRequest struct { type signinResponse struct { baseResponse - Data struct { + Data *struct { baseResponseData Result bool `json:"result"` - } `json:"data"` + } `json:"data,omitempty"` } type UploadHttpsCertificateRequest struct { @@ -56,13 +56,13 @@ type UploadHttpsCertificateResponse struct { baseResponse Data *struct { baseResponseData - Status int `json:"status"` + Status int32 `json:"status"` Result struct { CertificateId string `json:"certificate_id"` CommonName string `json:"commonName"` Serial string `json:"serial"` } `json:"result"` - } `json:"data"` + } `json:"data,omitempty"` } type GetHttpsCertificateManagerRequest struct { @@ -76,7 +76,7 @@ type GetHttpsCertificateManagerResponse struct { AuthenticateNum int32 `json:"authenticate_num"` AuthenticateDomains []string `json:"authenticate_domain"` Domains []HttpsCertificateManagerDomain `json:"domains"` - } `json:"data"` + } `json:"data,omitempty"` } type HttpsCertificateManagerDomain struct { @@ -98,7 +98,7 @@ type UpdateHttpsCertificateManagerResponse struct { Data *struct { baseResponseData Status bool `json:"status"` - } `json:"data"` + } `json:"data,omitempty"` } type GetHttpsServiceManagerRequest struct { @@ -109,9 +109,9 @@ type GetHttpsServiceManagerResponse struct { baseResponse Data *struct { baseResponseData - Status int `json:"status"` + Status int32 `json:"status"` Domains []HttpsServiceManagerDomain `json:"result"` - } `json:"data"` + } `json:"data,omitempty"` } type HttpsServiceManagerDomain struct { @@ -137,5 +137,5 @@ type MigrateHttpsDomainResponse struct { Data *struct { baseResponseData Status bool `json:"status"` - } `json:"data"` + } `json:"data,omitempty"` } diff --git a/internal/repository/access.go b/internal/repository/access.go index 0bfeaea9..d25a6366 100644 --- a/internal/repository/access.go +++ b/internal/repository/access.go @@ -39,6 +39,11 @@ func (r *AccessRepository) castRecordToModel(record *core.Record) (*domain.Acces return nil, fmt.Errorf("record is nil") } + config := make(map[string]any) + if err := record.UnmarshalJSONField("config", &config); err != nil { + return nil, err + } + access := &domain.Access{ Meta: domain.Meta{ Id: record.Id, @@ -47,7 +52,7 @@ func (r *AccessRepository) castRecordToModel(record *core.Record) (*domain.Acces }, Name: record.GetString("name"), Provider: record.GetString("provider"), - Config: record.GetString("config"), + Config: config, } return access, nil } diff --git a/internal/workflow/node-processor/apply_node.go b/internal/workflow/node-processor/apply_node.go index a7d6a101..a1ca977d 100644 --- a/internal/workflow/node-processor/apply_node.go +++ b/internal/workflow/node-processor/apply_node.go @@ -45,7 +45,7 @@ func (n *applyNode) Process(ctx context.Context) error { n.logger.Info(fmt.Sprintf("skip this application, because %s", skipReason)) return nil } else if skipReason != "" { - n.logger.Info(fmt.Sprintf("continue to apply, because %s", skipReason)) + n.logger.Info(fmt.Sprintf("re-apply, because %s", skipReason)) } // 初始化申请器 diff --git a/internal/workflow/node-processor/deploy_node.go b/internal/workflow/node-processor/deploy_node.go index 42bc9ca6..edb3c53d 100644 --- a/internal/workflow/node-processor/deploy_node.go +++ b/internal/workflow/node-processor/deploy_node.go @@ -58,7 +58,7 @@ func (n *deployNode) Process(ctx context.Context) error { n.logger.Info(fmt.Sprintf("skip this deployment, because %s", skipReason)) return nil } else if skipReason != "" { - n.logger.Info(fmt.Sprintf("continue to deploy, because %s", skipReason)) + n.logger.Info(fmt.Sprintf("re-deploy, because %s", skipReason)) } } diff --git a/internal/workflow/node-processor/upload_node.go b/internal/workflow/node-processor/upload_node.go index 6c46e90f..891f2978 100644 --- a/internal/workflow/node-processor/upload_node.go +++ b/internal/workflow/node-processor/upload_node.go @@ -43,7 +43,7 @@ func (n *uploadNode) Process(ctx context.Context) error { n.logger.Info(fmt.Sprintf("skip this upload, because %s", skipReason)) return nil } else if skipReason != "" { - n.logger.Info(fmt.Sprintf("continue to upload, because %s", skipReason)) + n.logger.Info(fmt.Sprintf("re-upload, because %s", skipReason)) } // 生成证书实体 diff --git a/migrations/1742644800_upgrade.go b/migrations/1742644800_upgrade.go new file mode 100644 index 00000000..b28634a1 --- /dev/null +++ b/migrations/1742644800_upgrade.go @@ -0,0 +1,191 @@ +package migrations + +import ( + "github.com/pocketbase/pocketbase/core" + m "github.com/pocketbase/pocketbase/migrations" +) + +func init() { + m.Register(func(app core.App) error { + // update collection `workflow_run` + { + collection, err := app.FindCollectionByNameOrId("qjp8lygssgwyqyz") + if err != nil { + return err + } + + // update field + if err := collection.Fields.AddMarshaledJSONAt(7, []byte(`{ + "autogeneratePattern": "", + "hidden": false, + "id": "hvebkuxw", + "max": 20000, + "min": 0, + "name": "error", + "pattern": "", + "presentable": false, + "primaryKey": false, + "required": false, + "system": false, + "type": "text" + }`)); err != nil { + return err + } + + if err := app.Save(collection); err != nil { + return err + } + } + + // update collection `workflow_output` + { + collection, err := app.FindCollectionByNameOrId("bqnxb95f2cooowp") + if err != nil { + return err + } + + // update field + if err := collection.Fields.AddMarshaledJSONAt(5, []byte(`{ + "hidden": false, + "id": "he4cceqb", + "maxSize": 5000000, + "name": "outputs", + "presentable": false, + "required": false, + "system": false, + "type": "json" + }`)); err != nil { + return err + } + + if err := app.Save(collection); err != nil { + return err + } + } + + // update collection `workflow_logs` + { + collection, err := app.FindCollectionByNameOrId("pbc_1682296116") + if err != nil { + return err + } + + // update field + if err := collection.Fields.AddMarshaledJSONAt(7, []byte(`{ + "autogeneratePattern": "", + "hidden": false, + "id": "text3065852031", + "max": 20000, + "min": 0, + "name": "message", + "pattern": "", + "presentable": false, + "primaryKey": false, + "required": false, + "system": false, + "type": "text" + }`)); err != nil { + return err + } + + // update field + if err := collection.Fields.AddMarshaledJSONAt(8, []byte(`{ + "hidden": false, + "id": "json2918445923", + "maxSize": 5000000, + "name": "data", + "presentable": false, + "required": false, + "system": false, + "type": "json" + }`)); err != nil { + return err + } + + if err := app.Save(collection); err != nil { + return err + } + } + + // update collection `access` + { + collection, err := app.FindCollectionByNameOrId("4yzbv8urny5ja1e") + if err != nil { + return err + } + + // update field + if err := collection.Fields.AddMarshaledJSONAt(2, []byte(`{ + "hidden": false, + "id": "hwy7m03o", + "maxSelect": 1, + "name": "provider", + "presentable": false, + "required": false, + "system": false, + "type": "select", + "values": [ + "1panel", + "acmehttpreq", + "akamai", + "aliyun", + "aws", + "azure", + "baiducloud", + "baishan", + "baotapanel", + "byteplus", + "cachefly", + "cdnfly", + "cloudflare", + "cloudns", + "cmcccloud", + "ctcccloud", + "cucccloud", + "desec", + "dnsla", + "dogecloud", + "dynv6", + "edgio", + "fastly", + "gname", + "gcore", + "godaddy", + "goedge", + "huaweicloud", + "jdcloud", + "k8s", + "local", + "namecheap", + "namedotcom", + "namesilo", + "ns1", + "porkbun", + "powerdns", + "qiniu", + "qingcloud", + "rainyun", + "safeline", + "ssh", + "tencentcloud", + "ucloud", + "upyun", + "vercel", + "volcengine", + "webhook", + "westcn" + ] + }`)); err != nil { + return err + } + + if err := app.Save(collection); err != nil { + return err + } + } + + return nil + }, func(app core.App) error { + return nil + }) +} diff --git a/ui/public/imgs/providers/desec.svg b/ui/public/imgs/providers/desec.svg new file mode 100644 index 00000000..b20baa59 --- /dev/null +++ b/ui/public/imgs/providers/desec.svg @@ -0,0 +1,87 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/ui/public/imgs/providers/porkbun.svg b/ui/public/imgs/providers/porkbun.svg new file mode 100644 index 00000000..096d03ac --- /dev/null +++ b/ui/public/imgs/providers/porkbun.svg @@ -0,0 +1 @@ + diff --git a/ui/public/imgs/providers/vercel.svg b/ui/public/imgs/providers/vercel.svg new file mode 100644 index 00000000..65731f98 --- /dev/null +++ b/ui/public/imgs/providers/vercel.svg @@ -0,0 +1 @@ + diff --git a/ui/src/components/access/AccessForm.tsx b/ui/src/components/access/AccessForm.tsx index 63a66875..487d449a 100644 --- a/ui/src/components/access/AccessForm.tsx +++ b/ui/src/components/access/AccessForm.tsx @@ -23,6 +23,7 @@ import AccessFormCdnflyConfig from "./AccessFormCdnflyConfig"; import AccessFormCloudflareConfig from "./AccessFormCloudflareConfig"; import AccessFormClouDNSConfig from "./AccessFormClouDNSConfig"; import AccessFormCMCCCloudConfig from "./AccessFormCMCCCloudConfig"; +import AccessFormDeSECConfig from "./AccessFormDeSECConfig"; import AccessFormDNSLAConfig from "./AccessFormDNSLAConfig"; import AccessFormDogeCloudConfig from "./AccessFormDogeCloudConfig"; import AccessFormDynv6Config from "./AccessFormDynv6Config"; @@ -38,6 +39,7 @@ import AccessFormNamecheapConfig from "./AccessFormNamecheapConfig"; import AccessFormNameDotComConfig from "./AccessFormNameDotComConfig"; import AccessFormNameSiloConfig from "./AccessFormNameSiloConfig"; import AccessFormNS1Config from "./AccessFormNS1Config"; +import AccessFormPorkbunConfig from "./AccessFormPorkbunConfig"; import AccessFormPowerDNSConfig from "./AccessFormPowerDNSConfig"; import AccessFormQiniuConfig from "./AccessFormQiniuConfig"; import AccessFormRainYunConfig from "./AccessFormRainYunConfig"; @@ -46,6 +48,7 @@ import AccessFormSSHConfig from "./AccessFormSSHConfig"; import AccessFormTencentCloudConfig from "./AccessFormTencentCloudConfig"; import AccessFormUCloudConfig from "./AccessFormUCloudConfig"; import AccessFormUpyunConfig from "./AccessFormUpyunConfig"; +import AccessFormVercelConfig from "./AccessFormVercelConfig"; import AccessFormVolcEngineConfig from "./AccessFormVolcEngineConfig"; import AccessFormWebhookConfig from "./AccessFormWebhookConfig"; import AccessFormWestcnConfig from "./AccessFormWestcnConfig"; @@ -130,6 +133,8 @@ const AccessForm = forwardRef(({ className, return ; case ACCESS_PROVIDERS.CMCCCLOUD: return ; + case ACCESS_PROVIDERS.DESEC: + return ; case ACCESS_PROVIDERS.DNSLA: return ; case ACCESS_PROVIDERS.DOGECLOUD: @@ -160,6 +165,8 @@ const AccessForm = forwardRef(({ className, return ; case ACCESS_PROVIDERS.NS1: return ; + case ACCESS_PROVIDERS.PORKBUN: + return ; case ACCESS_PROVIDERS.POWERDNS: return ; case ACCESS_PROVIDERS.QINIU: @@ -176,6 +183,8 @@ const AccessForm = forwardRef(({ className, return ; case ACCESS_PROVIDERS.UPYUN: return ; + case ACCESS_PROVIDERS.VERCEL: + return ; case ACCESS_PROVIDERS.VOLCENGINE: return ; case ACCESS_PROVIDERS.WEBHOOK: diff --git a/ui/src/components/access/AccessFormDeSECConfig.tsx b/ui/src/components/access/AccessFormDeSECConfig.tsx new file mode 100644 index 00000000..4ba65a69 --- /dev/null +++ b/ui/src/components/access/AccessFormDeSECConfig.tsx @@ -0,0 +1,61 @@ +import { useTranslation } from "react-i18next"; +import { Form, type FormInstance, Input } from "antd"; +import { createSchemaFieldRule } from "antd-zod"; +import { z } from "zod"; + +import { type AccessConfigForDeSEC } from "@/domain/access"; + +type AccessFormDeSECConfigFieldValues = Nullish; + +export type AccessFormDeSECConfigProps = { + form: FormInstance; + formName: string; + disabled?: boolean; + initialValues?: AccessFormDeSECConfigFieldValues; + onValuesChange?: (values: AccessFormDeSECConfigFieldValues) => void; +}; + +const initFormModel = (): AccessFormDeSECConfigFieldValues => { + return { + token: "", + }; +}; + +const AccessFormDeSECConfig = ({ form: formInst, formName, disabled, initialValues, onValuesChange }: AccessFormDeSECConfigProps) => { + const { t } = useTranslation(); + + const formSchema = z.object({ + token: z + .string() + .min(1, t("access.form.desec_token.placeholder")) + .max(256, t("common.errmsg.string_max", { max: 256 })) + .trim(), + }); + const formRule = createSchemaFieldRule(formSchema); + + const handleFormChange = (_: unknown, values: z.infer) => { + onValuesChange?.(values); + }; + + return ( +
+ } + > + + +
+ ); +}; + +export default AccessFormDeSECConfig; diff --git a/ui/src/components/access/AccessFormPorkbunConfig.tsx b/ui/src/components/access/AccessFormPorkbunConfig.tsx new file mode 100644 index 00000000..20cbc38a --- /dev/null +++ b/ui/src/components/access/AccessFormPorkbunConfig.tsx @@ -0,0 +1,76 @@ +import { useTranslation } from "react-i18next"; +import { Form, type FormInstance, Input } from "antd"; +import { createSchemaFieldRule } from "antd-zod"; +import { z } from "zod"; + +import { type AccessConfigForPorkbun } from "@/domain/access"; + +type AccessFormPorkbunConfigFieldValues = Nullish; + +export type AccessFormPorkbunConfigProps = { + form: FormInstance; + formName: string; + disabled?: boolean; + initialValues?: AccessFormPorkbunConfigFieldValues; + onValuesChange?: (values: AccessFormPorkbunConfigFieldValues) => void; +}; + +const initFormModel = (): AccessFormPorkbunConfigFieldValues => { + return { + apiKey: "", + secretApiKey: "", + }; +}; + +const AccessFormPorkbunConfig = ({ form: formInst, formName, disabled, initialValues, onValuesChange }: AccessFormPorkbunConfigProps) => { + const { t } = useTranslation(); + + const formSchema = z.object({ + apiKey: z + .string() + .min(1, t("access.form.porkbun_api_key.placeholder")) + .max(256, t("common.errmsg.string_max", { max: 256 })) + .trim(), + secretApiKey: z + .string() + .min(1, t("access.form.porkbun_secret_api_key.placeholder")) + .max(256, t("common.errmsg.string_max", { max: 256 })) + .trim(), + }); + const formRule = createSchemaFieldRule(formSchema); + + const handleFormChange = (_: unknown, values: z.infer) => { + onValuesChange?.(values); + }; + + return ( +
+ } + > + + + + } + > + + +
+ ); +}; + +export default AccessFormPorkbunConfig; diff --git a/ui/src/components/access/AccessFormUCloudConfig.tsx b/ui/src/components/access/AccessFormUCloudConfig.tsx index f230e7c2..495d21b9 100644 --- a/ui/src/components/access/AccessFormUCloudConfig.tsx +++ b/ui/src/components/access/AccessFormUCloudConfig.tsx @@ -28,9 +28,9 @@ const AccessFormUCloudConfig = ({ form: formInst, formName, disabled, initialVal const formSchema = z.object({ privateKey: z .string() - .trim() .min(1, t("access.form.ucloud_private_key.placeholder")) - .max(64, t("common.errmsg.string_max", { max: 64 })), + .max(64, t("common.errmsg.string_max", { max: 64 })) + .trim(), publicKey: z .string() .min(1, t("access.form.ucloud_public_key.placeholder")) diff --git a/ui/src/components/access/AccessFormVercelConfig.tsx b/ui/src/components/access/AccessFormVercelConfig.tsx new file mode 100644 index 00000000..b1ed7b6f --- /dev/null +++ b/ui/src/components/access/AccessFormVercelConfig.tsx @@ -0,0 +1,75 @@ +import { useTranslation } from "react-i18next"; +import { Form, type FormInstance, Input } from "antd"; +import { createSchemaFieldRule } from "antd-zod"; +import { z } from "zod"; + +import { type AccessConfigForVercel } from "@/domain/access"; + +type AccessFormVercelConfigFieldValues = Nullish; + +export type AccessFormVercelConfigProps = { + form: FormInstance; + formName: string; + disabled?: boolean; + initialValues?: AccessFormVercelConfigFieldValues; + onValuesChange?: (values: AccessFormVercelConfigFieldValues) => void; +}; + +const initFormModel = (): AccessFormVercelConfigFieldValues => { + return { + apiAccessToken: "", + }; +}; + +const AccessFormVercelConfig = ({ form: formInst, formName, disabled, initialValues, onValuesChange }: AccessFormVercelConfigProps) => { + const { t } = useTranslation(); + + const formSchema = z.object({ + apiAccessToken: z + .string() + .min(1, t("access.form.vercel_api_access_token.placeholder")) + .max(256, t("common.errmsg.string_max", { max: 256 })) + .trim(), + teamId: z + .string() + .max(256, t("common.errmsg.string_max", { max: 256 })) + .trim() + .nullish(), + }); + const formRule = createSchemaFieldRule(formSchema); + + const handleFormChange = (_: unknown, values: z.infer) => { + onValuesChange?.(values); + }; + + return ( +
+ } + > + + + + } + > + + +
+ ); +}; + +export default AccessFormVercelConfig; diff --git a/ui/src/components/access/AccessFormVolcEngineConfig.tsx b/ui/src/components/access/AccessFormVolcEngineConfig.tsx index 02a693b0..8d8d18de 100644 --- a/ui/src/components/access/AccessFormVolcEngineConfig.tsx +++ b/ui/src/components/access/AccessFormVolcEngineConfig.tsx @@ -28,9 +28,9 @@ const AccessFormVolcEngineConfig = ({ form: formInst, formName, disabled, initia const formSchema = z.object({ accessKeyId: z .string() - .trim() .min(1, t("access.form.volcengine_access_key_id.placeholder")) - .max(64, t("common.errmsg.string_max", { max: 64 })), + .max(64, t("common.errmsg.string_max", { max: 64 })) + .trim(), secretAccessKey: z .string() .min(1, t("access.form.volcengine_secret_access_key.placeholder")) diff --git a/ui/src/components/access/AccessFormWestcnConfig.tsx b/ui/src/components/access/AccessFormWestcnConfig.tsx index 0b0257ed..ab21260c 100644 --- a/ui/src/components/access/AccessFormWestcnConfig.tsx +++ b/ui/src/components/access/AccessFormWestcnConfig.tsx @@ -28,9 +28,9 @@ const AccessFormWestcnConfig = ({ form: formInst, formName, disabled, initialVal const formSchema = z.object({ username: z .string() - .trim() .min(1, t("access.form.westcn_username.placeholder")) - .max(64, t("common.errmsg.string_max", { max: 64 })), + .max(64, t("common.errmsg.string_max", { max: 64 })) + .trim(), apiPassword: z .string() .min(1, t("access.form.westcn_api_password.placeholder")) diff --git a/ui/src/components/access/AccessSelect.tsx b/ui/src/components/access/AccessSelect.tsx index 3ad60348..7077e78d 100644 --- a/ui/src/components/access/AccessSelect.tsx +++ b/ui/src/components/access/AccessSelect.tsx @@ -21,9 +21,9 @@ const AccessSelect = ({ filter, ...props }: AccessTypeSelectProps) => { const [options, setOptions] = useState>([]); useEffect(() => { - const items = filter != null ? accesses.filter(filter) : accesses; + const filteredItems = filter != null ? accesses.filter(filter) : accesses; setOptions( - items.map((item) => ({ + filteredItems.map((item) => ({ key: item.id, value: item.id, label: item.name, diff --git a/ui/src/components/provider/AccessProviderSelect.tsx b/ui/src/components/provider/AccessProviderSelect.tsx index 97cd35fd..0e0a992c 100644 --- a/ui/src/components/provider/AccessProviderSelect.tsx +++ b/ui/src/components/provider/AccessProviderSelect.tsx @@ -1,22 +1,32 @@ -import { memo } from "react"; +import { memo, useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import { Avatar, Select, type SelectProps, Space, Tag, Typography } from "antd"; -import { ACCESS_USAGES, accessProvidersMap } from "@/domain/provider"; +import { ACCESS_USAGES, type AccessProvider, accessProvidersMap } from "@/domain/provider"; export type AccessProviderSelectProps = Omit< SelectProps, "filterOption" | "filterSort" | "labelRender" | "options" | "optionFilterProp" | "optionLabelProp" | "optionRender" ->; +> & { + filter?: (record: AccessProvider) => boolean; +}; -const AccessProviderSelect = (props: AccessProviderSelectProps) => { +const AccessProviderSelect = ({ filter, ...props }: AccessProviderSelectProps) => { const { t } = useTranslation(); - const options = Array.from(accessProvidersMap.values()).map((item) => ({ - key: item.type, - value: item.type, - label: t(item.name), - })); + const [options, setOptions] = useState>([]); + useEffect(() => { + const allItems = Array.from(accessProvidersMap.values()); + const filteredItems = filter != null ? allItems.filter(filter) : allItems; + setOptions( + filteredItems.map((item) => ({ + key: item.type, + value: item.type, + label: t(item.name), + data: item, + })) + ); + }, [filter]); const renderOption = (key: string) => { const provider = accessProvidersMap.get(key); diff --git a/ui/src/components/provider/ApplyDNSProviderSelect.tsx b/ui/src/components/provider/ApplyDNSProviderSelect.tsx index c88cfebf..f7e3c259 100644 --- a/ui/src/components/provider/ApplyDNSProviderSelect.tsx +++ b/ui/src/components/provider/ApplyDNSProviderSelect.tsx @@ -1,22 +1,32 @@ -import { memo } from "react"; +import { memo, useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import { Avatar, Select, type SelectProps, Space, Typography } from "antd"; -import { applyDNSProvidersMap } from "@/domain/provider"; +import { type ApplyDNSProvider, applyDNSProvidersMap } from "@/domain/provider"; export type ApplyDNSProviderSelectProps = Omit< SelectProps, "filterOption" | "filterSort" | "labelRender" | "options" | "optionFilterProp" | "optionLabelProp" | "optionRender" ->; +> & { + filter?: (record: ApplyDNSProvider) => boolean; +}; -const ApplyDNSProviderSelect = (props: ApplyDNSProviderSelectProps) => { +const ApplyDNSProviderSelect = ({ filter, ...props }: ApplyDNSProviderSelectProps) => { const { t } = useTranslation(); - const options = Array.from(applyDNSProvidersMap.values()).map((item) => ({ - key: item.type, - value: item.type, - label: t(item.name), - })); + const [options, setOptions] = useState>([]); + useEffect(() => { + const allItems = Array.from(applyDNSProvidersMap.values()); + const filteredItems = filter != null ? allItems.filter(filter) : allItems; + setOptions( + filteredItems.map((item) => ({ + key: item.type, + value: item.type, + label: t(item.name), + data: item, + })) + ); + }, [filter]); const renderOption = (key: string) => { const provider = applyDNSProvidersMap.get(key); diff --git a/ui/src/components/provider/DeployProviderSelect.tsx b/ui/src/components/provider/DeployProviderSelect.tsx index cc2b13ea..5be10cb7 100644 --- a/ui/src/components/provider/DeployProviderSelect.tsx +++ b/ui/src/components/provider/DeployProviderSelect.tsx @@ -1,22 +1,32 @@ -import { memo } from "react"; +import { memo, useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import { Avatar, Select, type SelectProps, Space, Typography } from "antd"; -import { deployProvidersMap } from "@/domain/provider"; +import { type DeployProvider, deployProvidersMap } from "@/domain/provider"; export type DeployProviderSelectProps = Omit< SelectProps, "filterOption" | "filterSort" | "labelRender" | "options" | "optionFilterProp" | "optionLabelProp" | "optionRender" ->; +> & { + filter?: (record: DeployProvider) => boolean; +}; -const DeployProviderSelect = (props: DeployProviderSelectProps) => { +const DeployProviderSelect = ({ filter, ...props }: DeployProviderSelectProps) => { const { t } = useTranslation(); - const options = Array.from(deployProvidersMap.values()).map((item) => ({ - key: item.type, - value: item.type, - label: t(item.name), - })); + const [options, setOptions] = useState>([]); + useEffect(() => { + const allItems = Array.from(deployProvidersMap.values()); + const filteredItems = filter != null ? allItems.filter(filter) : allItems; + setOptions( + filteredItems.map((item) => ({ + key: item.type, + value: item.type, + label: t(item.name), + data: item, + })) + ); + }, [filter]); const renderOption = (key: string) => { const provider = deployProvidersMap.get(key); diff --git a/ui/src/components/workflow/WorkflowRunDetail.tsx b/ui/src/components/workflow/WorkflowRunDetail.tsx index 5d8c7f29..e104410a 100644 --- a/ui/src/components/workflow/WorkflowRunDetail.tsx +++ b/ui/src/components/workflow/WorkflowRunDetail.tsx @@ -37,6 +37,7 @@ import Show from "@/components/Show"; import { type CertificateModel } from "@/domain/certificate"; import type { WorkflowLogModel } from "@/domain/workflowLog"; import { WORKFLOW_RUN_STATUSES, type WorkflowRunModel } from "@/domain/workflowRun"; +import { useBrowserTheme } from "@/hooks"; import { listByWorkflowRunId as listCertificatesByWorkflowRunId } from "@/repository/certificate"; import { listByWorkflowRunId as listLogsByWorkflowRunId } from "@/repository/workflowLog"; import { mergeCls } from "@/utils/css"; @@ -67,6 +68,7 @@ const WorkflowRunLogs = ({ runId, runStatus }: { runId: string; runStatus: strin const { t } = useTranslation(); const { token: themeToken } = theme.useToken(); + const { theme: browserTheme } = useBrowserTheme(); type Log = Pick; type LogGroup = { id: string; name: string; records: Log[] }; @@ -212,7 +214,7 @@ const WorkflowRunLogs = ({ runId, runStatus }: { runId: string; runStatus: strin }} trigger={["click"]} > -