mirror of
https://github.com/certimate-go/certimate.git
synced 2026-09-24 23:10:13 +08:00
feat(provider): new deployment provider: byteplus tos
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
package deployers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/certimate-go/certimate/internal/domain"
|
||||
"github.com/certimate-go/certimate/pkg/core"
|
||||
byteplustos "github.com/certimate-go/certimate/pkg/core/deployer/providers/byteplus-tos"
|
||||
xmaps "github.com/certimate-go/certimate/pkg/utils/maps"
|
||||
)
|
||||
|
||||
func init() {
|
||||
Registries.MustRegister(domain.DeploymentProviderTypeBytePlusTOS, func(options *ProviderFactoryOptions) (core.Deployer, error) {
|
||||
credentials := domain.AccessConfigForBytePlus{}
|
||||
if err := xmaps.Populate(options.ProviderAccessConfig, &credentials); err != nil {
|
||||
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
||||
}
|
||||
|
||||
provider, err := byteplustos.NewDeployer(&byteplustos.DeployerConfig{
|
||||
AccessKeyId: credentials.AccessKeyId,
|
||||
SecretAccessKey: credentials.SecretAccessKey,
|
||||
ProjectName: credentials.ProjectName,
|
||||
Region: xmaps.GetString(options.ProviderExtendedConfig, "region"),
|
||||
Bucket: xmaps.GetString(options.ProviderExtendedConfig, "bucket"),
|
||||
Domain: xmaps.GetString(options.ProviderExtendedConfig, "domain"),
|
||||
})
|
||||
return provider, err
|
||||
})
|
||||
}
|
||||
@@ -340,6 +340,7 @@ const (
|
||||
DeploymentProviderTypeBunnyCDN = DeploymentProviderType(AccessProviderTypeBunny + "-cdn")
|
||||
DeploymentProviderTypeBytePlusCDN = DeploymentProviderType(AccessProviderTypeBytePlus + "-cdn")
|
||||
DeploymentProviderTypeBytePlusCertCenter = DeploymentProviderType(AccessProviderTypeBytePlus + "-certcenter")
|
||||
DeploymentProviderTypeBytePlusTOS = DeploymentProviderType(AccessProviderTypeBytePlus + "-tos")
|
||||
DeploymentProviderTypeCacheFly = DeploymentProviderType(AccessProviderTypeCacheFly)
|
||||
DeploymentProviderTypeCdnfly = DeploymentProviderType(AccessProviderTypeCdnfly)
|
||||
DeploymentProviderTypeCPanel = DeploymentProviderType(AccessProviderTypeCPanel)
|
||||
|
||||
@@ -0,0 +1,125 @@
|
||||
package byteplustos
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
|
||||
"github.com/volcengine/ve-tos-golang-sdk/v2/tos"
|
||||
|
||||
"github.com/certimate-go/certimate/pkg/core/certmgr"
|
||||
certmgrimpl "github.com/certimate-go/certimate/pkg/core/certmgr/providers/byteplus-certcenter"
|
||||
"github.com/certimate-go/certimate/pkg/core/deployer"
|
||||
)
|
||||
|
||||
type DeployerConfig struct {
|
||||
// BytePlus AccessKeyId。
|
||||
AccessKeyId string `json:"accessKeyId"`
|
||||
// BytePlus SecretAccessKey。
|
||||
SecretAccessKey string `json:"secretAccessKey"`
|
||||
// BytePlus 项目名称。
|
||||
ProjectName string `json:"projectName,omitempty"`
|
||||
// BytePlus 地域。
|
||||
Region string `json:"region"`
|
||||
// 存储桶名。
|
||||
Bucket string `json:"bucket"`
|
||||
// 自定义域名(不支持泛域名)。
|
||||
Domain string `json:"domain"`
|
||||
}
|
||||
|
||||
type Deployer struct {
|
||||
config *DeployerConfig
|
||||
logger *slog.Logger
|
||||
sdkClient *tos.ClientV2
|
||||
sdkCertmgr certmgr.Provider
|
||||
}
|
||||
|
||||
var _ deployer.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)
|
||||
}
|
||||
|
||||
pcertmgr, err := certmgrimpl.NewCertmgr(&certmgrimpl.CertmgrConfig{
|
||||
AccessKeyId: config.AccessKeyId,
|
||||
SecretAccessKey: config.SecretAccessKey,
|
||||
ProjectName: config.ProjectName,
|
||||
Region: config.Region,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not create certmgr: %w", err)
|
||||
}
|
||||
|
||||
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) (*deployer.DeployResult, error) {
|
||||
if d.config.Bucket == "" {
|
||||
return nil, fmt.Errorf("config `bucket` is required")
|
||||
}
|
||||
if d.config.Domain == "" {
|
||||
return nil, fmt.Errorf("config `domain` 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))
|
||||
}
|
||||
|
||||
// 设置自定义域名
|
||||
// REF: https://docs.byteplus.com/en/docs/tos/Putbucketcustomdomain
|
||||
// REF: https://docs.byteplus.com/en/docs/tos/Manage-custom-domain-names-go-sdk
|
||||
putBucketCustomDomainReq := &tos.PutBucketCustomDomainInput{
|
||||
Bucket: d.config.Bucket,
|
||||
Rule: tos.CustomDomainRule{
|
||||
Domain: d.config.Domain,
|
||||
CertID: upres.CertId,
|
||||
},
|
||||
}
|
||||
putBucketCustomDomainResp, err := d.sdkClient.PutBucketCustomDomain(ctx, putBucketCustomDomainReq)
|
||||
d.logger.Debug("sdk request 'tos.PutBucketCustomDomain'", slog.Any("request", putBucketCustomDomainReq), slog.Any("response", putBucketCustomDomainResp))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to execute sdk request 'tos.PutBucketCustomDomain': %w", err)
|
||||
}
|
||||
|
||||
return &deployer.DeployResult{}, nil
|
||||
}
|
||||
|
||||
func createSDKClient(accessKeyId, secretAccessKey, region string) (*tos.ClientV2, error) {
|
||||
endpoint := fmt.Sprintf("tos-%s.bytepluses.com", region)
|
||||
|
||||
client, err := tos.NewClientV2(
|
||||
endpoint,
|
||||
tos.WithRegion(region),
|
||||
tos.WithCredentials(tos.NewStaticCredentials(accessKeyId, secretAccessKey)),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return client, nil
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package byteplustos_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/certimate-go/certimate/pkg/core/deployer/internal/tester"
|
||||
impl "github.com/certimate-go/certimate/pkg/core/deployer/providers/byteplus-tos"
|
||||
)
|
||||
|
||||
var (
|
||||
fp = tester.Args("BYTEPLUSTOS_")
|
||||
fTestCertPath string
|
||||
fTestKeyPath string
|
||||
fAccessKeyId string
|
||||
fSecretAccessKey string
|
||||
fRegion string
|
||||
fBucket string
|
||||
fDomain string
|
||||
)
|
||||
|
||||
func init() {
|
||||
fp.DefineString(&fTestCertPath, "TESTCERTPATH")
|
||||
fp.DefineString(&fTestKeyPath, "TESTKEYPATH")
|
||||
fp.DefineString(&fAccessKeyId, "ACCESSKEYID")
|
||||
fp.DefineString(&fSecretAccessKey, "SECRETACCESSKEY")
|
||||
fp.DefineString(&fRegion, "REGION")
|
||||
fp.DefineString(&fBucket, "BUCKET")
|
||||
fp.DefineString(&fDomain, "DOMAIN")
|
||||
}
|
||||
|
||||
/*
|
||||
Shell command to run this test:
|
||||
|
||||
go test -v ./byteplus_tos_test.go -args \
|
||||
--BYTEPLUSTOS_TESTCERTPATH="/path/to/your-test-cert.pem" \
|
||||
--BYTEPLUSTOS_TESTKEYPATH="/path/to/your-test-key.pem" \
|
||||
--BYTEPLUSTOS_ACCESSKEYID="your-access-key-id" \
|
||||
--BYTEPLUSTOS_SECRETACCESSKEY="your-secret-access-key" \
|
||||
--BYTEPLUSTOS_REGION="cn-beijing" \
|
||||
--BYTEPLUSTOS_BUCKET="your-tos-bucket" \
|
||||
--BYTEPLUSTOS_DOMAIN="example.com"
|
||||
*/
|
||||
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,
|
||||
Bucket: fBucket,
|
||||
Domain: fDomain,
|
||||
})
|
||||
if err != nil {
|
||||
t.Errorf("err: %+v", err)
|
||||
return
|
||||
}
|
||||
|
||||
tester.TestDeploy(t, provider, tester.TestDeployArgs{CertPath: fTestCertPath, KeyPath: fTestKeyPath})
|
||||
})
|
||||
}
|
||||
@@ -196,7 +196,7 @@ func (d *Deployer) Deploy(ctx context.Context, certPEM, privkeyPEM string) (*dep
|
||||
return nil, fmt.Errorf("failed to parse private key: %w", err)
|
||||
}
|
||||
|
||||
privkeyAlg, _, _ := xcertkey.DetectPrivateKeyAlgorithm(privkey)
|
||||
privkeyAlg, _, _ := xcertkey.GetPrivateKeyAlgorithm(privkey)
|
||||
privkeyAlgStr := ""
|
||||
switch privkeyAlg {
|
||||
case x509.RSA:
|
||||
|
||||
@@ -623,6 +623,7 @@ export const DEPLOYMENT_PROVIDERS = Object.freeze({
|
||||
BUNNY_CDN: `${ACCESS_PROVIDERS.BUNNY}-cdn`,
|
||||
BYTEPLUS_CDN: `${ACCESS_PROVIDERS.BYTEPLUS}-cdn`,
|
||||
BYTEPLUS_CERTCENTER: `${ACCESS_PROVIDERS.BYTEPLUS}-certcenter`,
|
||||
BYTEPLUS_TOS: `${ACCESS_PROVIDERS.BYTEPLUS}-tos`,
|
||||
CACHEFLY: `${ACCESS_PROVIDERS.CACHEFLY}`,
|
||||
CDNFLY: `${ACCESS_PROVIDERS.CDNFLY}`,
|
||||
CPANEL: `${ACCESS_PROVIDERS.CPANEL}`,
|
||||
@@ -825,6 +826,7 @@ export const deploymentProvidersMap: Map<DeploymentProvider["type"] | string, De
|
||||
[DEPLOYMENT_PROVIDERS.DOGECLOUD_CDN, "provider.dogecloud_cdn", DEPLOYMENT_CATEGORIES.CDN],
|
||||
[DEPLOYMENT_PROVIDERS.KSYUN_CDN, "provider.ksyun_cdn", DEPLOYMENT_CATEGORIES.CDN],
|
||||
[DEPLOYMENT_PROVIDERS.KSYUN_SLB, "provider.ksyun_slb", DEPLOYMENT_CATEGORIES.LOADBALANCE],
|
||||
[DEPLOYMENT_PROVIDERS.BYTEPLUS_TOS, "provider.byteplus_tos", DEPLOYMENT_CATEGORIES.STORAGE],
|
||||
[DEPLOYMENT_PROVIDERS.BYTEPLUS_CDN, "provider.byteplus_cdn", DEPLOYMENT_CATEGORIES.CDN],
|
||||
[DEPLOYMENT_PROVIDERS.BYTEPLUS_CERTCENTER, "provider.byteplus_certcenter_upload", DEPLOYMENT_CATEGORIES.SSL],
|
||||
[DEPLOYMENT_PROVIDERS.UCLOUD_US3, "provider.ucloud_us3", DEPLOYMENT_CATEGORIES.STORAGE],
|
||||
|
||||
@@ -92,6 +92,7 @@
|
||||
"byteplus_cdn": "BytePlus - CDN (Content Delivery Network)",
|
||||
"byteplus_certcenter_upload": "BytePlus - Upload to Certificate Center",
|
||||
"byteplus_dns": "BytePlus - DNS",
|
||||
"byteplus_tos": "BytePlus - TOS (Torch Object Storage)",
|
||||
"cachefly": "CacheFly",
|
||||
"cdnfly": "Cdnfly",
|
||||
"cloudflare": "Cloudflare",
|
||||
|
||||
@@ -1217,6 +1217,19 @@
|
||||
"label": "BytePlus region",
|
||||
"placeholder": "Please enter BytePlus Certificate Center region (e.g. ap-singapore-1)"
|
||||
},
|
||||
"byteplus_tos_region": {
|
||||
"label": "BytePlus region",
|
||||
"placeholder": "Please enter BytePlus TOS region (e.g. ap-singapore-1)",
|
||||
"tooltip": "For more information, see <a href=\"https://www.volcengine.com/docs/6349/107356\" target=\"_blank\">https://www.volcengine.com/docs/6349/107356</a>"
|
||||
},
|
||||
"byteplus_tos_bucket": {
|
||||
"label": "BytePlus TOS bucket",
|
||||
"placeholder": "Please enter BytePlus TOS bucket name"
|
||||
},
|
||||
"byteplus_tos_domain": {
|
||||
"label": "BytePlus TOS custom domain",
|
||||
"placeholder": "Please enter BytePlus TOS bucket custom domain name"
|
||||
},
|
||||
"cdnfly_deploy_target": {
|
||||
"option": {
|
||||
"website": {
|
||||
|
||||
@@ -92,6 +92,7 @@
|
||||
"byteplus_cdn": "BytePlus - 内容分发网络 CDN",
|
||||
"byteplus_certcenter_upload": "BytePlus - 上传到证书中心",
|
||||
"byteplus_dns": "BytePlus - DNS",
|
||||
"byteplus_tos": "BytePlus - 对象存储 TOS",
|
||||
"cachefly": "CacheFly",
|
||||
"cdnfly": "Cdnfly",
|
||||
"cloudflare": "Cloudflare",
|
||||
|
||||
@@ -1213,9 +1213,22 @@
|
||||
"placeholder": "请输入 BytePlus CDN 域名"
|
||||
},
|
||||
"byteplus_certcenter_region": {
|
||||
"label": "BytePlus 证书中心服务地域",
|
||||
"label": "BytePlus 服务地域",
|
||||
"placeholder": "请输入 BytePlus 证书中心服务地域(例如:ap-singapore-1)"
|
||||
},
|
||||
"byteplus_tos_region": {
|
||||
"label": "BytePlus 服务地域",
|
||||
"placeholder": "请输入 BytePlus TOS 服务地域(例如:ap-singapore-1)",
|
||||
"tooltip": "这是什么?请参阅 <a href=\"https://www.volcengine.com/docs/6349/107356\" target=\"_blank\">https://www.volcengine.com/docs/6349/107356</a>"
|
||||
},
|
||||
"byteplus_tos_bucket": {
|
||||
"label": "BytePlus TOS 存储桶名",
|
||||
"placeholder": "请输入 BytePlus TOS 存储桶名"
|
||||
},
|
||||
"byteplus_tos_domain": {
|
||||
"label": "BytePlus TOS 自定义域名",
|
||||
"placeholder": "请输入 BytePlus TOS 自定义域名"
|
||||
},
|
||||
"cdnfly_deploy_target": {
|
||||
"option": {
|
||||
"website": {
|
||||
|
||||
Reference in New Issue
Block a user