certimate/internal/deployer/volcengine_live.go
2024-11-21 11:23:15 +08:00

149 lines
4.4 KiB
Go

package deployer
import (
"context"
"encoding/json"
"fmt"
"regexp"
"strings"
xerrors "github.com/pkg/errors"
"github.com/usual2970/certimate/internal/domain"
"github.com/usual2970/certimate/internal/pkg/core/uploader"
volcenginelive "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/volcengine-live"
"github.com/usual2970/certimate/internal/pkg/utils/cast"
"github.com/volcengine/volc-sdk-golang/base"
live "github.com/volcengine/volc-sdk-golang/service/live/v20230101"
)
type VolcengineLiveDeployer struct {
option *DeployerOption
infos []string
sdkClient *live.Live
sslUploader uploader.Uploader
}
func NewVolcengineLiveDeployer(option *DeployerOption) (Deployer, error) {
access := &domain.VolcEngineAccess{}
if err := json.Unmarshal([]byte(option.Access), access); err != nil {
return nil, xerrors.Wrap(err, "failed to get access")
}
client := live.NewInstance()
client.SetCredential(base.Credentials{
AccessKeyID: access.AccessKeyId,
SecretAccessKey: access.SecretAccessKey,
})
uploader, err := volcenginelive.New(&volcenginelive.VolcEngineLiveUploaderConfig{
AccessKeyId: access.AccessKeyId,
AccessKeySecret: access.SecretAccessKey,
})
if err != nil {
return nil, xerrors.Wrap(err, "failed to create ssl uploader")
}
return &VolcengineLiveDeployer{
option: option,
infos: make([]string, 0),
sdkClient: client,
sslUploader: uploader,
}, nil
}
func (d *VolcengineLiveDeployer) GetID() string {
return fmt.Sprintf("%s-%s", d.option.AccessRecord.GetString("name"), d.option.AccessRecord.Id)
}
func (d *VolcengineLiveDeployer) GetInfos() []string {
return d.infos
}
func (d *VolcengineLiveDeployer) Deploy(ctx context.Context) error {
apiCtx := context.Background()
// 上传证书
upres, err := d.sslUploader.Upload(apiCtx, d.option.Certificate.Certificate, d.option.Certificate.PrivateKey)
if err != nil {
return err
}
d.infos = append(d.infos, toStr("已上传证书", upres))
domains := make([]string, 0)
configDomain := d.option.DeployConfig.GetConfigAsString("domain")
if strings.HasPrefix(configDomain, "*.") {
// 如果是泛域名,获取所有的域名并匹配
matchDomains, err := d.getDomainsByWildcardDomain(apiCtx, configDomain)
if err != nil {
d.infos = append(d.infos, toStr("获取域名列表失败", upres))
return xerrors.Wrap(err, "failed to execute sdk request 'live.ListDomainDetail'")
}
if len(matchDomains) == 0 {
return xerrors.Errorf("未查询到匹配的域名: %s", configDomain)
}
domains = matchDomains
} else {
domains = append(domains, configDomain)
}
// 部署证书
// REF: https://www.volcengine.com/docs/6469/1186278#%E7%BB%91%E5%AE%9A%E8%AF%81%E4%B9%A6d
for i := range domains {
bindCertReq := &live.BindCertBody{
ChainID: upres.CertId,
Domain: domains[i],
HTTPS: cast.BoolPtr(true),
}
bindCertResp, err := d.sdkClient.BindCert(apiCtx, bindCertReq)
if err != nil {
return xerrors.Wrap(err, "failed to execute sdk request 'live.BindCert'")
} else {
d.infos = append(d.infos, toStr(fmt.Sprintf("%s域名的证书已修改", domains[i]), bindCertResp))
}
}
return nil
}
func (d *VolcengineLiveDeployer) getDomainsByWildcardDomain(ctx context.Context, wildcardDomain string) ([]string, error) {
pageNum := int32(1)
searchTotal := 0
domains := make([]string, 0)
for {
listDomainDetailReq := &live.ListDomainDetailBody{
PageNum: pageNum,
PageSize: 1000,
}
// 查询域名列表
// 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
listDomainDetailResp, err := d.sdkClient.ListDomainDetail(ctx, listDomainDetailReq)
if err != nil {
return domains, err
}
if listDomainDetailResp.Result.DomainList != nil {
for _, item := range listDomainDetailResp.Result.DomainList {
if matchWildcardDomain(item.Domain, wildcardDomain) {
domains = append(domains, item.Domain)
}
}
}
searchTotal += len(listDomainDetailResp.Result.DomainList)
if int(listDomainDetailResp.Result.Total) > searchTotal {
pageNum++
} else {
break
}
}
return domains, nil
}
func matchWildcardDomain(domain, wildcardDomain string) bool {
if strings.HasPrefix(wildcardDomain, "*.") {
if "*."+domain == wildcardDomain {
return true
}
regexPattern := "^([a-zA-Z0-9_-]+)\\." + regexp.QuoteMeta(wildcardDomain[2:]) + "$"
regex := regexp.MustCompile(regexPattern)
return regex.MatchString(domain)
}
return domain == wildcardDomain
}