refactor: extend qiniu sdk

This commit is contained in:
Fu Diwei
2024-10-31 11:37:03 +08:00
parent ce55365292
commit 3c3d4e9109
5 changed files with 338 additions and 251 deletions

View File

@@ -1,38 +1,53 @@
package deployer
import (
"bytes"
"context"
"encoding/json"
"fmt"
"io"
"net/http"
xerrors "github.com/pkg/errors"
"github.com/qiniu/go-sdk/v7/auth"
"github.com/usual2970/certimate/internal/domain"
xhttp "github.com/usual2970/certimate/internal/utils/http"
"github.com/usual2970/certimate/internal/pkg/core/uploader"
qiniuEx "github.com/usual2970/certimate/internal/pkg/vendors/qiniu-sdk"
)
const qiniuGateway = "http://api.qiniu.com"
type QiniuCDNDeployer struct {
option *DeployerOption
info []string
credentials *auth.Credentials
option *DeployerOption
infos []string
sdkClient *qiniuEx.Client
sslUploader uploader.Uploader
}
func NewQiniuCDNDeployer(option *DeployerOption) (*QiniuCDNDeployer, error) {
func NewQiniuCDNDeployer(option *DeployerOption) (Deployer, error) {
access := &domain.QiniuAccess{}
if err := json.Unmarshal([]byte(option.Access), access); err != nil {
return nil, fmt.Errorf("failed to get access: %w", err)
return nil, xerrors.Wrap(err, "failed to get access")
}
client, err := (&QiniuCDNDeployer{}).createSdkClient(
access.AccessKey,
access.SecretKey,
)
if err != nil {
return nil, xerrors.Wrap(err, "failed to create sdk client")
}
uploader, err := uploader.NewQiniuSSLCertUploader(&uploader.QiniuSSLCertUploaderConfig{
AccessKey: access.AccessKey,
SecretKey: access.SecretKey,
})
if err != nil {
return nil, xerrors.Wrap(err, "failed to create ssl uploader")
}
return &QiniuCDNDeployer{
option: option,
info: make([]string, 0),
credentials: auth.New(access.AccessKey, access.SecretKey),
option: option,
infos: make([]string, 0),
sdkClient: client,
sslUploader: uploader,
}, nil
}
@@ -41,176 +56,51 @@ func (d *QiniuCDNDeployer) GetID() string {
}
func (d *QiniuCDNDeployer) GetInfo() []string {
return d.info
return d.infos
}
func (d *QiniuCDNDeployer) Deploy(ctx context.Context) error {
// 上传证书
certId, err := d.uploadCert()
upres, err := d.sslUploader.Upload(ctx, d.option.Certificate.Certificate, d.option.Certificate.PrivateKey)
if err != nil {
return fmt.Errorf("uploadCert failed: %w", err)
return err
}
d.infos = append(d.infos, toStr("已上传证书", upres))
// 获取域名信息
domainInfo, err := d.getDomainInfo()
// REF: https://developer.qiniu.com/fusion/4246/the-domain-name
domain := d.option.DeployConfig.GetConfigAsString("domain")
getDomainInfoResp, err := d.sdkClient.GetDomainInfo(domain)
if err != nil {
return fmt.Errorf("getDomainInfo failed: %w", err)
return xerrors.Wrap(err, "failed to execute sdk request 'cdn.GetDomainInfo'")
}
// 判断域名是否启用 https
if domainInfo.Https != nil && domainInfo.Https.CertID != "" {
// 启用了 https
// 修改域名证书
err = d.modifyDomainCert(certId, domainInfo.Https.ForceHttps, domainInfo.Https.Http2Enable)
d.infos = append(d.infos, toStr("已获取域名信息", 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 fmt.Errorf("modifyDomainCert failed: %w", err)
return xerrors.Wrap(err, "failed to execute sdk request 'cdn.ModifyDomainHttpsConf'")
}
d.infos = append(d.infos, toStr("已修改域名证书", modifyDomainHttpsConfResp))
} else {
// 没启用 https
// 启用 https
err = d.enableHttps(certId)
enableDomainHttpsResp, err := d.sdkClient.EnableDomainHttps(domain, upres.CertId, true, true)
if err != nil {
return fmt.Errorf("enableHttps failed: %w", err)
return xerrors.Wrap(err, "failed to execute sdk request 'cdn.EnableDomainHttps'")
}
d.infos = append(d.infos, toStr("已将域名升级为 HTTPS", enableDomainHttpsResp))
}
return nil
}
func (d *QiniuCDNDeployer) enableHttps(certId string) error {
domain := d.option.DeployConfig.GetDomain()
path := fmt.Sprintf("/domain/%s/sslize", domain)
body := &qiniuModifyDomainCertReq{
CertID: certId,
ForceHttps: true,
Http2Enable: true,
}
bodyBytes, err := json.Marshal(body)
if err != nil {
return fmt.Errorf("enable https failed: %w", err)
}
_, err = d.req(qiniuGateway+path, http.MethodPut, bytes.NewReader(bodyBytes))
if err != nil {
return fmt.Errorf("enable https failed: %w", err)
}
return nil
}
type qiniuDomainInfo struct {
Https *qiniuModifyDomainCertReq `json:"https"`
}
func (d *QiniuCDNDeployer) getDomainInfo() (*qiniuDomainInfo, error) {
domain := d.option.DeployConfig.GetDomain()
path := fmt.Sprintf("/domain/%s", domain)
res, err := d.req(qiniuGateway+path, http.MethodGet, nil)
if err != nil {
return nil, fmt.Errorf("req failed: %w", err)
}
resp := &qiniuDomainInfo{}
err = json.Unmarshal(res, resp)
if err != nil {
return nil, fmt.Errorf("json.Unmarshal failed: %w", err)
}
return resp, nil
}
type qiniuUploadCertReq struct {
Name string `json:"name"`
CommonName string `json:"common_name"`
Pri string `json:"pri"`
Ca string `json:"ca"`
}
type qiniuUploadCertResp struct {
CertID string `json:"certID"`
}
func (d *QiniuCDNDeployer) uploadCert() (string, error) {
path := "/sslcert"
body := &qiniuUploadCertReq{
Name: getDeployString(d.option.DeployConfig, "domain"),
CommonName: getDeployString(d.option.DeployConfig, "domain"),
Pri: d.option.Certificate.PrivateKey,
Ca: d.option.Certificate.Certificate,
}
bodyBytes, err := json.Marshal(body)
if err != nil {
return "", fmt.Errorf("json.Marshal failed: %w", err)
}
res, err := d.req(qiniuGateway+path, http.MethodPost, bytes.NewReader(bodyBytes))
if err != nil {
return "", fmt.Errorf("req failed: %w", err)
}
resp := &qiniuUploadCertResp{}
err = json.Unmarshal(res, resp)
if err != nil {
return "", fmt.Errorf("json.Unmarshal failed: %w", err)
}
return resp.CertID, nil
}
type qiniuModifyDomainCertReq struct {
CertID string `json:"certId"`
ForceHttps bool `json:"forceHttps"`
Http2Enable bool `json:"http2Enable"`
}
func (d *QiniuCDNDeployer) modifyDomainCert(certId string, forceHttps, http2Enable bool) error {
domain := d.option.DeployConfig.GetDomain()
path := fmt.Sprintf("/domain/%s/httpsconf", domain)
body := &qiniuModifyDomainCertReq{
CertID: certId,
ForceHttps: forceHttps,
Http2Enable: http2Enable,
}
bodyBytes, err := json.Marshal(body)
if err != nil {
return fmt.Errorf("json.Marshal failed: %w", err)
}
_, err = d.req(qiniuGateway+path, http.MethodPut, bytes.NewReader(bodyBytes))
if err != nil {
return fmt.Errorf("req failed: %w", err)
}
return nil
}
func (d *QiniuCDNDeployer) req(url, method string, body io.Reader) ([]byte, error) {
req := xhttp.BuildReq(url, method, body, map[string]string{
"Content-Type": "application/json",
})
if err := d.credentials.AddToken(auth.TokenQBox, req); err != nil {
return nil, fmt.Errorf("credentials.AddToken failed: %w", err)
}
respBody, err := xhttp.ToRequest(req)
if err != nil {
return nil, fmt.Errorf("ToRequest failed: %w", err)
}
defer respBody.Close()
res, err := io.ReadAll(respBody)
if err != nil {
return nil, fmt.Errorf("io.ReadAll failed: %w", err)
}
return res, nil
func (u *QiniuCDNDeployer) createSdkClient(accessKey, secretKey string) (*qiniuEx.Client, error) {
credential := auth.New(accessKey, secretKey)
client := qiniuEx.NewClient(credential)
return client, nil
}