mirror of
https://github.com/woodchen-ink/certimate.git
synced 2025-07-19 01:41:55 +08:00
feat: implement more Deployer
This commit is contained in:
parent
643a666853
commit
bde51d8d38
@ -23,7 +23,7 @@ func (a *volcengine) Apply() (*Certificate, error) {
|
||||
access := &domain.VolcengineAccess{}
|
||||
json.Unmarshal([]byte(a.option.Access), access)
|
||||
|
||||
os.Setenv("VOLC_ACCESSKEY", access.AccessKeyID)
|
||||
os.Setenv("VOLC_ACCESSKEY", access.AccessKeyId)
|
||||
os.Setenv("VOLC_SECRETKEY", access.SecretAccessKey)
|
||||
os.Setenv("VOLC_PROPAGATION_TIMEOUT", fmt.Sprintf("%d", a.option.Timeout))
|
||||
dnsProvider, err := volcengineDns.NewDNSProvider()
|
||||
|
@ -27,10 +27,10 @@ func NewVolcengineCDNDeployer(option *DeployerOption) (Deployer, error) {
|
||||
return nil, xerrors.Wrap(err, "failed to get access")
|
||||
}
|
||||
client := cdn.NewInstance()
|
||||
client.Client.SetAccessKey(access.AccessKeyID)
|
||||
client.Client.SetAccessKey(access.AccessKeyId)
|
||||
client.Client.SetSecretKey(access.SecretAccessKey)
|
||||
uploader, err := volcenginecdn.New(&volcenginecdn.VolcEngineCDNUploaderConfig{
|
||||
AccessKeyId: access.AccessKeyID,
|
||||
AccessKeyId: access.AccessKeyId,
|
||||
AccessKeySecret: access.SecretAccessKey,
|
||||
})
|
||||
if err != nil {
|
||||
|
@ -30,11 +30,11 @@ func NewVolcengineLiveDeployer(option *DeployerOption) (Deployer, error) {
|
||||
}
|
||||
client := live.NewInstance()
|
||||
client.SetCredential(base.Credentials{
|
||||
AccessKeyID: access.AccessKeyID,
|
||||
AccessKeyID: access.AccessKeyId,
|
||||
SecretAccessKey: access.SecretAccessKey,
|
||||
})
|
||||
uploader, err := volcenginelive.New(&volcenginelive.VolcEngineLiveUploaderConfig{
|
||||
AccessKeyId: access.AccessKeyID,
|
||||
AccessKeyId: access.AccessKeyId,
|
||||
AccessKeySecret: access.SecretAccessKey,
|
||||
})
|
||||
if err != nil {
|
||||
|
@ -62,7 +62,12 @@ type PdnsAccess struct {
|
||||
}
|
||||
|
||||
type VolcengineAccess struct {
|
||||
AccessKeyID string `json:"accessKeyId"`
|
||||
AccessKey string `json:"accessKey"`
|
||||
SecretKey string `json:"secretKey"`
|
||||
|
||||
// Deprecated: Use [AccessKey] and [SecretKey] instead in the future
|
||||
AccessKeyId string `json:"accessKeyId"`
|
||||
// Deprecated: Use [AccessKey] and [SecretKey] instead in the future
|
||||
SecretAccessKey string `json:"secretAccessKey"`
|
||||
}
|
||||
|
||||
|
@ -5,20 +5,20 @@ import (
|
||||
|
||||
"github.com/usual2970/certimate/internal/domain"
|
||||
"github.com/usual2970/certimate/internal/pkg/core/notifier"
|
||||
npBark "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/bark"
|
||||
npDingTalk "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/dingtalk"
|
||||
npEmail "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/email"
|
||||
npLark "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/lark"
|
||||
npServerChan "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/serverchan"
|
||||
npTelegram "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/telegram"
|
||||
npWebhook "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/webhook"
|
||||
providerBark "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/bark"
|
||||
providerDingTalk "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/dingtalk"
|
||||
providerEmail "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/email"
|
||||
providerLark "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/lark"
|
||||
providerServerChan "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/serverchan"
|
||||
providerTelegram "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/telegram"
|
||||
providerWebhook "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/webhook"
|
||||
"github.com/usual2970/certimate/internal/pkg/utils/maps"
|
||||
)
|
||||
|
||||
func createNotifier(channel string, channelConfig map[string]any) (notifier.Notifier, error) {
|
||||
switch channel {
|
||||
case domain.NotifyChannelEmail:
|
||||
return npEmail.New(&npEmail.EmailNotifierConfig{
|
||||
return providerEmail.New(&providerEmail.EmailNotifierConfig{
|
||||
SmtpHost: maps.GetValueAsString(channelConfig, "smtpHost"),
|
||||
SmtpPort: maps.GetValueAsInt32(channelConfig, "smtpPort"),
|
||||
SmtpTLS: maps.GetValueOrDefaultAsBool(channelConfig, "smtpTLS", true),
|
||||
@ -29,34 +29,34 @@ func createNotifier(channel string, channelConfig map[string]any) (notifier.Noti
|
||||
})
|
||||
|
||||
case domain.NotifyChannelWebhook:
|
||||
return npWebhook.New(&npWebhook.WebhookNotifierConfig{
|
||||
return providerWebhook.New(&providerWebhook.WebhookNotifierConfig{
|
||||
Url: maps.GetValueAsString(channelConfig, "url"),
|
||||
})
|
||||
|
||||
case domain.NotifyChannelDingtalk:
|
||||
return npDingTalk.New(&npDingTalk.DingTalkNotifierConfig{
|
||||
return providerDingTalk.New(&providerDingTalk.DingTalkNotifierConfig{
|
||||
AccessToken: maps.GetValueAsString(channelConfig, "accessToken"),
|
||||
Secret: maps.GetValueAsString(channelConfig, "secret"),
|
||||
})
|
||||
|
||||
case domain.NotifyChannelLark:
|
||||
return npLark.New(&npLark.LarkNotifierConfig{
|
||||
return providerLark.New(&providerLark.LarkNotifierConfig{
|
||||
WebhookUrl: maps.GetValueAsString(channelConfig, "webhookUrl"),
|
||||
})
|
||||
|
||||
case domain.NotifyChannelTelegram:
|
||||
return npTelegram.New(&npTelegram.TelegramNotifierConfig{
|
||||
return providerTelegram.New(&providerTelegram.TelegramNotifierConfig{
|
||||
ApiToken: maps.GetValueAsString(channelConfig, "apiToken"),
|
||||
ChatId: maps.GetValueAsInt64(channelConfig, "chatId"),
|
||||
})
|
||||
|
||||
case domain.NotifyChannelServerChan:
|
||||
return npServerChan.New(&npServerChan.ServerChanNotifierConfig{
|
||||
return providerServerChan.New(&providerServerChan.ServerChanNotifierConfig{
|
||||
Url: maps.GetValueAsString(channelConfig, "url"),
|
||||
})
|
||||
|
||||
case domain.NotifyChannelBark:
|
||||
return npBark.New(&npBark.BarkNotifierConfig{
|
||||
return providerBark.New(&providerBark.BarkNotifierConfig{
|
||||
DeviceKey: maps.GetValueAsString(channelConfig, "deviceKey"),
|
||||
ServerUrl: maps.GetValueAsString(channelConfig, "serverUrl"),
|
||||
})
|
||||
|
@ -13,7 +13,7 @@ import (
|
||||
|
||||
"github.com/usual2970/certimate/internal/pkg/core/deployer"
|
||||
"github.com/usual2970/certimate/internal/pkg/core/uploader"
|
||||
upAliyunCas "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/aliyun-cas"
|
||||
providerCas "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/aliyun-cas"
|
||||
)
|
||||
|
||||
type AliyunALBDeployerConfig struct {
|
||||
@ -71,7 +71,7 @@ func NewWithLogger(config *AliyunALBDeployerConfig, logger deployer.Logger) (*Al
|
||||
aliyunCasRegion = "cn-hangzhou"
|
||||
}
|
||||
}
|
||||
uploader, err := upAliyunCas.New(&upAliyunCas.AliyunCASUploaderConfig{
|
||||
uploader, err := providerCas.New(&providerCas.AliyunCASUploaderConfig{
|
||||
AccessKeyId: config.AccessKeyId,
|
||||
AccessKeySecret: config.AccessKeySecret,
|
||||
Region: aliyunCasRegion,
|
||||
|
@ -8,7 +8,7 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
dpAliyunAlb "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-alb"
|
||||
provider "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-alb"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -59,11 +59,11 @@ func Test(t *testing.T) {
|
||||
fmt.Sprintf("LOADBALANCERID: %v", fLoadbalancerId),
|
||||
}, "\n"))
|
||||
|
||||
deployer, err := dpAliyunAlb.New(&dpAliyunAlb.AliyunALBDeployerConfig{
|
||||
deployer, err := provider.New(&provider.AliyunALBDeployerConfig{
|
||||
AccessKeyId: fAccessKeyId,
|
||||
AccessKeySecret: fAccessKeySecret,
|
||||
Region: fRegion,
|
||||
ResourceType: dpAliyunAlb.DEPLOY_RESOURCE_LOADBALANCER,
|
||||
ResourceType: provider.DEPLOY_RESOURCE_LOADBALANCER,
|
||||
LoadbalancerId: fLoadbalancerId,
|
||||
})
|
||||
if err != nil {
|
||||
@ -93,11 +93,11 @@ func Test(t *testing.T) {
|
||||
fmt.Sprintf("LISTENERID: %v", fListenerId),
|
||||
}, "\n"))
|
||||
|
||||
deployer, err := dpAliyunAlb.New(&dpAliyunAlb.AliyunALBDeployerConfig{
|
||||
deployer, err := provider.New(&provider.AliyunALBDeployerConfig{
|
||||
AccessKeyId: fAccessKeyId,
|
||||
AccessKeySecret: fAccessKeySecret,
|
||||
Region: fRegion,
|
||||
ResourceType: dpAliyunAlb.DEPLOY_RESOURCE_LISTENER,
|
||||
ResourceType: provider.DEPLOY_RESOURCE_LISTENER,
|
||||
ListenerId: fListenerId,
|
||||
})
|
||||
if err != nil {
|
||||
|
@ -8,7 +8,7 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
dpAliyunCdn "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-cdn"
|
||||
provider "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-cdn"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -37,7 +37,7 @@ Shell command to run this test:
|
||||
--CERTIMATE_DEPLOYER_ALIYUNCDN_INPUTKEYPATH="/path/to/your-input-key.pem" \
|
||||
--CERTIMATE_DEPLOYER_ALIYUNCDN_ACCESSKEYID="your-access-key-id" \
|
||||
--CERTIMATE_DEPLOYER_ALIYUNCDN_ACCESSKEYSECRET="your-access-key-secret" \
|
||||
--CERTIMATE_DEPLOYER_ALIYUNCDN_DOMAIN="example.com" \
|
||||
--CERTIMATE_DEPLOYER_ALIYUNCDN_DOMAIN="example.com"
|
||||
*/
|
||||
func Test(t *testing.T) {
|
||||
flag.Parse()
|
||||
@ -52,7 +52,7 @@ func Test(t *testing.T) {
|
||||
fmt.Sprintf("DOMAIN: %v", fDomain),
|
||||
}, "\n"))
|
||||
|
||||
deployer, err := dpAliyunCdn.New(&dpAliyunCdn.AliyunCDNDeployerConfig{
|
||||
deployer, err := provider.New(&provider.AliyunCDNDeployerConfig{
|
||||
AccessKeyId: fAccessKeyId,
|
||||
AccessKeySecret: fAccessKeySecret,
|
||||
Domain: fDomain,
|
||||
|
@ -12,7 +12,7 @@ import (
|
||||
|
||||
"github.com/usual2970/certimate/internal/pkg/core/deployer"
|
||||
"github.com/usual2970/certimate/internal/pkg/core/uploader"
|
||||
upAliyunSlb "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/aliyun-slb"
|
||||
providerSlb "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/aliyun-slb"
|
||||
)
|
||||
|
||||
type AliyunCLBDeployerConfig struct {
|
||||
@ -59,7 +59,7 @@ func NewWithLogger(config *AliyunCLBDeployerConfig, logger deployer.Logger) (*Al
|
||||
return nil, xerrors.Wrap(err, "failed to create sdk client")
|
||||
}
|
||||
|
||||
uploader, err := upAliyunSlb.New(&upAliyunSlb.AliyunSLBUploaderConfig{
|
||||
uploader, err := providerSlb.New(&providerSlb.AliyunSLBUploaderConfig{
|
||||
AccessKeyId: config.AccessKeyId,
|
||||
AccessKeySecret: config.AccessKeySecret,
|
||||
Region: config.Region,
|
||||
|
@ -8,7 +8,7 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
dpAliyunClb "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-clb"
|
||||
provider "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-clb"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -59,11 +59,11 @@ func Test(t *testing.T) {
|
||||
fmt.Sprintf("LOADBALANCERID: %v", fLoadbalancerId),
|
||||
}, "\n"))
|
||||
|
||||
deployer, err := dpAliyunClb.New(&dpAliyunClb.AliyunCLBDeployerConfig{
|
||||
deployer, err := provider.New(&provider.AliyunCLBDeployerConfig{
|
||||
AccessKeyId: fAccessKeyId,
|
||||
AccessKeySecret: fAccessKeySecret,
|
||||
Region: fRegion,
|
||||
ResourceType: dpAliyunClb.DEPLOY_RESOURCE_LOADBALANCER,
|
||||
ResourceType: provider.DEPLOY_RESOURCE_LOADBALANCER,
|
||||
LoadbalancerId: fLoadbalancerId,
|
||||
})
|
||||
if err != nil {
|
||||
@ -94,11 +94,11 @@ func Test(t *testing.T) {
|
||||
fmt.Sprintf("LISTENERPORT: %v", fListenerPort),
|
||||
}, "\n"))
|
||||
|
||||
deployer, err := dpAliyunClb.New(&dpAliyunClb.AliyunCLBDeployerConfig{
|
||||
deployer, err := provider.New(&provider.AliyunCLBDeployerConfig{
|
||||
AccessKeyId: fAccessKeyId,
|
||||
AccessKeySecret: fAccessKeySecret,
|
||||
Region: fRegion,
|
||||
ResourceType: dpAliyunClb.DEPLOY_RESOURCE_LISTENER,
|
||||
ResourceType: provider.DEPLOY_RESOURCE_LISTENER,
|
||||
LoadbalancerId: fLoadbalancerId,
|
||||
ListenerPort: int32(fListenerPort),
|
||||
})
|
||||
|
@ -8,7 +8,7 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
dpAliyunDcdn "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-dcdn"
|
||||
provider "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-dcdn"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -37,7 +37,7 @@ Shell command to run this test:
|
||||
--CERTIMATE_DEPLOYER_ALIYUNDCDN_INPUTKEYPATH="/path/to/your-input-key.pem" \
|
||||
--CERTIMATE_DEPLOYER_ALIYUNDCDN_ACCESSKEYID="your-access-key-id" \
|
||||
--CERTIMATE_DEPLOYER_ALIYUNDCDN_ACCESSKEYSECRET="your-access-key-secret" \
|
||||
--CERTIMATE_DEPLOYER_ALIYUNDCDN_DOMAIN="example.com" \
|
||||
--CERTIMATE_DEPLOYER_ALIYUNDCDN_DOMAIN="example.com"
|
||||
*/
|
||||
func Test(t *testing.T) {
|
||||
flag.Parse()
|
||||
@ -52,7 +52,7 @@ func Test(t *testing.T) {
|
||||
fmt.Sprintf("DOMAIN: %v", fDomain),
|
||||
}, "\n"))
|
||||
|
||||
deployer, err := dpAliyunDcdn.New(&dpAliyunDcdn.AliyunDCDNDeployerConfig{
|
||||
deployer, err := provider.New(&provider.AliyunDCDNDeployerConfig{
|
||||
AccessKeyId: fAccessKeyId,
|
||||
AccessKeySecret: fAccessKeySecret,
|
||||
Domain: fDomain,
|
||||
|
@ -13,7 +13,7 @@ import (
|
||||
|
||||
"github.com/usual2970/certimate/internal/pkg/core/deployer"
|
||||
"github.com/usual2970/certimate/internal/pkg/core/uploader"
|
||||
upAliyunCas "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/aliyun-cas"
|
||||
providerCas "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/aliyun-cas"
|
||||
)
|
||||
|
||||
type AliyunNLBDeployerConfig struct {
|
||||
@ -71,7 +71,7 @@ func NewWithLogger(config *AliyunNLBDeployerConfig, logger deployer.Logger) (*Al
|
||||
aliyunCasRegion = "cn-hangzhou"
|
||||
}
|
||||
}
|
||||
uploader, err := upAliyunCas.New(&upAliyunCas.AliyunCASUploaderConfig{
|
||||
uploader, err := providerCas.New(&providerCas.AliyunCASUploaderConfig{
|
||||
AccessKeyId: config.AccessKeyId,
|
||||
AccessKeySecret: config.AccessKeySecret,
|
||||
Region: aliyunCasRegion,
|
||||
|
@ -8,7 +8,7 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
dpAliyunClb "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-nlb"
|
||||
provider "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-nlb"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -59,11 +59,11 @@ func Test(t *testing.T) {
|
||||
fmt.Sprintf("LOADBALANCERID: %v", fLoadbalancerId),
|
||||
}, "\n"))
|
||||
|
||||
deployer, err := dpAliyunClb.New(&dpAliyunClb.AliyunNLBDeployerConfig{
|
||||
deployer, err := provider.New(&provider.AliyunNLBDeployerConfig{
|
||||
AccessKeyId: fAccessKeyId,
|
||||
AccessKeySecret: fAccessKeySecret,
|
||||
Region: fRegion,
|
||||
ResourceType: dpAliyunClb.DEPLOY_RESOURCE_LOADBALANCER,
|
||||
ResourceType: provider.DEPLOY_RESOURCE_LOADBALANCER,
|
||||
LoadbalancerId: fLoadbalancerId,
|
||||
})
|
||||
if err != nil {
|
||||
@ -94,11 +94,11 @@ func Test(t *testing.T) {
|
||||
fmt.Sprintf("LISTENERID: %v", fListenerId),
|
||||
}, "\n"))
|
||||
|
||||
deployer, err := dpAliyunClb.New(&dpAliyunClb.AliyunNLBDeployerConfig{
|
||||
deployer, err := provider.New(&provider.AliyunNLBDeployerConfig{
|
||||
AccessKeyId: fAccessKeyId,
|
||||
AccessKeySecret: fAccessKeySecret,
|
||||
Region: fRegion,
|
||||
ResourceType: dpAliyunClb.DEPLOY_RESOURCE_LISTENER,
|
||||
ResourceType: provider.DEPLOY_RESOURCE_LISTENER,
|
||||
ListenerId: fListenerId,
|
||||
})
|
||||
if err != nil {
|
||||
|
@ -8,7 +8,7 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
dpAliyunOss "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-oss"
|
||||
provider "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-oss"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -42,8 +42,8 @@ Shell command to run this test:
|
||||
--CERTIMATE_DEPLOYER_ALIYUNOSS_ACCESSKEYID="your-access-key-id" \
|
||||
--CERTIMATE_DEPLOYER_ALIYUNOSS_ACCESSKEYSECRET="your-access-key-secret" \
|
||||
--CERTIMATE_DEPLOYER_ALIYUNOSS_REGION="cn-hangzhou" \
|
||||
--CERTIMATE_DEPLOYER_ALIYUNOSS_BUCKET="your-bucket" \
|
||||
--CERTIMATE_DEPLOYER_ALIYUNOSS_DOMAIN="example.com" \
|
||||
--CERTIMATE_DEPLOYER_ALIYUNOSS_BUCKET="your-oss-bucket" \
|
||||
--CERTIMATE_DEPLOYER_ALIYUNOSS_DOMAIN="example.com"
|
||||
*/
|
||||
func Test(t *testing.T) {
|
||||
flag.Parse()
|
||||
@ -60,7 +60,7 @@ func Test(t *testing.T) {
|
||||
fmt.Sprintf("DOMAIN: %v", fDomain),
|
||||
}, "\n"))
|
||||
|
||||
deployer, err := dpAliyunOss.New(&dpAliyunOss.AliyunOSSDeployerConfig{
|
||||
deployer, err := provider.New(&provider.AliyunOSSDeployerConfig{
|
||||
AccessKeyId: fAccessKeyId,
|
||||
AccessKeySecret: fAccessKeySecret,
|
||||
Region: fRegion,
|
||||
|
@ -0,0 +1,86 @@
|
||||
package baiducloudcdn
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
bceCdn "github.com/baidubce/bce-sdk-go/services/cdn"
|
||||
bceCdnApi "github.com/baidubce/bce-sdk-go/services/cdn/api"
|
||||
xerrors "github.com/pkg/errors"
|
||||
|
||||
"github.com/usual2970/certimate/internal/pkg/core/deployer"
|
||||
)
|
||||
|
||||
type BaiduCloudCDNDeployerConfig struct {
|
||||
// 百度智能云 AccessKeyId。
|
||||
AccessKeyId string `json:"accessKeyId"`
|
||||
// 百度智能云 SecretAccessKey。
|
||||
SecretAccessKey string `json:"secretAccessKey"`
|
||||
// 加速域名(不支持泛域名)。
|
||||
Domain string `json:"domain"`
|
||||
}
|
||||
|
||||
type BaiduCloudCDNDeployer struct {
|
||||
config *BaiduCloudCDNDeployerConfig
|
||||
logger deployer.Logger
|
||||
sdkClient *bceCdn.Client
|
||||
}
|
||||
|
||||
var _ deployer.Deployer = (*BaiduCloudCDNDeployer)(nil)
|
||||
|
||||
func New(config *BaiduCloudCDNDeployerConfig) (*BaiduCloudCDNDeployer, error) {
|
||||
return NewWithLogger(config, deployer.NewNilLogger())
|
||||
}
|
||||
|
||||
func NewWithLogger(config *BaiduCloudCDNDeployerConfig, logger deployer.Logger) (*BaiduCloudCDNDeployer, error) {
|
||||
if config == nil {
|
||||
return nil, errors.New("config is nil")
|
||||
}
|
||||
|
||||
if logger == nil {
|
||||
return nil, errors.New("logger is nil")
|
||||
}
|
||||
|
||||
client, err := createSdkClient(config.AccessKeyId, config.SecretAccessKey)
|
||||
if err != nil {
|
||||
return nil, xerrors.Wrap(err, "failed to create sdk client")
|
||||
}
|
||||
|
||||
return &BaiduCloudCDNDeployer{
|
||||
logger: logger,
|
||||
config: config,
|
||||
sdkClient: client,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (d *BaiduCloudCDNDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
|
||||
// 修改域名证书
|
||||
// REF: https://cloud.baidu.com/doc/CDN/s/qjzuz2hp8
|
||||
putCertResp, err := d.sdkClient.PutCert(
|
||||
d.config.Domain,
|
||||
&bceCdnApi.UserCertificate{
|
||||
CertName: fmt.Sprintf("certimate-%d", time.Now().UnixMilli()),
|
||||
ServerData: certPem,
|
||||
PrivateData: privkeyPem,
|
||||
},
|
||||
"ON",
|
||||
)
|
||||
if err != nil {
|
||||
return nil, xerrors.Wrap(err, "failed to execute sdk request 'cdn.PutCert'")
|
||||
}
|
||||
|
||||
d.logger.Appendt("已修改域名证书", putCertResp)
|
||||
|
||||
return &deployer.DeployResult{}, nil
|
||||
}
|
||||
|
||||
func createSdkClient(accessKeyId, secretAccessKey string) (*bceCdn.Client, error) {
|
||||
client, err := bceCdn.NewClient(accessKeyId, secretAccessKey, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return client, nil
|
||||
}
|
@ -0,0 +1,75 @@
|
||||
package baiducloudcdn_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
provider "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/baiducloud-cdn"
|
||||
)
|
||||
|
||||
var (
|
||||
fInputCertPath string
|
||||
fInputKeyPath string
|
||||
fAccessKeyId string
|
||||
fSecretAccessKey string
|
||||
fDomain string
|
||||
)
|
||||
|
||||
func init() {
|
||||
argsPrefix := "CERTIMATE_DEPLOYER_BAIDUCLOUDCDN_"
|
||||
|
||||
flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "")
|
||||
flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "")
|
||||
flag.StringVar(&fAccessKeyId, argsPrefix+"ACCESSKEYID", "", "")
|
||||
flag.StringVar(&fSecretAccessKey, argsPrefix+"SECRETACCESSKEY", "", "")
|
||||
flag.StringVar(&fDomain, argsPrefix+"DOMAIN", "", "")
|
||||
}
|
||||
|
||||
/*
|
||||
Shell command to run this test:
|
||||
|
||||
go test -v baiducloud_cdn_test.go -args \
|
||||
--CERTIMATE_DEPLOYER_BAIDUCLOUDCDN_INPUTCERTPATH="/path/to/your-input-cert.pem" \
|
||||
--CERTIMATE_DEPLOYER_BAIDUCLOUDCDN_INPUTKEYPATH="/path/to/your-input-key.pem" \
|
||||
--CERTIMATE_DEPLOYER_BAIDUCLOUDCDN_ACCESSKEYID="your-access-key-id" \
|
||||
--CERTIMATE_DEPLOYER_BAIDUCLOUDCDN_SECRETACCESSKEY="your-secret-access-key" \
|
||||
--CERTIMATE_DEPLOYER_BAIDUCLOUDCDN_DOMAIN="example.com"
|
||||
*/
|
||||
func Test(t *testing.T) {
|
||||
flag.Parse()
|
||||
|
||||
t.Run("Deploy", func(t *testing.T) {
|
||||
t.Log(strings.Join([]string{
|
||||
"args:",
|
||||
fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath),
|
||||
fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath),
|
||||
fmt.Sprintf("ACCESSKEYID: %v", fAccessKeyId),
|
||||
fmt.Sprintf("SECRETACCESSKEY: %v", fSecretAccessKey),
|
||||
fmt.Sprintf("DOMAIN: %v", fDomain),
|
||||
}, "\n"))
|
||||
|
||||
deployer, err := provider.New(&provider.BaiduCloudCDNDeployerConfig{
|
||||
AccessKeyId: fAccessKeyId,
|
||||
SecretAccessKey: fSecretAccessKey,
|
||||
Domain: fDomain,
|
||||
})
|
||||
if err != nil {
|
||||
t.Errorf("err: %+v", err)
|
||||
return
|
||||
}
|
||||
|
||||
fInputCertData, _ := os.ReadFile(fInputCertPath)
|
||||
fInputKeyData, _ := os.ReadFile(fInputKeyPath)
|
||||
res, err := deployer.Deploy(context.Background(), string(fInputCertData), string(fInputKeyData))
|
||||
if err != nil {
|
||||
t.Errorf("err: %+v", err)
|
||||
return
|
||||
}
|
||||
|
||||
t.Logf("ok: %v", res)
|
||||
})
|
||||
}
|
@ -0,0 +1,136 @@
|
||||
package bytepluscdn
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
bpCdn "github.com/byteplus-sdk/byteplus-sdk-golang/service/cdn"
|
||||
xerrors "github.com/pkg/errors"
|
||||
|
||||
"github.com/usual2970/certimate/internal/pkg/core/deployer"
|
||||
"github.com/usual2970/certimate/internal/pkg/core/uploader"
|
||||
providerCdn "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/byteplus-cdn"
|
||||
)
|
||||
|
||||
type BytePlusCDNDeployerConfig struct {
|
||||
// BytePlus AccessKey。
|
||||
AccessKey string `json:"accessKey"`
|
||||
// BytePlus SecretKey。
|
||||
SecretKey string `json:"secretKey"`
|
||||
// 加速域名(支持泛域名)。
|
||||
Domain string `json:"domain"`
|
||||
}
|
||||
|
||||
type BytePlusCDNDeployer struct {
|
||||
config *BytePlusCDNDeployerConfig
|
||||
logger deployer.Logger
|
||||
sdkClient *bpCdn.CDN
|
||||
sslUploader uploader.Uploader
|
||||
}
|
||||
|
||||
var _ deployer.Deployer = (*BytePlusCDNDeployer)(nil)
|
||||
|
||||
func New(config *BytePlusCDNDeployerConfig) (*BytePlusCDNDeployer, error) {
|
||||
return NewWithLogger(config, deployer.NewNilLogger())
|
||||
}
|
||||
|
||||
func NewWithLogger(config *BytePlusCDNDeployerConfig, logger deployer.Logger) (*BytePlusCDNDeployer, error) {
|
||||
if config == nil {
|
||||
return nil, errors.New("config is nil")
|
||||
}
|
||||
|
||||
if logger == nil {
|
||||
return nil, errors.New("logger is nil")
|
||||
}
|
||||
|
||||
client := bpCdn.NewInstance()
|
||||
client.Client.SetAccessKey(config.AccessKey)
|
||||
client.Client.SetSecretKey(config.SecretKey)
|
||||
|
||||
uploader, err := providerCdn.New(&providerCdn.ByteplusCDNUploaderConfig{
|
||||
AccessKey: config.AccessKey,
|
||||
SecretKey: config.SecretKey,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, xerrors.Wrap(err, "failed to create ssl uploader")
|
||||
}
|
||||
|
||||
return &BytePlusCDNDeployer{
|
||||
logger: logger,
|
||||
config: config,
|
||||
sdkClient: client,
|
||||
sslUploader: uploader,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (d *BytePlusCDNDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
|
||||
// 上传证书到 CDN
|
||||
upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem)
|
||||
if err != nil {
|
||||
return nil, xerrors.Wrap(err, "failed to upload certificate file")
|
||||
}
|
||||
|
||||
d.logger.Appendt("certificate file uploaded", upres)
|
||||
|
||||
domains := make([]string, 0)
|
||||
if strings.HasPrefix(d.config.Domain, "*.") {
|
||||
// 获取指定证书可关联的域名
|
||||
// REF: https://docs.byteplus.com/en/docs/byteplus-cdn/reference-describecertconfig-9ea17
|
||||
describeCertConfigReq := &bpCdn.DescribeCertConfigRequest{
|
||||
CertId: upres.CertId,
|
||||
}
|
||||
describeCertConfigResp, err := d.sdkClient.DescribeCertConfig(describeCertConfigReq)
|
||||
if err != nil {
|
||||
return nil, xerrors.Wrap(err, "failed to execute sdk request 'cdn.DescribeCertConfig'")
|
||||
}
|
||||
|
||||
if describeCertConfigResp.Result.CertNotConfig != nil {
|
||||
for i := range describeCertConfigResp.Result.CertNotConfig {
|
||||
domains = append(domains, describeCertConfigResp.Result.CertNotConfig[i].Domain)
|
||||
}
|
||||
}
|
||||
|
||||
if describeCertConfigResp.Result.OtherCertConfig != nil {
|
||||
for i := range describeCertConfigResp.Result.OtherCertConfig {
|
||||
domains = append(domains, describeCertConfigResp.Result.OtherCertConfig[i].Domain)
|
||||
}
|
||||
}
|
||||
|
||||
if len(domains) == 0 {
|
||||
if len(describeCertConfigResp.Result.SpecifiedCertConfig) > 0 {
|
||||
// 所有可关联的域名都配置了该证书,跳过部署
|
||||
} else {
|
||||
return nil, xerrors.New("domain not found")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
domains = append(domains, d.config.Domain)
|
||||
}
|
||||
|
||||
if len(domains) > 0 {
|
||||
var errs []error
|
||||
|
||||
for _, domain := range domains {
|
||||
// 关联证书与加速域名
|
||||
// REF: https://docs.byteplus.com/en/docs/byteplus-cdn/reference-batchdeploycert
|
||||
batchDeployCertReq := &bpCdn.BatchDeployCertRequest{
|
||||
CertId: upres.CertId,
|
||||
Domain: domain,
|
||||
}
|
||||
batchDeployCertResp, err := d.sdkClient.BatchDeployCert(batchDeployCertReq)
|
||||
if err != nil {
|
||||
errs = append(errs, err)
|
||||
} else {
|
||||
d.logger.Appendt(fmt.Sprintf("已关联证书到域名 %s", domain), batchDeployCertResp)
|
||||
}
|
||||
}
|
||||
|
||||
if len(errs) > 0 {
|
||||
return nil, errors.Join(errs...)
|
||||
}
|
||||
}
|
||||
|
||||
return &deployer.DeployResult{}, nil
|
||||
}
|
@ -0,0 +1,75 @@
|
||||
package bytepluscdn_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
provider "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/byteplus-cdn"
|
||||
)
|
||||
|
||||
var (
|
||||
fInputCertPath string
|
||||
fInputKeyPath string
|
||||
fAccessKey string
|
||||
fSecretKey string
|
||||
fDomain string
|
||||
)
|
||||
|
||||
func init() {
|
||||
argsPrefix := "CERTIMATE_DEPLOYER_BYTEPLUSCDN_"
|
||||
|
||||
flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "")
|
||||
flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "")
|
||||
flag.StringVar(&fAccessKey, argsPrefix+"ACCESSKEY", "", "")
|
||||
flag.StringVar(&fSecretKey, argsPrefix+"SECRETKEY", "", "")
|
||||
flag.StringVar(&fDomain, argsPrefix+"DOMAIN", "", "")
|
||||
}
|
||||
|
||||
/*
|
||||
Shell command to run this test:
|
||||
|
||||
go test -v byteplus_cdn_test.go -args \
|
||||
--CERTIMATE_DEPLOYER_BYTEPLUSCDN_INPUTCERTPATH="/path/to/your-input-cert.pem" \
|
||||
--CERTIMATE_DEPLOYER_BYTEPLUSCDN_INPUTKEYPATH="/path/to/your-input-key.pem" \
|
||||
--CERTIMATE_DEPLOYER_BYTEPLUSCDN_ACCESSKEY="your-access-key" \
|
||||
--CERTIMATE_DEPLOYER_BYTEPLUSCDN_SECRETKEY="your-secret-key" \
|
||||
--CERTIMATE_DEPLOYER_BYTEPLUSCDN_DOMAIN="example.com"
|
||||
*/
|
||||
func Test(t *testing.T) {
|
||||
flag.Parse()
|
||||
|
||||
t.Run("Deploy", func(t *testing.T) {
|
||||
t.Log(strings.Join([]string{
|
||||
"args:",
|
||||
fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath),
|
||||
fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath),
|
||||
fmt.Sprintf("ACCESSKEY: %v", fAccessKey),
|
||||
fmt.Sprintf("SECRETKEY: %v", fSecretKey),
|
||||
fmt.Sprintf("DOMAIN: %v", fDomain),
|
||||
}, "\n"))
|
||||
|
||||
deployer, err := provider.New(&provider.BytePlusCDNDeployerConfig{
|
||||
AccessKey: fAccessKey,
|
||||
SecretKey: fSecretKey,
|
||||
Domain: fDomain,
|
||||
})
|
||||
if err != nil {
|
||||
t.Errorf("err: %+v", err)
|
||||
return
|
||||
}
|
||||
|
||||
fInputCertData, _ := os.ReadFile(fInputCertPath)
|
||||
fInputKeyData, _ := os.ReadFile(fInputKeyPath)
|
||||
res, err := deployer.Deploy(context.Background(), string(fInputCertData), string(fInputKeyData))
|
||||
if err != nil {
|
||||
t.Errorf("err: %+v", err)
|
||||
return
|
||||
}
|
||||
|
||||
t.Logf("ok: %v", res)
|
||||
})
|
||||
}
|
@ -0,0 +1,85 @@
|
||||
package dogecloudcdn
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"strconv"
|
||||
|
||||
xerrors "github.com/pkg/errors"
|
||||
|
||||
"github.com/usual2970/certimate/internal/pkg/core/deployer"
|
||||
"github.com/usual2970/certimate/internal/pkg/core/uploader"
|
||||
providerDoge "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/dogecloud"
|
||||
dogesdk "github.com/usual2970/certimate/internal/pkg/vendors/dogecloud-sdk"
|
||||
)
|
||||
|
||||
type DogeCloudCDNDeployerConfig struct {
|
||||
// 多吉云 AccessKey。
|
||||
AccessKey string `json:"accessKey"`
|
||||
// 多吉云 SecretKey。
|
||||
SecretKey string `json:"secretKey"`
|
||||
// 加速域名(不支持泛域名)。
|
||||
Domain string `json:"domain"`
|
||||
}
|
||||
|
||||
type DogeCloudCDNDeployer struct {
|
||||
config *DogeCloudCDNDeployerConfig
|
||||
logger deployer.Logger
|
||||
sdkClient *dogesdk.Client
|
||||
sslUploader uploader.Uploader
|
||||
}
|
||||
|
||||
var _ deployer.Deployer = (*DogeCloudCDNDeployer)(nil)
|
||||
|
||||
func New(config *DogeCloudCDNDeployerConfig) (*DogeCloudCDNDeployer, error) {
|
||||
return NewWithLogger(config, deployer.NewNilLogger())
|
||||
}
|
||||
|
||||
func NewWithLogger(config *DogeCloudCDNDeployerConfig, logger deployer.Logger) (*DogeCloudCDNDeployer, error) {
|
||||
if config == nil {
|
||||
return nil, errors.New("config is nil")
|
||||
}
|
||||
|
||||
if logger == nil {
|
||||
return nil, errors.New("logger is nil")
|
||||
}
|
||||
|
||||
client := dogesdk.NewClient(config.AccessKey, config.SecretKey)
|
||||
|
||||
uploader, err := providerDoge.New(&providerDoge.DogeCloudUploaderConfig{
|
||||
AccessKey: config.AccessKey,
|
||||
SecretKey: config.SecretKey,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, xerrors.Wrap(err, "failed to create ssl uploader")
|
||||
}
|
||||
|
||||
return &DogeCloudCDNDeployer{
|
||||
logger: logger,
|
||||
config: config,
|
||||
sdkClient: client,
|
||||
sslUploader: uploader,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (d *DogeCloudCDNDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
|
||||
// 上传证书到 CDN
|
||||
upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem)
|
||||
if err != nil {
|
||||
return nil, xerrors.Wrap(err, "failed to upload certificate file")
|
||||
}
|
||||
|
||||
d.logger.Appendt("certificate file uploaded", upres)
|
||||
|
||||
// 绑定证书
|
||||
// REF: https://docs.dogecloud.com/cdn/api-cert-bind
|
||||
bindCdnCertId, _ := strconv.ParseInt(upres.CertId, 10, 64)
|
||||
bindCdnCertResp, err := d.sdkClient.BindCdnCertWithDomain(bindCdnCertId, d.config.Domain)
|
||||
if err != nil {
|
||||
return nil, xerrors.Wrap(err, "failed to execute sdk request 'cdn.BindCdnCert'")
|
||||
}
|
||||
|
||||
d.logger.Appendt("已绑定证书", bindCdnCertResp)
|
||||
|
||||
return &deployer.DeployResult{}, nil
|
||||
}
|
@ -0,0 +1,75 @@
|
||||
package dogecloudcdn_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
provider "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/dogecloud-cdn"
|
||||
)
|
||||
|
||||
var (
|
||||
fInputCertPath string
|
||||
fInputKeyPath string
|
||||
fAccessKey string
|
||||
fSecretKey string
|
||||
fDomain string
|
||||
)
|
||||
|
||||
func init() {
|
||||
argsPrefix := "CERTIMATE_DEPLOYER_DOGECLOUDCDN_"
|
||||
|
||||
flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "")
|
||||
flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "")
|
||||
flag.StringVar(&fAccessKey, argsPrefix+"ACCESSKEY", "", "")
|
||||
flag.StringVar(&fSecretKey, argsPrefix+"SECRETKEY", "", "")
|
||||
flag.StringVar(&fDomain, argsPrefix+"DOMAIN", "", "")
|
||||
}
|
||||
|
||||
/*
|
||||
Shell command to run this test:
|
||||
|
||||
go test -v dogecloud_cdn_test.go -args \
|
||||
--CERTIMATE_DEPLOYER_DOGECLOUDCDN_INPUTCERTPATH="/path/to/your-input-cert.pem" \
|
||||
--CERTIMATE_DEPLOYER_DOGECLOUDCDN_INPUTKEYPATH="/path/to/your-input-key.pem" \
|
||||
--CERTIMATE_DEPLOYER_DOGECLOUDCDN_ACCESSKEY="your-access-key" \
|
||||
--CERTIMATE_DEPLOYER_DOGECLOUDCDN_SECRETKEY="your-secret-key" \
|
||||
--CERTIMATE_DEPLOYER_DOGECLOUDCDN_DOMAIN="example.com"
|
||||
*/
|
||||
func Test(t *testing.T) {
|
||||
flag.Parse()
|
||||
|
||||
t.Run("Deploy", func(t *testing.T) {
|
||||
t.Log(strings.Join([]string{
|
||||
"args:",
|
||||
fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath),
|
||||
fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath),
|
||||
fmt.Sprintf("ACCESSKEY: %v", fAccessKey),
|
||||
fmt.Sprintf("SECRETKEY: %v", fSecretKey),
|
||||
fmt.Sprintf("DOMAIN: %v", fDomain),
|
||||
}, "\n"))
|
||||
|
||||
deployer, err := provider.New(&provider.DogeCloudCDNDeployerConfig{
|
||||
AccessKey: fAccessKey,
|
||||
SecretKey: fSecretKey,
|
||||
Domain: fDomain,
|
||||
})
|
||||
if err != nil {
|
||||
t.Errorf("err: %+v", err)
|
||||
return
|
||||
}
|
||||
|
||||
fInputCertData, _ := os.ReadFile(fInputCertPath)
|
||||
fInputKeyData, _ := os.ReadFile(fInputKeyPath)
|
||||
res, err := deployer.Deploy(context.Background(), string(fInputCertData), string(fInputKeyData))
|
||||
if err != nil {
|
||||
t.Errorf("err: %+v", err)
|
||||
return
|
||||
}
|
||||
|
||||
t.Logf("ok: %v", res)
|
||||
})
|
||||
}
|
@ -0,0 +1,152 @@
|
||||
package huaweicloudcdn
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/global"
|
||||
hcCdn "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/cdn/v2"
|
||||
hcCdnModel "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/cdn/v2/model"
|
||||
hcCdnRegion "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/cdn/v2/region"
|
||||
xerrors "github.com/pkg/errors"
|
||||
|
||||
"github.com/usual2970/certimate/internal/pkg/core/deployer"
|
||||
"github.com/usual2970/certimate/internal/pkg/core/uploader"
|
||||
providerScm "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/huaweicloud-scm"
|
||||
"github.com/usual2970/certimate/internal/pkg/utils/cast"
|
||||
huaweicloudsdk "github.com/usual2970/certimate/internal/pkg/vendors/huaweicloud-cdn-sdk"
|
||||
)
|
||||
|
||||
type HuaweiCloudCDNDeployerConfig struct {
|
||||
// 华为云 AccessKeyId。
|
||||
AccessKeyId string `json:"accessKeyId"`
|
||||
// 华为云 SecretAccessKey。
|
||||
SecretAccessKey string `json:"secretAccessKey"`
|
||||
// 华为云地域。
|
||||
Region string `json:"region"`
|
||||
// 加速域名(不支持泛域名)。
|
||||
Domain string `json:"domain"`
|
||||
}
|
||||
|
||||
type HuaweiCloudCDNDeployer struct {
|
||||
config *HuaweiCloudCDNDeployerConfig
|
||||
logger deployer.Logger
|
||||
sdkClient *huaweicloudsdk.Client
|
||||
sslUploader uploader.Uploader
|
||||
}
|
||||
|
||||
var _ deployer.Deployer = (*HuaweiCloudCDNDeployer)(nil)
|
||||
|
||||
func New(config *HuaweiCloudCDNDeployerConfig) (*HuaweiCloudCDNDeployer, error) {
|
||||
return NewWithLogger(config, deployer.NewNilLogger())
|
||||
}
|
||||
|
||||
func NewWithLogger(config *HuaweiCloudCDNDeployerConfig, logger deployer.Logger) (*HuaweiCloudCDNDeployer, error) {
|
||||
if config == nil {
|
||||
return nil, errors.New("config is nil")
|
||||
}
|
||||
|
||||
if logger == nil {
|
||||
return nil, errors.New("logger is nil")
|
||||
}
|
||||
|
||||
client, err := createSdkClient(
|
||||
config.AccessKeyId,
|
||||
config.SecretAccessKey,
|
||||
config.Region,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, xerrors.Wrap(err, "failed to create sdk client")
|
||||
}
|
||||
|
||||
uploader, err := providerScm.New(&providerScm.HuaweiCloudSCMUploaderConfig{
|
||||
AccessKeyId: config.AccessKeyId,
|
||||
SecretAccessKey: config.SecretAccessKey,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, xerrors.Wrap(err, "failed to create ssl uploader")
|
||||
}
|
||||
|
||||
return &HuaweiCloudCDNDeployer{
|
||||
logger: logger,
|
||||
config: config,
|
||||
sdkClient: client,
|
||||
sslUploader: uploader,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (d *HuaweiCloudCDNDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
|
||||
// 上传证书到 SCM
|
||||
upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem)
|
||||
if err != nil {
|
||||
return nil, xerrors.Wrap(err, "failed to upload certificate file")
|
||||
}
|
||||
|
||||
d.logger.Appendt("certificate file uploaded", upres)
|
||||
|
||||
// 查询加速域名配置
|
||||
// REF: https://support.huaweicloud.com/api-cdn/ShowDomainFullConfig.html
|
||||
showDomainFullConfigReq := &hcCdnModel.ShowDomainFullConfigRequest{
|
||||
DomainName: d.config.Domain,
|
||||
}
|
||||
showDomainFullConfigResp, err := d.sdkClient.ShowDomainFullConfig(showDomainFullConfigReq)
|
||||
if err != nil {
|
||||
return nil, xerrors.Wrap(err, "failed to execute sdk request 'cdn.ShowDomainFullConfig'")
|
||||
}
|
||||
|
||||
d.logger.Appendt("已查询到加速域名配置", showDomainFullConfigResp)
|
||||
|
||||
// 更新加速域名配置
|
||||
// REF: https://support.huaweicloud.com/api-cdn/UpdateDomainMultiCertificates.html
|
||||
// REF: https://support.huaweicloud.com/usermanual-cdn/cdn_01_0306.html
|
||||
updateDomainMultiCertificatesReqBodyContent := &huaweicloudsdk.UpdateDomainMultiCertificatesExRequestBodyContent{}
|
||||
updateDomainMultiCertificatesReqBodyContent.DomainName = d.config.Domain
|
||||
updateDomainMultiCertificatesReqBodyContent.HttpsSwitch = 1
|
||||
updateDomainMultiCertificatesReqBodyContent.CertificateType = cast.Int32Ptr(2)
|
||||
updateDomainMultiCertificatesReqBodyContent.SCMCertificateId = cast.StringPtr(upres.CertId)
|
||||
updateDomainMultiCertificatesReqBodyContent.CertName = cast.StringPtr(upres.CertName)
|
||||
updateDomainMultiCertificatesReqBodyContent = updateDomainMultiCertificatesReqBodyContent.MergeConfig(showDomainFullConfigResp.Configs)
|
||||
updateDomainMultiCertificatesReq := &huaweicloudsdk.UpdateDomainMultiCertificatesExRequest{
|
||||
Body: &huaweicloudsdk.UpdateDomainMultiCertificatesExRequestBody{
|
||||
Https: updateDomainMultiCertificatesReqBodyContent,
|
||||
},
|
||||
}
|
||||
updateDomainMultiCertificatesResp, err := d.sdkClient.UploadDomainMultiCertificatesEx(updateDomainMultiCertificatesReq)
|
||||
if err != nil {
|
||||
return nil, xerrors.Wrap(err, "failed to execute sdk request 'cdn.UploadDomainMultiCertificatesEx'")
|
||||
}
|
||||
|
||||
d.logger.Appendt("已更新加速域名配置", updateDomainMultiCertificatesResp)
|
||||
|
||||
return &deployer.DeployResult{}, nil
|
||||
}
|
||||
|
||||
func createSdkClient(accessKeyId, secretAccessKey, region string) (*huaweicloudsdk.Client, error) {
|
||||
if region == "" {
|
||||
region = "cn-north-1" // CDN 服务默认区域:华北一北京
|
||||
}
|
||||
|
||||
auth, err := global.NewCredentialsBuilder().
|
||||
WithAk(accessKeyId).
|
||||
WithSk(secretAccessKey).
|
||||
SafeBuild()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
hcRegion, err := hcCdnRegion.SafeValueOf(region)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
hcClient, err := hcCdn.CdnClientBuilder().
|
||||
WithRegion(hcRegion).
|
||||
WithCredential(auth).
|
||||
SafeBuild()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
client := huaweicloudsdk.NewClient(hcClient)
|
||||
return client, nil
|
||||
}
|
@ -0,0 +1,80 @@
|
||||
package huaweicloudcdn_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
provider "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/huaweicloud-cdn"
|
||||
)
|
||||
|
||||
var (
|
||||
fInputCertPath string
|
||||
fInputKeyPath string
|
||||
fAccessKeyId string
|
||||
fSecretAccessKey string
|
||||
fRegion string
|
||||
fDomain string
|
||||
)
|
||||
|
||||
func init() {
|
||||
argsPrefix := "CERTIMATE_DEPLOYER_HUAWEICLOUDCDN_"
|
||||
|
||||
flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "")
|
||||
flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "")
|
||||
flag.StringVar(&fAccessKeyId, argsPrefix+"ACCESSKEYID", "", "")
|
||||
flag.StringVar(&fSecretAccessKey, argsPrefix+"SECRETACCESSKEY", "", "")
|
||||
flag.StringVar(&fRegion, argsPrefix+"REGION", "", "")
|
||||
flag.StringVar(&fDomain, argsPrefix+"DOMAIN", "", "")
|
||||
}
|
||||
|
||||
/*
|
||||
Shell command to run this test:
|
||||
|
||||
go test -v huaweicloud_cdn_test.go -args \
|
||||
--CERTIMATE_DEPLOYER_HUAWEICLOUDCDN_INPUTCERTPATH="/path/to/your-input-cert.pem" \
|
||||
--CERTIMATE_DEPLOYER_HUAWEICLOUDCDN_INPUTKEYPATH="/path/to/your-input-key.pem" \
|
||||
--CERTIMATE_DEPLOYER_HUAWEICLOUDCDN_ACCESSKEYID="your-access-key-id" \
|
||||
--CERTIMATE_DEPLOYER_HUAWEICLOUDCDN_SECRETACCESSKEY="your-secret-access-key" \
|
||||
--CERTIMATE_DEPLOYER_HUAWEICLOUDCDN_REGION="cn-north-1" \
|
||||
--CERTIMATE_DEPLOYER_HUAWEICLOUDCDN_DOMAIN="example.com"
|
||||
*/
|
||||
func Test(t *testing.T) {
|
||||
flag.Parse()
|
||||
|
||||
t.Run("Deploy", func(t *testing.T) {
|
||||
t.Log(strings.Join([]string{
|
||||
"args:",
|
||||
fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath),
|
||||
fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath),
|
||||
fmt.Sprintf("ACCESSKEYID: %v", fAccessKeyId),
|
||||
fmt.Sprintf("SECRETACCESSKEY: %v", fSecretAccessKey),
|
||||
fmt.Sprintf("REGION: %v", fRegion),
|
||||
fmt.Sprintf("DOMAIN: %v", fDomain),
|
||||
}, "\n"))
|
||||
|
||||
deployer, err := provider.New(&provider.HuaweiCloudCDNDeployerConfig{
|
||||
AccessKeyId: fAccessKeyId,
|
||||
SecretAccessKey: fSecretAccessKey,
|
||||
Region: fRegion,
|
||||
Domain: fDomain,
|
||||
})
|
||||
if err != nil {
|
||||
t.Errorf("err: %+v", err)
|
||||
return
|
||||
}
|
||||
|
||||
fInputCertData, _ := os.ReadFile(fInputCertPath)
|
||||
fInputKeyData, _ := os.ReadFile(fInputKeyPath)
|
||||
res, err := deployer.Deploy(context.Background(), string(fInputCertData), string(fInputKeyData))
|
||||
if err != nil {
|
||||
t.Errorf("err: %+v", err)
|
||||
return
|
||||
}
|
||||
|
||||
t.Logf("ok: %v", res)
|
||||
})
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package huaweicloudelb
|
||||
|
||||
type DeployResourceType string
|
||||
|
||||
const (
|
||||
// 资源类型:替换指定证书。
|
||||
DEPLOY_RESOURCE_CERTIFICATE = DeployResourceType("certificate")
|
||||
// 资源类型:部署到指定负载均衡器。
|
||||
DEPLOY_RESOURCE_LOADBALANCER = DeployResourceType("loadbalancer")
|
||||
// 资源类型:部署到指定监听器。
|
||||
DEPLOY_RESOURCE_LISTENER = DeployResourceType("listener")
|
||||
)
|
@ -0,0 +1,399 @@
|
||||
package huaweicloudelb
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/basic"
|
||||
"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/global"
|
||||
hcElb "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/elb/v3"
|
||||
hcElbModel "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/elb/v3/model"
|
||||
hcElbRegion "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/elb/v3/region"
|
||||
hcIam "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/iam/v3"
|
||||
hcIamModel "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/iam/v3/model"
|
||||
hcIamRegion "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/iam/v3/region"
|
||||
xerrors "github.com/pkg/errors"
|
||||
"golang.org/x/exp/slices"
|
||||
|
||||
"github.com/usual2970/certimate/internal/pkg/core/deployer"
|
||||
"github.com/usual2970/certimate/internal/pkg/core/uploader"
|
||||
providerElb "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/huaweicloud-elb"
|
||||
"github.com/usual2970/certimate/internal/pkg/utils/cast"
|
||||
)
|
||||
|
||||
type HuaweiCloudELBDeployerConfig struct {
|
||||
// 华为云 AccessKeyId。
|
||||
AccessKeyId string `json:"accessKeyId"`
|
||||
// 华为云 SecretAccessKey。
|
||||
SecretAccessKey string `json:"secretAccessKey"`
|
||||
// 华为云地域。
|
||||
Region string `json:"region"`
|
||||
// 部署资源类型。
|
||||
ResourceType DeployResourceType `json:"resourceType"`
|
||||
// 证书 ID。
|
||||
// 部署资源类型为 [DEPLOY_RESOURCE_CERTIFICATE] 时必填。
|
||||
CertificateId string `json:"certificateId,omitempty"`
|
||||
// 负载均衡实例 ID。
|
||||
// 部署资源类型为 [DEPLOY_RESOURCE_LOADBALANCER] 时必填。
|
||||
LoadbalancerId string `json:"loadbalancerId,omitempty"`
|
||||
// 负载均衡监听 ID。
|
||||
// 部署资源类型为 [DEPLOY_RESOURCE_LISTENER] 时必填。
|
||||
ListenerId string `json:"listenerId,omitempty"`
|
||||
}
|
||||
|
||||
type HuaweiCloudELBDeployer struct {
|
||||
config *HuaweiCloudELBDeployerConfig
|
||||
logger deployer.Logger
|
||||
sdkClient *hcElb.ElbClient
|
||||
sslUploader uploader.Uploader
|
||||
}
|
||||
|
||||
var _ deployer.Deployer = (*HuaweiCloudELBDeployer)(nil)
|
||||
|
||||
func New(config *HuaweiCloudELBDeployerConfig) (*HuaweiCloudELBDeployer, error) {
|
||||
return NewWithLogger(config, deployer.NewNilLogger())
|
||||
}
|
||||
|
||||
func NewWithLogger(config *HuaweiCloudELBDeployerConfig, logger deployer.Logger) (*HuaweiCloudELBDeployer, error) {
|
||||
if config == nil {
|
||||
return nil, errors.New("config is nil")
|
||||
}
|
||||
|
||||
if logger == nil {
|
||||
return nil, errors.New("logger is nil")
|
||||
}
|
||||
|
||||
client, err := createSdkClient(config.AccessKeyId, config.SecretAccessKey, config.Region)
|
||||
if err != nil {
|
||||
return nil, xerrors.Wrap(err, "failed to create sdk client")
|
||||
}
|
||||
|
||||
uploader, err := providerElb.New(&providerElb.HuaweiCloudELBUploaderConfig{
|
||||
AccessKeyId: config.AccessKeyId,
|
||||
SecretAccessKey: config.SecretAccessKey,
|
||||
Region: config.Region,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, xerrors.Wrap(err, "failed to create ssl uploader")
|
||||
}
|
||||
|
||||
return &HuaweiCloudELBDeployer{
|
||||
logger: logger,
|
||||
config: config,
|
||||
sdkClient: client,
|
||||
sslUploader: uploader,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (d *HuaweiCloudELBDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
|
||||
// 上传证书到 SCM
|
||||
upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem)
|
||||
if err != nil {
|
||||
return nil, xerrors.Wrap(err, "failed to upload certificate file")
|
||||
}
|
||||
|
||||
d.logger.Appendt("certificate file uploaded", upres)
|
||||
|
||||
// 根据部署资源类型决定部署方式
|
||||
switch d.config.ResourceType {
|
||||
case DEPLOY_RESOURCE_CERTIFICATE:
|
||||
if err := d.deployToCertificate(ctx, certPem, privkeyPem); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
case DEPLOY_RESOURCE_LOADBALANCER:
|
||||
if err := d.deployToLoadbalancer(ctx, certPem, privkeyPem); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
case DEPLOY_RESOURCE_LISTENER:
|
||||
if err := d.deployToListener(ctx, certPem, privkeyPem); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported resource type: %s", d.config.ResourceType)
|
||||
}
|
||||
|
||||
return &deployer.DeployResult{}, nil
|
||||
}
|
||||
|
||||
func (d *HuaweiCloudELBDeployer) deployToCertificate(ctx context.Context, certPem string, privkeyPem string) error {
|
||||
if d.config.CertificateId == "" {
|
||||
return errors.New("config `certificateId` is required")
|
||||
}
|
||||
|
||||
// 更新证书
|
||||
// REF: https://support.huaweicloud.com/api-elb/UpdateCertificate.html
|
||||
updateCertificateReq := &hcElbModel.UpdateCertificateRequest{
|
||||
CertificateId: d.config.CertificateId,
|
||||
Body: &hcElbModel.UpdateCertificateRequestBody{
|
||||
Certificate: &hcElbModel.UpdateCertificateOption{
|
||||
Certificate: cast.StringPtr(certPem),
|
||||
PrivateKey: cast.StringPtr(privkeyPem),
|
||||
},
|
||||
},
|
||||
}
|
||||
updateCertificateResp, err := d.sdkClient.UpdateCertificate(updateCertificateReq)
|
||||
if err != nil {
|
||||
return xerrors.Wrap(err, "failed to execute sdk request 'elb.UpdateCertificate'")
|
||||
}
|
||||
|
||||
d.logger.Appendt("已更新 ELB 证书", updateCertificateResp)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *HuaweiCloudELBDeployer) deployToLoadbalancer(ctx context.Context, certPem string, privkeyPem string) error {
|
||||
if d.config.LoadbalancerId == "" {
|
||||
return errors.New("config `loadbalancerId` is required")
|
||||
}
|
||||
|
||||
listenerIds := make([]string, 0)
|
||||
|
||||
// 查询负载均衡器详情
|
||||
// REF: https://support.huaweicloud.com/api-elb/ShowLoadBalancer.html
|
||||
showLoadBalancerReq := &hcElbModel.ShowLoadBalancerRequest{
|
||||
LoadbalancerId: d.config.LoadbalancerId,
|
||||
}
|
||||
showLoadBalancerResp, err := d.sdkClient.ShowLoadBalancer(showLoadBalancerReq)
|
||||
if err != nil {
|
||||
return xerrors.Wrap(err, "failed to execute sdk request 'elb.ShowLoadBalancer'")
|
||||
}
|
||||
|
||||
d.logger.Appendt("已查询到 ELB 负载均衡器", showLoadBalancerResp)
|
||||
|
||||
// 查询监听器列表
|
||||
// REF: https://support.huaweicloud.com/api-elb/ListListeners.html
|
||||
listListenersLimit := int32(2000)
|
||||
var listListenersMarker *string = nil
|
||||
for {
|
||||
listListenersReq := &hcElbModel.ListListenersRequest{
|
||||
Limit: cast.Int32Ptr(listListenersLimit),
|
||||
Marker: listListenersMarker,
|
||||
Protocol: &[]string{"HTTPS", "TERMINATED_HTTPS"},
|
||||
LoadbalancerId: &[]string{showLoadBalancerResp.Loadbalancer.Id},
|
||||
}
|
||||
listListenersResp, err := d.sdkClient.ListListeners(listListenersReq)
|
||||
if err != nil {
|
||||
return xerrors.Wrap(err, "failed to execute sdk request 'elb.ListListeners'")
|
||||
}
|
||||
|
||||
if listListenersResp.Listeners != nil {
|
||||
for _, listener := range *listListenersResp.Listeners {
|
||||
listenerIds = append(listenerIds, listener.Id)
|
||||
}
|
||||
}
|
||||
|
||||
if listListenersResp.Listeners == nil || len(*listListenersResp.Listeners) < int(listListenersLimit) {
|
||||
break
|
||||
} else {
|
||||
listListenersMarker = listListenersResp.PageInfo.NextMarker
|
||||
}
|
||||
}
|
||||
|
||||
d.logger.Appendt("已查询到 ELB 负载均衡器下的监听器", listenerIds)
|
||||
|
||||
// 上传证书到 SCM
|
||||
upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem)
|
||||
if err != nil {
|
||||
return xerrors.Wrap(err, "failed to upload certificate file")
|
||||
}
|
||||
|
||||
d.logger.Appendt("certificate file uploaded", upres)
|
||||
|
||||
// 批量更新监听器证书
|
||||
var errs []error
|
||||
for _, listenerId := range listenerIds {
|
||||
if err := d.modifyListenerCertificate(ctx, listenerId, upres.CertId); err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
}
|
||||
if len(errs) > 0 {
|
||||
return errors.Join(errs...)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *HuaweiCloudELBDeployer) deployToListener(ctx context.Context, certPem string, privkeyPem string) error {
|
||||
if d.config.ListenerId == "" {
|
||||
return errors.New("config `listenerId` is required")
|
||||
}
|
||||
|
||||
// 上传证书到 SCM
|
||||
upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem)
|
||||
if err != nil {
|
||||
return xerrors.Wrap(err, "failed to upload certificate file")
|
||||
}
|
||||
|
||||
d.logger.Appendt("certificate file uploaded", upres)
|
||||
|
||||
// 更新监听器证书
|
||||
if err := d.modifyListenerCertificate(ctx, d.config.ListenerId, upres.CertId); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *HuaweiCloudELBDeployer) modifyListenerCertificate(ctx context.Context, cloudListenerId string, cloudCertId string) error {
|
||||
// 查询监听器详情
|
||||
// REF: https://support.huaweicloud.com/api-elb/ShowListener.html
|
||||
showListenerReq := &hcElbModel.ShowListenerRequest{
|
||||
ListenerId: cloudListenerId,
|
||||
}
|
||||
showListenerResp, err := d.sdkClient.ShowListener(showListenerReq)
|
||||
if err != nil {
|
||||
return xerrors.Wrap(err, "failed to execute sdk request 'elb.ShowListener'")
|
||||
}
|
||||
|
||||
d.logger.Appendt("已查询到 ELB 监听器", showListenerResp)
|
||||
|
||||
// 更新监听器
|
||||
// REF: https://support.huaweicloud.com/api-elb/UpdateListener.html
|
||||
updateListenerReq := &hcElbModel.UpdateListenerRequest{
|
||||
ListenerId: cloudListenerId,
|
||||
Body: &hcElbModel.UpdateListenerRequestBody{
|
||||
Listener: &hcElbModel.UpdateListenerOption{
|
||||
DefaultTlsContainerRef: cast.StringPtr(cloudCertId),
|
||||
},
|
||||
},
|
||||
}
|
||||
if showListenerResp.Listener.SniContainerRefs != nil {
|
||||
if len(showListenerResp.Listener.SniContainerRefs) > 0 {
|
||||
// 如果开启 SNI,需替换同 SAN 的证书
|
||||
sniCertIds := make([]string, 0)
|
||||
sniCertIds = append(sniCertIds, cloudCertId)
|
||||
|
||||
listOldCertificateReq := &hcElbModel.ListCertificatesRequest{
|
||||
Id: &showListenerResp.Listener.SniContainerRefs,
|
||||
}
|
||||
listOldCertificateResp, err := d.sdkClient.ListCertificates(listOldCertificateReq)
|
||||
if err != nil {
|
||||
return xerrors.Wrap(err, "failed to execute sdk request 'elb.ListCertificates'")
|
||||
}
|
||||
|
||||
showNewCertificateReq := &hcElbModel.ShowCertificateRequest{
|
||||
CertificateId: cloudCertId,
|
||||
}
|
||||
showNewCertificateResp, err := d.sdkClient.ShowCertificate(showNewCertificateReq)
|
||||
if err != nil {
|
||||
return xerrors.Wrap(err, "failed to execute sdk request 'elb.ShowCertificate'")
|
||||
}
|
||||
|
||||
for _, certificate := range *listOldCertificateResp.Certificates {
|
||||
oldCertificate := certificate
|
||||
newCertificate := showNewCertificateResp.Certificate
|
||||
|
||||
if oldCertificate.SubjectAlternativeNames != nil && newCertificate.SubjectAlternativeNames != nil {
|
||||
if slices.Equal(*oldCertificate.SubjectAlternativeNames, *newCertificate.SubjectAlternativeNames) {
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
if oldCertificate.Domain == newCertificate.Domain {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
sniCertIds = append(sniCertIds, certificate.Id)
|
||||
}
|
||||
|
||||
updateListenerReq.Body.Listener.SniContainerRefs = &sniCertIds
|
||||
}
|
||||
|
||||
if showListenerResp.Listener.SniMatchAlgo != "" {
|
||||
updateListenerReq.Body.Listener.SniMatchAlgo = cast.StringPtr(showListenerResp.Listener.SniMatchAlgo)
|
||||
}
|
||||
}
|
||||
updateListenerResp, err := d.sdkClient.UpdateListener(updateListenerReq)
|
||||
if err != nil {
|
||||
return xerrors.Wrap(err, "failed to execute sdk request 'elb.UpdateListener'")
|
||||
}
|
||||
|
||||
d.logger.Appendt("已更新 ELB 监听器", updateListenerResp)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func createSdkClient(accessKeyId, secretAccessKey, region string) (*hcElb.ElbClient, error) {
|
||||
if region == "" {
|
||||
region = "cn-north-4" // ELB 服务默认区域:华北四北京
|
||||
}
|
||||
|
||||
projectId, err := (&HuaweiCloudELBDeployer{}).getSdkProjectId(
|
||||
accessKeyId,
|
||||
secretAccessKey,
|
||||
region,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
auth, err := basic.NewCredentialsBuilder().
|
||||
WithAk(accessKeyId).
|
||||
WithSk(secretAccessKey).
|
||||
WithProjectId(projectId).
|
||||
SafeBuild()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
hcRegion, err := hcElbRegion.SafeValueOf(region)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
hcClient, err := hcElb.ElbClientBuilder().
|
||||
WithRegion(hcRegion).
|
||||
WithCredential(auth).
|
||||
SafeBuild()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
client := hcElb.NewElbClient(hcClient)
|
||||
return client, nil
|
||||
}
|
||||
|
||||
func getSdkProjectId(accessKeyId, secretAccessKey, region string) (string, error) {
|
||||
if region == "" {
|
||||
region = "cn-north-4" // IAM 服务默认区域:华北四北京
|
||||
}
|
||||
|
||||
auth, err := global.NewCredentialsBuilder().
|
||||
WithAk(accessKeyId).
|
||||
WithSk(secretAccessKey).
|
||||
SafeBuild()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
hcRegion, err := hcIamRegion.SafeValueOf(region)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
hcClient, err := hcIam.IamClientBuilder().
|
||||
WithRegion(hcRegion).
|
||||
WithCredential(auth).
|
||||
SafeBuild()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
client := hcIam.NewIamClient(hcClient)
|
||||
|
||||
request := &hcIamModel.KeystoneListProjectsRequest{
|
||||
Name: ®ion,
|
||||
}
|
||||
response, err := client.KeystoneListProjects(request)
|
||||
if err != nil {
|
||||
return "", err
|
||||
} else if response.Projects == nil || len(*response.Projects) == 0 {
|
||||
return "", errors.New("no project found")
|
||||
}
|
||||
|
||||
return (*response.Projects)[0].Id, nil
|
||||
}
|
@ -0,0 +1,155 @@
|
||||
package huaweicloudelb_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
provider "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/huaweicloud-elb"
|
||||
)
|
||||
|
||||
var (
|
||||
fInputCertPath string
|
||||
fInputKeyPath string
|
||||
fAccessKeyId string
|
||||
fSecretAccessKey string
|
||||
fRegion string
|
||||
fCertificateId string
|
||||
fLoadbalancerId string
|
||||
fListenerId string
|
||||
)
|
||||
|
||||
func init() {
|
||||
argsPrefix := "CERTIMATE_DEPLOYER_HUAWEICLOUDELB_"
|
||||
|
||||
flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "")
|
||||
flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "")
|
||||
flag.StringVar(&fAccessKeyId, argsPrefix+"ACCESSKEYID", "", "")
|
||||
flag.StringVar(&fSecretAccessKey, argsPrefix+"SECRETACCESSKEY", "", "")
|
||||
flag.StringVar(&fRegion, argsPrefix+"REGION", "", "")
|
||||
flag.StringVar(&fCertificateId, argsPrefix+"CERTIFICATEID", "", "")
|
||||
flag.StringVar(&fLoadbalancerId, argsPrefix+"LOADBALANCERID", "", "")
|
||||
flag.StringVar(&fListenerId, argsPrefix+"LISTENERID", "", "")
|
||||
}
|
||||
|
||||
/*
|
||||
Shell command to run this test:
|
||||
|
||||
go test -v huaweicloud_elb_test.go -args \
|
||||
--CERTIMATE_DEPLOYER_HUAWEICLOUDELB_INPUTCERTPATH="/path/to/your-input-cert.pem" \
|
||||
--CERTIMATE_DEPLOYER_HUAWEICLOUDELB_INPUTKEYPATH="/path/to/your-input-key.pem" \
|
||||
--CERTIMATE_DEPLOYER_HUAWEICLOUDELB_ACCESSKEYID="your-access-key-id" \
|
||||
--CERTIMATE_DEPLOYER_HUAWEICLOUDELB_SECRETACCESSKEY="your-secret-access-key" \
|
||||
--CERTIMATE_DEPLOYER_HUAWEICLOUDELB_REGION="cn-north-1" \
|
||||
--CERTIMATE_DEPLOYER_HUAWEICLOUDELB_CERTIFICATEID="your-elb-cert-id" \
|
||||
--CERTIMATE_DEPLOYER_HUAWEICLOUDELB_LOADBALANCERID="your-elb-loadbalancer-id" \
|
||||
--CERTIMATE_DEPLOYER_HUAWEICLOUDELB_LISTENERID="your-elb-listener-id"
|
||||
*/
|
||||
func Test(t *testing.T) {
|
||||
flag.Parse()
|
||||
|
||||
t.Run("Deploy_ToCertificate", func(t *testing.T) {
|
||||
t.Log(strings.Join([]string{
|
||||
"args:",
|
||||
fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath),
|
||||
fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath),
|
||||
fmt.Sprintf("ACCESSKEYID: %v", fAccessKeyId),
|
||||
fmt.Sprintf("SECRETACCESSKEY: %v", fSecretAccessKey),
|
||||
fmt.Sprintf("REGION: %v", fRegion),
|
||||
fmt.Sprintf("CERTIFICATEID: %v", fCertificateId),
|
||||
}, "\n"))
|
||||
|
||||
deployer, err := provider.New(&provider.HuaweiCloudELBDeployerConfig{
|
||||
AccessKeyId: fAccessKeyId,
|
||||
SecretAccessKey: fSecretAccessKey,
|
||||
Region: fRegion,
|
||||
ResourceType: provider.DEPLOY_RESOURCE_CERTIFICATE,
|
||||
CertificateId: fCertificateId,
|
||||
})
|
||||
if err != nil {
|
||||
t.Errorf("err: %+v", err)
|
||||
return
|
||||
}
|
||||
|
||||
fInputCertData, _ := os.ReadFile(fInputCertPath)
|
||||
fInputKeyData, _ := os.ReadFile(fInputKeyPath)
|
||||
res, err := deployer.Deploy(context.Background(), string(fInputCertData), string(fInputKeyData))
|
||||
if err != nil {
|
||||
t.Errorf("err: %+v", err)
|
||||
return
|
||||
}
|
||||
|
||||
t.Logf("ok: %v", res)
|
||||
})
|
||||
|
||||
t.Run("Deploy_ToLoadbalancer", func(t *testing.T) {
|
||||
t.Log(strings.Join([]string{
|
||||
"args:",
|
||||
fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath),
|
||||
fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath),
|
||||
fmt.Sprintf("ACCESSKEYID: %v", fAccessKeyId),
|
||||
fmt.Sprintf("SECRETACCESSKEY: %v", fSecretAccessKey),
|
||||
fmt.Sprintf("REGION: %v", fRegion),
|
||||
fmt.Sprintf("LOADBALANCERID: %v", fLoadbalancerId),
|
||||
}, "\n"))
|
||||
|
||||
deployer, err := provider.New(&provider.HuaweiCloudELBDeployerConfig{
|
||||
AccessKeyId: fAccessKeyId,
|
||||
SecretAccessKey: fSecretAccessKey,
|
||||
Region: fRegion,
|
||||
ResourceType: provider.DEPLOY_RESOURCE_LOADBALANCER,
|
||||
LoadbalancerId: fLoadbalancerId,
|
||||
})
|
||||
if err != nil {
|
||||
t.Errorf("err: %+v", err)
|
||||
return
|
||||
}
|
||||
|
||||
fInputCertData, _ := os.ReadFile(fInputCertPath)
|
||||
fInputKeyData, _ := os.ReadFile(fInputKeyPath)
|
||||
res, err := deployer.Deploy(context.Background(), string(fInputCertData), string(fInputKeyData))
|
||||
if err != nil {
|
||||
t.Errorf("err: %+v", err)
|
||||
return
|
||||
}
|
||||
|
||||
t.Logf("ok: %v", res)
|
||||
})
|
||||
|
||||
t.Run("Deploy_ToListenerId", func(t *testing.T) {
|
||||
t.Log(strings.Join([]string{
|
||||
"args:",
|
||||
fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath),
|
||||
fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath),
|
||||
fmt.Sprintf("ACCESSKEYID: %v", fAccessKeyId),
|
||||
fmt.Sprintf("SECRETACCESSKEY: %v", fSecretAccessKey),
|
||||
fmt.Sprintf("REGION: %v", fRegion),
|
||||
fmt.Sprintf("LISTENERID: %v", fListenerId),
|
||||
}, "\n"))
|
||||
|
||||
deployer, err := provider.New(&provider.HuaweiCloudELBDeployerConfig{
|
||||
AccessKeyId: fAccessKeyId,
|
||||
SecretAccessKey: fSecretAccessKey,
|
||||
Region: fRegion,
|
||||
ResourceType: provider.DEPLOY_RESOURCE_LISTENER,
|
||||
ListenerId: fListenerId,
|
||||
})
|
||||
if err != nil {
|
||||
t.Errorf("err: %+v", err)
|
||||
return
|
||||
}
|
||||
|
||||
fInputCertData, _ := os.ReadFile(fInputCertPath)
|
||||
fInputKeyData, _ := os.ReadFile(fInputKeyPath)
|
||||
res, err := deployer.Deploy(context.Background(), string(fInputCertData), string(fInputKeyData))
|
||||
if err != nil {
|
||||
t.Errorf("err: %+v", err)
|
||||
return
|
||||
}
|
||||
|
||||
t.Logf("ok: %v", res)
|
||||
})
|
||||
}
|
@ -8,7 +8,7 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
dpK8sSecret "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/k8s-secret"
|
||||
provider "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/k8s-secret"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -56,7 +56,7 @@ func Test(t *testing.T) {
|
||||
fmt.Sprintf("SECRETDATAKEYFORKEY: %v", fSecretDataKeyForKey),
|
||||
}, "\n"))
|
||||
|
||||
deployer, err := dpK8sSecret.New(&dpK8sSecret.K8sSecretDeployerConfig{
|
||||
deployer, err := provider.New(&provider.K8sSecretDeployerConfig{
|
||||
Namespace: fNamespace,
|
||||
SecretName: fSecretName,
|
||||
SecretDataKeyForCrt: fSecretDataKeyForCrt,
|
||||
|
@ -8,7 +8,7 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
dpLocal "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/local"
|
||||
provider "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/local"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -60,7 +60,7 @@ func Test(t *testing.T) {
|
||||
fmt.Sprintf("OUTPUTKEYPATH: %v", fOutputKeyPath),
|
||||
}, "\n"))
|
||||
|
||||
deployer, err := dpLocal.New(&dpLocal.LocalDeployerConfig{
|
||||
deployer, err := provider.New(&provider.LocalDeployerConfig{
|
||||
OutputCertPath: fOutputCertPath,
|
||||
OutputKeyPath: fOutputKeyPath,
|
||||
})
|
||||
@ -108,8 +108,8 @@ func Test(t *testing.T) {
|
||||
fmt.Sprintf("PFXPASSWORD: %v", fPfxPassword),
|
||||
}, "\n"))
|
||||
|
||||
deployer, err := dpLocal.New(&dpLocal.LocalDeployerConfig{
|
||||
OutputFormat: dpLocal.OUTPUT_FORMAT_PFX,
|
||||
deployer, err := provider.New(&provider.LocalDeployerConfig{
|
||||
OutputFormat: provider.OUTPUT_FORMAT_PFX,
|
||||
OutputCertPath: fOutputCertPath,
|
||||
OutputKeyPath: fOutputKeyPath,
|
||||
PfxPassword: fPfxPassword,
|
||||
@ -151,8 +151,8 @@ func Test(t *testing.T) {
|
||||
fmt.Sprintf("JKSSTOREPASS: %v", fJksStorepass),
|
||||
}, "\n"))
|
||||
|
||||
deployer, err := dpLocal.New(&dpLocal.LocalDeployerConfig{
|
||||
OutputFormat: dpLocal.OUTPUT_FORMAT_JKS,
|
||||
deployer, err := provider.New(&provider.LocalDeployerConfig{
|
||||
OutputFormat: provider.OUTPUT_FORMAT_JKS,
|
||||
OutputCertPath: fOutputCertPath,
|
||||
OutputKeyPath: fOutputKeyPath,
|
||||
JksAlias: fJksAlias,
|
||||
|
106
internal/pkg/core/deployer/providers/qiniu-cdn/qiniu_cdn.go
Normal file
106
internal/pkg/core/deployer/providers/qiniu-cdn/qiniu_cdn.go
Normal file
@ -0,0 +1,106 @@
|
||||
package qiniucdn
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"strings"
|
||||
|
||||
xerrors "github.com/pkg/errors"
|
||||
"github.com/qiniu/go-sdk/v7/auth"
|
||||
|
||||
"github.com/usual2970/certimate/internal/pkg/core/deployer"
|
||||
"github.com/usual2970/certimate/internal/pkg/core/uploader"
|
||||
providerQiniu "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/qiniu-sslcert"
|
||||
qiniusdk "github.com/usual2970/certimate/internal/pkg/vendors/qiniu-sdk"
|
||||
)
|
||||
|
||||
type QiniuCDNDeployerConfig struct {
|
||||
// 七牛云 AccessKey。
|
||||
AccessKey string `json:"accessKey"`
|
||||
// 七牛云 SecretKey。
|
||||
SecretKey string `json:"secretKey"`
|
||||
// 加速域名(支持泛域名)。
|
||||
Domain string `json:"domain"`
|
||||
}
|
||||
|
||||
type QiniuCDNDeployer struct {
|
||||
config *QiniuCDNDeployerConfig
|
||||
logger deployer.Logger
|
||||
sdkClient *qiniusdk.Client
|
||||
sslUploader uploader.Uploader
|
||||
}
|
||||
|
||||
var _ deployer.Deployer = (*QiniuCDNDeployer)(nil)
|
||||
|
||||
func New(config *QiniuCDNDeployerConfig) (*QiniuCDNDeployer, error) {
|
||||
return NewWithLogger(config, deployer.NewNilLogger())
|
||||
}
|
||||
|
||||
func NewWithLogger(config *QiniuCDNDeployerConfig, logger deployer.Logger) (*QiniuCDNDeployer, error) {
|
||||
if config == nil {
|
||||
return nil, errors.New("config is nil")
|
||||
}
|
||||
|
||||
if logger == nil {
|
||||
return nil, errors.New("logger is nil")
|
||||
}
|
||||
|
||||
client := qiniusdk.NewClient(auth.New(config.AccessKey, config.SecretKey))
|
||||
|
||||
uploader, err := providerQiniu.New(&providerQiniu.QiniuSSLCertUploaderConfig{
|
||||
AccessKey: config.AccessKey,
|
||||
SecretKey: config.SecretKey,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, xerrors.Wrap(err, "failed to create ssl uploader")
|
||||
}
|
||||
|
||||
return &QiniuCDNDeployer{
|
||||
logger: logger,
|
||||
config: config,
|
||||
sdkClient: client,
|
||||
sslUploader: uploader,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (d *QiniuCDNDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
|
||||
// 上传证书到 CDN
|
||||
upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem)
|
||||
if err != nil {
|
||||
return nil, xerrors.Wrap(err, "failed to upload certificate file")
|
||||
}
|
||||
|
||||
d.logger.Appendt("certificate file uploaded", upres)
|
||||
|
||||
// "*.example.com" → ".example.com",适配七牛云 CDN 要求的泛域名格式
|
||||
domain := strings.TrimPrefix(d.config.Domain, "*")
|
||||
|
||||
// 获取域名信息
|
||||
// REF: https://developer.qiniu.com/fusion/4246/the-domain-name
|
||||
getDomainInfoResp, err := d.sdkClient.GetDomainInfo(domain)
|
||||
if err != nil {
|
||||
return nil, xerrors.Wrap(err, "failed to execute sdk request 'cdn.GetDomainInfo'")
|
||||
}
|
||||
|
||||
d.logger.Appendt("已获取域名信息", getDomainInfoResp)
|
||||
|
||||
// 判断域名是否已启用 HTTPS。如果已启用,修改域名证书;否则,启用 HTTPS
|
||||
// REF: https://developer.qiniu.com/fusion/4246/the-domain-name
|
||||
if getDomainInfoResp.Https != nil && getDomainInfoResp.Https.CertID != "" {
|
||||
modifyDomainHttpsConfResp, err := d.sdkClient.ModifyDomainHttpsConf(domain, upres.CertId, getDomainInfoResp.Https.ForceHttps, getDomainInfoResp.Https.Http2Enable)
|
||||
if err != nil {
|
||||
return nil, xerrors.Wrap(err, "failed to execute sdk request 'cdn.ModifyDomainHttpsConf'")
|
||||
}
|
||||
|
||||
d.logger.Appendt("已修改域名证书", modifyDomainHttpsConfResp)
|
||||
} else {
|
||||
enableDomainHttpsResp, err := d.sdkClient.EnableDomainHttps(domain, upres.CertId, true, true)
|
||||
if err != nil {
|
||||
return nil, xerrors.Wrap(err, "failed to execute sdk request 'cdn.EnableDomainHttps'")
|
||||
}
|
||||
|
||||
d.logger.Appendt("已将域名升级为 HTTPS", enableDomainHttpsResp)
|
||||
}
|
||||
|
||||
return &deployer.DeployResult{}, nil
|
||||
}
|
@ -0,0 +1,75 @@
|
||||
package qiniucdn_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
provider "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/qiniu-cdn"
|
||||
)
|
||||
|
||||
var (
|
||||
fInputCertPath string
|
||||
fInputKeyPath string
|
||||
fAccessKey string
|
||||
fSecretKey string
|
||||
fDomain string
|
||||
)
|
||||
|
||||
func init() {
|
||||
argsPrefix := "CERTIMATE_DEPLOYER_QINIUCDN_"
|
||||
|
||||
flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "")
|
||||
flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "")
|
||||
flag.StringVar(&fAccessKey, argsPrefix+"ACCESSKEY", "", "")
|
||||
flag.StringVar(&fSecretKey, argsPrefix+"SECRETKEY", "", "")
|
||||
flag.StringVar(&fDomain, argsPrefix+"DOMAIN", "", "")
|
||||
}
|
||||
|
||||
/*
|
||||
Shell command to run this test:
|
||||
|
||||
go test -v qiniu_cdn_test.go -args \
|
||||
--CERTIMATE_DEPLOYER_QINIUCDN_INPUTCERTPATH="/path/to/your-input-cert.pem" \
|
||||
--CERTIMATE_DEPLOYER_QINIUCDN_INPUTKEYPATH="/path/to/your-input-key.pem" \
|
||||
--CERTIMATE_DEPLOYER_QINIUCDN_ACCESSKEY="your-access-key" \
|
||||
--CERTIMATE_DEPLOYER_QINIUCDN_SECRETKEY="your-secret-key" \
|
||||
--CERTIMATE_DEPLOYER_QINIUCDN_DOMAIN="example.com" \
|
||||
*/
|
||||
func Test(t *testing.T) {
|
||||
flag.Parse()
|
||||
|
||||
t.Run("Deploy", func(t *testing.T) {
|
||||
t.Log(strings.Join([]string{
|
||||
"args:",
|
||||
fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath),
|
||||
fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath),
|
||||
fmt.Sprintf("ACCESSKEY: %v", fAccessKey),
|
||||
fmt.Sprintf("SECRETKEY: %v", fSecretKey),
|
||||
fmt.Sprintf("DOMAIN: %v", fDomain),
|
||||
}, "\n"))
|
||||
|
||||
deployer, err := provider.New(&provider.QiniuCDNDeployerConfig{
|
||||
AccessKey: fAccessKey,
|
||||
SecretKey: fSecretKey,
|
||||
Domain: fDomain,
|
||||
})
|
||||
if err != nil {
|
||||
t.Errorf("err: %+v", err)
|
||||
return
|
||||
}
|
||||
|
||||
fInputCertData, _ := os.ReadFile(fInputCertPath)
|
||||
fInputKeyData, _ := os.ReadFile(fInputKeyPath)
|
||||
res, err := deployer.Deploy(context.Background(), string(fInputCertData), string(fInputKeyData))
|
||||
if err != nil {
|
||||
t.Errorf("err: %+v", err)
|
||||
return
|
||||
}
|
||||
|
||||
t.Logf("ok: %v", res)
|
||||
})
|
||||
}
|
@ -8,7 +8,7 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
dpSsh "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/ssh"
|
||||
provider "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/ssh"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -64,7 +64,7 @@ func Test(t *testing.T) {
|
||||
fmt.Sprintf("OUTPUTKEYPATH: %v", fOutputKeyPath),
|
||||
}, "\n"))
|
||||
|
||||
deployer, err := dpSsh.New(&dpSsh.SshDeployerConfig{
|
||||
deployer, err := provider.New(&provider.SshDeployerConfig{
|
||||
SshHost: fSshHost,
|
||||
SshPort: int32(fSshPort),
|
||||
SshUsername: fSshUsername,
|
||||
|
@ -0,0 +1,136 @@
|
||||
package volcenginecdn
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
xerrors "github.com/pkg/errors"
|
||||
veCdn "github.com/volcengine/volc-sdk-golang/service/cdn"
|
||||
|
||||
"github.com/usual2970/certimate/internal/pkg/core/deployer"
|
||||
"github.com/usual2970/certimate/internal/pkg/core/uploader"
|
||||
providerCdn "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/volcengine-cdn"
|
||||
)
|
||||
|
||||
type VolcEngineCDNDeployerConfig struct {
|
||||
// 火山引擎 AccessKey。
|
||||
AccessKey string `json:"accessKey"`
|
||||
// 火山引擎 SecretKey。
|
||||
SecretKey string `json:"secretKey"`
|
||||
// 加速域名(支持泛域名)。
|
||||
Domain string `json:"domain"`
|
||||
}
|
||||
|
||||
type VolcEngineCDNDeployer struct {
|
||||
config *VolcEngineCDNDeployerConfig
|
||||
logger deployer.Logger
|
||||
sdkClient *veCdn.CDN
|
||||
sslUploader uploader.Uploader
|
||||
}
|
||||
|
||||
var _ deployer.Deployer = (*VolcEngineCDNDeployer)(nil)
|
||||
|
||||
func New(config *VolcEngineCDNDeployerConfig) (*VolcEngineCDNDeployer, error) {
|
||||
return NewWithLogger(config, deployer.NewNilLogger())
|
||||
}
|
||||
|
||||
func NewWithLogger(config *VolcEngineCDNDeployerConfig, logger deployer.Logger) (*VolcEngineCDNDeployer, error) {
|
||||
if config == nil {
|
||||
return nil, errors.New("config is nil")
|
||||
}
|
||||
|
||||
if logger == nil {
|
||||
return nil, errors.New("logger is nil")
|
||||
}
|
||||
|
||||
client := veCdn.NewInstance()
|
||||
client.Client.SetAccessKey(config.AccessKey)
|
||||
client.Client.SetSecretKey(config.SecretKey)
|
||||
|
||||
uploader, err := providerCdn.New(&providerCdn.VolcEngineCDNUploaderConfig{
|
||||
AccessKeyId: config.AccessKey,
|
||||
AccessKeySecret: config.SecretKey,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, xerrors.Wrap(err, "failed to create ssl uploader")
|
||||
}
|
||||
|
||||
return &VolcEngineCDNDeployer{
|
||||
logger: logger,
|
||||
config: config,
|
||||
sdkClient: client,
|
||||
sslUploader: uploader,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (d *VolcEngineCDNDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
|
||||
// 上传证书到 CDN
|
||||
upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem)
|
||||
if err != nil {
|
||||
return nil, xerrors.Wrap(err, "failed to upload certificate file")
|
||||
}
|
||||
|
||||
d.logger.Appendt("certificate file uploaded", upres)
|
||||
|
||||
domains := make([]string, 0)
|
||||
if strings.HasPrefix(d.config.Domain, "*.") {
|
||||
// 获取指定证书可关联的域名
|
||||
// REF: https://www.volcengine.com/docs/6454/125711
|
||||
describeCertConfigReq := &veCdn.DescribeCertConfigRequest{
|
||||
CertId: upres.CertId,
|
||||
}
|
||||
describeCertConfigResp, err := d.sdkClient.DescribeCertConfig(describeCertConfigReq)
|
||||
if err != nil {
|
||||
return nil, xerrors.Wrap(err, "failed to execute sdk request 'cdn.DescribeCertConfig'")
|
||||
}
|
||||
|
||||
if describeCertConfigResp.Result.CertNotConfig != nil {
|
||||
for i := range describeCertConfigResp.Result.CertNotConfig {
|
||||
domains = append(domains, describeCertConfigResp.Result.CertNotConfig[i].Domain)
|
||||
}
|
||||
}
|
||||
|
||||
if describeCertConfigResp.Result.OtherCertConfig != nil {
|
||||
for i := range describeCertConfigResp.Result.OtherCertConfig {
|
||||
domains = append(domains, describeCertConfigResp.Result.OtherCertConfig[i].Domain)
|
||||
}
|
||||
}
|
||||
|
||||
if len(domains) == 0 {
|
||||
if len(describeCertConfigResp.Result.SpecifiedCertConfig) > 0 {
|
||||
// 所有可关联的域名都配置了该证书,跳过部署
|
||||
} else {
|
||||
return nil, xerrors.New("domain not found")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
domains = append(domains, d.config.Domain)
|
||||
}
|
||||
|
||||
if len(domains) > 0 {
|
||||
var errs []error
|
||||
|
||||
for _, domain := range domains {
|
||||
// 关联证书与加速域名
|
||||
// REF: https://www.volcengine.com/docs/6454/125712
|
||||
batchDeployCertReq := &veCdn.BatchDeployCertRequest{
|
||||
CertId: upres.CertId,
|
||||
Domain: domain,
|
||||
}
|
||||
batchDeployCertResp, err := d.sdkClient.BatchDeployCert(batchDeployCertReq)
|
||||
if err != nil {
|
||||
errs = append(errs, err)
|
||||
} else {
|
||||
d.logger.Appendt(fmt.Sprintf("已关联证书到域名 %s", domain), batchDeployCertResp)
|
||||
}
|
||||
}
|
||||
|
||||
if len(errs) > 0 {
|
||||
return nil, errors.Join(errs...)
|
||||
}
|
||||
}
|
||||
|
||||
return &deployer.DeployResult{}, nil
|
||||
}
|
@ -0,0 +1,75 @@
|
||||
package volcenginecdn_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
provider "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/volcengine-cdn"
|
||||
)
|
||||
|
||||
var (
|
||||
fInputCertPath string
|
||||
fInputKeyPath string
|
||||
fAccessKey string
|
||||
fSecretKey string
|
||||
fDomain string
|
||||
)
|
||||
|
||||
func init() {
|
||||
argsPrefix := "CERTIMATE_DEPLOYER_VOLCENGINECDN_"
|
||||
|
||||
flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "")
|
||||
flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "")
|
||||
flag.StringVar(&fAccessKey, argsPrefix+"ACCESSKEY", "", "")
|
||||
flag.StringVar(&fSecretKey, argsPrefix+"SECRETKEY", "", "")
|
||||
flag.StringVar(&fDomain, argsPrefix+"DOMAIN", "", "")
|
||||
}
|
||||
|
||||
/*
|
||||
Shell command to run this test:
|
||||
|
||||
go test -v volcengine_cdn_test.go -args \
|
||||
--CERTIMATE_DEPLOYER_VOLCENGINECDN_INPUTCERTPATH="/path/to/your-input-cert.pem" \
|
||||
--CERTIMATE_DEPLOYER_VOLCENGINECDN_INPUTKEYPATH="/path/to/your-input-key.pem" \
|
||||
--CERTIMATE_DEPLOYER_VOLCENGINECDN_ACCESSKEY="your-access-key" \
|
||||
--CERTIMATE_DEPLOYER_VOLCENGINECDN_SECRETKEY="your-secret-key" \
|
||||
--CERTIMATE_DEPLOYER_VOLCENGINECDN_DOMAIN="example.com"
|
||||
*/
|
||||
func Test(t *testing.T) {
|
||||
flag.Parse()
|
||||
|
||||
t.Run("Deploy", func(t *testing.T) {
|
||||
t.Log(strings.Join([]string{
|
||||
"args:",
|
||||
fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath),
|
||||
fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath),
|
||||
fmt.Sprintf("ACCESSKEY: %v", fAccessKey),
|
||||
fmt.Sprintf("SECRETKEY: %v", fSecretKey),
|
||||
fmt.Sprintf("DOMAIN: %v", fDomain),
|
||||
}, "\n"))
|
||||
|
||||
deployer, err := provider.New(&provider.VolcEngineCDNDeployerConfig{
|
||||
AccessKey: fAccessKey,
|
||||
SecretKey: fSecretKey,
|
||||
Domain: fDomain,
|
||||
})
|
||||
if err != nil {
|
||||
t.Errorf("err: %+v", err)
|
||||
return
|
||||
}
|
||||
|
||||
fInputCertData, _ := os.ReadFile(fInputCertPath)
|
||||
fInputKeyData, _ := os.ReadFile(fInputKeyPath)
|
||||
res, err := deployer.Deploy(context.Background(), string(fInputCertData), string(fInputKeyData))
|
||||
if err != nil {
|
||||
t.Errorf("err: %+v", err)
|
||||
return
|
||||
}
|
||||
|
||||
t.Logf("ok: %v", res)
|
||||
})
|
||||
}
|
@ -0,0 +1,146 @@
|
||||
package volcenginelive
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
xerrors "github.com/pkg/errors"
|
||||
veLive "github.com/volcengine/volc-sdk-golang/service/live/v20230101"
|
||||
|
||||
"github.com/usual2970/certimate/internal/pkg/core/deployer"
|
||||
"github.com/usual2970/certimate/internal/pkg/core/uploader"
|
||||
providerLive "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/volcengine-live"
|
||||
"github.com/usual2970/certimate/internal/pkg/utils/cast"
|
||||
)
|
||||
|
||||
type VolcEngineLiveDeployerConfig struct {
|
||||
// 火山引擎 AccessKey。
|
||||
AccessKey string `json:"accessKeyId"`
|
||||
// 火山引擎 SecretKey。
|
||||
SecretKey string `json:"secretAccessKey"`
|
||||
// 加速域名(支持泛域名)。
|
||||
Domain string `json:"domain"`
|
||||
}
|
||||
|
||||
type VolcEngineLiveDeployer struct {
|
||||
config *VolcEngineLiveDeployerConfig
|
||||
logger deployer.Logger
|
||||
sdkClient *veLive.Live
|
||||
sslUploader uploader.Uploader
|
||||
}
|
||||
|
||||
var _ deployer.Deployer = (*VolcEngineLiveDeployer)(nil)
|
||||
|
||||
func New(config *VolcEngineLiveDeployerConfig) (*VolcEngineLiveDeployer, error) {
|
||||
return NewWithLogger(config, deployer.NewNilLogger())
|
||||
}
|
||||
|
||||
func NewWithLogger(config *VolcEngineLiveDeployerConfig, logger deployer.Logger) (*VolcEngineLiveDeployer, error) {
|
||||
if config == nil {
|
||||
return nil, errors.New("config is nil")
|
||||
}
|
||||
|
||||
if logger == nil {
|
||||
return nil, errors.New("logger is nil")
|
||||
}
|
||||
|
||||
client := veLive.NewInstance()
|
||||
client.SetAccessKey(config.AccessKey)
|
||||
client.SetSecretKey(config.SecretKey)
|
||||
|
||||
uploader, err := providerLive.New(&providerLive.VolcEngineLiveUploaderConfig{
|
||||
AccessKeyId: config.AccessKey,
|
||||
AccessKeySecret: config.SecretKey,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, xerrors.Wrap(err, "failed to create ssl uploader")
|
||||
}
|
||||
|
||||
return &VolcEngineLiveDeployer{
|
||||
logger: logger,
|
||||
config: config,
|
||||
sdkClient: client,
|
||||
sslUploader: uploader,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (d *VolcEngineLiveDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
|
||||
// 上传证书到 Live
|
||||
upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem)
|
||||
if err != nil {
|
||||
return nil, xerrors.Wrap(err, "failed to upload certificate file")
|
||||
}
|
||||
|
||||
d.logger.Appendt("certificate file uploaded", upres)
|
||||
|
||||
domains := make([]string, 0)
|
||||
if strings.HasPrefix(d.config.Domain, "*.") {
|
||||
listDomainDetailPageNum := int32(1)
|
||||
listDomainDetailPageSize := int32(1000)
|
||||
listDomainDetailTotal := 0
|
||||
for {
|
||||
// 查询域名列表
|
||||
// REF: https://www.volcengine.com/docs/6469/1186277#%E6%9F%A5%E8%AF%A2%E5%9F%9F%E5%90%8D%E5%88%97%E8%A1%A8
|
||||
listDomainDetailReq := &veLive.ListDomainDetailBody{
|
||||
PageNum: listDomainDetailPageNum,
|
||||
PageSize: listDomainDetailPageSize,
|
||||
}
|
||||
listDomainDetailResp, err := d.sdkClient.ListDomainDetail(ctx, listDomainDetailReq)
|
||||
if err != nil {
|
||||
return nil, xerrors.Wrap(err, "failed to execute sdk request 'live.ListDomainDetail'")
|
||||
}
|
||||
|
||||
if listDomainDetailResp.Result.DomainList != nil {
|
||||
for _, item := range listDomainDetailResp.Result.DomainList {
|
||||
// 仅匹配泛域名的下一级子域名
|
||||
wildcardDomain := strings.TrimPrefix(d.config.Domain, "*")
|
||||
if strings.HasSuffix(item.Domain, wildcardDomain) && !strings.Contains(strings.TrimSuffix(item.Domain, wildcardDomain), ".") {
|
||||
domains = append(domains, item.Domain)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
listDomainDetailLen := len(listDomainDetailResp.Result.DomainList)
|
||||
if listDomainDetailLen < int(listDomainDetailPageSize) || int(listDomainDetailResp.Result.Total) <= listDomainDetailTotal+listDomainDetailLen {
|
||||
break
|
||||
} else {
|
||||
listDomainDetailPageNum++
|
||||
listDomainDetailTotal += listDomainDetailLen
|
||||
}
|
||||
}
|
||||
|
||||
if len(domains) == 0 {
|
||||
return nil, xerrors.Errorf("未查询到匹配的域名: %s", d.config.Domain)
|
||||
}
|
||||
} else {
|
||||
domains = append(domains, d.config.Domain)
|
||||
}
|
||||
|
||||
if len(domains) > 0 {
|
||||
var errs []error
|
||||
|
||||
for _, domain := range domains {
|
||||
// 绑定证书
|
||||
// REF: https://www.volcengine.com/docs/6469/1186278#%E7%BB%91%E5%AE%9A%E8%AF%81%E4%B9%A6
|
||||
bindCertReq := &veLive.BindCertBody{
|
||||
ChainID: upres.CertId,
|
||||
Domain: domain,
|
||||
HTTPS: cast.BoolPtr(true),
|
||||
}
|
||||
bindCertResp, err := d.sdkClient.BindCert(ctx, bindCertReq)
|
||||
if err != nil {
|
||||
errs = append(errs, err)
|
||||
} else {
|
||||
d.logger.Appendt(fmt.Sprintf("已绑定证书到域名 %s", domain), bindCertResp)
|
||||
}
|
||||
}
|
||||
|
||||
if len(errs) > 0 {
|
||||
return nil, errors.Join(errs...)
|
||||
}
|
||||
}
|
||||
|
||||
return &deployer.DeployResult{}, nil
|
||||
}
|
@ -0,0 +1,75 @@
|
||||
package volcenginelive_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
provider "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/volcengine-live"
|
||||
)
|
||||
|
||||
var (
|
||||
fInputCertPath string
|
||||
fInputKeyPath string
|
||||
fAccessKey string
|
||||
fSecretKey string
|
||||
fDomain string
|
||||
)
|
||||
|
||||
func init() {
|
||||
argsPrefix := "CERTIMATE_DEPLOYER_VOLCENGINELIVE_"
|
||||
|
||||
flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "")
|
||||
flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "")
|
||||
flag.StringVar(&fAccessKey, argsPrefix+"ACCESSKEY", "", "")
|
||||
flag.StringVar(&fSecretKey, argsPrefix+"SECRETKEY", "", "")
|
||||
flag.StringVar(&fDomain, argsPrefix+"DOMAIN", "", "")
|
||||
}
|
||||
|
||||
/*
|
||||
Shell command to run this test:
|
||||
|
||||
go test -v volcengine_live_test.go -args \
|
||||
--CERTIMATE_DEPLOYER_VOLCENGINELIVE_INPUTCERTPATH="/path/to/your-input-cert.pem" \
|
||||
--CERTIMATE_DEPLOYER_VOLCENGINELIVE_INPUTKEYPATH="/path/to/your-input-key.pem" \
|
||||
--CERTIMATE_DEPLOYER_VOLCENGINELIVE_ACCESSKEY="your-access-key" \
|
||||
--CERTIMATE_DEPLOYER_VOLCENGINELIVE_SECRETKEY="your-secret-key" \
|
||||
--CERTIMATE_DEPLOYER_VOLCENGINELIVE_DOMAIN="example.com"
|
||||
*/
|
||||
func Test(t *testing.T) {
|
||||
flag.Parse()
|
||||
|
||||
t.Run("Deploy", func(t *testing.T) {
|
||||
t.Log(strings.Join([]string{
|
||||
"args:",
|
||||
fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath),
|
||||
fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath),
|
||||
fmt.Sprintf("ACCESSKEY: %v", fAccessKey),
|
||||
fmt.Sprintf("SECRETKEY: %v", fSecretKey),
|
||||
fmt.Sprintf("DOMAIN: %v", fDomain),
|
||||
}, "\n"))
|
||||
|
||||
deployer, err := provider.New(&provider.VolcEngineLiveDeployerConfig{
|
||||
AccessKey: fAccessKey,
|
||||
SecretKey: fSecretKey,
|
||||
Domain: fDomain,
|
||||
})
|
||||
if err != nil {
|
||||
t.Errorf("err: %+v", err)
|
||||
return
|
||||
}
|
||||
|
||||
fInputCertData, _ := os.ReadFile(fInputCertPath)
|
||||
fInputKeyData, _ := os.ReadFile(fInputKeyPath)
|
||||
res, err := deployer.Deploy(context.Background(), string(fInputCertData), string(fInputKeyData))
|
||||
if err != nil {
|
||||
t.Errorf("err: %+v", err)
|
||||
return
|
||||
}
|
||||
|
||||
t.Logf("ok: %v", res)
|
||||
})
|
||||
}
|
@ -8,7 +8,7 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
dpWebhook "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/webhook"
|
||||
provider "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/webhook"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -44,7 +44,7 @@ func Test(t *testing.T) {
|
||||
fmt.Sprintf("URL: %v", fUrl),
|
||||
}, "\n"))
|
||||
|
||||
deployer, err := dpWebhook.New(&dpWebhook.WebhookDeployerConfig{
|
||||
deployer, err := provider.New(&provider.WebhookDeployerConfig{
|
||||
Url: fUrl,
|
||||
})
|
||||
if err != nil {
|
||||
|
@ -7,7 +7,7 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
npEmail "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/email"
|
||||
provider "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/email"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -64,7 +64,7 @@ func Test(t *testing.T) {
|
||||
fmt.Sprintf("RECEIVERADDRESS: %v", fReceiverAddress),
|
||||
}, "\n"))
|
||||
|
||||
notifier, err := npEmail.New(&npEmail.EmailNotifierConfig{
|
||||
notifier, err := provider.New(&provider.EmailNotifierConfig{
|
||||
SmtpHost: fSmtpHost,
|
||||
SmtpPort: int32(fSmtpPort),
|
||||
SmtpTLS: fSmtpTLS,
|
||||
|
@ -7,7 +7,7 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
npWebhook "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/webhook"
|
||||
provider "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/webhook"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -38,7 +38,7 @@ func Test(t *testing.T) {
|
||||
fmt.Sprintf("URL: %v", fUrl),
|
||||
}, "\n"))
|
||||
|
||||
notifier, err := npWebhook.New(&npWebhook.WebhookNotifierConfig{
|
||||
notifier, err := provider.New(&provider.WebhookNotifierConfig{
|
||||
Url: fUrl,
|
||||
})
|
||||
if err != nil {
|
||||
|
Loading…
x
Reference in New Issue
Block a user