mirror of
https://github.com/certimate-go/certimate.git
synced 2026-09-24 23:10:13 +08:00
feat(provider): new deployment provider: tencentcloud ga2
This commit is contained in:
@@ -67,7 +67,8 @@ require (
|
||||
github.com/spf13/pflag v1.0.10
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cdn v1.3.90
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/clb v1.3.105
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.3.112
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.3.113
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ga2 v1.3.113
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/gaap v1.3.34
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/live v1.3.103
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/scf v1.3.101
|
||||
|
||||
@@ -905,8 +905,11 @@ github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.3.103/go.mod
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.3.105/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.3.107/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.3.111/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.3.112 h1:PNCN4HXHVAfG87Msvelk7Ks5MhotAXk2vqPVvfy1Epw=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.3.112/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.3.113 h1:kDwta48HDOTca5opVg66MUoSmD5gvDXKf0OFEWcnDqM=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.3.113/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ga2 v1.3.113 h1:3bIFxCPMNzAVt3f4BKuya4egCCXf9L5DmAZxZX4UQM4=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ga2 v1.3.113/go.mod h1:F0YNVLpyAjYLg6unFc+R873i5YUwyXE/Vlf/lidlu6s=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/gaap v1.3.34 h1:/QJeztyMC2tYPJceIoObx7LZqqgFcdDM0SQ/Wd0RtEI=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/gaap v1.3.34/go.mod h1:LiTqyLKs+CUdXeiTezJrsMcgi1RhVQ2gFuCcDxQBK9U=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/live v1.3.103 h1:fQVRiT5cGIjomdYOJiy0lWBvBO71AaUTdXSu4/u2NwM=
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
package deployers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/certimate-go/certimate/internal/domain"
|
||||
"github.com/certimate-go/certimate/pkg/core"
|
||||
dplyimpl "github.com/certimate-go/certimate/pkg/core/deployer/providers/tencentcloud-ga2"
|
||||
xmaps "github.com/certimate-go/certimate/pkg/utils/maps"
|
||||
)
|
||||
|
||||
func init() {
|
||||
Registries.MustRegister(domain.DeploymentProviderTypeTencentCloudGA2, func(options *ProviderFactoryOptions) (core.Deployer, error) {
|
||||
credentials := domain.AccessConfigForTencentCloud{}
|
||||
if err := xmaps.Populate(options.ProviderAccessConfig, &credentials); err != nil {
|
||||
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
||||
}
|
||||
|
||||
provider, err := dplyimpl.NewDeployer(&dplyimpl.DeployerConfig{
|
||||
SecretId: credentials.SecretId,
|
||||
SecretKey: credentials.SecretKey,
|
||||
ProjectId: credentials.ProjectId,
|
||||
Endpoint: xmaps.GetString(options.ProviderExtendedConfig, "endpoint"),
|
||||
DeployTarget: xmaps.GetString(options.ProviderExtendedConfig, "deployTarget"),
|
||||
AcceleratorId: xmaps.GetString(options.ProviderExtendedConfig, "acceleratorId"),
|
||||
ListenerId: xmaps.GetString(options.ProviderExtendedConfig, "listenerId"),
|
||||
})
|
||||
return provider, err
|
||||
})
|
||||
}
|
||||
@@ -414,6 +414,7 @@ const (
|
||||
DeploymentProviderTypeTencentCloudCSS = DeploymentProviderType(AccessProviderTypeTencentCloud + "-css")
|
||||
DeploymentProviderTypeTencentCloudECDN = DeploymentProviderType(AccessProviderTypeTencentCloud + "-ecdn")
|
||||
DeploymentProviderTypeTencentCloudEO = DeploymentProviderType(AccessProviderTypeTencentCloud + "-eo")
|
||||
DeploymentProviderTypeTencentCloudGA2 = DeploymentProviderType(AccessProviderTypeTencentCloud + "-ga2")
|
||||
DeploymentProviderTypeTencentCloudGAAP = DeploymentProviderType(AccessProviderTypeTencentCloud + "-gaap")
|
||||
DeploymentProviderTypeTencentCloudSCF = DeploymentProviderType(AccessProviderTypeTencentCloud + "-scf")
|
||||
DeploymentProviderTypeTencentCloudSSL = DeploymentProviderType(AccessProviderTypeTencentCloud + "-ssl")
|
||||
|
||||
@@ -0,0 +1,179 @@
|
||||
package tencentcloudgaap
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/samber/lo"
|
||||
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
|
||||
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile"
|
||||
|
||||
tcgaap "github.com/certimate-go/certimate/pkg/sdk3rd-trimmed/github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/gaap/v20180529"
|
||||
|
||||
"github.com/certimate-go/certimate/pkg/core"
|
||||
xcert "github.com/certimate-go/certimate/pkg/utils/cert"
|
||||
)
|
||||
|
||||
type (
|
||||
Provider = core.Certmgr
|
||||
UploadResult = core.CertmgrUploadResult
|
||||
ReplaceResult = core.CertmgrReplaceResult
|
||||
)
|
||||
|
||||
type CertmgrConfig struct {
|
||||
// 腾讯云 SecretId。
|
||||
SecretId string `json:"secretId"`
|
||||
// 腾讯云 SecretKey。
|
||||
SecretKey string `json:"secretKey"`
|
||||
// 腾讯云项目 ID。
|
||||
ProjectId int64 `json:"projectId,omitempty"`
|
||||
// 腾讯云接口端点。
|
||||
Endpoint string `json:"endpoint,omitempty"`
|
||||
}
|
||||
|
||||
type Certmgr struct {
|
||||
config *CertmgrConfig
|
||||
logger *slog.Logger
|
||||
sdkClient *tcgaap.Client
|
||||
}
|
||||
|
||||
var _ Provider = (*Certmgr)(nil)
|
||||
|
||||
func NewCertmgr(config *CertmgrConfig) (*Certmgr, error) {
|
||||
if config == nil {
|
||||
return nil, fmt.Errorf("the configuration of the certmgr provider is nil")
|
||||
}
|
||||
|
||||
client, err := createSDKClient(config.SecretId, config.SecretKey, config.Endpoint)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not create client: %w", err)
|
||||
}
|
||||
|
||||
return &Certmgr{
|
||||
config: config,
|
||||
logger: slog.Default(),
|
||||
sdkClient: client,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *Certmgr) SetLogger(logger *slog.Logger) {
|
||||
if logger == nil {
|
||||
c.logger = slog.New(slog.DiscardHandler)
|
||||
} else {
|
||||
c.logger = logger
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Certmgr) Upload(ctx context.Context, certPEM, privkeyPEM string) (*UploadResult, error) {
|
||||
// 解析证书内容
|
||||
certX509, err := xcert.ParseCertificateFromPEM(certPEM)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 查询服务器证书列表,避免重复上传
|
||||
// REF: https://cloud.tencent.com/document/api/1364/98588
|
||||
// REF: https://cloud.tencent.com/document/api/608/36978
|
||||
describeCertificatesOffset := 0
|
||||
describeCertificatesLimit := 100
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return nil, ctx.Err()
|
||||
default:
|
||||
}
|
||||
|
||||
describeCertificatesReq := tcgaap.NewDescribeCertificatesRequest()
|
||||
describeCertificatesReq.CertificateType = common.Int64Ptr(2)
|
||||
describeCertificatesReq.Offset = common.Uint64Ptr(uint64(describeCertificatesOffset))
|
||||
describeCertificatesReq.Limit = common.Uint64Ptr(uint64(describeCertificatesLimit))
|
||||
describeCertificatesResp, err := c.sdkClient.DescribeCertificatesWithContext(ctx, describeCertificatesReq)
|
||||
c.logger.Debug("sdk request 'gaap.DescribeCertificates'", slog.Any("request", describeCertificatesReq), slog.Any("response", describeCertificatesResp))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to execute sdk request 'gaap.DescribeCertificates': %w", err)
|
||||
}
|
||||
|
||||
for _, certItem := range describeCertificatesResp.Response.CertificateSet {
|
||||
// 对比证书通用名称
|
||||
if !strings.EqualFold(certX509.Subject.CommonName, lo.FromPtr(certItem.SubjectCN)) {
|
||||
continue
|
||||
}
|
||||
|
||||
// 对比证书有效期
|
||||
if certX509.NotBefore.Unix() != int64(lo.FromPtr(certItem.BeginTime)) ||
|
||||
certX509.NotAfter.Unix() != int64(lo.FromPtr(certItem.EndTime)) {
|
||||
continue
|
||||
}
|
||||
|
||||
// 对比证书内容
|
||||
describeCertificateDetailReq := tcgaap.NewDescribeCertificateDetailRequest()
|
||||
describeCertificateDetailReq.CertificateId = certItem.CertificateId
|
||||
describeCertificateDetailResp, err := c.sdkClient.DescribeCertificateDetailWithContext(ctx, describeCertificateDetailReq)
|
||||
c.logger.Debug("sdk request 'gaap.DescribeCertificateDetail'", slog.Any("request", describeCertificateDetailReq), slog.Any("response", describeCertificateDetailResp))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to execute sdk request 'gaap.DescribeCertificateDetail': %w", err)
|
||||
} else {
|
||||
if !xcert.EqualCertificatesFromPEM(certPEM, lo.FromPtr(describeCertificateDetailResp.Response.CertificateDetail.CertificateContent)) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// 如果以上信息都一致,则视为已存在相同证书,直接返回
|
||||
c.logger.Info("ssl certificate already exists")
|
||||
return &UploadResult{
|
||||
CertId: lo.FromPtr(certItem.CertificateId),
|
||||
CertName: lo.FromPtr(certItem.CertificateAlias),
|
||||
}, nil
|
||||
}
|
||||
|
||||
if len(describeCertificatesResp.Response.CertificateSet) < describeCertificatesLimit {
|
||||
break
|
||||
}
|
||||
|
||||
describeCertificatesOffset += describeCertificatesLimit
|
||||
}
|
||||
|
||||
// 生成新证书名(需符合腾讯云命名规则)
|
||||
certName := fmt.Sprintf("certimate_%d", time.Now().UnixMilli())
|
||||
|
||||
// 创建云原生网关证书
|
||||
// REF: https://cloud.tencent.com/document/api/608/36980
|
||||
createCertificateReq := tcgaap.NewCreateCertificateRequest()
|
||||
createCertificateReq.CertificateType = common.Int64Ptr(2)
|
||||
createCertificateReq.CertificateAlias = common.StringPtr(certName)
|
||||
createCertificateReq.CertificateContent = common.StringPtr(certPEM)
|
||||
createCertificateReq.CertificateKey = common.StringPtr(privkeyPEM)
|
||||
createCertificateResp, err := c.sdkClient.CreateCertificateWithContext(ctx, createCertificateReq)
|
||||
c.logger.Debug("sdk request 'gaap.CreateCertificate'", slog.Any("request", createCertificateReq), slog.Any("response", createCertificateResp))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to execute sdk request 'gaap.CreateCertificate': %w", err)
|
||||
}
|
||||
|
||||
return &UploadResult{
|
||||
CertId: lo.FromPtr(createCertificateResp.Response.CertificateId),
|
||||
CertName: certName,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *Certmgr) Replace(ctx context.Context, certIdOrName string, certPEM, privkeyPEM string) (*ReplaceResult, error) {
|
||||
return nil, core.ErrUnsupported
|
||||
}
|
||||
|
||||
func createSDKClient(secretId, secretKey, endpoint string) (*tcgaap.Client, error) {
|
||||
credential := common.NewCredential(secretId, secretKey)
|
||||
|
||||
cpf := profile.NewClientProfile()
|
||||
if endpoint != "" {
|
||||
cpf.HttpProfile.Endpoint = endpoint
|
||||
}
|
||||
|
||||
client, err := tcgaap.NewClient(credential, "", cpf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return client, nil
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package tencentcloudgaap_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/certimate-go/certimate/pkg/core/certmgr/internal/tester"
|
||||
impl "github.com/certimate-go/certimate/pkg/core/certmgr/providers/tencentcloud-gaap"
|
||||
)
|
||||
|
||||
var (
|
||||
fp = tester.Args("TENCENTCLOUDGAAP_")
|
||||
fTestCertPath string
|
||||
fTestKeyPath string
|
||||
fSecretId string
|
||||
fSecretKey string
|
||||
)
|
||||
|
||||
func init() {
|
||||
fp.DefineString(&fTestCertPath, "TESTCERTPATH")
|
||||
fp.DefineString(&fTestKeyPath, "TESTKEYPATH")
|
||||
fp.DefineString(&fSecretId, "SECRETID")
|
||||
fp.DefineString(&fSecretKey, "SECRETKEY")
|
||||
}
|
||||
|
||||
/*
|
||||
Shell command to run this test:
|
||||
|
||||
go test -v ./tencentcloud_gaap_test.go -args \
|
||||
--TENCENTCLOUDGAAP_TESTCERTPATH="/path/to/your-test-cert.pem" \
|
||||
--TENCENTCLOUDGAAP_TESTKEYPATH="/path/to/your-test-key.pem" \
|
||||
--TENCENTCLOUDGAAP_SECRETID="your-secret-id" \
|
||||
--TENCENTCLOUDGAAP_SECRETKEY="your-secret-key"
|
||||
*/
|
||||
func TestProvider(t *testing.T) {
|
||||
fp.Parse()
|
||||
|
||||
t.Run("Upload", func(t *testing.T) {
|
||||
provider, err := impl.NewCertmgr(&impl.CertmgrConfig{
|
||||
SecretId: fSecretId,
|
||||
SecretKey: fSecretKey,
|
||||
})
|
||||
if err != nil {
|
||||
t.Errorf("err: %+v", err)
|
||||
return
|
||||
}
|
||||
|
||||
tester.TestUpload(t, provider, tester.TestUploadArgs{CertPath: fTestCertPath, KeyPath: fTestKeyPath})
|
||||
})
|
||||
}
|
||||
@@ -46,9 +46,9 @@ type CertmgrConfig struct {
|
||||
}
|
||||
|
||||
type Certmgr struct {
|
||||
config *CertmgrConfig
|
||||
logger *slog.Logger
|
||||
sdkClient *wSDKClients
|
||||
config *CertmgrConfig
|
||||
logger *slog.Logger
|
||||
sdkClients *wSDKClients
|
||||
}
|
||||
|
||||
var _ Provider = (*Certmgr)(nil)
|
||||
@@ -63,15 +63,15 @@ func NewCertmgr(config *CertmgrConfig) (*Certmgr, error) {
|
||||
return nil, fmt.Errorf("the configuration of the certmgr provider is nil")
|
||||
}
|
||||
|
||||
client, err := createSDKClients(config.SecretId, config.SecretKey, config.Endpoint, config.Region)
|
||||
clients, err := createSDKClients(config.SecretId, config.SecretKey, config.Endpoint, config.Region)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not create client: %w", err)
|
||||
}
|
||||
|
||||
return &Certmgr{
|
||||
config: config,
|
||||
logger: slog.Default(),
|
||||
sdkClient: client,
|
||||
config: config,
|
||||
logger: slog.Default(),
|
||||
sdkClients: clients,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -117,7 +117,7 @@ func (c *Certmgr) uploadToCloudNative(ctx context.Context, certPEM, privkeyPEM s
|
||||
uploadCertificateReq.CertificatePublicKey = common.StringPtr(certPEM)
|
||||
uploadCertificateReq.CertificatePrivateKey = common.StringPtr(privkeyPEM)
|
||||
uploadCertificateReq.Repeatable = common.BoolPtr(false)
|
||||
uploadCertificateResp, err := c.sdkClient.SSL.UploadCertificateWithContext(ctx, uploadCertificateReq)
|
||||
uploadCertificateResp, err := c.sdkClients.SSL.UploadCertificateWithContext(ctx, uploadCertificateReq)
|
||||
c.logger.Debug("sdk request 'ssl.UploadCertificate'", slog.Any("request", uploadCertificateReq), slog.Any("response", uploadCertificateResp))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to execute sdk request 'ssl.UploadCertificate': %w", err)
|
||||
@@ -138,7 +138,7 @@ func (c *Certmgr) uploadToCloudNative(ctx context.Context, certPEM, privkeyPEM s
|
||||
describeCloudNativeAPIGatewayCertificatesReq.GatewayId = common.StringPtr(c.config.GatewayId)
|
||||
describeCloudNativeAPIGatewayCertificatesReq.Offset = common.Int64Ptr(int64(describeCloudNativeAPIGatewayCertificatesOffset))
|
||||
describeCloudNativeAPIGatewayCertificatesReq.Limit = common.Int64Ptr(int64(describeCloudNativeAPIGatewayCertificatesLimit))
|
||||
describeCloudNativeAPIGatewayCertificatesResp, err := c.sdkClient.TSE.DescribeCloudNativeAPIGatewayCertificatesWithContext(ctx, describeCloudNativeAPIGatewayCertificatesReq)
|
||||
describeCloudNativeAPIGatewayCertificatesResp, err := c.sdkClients.TSE.DescribeCloudNativeAPIGatewayCertificatesWithContext(ctx, describeCloudNativeAPIGatewayCertificatesReq)
|
||||
c.logger.Debug("sdk request 'tse.DescribeCloudNativeAPIGatewayCertificates'", slog.Any("request", describeCloudNativeAPIGatewayCertificatesReq), slog.Any("response", describeCloudNativeAPIGatewayCertificatesResp))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to execute sdk request 'tse.DescribeCloudNativeAPIGatewayCertificates': %w", err)
|
||||
@@ -173,7 +173,7 @@ func (c *Certmgr) uploadToCloudNative(ctx context.Context, certPEM, privkeyPEM s
|
||||
createCloudNativeAPIGatewayCertificateReq.Name = common.StringPtr(certName)
|
||||
createCloudNativeAPIGatewayCertificateReq.CertId = uploadCertificateResp.Response.CertificateId
|
||||
createCloudNativeAPIGatewayCertificateReq.BindDomains = common.StringPtrs(lo.Ternary(len(c.config.Domains) != 0, c.config.Domains, certX509.DNSNames))
|
||||
createCloudNativeAPIGatewayCertificateResp, err := c.sdkClient.TSE.CreateCloudNativeAPIGatewayCertificateWithContext(ctx, createCloudNativeAPIGatewayCertificateReq)
|
||||
createCloudNativeAPIGatewayCertificateResp, err := c.sdkClients.TSE.CreateCloudNativeAPIGatewayCertificateWithContext(ctx, createCloudNativeAPIGatewayCertificateReq)
|
||||
c.logger.Debug("sdk request 'tse.CreateCloudNativeAPIGatewayCertificate'", slog.Any("request", createCloudNativeAPIGatewayCertificateReq), slog.Any("response", createCloudNativeAPIGatewayCertificateResp))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to execute sdk request 'tse.CreateCloudNativeAPIGatewayCertificate': %w", err)
|
||||
@@ -194,7 +194,7 @@ func (c *Certmgr) replaceToCloudNative(ctx context.Context, certIdOrName string,
|
||||
modifyCloudNativeAPIGatewayCertificateReq.Crt = common.StringPtr(certPEM)
|
||||
modifyCloudNativeAPIGatewayCertificateReq.Key = common.StringPtr(privkeyPEM)
|
||||
modifyCloudNativeAPIGatewayCertificateReq.CertSource = common.StringPtr("native")
|
||||
modifyCloudNativeAPIGatewayCertificateResp, err := c.sdkClient.TSE.ModifyCloudNativeAPIGatewayCertificateWithContext(ctx, modifyCloudNativeAPIGatewayCertificateReq)
|
||||
modifyCloudNativeAPIGatewayCertificateResp, err := c.sdkClients.TSE.ModifyCloudNativeAPIGatewayCertificateWithContext(ctx, modifyCloudNativeAPIGatewayCertificateReq)
|
||||
c.logger.Debug("sdk request 'tse.ModifyCloudNativeAPIGatewayCertificate'", slog.Any("request", modifyCloudNativeAPIGatewayCertificateReq), slog.Any("response", modifyCloudNativeAPIGatewayCertificateResp))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to execute sdk request 'tse.ModifyCloudNativeAPIGatewayCertificate': %w", err)
|
||||
|
||||
@@ -376,15 +376,14 @@ func (d *Deployer) updateListenerCertificate(ctx context.Context, cloudListenerI
|
||||
errs = append(errs, fmt.Errorf("failed to execute sdk request 'cas.GetCertificateDetail': %w", err))
|
||||
continue
|
||||
} else {
|
||||
certCNMatched := tea.StringValue(getCertificateDetailResp.Body.CommonName) == d.config.Domain
|
||||
certSANDiff, _ := lo.Difference(tea.StringSliceValue(getCertificateDetailResp.Body.SubjectAlternativeNames), cloudCertSANs)
|
||||
if certCNMatched || len(certSANDiff) == 0 {
|
||||
if len(certSANDiff) == 0 { // 同域名证书需要删除
|
||||
certificateIdsToDissociate = append(certificateIdsToDissociate, certIdWithRegion)
|
||||
continue
|
||||
}
|
||||
|
||||
certNotAfter := time.Unix(tea.Int64Value(getCertificateDetailResp.Body.NotAfter)/1000, 0)
|
||||
if certNotAfter.Before(time.Now()) {
|
||||
if certNotAfter.Before(time.Now()) { // 过期证书需要删除
|
||||
certificateIdsToDissociate = append(certificateIdsToDissociate, certIdWithRegion)
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -212,13 +212,17 @@ func (d *Deployer) checkIsBind(ctx context.Context, cloudCertId string) (bool, e
|
||||
}
|
||||
|
||||
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
|
||||
wsdk := &wSDKClients{}
|
||||
|
||||
{
|
||||
credential := common.NewCredential(secretId, secretKey)
|
||||
client, err := tcssl.NewClient(credential, region, profile.NewClientProfile())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
wsdk.SSL = client
|
||||
}
|
||||
|
||||
return &wSDKClients{
|
||||
SSL: client,
|
||||
}, nil
|
||||
return wsdk, nil
|
||||
}
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
package tencentcloudga2
|
||||
|
||||
const (
|
||||
// 部署目标:部署到指定监听器。
|
||||
DEPLOY_TARGET_LISTENER = "listener"
|
||||
)
|
||||
@@ -0,0 +1,247 @@
|
||||
package tencentcloudga2
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"strings"
|
||||
|
||||
"github.com/samber/lo"
|
||||
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
|
||||
tcerrors "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/errors"
|
||||
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile"
|
||||
|
||||
tcga2 "github.com/certimate-go/certimate/pkg/sdk3rd-trimmed/github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ga2/v20250115"
|
||||
tcssl "github.com/certimate-go/certimate/pkg/sdk3rd-trimmed/github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssl/v20191205"
|
||||
|
||||
"github.com/certimate-go/certimate/pkg/core"
|
||||
cmgrimpl "github.com/certimate-go/certimate/pkg/core/certmgr/providers/tencentcloud-ssl"
|
||||
xcert "github.com/certimate-go/certimate/pkg/utils/cert"
|
||||
)
|
||||
|
||||
type (
|
||||
Provider = core.Deployer
|
||||
DeployResult = core.DeployerDeployResult
|
||||
)
|
||||
|
||||
type DeployerConfig struct {
|
||||
// 腾讯云 SecretId。
|
||||
SecretId string `json:"secretId"`
|
||||
// 腾讯云 SecretKey。
|
||||
SecretKey string `json:"secretKey"`
|
||||
// 腾讯云项目 ID。
|
||||
ProjectId int64 `json:"projectId,omitempty"`
|
||||
// 腾讯云接口端点。
|
||||
Endpoint string `json:"endpoint,omitempty"`
|
||||
// 部署目标。
|
||||
DeployTarget string `json:"deployTarget"`
|
||||
// 全球加速实例 ID。
|
||||
// 部署目标为 [DEPLOY_TARGET_LISTENER] 时必填。
|
||||
AcceleratorId string `json:"acceleratorId,omitempty"`
|
||||
// 监听器 ID。
|
||||
// 部署目标为 [DEPLOY_TARGET_LISTENER] 时必填。
|
||||
ListenerId string `json:"listenerId,omitempty"`
|
||||
}
|
||||
|
||||
type Deployer struct {
|
||||
config *DeployerConfig
|
||||
logger *slog.Logger
|
||||
sdkClients *wSDKClients
|
||||
sdkCertmgr core.Certmgr
|
||||
}
|
||||
|
||||
var _ Provider = (*Deployer)(nil)
|
||||
|
||||
type wSDKClients struct {
|
||||
GA2 *tcga2.Client
|
||||
SSL *tcssl.Client
|
||||
}
|
||||
|
||||
func NewDeployer(config *DeployerConfig) (*Deployer, error) {
|
||||
if config == nil {
|
||||
return nil, fmt.Errorf("the configuration of the deployer provider is nil")
|
||||
}
|
||||
|
||||
clients, err := createSDKClients(config.SecretId, config.SecretKey, config.Endpoint)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not create client: %w", err)
|
||||
}
|
||||
|
||||
pcertmgr, err := cmgrimpl.NewCertmgr(&cmgrimpl.CertmgrConfig{
|
||||
SecretId: config.SecretId,
|
||||
SecretKey: config.SecretKey,
|
||||
ProjectId: config.ProjectId,
|
||||
Endpoint: lo.
|
||||
If(strings.HasSuffix(config.Endpoint, "intl.tencentcloudapi.com"), "ssl.intl.tencentcloudapi.com"). // 国际站使用独立的接口端点
|
||||
Else(""),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not create certmgr: %w", err)
|
||||
}
|
||||
|
||||
return &Deployer{
|
||||
config: config,
|
||||
logger: slog.Default(),
|
||||
sdkClients: clients,
|
||||
sdkCertmgr: pcertmgr,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (d *Deployer) SetLogger(logger *slog.Logger) {
|
||||
if logger == nil {
|
||||
d.logger = slog.New(slog.DiscardHandler)
|
||||
} else {
|
||||
d.logger = logger
|
||||
}
|
||||
|
||||
d.sdkCertmgr.SetLogger(logger)
|
||||
}
|
||||
|
||||
func (d *Deployer) Deploy(ctx context.Context, certPEM, privkeyPEM string) (*DeployResult, error) {
|
||||
// 解析证书内容
|
||||
certX509, err := xcert.ParseCertificateFromPEM(certPEM)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 上传证书
|
||||
upres, err := d.sdkCertmgr.Upload(ctx, certPEM, privkeyPEM)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to upload certificate file: %w", err)
|
||||
} else {
|
||||
d.logger.Info("ssl certificate uploaded", slog.Any("result", upres))
|
||||
}
|
||||
|
||||
// 根据部署目标决定业务流程
|
||||
switch d.config.DeployTarget {
|
||||
case DEPLOY_TARGET_LISTENER:
|
||||
if err := d.deployToListener(ctx, upres.CertId, certX509.DNSNames); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported deploy target '%s'", d.config.DeployTarget)
|
||||
}
|
||||
|
||||
return &DeployResult{}, nil
|
||||
}
|
||||
|
||||
func (d *Deployer) deployToListener(ctx context.Context, cloudCertId string, cloudCertSANs []string) error {
|
||||
if d.config.AcceleratorId == "" {
|
||||
return fmt.Errorf("config `acceleratorId` is required")
|
||||
}
|
||||
if d.config.ListenerId == "" {
|
||||
return fmt.Errorf("config `listenerId` is required")
|
||||
}
|
||||
|
||||
// 更新监听器证书
|
||||
if err := d.updateListenerCertificate(ctx, d.config.AcceleratorId, d.config.ListenerId, cloudCertId, cloudCertSANs); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Deployer) updateListenerCertificate(ctx context.Context, cloudAcceleratorId, cloudListenerId, cloudCertId string, cloudCertSANs []string) error {
|
||||
// 查询监听器
|
||||
// REF: https://cloud.tencent.com/document/product/1817/130160
|
||||
describeListenersReq := tcga2.NewDescribeListenersRequest()
|
||||
describeListenersReq.GlobalAcceleratorId = common.StringPtr(cloudAcceleratorId)
|
||||
describeListenersReq.Filters = []*tcga2.Filter{
|
||||
{
|
||||
Name: common.StringPtr("listener-id"),
|
||||
Values: []*string{common.StringPtr(cloudListenerId)},
|
||||
},
|
||||
}
|
||||
describeListenersReq.Offset = common.Uint64Ptr(0)
|
||||
describeListenersReq.Limit = common.Uint64Ptr(1)
|
||||
describeListenersResp, err := d.sdkClients.GA2.DescribeListenersWithContext(ctx, describeListenersReq)
|
||||
d.logger.Debug("sdk request 'ga2.DescribeListeners'", slog.Any("request", describeListenersReq), slog.Any("response", describeListenersResp))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to execute sdk request 'ga2.DescribeListeners': %w", err)
|
||||
} else if len(describeListenersResp.Response.ListenerSet) == 0 {
|
||||
return fmt.Errorf("could not find listener '%s'", cloudListenerId)
|
||||
}
|
||||
|
||||
// 获取证书信息,避免重复绑定
|
||||
// REF: https://cloud.tencent.com/document/api/400/41674
|
||||
serverCertificateIds := make([]string, 0)
|
||||
for _, serverCertificateId := range describeListenersResp.Response.ListenerSet[0].ServerCertificates {
|
||||
if cloudCertId == lo.FromPtr(serverCertificateId) {
|
||||
return nil
|
||||
}
|
||||
|
||||
describeCertificateReq := tcssl.NewDescribeCertificateRequest()
|
||||
describeCertificateReq.CertificateId = serverCertificateId
|
||||
describeCertificateResp, err := d.sdkClients.SSL.DescribeCertificateWithContext(ctx, describeCertificateReq)
|
||||
d.logger.Debug("sdk request 'ssl.DescribeCertificate'", slog.Any("request", describeCertificateReq), slog.Any("response", describeCertificateResp))
|
||||
if err != nil {
|
||||
if sdkerr, ok := err.(*tcerrors.TencentCloudSDKError); ok {
|
||||
if sdkerr.Code == "FailedOperation.CertificateNotFound" {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
return fmt.Errorf("failed to execute sdk request 'ssl.DescribeCertificate': %w", err)
|
||||
} else {
|
||||
certSANDiff, _ := lo.Difference(lo.FromSlicePtr(describeCertificateResp.Response.SubjectAltName), cloudCertSANs)
|
||||
if len(certSANDiff) == 0 { // 同域名证书需要删除
|
||||
continue
|
||||
}
|
||||
|
||||
serverCertificateIds = append(serverCertificateIds, lo.FromPtr(serverCertificateId))
|
||||
}
|
||||
}
|
||||
|
||||
// 修改监听器
|
||||
// REF: https://cloud.tencent.com/document/product/1817/130155
|
||||
modifyListenerReq := tcga2.NewModifyListenerRequest()
|
||||
modifyListenerReq.GlobalAcceleratorId = common.StringPtr(cloudAcceleratorId)
|
||||
modifyListenerReq.ListenerId = common.StringPtr(cloudListenerId)
|
||||
modifyListenerReq.ServerCertificates = common.StringPtrs(append(serverCertificateIds, cloudCertId))
|
||||
modifyListenerResp, err := d.sdkClients.GA2.ModifyListenerWithContext(ctx, modifyListenerReq)
|
||||
d.logger.Debug("sdk request 'ga2.ModifyListener'", slog.Any("request", modifyListenerReq), slog.Any("response", modifyListenerResp))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to execute sdk request 'ga2.ModifyListener': %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func createSDKClients(secretId, secretKey, endpoint string) (*wSDKClients, error) {
|
||||
wsdk := &wSDKClients{}
|
||||
|
||||
{
|
||||
credential := common.NewCredential(secretId, secretKey)
|
||||
|
||||
cpf := profile.NewClientProfile()
|
||||
if endpoint != "" {
|
||||
cpf.HttpProfile.Endpoint = endpoint
|
||||
}
|
||||
|
||||
client, err := tcga2.NewClient(credential, "", cpf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
wsdk.GA2 = client
|
||||
}
|
||||
|
||||
{
|
||||
credential := common.NewCredential(secretId, secretKey)
|
||||
|
||||
cpf := profile.NewClientProfile()
|
||||
if strings.HasSuffix(endpoint, "intl.tencentcloudapi.com") {
|
||||
cpf.HttpProfile.Endpoint = "ssl.intl.tencentcloudapi.com"
|
||||
}
|
||||
|
||||
client, err := tcssl.NewClient(credential, "", cpf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
wsdk.SSL = client
|
||||
}
|
||||
|
||||
return wsdk, nil
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package tencentcloudga2_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/certimate-go/certimate/pkg/core/deployer/internal/tester"
|
||||
impl "github.com/certimate-go/certimate/pkg/core/deployer/providers/tencentcloud-ga2"
|
||||
)
|
||||
|
||||
var (
|
||||
fp = tester.Args("TENCENTCLOUDGA2_")
|
||||
fTestCertPath string
|
||||
fTestKeyPath string
|
||||
fSecretId string
|
||||
fSecretKey string
|
||||
fAcceleratorId string
|
||||
fListenerId string
|
||||
)
|
||||
|
||||
func init() {
|
||||
fp.DefineString(&fTestCertPath, "TESTCERTPATH")
|
||||
fp.DefineString(&fTestKeyPath, "TESTKEYPATH")
|
||||
fp.DefineString(&fSecretId, "SECRETID")
|
||||
fp.DefineString(&fSecretKey, "SECRETKEY")
|
||||
fp.DefineString(&fAcceleratorId, "ACCELERATORID")
|
||||
fp.DefineString(&fListenerId, "LISTENERID")
|
||||
}
|
||||
|
||||
/*
|
||||
Shell command to run this test:
|
||||
|
||||
go test -v ./tencentcloud_ga2_test.go -args \
|
||||
--TENCENTCLOUDGA2_TESTCERTPATH="/path/to/your-test-cert.pem" \
|
||||
--TENCENTCLOUDGA2_TESTKEYPATH="/path/to/your-test-key.pem" \
|
||||
--TENCENTCLOUDGA2_SECRETID="your-secret-id" \
|
||||
--TENCENTCLOUDGA2_SECRETKEY="your-secret-key" \
|
||||
--TENCENTCLOUDGA2_ACCELERATORID="your-ga2-accelerator-id" \
|
||||
--TENCENTCLOUDGA2_LISTENERID="your-ga2-listener-id"
|
||||
*/
|
||||
func TestProvider(t *testing.T) {
|
||||
fp.Parse()
|
||||
|
||||
t.Run("Deploy_ToListener", func(t *testing.T) {
|
||||
provider, err := impl.NewDeployer(&impl.DeployerConfig{
|
||||
SecretId: fSecretId,
|
||||
SecretKey: fSecretKey,
|
||||
DeployTarget: impl.DEPLOY_TARGET_LISTENER,
|
||||
AcceleratorId: fAcceleratorId,
|
||||
ListenerId: fListenerId,
|
||||
})
|
||||
if err != nil {
|
||||
t.Errorf("err: %+v", err)
|
||||
return
|
||||
}
|
||||
|
||||
tester.TestDeploy(t, provider, tester.TestDeployArgs{CertPath: fTestCertPath, KeyPath: fTestKeyPath})
|
||||
})
|
||||
}
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"strings"
|
||||
|
||||
"github.com/samber/lo"
|
||||
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
|
||||
@@ -13,7 +12,7 @@ import (
|
||||
tcgaap "github.com/certimate-go/certimate/pkg/sdk3rd-trimmed/github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/gaap/v20180529"
|
||||
|
||||
"github.com/certimate-go/certimate/pkg/core"
|
||||
cmgrimpl "github.com/certimate-go/certimate/pkg/core/certmgr/providers/tencentcloud-ssl"
|
||||
cmgrimpl "github.com/certimate-go/certimate/pkg/core/certmgr/providers/tencentcloud-gaap"
|
||||
)
|
||||
|
||||
type (
|
||||
@@ -35,7 +34,7 @@ type DeployerConfig struct {
|
||||
// 通道 ID。
|
||||
// 选填。
|
||||
ProxyId string `json:"proxyId,omitempty"`
|
||||
// 负载均衡监听 ID。
|
||||
// 监听器 ID。
|
||||
// 部署目标为 [DEPLOY_TARGET_LISTENER] 时必填。
|
||||
ListenerId string `json:"listenerId,omitempty"`
|
||||
}
|
||||
@@ -54,7 +53,7 @@ func NewDeployer(config *DeployerConfig) (*Deployer, error) {
|
||||
return nil, fmt.Errorf("the configuration of the deployer provider is nil")
|
||||
}
|
||||
|
||||
client, err := createSDKClients(config.SecretId, config.SecretKey, config.Endpoint)
|
||||
client, err := createSDKClient(config.SecretId, config.SecretKey, config.Endpoint)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not create client: %w", err)
|
||||
}
|
||||
@@ -63,9 +62,7 @@ func NewDeployer(config *DeployerConfig) (*Deployer, error) {
|
||||
SecretId: config.SecretId,
|
||||
SecretKey: config.SecretKey,
|
||||
ProjectId: config.ProjectId,
|
||||
Endpoint: lo.
|
||||
If(strings.HasSuffix(config.Endpoint, "intl.tencentcloudapi.com"), "ssl.intl.tencentcloudapi.com"). // 国际站使用独立的接口端点
|
||||
Else(""),
|
||||
Endpoint: config.Endpoint,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not create certmgr: %w", err)
|
||||
@@ -155,7 +152,7 @@ func (d *Deployer) updateHttpsListenerCertificate(ctx context.Context, cloudList
|
||||
return nil
|
||||
}
|
||||
|
||||
func createSDKClients(secretId, secretKey, endpoint string) (*tcgaap.Client, error) {
|
||||
func createSDKClient(secretId, secretKey, endpoint string) (*tcgaap.Client, error) {
|
||||
credential := common.NewCredential(secretId, secretKey)
|
||||
|
||||
cpf := profile.NewClientProfile()
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
fp = tester.Args("TENCENTCLOUDCDN_")
|
||||
fp = tester.Args("TENCENTCLOUGAAP_")
|
||||
fTestCertPath string
|
||||
fTestKeyPath string
|
||||
fSecretId string
|
||||
@@ -35,7 +35,7 @@ Shell command to run this test:
|
||||
--TENCENTCLOUDGAAP_SECRETID="your-secret-id" \
|
||||
--TENCENTCLOUDGAAP_SECRETKEY="your-secret-key" \
|
||||
--TENCENTCLOUDGAAP_PROXYID="your-gaap-group-id" \
|
||||
--TENCENTCLOUDGAAP_LISTENERID="your-clb-listener-id"
|
||||
--TENCENTCLOUDGAAP_LISTENERID="your-gaap-listener-id"
|
||||
*/
|
||||
func TestProvider(t *testing.T) {
|
||||
fp.Parse()
|
||||
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
package v20250115
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
|
||||
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile"
|
||||
ga2 "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ga2/v20250115"
|
||||
)
|
||||
|
||||
const APIVersion = ga2.APIVersion
|
||||
|
||||
type Client struct {
|
||||
common.Client
|
||||
}
|
||||
|
||||
func NewClient(credential common.CredentialIface, region string, clientProfile *profile.ClientProfile) (client *Client, err error) {
|
||||
client = &Client{}
|
||||
client.Init(region).
|
||||
WithCredential(credential).
|
||||
WithProfile(clientProfile)
|
||||
return
|
||||
}
|
||||
|
||||
func NewDescribeListenersRequest() (request *DescribeListenersRequest) {
|
||||
return ga2.NewDescribeListenersRequest()
|
||||
}
|
||||
|
||||
func NewDescribeListenersResponse() (response *DescribeListenersResponse) {
|
||||
return ga2.NewDescribeListenersResponse()
|
||||
}
|
||||
|
||||
func (c *Client) DescribeListenersWithContext(ctx context.Context, request *DescribeListenersRequest) (response *DescribeListenersResponse, err error) {
|
||||
if request == nil {
|
||||
request = NewDescribeListenersRequest()
|
||||
}
|
||||
c.InitBaseRequest(&request.BaseRequest, "ga2", APIVersion, "DescribeListeners")
|
||||
|
||||
if c.GetCredential() == nil {
|
||||
return nil, errors.New("DescribeListeners require credential")
|
||||
}
|
||||
|
||||
request.SetContext(ctx)
|
||||
|
||||
response = NewDescribeListenersResponse()
|
||||
err = c.Send(request, response)
|
||||
return
|
||||
}
|
||||
|
||||
func NewModifyListenerRequest() (request *ModifyListenerRequest) {
|
||||
return ga2.NewModifyListenerRequest()
|
||||
}
|
||||
|
||||
func NewModifyListenerResponse() (response *ModifyListenerResponse) {
|
||||
return ga2.NewModifyListenerResponse()
|
||||
}
|
||||
|
||||
func (c *Client) ModifyListenerWithContext(ctx context.Context, request *ModifyListenerRequest) (response *ModifyListenerResponse, err error) {
|
||||
if request == nil {
|
||||
request = NewModifyListenerRequest()
|
||||
}
|
||||
c.InitBaseRequest(&request.BaseRequest, "ga2", APIVersion, "ModifyListener")
|
||||
|
||||
if c.GetCredential() == nil {
|
||||
return nil, errors.New("ModifyListener require credential")
|
||||
}
|
||||
|
||||
request.SetContext(ctx)
|
||||
|
||||
response = NewModifyListenerResponse()
|
||||
err = c.Send(request, response)
|
||||
return
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
package v20250115
|
||||
|
||||
import (
|
||||
ga2 "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ga2/v20250115"
|
||||
)
|
||||
|
||||
type (
|
||||
Filter = ga2.Filter
|
||||
)
|
||||
|
||||
type DescribeListenersRequest = ga2.DescribeListenersRequest
|
||||
|
||||
type DescribeListenersResponse = ga2.DescribeListenersResponse
|
||||
|
||||
type ModifyListenerRequest = ga2.ModifyListenerRequest
|
||||
|
||||
type ModifyListenerResponse = ga2.ModifyListenerResponse
|
||||
+75
@@ -23,6 +23,81 @@ func NewClient(credential common.CredentialIface, region string, clientProfile *
|
||||
return
|
||||
}
|
||||
|
||||
func NewCreateCertificateRequest() (request *CreateCertificateRequest) {
|
||||
return gaap.NewCreateCertificateRequest()
|
||||
}
|
||||
|
||||
func NewCreateCertificateResponse() (response *CreateCertificateResponse) {
|
||||
return gaap.NewCreateCertificateResponse()
|
||||
}
|
||||
|
||||
func (c *Client) CreateCertificateWithContext(ctx context.Context, request *CreateCertificateRequest) (response *CreateCertificateResponse, err error) {
|
||||
if request == nil {
|
||||
request = NewCreateCertificateRequest()
|
||||
}
|
||||
c.InitBaseRequest(&request.BaseRequest, "gaap", APIVersion, "CreateCertificate")
|
||||
|
||||
if c.GetCredential() == nil {
|
||||
return nil, errors.New("CreateCertificate require credential")
|
||||
}
|
||||
|
||||
request.SetContext(ctx)
|
||||
|
||||
response = NewCreateCertificateResponse()
|
||||
err = c.Send(request, response)
|
||||
return
|
||||
}
|
||||
|
||||
func NewDescribeCertificatesRequest() (request *DescribeCertificatesRequest) {
|
||||
return gaap.NewDescribeCertificatesRequest()
|
||||
}
|
||||
|
||||
func NewDescribeCertificatesResponse() (response *DescribeCertificatesResponse) {
|
||||
return gaap.NewDescribeCertificatesResponse()
|
||||
}
|
||||
|
||||
func (c *Client) DescribeCertificatesWithContext(ctx context.Context, request *DescribeCertificatesRequest) (response *DescribeCertificatesResponse, err error) {
|
||||
if request == nil {
|
||||
request = NewDescribeCertificatesRequest()
|
||||
}
|
||||
c.InitBaseRequest(&request.BaseRequest, "gaap", APIVersion, "DescribeCertificates")
|
||||
|
||||
if c.GetCredential() == nil {
|
||||
return nil, errors.New("DescribeCertificates require credential")
|
||||
}
|
||||
|
||||
request.SetContext(ctx)
|
||||
|
||||
response = NewDescribeCertificatesResponse()
|
||||
err = c.Send(request, response)
|
||||
return
|
||||
}
|
||||
|
||||
func NewDescribeCertificateDetailRequest() (request *DescribeCertificateDetailRequest) {
|
||||
return gaap.NewDescribeCertificateDetailRequest()
|
||||
}
|
||||
|
||||
func NewDescribeCertificateDetailResponse() (response *DescribeCertificateDetailResponse) {
|
||||
return gaap.NewDescribeCertificateDetailResponse()
|
||||
}
|
||||
|
||||
func (c *Client) DescribeCertificateDetailWithContext(ctx context.Context, request *DescribeCertificateDetailRequest) (response *DescribeCertificateDetailResponse, err error) {
|
||||
if request == nil {
|
||||
request = NewDescribeCertificateDetailRequest()
|
||||
}
|
||||
c.InitBaseRequest(&request.BaseRequest, "gaap", APIVersion, "DescribeCertificateDetail")
|
||||
|
||||
if c.GetCredential() == nil {
|
||||
return nil, errors.New("DescribeCertificateDetail require credential")
|
||||
}
|
||||
|
||||
request.SetContext(ctx)
|
||||
|
||||
response = NewDescribeCertificateDetailResponse()
|
||||
err = c.Send(request, response)
|
||||
return
|
||||
}
|
||||
|
||||
func NewDescribeHTTPSListenersRequest() (request *DescribeHTTPSListenersRequest) {
|
||||
return gaap.NewDescribeHTTPSListenersRequest()
|
||||
}
|
||||
|
||||
+12
@@ -4,6 +4,18 @@ import (
|
||||
gaap "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/gaap/v20180529"
|
||||
)
|
||||
|
||||
type CreateCertificateRequest = gaap.CreateCertificateRequest
|
||||
|
||||
type CreateCertificateResponse = gaap.CreateCertificateResponse
|
||||
|
||||
type DescribeCertificatesRequest = gaap.DescribeCertificatesRequest
|
||||
|
||||
type DescribeCertificatesResponse = gaap.DescribeCertificatesResponse
|
||||
|
||||
type DescribeCertificateDetailRequest = gaap.DescribeCertificateDetailRequest
|
||||
|
||||
type DescribeCertificateDetailResponse = gaap.DescribeCertificateDetailResponse
|
||||
|
||||
type DescribeHTTPSListenersRequest = gaap.DescribeHTTPSListenersRequest
|
||||
|
||||
type DescribeHTTPSListenersResponse = gaap.DescribeHTTPSListenersResponse
|
||||
|
||||
+24
@@ -23,6 +23,30 @@ func NewClient(credential common.CredentialIface, region string, clientProfile *
|
||||
return
|
||||
}
|
||||
|
||||
func NewDescribeCertificateRequest() (request *DescribeCertificateRequest) {
|
||||
return ssl.NewDescribeCertificateRequest()
|
||||
}
|
||||
|
||||
func NewDescribeCertificateResponse() (response *DescribeCertificateResponse) {
|
||||
return ssl.NewDescribeCertificateResponse()
|
||||
}
|
||||
|
||||
func (c *Client) DescribeCertificateWithContext(ctx context.Context, request *DescribeCertificateRequest) (response *DescribeCertificateResponse, err error) {
|
||||
if request == nil {
|
||||
request = NewDescribeCertificateRequest()
|
||||
}
|
||||
c.InitBaseRequest(&request.BaseRequest, "ssl", ssl.APIVersion, "DescribeCertificate")
|
||||
|
||||
if c.GetCredential() == nil {
|
||||
return nil, errors.New("DescribeCertificate require credential")
|
||||
}
|
||||
|
||||
request.SetContext(ctx)
|
||||
response = NewDescribeCertificateResponse()
|
||||
err = c.Send(request, response)
|
||||
return
|
||||
}
|
||||
|
||||
func NewDescribeHostCosInstanceListRequest() (request *DescribeHostCosInstanceListRequest) {
|
||||
return ssl.NewDescribeHostCosInstanceListRequest()
|
||||
}
|
||||
|
||||
+4
@@ -8,6 +8,10 @@ type (
|
||||
ResourceTypeRegions = ssl.ResourceTypeRegions
|
||||
)
|
||||
|
||||
type DescribeCertificateRequest = ssl.DescribeCertificateRequest
|
||||
|
||||
type DescribeCertificateResponse = ssl.DescribeCertificateResponse
|
||||
|
||||
type DescribeHostCosInstanceListRequest = ssl.DescribeHostCosInstanceListRequest
|
||||
|
||||
type DescribeHostCosInstanceListResponse = ssl.DescribeHostCosInstanceListResponse
|
||||
|
||||
@@ -103,6 +103,7 @@ import BizDeployNodeConfigFieldsProviderTencentCloudCOS from "./BizDeployNodeCon
|
||||
import BizDeployNodeConfigFieldsProviderTencentCloudCSS from "./BizDeployNodeConfigFieldsProviderTencentCloudCSS";
|
||||
import BizDeployNodeConfigFieldsProviderTencentCloudECDN from "./BizDeployNodeConfigFieldsProviderTencentCloudECDN";
|
||||
import BizDeployNodeConfigFieldsProviderTencentCloudEO from "./BizDeployNodeConfigFieldsProviderTencentCloudEO";
|
||||
import BizDeployNodeConfigFieldsProviderTencentCloudGA2 from "./BizDeployNodeConfigFieldsProviderTencentCloudGA2";
|
||||
import BizDeployNodeConfigFieldsProviderTencentCloudGAAP from "./BizDeployNodeConfigFieldsProviderTencentCloudGAAP";
|
||||
import BizDeployNodeConfigFieldsProviderTencentCloudSCF from "./BizDeployNodeConfigFieldsProviderTencentCloudSCF";
|
||||
import BizDeployNodeConfigFieldsProviderTencentCloudSSL from "./BizDeployNodeConfigFieldsProviderTencentCloudSSL";
|
||||
@@ -245,6 +246,7 @@ const providerComponentMap: Partial<Record<DeploymentProviderType, React.Compone
|
||||
[DEPLOYMENT_PROVIDERS.TENCENTCLOUD_ECDN]: BizDeployNodeConfigFieldsProviderTencentCloudECDN,
|
||||
[DEPLOYMENT_PROVIDERS.TENCENTCLOUD_EO]: BizDeployNodeConfigFieldsProviderTencentCloudEO,
|
||||
[DEPLOYMENT_PROVIDERS.TENCENTCLOUD_GAAP]: BizDeployNodeConfigFieldsProviderTencentCloudGAAP,
|
||||
[DEPLOYMENT_PROVIDERS.TENCENTCLOUD_GA2]: BizDeployNodeConfigFieldsProviderTencentCloudGA2,
|
||||
[DEPLOYMENT_PROVIDERS.TENCENTCLOUD_SCF]: BizDeployNodeConfigFieldsProviderTencentCloudSCF,
|
||||
[DEPLOYMENT_PROVIDERS.TENCENTCLOUD_SSL]: BizDeployNodeConfigFieldsProviderTencentCloudSSL,
|
||||
[DEPLOYMENT_PROVIDERS.TENCENTCLOUD_SSL_DEPLOY]: BizDeployNodeConfigFieldsProviderTencentCloudSSLDeploy,
|
||||
|
||||
+118
@@ -0,0 +1,118 @@
|
||||
import { getI18n, useTranslation } from "react-i18next";
|
||||
import { Form, Input, Select } from "antd";
|
||||
import { createSchemaFieldRule } from "antd-zod";
|
||||
import { z } from "zod";
|
||||
|
||||
import Show from "@/components/Show";
|
||||
|
||||
import { useFormNestedFieldsContext } from "./_context";
|
||||
|
||||
const DEPLOY_TARGET_LISTENER = "listener" as const;
|
||||
|
||||
const BizDeployNodeConfigFieldsProviderTencentCloudGA2 = () => {
|
||||
const { i18n, t } = useTranslation();
|
||||
|
||||
const { parentNamePath } = useFormNestedFieldsContext();
|
||||
const formSchema = z.object({
|
||||
[parentNamePath]: getSchema({ i18n }),
|
||||
});
|
||||
const formRule = createSchemaFieldRule(formSchema);
|
||||
const formInst = Form.useFormInstance();
|
||||
const initialValues = getInitialValues();
|
||||
|
||||
const fieldResourceType = Form.useWatch([parentNamePath, "deployTarget"], formInst);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Form.Item
|
||||
name={[parentNamePath, "endpoint"]}
|
||||
initialValue={initialValues.endpoint}
|
||||
label={t("workflow_node.deploy.form.tencentcloud_ga2_endpoint.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.tencentcloud_ga2_endpoint.tooltip") }}></span>}
|
||||
>
|
||||
<Input allowClear placeholder={t("workflow_node.deploy.form.tencentcloud_ga2_endpoint.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name={[parentNamePath, "deployTarget"]}
|
||||
initialValue={initialValues.deployTarget}
|
||||
label={t("workflow_node.deploy.form.shared_deploy_target.label")}
|
||||
rules={[formRule]}
|
||||
>
|
||||
<Select
|
||||
options={[DEPLOY_TARGET_LISTENER].map((s) => ({
|
||||
label: t(`workflow_node.deploy.form.tencentcloud_ga2_deploy_target.option.${s}.label`),
|
||||
value: s,
|
||||
}))}
|
||||
placeholder={t("workflow_node.deploy.form.shared_deploy_target.placeholder")}
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name={[parentNamePath, "acceleratorId"]}
|
||||
initialValue={initialValues.acceleratorId}
|
||||
label={t("workflow_node.deploy.form.tencentcloud_ga2_accelerator_id.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.tencentcloud_ga2_accelerator_id.tooltip") }}></span>}
|
||||
>
|
||||
<Input placeholder={t("workflow_node.deploy.form.tencentcloud_ga2_accelerator_id.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Show when={fieldResourceType === DEPLOY_TARGET_LISTENER}>
|
||||
<Form.Item
|
||||
name={[parentNamePath, "listenerId"]}
|
||||
initialValue={initialValues.listenerId}
|
||||
label={t("workflow_node.deploy.form.tencentcloud_ga2_listener_id.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.tencentcloud_ga2_listener_id.tooltip") }}></span>}
|
||||
>
|
||||
<Input placeholder={t("workflow_node.deploy.form.tencentcloud_ga2_listener_id.placeholder")} />
|
||||
</Form.Item>
|
||||
</Show>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const getInitialValues = (): Nullish<z.infer<ReturnType<typeof getSchema>>> => {
|
||||
return {
|
||||
acceleratorId: "",
|
||||
deployTarget: DEPLOY_TARGET_LISTENER,
|
||||
};
|
||||
};
|
||||
|
||||
const getSchema = ({ i18n = getI18n() }: { i18n?: ReturnType<typeof getI18n> }) => {
|
||||
const { t: _ } = i18n;
|
||||
|
||||
return z
|
||||
.object({
|
||||
endpoint: z.string().nullish(),
|
||||
deployTarget: z.enum([DEPLOY_TARGET_LISTENER]),
|
||||
acceleratorId: z.string().nonempty(),
|
||||
listenerId: z.string().nullish(),
|
||||
})
|
||||
.superRefine((values, ctx) => {
|
||||
switch (values.deployTarget) {
|
||||
case DEPLOY_TARGET_LISTENER:
|
||||
{
|
||||
const scListenerId = z.string().nonempty();
|
||||
const spListenerId = scListenerId.safeParse(values.listenerId);
|
||||
if (!spListenerId.success) {
|
||||
ctx.addIssue({
|
||||
code: "custom",
|
||||
message: z.treeifyError(spListenerId.error).errors.join(),
|
||||
path: ["listenerId"],
|
||||
});
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const _default = Object.assign(BizDeployNodeConfigFieldsProviderTencentCloudGA2, {
|
||||
getInitialValues,
|
||||
getSchema,
|
||||
});
|
||||
|
||||
export default _default;
|
||||
@@ -700,6 +700,7 @@ export const DEPLOYMENT_PROVIDERS = Object.freeze({
|
||||
TENCENTCLOUD_ECDN: `${ACCESS_PROVIDERS.TENCENTCLOUD}-ecdn`,
|
||||
TENCENTCLOUD_EO: `${ACCESS_PROVIDERS.TENCENTCLOUD}-eo`,
|
||||
TENCENTCLOUD_GAAP: `${ACCESS_PROVIDERS.TENCENTCLOUD}-gaap`,
|
||||
TENCENTCLOUD_GA2: `${ACCESS_PROVIDERS.TENCENTCLOUD}-ga2`,
|
||||
TENCENTCLOUD_SCF: `${ACCESS_PROVIDERS.TENCENTCLOUD}-scf`,
|
||||
TENCENTCLOUD_SSL: `${ACCESS_PROVIDERS.TENCENTCLOUD}-ssl`,
|
||||
TENCENTCLOUD_SSL_DEPLOY: `${ACCESS_PROVIDERS.TENCENTCLOUD}-ssldeploy`,
|
||||
@@ -800,6 +801,7 @@ export const deploymentProvidersMap: Map<DeploymentProvider["type"] | string, De
|
||||
[DEPLOYMENT_PROVIDERS.TENCENTCLOUD_SCF, "provider.tencentcloud_scf", DEPLOYMENT_CATEGORIES.SERVERLESS],
|
||||
[DEPLOYMENT_PROVIDERS.TENCENTCLOUD_TSE, "provider.tencentcloud_tse", DEPLOYMENT_CATEGORIES.APIGATEWAY],
|
||||
[DEPLOYMENT_PROVIDERS.TENCENTCLOUD_GAAP, "provider.tencentcloud_gaap", DEPLOYMENT_CATEGORIES.ACCELERATOR],
|
||||
[DEPLOYMENT_PROVIDERS.TENCENTCLOUD_GA2, "provider.tencentcloud_ga2", DEPLOYMENT_CATEGORIES.ACCELERATOR],
|
||||
[DEPLOYMENT_PROVIDERS.TENCENTCLOUD_SSL, "provider.tencentcloud_ssl_upload", DEPLOYMENT_CATEGORIES.SSL],
|
||||
[DEPLOYMENT_PROVIDERS.TENCENTCLOUD_SSL_DEPLOY, "provider.tencentcloud_ssl_deploy", DEPLOYMENT_CATEGORIES.SSL],
|
||||
[DEPLOYMENT_PROVIDERS.TENCENTCLOUD_SSL_UPDATE, "provider.tencentcloud_ssl_update", DEPLOYMENT_CATEGORIES.SSL],
|
||||
|
||||
@@ -238,6 +238,7 @@
|
||||
"tencentcloud_dns": "Tencent Cloud - DNS",
|
||||
"tencentcloud_ecdn": "Tencent Cloud - ECDN (Enterprise Content Delivery Network)",
|
||||
"tencentcloud_eo": "Tencent Cloud - EdgeOne",
|
||||
"tencentcloud_ga2": "Tencent Cloud - GA2 (Global Accelerator 2.0)",
|
||||
"tencentcloud_gaap": "Tencent Cloud - GAAP (Global Application Acceleration Platform)",
|
||||
"tencentcloud_scf": "Tencent Cloud - SCF (Serverless Cloud Function)",
|
||||
"tencentcloud_ssl_deploy": "Tencent Cloud - Deploy via SSL Certificate Service",
|
||||
|
||||
@@ -2213,6 +2213,28 @@
|
||||
"off": "Disallow"
|
||||
}
|
||||
},
|
||||
"tencentcloud_ga2_endpoint": {
|
||||
"label": "Tencent Cloud API endpoint (Optional)",
|
||||
"placeholder": "Please enter Tencent Cloud GA2 API endpoint (e.g. ga2.intl.tencentcloudapi.com)",
|
||||
"tooltip": "<ul style=\"list-style: disc;\"><li><strong>ga2.intl.tencentcloudapi.com</strong> for Tencent Cloud International</li><li><strong>ga2.tencentcloudapi.com</strong> for Tencent Cloud in China</li></ul>"
|
||||
},
|
||||
"tencentcloud_ga2_deploy_target": {
|
||||
"option": {
|
||||
"listener": {
|
||||
"label": "GA2 listener"
|
||||
}
|
||||
}
|
||||
},
|
||||
"tencentcloud_ga2_accelerator_id": {
|
||||
"label": "Tencent Cloud GA2 accelerator ID (Optional)",
|
||||
"placeholder": "Please enter Tencent Cloud GA2 accelerator ID",
|
||||
"tooltip": "For more information, see <a href=\"https://console.tencentcloud.com/gaap\" target=\"_blank\">https://console.tencentcloud.com/gaap</a>"
|
||||
},
|
||||
"tencentcloud_ga2_listener_id": {
|
||||
"label": "Tencent Cloud GA2 listener ID",
|
||||
"placeholder": "Please enter Tencent Cloud GA2 listener ID",
|
||||
"tooltip": "For more information, see <a href=\"https://console.tencentcloud.com/gaap\" target=\"_blank\">https://console.tencentcloud.com/gaap</a>"
|
||||
},
|
||||
"tencentcloud_gaap_endpoint": {
|
||||
"label": "Tencent Cloud API endpoint (Optional)",
|
||||
"placeholder": "Please enter Tencent Cloud GAAP API endpoint (e.g. gaap.intl.tencentcloudapi.com)",
|
||||
|
||||
@@ -238,6 +238,7 @@
|
||||
"tencentcloud_dns": "腾讯云 - 云解析 DNS",
|
||||
"tencentcloud_ecdn": "腾讯云 - 全站加速网络 ECDN",
|
||||
"tencentcloud_eo": "腾讯云 - 边缘安全加速平台 EdgeOne",
|
||||
"tencentcloud_ga2": "腾讯云 - 全球加速 2.0 GA2",
|
||||
"tencentcloud_gaap": "腾讯云 - 全球应用加速 GAAP",
|
||||
"tencentcloud_scf": "腾讯云 - 云函数 SCF",
|
||||
"tencentcloud_ssl_deploy": "腾讯云 - 通过 SSL 证书服务创建部署任务",
|
||||
|
||||
@@ -2209,6 +2209,28 @@
|
||||
"off": "不"
|
||||
}
|
||||
},
|
||||
"tencentcloud_ga2_endpoint": {
|
||||
"label": "腾讯云接口端点(可选)",
|
||||
"placeholder": "请输入腾讯云 GA2 接口端点(例如:ga2.tencentcloudapi.com)",
|
||||
"tooltip": "这是什么?请参阅 <a href=\"https://cloud.tencent.com/document/product/1817/129372\" target=\"_blank\">https://cloud.tencent.com/document/product/1817/129372</a><br>国际站用户请填写 <em>ga2.intl.tencentcloudapi.com</em>。"
|
||||
},
|
||||
"tencentcloud_ga2_deploy_target": {
|
||||
"option": {
|
||||
"listener": {
|
||||
"label": "部署到指定监听器"
|
||||
}
|
||||
}
|
||||
},
|
||||
"tencentcloud_ga2_accelerator_id": {
|
||||
"label": "腾讯云 GA2 加速实例 ID",
|
||||
"placeholder": "请输入腾讯云 GA2 加速实例 ID",
|
||||
"tooltip": "这是什么?请参阅 <a href=\"https://console.cloud.tencent.com/gaap\" target=\"_blank\">https://console.cloud.tencent.com/gaap</a>"
|
||||
},
|
||||
"tencentcloud_ga2_listener_id": {
|
||||
"label": "腾讯云 GA2 监听器 ID",
|
||||
"placeholder": "请输入腾讯云 GA2 监听器 ID",
|
||||
"tooltip": "这是什么?请参阅 <a href=\"https://console.cloud.tencent.com/gaap\" target=\"_blank\">https://console.cloud.tencent.com/gaap</a>"
|
||||
},
|
||||
"tencentcloud_gaap_endpoint": {
|
||||
"label": "腾讯云接口端点(可选)",
|
||||
"placeholder": "请输入腾讯云 GAAP 接口端点(例如:gaap.tencentcloudapi.com)",
|
||||
|
||||
Reference in New Issue
Block a user