mirror of
https://github.com/certimate-go/certimate.git
synced 2026-07-20 21:01:41 +08:00
feat(provider): new deployment provider: aws clb
This commit is contained in:
parent
ed9f5b3322
commit
fc7975972d
13
go.mod
13
go.mod
@ -30,11 +30,12 @@ require (
|
||||
github.com/alibabacloud-go/vod-20170321/v4 v4.11.3
|
||||
github.com/alibabacloud-go/waf-openapi-20211001/v7 v7.7.0
|
||||
github.com/aliyun/alibabacloud-oss-go-sdk-v2 v1.5.1
|
||||
github.com/aws/aws-sdk-go-v2 v1.41.8
|
||||
github.com/aws/aws-sdk-go-v2 v1.41.11
|
||||
github.com/aws/aws-sdk-go-v2/config v1.32.19
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.19.18
|
||||
github.com/aws/aws-sdk-go-v2/service/acm v1.38.3
|
||||
github.com/aws/aws-sdk-go-v2/service/cloudfront v1.63.0
|
||||
github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing v1.34.2
|
||||
github.com/aws/aws-sdk-go-v2/service/iam v1.53.10
|
||||
github.com/aws/aws-sdk-go-v2/service/lightsail v1.54.1
|
||||
github.com/baidubce/bce-sdk-go v0.9.267
|
||||
@ -84,8 +85,10 @@ require (
|
||||
gitlab.ecloud.com/ecloud/ecloudsdkclouddns v1.0.1
|
||||
gitlab.ecloud.com/ecloud/ecloudsdkcore v1.0.0
|
||||
golang.org/x/crypto v0.52.0
|
||||
golang.org/x/oauth2 v0.36.0
|
||||
golang.org/x/sync v0.20.0
|
||||
golang.org/x/sys v0.45.0
|
||||
google.golang.org/api v0.280.0
|
||||
google.golang.org/protobuf v1.36.11
|
||||
k8s.io/api v0.35.3
|
||||
k8s.io/apimachinery v0.35.3
|
||||
@ -186,8 +189,8 @@ require (
|
||||
github.com/aliyun/credentials-go v1.4.12 // indirect
|
||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.24 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.24 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.24 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.27 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.27 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.25 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.9 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.24 // indirect
|
||||
@ -195,7 +198,7 @@ require (
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.30.18 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.36.1 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.42.2 // indirect
|
||||
github.com/aws/smithy-go v1.25.1 // indirect
|
||||
github.com/aws/smithy-go v1.27.0 // indirect
|
||||
github.com/aymerick/douceur v0.2.0 // indirect
|
||||
github.com/bodgit/gssapi v0.0.3 // indirect
|
||||
github.com/bodgit/tsig v1.3.1 // indirect
|
||||
@ -277,12 +280,10 @@ require (
|
||||
golang.org/x/image v0.40.0 // indirect
|
||||
golang.org/x/mod v0.36.0 // indirect
|
||||
golang.org/x/net v0.55.0 // indirect
|
||||
golang.org/x/oauth2 v0.36.0 // indirect
|
||||
golang.org/x/term v0.43.0 // indirect
|
||||
golang.org/x/text v0.37.0 // indirect
|
||||
golang.org/x/time v0.15.0 // indirect
|
||||
golang.org/x/tools v0.44.0 // indirect
|
||||
google.golang.org/api v0.280.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260511170946-3700d4141b60 // indirect
|
||||
google.golang.org/grpc v1.81.1 // indirect
|
||||
gopkg.in/ini.v1 v1.67.2 // indirect
|
||||
|
||||
18
go.sum
18
go.sum
@ -203,18 +203,18 @@ github.com/aws/aws-sdk-go v1.40.45/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm
|
||||
github.com/aws/aws-sdk-go v1.55.8 h1:JRmEUbU52aJQZ2AjX4q4Wu7t4uZjOu71uyNmaWlUkJQ=
|
||||
github.com/aws/aws-sdk-go v1.55.8/go.mod h1:ZkViS9AqA6otK+JBBNH2++sx1sgxrPKcSzPPvQkUtXk=
|
||||
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.41.8 h1:sRs7nG6/RiEBZ/K5UO2sNw0w40U02Nmz1VtARloTZXk=
|
||||
github.com/aws/aws-sdk-go-v2 v1.41.8/go.mod h1:4LAfZOPHNVNQEckOACQx60Y8pSRjIkNZQz1w92xpMJc=
|
||||
github.com/aws/aws-sdk-go-v2 v1.41.11 h1:9PRf7jyTMEUM6fuNRAJa2mO/skJfrF50rENJwf2LXqw=
|
||||
github.com/aws/aws-sdk-go-v2 v1.41.11/go.mod h1:iiUX27gOXRuYaoeUVXhUpPwjJHzISfPAjjcuhUbLSVs=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.32.19 h1:qRhIJMbevHUvIE7X4TK8N8zye5+5AhapcslPrvB+qKE=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.32.19/go.mod h1:RbJ24nfoya63+Mf5VI+CGCGk9vEdv28xPeii+gojRYs=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.19.18 h1:GcXQz2M/0ZvMo0v5DakUqbDBeBM1ZNaivkolEF4Esgw=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.19.18/go.mod h1:sHJ06tMGcD3ZpmMyJqV+VBsGilhSIZPIN+ZFy5Dg0C4=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.24 h1:FQm5ApnyzkuJdXLGskPce83CK1CQKC4RUnIHKVe4BU4=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.24/go.mod h1:JsC7dqQc55MlZ5mvNsDMMge71u8pVcSzU3RNz2h/5yQ=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.24 h1:u6kJU2i0va1AgtJsH3RdWKWqHULlTh7zHwb35Womf74=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.24/go.mod h1:7GY+xLcXOFUpCkNwDReft9qOAVg54A4/AnjHIU7sSAY=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.24 h1:Xhbcf3KugX6vX7SDyUK205Oicyfg7EGuvoVNyP5L6DM=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.24/go.mod h1:rwDgb2HNOGZsnTHylOUedM7Vnl+bCfnXDqUNPsFWYfk=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.27 h1:8sPbKi1/KRHwl5oR3qN9mUXestCeHuaRutxylnr/eVY=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.27/go.mod h1:QV9IVIopJ1dpQUno0f9VYDUwOEjj8u0iEJ4JiZVre3Y=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.27 h1:9d8AoASQY9UwrOSmiJ7uSM0MGUPFhnenwSvpaFfat2c=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.27/go.mod h1:x0rldpsnUQaQIs4Rh+Vwm9Z/0vI6BxadGtsgJfZFb8s=
|
||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.25 h1:54CTMmlJ71Rk2dYvM9qZOob+39wjlVja2zDLxCu69Ew=
|
||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.25/go.mod h1:BZaHqxsS9vN1fvV5EfEl0OBLOk5+AajWsMu6MjqnZB4=
|
||||
github.com/aws/aws-sdk-go-v2/service/acm v1.38.3 h1:Fzab84hCu3rw9R9Y3mH7SHfr/cSEHnCB0Mq1JCdr9t0=
|
||||
@ -222,6 +222,8 @@ github.com/aws/aws-sdk-go-v2/service/acm v1.38.3/go.mod h1:yCteizCNPaHt0SnNusoGG
|
||||
github.com/aws/aws-sdk-go-v2/service/cloudfront v1.63.0 h1:YNpvY2mAGhoTHPEvsqPuDb8K5JBjorbVMaitP8i4OXI=
|
||||
github.com/aws/aws-sdk-go-v2/service/cloudfront v1.63.0/go.mod h1:brhMG/gR2xEB5lezxL2Cx+hqsEzGUn4LhNUtu7+ePFE=
|
||||
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/elasticloadbalancing v1.34.2 h1:N69Uy8towDrupiVOPgH3ADlstEQEhXv5QCXOqEfvmJ0=
|
||||
github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing v1.34.2/go.mod h1:1Yr+5r8qPhVQbDlN/kgxzjc++aNkxcKQZpMckhk4+94=
|
||||
github.com/aws/aws-sdk-go-v2/service/iam v1.53.10 h1:kcN3I3llO7VwIY5w3Pc5FmEonpsr23Ou7Cwk4qf7dik=
|
||||
github.com/aws/aws-sdk-go-v2/service/iam v1.53.10/go.mod h1:1vkJzjCYC3byO0kIrBqLPzvZpuvYhPXkuyARs6E7tM4=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.9 h1:FLudkZLt5ci0ozzgkVo8BJGwvqNaZbTWb3UcucAateA=
|
||||
@ -241,8 +243,8 @@ github.com/aws/aws-sdk-go-v2/service/ssooidc v1.36.1/go.mod h1:er0SFJfdV89Rit5hI
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.42.2 h1:XKnxlM4KZH1gktcsh3zSWc7GW4KivEv/OkifmHOhCUY=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.42.2/go.mod h1:KJYmkQaFB3SUW2j3aBkPsxNmAb4ZsSOvbvCpuxzHJA0=
|
||||
github.com/aws/smithy-go v1.8.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E=
|
||||
github.com/aws/smithy-go v1.25.1 h1:J8ERsGSU7d+aCmdQur5Txg6bVoYelvQJgtZehD12GkI=
|
||||
github.com/aws/smithy-go v1.25.1/go.mod h1:YE2RhdIuDbA5E5bTdciG9KrW3+TiEONeUWCqxX9i1Fc=
|
||||
github.com/aws/smithy-go v1.27.0 h1:ZoFioDKJxkSIW2otF9T0aPtNlUwhdVCcuZh/rzH9Hus=
|
||||
github.com/aws/smithy-go v1.27.0/go.mod h1:YE2RhdIuDbA5E5bTdciG9KrW3+TiEONeUWCqxX9i1Fc=
|
||||
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
|
||||
github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
|
||||
github.com/baidubce/bce-sdk-go v0.9.267 h1:0l3UipFvWVsEv+FcontxWRs6ny8xvBeRISLbdNtO/bw=
|
||||
|
||||
29
internal/certmgmt/deployers/sp_aws_clb.go
Normal file
29
internal/certmgmt/deployers/sp_aws_clb.go
Normal file
@ -0,0 +1,29 @@
|
||||
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/aws-clb"
|
||||
xmaps "github.com/certimate-go/certimate/pkg/utils/maps"
|
||||
)
|
||||
|
||||
func init() {
|
||||
Registries.MustRegister(domain.DeploymentProviderTypeAWSCLB, func(options *ProviderFactoryOptions) (core.Deployer, error) {
|
||||
credentials := domain.AccessConfigForAWS{}
|
||||
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{
|
||||
AccessKeyId: credentials.AccessKeyId,
|
||||
SecretAccessKey: credentials.SecretAccessKey,
|
||||
Region: xmaps.GetString(options.ProviderExtendedConfig, "region"),
|
||||
LoadbalancerName: xmaps.GetString(options.ProviderExtendedConfig, "loadbalancerName"),
|
||||
LoadbalancerPort: xmaps.GetOrDefaultInt32(options.ProviderExtendedConfig, "loadbalancerPort", 443),
|
||||
CertificateSource: xmaps.GetOrDefaultString(options.ProviderExtendedConfig, "certificateSource", dplyimpl.CERTIFICATE_SOURCE_ACM),
|
||||
})
|
||||
return provider, err
|
||||
})
|
||||
}
|
||||
@ -21,7 +21,7 @@ func init() {
|
||||
SecretAccessKey: credentials.SecretAccessKey,
|
||||
Region: xmaps.GetString(options.ProviderExtendedConfig, "region"),
|
||||
DistributionId: xmaps.GetString(options.ProviderExtendedConfig, "distributionId"),
|
||||
CertificateSource: xmaps.GetOrDefaultString(options.ProviderExtendedConfig, "certificateSource", "ACM"),
|
||||
CertificateSource: xmaps.GetOrDefaultString(options.ProviderExtendedConfig, "certificateSource", dplyimpl.CERTIFICATE_SOURCE_ACM),
|
||||
})
|
||||
return provider, err
|
||||
})
|
||||
|
||||
@ -326,6 +326,7 @@ const (
|
||||
DeploymentProviderTypeAliyunWAF = DeploymentProviderType(AccessProviderTypeAliyun + "-waf")
|
||||
DeploymentProviderTypeAPISIX = DeploymentProviderType(AccessProviderTypeAPISIX)
|
||||
DeploymentProviderTypeAWSACM = DeploymentProviderType(AccessProviderTypeAWS + "-acm")
|
||||
DeploymentProviderTypeAWSCLB = DeploymentProviderType(AccessProviderTypeAWS + "-clb")
|
||||
DeploymentProviderTypeAWSCloudFront = DeploymentProviderType(AccessProviderTypeAWS + "-cloudfront")
|
||||
DeploymentProviderTypeAWSIAM = DeploymentProviderType(AccessProviderTypeAWS + "-iam")
|
||||
DeploymentProviderTypeAzureKeyVault = DeploymentProviderType(AccessProviderTypeAzure + "-keyvault")
|
||||
|
||||
@ -77,8 +77,8 @@ func (c *Certmgr) Upload(ctx context.Context, certPEM, privkeyPEM string) (*Uplo
|
||||
}
|
||||
|
||||
// 获取证书列表,避免重复上传
|
||||
// REF: https://docs.aws.amazon.com/en_us/acm/latest/APIReference/API_ListCertificates.html
|
||||
// REF: https://docs.aws.amazon.com/en_us/acm/latest/APIReference/API_GetCertificate.html
|
||||
// REF: https://docs.aws.amazon.com/acm/latest/APIReference/API_ListCertificates.html
|
||||
// REF: https://docs.aws.amazon.com/acm/latest/APIReference/API_GetCertificate.html
|
||||
listCertificatesNextToken := (*string)(nil)
|
||||
for {
|
||||
select {
|
||||
@ -127,7 +127,10 @@ func (c *Certmgr) Upload(ctx context.Context, certPEM, privkeyPEM string) (*Uplo
|
||||
// 如果以上信息都一致,则视为已存在相同证书,直接返回
|
||||
c.logger.Info("ssl certificate already exists")
|
||||
return &UploadResult{
|
||||
CertId: *certItem.CertificateArn,
|
||||
CertId: aws.ToString(certItem.CertificateArn),
|
||||
ExtendedData: map[string]any{
|
||||
"Arn": aws.ToString(certItem.CertificateArn),
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
@ -139,7 +142,7 @@ func (c *Certmgr) Upload(ctx context.Context, certPEM, privkeyPEM string) (*Uplo
|
||||
}
|
||||
|
||||
// 导入证书
|
||||
// REF: https://docs.aws.amazon.com/en_us/acm/latest/APIReference/API_ImportCertificate.html
|
||||
// REF: https://docs.aws.amazon.com/acm/latest/APIReference/API_ImportCertificate.html
|
||||
importCertificateReq := &awsacm.ImportCertificateInput{
|
||||
Certificate: ([]byte)(serverCertPEM),
|
||||
CertificateChain: ([]byte)(intermediaCertPEM),
|
||||
@ -153,6 +156,9 @@ func (c *Certmgr) Upload(ctx context.Context, certPEM, privkeyPEM string) (*Uplo
|
||||
|
||||
return &UploadResult{
|
||||
CertId: aws.ToString(importCertificateResp.CertificateArn),
|
||||
ExtendedData: map[string]any{
|
||||
"Arn": aws.ToString(importCertificateResp.CertificateArn),
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
@ -164,7 +170,7 @@ func (c *Certmgr) Replace(ctx context.Context, certIdOrName string, certPEM, pri
|
||||
}
|
||||
|
||||
// 导入证书
|
||||
// REF: https://docs.aws.amazon.com/en_us/acm/latest/APIReference/API_ImportCertificate.html
|
||||
// REF: https://docs.aws.amazon.com/acm/latest/APIReference/API_ImportCertificate.html
|
||||
importCertificateReq := &awsacm.ImportCertificateInput{
|
||||
CertificateArn: aws.String(certIdOrName),
|
||||
Certificate: ([]byte)(serverCertPEM),
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package awsiam
|
||||
|
||||
import (
|
||||
"cmp"
|
||||
"context"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
@ -80,8 +81,8 @@ func (c *Certmgr) Upload(ctx context.Context, certPEM, privkeyPEM string) (*Uplo
|
||||
}
|
||||
|
||||
// 获取证书列表,避免重复上传
|
||||
// REF: https://docs.aws.amazon.com/en_us/IAM/latest/APIReference/API_ListServerCertificates.html
|
||||
// REF: https://docs.aws.amazon.com/en_us/IAM/latest/APIReference/API_GetServerCertificate.html
|
||||
// REF: https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListServerCertificates.html
|
||||
// REF: https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetServerCertificate.html
|
||||
listServerCertificatesMarker := (*string)(nil)
|
||||
for {
|
||||
select {
|
||||
@ -132,6 +133,10 @@ func (c *Certmgr) Upload(ctx context.Context, certPEM, privkeyPEM string) (*Uplo
|
||||
return &UploadResult{
|
||||
CertId: aws.ToString(certItem.ServerCertificateId),
|
||||
CertName: aws.ToString(certItem.ServerCertificateName),
|
||||
ExtendedData: map[string]any{
|
||||
"Arn": aws.ToString(certItem.Arn),
|
||||
"Path": aws.ToString(certItem.Path),
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
@ -146,17 +151,14 @@ func (c *Certmgr) Upload(ctx context.Context, certPEM, privkeyPEM string) (*Uplo
|
||||
certName := fmt.Sprintf("certimate-%d", time.Now().UnixMilli())
|
||||
|
||||
// 导入证书
|
||||
// REF: https://docs.aws.amazon.com/en_us/IAM/latest/APIReference/API_UploadServerCertificate.html
|
||||
// REF: https://docs.aws.amazon.com/IAM/latest/APIReference/API_UploadServerCertificate.html
|
||||
uploadServerCertificateReq := &awsiam.UploadServerCertificateInput{
|
||||
ServerCertificateName: aws.String(certName),
|
||||
Path: aws.String(c.config.CertificatePath),
|
||||
Path: aws.String(cmp.Or(c.config.CertificatePath, "/")),
|
||||
CertificateBody: aws.String(serverCertPEM),
|
||||
CertificateChain: aws.String(intermediaCertPEM),
|
||||
PrivateKey: aws.String(privkeyPEM),
|
||||
}
|
||||
if c.config.CertificatePath == "" {
|
||||
uploadServerCertificateReq.Path = aws.String("/")
|
||||
}
|
||||
uploadServerCertificateResp, err := c.sdkClient.UploadServerCertificate(ctx, uploadServerCertificateReq)
|
||||
c.logger.Debug("sdk request 'iam.UploadServerCertificate'", slog.Any("request", uploadServerCertificateReq), slog.Any("response", uploadServerCertificateResp))
|
||||
if err != nil {
|
||||
@ -165,7 +167,11 @@ func (c *Certmgr) Upload(ctx context.Context, certPEM, privkeyPEM string) (*Uplo
|
||||
|
||||
return &UploadResult{
|
||||
CertId: aws.ToString(uploadServerCertificateResp.ServerCertificateMetadata.ServerCertificateId),
|
||||
CertName: certName,
|
||||
CertName: aws.ToString(uploadServerCertificateResp.ServerCertificateMetadata.ServerCertificateName),
|
||||
ExtendedData: map[string]any{
|
||||
"Arn": aws.ToString(uploadServerCertificateResp.ServerCertificateMetadata.Arn),
|
||||
"Path": aws.ToString(uploadServerCertificateResp.ServerCertificateMetadata.Path),
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
||||
146
pkg/core/deployer/providers/aws-clb/aws_clb.go
Normal file
146
pkg/core/deployer/providers/aws-clb/aws_clb.go
Normal file
@ -0,0 +1,146 @@
|
||||
package awsclb
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
|
||||
aws "github.com/aws/aws-sdk-go-v2/aws"
|
||||
awscfg "github.com/aws/aws-sdk-go-v2/config"
|
||||
awscred "github.com/aws/aws-sdk-go-v2/credentials"
|
||||
"github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing"
|
||||
|
||||
"github.com/certimate-go/certimate/pkg/core"
|
||||
cmgrimplacm "github.com/certimate-go/certimate/pkg/core/certmgr/providers/aws-acm"
|
||||
cmgrimpliam "github.com/certimate-go/certimate/pkg/core/certmgr/providers/aws-iam"
|
||||
)
|
||||
|
||||
type (
|
||||
Provider = core.Deployer
|
||||
DeployResult = core.DeployerDeployResult
|
||||
)
|
||||
|
||||
type DeployerConfig struct {
|
||||
// AWS AccessKeyId。
|
||||
AccessKeyId string `json:"accessKeyId"`
|
||||
// AWS SecretAccessKey。
|
||||
SecretAccessKey string `json:"secretAccessKey"`
|
||||
// AWS 区域。
|
||||
Region string `json:"region"`
|
||||
// AWS CLB 负载均衡器名称。
|
||||
LoadbalancerName string `json:"loadbalancerName"`
|
||||
// AWS CLB 负载均衡器端口。
|
||||
LoadbalancerPort int32 `json:"loadbalancerPort"`
|
||||
// AWS CLB 证书来源。
|
||||
// 可取值 "ACM"、"IAM"。
|
||||
CertificateSource string `json:"certificateSource"`
|
||||
}
|
||||
|
||||
type Deployer struct {
|
||||
config *DeployerConfig
|
||||
logger *slog.Logger
|
||||
sdkClient *elasticloadbalancing.Client
|
||||
sdkCertmgr core.Certmgr
|
||||
}
|
||||
|
||||
var _ Provider = (*Deployer)(nil)
|
||||
|
||||
func NewDeployer(config *DeployerConfig) (*Deployer, error) {
|
||||
if config == nil {
|
||||
return nil, fmt.Errorf("the configuration of the deployer provider is nil")
|
||||
}
|
||||
|
||||
client, err := createSDKClient(config.AccessKeyId, config.SecretAccessKey, config.Region)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not create client: %w", err)
|
||||
}
|
||||
|
||||
var pcertmgr core.Certmgr
|
||||
switch config.CertificateSource {
|
||||
case CERTIFICATE_SOURCE_ACM:
|
||||
pcertmgr, err = cmgrimplacm.NewCertmgr(&cmgrimplacm.CertmgrConfig{
|
||||
AccessKeyId: config.AccessKeyId,
|
||||
SecretAccessKey: config.SecretAccessKey,
|
||||
Region: config.Region,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not create certmgr: %w", err)
|
||||
}
|
||||
|
||||
case CERTIFICATE_SOURCE_IAM:
|
||||
pcertmgr, err = cmgrimpliam.NewCertmgr(&cmgrimpliam.CertmgrConfig{
|
||||
AccessKeyId: config.AccessKeyId,
|
||||
SecretAccessKey: config.SecretAccessKey,
|
||||
Region: config.Region,
|
||||
CertificatePath: "/elb/",
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not create certmgr: %w", err)
|
||||
}
|
||||
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported certificate source: '%s'", config.CertificateSource)
|
||||
}
|
||||
|
||||
return &Deployer{
|
||||
config: config,
|
||||
logger: slog.Default(),
|
||||
sdkClient: client,
|
||||
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) {
|
||||
if d.config.LoadbalancerName == "" {
|
||||
return nil, fmt.Errorf("config `loadbalancerName` is required")
|
||||
}
|
||||
if d.config.LoadbalancerPort == 0 {
|
||||
return nil, fmt.Errorf("config `loadbalancerPort` is required")
|
||||
}
|
||||
|
||||
// 上传证书
|
||||
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))
|
||||
}
|
||||
|
||||
// 替换 HTTPS 侦听器 SSL 证书
|
||||
// REF: https://docs.aws.amazon.com/elasticloadbalancing/2012-06-01/APIReference/API_SetLoadBalancerListenerSSLCertificate.html
|
||||
setLoadBalancerListenerSSLCertificateReq := &elasticloadbalancing.SetLoadBalancerListenerSSLCertificateInput{
|
||||
LoadBalancerName: aws.String(d.config.LoadbalancerName),
|
||||
LoadBalancerPort: d.config.LoadbalancerPort,
|
||||
SSLCertificateId: aws.String(upres.ExtendedData["Arn"].(string)),
|
||||
}
|
||||
setLoadBalancerListenerSSLCertificateResp, err := d.sdkClient.SetLoadBalancerListenerSSLCertificate(ctx, setLoadBalancerListenerSSLCertificateReq)
|
||||
d.logger.Debug("sdk request 'elasticloadbalancing.SetLoadBalancerListenerSSLCertificate'", slog.Any("request", setLoadBalancerListenerSSLCertificateReq), slog.Any("response", setLoadBalancerListenerSSLCertificateResp))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to execute sdk request 'elasticloadbalancing.SetLoadBalancerListenerSSLCertificate': %w", err)
|
||||
}
|
||||
|
||||
return &DeployResult{}, nil
|
||||
}
|
||||
|
||||
func createSDKClient(accessKeyId, secretAccessKey, region string) (*elasticloadbalancing.Client, error) {
|
||||
cfg, err := awscfg.LoadDefaultConfig(context.Background())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
client := elasticloadbalancing.NewFromConfig(cfg, func(o *elasticloadbalancing.Options) {
|
||||
o.Region = region
|
||||
o.Credentials = aws.NewCredentialsCache(awscred.NewStaticCredentialsProvider(accessKeyId, secretAccessKey, ""))
|
||||
})
|
||||
return client, nil
|
||||
}
|
||||
62
pkg/core/deployer/providers/aws-clb/aws_clb_test.go
Normal file
62
pkg/core/deployer/providers/aws-clb/aws_clb_test.go
Normal file
@ -0,0 +1,62 @@
|
||||
package awsclb_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/certimate-go/certimate/pkg/core/deployer/internal/tester"
|
||||
impl "github.com/certimate-go/certimate/pkg/core/deployer/providers/aws-clb"
|
||||
)
|
||||
|
||||
var (
|
||||
fp = tester.Args("AWSCLB_")
|
||||
fTestCertPath string
|
||||
fTestKeyPath string
|
||||
fAccessKeyId string
|
||||
fSecretAccessKey string
|
||||
fRegion string
|
||||
fLoadbalancerName string
|
||||
fLoadbalancerPort int
|
||||
)
|
||||
|
||||
func init() {
|
||||
fp.DefineString(&fTestCertPath, "TESTCERTPATH")
|
||||
fp.DefineString(&fTestKeyPath, "TESTKEYPATH")
|
||||
fp.DefineString(&fAccessKeyId, "ACCESSKEYID")
|
||||
fp.DefineString(&fSecretAccessKey, "SECRETACCESSKEY")
|
||||
fp.DefineString(&fRegion, "REGION")
|
||||
fp.DefineString(&fLoadbalancerName, "LOADBALANCERNAME")
|
||||
fp.DefineInt(&fLoadbalancerPort, "LOADBALANCERPORT")
|
||||
}
|
||||
|
||||
/*
|
||||
Shell command to run this test:
|
||||
|
||||
go test -v ./aws_clb_test.go -args \
|
||||
--AWSCLB_TESTCERTPATH="/path/to/your-test-cert.pem" \
|
||||
--AWSCLB_TESTKEYPATH="/path/to/your-test-key.pem" \
|
||||
--AWSCLB_ACCESSKEYID="your-access-key-id" \
|
||||
--AWSCLB_SECRETACCESSKEY="your-secret-access-id" \
|
||||
--AWSCLB_REGION="us-east-1" \
|
||||
--AWSCLB_LOADBALANCERNAME="your-loadbalancer-name" \
|
||||
--AWSCLB_LOADBALANCERPORT=443
|
||||
*/
|
||||
func TestProvider(t *testing.T) {
|
||||
fp.Parse()
|
||||
|
||||
t.Run("Deploy", func(t *testing.T) {
|
||||
provider, err := impl.NewDeployer(&impl.DeployerConfig{
|
||||
AccessKeyId: fAccessKeyId,
|
||||
SecretAccessKey: fSecretAccessKey,
|
||||
Region: fRegion,
|
||||
LoadbalancerName: fLoadbalancerName,
|
||||
LoadbalancerPort: int32(fLoadbalancerPort),
|
||||
CertificateSource: impl.CERTIFICATE_SOURCE_ACM,
|
||||
})
|
||||
if err != nil {
|
||||
t.Errorf("err: %+v", err)
|
||||
return
|
||||
}
|
||||
|
||||
tester.TestDeploy(t, provider, tester.TestDeployArgs{CertPath: fTestCertPath, KeyPath: fTestKeyPath})
|
||||
})
|
||||
}
|
||||
6
pkg/core/deployer/providers/aws-clb/consts.go
Normal file
6
pkg/core/deployer/providers/aws-clb/consts.go
Normal file
@ -0,0 +1,6 @@
|
||||
package awsclb
|
||||
|
||||
const (
|
||||
CERTIFICATE_SOURCE_ACM = "ACM"
|
||||
CERTIFICATE_SOURCE_IAM = "IAM"
|
||||
)
|
||||
@ -101,7 +101,7 @@ func (d *Deployer) SetLogger(logger *slog.Logger) {
|
||||
|
||||
func (d *Deployer) Deploy(ctx context.Context, certPEM, privkeyPEM string) (*DeployResult, error) {
|
||||
if d.config.DistributionId == "" {
|
||||
return nil, fmt.Errorf("config `distribuitionId` is required")
|
||||
return nil, fmt.Errorf("config `distributionId` is required")
|
||||
}
|
||||
|
||||
// 上传证书
|
||||
@ -113,7 +113,7 @@ func (d *Deployer) Deploy(ctx context.Context, certPEM, privkeyPEM string) (*Dep
|
||||
}
|
||||
|
||||
// 获取分配配置
|
||||
// REF: https://docs.aws.amazon.com/en_us/cloudfront/latest/APIReference/API_GetDistributionConfig.html
|
||||
// REF: https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_GetDistributionConfig.html
|
||||
getDistributionConfigReq := &cloudfront.GetDistributionConfigInput{
|
||||
Id: aws.String(d.config.DistributionId),
|
||||
}
|
||||
@ -124,7 +124,7 @@ func (d *Deployer) Deploy(ctx context.Context, certPEM, privkeyPEM string) (*Dep
|
||||
}
|
||||
|
||||
// 更新分配配置
|
||||
// REF: https://docs.aws.amazon.com/zh_cn/cloudfront/latest/APIReference/API_UpdateDistribution.html
|
||||
// REF: https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_UpdateDistribution.html
|
||||
updateDistributionReq := &cloudfront.UpdateDistributionInput{
|
||||
Id: aws.String(d.config.DistributionId),
|
||||
DistributionConfig: getDistributionConfigResp.DistributionConfig,
|
||||
|
||||
@ -14,7 +14,7 @@ var (
|
||||
fAccessKeyId string
|
||||
fSecretAccessKey string
|
||||
fRegion string
|
||||
fDistribuitionId string
|
||||
fDistributionId string
|
||||
)
|
||||
|
||||
func init() {
|
||||
@ -23,7 +23,7 @@ func init() {
|
||||
fp.DefineString(&fAccessKeyId, "ACCESSKEYID")
|
||||
fp.DefineString(&fSecretAccessKey, "SECRETACCESSKEY")
|
||||
fp.DefineString(&fRegion, "REGION")
|
||||
fp.DefineString(&fDistribuitionId, "DISTRIBUTIONID")
|
||||
fp.DefineString(&fDistributionId, "DISTRIBUTIONID")
|
||||
}
|
||||
|
||||
/*
|
||||
@ -42,10 +42,11 @@ func TestProvider(t *testing.T) {
|
||||
|
||||
t.Run("Deploy", func(t *testing.T) {
|
||||
provider, err := impl.NewDeployer(&impl.DeployerConfig{
|
||||
AccessKeyId: fAccessKeyId,
|
||||
SecretAccessKey: fSecretAccessKey,
|
||||
Region: fRegion,
|
||||
DistributionId: fDistribuitionId,
|
||||
AccessKeyId: fAccessKeyId,
|
||||
SecretAccessKey: fSecretAccessKey,
|
||||
Region: fRegion,
|
||||
DistributionId: fDistributionId,
|
||||
CertificateSource: impl.CERTIFICATE_SOURCE_ACM,
|
||||
})
|
||||
if err != nil {
|
||||
t.Errorf("err: %+v", err)
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
import { DEPLOYMENT_PROVIDERS, type DeploymentProviderType } from "@/domain/provider";
|
||||
|
||||
@ -23,6 +23,7 @@ import BizDeployNodeConfigFieldsProviderAliyunVOD from "./BizDeployNodeConfigFie
|
||||
import BizDeployNodeConfigFieldsProviderAliyunWAF from "./BizDeployNodeConfigFieldsProviderAliyunWAF";
|
||||
import BizDeployNodeConfigFieldsProviderAPISIX from "./BizDeployNodeConfigFieldsProviderAPISIX";
|
||||
import BizDeployNodeConfigFieldsProviderAWSACM from "./BizDeployNodeConfigFieldsProviderAWSACM";
|
||||
import BizDeployNodeConfigFieldsProviderAWSCLB from "./BizDeployNodeConfigFieldsProviderAWSCLB";
|
||||
import BizDeployNodeConfigFieldsProviderAWSCloudFront from "./BizDeployNodeConfigFieldsProviderAWSCloudFront";
|
||||
import BizDeployNodeConfigFieldsProviderAWSIAM from "./BizDeployNodeConfigFieldsProviderAWSIAM";
|
||||
import BizDeployNodeConfigFieldsProviderAzureKeyVault from "./BizDeployNodeConfigFieldsProviderAzureKeyVault";
|
||||
@ -157,6 +158,7 @@ const providerComponentMap: Partial<Record<DeploymentProviderType, React.Compone
|
||||
[DEPLOYMENT_PROVIDERS.ALIYUN_WAF]: BizDeployNodeConfigFieldsProviderAliyunWAF,
|
||||
[DEPLOYMENT_PROVIDERS.APISIX]: BizDeployNodeConfigFieldsProviderAPISIX,
|
||||
[DEPLOYMENT_PROVIDERS.AWS_ACM]: BizDeployNodeConfigFieldsProviderAWSACM,
|
||||
[DEPLOYMENT_PROVIDERS.AWS_CLB]: BizDeployNodeConfigFieldsProviderAWSCLB,
|
||||
[DEPLOYMENT_PROVIDERS.AWS_CLOUDFRONT]: BizDeployNodeConfigFieldsProviderAWSCloudFront,
|
||||
[DEPLOYMENT_PROVIDERS.AWS_IAM]: BizDeployNodeConfigFieldsProviderAWSIAM,
|
||||
[DEPLOYMENT_PROVIDERS.AZURE_KEYVAULT]: BizDeployNodeConfigFieldsProviderAzureKeyVault,
|
||||
|
||||
@ -0,0 +1,92 @@
|
||||
import { getI18n, useTranslation } from "react-i18next";
|
||||
import { Form, Input, Select } from "antd";
|
||||
import { createSchemaFieldRule } from "antd-zod";
|
||||
import { z } from "zod";
|
||||
|
||||
import { isPortNumber } from "@/utils/validator";
|
||||
|
||||
import { useFormNestedFieldsContext } from "./_context";
|
||||
|
||||
const BizDeployNodeConfigFieldsProviderAWSCLB = () => {
|
||||
const { i18n, t } = useTranslation();
|
||||
|
||||
const { parentNamePath } = useFormNestedFieldsContext();
|
||||
const formSchema = z.object({
|
||||
[parentNamePath]: getSchema({ i18n }),
|
||||
});
|
||||
const formRule = createSchemaFieldRule(formSchema);
|
||||
const initialValues = getInitialValues();
|
||||
|
||||
return (
|
||||
<>
|
||||
<Form.Item
|
||||
name={[parentNamePath, "region"]}
|
||||
initialValue={initialValues.region}
|
||||
label={t("workflow_node.deploy.form.aws_clb_region.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.aws_clb_region.tooltip") }}></span>}
|
||||
>
|
||||
<Input placeholder={t("workflow_node.deploy.form.aws_clb_region.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name={[parentNamePath, "loadbalancerName"]}
|
||||
initialValue={initialValues.loadbalancerName}
|
||||
label={t("workflow_node.deploy.form.aws_clb_loadbalancer_name.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.aws_clb_loadbalancer_name.tooltip") }}></span>}
|
||||
>
|
||||
<Input placeholder={t("workflow_node.deploy.form.aws_clb_loadbalancer_name.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name={[parentNamePath, "loadbalancerPort"]}
|
||||
initialValue={initialValues.loadbalancerPort}
|
||||
label={t("workflow_node.deploy.form.aws_clb_loadbalancer_port.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.aws_clb_loadbalancer_port.tooltip") }}></span>}
|
||||
>
|
||||
<Input type="number" min={1} max={65535} placeholder={t("workflow_node.deploy.form.aws_clb_loadbalancer_port.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name={[parentNamePath, "certificateSource"]}
|
||||
initialValue={initialValues.certificateSource}
|
||||
label={t("workflow_node.deploy.form.aws_clb_certificate_source.label")}
|
||||
rules={[formRule]}
|
||||
>
|
||||
<Select
|
||||
options={["ACM", "IAM"].map((s) => ({ label: s, value: s }))}
|
||||
placeholder={t("workflow_node.deploy.form.aws_clb_certificate_source.placeholder")}
|
||||
/>
|
||||
</Form.Item>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const getInitialValues = (): Nullish<z.infer<ReturnType<typeof getSchema>>> => {
|
||||
return {
|
||||
region: "",
|
||||
loadbalancerName: "",
|
||||
loadbalancerPort: 443,
|
||||
certificateSource: "ACM",
|
||||
};
|
||||
};
|
||||
|
||||
const getSchema = ({ i18n = getI18n() }: { i18n?: ReturnType<typeof getI18n> }) => {
|
||||
const { t } = i18n;
|
||||
|
||||
return z.object({
|
||||
region: z.string().nonempty(),
|
||||
loadbalancerName: z.string().nonempty(),
|
||||
loadbalancerPort: z.coerce.number().refine((v) => isPortNumber(v), t("common.errmsg.port_invalid")),
|
||||
certificateSource: z.string().nonempty(),
|
||||
});
|
||||
};
|
||||
|
||||
const _default = Object.assign(BizDeployNodeConfigFieldsProviderAWSCLB, {
|
||||
getInitialValues,
|
||||
getSchema,
|
||||
});
|
||||
|
||||
export default _default;
|
||||
@ -611,6 +611,7 @@ export const DEPLOYMENT_PROVIDERS = Object.freeze({
|
||||
ALIYUN_WAF: `${ACCESS_PROVIDERS.ALIYUN}-waf`,
|
||||
APISIX: `${ACCESS_PROVIDERS.APISIX}`,
|
||||
AWS_ACM: `${ACCESS_PROVIDERS.AWS}-acm`,
|
||||
AWS_CLB: `${ACCESS_PROVIDERS.AWS}-clb`,
|
||||
AWS_CLOUDFRONT: `${ACCESS_PROVIDERS.AWS}-cloudfront`,
|
||||
AWS_IAM: `${ACCESS_PROVIDERS.AWS}-iam`,
|
||||
AZURE_KEYVAULT: `${ACCESS_PROVIDERS.AZURE}-keyvault`,
|
||||
@ -859,6 +860,7 @@ export const deploymentProvidersMap: Map<DeploymentProvider["type"] | string, De
|
||||
[DEPLOYMENT_PROVIDERS.RAINYUN_SSLCENTER, "provider.rainyun_sslcenter_upload", DEPLOYMENT_CATEGORIES.SSL],
|
||||
[DEPLOYMENT_PROVIDERS.UNICLOUD_WEBHOST, "provider.unicloud_webhost", DEPLOYMENT_CATEGORIES.WEBSITE],
|
||||
[DEPLOYMENT_PROVIDERS.AWS_CLOUDFRONT, "provider.aws_cloudfront", DEPLOYMENT_CATEGORIES.CDN],
|
||||
[DEPLOYMENT_PROVIDERS.AWS_CLB, "provider.aws_clb", DEPLOYMENT_CATEGORIES.LOADBALANCE],
|
||||
[DEPLOYMENT_PROVIDERS.AWS_ACM, "provider.aws_acm", DEPLOYMENT_CATEGORIES.SSL],
|
||||
[DEPLOYMENT_PROVIDERS.AWS_IAM, "provider.aws_iam", DEPLOYMENT_CATEGORIES.SSL],
|
||||
[DEPLOYMENT_PROVIDERS.AZURE_KEYVAULT, "provider.azure_keyvault", DEPLOYMENT_CATEGORIES.SSL],
|
||||
|
||||
@ -60,6 +60,7 @@
|
||||
"arvancloud": "ArvanCloud",
|
||||
"aws": "AWS",
|
||||
"aws_acm": "AWS - ACM (Amazon Certificate Manager)",
|
||||
"aws_clb": "AWS - CLB (Classic Load Balancer)",
|
||||
"aws_cloudfront": "AWS - CloudFront",
|
||||
"aws_iam": "AWS - IAM (Identity and Access Management)",
|
||||
"aws_lightsail": "AWS - Lightsail",
|
||||
|
||||
@ -969,6 +969,25 @@
|
||||
"label": "AWS CloudFront certificate source",
|
||||
"placeholder": "Please select AWS CloudFront certificate source"
|
||||
},
|
||||
"aws_clb_region": {
|
||||
"label": "AWS Region",
|
||||
"placeholder": "Please enter AWS CLB region (e.g. us-east-1)",
|
||||
"tooltip": "For more information, see <a href=\"https://docs.aws.amazon.com/en_us/general/latest/gr/rande.html#regional-endpoints\" target=\"_blank\">https://docs.aws.amazon.com/en_us/general/latest/gr/rande.html#regional-endpoints</a>"
|
||||
},
|
||||
"aws_clb_loadbalancer_name": {
|
||||
"label": "AWS CLB load balancer name",
|
||||
"placeholder": "Please enter AWS CLB load balancer name",
|
||||
"tooltip": "For more information, see <a href=\"https://docs.aws.amazon.com/en_us/elasticloadbalancing/latest/classic/elb-create-https-ssl-load-balancer.html\" target=\"_blank\">https://docs.aws.amazon.com/en_us/elasticloadbalancing/latest/classic/elb-create-https-ssl-load-balancer.html</a>"
|
||||
},
|
||||
"aws_clb_loadbalancer_port": {
|
||||
"label": "AWS CLB load balancer port",
|
||||
"placeholder": "Please enter AWS CLB load balancer port",
|
||||
"tooltip": "For more information, see <a href=\"https://docs.aws.amazon.com/en_us/elasticloadbalancing/latest/classic/elb-create-https-ssl-load-balancer.html\" target=\"_blank\">https://docs.aws.amazon.com/en_us/elasticloadbalancing/latest/classic/elb-create-https-ssl-load-balancer.html</a>"
|
||||
},
|
||||
"aws_clb_certificate_source": {
|
||||
"label": "AWS CLB certificate source",
|
||||
"placeholder": "Please select AWS CLB certificate source"
|
||||
},
|
||||
"aws_iam_region": {
|
||||
"label": "AWS Region",
|
||||
"placeholder": "Please enter AWS IAM region (e.g. us-east-1)",
|
||||
|
||||
@ -60,6 +60,7 @@
|
||||
"arvancloud": "ArvanCloud",
|
||||
"aws": "AWS",
|
||||
"aws_acm": "AWS - ACM (Amazon Certificate Manager)",
|
||||
"aws_clb": "AWS - CLB (Classic Load Balancer)",
|
||||
"aws_cloudfront": "AWS - CloudFront",
|
||||
"aws_iam": "AWS - IAM (Identity and Access Management)",
|
||||
"aws_lightsail": "AWS - Lightsail",
|
||||
|
||||
@ -968,6 +968,25 @@
|
||||
"label": "AWS CloudFront 证书来源",
|
||||
"placeholder": "请选择 AWS CloudFront 证书来源"
|
||||
},
|
||||
"aws_clb_region": {
|
||||
"label": "AWS 服务区域",
|
||||
"placeholder": "请输入 AWS CLB 服务区域(例如:us-east-1)",
|
||||
"tooltip": "这是什么?请参阅 <a href=\"https://docs.aws.amazon.com/zh_cn/general/latest/gr/rande.html#regional-endpoints\" target=\"_blank\">https://docs.aws.amazon.com/zh_cn/general/latest/gr/rande.html#regional-endpoints</a>"
|
||||
},
|
||||
"aws_clb_loadbalancer_name": {
|
||||
"label": "AWS CLB 负载均衡器名称",
|
||||
"placeholder": "请输入 AWS CLB 负载均衡器名称",
|
||||
"tooltip": "这是什么?请参阅 <a href=\"https://docs.aws.amazon.com/zh_cn/elasticloadbalancing/latest/classic/elb-create-https-ssl-load-balancer.html\" target=\"_blank\">https://docs.aws.amazon.com/zh_cn/elasticloadbalancing/latest/classic/elb-create-https-ssl-load-balancer.html</a>"
|
||||
},
|
||||
"aws_clb_loadbalancer_port": {
|
||||
"label": "AWS CLB 负载均衡器侦听端口",
|
||||
"placeholder": "请输入 AWS CLB 负载均衡器侦听端口",
|
||||
"tooltip": "这是什么?请参阅 <a href=\"https://docs.aws.amazon.com/zh_cn/elasticloadbalancing/latest/classic/elb-create-https-ssl-load-balancer.html\" target=\"_blank\">https://docs.aws.amazon.com/zh_cn/elasticloadbalancing/latest/classic/elb-create-https-ssl-load-balancer.html</a>"
|
||||
},
|
||||
"aws_clb_certificate_source": {
|
||||
"label": "AWS CLB 证书来源",
|
||||
"placeholder": "请选择 AWS CLB 证书来源"
|
||||
},
|
||||
"aws_iam_region": {
|
||||
"label": "AWS 服务区域",
|
||||
"placeholder": "请输入 AWS IAM 服务区域(例如:us-east-1)",
|
||||
|
||||
Loading…
Reference in New Issue
Block a user