feat: add aws acm uploader

This commit is contained in:
Fu Diwei
2025-01-23 21:55:05 +08:00
parent 9370f9d68f
commit 1651cda5b4
6 changed files with 137 additions and 13 deletions

View File

@@ -0,0 +1,97 @@
package awsacm
import (
"context"
"errors"
"fmt"
"time"
aws "github.com/aws/aws-sdk-go-v2/aws"
awsCfg "github.com/aws/aws-sdk-go-v2/config"
awsCred "github.com/aws/aws-sdk-go-v2/credentials"
awsAcm "github.com/aws/aws-sdk-go-v2/service/acm"
xerrors "github.com/pkg/errors"
"github.com/usual2970/certimate/internal/pkg/core/uploader"
"github.com/usual2970/certimate/internal/pkg/utils/certs"
)
type AWSCertificateManagerUploaderConfig struct {
// AWS AccessKeyId。
AccessKeyId string `json:"accessKeyId"`
// AWS SecretAccessKey。
SecretAccessKey string `json:"secretAccessKey"`
// AWS 区域。
Region string `json:"region"`
}
type AWSCertificateManagerUploader struct {
config *AWSCertificateManagerUploaderConfig
sdkClient *awsAcm.Client
}
var _ uploader.Uploader = (*AWSCertificateManagerUploader)(nil)
func New(config *AWSCertificateManagerUploaderConfig) (*AWSCertificateManagerUploader, error) {
if config == nil {
return nil, errors.New("config is nil")
}
client, err := createSdkClient(config.AccessKeyId, config.SecretAccessKey, config.Region)
if err != nil {
return nil, xerrors.Wrap(err, "failed to create sdk client")
}
return &AWSCertificateManagerUploader{
config: config,
sdkClient: client,
}, nil
}
func (u *AWSCertificateManagerUploader) Upload(ctx context.Context, certPem string, privkeyPem string) (res *uploader.UploadResult, err error) {
// 解析证书内容
certX509, err := certs.ParseCertificateFromPEM(certPem)
if err != nil {
return nil, err
}
// 生成 AWS 所需的服务端证书和证书链参数
scertPem, _ := certs.ConvertCertificateToPEM(certX509)
bcertPem := certPem
// 生成新证书名(需符合 AWS 命名规则)
var certId, certName string
certName = fmt.Sprintf("certimate_%d", time.Now().UnixMilli())
// 导入证书
// REF: https://docs.aws.amazon.com/en_us/acm/latest/APIReference/API_ImportCertificate.html
importCertificateReq := &awsAcm.ImportCertificateInput{
Certificate: ([]byte)(scertPem),
CertificateChain: ([]byte)(bcertPem),
PrivateKey: ([]byte)(privkeyPem),
}
importCertificateResp, err := u.sdkClient.ImportCertificate(context.TODO(), importCertificateReq)
if err != nil {
return nil, xerrors.Wrap(err, "failed to execute sdk request 'acm.ImportCertificate'")
}
certId = *importCertificateResp.CertificateArn
return &uploader.UploadResult{
CertId: certId,
CertName: certName,
}, nil
}
func createSdkClient(accessKeyId, secretAccessKey, region string) (*awsAcm.Client, error) {
cfg, err := awsCfg.LoadDefaultConfig(context.TODO())
if err != nil {
return nil, err
}
client := awsAcm.NewFromConfig(cfg, func(o *awsAcm.Options) {
o.Region = region
o.Credentials = aws.NewCredentialsCache(awsCred.NewStaticCredentialsProvider(accessKeyId, secretAccessKey, ""))
})
return client, nil
}

View File

@@ -76,7 +76,7 @@ func (u *UCloudUSSLUploader) Upload(ctx context.Context, certPem string, privkey
uploadNormalCertificateResp, err := u.sdkClient.UploadNormalCertificate(uploadNormalCertificateReq)
if err != nil {
if uploadNormalCertificateResp != nil && uploadNormalCertificateResp.GetRetCode() == 80035 {
return u.getExistCert(ctx, certPem, privkeyPem)
return u.getExistCert(ctx, certPem)
}
return nil, xerrors.Wrap(err, "failed to execute sdk request 'ussl.UploadNormalCertificate'")
@@ -92,7 +92,7 @@ func (u *UCloudUSSLUploader) Upload(ctx context.Context, certPem string, privkey
}, nil
}
func (u *UCloudUSSLUploader) getExistCert(ctx context.Context, certPem string, privkeyPem string) (res *uploader.UploadResult, err error) {
func (u *UCloudUSSLUploader) getExistCert(ctx context.Context, certPem string) (res *uploader.UploadResult, err error) {
// 解析证书内容
certX509, err := certs.ParseCertificateFromPEM(certPem)
if err != nil {

View File

@@ -14,6 +14,10 @@ import (
// 出参:
// - 是否相同。
func EqualCertificate(a, b *x509.Certificate) bool {
if a == nil || b == nil {
return false
}
return string(a.Signature) == string(b.Signature) &&
a.SignatureAlgorithm == b.SignatureAlgorithm &&
a.SerialNumber.String() == b.SerialNumber.String() &&

View File

@@ -8,6 +8,27 @@ import (
xerrors "github.com/pkg/errors"
)
// 将 x509.Certificate 对象转换为 PEM 编码的字符串。
//
// 入参:
// - cert: x509.Certificate 对象。
//
// 出参:
// - certPem: 证书 PEM 内容。
// - err: 错误。
func ConvertCertificateToPEM(cert *x509.Certificate) (certPem string, err error) {
if cert == nil {
return "", xerrors.New("cert is nil")
}
block := &pem.Block{
Type: "CERTIFICATE",
Bytes: cert.Raw,
}
return string(pem.EncodeToMemory(block)), nil
}
// 将 ecdsa.PrivateKey 对象转换为 PEM 编码的字符串。
//
// 入参:
@@ -17,6 +38,10 @@ import (
// - privkeyPem: 私钥 PEM 内容。
// - err: 错误。
func ConvertECPrivateKeyToPEM(privkey *ecdsa.PrivateKey) (privkeyPem string, err error) {
if privkey == nil {
return "", xerrors.New("privkey is nil")
}
data, err := x509.MarshalECPrivateKey(privkey)
if err != nil {
return "", xerrors.Wrap(err, "failed to marshal EC private key")