Merge branch 'main' of https://github.com/certimate-go/certimate into certimate-go-main

This commit is contained in:
wood chen 2025-06-25 19:12:51 +08:00
commit 456689d12b
255 changed files with 3033 additions and 1859 deletions

90
go.mod
View File

@ -6,18 +6,18 @@ toolchain go1.24.3
require (
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.0
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azcertificates v1.3.1
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.1
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azcertificates v1.4.0
github.com/Edgio/edgio-api v0.0.0-workspace
github.com/G-Core/gcorelabscdn-go v1.0.31
github.com/alibabacloud-go/alb-20200616/v2 v2.2.8
github.com/alibabacloud-go/alb-20200616/v2 v2.2.9
github.com/alibabacloud-go/apig-20240327/v3 v3.2.2
github.com/alibabacloud-go/cas-20200407/v3 v3.0.4
github.com/alibabacloud-go/cdn-20180510/v5 v5.2.2
github.com/alibabacloud-go/cloudapi-20160714/v5 v5.7.4
github.com/alibabacloud-go/darabonba-openapi/v2 v2.1.7
github.com/alibabacloud-go/ddoscoo-20200101/v4 v4.0.0
github.com/alibabacloud-go/esa-20240910/v2 v2.33.0
github.com/alibabacloud-go/esa-20240910/v2 v2.34.1
github.com/alibabacloud-go/fc-20230330/v4 v4.3.5
github.com/alibabacloud-go/fc-open-20210406/v2 v2.0.12
github.com/alibabacloud-go/ga-20191120/v3 v3.1.8
@ -26,19 +26,19 @@ require (
github.com/alibabacloud-go/slb-20140515/v4 v4.0.10
github.com/alibabacloud-go/tea v1.3.9
github.com/alibabacloud-go/vod-20170321/v4 v4.8.4
github.com/alibabacloud-go/waf-openapi-20211001/v5 v5.1.3
github.com/alibabacloud-go/waf-openapi-20211001/v5 v5.4.0
github.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible
github.com/aws/aws-sdk-go-v2/service/acm v1.32.0
github.com/aws/aws-sdk-go-v2/service/cloudfront v1.46.1
github.com/aws/aws-sdk-go-v2/service/iam v1.42.0
github.com/baidubce/bce-sdk-go v0.9.228
github.com/aws/aws-sdk-go-v2/service/acm v1.33.0
github.com/aws/aws-sdk-go-v2/service/cloudfront v1.46.3
github.com/aws/aws-sdk-go-v2/service/iam v1.42.2
github.com/baidubce/bce-sdk-go v0.9.231
github.com/blinkbean/dingtalk v1.1.3
github.com/byteplus-sdk/byteplus-sdk-golang v1.0.46
github.com/byteplus-sdk/byteplus-sdk-golang v1.0.50
github.com/go-acme/lego/v4 v4.23.1
github.com/go-lark/lark v1.16.0
github.com/go-resty/resty/v2 v2.16.5
github.com/go-viper/mapstructure/v2 v2.2.1
github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.150
github.com/go-viper/mapstructure/v2 v2.3.0
github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.155
github.com/jdcloud-api/jdcloud-sdk-go v1.64.0
github.com/libdns/dynv6 v1.0.0
github.com/libdns/libdns v0.2.3
@ -46,30 +46,30 @@ require (
github.com/pavlo-v-chernykh/keystore-go/v4 v4.5.0
github.com/pkg/sftp v1.13.9
github.com/pocketbase/dbx v1.11.0
github.com/pocketbase/pocketbase v0.28.2
github.com/pocketbase/pocketbase v0.28.4
github.com/povsister/scp v0.0.0-20250504051308-e467f71ea63c
github.com/qiniu/go-sdk/v7 v7.25.3
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cdn v1.0.1155
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/clb v1.0.1166
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1173
github.com/qiniu/go-sdk/v7 v7.25.4
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cdn v1.0.1193
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/clb v1.0.1188
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1193
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/gaap v1.0.1163
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/live v1.0.1150
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/live v1.0.1193
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/scf v1.0.1172
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssl v1.0.1169
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/teo v1.0.1166
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vod v1.0.1164
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/waf v1.0.1170
github.com/ucloud/ucloud-sdk-go v0.22.41
github.com/volcengine/ve-tos-golang-sdk/v2 v2.7.12
github.com/volcengine/volc-sdk-golang v1.0.208
github.com/volcengine/volcengine-go-sdk v1.1.8
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssl v1.0.1193
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/teo v1.0.1191
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vod v1.0.1183
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/waf v1.0.1182
github.com/ucloud/ucloud-sdk-go v0.22.44
github.com/volcengine/ve-tos-golang-sdk/v2 v2.7.17
github.com/volcengine/volc-sdk-golang v1.0.212
github.com/volcengine/volcengine-go-sdk v1.1.18
gitlab.ecloud.com/ecloud/ecloudsdkclouddns v1.0.1
gitlab.ecloud.com/ecloud/ecloudsdkcore v1.0.0
golang.org/x/crypto v0.38.0
golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6
k8s.io/api v0.33.1
k8s.io/apimachinery v0.33.1
k8s.io/client-go v0.33.1
golang.org/x/crypto v0.39.0
golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b
k8s.io/api v0.33.2
k8s.io/apimachinery v0.33.2
k8s.io/client-go v0.33.2
software.sslmate.com/src/go-pkcs12 v0.5.0
)
@ -78,7 +78,7 @@ require (
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dns/armdns v1.2.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/privatedns/armprivatedns v1.3.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resourcegraph/armresourcegraph v0.9.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.1.1 // indirect
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.2.0 // indirect
github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2 // indirect
github.com/alibabacloud-go/alibabacloud-gateway-fc-util v0.0.7 // indirect
github.com/alibabacloud-go/openplatform-20191219/v2 v2.0.1 // indirect
@ -154,19 +154,19 @@ require (
github.com/aliyun/alibaba-cloud-sdk-go v1.63.100 // indirect
github.com/aliyun/credentials-go v1.4.6 // indirect
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
github.com/aws/aws-sdk-go-v2 v1.36.3
github.com/aws/aws-sdk-go-v2 v1.36.5
github.com/aws/aws-sdk-go-v2/config v1.29.9
github.com/aws/aws-sdk-go-v2/credentials v1.17.62
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.30 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.36 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.36 // indirect
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.15 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.25.1 // indirect
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.29.1 // indirect
github.com/aws/aws-sdk-go-v2/service/sts v1.33.17 // indirect
github.com/aws/smithy-go v1.22.2 // indirect
github.com/aws/smithy-go v1.22.4 // indirect
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
github.com/clbanning/mxj/v2 v2.7.0 // indirect
github.com/cloudflare/cloudflare-go v0.115.0 // indirect
@ -195,28 +195,28 @@ require (
github.com/nrdcg/namesilo v0.2.1 // indirect
github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/spf13/cast v1.8.0 // indirect
github.com/spf13/cast v1.9.2 // indirect
github.com/spf13/cobra v1.9.1 // indirect
github.com/spf13/pflag v1.0.6 // indirect
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1128 // indirect
github.com/tjfoc/gmsm v1.4.1 // indirect
golang.org/x/image v0.27.0 // indirect
golang.org/x/mod v0.24.0 // indirect
golang.org/x/net v0.40.0 // indirect
golang.org/x/image v0.28.0 // indirect
golang.org/x/mod v0.25.0 // indirect
golang.org/x/net v0.41.0 // indirect
golang.org/x/oauth2 v0.30.0 // indirect
golang.org/x/sync v0.14.0
golang.org/x/sync v0.15.0
golang.org/x/sys v0.33.0 // indirect
golang.org/x/term v0.32.0 // indirect
golang.org/x/text v0.25.0 // indirect
golang.org/x/text v0.26.0 // indirect
golang.org/x/time v0.11.0
golang.org/x/tools v0.33.0 // indirect
golang.org/x/tools v0.34.0 // indirect
google.golang.org/protobuf v1.36.5 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
modernc.org/libc v1.65.7 // indirect
modernc.org/libc v1.65.10 // indirect
modernc.org/mathutil v1.7.1 // indirect
modernc.org/memory v1.11.0 // indirect
modernc.org/sqlite v1.37.1 // indirect
modernc.org/sqlite v1.38.0 // indirect
)
replace github.com/Edgio/edgio-api v0.0.0-workspace => ./pkg/sdk3rd/edgio/edgio-api@v0.0.0-workspace

204
go.sum
View File

@ -36,8 +36,8 @@ filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4
github.com/Azure/azure-sdk-for-go v68.0.0+incompatible h1:fcYLmCpyNYRnvJbPerq7U0hS+6+I79yEDJBqVNcqUzU=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0 h1:Gt0j3wceWMwPmiazCa8MzMA0MfhmPIz0Qp0FJ6qcM0U=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0/go.mod h1:Ot/6aikWnKWi4l9QB7qVSwa8iMphQNqkWALMoNT3rzM=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.0 h1:j8BorDEigD8UFOSZQiSqAMOOleyQOOQPnUAwV+Ls1gA=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.0/go.mod h1:JdM5psgjfBf5fo2uWOZhflPWyDBZ/O/CNAH9CtsuZE4=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.1 h1:B+blDbyVIG3WaikNxPnhPiJ1MThR03b3vKGtER95TP4=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.1/go.mod h1:JdM5psgjfBf5fo2uWOZhflPWyDBZ/O/CNAH9CtsuZE4=
github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2 h1:yz1bePFlP5Vws5+8ez6T3HWXPmwOK7Yvq8QxDBD3SKY=
github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2/go.mod h1:Pa9ZNPuoNu/GztvBSKk9J1cDJW6vk/n0zLtV4mgd8N8=
github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1 h1:FPKJS1T+clwv+OLGt13a8UjqeRuh0O4SJ3lUriThc+4=
@ -52,10 +52,10 @@ github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resourcegraph/armresourceg
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resourcegraph/armresourcegraph v0.9.0/go.mod h1:wVEOJfGTj0oPAUGA1JuRAvz/lxXQsWW16axmHPP47Bk=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.2.0 h1:Dd+RhdJn0OTtVGaeDLZpcumkIVCtA/3/Fo42+eoYvVM=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.2.0/go.mod h1:5kakwfW5CjC9KK+Q4wjXAg+ShuIm2mBMua0ZFj2C8PE=
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azcertificates v1.3.1 h1:HUJQzFYTv7t3V1dxPms52eEgl0l9xCNqutDrY45Lvmw=
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azcertificates v1.3.1/go.mod h1:ig/8nSkzmfxm5QGeIy5JYIEj8JEFy5JxvY3OB1YNRC4=
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.1.1 h1:bFWuoEKg+gImo7pvkiQEFAc8ocibADgXeiLAxWhWmkI=
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.1.1/go.mod h1:Vih/3yc6yac2JzU4hzpaDupBJP0Flaia9rXXrU8xyww=
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azcertificates v1.4.0 h1:mtvR5ZXH5Ew6PSONd5lO5OXovWP1E3oAlgC8fpxor2Q=
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azcertificates v1.4.0/go.mod h1:u560+RFVfG0CBPzkXlDW43slESbBAQjgDGi3r6z+wk8=
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.2.0 h1:nCYfgcSyHZXJI8J0IWE5MsCGlb2xp9fJiXyxWgmOFg4=
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.2.0/go.mod h1:ucUjca2JtSZboY8IoUqyQyuuXvwbMBVwFOm0vdQPNhA=
github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1 h1:WJTmL004Abzc5wDB5VtZG2PJk5ndYDgVacGqfirKxjM=
github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1/go.mod h1:tCcJZ0uHAmvjsVYzEFivsRTN00oz5BEsRgQHu5JZ9WE=
github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2 h1:oygO0locgZJe7PpYPXT5A29ZkwJaPqcva7BVeemZOZs=
@ -86,8 +86,8 @@ github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRF
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
github.com/alex-ant/gomath v0.0.0-20160516115720-89013a210a82/go.mod h1:nLnM0KdK1CmygvjpDUO6m1TjSsiQtL61juhNsvV/JVI=
github.com/alibabacloud-go/alb-20200616/v2 v2.2.8 h1:/6+1AqIiENG3u6RmEYWEQ/YZv3YgdFZkE6Xd9RZM6n0=
github.com/alibabacloud-go/alb-20200616/v2 v2.2.8/go.mod h1:jU/K+GVb5b0vjiDpkf6E0dH77tsi1jTLGWm4ouCiRxk=
github.com/alibabacloud-go/alb-20200616/v2 v2.2.9 h1:0pEYgxbkQiXOLKhkCBHPnTEl4X1Ahkoo45qMcyElm+U=
github.com/alibabacloud-go/alb-20200616/v2 v2.2.9/go.mod h1:7revp3b2AHMZq+8GhU+WMFCwqbHC2KSvEDPeAzmTdY0=
github.com/alibabacloud-go/alibabacloud-gateway-fc-util v0.0.7 h1:RDatRb9RG39HjkevgzTeiVoDDaamoB+12GHNairp3Ag=
github.com/alibabacloud-go/alibabacloud-gateway-fc-util v0.0.7/go.mod h1:H0RPHXHP/ICfEQrKzQcCqXI15jcV4zaDPCOAmh3U9O8=
github.com/alibabacloud-go/alibabacloud-gateway-pop v0.0.6 h1:eIf+iGJxdU4U9ypaUfbtOWCsZSbTb8AUHvyPrxu6mAA=
@ -132,8 +132,8 @@ github.com/alibabacloud-go/debug v1.0.1/go.mod h1:8gfgZCCAC3+SCzjWtY053FrOcd4/ql
github.com/alibabacloud-go/endpoint-util v1.1.0/go.mod h1:O5FuCALmCKs2Ff7JFJMudHs0I5EBgecXXxZRyswlEjE=
github.com/alibabacloud-go/endpoint-util v1.1.1 h1:ZkBv2/jnghxtU0p+upSU0GGzW1VL9GQdZO3mcSUTUy8=
github.com/alibabacloud-go/endpoint-util v1.1.1/go.mod h1:O5FuCALmCKs2Ff7JFJMudHs0I5EBgecXXxZRyswlEjE=
github.com/alibabacloud-go/esa-20240910/v2 v2.33.0 h1:10IWxrMcF1W6/7BUJIJifrofduSG0wRFqDbRfIsR3Zw=
github.com/alibabacloud-go/esa-20240910/v2 v2.33.0/go.mod h1:HZS5PmYJvcmH4vrJYuCvK3AnYzD9hLlO8CT0hgRyDXo=
github.com/alibabacloud-go/esa-20240910/v2 v2.34.1 h1:G8AWEhIGZ6QhZ6Or/bdhAZP0o9qEXCbxT5dkLqdl6gY=
github.com/alibabacloud-go/esa-20240910/v2 v2.34.1/go.mod h1:HZS5PmYJvcmH4vrJYuCvK3AnYzD9hLlO8CT0hgRyDXo=
github.com/alibabacloud-go/fc-20230330/v4 v4.3.5 h1:nDNjVzGwkQPbQnAuxAmxvS9x8QGLph8j0ptEdZDPGBA=
github.com/alibabacloud-go/fc-20230330/v4 v4.3.5/go.mod h1:vEJimQ6E/e+m2z0/oXdeQWlFw/Pi/Ar6NKcMrSvcILE=
github.com/alibabacloud-go/fc-open-20210406/v2 v2.0.12 h1:A3D8Mp6qf8DfR6Dt5MpS8aDVaWfS4N85T5CvGUvgrjM=
@ -190,8 +190,8 @@ github.com/alibabacloud-go/tea-xml v1.1.3 h1:7LYnm+JbOq2B+T/B0fHC4Ies4/FofC4zHzY
github.com/alibabacloud-go/tea-xml v1.1.3/go.mod h1:Rq08vgCcCAjHyRi/M7xlHKUykZCEtyBy9+DPF6GgEu8=
github.com/alibabacloud-go/vod-20170321/v4 v4.8.4 h1:MYP2xfrcud8vlWljQ4lhemNgAgi9/AUAa450n8TUXZo=
github.com/alibabacloud-go/vod-20170321/v4 v4.8.4/go.mod h1:5ocQ6hIc9tpGixD2iy099aOGwIgpzjT2le4Krd4aLn8=
github.com/alibabacloud-go/waf-openapi-20211001/v5 v5.1.3 h1:25tmcJxIitrk55crBGssPlqRzmFcpGVW5TEFxdUvfg0=
github.com/alibabacloud-go/waf-openapi-20211001/v5 v5.1.3/go.mod h1:9itYSTzipL3NlvhvNYfTjFaapoZzG68nlu/KUdh9SpA=
github.com/alibabacloud-go/waf-openapi-20211001/v5 v5.4.0 h1:eEfAqN1Z9PW9SzQ3YOvT5EADzjVwG9Fg4s3xLGSHJxk=
github.com/alibabacloud-go/waf-openapi-20211001/v5 v5.4.0/go.mod h1:9itYSTzipL3NlvhvNYfTjFaapoZzG68nlu/KUdh9SpA=
github.com/aliyun/alibaba-cloud-sdk-go v1.63.100 h1:yUkCbrSM1cWtgBfRVKMQtdt22KhDvKY7g4V+92eG9wA=
github.com/aliyun/alibaba-cloud-sdk-go v1.63.100/go.mod h1:SOSDHfe1kX91v3W5QiBsWSLqeLxImobbMX1mxrFHsVQ=
github.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible h1:8psS8a+wKfiLt1iVDX79F7Y6wUM49Lcha2FMXt4UM8g=
@ -216,27 +216,27 @@ github.com/avast/retry-go v3.0.0+incompatible h1:4SOWQ7Qs+oroOTQOYnAHqelpCO0biHS
github.com/avast/retry-go v3.0.0+incompatible/go.mod h1:XtSnn+n/sHqQIpZ10K1qAevBhOOCWBLXXy3hyiqqBrY=
github.com/aws/aws-sdk-go v1.40.45/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q=
github.com/aws/aws-sdk-go-v2 v1.9.1/go.mod h1:cK/D0BBs0b/oWPIcX/Z/obahJK1TT7IPVjy53i/mX/4=
github.com/aws/aws-sdk-go-v2 v1.36.3 h1:mJoei2CxPutQVxaATCzDUjcZEjVRdpsiiXi2o38yqWM=
github.com/aws/aws-sdk-go-v2 v1.36.3/go.mod h1:LLXuLpgzEbD766Z5ECcRmi8AzSwfZItDtmABVkRLGzg=
github.com/aws/aws-sdk-go-v2 v1.36.5 h1:0OF9RiEMEdDdZEMqF9MRjevyxAQcf6gY+E7vwBILFj0=
github.com/aws/aws-sdk-go-v2 v1.36.5/go.mod h1:EYrzvCCN9CMUTa5+6lf6MM4tq3Zjp8UhSGR/cBsjai0=
github.com/aws/aws-sdk-go-v2/config v1.29.9 h1:Kg+fAYNaJeGXp1vmjtidss8O2uXIsXwaRqsQJKXVr+0=
github.com/aws/aws-sdk-go-v2/config v1.29.9/go.mod h1:oU3jj2O53kgOU4TXq/yipt6ryiooYjlkqqVaZk7gY/U=
github.com/aws/aws-sdk-go-v2/credentials v1.17.62 h1:fvtQY3zFzYJ9CfixuAQ96IxDrBajbBWGqjNTCa79ocU=
github.com/aws/aws-sdk-go-v2/credentials v1.17.62/go.mod h1:ElETBxIQqcxej++Cs8GyPBbgMys5DgQPTwo7cUPDKt8=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.30 h1:x793wxmUWVDhshP8WW2mlnXuFrO4cOd3HLBroh1paFw=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.30/go.mod h1:Jpne2tDnYiFascUEs2AWHJL9Yp7A5ZVy3TNyxaAjD6M=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34 h1:ZK5jHhnrioRkUNOc+hOgQKlUL5JeC3S6JgLxtQ+Rm0Q=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34/go.mod h1:p4VfIceZokChbA9FzMbRGz5OV+lekcVtHlPKEO0gSZY=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34 h1:SZwFm17ZUNNg5Np0ioo/gq8Mn6u9w19Mri8DnJ15Jf0=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34/go.mod h1:dFZsC0BLo346mvKQLWmoJxT+Sjp+qcVR1tRVHQGOH9Q=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.36 h1:SsytQyTMHMDPspp+spo7XwXTP44aJZZAC7fBV2C5+5s=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.36/go.mod h1:Q1lnJArKRXkenyog6+Y+zr7WDpk4e6XlR6gs20bbeNo=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.36 h1:i2vNHQiXUvKhs3quBR6aqlgJaiaexz/aNvdCktW/kAM=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.36/go.mod h1:UdyGa7Q91id/sdyHPwth+043HhmP6yP9MBHgbZM0xo8=
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 h1:bIqFDwgGXXN1Kpp99pDOdKMTTb5d2KyU5X/BZxjOkRo=
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3/go.mod h1:H5O/EsxDWyU+LP/V8i5sm8cxoZgc2fdNR9bxlOFrQTo=
github.com/aws/aws-sdk-go-v2/service/acm v1.32.0 h1:Ik/TAn4TBw/t3JhQJKtwjgoOf6kg5nXc190TiGhNrmI=
github.com/aws/aws-sdk-go-v2/service/acm v1.32.0/go.mod h1:3sKYAgRbuBa2QMYGh/WEclwnmfx+QoPhhX25PdSQSQM=
github.com/aws/aws-sdk-go-v2/service/cloudfront v1.46.1 h1:6xZNYtuVwzBs8k+TmraERt0vL68Ppg9aUi+aTQmPaVM=
github.com/aws/aws-sdk-go-v2/service/cloudfront v1.46.1/go.mod h1:FIBJ48TS+qJb+Ne4qJ+0NeIhtPTVXItXooTeNeVI4Po=
github.com/aws/aws-sdk-go-v2/service/acm v1.33.0 h1:Z3MHBWR1KiviwaAiG7MTPB6T5gLYRPhUECuKLgltCwA=
github.com/aws/aws-sdk-go-v2/service/acm v1.33.0/go.mod h1:t3jPqKBnySV3qsU40cj1TWleOYx5vyz1xBeZiplAVcs=
github.com/aws/aws-sdk-go-v2/service/cloudfront v1.46.3 h1:ULVZL6Ro+vqmXFVFgZ5Q92pqWnhJfwOnWlNtibQPnIs=
github.com/aws/aws-sdk-go-v2/service/cloudfront v1.46.3/go.mod h1:vudWcTOLhQf4lzRH0qHUszJh8Gpo+Lp6dqH/HgVR9Xg=
github.com/aws/aws-sdk-go-v2/service/cloudwatch v1.8.1/go.mod h1:CM+19rL1+4dFWnOQKwDc7H1KwXTz+h61oUSHyhV0b3o=
github.com/aws/aws-sdk-go-v2/service/iam v1.42.0 h1:G6+UzGvubaet9QOh0664E9JeT+b6Zvop3AChozRqkrA=
github.com/aws/aws-sdk-go-v2/service/iam v1.42.0/go.mod h1:mPJkGQzeCoPs82ElNILor2JzZgYENr4UaSKUT8K27+c=
github.com/aws/aws-sdk-go-v2/service/iam v1.42.2 h1:IrauIGCnD90jXDFpAKYzCgrbagk/Yta4L+zxcVLOA58=
github.com/aws/aws-sdk-go-v2/service/iam v1.42.2/go.mod h1:QRtwvoAGc59uxv4vQHPKr75SLzhYCRSoETxAA98r6O4=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3 h1:eAh2A4b5IzM/lum78bZ590jy36+d/aFLgKF/4Vd1xPE=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3/go.mod h1:0yKJC/kb8sAnmlYa6Zs3QVYqaC8ug2AbnNChv5Ox3uA=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.15 h1:dM9/92u2F1JbDaGooxTq18wmmFzbJRfXfVfy96/1CXM=
@ -250,10 +250,10 @@ github.com/aws/aws-sdk-go-v2/service/ssooidc v1.29.1/go.mod h1:MlYRNmYu/fGPoxBQV
github.com/aws/aws-sdk-go-v2/service/sts v1.33.17 h1:PZV5W8yk4OtH1JAuhV2PXwwO9v5G5Aoj+eMCn4T+1Kc=
github.com/aws/aws-sdk-go-v2/service/sts v1.33.17/go.mod h1:cQnB8CUnxbMU82JvlqjKR2HBOm3fe9pWorWBza6MBJ4=
github.com/aws/smithy-go v1.8.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E=
github.com/aws/smithy-go v1.22.2 h1:6D9hW43xKFrRx/tXXfAlIZc4JI+yQe6snnWcQyxSyLQ=
github.com/aws/smithy-go v1.22.2/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg=
github.com/baidubce/bce-sdk-go v0.9.228 h1:XEY3/oAxXcsi7+3atib9fMI6YNE9sL5qo+WMZ+iqmNE=
github.com/baidubce/bce-sdk-go v0.9.228/go.mod h1:zbYJMQwE4IZuyrJiFO8tO8NbtYiKTFTbwh4eIsqjVdg=
github.com/aws/smithy-go v1.22.4 h1:uqXzVZNuNexwc/xrh6Tb56u89WDlJY6HS+KC0S4QSjw=
github.com/aws/smithy-go v1.22.4/go.mod h1:t1ufH5HMublsJYulve2RKmHDC15xu1f26kHCp/HgceI=
github.com/baidubce/bce-sdk-go v0.9.231 h1:inKgFMUkVXy05D3jfdKxEuOFiXxlLk/1A2+dWChu2X4=
github.com/baidubce/bce-sdk-go v0.9.231/go.mod h1:zbYJMQwE4IZuyrJiFO8tO8NbtYiKTFTbwh4eIsqjVdg=
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
@ -263,8 +263,8 @@ github.com/blinkbean/dingtalk v1.1.3 h1:MbidFZYom7DTFHD/YIs+eaI7kRy52kmWE/sy0xjo
github.com/blinkbean/dingtalk v1.1.3/go.mod h1:9BaLuGSBqY3vT5hstValh48DbsKO7vaHaJnG9pXwbto=
github.com/buger/goterm v1.0.4 h1:Z9YvGmOih81P0FbVtEYTFF6YsSgxSUKEhf/f9bTMXbY=
github.com/buger/goterm v1.0.4/go.mod h1:HiFWV3xnkolgrBV3mY8m0X0Pumt4zg4QhbdOzQtB8tE=
github.com/byteplus-sdk/byteplus-sdk-golang v1.0.46 h1:Z0TagIjBDaoCZuJANP/P8+z+ef8dStVCBPjMZcI/y8s=
github.com/byteplus-sdk/byteplus-sdk-golang v1.0.46/go.mod h1:CIL/T2dxgbIA79os+wl0Fq0vCbADTZNIddV6PNYB6DY=
github.com/byteplus-sdk/byteplus-sdk-golang v1.0.50 h1:iwaWNNgRxFwJ/ejnj5LXpfqwwsdgF/ByA3QczXOCKbg=
github.com/byteplus-sdk/byteplus-sdk-golang v1.0.50/go.mod h1:CIL/T2dxgbIA79os+wl0Fq0vCbADTZNIddV6PNYB6DY=
github.com/casbin/casbin/v2 v2.37.0/go.mod h1:vByNa/Fchek0KZUgG5wEsl7iFsiviAYKRtgrQfcJqHg=
github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
github.com/cenkalti/backoff/v4 v4.1.2/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
@ -407,8 +407,8 @@ github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1v
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM=
github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss=
github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/go-viper/mapstructure/v2 v2.3.0 h1:27XbWsHIqhbdR5TIC911OfYvgSaW93HM+dX7970Q7jk=
github.com/go-viper/mapstructure/v2 v2.3.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/go-zookeeper/zk v1.0.2/go.mod h1:nOB03cncLtlp4t+UAkGSV+9beXP/akpekBwL+UX1Qcw=
github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
@ -547,8 +547,8 @@ github.com/hashicorp/mdns v1.0.1/go.mod h1:4gW7WsVCke5TE7EPeYliwHlRUyBtfCwuFwuMg
github.com/hashicorp/memberlist v0.2.2/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE=
github.com/hashicorp/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKENpqIUyk=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.150 h1:Ih+z79Ko1ClH4dlv7O1lyHRiVCjkb2NZYYk+1cSZbU8=
github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.150/go.mod h1:Y/+YLCFCJtS29i2MbYPTUlNNfwXvkzEsZKR0imY/2aY=
github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.155 h1:R8hjwhuy5qzrYbqpj0D/fwGPDZgmlIyBjT3fzZbM38Q=
github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.155/go.mod h1:Y/+YLCFCJtS29i2MbYPTUlNNfwXvkzEsZKR0imY/2aY=
github.com/hudl/fargo v1.4.0/go.mod h1:9Ai6uvFy5fQNq6VPKtg+Ceq1+eTY4nKUlR2JElEOcDo=
github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
@ -739,8 +739,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRI
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pocketbase/dbx v1.11.0 h1:LpZezioMfT3K4tLrqA55wWFw1EtH1pM4tzSVa7kgszU=
github.com/pocketbase/dbx v1.11.0/go.mod h1:xXRCIAKTHMgUCyCKZm55pUOdvFziJjQfXaWKhu2vhMs=
github.com/pocketbase/pocketbase v0.28.2 h1:b6cfUfr5d4whvUFGFhI8oHRzx/eB76GCUQGftqgv9lM=
github.com/pocketbase/pocketbase v0.28.2/go.mod h1:ElwIYS1b5xS9w0U7AK7tsm6FuC0lzw57H8p/118Cu7g=
github.com/pocketbase/pocketbase v0.28.4 h1:RmhWXDcfKrFM9/W0G0Zrlv4eKBM8/s/v4SQKytjgD20=
github.com/pocketbase/pocketbase v0.28.4/go.mod h1:jSuN93vE/oeJVOz2D2ZxcYyr2bYNmDOMCUkM+JhyJQ0=
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s=
github.com/povsister/scp v0.0.0-20250504051308-e467f71ea63c h1:1+j5JHz9mUzYSp0scuF6hzvJP28EDBFe5eBJb0xnGk4=
@ -767,8 +767,8 @@ github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/qiniu/dyn v1.3.0 h1:s+xPTeV0H8yikgM4ZMBc7Rrefam8UNI3asBlkaOQg5o=
github.com/qiniu/dyn v1.3.0/go.mod h1:E8oERcm8TtwJiZvkQPbcAh0RL8jO1G0VXJMW3FAWdkk=
github.com/qiniu/go-sdk/v7 v7.25.3 h1:eYHh02q4i5MrlEn3qy823w7moieymFzb4dsP38Y43AI=
github.com/qiniu/go-sdk/v7 v7.25.3/go.mod h1:dmKtJ2ahhPWFVi9o1D5GemmWoh/ctuB9peqTowyTO8o=
github.com/qiniu/go-sdk/v7 v7.25.4 h1:ulCKlTEyrZzmNytXweOrnva49+Q4+ASjYBCSXhkRWTo=
github.com/qiniu/go-sdk/v7 v7.25.4/go.mod h1:dmKtJ2ahhPWFVi9o1D5GemmWoh/ctuB9peqTowyTO8o=
github.com/qiniu/x v1.10.5 h1:7V/CYWEmo9axJULvrJN6sMYh2FdY+esN5h8jwDkA4b0=
github.com/qiniu/x v1.10.5/go.mod h1:03Ni9tj+N2h2aKnAz+6N0Xfl8FwMEDRC2PAlxekASDs=
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
@ -801,8 +801,8 @@ github.com/smartystreets/assertions v1.1.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYl
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/cast v1.8.0 h1:gEN9K4b8Xws4EX0+a0reLmhq8moKn7ntRlQYgjPeCDk=
github.com/spf13/cast v1.8.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
github.com/spf13/cast v1.9.2 h1:SsGfm7M8QOFtEzumm7UZrZdLLquNdzFYfIbEXntcFbE=
github.com/spf13/cast v1.9.2/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo=
github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo=
github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0=
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
@ -829,37 +829,45 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cdn v1.0.1155 h1:ildxJtjnqiKZxWDVKHT/ncIknGDijtg60MuFELON8bY=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cdn v1.0.1155/go.mod h1:iLASpooTdyXtx642E5Ws7cfWENsp4/uZ/78TFoln7OI=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/clb v1.0.1166 h1:cEoDsBt7vGh7YtfVHVmgXKQURZANBE8UKK/So84QUdU=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/clb v1.0.1166/go.mod h1:0o5Cfgdh+bAx7kpQ5a5wce/ZUiDvy4Md8NcbrLtk6i8=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cdn v1.0.1187 h1:x2q6BAFm2f+9YaE7/lGPWXL7HzRkovjoqOMbdtRdpBw=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cdn v1.0.1187/go.mod h1:GoIHP0ayv0QOWN4c9aUEaKi74lY/tbeJz7h5i8y2gdU=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cdn v1.0.1193 h1:zOWZKDVA3kvA5/b+AwKzDtz5ewdiibeKxVqtCFJSTNI=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cdn v1.0.1193/go.mod h1:ufxDBGyS3X/9QKkZzuOFKLNra9FmSfgAHBO/FlFZaTU=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/clb v1.0.1188 h1:zzaIE12soTfyAgRvBYhb5bYxFXRCelvYXDEfvtkT5Y4=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/clb v1.0.1188/go.mod h1:qIWFhWbmMuUaWCCKVSkdJ1BzKEOqkMeo+uKYS6jJimQ=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1128/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1150/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1155/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1163/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1164/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1166/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1169/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1170/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1172/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1173 h1:W5bzEWiJwiwRZR0/P1l78OYWUXYsXLjhBaQ64c+9+fk=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1173/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1182/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1183/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1187/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1188/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1189/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1191/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1192 h1:3K6aJXXkjBLxqFYnBqAqFW5YqxmwMT0HR2F4gxQiNMU=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1192/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1193 h1:anxhOjL4WrQDqUcX7eT8VEaQITiKWllKwsH1fEt6lBw=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1193/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1128 h1:mrJ5Fbkd7sZIJ5F6oRfh5zebPQaudPH9Y0+GUmFytYU=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1128/go.mod h1:zbsYIBT+VTX4z4ocjTAdLBIWyNYj3z0BRqd0iPdnjsk=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/gaap v1.0.1163 h1:putqrH5n1SVRqFWHOylVqYI5yLQUjRTkHqZPLT2yeVY=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/gaap v1.0.1163/go.mod h1:aEWRXlAvovPUUoS3kVB/LVWEQ19WqzTj2lXGvR1YArY=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/live v1.0.1150 h1:RQQYfZOFYlkxKR2+xp8el3+8xs9DhxBy+ajlHtapqtQ=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/live v1.0.1150/go.mod h1:zpfr6EBWy7ClASTGUgIy01Gn4R79UXf+2QGQeyR124A=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/live v1.0.1192 h1:2430drceaOXASJZyVZ+e7QSzgBfgwSjDEDM5rh4046M=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/live v1.0.1192/go.mod h1:JHZLo95Fde/0et2Ag2E5P6VmCZQIq74MClUtanJ4JcY=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/live v1.0.1193 h1:VtXqRnzGz3KheXu2msNPvA/fUYQGsVVRC30WgyAUEqg=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/live v1.0.1193/go.mod h1:42I1OwaedHR6Yvg7J6UYoOjNYUYfFqwaeEkvx3x+NZc=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/scf v1.0.1172 h1:6SUO0hTie3zxnUEMxmhnS1iRIXpAukSZV27Nrx4NwIk=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/scf v1.0.1172/go.mod h1:tmN4zfu70SD0iee3qfpc09NRLel30zGoAuzIs4X0Kfs=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssl v1.0.1169 h1:oBymtJEmKDnS2NIR0PDLd+xCGQ+7uMoEt7zEB5Q3x8U=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssl v1.0.1169/go.mod h1:K27PNEgRJ602ESXUNnlRnCkf1+XYHI6RVP/ylIe/Aro=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/teo v1.0.1166 h1:+kIsoG2If/0y15PpZsXfT0QqTuwec9nMgo1JP8KQMkw=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/teo v1.0.1166/go.mod h1:lGmBMXqe3vBg6Bi9h4mVpWLKd7jQIMRbndr8KNHBqSw=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vod v1.0.1164 h1:caaIGWOs/JtWOK5ptVMEiiGgzU7Jf6UpMv+9IbIa4vs=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vod v1.0.1164/go.mod h1:SJI2mc77gDC7Tw1QoF/4d5SwLvz8HQFUecWtIXb+r/Q=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/waf v1.0.1170 h1:kcQCWuI9zOkZgL5CK66HNAJmSWCSJxRrDxXT+j02CeE=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/waf v1.0.1170/go.mod h1:vTukVfThbBIc4lOf4eq/q51eEk78oZUJd2lAoJBOJwI=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssl v1.0.1189 h1:Db7gmkey7On70PAohvrna6RMLZzLHRjbALxPlH5JC3c=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssl v1.0.1189/go.mod h1:x+WlMCjbePO7M3R0qzKmrpmieUWrtsRpcKBDpxJNQ5A=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssl v1.0.1193 h1:tmACSthp5JLjrdxzng6XFs4gfQcZHBTTVlXR0tO6hSk=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssl v1.0.1193/go.mod h1:LWf5UPUl41EQICrq0jswgQEO/BtRQY+CxAI6X+i709o=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/teo v1.0.1191 h1:4l1Db+yFh9HgqNynYbG93khxLtXSBwnXZgNmc88jOE0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/teo v1.0.1191/go.mod h1:y8if4wInFJoO6PU0/741VEYREHPtfxljhJ5HFD2ZkEA=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vod v1.0.1183 h1:3fvxkF/R1WaO937Wrx5ZCYoIof1X9sqSDXL218uRfJY=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vod v1.0.1183/go.mod h1:d47RTYqj/2xjIk/lmq8bQ9deUwfEQcWhPQxUgqZnz24=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/waf v1.0.1182 h1:2DaykFM5mXvQBvuhQEU/aOG5amissS31XI1wZh+FeMA=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/waf v1.0.1182/go.mod h1:pTAgdVcS28xFIARJXhg10hx2+g/Q9FqVkAkal3ARNfc=
github.com/tjfoc/gmsm v1.3.2/go.mod h1:HaUcFuY0auTiaHB9MHFGCPx5IaLhTUd2atbCFBQXn9w=
github.com/tjfoc/gmsm v1.4.1 h1:aMe1GlZb+0bLjn+cKTPEvvn9oUEBlJitaZiiBwsbgho=
github.com/tjfoc/gmsm v1.4.1/go.mod h1:j4INPkHWMrhJb38G+J6W4Tw0AbuN8Thu3PbdVYhVcTE=
@ -868,18 +876,18 @@ github.com/uber/jaeger-client-go v2.30.0+incompatible h1:D6wyKGCecFaSRUpo8lCVbaO
github.com/uber/jaeger-client-go v2.30.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk=
github.com/uber/jaeger-lib v2.4.1+incompatible h1:td4jdvLcExb4cBISKIpHuGoVXh+dVKhn2Um6rjCsSsg=
github.com/uber/jaeger-lib v2.4.1+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U=
github.com/ucloud/ucloud-sdk-go v0.22.41 h1:JndTJhCx7A1wggZfVb4KMm7D0Wfvd/HkmQVfSNjClQA=
github.com/ucloud/ucloud-sdk-go v0.22.41/go.mod h1:dyLmFHmUfgb4RZKYQP9IArlvQ2pxzFthfhwxRzOEPIw=
github.com/ucloud/ucloud-sdk-go v0.22.44 h1:AuWtd6xw2abQ8MAAI6ebWIYsTpoUfE6v2WMY8s5inPY=
github.com/ucloud/ucloud-sdk-go v0.22.44/go.mod h1:dyLmFHmUfgb4RZKYQP9IArlvQ2pxzFthfhwxRzOEPIw=
github.com/ulikunitz/xz v0.5.11 h1:kpFauv27b6ynzBNT/Xy+1k+fK4WswhN/6PN5WhFAGw8=
github.com/ulikunitz/xz v0.5.11/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
github.com/volcengine/ve-tos-golang-sdk/v2 v2.7.12 h1:u9+32DXQIOFPG8oQ3xrjSAUSyAcaq5bqO4cEBom/6lA=
github.com/volcengine/ve-tos-golang-sdk/v2 v2.7.12/go.mod h1:IrjK84IJJTuOZOTMv/P18Ydjy/x+ow7fF7q11jAxXLM=
github.com/volcengine/ve-tos-golang-sdk/v2 v2.7.17 h1:j3czHCTIG/xwjzQ71bwM57+Wg7R1XTe757o6PeCh+B4=
github.com/volcengine/ve-tos-golang-sdk/v2 v2.7.17/go.mod h1:IrjK84IJJTuOZOTMv/P18Ydjy/x+ow7fF7q11jAxXLM=
github.com/volcengine/volc-sdk-golang v1.0.23/go.mod h1:AfG/PZRUkHJ9inETvbjNifTDgut25Wbkm2QoYBTbvyU=
github.com/volcengine/volc-sdk-golang v1.0.208 h1:DyGUPjEKhWS08BkptfqenXTuUq+LKb7+gX/RBAtNl8w=
github.com/volcengine/volc-sdk-golang v1.0.208/go.mod h1:stZX+EPgv1vF4nZwOlEe8iGcriUPRBKX8zA19gXycOQ=
github.com/volcengine/volcengine-go-sdk v1.1.8 h1:/T2p7qeeLWWhGrhtB00b8VNlE32S266LcO+jqFUYwzY=
github.com/volcengine/volcengine-go-sdk v1.1.8/go.mod h1:EyKoi6t6eZxoPNGr2GdFCZti2Skd7MO3eUzx7TtSvNo=
github.com/volcengine/volc-sdk-golang v1.0.212 h1:evyoDoYTPqc1j23cnTnbHO7Vu813O2VERWQ/FVm8z+k=
github.com/volcengine/volc-sdk-golang v1.0.212/go.mod h1:stZX+EPgv1vF4nZwOlEe8iGcriUPRBKX8zA19gXycOQ=
github.com/volcengine/volcengine-go-sdk v1.1.18 h1:tVcp1m6R8fgwZFb/MaltrpZY7b2+vYNbmO1MHlDSXIs=
github.com/volcengine/volcengine-go-sdk v1.1.18/go.mod h1:EyKoi6t6eZxoPNGr2GdFCZti2Skd7MO3eUzx7TtSvNo=
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
@ -947,8 +955,8 @@ golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOM
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM=
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8=
golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw=
golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM=
golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U=
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@ -962,14 +970,14 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6 h1:y5zboxd6LQAqYIhHnB48p0ByQ/GnQx2BE33L8BOHQkI=
golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6/go.mod h1:U6Lno4MTRCDY+Ba7aCcauB9T60gsv5s4ralQzP72ZoQ=
golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b h1:M2rDM6z3Fhozi9O7NWsxAkg/yqS/lQJ6PmkyIV3YP+o=
golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b/go.mod h1:3//PLf8L/X+8b4vuAfHzxeRUl04Adcb341+IGKfnqS8=
golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.27.0 h1:C8gA4oWU/tKkdCfYT6T2u4faJu3MeNS5O8UPWlPF61w=
golang.org/x/image v0.27.0/go.mod h1:xbdrClrAUway1MUTEZDq9mz/UpRwYAkFFNUslZtcB+g=
golang.org/x/image v0.28.0 h1:gdem5JW1OLS4FbkWgLO+7ZeFzYtL3xClb97GaUzYMFE=
golang.org/x/image v0.28.0/go.mod h1:GUJYXtnGKEUgggyzh+Vxt+AviiCcyiwpsl8iQ8MvwGY=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@ -995,8 +1003,8 @@ golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU=
golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
golang.org/x/mod v0.25.0 h1:n7a+ZbQKQA/Ysbyb0/6IbB1H/X41mKgbhfv7AfG/44w=
golang.org/x/mod v0.25.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@ -1052,8 +1060,8 @@ golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw=
golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@ -1079,8 +1087,8 @@ golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ=
golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8=
golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@ -1196,8 +1204,8 @@ golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M=
golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@ -1259,8 +1267,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc=
golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI=
golang.org/x/tools v0.34.0 h1:qIpSLOxeCYGg9TrcJokLBG4KFA6d795g0xkBkiESGlo=
golang.org/x/tools v0.34.0/go.mod h1:pAP9OwEaY1CAW3HOmg3hLZC5Z0CCmzjAF2UQMSqNARg=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@ -1400,12 +1408,12 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
k8s.io/api v0.33.1 h1:tA6Cf3bHnLIrUK4IqEgb2v++/GYUtqiu9sRVk3iBXyw=
k8s.io/api v0.33.1/go.mod h1:87esjTn9DRSRTD4fWMXamiXxJhpOIREjWOSjsW1kEHw=
k8s.io/apimachinery v0.33.1 h1:mzqXWV8tW9Rw4VeW9rEkqvnxj59k1ezDUl20tFK/oM4=
k8s.io/apimachinery v0.33.1/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM=
k8s.io/client-go v0.33.1 h1:ZZV/Ks2g92cyxWkRRnfUDsnhNn28eFpt26aGc8KbXF4=
k8s.io/client-go v0.33.1/go.mod h1:JAsUrl1ArO7uRVFWfcj6kOomSlCv+JpvIsp6usAGefA=
k8s.io/api v0.33.2 h1:YgwIS5jKfA+BZg//OQhkJNIfie/kmRsO0BmNaVSimvY=
k8s.io/api v0.33.2/go.mod h1:fhrbphQJSM2cXzCWgqU29xLDuks4mu7ti9vveEnpSXs=
k8s.io/apimachinery v0.33.2 h1:IHFVhqg59mb8PJWTLi8m1mAoepkUNYmptHsV+Z1m5jY=
k8s.io/apimachinery v0.33.2/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM=
k8s.io/client-go v0.33.2 h1:z8CIcc0P581x/J1ZYf4CNzRKxRvQAwoAolYPbtQes+E=
k8s.io/client-go v0.33.2/go.mod h1:9mCgT4wROvL948w6f6ArJNb7yQd7QsvqavDeZHvNmHo=
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff h1:/usPimJzUKKu+m+TE36gUyGcf03XZEP0ZIKgKj35LS4=
@ -1417,12 +1425,12 @@ modernc.org/cc/v4 v4.26.1/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0=
modernc.org/ccgo/v4 v4.28.0 h1:rjznn6WWehKq7dG4JtLRKxb52Ecv8OUGah8+Z/SfpNU=
modernc.org/ccgo/v4 v4.28.0/go.mod h1:JygV3+9AV6SmPhDasu4JgquwU81XAKLd3OKTUDNOiKE=
modernc.org/fileutil v1.0.0/go.mod h1:JHsWpkrk/CnVV1H/eGlFf85BEpfkrp56ro8nojIq9Q8=
modernc.org/fileutil v1.3.1 h1:8vq5fe7jdtEvoCf3Zf9Nm0Q05sH6kGx0Op2CPx1wTC8=
modernc.org/fileutil v1.3.1/go.mod h1:HxmghZSZVAz/LXcMNwZPA/DRrQZEVP9VX0V4LQGQFOc=
modernc.org/fileutil v1.3.3 h1:3qaU+7f7xxTUmvU1pJTZiDLAIoJVdUSSauJNHg9yXoA=
modernc.org/fileutil v1.3.3/go.mod h1:HxmghZSZVAz/LXcMNwZPA/DRrQZEVP9VX0V4LQGQFOc=
modernc.org/gc/v2 v2.6.5 h1:nyqdV8q46KvTpZlsw66kWqwXRHdjIlJOhG6kxiV/9xI=
modernc.org/gc/v2 v2.6.5/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito=
modernc.org/libc v1.65.7 h1:Ia9Z4yzZtWNtUIuiPuQ7Qf7kxYrxP1/jeHZzG8bFu00=
modernc.org/libc v1.65.7/go.mod h1:011EQibzzio/VX3ygj1qGFt5kMjP0lHb0qCW5/D/pQU=
modernc.org/libc v1.65.10 h1:ZwEk8+jhW7qBjHIT+wd0d9VjitRyQef9BnzlzGwMODc=
modernc.org/libc v1.65.10/go.mod h1:StFvYpx7i/mXtBAfVOjaU0PWZOvIRoZSgXhrwXzr8Po=
modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU=
modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg=
modernc.org/memory v1.11.0 h1:o4QC8aMQzmcwCK3t3Ux/ZHmwFPzE6hf2Y5LbkRs+hbI=
@ -1431,8 +1439,8 @@ modernc.org/opt v0.1.4 h1:2kNGMRiUjrp4LcaPuLY2PzUfqM/w9N23quVwhKt5Qm8=
modernc.org/opt v0.1.4/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns=
modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w=
modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE=
modernc.org/sqlite v1.37.1 h1:EgHJK/FPoqC+q2YBXg7fUmES37pCHFc97sI7zSayBEs=
modernc.org/sqlite v1.37.1/go.mod h1:XwdRtsE1MpiBcL54+MbKcaDvcuej+IYSMfLN6gSKV8g=
modernc.org/sqlite v1.38.0 h1:+4OrfPQ8pxHKuWG4md1JpR/EYAh3Md7TdejuuzE7EUI=
modernc.org/sqlite v1.38.0/go.mod h1:1Bj+yES4SVvBZ4cBOpVZ6QgesMCKpJZDq0nxYzOpmNE=
modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0=
modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A=
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=

View File

@ -64,6 +64,7 @@ func NewWithWorkflowNode(config ApplicantWithWorkflowNodeConfig) (Applicant, err
CAProviderAccessConfig: make(map[string]any),
CAProviderServiceConfig: nodeCfg.CAProviderConfig,
KeyAlgorithm: nodeCfg.KeyAlgorithm,
ACMEProfile: nodeCfg.ACMEProfile,
Nameservers: xslices.Filter(strings.Split(nodeCfg.Nameservers, ";"), func(s string) bool { return s != "" }),
DnsPropagationWait: nodeCfg.DnsPropagationWait,
DnsPropagationTimeout: nodeCfg.DnsPropagationTimeout,
@ -235,6 +236,7 @@ func applyUseLego(legoProvider challenge.Provider, options *applicantProviderOpt
certRequest := certificate.ObtainRequest{
Domains: options.Domains,
Bundle: true,
Profile: options.ACMEProfile,
}
if options.ARIReplaceAcct == user.Registration.URI {
certRequest.ReplacesCertID = options.ARIReplaceCert

View File

@ -38,6 +38,7 @@ import (
pPorkbun "github.com/certimate-go/certimate/pkg/core/ssl-applicator/acme-dns01/providers/porkbun"
pPowerDNS "github.com/certimate-go/certimate/pkg/core/ssl-applicator/acme-dns01/providers/powerdns"
pRainYun "github.com/certimate-go/certimate/pkg/core/ssl-applicator/acme-dns01/providers/rainyun"
pSpaceship "github.com/certimate-go/certimate/pkg/core/ssl-applicator/acme-dns01/providers/spaceship"
pTencentCloud "github.com/certimate-go/certimate/pkg/core/ssl-applicator/acme-dns01/providers/tencentcloud"
pTencentCloudEO "github.com/certimate-go/certimate/pkg/core/ssl-applicator/acme-dns01/providers/tencentcloud-eo"
pUCloudUDNR "github.com/certimate-go/certimate/pkg/core/ssl-applicator/acme-dns01/providers/ucloud-udnr"
@ -62,6 +63,7 @@ type applicantProviderOptions struct {
DnsPropagationWait int32
DnsPropagationTimeout int32
DnsTTL int32
ACMEProfile string
DisableFollowCNAME bool
ARIReplaceAcct string
ARIReplaceCert string
@ -582,6 +584,22 @@ func createApplicantProvider(options *applicantProviderOptions) (challenge.Provi
return applicant, err
}
case domain.ACMEDns01ProviderTypeSpaceship:
{
access := domain.AccessConfigForSpaceship{}
if err := xmaps.Populate(options.ProviderAccessConfig, &access); err != nil {
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
}
applicant, err := pSpaceship.NewChallengeProvider(&pSpaceship.ChallengeProviderConfig{
ApiKey: access.ApiKey,
ApiSecret: access.ApiSecret,
DnsPropagationTimeout: options.DnsPropagationTimeout,
DnsTTL: options.DnsTTL,
})
return applicant, err
}
case domain.ACMEDns01ProviderTypeTencentCloud, domain.ACMEDns01ProviderTypeTencentCloudDNS, domain.ACMEDns01ProviderTypeTencentCloudEO:
{
access := domain.AccessConfigForTencentCloud{}

View File

@ -84,6 +84,7 @@ import (
pTencentCloudSCF "github.com/certimate-go/certimate/pkg/core/ssl-deployer/providers/tencentcloud-scf"
pTencentCloudSSL "github.com/certimate-go/certimate/pkg/core/ssl-deployer/providers/tencentcloud-ssl"
pTencentCloudSSLDeploy "github.com/certimate-go/certimate/pkg/core/ssl-deployer/providers/tencentcloud-ssl-deploy"
pTencentCloudSSLUpdate "github.com/certimate-go/certimate/pkg/core/ssl-deployer/providers/tencentcloud-ssl-update"
pTencentCloudVOD "github.com/certimate-go/certimate/pkg/core/ssl-deployer/providers/tencentcloud-vod"
pTencentCloudWAF "github.com/certimate-go/certimate/pkg/core/ssl-deployer/providers/tencentcloud-waf"
pUCloudUCDN "github.com/certimate-go/certimate/pkg/core/ssl-deployer/providers/ucloud-ucdn"
@ -1011,7 +1012,7 @@ func createSSLDeployerProvider(options *deployerProviderOptions) (core.SSLDeploy
}
switch options.Provider {
case domain.DeploymentProviderTypeTencentCloudCDN:
case domain.DeploymentProviderTypeRainYunRCDN:
deployer, err := pRainYunRCDN.NewSSLDeployerProvider(&pRainYunRCDN.SSLDeployerProviderConfig{
ApiKey: access.ApiKey,
InstanceId: xmaps.GetInt32(options.ProviderServiceConfig, "instanceId"),
@ -1118,7 +1119,7 @@ func createSSLDeployerProvider(options *deployerProviderOptions) (core.SSLDeploy
return deployer, err
}
case domain.DeploymentProviderTypeTencentCloudCDN, domain.DeploymentProviderTypeTencentCloudCLB, domain.DeploymentProviderTypeTencentCloudCOS, domain.DeploymentProviderTypeTencentCloudCSS, domain.DeploymentProviderTypeTencentCloudECDN, domain.DeploymentProviderTypeTencentCloudEO, domain.DeploymentProviderTypeTencentCloudGAAP, domain.DeploymentProviderTypeTencentCloudSCF, domain.DeploymentProviderTypeTencentCloudSSL, domain.DeploymentProviderTypeTencentCloudSSLDeploy, domain.DeploymentProviderTypeTencentCloudVOD, domain.DeploymentProviderTypeTencentCloudWAF:
case domain.DeploymentProviderTypeTencentCloudCDN, domain.DeploymentProviderTypeTencentCloudCLB, domain.DeploymentProviderTypeTencentCloudCOS, domain.DeploymentProviderTypeTencentCloudCSS, domain.DeploymentProviderTypeTencentCloudECDN, domain.DeploymentProviderTypeTencentCloudEO, domain.DeploymentProviderTypeTencentCloudGAAP, domain.DeploymentProviderTypeTencentCloudSCF, domain.DeploymentProviderTypeTencentCloudSSL, domain.DeploymentProviderTypeTencentCloudSSLDeploy, domain.DeploymentProviderTypeTencentCloudSSLUpdate, domain.DeploymentProviderTypeTencentCloudVOD, domain.DeploymentProviderTypeTencentCloudWAF:
{
access := domain.AccessConfigForTencentCloud{}
if err := xmaps.Populate(options.ProviderAccessConfig, &access); err != nil {
@ -1130,6 +1131,7 @@ func createSSLDeployerProvider(options *deployerProviderOptions) (core.SSLDeploy
deployer, err := pTencentCloudCDN.NewSSLDeployerProvider(&pTencentCloudCDN.SSLDeployerProviderConfig{
SecretId: access.SecretId,
SecretKey: access.SecretKey,
Endpoint: xmaps.GetString(options.ProviderServiceConfig, "endpoint"),
Domain: xmaps.GetString(options.ProviderServiceConfig, "domain"),
})
return deployer, err
@ -1138,6 +1140,7 @@ func createSSLDeployerProvider(options *deployerProviderOptions) (core.SSLDeploy
deployer, err := pTencentCloudCLB.NewSSLDeployerProvider(&pTencentCloudCLB.SSLDeployerProviderConfig{
SecretId: access.SecretId,
SecretKey: access.SecretKey,
Endpoint: xmaps.GetString(options.ProviderServiceConfig, "endpoint"),
Region: xmaps.GetString(options.ProviderServiceConfig, "region"),
ResourceType: pTencentCloudCLB.ResourceType(xmaps.GetString(options.ProviderServiceConfig, "resourceType")),
LoadbalancerId: xmaps.GetString(options.ProviderServiceConfig, "loadbalancerId"),
@ -1160,6 +1163,7 @@ func createSSLDeployerProvider(options *deployerProviderOptions) (core.SSLDeploy
deployer, err := pTencentCloudCSS.NewSSLDeployerProvider(&pTencentCloudCSS.SSLDeployerProviderConfig{
SecretId: access.SecretId,
SecretKey: access.SecretKey,
Endpoint: xmaps.GetString(options.ProviderServiceConfig, "endpoint"),
Domain: xmaps.GetString(options.ProviderServiceConfig, "domain"),
})
return deployer, err
@ -1168,6 +1172,7 @@ func createSSLDeployerProvider(options *deployerProviderOptions) (core.SSLDeploy
deployer, err := pTencentCloudECDN.NewSSLDeployerProvider(&pTencentCloudECDN.SSLDeployerProviderConfig{
SecretId: access.SecretId,
SecretKey: access.SecretKey,
Endpoint: xmaps.GetString(options.ProviderServiceConfig, "endpoint"),
Domain: xmaps.GetString(options.ProviderServiceConfig, "domain"),
})
return deployer, err
@ -1176,6 +1181,7 @@ func createSSLDeployerProvider(options *deployerProviderOptions) (core.SSLDeploy
deployer, err := pTencentCloudEO.NewSSLDeployerProvider(&pTencentCloudEO.SSLDeployerProviderConfig{
SecretId: access.SecretId,
SecretKey: access.SecretKey,
Endpoint: xmaps.GetString(options.ProviderServiceConfig, "endpoint"),
ZoneId: xmaps.GetString(options.ProviderServiceConfig, "zoneId"),
Domain: xmaps.GetString(options.ProviderServiceConfig, "domain"),
})
@ -1185,6 +1191,7 @@ func createSSLDeployerProvider(options *deployerProviderOptions) (core.SSLDeploy
deployer, err := pTencentCloudGAAP.NewSSLDeployerProvider(&pTencentCloudGAAP.SSLDeployerProviderConfig{
SecretId: access.SecretId,
SecretKey: access.SecretKey,
Endpoint: xmaps.GetString(options.ProviderServiceConfig, "endpoint"),
ResourceType: pTencentCloudGAAP.ResourceType(xmaps.GetString(options.ProviderServiceConfig, "resourceType")),
ProxyId: xmaps.GetString(options.ProviderServiceConfig, "proxyId"),
ListenerId: xmaps.GetString(options.ProviderServiceConfig, "listenerId"),
@ -1195,6 +1202,7 @@ func createSSLDeployerProvider(options *deployerProviderOptions) (core.SSLDeploy
deployer, err := pTencentCloudSCF.NewSSLDeployerProvider(&pTencentCloudSCF.SSLDeployerProviderConfig{
SecretId: access.SecretId,
SecretKey: access.SecretKey,
Endpoint: xmaps.GetString(options.ProviderServiceConfig, "endpoint"),
Region: xmaps.GetString(options.ProviderServiceConfig, "region"),
Domain: xmaps.GetString(options.ProviderServiceConfig, "domain"),
})
@ -1204,6 +1212,7 @@ func createSSLDeployerProvider(options *deployerProviderOptions) (core.SSLDeploy
deployer, err := pTencentCloudSSL.NewSSLDeployerProvider(&pTencentCloudSSL.SSLDeployerProviderConfig{
SecretId: access.SecretId,
SecretKey: access.SecretKey,
Endpoint: xmaps.GetString(options.ProviderServiceConfig, "endpoint"),
})
return deployer, err
@ -1211,16 +1220,30 @@ func createSSLDeployerProvider(options *deployerProviderOptions) (core.SSLDeploy
deployer, err := pTencentCloudSSLDeploy.NewSSLDeployerProvider(&pTencentCloudSSLDeploy.SSLDeployerProviderConfig{
SecretId: access.SecretId,
SecretKey: access.SecretKey,
Endpoint: xmaps.GetString(options.ProviderServiceConfig, "endpoint"),
Region: xmaps.GetString(options.ProviderServiceConfig, "region"),
ResourceType: xmaps.GetString(options.ProviderServiceConfig, "resourceType"),
ResourceIds: xslices.Filter(strings.Split(xmaps.GetString(options.ProviderServiceConfig, "resourceIds"), ";"), func(s string) bool { return s != "" }),
})
return deployer, err
case domain.DeploymentProviderTypeTencentCloudSSLUpdate:
deployer, err := pTencentCloudSSLUpdate.NewSSLDeployerProvider(&pTencentCloudSSLUpdate.SSLDeployerProviderConfig{
SecretId: access.SecretId,
SecretKey: access.SecretKey,
Endpoint: xmaps.GetString(options.ProviderServiceConfig, "endpoint"),
CertificiateId: xmaps.GetString(options.ProviderServiceConfig, "certificiateId"),
IsReplaced: xmaps.GetBool(options.ProviderServiceConfig, "isReplaced"),
ResourceTypes: xslices.Filter(strings.Split(xmaps.GetString(options.ProviderServiceConfig, "resourceTypes"), ";"), func(s string) bool { return s != "" }),
ResourceRegions: xslices.Filter(strings.Split(xmaps.GetString(options.ProviderServiceConfig, "resourceRegions"), ";"), func(s string) bool { return s != "" }),
})
return deployer, err
case domain.DeploymentProviderTypeTencentCloudVOD:
deployer, err := pTencentCloudVOD.NewSSLDeployerProvider(&pTencentCloudVOD.SSLDeployerProviderConfig{
SecretId: access.SecretId,
SecretKey: access.SecretKey,
Endpoint: xmaps.GetString(options.ProviderServiceConfig, "endpoint"),
SubAppId: xmaps.GetInt64(options.ProviderServiceConfig, "subAppId"),
Domain: xmaps.GetString(options.ProviderServiceConfig, "domain"),
})
@ -1230,6 +1253,7 @@ func createSSLDeployerProvider(options *deployerProviderOptions) (core.SSLDeploy
deployer, err := pTencentCloudWAF.NewSSLDeployerProvider(&pTencentCloudWAF.SSLDeployerProviderConfig{
SecretId: access.SecretId,
SecretKey: access.SecretKey,
Endpoint: xmaps.GetString(options.ProviderServiceConfig, "endpoint"),
Domain: xmaps.GetString(options.ProviderServiceConfig, "domain"),
DomainId: xmaps.GetString(options.ProviderServiceConfig, "domainId"),
InstanceId: xmaps.GetString(options.ProviderServiceConfig, "instanceId"),

View File

@ -324,6 +324,11 @@ type AccessConfigForSlackBot struct {
DefaultChannelId string `json:"defaultChannelId,omitempty"`
}
type AccessConfigForSpaceship struct {
ApiKey string `json:"apiKey"`
ApiSecret string `json:"apiSecret"`
}
type AccessConfigForSSH struct {
Host string `json:"host"`
Port int32 `json:"port"`

View File

@ -74,6 +74,7 @@ const (
AccessProviderTypeRatPanel = AccessProviderType("ratpanel")
AccessProviderTypeSafeLine = AccessProviderType("safeline")
AccessProviderTypeSlackBot = AccessProviderType("slackbot")
AccessProviderTypeSpaceship = AccessProviderType("spaceship")
AccessProviderTypeSSH = AccessProviderType("ssh")
AccessProviderTypeSSLCOM = AccessProviderType("sslcom")
AccessProviderTypeTelegramBot = AccessProviderType("telegrambot")
@ -159,6 +160,7 @@ const (
ACMEDns01ProviderTypePorkbun = ACMEDns01ProviderType(AccessProviderTypePorkbun)
ACMEDns01ProviderTypePowerDNS = ACMEDns01ProviderType(AccessProviderTypePowerDNS)
ACMEDns01ProviderTypeRainYun = ACMEDns01ProviderType(AccessProviderTypeRainYun)
ACMEDns01ProviderTypeSpaceship = ACMEDns01ProviderType(AccessProviderTypeSpaceship)
ACMEDns01ProviderTypeTencentCloud = ACMEDns01ProviderType(AccessProviderTypeTencentCloud) // 兼容旧值,等同于 [ACMEDns01ProviderTypeTencentCloudDNS]
ACMEDns01ProviderTypeTencentCloudDNS = ACMEDns01ProviderType(AccessProviderTypeTencentCloud + "-dns")
ACMEDns01ProviderTypeTencentCloudEO = ACMEDns01ProviderType(AccessProviderTypeTencentCloud + "-eo")
@ -257,6 +259,7 @@ const (
DeploymentProviderTypeTencentCloudSCF = DeploymentProviderType(AccessProviderTypeTencentCloud + "-scf")
DeploymentProviderTypeTencentCloudSSL = DeploymentProviderType(AccessProviderTypeTencentCloud + "-ssl")
DeploymentProviderTypeTencentCloudSSLDeploy = DeploymentProviderType(AccessProviderTypeTencentCloud + "-ssldeploy")
DeploymentProviderTypeTencentCloudSSLUpdate = DeploymentProviderType(AccessProviderTypeTencentCloud + "-sslupdate")
DeploymentProviderTypeTencentCloudVOD = DeploymentProviderType(AccessProviderTypeTencentCloud + "-vod")
DeploymentProviderTypeTencentCloudWAF = DeploymentProviderType(AccessProviderTypeTencentCloud + "-waf")
DeploymentProviderTypeUCloudUCDN = DeploymentProviderType(AccessProviderTypeUCloud + "-ucdn")

View File

@ -75,6 +75,7 @@ type WorkflowNodeConfigForApply struct {
CAProviderAccessId string `json:"caProviderAccessId,omitempty"` // CA 提供商授权记录 ID
CAProviderConfig map[string]any `json:"caProviderConfig,omitempty"` // CA 提供商额外配置
KeyAlgorithm string `json:"keyAlgorithm"` // 证书算法
ACMEProfile string `json:"acmeProfile,omitempty"` // ACME Profiles Extension
Nameservers string `json:"nameservers,omitempty"` // DNS 服务器列表,以半角分号分隔
DnsPropagationWait int32 `json:"dnsPropagationWait,omitempty"` // DNS 传播等待时间,等同于 lego 的 `--dns-propagation-wait` 参数
DnsPropagationTimeout int32 `json:"dnsPropagationTimeout,omitempty"` // DNS 传播检查超时时间(零值时使用提供商的默认值)
@ -130,6 +131,7 @@ func (n *WorkflowNode) GetConfigForApply() WorkflowNodeConfigForApply {
CAProviderAccessId: xmaps.GetString(n.Config, "caProviderAccessId"),
CAProviderConfig: xmaps.GetKVMapAny(n.Config, "caProviderConfig"),
KeyAlgorithm: xmaps.GetOrDefaultString(n.Config, "keyAlgorithm", string(CertificateKeyAlgorithmTypeRSA2048)),
ACMEProfile: xmaps.GetString(n.Config, "acmeProfile"),
Nameservers: xmaps.GetString(n.Config, "nameservers"),
DnsPropagationWait: xmaps.GetInt32(n.Config, "dnsPropagationWait"),
DnsPropagationTimeout: xmaps.GetInt32(n.Config, "dnsPropagationTimeout"),

View File

@ -0,0 +1,93 @@
package migrations
import (
"encoding/json"
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
tracer := NewTracer("(v0.3)1750687200")
tracer.Printf("go ...")
// update collection `workflow_run`
{
collection, err := app.FindCollectionByNameOrId("qjp8lygssgwyqyz")
if err != nil {
return err
}
// update collection data
if err := json.Unmarshal([]byte(`{
"indexes": [
"CREATE INDEX `+"`"+`idx_7ZpfjTFsD2`+"`"+` ON `+"`"+`workflow_run`+"`"+` (`+"`"+`workflowId`+"`"+`)"
]
}`), &collection); err != nil {
return err
}
if err := app.Save(collection); err != nil {
return err
}
tracer.Printf("collection '%s' updated", collection.Name)
}
// update collection `workflow_output`
{
collection, err := app.FindCollectionByNameOrId("bqnxb95f2cooowp")
if err != nil {
return err
}
// update collection data
if err := json.Unmarshal([]byte(`{
"indexes": [
"CREATE INDEX `+"`"+`idx_BYoQPsz4my`+"`"+` ON `+"`"+`workflow_output`+"`"+` (`+"`"+`workflowId`+"`"+`)",
"CREATE INDEX `+"`"+`idx_O9zxLETuxJ`+"`"+` ON `+"`"+`workflow_output`+"`"+` (`+"`"+`runId`+"`"+`)",
"CREATE INDEX `+"`"+`idx_luac8Ul34G`+"`"+` ON `+"`"+`workflow_output`+"`"+` (`+"`"+`nodeId`+"`"+`)"
]
}`), &collection); err != nil {
return err
}
if err := app.Save(collection); err != nil {
return err
}
tracer.Printf("collection '%s' updated", collection.Name)
}
// update collection `workflow_logs`
{
collection, err := app.FindCollectionByNameOrId("pbc_1682296116")
if err != nil {
return err
}
// update collection data
if err := json.Unmarshal([]byte(`{
"indexes": [
"CREATE INDEX `+"`"+`idx_IOlpy6XuJ2`+"`"+` ON `+"`"+`workflow_logs`+"`"+` (`+"`"+`workflowId`+"`"+`)",
"CREATE INDEX `+"`"+`idx_qVlTb2yl7v`+"`"+` ON `+"`"+`workflow_logs`+"`"+` (`+"`"+`runId`+"`"+`)",
"CREATE INDEX `+"`"+`idx_UL4tdCXNlA`+"`"+` ON `+"`"+`workflow_logs`+"`"+` (`+"`"+`nodeId`+"`"+`)"
]
}`), &collection); err != nil {
return err
}
if err := app.Save(collection); err != nil {
return err
}
tracer.Printf("collection '%s' updated", collection.Name)
}
tracer.Printf("done")
return nil
}, func(app core.App) error {
return nil
})
}

View File

@ -0,0 +1,40 @@
package spaceship
import (
"errors"
"time"
"github.com/go-acme/lego/v4/providers/dns/spaceship"
"github.com/certimate-go/certimate/pkg/core"
)
type ChallengeProviderConfig struct {
ApiKey string `json:"apiKey"`
ApiSecret string `json:"apiSecret"`
DnsPropagationTimeout int32 `json:"dnsPropagationTimeout,omitempty"`
DnsTTL int32 `json:"dnsTTL,omitempty"`
}
func NewChallengeProvider(config *ChallengeProviderConfig) (core.ACMEChallenger, error) {
if config == nil {
return nil, errors.New("the configuration of the acme challenge provider is nil")
}
providerConfig := spaceship.NewDefaultConfig()
providerConfig.APIKey = config.ApiKey
providerConfig.APISecret = config.ApiSecret
if config.DnsPropagationTimeout != 0 {
providerConfig.PropagationTimeout = time.Duration(config.DnsPropagationTimeout) * time.Second
}
if config.DnsTTL != 0 {
providerConfig.TTL = int(config.DnsTTL)
}
provider, err := spaceship.NewDNSProviderConfig(providerConfig)
if err != nil {
return nil, err
}
return provider, nil
}

View File

@ -17,6 +17,7 @@ import (
"github.com/certimate-go/certimate/pkg/core"
sslmgrsp "github.com/certimate-go/certimate/pkg/core/ssl-manager/providers/aliyun-cas"
"github.com/certimate-go/certimate/pkg/utils/ifelse"
)
type SSLDeployerProviderConfig struct {
@ -65,7 +66,15 @@ func NewSSLDeployerProvider(config *SSLDeployerProviderConfig) (*SSLDeployerProv
return nil, fmt.Errorf("could not create sdk client: %w", err)
}
sslmgr, err := createSSLManager(config.AccessKeyId, config.AccessKeySecret, config.ResourceGroupId, config.Region)
sslmgr, err := sslmgrsp.NewSSLManagerProvider(&sslmgrsp.SSLManagerProviderConfig{
AccessKeyId: config.AccessKeyId,
AccessKeySecret: config.AccessKeySecret,
ResourceGroupId: config.ResourceGroupId,
Region: ifelse.
If[string](config.Region == "" || strings.HasPrefix(config.Region, "cn-")).
Then("cn-hangzhou").
Else("ap-southeast-1"),
})
if err != nil {
return nil, fmt.Errorf("could not create ssl manager: %w", err)
}
@ -463,25 +472,3 @@ func createSDKClients(accessKeyId, accessKeySecret, region string) (*wSDKClients
CAS: casClient,
}, nil
}
func createSSLManager(accessKeyId, accessKeySecret, resourceGroupId, region string) (core.SSLManager, error) {
casRegion := region
if casRegion != "" {
// 阿里云 CAS 服务接入点是独立于 ALB 服务的
// 国内版固定接入点:华东一杭州
// 国际版固定接入点:亚太东南一新加坡
if !strings.HasPrefix(casRegion, "cn-") {
casRegion = "ap-southeast-1"
} else {
casRegion = "cn-hangzhou"
}
}
sslmgr, err := sslmgrsp.NewSSLManagerProvider(&sslmgrsp.SSLManagerProviderConfig{
AccessKeyId: accessKeyId,
AccessKeySecret: accessKeySecret,
ResourceGroupId: resourceGroupId,
Region: casRegion,
})
return sslmgr, err
}

View File

@ -15,6 +15,7 @@ import (
"github.com/certimate-go/certimate/pkg/core"
sslmgrsp "github.com/certimate-go/certimate/pkg/core/ssl-manager/providers/aliyun-cas"
"github.com/certimate-go/certimate/pkg/utils/ifelse"
xtypes "github.com/certimate-go/certimate/pkg/utils/types"
)
@ -63,7 +64,15 @@ func NewSSLDeployerProvider(config *SSLDeployerProviderConfig) (*SSLDeployerProv
return nil, fmt.Errorf("could not create sdk client: %w", err)
}
sslmgr, err := createSSLManager(config.AccessKeyId, config.AccessKeySecret, config.ResourceGroupId, config.Region)
sslmgr, err := sslmgrsp.NewSSLManagerProvider(&sslmgrsp.SSLManagerProviderConfig{
AccessKeyId: config.AccessKeyId,
AccessKeySecret: config.AccessKeySecret,
ResourceGroupId: config.ResourceGroupId,
Region: ifelse.
If[string](config.Region == "" || strings.HasPrefix(config.Region, "cn-")).
Then("cn-hangzhou").
Else("ap-southeast-1"),
})
if err != nil {
return nil, fmt.Errorf("could not create ssl manager: %w", err)
}
@ -225,7 +234,14 @@ func (d *SSLDeployerProvider) deployToCloudNative(ctx context.Context, certPEM s
func createSDKClients(accessKeyId, accessKeySecret, region string) (*wSDKClients, error) {
// 接入点一览 https://api.aliyun.com/product/APIG
cloudNativeAPIGEndpoint := strings.ReplaceAll(fmt.Sprintf("apig.%s.aliyuncs.com", region), "..", ".")
var cloudNativeAPIGEndpoint string
switch region {
case "":
cloudNativeAPIGEndpoint = "apig.cn-hangzhou.aliyuncs.com"
default:
cloudNativeAPIGEndpoint = fmt.Sprintf("apig.%s.aliyuncs.com", region)
}
cloudNativeAPIGConfig := &aliopen.Config{
AccessKeyId: tea.String(accessKeyId),
AccessKeySecret: tea.String(accessKeySecret),
@ -237,7 +253,14 @@ func createSDKClients(accessKeyId, accessKeySecret, region string) (*wSDKClients
}
// 接入点一览 https://api.aliyun.com/product/CloudAPI
traditionalAPIGEndpoint := strings.ReplaceAll(fmt.Sprintf("apigateway.%s.aliyuncs.com", region), "..", ".")
var traditionalAPIGEndpoint string
switch region {
case "":
traditionalAPIGEndpoint = "apigateway.cn-hangzhou.aliyuncs.com"
default:
traditionalAPIGEndpoint = fmt.Sprintf("apigateway.%s.aliyuncs.com", region)
}
traditionalAPIGConfig := &aliopen.Config{
AccessKeyId: tea.String(accessKeyId),
AccessKeySecret: tea.String(accessKeySecret),
@ -253,25 +276,3 @@ func createSDKClients(accessKeyId, accessKeySecret, region string) (*wSDKClients
TraditionalAPIGateway: traditionalAPIGClient,
}, nil
}
func createSSLManager(accessKeyId, accessKeySecret, resourceGroupId, region string) (core.SSLManager, error) {
casRegion := region
if casRegion != "" {
// 阿里云 CAS 服务接入点是独立于 APIGateway 服务的
// 国内版固定接入点:华东一杭州
// 国际版固定接入点:亚太东南一新加坡
if !strings.HasPrefix(casRegion, "cn-") {
casRegion = "ap-southeast-1"
} else {
casRegion = "cn-hangzhou"
}
}
sslmgr, err := sslmgrsp.NewSSLManagerProvider(&sslmgrsp.SSLManagerProviderConfig{
AccessKeyId: accessKeyId,
AccessKeySecret: accessKeySecret,
ResourceGroupId: resourceGroupId,
Region: casRegion,
})
return sslmgr, err
}

View File

@ -25,9 +25,9 @@ type SSLDeployerProviderConfig struct {
ResourceGroupId string `json:"resourceGroupId,omitempty"`
// 阿里云地域。
Region string `json:"region"`
// 阿里云云产品资源 ID 数组。
// 云产品资源 ID 数组。
ResourceIds []string `json:"resourceIds"`
// 阿里云云联系人 ID 数组。
// 云联系人 ID 数组。
// 零值时使用账号下第一个联系人。
ContactIds []string `json:"contactIds"`
}
@ -51,7 +51,12 @@ func NewSSLDeployerProvider(config *SSLDeployerProviderConfig) (*SSLDeployerProv
return nil, fmt.Errorf("could not create sdk client: %w", err)
}
sslmgr, err := createSSLManager(config.AccessKeyId, config.AccessKeySecret, config.ResourceGroupId, config.Region)
sslmgr, err := sslmgrsp.NewSSLManagerProvider(&sslmgrsp.SSLManagerProviderConfig{
AccessKeyId: config.AccessKeyId,
AccessKeySecret: config.AccessKeySecret,
ResourceGroupId: config.ResourceGroupId,
Region: config.Region,
})
if err != nil {
return nil, fmt.Errorf("could not create ssl manager: %w", err)
}
@ -177,25 +182,3 @@ func createSDKClient(accessKeyId, accessKeySecret, region string) (*alicas.Clien
return client, nil
}
func createSSLManager(accessKeyId, accessKeySecret, resourceGroupId, region string) (core.SSLManager, error) {
casRegion := region
if casRegion != "" {
// 阿里云 CAS 服务接入点是独立于其他服务的
// 国内版固定接入点:华东一杭州
// 国际版固定接入点:亚太东南一新加坡
if !strings.HasPrefix(casRegion, "cn-") {
casRegion = "ap-southeast-1"
} else {
casRegion = "cn-hangzhou"
}
}
sslmgr, err := sslmgrsp.NewSSLManagerProvider(&sslmgrsp.SSLManagerProviderConfig{
AccessKeyId: accessKeyId,
AccessKeySecret: accessKeySecret,
ResourceGroupId: resourceGroupId,
Region: casRegion,
})
return sslmgr, err
}

View File

@ -5,6 +5,7 @@ import (
"errors"
"fmt"
"log/slog"
"strings"
aliopen "github.com/alibabacloud-go/darabonba-openapi/v2/client"
alislb "github.com/alibabacloud-go/slb-20140515/v4/client"
@ -12,6 +13,7 @@ import (
"github.com/certimate-go/certimate/pkg/core"
sslmgrsp "github.com/certimate-go/certimate/pkg/core/ssl-manager/providers/aliyun-slb"
"github.com/certimate-go/certimate/pkg/utils/ifelse"
)
type SSLDeployerProviderConfig struct {
@ -55,7 +57,15 @@ func NewSSLDeployerProvider(config *SSLDeployerProviderConfig) (*SSLDeployerProv
return nil, fmt.Errorf("could not create sdk client: %w", err)
}
sslmgr, err := createSSLManager(config.AccessKeyId, config.AccessKeySecret, config.ResourceGroupId, config.Region)
sslmgr, err := sslmgrsp.NewSSLManagerProvider(&sslmgrsp.SSLManagerProviderConfig{
AccessKeyId: config.AccessKeyId,
AccessKeySecret: config.AccessKeySecret,
ResourceGroupId: config.ResourceGroupId,
Region: ifelse.
If[string](config.Region == "" || strings.HasPrefix(config.Region, "cn-")).
Then("cn-hangzhou").
Else("ap-southeast-1"),
})
if err != nil {
return nil, fmt.Errorf("could not create ssl manager: %w", err)
}
@ -307,13 +317,3 @@ func createSDKClient(accessKeyId, accessKeySecret, region string) (*alislb.Clien
return client, nil
}
func createSSLManager(accessKeyId, accessKeySecret, resourceGroupId, region string) (core.SSLManager, error) {
sslmgr, err := sslmgrsp.NewSSLManagerProvider(&sslmgrsp.SSLManagerProviderConfig{
AccessKeyId: accessKeyId,
AccessKeySecret: accessKeySecret,
ResourceGroupId: resourceGroupId,
Region: region,
})
return sslmgr, err
}

View File

@ -14,6 +14,7 @@ import (
"github.com/certimate-go/certimate/pkg/core"
sslmgrsp "github.com/certimate-go/certimate/pkg/core/ssl-manager/providers/aliyun-slb"
"github.com/certimate-go/certimate/pkg/utils/ifelse"
)
type SSLDeployerProviderConfig struct {
@ -48,7 +49,15 @@ func NewSSLDeployerProvider(config *SSLDeployerProviderConfig) (*SSLDeployerProv
return nil, fmt.Errorf("could not create sdk client: %w", err)
}
sslmgr, err := createSSLManager(config.AccessKeyId, config.AccessKeySecret, config.ResourceGroupId, config.Region)
sslmgr, err := sslmgrsp.NewSSLManagerProvider(&sslmgrsp.SSLManagerProviderConfig{
AccessKeyId: config.AccessKeyId,
AccessKeySecret: config.AccessKeySecret,
ResourceGroupId: config.ResourceGroupId,
Region: ifelse.
If[string](config.Region == "" || strings.HasPrefix(config.Region, "cn-")).
Then("cn-hangzhou").
Else("ap-southeast-1"),
})
if err != nil {
return nil, fmt.Errorf("could not create ssl manager: %w", err)
}
@ -102,10 +111,18 @@ func (d *SSLDeployerProvider) Deploy(ctx context.Context, certPEM string, privke
func createSDKClient(accessKeyId, accessKeySecret, region string) (*aliddos.Client, error) {
// 接入点一览 https://api.aliyun.com/product/ddoscoo
var endpoint string
switch region {
case "":
endpoint = "ddoscoo.cn-hangzhou.aliyuncs.com"
default:
endpoint = fmt.Sprintf("ddoscoo.%s.aliyuncs.com", region)
}
config := &aliopen.Config{
AccessKeyId: tea.String(accessKeyId),
AccessKeySecret: tea.String(accessKeySecret),
Endpoint: tea.String(strings.ReplaceAll(fmt.Sprintf("ddoscoo.%s.aliyuncs.com", region), "..", ".")),
Endpoint: tea.String(endpoint),
}
client, err := aliddos.NewClient(config)
@ -115,25 +132,3 @@ func createSDKClient(accessKeyId, accessKeySecret, region string) (*aliddos.Clie
return client, nil
}
func createSSLManager(accessKeyId, accessKeySecret, resourceGroupId, region string) (core.SSLManager, error) {
casRegion := region
if casRegion != "" {
// 阿里云 CAS 服务接入点是独立于 Anti-DDoS 服务的
// 国内版固定接入点:华东一杭州
// 国际版固定接入点:亚太东南一新加坡
if !strings.HasPrefix(casRegion, "cn-") {
casRegion = "ap-southeast-1"
} else {
casRegion = "cn-hangzhou"
}
}
sslmgr, err := sslmgrsp.NewSSLManagerProvider(&sslmgrsp.SSLManagerProviderConfig{
AccessKeyId: accessKeyId,
AccessKeySecret: accessKeySecret,
ResourceGroupId: resourceGroupId,
Region: casRegion,
})
return sslmgr, err
}

View File

@ -14,6 +14,7 @@ import (
"github.com/certimate-go/certimate/pkg/core"
sslmgrsp "github.com/certimate-go/certimate/pkg/core/ssl-manager/providers/aliyun-cas"
"github.com/certimate-go/certimate/pkg/utils/ifelse"
)
type SSLDeployerProviderConfig struct {
@ -48,7 +49,15 @@ func NewSSLDeployerProvider(config *SSLDeployerProviderConfig) (*SSLDeployerProv
return nil, fmt.Errorf("could not create sdk client: %w", err)
}
sslmgr, err := createSSLManager(config.AccessKeyId, config.AccessKeySecret, config.ResourceGroupId, config.Region)
sslmgr, err := sslmgrsp.NewSSLManagerProvider(&sslmgrsp.SSLManagerProviderConfig{
AccessKeyId: config.AccessKeyId,
AccessKeySecret: config.AccessKeySecret,
ResourceGroupId: config.ResourceGroupId,
Region: ifelse.
If[string](config.Region == "" || strings.HasPrefix(config.Region, "cn-")).
Then("cn-hangzhou").
Else("ap-southeast-1"),
})
if err != nil {
return nil, fmt.Errorf("could not create ssl manager: %w", err)
}
@ -103,10 +112,18 @@ func (d *SSLDeployerProvider) Deploy(ctx context.Context, certPEM string, privke
func createSDKClient(accessKeyId, accessKeySecret, region string) (*aliesa.Client, error) {
// 接入点一览 https://api.aliyun.com/product/ESA
var endpoint string
switch region {
case "":
endpoint = "esa.cn-hangzhou.aliyuncs.com"
default:
endpoint = fmt.Sprintf("esa.%s.aliyuncs.com", region)
}
config := &aliopen.Config{
AccessKeyId: tea.String(accessKeyId),
AccessKeySecret: tea.String(accessKeySecret),
Endpoint: tea.String(strings.ReplaceAll(fmt.Sprintf("esa.%s.aliyuncs.com", region), "..", ".")),
Endpoint: tea.String(endpoint),
}
client, err := aliesa.NewClient(config)
@ -116,25 +133,3 @@ func createSDKClient(accessKeyId, accessKeySecret, region string) (*aliesa.Clien
return client, nil
}
func createSSLManager(accessKeyId, accessKeySecret, resourceGroupId, region string) (core.SSLManager, error) {
casRegion := region
if casRegion != "" {
// 阿里云 CAS 服务接入点是独立于 ESA 服务的
// 国内版固定接入点:华东一杭州
// 国际版固定接入点:亚太东南一新加坡
if !strings.HasPrefix(casRegion, "cn-") {
casRegion = "ap-southeast-1"
} else {
casRegion = "cn-hangzhou"
}
}
sslmgr, err := sslmgrsp.NewSSLManagerProvider(&sslmgrsp.SSLManagerProviderConfig{
AccessKeyId: accessKeyId,
AccessKeySecret: accessKeySecret,
ResourceGroupId: resourceGroupId,
Region: casRegion,
})
return sslmgr, err
}

View File

@ -5,7 +5,6 @@ import (
"errors"
"fmt"
"log/slog"
"strings"
"time"
aliopen "github.com/alibabacloud-go/darabonba-openapi/v2/client"
@ -184,8 +183,17 @@ func createSDKClients(accessKeyId, accessKeySecret, region string) (*wSDKClients
return nil, err
}
// 接入点一览 https://api.aliyun.com/product/FC-Open
fc3Endpoint := strings.ReplaceAll(fmt.Sprintf("fcv3.%s.aliyuncs.com", region), "..", ".")
// 接入点一览 https://api.aliyun.com/product/FC
var fc3Endpoint string
switch region {
case "":
fc3Endpoint = "fcv3.cn-hangzhou.aliyuncs.com"
case "me-central-1", "cn-hangzhou-finance", "cn-shanghai-finance-1", "cn-heyuan-acdr-1":
fc3Endpoint = fmt.Sprintf("%s.fc.aliyuncs.com", region)
default:
fc3Endpoint = fmt.Sprintf("fcv3.%s.aliyuncs.com", region)
}
fc3Config := &aliopen.Config{
AccessKeyId: tea.String(accessKeyId),
AccessKeySecret: tea.String(accessKeySecret),

View File

@ -54,7 +54,12 @@ func NewSSLDeployerProvider(config *SSLDeployerProviderConfig) (*SSLDeployerProv
return nil, fmt.Errorf("could not create sdk client: %w", err)
}
sslmgr, err := createSSLManager(config.AccessKeyId, config.AccessKeySecret, config.ResourceGroupId)
sslmgr, err := sslmgrsp.NewSSLManagerProvider(&sslmgrsp.SSLManagerProviderConfig{
AccessKeyId: config.AccessKeyId,
AccessKeySecret: config.AccessKeySecret,
ResourceGroupId: config.ResourceGroupId,
Region: "cn-hangzhou",
})
if err != nil {
return nil, fmt.Errorf("could not create ssl manager: %w", err)
}
@ -313,13 +318,3 @@ func createSDKClient(accessKeyId, accessKeySecret string) (*aliga.Client, error)
return client, nil
}
func createSSLManager(accessKeyId, accessKeySecret, resourceGroupId string) (core.SSLManager, error) {
sslmgr, err := sslmgrsp.NewSSLManagerProvider(&sslmgrsp.SSLManagerProviderConfig{
AccessKeyId: accessKeyId,
AccessKeySecret: accessKeySecret,
ResourceGroupId: resourceGroupId,
Region: "cn-hangzhou",
})
return sslmgr, err
}

View File

@ -13,6 +13,7 @@ import (
"github.com/certimate-go/certimate/pkg/core"
sslmgrsp "github.com/certimate-go/certimate/pkg/core/ssl-manager/providers/aliyun-cas"
"github.com/certimate-go/certimate/pkg/utils/ifelse"
)
type SSLDeployerProviderConfig struct {
@ -53,7 +54,15 @@ func NewSSLDeployerProvider(config *SSLDeployerProviderConfig) (*SSLDeployerProv
return nil, fmt.Errorf("could not create sdk client: %w", err)
}
sslmgr, err := createSSLManager(config.AccessKeyId, config.AccessKeySecret, config.ResourceGroupId, config.Region)
sslmgr, err := sslmgrsp.NewSSLManagerProvider(&sslmgrsp.SSLManagerProviderConfig{
AccessKeyId: config.AccessKeyId,
AccessKeySecret: config.AccessKeySecret,
ResourceGroupId: config.ResourceGroupId,
Region: ifelse.
If[string](config.Region == "" || strings.HasPrefix(config.Region, "cn-")).
Then("cn-hangzhou").
Else("ap-southeast-1"),
})
if err != nil {
return nil, fmt.Errorf("could not create ssl manager: %w", err)
}
@ -225,7 +234,14 @@ func (d *SSLDeployerProvider) updateListenerCertificate(ctx context.Context, clo
func createSDKClient(accessKeyId, accessKeySecret, region string) (*alinlb.Client, error) {
// 接入点一览 https://api.aliyun.com/product/Nlb
endpoint := strings.ReplaceAll(fmt.Sprintf("nlb.%s.aliyuncs.com", region), "..", ".")
var endpoint string
switch region {
case "":
endpoint = "nlb.cn-hangzhou.aliyuncs.com"
default:
endpoint = fmt.Sprintf("nlb.%s.aliyuncs.com", region)
}
config := &aliopen.Config{
AccessKeyId: tea.String(accessKeyId),
AccessKeySecret: tea.String(accessKeySecret),
@ -239,25 +255,3 @@ func createSDKClient(accessKeyId, accessKeySecret, region string) (*alinlb.Clien
return client, nil
}
func createSSLManager(accessKeyId, accessKeySecret, resourceGroupId, region string) (core.SSLManager, error) {
casRegion := region
if casRegion != "" {
// 阿里云 CAS 服务接入点是独立于 NLB 服务的
// 国内版固定接入点:华东一杭州
// 国际版固定接入点:亚太东南一新加坡
if !strings.HasPrefix(casRegion, "cn-") {
casRegion = "ap-southeast-1"
} else {
casRegion = "cn-hangzhou"
}
}
sslmgr, err := sslmgrsp.NewSSLManagerProvider(&sslmgrsp.SSLManagerProviderConfig{
AccessKeyId: accessKeyId,
AccessKeySecret: accessKeySecret,
ResourceGroupId: resourceGroupId,
Region: casRegion,
})
return sslmgr, err
}

View File

@ -5,7 +5,6 @@ import (
"errors"
"fmt"
"log/slog"
"strings"
"time"
aliopen "github.com/alibabacloud-go/darabonba-openapi/v2/client"
@ -86,7 +85,14 @@ func (d *SSLDeployerProvider) Deploy(ctx context.Context, certPEM string, privke
func createSDKClient(accessKeyId, accessKeySecret, region string) (*alivod.Client, error) {
// 接入点一览 https://api.aliyun.com/product/vod
endpoint := strings.ReplaceAll(fmt.Sprintf("vod.%s.aliyuncs.com", region), "..", ".")
var endpoint string
switch region {
case "":
endpoint = "vod.cn-hangzhou.aliyuncs.com"
default:
endpoint = fmt.Sprintf("vod.%s.aliyuncs.com", region)
}
config := &aliopen.Config{
AccessKeyId: tea.String(accessKeyId),
AccessKeySecret: tea.String(accessKeySecret),

View File

@ -13,6 +13,7 @@ import (
"github.com/certimate-go/certimate/pkg/core"
sslmgrsp "github.com/certimate-go/certimate/pkg/core/ssl-manager/providers/aliyun-cas"
"github.com/certimate-go/certimate/pkg/utils/ifelse"
xslices "github.com/certimate-go/certimate/pkg/utils/slices"
xtypes "github.com/certimate-go/certimate/pkg/utils/types"
)
@ -53,7 +54,15 @@ func NewSSLDeployerProvider(config *SSLDeployerProviderConfig) (*SSLDeployerProv
return nil, fmt.Errorf("could not create sdk client: %w", err)
}
sslmgr, err := createSSLManager(config.AccessKeyId, config.AccessKeySecret, config.ResourceGroupId, config.Region)
sslmgr, err := sslmgrsp.NewSSLManagerProvider(&sslmgrsp.SSLManagerProviderConfig{
AccessKeyId: config.AccessKeyId,
AccessKeySecret: config.AccessKeySecret,
ResourceGroupId: config.ResourceGroupId,
Region: ifelse.
If[string](config.Region == "" || strings.HasPrefix(config.Region, "cn-")).
Then("cn-hangzhou").
Else("ap-southeast-1"),
})
if err != nil {
return nil, fmt.Errorf("could not create ssl manager: %w", err)
}
@ -176,7 +185,14 @@ func (d *SSLDeployerProvider) deployToWAF3(ctx context.Context, certPEM string,
func createSDKClient(accessKeyId, accessKeySecret, region string) (*aliwaf.Client, error) {
// 接入点一览https://api.aliyun.com/product/waf-openapi
endpoint := strings.ReplaceAll(fmt.Sprintf("wafopenapi.%s.aliyuncs.com", region), "..", ".")
var endpoint string
switch region {
case "":
endpoint = "wafopenapi.cn-hangzhou.aliyuncs.com"
default:
endpoint = fmt.Sprintf("wafopenapi.%s.aliyuncs.com", region)
}
config := &aliopen.Config{
AccessKeyId: tea.String(accessKeyId),
AccessKeySecret: tea.String(accessKeySecret),
@ -191,28 +207,6 @@ func createSDKClient(accessKeyId, accessKeySecret, region string) (*aliwaf.Clien
return client, nil
}
func createSSLManager(accessKeyId, accessKeySecret, resourceGroupId, region string) (core.SSLManager, error) {
casRegion := region
if casRegion != "" {
// 阿里云 CAS 服务接入点是独立于 WAF 服务的
// 国内版固定接入点:华东一杭州
// 国际版固定接入点:亚太东南一新加坡
if !strings.HasPrefix(casRegion, "cn-") {
casRegion = "ap-southeast-1"
} else {
casRegion = "cn-hangzhou"
}
}
sslmgr, err := sslmgrsp.NewSSLManagerProvider(&sslmgrsp.SSLManagerProviderConfig{
AccessKeyId: accessKeyId,
AccessKeySecret: accessKeySecret,
ResourceGroupId: resourceGroupId,
Region: casRegion,
})
return sslmgr, err
}
func assign(source *aliwaf.ModifyDomainRequest, target *aliwaf.DescribeDomainDetailResponseBody) *aliwaf.ModifyDomainRequest {
// `ModifyDomain` 中不传的字段表示使用默认值、而非保留原值,
// 因此这里需要把原配置中的参数重新赋值回去。

View File

@ -102,7 +102,7 @@ func (d *SSLDeployerProvider) Deploy(ctx context.Context, certPEM string, privke
if err != nil {
return nil, fmt.Errorf("failed to execute sdk request 'baishan.GetDomainConfig': %w", err)
} else if len(getDomainConfigResp.Data) == 0 {
return nil, errors.New("domain config not found")
return nil, fmt.Errorf("domain %s not found", d.config.Domain)
}
// 设置域名配置

View File

@ -6,16 +6,15 @@ import (
"fmt"
"log/slog"
"strings"
"time"
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"
"golang.org/x/exp/slices"
"github.com/certimate-go/certimate/pkg/core"
sslmgrsp "github.com/certimate-go/certimate/pkg/core/ssl-manager/providers/tencentcloud-ssl"
"github.com/certimate-go/certimate/pkg/utils/ifelse"
)
type SSLDeployerProviderConfig struct {
@ -23,6 +22,8 @@ type SSLDeployerProviderConfig struct {
SecretId string `json:"secretId"`
// 腾讯云 SecretKey。
SecretKey string `json:"secretKey"`
// 腾讯云接口端点。
Endpoint string `json:"endpoint,omitempty"`
// 加速域名(支持泛域名)。
Domain string `json:"domain"`
}
@ -30,7 +31,7 @@ type SSLDeployerProviderConfig struct {
type SSLDeployerProvider struct {
config *SSLDeployerProviderConfig
logger *slog.Logger
sdkClients *wSDKClients
sdkClient *tccdn.Client
sslManager core.SSLManager
}
@ -46,7 +47,7 @@ func NewSSLDeployerProvider(config *SSLDeployerProviderConfig) (*SSLDeployerProv
return nil, errors.New("the configuration of the ssl deployer provider is nil")
}
clients, err := createSDKClients(config.SecretId, config.SecretKey)
client, err := createSDKClient(config.SecretId, config.SecretKey, config.Endpoint)
if err != nil {
return nil, fmt.Errorf("could not create sdk client: %w", err)
}
@ -54,6 +55,10 @@ func NewSSLDeployerProvider(config *SSLDeployerProviderConfig) (*SSLDeployerProv
sslmgr, err := sslmgrsp.NewSSLManagerProvider(&sslmgrsp.SSLManagerProviderConfig{
SecretId: config.SecretId,
SecretKey: config.SecretKey,
Endpoint: ifelse.
If[string](strings.HasSuffix(strings.TrimSpace(config.Endpoint), "intl.tencentcloudapi.com")).
Then("ssl.intl.tencentcloudapi.com"). // 国际站使用独立的接口端点
Else(""),
})
if err != nil {
return nil, fmt.Errorf("could not create ssl manager: %w", err)
@ -62,7 +67,7 @@ func NewSSLDeployerProvider(config *SSLDeployerProviderConfig) (*SSLDeployerProv
return &SSLDeployerProvider{
config: config,
logger: slog.Default(),
sdkClients: clients,
sdkClient: client,
sslManager: sslmgr,
}, nil
}
@ -92,106 +97,51 @@ func (d *SSLDeployerProvider) Deploy(ctx context.Context, certPEM string, privke
// 获取待部署的 CDN 实例
// 如果是泛域名,根据证书匹配 CDN 实例
instanceIds := make([]string, 0)
domains := make([]string, 0)
if strings.HasPrefix(d.config.Domain, "*.") {
domains, err := d.getDomainsByCertificateId(upres.CertId)
temp, err := d.getDomainsByCertId(ctx, upres.CertId)
if err != nil {
return nil, err
}
instanceIds = domains
domains = temp
} else {
instanceIds = append(instanceIds, d.config.Domain)
domains = append(domains, d.config.Domain)
}
// 跳过已部署的 CDN 实例
if len(instanceIds) > 0 {
deployedDomains, err := d.getDeployedDomainsByCertificateId(upres.CertId)
if err != nil {
return nil, err
}
temp := make([]string, 0)
for _, instanceId := range instanceIds {
if !slices.Contains(deployedDomains, instanceId) {
temp = append(temp, instanceId)
}
}
instanceIds = temp
}
if len(instanceIds) == 0 {
d.logger.Info("no cdn instances to deploy")
// 遍历更新域名证书
if len(domains) == 0 {
d.logger.Info("no cdn domains to deploy")
} else {
d.logger.Info("found cdn instances to deploy", slog.Any("instanceIds", instanceIds))
d.logger.Info("found cdn domains to deploy", slog.Any("domains", domains))
var errs []error
// 证书部署到 CDN 实例
// REF: https://cloud.tencent.com/document/product/400/91667
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)
d.logger.Debug("sdk request 'ssl.DeployCertificateInstance'", slog.Any("request", deployCertificateInstanceReq), slog.Any("response", deployCertificateInstanceResp))
if err != nil {
return nil, fmt.Errorf("failed to execute sdk request 'ssl.DeployCertificateInstance': %w", err)
}
// 循环获取部署任务详情,等待任务状态变更
// REF: https://cloud.tencent.com/document/api/400/91658
for {
for _, domain := range domains {
select {
case <-ctx.Done():
return nil, ctx.Err()
default:
}
describeHostDeployRecordDetailReq := tcssl.NewDescribeHostDeployRecordDetailRequest()
describeHostDeployRecordDetailReq.DeployRecordId = common.StringPtr(fmt.Sprintf("%d", *deployCertificateInstanceResp.Response.DeployRecordId))
describeHostDeployRecordDetailResp, err := d.sdkClients.SSL.DescribeHostDeployRecordDetail(describeHostDeployRecordDetailReq)
d.logger.Debug("sdk request 'ssl.DescribeHostDeployRecordDetail'", slog.Any("request", describeHostDeployRecordDetailReq), slog.Any("response", describeHostDeployRecordDetailResp))
if err != nil {
return nil, fmt.Errorf("failed to execute sdk request 'ssl.DescribeHostDeployRecordDetail': %w", err)
}
var runningCount, succeededCount, failedCount, totalCount int64
if describeHostDeployRecordDetailResp.Response.TotalCount == nil {
return nil, errors.New("unexpected deployment job status")
} else {
if describeHostDeployRecordDetailResp.Response.RunningTotalCount != nil {
runningCount = *describeHostDeployRecordDetailResp.Response.RunningTotalCount
}
if describeHostDeployRecordDetailResp.Response.SuccessTotalCount != nil {
succeededCount = *describeHostDeployRecordDetailResp.Response.SuccessTotalCount
}
if describeHostDeployRecordDetailResp.Response.FailedTotalCount != nil {
failedCount = *describeHostDeployRecordDetailResp.Response.FailedTotalCount
}
if describeHostDeployRecordDetailResp.Response.TotalCount != nil {
totalCount = *describeHostDeployRecordDetailResp.Response.TotalCount
}
if succeededCount+failedCount == totalCount {
break
if err := d.updateDomainHttpsServerCert(ctx, domain, upres.CertId); err != nil {
errs = append(errs, err)
}
}
}
d.logger.Info(fmt.Sprintf("waiting for deployment job completion (running: %d, succeeded: %d, failed: %d, total: %d) ...", runningCount, succeededCount, failedCount, totalCount))
time.Sleep(time.Second * 5)
if len(errs) > 0 {
return nil, errors.Join(errs...)
}
}
return &core.SSLDeployResult{}, nil
}
func (d *SSLDeployerProvider) getDomainsByCertificateId(cloudCertId string) ([]string, error) {
func (d *SSLDeployerProvider) getDomainsByCertId(ctx context.Context, cloudCertId string) ([]string, error) {
// 获取证书中的可用域名
// REF: https://cloud.tencent.com/document/product/228/42491
// REF: https://cloud.tencent.com/document/api/228/42491
describeCertDomainsReq := tccdn.NewDescribeCertDomainsRequest()
describeCertDomainsReq.CertId = common.StringPtr(cloudCertId)
describeCertDomainsReq.Product = common.StringPtr("cdn")
describeCertDomainsResp, err := d.sdkClients.CDN.DescribeCertDomains(describeCertDomainsReq)
describeCertDomainsResp, err := d.sdkClient.DescribeCertDomains(describeCertDomainsReq)
d.logger.Debug("sdk request 'cdn.DescribeCertDomains'", slog.Any("request", describeCertDomainsReq), slog.Any("response", describeCertDomainsResp))
if err != nil {
return nil, fmt.Errorf("failed to execute sdk request 'cdn.DescribeCertDomains': %w", err)
@ -207,45 +157,68 @@ func (d *SSLDeployerProvider) getDomainsByCertificateId(cloudCertId string) ([]s
return domains, nil
}
func (d *SSLDeployerProvider) getDeployedDomainsByCertificateId(cloudCertId string) ([]string, error) {
// 根据证书查询关联资源
// REF: https://cloud.tencent.com/document/product/400/62674
describeDeployedResourcesReq := tcssl.NewDescribeDeployedResourcesRequest()
describeDeployedResourcesReq.CertificateIds = common.StringPtrs([]string{cloudCertId})
describeDeployedResourcesReq.ResourceType = common.StringPtr("cdn")
describeDeployedResourcesResp, err := d.sdkClients.SSL.DescribeDeployedResources(describeDeployedResourcesReq)
d.logger.Debug("sdk request 'cdn.DescribeDeployedResources'", slog.Any("request", describeDeployedResourcesReq), slog.Any("response", describeDeployedResourcesResp))
func (d *SSLDeployerProvider) updateDomainHttpsServerCert(ctx context.Context, domain string, cloudCertId string) error {
// 查询域名详细配置
// REF: https://cloud.tencent.com/document/api/228/41117
describeDomainsConfigReq := tccdn.NewDescribeDomainsConfigRequest()
describeDomainsConfigReq.Filters = []*tccdn.DomainFilter{
{
Name: common.StringPtr("domain"),
Value: common.StringPtrs([]string{domain}),
},
}
describeDomainsConfigReq.Offset = common.Int64Ptr(0)
describeDomainsConfigReq.Limit = common.Int64Ptr(1)
describeDomainsConfigResp, err := d.sdkClient.DescribeDomainsConfig(describeDomainsConfigReq)
d.logger.Debug("sdk request 'cdn.DescribeDomainsConfig'", slog.Any("request", describeDomainsConfigReq), slog.Any("response", describeDomainsConfigResp))
if err != nil {
return nil, fmt.Errorf("failed to execute sdk request 'cdn.DescribeDeployedResources': %w", err)
return fmt.Errorf("failed to execute sdk request 'cdn.DescribeDomainsConfig': %w", err)
} else if len(describeDomainsConfigResp.Response.Domains) == 0 {
return fmt.Errorf("domain %s not found", domain)
}
domains := make([]string, 0)
if describeDeployedResourcesResp.Response.DeployedResources != nil {
for _, deployedResource := range describeDeployedResourcesResp.Response.DeployedResources {
for _, resource := range deployedResource.Resources {
domains = append(domains, *resource)
}
domainConfig := describeDomainsConfigResp.Response.Domains[0]
if domainConfig.Https != nil && domainConfig.Https.CertInfo != nil && domainConfig.Https.CertInfo.CertId != nil && *domainConfig.Https.CertInfo.CertId == cloudCertId {
// 已部署过此域名,跳过
return nil
}
// 更新加速域名配置
// REF: https://cloud.tencent.com/document/api/228/41116
updateDomainConfigReq := tccdn.NewUpdateDomainConfigRequest()
updateDomainConfigReq.Domain = common.StringPtr(domain)
updateDomainConfigReq.Https = domainConfig.Https
if updateDomainConfigReq.Https == nil {
updateDomainConfigReq.Https = &tccdn.Https{
Switch: common.StringPtr("on"),
}
} else {
updateDomainConfigReq.Https.SslStatus = nil
}
updateDomainConfigReq.Https.CertInfo = &tccdn.ServerCert{
CertId: common.StringPtr(cloudCertId),
}
updateDomainConfigResp, err := d.sdkClient.UpdateDomainConfig(updateDomainConfigReq)
d.logger.Debug("sdk request 'cdn.UpdateDomainConfig'", slog.Any("request", updateDomainConfigReq), slog.Any("response", updateDomainConfigResp))
if err != nil {
return fmt.Errorf("failed to execute sdk request 'cdn.UpdateDomainConfig': %w", err)
}
return domains, nil
return nil
}
func createSDKClients(secretId, secretKey string) (*wSDKClients, error) {
func createSDKClient(secretId, secretKey, endpoint string) (*tccdn.Client, error) {
credential := common.NewCredential(secretId, secretKey)
sslClient, err := tcssl.NewClient(credential, "", profile.NewClientProfile())
cpf := profile.NewClientProfile()
if endpoint != "" {
cpf.HttpProfile.Endpoint = endpoint
}
client, err := tccdn.NewClient(credential, "", cpf)
if err != nil {
return nil, err
}
cdnClient, err := tccdn.NewClient(credential, "", profile.NewClientProfile())
if err != nil {
return nil, err
}
return &wSDKClients{
SSL: sslClient,
CDN: cdnClient,
}, nil
return client, nil
}

View File

@ -5,6 +5,7 @@ import (
"errors"
"fmt"
"log/slog"
"strings"
"time"
tcclb "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/clb/v20180317"
@ -14,6 +15,7 @@ import (
"github.com/certimate-go/certimate/pkg/core"
sslmgrsp "github.com/certimate-go/certimate/pkg/core/ssl-manager/providers/tencentcloud-ssl"
"github.com/certimate-go/certimate/pkg/utils/ifelse"
)
type SSLDeployerProviderConfig struct {
@ -21,6 +23,8 @@ type SSLDeployerProviderConfig struct {
SecretId string `json:"secretId"`
// 腾讯云 SecretKey。
SecretKey string `json:"secretKey"`
// 腾讯云接口端点。
Endpoint string `json:"endpoint,omitempty"`
// 腾讯云地域。
Region string `json:"region"`
// 部署资源类型。
@ -55,7 +59,7 @@ func NewSSLDeployerProvider(config *SSLDeployerProviderConfig) (*SSLDeployerProv
return nil, errors.New("the configuration of the ssl deployer provider is nil")
}
clients, err := createSDKClients(config.SecretId, config.SecretKey, config.Region)
clients, err := createSDKClients(config.SecretId, config.SecretKey, config.Endpoint, config.Region)
if err != nil {
return nil, fmt.Errorf("could not create sdk client: %w", err)
}
@ -63,6 +67,10 @@ func NewSSLDeployerProvider(config *SSLDeployerProviderConfig) (*SSLDeployerProv
sslmgr, err := sslmgrsp.NewSSLManagerProvider(&sslmgrsp.SSLManagerProviderConfig{
SecretId: config.SecretId,
SecretKey: config.SecretKey,
Endpoint: ifelse.
If[string](strings.HasSuffix(strings.TrimSpace(config.Endpoint), "intl.tencentcloudapi.com")).
Then("ssl.intl.tencentcloudapi.com"). // 国际站使用独立的接口端点
Else(""),
})
if err != nil {
return nil, fmt.Errorf("could not create ssl manager: %w", err)
@ -133,7 +141,7 @@ func (d *SSLDeployerProvider) deployViaSslService(ctx context.Context, cloudCert
}
// 证书部署到 CLB 实例
// REF: https://cloud.tencent.com/document/product/400/91667
// REF: https://cloud.tencent.com/document/api/400/91667
deployCertificateInstanceReq := tcssl.NewDeployCertificateInstanceRequest()
deployCertificateInstanceReq.CertificateId = common.StringPtr(cloudCertId)
deployCertificateInstanceReq.ResourceType = common.StringPtr("clb")
@ -306,11 +314,11 @@ func (d *SSLDeployerProvider) modifyListenerCertificate(ctx context.Context, clo
if err != nil {
return fmt.Errorf("failed to execute sdk request 'clb.DescribeListeners': %w", err)
} else if len(describeListenersResp.Response.Listeners) == 0 {
return errors.New("listener not found")
return fmt.Errorf("listener %s not found", cloudListenerId)
}
// 修改监听器属性
// REF: https://cloud.tencent.com/document/product/214/30681
// REF: https://cloud.tencent.com/document/api/214/30681
modifyListenerReq := tcclb.NewModifyListenerRequest()
modifyListenerReq.LoadBalancerId = common.StringPtr(cloudLoadbalancerId)
modifyListenerReq.ListenerId = common.StringPtr(cloudListenerId)
@ -330,16 +338,28 @@ func (d *SSLDeployerProvider) modifyListenerCertificate(ctx context.Context, clo
return nil
}
func createSDKClients(secretId, secretKey, region string) (*wSDKClients, error) {
func createSDKClients(secretId, secretKey, endpoint, region string) (*wSDKClients, error) {
credential := common.NewCredential(secretId, secretKey)
sslCpf := profile.NewClientProfile()
if endpoint != "" {
if strings.HasSuffix(endpoint, "intl.tencentcloudapi.com") {
sslCpf.HttpProfile.Endpoint = "ssl.intl.tencentcloudapi.com"
}
}
// 注意虽然官方文档中地域无需指定,但实际需要部署到 CLB 时必传
sslClient, err := tcssl.NewClient(credential, region, profile.NewClientProfile())
sslClient, err := tcssl.NewClient(credential, region, sslCpf)
if err != nil {
return nil, err
}
clbClient, err := tcclb.NewClient(credential, region, profile.NewClientProfile())
clbCpf := profile.NewClientProfile()
if endpoint != "" {
clbCpf.HttpProfile.Endpoint = endpoint
}
clbClient, err := tcclb.NewClient(credential, region, clbCpf)
if err != nil {
return nil, err
}

View File

@ -31,18 +31,22 @@ type SSLDeployerProviderConfig struct {
type SSLDeployerProvider struct {
config *SSLDeployerProviderConfig
logger *slog.Logger
sdkClient *tcssl.Client
sdkClient *wSDKClients
sslManager core.SSLManager
}
var _ core.SSLDeployer = (*SSLDeployerProvider)(nil)
type wSDKClients struct {
SSL *tcssl.Client
}
func NewSSLDeployerProvider(config *SSLDeployerProviderConfig) (*SSLDeployerProvider, error) {
if config == nil {
return nil, errors.New("the configuration of the ssl deployer provider is nil")
}
client, err := createSDKClient(config.SecretId, config.SecretKey, config.Region)
clients, err := createSDKClients(config.SecretId, config.SecretKey, config.Region)
if err != nil {
return nil, fmt.Errorf("could not create sdk client: %w", err)
}
@ -58,7 +62,7 @@ func NewSSLDeployerProvider(config *SSLDeployerProviderConfig) (*SSLDeployerProv
return &SSLDeployerProvider{
config: config,
logger: slog.Default(),
sdkClient: client,
sdkClient: clients,
sslManager: sslmgr,
}, nil
}
@ -90,13 +94,13 @@ func (d *SSLDeployerProvider) Deploy(ctx context.Context, certPEM string, privke
}
// 证书部署到 COS 实例
// REF: https://cloud.tencent.com/document/product/400/91667
// REF: https://cloud.tencent.com/document/api/400/91667
deployCertificateInstanceReq := tcssl.NewDeployCertificateInstanceRequest()
deployCertificateInstanceReq.CertificateId = common.StringPtr(upres.CertId)
deployCertificateInstanceReq.ResourceType = common.StringPtr("cos")
deployCertificateInstanceReq.Status = common.Int64Ptr(1)
deployCertificateInstanceReq.InstanceIdList = common.StringPtrs([]string{fmt.Sprintf("%s#%s#%s", d.config.Region, d.config.Bucket, d.config.Domain)})
deployCertificateInstanceResp, err := d.sdkClient.DeployCertificateInstance(deployCertificateInstanceReq)
deployCertificateInstanceResp, err := d.sdkClient.SSL.DeployCertificateInstance(deployCertificateInstanceReq)
d.logger.Debug("sdk request 'ssl.DeployCertificateInstance'", slog.Any("request", deployCertificateInstanceReq), slog.Any("response", deployCertificateInstanceResp))
if err != nil {
return nil, fmt.Errorf("failed to execute sdk request 'ssl.DeployCertificateInstance': %w", err)
@ -113,7 +117,7 @@ func (d *SSLDeployerProvider) Deploy(ctx context.Context, certPEM string, privke
describeHostDeployRecordDetailReq := tcssl.NewDescribeHostDeployRecordDetailRequest()
describeHostDeployRecordDetailReq.DeployRecordId = common.StringPtr(fmt.Sprintf("%d", *deployCertificateInstanceResp.Response.DeployRecordId))
describeHostDeployRecordDetailResp, err := d.sdkClient.DescribeHostDeployRecordDetail(describeHostDeployRecordDetailReq)
describeHostDeployRecordDetailResp, err := d.sdkClient.SSL.DescribeHostDeployRecordDetail(describeHostDeployRecordDetailReq)
d.logger.Debug("sdk request 'ssl.DescribeHostDeployRecordDetail'", slog.Any("request", describeHostDeployRecordDetailReq), slog.Any("response", describeHostDeployRecordDetailResp))
if err != nil {
return nil, fmt.Errorf("failed to execute sdk request 'ssl.DescribeHostDeployRecordDetail': %w", err)
@ -148,12 +152,14 @@ func (d *SSLDeployerProvider) Deploy(ctx context.Context, certPEM string, privke
return &core.SSLDeployResult{}, nil
}
func createSDKClient(secretId, secretKey, region string) (*tcssl.Client, error) {
func createSDKClients(secretId, secretKey, region string) (*wSDKClients, error) {
credential := common.NewCredential(secretId, secretKey)
client, err := tcssl.NewClient(credential, region, profile.NewClientProfile())
if err != nil {
return nil, err
}
return client, nil
return &wSDKClients{
SSL: client,
}, nil
}

View File

@ -5,6 +5,7 @@ import (
"errors"
"fmt"
"log/slog"
"strings"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile"
@ -12,6 +13,7 @@ import (
"github.com/certimate-go/certimate/pkg/core"
sslmgrsp "github.com/certimate-go/certimate/pkg/core/ssl-manager/providers/tencentcloud-ssl"
"github.com/certimate-go/certimate/pkg/utils/ifelse"
)
type SSLDeployerProviderConfig struct {
@ -19,6 +21,8 @@ type SSLDeployerProviderConfig struct {
SecretId string `json:"secretId"`
// 腾讯云 SecretKey。
SecretKey string `json:"secretKey"`
// 腾讯云接口端点。
Endpoint string `json:"endpoint,omitempty"`
// 直播播放域名(不支持泛域名)。
Domain string `json:"domain"`
}
@ -37,7 +41,7 @@ func NewSSLDeployerProvider(config *SSLDeployerProviderConfig) (*SSLDeployerProv
return nil, errors.New("the configuration of the ssl deployer provider is nil")
}
client, err := createSDKClient(config.SecretId, config.SecretKey)
client, err := createSDKClient(config.SecretId, config.SecretKey, config.Endpoint)
if err != nil {
return nil, fmt.Errorf("could not create sdk client: %w", err)
}
@ -45,6 +49,10 @@ func NewSSLDeployerProvider(config *SSLDeployerProviderConfig) (*SSLDeployerProv
sslmgr, err := sslmgrsp.NewSSLManagerProvider(&sslmgrsp.SSLManagerProviderConfig{
SecretId: config.SecretId,
SecretKey: config.SecretKey,
Endpoint: ifelse.
If[string](strings.HasSuffix(strings.TrimSpace(config.Endpoint), "intl.tencentcloudapi.com")).
Then("ssl.intl.tencentcloudapi.com"). // 国际站使用独立的接口端点
Else(""),
})
if err != nil {
return nil, fmt.Errorf("could not create ssl manager: %w", err)
@ -82,7 +90,7 @@ func (d *SSLDeployerProvider) Deploy(ctx context.Context, certPEM string, privke
}
// 绑定证书对应的播放域名
// REF: https://cloud.tencent.com/document/product/267/78655
// REF: https://cloud.tencent.com/document/api/267/78655
modifyLiveDomainCertBindingsReq := tclive.NewModifyLiveDomainCertBindingsRequest()
modifyLiveDomainCertBindingsReq.DomainInfos = []*tclive.LiveCertDomainInfo{
{
@ -100,10 +108,15 @@ func (d *SSLDeployerProvider) Deploy(ctx context.Context, certPEM string, privke
return &core.SSLDeployResult{}, nil
}
func createSDKClient(secretId, secretKey string) (*tclive.Client, error) {
func createSDKClient(secretId, secretKey, endpoint string) (*tclive.Client, error) {
credential := common.NewCredential(secretId, secretKey)
client, err := tclive.NewClient(credential, "", profile.NewClientProfile())
cpf := profile.NewClientProfile()
if endpoint != "" {
cpf.HttpProfile.Endpoint = endpoint
}
client, err := tclive.NewClient(credential, "", cpf)
if err != nil {
return nil, err
}

View File

@ -6,7 +6,6 @@ import (
"fmt"
"log/slog"
"strings"
"time"
tccdn "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cdn/v20180606"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
@ -15,6 +14,7 @@ import (
"github.com/certimate-go/certimate/pkg/core"
sslmgrsp "github.com/certimate-go/certimate/pkg/core/ssl-manager/providers/tencentcloud-ssl"
"github.com/certimate-go/certimate/pkg/utils/ifelse"
)
type SSLDeployerProviderConfig struct {
@ -22,6 +22,8 @@ type SSLDeployerProviderConfig struct {
SecretId string `json:"secretId"`
// 腾讯云 SecretKey。
SecretKey string `json:"secretKey"`
// 腾讯云接口端点。
Endpoint string `json:"endpoint,omitempty"`
// 加速域名(支持泛域名)。
Domain string `json:"domain"`
}
@ -29,7 +31,7 @@ type SSLDeployerProviderConfig struct {
type SSLDeployerProvider struct {
config *SSLDeployerProviderConfig
logger *slog.Logger
sdkClients *wSDKClients
sdkClient *tccdn.Client
sslManager core.SSLManager
}
@ -45,7 +47,7 @@ func NewSSLDeployerProvider(config *SSLDeployerProviderConfig) (*SSLDeployerProv
return nil, errors.New("the configuration of the ssl deployer provider is nil")
}
clients, err := createSDKClients(config.SecretId, config.SecretKey)
client, err := createSDKClient(config.SecretId, config.SecretKey, config.Endpoint)
if err != nil {
return nil, fmt.Errorf("could not create sdk client: %w", err)
}
@ -53,6 +55,10 @@ func NewSSLDeployerProvider(config *SSLDeployerProviderConfig) (*SSLDeployerProv
sslmgr, err := sslmgrsp.NewSSLManagerProvider(&sslmgrsp.SSLManagerProviderConfig{
SecretId: config.SecretId,
SecretKey: config.SecretKey,
Endpoint: ifelse.
If[string](strings.HasSuffix(strings.TrimSpace(config.Endpoint), "intl.tencentcloudapi.com")).
Then("ssl.intl.tencentcloudapi.com"). // 国际站使用独立的接口端点
Else(""),
})
if err != nil {
return nil, fmt.Errorf("could not create ssl manager: %w", err)
@ -61,7 +67,7 @@ func NewSSLDeployerProvider(config *SSLDeployerProviderConfig) (*SSLDeployerProv
return &SSLDeployerProvider{
config: config,
logger: slog.Default(),
sdkClients: clients,
sdkClient: client,
sslManager: sslmgr,
}, nil
}
@ -91,90 +97,51 @@ func (d *SSLDeployerProvider) Deploy(ctx context.Context, certPEM string, privke
// 获取待部署的 CDN 实例
// 如果是泛域名,根据证书匹配 CDN 实例
instanceIds := make([]string, 0)
domains := make([]string, 0)
if strings.HasPrefix(d.config.Domain, "*.") {
domains, err := d.getDomainsByCertificateId(upres.CertId)
temp, err := d.getDomainsByCertId(upres.CertId)
if err != nil {
return nil, err
}
instanceIds = domains
domains = temp
} else {
instanceIds = append(instanceIds, d.config.Domain)
domains = append(domains, d.config.Domain)
}
if len(instanceIds) == 0 {
d.logger.Info("no ecdn instances to deploy")
// 遍历更新域名证书
if len(domains) == 0 {
d.logger.Info("no ecdn domains to deploy")
} else {
d.logger.Info("found ecdn instances to deploy", slog.Any("instanceIds", instanceIds))
d.logger.Info("found ecdn domains to deploy", slog.Any("domains", domains))
var errs []error
// 证书部署到 CDN 实例
// REF: https://cloud.tencent.com/document/product/400/91667
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)
d.logger.Debug("sdk request 'ssl.DeployCertificateInstance'", slog.Any("request", deployCertificateInstanceReq), slog.Any("response", deployCertificateInstanceResp))
if err != nil {
return nil, fmt.Errorf("failed to execute sdk request 'ssl.DeployCertificateInstance': %w", err)
}
// 循环获取部署任务详情,等待任务状态变更
// REF: https://cloud.tencent.com/document/api/400/91658
for {
for _, domain := range domains {
select {
case <-ctx.Done():
return nil, ctx.Err()
default:
}
describeHostDeployRecordDetailReq := tcssl.NewDescribeHostDeployRecordDetailRequest()
describeHostDeployRecordDetailReq.DeployRecordId = common.StringPtr(fmt.Sprintf("%d", *deployCertificateInstanceResp.Response.DeployRecordId))
describeHostDeployRecordDetailResp, err := d.sdkClients.SSL.DescribeHostDeployRecordDetail(describeHostDeployRecordDetailReq)
d.logger.Debug("sdk request 'ssl.DescribeHostDeployRecordDetail'", slog.Any("request", describeHostDeployRecordDetailReq), slog.Any("response", describeHostDeployRecordDetailResp))
if err != nil {
return nil, fmt.Errorf("failed to execute sdk request 'ssl.DescribeHostDeployRecordDetail': %w", err)
}
var runningCount, succeededCount, failedCount, totalCount int64
if describeHostDeployRecordDetailResp.Response.TotalCount == nil {
return nil, errors.New("unexpected deployment job status")
} else {
if describeHostDeployRecordDetailResp.Response.RunningTotalCount != nil {
runningCount = *describeHostDeployRecordDetailResp.Response.RunningTotalCount
}
if describeHostDeployRecordDetailResp.Response.SuccessTotalCount != nil {
succeededCount = *describeHostDeployRecordDetailResp.Response.SuccessTotalCount
}
if describeHostDeployRecordDetailResp.Response.FailedTotalCount != nil {
failedCount = *describeHostDeployRecordDetailResp.Response.FailedTotalCount
}
if describeHostDeployRecordDetailResp.Response.TotalCount != nil {
totalCount = *describeHostDeployRecordDetailResp.Response.TotalCount
}
if succeededCount+failedCount == totalCount {
break
if err := d.updateDomainHttpsServerCert(ctx, domain, upres.CertId); err != nil {
errs = append(errs, err)
}
}
}
d.logger.Info(fmt.Sprintf("waiting for deployment job completion (running: %d, succeeded: %d, failed: %d, total: %d) ...", runningCount, succeededCount, failedCount, totalCount))
time.Sleep(time.Second * 5)
if len(errs) > 0 {
return nil, errors.Join(errs...)
}
}
return &core.SSLDeployResult{}, nil
}
func (d *SSLDeployerProvider) getDomainsByCertificateId(cloudCertId string) ([]string, error) {
func (d *SSLDeployerProvider) getDomainsByCertId(cloudCertId string) ([]string, error) {
// 获取证书中的可用域名
// REF: https://cloud.tencent.com/document/product/228/42491
// REF: https://cloud.tencent.com/document/api/228/42491
describeCertDomainsReq := tccdn.NewDescribeCertDomainsRequest()
describeCertDomainsReq.CertId = common.StringPtr(cloudCertId)
describeCertDomainsReq.Product = common.StringPtr("ecdn")
describeCertDomainsResp, err := d.sdkClients.CDN.DescribeCertDomains(describeCertDomainsReq)
describeCertDomainsResp, err := d.sdkClient.DescribeCertDomains(describeCertDomainsReq)
d.logger.Debug("sdk request 'cdn.DescribeCertDomains'", slog.Any("request", describeCertDomainsReq), slog.Any("response", describeCertDomainsResp))
if err != nil {
return nil, fmt.Errorf("failed to execute sdk request 'cdn.DescribeCertDomains': %w", err)
@ -190,21 +157,68 @@ func (d *SSLDeployerProvider) getDomainsByCertificateId(cloudCertId string) ([]s
return domains, nil
}
func createSDKClients(secretId, secretKey string) (*wSDKClients, error) {
func (d *SSLDeployerProvider) updateDomainHttpsServerCert(ctx context.Context, domain string, cloudCertId string) error {
// 查询域名详细配置
// REF: https://cloud.tencent.com/document/api/228/41117
describeDomainsConfigReq := tccdn.NewDescribeDomainsConfigRequest()
describeDomainsConfigReq.Filters = []*tccdn.DomainFilter{
{
Name: common.StringPtr("domain"),
Value: common.StringPtrs([]string{domain}),
},
}
describeDomainsConfigReq.Offset = common.Int64Ptr(0)
describeDomainsConfigReq.Limit = common.Int64Ptr(1)
describeDomainsConfigResp, err := d.sdkClient.DescribeDomainsConfig(describeDomainsConfigReq)
d.logger.Debug("sdk request 'cdn.DescribeDomainsConfig'", slog.Any("request", describeDomainsConfigReq), slog.Any("response", describeDomainsConfigResp))
if err != nil {
return fmt.Errorf("failed to execute sdk request 'cdn.DescribeDomainsConfig': %w", err)
} else if len(describeDomainsConfigResp.Response.Domains) == 0 {
return fmt.Errorf("domain %s not found", domain)
}
domainConfig := describeDomainsConfigResp.Response.Domains[0]
if domainConfig.Https != nil && domainConfig.Https.CertInfo != nil && domainConfig.Https.CertInfo.CertId != nil && *domainConfig.Https.CertInfo.CertId == cloudCertId {
// 已部署过此域名,跳过
return nil
}
// 更新加速域名配置
// REF: https://cloud.tencent.com/document/api/228/41116
updateDomainConfigReq := tccdn.NewUpdateDomainConfigRequest()
updateDomainConfigReq.Domain = common.StringPtr(domain)
updateDomainConfigReq.Https = domainConfig.Https
if updateDomainConfigReq.Https == nil {
updateDomainConfigReq.Https = &tccdn.Https{
Switch: common.StringPtr("on"),
}
} else {
updateDomainConfigReq.Https.SslStatus = nil
}
updateDomainConfigReq.Https.CertInfo = &tccdn.ServerCert{
CertId: common.StringPtr(cloudCertId),
}
updateDomainConfigResp, err := d.sdkClient.UpdateDomainConfig(updateDomainConfigReq)
d.logger.Debug("sdk request 'cdn.UpdateDomainConfig'", slog.Any("request", updateDomainConfigReq), slog.Any("response", updateDomainConfigResp))
if err != nil {
return fmt.Errorf("failed to execute sdk request 'cdn.UpdateDomainConfig': %w", err)
}
return nil
}
func createSDKClient(secretId, secretKey, endpoint string) (*tccdn.Client, error) {
credential := common.NewCredential(secretId, secretKey)
sslClient, err := tcssl.NewClient(credential, "", profile.NewClientProfile())
cpf := profile.NewClientProfile()
if endpoint != "" {
cpf.HttpProfile.Endpoint = endpoint
}
client, err := tccdn.NewClient(credential, "", cpf)
if err != nil {
return nil, err
}
cdnClient, err := tccdn.NewClient(credential, "", profile.NewClientProfile())
if err != nil {
return nil, err
}
return &wSDKClients{
SSL: sslClient,
CDN: cdnClient,
}, nil
return client, nil
}

View File

@ -5,14 +5,15 @@ import (
"errors"
"fmt"
"log/slog"
"strings"
"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"
"github.com/certimate-go/certimate/pkg/core"
sslmgrsp "github.com/certimate-go/certimate/pkg/core/ssl-manager/providers/tencentcloud-ssl"
"github.com/certimate-go/certimate/pkg/utils/ifelse"
)
type SSLDeployerProviderConfig struct {
@ -20,6 +21,8 @@ type SSLDeployerProviderConfig struct {
SecretId string `json:"secretId"`
// 腾讯云 SecretKey。
SecretKey string `json:"secretKey"`
// 腾讯云接口端点。
Endpoint string `json:"endpoint,omitempty"`
// 站点 ID。
ZoneId string `json:"zoneId"`
// 加速域名(支持泛域名)。
@ -29,23 +32,18 @@ type SSLDeployerProviderConfig struct {
type SSLDeployerProvider struct {
config *SSLDeployerProviderConfig
logger *slog.Logger
sdkClients *wSDKClients
sdkClient *tcteo.Client
sslManager core.SSLManager
}
var _ core.SSLDeployer = (*SSLDeployerProvider)(nil)
type wSDKClients struct {
SSL *tcssl.Client
TEO *tcteo.Client
}
func NewSSLDeployerProvider(config *SSLDeployerProviderConfig) (*SSLDeployerProvider, error) {
if config == nil {
return nil, errors.New("the configuration of the ssl deployer provider is nil")
}
clients, err := createSDKClients(config.SecretId, config.SecretKey)
client, err := createSDKClient(config.SecretId, config.SecretKey, config.Endpoint)
if err != nil {
return nil, fmt.Errorf("could not create sdk client: %w", err)
}
@ -53,6 +51,10 @@ func NewSSLDeployerProvider(config *SSLDeployerProviderConfig) (*SSLDeployerProv
sslmgr, err := sslmgrsp.NewSSLManagerProvider(&sslmgrsp.SSLManagerProviderConfig{
SecretId: config.SecretId,
SecretKey: config.SecretKey,
Endpoint: ifelse.
If[string](strings.HasSuffix(strings.TrimSpace(config.Endpoint), "intl.tencentcloudapi.com")).
Then("ssl.intl.tencentcloudapi.com"). // 国际站使用独立的接口端点
Else(""),
})
if err != nil {
return nil, fmt.Errorf("could not create ssl manager: %w", err)
@ -61,7 +63,7 @@ func NewSSLDeployerProvider(config *SSLDeployerProviderConfig) (*SSLDeployerProv
return &SSLDeployerProvider{
config: config,
logger: slog.Default(),
sdkClients: clients,
sdkClient: client,
sslManager: sslmgr,
}, nil
}
@ -93,13 +95,13 @@ func (d *SSLDeployerProvider) Deploy(ctx context.Context, certPEM string, privke
}
// 配置域名证书
// REF: https://cloud.tencent.com/document/product/1552/80764
// REF: https://cloud.tencent.com/document/api/1552/80764
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)
modifyHostsCertificateResp, err := d.sdkClient.ModifyHostsCertificate(modifyHostsCertificateReq)
d.logger.Debug("sdk request 'teo.ModifyHostsCertificate'", slog.Any("request", modifyHostsCertificateReq), slog.Any("response", modifyHostsCertificateResp))
if err != nil {
return nil, fmt.Errorf("failed to execute sdk request 'teo.ModifyHostsCertificate': %w", err)
@ -108,21 +110,18 @@ func (d *SSLDeployerProvider) Deploy(ctx context.Context, certPEM string, privke
return &core.SSLDeployResult{}, nil
}
func createSDKClients(secretId, secretKey string) (*wSDKClients, error) {
func createSDKClient(secretId, secretKey, endpoint string) (*tcteo.Client, error) {
credential := common.NewCredential(secretId, secretKey)
sslClient, err := tcssl.NewClient(credential, "", profile.NewClientProfile())
cpf := profile.NewClientProfile()
if endpoint != "" {
cpf.HttpProfile.Endpoint = endpoint
}
client, err := tcteo.NewClient(credential, "", cpf)
if err != nil {
return nil, err
}
teoClient, err := tcteo.NewClient(credential, "", profile.NewClientProfile())
if err != nil {
return nil, err
}
return &wSDKClients{
SSL: sslClient,
TEO: teoClient,
}, nil
return client, nil
}

View File

@ -5,6 +5,7 @@ import (
"errors"
"fmt"
"log/slog"
"strings"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile"
@ -12,6 +13,7 @@ import (
"github.com/certimate-go/certimate/pkg/core"
sslmgrsp "github.com/certimate-go/certimate/pkg/core/ssl-manager/providers/tencentcloud-ssl"
"github.com/certimate-go/certimate/pkg/utils/ifelse"
xtypes "github.com/certimate-go/certimate/pkg/utils/types"
)
@ -20,6 +22,8 @@ type SSLDeployerProviderConfig struct {
SecretId string `json:"secretId"`
// 腾讯云 SecretKey。
SecretKey string `json:"secretKey"`
// 腾讯云接口端点。
Endpoint string `json:"endpoint,omitempty"`
// 部署资源类型。
ResourceType ResourceType `json:"resourceType"`
// 通道 ID。
@ -44,7 +48,7 @@ func NewSSLDeployerProvider(config *SSLDeployerProviderConfig) (*SSLDeployerProv
return nil, errors.New("the configuration of the ssl deployer provider is nil")
}
client, err := createSDKClients(config.SecretId, config.SecretKey)
client, err := createSDKClients(config.SecretId, config.SecretKey, config.Endpoint)
if err != nil {
return nil, fmt.Errorf("could not create sdk client: %w", err)
}
@ -52,6 +56,10 @@ func NewSSLDeployerProvider(config *SSLDeployerProviderConfig) (*SSLDeployerProv
sslmgr, err := sslmgrsp.NewSSLManagerProvider(&sslmgrsp.SSLManagerProviderConfig{
SecretId: config.SecretId,
SecretKey: config.SecretKey,
Endpoint: ifelse.
If[string](strings.HasSuffix(strings.TrimSpace(config.Endpoint), "intl.tencentcloudapi.com")).
Then("ssl.intl.tencentcloudapi.com"). // 国际站使用独立的接口端点
Else(""),
})
if err != nil {
return nil, fmt.Errorf("could not create ssl manager: %w", err)
@ -113,7 +121,7 @@ func (d *SSLDeployerProvider) deployToListener(ctx context.Context, cloudCertId
func (d *SSLDeployerProvider) modifyHttpsListenerCertificate(ctx context.Context, cloudListenerId, cloudCertId string) error {
// 查询 HTTPS 监听器信息
// REF: https://cloud.tencent.com/document/product/608/37001
// REF: https://cloud.tencent.com/document/api/608/37001
describeHTTPSListenersReq := tcgaap.NewDescribeHTTPSListenersRequest()
describeHTTPSListenersReq.ListenerId = common.StringPtr(cloudListenerId)
describeHTTPSListenersReq.Offset = common.Uint64Ptr(0)
@ -123,11 +131,11 @@ func (d *SSLDeployerProvider) modifyHttpsListenerCertificate(ctx context.Context
if err != nil {
return fmt.Errorf("failed to execute sdk request 'gaap.DescribeHTTPSListeners': %w", err)
} else if len(describeHTTPSListenersResp.Response.ListenerSet) == 0 {
return errors.New("listener not found")
return fmt.Errorf("listener %s not found", cloudListenerId)
}
// 修改 HTTPS 监听器配置
// REF: https://cloud.tencent.com/document/product/608/36996
// REF: https://cloud.tencent.com/document/api/608/36996
modifyHTTPSListenerAttributeReq := tcgaap.NewModifyHTTPSListenerAttributeRequest()
modifyHTTPSListenerAttributeReq.ProxyId = xtypes.ToPtrOrZeroNil(d.config.ProxyId)
modifyHTTPSListenerAttributeReq.ListenerId = common.StringPtr(cloudListenerId)
@ -141,10 +149,15 @@ func (d *SSLDeployerProvider) modifyHttpsListenerCertificate(ctx context.Context
return nil
}
func createSDKClients(secretId, secretKey string) (*tcgaap.Client, error) {
func createSDKClients(secretId, secretKey, endpoint string) (*tcgaap.Client, error) {
credential := common.NewCredential(secretId, secretKey)
client, err := tcgaap.NewClient(credential, "", profile.NewClientProfile())
cpf := profile.NewClientProfile()
if endpoint != "" {
cpf.HttpProfile.Endpoint = endpoint
}
client, err := tcgaap.NewClient(credential, "", cpf)
if err != nil {
return nil, err
}

View File

@ -5,6 +5,7 @@ import (
"errors"
"fmt"
"log/slog"
"strings"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile"
@ -12,6 +13,7 @@ import (
"github.com/certimate-go/certimate/pkg/core"
sslmgrsp "github.com/certimate-go/certimate/pkg/core/ssl-manager/providers/tencentcloud-ssl"
"github.com/certimate-go/certimate/pkg/utils/ifelse"
)
type SSLDeployerProviderConfig struct {
@ -19,6 +21,8 @@ type SSLDeployerProviderConfig struct {
SecretId string `json:"secretId"`
// 腾讯云 SecretKey。
SecretKey string `json:"secretKey"`
// 腾讯云接口端点。
Endpoint string `json:"endpoint,omitempty"`
// 腾讯云地域。
Region string `json:"region"`
// 自定义域名(不支持泛域名)。
@ -39,7 +43,7 @@ func NewSSLDeployerProvider(config *SSLDeployerProviderConfig) (*SSLDeployerProv
return nil, errors.New("the configuration of the ssl deployer provider is nil")
}
client, err := createSDKClient(config.SecretId, config.SecretKey, config.Region)
client, err := createSDKClient(config.SecretId, config.SecretKey, config.Endpoint, config.Region)
if err != nil {
return nil, fmt.Errorf("could not create sdk client: %w", err)
}
@ -47,6 +51,10 @@ func NewSSLDeployerProvider(config *SSLDeployerProviderConfig) (*SSLDeployerProv
sslmgr, err := sslmgrsp.NewSSLManagerProvider(&sslmgrsp.SSLManagerProviderConfig{
SecretId: config.SecretId,
SecretKey: config.SecretKey,
Endpoint: ifelse.
If[string](strings.HasSuffix(strings.TrimSpace(config.Endpoint), "intl.tencentcloudapi.com")).
Then("ssl.intl.tencentcloudapi.com"). // 国际站使用独立的接口端点
Else(""),
})
if err != nil {
return nil, fmt.Errorf("could not create ssl manager: %w", err)
@ -76,7 +84,7 @@ func (d *SSLDeployerProvider) Deploy(ctx context.Context, certPEM string, privke
}
// 查看云函数自定义域名详情
// REF: https://cloud.tencent.com/document/product/583/111924
// REF: https://cloud.tencent.com/document/api/583/111924
getCustomDomainReq := tcscf.NewGetCustomDomainRequest()
getCustomDomainReq.Domain = common.StringPtr(d.config.Domain)
getCustomDomainResp, err := d.sdkClient.GetCustomDomain(getCustomDomainReq)
@ -94,7 +102,7 @@ func (d *SSLDeployerProvider) Deploy(ctx context.Context, certPEM string, privke
}
// 更新云函数自定义域名
// REF: https://cloud.tencent.com/document/product/583/111922
// REF: https://cloud.tencent.com/document/api/583/111922
updateCustomDomainReq := tcscf.NewUpdateCustomDomainRequest()
updateCustomDomainReq.Domain = common.StringPtr(d.config.Domain)
updateCustomDomainReq.CertConfig = &tcscf.CertConf{
@ -110,9 +118,15 @@ func (d *SSLDeployerProvider) Deploy(ctx context.Context, certPEM string, privke
return &core.SSLDeployResult{}, nil
}
func createSDKClient(secretId, secretKey, region string) (*tcscf.Client, error) {
func createSDKClient(secretId, secretKey, endpoint, region string) (*tcscf.Client, error) {
credential := common.NewCredential(secretId, secretKey)
client, err := tcscf.NewClient(credential, region, profile.NewClientProfile())
cpf := profile.NewClientProfile()
if endpoint != "" {
cpf.HttpProfile.Endpoint = endpoint
}
client, err := tcscf.NewClient(credential, region, cpf)
if err != nil {
return nil, err
}

View File

@ -20,12 +20,14 @@ type SSLDeployerProviderConfig struct {
SecretId string `json:"secretId"`
// 腾讯云 SecretKey。
SecretKey string `json:"secretKey"`
// 腾讯云接口端点。
Endpoint string `json:"endpoint,omitempty"`
// 腾讯云地域。
Region string `json:"region"`
// 腾讯云云资源类型。
// 云资源类型。
ResourceType string `json:"resourceType"`
// 腾讯云云资源 ID 数组。
ResourceIds []string `json:"resourceIds"`
// 云资源 ID 数组。
ResourceIds []string `json:"resourceIds,omitempty"`
}
type SSLDeployerProvider struct {
@ -42,7 +44,7 @@ func NewSSLDeployerProvider(config *SSLDeployerProviderConfig) (*SSLDeployerProv
return nil, errors.New("the configuration of the ssl deployer provider is nil")
}
client, err := createSDKClient(config.SecretId, config.SecretKey, config.Region)
client, err := createSDKClient(config.SecretId, config.SecretKey, config.Endpoint, config.Region)
if err != nil {
return nil, fmt.Errorf("could not create sdk client: %w", err)
}
@ -50,6 +52,7 @@ func NewSSLDeployerProvider(config *SSLDeployerProviderConfig) (*SSLDeployerProv
sslmgr, err := sslmgrsp.NewSSLManagerProvider(&sslmgrsp.SSLManagerProviderConfig{
SecretId: config.SecretId,
SecretKey: config.SecretKey,
Endpoint: config.Endpoint,
})
if err != nil {
return nil, fmt.Errorf("could not create ssl manager: %w", err)
@ -90,7 +93,7 @@ func (d *SSLDeployerProvider) Deploy(ctx context.Context, certPEM string, privke
}
// 证书部署到云资源实例列表
// REF: https://cloud.tencent.com/document/product/400/91667
// REF: https://cloud.tencent.com/document/api/400/91667
deployCertificateInstanceReq := tcssl.NewDeployCertificateInstanceRequest()
deployCertificateInstanceReq.CertificateId = common.StringPtr(upres.CertId)
deployCertificateInstanceReq.ResourceType = common.StringPtr(d.config.ResourceType)
@ -150,10 +153,15 @@ func (d *SSLDeployerProvider) Deploy(ctx context.Context, certPEM string, privke
return &core.SSLDeployResult{}, nil
}
func createSDKClient(secretId, secretKey, region string) (*tcssl.Client, error) {
func createSDKClient(secretId, secretKey, endpoint, region string) (*tcssl.Client, error) {
credential := common.NewCredential(secretId, secretKey)
client, err := tcssl.NewClient(credential, region, profile.NewClientProfile())
cpf := profile.NewClientProfile()
if endpoint != "" {
cpf.HttpProfile.Endpoint = endpoint
}
client, err := tcssl.NewClient(credential, region, cpf)
if err != nil {
return nil, err
}

View File

@ -0,0 +1,306 @@
package tencentcloudsslupdate
import (
"context"
"errors"
"fmt"
"log/slog"
"slices"
"time"
"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"
"github.com/certimate-go/certimate/pkg/core"
sslmgrsp "github.com/certimate-go/certimate/pkg/core/ssl-manager/providers/tencentcloud-ssl"
)
type SSLDeployerProviderConfig struct {
// 腾讯云 SecretId。
SecretId string `json:"secretId"`
// 腾讯云 SecretKey。
SecretKey string `json:"secretKey"`
// 腾讯云接口端点。
Endpoint string `json:"endpoint,omitempty"`
// 原证书 ID。
CertificiateId string `json:"certificateId"`
// 是否替换原有证书(即保持原证书 ID 不变)。
IsReplaced bool `json:"isReplaced,omitempty"`
// 云资源类型数组。
ResourceTypes []string `json:"resourceTypes"`
// 云资源地域数组。
ResourceRegions []string `json:"resourceRegions"`
}
type SSLDeployerProvider struct {
config *SSLDeployerProviderConfig
logger *slog.Logger
sdkClient *tcssl.Client
sslManager core.SSLManager
}
var _ core.SSLDeployer = (*SSLDeployerProvider)(nil)
func NewSSLDeployerProvider(config *SSLDeployerProviderConfig) (*SSLDeployerProvider, error) {
if config == nil {
return nil, errors.New("the configuration of the ssl deployer provider is nil")
}
client, err := createSDKClient(config.SecretId, config.SecretKey, config.Endpoint)
if err != nil {
return nil, fmt.Errorf("could not create sdk client: %w", err)
}
sslmgr, err := sslmgrsp.NewSSLManagerProvider(&sslmgrsp.SSLManagerProviderConfig{
SecretId: config.SecretId,
SecretKey: config.SecretKey,
Endpoint: config.Endpoint,
})
if err != nil {
return nil, fmt.Errorf("could not create ssl manager: %w", err)
}
return &SSLDeployerProvider{
config: config,
logger: slog.Default(),
sdkClient: client,
sslManager: sslmgr,
}, nil
}
func (d *SSLDeployerProvider) SetLogger(logger *slog.Logger) {
if logger == nil {
d.logger = slog.New(slog.DiscardHandler)
} else {
d.logger = logger
}
d.sslManager.SetLogger(logger)
}
func (d *SSLDeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*core.SSLDeployResult, error) {
if d.config.CertificiateId == "" {
return nil, errors.New("config `certificateId` is required")
}
if len(d.config.ResourceTypes) == 0 {
return nil, errors.New("config `resourceTypes` is required")
}
if d.config.IsReplaced {
if err := d.executeUploadUpdateCertificateInstance(ctx, certPEM, privkeyPEM); err != nil {
return nil, err
}
} else {
if err := d.executeUpdateCertificateInstance(ctx, certPEM, privkeyPEM); err != nil {
return nil, err
}
}
return &core.SSLDeployResult{}, nil
}
func (d *SSLDeployerProvider) executeUpdateCertificateInstance(ctx context.Context, certPEM string, privkeyPEM string) error {
// 上传证书
upres, err := d.sslManager.Upload(ctx, certPEM, privkeyPEM)
if err != nil {
return fmt.Errorf("failed to upload certificate file: %w", err)
} else {
d.logger.Info("ssl certificate uploaded", slog.Any("result", upres))
}
// 一键更新新旧证书资源
// REF: https://cloud.tencent.com/document/product/400/91649
var deployRecordId string
for {
select {
case <-ctx.Done():
return ctx.Err()
default:
}
updateCertificateInstanceReq := tcssl.NewUpdateCertificateInstanceRequest()
updateCertificateInstanceReq.OldCertificateId = common.StringPtr(d.config.CertificiateId)
updateCertificateInstanceReq.CertificateId = common.StringPtr(upres.CertId)
updateCertificateInstanceReq.ResourceTypes = common.StringPtrs(d.config.ResourceTypes)
updateCertificateInstanceReq.ResourceTypesRegions = wrapResourceTypeRegions(d.config.ResourceTypes, d.config.ResourceRegions)
updateCertificateInstanceResp, err := d.sdkClient.UpdateCertificateInstance(updateCertificateInstanceReq)
d.logger.Debug("sdk request 'ssl.UpdateCertificateInstance'", slog.Any("request", updateCertificateInstanceReq), slog.Any("response", updateCertificateInstanceResp))
if err != nil {
return fmt.Errorf("failed to execute sdk request 'ssl.UpdateCertificateInstance': %w", err)
}
if updateCertificateInstanceResp.Response.DeployStatus == nil {
return errors.New("unexpected deployment job status")
} else if *updateCertificateInstanceResp.Response.DeployStatus == 1 {
deployRecordId = fmt.Sprintf("%d", *updateCertificateInstanceResp.Response.DeployRecordId)
break
}
time.Sleep(time.Second * 5)
}
// 循环查询证书云资源更新记录详情,等待任务状态变更
// REF: https://cloud.tencent.com/document/api/400/91652
for {
select {
case <-ctx.Done():
return ctx.Err()
default:
}
describeHostUpdateRecordDetailReq := tcssl.NewDescribeHostUpdateRecordDetailRequest()
describeHostUpdateRecordDetailReq.DeployRecordId = common.StringPtr(deployRecordId)
describeHostUpdateRecordDetailResp, err := d.sdkClient.DescribeHostUpdateRecordDetail(describeHostUpdateRecordDetailReq)
d.logger.Debug("sdk request 'ssl.DescribeHostUpdateRecordDetail'", slog.Any("request", describeHostUpdateRecordDetailReq), slog.Any("response", describeHostUpdateRecordDetailResp))
if err != nil {
return fmt.Errorf("failed to execute sdk request 'ssl.DescribeHostUpdateRecordDetail': %w", err)
}
var runningCount, succeededCount, failedCount, totalCount int64
if describeHostUpdateRecordDetailResp.Response.TotalCount == nil {
return errors.New("unexpected deployment job status")
} else {
if describeHostUpdateRecordDetailResp.Response.RunningTotalCount != nil {
runningCount = *describeHostUpdateRecordDetailResp.Response.RunningTotalCount
}
if describeHostUpdateRecordDetailResp.Response.SuccessTotalCount != nil {
succeededCount = *describeHostUpdateRecordDetailResp.Response.SuccessTotalCount
}
if describeHostUpdateRecordDetailResp.Response.FailedTotalCount != nil {
failedCount = *describeHostUpdateRecordDetailResp.Response.FailedTotalCount
}
if describeHostUpdateRecordDetailResp.Response.TotalCount != nil {
totalCount = *describeHostUpdateRecordDetailResp.Response.TotalCount
}
if succeededCount+failedCount == totalCount {
break
}
}
d.logger.Info(fmt.Sprintf("waiting for deployment job completion (running: %d, succeeded: %d, failed: %d, total: %d) ...", runningCount, succeededCount, failedCount, totalCount))
time.Sleep(time.Second * 5)
}
return nil
}
func (d *SSLDeployerProvider) executeUploadUpdateCertificateInstance(ctx context.Context, certPEM string, privkeyPEM string) error {
// 更新证书内容并更新关联的云资源
// REF: https://cloud.tencent.com/document/product/400/119791
var deployRecordId int64
for {
select {
case <-ctx.Done():
return ctx.Err()
default:
}
uploadUpdateCertificateInstanceReq := tcssl.NewUploadUpdateCertificateInstanceRequest()
uploadUpdateCertificateInstanceReq.OldCertificateId = common.StringPtr(d.config.CertificiateId)
uploadUpdateCertificateInstanceReq.CertificatePublicKey = common.StringPtr(certPEM)
uploadUpdateCertificateInstanceReq.CertificatePrivateKey = common.StringPtr(privkeyPEM)
uploadUpdateCertificateInstanceReq.ResourceTypes = common.StringPtrs(d.config.ResourceTypes)
uploadUpdateCertificateInstanceReq.ResourceTypesRegions = wrapResourceTypeRegions(d.config.ResourceTypes, d.config.ResourceRegions)
uploadUpdateCertificateInstanceResp, err := d.sdkClient.UploadUpdateCertificateInstance(uploadUpdateCertificateInstanceReq)
d.logger.Debug("sdk request 'ssl.UploadUpdateCertificateInstance'", slog.Any("request", uploadUpdateCertificateInstanceReq), slog.Any("response", uploadUpdateCertificateInstanceResp))
if err != nil {
return fmt.Errorf("failed to execute sdk request 'ssl.UploadUpdateCertificateInstance': %w", err)
}
if uploadUpdateCertificateInstanceResp.Response.DeployStatus == nil {
return errors.New("unexpected deployment job status")
} else if *uploadUpdateCertificateInstanceResp.Response.DeployStatus == 1 {
deployRecordId = int64(*uploadUpdateCertificateInstanceResp.Response.DeployRecordId)
break
}
time.Sleep(time.Second * 5)
}
// 循环查询证书云资源更新记录详情,等待任务状态变更
// REF: https://cloud.tencent.com/document/product/400/120056
for {
select {
case <-ctx.Done():
return ctx.Err()
default:
}
describeHostUploadUpdateRecordDetailReq := tcssl.NewDescribeHostUploadUpdateRecordDetailRequest()
describeHostUploadUpdateRecordDetailReq.DeployRecordId = common.Int64Ptr(deployRecordId)
describeHostUploadUpdateRecordDetailReq.Limit = common.Int64Ptr(200)
describeHostUploadUpdateRecordDetailResp, err := d.sdkClient.DescribeHostUploadUpdateRecordDetail(describeHostUploadUpdateRecordDetailReq)
d.logger.Debug("sdk request 'ssl.DescribeHostUploadUpdateRecordDetail'", slog.Any("request", describeHostUploadUpdateRecordDetailReq), slog.Any("response", describeHostUploadUpdateRecordDetailResp))
if err != nil {
return fmt.Errorf("failed to execute sdk request 'ssl.DescribeHostUploadUpdateRecordDetail': %w", err)
}
var runningCount, succeededCount, failedCount, totalCount int64
if describeHostUploadUpdateRecordDetailResp.Response.DeployRecordDetail == nil {
return errors.New("unexpected deployment job status")
} else {
for _, record := range describeHostUploadUpdateRecordDetailResp.Response.DeployRecordDetail {
if record.RunningTotalCount != nil {
runningCount = *record.RunningTotalCount
}
if record.SuccessTotalCount != nil {
succeededCount = *record.SuccessTotalCount
}
if record.FailedTotalCount != nil {
failedCount = *record.FailedTotalCount
}
if record.TotalCount != nil {
totalCount = *record.TotalCount
}
}
if succeededCount+failedCount == totalCount {
break
}
}
d.logger.Info(fmt.Sprintf("waiting for deployment job completion (running: %d, succeeded: %d, failed: %d, total: %d) ...", runningCount, succeededCount, failedCount, totalCount))
time.Sleep(time.Second * 5)
}
return nil
}
func createSDKClient(secretId, secretKey, endpoint string) (*tcssl.Client, error) {
credential := common.NewCredential(secretId, secretKey)
cpf := profile.NewClientProfile()
if endpoint != "" {
cpf.HttpProfile.Endpoint = endpoint
}
client, err := tcssl.NewClient(credential, "", cpf)
if err != nil {
return nil, err
}
return client, nil
}
func wrapResourceTypeRegions(resourceTypes, resourceRegions []string) []*tcssl.ResourceTypeRegions {
if len(resourceTypes) == 0 || len(resourceRegions) == 0 {
return nil
}
// 仅以下云资源类型支持地域
resourceTypesRequireRegion := []string{"apigateway", "clb", "cos", "tcb", "tke", "tse", "waf"}
temp := make([]*tcssl.ResourceTypeRegions, 0)
for _, resourceType := range resourceTypes {
if slices.Contains(resourceTypesRequireRegion, resourceType) {
temp = append(temp, &tcssl.ResourceTypeRegions{
ResourceType: common.StringPtr(resourceType),
Regions: common.StringPtrs(resourceRegions),
})
}
}
return temp
}

View File

@ -15,6 +15,8 @@ type SSLDeployerProviderConfig struct {
SecretId string `json:"secretId"`
// 腾讯云 SecretKey。
SecretKey string `json:"secretKey"`
// 腾讯云接口端点。
Endpoint string `json:"endpoint,omitempty"`
}
type SSLDeployerProvider struct {
@ -33,6 +35,7 @@ func NewSSLDeployerProvider(config *SSLDeployerProviderConfig) (*SSLDeployerProv
sslmgr, err := sslmgrsp.NewSSLManagerProvider(&sslmgrsp.SSLManagerProviderConfig{
SecretId: config.SecretId,
SecretKey: config.SecretKey,
Endpoint: config.Endpoint,
})
if err != nil {
return nil, fmt.Errorf("could not create ssl manager: %w", err)

View File

@ -5,6 +5,7 @@ import (
"errors"
"fmt"
"log/slog"
"strings"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile"
@ -12,6 +13,7 @@ import (
"github.com/certimate-go/certimate/pkg/core"
sslmgrsp "github.com/certimate-go/certimate/pkg/core/ssl-manager/providers/tencentcloud-ssl"
"github.com/certimate-go/certimate/pkg/utils/ifelse"
)
type SSLDeployerProviderConfig struct {
@ -19,6 +21,8 @@ type SSLDeployerProviderConfig struct {
SecretId string `json:"secretId"`
// 腾讯云 SecretKey。
SecretKey string `json:"secretKey"`
// 腾讯云接口端点。
Endpoint string `json:"endpoint,omitempty"`
// 点播应用 ID。
SubAppId int64 `json:"subAppId"`
// 点播加速域名(不支持泛域名)。
@ -39,7 +43,7 @@ func NewSSLDeployerProvider(config *SSLDeployerProviderConfig) (*SSLDeployerProv
return nil, errors.New("the configuration of the ssl deployer provider is nil")
}
client, err := createSDKClient(config.SecretId, config.SecretKey)
client, err := createSDKClient(config.SecretId, config.SecretKey, config.Endpoint)
if err != nil {
return nil, fmt.Errorf("could not create sdk client: %w", err)
}
@ -47,6 +51,10 @@ func NewSSLDeployerProvider(config *SSLDeployerProviderConfig) (*SSLDeployerProv
sslmgr, err := sslmgrsp.NewSSLManagerProvider(&sslmgrsp.SSLManagerProviderConfig{
SecretId: config.SecretId,
SecretKey: config.SecretKey,
Endpoint: ifelse.
If[string](strings.HasSuffix(strings.TrimSpace(config.Endpoint), "intl.tencentcloudapi.com")).
Then("ssl.intl.tencentcloudapi.com"). // 国际站使用独立的接口端点
Else(""),
})
if err != nil {
return nil, fmt.Errorf("could not create ssl manager: %w", err)
@ -101,9 +109,15 @@ func (d *SSLDeployerProvider) Deploy(ctx context.Context, certPEM string, privke
return &core.SSLDeployResult{}, nil
}
func createSDKClient(secretId, secretKey string) (*tcvod.Client, error) {
func createSDKClient(secretId, secretKey, endpoint string) (*tcvod.Client, error) {
credential := common.NewCredential(secretId, secretKey)
client, err := tcvod.NewClient(credential, "", profile.NewClientProfile())
cpf := profile.NewClientProfile()
if endpoint != "" {
cpf.HttpProfile.Endpoint = endpoint
}
client, err := tcvod.NewClient(credential, "", cpf)
if err != nil {
return nil, err
}

View File

@ -5,6 +5,7 @@ import (
"errors"
"fmt"
"log/slog"
"strings"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile"
@ -12,6 +13,7 @@ import (
"github.com/certimate-go/certimate/pkg/core"
sslmgrsp "github.com/certimate-go/certimate/pkg/core/ssl-manager/providers/tencentcloud-ssl"
"github.com/certimate-go/certimate/pkg/utils/ifelse"
)
type SSLDeployerProviderConfig struct {
@ -19,6 +21,8 @@ type SSLDeployerProviderConfig struct {
SecretId string `json:"secretId"`
// 腾讯云 SecretKey。
SecretKey string `json:"secretKey"`
// 腾讯云接口端点。
Endpoint string `json:"endpoint,omitempty"`
// 腾讯云地域。
Region string `json:"region"`
// 防护域名(不支持泛域名)。
@ -43,7 +47,7 @@ func NewSSLDeployerProvider(config *SSLDeployerProviderConfig) (*SSLDeployerProv
return nil, errors.New("the configuration of the ssl deployer provider is nil")
}
client, err := createSDKClient(config.SecretId, config.SecretKey, config.Region)
client, err := createSDKClient(config.SecretId, config.SecretKey, config.Endpoint, config.Region)
if err != nil {
return nil, fmt.Errorf("could not create sdk client: %w", err)
}
@ -51,6 +55,10 @@ func NewSSLDeployerProvider(config *SSLDeployerProviderConfig) (*SSLDeployerProv
sslmgr, err := sslmgrsp.NewSSLManagerProvider(&sslmgrsp.SSLManagerProviderConfig{
SecretId: config.SecretId,
SecretKey: config.SecretKey,
Endpoint: ifelse.
If[string](strings.HasSuffix(strings.TrimSpace(config.Endpoint), "intl.tencentcloudapi.com")).
Then("ssl.intl.tencentcloudapi.com"). // 国际站使用独立的接口端点
Else(""),
})
if err != nil {
return nil, fmt.Errorf("could not create ssl manager: %w", err)
@ -122,9 +130,15 @@ func (d *SSLDeployerProvider) Deploy(ctx context.Context, certPEM string, privke
return &core.SSLDeployResult{}, nil
}
func createSDKClient(secretId, secretKey, region string) (*tcwaf.Client, error) {
func createSDKClient(secretId, secretKey, endpoint, region string) (*tcwaf.Client, error) {
credential := common.NewCredential(secretId, secretKey)
client, err := tcwaf.NewClient(credential, region, profile.NewClientProfile())
cpf := profile.NewClientProfile()
if endpoint != "" {
cpf.HttpProfile.Endpoint = endpoint
}
client, err := tcwaf.NewClient(credential, region, cpf)
if err != nil {
return nil, err
}

View File

@ -97,7 +97,7 @@ func (d *SSLDeployerProvider) Deploy(ctx context.Context, certPEM string, privke
if err != nil {
return nil, fmt.Errorf("failed to execute sdk request 'ucdn.GetUcdnDomainConfig': %w", err)
} else if len(getUcdnDomainConfigResp.DomainList) == 0 {
return nil, errors.New("no domain found")
return nil, fmt.Errorf("domain %s not found", d.config.DomainId)
}
// 更新 HTTPS 加速配置

View File

@ -17,6 +17,8 @@ type SSLManagerProviderConfig struct {
SecretId string `json:"secretId"`
// 腾讯云 SecretKey。
SecretKey string `json:"secretKey"`
// 腾讯云接口端点。
Endpoint string `json:"endpoint,omitempty"`
}
type SSLManagerProvider struct {
@ -32,7 +34,7 @@ func NewSSLManagerProvider(config *SSLManagerProviderConfig) (*SSLManagerProvide
return nil, errors.New("the configuration of the ssl manager provider is nil")
}
client, err := createSDKClient(config.SecretId, config.SecretKey)
client, err := createSDKClient(config.SecretId, config.SecretKey, config.Endpoint)
if err != nil {
return nil, fmt.Errorf("could not create sdk client: %w", err)
}
@ -54,7 +56,7 @@ func (m *SSLManagerProvider) SetLogger(logger *slog.Logger) {
func (m *SSLManagerProvider) Upload(ctx context.Context, certPEM string, privkeyPEM string) (*core.SSLManageUploadResult, error) {
// 上传新证书
// REF: https://cloud.tencent.com/document/product/400/41665
// REF: https://cloud.tencent.com/document/api/400/41665
uploadCertificateReq := tcssl.NewUploadCertificateRequest()
uploadCertificateReq.CertificatePublicKey = common.StringPtr(certPEM)
uploadCertificateReq.CertificatePrivateKey = common.StringPtr(privkeyPEM)
@ -70,9 +72,15 @@ func (m *SSLManagerProvider) Upload(ctx context.Context, certPEM string, privkey
}, nil
}
func createSDKClient(secretId, secretKey string) (*tcssl.Client, error) {
func createSDKClient(secretId, secretKey, endpoint string) (*tcssl.Client, error) {
credential := common.NewCredential(secretId, secretKey)
client, err := tcssl.NewClient(credential, "", profile.NewClientProfile())
cpf := profile.NewClientProfile()
if endpoint != "" {
cpf.HttpProfile.Endpoint = endpoint
}
client, err := tcssl.NewClient(credential, "", cpf)
if err != nil {
return nil, err
}

View File

@ -0,0 +1,34 @@
package ifelse
type ifExpr[T any] struct {
condition bool
}
type thenExpr[T any] struct {
condition bool
consequent T
}
// 示例:
//
// result := ifelse.If[T](condition).Then(consequent).Else(alternative)
func If[T any](condition bool) *ifExpr[T] {
return &ifExpr[T]{
condition: condition,
}
}
func (e *ifExpr[T]) Then(consequent T) *thenExpr[T] {
return &thenExpr[T]{
condition: e.condition,
consequent: consequent,
}
}
func (e *thenExpr[T]) Else(alternative T) T {
if e.condition {
return e.consequent
}
return alternative
}

View File

@ -0,0 +1,35 @@
package ifelse
// 三目条件函数。
//
// 入参:
// - condition: 条件。
// - consequent: 条件为真时返回的值。
// - alternative: 条件为假时返回的值。
//
// 出参:
// - 若 condition 的为真,将返回 consequent否则将返回 alternative。
func Ternary[T any](condition bool, consequent, alternative T) T {
if condition {
return consequent
} else {
return alternative
}
}
// 与 [Ternary] 类似,但返回值支持延迟计算函数。
//
// 入参:
// - condition: 条件。
// - consequentFunc: 条件为真时返回的计算函数。
// - alternativeFunc: 条件为假时返回的计算函数。
//
// 出参:
// - 若 condition 的为真,将返回 consequentFunc 的计算结果;否则,将返回 alternativeFunc 的计算结果。
func TernaryFunc[T any](condition bool, consequentFunc, alternativeFunc func() T) T {
if condition {
return consequentFunc()
} else {
return alternativeFunc()
}
}

939
ui/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -11,34 +11,34 @@
},
"dependencies": {
"@ant-design/icons": "^6.0.0",
"@ant-design/pro-components": "^2.8.7",
"@codemirror/lang-json": "^6.0.1",
"@ant-design/pro-components": "^2.8.9",
"@codemirror/lang-json": "^6.0.2",
"@codemirror/lang-yaml": "^6.1.2",
"@codemirror/language": "^6.11.0",
"@codemirror/language": "^6.11.1",
"@codemirror/legacy-modes": "^6.5.1",
"@uiw/codemirror-extensions-basic-setup": "^4.23.12",
"@uiw/codemirror-theme-vscode": "^4.23.12",
"@uiw/react-codemirror": "^4.23.12",
"@uiw/codemirror-extensions-basic-setup": "^4.23.13",
"@uiw/codemirror-theme-vscode": "^4.23.13",
"@uiw/react-codemirror": "^4.23.13",
"ahooks": "^3.8.5",
"antd": "^5.25.3",
"antd-zod": "^6.1.0",
"antd": "^5.26.1",
"antd-zod": "^7.0.0",
"clsx": "^2.1.1",
"cron-parser": "^5.2.0",
"cron-parser": "^5.3.0",
"file-saver": "^2.0.5",
"i18next": "^25.2.1",
"i18next-browser-languagedetector": "^8.1.0",
"i18next-browser-languagedetector": "^8.2.0",
"immer": "^10.1.1",
"lucide-react": "^0.511.0",
"lucide-react": "^0.522.0",
"nanoid": "^5.1.5",
"pocketbase": "^0.26.0",
"radash": "^12.1.0",
"pocketbase": "^0.26.1",
"radash": "^12.1.1",
"react": "^18.3.1",
"react-copy-to-clipboard": "^5.1.0",
"react-dom": "^18.3.1",
"react-i18next": "^15.5.2",
"react-router-dom": "^7.6.1",
"react-i18next": "^15.5.3",
"react-router-dom": "^7.6.2",
"tailwind-merge": "^2.6.0",
"zod": "^3.25.28",
"zod": "^3.25.67",
"zustand": "^5.0.5"
},
"devDependencies": {
@ -48,22 +48,22 @@
"@types/react": "^18.3.12",
"@types/react-copy-to-clipboard": "^5.0.7",
"@types/react-dom": "^18.3.1",
"@typescript-eslint/eslint-plugin": "^8.32.1",
"@typescript-eslint/parser": "^8.32.1",
"@typescript-eslint/eslint-plugin": "^8.34.1",
"@typescript-eslint/parser": "^8.34.1",
"@vitejs/plugin-legacy": "^6.1.1",
"@vitejs/plugin-react": "^4.5.0",
"@vitejs/plugin-react": "^4.6.0",
"autoprefixer": "^10.4.21",
"eslint": "^8.57.0",
"eslint-config-prettier": "^10.1.5",
"eslint-import-resolver-typescript": "^3.8.3",
"eslint-plugin-import": "^2.31.0",
"eslint-plugin-prettier": "^5.4.0",
"eslint-plugin-import": "^2.32.0",
"eslint-plugin-prettier": "^5.5.0",
"eslint-plugin-react-hooks": "^5.2.0",
"eslint-plugin-react-refresh": "^0.4.20",
"eslint-plugin-tailwindcss": "^3.18.0",
"fs-extra": "^11.3.0",
"postcss": "^8.5.3",
"prettier": "^3.5.3",
"postcss": "^8.5.6",
"prettier": "^3.6.0",
"tailwindcss": "^3.4.17",
"tailwindcss-animate": "^1.0.7",
"typescript": "^5.8.3",

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

View File

@ -2,7 +2,7 @@ import { forwardRef, useImperativeHandle, useMemo, useState } from "react";
import { useTranslation } from "react-i18next";
import { Form, type FormInstance, Input } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { z } from "zod/v4";
import AccessProviderPicker from "@/components/provider/AccessProviderPicker";
import AccessProviderSelect from "@/components/provider/AccessProviderSelect";
@ -68,6 +68,7 @@ import AccessFormRainYunConfig from "./AccessFormRainYunConfig";
import AccessFormRatPanelConfig from "./AccessFormRatPanelConfig";
import AccessFormSafeLineConfig from "./AccessFormSafeLineConfig";
import AccessFormSlackBotConfig from "./AccessFormSlackBotConfig";
import AccessFormSpaceshipConfig from "./AccessFormSpaceshipConfig";
import AccessFormSSHConfig from "./AccessFormSSHConfig";
import AccessFormSSLComConfig from "./AccessFormSSLComConfig";
import AccessFormTelegramBotConfig from "./AccessFormTelegramBotConfig";
@ -108,7 +109,7 @@ const AccessForm = forwardRef<AccessFormInstance, AccessFormProps>(({ className,
const formSchema = z.object({
name: z
.string({ message: t("access.form.name.placeholder") })
.string(t("access.form.name.placeholder"))
.min(1, t("access.form.name.placeholder"))
.max(64, t("common.errmsg.string_max", { max: 64 })),
provider: z.nativeEnum(ACCESS_PROVIDERS, {
@ -301,6 +302,8 @@ const AccessForm = forwardRef<AccessFormInstance, AccessFormProps>(({ className,
return <AccessFormSafeLineConfig {...nestedFormProps} />;
case ACCESS_PROVIDERS.SLACKBOT:
return <AccessFormSlackBotConfig {...nestedFormProps} />;
case ACCESS_PROVIDERS.SPACESHIP:
return <AccessFormSpaceshipConfig {...nestedFormProps} />;
case ACCESS_PROVIDERS.SSH:
return <AccessFormSSHConfig {...nestedFormProps} />;
case ACCESS_PROVIDERS.TELEGRAMBOT:

View File

@ -1,7 +1,7 @@
import { useTranslation } from "react-i18next";
import { Form, type FormInstance, Input, Select, Switch } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { z } from "zod/v4";
import { type AccessConfigFor1Panel } from "@/domain/access";
@ -27,7 +27,7 @@ const AccessForm1PanelConfig = ({ form: formInst, formName, disabled, initialVal
const { t } = useTranslation();
const formSchema = z.object({
serverUrl: z.string().url(t("common.errmsg.url_invalid")),
serverUrl: z.url(t("common.errmsg.url_invalid")),
apiVersion: z.string().nonempty(t("access.form.1panel_api_version.placeholder")),
apiKey: z
.string()

View File

@ -1,7 +1,7 @@
import { useTranslation } from "react-i18next";
import { Form, type FormInstance, Input } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { z } from "zod/v4";
import { type AccessConfigForACMECA } from "@/domain/access";
@ -25,7 +25,7 @@ const AccessFormACMECAConfig = ({ form: formInst, formName, disabled, initialVal
const { t } = useTranslation();
const formSchema = z.object({
endpoint: z.string().url(t("common.errmsg.url_invalid")),
endpoint: z.url(t("common.errmsg.url_invalid")),
eabKid: z.string().nullish(),
eabHmacKey: z.string().nullish(),
});

View File

@ -1,7 +1,7 @@
import { useTranslation } from "react-i18next";
import { Form, type FormInstance, Input, Select } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { z } from "zod/v4";
import { type AccessConfigForACMEHttpReq } from "@/domain/access";
@ -26,7 +26,7 @@ const AccessFormACMEHttpReqConfig = ({ form: formInst, formName, disabled, initi
const { t } = useTranslation();
const formSchema = z.object({
endpoint: z.string().url(t("common.errmsg.url_invalid")),
endpoint: z.url(t("common.errmsg.url_invalid")),
mode: z.string().nullish(),
username: z
.string()

View File

@ -1,7 +1,7 @@
import { useTranslation } from "react-i18next";
import { Form, type FormInstance, Input, Switch } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { z } from "zod/v4";
import { type AccessConfigForAPISIX } from "@/domain/access";
@ -26,7 +26,7 @@ const AccessFormAPISIXConfig = ({ form: formInst, formName, disabled, initialVal
const { t } = useTranslation();
const formSchema = z.object({
serverUrl: z.string().url(t("common.errmsg.url_invalid")),
serverUrl: z.url(t("common.errmsg.url_invalid")),
apiKey: z.string().nonempty(t("access.form.apisix_api_key.placeholder")),
allowInsecureConnections: z.boolean().nullish(),
});

View File

@ -1,7 +1,7 @@
import { useTranslation } from "react-i18next";
import { Form, type FormInstance, Input } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { z } from "zod/v4";
import { type AccessConfigForAWS } from "@/domain/access";

View File

@ -1,7 +1,7 @@
import { useTranslation } from "react-i18next";
import { Form, type FormInstance, Input } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { z } from "zod/v4";
import { type AccessConfigForAliyun } from "@/domain/access";

View File

@ -1,7 +1,7 @@
import { useTranslation } from "react-i18next";
import { AutoComplete, Form, type FormInstance, Input } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { z } from "zod/v4";
import { type AccessConfigForAzure } from "@/domain/access";

View File

@ -1,7 +1,7 @@
import { useTranslation } from "react-i18next";
import { Form, type FormInstance, Input } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { z } from "zod/v4";
import { type AccessConfigForBaiduCloud } from "@/domain/access";

View File

@ -1,7 +1,7 @@
import { useTranslation } from "react-i18next";
import { Form, type FormInstance, Input } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { z } from "zod/v4";
import { type AccessConfigForBaishan } from "@/domain/access";

View File

@ -1,7 +1,7 @@
import { useTranslation } from "react-i18next";
import { Form, type FormInstance, Input, Switch } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { z } from "zod/v4";
import { type AccessConfigForBaotaPanel } from "@/domain/access";
@ -26,7 +26,7 @@ const AccessFormBaotaPanelConfig = ({ form: formInst, formName, disabled, initia
const { t } = useTranslation();
const formSchema = z.object({
serverUrl: z.string().url(t("common.errmsg.url_invalid")),
serverUrl: z.url(t("common.errmsg.url_invalid")),
apiKey: z.string().nonempty(t("access.form.baotapanel_api_key.placeholder")),
allowInsecureConnections: z.boolean().nullish(),
});

View File

@ -1,7 +1,7 @@
import { useTranslation } from "react-i18next";
import { Form, type FormInstance, Input, Switch } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { z } from "zod/v4";
import { type AccessConfigForBaotaWAF } from "@/domain/access";
@ -26,7 +26,7 @@ const AccessFormBaotaWAFConfig = ({ form: formInst, formName, disabled, initialV
const { t } = useTranslation();
const formSchema = z.object({
serverUrl: z.string().url(t("common.errmsg.url_invalid")),
serverUrl: z.url(t("common.errmsg.url_invalid")),
apiKey: z.string().nonempty(t("access.form.baotawaf_api_key.placeholder")),
allowInsecureConnections: z.boolean().nullish(),
});

View File

@ -1,7 +1,7 @@
import { useTranslation } from "react-i18next";
import { Form, type FormInstance, Input } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { z } from "zod/v4";
import { type AccessConfigForBunny } from "@/domain/access";

View File

@ -1,7 +1,7 @@
import { useTranslation } from "react-i18next";
import { Form, type FormInstance, Input } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { z } from "zod/v4";
import { type AccessConfigForBytePlus } from "@/domain/access";

View File

@ -1,7 +1,7 @@
import { useTranslation } from "react-i18next";
import { Form, type FormInstance, Input } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { z } from "zod/v4";
import { type AccessConfigForCMCCCloud } from "@/domain/access";
type AccessFormCMCCCloudConfigFieldValues = Nullish<AccessConfigForCMCCCloud>;

View File

@ -1,7 +1,7 @@
import { useTranslation } from "react-i18next";
import { Form, type FormInstance, Input } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { z } from "zod/v4";
import { type AccessConfigForCTCCCloud } from "@/domain/access";
type AccessFormCTCCCloudConfigFieldValues = Nullish<AccessConfigForCTCCCloud>;

View File

@ -1,7 +1,7 @@
import { useTranslation } from "react-i18next";
import { Form, type FormInstance, Input } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { z } from "zod/v4";
import { type AccessConfigForCacheFly } from "@/domain/access";
@ -25,10 +25,7 @@ const AccessFormCacheFlyConfig = ({ form: formInst, formName, disabled, initialV
const { t } = useTranslation();
const formSchema = z.object({
apiToken: z
.string()
.min(1, t("access.form.cachefly_api_token.placeholder"))
.max(64, t("common.errmsg.string_max", { max: 64 })),
apiToken: z.string().nonempty(t("access.form.cachefly_api_token.placeholder")),
});
const formRule = createSchemaFieldRule(formSchema);

View File

@ -1,7 +1,7 @@
import { useTranslation } from "react-i18next";
import { Form, type FormInstance, Input, Switch } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { z } from "zod/v4";
import { type AccessConfigForCdnfly } from "@/domain/access";
@ -27,7 +27,7 @@ const AccessFormCdnflyConfig = ({ form: formInst, formName, disabled, initialVal
const { t } = useTranslation();
const formSchema = z.object({
serverUrl: z.string().url(t("common.errmsg.url_invalid")),
serverUrl: z.url(t("common.errmsg.url_invalid")),
apiKey: z
.string()
.min(1, t("access.form.cdnfly_api_key.placeholder"))

View File

@ -1,7 +1,7 @@
import { useTranslation } from "react-i18next";
import { Form, type FormInstance, Input } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { z } from "zod/v4";
import { type AccessConfigForClouDNS } from "@/domain/access";

View File

@ -1,7 +1,7 @@
import { useTranslation } from "react-i18next";
import { Form, type FormInstance, Input } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { z } from "zod/v4";
import { type AccessConfigForCloudflare } from "@/domain/access";

View File

@ -1,7 +1,7 @@
import { useTranslation } from "react-i18next";
import { Form, type FormInstance, Input } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { z } from "zod/v4";
import { type AccessConfigForConstellix } from "@/domain/access";
type AccessFormConstellixConfigFieldValues = Nullish<AccessConfigForConstellix>;

View File

@ -1,7 +1,7 @@
import { useTranslation } from "react-i18next";
import { Form, type FormInstance, Input } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { z } from "zod/v4";
import { type AccessConfigForDNSLA } from "@/domain/access";

View File

@ -1,7 +1,7 @@
import { useTranslation } from "react-i18next";
import { Form, type FormInstance, Input } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { z } from "zod/v4";
import { type AccessConfigForDeSEC } from "@/domain/access";

View File

@ -1,7 +1,7 @@
import { useTranslation } from "react-i18next";
import { Form, type FormInstance, Input } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { z } from "zod/v4";
import { type AccessConfigForDigitalOcean } from "@/domain/access";

View File

@ -1,7 +1,7 @@
import { useTranslation } from "react-i18next";
import { Form, type FormInstance, Input } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { z } from "zod/v4";
import { type AccessConfigForDingTalkBot } from "@/domain/access";
@ -26,7 +26,7 @@ const AccessFormDingTalkBotConfig = ({ form: formInst, formName, disabled, initi
const { t } = useTranslation();
const formSchema = z.object({
webhookUrl: z.string().url(t("common.errmsg.url_invalid")),
webhookUrl: z.url(t("common.errmsg.url_invalid")),
secret: z.string().nonempty(t("access.form.dingtalkbot_secret.placeholder")),
});
const formRule = createSchemaFieldRule(formSchema);

View File

@ -1,7 +1,7 @@
import { useTranslation } from "react-i18next";
import { Form, type FormInstance, Input } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { z } from "zod/v4";
import { type AccessConfigForDiscordBot } from "@/domain/access";
@ -26,7 +26,7 @@ const AccessFormDiscordBotConfig = ({ form: formInst, formName, disabled, initia
const formSchema = z.object({
botToken: z
.string({ message: t("access.form.discordbot_token.placeholder") })
.string(t("access.form.discordbot_token.placeholder"))
.min(1, t("access.form.discordbot_token.placeholder"))
.max(256, t("common.errmsg.string_max", { max: 256 })),
defaultChannelId: z.string().nullish(),

View File

@ -1,7 +1,7 @@
import { useTranslation } from "react-i18next";
import { Form, type FormInstance, Input } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { z } from "zod/v4";
import { type AccessConfigForDogeCloud } from "@/domain/access";

View File

@ -1,7 +1,7 @@
import { useTranslation } from "react-i18next";
import { Form, type FormInstance, Input } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { z } from "zod/v4";
import { type AccessConfigForDuckDNS } from "@/domain/access";

View File

@ -1,7 +1,7 @@
import { useTranslation } from "react-i18next";
import { Form, type FormInstance, Input } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { z } from "zod/v4";
import { type AccessConfigForDynv6 } from "@/domain/access";

View File

@ -1,7 +1,7 @@
import { useTranslation } from "react-i18next";
import { Form, type FormInstance, Input } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { z } from "zod/v4";
import { type AccessConfigForEdgio } from "@/domain/access";

View File

@ -1,7 +1,7 @@
import { useTranslation } from "react-i18next";
import { Form, type FormInstance, Input, InputNumber, Switch } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { z } from "zod/v4";
import { type AccessConfigForEmail } from "@/domain/access";
import { validEmailAddress, validPortNumber } from "@/utils/validators";

View File

@ -1,7 +1,7 @@
import { useTranslation } from "react-i18next";
import { Form, type FormInstance, Input, Radio, Switch } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { z } from "zod/v4";
import { type AccessConfigForFlexCDN } from "@/domain/access";
@ -28,10 +28,8 @@ const AccessFormFlexCDNConfig = ({ form: formInst, formName, disabled, initialVa
const { t } = useTranslation();
const formSchema = z.object({
serverUrl: z.string().url(t("common.errmsg.url_invalid")),
role: z.union([z.literal("user"), z.literal("admin")], {
message: t("access.form.flexcdn_api_role.placeholder"),
}),
serverUrl: z.url(t("common.errmsg.url_invalid")),
role: z.literal(["user", "admin"], t("access.form.flexcdn_api_role.placeholder")),
accessKeyId: z.string().nonempty(t("access.form.flexcdn_access_key_id.placeholder")),
accessKey: z.string().nonempty(t("access.form.flexcdn_access_key.placeholder")),
allowInsecureConnections: z.boolean().nullish(),

View File

@ -1,7 +1,7 @@
import { useTranslation } from "react-i18next";
import { Form, type FormInstance, Input } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { z } from "zod/v4";
import { type AccessConfigForGcore } from "@/domain/access";

View File

@ -1,7 +1,7 @@
import { useTranslation } from "react-i18next";
import { Form, type FormInstance, Input } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { z } from "zod/v4";
import { type AccessConfigForGname } from "@/domain/access";

View File

@ -1,7 +1,7 @@
import { useTranslation } from "react-i18next";
import { Form, type FormInstance, Input } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { z } from "zod/v4";
import { type AccessConfigForGoDaddy } from "@/domain/access";

View File

@ -1,7 +1,7 @@
import { useTranslation } from "react-i18next";
import { Form, type FormInstance, Input, Radio, Switch } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { z } from "zod/v4";
import { type AccessConfigForGoEdge } from "@/domain/access";
@ -28,10 +28,8 @@ const AccessFormGoEdgeConfig = ({ form: formInst, formName, disabled, initialVal
const { t } = useTranslation();
const formSchema = z.object({
serverUrl: z.string().url(t("common.errmsg.url_invalid")),
role: z.union([z.literal("user"), z.literal("admin")], {
message: t("access.form.goedge_api_role.placeholder"),
}),
serverUrl: z.url(t("common.errmsg.url_invalid")),
role: z.literal(["user", "admin"], t("access.form.goedge_api_role.placeholder")),
accessKeyId: z.string().nonempty(t("access.form.goedge_access_key_id.placeholder")),
accessKey: z.string().nonempty(t("access.form.goedge_access_key.placeholder")),
allowInsecureConnections: z.boolean().nullish(),

View File

@ -1,7 +1,7 @@
import { useTranslation } from "react-i18next";
import { Form, type FormInstance, Input } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { z } from "zod/v4";
import { type AccessConfigForGoogleTrustServices } from "@/domain/access";

View File

@ -1,7 +1,7 @@
import { useTranslation } from "react-i18next";
import { Form, type FormInstance, Input } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { z } from "zod/v4";
import { type AccessConfigForHetzner } from "@/domain/access";

View File

@ -1,7 +1,7 @@
import { useTranslation } from "react-i18next";
import { Form, type FormInstance, Input } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { z } from "zod/v4";
import { type AccessConfigForHuaweiCloud } from "@/domain/access";

View File

@ -1,7 +1,7 @@
import { useTranslation } from "react-i18next";
import { Form, type FormInstance, Input } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { z } from "zod/v4";
import { type AccessConfigForJDCloud } from "@/domain/access";

View File

@ -1,7 +1,7 @@
import { useTranslation } from "react-i18next";
import { Form, type FormInstance } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { z } from "zod/v4";
import TextFileInput from "@/components/TextFileInput";
import { type AccessConfigForKubernetes } from "@/domain/access";

View File

@ -1,7 +1,7 @@
import { useTranslation } from "react-i18next";
import { Form, type FormInstance, Input } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { z } from "zod/v4";
import { type AccessConfigForLarkBot } from "@/domain/access";
@ -25,7 +25,7 @@ const AccessFormLarkBotConfig = ({ form: formInst, formName, disabled, initialVa
const { t } = useTranslation();
const formSchema = z.object({
webhookUrl: z.string().url(t("common.errmsg.url_invalid")),
webhookUrl: z.url(t("common.errmsg.url_invalid")),
});
const formRule = createSchemaFieldRule(formSchema);

View File

@ -1,7 +1,7 @@
import { useTranslation } from "react-i18next";
import { Form, type FormInstance, Input, Radio, Select, Switch } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { z } from "zod/v4";
import { type AccessConfigForLeCDN } from "@/domain/access";
@ -29,10 +29,8 @@ const AccessFormLeCDNConfig = ({ form: formInst, formName, disabled, initialValu
const { t } = useTranslation();
const formSchema = z.object({
serverUrl: z.string().url(t("common.errmsg.url_invalid")),
role: z.union([z.literal("client"), z.literal("master")], {
message: t("access.form.lecdn_api_role.placeholder"),
}),
serverUrl: z.url(t("common.errmsg.url_invalid")),
role: z.literal(["client", "master"], t("access.form.lecdn_api_role.placeholder")),
username: z.string().nonempty(t("access.form.lecdn_username.placeholder")),
password: z.string().nonempty(t("access.form.lecdn_password.placeholder")),
allowInsecureConnections: z.boolean().nullish(),

View File

@ -1,7 +1,7 @@
import { useTranslation } from "react-i18next";
import { Form, type FormInstance, Input } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { z } from "zod/v4";
import { type AccessConfigForMattermost } from "@/domain/access";
@ -27,7 +27,7 @@ const AccessFormMattermostConfig = ({ form: formInst, formName, disabled, initia
const { t } = useTranslation();
const formSchema = z.object({
serverUrl: z.string().url(t("common.errmsg.url_invalid")),
serverUrl: z.url(t("common.errmsg.url_invalid")),
username: z.string().nonempty(t("access.form.mattermost_username.placeholder")),
password: z.string().nonempty(t("access.form.mattermost_password.placeholder")),
defaultChannelId: z.string().nullish(),

View File

@ -1,7 +1,7 @@
import { useTranslation } from "react-i18next";
import { Form, type FormInstance, Input } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { z } from "zod/v4";
import { type AccessConfigForNS1 } from "@/domain/access";

View File

@ -1,7 +1,7 @@
import { useTranslation } from "react-i18next";
import { Form, type FormInstance, Input } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { z } from "zod/v4";
import { type AccessConfigForNameDotCom } from "@/domain/access";

View File

@ -1,7 +1,7 @@
import { useTranslation } from "react-i18next";
import { Form, type FormInstance, Input } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { z } from "zod/v4";
import { type AccessConfigForNameSilo } from "@/domain/access";

View File

@ -1,7 +1,7 @@
import { useTranslation } from "react-i18next";
import { Form, type FormInstance, Input } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { z } from "zod/v4";
import { type AccessConfigForNamecheap } from "@/domain/access";

View File

@ -1,7 +1,7 @@
import { useTranslation } from "react-i18next";
import { Form, type FormInstance, Input } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { z } from "zod/v4";
import { type AccessConfigForNetcup } from "@/domain/access";

View File

@ -1,7 +1,7 @@
import { useTranslation } from "react-i18next";
import { Form, type FormInstance, Input } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { z } from "zod/v4";
import { type AccessConfigForNetlify } from "@/domain/access";

View File

@ -1,7 +1,7 @@
import { useTranslation } from "react-i18next";
import { Form, type FormInstance, Input } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { z } from "zod/v4";
import { type AccessConfigForPorkbun } from "@/domain/access";

View File

@ -1,7 +1,7 @@
import { useTranslation } from "react-i18next";
import { Form, type FormInstance, Input, Switch } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { z } from "zod/v4";
import { type AccessConfigForPowerDNS } from "@/domain/access";
@ -26,7 +26,7 @@ const AccessFormPowerDNSConfig = ({ form: formInst, formName, disabled, initialV
const { t } = useTranslation();
const formSchema = z.object({
serverUrl: z.string().url(t("common.errmsg.url_invalid")),
serverUrl: z.url(t("common.errmsg.url_invalid")),
apiKey: z
.string()
.min(1, t("access.form.powerdns_api_key.placeholder"))

View File

@ -1,7 +1,7 @@
import { useTranslation } from "react-i18next";
import { Form, type FormInstance, Input, Switch } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { z } from "zod/v4";
import { type AccessConfigForProxmoxVE } from "@/domain/access";
@ -26,7 +26,7 @@ const AccessFormProxmoxVEConfig = ({ form: formInst, formName, disabled, initial
const { t } = useTranslation();
const formSchema = z.object({
serverUrl: z.string().url(t("common.errmsg.url_invalid")),
serverUrl: z.url(t("common.errmsg.url_invalid")),
apiToken: z.string().nonempty(t("access.form.proxmoxve_api_token.placeholder")),
apiTokenSecret: z.string().nullish(),
allowInsecureConnections: z.boolean().nullish(),

View File

@ -1,7 +1,7 @@
import { useTranslation } from "react-i18next";
import { Form, type FormInstance, Input } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { z } from "zod/v4";
import { type AccessConfigForQiniu } from "@/domain/access";

View File

@ -1,7 +1,7 @@
import { useTranslation } from "react-i18next";
import { Form, type FormInstance, Input } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { z } from "zod/v4";
import { type AccessConfigForRainYun } from "@/domain/access";

View File

@ -1,7 +1,7 @@
import { useTranslation } from "react-i18next";
import { Form, type FormInstance, Input, Switch } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { z } from "zod/v4";
import { type AccessConfigForRatPanel } from "@/domain/access";
@ -27,7 +27,7 @@ const AccessFormRatPanelConfig = ({ form: formInst, formName, disabled, initialV
const { t } = useTranslation();
const formSchema = z.object({
serverUrl: z.string().url(t("common.errmsg.url_invalid")),
serverUrl: z.url(t("common.errmsg.url_invalid")),
accessTokenId: z.preprocess((v) => Number(v), z.number().positive(t("access.form.ratpanel_access_token_id.placeholder"))),
accessToken: z.string().nonempty(t("access.form.ratpanel_access_token.placeholder")),
allowInsecureConnections: z.boolean().nullish(),

View File

@ -2,7 +2,7 @@ import { useTranslation } from "react-i18next";
import { ArrowDownOutlined, ArrowUpOutlined, CloseOutlined, PlusOutlined } from "@ant-design/icons";
import { Button, Collapse, Form, type FormInstance, Input, InputNumber, Select, Space } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { z } from "zod/v4";
import Show from "@/components/Show";
import TextFileInput from "@/components/TextFileInput";
@ -44,9 +44,7 @@ const AccessFormSSHConfig = ({ form: formInst, formName, disabled, initialValues
.int(t("access.form.ssh_port.placeholder"))
.refine((v) => validPortNumber(v), t("common.errmsg.port_invalid"))
),
authMethod: z.union([z.literal(AUTH_METHOD_NONE), z.literal(AUTH_METHOD_PASSWORD), z.literal(AUTH_METHOD_KEY)], {
message: t("access.form.ssh_auth_method.placeholder"),
}),
authMethod: z.literal([AUTH_METHOD_NONE, AUTH_METHOD_PASSWORD, AUTH_METHOD_KEY], t("access.form.ssh_auth_method.placeholder")),
username: z
.string()
.min(1, t("access.form.ssh_username.placeholder"))
@ -55,12 +53,18 @@ const AccessFormSSHConfig = ({ form: formInst, formName, disabled, initialValues
.string()
.max(64, t("common.errmsg.string_max", { max: 64 }))
.nullish()
.refine((v) => fieldAuthMethod !== AUTH_METHOD_PASSWORD || !!v?.trim(), t("access.form.ssh_password.placeholder")),
.refine((v) => {
if (fieldAuthMethod !== AUTH_METHOD_PASSWORD) return true;
return !!v?.trim();
}, t("access.form.ssh_password.placeholder")),
key: z
.string()
.max(20480, t("common.errmsg.string_max", { max: 20480 }))
.nullish()
.refine((v) => fieldAuthMethod !== AUTH_METHOD_KEY || !!v?.trim(), t("access.form.ssh_key.placeholder")),
.refine((v) => {
if (fieldAuthMethod !== AUTH_METHOD_KEY) return true;
return !!v?.trim();
}, t("access.form.ssh_key.placeholder")),
keyPassphrase: z
.string()
.max(20480, t("common.errmsg.string_max", { max: 20480 }))
@ -77,9 +81,7 @@ const AccessFormSSHConfig = ({ form: formInst, formName, disabled, initialValues
.int(t("access.form.ssh_port.placeholder"))
.refine((v) => validPortNumber(v), t("common.errmsg.port_invalid"))
),
authMethod: z.union([z.literal(AUTH_METHOD_NONE), z.literal(AUTH_METHOD_PASSWORD), z.literal(AUTH_METHOD_KEY)], {
message: t("access.form.ssh_auth_method.placeholder"),
}),
authMethod: z.literal([AUTH_METHOD_NONE, AUTH_METHOD_PASSWORD, AUTH_METHOD_KEY], t("access.form.ssh_auth_method.placeholder")),
username: z
.string()
.min(1, t("access.form.ssh_username.placeholder"))
@ -97,7 +99,7 @@ const AccessFormSSHConfig = ({ form: formInst, formName, disabled, initialValues
.max(20480, t("common.errmsg.string_max", { max: 20480 }))
.nullish(),
}),
{ message: t("access.form.ssh_jump_servers.errmsg.invalid") }
{ error: t("access.form.ssh_jump_servers.errmsg.invalid") }
)
.nullish(),
});

View File

@ -1,7 +1,7 @@
import { useTranslation } from "react-i18next";
import { Form, type FormInstance, Input } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { z } from "zod/v4";
import { type AccessConfigForSSLCom } from "@/domain/access";

Some files were not shown because too many files have changed in this diff Show More