This commit is contained in:
Fu Diwei 2026-06-23 22:23:53 +08:00 committed by RHQYZ
parent ca4564a983
commit b36d6fc87b
7 changed files with 173 additions and 28 deletions

View File

@ -76,30 +76,12 @@ func (d *Deployer) Deploy(ctx context.Context, certPEM, privkeyPEM string) (*Dep
switch d.config.SiteType {
case "any":
{
// 上传证书
sslCertSaveCertReq := &btpanelsdk.SSLCertSaveCertRequest{
Certificate: certPEM,
PrivateKey: privkeyPEM,
}
sslCertSaveCertResp, err := d.sdkClient.SSLCertSaveCertWithContext(ctx, sslCertSaveCertReq)
d.logger.Debug("sdk request 'ssl.cert.SaveCert'", slog.Any("request", sslCertSaveCertReq), slog.Any("response", sslCertSaveCertResp))
if err != nil {
return nil, fmt.Errorf("failed to execute sdk request 'ssl.cert.SaveCert': %w", err)
}
// 设置站点证书
sslSetBatchCertToSiteReq := &btpanelsdk.SSLSetBatchCertToSiteRequest{
BatchInfo: lo.Map(d.config.SiteNames, func(siteName string, _ int) *btpanelsdk.SSLSetBatchCertToSiteRequestBatchInfo {
return &btpanelsdk.SSLSetBatchCertToSiteRequestBatchInfo{
SiteName: siteName,
SSLHash: sslCertSaveCertResp.SSLHash,
}
}),
}
sslSetBatchCertToSiteResp, err := d.sdkClient.SSLSetBatchCertToSiteWithContext(ctx, sslSetBatchCertToSiteReq)
d.logger.Debug("sdk request 'ssl.SetBatchCertToSite'", slog.Any("request", sslSetBatchCertToSiteReq), slog.Any("response", sslSetBatchCertToSiteResp))
if err != nil {
return nil, fmt.Errorf("failed to execute sdk request 'ssl.SetBatchCertToSite': %w", err)
// 批量更新站点证书
// 注意,如果 v1 接口不可用,则尝试使用 v2 接口重试
if err1 := d.updateSitesCertificateByAny(ctx, d.config.SiteNames, certPEM, privkeyPEM); err1 != nil {
if err2 := d.updateSitesCertificateByAnyV2(ctx, d.config.SiteNames, certPEM, privkeyPEM); err2 != nil {
return nil, errors.Join(err1, err2)
}
}
}
@ -171,6 +153,63 @@ func (d *Deployer) updateSiteCertificate(ctx context.Context, siteType, siteName
return nil
}
func (d *Deployer) updateSitesCertificateByAny(ctx context.Context, siteNames []string, certPEM, privkeyPEM string) error {
// 上传证书
sslCertSaveCertReq := &btpanelsdk.SSLCertSaveCertRequest{
Certificate: certPEM,
PrivateKey: privkeyPEM,
}
sslCertSaveCertResp, err := d.sdkClient.SSLCertSaveCertWithContext(ctx, sslCertSaveCertReq)
d.logger.Debug("sdk request 'ssl.cert.SaveCert'", slog.Any("request", sslCertSaveCertReq), slog.Any("response", sslCertSaveCertResp))
if err != nil {
return fmt.Errorf("failed to execute sdk request 'ssl.cert.SaveCert': %w", err)
}
// 设置站点证书
sslSetBatchCertToSiteReq := &btpanelsdk.SSLSetBatchCertToSiteRequest{
BatchInfo: lo.Map(siteNames, func(siteName string, _ int) *btpanelsdk.SSLSetBatchCertToSiteRequestBatchInfo {
return &btpanelsdk.SSLSetBatchCertToSiteRequestBatchInfo{
SiteName: siteName,
SSLHash: sslCertSaveCertResp.SSLHash,
}
}),
}
sslSetBatchCertToSiteResp, err := d.sdkClient.SSLSetBatchCertToSiteWithContext(ctx, sslSetBatchCertToSiteReq)
d.logger.Debug("sdk request 'ssl.SetBatchCertToSite'", slog.Any("request", sslSetBatchCertToSiteReq), slog.Any("response", sslSetBatchCertToSiteResp))
if err != nil {
return fmt.Errorf("failed to execute sdk request 'ssl.SetBatchCertToSite': %w", err)
}
return nil
}
func (d *Deployer) updateSitesCertificateByAnyV2(ctx context.Context, siteNames []string, certPEM, privkeyPEM string) error {
// 上传证书
sslDomainUploadCertV2Req := &btpanelsdk.SSLDomainUploadCertV2Request{
Certificate: certPEM,
PrivateKey: privkeyPEM,
}
sslDomainUploadCertV2Resp, err := d.sdkClient.SSLDomainUploadCertV2WithContext(ctx, sslDomainUploadCertV2Req)
d.logger.Debug("sdk request 'v2.ssldomain.UploadCert'", slog.Any("request", sslDomainUploadCertV2Req), slog.Any("response", sslDomainUploadCertV2Resp))
if err != nil {
return fmt.Errorf("failed to execute sdk request 'v2.ssldomain.UploadCert': %w", err)
}
// 设置站点证书
sslDomainCertDeploySitesV2Req := &btpanelsdk.SSLDomainCertDeploySitesV2Request{
SSLHash: sslDomainUploadCertV2Resp.Message.SSLHash,
Domains: siteNames,
Append: 1,
}
sslDomainCertDeploySitesV2Resp, err := d.sdkClient.SSLDomainCertDeploySitesV2WithContext(ctx, sslDomainCertDeploySitesV2Req)
d.logger.Debug("sdk request 'v2.ssldomain.CertDeploySites'", slog.Any("request", sslDomainCertDeploySitesV2Req), slog.Any("response", sslDomainCertDeploySitesV2Resp))
if err != nil {
return fmt.Errorf("failed to execute sdk request 'v2.ssldomain.CertDeploySites': %w", err)
}
return nil
}
func createSDKClient(serverUrl, apiKey string, skipTlsVerify bool) (*btpanelsdk.Client, error) {
client, err := btpanelsdk.NewClient(serverUrl,
btpanelsdk.WithApiKey(apiKey),

View File

@ -0,0 +1,36 @@
package btpanel
import (
"context"
"net/http"
)
type SSLDomainCertDeploySitesV2Request struct {
SSLHash string `json:"hash"`
Domains []string `json:"domains"`
Append int32 `json:"append"`
}
type SSLDomainCertDeploySitesV2Response struct {
sdkResponseBaseV2
}
func (c *Client) SSLDomainCertDeploySitesV2(req *SSLDomainCertDeploySitesV2Request) (*SSLDomainCertDeploySitesV2Response, error) {
return c.SSLDomainCertDeploySitesV2WithContext(context.Background(), req)
}
func (c *Client) SSLDomainCertDeploySitesV2WithContext(ctx context.Context, req *SSLDomainCertDeploySitesV2Request) (*SSLDomainCertDeploySitesV2Response, error) {
httpreq, err := c.newRequest(http.MethodPost, "/v2/ssl_domain?action=cert_deploy_sites", req)
if err != nil {
return nil, err
} else {
httpreq.SetContext(ctx)
}
result := &SSLDomainCertDeploySitesV2Response{}
if _, err := c.doRequestWithResult(httpreq, result); err != nil {
return result, err
}
return result, nil
}

View File

@ -0,0 +1,39 @@
package btpanel
import (
"context"
"net/http"
)
type SSLDomainUploadCertV2Request struct {
PrivateKey string `json:"key"`
Certificate string `json:"cert"`
}
type SSLDomainUploadCertV2Response struct {
sdkResponseBaseV2
Message *struct {
SSLHash string `json:"hash,omitempty"`
} `json:"message,omitempty"`
}
func (c *Client) SSLDomainUploadCertV2(req *SSLDomainUploadCertV2Request) (*SSLDomainUploadCertV2Response, error) {
return c.SSLDomainUploadCertV2WithContext(context.Background(), req)
}
func (c *Client) SSLDomainUploadCertV2WithContext(ctx context.Context, req *SSLDomainUploadCertV2Request) (*SSLDomainUploadCertV2Response, error) {
httpreq, err := c.newRequest(http.MethodPost, "/v2/ssl_domain?action=upload_cert", req)
if err != nil {
return nil, err
} else {
httpreq.SetContext(ctx)
}
result := &SSLDomainUploadCertV2Response{}
if _, err := c.doRequestWithResult(httpreq, result); err != nil {
return result, err
}
return result, nil
}

View File

@ -17,3 +17,32 @@ func (r *sdkResponseBase) GetStatus() *bool {
func (r *sdkResponseBase) GetMessage() *string {
return r.Message
}
var _ sdkResponse = (*sdkResponseBase)(nil)
type sdkResponseBaseV2 struct {
Status *int32 `json:"status,omitempty"`
Timestamp *int64 `json:"timestamp,omitempty"`
Message *struct {
Result *string `json:"result,omitempty"`
} `json:"message,omitempty"`
}
func (r *sdkResponseBaseV2) GetStatus() *bool {
if r.Status != nil {
status := *r.Status == 0
return &status
}
return nil
}
func (r *sdkResponseBaseV2) GetMessage() *string {
if r.Message != nil {
return r.Message.Result
}
return nil
}
var _ sdkResponse = (*sdkResponseBaseV2)(nil)

View File

@ -22,3 +22,5 @@ func (r *sdkResponseBase) GetStatus() json.RawMessage {
func (r *sdkResponseBase) GetMessage() *string {
return r.Message
}
var _ sdkResponse = (*sdkResponseBase)(nil)

View File

@ -1173,7 +1173,7 @@
"tooltip": "For more information, see <a href=\"https://cdnx.console.baishan.com/#/cdn/cert\" target=\"_blank\">https://cdnx.console.baishan.com/#/cdn/cert</a>"
},
"baotapanel": {
"guide": "Requires aaPanel v7.0 or higher."
"guide": "Requires aaPanel v7.0 / BaotaPanel v8.3 or higher."
},
"baotapanel_site_type": {
"label": "aaPanel website type",
@ -1204,7 +1204,7 @@
"label": "General Project"
},
"any": {
"label": "Any Project (aaPanel v7.26+)"
"label": "Any Project (aaPanel v7.26+ / BaotaPanel v9.4+)"
}
}
},

View File

@ -1172,7 +1172,7 @@
"tooltip": "这是什么?请参阅 <a href=\"https://cdnx.console.baishan.com/#/cdn/cert\" target=\"_blank\">https://cdnx.console.baishan.com/#/cdn/cert</a>"
},
"baotapanel": {
"guide": "需要宝塔面板 v8.3 或更高版本。"
"guide": "需要宝塔面板 v8.3 / aaPanel v7.0 或更高版本。"
},
"baotapanel_site_type": {
"label": "宝塔面板网站类型",
@ -1203,7 +1203,7 @@
"label": "通用项目"
},
"any": {
"label": "任意类型(需要宝塔面板 v9.4+"
"label": "任意类型(需要宝塔面板 v9.4+ / aaPanel v7.26+"
}
}
},