mirror of
https://github.com/woodchen-ink/certimate.git
synced 2025-07-18 17:31: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{}
|
access := &domain.VolcengineAccess{}
|
||||||
json.Unmarshal([]byte(a.option.Access), access)
|
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_SECRETKEY", access.SecretAccessKey)
|
||||||
os.Setenv("VOLC_PROPAGATION_TIMEOUT", fmt.Sprintf("%d", a.option.Timeout))
|
os.Setenv("VOLC_PROPAGATION_TIMEOUT", fmt.Sprintf("%d", a.option.Timeout))
|
||||||
dnsProvider, err := volcengineDns.NewDNSProvider()
|
dnsProvider, err := volcengineDns.NewDNSProvider()
|
||||||
|
@ -27,10 +27,10 @@ func NewVolcengineCDNDeployer(option *DeployerOption) (Deployer, error) {
|
|||||||
return nil, xerrors.Wrap(err, "failed to get access")
|
return nil, xerrors.Wrap(err, "failed to get access")
|
||||||
}
|
}
|
||||||
client := cdn.NewInstance()
|
client := cdn.NewInstance()
|
||||||
client.Client.SetAccessKey(access.AccessKeyID)
|
client.Client.SetAccessKey(access.AccessKeyId)
|
||||||
client.Client.SetSecretKey(access.SecretAccessKey)
|
client.Client.SetSecretKey(access.SecretAccessKey)
|
||||||
uploader, err := volcenginecdn.New(&volcenginecdn.VolcEngineCDNUploaderConfig{
|
uploader, err := volcenginecdn.New(&volcenginecdn.VolcEngineCDNUploaderConfig{
|
||||||
AccessKeyId: access.AccessKeyID,
|
AccessKeyId: access.AccessKeyId,
|
||||||
AccessKeySecret: access.SecretAccessKey,
|
AccessKeySecret: access.SecretAccessKey,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -30,11 +30,11 @@ func NewVolcengineLiveDeployer(option *DeployerOption) (Deployer, error) {
|
|||||||
}
|
}
|
||||||
client := live.NewInstance()
|
client := live.NewInstance()
|
||||||
client.SetCredential(base.Credentials{
|
client.SetCredential(base.Credentials{
|
||||||
AccessKeyID: access.AccessKeyID,
|
AccessKeyID: access.AccessKeyId,
|
||||||
SecretAccessKey: access.SecretAccessKey,
|
SecretAccessKey: access.SecretAccessKey,
|
||||||
})
|
})
|
||||||
uploader, err := volcenginelive.New(&volcenginelive.VolcEngineLiveUploaderConfig{
|
uploader, err := volcenginelive.New(&volcenginelive.VolcEngineLiveUploaderConfig{
|
||||||
AccessKeyId: access.AccessKeyID,
|
AccessKeyId: access.AccessKeyId,
|
||||||
AccessKeySecret: access.SecretAccessKey,
|
AccessKeySecret: access.SecretAccessKey,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -62,7 +62,12 @@ type PdnsAccess struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type VolcengineAccess 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"`
|
SecretAccessKey string `json:"secretAccessKey"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,20 +5,20 @@ import (
|
|||||||
|
|
||||||
"github.com/usual2970/certimate/internal/domain"
|
"github.com/usual2970/certimate/internal/domain"
|
||||||
"github.com/usual2970/certimate/internal/pkg/core/notifier"
|
"github.com/usual2970/certimate/internal/pkg/core/notifier"
|
||||||
npBark "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/bark"
|
providerBark "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/bark"
|
||||||
npDingTalk "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/dingtalk"
|
providerDingTalk "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/dingtalk"
|
||||||
npEmail "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/email"
|
providerEmail "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/email"
|
||||||
npLark "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/lark"
|
providerLark "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/lark"
|
||||||
npServerChan "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/serverchan"
|
providerServerChan "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/serverchan"
|
||||||
npTelegram "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/telegram"
|
providerTelegram "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/telegram"
|
||||||
npWebhook "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/webhook"
|
providerWebhook "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/webhook"
|
||||||
"github.com/usual2970/certimate/internal/pkg/utils/maps"
|
"github.com/usual2970/certimate/internal/pkg/utils/maps"
|
||||||
)
|
)
|
||||||
|
|
||||||
func createNotifier(channel string, channelConfig map[string]any) (notifier.Notifier, error) {
|
func createNotifier(channel string, channelConfig map[string]any) (notifier.Notifier, error) {
|
||||||
switch channel {
|
switch channel {
|
||||||
case domain.NotifyChannelEmail:
|
case domain.NotifyChannelEmail:
|
||||||
return npEmail.New(&npEmail.EmailNotifierConfig{
|
return providerEmail.New(&providerEmail.EmailNotifierConfig{
|
||||||
SmtpHost: maps.GetValueAsString(channelConfig, "smtpHost"),
|
SmtpHost: maps.GetValueAsString(channelConfig, "smtpHost"),
|
||||||
SmtpPort: maps.GetValueAsInt32(channelConfig, "smtpPort"),
|
SmtpPort: maps.GetValueAsInt32(channelConfig, "smtpPort"),
|
||||||
SmtpTLS: maps.GetValueOrDefaultAsBool(channelConfig, "smtpTLS", true),
|
SmtpTLS: maps.GetValueOrDefaultAsBool(channelConfig, "smtpTLS", true),
|
||||||
@ -29,34 +29,34 @@ func createNotifier(channel string, channelConfig map[string]any) (notifier.Noti
|
|||||||
})
|
})
|
||||||
|
|
||||||
case domain.NotifyChannelWebhook:
|
case domain.NotifyChannelWebhook:
|
||||||
return npWebhook.New(&npWebhook.WebhookNotifierConfig{
|
return providerWebhook.New(&providerWebhook.WebhookNotifierConfig{
|
||||||
Url: maps.GetValueAsString(channelConfig, "url"),
|
Url: maps.GetValueAsString(channelConfig, "url"),
|
||||||
})
|
})
|
||||||
|
|
||||||
case domain.NotifyChannelDingtalk:
|
case domain.NotifyChannelDingtalk:
|
||||||
return npDingTalk.New(&npDingTalk.DingTalkNotifierConfig{
|
return providerDingTalk.New(&providerDingTalk.DingTalkNotifierConfig{
|
||||||
AccessToken: maps.GetValueAsString(channelConfig, "accessToken"),
|
AccessToken: maps.GetValueAsString(channelConfig, "accessToken"),
|
||||||
Secret: maps.GetValueAsString(channelConfig, "secret"),
|
Secret: maps.GetValueAsString(channelConfig, "secret"),
|
||||||
})
|
})
|
||||||
|
|
||||||
case domain.NotifyChannelLark:
|
case domain.NotifyChannelLark:
|
||||||
return npLark.New(&npLark.LarkNotifierConfig{
|
return providerLark.New(&providerLark.LarkNotifierConfig{
|
||||||
WebhookUrl: maps.GetValueAsString(channelConfig, "webhookUrl"),
|
WebhookUrl: maps.GetValueAsString(channelConfig, "webhookUrl"),
|
||||||
})
|
})
|
||||||
|
|
||||||
case domain.NotifyChannelTelegram:
|
case domain.NotifyChannelTelegram:
|
||||||
return npTelegram.New(&npTelegram.TelegramNotifierConfig{
|
return providerTelegram.New(&providerTelegram.TelegramNotifierConfig{
|
||||||
ApiToken: maps.GetValueAsString(channelConfig, "apiToken"),
|
ApiToken: maps.GetValueAsString(channelConfig, "apiToken"),
|
||||||
ChatId: maps.GetValueAsInt64(channelConfig, "chatId"),
|
ChatId: maps.GetValueAsInt64(channelConfig, "chatId"),
|
||||||
})
|
})
|
||||||
|
|
||||||
case domain.NotifyChannelServerChan:
|
case domain.NotifyChannelServerChan:
|
||||||
return npServerChan.New(&npServerChan.ServerChanNotifierConfig{
|
return providerServerChan.New(&providerServerChan.ServerChanNotifierConfig{
|
||||||
Url: maps.GetValueAsString(channelConfig, "url"),
|
Url: maps.GetValueAsString(channelConfig, "url"),
|
||||||
})
|
})
|
||||||
|
|
||||||
case domain.NotifyChannelBark:
|
case domain.NotifyChannelBark:
|
||||||
return npBark.New(&npBark.BarkNotifierConfig{
|
return providerBark.New(&providerBark.BarkNotifierConfig{
|
||||||
DeviceKey: maps.GetValueAsString(channelConfig, "deviceKey"),
|
DeviceKey: maps.GetValueAsString(channelConfig, "deviceKey"),
|
||||||
ServerUrl: maps.GetValueAsString(channelConfig, "serverUrl"),
|
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/deployer"
|
||||||
"github.com/usual2970/certimate/internal/pkg/core/uploader"
|
"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 {
|
type AliyunALBDeployerConfig struct {
|
||||||
@ -71,7 +71,7 @@ func NewWithLogger(config *AliyunALBDeployerConfig, logger deployer.Logger) (*Al
|
|||||||
aliyunCasRegion = "cn-hangzhou"
|
aliyunCasRegion = "cn-hangzhou"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
uploader, err := upAliyunCas.New(&upAliyunCas.AliyunCASUploaderConfig{
|
uploader, err := providerCas.New(&providerCas.AliyunCASUploaderConfig{
|
||||||
AccessKeyId: config.AccessKeyId,
|
AccessKeyId: config.AccessKeyId,
|
||||||
AccessKeySecret: config.AccessKeySecret,
|
AccessKeySecret: config.AccessKeySecret,
|
||||||
Region: aliyunCasRegion,
|
Region: aliyunCasRegion,
|
||||||
|
@ -8,7 +8,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"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 (
|
var (
|
||||||
@ -59,11 +59,11 @@ func Test(t *testing.T) {
|
|||||||
fmt.Sprintf("LOADBALANCERID: %v", fLoadbalancerId),
|
fmt.Sprintf("LOADBALANCERID: %v", fLoadbalancerId),
|
||||||
}, "\n"))
|
}, "\n"))
|
||||||
|
|
||||||
deployer, err := dpAliyunAlb.New(&dpAliyunAlb.AliyunALBDeployerConfig{
|
deployer, err := provider.New(&provider.AliyunALBDeployerConfig{
|
||||||
AccessKeyId: fAccessKeyId,
|
AccessKeyId: fAccessKeyId,
|
||||||
AccessKeySecret: fAccessKeySecret,
|
AccessKeySecret: fAccessKeySecret,
|
||||||
Region: fRegion,
|
Region: fRegion,
|
||||||
ResourceType: dpAliyunAlb.DEPLOY_RESOURCE_LOADBALANCER,
|
ResourceType: provider.DEPLOY_RESOURCE_LOADBALANCER,
|
||||||
LoadbalancerId: fLoadbalancerId,
|
LoadbalancerId: fLoadbalancerId,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -93,11 +93,11 @@ func Test(t *testing.T) {
|
|||||||
fmt.Sprintf("LISTENERID: %v", fListenerId),
|
fmt.Sprintf("LISTENERID: %v", fListenerId),
|
||||||
}, "\n"))
|
}, "\n"))
|
||||||
|
|
||||||
deployer, err := dpAliyunAlb.New(&dpAliyunAlb.AliyunALBDeployerConfig{
|
deployer, err := provider.New(&provider.AliyunALBDeployerConfig{
|
||||||
AccessKeyId: fAccessKeyId,
|
AccessKeyId: fAccessKeyId,
|
||||||
AccessKeySecret: fAccessKeySecret,
|
AccessKeySecret: fAccessKeySecret,
|
||||||
Region: fRegion,
|
Region: fRegion,
|
||||||
ResourceType: dpAliyunAlb.DEPLOY_RESOURCE_LISTENER,
|
ResourceType: provider.DEPLOY_RESOURCE_LISTENER,
|
||||||
ListenerId: fListenerId,
|
ListenerId: fListenerId,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -8,7 +8,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"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 (
|
var (
|
||||||
@ -37,7 +37,7 @@ Shell command to run this test:
|
|||||||
--CERTIMATE_DEPLOYER_ALIYUNCDN_INPUTKEYPATH="/path/to/your-input-key.pem" \
|
--CERTIMATE_DEPLOYER_ALIYUNCDN_INPUTKEYPATH="/path/to/your-input-key.pem" \
|
||||||
--CERTIMATE_DEPLOYER_ALIYUNCDN_ACCESSKEYID="your-access-key-id" \
|
--CERTIMATE_DEPLOYER_ALIYUNCDN_ACCESSKEYID="your-access-key-id" \
|
||||||
--CERTIMATE_DEPLOYER_ALIYUNCDN_ACCESSKEYSECRET="your-access-key-secret" \
|
--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) {
|
func Test(t *testing.T) {
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
@ -52,7 +52,7 @@ func Test(t *testing.T) {
|
|||||||
fmt.Sprintf("DOMAIN: %v", fDomain),
|
fmt.Sprintf("DOMAIN: %v", fDomain),
|
||||||
}, "\n"))
|
}, "\n"))
|
||||||
|
|
||||||
deployer, err := dpAliyunCdn.New(&dpAliyunCdn.AliyunCDNDeployerConfig{
|
deployer, err := provider.New(&provider.AliyunCDNDeployerConfig{
|
||||||
AccessKeyId: fAccessKeyId,
|
AccessKeyId: fAccessKeyId,
|
||||||
AccessKeySecret: fAccessKeySecret,
|
AccessKeySecret: fAccessKeySecret,
|
||||||
Domain: fDomain,
|
Domain: fDomain,
|
||||||
|
@ -12,7 +12,7 @@ import (
|
|||||||
|
|
||||||
"github.com/usual2970/certimate/internal/pkg/core/deployer"
|
"github.com/usual2970/certimate/internal/pkg/core/deployer"
|
||||||
"github.com/usual2970/certimate/internal/pkg/core/uploader"
|
"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 {
|
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")
|
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,
|
AccessKeyId: config.AccessKeyId,
|
||||||
AccessKeySecret: config.AccessKeySecret,
|
AccessKeySecret: config.AccessKeySecret,
|
||||||
Region: config.Region,
|
Region: config.Region,
|
||||||
|
@ -8,7 +8,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"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 (
|
var (
|
||||||
@ -59,11 +59,11 @@ func Test(t *testing.T) {
|
|||||||
fmt.Sprintf("LOADBALANCERID: %v", fLoadbalancerId),
|
fmt.Sprintf("LOADBALANCERID: %v", fLoadbalancerId),
|
||||||
}, "\n"))
|
}, "\n"))
|
||||||
|
|
||||||
deployer, err := dpAliyunClb.New(&dpAliyunClb.AliyunCLBDeployerConfig{
|
deployer, err := provider.New(&provider.AliyunCLBDeployerConfig{
|
||||||
AccessKeyId: fAccessKeyId,
|
AccessKeyId: fAccessKeyId,
|
||||||
AccessKeySecret: fAccessKeySecret,
|
AccessKeySecret: fAccessKeySecret,
|
||||||
Region: fRegion,
|
Region: fRegion,
|
||||||
ResourceType: dpAliyunClb.DEPLOY_RESOURCE_LOADBALANCER,
|
ResourceType: provider.DEPLOY_RESOURCE_LOADBALANCER,
|
||||||
LoadbalancerId: fLoadbalancerId,
|
LoadbalancerId: fLoadbalancerId,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -94,11 +94,11 @@ func Test(t *testing.T) {
|
|||||||
fmt.Sprintf("LISTENERPORT: %v", fListenerPort),
|
fmt.Sprintf("LISTENERPORT: %v", fListenerPort),
|
||||||
}, "\n"))
|
}, "\n"))
|
||||||
|
|
||||||
deployer, err := dpAliyunClb.New(&dpAliyunClb.AliyunCLBDeployerConfig{
|
deployer, err := provider.New(&provider.AliyunCLBDeployerConfig{
|
||||||
AccessKeyId: fAccessKeyId,
|
AccessKeyId: fAccessKeyId,
|
||||||
AccessKeySecret: fAccessKeySecret,
|
AccessKeySecret: fAccessKeySecret,
|
||||||
Region: fRegion,
|
Region: fRegion,
|
||||||
ResourceType: dpAliyunClb.DEPLOY_RESOURCE_LISTENER,
|
ResourceType: provider.DEPLOY_RESOURCE_LISTENER,
|
||||||
LoadbalancerId: fLoadbalancerId,
|
LoadbalancerId: fLoadbalancerId,
|
||||||
ListenerPort: int32(fListenerPort),
|
ListenerPort: int32(fListenerPort),
|
||||||
})
|
})
|
||||||
|
@ -8,7 +8,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"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 (
|
var (
|
||||||
@ -37,7 +37,7 @@ Shell command to run this test:
|
|||||||
--CERTIMATE_DEPLOYER_ALIYUNDCDN_INPUTKEYPATH="/path/to/your-input-key.pem" \
|
--CERTIMATE_DEPLOYER_ALIYUNDCDN_INPUTKEYPATH="/path/to/your-input-key.pem" \
|
||||||
--CERTIMATE_DEPLOYER_ALIYUNDCDN_ACCESSKEYID="your-access-key-id" \
|
--CERTIMATE_DEPLOYER_ALIYUNDCDN_ACCESSKEYID="your-access-key-id" \
|
||||||
--CERTIMATE_DEPLOYER_ALIYUNDCDN_ACCESSKEYSECRET="your-access-key-secret" \
|
--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) {
|
func Test(t *testing.T) {
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
@ -52,7 +52,7 @@ func Test(t *testing.T) {
|
|||||||
fmt.Sprintf("DOMAIN: %v", fDomain),
|
fmt.Sprintf("DOMAIN: %v", fDomain),
|
||||||
}, "\n"))
|
}, "\n"))
|
||||||
|
|
||||||
deployer, err := dpAliyunDcdn.New(&dpAliyunDcdn.AliyunDCDNDeployerConfig{
|
deployer, err := provider.New(&provider.AliyunDCDNDeployerConfig{
|
||||||
AccessKeyId: fAccessKeyId,
|
AccessKeyId: fAccessKeyId,
|
||||||
AccessKeySecret: fAccessKeySecret,
|
AccessKeySecret: fAccessKeySecret,
|
||||||
Domain: fDomain,
|
Domain: fDomain,
|
||||||
|
@ -13,7 +13,7 @@ import (
|
|||||||
|
|
||||||
"github.com/usual2970/certimate/internal/pkg/core/deployer"
|
"github.com/usual2970/certimate/internal/pkg/core/deployer"
|
||||||
"github.com/usual2970/certimate/internal/pkg/core/uploader"
|
"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 {
|
type AliyunNLBDeployerConfig struct {
|
||||||
@ -71,7 +71,7 @@ func NewWithLogger(config *AliyunNLBDeployerConfig, logger deployer.Logger) (*Al
|
|||||||
aliyunCasRegion = "cn-hangzhou"
|
aliyunCasRegion = "cn-hangzhou"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
uploader, err := upAliyunCas.New(&upAliyunCas.AliyunCASUploaderConfig{
|
uploader, err := providerCas.New(&providerCas.AliyunCASUploaderConfig{
|
||||||
AccessKeyId: config.AccessKeyId,
|
AccessKeyId: config.AccessKeyId,
|
||||||
AccessKeySecret: config.AccessKeySecret,
|
AccessKeySecret: config.AccessKeySecret,
|
||||||
Region: aliyunCasRegion,
|
Region: aliyunCasRegion,
|
||||||
|
@ -8,7 +8,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"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 (
|
var (
|
||||||
@ -59,11 +59,11 @@ func Test(t *testing.T) {
|
|||||||
fmt.Sprintf("LOADBALANCERID: %v", fLoadbalancerId),
|
fmt.Sprintf("LOADBALANCERID: %v", fLoadbalancerId),
|
||||||
}, "\n"))
|
}, "\n"))
|
||||||
|
|
||||||
deployer, err := dpAliyunClb.New(&dpAliyunClb.AliyunNLBDeployerConfig{
|
deployer, err := provider.New(&provider.AliyunNLBDeployerConfig{
|
||||||
AccessKeyId: fAccessKeyId,
|
AccessKeyId: fAccessKeyId,
|
||||||
AccessKeySecret: fAccessKeySecret,
|
AccessKeySecret: fAccessKeySecret,
|
||||||
Region: fRegion,
|
Region: fRegion,
|
||||||
ResourceType: dpAliyunClb.DEPLOY_RESOURCE_LOADBALANCER,
|
ResourceType: provider.DEPLOY_RESOURCE_LOADBALANCER,
|
||||||
LoadbalancerId: fLoadbalancerId,
|
LoadbalancerId: fLoadbalancerId,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -94,11 +94,11 @@ func Test(t *testing.T) {
|
|||||||
fmt.Sprintf("LISTENERID: %v", fListenerId),
|
fmt.Sprintf("LISTENERID: %v", fListenerId),
|
||||||
}, "\n"))
|
}, "\n"))
|
||||||
|
|
||||||
deployer, err := dpAliyunClb.New(&dpAliyunClb.AliyunNLBDeployerConfig{
|
deployer, err := provider.New(&provider.AliyunNLBDeployerConfig{
|
||||||
AccessKeyId: fAccessKeyId,
|
AccessKeyId: fAccessKeyId,
|
||||||
AccessKeySecret: fAccessKeySecret,
|
AccessKeySecret: fAccessKeySecret,
|
||||||
Region: fRegion,
|
Region: fRegion,
|
||||||
ResourceType: dpAliyunClb.DEPLOY_RESOURCE_LISTENER,
|
ResourceType: provider.DEPLOY_RESOURCE_LISTENER,
|
||||||
ListenerId: fListenerId,
|
ListenerId: fListenerId,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -8,7 +8,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"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 (
|
var (
|
||||||
@ -42,8 +42,8 @@ Shell command to run this test:
|
|||||||
--CERTIMATE_DEPLOYER_ALIYUNOSS_ACCESSKEYID="your-access-key-id" \
|
--CERTIMATE_DEPLOYER_ALIYUNOSS_ACCESSKEYID="your-access-key-id" \
|
||||||
--CERTIMATE_DEPLOYER_ALIYUNOSS_ACCESSKEYSECRET="your-access-key-secret" \
|
--CERTIMATE_DEPLOYER_ALIYUNOSS_ACCESSKEYSECRET="your-access-key-secret" \
|
||||||
--CERTIMATE_DEPLOYER_ALIYUNOSS_REGION="cn-hangzhou" \
|
--CERTIMATE_DEPLOYER_ALIYUNOSS_REGION="cn-hangzhou" \
|
||||||
--CERTIMATE_DEPLOYER_ALIYUNOSS_BUCKET="your-bucket" \
|
--CERTIMATE_DEPLOYER_ALIYUNOSS_BUCKET="your-oss-bucket" \
|
||||||
--CERTIMATE_DEPLOYER_ALIYUNOSS_DOMAIN="example.com" \
|
--CERTIMATE_DEPLOYER_ALIYUNOSS_DOMAIN="example.com"
|
||||||
*/
|
*/
|
||||||
func Test(t *testing.T) {
|
func Test(t *testing.T) {
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
@ -60,7 +60,7 @@ func Test(t *testing.T) {
|
|||||||
fmt.Sprintf("DOMAIN: %v", fDomain),
|
fmt.Sprintf("DOMAIN: %v", fDomain),
|
||||||
}, "\n"))
|
}, "\n"))
|
||||||
|
|
||||||
deployer, err := dpAliyunOss.New(&dpAliyunOss.AliyunOSSDeployerConfig{
|
deployer, err := provider.New(&provider.AliyunOSSDeployerConfig{
|
||||||
AccessKeyId: fAccessKeyId,
|
AccessKeyId: fAccessKeyId,
|
||||||
AccessKeySecret: fAccessKeySecret,
|
AccessKeySecret: fAccessKeySecret,
|
||||||
Region: fRegion,
|
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"
|
"strings"
|
||||||
"testing"
|
"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 (
|
var (
|
||||||
@ -56,7 +56,7 @@ func Test(t *testing.T) {
|
|||||||
fmt.Sprintf("SECRETDATAKEYFORKEY: %v", fSecretDataKeyForKey),
|
fmt.Sprintf("SECRETDATAKEYFORKEY: %v", fSecretDataKeyForKey),
|
||||||
}, "\n"))
|
}, "\n"))
|
||||||
|
|
||||||
deployer, err := dpK8sSecret.New(&dpK8sSecret.K8sSecretDeployerConfig{
|
deployer, err := provider.New(&provider.K8sSecretDeployerConfig{
|
||||||
Namespace: fNamespace,
|
Namespace: fNamespace,
|
||||||
SecretName: fSecretName,
|
SecretName: fSecretName,
|
||||||
SecretDataKeyForCrt: fSecretDataKeyForCrt,
|
SecretDataKeyForCrt: fSecretDataKeyForCrt,
|
||||||
|
@ -8,7 +8,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
dpLocal "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/local"
|
provider "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/local"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -60,7 +60,7 @@ func Test(t *testing.T) {
|
|||||||
fmt.Sprintf("OUTPUTKEYPATH: %v", fOutputKeyPath),
|
fmt.Sprintf("OUTPUTKEYPATH: %v", fOutputKeyPath),
|
||||||
}, "\n"))
|
}, "\n"))
|
||||||
|
|
||||||
deployer, err := dpLocal.New(&dpLocal.LocalDeployerConfig{
|
deployer, err := provider.New(&provider.LocalDeployerConfig{
|
||||||
OutputCertPath: fOutputCertPath,
|
OutputCertPath: fOutputCertPath,
|
||||||
OutputKeyPath: fOutputKeyPath,
|
OutputKeyPath: fOutputKeyPath,
|
||||||
})
|
})
|
||||||
@ -108,8 +108,8 @@ func Test(t *testing.T) {
|
|||||||
fmt.Sprintf("PFXPASSWORD: %v", fPfxPassword),
|
fmt.Sprintf("PFXPASSWORD: %v", fPfxPassword),
|
||||||
}, "\n"))
|
}, "\n"))
|
||||||
|
|
||||||
deployer, err := dpLocal.New(&dpLocal.LocalDeployerConfig{
|
deployer, err := provider.New(&provider.LocalDeployerConfig{
|
||||||
OutputFormat: dpLocal.OUTPUT_FORMAT_PFX,
|
OutputFormat: provider.OUTPUT_FORMAT_PFX,
|
||||||
OutputCertPath: fOutputCertPath,
|
OutputCertPath: fOutputCertPath,
|
||||||
OutputKeyPath: fOutputKeyPath,
|
OutputKeyPath: fOutputKeyPath,
|
||||||
PfxPassword: fPfxPassword,
|
PfxPassword: fPfxPassword,
|
||||||
@ -151,8 +151,8 @@ func Test(t *testing.T) {
|
|||||||
fmt.Sprintf("JKSSTOREPASS: %v", fJksStorepass),
|
fmt.Sprintf("JKSSTOREPASS: %v", fJksStorepass),
|
||||||
}, "\n"))
|
}, "\n"))
|
||||||
|
|
||||||
deployer, err := dpLocal.New(&dpLocal.LocalDeployerConfig{
|
deployer, err := provider.New(&provider.LocalDeployerConfig{
|
||||||
OutputFormat: dpLocal.OUTPUT_FORMAT_JKS,
|
OutputFormat: provider.OUTPUT_FORMAT_JKS,
|
||||||
OutputCertPath: fOutputCertPath,
|
OutputCertPath: fOutputCertPath,
|
||||||
OutputKeyPath: fOutputKeyPath,
|
OutputKeyPath: fOutputKeyPath,
|
||||||
JksAlias: fJksAlias,
|
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"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
dpSsh "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/ssh"
|
provider "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/ssh"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -64,7 +64,7 @@ func Test(t *testing.T) {
|
|||||||
fmt.Sprintf("OUTPUTKEYPATH: %v", fOutputKeyPath),
|
fmt.Sprintf("OUTPUTKEYPATH: %v", fOutputKeyPath),
|
||||||
}, "\n"))
|
}, "\n"))
|
||||||
|
|
||||||
deployer, err := dpSsh.New(&dpSsh.SshDeployerConfig{
|
deployer, err := provider.New(&provider.SshDeployerConfig{
|
||||||
SshHost: fSshHost,
|
SshHost: fSshHost,
|
||||||
SshPort: int32(fSshPort),
|
SshPort: int32(fSshPort),
|
||||||
SshUsername: fSshUsername,
|
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"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
dpWebhook "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/webhook"
|
provider "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/webhook"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -44,7 +44,7 @@ func Test(t *testing.T) {
|
|||||||
fmt.Sprintf("URL: %v", fUrl),
|
fmt.Sprintf("URL: %v", fUrl),
|
||||||
}, "\n"))
|
}, "\n"))
|
||||||
|
|
||||||
deployer, err := dpWebhook.New(&dpWebhook.WebhookDeployerConfig{
|
deployer, err := provider.New(&provider.WebhookDeployerConfig{
|
||||||
Url: fUrl,
|
Url: fUrl,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -7,7 +7,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
npEmail "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/email"
|
provider "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/email"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -64,7 +64,7 @@ func Test(t *testing.T) {
|
|||||||
fmt.Sprintf("RECEIVERADDRESS: %v", fReceiverAddress),
|
fmt.Sprintf("RECEIVERADDRESS: %v", fReceiverAddress),
|
||||||
}, "\n"))
|
}, "\n"))
|
||||||
|
|
||||||
notifier, err := npEmail.New(&npEmail.EmailNotifierConfig{
|
notifier, err := provider.New(&provider.EmailNotifierConfig{
|
||||||
SmtpHost: fSmtpHost,
|
SmtpHost: fSmtpHost,
|
||||||
SmtpPort: int32(fSmtpPort),
|
SmtpPort: int32(fSmtpPort),
|
||||||
SmtpTLS: fSmtpTLS,
|
SmtpTLS: fSmtpTLS,
|
||||||
|
@ -7,7 +7,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
npWebhook "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/webhook"
|
provider "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/webhook"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -38,7 +38,7 @@ func Test(t *testing.T) {
|
|||||||
fmt.Sprintf("URL: %v", fUrl),
|
fmt.Sprintf("URL: %v", fUrl),
|
||||||
}, "\n"))
|
}, "\n"))
|
||||||
|
|
||||||
notifier, err := npWebhook.New(&npWebhook.WebhookNotifierConfig{
|
notifier, err := provider.New(&provider.WebhookNotifierConfig{
|
||||||
Url: fUrl,
|
Url: fUrl,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user