feat: add huaweicloud elb uploader

This commit is contained in:
Fu Diwei 2024-10-20 21:33:08 +08:00
parent fc55e37454
commit f168bd903d
2 changed files with 183 additions and 18 deletions

View File

@ -0,0 +1,160 @@
package impl
import (
"context"
"fmt"
"time"
"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/basic"
elb "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/elb/v3"
elbModel "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/elb/v3/model"
elbRegion "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/elb/v3/region"
"github.com/usual2970/certimate/internal/pkg/core/uploader"
"github.com/usual2970/certimate/internal/pkg/utils/cast"
"github.com/usual2970/certimate/internal/pkg/utils/x509"
)
type HuaweiCloudELBUploaderConfig struct {
Region string `json:"region"`
ProjectId string `json:"projectId"`
AccessKeyId string `json:"accessKeyId"`
SecretAccessKey string `json:"secretAccessKey"`
}
type HuaweiCloudELBUploader struct {
config *HuaweiCloudELBUploaderConfig
sdkClient *elb.ElbClient
}
func NewHuaweiCloudELBUploader(config *HuaweiCloudELBUploaderConfig) (*HuaweiCloudELBUploader, error) {
client, err := (&HuaweiCloudELBUploader{config: config}).createSdkClient()
if err != nil {
return nil, fmt.Errorf("failed to create sdk client: %w", err)
}
return &HuaweiCloudELBUploader{
config: config,
sdkClient: client,
}, nil
}
func (u *HuaweiCloudELBUploader) Upload(ctx context.Context, certPem string, privkeyPem string) (res *uploader.UploadResult, err error) {
// 解析证书内容
newCert, err := x509.ParseCertificateFromPEM(certPem)
if err != nil {
return nil, err
}
// 遍历查询已有证书,避免重复上传
// REF: https://support.huaweicloud.com/api-elb/ListCertificates.html
listCertificatesPage := 1
listCertificatesLimit := int32(2000)
var listCertificatesMarker *string = nil
for {
listCertificatesReq := &elbModel.ListCertificatesRequest{
Limit: cast.Int32Ptr(listCertificatesLimit),
Marker: listCertificatesMarker,
Type: &[]string{"server"},
}
listCertificatesResp, err := u.sdkClient.ListCertificates(listCertificatesReq)
if err != nil {
return nil, fmt.Errorf("failed to execute sdk request 'elb.ListCertificates': %w", err)
}
if listCertificatesResp.Certificates != nil {
for _, certDetail := range *listCertificatesResp.Certificates {
var isSameCert bool
if certDetail.Certificate == certPem {
isSameCert = true
} else {
cert, err := x509.ParseCertificateFromPEM(certDetail.Certificate)
if err != nil {
continue
}
isSameCert = x509.EqualCertificate(cert, newCert)
}
// 如果已存在相同证书,直接返回已有的证书信息
if isSameCert {
return &uploader.UploadResult{
CertId: certDetail.Id,
CertName: certDetail.Name,
}, nil
}
}
}
if listCertificatesResp.Certificates == nil || len(*listCertificatesResp.Certificates) < int(listCertificatesLimit) {
break
}
listCertificatesMarker = listCertificatesResp.PageInfo.NextMarker
listCertificatesPage++
if listCertificatesPage >= 9 { // 避免无限获取
break
}
}
// 生成证书名(需符合华为云命名规则)
var certId, certName string
certName = fmt.Sprintf("certimate-%d", time.Now().UnixMilli())
// 创建新证书
// REF: https://support.huaweicloud.com/api-elb/CreateCertificate.html
createCertificateReq := &elbModel.CreateCertificateRequest{
Body: &elbModel.CreateCertificateRequestBody{
Certificate: &elbModel.CreateCertificateOption{
ProjectId: cast.StringPtr(u.config.ProjectId),
Name: cast.StringPtr(certName),
Certificate: cast.StringPtr(certPem),
PrivateKey: cast.StringPtr(privkeyPem),
},
},
}
createCertificateResp, err := u.sdkClient.CreateCertificate(createCertificateReq)
if err != nil {
return nil, fmt.Errorf("failed to execute sdk request 'elb.CreateCertificate': %w", err)
}
certId = createCertificateResp.Certificate.Id
certName = createCertificateResp.Certificate.Name
return &uploader.UploadResult{
CertId: certId,
CertName: certName,
}, nil
}
func (u *HuaweiCloudELBUploader) createSdkClient() (*elb.ElbClient, error) {
region := u.config.Region
accessKeyId := u.config.AccessKeyId
secretAccessKey := u.config.SecretAccessKey
if region == "" {
region = "cn-north-4" // ELB 服务默认区域:华北北京四
}
auth, err := basic.NewCredentialsBuilder().
WithAk(accessKeyId).
WithSk(secretAccessKey).
SafeBuild()
if err != nil {
return nil, err
}
hcRegion, err := elbRegion.SafeValueOf(region)
if err != nil {
return nil, err
}
hcClient, err := elb.ElbClientBuilder().
WithRegion(hcRegion).
WithCredential(auth).
SafeBuild()
if err != nil {
return nil, err
}
client := elb.NewElbClient(hcClient)
return client, nil
}

View File

@ -22,19 +22,19 @@ type HuaweiCloudSCMUploaderConfig struct {
}
type HuaweiCloudSCMUploader struct {
config *HuaweiCloudSCMUploaderConfig
client *scm.ScmClient
config *HuaweiCloudSCMUploaderConfig
sdkClient *scm.ScmClient
}
func NewHuaweiCloudSCMUploader(config *HuaweiCloudSCMUploaderConfig) (*HuaweiCloudSCMUploader, error) {
client, err := createClient(config.Region, config.AccessKeyId, config.SecretAccessKey)
client, err := (&HuaweiCloudSCMUploader{config: config}).createSdkClient()
if err != nil {
return nil, fmt.Errorf("failed to create client: %w", err)
return nil, fmt.Errorf("failed to create sdk client: %w", err)
}
return &HuaweiCloudSCMUploader{
config: config,
client: client,
config: config,
sdkClient: client,
}, nil
}
@ -48,6 +48,7 @@ func (u *HuaweiCloudSCMUploader) Upload(ctx context.Context, certPem string, pri
// 遍历查询已有证书,避免重复上传
// REF: https://support.huaweicloud.com/api-ccm/ListCertificates.html
// REF: https://support.huaweicloud.com/api-ccm/ExportCertificate_0.html
listCertificatesPage := 1
listCertificatesLimit := int32(50)
listCertificatesOffset := int32(0)
for {
@ -57,9 +58,9 @@ func (u *HuaweiCloudSCMUploader) Upload(ctx context.Context, certPem string, pri
SortDir: cast.StringPtr("DESC"),
SortKey: cast.StringPtr("certExpiredTime"),
}
listCertificatesResp, err := u.client.ListCertificates(listCertificatesReq)
listCertificatesResp, err := u.sdkClient.ListCertificates(listCertificatesReq)
if err != nil {
return nil, fmt.Errorf("failed to execute request 'scm.ListCertificates': %w", err)
return nil, fmt.Errorf("failed to execute sdk request 'scm.ListCertificates': %w", err)
}
if listCertificatesResp.Certificates != nil {
@ -67,12 +68,12 @@ func (u *HuaweiCloudSCMUploader) Upload(ctx context.Context, certPem string, pri
exportCertificateReq := &scmModel.ExportCertificateRequest{
CertificateId: certDetail.Id,
}
exportCertificateResp, err := u.client.ExportCertificate(exportCertificateReq)
exportCertificateResp, err := u.sdkClient.ExportCertificate(exportCertificateReq)
if err != nil {
if exportCertificateResp != nil && exportCertificateResp.HttpStatusCode == 404 {
continue
}
return nil, fmt.Errorf("failed to execute request 'scm.ExportCertificate': %w", err)
return nil, fmt.Errorf("failed to execute sdk request 'scm.ExportCertificate': %w", err)
}
var isSameCert bool
@ -102,7 +103,8 @@ func (u *HuaweiCloudSCMUploader) Upload(ctx context.Context, certPem string, pri
}
listCertificatesOffset += listCertificatesLimit
if listCertificatesOffset >= 999 { // 避免无限获取
listCertificatesPage += 1
if listCertificatesPage > 99 { // 避免无限获取
break
}
}
@ -120,9 +122,9 @@ func (u *HuaweiCloudSCMUploader) Upload(ctx context.Context, certPem string, pri
PrivateKey: privkeyPem,
},
}
importCertificateResp, err := u.client.ImportCertificate(importCertificateReq)
importCertificateResp, err := u.sdkClient.ImportCertificate(importCertificateReq)
if err != nil {
return nil, fmt.Errorf("failed to execute request 'scm.ImportCertificate': %w", err)
return nil, fmt.Errorf("failed to execute sdk request 'scm.ImportCertificate': %w", err)
}
certId = *importCertificateResp.CertificateId
@ -132,7 +134,14 @@ func (u *HuaweiCloudSCMUploader) Upload(ctx context.Context, certPem string, pri
}, nil
}
func (u *HuaweiCloudSCMUploader) createClient(region, accessKeyId, secretAccessKey string) (*scm.ScmClient, error) {
func (u *HuaweiCloudSCMUploader) createSdkClient() (*scm.ScmClient, error) {
region := u.config.Region
accessKeyId := u.config.AccessKeyId
secretAccessKey := u.config.SecretAccessKey
if region == "" {
region = "cn-north-4" // SCM 服务默认区域:华北北京四
}
auth, err := basic.NewCredentialsBuilder().
WithAk(accessKeyId).
WithSk(secretAccessKey).
@ -141,10 +150,6 @@ func (u *HuaweiCloudSCMUploader) createClient(region, accessKeyId, secretAccessK
return nil, err
}
if region == "" {
region = "cn-north-4" // SCM 服务默认区域:华北北京四
}
hcRegion, err := scmRegion.SafeValueOf(region)
if err != nil {
return nil, err