refactor: re-impl sdk3rd

This commit is contained in:
Fu Diwei 2025-06-17 10:39:39 +08:00
parent 9421da2cde
commit 299a722aa9
280 changed files with 6923 additions and 4658 deletions

View File

@ -6,7 +6,7 @@ import (
"github.com/go-acme/lego/v4/challenge" "github.com/go-acme/lego/v4/challenge"
"github.com/go-acme/lego/v4/providers/dns/azuredns" "github.com/go-acme/lego/v4/providers/dns/azuredns"
azcommon "github.com/usual2970/certimate/internal/pkg/sdk3rd/azure/common" azenv "github.com/usual2970/certimate/internal/pkg/sdk3rd/azure/env"
) )
type ChallengeProviderConfig struct { type ChallengeProviderConfig struct {
@ -28,7 +28,7 @@ func NewChallengeProvider(config *ChallengeProviderConfig) (challenge.Provider,
providerConfig.ClientID = config.ClientId providerConfig.ClientID = config.ClientId
providerConfig.ClientSecret = config.ClientSecret providerConfig.ClientSecret = config.ClientSecret
if config.CloudName != "" { if config.CloudName != "" {
env, err := azcommon.GetCloudEnvironmentConfiguration(config.CloudName) env, err := azenv.GetCloudEnvConfiguration(config.CloudName)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -69,8 +69,12 @@ func NewDNSProviderConfig(config *Config) (*DNSProvider, error) {
return nil, errors.New("dnsla: the configuration of the DNS provider is nil") return nil, errors.New("dnsla: the configuration of the DNS provider is nil")
} }
client := dnslasdk.NewClient(config.APIId, config.APISecret). client, err := dnslasdk.NewClient(config.APIId, config.APISecret)
WithTimeout(config.HTTPTimeout) if err != nil {
return nil, err
} else {
client.SetTimeout(config.HTTPTimeout)
}
return &DNSProvider{ return &DNSProvider{
client: client, client: client,
@ -122,13 +126,13 @@ func (d *DNSProvider) Timeout() (timeout, interval time.Duration) {
return d.config.PropagationTimeout, d.config.PollingInterval return d.config.PropagationTimeout, d.config.PollingInterval
} }
func (d *DNSProvider) getDNSZone(zoneName string) (*dnslasdk.DomainInfo, error) { func (d *DNSProvider) getDNSZone(zoneName string) (*dnslasdk.DomainRecord, error) {
pageIndex := 1 pageIndex := int32(1)
pageSize := 100 pageSize := int32(100)
for { for {
request := &dnslasdk.ListDomainsRequest{ request := &dnslasdk.ListDomainsRequest{
PageIndex: int32(pageIndex), PageIndex: &pageIndex,
PageSize: int32(pageSize), PageSize: &pageSize,
} }
response, err := d.client.ListDomains(request) response, err := d.client.ListDomains(request)
if err != nil { if err != nil {
@ -143,7 +147,7 @@ func (d *DNSProvider) getDNSZone(zoneName string) (*dnslasdk.DomainInfo, error)
} }
} }
if response.Data == nil || len(response.Data.Results) < pageSize { if response.Data == nil || len(response.Data.Results) < int(pageSize) {
break break
} }
@ -153,20 +157,20 @@ func (d *DNSProvider) getDNSZone(zoneName string) (*dnslasdk.DomainInfo, error)
return nil, fmt.Errorf("dnsla: zone %s not found", zoneName) return nil, fmt.Errorf("dnsla: zone %s not found", zoneName)
} }
func (d *DNSProvider) getDNSZoneAndRecord(zoneName, subDomain string) (*dnslasdk.DomainInfo, *dnslasdk.RecordInfo, error) { func (d *DNSProvider) getDNSZoneAndRecord(zoneName, subDomain string) (*dnslasdk.DomainRecord, *dnslasdk.DnsRecord, error) {
zone, err := d.getDNSZone(zoneName) zone, err := d.getDNSZone(zoneName)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
pageIndex := 1 pageIndex := int32(1)
pageSize := 100 pageSize := int32(100)
for { for {
request := &dnslasdk.ListRecordsRequest{ request := &dnslasdk.ListRecordsRequest{
DomainId: zone.Id, DomainId: &zone.Id,
Host: &subDomain, Host: &subDomain,
PageIndex: int32(pageIndex), PageIndex: &pageIndex,
PageSize: int32(pageSize), PageSize: &pageSize,
} }
response, err := d.client.ListRecords(request) response, err := d.client.ListRecords(request)
if err != nil { if err != nil {
@ -181,7 +185,7 @@ func (d *DNSProvider) getDNSZoneAndRecord(zoneName, subDomain string) (*dnslasdk
} }
} }
if response.Data == nil || len(response.Data.Results) < pageSize { if response.Data == nil || len(response.Data.Results) < int(pageSize) {
break break
} }
@ -231,10 +235,7 @@ func (d *DNSProvider) removeDNSRecord(zoneName, subDomain string) error {
if record == nil { if record == nil {
return nil return nil
} else { } else {
request := &dnslasdk.DeleteRecordRequest{ _, err = d.client.DeleteRecord(record.Id)
Id: record.Id,
}
_, err = d.client.DeleteRecord(request)
return err return err
} }
} }

View File

@ -10,6 +10,7 @@ import (
"github.com/go-acme/lego/v4/platform/config/env" "github.com/go-acme/lego/v4/platform/config/env"
gnamesdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/gname" gnamesdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/gname"
xtypes "github.com/usual2970/certimate/internal/pkg/utils/types"
) )
const ( const (
@ -68,8 +69,12 @@ func NewDNSProviderConfig(config *Config) (*DNSProvider, error) {
return nil, errors.New("gname: the configuration of the DNS provider is nil") return nil, errors.New("gname: the configuration of the DNS provider is nil")
} }
client := gnamesdk.NewClient(config.AppID, config.AppKey). client, err := gnamesdk.NewClient(config.AppID, config.AppKey)
WithTimeout(config.HTTPTimeout) if err != nil {
return nil, err
} else {
client.SetTimeout(config.HTTPTimeout)
}
return &DNSProvider{ return &DNSProvider{
client: client, client: client,
@ -121,14 +126,15 @@ func (d *DNSProvider) Timeout() (timeout, interval time.Duration) {
return d.config.PropagationTimeout, d.config.PollingInterval return d.config.PropagationTimeout, d.config.PollingInterval
} }
func (d *DNSProvider) findDNSRecord(zoneName, subDomain string) (*gnamesdk.ResolutionRecord, error) { func (d *DNSProvider) findDNSRecord(zoneName, subDomain string) (*gnamesdk.DomainResolutionRecordord, error) {
page := int32(1) page := int32(1)
pageSize := int32(20) pageSize := int32(20)
for { for {
request := &gnamesdk.ListDomainResolutionRequest{} request := &gnamesdk.ListDomainResolutionRequest{
request.ZoneName = zoneName ZoneName: xtypes.ToPtr(zoneName),
request.Page = &page Page: xtypes.ToPtr(page),
request.PageSize = &pageSize PageSize: xtypes.ToPtr(pageSize),
}
response, err := d.client.ListDomainResolution(request) response, err := d.client.ListDomainResolution(request)
if err != nil { if err != nil {
@ -162,23 +168,23 @@ func (d *DNSProvider) addOrUpdateDNSRecord(zoneName, subDomain, value string) er
if record == nil { if record == nil {
request := &gnamesdk.AddDomainResolutionRequest{ request := &gnamesdk.AddDomainResolutionRequest{
ZoneName: zoneName, ZoneName: xtypes.ToPtr(zoneName),
RecordType: "TXT", RecordType: xtypes.ToPtr("TXT"),
RecordName: subDomain, RecordName: xtypes.ToPtr(subDomain),
RecordValue: value, RecordValue: xtypes.ToPtr(value),
TTL: int32(d.config.TTL), TTL: xtypes.ToPtr(int32(d.config.TTL)),
} }
_, err := d.client.AddDomainResolution(request) _, err := d.client.AddDomainResolution(request)
return err return err
} else { } else {
recordId, _ := record.ID.Int64() recordId, _ := record.ID.Int64()
request := &gnamesdk.ModifyDomainResolutionRequest{ request := &gnamesdk.ModifyDomainResolutionRequest{
ID: recordId, ID: xtypes.ToPtr(recordId),
ZoneName: zoneName, ZoneName: xtypes.ToPtr(zoneName),
RecordType: "TXT", RecordType: xtypes.ToPtr("TXT"),
RecordName: subDomain, RecordName: xtypes.ToPtr(subDomain),
RecordValue: value, RecordValue: xtypes.ToPtr(value),
TTL: int32(d.config.TTL), TTL: xtypes.ToPtr(int32(d.config.TTL)),
} }
_, err := d.client.ModifyDomainResolution(request) _, err := d.client.ModifyDomainResolution(request)
return err return err
@ -197,8 +203,8 @@ func (d *DNSProvider) removeDNSRecord(zoneName, subDomain string) error {
recordId, _ := record.ID.Int64() recordId, _ := record.ID.Int64()
request := &gnamesdk.DeleteDomainResolutionRequest{ request := &gnamesdk.DeleteDomainResolutionRequest{
ZoneName: zoneName, ZoneName: xtypes.ToPtr(zoneName),
RecordID: recordId, RecordID: xtypes.ToPtr(recordId),
} }
_, err = d.client.DeleteDomainResolution(request) _, err = d.client.DeleteDomainResolution(request)
return err return err

View File

@ -71,6 +71,7 @@ func NewDNSProviderConfig(config *Config) (*DNSProvider, error) {
} }
cfg := ucloud.NewConfig() cfg := ucloud.NewConfig()
cfg.Timeout = config.HTTPTimeout
credential := auth.NewCredential() credential := auth.NewCredential()
credential.PrivateKey = config.PrivateKey credential.PrivateKey = config.PrivateKey
credential.PublicKey = config.PublicKey credential.PublicKey = config.PublicKey

View File

@ -3,13 +3,13 @@ package onepanelconsole
import ( import (
"context" "context"
"crypto/tls" "crypto/tls"
"errors"
"fmt" "fmt"
"log/slog" "log/slog"
"net/url" "strconv"
"github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/deployer"
onepanelsdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/1panel" onepanelsdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/1panel"
onepanelsdkv2 "github.com/usual2970/certimate/internal/pkg/sdk3rd/1panel/v2"
) )
type DeployerConfig struct { type DeployerConfig struct {
@ -29,7 +29,7 @@ type DeployerConfig struct {
type DeployerProvider struct { type DeployerProvider struct {
config *DeployerConfig config *DeployerConfig
logger *slog.Logger logger *slog.Logger
sdkClient *onepanelsdk.Client sdkClient any
} }
var _ deployer.Deployer = (*DeployerProvider)(nil) var _ deployer.Deployer = (*DeployerProvider)(nil)
@ -62,48 +62,75 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer {
func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) {
// 设置面板 SSL 证书 // 设置面板 SSL 证书
SSLEnable := "enable" switch sdkClient := d.sdkClient.(type) {
if d.config.ApiVersion == "v2" { case *onepanelsdk.Client:
SSLEnable = "Enable" {
} updateSettingsSSLReq := &onepanelsdk.UpdateSettingsSSLRequest{
Cert: certPEM,
Key: privkeyPEM,
SSL: "enable",
SSLType: "import-paste",
AutoRestart: strconv.FormatBool(d.config.AutoRestart),
}
updateSystemSSLResp, err := sdkClient.UpdateSettingsSSL(updateSettingsSSLReq)
d.logger.Debug("sdk request '1panel.UpdateSettingsSSL'", slog.Any("request", updateSettingsSSLReq), slog.Any("response", updateSystemSSLResp))
if err != nil {
return nil, fmt.Errorf("failed to execute sdk request '1panel.UpdateSettingsSSL': %w", err)
}
}
updateSystemSSLReq := &onepanelsdk.UpdateSystemSSLRequest{ case *onepanelsdkv2.Client:
Cert: certPEM, {
Key: privkeyPEM, updateCoreSettingsSSLReq := &onepanelsdkv2.UpdateCoreSettingsSSLRequest{
SSL: SSLEnable, Cert: certPEM,
SSLType: "import-paste", Key: privkeyPEM,
} SSL: "Enable",
if d.config.AutoRestart { SSLType: "import-paste",
updateSystemSSLReq.AutoRestart = "true" AutoRestart: strconv.FormatBool(d.config.AutoRestart),
} else { }
updateSystemSSLReq.AutoRestart = "false" updateCoreSystemSSLResp, err := sdkClient.UpdateCoreSettingsSSL(updateCoreSettingsSSLReq)
} d.logger.Debug("sdk request '1panel.UpdateCoreSettingsSSL'", slog.Any("request", updateCoreSettingsSSLReq), slog.Any("response", updateCoreSystemSSLResp))
updateSystemSSLResp, err := d.sdkClient.UpdateSystemSSL(updateSystemSSLReq) if err != nil {
d.logger.Debug("sdk request '1panel.UpdateSystemSSL'", slog.Any("request", updateSystemSSLReq), slog.Any("response", updateSystemSSLResp)) return nil, fmt.Errorf("failed to execute sdk request '1panel.UpdateCoreSettingsSSL': %w", err)
if err != nil { }
return nil, fmt.Errorf("failed to execute sdk request '1panel.UpdateSystemSSL': %w", err) }
default:
panic("sdk client is not implemented")
} }
return &deployer.DeployResult{}, nil return &deployer.DeployResult{}, nil
} }
func createSdkClient(serverUrl, apiVersion, apiKey string, skipTlsVerify bool) (*onepanelsdk.Client, error) { const (
if _, err := url.Parse(serverUrl); err != nil { sdkVersionV1 = "v1"
return nil, errors.New("invalid 1panel server url") sdkVersionV2 = "v2"
)
func createSdkClient(serverUrl, apiVersion, apiKey string, skipTlsVerify bool) (any, error) {
if apiVersion == sdkVersionV1 {
client, err := onepanelsdk.NewClient(serverUrl, apiKey)
if err != nil {
return nil, err
}
if skipTlsVerify {
client.SetTLSConfig(&tls.Config{InsecureSkipVerify: true})
}
return client, nil
} else if apiVersion == sdkVersionV2 {
client, err := onepanelsdkv2.NewClient(serverUrl, apiKey)
if err != nil {
return nil, err
}
if skipTlsVerify {
client.SetTLSConfig(&tls.Config{InsecureSkipVerify: true})
}
return client, nil
} }
if apiVersion == "" { return nil, fmt.Errorf("invalid 1panel api version")
return nil, errors.New("invalid 1panel api version")
}
if apiKey == "" {
return nil, errors.New("invalid 1panel api key")
}
client := onepanelsdk.NewClient(serverUrl, apiVersion, apiKey)
if skipTlsVerify {
client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true})
}
return client, nil
} }

View File

@ -6,13 +6,13 @@ import (
"errors" "errors"
"fmt" "fmt"
"log/slog" "log/slog"
"net/url"
"strconv" "strconv"
"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"
uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/1panel-ssl" uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/1panel-ssl"
onepanelsdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/1panel" onepanelsdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/1panel"
onepanelsdkv2 "github.com/usual2970/certimate/internal/pkg/sdk3rd/1panel/v2"
) )
type DeployerConfig struct { type DeployerConfig struct {
@ -38,7 +38,7 @@ type DeployerConfig struct {
type DeployerProvider struct { type DeployerProvider struct {
config *DeployerConfig config *DeployerConfig
logger *slog.Logger logger *slog.Logger
sdkClient *onepanelsdk.Client sdkClient any
sslUploader uploader.Uploader sslUploader uploader.Uploader
} }
@ -107,16 +107,6 @@ func (d *DeployerProvider) deployToWebsite(ctx context.Context, certPEM string,
return errors.New("config `websiteId` is required") return errors.New("config `websiteId` is required")
} }
// 获取网站 HTTPS 配置
getHttpsConfReq := &onepanelsdk.GetHttpsConfRequest{
WebsiteID: d.config.WebsiteId,
}
getHttpsConfResp, err := d.sdkClient.GetHttpsConf(getHttpsConfReq)
d.logger.Debug("sdk request '1panel.GetHttpsConf'", slog.Any("request", getHttpsConfReq), slog.Any("response", getHttpsConfResp))
if err != nil {
return fmt.Errorf("failed to execute sdk request '1panel.GetHttpsConf': %w", err)
}
// 上传证书到面板 // 上传证书到面板
upres, err := d.sslUploader.Upload(ctx, certPEM, privkeyPEM) upres, err := d.sslUploader.Upload(ctx, certPEM, privkeyPEM)
if err != nil { if err != nil {
@ -125,22 +115,65 @@ func (d *DeployerProvider) deployToWebsite(ctx context.Context, certPEM string,
d.logger.Info("ssl certificate uploaded", slog.Any("result", upres)) d.logger.Info("ssl certificate uploaded", slog.Any("result", upres))
} }
// 修改网站 HTTPS 配置 switch sdkClient := d.sdkClient.(type) {
certId, _ := strconv.ParseInt(upres.CertId, 10, 64) case *onepanelsdk.Client:
updateHttpsConfReq := &onepanelsdk.UpdateHttpsConfRequest{ {
WebsiteID: d.config.WebsiteId, // 获取网站 HTTPS 配置
Type: "existed", getHttpsConfResp, err := sdkClient.GetHttpsConf(d.config.WebsiteId)
WebsiteSSLID: certId, d.logger.Debug("sdk request '1panel.GetHttpsConf'", slog.Int64("websiteId", d.config.WebsiteId), slog.Any("response", getHttpsConfResp))
Enable: getHttpsConfResp.Data.Enable, if err != nil {
HttpConfig: getHttpsConfResp.Data.HttpConfig, return fmt.Errorf("failed to execute sdk request '1panel.GetHttpsConf': %w", err)
SSLProtocol: getHttpsConfResp.Data.SSLProtocol, }
Algorithm: getHttpsConfResp.Data.Algorithm,
Hsts: getHttpsConfResp.Data.Hsts, // 修改网站 HTTPS 配置
} certId, _ := strconv.ParseInt(upres.CertId, 10, 64)
updateHttpsConfResp, err := d.sdkClient.UpdateHttpsConf(updateHttpsConfReq) updateHttpsConfReq := &onepanelsdk.UpdateHttpsConfRequest{
d.logger.Debug("sdk request '1panel.UpdateHttpsConf'", slog.Any("request", updateHttpsConfReq), slog.Any("response", updateHttpsConfResp)) WebsiteID: d.config.WebsiteId,
if err != nil { Type: "existed",
return fmt.Errorf("failed to execute sdk request '1panel.UpdateHttpsConf': %w", err) WebsiteSSLID: certId,
Enable: getHttpsConfResp.Data.Enable,
HttpConfig: getHttpsConfResp.Data.HttpConfig,
SSLProtocol: getHttpsConfResp.Data.SSLProtocol,
Algorithm: getHttpsConfResp.Data.Algorithm,
Hsts: getHttpsConfResp.Data.Hsts,
}
updateHttpsConfResp, err := sdkClient.UpdateHttpsConf(d.config.WebsiteId, updateHttpsConfReq)
d.logger.Debug("sdk request '1panel.UpdateHttpsConf'", slog.Int64("websiteId", d.config.WebsiteId), slog.Any("request", updateHttpsConfReq), slog.Any("response", updateHttpsConfResp))
if err != nil {
return fmt.Errorf("failed to execute sdk request '1panel.UpdateHttpsConf': %w", err)
}
}
case *onepanelsdkv2.Client:
{
// 获取网站 HTTPS 配置
getHttpsConfResp, err := sdkClient.GetHttpsConf(d.config.WebsiteId)
d.logger.Debug("sdk request '1panel.GetHttpsConf'", slog.Int64("websiteId", d.config.WebsiteId), slog.Any("response", getHttpsConfResp))
if err != nil {
return fmt.Errorf("failed to execute sdk request '1panel.GetHttpsConf': %w", err)
}
// 修改网站 HTTPS 配置
certId, _ := strconv.ParseInt(upres.CertId, 10, 64)
updateHttpsConfReq := &onepanelsdkv2.UpdateHttpsConfRequest{
WebsiteID: d.config.WebsiteId,
Type: "existed",
WebsiteSSLID: certId,
Enable: getHttpsConfResp.Data.Enable,
HttpConfig: getHttpsConfResp.Data.HttpConfig,
SSLProtocol: getHttpsConfResp.Data.SSLProtocol,
Algorithm: getHttpsConfResp.Data.Algorithm,
Hsts: getHttpsConfResp.Data.Hsts,
}
updateHttpsConfResp, err := sdkClient.UpdateHttpsConf(d.config.WebsiteId, updateHttpsConfReq)
d.logger.Debug("sdk request '1panel.UpdateHttpsConf'", slog.Int64("websiteId", d.config.WebsiteId), slog.Any("request", updateHttpsConfReq), slog.Any("response", updateHttpsConfResp))
if err != nil {
return fmt.Errorf("failed to execute sdk request '1panel.UpdateHttpsConf': %w", err)
}
}
default:
panic("sdk client is not implemented")
} }
return nil return nil
@ -151,50 +184,91 @@ func (d *DeployerProvider) deployToCertificate(ctx context.Context, certPEM stri
return errors.New("config `certificateId` is required") return errors.New("config `certificateId` is required")
} }
// 获取证书详情 switch sdkClient := d.sdkClient.(type) {
getWebsiteSSLReq := &onepanelsdk.GetWebsiteSSLRequest{ case *onepanelsdk.Client:
SSLID: d.config.CertificateId, {
} // 获取证书详情
getWebsiteSSLResp, err := d.sdkClient.GetWebsiteSSL(getWebsiteSSLReq) getWebsiteSSLResp, err := sdkClient.GetWebsiteSSL(d.config.CertificateId)
d.logger.Debug("sdk request '1panel.GetWebsiteSSL'", slog.Any("request", getWebsiteSSLReq), slog.Any("response", getWebsiteSSLResp)) d.logger.Debug("sdk request '1panel.GetWebsiteSSL'", slog.Any("sslId", d.config.CertificateId), slog.Any("response", getWebsiteSSLResp))
if err != nil { if err != nil {
return fmt.Errorf("failed to execute sdk request '1panel.GetWebsiteSSL': %w", err) return fmt.Errorf("failed to execute sdk request '1panel.GetWebsiteSSL': %w", err)
} }
// 更新证书 // 更新证书
uploadWebsiteSSLReq := &onepanelsdk.UploadWebsiteSSLRequest{ uploadWebsiteSSLReq := &onepanelsdk.UploadWebsiteSSLRequest{
Type: "paste", SSLID: d.config.CertificateId,
SSLID: d.config.CertificateId, Type: "paste",
Description: getWebsiteSSLResp.Data.Description, Description: getWebsiteSSLResp.Data.Description,
Certificate: certPEM, Certificate: certPEM,
PrivateKey: privkeyPEM, PrivateKey: privkeyPEM,
} }
uploadWebsiteSSLResp, err := d.sdkClient.UploadWebsiteSSL(uploadWebsiteSSLReq) uploadWebsiteSSLResp, err := sdkClient.UploadWebsiteSSL(uploadWebsiteSSLReq)
d.logger.Debug("sdk request '1panel.UploadWebsiteSSL'", slog.Any("request", uploadWebsiteSSLReq), slog.Any("response", uploadWebsiteSSLResp)) d.logger.Debug("sdk request '1panel.UploadWebsiteSSL'", slog.Any("request", uploadWebsiteSSLReq), slog.Any("response", uploadWebsiteSSLResp))
if err != nil { if err != nil {
return fmt.Errorf("failed to execute sdk request '1panel.UploadWebsiteSSL': %w", err) return fmt.Errorf("failed to execute sdk request '1panel.UploadWebsiteSSL': %w", err)
}
}
case *onepanelsdkv2.Client:
{
// 获取证书详情
getWebsiteSSLResp, err := sdkClient.GetWebsiteSSL(d.config.CertificateId)
d.logger.Debug("sdk request '1panel.GetWebsiteSSL'", slog.Any("sslId", d.config.CertificateId), slog.Any("response", getWebsiteSSLResp))
if err != nil {
return fmt.Errorf("failed to execute sdk request '1panel.GetWebsiteSSL': %w", err)
}
// 更新证书
uploadWebsiteSSLReq := &onepanelsdkv2.UploadWebsiteSSLRequest{
SSLID: d.config.CertificateId,
Type: "paste",
Description: getWebsiteSSLResp.Data.Description,
Certificate: certPEM,
PrivateKey: privkeyPEM,
}
uploadWebsiteSSLResp, err := sdkClient.UploadWebsiteSSL(uploadWebsiteSSLReq)
d.logger.Debug("sdk request '1panel.UploadWebsiteSSL'", slog.Any("request", uploadWebsiteSSLReq), slog.Any("response", uploadWebsiteSSLResp))
if err != nil {
return fmt.Errorf("failed to execute sdk request '1panel.UploadWebsiteSSL': %w", err)
}
}
default:
panic("sdk client is not implemented")
} }
return nil return nil
} }
func createSdkClient(serverUrl, apiVersion, apiKey string, skipTlsVerify bool) (*onepanelsdk.Client, error) { const (
if _, err := url.Parse(serverUrl); err != nil { sdkVersionV1 = "v1"
return nil, errors.New("invalid 1panel server url") sdkVersionV2 = "v2"
)
func createSdkClient(serverUrl, apiVersion, apiKey string, skipTlsVerify bool) (any, error) {
if apiVersion == sdkVersionV1 {
client, err := onepanelsdk.NewClient(serverUrl, apiKey)
if err != nil {
return nil, err
}
if skipTlsVerify {
client.SetTLSConfig(&tls.Config{InsecureSkipVerify: true})
}
return client, nil
} else if apiVersion == sdkVersionV2 {
client, err := onepanelsdkv2.NewClient(serverUrl, apiKey)
if err != nil {
return nil, err
}
if skipTlsVerify {
client.SetTLSConfig(&tls.Config{InsecureSkipVerify: true})
}
return client, nil
} }
if apiVersion == "" { return nil, fmt.Errorf("invalid 1panel api version")
return nil, errors.New("invalid 1panel api version")
}
if apiKey == "" {
return nil, errors.New("invalid 1panel api key")
}
client := onepanelsdk.NewClient(serverUrl, apiVersion, apiKey)
if skipTlsVerify {
client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true})
}
return client, nil
} }

View File

@ -6,7 +6,6 @@ import (
"errors" "errors"
"fmt" "fmt"
"log/slog" "log/slog"
"net/url"
"github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/deployer"
apisixsdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/apisix" apisixsdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/apisix"
@ -91,15 +90,14 @@ func (d *DeployerProvider) deployToCertificate(ctx context.Context, certPEM stri
// 更新 SSL 证书 // 更新 SSL 证书
// REF: https://apisix.apache.org/zh/docs/apisix/admin-api/#ssl // REF: https://apisix.apache.org/zh/docs/apisix/admin-api/#ssl
updateSSLReq := &apisixsdk.UpdateSSLRequest{ updateSSLReq := &apisixsdk.UpdateSSLRequest{
ID: d.config.CertificateId,
Cert: xtypes.ToPtr(certPEM), Cert: xtypes.ToPtr(certPEM),
Key: xtypes.ToPtr(privkeyPEM), Key: xtypes.ToPtr(privkeyPEM),
SNIs: xtypes.ToPtr(certX509.DNSNames), SNIs: xtypes.ToPtr(certX509.DNSNames),
Type: xtypes.ToPtr("server"), Type: xtypes.ToPtr("server"),
Status: xtypes.ToPtr(int32(1)), Status: xtypes.ToPtr(int32(1)),
} }
updateSSLResp, err := d.sdkClient.UpdateSSL(updateSSLReq) updateSSLResp, err := d.sdkClient.UpdateSSL(d.config.CertificateId, updateSSLReq)
d.logger.Debug("sdk request 'apisix.UpdateSSL'", slog.Any("request", updateSSLReq), slog.Any("response", updateSSLResp)) d.logger.Debug("sdk request 'apisix.UpdateSSL'", slog.String("sslId", d.config.CertificateId), slog.Any("request", updateSSLReq), slog.Any("response", updateSSLResp))
if err != nil { if err != nil {
return fmt.Errorf("failed to execute sdk request 'apisix.UpdateSSL': %w", err) return fmt.Errorf("failed to execute sdk request 'apisix.UpdateSSL': %w", err)
} }
@ -108,17 +106,13 @@ func (d *DeployerProvider) deployToCertificate(ctx context.Context, certPEM stri
} }
func createSdkClient(serverUrl, apiKey string, skipTlsVerify bool) (*apisixsdk.Client, error) { func createSdkClient(serverUrl, apiKey string, skipTlsVerify bool) (*apisixsdk.Client, error) {
if _, err := url.Parse(serverUrl); err != nil { client, err := apisixsdk.NewClient(serverUrl, apiKey)
return nil, errors.New("invalid apisix server url") if err != nil {
return nil, err
} }
if apiKey == "" {
return nil, errors.New("invalid apisix api key")
}
client := apisixsdk.NewClient(serverUrl, apiKey)
if skipTlsVerify { if skipTlsVerify {
client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true}) client.SetTLSConfig(&tls.Config{InsecureSkipVerify: true})
} }
return client, nil return client, nil

View File

@ -16,7 +16,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"
uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/azure-keyvault" uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/azure-keyvault"
azcommon "github.com/usual2970/certimate/internal/pkg/sdk3rd/azure/common" azenv "github.com/usual2970/certimate/internal/pkg/sdk3rd/azure/env"
xcert "github.com/usual2970/certimate/internal/pkg/utils/cert" xcert "github.com/usual2970/certimate/internal/pkg/utils/cert"
) )
@ -149,7 +149,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPE
} }
func createSdkClient(tenantId, clientId, clientSecret, cloudName, keyvaultName string) (*azcertificates.Client, error) { func createSdkClient(tenantId, clientId, clientSecret, cloudName, keyvaultName string) (*azcertificates.Client, error) {
env, err := azcommon.GetCloudEnvironmentConfiguration(cloudName) env, err := azenv.GetCloudEnvConfiguration(cloudName)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -162,9 +162,9 @@ func createSdkClient(tenantId, clientId, clientSecret, cloudName, keyvaultName s
} }
endpoint := fmt.Sprintf("https://%s.vault.azure.net", keyvaultName) endpoint := fmt.Sprintf("https://%s.vault.azure.net", keyvaultName)
if azcommon.IsEnvironmentGovernment(cloudName) { if azenv.IsUSGovernmentEnv(cloudName) {
endpoint = fmt.Sprintf("https://%s.vault.usgovcloudapi.net", keyvaultName) endpoint = fmt.Sprintf("https://%s.vault.usgovcloudapi.net", keyvaultName)
} else if azcommon.IsEnvironmentChina(cloudName) { } else if azenv.IsChinaEnv(cloudName) {
endpoint = fmt.Sprintf("https://%s.vault.azure.cn", keyvaultName) endpoint = fmt.Sprintf("https://%s.vault.azure.cn", keyvaultName)
} }

View File

@ -12,6 +12,7 @@ import (
"github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/deployer"
bssdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/baishan" bssdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/baishan"
xtypes "github.com/usual2970/certimate/internal/pkg/utils/types"
) )
type DeployerConfig struct { type DeployerConfig struct {
@ -68,34 +69,34 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPE
// 新增证书 // 新增证书
// REF: https://portal.baishancloud.com/track/document/downloadPdf/1441 // REF: https://portal.baishancloud.com/track/document/downloadPdf/1441
certificateId := "" certificateId := ""
createCertificateReq := &bssdk.CreateCertificateRequest{ setDomainCertificateReq := &bssdk.SetDomainCertificateRequest{
Certificate: certPEM, Name: xtypes.ToPtr(fmt.Sprintf("certimate_%d", time.Now().UnixMilli())),
Key: privkeyPEM, Certificate: xtypes.ToPtr(certPEM),
Name: fmt.Sprintf("certimate_%d", time.Now().UnixMilli()), Key: xtypes.ToPtr(privkeyPEM),
} }
createCertificateResp, err := d.sdkClient.CreateCertificate(createCertificateReq) setDomainCertificateResp, err := d.sdkClient.SetDomainCertificate(setDomainCertificateReq)
d.logger.Debug("sdk request 'baishan.CreateCertificate'", slog.Any("request", createCertificateReq), slog.Any("response", createCertificateResp)) d.logger.Debug("sdk request 'baishan.SetDomainCertificate'", slog.Any("request", setDomainCertificateReq), slog.Any("response", setDomainCertificateResp))
if err != nil { if err != nil {
if createCertificateResp != nil { if setDomainCertificateResp != nil {
if createCertificateResp.GetCode() == 400699 && strings.Contains(createCertificateResp.GetMessage(), "this certificate is exists") { if setDomainCertificateResp.GetCode() == 400699 && strings.Contains(setDomainCertificateResp.GetMessage(), "this certificate is exists") {
// 证书已存在,忽略新增证书接口错误 // 证书已存在,忽略新增证书接口错误
re := regexp.MustCompile(`\d+`) re := regexp.MustCompile(`\d+`)
certificateId = re.FindString(createCertificateResp.GetMessage()) certificateId = re.FindString(setDomainCertificateResp.GetMessage())
} }
} }
if certificateId == "" { if certificateId == "" {
return nil, fmt.Errorf("failed to execute sdk request 'baishan.CreateCertificate': %w", err) return nil, fmt.Errorf("failed to execute sdk request 'baishan.SetDomainCertificate': %w", err)
} }
} else { } else {
certificateId = createCertificateResp.Data.CertId.String() certificateId = setDomainCertificateResp.Data.CertId.String()
} }
// 查询域名配置 // 查询域名配置
// REF: https://portal.baishancloud.com/track/document/api/1/1065 // REF: https://portal.baishancloud.com/track/document/api/1/1065
getDomainConfigReq := &bssdk.GetDomainConfigRequest{ getDomainConfigReq := &bssdk.GetDomainConfigRequest{
Domains: d.config.Domain, Domains: xtypes.ToPtr(d.config.Domain),
Config: []string{"https"}, Config: xtypes.ToPtr([]string{"https"}),
} }
getDomainConfigResp, err := d.sdkClient.GetDomainConfig(getDomainConfigReq) getDomainConfigResp, err := d.sdkClient.GetDomainConfig(getDomainConfigReq)
d.logger.Debug("sdk request 'baishan.GetDomainConfig'", slog.Any("request", getDomainConfigReq), slog.Any("response", getDomainConfigResp)) d.logger.Debug("sdk request 'baishan.GetDomainConfig'", slog.Any("request", getDomainConfigReq), slog.Any("response", getDomainConfigResp))
@ -108,7 +109,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPE
// 设置域名配置 // 设置域名配置
// REF: https://portal.baishancloud.com/track/document/api/1/1045 // REF: https://portal.baishancloud.com/track/document/api/1/1045
setDomainConfigReq := &bssdk.SetDomainConfigRequest{ setDomainConfigReq := &bssdk.SetDomainConfigRequest{
Domains: d.config.Domain, Domains: xtypes.ToPtr(d.config.Domain),
Config: &bssdk.DomainConfig{ Config: &bssdk.DomainConfig{
Https: &bssdk.DomainConfigHttps{ Https: &bssdk.DomainConfigHttps{
CertId: json.Number(certificateId), CertId: json.Number(certificateId),
@ -126,16 +127,16 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPE
} else { } else {
// 替换证书 // 替换证书
// REF: https://portal.baishancloud.com/track/document/downloadPdf/1441 // REF: https://portal.baishancloud.com/track/document/downloadPdf/1441
createCertificateReq := &bssdk.CreateCertificateRequest{ setDomainCertificateReq := &bssdk.SetDomainCertificateRequest{
CertificateId: &d.config.CertificateId, CertificateId: &d.config.CertificateId,
Certificate: certPEM, Name: xtypes.ToPtr(fmt.Sprintf("certimate_%d", time.Now().UnixMilli())),
Key: privkeyPEM, Certificate: xtypes.ToPtr(certPEM),
Name: fmt.Sprintf("certimate_%d", time.Now().UnixMilli()), Key: xtypes.ToPtr(privkeyPEM),
} }
createCertificateResp, err := d.sdkClient.CreateCertificate(createCertificateReq) setDomainCertificateResp, err := d.sdkClient.SetDomainCertificate(setDomainCertificateReq)
d.logger.Debug("sdk request 'baishan.CreateCertificate'", slog.Any("request", createCertificateReq), slog.Any("response", createCertificateResp)) d.logger.Debug("sdk request 'baishan.SetDomainCertificate'", slog.Any("request", setDomainCertificateReq), slog.Any("response", setDomainCertificateResp))
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to execute sdk request 'baishan.CreateCertificate': %w", err) return nil, fmt.Errorf("failed to execute sdk request 'baishan.SetDomainCertificate': %w", err)
} }
} }
@ -143,10 +144,5 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPE
} }
func createSdkClient(apiToken string) (*bssdk.Client, error) { func createSdkClient(apiToken string) (*bssdk.Client, error) {
if apiToken == "" { return bssdk.NewClient(apiToken)
return nil, errors.New("invalid baishan api token")
}
client := bssdk.NewClient(apiToken)
return client, nil
} }

View File

@ -3,10 +3,8 @@ package baotapanelconsole
import ( import (
"context" "context"
"crypto/tls" "crypto/tls"
"errors"
"fmt" "fmt"
"log/slog" "log/slog"
"net/url"
"github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/deployer"
btsdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/btpanel" btsdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/btpanel"
@ -83,17 +81,13 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPE
} }
func createSdkClient(serverUrl, apiKey string, skipTlsVerify bool) (*btsdk.Client, error) { func createSdkClient(serverUrl, apiKey string, skipTlsVerify bool) (*btsdk.Client, error) {
if _, err := url.Parse(serverUrl); err != nil { client, err := btsdk.NewClient(serverUrl, apiKey)
return nil, errors.New("invalid baota server url") if err != nil {
return nil, err
} }
if apiKey == "" {
return nil, errors.New("invalid baota api key")
}
client := btsdk.NewClient(serverUrl, apiKey)
if skipTlsVerify { if skipTlsVerify {
client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true}) client.SetTLSConfig(&tls.Config{InsecureSkipVerify: true})
} }
return client, nil return client, nil

View File

@ -6,7 +6,6 @@ import (
"errors" "errors"
"fmt" "fmt"
"log/slog" "log/slog"
"net/url"
"github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/deployer"
btsdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/btpanel" btsdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/btpanel"
@ -125,17 +124,13 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPE
} }
func createSdkClient(serverUrl, apiKey string, skipTlsVerify bool) (*btsdk.Client, error) { func createSdkClient(serverUrl, apiKey string, skipTlsVerify bool) (*btsdk.Client, error) {
if _, err := url.Parse(serverUrl); err != nil { client, err := btsdk.NewClient(serverUrl, apiKey)
return nil, errors.New("invalid baota server url") if err != nil {
return nil, err
} }
if apiKey == "" {
return nil, errors.New("invalid baota api key")
}
client := btsdk.NewClient(serverUrl, apiKey)
if skipTlsVerify { if skipTlsVerify {
client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true}) client.SetTLSConfig(&tls.Config{InsecureSkipVerify: true})
} }
return client, nil return client, nil

View File

@ -3,13 +3,12 @@ package baotapanelconsole
import ( import (
"context" "context"
"crypto/tls" "crypto/tls"
"errors"
"fmt" "fmt"
"log/slog" "log/slog"
"net/url"
"github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/deployer"
btsdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/btwaf" btwafsdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/btwaf"
xtypes "github.com/usual2970/certimate/internal/pkg/utils/types"
) )
type DeployerConfig struct { type DeployerConfig struct {
@ -24,7 +23,7 @@ type DeployerConfig struct {
type DeployerProvider struct { type DeployerProvider struct {
config *DeployerConfig config *DeployerConfig
logger *slog.Logger logger *slog.Logger
sdkClient *btsdk.Client sdkClient *btwafsdk.Client
} }
var _ deployer.Deployer = (*DeployerProvider)(nil) var _ deployer.Deployer = (*DeployerProvider)(nil)
@ -57,31 +56,27 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer {
func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) {
// 设置面板 SSL // 设置面板 SSL
configSetSSLReq := &btsdk.ConfigSetSSLRequest{ configSetCertReq := &btwafsdk.ConfigSetCertRequest{
CertContent: certPEM, CertContent: xtypes.ToPtr(certPEM),
KeyContent: privkeyPEM, KeyContent: xtypes.ToPtr(privkeyPEM),
} }
configSetSSLResp, err := d.sdkClient.ConfigSetSSL(configSetSSLReq) configSetCertResp, err := d.sdkClient.ConfigSetCert(configSetCertReq)
d.logger.Debug("sdk request 'bt.ConfigSetSSL'", slog.Any("request", configSetSSLReq), slog.Any("response", configSetSSLResp)) d.logger.Debug("sdk request 'bt.ConfigSetCert'", slog.Any("request", configSetCertReq), slog.Any("response", configSetCertResp))
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to execute sdk request 'bt.ConfigSetSSL': %w", err) return nil, fmt.Errorf("failed to execute sdk request 'bt.ConfigSetCert': %w", err)
} }
return &deployer.DeployResult{}, nil return &deployer.DeployResult{}, nil
} }
func createSdkClient(serverUrl, apiKey string, skipTlsVerify bool) (*btsdk.Client, error) { func createSdkClient(serverUrl, apiKey string, skipTlsVerify bool) (*btwafsdk.Client, error) {
if _, err := url.Parse(serverUrl); err != nil { client, err := btwafsdk.NewClient(serverUrl, apiKey)
return nil, errors.New("invalid baota server url") if err != nil {
return nil, err
} }
if apiKey == "" {
return nil, errors.New("invalid baota api key")
}
client := btsdk.NewClient(serverUrl, apiKey)
if skipTlsVerify { if skipTlsVerify {
client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true}) client.SetTLSConfig(&tls.Config{InsecureSkipVerify: true})
} }
return client, nil return client, nil

View File

@ -6,10 +6,9 @@ import (
"errors" "errors"
"fmt" "fmt"
"log/slog" "log/slog"
"net/url"
"github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/deployer"
btsdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/btwaf" btwafsdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/btwaf"
xtypes "github.com/usual2970/certimate/internal/pkg/utils/types" xtypes "github.com/usual2970/certimate/internal/pkg/utils/types"
) )
@ -30,7 +29,7 @@ type DeployerConfig struct {
type DeployerProvider struct { type DeployerProvider struct {
config *DeployerConfig config *DeployerConfig
logger *slog.Logger logger *slog.Logger
sdkClient *btsdk.Client sdkClient *btwafsdk.Client
} }
var _ deployer.Deployer = (*DeployerProvider)(nil) var _ deployer.Deployer = (*DeployerProvider)(nil)
@ -81,7 +80,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPE
default: default:
} }
getSiteListReq := &btsdk.GetSiteListRequest{ getSiteListReq := &btwafsdk.GetSiteListRequest{
SiteName: xtypes.ToPtr(d.config.SiteName), SiteName: xtypes.ToPtr(d.config.SiteName),
Page: xtypes.ToPtr(getSitListPage), Page: xtypes.ToPtr(getSitListPage),
PageSize: xtypes.ToPtr(getSitListPageSize), PageSize: xtypes.ToPtr(getSitListPageSize),
@ -112,12 +111,12 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPE
} }
// 修改站点配置 // 修改站点配置
modifySiteReq := &btsdk.ModifySiteRequest{ modifySiteReq := &btwafsdk.ModifySiteRequest{
SiteId: siteId, SiteId: xtypes.ToPtr(siteId),
Type: xtypes.ToPtr("openCert"), Type: xtypes.ToPtr("openCert"),
Server: &btsdk.SiteServerInfo{ Server: &btwafsdk.SiteServerInfo{
ListenSSLPorts: xtypes.ToPtr([]int32{d.config.SitePort}), ListenSSLPorts: xtypes.ToPtr([]int32{d.config.SitePort}),
SSL: &btsdk.SiteServerSSLInfo{ SSL: &btwafsdk.SiteServerSSLInfo{
IsSSL: xtypes.ToPtr(int32(1)), IsSSL: xtypes.ToPtr(int32(1)),
FullChain: xtypes.ToPtr(certPEM), FullChain: xtypes.ToPtr(certPEM),
PrivateKey: xtypes.ToPtr(privkeyPEM), PrivateKey: xtypes.ToPtr(privkeyPEM),
@ -133,18 +132,14 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPE
return &deployer.DeployResult{}, nil return &deployer.DeployResult{}, nil
} }
func createSdkClient(serverUrl, apiKey string, skipTlsVerify bool) (*btsdk.Client, error) { func createSdkClient(serverUrl, apiKey string, skipTlsVerify bool) (*btwafsdk.Client, error) {
if _, err := url.Parse(serverUrl); err != nil { client, err := btwafsdk.NewClient(serverUrl, apiKey)
return nil, errors.New("invalid baota server url") if err != nil {
return nil, err
} }
if apiKey == "" {
return nil, errors.New("invalid baota api key")
}
client := btsdk.NewClient(serverUrl, apiKey)
if skipTlsVerify { if skipTlsVerify {
client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true}) client.SetTLSConfig(&tls.Config{InsecureSkipVerify: true})
} }
return client, nil return client, nil

View File

@ -32,10 +32,15 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
panic("config is nil") panic("config is nil")
} }
client, err := createSdkClient(config.ApiKey)
if err != nil {
return nil, fmt.Errorf("failed to create sdk client: %w", err)
}
return &DeployerProvider{ return &DeployerProvider{
config: config, config: config,
logger: slog.Default(), logger: slog.Default(),
sdkClient: bunnysdk.NewClient(config.ApiKey), sdkClient: client,
}, nil }, nil
} }
@ -49,18 +54,25 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer {
} }
func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) {
if d.config.PullZoneId == "" {
return nil, fmt.Errorf("config `pullZoneId` is required")
}
// 上传证书 // 上传证书
createCertificateReq := &bunnysdk.AddCustomCertificateRequest{ createCertificateReq := &bunnysdk.AddCustomCertificateRequest{
Hostname: d.config.Hostname, Hostname: d.config.Hostname,
PullZoneId: d.config.PullZoneId,
Certificate: base64.StdEncoding.EncodeToString([]byte(certPEM)), Certificate: base64.StdEncoding.EncodeToString([]byte(certPEM)),
CertificateKey: base64.StdEncoding.EncodeToString([]byte(privkeyPEM)), CertificateKey: base64.StdEncoding.EncodeToString([]byte(privkeyPEM)),
} }
createCertificateResp, err := d.sdkClient.AddCustomCertificate(createCertificateReq) err := d.sdkClient.AddCustomCertificate(d.config.PullZoneId, createCertificateReq)
d.logger.Debug("sdk request 'bunny.AddCustomCertificate'", slog.Any("request", createCertificateReq), slog.Any("response", createCertificateResp)) d.logger.Debug("sdk request 'bunny.AddCustomCertificate'", slog.Any("request", createCertificateReq))
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to execute sdk request 'bunny.AddCustomCertificate': %w", err) return nil, fmt.Errorf("failed to execute sdk request 'bunny.AddCustomCertificate': %w", err)
} }
return &deployer.DeployResult{}, nil return &deployer.DeployResult{}, nil
} }
func createSdkClient(apiKey string) (*bunnysdk.Client, error) {
return bunnysdk.NewClient(apiKey)
}

View File

@ -2,12 +2,12 @@ package cachefly
import ( import (
"context" "context"
"errors"
"fmt" "fmt"
"log/slog" "log/slog"
"github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/deployer"
cfsdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/cachefly" cacheflysdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/cachefly"
xtypes "github.com/usual2970/certimate/internal/pkg/utils/types"
) )
type DeployerConfig struct { type DeployerConfig struct {
@ -18,7 +18,7 @@ type DeployerConfig struct {
type DeployerProvider struct { type DeployerProvider struct {
config *DeployerConfig config *DeployerConfig
logger *slog.Logger logger *slog.Logger
sdkClient *cfsdk.Client sdkClient *cacheflysdk.Client
} }
var _ deployer.Deployer = (*DeployerProvider)(nil) var _ deployer.Deployer = (*DeployerProvider)(nil)
@ -52,9 +52,9 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer {
func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) {
// 上传证书 // 上传证书
// REF: https://api.cachefly.com/api/2.5/docs#tag/Certificates/paths/~1certificates/post // REF: https://api.cachefly.com/api/2.5/docs#tag/Certificates/paths/~1certificates/post
createCertificateReq := &cfsdk.CreateCertificateRequest{ createCertificateReq := &cacheflysdk.CreateCertificateRequest{
Certificate: certPEM, Certificate: xtypes.ToPtr(certPEM),
CertificateKey: privkeyPEM, CertificateKey: xtypes.ToPtr(privkeyPEM),
} }
createCertificateResp, err := d.sdkClient.CreateCertificate(createCertificateReq) createCertificateResp, err := d.sdkClient.CreateCertificate(createCertificateReq)
d.logger.Debug("sdk request 'cachefly.CreateCertificate'", slog.Any("request", createCertificateReq), slog.Any("response", createCertificateResp)) d.logger.Debug("sdk request 'cachefly.CreateCertificate'", slog.Any("request", createCertificateReq), slog.Any("response", createCertificateResp))
@ -65,11 +65,6 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPE
return &deployer.DeployResult{}, nil return &deployer.DeployResult{}, nil
} }
func createSdkClient(apiToken string) (*cfsdk.Client, error) { func createSdkClient(apiToken string) (*cacheflysdk.Client, error) {
if apiToken == "" { return cacheflysdk.NewClient(apiToken)
return nil, errors.New("invalid cachefly api token")
}
client := cfsdk.NewClient(apiToken)
return client, nil
} }

View File

@ -7,11 +7,11 @@ import (
"errors" "errors"
"fmt" "fmt"
"log/slog" "log/slog"
"net/url"
"time" "time"
"github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/deployer"
cfsdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/cdnfly" cdnflysdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/cdnfly"
xtypes "github.com/usual2970/certimate/internal/pkg/utils/types"
) )
type DeployerConfig struct { type DeployerConfig struct {
@ -36,7 +36,7 @@ type DeployerConfig struct {
type DeployerProvider struct { type DeployerProvider struct {
config *DeployerConfig config *DeployerConfig
logger *slog.Logger logger *slog.Logger
sdkClient *cfsdk.Client sdkClient *cdnflysdk.Client
} }
var _ deployer.Deployer = (*DeployerProvider)(nil) var _ deployer.Deployer = (*DeployerProvider)(nil)
@ -94,27 +94,24 @@ func (d *DeployerProvider) deployToSite(ctx context.Context, certPEM string, pri
// 获取单个网站详情 // 获取单个网站详情
// REF: https://doc.cdnfly.cn/wangzhanguanli-v1-sites.html#%E8%8E%B7%E5%8F%96%E5%8D%95%E4%B8%AA%E7%BD%91%E7%AB%99%E8%AF%A6%E6%83%85 // REF: https://doc.cdnfly.cn/wangzhanguanli-v1-sites.html#%E8%8E%B7%E5%8F%96%E5%8D%95%E4%B8%AA%E7%BD%91%E7%AB%99%E8%AF%A6%E6%83%85
getSiteReq := &cfsdk.GetSiteRequest{ getSiteResp, err := d.sdkClient.GetSite(d.config.SiteId)
Id: d.config.SiteId, d.logger.Debug("sdk request 'cdnfly.GetSite'", slog.Any("siteId", d.config.SiteId), slog.Any("response", getSiteResp))
}
getSiteResp, err := d.sdkClient.GetSite(getSiteReq)
d.logger.Debug("sdk request 'cdnfly.GetSite'", slog.Any("request", getSiteReq), slog.Any("response", getSiteResp))
if err != nil { if err != nil {
return fmt.Errorf("failed to execute sdk request 'cdnfly.GetSite': %w", err) return fmt.Errorf("failed to execute sdk request 'cdnfly.GetSite': %w", err)
} }
// 添加单个证书 // 添加单个证书
// REF: https://doc.cdnfly.cn/wangzhanzhengshu-v1-certs.html#%E6%B7%BB%E5%8A%A0%E5%8D%95%E4%B8%AA%E6%88%96%E5%A4%9A%E4%B8%AA%E8%AF%81%E4%B9%A6-%E5%A4%9A%E4%B8%AA%E8%AF%81%E4%B9%A6%E6%97%B6%E6%95%B0%E6%8D%AE%E6%A0%BC%E5%BC%8F%E4%B8%BA%E6%95%B0%E7%BB%84 // REF: https://doc.cdnfly.cn/wangzhanzhengshu-v1-certs.html#%E6%B7%BB%E5%8A%A0%E5%8D%95%E4%B8%AA%E6%88%96%E5%A4%9A%E4%B8%AA%E8%AF%81%E4%B9%A6-%E5%A4%9A%E4%B8%AA%E8%AF%81%E4%B9%A6%E6%97%B6%E6%95%B0%E6%8D%AE%E6%A0%BC%E5%BC%8F%E4%B8%BA%E6%95%B0%E7%BB%84
createCertificateReq := &cfsdk.CreateCertificateRequest{ createCertificateReq := &cdnflysdk.CreateCertRequest{
Name: fmt.Sprintf("certimate-%d", time.Now().UnixMilli()), Name: xtypes.ToPtr(fmt.Sprintf("certimate-%d", time.Now().UnixMilli())),
Type: "custom", Type: xtypes.ToPtr("custom"),
Cert: certPEM, Cert: xtypes.ToPtr(certPEM),
Key: privkeyPEM, Key: xtypes.ToPtr(privkeyPEM),
} }
createCertificateResp, err := d.sdkClient.CreateCertificate(createCertificateReq) createCertificateResp, err := d.sdkClient.CreateCert(createCertificateReq)
d.logger.Debug("sdk request 'cdnfly.CreateCertificate'", slog.Any("request", createCertificateReq), slog.Any("response", createCertificateResp)) d.logger.Debug("sdk request 'cdnfly.CreateCert'", slog.Any("request", createCertificateReq), slog.Any("response", createCertificateResp))
if err != nil { if err != nil {
return fmt.Errorf("failed to execute sdk request 'cdnfly.CreateCertificate': %w", err) return fmt.Errorf("failed to execute sdk request 'cdnfly.CreateCert': %w", err)
} }
// 修改单个网站 // 修改单个网站
@ -123,13 +120,11 @@ func (d *DeployerProvider) deployToSite(ctx context.Context, certPEM string, pri
_ = json.Unmarshal([]byte(getSiteResp.Data.HttpsListen), &updateSiteHttpsListenMap) _ = json.Unmarshal([]byte(getSiteResp.Data.HttpsListen), &updateSiteHttpsListenMap)
updateSiteHttpsListenMap["cert"] = createCertificateResp.Data updateSiteHttpsListenMap["cert"] = createCertificateResp.Data
updateSiteHttpsListenData, _ := json.Marshal(updateSiteHttpsListenMap) updateSiteHttpsListenData, _ := json.Marshal(updateSiteHttpsListenMap)
updateSiteHttpsListen := string(updateSiteHttpsListenData) updateSiteReq := &cdnflysdk.UpdateSiteRequest{
updateSiteReq := &cfsdk.UpdateSiteRequest{ HttpsListen: xtypes.ToPtr(string(updateSiteHttpsListenData)),
Id: d.config.SiteId,
HttpsListen: &updateSiteHttpsListen,
} }
updateSiteResp, err := d.sdkClient.UpdateSite(updateSiteReq) updateSiteResp, err := d.sdkClient.UpdateSite(d.config.SiteId, updateSiteReq)
d.logger.Debug("sdk request 'cdnfly.UpdateSite'", slog.Any("request", updateSiteReq), slog.Any("response", updateSiteResp)) d.logger.Debug("sdk request 'cdnfly.UpdateSite'", slog.String("siteId", d.config.SiteId), slog.Any("request", updateSiteReq), slog.Any("response", updateSiteResp))
if err != nil { if err != nil {
return fmt.Errorf("failed to execute sdk request 'cdnfly.UpdateSite': %w", err) return fmt.Errorf("failed to execute sdk request 'cdnfly.UpdateSite': %w", err)
} }
@ -144,38 +139,28 @@ func (d *DeployerProvider) deployToCertificate(ctx context.Context, certPEM stri
// 修改单个证书 // 修改单个证书
// REF: https://doc.cdnfly.cn/wangzhanzhengshu-v1-certs.html#%E4%BF%AE%E6%94%B9%E5%8D%95%E4%B8%AA%E8%AF%81%E4%B9%A6 // REF: https://doc.cdnfly.cn/wangzhanzhengshu-v1-certs.html#%E4%BF%AE%E6%94%B9%E5%8D%95%E4%B8%AA%E8%AF%81%E4%B9%A6
updateCertificateType := "custom" updateCertReq := &cdnflysdk.UpdateCertRequest{
updateCertificateReq := &cfsdk.UpdateCertificateRequest{ Type: xtypes.ToPtr("custom"),
Id: d.config.CertificateId, Cert: xtypes.ToPtr(certPEM),
Type: &updateCertificateType, Key: xtypes.ToPtr(privkeyPEM),
Cert: &certPEM,
Key: &privkeyPEM,
} }
updateCertificateResp, err := d.sdkClient.UpdateCertificate(updateCertificateReq) updateCertResp, err := d.sdkClient.UpdateCert(d.config.CertificateId, updateCertReq)
d.logger.Debug("sdk request 'cdnfly.UpdateCertificate'", slog.Any("request", updateCertificateReq), slog.Any("response", updateCertificateResp)) d.logger.Debug("sdk request 'cdnfly.UpdateCert'", slog.String("certId", d.config.CertificateId), slog.Any("request", updateCertReq), slog.Any("response", updateCertResp))
if err != nil { if err != nil {
return fmt.Errorf("failed to execute sdk request 'cdnfly.UpdateCertificate': %w", err) return fmt.Errorf("failed to execute sdk request 'cdnfly.UpdateCert': %w", err)
} }
return nil return nil
} }
func createSdkClient(serverUrl, apiKey, apiSecret string, skipTlsVerify bool) (*cfsdk.Client, error) { func createSdkClient(serverUrl, apiKey, apiSecret string, skipTlsVerify bool) (*cdnflysdk.Client, error) {
if _, err := url.Parse(serverUrl); err != nil { client, err := cdnflysdk.NewClient(serverUrl, apiKey, apiSecret)
return nil, errors.New("invalid cachefly server url") if err != nil {
return nil, err
} }
if apiKey == "" {
return nil, errors.New("invalid cachefly api key")
}
if apiSecret == "" {
return nil, errors.New("invalid cachefly api secret")
}
client := cfsdk.NewClient(serverUrl, apiKey, apiSecret)
if skipTlsVerify { if skipTlsVerify {
client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true}) client.SetTLSConfig(&tls.Config{InsecureSkipVerify: true})
} }
return client, nil return client, nil

View File

@ -35,7 +35,10 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
panic("config is nil") panic("config is nil")
} }
client := dogesdk.NewClient(config.AccessKey, config.SecretKey) client, err := createSdkClient(config.AccessKey, config.SecretKey)
if err != nil {
return nil, fmt.Errorf("failed to create sdk client: %w", err)
}
uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{
AccessKey: config.AccessKey, AccessKey: config.AccessKey,
@ -64,6 +67,10 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer {
} }
func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) {
if d.config.Domain == "" {
return nil, fmt.Errorf("config `domain` is required")
}
// 上传证书到 CDN // 上传证书到 CDN
upres, err := d.sslUploader.Upload(ctx, certPEM, privkeyPEM) upres, err := d.sslUploader.Upload(ctx, certPEM, privkeyPEM)
if err != nil { if err != nil {
@ -75,11 +82,19 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPE
// 绑定证书 // 绑定证书
// REF: https://docs.dogecloud.com/cdn/api-cert-bind // REF: https://docs.dogecloud.com/cdn/api-cert-bind
bindCdnCertId, _ := strconv.ParseInt(upres.CertId, 10, 64) bindCdnCertId, _ := strconv.ParseInt(upres.CertId, 10, 64)
bindCdnCertResp, err := d.sdkClient.BindCdnCertWithDomain(bindCdnCertId, d.config.Domain) bindCdnCertReq := &dogesdk.BindCdnCertRequest{
d.logger.Debug("sdk request 'cdn.BindCdnCert'", slog.Int64("request.certId", bindCdnCertId), slog.String("request.domain", d.config.Domain), slog.Any("response", bindCdnCertResp)) CertId: bindCdnCertId,
Domain: d.config.Domain,
}
bindCdnCertResp, err := d.sdkClient.BindCdnCert(bindCdnCertReq)
d.logger.Debug("sdk request 'cdn.BindCdnCert'", slog.Any("request", bindCdnCertReq), slog.Any("response", bindCdnCertResp))
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to execute sdk request 'cdn.BindCdnCert': %w", err) return nil, fmt.Errorf("failed to execute sdk request 'cdn.BindCdnCert': %w", err)
} }
return &deployer.DeployResult{}, nil return &deployer.DeployResult{}, nil
} }
func createSdkClient(accessKey, secretKey string) (*dogesdk.Client, error) {
return dogesdk.NewClient(accessKey, secretKey)
}

View File

@ -7,7 +7,6 @@ import (
"errors" "errors"
"fmt" "fmt"
"log/slog" "log/slog"
"net/url"
"time" "time"
"github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/deployer"
@ -120,25 +119,13 @@ func (d *DeployerProvider) deployToCertificate(ctx context.Context, certPEM stri
} }
func createSdkClient(serverUrl, apiRole, accessKeyId, accessKey string, skipTlsVerify bool) (*flexcdnsdk.Client, error) { func createSdkClient(serverUrl, apiRole, accessKeyId, accessKey string, skipTlsVerify bool) (*flexcdnsdk.Client, error) {
if _, err := url.Parse(serverUrl); err != nil { client, err := flexcdnsdk.NewClient(serverUrl, apiRole, accessKeyId, accessKey)
return nil, errors.New("invalid flexcdn server url") if err != nil {
return nil, err
} }
if apiRole != "user" && apiRole != "admin" {
return nil, errors.New("invalid flexcdn api role")
}
if accessKeyId == "" {
return nil, errors.New("invalid flexcdn access key id")
}
if accessKey == "" {
return nil, errors.New("invalid flexcdn access key")
}
client := flexcdnsdk.NewClient(serverUrl, apiRole, accessKeyId, accessKey)
if skipTlsVerify { if skipTlsVerify {
client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true}) client.SetTLSConfig(&tls.Config{InsecureSkipVerify: true})
} }
return client, nil return client, nil

View File

@ -15,7 +15,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"
uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/gcore-cdn" uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/gcore-cdn"
gcoresdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/gcore/common" gcoresdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/gcore"
) )
type DeployerConfig struct { type DeployerConfig struct {

View File

@ -7,7 +7,6 @@ import (
"errors" "errors"
"fmt" "fmt"
"log/slog" "log/slog"
"net/url"
"time" "time"
"github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/deployer"
@ -120,25 +119,13 @@ func (d *DeployerProvider) deployToCertificate(ctx context.Context, certPEM stri
} }
func createSdkClient(serverUrl, apiRole, accessKeyId, accessKey string, skipTlsVerify bool) (*goedgesdk.Client, error) { func createSdkClient(serverUrl, apiRole, accessKeyId, accessKey string, skipTlsVerify bool) (*goedgesdk.Client, error) {
if _, err := url.Parse(serverUrl); err != nil { client, err := goedgesdk.NewClient(serverUrl, apiRole, accessKeyId, accessKey)
return nil, errors.New("invalid goedge server url") if err != nil {
return nil, err
} }
if apiRole != "user" && apiRole != "admin" {
return nil, errors.New("invalid goedge api role")
}
if accessKeyId == "" {
return nil, errors.New("invalid goedge access key id")
}
if accessKey == "" {
return nil, errors.New("invalid goedge access key")
}
client := goedgesdk.NewClient(serverUrl, apiRole, accessKeyId, accessKey)
if skipTlsVerify { if skipTlsVerify {
client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true}) client.SetTLSConfig(&tls.Config{InsecureSkipVerify: true})
} }
return client, nil return client, nil

View File

@ -6,12 +6,11 @@ import (
"errors" "errors"
"fmt" "fmt"
"log/slog" "log/slog"
"net/url"
"time" "time"
"github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/deployer"
leclientsdkv3 "github.com/usual2970/certimate/internal/pkg/sdk3rd/lecdn/v3/client" leclientsdkv3 "github.com/usual2970/certimate/internal/pkg/sdk3rd/lecdn/client-v3"
lemastersdkv3 "github.com/usual2970/certimate/internal/pkg/sdk3rd/lecdn/v3/master" lemastersdkv3 "github.com/usual2970/certimate/internal/pkg/sdk3rd/lecdn/master-v3"
) )
type DeployerConfig struct { type DeployerConfig struct {
@ -42,18 +41,11 @@ type DeployerConfig struct {
type DeployerProvider struct { type DeployerProvider struct {
config *DeployerConfig config *DeployerConfig
logger *slog.Logger logger *slog.Logger
sdkClient interface{} sdkClient any
} }
var _ deployer.Deployer = (*DeployerProvider)(nil) var _ deployer.Deployer = (*DeployerProvider)(nil)
const (
apiVersionV3 = "v3"
apiRoleClient = "client"
apiRoleMaster = "master"
)
func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
if config == nil { if config == nil {
panic("config is nil") panic("config is nil")
@ -104,34 +96,38 @@ func (d *DeployerProvider) deployToCertificate(ctx context.Context, certPEM stri
// REF: https://wdk0pwf8ul.feishu.cn/wiki/YE1XwCRIHiLYeKkPupgcXrlgnDd // REF: https://wdk0pwf8ul.feishu.cn/wiki/YE1XwCRIHiLYeKkPupgcXrlgnDd
switch sdkClient := d.sdkClient.(type) { switch sdkClient := d.sdkClient.(type) {
case *leclientsdkv3.Client: case *leclientsdkv3.Client:
updateSSLCertReq := &leclientsdkv3.UpdateCertificateRequest{ {
Name: fmt.Sprintf("certimate-%d", time.Now().UnixMilli()), updateSSLCertReq := &leclientsdkv3.UpdateCertificateRequest{
Description: "upload from certimate", Name: fmt.Sprintf("certimate-%d", time.Now().UnixMilli()),
Type: "upload", Description: "upload from certimate",
SSLPEM: certPEM, Type: "upload",
SSLKey: privkeyPEM, SSLPEM: certPEM,
AutoRenewal: false, SSLKey: privkeyPEM,
} AutoRenewal: false,
updateSSLCertResp, err := sdkClient.UpdateCertificate(d.config.CertificateId, updateSSLCertReq) }
d.logger.Debug("sdk request 'lecdn.UpdateCertificate'", slog.Int64("certId", d.config.CertificateId), slog.Any("request", updateSSLCertReq), slog.Any("response", updateSSLCertResp)) updateSSLCertResp, err := sdkClient.UpdateCertificate(d.config.CertificateId, updateSSLCertReq)
if err != nil { d.logger.Debug("sdk request 'lecdn.UpdateCertificate'", slog.Int64("certId", d.config.CertificateId), slog.Any("request", updateSSLCertReq), slog.Any("response", updateSSLCertResp))
return fmt.Errorf("failed to execute sdk request 'lecdn.UpdateCertificate': %w", err) if err != nil {
return fmt.Errorf("failed to execute sdk request 'lecdn.UpdateCertificate': %w", err)
}
} }
case *lemastersdkv3.Client: case *lemastersdkv3.Client:
updateSSLCertReq := &lemastersdkv3.UpdateCertificateRequest{ {
ClientId: d.config.ClientId, updateSSLCertReq := &lemastersdkv3.UpdateCertificateRequest{
Name: fmt.Sprintf("certimate-%d", time.Now().UnixMilli()), ClientId: d.config.ClientId,
Description: "upload from certimate", Name: fmt.Sprintf("certimate-%d", time.Now().UnixMilli()),
Type: "upload", Description: "upload from certimate",
SSLPEM: certPEM, Type: "upload",
SSLKey: privkeyPEM, SSLPEM: certPEM,
AutoRenewal: false, SSLKey: privkeyPEM,
} AutoRenewal: false,
updateSSLCertResp, err := sdkClient.UpdateCertificate(d.config.CertificateId, updateSSLCertReq) }
d.logger.Debug("sdk request 'lecdn.UpdateCertificate'", slog.Int64("certId", d.config.CertificateId), slog.Any("request", updateSSLCertReq), slog.Any("response", updateSSLCertResp)) updateSSLCertResp, err := sdkClient.UpdateCertificate(d.config.CertificateId, updateSSLCertReq)
if err != nil { d.logger.Debug("sdk request 'lecdn.UpdateCertificate'", slog.Int64("certId", d.config.CertificateId), slog.Any("request", updateSSLCertReq), slog.Any("response", updateSSLCertResp))
return fmt.Errorf("failed to execute sdk request 'lecdn.UpdateCertificate': %w", err) if err != nil {
return fmt.Errorf("failed to execute sdk request 'lecdn.UpdateCertificate': %w", err)
}
} }
default: default:
@ -141,32 +137,35 @@ func (d *DeployerProvider) deployToCertificate(ctx context.Context, certPEM stri
return nil return nil
} }
func createSdkClient(serverUrl, apiVersion, apiRole, username, password string, skipTlsVerify bool) (interface{}, error) { const (
if _, err := url.Parse(serverUrl); err != nil { sdkVersionV3 = "v3"
return nil, errors.New("invalid lecdn server url")
}
if username == "" { sdkRoleClient = "client"
return nil, errors.New("invalid lecdn username") sdkRoleMaster = "master"
} )
if password == "" { func createSdkClient(serverUrl, apiVersion, apiRole, username, password string, skipTlsVerify bool) (any, error) {
return nil, errors.New("invalid lecdn password") if apiVersion == sdkVersionV3 && apiRole == sdkRoleClient {
}
if apiVersion == apiVersionV3 && apiRole == apiRoleClient {
// v3 版客户端 // v3 版客户端
client := leclientsdkv3.NewClient(serverUrl, username, password) client, err := leclientsdkv3.NewClient(serverUrl, username, password)
if err != nil {
return nil, err
}
if skipTlsVerify { if skipTlsVerify {
client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true}) client.SetTLSConfig(&tls.Config{InsecureSkipVerify: true})
} }
return client, nil return client, nil
} else if apiVersion == apiVersionV3 && apiRole == apiRoleMaster { } else if apiVersion == sdkVersionV3 && apiRole == sdkRoleMaster {
// v3 版主控端 // v3 版主控端
client := lemastersdkv3.NewClient(serverUrl, username, password) client, err := lemastersdkv3.NewClient(serverUrl, username, password)
if err != nil {
return nil, err
}
if skipTlsVerify { if skipTlsVerify {
client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true}) client.SetTLSConfig(&tls.Config{InsecureSkipVerify: true})
} }
return client, nil return client, nil

View File

@ -80,10 +80,5 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPE
} }
func createSdkClient(apiToken string) (*netlifysdk.Client, error) { func createSdkClient(apiToken string) (*netlifysdk.Client, error) {
if apiToken == "" { return netlifysdk.NewClient(apiToken)
return nil, errors.New("invalid netlify api token")
}
client := netlifysdk.NewClient(apiToken)
return client, nil
} }

View File

@ -15,7 +15,7 @@ var (
fInputCertPath string fInputCertPath string
fInputKeyPath string fInputKeyPath string
fApiToken string fApiToken string
fSiteId int64 fSiteId string
) )
func init() { func init() {
@ -24,7 +24,7 @@ func init() {
flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "") flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "")
flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "") flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "")
flag.StringVar(&fApiToken, argsPrefix+"APITOKEN", "", "") flag.StringVar(&fApiToken, argsPrefix+"APITOKEN", "", "")
flag.Int64Var(&fSiteId, argsPrefix+"SITEID", 0, "") flag.StringVar(&fSiteId, argsPrefix+"SITEID", "", "")
} }
/* /*

View File

@ -26,7 +26,7 @@ type DeployerConfig struct {
type DeployerProvider struct { type DeployerProvider struct {
config *DeployerConfig config *DeployerConfig
logger *slog.Logger logger *slog.Logger
sdkClient *qiniusdk.Client sdkClient *qiniusdk.CdnManager
sslUploader uploader.Uploader sslUploader uploader.Uploader
} }
@ -37,7 +37,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
panic("config is nil") panic("config is nil")
} }
client := qiniusdk.NewClient(auth.New(config.AccessKey, config.SecretKey)) client := qiniusdk.NewCdnManager(auth.New(config.AccessKey, config.SecretKey))
uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{
AccessKey: config.AccessKey, AccessKey: config.AccessKey,

View File

@ -2,7 +2,6 @@ package rainyunrcdn
import ( import (
"context" "context"
"errors"
"fmt" "fmt"
"log/slog" "log/slog"
"strconv" "strconv"
@ -92,10 +91,5 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPE
} }
func createSdkClient(apiKey string) (*rainyunsdk.Client, error) { func createSdkClient(apiKey string) (*rainyunsdk.Client, error) {
if apiKey == "" { return rainyunsdk.NewClient(apiKey)
return nil, errors.New("invalid rainyun api key")
}
client := rainyunsdk.NewClient(apiKey)
return client, nil
} }

View File

@ -53,8 +53,8 @@ func TestDeploy(t *testing.T) {
}, "\n")) }, "\n"))
deployer, err := provider.NewDeployer(&provider.DeployerConfig{ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
PrivateKey: fApiKey, ApiKey: fApiKey,
InstanceId: fInstanceId, InstanceId: int32(fInstanceId),
Domain: fDomain, Domain: fDomain,
}) })
if err != nil { if err != nil {

View File

@ -3,10 +3,8 @@ package ratpanelconsole
import ( import (
"context" "context"
"crypto/tls" "crypto/tls"
"errors"
"fmt" "fmt"
"log/slog" "log/slog"
"net/url"
"github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/deployer"
rpsdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/ratpanel" rpsdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/ratpanel"
@ -59,35 +57,27 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer {
func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) {
// 设置面板 SSL 证书 // 设置面板 SSL 证书
settingCertReq := &rpsdk.SettingCertRequest{ setSettingCertReq := &rpsdk.SetSettingCertRequest{
Certificate: certPEM, Certificate: certPEM,
PrivateKey: privkeyPEM, PrivateKey: privkeyPEM,
} }
settingCertResp, err := d.sdkClient.SettingCert(settingCertReq) setSettingCertResp, err := d.sdkClient.SetSettingCert(setSettingCertReq)
d.logger.Debug("sdk request 'ratpanel.SettingCert'", slog.Any("request", settingCertReq), slog.Any("response", settingCertResp)) d.logger.Debug("sdk request 'ratpanel.SetSettingCert'", slog.Any("request", setSettingCertReq), slog.Any("response", setSettingCertResp))
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to execute sdk request 'ratpanel.SettingCert': %w", err) return nil, fmt.Errorf("failed to execute sdk request 'ratpanel.SetSettingCert': %w", err)
} }
return &deployer.DeployResult{}, nil return &deployer.DeployResult{}, nil
} }
func createSdkClient(serverUrl string, accessTokenId int32, accessToken string, skipTlsVerify bool) (*rpsdk.Client, error) { func createSdkClient(serverUrl string, accessTokenId int32, accessToken string, skipTlsVerify bool) (*rpsdk.Client, error) {
if _, err := url.Parse(serverUrl); err != nil { client, err := rpsdk.NewClient(serverUrl, accessTokenId, accessToken)
return nil, errors.New("invalid ratpanel server url") if err != nil {
return nil, err
} }
if accessTokenId == 0 {
return nil, errors.New("invalid ratpanel access token id")
}
if accessToken == "" {
return nil, errors.New("invalid ratpanel access token")
}
client := rpsdk.NewClient(serverUrl, accessTokenId, accessToken)
if skipTlsVerify { if skipTlsVerify {
client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true}) client.SetTLSConfig(&tls.Config{InsecureSkipVerify: true})
} }
return client, nil return client, nil

View File

@ -6,7 +6,6 @@ import (
"errors" "errors"
"fmt" "fmt"
"log/slog" "log/slog"
"net/url"
"github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/deployer"
rpsdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/ratpanel" rpsdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/ratpanel"
@ -65,36 +64,28 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPE
} }
// 设置站点 SSL 证书 // 设置站点 SSL 证书
websiteCertReq := &rpsdk.WebsiteCertRequest{ setWebsiteCertReq := &rpsdk.SetWebsiteCertRequest{
SiteName: d.config.SiteName, SiteName: d.config.SiteName,
Certificate: certPEM, Certificate: certPEM,
PrivateKey: privkeyPEM, PrivateKey: privkeyPEM,
} }
websiteCertResp, err := d.sdkClient.WebsiteCert(websiteCertReq) setWebsiteCertResp, err := d.sdkClient.SetWebsiteCert(setWebsiteCertReq)
d.logger.Debug("sdk request 'ratpanel.WebsiteCert'", slog.Any("request", websiteCertReq), slog.Any("response", websiteCertResp)) d.logger.Debug("sdk request 'ratpanel.SetWebsiteCert'", slog.Any("request", setWebsiteCertReq), slog.Any("response", setWebsiteCertResp))
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to execute sdk request 'ratpanel.WebsiteCert': %w", err) return nil, fmt.Errorf("failed to execute sdk request 'ratpanel.SetWebsiteCert': %w", err)
} }
return &deployer.DeployResult{}, nil return &deployer.DeployResult{}, nil
} }
func createSdkClient(serverUrl string, accessTokenId int32, accessToken string, skipTlsVerify bool) (*rpsdk.Client, error) { func createSdkClient(serverUrl string, accessTokenId int32, accessToken string, skipTlsVerify bool) (*rpsdk.Client, error) {
if _, err := url.Parse(serverUrl); err != nil { client, err := rpsdk.NewClient(serverUrl, accessTokenId, accessToken)
return nil, errors.New("invalid ratpanel server url") if err != nil {
return nil, err
} }
if accessTokenId == 0 {
return nil, errors.New("invalid ratpanel access token id")
}
if accessToken == "" {
return nil, errors.New("invalid ratpanel access token")
}
client := rpsdk.NewClient(serverUrl, accessTokenId, accessToken)
if skipTlsVerify { if skipTlsVerify {
client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true}) client.SetTLSConfig(&tls.Config{InsecureSkipVerify: true})
} }
return client, nil return client, nil

View File

@ -6,7 +6,6 @@ import (
"errors" "errors"
"fmt" "fmt"
"log/slog" "log/slog"
"net/url"
"github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/deployer"
safelinesdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/safeline" safelinesdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/safeline"
@ -84,7 +83,7 @@ func (d *DeployerProvider) deployToCertificate(ctx context.Context, certPEM stri
updateCertificateReq := &safelinesdk.UpdateCertificateRequest{ updateCertificateReq := &safelinesdk.UpdateCertificateRequest{
Id: d.config.CertificateId, Id: d.config.CertificateId,
Type: 2, Type: 2,
Manual: &safelinesdk.UpdateCertificateRequestBodyManul{ Manual: &safelinesdk.CertificateManul{
Crt: certPEM, Crt: certPEM,
Key: privkeyPEM, Key: privkeyPEM,
}, },
@ -99,17 +98,13 @@ func (d *DeployerProvider) deployToCertificate(ctx context.Context, certPEM stri
} }
func createSdkClient(serverUrl, apiToken string, skipTlsVerify bool) (*safelinesdk.Client, error) { func createSdkClient(serverUrl, apiToken string, skipTlsVerify bool) (*safelinesdk.Client, error) {
if _, err := url.Parse(serverUrl); err != nil { client, err := safelinesdk.NewClient(serverUrl, apiToken)
return nil, errors.New("invalid safeline server url") if err != nil {
return nil, err
} }
if apiToken == "" {
return nil, errors.New("invalid safeline api token")
}
client := safelinesdk.NewClient(serverUrl, apiToken)
if skipTlsVerify { if skipTlsVerify {
client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true}) client.SetTLSConfig(&tls.Config{InsecureSkipVerify: true})
} }
return client, nil return client, nil

View File

@ -16,7 +16,6 @@ var (
fInputKeyPath string fInputKeyPath string
fSecretId string fSecretId string
fSecretKey string fSecretKey string
fProxyGroupId string
fProxyId string fProxyId string
fListenerId string fListenerId string
) )
@ -28,7 +27,6 @@ func init() {
flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "") flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "")
flag.StringVar(&fSecretId, argsPrefix+"SECRETID", "", "") flag.StringVar(&fSecretId, argsPrefix+"SECRETID", "", "")
flag.StringVar(&fSecretKey, argsPrefix+"SECRETKEY", "", "") flag.StringVar(&fSecretKey, argsPrefix+"SECRETKEY", "", "")
flag.StringVar(&fProxyGroupId, argsPrefix+"PROXYGROUPID", "", "")
flag.StringVar(&fProxyId, argsPrefix+"PROXYID", "", "") flag.StringVar(&fProxyId, argsPrefix+"PROXYID", "", "")
flag.StringVar(&fListenerId, argsPrefix+"LISTENERID", "", "") flag.StringVar(&fListenerId, argsPrefix+"LISTENERID", "", "")
} }
@ -41,7 +39,6 @@ Shell command to run this test:
--CERTIMATE_DEPLOYER_TENCENTCLOUDGAAP_INPUTKEYPATH="/path/to/your-input-key.pem" \ --CERTIMATE_DEPLOYER_TENCENTCLOUDGAAP_INPUTKEYPATH="/path/to/your-input-key.pem" \
--CERTIMATE_DEPLOYER_TENCENTCLOUDGAAP_SECRETID="your-secret-id" \ --CERTIMATE_DEPLOYER_TENCENTCLOUDGAAP_SECRETID="your-secret-id" \
--CERTIMATE_DEPLOYER_TENCENTCLOUDGAAP_SECRETKEY="your-secret-key" \ --CERTIMATE_DEPLOYER_TENCENTCLOUDGAAP_SECRETKEY="your-secret-key" \
--CERTIMATE_DEPLOYER_TENCENTCLOUDGAAP_PROXYGROUPID="your-gaap-group-id" \
--CERTIMATE_DEPLOYER_TENCENTCLOUDGAAP_PROXYID="your-gaap-group-id" \ --CERTIMATE_DEPLOYER_TENCENTCLOUDGAAP_PROXYID="your-gaap-group-id" \
--CERTIMATE_DEPLOYER_TENCENTCLOUDGAAP_LISTENERID="your-clb-listener-id" --CERTIMATE_DEPLOYER_TENCENTCLOUDGAAP_LISTENERID="your-clb-listener-id"
*/ */
@ -55,7 +52,6 @@ func TestDeploy(t *testing.T) {
fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath), fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath),
fmt.Sprintf("SECRETID: %v", fSecretId), fmt.Sprintf("SECRETID: %v", fSecretId),
fmt.Sprintf("SECRETKEY: %v", fSecretKey), fmt.Sprintf("SECRETKEY: %v", fSecretKey),
fmt.Sprintf("PROXYGROUPID: %v", fProxyGroupId),
fmt.Sprintf("PROXYID: %v", fProxyId), fmt.Sprintf("PROXYID: %v", fProxyId),
fmt.Sprintf("LISTENERID: %v", fListenerId), fmt.Sprintf("LISTENERID: %v", fListenerId),
}, "\n")) }, "\n"))
@ -64,7 +60,6 @@ func TestDeploy(t *testing.T) {
SecretId: fSecretId, SecretId: fSecretId,
SecretKey: fSecretKey, SecretKey: fSecretKey,
ResourceType: provider.RESOURCE_TYPE_LISTENER, ResourceType: provider.RESOURCE_TYPE_LISTENER,
ProxyGroupId: fProxyGroupId,
ProxyId: fProxyId, ProxyId: fProxyId,
ListenerId: fListenerId, ListenerId: fListenerId,
}) })

View File

@ -88,14 +88,5 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPE
} }
func createSdkClient(username, password string) (*unisdk.Client, error) { func createSdkClient(username, password string) (*unisdk.Client, error) {
if username == "" { return unisdk.NewClient(username, password)
return nil, errors.New("invalid unicloud username")
}
if password == "" {
return nil, errors.New("invalid unicloud password")
}
client := unisdk.NewClient(username, password)
return client, nil
} }

View File

@ -2,7 +2,6 @@ package upyuncdn
import ( import (
"context" "context"
"errors"
"fmt" "fmt"
"log/slog" "log/slog"
@ -116,14 +115,5 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPE
} }
func createSdkClient(username, password string) (*upyunsdk.Client, error) { func createSdkClient(username, password string) (*upyunsdk.Client, error) {
if username == "" { return upyunsdk.NewClient(username, password)
return nil, errors.New("invalid upyun username")
}
if password == "" {
return nil, errors.New("invalid upyun password")
}
client := upyunsdk.NewClient(username, password)
return client, nil
} }

View File

@ -2,7 +2,6 @@ package wangsucdn
import ( import (
"context" "context"
"errors"
"fmt" "fmt"
"log/slog" "log/slog"
"strconv" "strconv"
@ -97,13 +96,5 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPE
} }
func createSdkClient(accessKeyId, accessKeySecret string) (*wangsusdk.Client, error) { func createSdkClient(accessKeyId, accessKeySecret string) (*wangsusdk.Client, error) {
if accessKeyId == "" { return wangsusdk.NewClient(accessKeyId, accessKeySecret)
return nil, errors.New("invalid wangsu access key id")
}
if accessKeySecret == "" {
return nil, errors.New("invalid wangsu access key secret")
}
return wangsusdk.NewClient(accessKeyId, accessKeySecret), nil
} }

View File

@ -98,7 +98,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPE
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to encrypt private key: %w", err) return nil, fmt.Errorf("failed to encrypt private key: %w", err)
} }
certificateNewVersionInfo := &wangsucdn.CertificateVersion{ certificateNewVersionInfo := &wangsucdn.CertificateVersionInfo{
PrivateKey: xtypes.ToPtr(encryptedPrivateKey), PrivateKey: xtypes.ToPtr(encryptedPrivateKey),
Certificate: xtypes.ToPtr(certPEM), Certificate: xtypes.ToPtr(certPEM),
IdentificationInfo: &wangsucdn.CertificateVersionIdentificationInfo{ IdentificationInfo: &wangsucdn.CertificateVersionIdentificationInfo{
@ -131,7 +131,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPE
return nil, fmt.Errorf("failed to execute sdk request 'cdnpro.CreateCertificate': %w", err) return nil, fmt.Errorf("failed to execute sdk request 'cdnpro.CreateCertificate': %w", err)
} }
wangsuCertUrl = createCertificateResp.CertificateUrl wangsuCertUrl = createCertificateResp.CertificateLocation
d.logger.Info("ssl certificate uploaded", slog.Any("certUrl", wangsuCertUrl)) d.logger.Info("ssl certificate uploaded", slog.Any("certUrl", wangsuCertUrl))
wangsuCertIdMatches := regexp.MustCompile(`/certificates/([a-zA-Z0-9-]+)`).FindStringSubmatch(wangsuCertUrl) wangsuCertIdMatches := regexp.MustCompile(`/certificates/([a-zA-Z0-9-]+)`).FindStringSubmatch(wangsuCertUrl)
@ -154,7 +154,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPE
return nil, fmt.Errorf("failed to execute sdk request 'cdnpro.UpdateCertificate': %w", err) return nil, fmt.Errorf("failed to execute sdk request 'cdnpro.UpdateCertificate': %w", err)
} }
wangsuCertUrl = updateCertificateResp.CertificateUrl wangsuCertUrl = updateCertificateResp.CertificateLocation
d.logger.Info("ssl certificate uploaded", slog.Any("certUrl", wangsuCertUrl)) d.logger.Info("ssl certificate uploaded", slog.Any("certUrl", wangsuCertUrl))
wangsuCertIdMatches := regexp.MustCompile(`/certificates/([a-zA-Z0-9-]+)`).FindStringSubmatch(wangsuCertUrl) wangsuCertIdMatches := regexp.MustCompile(`/certificates/([a-zA-Z0-9-]+)`).FindStringSubmatch(wangsuCertUrl)
@ -174,7 +174,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPE
createDeploymentTaskReq := &wangsucdn.CreateDeploymentTaskRequest{ createDeploymentTaskReq := &wangsucdn.CreateDeploymentTaskRequest{
Name: xtypes.ToPtr(fmt.Sprintf("certimate_%d", time.Now().UnixMilli())), Name: xtypes.ToPtr(fmt.Sprintf("certimate_%d", time.Now().UnixMilli())),
Target: xtypes.ToPtr(d.config.Environment), Target: xtypes.ToPtr(d.config.Environment),
Actions: &[]wangsucdn.DeploymentTaskAction{ Actions: &[]wangsucdn.DeploymentTaskActionInfo{
{ {
Action: xtypes.ToPtr("deploy_cert"), Action: xtypes.ToPtr("deploy_cert"),
CertificateId: xtypes.ToPtr(wangsuCertId), CertificateId: xtypes.ToPtr(wangsuCertId),
@ -194,7 +194,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPE
// 循环获取部署任务详细信息,等待任务状态变更 // 循环获取部署任务详细信息,等待任务状态变更
// REF: https://www.wangsu.com/document/api-doc/27038 // REF: https://www.wangsu.com/document/api-doc/27038
var wangsuTaskId string var wangsuTaskId string
wangsuTaskMatches := regexp.MustCompile(`/deploymentTasks/([a-zA-Z0-9-]+)`).FindStringSubmatch(createDeploymentTaskResp.DeploymentTaskUrl) wangsuTaskMatches := regexp.MustCompile(`/deploymentTasks/([a-zA-Z0-9-]+)`).FindStringSubmatch(createDeploymentTaskResp.DeploymentTaskLocation)
if len(wangsuTaskMatches) > 1 { if len(wangsuTaskMatches) > 1 {
wangsuTaskId = wangsuTaskMatches[1] wangsuTaskId = wangsuTaskMatches[1]
} }
@ -225,15 +225,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPE
} }
func createSdkClient(accessKeyId, accessKeySecret string) (*wangsucdn.Client, error) { func createSdkClient(accessKeyId, accessKeySecret string) (*wangsucdn.Client, error) {
if accessKeyId == "" { return wangsucdn.NewClient(accessKeyId, accessKeySecret)
return nil, errors.New("invalid wangsu access key id")
}
if accessKeySecret == "" {
return nil, errors.New("invalid wangsu access key secret")
}
return wangsucdn.NewClient(accessKeyId, accessKeySecret), nil
} }
func encryptPrivateKey(privkeyPEM string, apiKey string, timestamp int64) (string, error) { func encryptPrivateKey(privkeyPEM string, apiKey string, timestamp int64) (string, error) {

View File

@ -2,7 +2,6 @@ package wangsucertificate
import ( import (
"context" "context"
"errors"
"fmt" "fmt"
"log/slog" "log/slog"
"time" "time"
@ -97,13 +96,5 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPE
} }
func createSdkClient(accessKeyId, accessKeySecret string) (*wangsusdk.Client, error) { func createSdkClient(accessKeyId, accessKeySecret string) (*wangsusdk.Client, error) {
if accessKeyId == "" { return wangsusdk.NewClient(accessKeyId, accessKeySecret)
return nil, errors.New("invalid wangsu access key id")
}
if accessKeySecret == "" {
return nil, errors.New("invalid wangsu access key secret")
}
return wangsusdk.NewClient(accessKeyId, accessKeySecret), nil
} }

View File

@ -24,7 +24,7 @@ func init() {
argsPrefix := "CERTIMATE_NOTIFIER_DISCORDBOT_" argsPrefix := "CERTIMATE_NOTIFIER_DISCORDBOT_"
flag.StringVar(&fApiToken, argsPrefix+"APITOKEN", "", "") flag.StringVar(&fApiToken, argsPrefix+"APITOKEN", "", "")
flag.StringVar(&fChannelId, argsPrefix+"CHANNELID", 0, "") flag.StringVar(&fChannelId, argsPrefix+"CHANNELID", "", "")
} }
/* /*

View File

@ -24,7 +24,7 @@ func init() {
argsPrefix := "CERTIMATE_NOTIFIER_SLACKBOT_" argsPrefix := "CERTIMATE_NOTIFIER_SLACKBOT_"
flag.StringVar(&fApiToken, argsPrefix+"APITOKEN", "", "") flag.StringVar(&fApiToken, argsPrefix+"APITOKEN", "", "")
flag.StringVar(&fChannelId, argsPrefix+"CHANNELID", 0, "") flag.StringVar(&fChannelId, argsPrefix+"CHANNELID", "", "")
} }
/* /*

View File

@ -3,15 +3,14 @@ package onepanelssl
import ( import (
"context" "context"
"crypto/tls" "crypto/tls"
"errors"
"fmt" "fmt"
"log/slog" "log/slog"
"net/url"
"strings" "strings"
"time" "time"
"github.com/usual2970/certimate/internal/pkg/core/uploader" "github.com/usual2970/certimate/internal/pkg/core/uploader"
onepanelsdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/1panel" onepanelsdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/1panel"
onepanelsdkv2 "github.com/usual2970/certimate/internal/pkg/sdk3rd/1panel/v2"
) )
type UploaderConfig struct { type UploaderConfig struct {
@ -28,7 +27,7 @@ type UploaderConfig struct {
type UploaderProvider struct { type UploaderProvider struct {
config *UploaderConfig config *UploaderConfig
logger *slog.Logger logger *slog.Logger
sdkClient *onepanelsdk.Client sdkClient any
} }
var _ uploader.Uploader = (*UploaderProvider)(nil) var _ uploader.Uploader = (*UploaderProvider)(nil)
@ -72,23 +71,46 @@ func (u *UploaderProvider) Upload(ctx context.Context, certPEM string, privkeyPE
certName := fmt.Sprintf("certimate-%d", time.Now().UnixMilli()) certName := fmt.Sprintf("certimate-%d", time.Now().UnixMilli())
// 上传证书 // 上传证书
uploadWebsiteSSLReq := &onepanelsdk.UploadWebsiteSSLRequest{ switch sdkClient := u.sdkClient.(type) {
Type: "paste", case *onepanelsdk.Client:
Description: certName, {
Certificate: certPEM, uploadWebsiteSSLReq := &onepanelsdk.UploadWebsiteSSLRequest{
PrivateKey: privkeyPEM, Type: "paste",
} Description: certName,
uploadWebsiteSSLResp, err := u.sdkClient.UploadWebsiteSSL(uploadWebsiteSSLReq) Certificate: certPEM,
u.logger.Debug("sdk request '1panel.UploadWebsiteSSL'", slog.Any("request", uploadWebsiteSSLReq), slog.Any("response", uploadWebsiteSSLResp)) PrivateKey: privkeyPEM,
if err != nil { }
return nil, fmt.Errorf("failed to execute sdk request '1panel.UploadWebsiteSSL': %w", err) uploadWebsiteSSLResp, err := sdkClient.UploadWebsiteSSL(uploadWebsiteSSLReq)
u.logger.Debug("sdk request '1panel.UploadWebsiteSSL'", slog.Any("request", uploadWebsiteSSLReq), slog.Any("response", uploadWebsiteSSLResp))
if err != nil {
return nil, fmt.Errorf("failed to execute sdk request '1panel.UploadWebsiteSSL': %w", err)
}
}
case *onepanelsdkv2.Client:
{
uploadWebsiteSSLReq := &onepanelsdkv2.UploadWebsiteSSLRequest{
Type: "paste",
Description: certName,
Certificate: certPEM,
PrivateKey: privkeyPEM,
}
uploadWebsiteSSLResp, err := sdkClient.UploadWebsiteSSL(uploadWebsiteSSLReq)
u.logger.Debug("sdk request '1panel.UploadWebsiteSSL'", slog.Any("request", uploadWebsiteSSLReq), slog.Any("response", uploadWebsiteSSLResp))
if err != nil {
return nil, fmt.Errorf("failed to execute sdk request '1panel.UploadWebsiteSSL': %w", err)
}
}
default:
panic("sdk client is not implemented")
} }
// 遍历证书列表,获取刚刚上传证书 ID // 遍历证书列表,获取刚刚上传证书 ID
if res, err := u.findCertIfExists(ctx, certPEM, privkeyPEM); err != nil { if res, err := u.findCertIfExists(ctx, certPEM, privkeyPEM); err != nil {
return nil, err return nil, err
} else if res == nil { } else if res == nil {
return nil, fmt.Errorf("no ssl certificate found, may be upload failed (code: %d, message: %s)", uploadWebsiteSSLResp.GetCode(), uploadWebsiteSSLResp.GetMessage()) return nil, fmt.Errorf("no ssl certificate found, may be upload failed")
} else { } else {
return res, nil return res, nil
} }
@ -97,6 +119,7 @@ func (u *UploaderProvider) Upload(ctx context.Context, certPEM string, privkeyPE
func (u *UploaderProvider) findCertIfExists(ctx context.Context, certPEM string, privkeyPEM string) (*uploader.UploadResult, error) { func (u *UploaderProvider) findCertIfExists(ctx context.Context, certPEM string, privkeyPEM string) (*uploader.UploadResult, error) {
searchWebsiteSSLPageNumber := int32(1) searchWebsiteSSLPageNumber := int32(1)
searchWebsiteSSLPageSize := int32(100) searchWebsiteSSLPageSize := int32(100)
searchWebsiteSSLItemsCount := int32(0)
for { for {
select { select {
case <-ctx.Done(): case <-ctx.Done():
@ -104,28 +127,68 @@ func (u *UploaderProvider) findCertIfExists(ctx context.Context, certPEM string,
default: default:
} }
searchWebsiteSSLReq := &onepanelsdk.SearchWebsiteSSLRequest{ switch sdkClient := u.sdkClient.(type) {
Page: searchWebsiteSSLPageNumber, case *onepanelsdk.Client:
PageSize: searchWebsiteSSLPageSize, {
} searchWebsiteSSLReq := &onepanelsdk.SearchWebsiteSSLRequest{
searchWebsiteSSLResp, err := u.sdkClient.SearchWebsiteSSL(searchWebsiteSSLReq) Page: searchWebsiteSSLPageNumber,
u.logger.Debug("sdk request '1panel.SearchWebsiteSSL'", slog.Any("request", searchWebsiteSSLReq), slog.Any("response", searchWebsiteSSLResp)) PageSize: searchWebsiteSSLPageSize,
if err != nil { }
return nil, fmt.Errorf("failed to execute sdk request '1panel.SearchWebsiteSSL': %w", err) searchWebsiteSSLResp, err := sdkClient.SearchWebsiteSSL(searchWebsiteSSLReq)
} u.logger.Debug("sdk request '1panel.SearchWebsiteSSL'", slog.Any("request", searchWebsiteSSLReq), slog.Any("response", searchWebsiteSSLResp))
if err != nil {
return nil, fmt.Errorf("failed to execute sdk request '1panel.SearchWebsiteSSL': %w", err)
}
for _, sslItem := range searchWebsiteSSLResp.Data.Items { if searchWebsiteSSLResp.Data != nil {
if strings.TrimSpace(sslItem.PEM) == strings.TrimSpace(certPEM) && for _, sslItem := range searchWebsiteSSLResp.Data.Items {
strings.TrimSpace(sslItem.PrivateKey) == strings.TrimSpace(privkeyPEM) { if strings.TrimSpace(sslItem.PEM) == strings.TrimSpace(certPEM) &&
// 如果已存在相同证书,直接返回 strings.TrimSpace(sslItem.PrivateKey) == strings.TrimSpace(privkeyPEM) {
return &uploader.UploadResult{ // 如果已存在相同证书,直接返回
CertId: fmt.Sprintf("%d", sslItem.ID), return &uploader.UploadResult{
CertName: sslItem.Description, CertId: fmt.Sprintf("%d", sslItem.ID),
}, nil CertName: sslItem.Description,
}, nil
}
}
}
searchWebsiteSSLItemsCount = searchWebsiteSSLResp.Data.Total
} }
case *onepanelsdkv2.Client:
{
searchWebsiteSSLReq := &onepanelsdkv2.SearchWebsiteSSLRequest{
Page: searchWebsiteSSLPageNumber,
PageSize: searchWebsiteSSLPageSize,
}
searchWebsiteSSLResp, err := sdkClient.SearchWebsiteSSL(searchWebsiteSSLReq)
u.logger.Debug("sdk request '1panel.SearchWebsiteSSL'", slog.Any("request", searchWebsiteSSLReq), slog.Any("response", searchWebsiteSSLResp))
if err != nil {
return nil, fmt.Errorf("failed to execute sdk request '1panel.SearchWebsiteSSL': %w", err)
}
if searchWebsiteSSLResp.Data != nil {
for _, sslItem := range searchWebsiteSSLResp.Data.Items {
if strings.TrimSpace(sslItem.PEM) == strings.TrimSpace(certPEM) &&
strings.TrimSpace(sslItem.PrivateKey) == strings.TrimSpace(privkeyPEM) {
// 如果已存在相同证书,直接返回
return &uploader.UploadResult{
CertId: fmt.Sprintf("%d", sslItem.ID),
CertName: sslItem.Description,
}, nil
}
}
}
searchWebsiteSSLItemsCount = searchWebsiteSSLResp.Data.Total
}
default:
panic("sdk client is not implemented")
} }
if len(searchWebsiteSSLResp.Data.Items) < int(searchWebsiteSSLPageSize) { if searchWebsiteSSLItemsCount < searchWebsiteSSLPageSize {
break break
} else { } else {
searchWebsiteSSLPageNumber++ searchWebsiteSSLPageNumber++
@ -135,23 +198,35 @@ func (u *UploaderProvider) findCertIfExists(ctx context.Context, certPEM string,
return nil, nil return nil, nil
} }
func createSdkClient(serverUrl, apiVersion, apiKey string, skipTlsVerify bool) (*onepanelsdk.Client, error) { const (
if _, err := url.Parse(serverUrl); err != nil { sdkVersionV1 = "v1"
return nil, errors.New("invalid 1panel server url") sdkVersionV2 = "v2"
)
func createSdkClient(serverUrl, apiVersion, apiKey string, skipTlsVerify bool) (any, error) {
if apiVersion == sdkVersionV1 {
client, err := onepanelsdk.NewClient(serverUrl, apiKey)
if err != nil {
return nil, err
}
if skipTlsVerify {
client.SetTLSConfig(&tls.Config{InsecureSkipVerify: true})
}
return client, nil
} else if apiVersion == sdkVersionV2 {
client, err := onepanelsdkv2.NewClient(serverUrl, apiKey)
if err != nil {
return nil, err
}
if skipTlsVerify {
client.SetTLSConfig(&tls.Config{InsecureSkipVerify: true})
}
return client, nil
} }
if apiVersion == "" { return nil, fmt.Errorf("invalid 1panel api version")
return nil, errors.New("invalid 1panel api version")
}
if apiKey == "" {
return nil, errors.New("invalid 1panel api key")
}
client := onepanelsdk.NewClient(serverUrl, apiVersion, apiKey)
if skipTlsVerify {
client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true})
}
return client, nil
} }

View File

@ -14,7 +14,7 @@ import (
"github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azcertificates" "github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azcertificates"
"github.com/usual2970/certimate/internal/pkg/core/uploader" "github.com/usual2970/certimate/internal/pkg/core/uploader"
azcommon "github.com/usual2970/certimate/internal/pkg/sdk3rd/azure/common" azenv "github.com/usual2970/certimate/internal/pkg/sdk3rd/azure/env"
xcert "github.com/usual2970/certimate/internal/pkg/utils/cert" xcert "github.com/usual2970/certimate/internal/pkg/utils/cert"
) )
@ -176,7 +176,7 @@ func (u *UploaderProvider) Upload(ctx context.Context, certPEM string, privkeyPE
} }
func createSdkClient(tenantId, clientId, clientSecret, cloudName, keyvaultName string) (*azcertificates.Client, error) { func createSdkClient(tenantId, clientId, clientSecret, cloudName, keyvaultName string) (*azcertificates.Client, error) {
env, err := azcommon.GetCloudEnvironmentConfiguration(cloudName) env, err := azenv.GetCloudEnvConfiguration(cloudName)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -189,9 +189,9 @@ func createSdkClient(tenantId, clientId, clientSecret, cloudName, keyvaultName s
} }
endpoint := fmt.Sprintf("https://%s.vault.azure.net", keyvaultName) endpoint := fmt.Sprintf("https://%s.vault.azure.net", keyvaultName)
if azcommon.IsEnvironmentGovernment(cloudName) { if azenv.IsUSGovernmentEnv(cloudName) {
endpoint = fmt.Sprintf("https://%s.vault.usgovcloudapi.net", keyvaultName) endpoint = fmt.Sprintf("https://%s.vault.usgovcloudapi.net", keyvaultName)
} else if azcommon.IsEnvironmentChina(cloudName) { } else if azenv.IsChinaEnv(cloudName) {
endpoint = fmt.Sprintf("https://%s.vault.azure.cn", keyvaultName) endpoint = fmt.Sprintf("https://%s.vault.azure.cn", keyvaultName)
} }

View File

@ -58,8 +58,13 @@ func (u *UploaderProvider) Upload(ctx context.Context, certPEM string, privkeyPE
// 上传新证书 // 上传新证书
// REF: https://docs.dogecloud.com/cdn/api-cert-upload // REF: https://docs.dogecloud.com/cdn/api-cert-upload
uploadSslCertResp, err := u.sdkClient.UploadCdnCert(certName, certPEM, privkeyPEM) uploadSslCertReq := &dogesdk.UploadCdnCertRequest{
u.logger.Debug("sdk request 'cdn.UploadCdnCert'", slog.Any("response", uploadSslCertResp)) Note: certName,
Certificate: certPEM,
PrivateKey: privkeyPEM,
}
uploadSslCertResp, err := u.sdkClient.UploadCdnCert(uploadSslCertReq)
u.logger.Debug("sdk request 'cdn.UploadCdnCert'", slog.Any("request", uploadSslCertReq), slog.Any("response", uploadSslCertResp))
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to execute sdk request 'cdn.UploadCdnCert': %w", err) return nil, fmt.Errorf("failed to execute sdk request 'cdn.UploadCdnCert': %w", err)
} }
@ -72,6 +77,5 @@ func (u *UploaderProvider) Upload(ctx context.Context, certPEM string, privkeyPE
} }
func createSdkClient(accessKey, secretKey string) (*dogesdk.Client, error) { func createSdkClient(accessKey, secretKey string) (*dogesdk.Client, error) {
client := dogesdk.NewClient(accessKey, secretKey) return dogesdk.NewClient(accessKey, secretKey)
return client, nil
} }

View File

@ -11,7 +11,7 @@ import (
"github.com/G-Core/gcorelabscdn-go/sslcerts" "github.com/G-Core/gcorelabscdn-go/sslcerts"
"github.com/usual2970/certimate/internal/pkg/core/uploader" "github.com/usual2970/certimate/internal/pkg/core/uploader"
gcoresdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/gcore/common" gcoresdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/gcore"
) )
type UploaderConfig struct { type UploaderConfig struct {

View File

@ -24,7 +24,7 @@ type UploaderConfig struct {
type UploaderProvider struct { type UploaderProvider struct {
config *UploaderConfig config *UploaderConfig
logger *slog.Logger logger *slog.Logger
sdkClient *qiniusdk.Client sdkClient *qiniusdk.CdnManager
} }
var _ uploader.Uploader = (*UploaderProvider)(nil) var _ uploader.Uploader = (*UploaderProvider)(nil)
@ -81,7 +81,7 @@ func (u *UploaderProvider) Upload(ctx context.Context, certPEM string, privkeyPE
}, nil }, nil
} }
func createSdkClient(accessKey, secretKey string) (*qiniusdk.Client, error) { func createSdkClient(accessKey, secretKey string) (*qiniusdk.CdnManager, error) {
if secretKey == "" { if secretKey == "" {
return nil, errors.New("invalid qiniu access key") return nil, errors.New("invalid qiniu access key")
} }
@ -91,6 +91,6 @@ func createSdkClient(accessKey, secretKey string) (*qiniusdk.Client, error) {
} }
credential := auth.New(accessKey, secretKey) credential := auth.New(accessKey, secretKey)
client := qiniusdk.NewClient(credential) client := qiniusdk.NewCdnManager(credential)
return client, nil return client, nil
} }

View File

@ -76,7 +76,7 @@ func (u *UploaderProvider) Upload(ctx context.Context, certPEM string, privkeyPE
if res, err := u.findCertIfExists(ctx, certPEM); err != nil { if res, err := u.findCertIfExists(ctx, certPEM); err != nil {
return nil, err return nil, err
} else if res == nil { } else if res == nil {
return nil, errors.New("rainyun sslcenter: no certificate found") return nil, errors.New("no ssl certificate found, may be upload failed")
} else { } else {
return res, nil return res, nil
} }
@ -166,10 +166,5 @@ func (u *UploaderProvider) findCertIfExists(ctx context.Context, certPEM string)
} }
func createSdkClient(apiKey string) (*rainyunsdk.Client, error) { func createSdkClient(apiKey string) (*rainyunsdk.Client, error) {
if apiKey == "" { return rainyunsdk.NewClient(apiKey)
return nil, errors.New("invalid rainyun api key")
}
client := rainyunsdk.NewClient(apiKey)
return client, nil
} }

View File

@ -2,7 +2,6 @@ package upyunssl
import ( import (
"context" "context"
"errors"
"fmt" "fmt"
"log/slog" "log/slog"
@ -69,14 +68,5 @@ func (u *UploaderProvider) Upload(ctx context.Context, certPEM string, privkeyPE
} }
func createSdkClient(username, password string) (*upyunsdk.Client, error) { func createSdkClient(username, password string) (*upyunsdk.Client, error) {
if username == "" { return upyunsdk.NewClient(username, password)
return nil, errors.New("invalid upyun username")
}
if password == "" {
return nil, errors.New("invalid upyun password")
}
client := upyunsdk.NewClient(username, password)
return client, nil
} }

View File

@ -2,7 +2,6 @@ package wangsucertificate
import ( import (
"context" "context"
"errors"
"fmt" "fmt"
"log/slog" "log/slog"
"regexp" "regexp"
@ -116,7 +115,7 @@ func (u *UploaderProvider) Upload(ctx context.Context, certPEM string, privkeyPE
// 网宿云证书 URL 中包含证书 ID // 网宿云证书 URL 中包含证书 ID
// 格式: // 格式:
// https://open.chinanetcenter.com/api/certificate/100001 // https://open.chinanetcenter.com/api/certificate/100001
wangsuCertIdMatches := regexp.MustCompile(`/certificate/([0-9]+)`).FindStringSubmatch(createCertificateResp.CertificateUrl) wangsuCertIdMatches := regexp.MustCompile(`/certificate/([0-9]+)`).FindStringSubmatch(createCertificateResp.CertificateLocation)
if len(wangsuCertIdMatches) > 1 { if len(wangsuCertIdMatches) > 1 {
certId = wangsuCertIdMatches[1] certId = wangsuCertIdMatches[1]
} else { } else {
@ -130,13 +129,5 @@ func (u *UploaderProvider) Upload(ctx context.Context, certPEM string, privkeyPE
} }
func createSdkClient(accessKeyId, accessKeySecret string) (*wangsusdk.Client, error) { func createSdkClient(accessKeyId, accessKeySecret string) (*wangsusdk.Client, error) {
if accessKeyId == "" { return wangsusdk.NewClient(accessKeyId, accessKeySecret)
return nil, errors.New("invalid wangsu access key id")
}
if accessKeySecret == "" {
return nil, errors.New("invalid wangsu access key secret")
}
return wangsusdk.NewClient(accessKeyId, accessKeySecret), nil
} }

View File

@ -1,60 +0,0 @@
package onepanel
import (
"fmt"
"net/http"
)
func (c *Client) UpdateSystemSSL(req *UpdateSystemSSLRequest) (*UpdateSystemSSLResponse, error) {
resp := &UpdateSystemSSLResponse{}
path := "/settings/ssl/update"
if c.version == "v2" {
path = "/core" + path
}
err := c.sendRequestWithResult(http.MethodPost, path, req, resp)
return resp, err
}
func (c *Client) SearchWebsiteSSL(req *SearchWebsiteSSLRequest) (*SearchWebsiteSSLResponse, error) {
resp := &SearchWebsiteSSLResponse{}
err := c.sendRequestWithResult(http.MethodPost, "/websites/ssl/search", req, resp)
return resp, err
}
func (c *Client) GetWebsiteSSL(req *GetWebsiteSSLRequest) (*GetWebsiteSSLResponse, error) {
if req.SSLID == 0 {
return nil, fmt.Errorf("1panel api error: invalid parameter: SSLID")
}
resp := &GetWebsiteSSLResponse{}
err := c.sendRequestWithResult(http.MethodGet, fmt.Sprintf("/websites/ssl/%d", req.SSLID), req, resp)
return resp, err
}
func (c *Client) UploadWebsiteSSL(req *UploadWebsiteSSLRequest) (*UploadWebsiteSSLResponse, error) {
resp := &UploadWebsiteSSLResponse{}
err := c.sendRequestWithResult(http.MethodPost, "/websites/ssl/upload", req, resp)
return resp, err
}
func (c *Client) GetHttpsConf(req *GetHttpsConfRequest) (*GetHttpsConfResponse, error) {
if req.WebsiteID == 0 {
return nil, fmt.Errorf("1panel api error: invalid parameter: WebsiteID")
}
resp := &GetHttpsConfResponse{}
err := c.sendRequestWithResult(http.MethodGet, fmt.Sprintf("/websites/%d/https", req.WebsiteID), req, resp)
return resp, err
}
func (c *Client) UpdateHttpsConf(req *UpdateHttpsConfRequest) (*UpdateHttpsConfResponse, error) {
if req.WebsiteID == 0 {
return nil, fmt.Errorf("1panel api error: invalid parameter: WebsiteID")
}
resp := &UpdateHttpsConfResponse{}
err := c.sendRequestWithResult(http.MethodPost, fmt.Sprintf("/websites/%d/https", req.WebsiteID), req, resp)
return resp, err
}

View File

@ -0,0 +1,43 @@
package onepanel
import (
"context"
"fmt"
"net/http"
)
type GetHttpsConfResponse struct {
apiResponseBase
Data *struct {
Enable bool `json:"enable"`
HttpConfig string `json:"httpConfig"`
SSLProtocol []string `json:"SSLProtocol"`
Algorithm string `json:"algorithm"`
Hsts bool `json:"hsts"`
} `json:"data,omitempty"`
}
func (c *Client) GetHttpsConf(websiteId int64) (*GetHttpsConfResponse, error) {
return c.GetHttpsConfWithContext(context.Background(), websiteId)
}
func (c *Client) GetHttpsConfWithContext(ctx context.Context, websiteId int64) (*GetHttpsConfResponse, error) {
if websiteId == 0 {
return nil, fmt.Errorf("sdkerr: unset websiteId")
}
httpreq, err := c.newRequest(http.MethodGet, fmt.Sprintf("/websites/%d/https", websiteId))
if err != nil {
return nil, err
} else {
httpreq.SetContext(ctx)
}
result := &GetHttpsConfResponse{}
if _, err := c.doRequestWithResult(httpreq, result); err != nil {
return result, err
}
return result, nil
}

View File

@ -0,0 +1,50 @@
package onepanel
import (
"context"
"fmt"
"net/http"
)
type GetWebsiteSSLResponse struct {
apiResponseBase
Data *struct {
ID int64 `json:"id"`
Provider string `json:"provider"`
Description string `json:"description"`
PrimaryDomain string `json:"primaryDomain"`
Domains string `json:"domains"`
Type string `json:"type"`
Organization string `json:"organization"`
Status string `json:"status"`
StartDate string `json:"startDate"`
ExpireDate string `json:"expireDate"`
CreatedAt string `json:"createdAt"`
UpdatedAt string `json:"updatedAt"`
} `json:"data,omitempty"`
}
func (c *Client) GetWebsiteSSL(sslId int64) (*GetWebsiteSSLResponse, error) {
return c.GetWebsiteSSLWithContext(context.Background(), sslId)
}
func (c *Client) GetWebsiteSSLWithContext(ctx context.Context, sslId int64) (*GetWebsiteSSLResponse, error) {
if sslId == 0 {
return nil, fmt.Errorf("sdkerr: unset sslId")
}
httpreq, err := c.newRequest(http.MethodGet, fmt.Sprintf("/websites/ssl/%d", sslId))
if err != nil {
return nil, err
} else {
httpreq.SetContext(ctx)
}
result := &GetWebsiteSSLResponse{}
if _, err := c.doRequestWithResult(httpreq, result); err != nil {
return result, err
}
return result, nil
}

View File

@ -0,0 +1,50 @@
package onepanel
import (
"context"
"net/http"
)
type SearchWebsiteSSLRequest struct {
Page int32 `json:"page"`
PageSize int32 `json:"pageSize"`
}
type SearchWebsiteSSLResponse struct {
apiResponseBase
Data *struct {
Items []*struct {
ID int64 `json:"id"`
PEM string `json:"pem"`
PrivateKey string `json:"privateKey"`
Domains string `json:"domains"`
Description string `json:"description"`
Status string `json:"status"`
UpdatedAt string `json:"updatedAt"`
CreatedAt string `json:"createdAt"`
} `json:"items"`
Total int32 `json:"total"`
} `json:"data,omitempty"`
}
func (c *Client) SearchWebsiteSSL(req *SearchWebsiteSSLRequest) (*SearchWebsiteSSLResponse, error) {
return c.SearchWebsiteSSLWithContext(context.Background(), req)
}
func (c *Client) SearchWebsiteSSLWithContext(ctx context.Context, req *SearchWebsiteSSLRequest) (*SearchWebsiteSSLResponse, error) {
httpreq, err := c.newRequest(http.MethodPost, "/websites/ssl/search")
if err != nil {
return nil, err
} else {
httpreq.SetBody(req)
httpreq.SetContext(ctx)
}
result := &SearchWebsiteSSLResponse{}
if _, err := c.doRequestWithResult(httpreq, result); err != nil {
return result, err
}
return result, nil
}

View File

@ -0,0 +1,53 @@
package onepanel
import (
"context"
"fmt"
"net/http"
)
type UpdateHttpsConfRequest struct {
WebsiteID int64 `json:"websiteId"`
Enable bool `json:"enable"`
Type string `json:"type"`
WebsiteSSLID int64 `json:"websiteSSLId"`
PrivateKey string `json:"privateKey"`
Certificate string `json:"certificate"`
PrivateKeyPath string `json:"privateKeyPath"`
CertificatePath string `json:"certificatePath"`
ImportType string `json:"importType"`
HttpConfig string `json:"httpConfig"`
SSLProtocol []string `json:"SSLProtocol"`
Algorithm string `json:"algorithm"`
Hsts bool `json:"hsts"`
}
type UpdateHttpsConfResponse struct {
apiResponseBase
}
func (c *Client) UpdateHttpsConf(websiteId int64, req *UpdateHttpsConfRequest) (*UpdateHttpsConfResponse, error) {
return c.UpdateHttpsConfWithContext(context.Background(), websiteId, req)
}
func (c *Client) UpdateHttpsConfWithContext(ctx context.Context, websiteId int64, req *UpdateHttpsConfRequest) (*UpdateHttpsConfResponse, error) {
if websiteId == 0 {
return nil, fmt.Errorf("sdkerr: unset websiteId")
}
httpreq, err := c.newRequest(http.MethodPost, fmt.Sprintf("/websites/%d/https", websiteId))
if err != nil {
return nil, err
} else {
req.WebsiteID = websiteId
httpreq.SetBody(req)
httpreq.SetContext(ctx)
}
result := &UpdateHttpsConfResponse{}
if _, err := c.doRequestWithResult(httpreq, result); err != nil {
return result, err
}
return result, nil
}

View File

@ -0,0 +1,40 @@
package onepanel
import (
"context"
"net/http"
)
type UpdateSettingsSSLRequest struct {
Cert string `json:"cert"`
Key string `json:"key"`
SSLType string `json:"sslType"`
SSL string `json:"ssl"`
SSLID int64 `json:"sslID"`
AutoRestart string `json:"autoRestart"`
}
type UpdateSettingsSSLResponse struct {
apiResponseBase
}
func (c *Client) UpdateSettingsSSL(req *UpdateSettingsSSLRequest) (*UpdateSettingsSSLResponse, error) {
return c.UpdateSettingsSSLWithContext(context.Background(), req)
}
func (c *Client) UpdateSettingsSSLWithContext(ctx context.Context, req *UpdateSettingsSSLRequest) (*UpdateSettingsSSLResponse, error) {
httpreq, err := c.newRequest(http.MethodPost, "/settings/ssl/update")
if err != nil {
return nil, err
} else {
httpreq.SetBody(req)
httpreq.SetContext(ctx)
}
result := &UpdateSettingsSSLResponse{}
if _, err := c.doRequestWithResult(httpreq, result); err != nil {
return result, err
}
return result, nil
}

View File

@ -0,0 +1,41 @@
package onepanel
import (
"context"
"net/http"
)
type UploadWebsiteSSLRequest struct {
SSLID int64 `json:"sslID"`
Type string `json:"type"`
Certificate string `json:"certificate"`
CertificatePath string `json:"certificatePath"`
PrivateKey string `json:"privateKey"`
PrivateKeyPath string `json:"privateKeyPath"`
Description string `json:"description"`
}
type UploadWebsiteSSLResponse struct {
apiResponseBase
}
func (c *Client) UploadWebsiteSSL(req *UploadWebsiteSSLRequest) (*UploadWebsiteSSLResponse, error) {
return c.UploadWebsiteSSLWithContext(context.Background(), req)
}
func (c *Client) UploadWebsiteSSLWithContext(ctx context.Context, req *UploadWebsiteSSLRequest) (*UploadWebsiteSSLResponse, error) {
httpreq, err := c.newRequest(http.MethodPost, "/websites/ssl/upload")
if err != nil {
return nil, err
} else {
httpreq.SetBody(req)
httpreq.SetContext(ctx)
}
result := &UploadWebsiteSSLResponse{}
if _, err := c.doRequestWithResult(httpreq, result); err != nil {
return result, err
}
return result, nil
}

View File

@ -7,6 +7,7 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"net/http" "net/http"
"net/url"
"strings" "strings"
"time" "time"
@ -14,17 +15,24 @@ import (
) )
type Client struct { type Client struct {
client *resty.Client client *resty.Client
version string
} }
func NewClient(serverUrl, apiVersion, apiKey string) *Client { func NewClient(serverUrl, apiKey string) (*Client, error) {
if apiVersion == "" { if serverUrl == "" {
apiVersion = "v1" return nil, fmt.Errorf("sdkerr: unset serverUrl")
}
if _, err := url.Parse(serverUrl); err != nil {
return nil, fmt.Errorf("sdkerr: invalid serverUrl: %w", err)
}
if apiKey == "" {
return nil, fmt.Errorf("sdkerr: unset apiKey")
} }
client := resty.New(). client := resty.New().
SetBaseURL(strings.TrimRight(serverUrl, "/")+"/api/"+apiVersion). SetBaseURL(strings.TrimRight(serverUrl, "/")+"/api/v1").
SetHeader("Accept", "application/json").
SetHeader("Content-Type", "application/json").
SetHeader("User-Agent", "certimate"). SetHeader("User-Agent", "certimate").
SetPreRequestHook(func(c *resty.Client, req *http.Request) error { SetPreRequestHook(func(c *resty.Client, req *http.Request) error {
timestamp := fmt.Sprintf("%d", time.Now().Unix()) timestamp := fmt.Sprintf("%d", time.Now().Unix())
@ -36,66 +44,73 @@ func NewClient(serverUrl, apiVersion, apiKey string) *Client {
return nil return nil
}) })
return &Client{ return &Client{client}, nil
client: client,
version: apiVersion,
}
} }
func (c *Client) WithTimeout(timeout time.Duration) *Client { func (c *Client) SetTimeout(timeout time.Duration) *Client {
c.client.SetTimeout(timeout) c.client.SetTimeout(timeout)
return c return c
} }
func (c *Client) WithTLSConfig(config *tls.Config) *Client { func (c *Client) SetTLSConfig(config *tls.Config) *Client {
c.client.SetTLSClientConfig(config) c.client.SetTLSClientConfig(config)
return c return c
} }
func (c *Client) sendRequest(method string, path string, params interface{}) (*resty.Response, error) { func (c *Client) newRequest(method string, path string) (*resty.Request, error) {
req := c.client.R() if method == "" {
if strings.EqualFold(method, http.MethodGet) { return nil, fmt.Errorf("sdkerr: unset method")
qs := make(map[string]string) }
if params != nil { if path == "" {
temp := make(map[string]any) return nil, fmt.Errorf("sdkerr: unset path")
jsonb, _ := json.Marshal(params)
json.Unmarshal(jsonb, &temp)
for k, v := range temp {
if v != nil {
qs[k] = fmt.Sprintf("%v", v)
}
}
}
req = req.SetQueryParams(qs)
} else {
req = req.SetHeader("Content-Type", "application/json").SetBody(params)
} }
resp, err := req.Execute(method, path) req := c.client.R()
req.Method = method
req.URL = path
return req, nil
}
func (c *Client) doRequest(req *resty.Request) (*resty.Response, error) {
if req == nil {
return nil, fmt.Errorf("sdkerr: nil request")
}
// WARN:
// PLEASE DO NOT USE `req.SetResult` or `req.SetError` HERE! USE `doRequestWithResult` INSTEAD.
resp, err := req.Send()
if err != nil { if err != nil {
return resp, fmt.Errorf("1panel api error: failed to send request: %w", err) return resp, fmt.Errorf("sdkerr: failed to send request: %w", err)
} else if resp.IsError() { } else if resp.IsError() {
return resp, fmt.Errorf("1panel api error: unexpected status code: %d, resp: %s", resp.StatusCode(), resp.String()) return resp, fmt.Errorf("sdkerr: unexpected status code: %d, resp: %s", resp.StatusCode(), resp.String())
} }
return resp, nil return resp, nil
} }
func (c *Client) sendRequestWithResult(method string, path string, params interface{}, result BaseResponse) error { func (c *Client) doRequestWithResult(req *resty.Request, res apiResponse) (*resty.Response, error) {
resp, err := c.sendRequest(method, path, params) if req == nil {
return nil, fmt.Errorf("sdkerr: nil request")
}
resp, err := c.doRequest(req)
if err != nil { if err != nil {
if resp != nil { if resp != nil {
json.Unmarshal(resp.Body(), &result) json.Unmarshal(resp.Body(), &res)
} }
return err return resp, err
} }
if err := json.Unmarshal(resp.Body(), &result); err != nil { if len(resp.Body()) != 0 {
return fmt.Errorf("1panel api error: failed to unmarshal response: %w", err) if err := json.Unmarshal(resp.Body(), &res); err != nil {
} else if errcode := result.GetCode(); errcode/100 != 2 { return resp, fmt.Errorf("sdkerr: failed to unmarshal response: %w", err)
return fmt.Errorf("1panel api error: code='%d', message='%s'", errcode, result.GetMessage()) } else {
if tcode := res.GetCode(); tcode/100 != 2 {
return resp, fmt.Errorf("sdkerr: api error: code='%d', message='%s'", tcode, res.GetMessage())
}
}
} }
return nil return resp, nil
} }

View File

@ -1,131 +0,0 @@
package onepanel
type BaseResponse interface {
GetCode() int32
GetMessage() string
}
type baseResponse struct {
Code *int32 `json:"code,omitempty"`
Message *string `json:"message,omitempty"`
}
func (r *baseResponse) GetCode() int32 {
if r.Code != nil {
return *r.Code
}
return 0
}
func (r *baseResponse) GetMessage() string {
if r.Message != nil {
return *r.Message
}
return ""
}
type UpdateSystemSSLRequest struct {
Cert string `json:"cert"`
Key string `json:"key"`
SSLType string `json:"sslType"`
SSL string `json:"ssl"`
SSLID int64 `json:"sslID"`
AutoRestart string `json:"autoRestart"`
}
type UpdateSystemSSLResponse struct {
baseResponse
}
type SearchWebsiteSSLRequest struct {
Page int32 `json:"page"`
PageSize int32 `json:"pageSize"`
}
type SearchWebsiteSSLResponse struct {
baseResponse
Data *struct {
Items []*struct {
ID int64 `json:"id"`
PEM string `json:"pem"`
PrivateKey string `json:"privateKey"`
Domains string `json:"domains"`
Description string `json:"description"`
Status string `json:"status"`
UpdatedAt string `json:"updatedAt"`
CreatedAt string `json:"createdAt"`
} `json:"items"`
Total int32 `json:"total"`
} `json:"data,omitempty"`
}
type GetWebsiteSSLRequest struct {
SSLID int64 `json:"-"`
}
type GetWebsiteSSLResponse struct {
baseResponse
Data *struct {
ID int64 `json:"id"`
Provider string `json:"provider"`
Description string `json:"description"`
PrimaryDomain string `json:"primaryDomain"`
Domains string `json:"domains"`
Type string `json:"type"`
Organization string `json:"organization"`
Status string `json:"status"`
StartDate string `json:"startDate"`
ExpireDate string `json:"expireDate"`
CreatedAt string `json:"createdAt"`
UpdatedAt string `json:"updatedAt"`
} `json:"data,omitempty"`
}
type UploadWebsiteSSLRequest struct {
Type string `json:"type"`
SSLID int64 `json:"sslID"`
Certificate string `json:"certificate"`
CertificatePath string `json:"certificatePath"`
PrivateKey string `json:"privateKey"`
PrivateKeyPath string `json:"privateKeyPath"`
Description string `json:"description"`
}
type UploadWebsiteSSLResponse struct {
baseResponse
}
type GetHttpsConfRequest struct {
WebsiteID int64 `json:"-"`
}
type GetHttpsConfResponse struct {
baseResponse
Data *struct {
Enable bool `json:"enable"`
HttpConfig string `json:"httpConfig"`
SSLProtocol []string `json:"SSLProtocol"`
Algorithm string `json:"algorithm"`
Hsts bool `json:"hsts"`
} `json:"data,omitempty"`
}
type UpdateHttpsConfRequest struct {
WebsiteID int64 `json:"websiteId"`
Enable bool `json:"enable"`
Type string `json:"type"`
WebsiteSSLID int64 `json:"websiteSSLId"`
PrivateKey string `json:"privateKey"`
Certificate string `json:"certificate"`
PrivateKeyPath string `json:"privateKeyPath"`
CertificatePath string `json:"certificatePath"`
ImportType string `json:"importType"`
HttpConfig string `json:"httpConfig"`
SSLProtocol []string `json:"SSLProtocol"`
Algorithm string `json:"algorithm"`
Hsts bool `json:"hsts"`
}
type UpdateHttpsConfResponse struct {
baseResponse
}

View File

@ -0,0 +1,29 @@
package onepanel
type apiResponse interface {
GetCode() int32
GetMessage() string
}
type apiResponseBase struct {
Code *int32 `json:"code,omitempty"`
Message *string `json:"message,omitempty"`
}
func (r *apiResponseBase) GetCode() int32 {
if r.Code == nil {
return 0
}
return *r.Code
}
func (r *apiResponseBase) GetMessage() string {
if r.Message == nil {
return ""
}
return *r.Message
}
var _ apiResponse = (*apiResponseBase)(nil)

View File

@ -0,0 +1,43 @@
package onepanelv2
import (
"context"
"fmt"
"net/http"
)
type GetHttpsConfResponse struct {
apiResponseBase
Data *struct {
Enable bool `json:"enable"`
HttpConfig string `json:"httpConfig"`
SSLProtocol []string `json:"SSLProtocol"`
Algorithm string `json:"algorithm"`
Hsts bool `json:"hsts"`
} `json:"data,omitempty"`
}
func (c *Client) GetHttpsConf(websiteId int64) (*GetHttpsConfResponse, error) {
return c.GetHttpsConfWithContext(context.Background(), websiteId)
}
func (c *Client) GetHttpsConfWithContext(ctx context.Context, websiteId int64) (*GetHttpsConfResponse, error) {
if websiteId == 0 {
return nil, fmt.Errorf("sdkerr: unset websiteId")
}
httpreq, err := c.newRequest(http.MethodGet, fmt.Sprintf("/websites/%d/https", websiteId))
if err != nil {
return nil, err
} else {
httpreq.SetContext(ctx)
}
result := &GetHttpsConfResponse{}
if _, err := c.doRequestWithResult(httpreq, result); err != nil {
return result, err
}
return result, nil
}

View File

@ -0,0 +1,50 @@
package onepanelv2
import (
"context"
"fmt"
"net/http"
)
type GetWebsiteSSLResponse struct {
apiResponseBase
Data *struct {
ID int64 `json:"id"`
Provider string `json:"provider"`
Description string `json:"description"`
PrimaryDomain string `json:"primaryDomain"`
Domains string `json:"domains"`
Type string `json:"type"`
Organization string `json:"organization"`
Status string `json:"status"`
StartDate string `json:"startDate"`
ExpireDate string `json:"expireDate"`
CreatedAt string `json:"createdAt"`
UpdatedAt string `json:"updatedAt"`
} `json:"data,omitempty"`
}
func (c *Client) GetWebsiteSSL(sslId int64) (*GetWebsiteSSLResponse, error) {
return c.GetWebsiteSSLWithContext(context.Background(), sslId)
}
func (c *Client) GetWebsiteSSLWithContext(ctx context.Context, sslId int64) (*GetWebsiteSSLResponse, error) {
if sslId == 0 {
return nil, fmt.Errorf("sdkerr: unset sslId")
}
httpreq, err := c.newRequest(http.MethodGet, fmt.Sprintf("/websites/ssl/%d", sslId))
if err != nil {
return nil, err
} else {
httpreq.SetContext(ctx)
}
result := &GetWebsiteSSLResponse{}
if _, err := c.doRequestWithResult(httpreq, result); err != nil {
return result, err
}
return result, nil
}

View File

@ -0,0 +1,50 @@
package onepanelv2
import (
"context"
"net/http"
)
type SearchWebsiteSSLRequest struct {
Page int32 `json:"page"`
PageSize int32 `json:"pageSize"`
}
type SearchWebsiteSSLResponse struct {
apiResponseBase
Data *struct {
Items []*struct {
ID int64 `json:"id"`
PEM string `json:"pem"`
PrivateKey string `json:"privateKey"`
Domains string `json:"domains"`
Description string `json:"description"`
Status string `json:"status"`
UpdatedAt string `json:"updatedAt"`
CreatedAt string `json:"createdAt"`
} `json:"items"`
Total int32 `json:"total"`
} `json:"data,omitempty"`
}
func (c *Client) SearchWebsiteSSL(req *SearchWebsiteSSLRequest) (*SearchWebsiteSSLResponse, error) {
return c.SearchWebsiteSSLWithContext(context.Background(), req)
}
func (c *Client) SearchWebsiteSSLWithContext(ctx context.Context, req *SearchWebsiteSSLRequest) (*SearchWebsiteSSLResponse, error) {
httpreq, err := c.newRequest(http.MethodPost, "/websites/ssl/search")
if err != nil {
return nil, err
} else {
httpreq.SetBody(req)
httpreq.SetContext(ctx)
}
result := &SearchWebsiteSSLResponse{}
if _, err := c.doRequestWithResult(httpreq, result); err != nil {
return result, err
}
return result, nil
}

View File

@ -0,0 +1,40 @@
package onepanelv2
import (
"context"
"net/http"
)
type UpdateCoreSettingsSSLRequest struct {
Cert string `json:"cert"`
Key string `json:"key"`
SSLType string `json:"sslType"`
SSL string `json:"ssl"`
SSLID int64 `json:"sslID"`
AutoRestart string `json:"autoRestart"`
}
type UpdateCoreSettingsSSLResponse struct {
apiResponseBase
}
func (c *Client) UpdateCoreSettingsSSL(req *UpdateCoreSettingsSSLRequest) (*UpdateCoreSettingsSSLResponse, error) {
return c.UpdateCoreSettingsSSLWithContext(context.Background(), req)
}
func (c *Client) UpdateCoreSettingsSSLWithContext(ctx context.Context, req *UpdateCoreSettingsSSLRequest) (*UpdateCoreSettingsSSLResponse, error) {
httpreq, err := c.newRequest(http.MethodPost, "/core/settings/ssl/update")
if err != nil {
return nil, err
} else {
httpreq.SetBody(req)
httpreq.SetContext(ctx)
}
result := &UpdateCoreSettingsSSLResponse{}
if _, err := c.doRequestWithResult(httpreq, result); err != nil {
return result, err
}
return result, nil
}

View File

@ -0,0 +1,53 @@
package onepanelv2
import (
"context"
"fmt"
"net/http"
)
type UpdateHttpsConfRequest struct {
WebsiteID int64 `json:"websiteId"`
Enable bool `json:"enable"`
Type string `json:"type"`
WebsiteSSLID int64 `json:"websiteSSLId"`
PrivateKey string `json:"privateKey"`
Certificate string `json:"certificate"`
PrivateKeyPath string `json:"privateKeyPath"`
CertificatePath string `json:"certificatePath"`
ImportType string `json:"importType"`
HttpConfig string `json:"httpConfig"`
SSLProtocol []string `json:"SSLProtocol"`
Algorithm string `json:"algorithm"`
Hsts bool `json:"hsts"`
}
type UpdateHttpsConfResponse struct {
apiResponseBase
}
func (c *Client) UpdateHttpsConf(websiteId int64, req *UpdateHttpsConfRequest) (*UpdateHttpsConfResponse, error) {
return c.UpdateHttpsConfWithContext(context.Background(), websiteId, req)
}
func (c *Client) UpdateHttpsConfWithContext(ctx context.Context, websiteId int64, req *UpdateHttpsConfRequest) (*UpdateHttpsConfResponse, error) {
if websiteId == 0 {
return nil, fmt.Errorf("sdkerr: unset websiteId")
}
httpreq, err := c.newRequest(http.MethodPost, fmt.Sprintf("/websites/%d/https", websiteId))
if err != nil {
return nil, err
} else {
req.WebsiteID = websiteId
httpreq.SetBody(req)
httpreq.SetContext(ctx)
}
result := &UpdateHttpsConfResponse{}
if _, err := c.doRequestWithResult(httpreq, result); err != nil {
return result, err
}
return result, nil
}

View File

@ -0,0 +1,41 @@
package onepanelv2
import (
"context"
"net/http"
)
type UploadWebsiteSSLRequest struct {
SSLID int64 `json:"sslID"`
Type string `json:"type"`
Certificate string `json:"certificate"`
CertificatePath string `json:"certificatePath"`
PrivateKey string `json:"privateKey"`
PrivateKeyPath string `json:"privateKeyPath"`
Description string `json:"description"`
}
type UploadWebsiteSSLResponse struct {
apiResponseBase
}
func (c *Client) UploadWebsiteSSL(req *UploadWebsiteSSLRequest) (*UploadWebsiteSSLResponse, error) {
return c.UploadWebsiteSSLWithContext(context.Background(), req)
}
func (c *Client) UploadWebsiteSSLWithContext(ctx context.Context, req *UploadWebsiteSSLRequest) (*UploadWebsiteSSLResponse, error) {
httpreq, err := c.newRequest(http.MethodPost, "/websites/ssl/upload")
if err != nil {
return nil, err
} else {
httpreq.SetBody(req)
httpreq.SetContext(ctx)
}
result := &UploadWebsiteSSLResponse{}
if _, err := c.doRequestWithResult(httpreq, result); err != nil {
return result, err
}
return result, nil
}

View File

@ -0,0 +1,116 @@
package onepanelv2
import (
"crypto/md5"
"crypto/tls"
"encoding/hex"
"encoding/json"
"fmt"
"net/http"
"net/url"
"strings"
"time"
"github.com/go-resty/resty/v2"
)
type Client struct {
client *resty.Client
}
func NewClient(serverUrl, apiKey string) (*Client, error) {
if serverUrl == "" {
return nil, fmt.Errorf("sdkerr: unset serverUrl")
}
if _, err := url.Parse(serverUrl); err != nil {
return nil, fmt.Errorf("sdkerr: invalid serverUrl: %w", err)
}
if apiKey == "" {
return nil, fmt.Errorf("sdkerr: unset apiKey")
}
client := resty.New().
SetBaseURL(strings.TrimRight(serverUrl, "/")+"/api/v2").
SetHeader("Accept", "application/json").
SetHeader("Content-Type", "application/json").
SetHeader("User-Agent", "certimate").
SetPreRequestHook(func(c *resty.Client, req *http.Request) error {
timestamp := fmt.Sprintf("%d", time.Now().Unix())
tokenMd5 := md5.Sum([]byte("1panel" + apiKey + timestamp))
tokenMd5Hex := hex.EncodeToString(tokenMd5[:])
req.Header.Set("1Panel-Timestamp", timestamp)
req.Header.Set("1Panel-Token", tokenMd5Hex)
return nil
})
return &Client{client}, nil
}
func (c *Client) SetTimeout(timeout time.Duration) *Client {
c.client.SetTimeout(timeout)
return c
}
func (c *Client) SetTLSConfig(config *tls.Config) *Client {
c.client.SetTLSClientConfig(config)
return c
}
func (c *Client) newRequest(method string, path string) (*resty.Request, error) {
if method == "" {
return nil, fmt.Errorf("sdkerr: unset method")
}
if path == "" {
return nil, fmt.Errorf("sdkerr: unset path")
}
req := c.client.R()
req.Method = method
req.URL = path
return req, nil
}
func (c *Client) doRequest(req *resty.Request) (*resty.Response, error) {
if req == nil {
return nil, fmt.Errorf("sdkerr: nil request")
}
// WARN:
// PLEASE DO NOT USE `req.SetResult` or `req.SetError` HERE! USE `doRequestWithResult` INSTEAD.
resp, err := req.Send()
if err != nil {
return resp, fmt.Errorf("sdkerr: failed to send request: %w", err)
} else if resp.IsError() {
return resp, fmt.Errorf("sdkerr: unexpected status code: %d, resp: %s", resp.StatusCode(), resp.String())
}
return resp, nil
}
func (c *Client) doRequestWithResult(req *resty.Request, res apiResponse) (*resty.Response, error) {
if req == nil {
return nil, fmt.Errorf("sdkerr: nil request")
}
resp, err := c.doRequest(req)
if err != nil {
if resp != nil {
json.Unmarshal(resp.Body(), &res)
}
return resp, err
}
if len(resp.Body()) != 0 {
if err := json.Unmarshal(resp.Body(), &res); err != nil {
return resp, fmt.Errorf("sdkerr: failed to unmarshal response: %w", err)
} else {
if tcode := res.GetCode(); tcode/100 != 2 {
return resp, fmt.Errorf("sdkerr: api error: code='%d', message='%s'", tcode, res.GetMessage())
}
}
}
return resp, nil
}

View File

@ -0,0 +1,29 @@
package onepanelv2
type apiResponse interface {
GetCode() int32
GetMessage() string
}
type apiResponseBase struct {
Code *int32 `json:"code,omitempty"`
Message *string `json:"message,omitempty"`
}
func (r *apiResponseBase) GetCode() int32 {
if r.Code == nil {
return 0
}
return *r.Code
}
func (r *apiResponseBase) GetMessage() string {
if r.Message == nil {
return ""
}
return *r.Message
}
var _ apiResponse = (*apiResponseBase)(nil)

View File

@ -1,16 +0,0 @@
package apisix
import (
"fmt"
"net/http"
)
func (c *Client) UpdateSSL(req *UpdateSSLRequest) (*UpdateSSLResponse, error) {
if req.ID == "" {
return nil, fmt.Errorf("1panel api error: invalid parameter: ID")
}
resp := &UpdateSSLResponse{}
err := c.sendRequestWithResult(http.MethodGet, fmt.Sprintf("/ssls/%s", req.ID), req, resp)
return resp, err
}

View File

@ -0,0 +1,44 @@
package apisix
import (
"context"
"fmt"
"net/http"
)
type UpdateSSLRequest struct {
Cert *string `json:"cert,omitempty"`
Key *string `json:"key,omitempty"`
SNIs *[]string `json:"snis,omitempty"`
Type *string `json:"type,omitempty"`
Status *int32 `json:"status,omitempty"`
}
type UpdateSSLResponse struct {
apiResponseBase
}
func (c *Client) UpdateSSL(sslId string, req *UpdateSSLRequest) (*UpdateSSLResponse, error) {
return c.UpdateSSLWithContext(context.Background(), sslId, req)
}
func (c *Client) UpdateSSLWithContext(ctx context.Context, sslId string, req *UpdateSSLRequest) (*UpdateSSLResponse, error) {
if sslId == "" {
return nil, fmt.Errorf("sdkerr: unset sslId")
}
httpreq, err := c.newRequest(http.MethodPut, fmt.Sprintf("/ssls/%s", sslId))
if err != nil {
return nil, err
} else {
httpreq.SetBody(req)
httpreq.SetContext(ctx)
}
result := &UpdateSSLResponse{}
if _, err := c.doRequestWithResult(httpreq, result); err != nil {
return result, err
}
return result, nil
}

View File

@ -5,6 +5,7 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"net/http" "net/http"
"net/url"
"strings" "strings"
"time" "time"
@ -15,9 +16,21 @@ type Client struct {
client *resty.Client client *resty.Client
} }
func NewClient(serverUrl, apiKey string) *Client { func NewClient(serverUrl, apiKey string) (*Client, error) {
if serverUrl == "" {
return nil, fmt.Errorf("sdkerr: unset serverUrl")
}
if _, err := url.Parse(serverUrl); err != nil {
return nil, fmt.Errorf("sdkerr: invalid serverUrl: %w", err)
}
if apiKey == "" {
return nil, fmt.Errorf("sdkerr: unset apiKey")
}
client := resty.New(). client := resty.New().
SetBaseURL(strings.TrimRight(serverUrl, "/")+"/apisix/admin"). SetBaseURL(strings.TrimRight(serverUrl, "/")+"/apisix/admin").
SetHeader("Accept", "application/json").
SetHeader("Content-Type", "application/json").
SetHeader("User-Agent", "certimate"). SetHeader("User-Agent", "certimate").
SetPreRequestHook(func(c *resty.Client, req *http.Request) error { SetPreRequestHook(func(c *resty.Client, req *http.Request) error {
req.Header.Set("X-API-KEY", apiKey) req.Header.Set("X-API-KEY", apiKey)
@ -25,63 +38,69 @@ func NewClient(serverUrl, apiKey string) *Client {
return nil return nil
}) })
return &Client{ return &Client{client}, nil
client: client,
}
} }
func (c *Client) WithTimeout(timeout time.Duration) *Client { func (c *Client) SetTimeout(timeout time.Duration) *Client {
c.client.SetTimeout(timeout) c.client.SetTimeout(timeout)
return c return c
} }
func (c *Client) WithTLSConfig(config *tls.Config) *Client { func (c *Client) SetTLSConfig(config *tls.Config) *Client {
c.client.SetTLSClientConfig(config) c.client.SetTLSClientConfig(config)
return c return c
} }
func (c *Client) sendRequest(method string, path string, params interface{}) (*resty.Response, error) { func (c *Client) newRequest(method string, path string) (*resty.Request, error) {
req := c.client.R() if method == "" {
if strings.EqualFold(method, http.MethodGet) { return nil, fmt.Errorf("sdkerr: unset method")
qs := make(map[string]string) }
if params != nil { if path == "" {
temp := make(map[string]any) return nil, fmt.Errorf("sdkerr: unset path")
jsonb, _ := json.Marshal(params)
json.Unmarshal(jsonb, &temp)
for k, v := range temp {
if v != nil {
qs[k] = fmt.Sprintf("%v", v)
}
}
}
req = req.SetQueryParams(qs)
} else {
req = req.SetHeader("Content-Type", "application/json").SetBody(params)
} }
resp, err := req.Execute(method, path) req := c.client.R()
req.Method = method
req.URL = path
return req, nil
}
func (c *Client) doRequest(req *resty.Request) (*resty.Response, error) {
if req == nil {
return nil, fmt.Errorf("sdkerr: nil request")
}
// WARN:
// PLEASE DO NOT USE `req.SetResult` or `req.SetError` HERE! USE `doRequestWithResult` INSTEAD.
resp, err := req.Send()
if err != nil { if err != nil {
return resp, fmt.Errorf("apisix api error: failed to send request: %w", err) return resp, fmt.Errorf("sdkerr: failed to send request: %w", err)
} else if resp.IsError() { } else if resp.IsError() {
return resp, fmt.Errorf("apisix api error: unexpected status code: %d, resp: %s", resp.StatusCode(), resp.String()) return resp, fmt.Errorf("sdkerr: unexpected status code: %d, resp: %s", resp.StatusCode(), resp.String())
} }
return resp, nil return resp, nil
} }
func (c *Client) sendRequestWithResult(method string, path string, params interface{}, result interface{}) error { func (c *Client) doRequestWithResult(req *resty.Request, res apiResponse) (*resty.Response, error) {
resp, err := c.sendRequest(method, path, params) if req == nil {
return nil, fmt.Errorf("sdkerr: nil request")
}
resp, err := c.doRequest(req)
if err != nil { if err != nil {
if resp != nil { if resp != nil {
json.Unmarshal(resp.Body(), &result) json.Unmarshal(resp.Body(), &res)
} }
return err return resp, err
} }
if err := json.Unmarshal(resp.Body(), &result); err != nil { if len(resp.Body()) != 0 {
return fmt.Errorf("apisix api error: failed to unmarshal response: %w", err) if err := json.Unmarshal(resp.Body(), &res); err != nil {
return resp, fmt.Errorf("sdkerr: failed to unmarshal response: %w", err)
}
} }
return nil return resp, nil
} }

View File

@ -1,12 +0,0 @@
package apisix
type UpdateSSLRequest struct {
ID string `json:"-"`
Cert *string `json:"cert,omitempty"`
Key *string `json:"key,omitempty"`
SNIs *[]string `json:"snis,omitempty"`
Type *string `json:"type,omitempty"`
Status *int32 `json:"status,omitempty"`
}
type UpdateSSLResponse struct{}

View File

@ -0,0 +1,7 @@
package apisix
type apiResponse interface{}
type apiResponseBase struct{}
var _ apiResponse = (*apiResponseBase)(nil)

View File

@ -1,4 +1,4 @@
package common package env
import ( import (
"fmt" "fmt"
@ -7,7 +7,7 @@ import (
"github.com/Azure/azure-sdk-for-go/sdk/azcore/cloud" "github.com/Azure/azure-sdk-for-go/sdk/azcore/cloud"
) )
func IsEnvironmentPublic(env string) bool { func IsPublicEnv(env string) bool {
switch strings.ToLower(env) { switch strings.ToLower(env) {
case "", "default", "public", "azurecloud": case "", "default", "public", "azurecloud":
return true return true
@ -16,7 +16,7 @@ func IsEnvironmentPublic(env string) bool {
} }
} }
func IsEnvironmentGovernment(env string) bool { func IsUSGovernmentEnv(env string) bool {
switch strings.ToLower(env) { switch strings.ToLower(env) {
case "usgovernment", "government", "azureusgovernment", "azuregovernment": case "usgovernment", "government", "azureusgovernment", "azuregovernment":
return true return true
@ -25,7 +25,7 @@ func IsEnvironmentGovernment(env string) bool {
} }
} }
func IsEnvironmentChina(env string) bool { func IsChinaEnv(env string) bool {
switch strings.ToLower(env) { switch strings.ToLower(env) {
case "china", "chinacloud", "azurechina", "azurechinacloud": case "china", "chinacloud", "azurechina", "azurechinacloud":
return true return true
@ -34,12 +34,12 @@ func IsEnvironmentChina(env string) bool {
} }
} }
func GetCloudEnvironmentConfiguration(env string) (cloud.Configuration, error) { func GetCloudEnvConfiguration(env string) (cloud.Configuration, error) {
if IsEnvironmentPublic(env) { if IsPublicEnv(env) {
return cloud.AzurePublic, nil return cloud.AzurePublic, nil
} else if IsEnvironmentGovernment(env) { } else if IsUSGovernmentEnv(env) {
return cloud.AzureGovernment, nil return cloud.AzureGovernment, nil
} else if IsEnvironmentChina(env) { } else if IsChinaEnv(env) {
return cloud.AzureChina, nil return cloud.AzureChina, nil
} }

View File

@ -13,5 +13,6 @@ func NewClient(ak, sk, endPoint string) (*Client, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &Client{client}, nil return &Client{client}, nil
} }

View File

@ -1,23 +0,0 @@
package baishan
import (
"net/http"
)
func (c *Client) CreateCertificate(req *CreateCertificateRequest) (*CreateCertificateResponse, error) {
resp := &CreateCertificateResponse{}
err := c.sendRequestWithResult(http.MethodPost, "/v2/domain/certificate", req, resp)
return resp, err
}
func (c *Client) GetDomainConfig(req *GetDomainConfigRequest) (*GetDomainConfigResponse, error) {
resp := &GetDomainConfigResponse{}
err := c.sendRequestWithResult(http.MethodGet, "/v2/domain/config", req, resp)
return resp, err
}
func (c *Client) SetDomainConfig(req *SetDomainConfigRequest) (*SetDomainConfigResponse, error) {
resp := &SetDomainConfigResponse{}
err := c.sendRequestWithResult(http.MethodPost, "/v2/domain/config", req, resp)
return resp, err
}

View File

@ -0,0 +1,49 @@
package baishan
import (
"context"
"net/http"
)
type GetDomainConfigRequest struct {
Domains *string `json:"domains,omitempty"`
Config *[]string `json:"config,omitempty"`
}
type GetDomainConfigResponse struct {
apiResponseBase
Data []*struct {
Domain string `json:"domain"`
Config *DomainConfig `json:"config"`
} `json:"data,omitempty"`
}
func (c *Client) GetDomainConfig(req *GetDomainConfigRequest) (*GetDomainConfigResponse, error) {
return c.GetDomainConfigWithContext(context.Background(), req)
}
func (c *Client) GetDomainConfigWithContext(ctx context.Context, req *GetDomainConfigRequest) (*GetDomainConfigResponse, error) {
httpreq, err := c.newRequest(http.MethodGet, "/v2/domain/config")
if err != nil {
return nil, err
} else {
if req.Domains != nil {
httpreq.SetQueryParam("domains", *req.Domains)
}
if req.Config != nil {
for _, config := range *req.Config {
httpreq.QueryParam.Add("config[]", config)
}
}
httpreq.SetContext(ctx)
}
result := &GetDomainConfigResponse{}
if _, err := c.doRequestWithResult(httpreq, result); err != nil {
return result, err
}
return result, nil
}

View File

@ -0,0 +1,40 @@
package baishan
import (
"context"
"net/http"
)
type SetDomainCertificateRequest struct {
CertificateId *string `json:"cert_id,omitempty"`
Certificate *string `json:"certificate,omitempty"`
Key *string `json:"key,omitempty"`
Name *string `json:"name,omitempty"`
}
type SetDomainCertificateResponse struct {
apiResponseBase
Data *DomainCertificate `json:"data,omitempty"`
}
func (c *Client) SetDomainCertificate(req *SetDomainCertificateRequest) (*SetDomainCertificateResponse, error) {
return c.SetDomainCertificateWithContext(context.Background(), req)
}
func (c *Client) SetDomainCertificateWithContext(ctx context.Context, req *SetDomainCertificateRequest) (*SetDomainCertificateResponse, error) {
httpreq, err := c.newRequest(http.MethodPost, "/v2/domain/certificate")
if err != nil {
return nil, err
} else {
httpreq.SetBody(req)
httpreq.SetContext(ctx)
}
result := &SetDomainCertificateResponse{}
if _, err := c.doRequestWithResult(httpreq, result); err != nil {
return result, err
}
return result, nil
}

View File

@ -0,0 +1,40 @@
package baishan
import (
"context"
"net/http"
)
type SetDomainConfigRequest struct {
Domains *string `json:"domains,omitempty"`
Config *DomainConfig `json:"config,omitempty"`
}
type SetDomainConfigResponse struct {
apiResponseBase
Data *struct {
Config *DomainConfig `json:"config"`
} `json:"data,omitempty"`
}
func (c *Client) SetDomainConfig(req *SetDomainConfigRequest) (*SetDomainConfigResponse, error) {
return c.SetDomainConfigWithContext(context.Background(), req)
}
func (c *Client) SetDomainConfigWithContext(ctx context.Context, req *SetDomainConfigRequest) (*SetDomainConfigResponse, error) {
httpreq, err := c.newRequest(http.MethodPost, "/v2/domain/config")
if err != nil {
return nil, err
} else {
httpreq.SetBody(req)
httpreq.SetContext(ctx)
}
result := &SetDomainConfigResponse{}
if _, err := c.doRequestWithResult(httpreq, result); err != nil {
return result, err
}
return result, nil
}

View File

@ -3,10 +3,6 @@ package baishan
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"net/http"
"net/url"
"reflect"
"strings"
"time" "time"
"github.com/go-resty/resty/v2" "github.com/go-resty/resty/v2"
@ -16,78 +12,80 @@ type Client struct {
client *resty.Client client *resty.Client
} }
func NewClient(apiToken string) *Client { func NewClient(apiToken string) (*Client, error) {
if apiToken == "" {
return nil, fmt.Errorf("sdkerr: unset apiToken")
}
client := resty.New(). client := resty.New().
SetBaseURL("https://cdn.api.baishan.com"). SetBaseURL("https://cdn.api.baishan.com").
SetHeader("Accept", "application/json").
SetHeader("Content-Type", "application/json").
SetHeader("User-Agent", "certimate"). SetHeader("User-Agent", "certimate").
SetHeader("Token", apiToken) SetHeader("Token", apiToken)
return &Client{ return &Client{client}, nil
client: client,
}
} }
func (c *Client) WithTimeout(timeout time.Duration) *Client { func (c *Client) SetTimeout(timeout time.Duration) *Client {
c.client.SetTimeout(timeout) c.client.SetTimeout(timeout)
return c return c
} }
func (c *Client) sendRequest(method string, path string, params interface{}) (*resty.Response, error) { func (c *Client) newRequest(method string, path string) (*resty.Request, error) {
req := c.client.R() if method == "" {
if strings.EqualFold(method, http.MethodGet) { return nil, fmt.Errorf("sdkerr: unset method")
qs := url.Values{} }
if params != nil { if path == "" {
temp := make(map[string]any) return nil, fmt.Errorf("sdkerr: unset path")
jsonb, _ := json.Marshal(params)
json.Unmarshal(jsonb, &temp)
for k, v := range temp {
if v != nil {
rv := reflect.ValueOf(v)
switch rv.Kind() {
case reflect.Slice, reflect.Array:
for i := 0; i < rv.Len(); i++ {
qs.Add(fmt.Sprintf("%s[]", k), fmt.Sprintf("%v", rv.Index(i).Interface()))
}
case reflect.Map:
for _, rk := range rv.MapKeys() {
qs.Add(fmt.Sprintf("%s[%s]", k, rk.Interface()), fmt.Sprintf("%v", rv.MapIndex(rk).Interface()))
}
default:
qs.Set(k, fmt.Sprintf("%v", v))
}
}
}
}
req = req.SetQueryParamsFromValues(qs)
} else {
req = req.SetHeader("Content-Type", "application/json").SetBody(params)
} }
resp, err := req.Execute(method, path) req := c.client.R()
req.Method = method
req.URL = path
return req, nil
}
func (c *Client) doRequest(req *resty.Request) (*resty.Response, error) {
if req == nil {
return nil, fmt.Errorf("sdkerr: nil request")
}
// WARN:
// PLEASE DO NOT USE `req.SetResult` or `req.SetError` HERE! USE `doRequestWithResult` INSTEAD.
resp, err := req.Send()
if err != nil { if err != nil {
return resp, fmt.Errorf("baishan api error: failed to send request: %w", err) return resp, fmt.Errorf("sdkerr: failed to send request: %w", err)
} else if resp.IsError() { } else if resp.IsError() {
return resp, fmt.Errorf("baishan api error: unexpected status code: %d, resp: %s", resp.StatusCode(), resp.String()) return resp, fmt.Errorf("sdkerr: unexpected status code: %d, resp: %s", resp.StatusCode(), resp.String())
} }
return resp, nil return resp, nil
} }
func (c *Client) sendRequestWithResult(method string, path string, params interface{}, result BaseResponse) error { func (c *Client) doRequestWithResult(req *resty.Request, res apiResponse) (*resty.Response, error) {
resp, err := c.sendRequest(method, path, params) if req == nil {
return nil, fmt.Errorf("sdkerr: nil request")
}
resp, err := c.doRequest(req)
if err != nil { if err != nil {
if resp != nil { if resp != nil {
json.Unmarshal(resp.Body(), &result) json.Unmarshal(resp.Body(), &res)
} }
return err return resp, err
} }
if err := json.Unmarshal(resp.Body(), &result); err != nil { if len(resp.Body()) != 0 {
return fmt.Errorf("baishan api error: failed to unmarshal response: %w", err) if err := json.Unmarshal(resp.Body(), &res); err != nil {
} else if errcode := result.GetCode(); errcode != 0 { return resp, fmt.Errorf("sdkerr: failed to unmarshal response: %w", err)
return fmt.Errorf("baishan api error: code='%d', message='%s'", errcode, result.GetMessage()) } else {
if tcode := res.GetCode(); tcode != 0 {
return resp, fmt.Errorf("sdkerr: code='%d', message='%s'", tcode, res.GetMessage())
}
}
} }
return nil return resp, nil
} }

View File

@ -1,82 +0,0 @@
package baishan
import "encoding/json"
type BaseResponse interface {
GetCode() int32
GetMessage() string
}
type baseResponse struct {
Code *int32 `json:"code,omitempty"`
Message *string `json:"message,omitempty"`
}
func (r *baseResponse) GetCode() int32 {
if r.Code != nil {
return *r.Code
}
return 0
}
func (r *baseResponse) GetMessage() string {
if r.Message != nil {
return *r.Message
}
return ""
}
type CreateCertificateRequest struct {
CertificateId *string `json:"cert_id,omitempty"`
Certificate string `json:"certificate"`
Key string `json:"key"`
Name string `json:"name"`
}
type CreateCertificateResponse struct {
baseResponse
Data *DomainCertificate `json:"data,omitempty"`
}
type GetDomainConfigRequest struct {
Domains string `json:"domains"`
Config []string `json:"config"`
}
type GetDomainConfigResponse struct {
baseResponse
Data []*struct {
Domain string `json:"domain"`
Config *DomainConfig `json:"config"`
} `json:"data,omitempty"`
}
type SetDomainConfigRequest struct {
Domains string `json:"domains"`
Config *DomainConfig `json:"config"`
}
type SetDomainConfigResponse struct {
baseResponse
Data *struct {
Config *DomainConfig `json:"config"`
} `json:"data,omitempty"`
}
type DomainCertificate struct {
CertId json.Number `json:"cert_id"`
Name string `json:"name"`
CertStartTime string `json:"cert_start_time"`
CertExpireTime string `json:"cert_expire_time"`
}
type DomainConfig struct {
Https *DomainConfigHttps `json:"https"`
}
type DomainConfigHttps struct {
CertId json.Number `json:"cert_id"`
ForceHttps *string `json:"force_https,omitempty"`
EnableHttp2 *string `json:"http2,omitempty"`
EnableOcsp *string `json:"ocsp,omitempty"`
}

View File

@ -0,0 +1,49 @@
package baishan
import "encoding/json"
type apiResponse interface {
GetCode() int32
GetMessage() string
}
type apiResponseBase struct {
Code *int32 `json:"code,omitempty"`
Message *string `json:"message,omitempty"`
}
func (r *apiResponseBase) GetCode() int32 {
if r.Code == nil {
return 0
}
return *r.Code
}
func (r *apiResponseBase) GetMessage() string {
if r.Message == nil {
return ""
}
return *r.Message
}
var _ apiResponse = (*apiResponseBase)(nil)
type DomainCertificate struct {
CertId json.Number `json:"cert_id"`
Name string `json:"name"`
CertStartTime string `json:"cert_start_time"`
CertExpireTime string `json:"cert_expire_time"`
}
type DomainConfig struct {
Https *DomainConfigHttps `json:"https"`
}
type DomainConfigHttps struct {
CertId json.Number `json:"cert_id"`
ForceHttps *string `json:"force_https,omitempty"`
EnableHttp2 *string `json:"http2,omitempty"`
EnableOcsp *string `json:"ocsp,omitempty"`
}

View File

@ -1,31 +0,0 @@
package btpanel
func (c *Client) ConfigSavePanelSSL(req *ConfigSavePanelSSLRequest) (*ConfigSavePanelSSLResponse, error) {
resp := &ConfigSavePanelSSLResponse{}
err := c.sendRequestWithResult("/config?action=SavePanelSSL", req, resp)
return resp, err
}
func (c *Client) SiteSetSSL(req *SiteSetSSLRequest) (*SiteSetSSLResponse, error) {
resp := &SiteSetSSLResponse{}
err := c.sendRequestWithResult("/site?action=SetSSL", req, resp)
return resp, err
}
func (c *Client) SystemServiceAdmin(req *SystemServiceAdminRequest) (*SystemServiceAdminResponse, error) {
resp := &SystemServiceAdminResponse{}
err := c.sendRequestWithResult("/system?action=ServiceAdmin", req, resp)
return resp, err
}
func (c *Client) SSLCertSaveCert(req *SSLCertSaveCertRequest) (*SSLCertSaveCertResponse, error) {
resp := &SSLCertSaveCertResponse{}
err := c.sendRequestWithResult("/ssl/cert/save_cert", req, resp)
return resp, err
}
func (c *Client) SSLSetBatchCertToSite(req *SSLSetBatchCertToSiteRequest) (*SSLSetBatchCertToSiteResponse, error) {
resp := &SSLSetBatchCertToSiteResponse{}
err := c.sendRequestWithResult("/ssl?action=SetBatchCertToSite", req, resp)
return resp, err
}

View File

@ -0,0 +1,35 @@
package btpanel
import (
"context"
"net/http"
)
type ConfigSavePanelSSLRequest struct {
PrivateKey string `json:"privateKey"`
Certificate string `json:"certPem"`
}
type ConfigSavePanelSSLResponse struct {
apiResponseBase
}
func (c *Client) ConfigSavePanelSSL(req *ConfigSavePanelSSLRequest) (*ConfigSavePanelSSLResponse, error) {
return c.ConfigSavePanelSSLWithContext(context.Background(), req)
}
func (c *Client) ConfigSavePanelSSLWithContext(ctx context.Context, req *ConfigSavePanelSSLRequest) (*ConfigSavePanelSSLResponse, error) {
httpreq, err := c.newRequest(http.MethodPost, "/config?action=SavePanelSSL", req)
if err != nil {
return nil, err
} else {
httpreq.SetContext(ctx)
}
result := &ConfigSavePanelSSLResponse{}
if _, err := c.doRequestWithResult(httpreq, result); err != nil {
return result, err
}
return result, nil
}

View File

@ -0,0 +1,37 @@
package btpanel
import (
"context"
"net/http"
)
type SiteSetSSLRequest struct {
Type string `json:"type"`
SiteName string `json:"siteName"`
PrivateKey string `json:"key"`
Certificate string `json:"csr"`
}
type SiteSetSSLResponse struct {
apiResponseBase
}
func (c *Client) SiteSetSSL(req *SiteSetSSLRequest) (*SiteSetSSLResponse, error) {
return c.SiteSetSSLWithContext(context.Background(), req)
}
func (c *Client) SiteSetSSLWithContext(ctx context.Context, req *SiteSetSSLRequest) (*SiteSetSSLResponse, error) {
httpreq, err := c.newRequest(http.MethodPost, "/site?action=SetSSL", req)
if err != nil {
return nil, err
} else {
httpreq.SetContext(ctx)
}
result := &SiteSetSSLResponse{}
if _, err := c.doRequestWithResult(httpreq, result); err != nil {
return result, err
}
return result, nil
}

View File

@ -0,0 +1,37 @@
package btpanel
import (
"context"
"net/http"
)
type SSLCertSaveCertRequest struct {
PrivateKey string `json:"key"`
Certificate string `json:"csr"`
}
type SSLCertSaveCertResponse struct {
apiResponseBase
SSLHash string `json:"ssl_hash"`
}
func (c *Client) SSLCertSaveCert(req *SSLCertSaveCertRequest) (*SSLCertSaveCertResponse, error) {
return c.SSLCertSaveCertWithContext(context.Background(), req)
}
func (c *Client) SSLCertSaveCertWithContext(ctx context.Context, req *SSLCertSaveCertRequest) (*SSLCertSaveCertResponse, error) {
httpreq, err := c.newRequest(http.MethodPost, "/ssl/cert/save_cert", req)
if err != nil {
return nil, err
} else {
httpreq.SetContext(ctx)
}
result := &SSLCertSaveCertResponse{}
if _, err := c.doRequestWithResult(httpreq, result); err != nil {
return result, err
}
return result, nil
}

View File

@ -0,0 +1,44 @@
package btpanel
import (
"context"
"net/http"
)
type SSLSetBatchCertToSiteRequest struct {
BatchInfo []*SSLSetBatchCertToSiteRequestBatchInfo `json:"BatchInfo"`
}
type SSLSetBatchCertToSiteRequestBatchInfo struct {
SSLHash string `json:"ssl_hash"`
SiteName string `json:"siteName"`
CertName string `json:"certName"`
}
type SSLSetBatchCertToSiteResponse struct {
apiResponseBase
TotalCount int32 `json:"total"`
SuccessCount int32 `json:"success"`
FailedCount int32 `json:"faild"`
}
func (c *Client) SSLSetBatchCertToSite(req *SSLSetBatchCertToSiteRequest) (*SSLSetBatchCertToSiteResponse, error) {
return c.SSLSetBatchCertToSiteWithContext(context.Background(), req)
}
func (c *Client) SSLSetBatchCertToSiteWithContext(ctx context.Context, req *SSLSetBatchCertToSiteRequest) (*SSLSetBatchCertToSiteResponse, error) {
httpreq, err := c.newRequest(http.MethodPost, "/ssl?action=SetBatchCertToSite", req)
if err != nil {
return nil, err
} else {
httpreq.SetContext(ctx)
}
result := &SSLSetBatchCertToSiteResponse{}
if _, err := c.doRequestWithResult(httpreq, result); err != nil {
return result, err
}
return result, nil
}

View File

@ -0,0 +1,35 @@
package btpanel
import (
"context"
"net/http"
)
type SystemServiceAdminRequest struct {
Name string `json:"name"`
Type string `json:"type"`
}
type SystemServiceAdminResponse struct {
apiResponseBase
}
func (c *Client) SystemServiceAdmin(req *SystemServiceAdminRequest) (*SystemServiceAdminResponse, error) {
return c.SystemServiceAdminWithContext(context.Background(), req)
}
func (c *Client) SystemServiceAdminWithContext(ctx context.Context, req *SystemServiceAdminRequest) (*SystemServiceAdminResponse, error) {
httpreq, err := c.newRequest(http.MethodPost, "/system?action=ServiceAdmin", req)
if err != nil {
return nil, err
} else {
httpreq.SetContext(ctx)
}
result := &SystemServiceAdminResponse{}
if _, err := c.doRequestWithResult(httpreq, result); err != nil {
return result, err
}
return result, nil
}

View File

@ -6,6 +6,7 @@ import (
"encoding/hex" "encoding/hex"
"encoding/json" "encoding/json"
"fmt" "fmt"
"net/url"
"reflect" "reflect"
"strings" "strings"
"time" "time"
@ -19,39 +20,46 @@ type Client struct {
client *resty.Client client *resty.Client
} }
func NewClient(serverUrl, apiKey string) *Client { func NewClient(serverUrl, apiKey string) (*Client, error) {
if serverUrl == "" {
return nil, fmt.Errorf("sdkerr: unset serverUrl")
}
if _, err := url.Parse(serverUrl); err != nil {
return nil, fmt.Errorf("sdkerr: invalid serverUrl: %w", err)
}
if apiKey == "" {
return nil, fmt.Errorf("sdkerr: unset apiKey")
}
client := resty.New(). client := resty.New().
SetBaseURL(strings.TrimRight(serverUrl, "/")). SetBaseURL(strings.TrimRight(serverUrl, "/")).
SetHeader("Accept", "application/json").
SetHeader("Content-Type", "application/x-www-form-urlencoded"). SetHeader("Content-Type", "application/x-www-form-urlencoded").
SetHeader("User-Agent", "certimate") SetHeader("User-Agent", "certimate")
return &Client{ return &Client{
apiKey: apiKey, apiKey: apiKey,
client: client, client: client,
} }, nil
} }
func (c *Client) WithTimeout(timeout time.Duration) *Client { func (c *Client) SetTimeout(timeout time.Duration) *Client {
c.client.SetTimeout(timeout) c.client.SetTimeout(timeout)
return c return c
} }
func (c *Client) WithTLSConfig(config *tls.Config) *Client { func (c *Client) SetTLSConfig(config *tls.Config) *Client {
c.client.SetTLSClientConfig(config) c.client.SetTLSClientConfig(config)
return c return c
} }
func (c *Client) generateSignature(timestamp string) string { func (c *Client) newRequest(method string, path string, params any) (*resty.Request, error) {
keyMd5 := md5.Sum([]byte(c.apiKey)) if method == "" {
keyMd5Hex := strings.ToLower(hex.EncodeToString(keyMd5[:])) return nil, fmt.Errorf("sdkerr: unset method")
}
signMd5 := md5.Sum([]byte(timestamp + keyMd5Hex)) if path == "" {
signMd5Hex := strings.ToLower(hex.EncodeToString(signMd5[:])) return nil, fmt.Errorf("sdkerr: unset path")
return signMd5Hex }
}
func (c *Client) sendRequest(path string, params interface{}) (*resty.Response, error) {
timestamp := time.Now().Unix()
data := make(map[string]string) data := make(map[string]string)
if params != nil { if params != nil {
@ -59,52 +67,93 @@ func (c *Client) sendRequest(path string, params interface{}) (*resty.Response,
jsonb, _ := json.Marshal(params) jsonb, _ := json.Marshal(params)
json.Unmarshal(jsonb, &temp) json.Unmarshal(jsonb, &temp)
for k, v := range temp { for k, v := range temp {
if v != nil { if v == nil {
switch reflect.Indirect(reflect.ValueOf(v)).Kind() { continue
case reflect.String: }
data[k] = v.(string)
case reflect.Bool, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Float32, reflect.Float64: switch reflect.Indirect(reflect.ValueOf(v)).Kind() {
data[k] = fmt.Sprintf("%v", v) case reflect.String:
default: data[k] = v.(string)
if t, ok := v.(time.Time); ok {
data[k] = t.Format(time.RFC3339) case reflect.Bool, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Float32, reflect.Float64:
} else { data[k] = fmt.Sprintf("%v", v)
jbytes, _ := json.Marshal(v)
data[k] = string(jbytes) default:
} if t, ok := v.(time.Time); ok {
data[k] = t.Format(time.RFC3339)
} else {
jsonb, _ := json.Marshal(v)
data[k] = string(jsonb)
} }
} }
} }
} }
data["request_time"] = fmt.Sprintf("%d", timestamp)
data["request_token"] = c.generateSignature(fmt.Sprintf("%d", timestamp))
req := c.client.R().SetFormData(data) timestamp := time.Now().Unix()
resp, err := req.Post(path) data["request_time"] = fmt.Sprintf("%d", timestamp)
data["request_token"] = generateSignature(fmt.Sprintf("%d", timestamp), c.apiKey)
req := c.client.R()
req.Method = method
req.URL = path
req.SetFormData(data)
return req, nil
}
func (c *Client) doRequest(req *resty.Request) (*resty.Response, error) {
if req == nil {
return nil, fmt.Errorf("sdkerr: nil request")
}
// WARN:
// PLEASE DO NOT USE `req.SetBody` or `req.SetFormData` HERE! USE `newRequest` INSTEAD.
// PLEASE DO NOT USE `req.SetResult` or `req.SetError` HERE! USE `doRequestWithResult` INSTEAD.
resp, err := req.Send()
if err != nil { if err != nil {
return resp, fmt.Errorf("baota api error: failed to send request: %w", err) return resp, fmt.Errorf("sdkerr: failed to send request: %w", err)
} else if resp.IsError() { } else if resp.IsError() {
return resp, fmt.Errorf("baota api error: unexpected status code: %d, resp: %s", resp.StatusCode(), resp.String()) return resp, fmt.Errorf("sdkerr: unexpected status code: %d, resp: %s", resp.StatusCode(), resp.String())
} }
return resp, nil return resp, nil
} }
func (c *Client) sendRequestWithResult(path string, params interface{}, result BaseResponse) error { func (c *Client) doRequestWithResult(req *resty.Request, res apiResponse) (*resty.Response, error) {
resp, err := c.sendRequest(path, params) if req == nil {
if err != nil { return nil, fmt.Errorf("sdkerr: nil request")
return err
} }
if err := json.Unmarshal(resp.Body(), &result); err != nil { resp, err := c.doRequest(req)
return fmt.Errorf("baota api error: failed to unmarshal response: %w", err) if err != nil {
} else if errstatus := result.GetStatus(); errstatus != nil && !*errstatus { if resp != nil {
if result.GetMessage() == nil { json.Unmarshal(resp.Body(), &res)
return fmt.Errorf("baota api error: unknown error") }
return resp, err
}
if len(resp.Body()) != 0 {
if err := json.Unmarshal(resp.Body(), &res); err != nil {
return resp, fmt.Errorf("sdkerr: failed to unmarshal response: %w", err)
} else { } else {
return fmt.Errorf("baota api error: message='%s'", *result.GetMessage()) if tstatus := res.GetStatus(); tstatus != nil && !*tstatus {
if res.GetMessage() == nil {
return resp, fmt.Errorf("sdkerr: api error: unknown error")
} else {
return resp, fmt.Errorf("sdkerr: api error: message='%s'", *res.GetMessage())
}
}
} }
} }
return nil return resp, nil
}
func generateSignature(timestamp string, apiKey string) string {
keyMd5 := md5.Sum([]byte(apiKey))
keyMd5Hex := strings.ToLower(hex.EncodeToString(keyMd5[:]))
signMd5 := md5.Sum([]byte(timestamp + keyMd5Hex))
signMd5Hex := strings.ToLower(hex.EncodeToString(signMd5[:]))
return signMd5Hex
} }

View File

@ -1,75 +0,0 @@
package btpanel
type BaseResponse interface {
GetStatus() *bool
GetMessage() *string
}
type baseResponse struct {
Status *bool `json:"status,omitempty"`
Message *string `json:"msg,omitempty"`
}
func (r *baseResponse) GetStatus() *bool {
return r.Status
}
func (r *baseResponse) GetMessage() *string {
return r.Message
}
type ConfigSavePanelSSLRequest struct {
PrivateKey string `json:"privateKey"`
Certificate string `json:"certPem"`
}
type ConfigSavePanelSSLResponse struct {
baseResponse
}
type SiteSetSSLRequest struct {
Type string `json:"type"`
SiteName string `json:"siteName"`
PrivateKey string `json:"key"`
Certificate string `json:"csr"`
}
type SiteSetSSLResponse struct {
baseResponse
}
type SystemServiceAdminRequest struct {
Name string `json:"name"`
Type string `json:"type"`
}
type SystemServiceAdminResponse struct {
baseResponse
}
type SSLCertSaveCertRequest struct {
PrivateKey string `json:"key"`
Certificate string `json:"csr"`
}
type SSLCertSaveCertResponse struct {
baseResponse
SSLHash string `json:"ssl_hash"`
}
type SSLSetBatchCertToSiteRequest struct {
BatchInfo []*SSLSetBatchCertToSiteRequestBatchInfo `json:"BatchInfo"`
}
type SSLSetBatchCertToSiteRequestBatchInfo struct {
SSLHash string `json:"ssl_hash"`
SiteName string `json:"siteName"`
CertName string `json:"certName"`
}
type SSLSetBatchCertToSiteResponse struct {
baseResponse
TotalCount int32 `json:"total"`
SuccessCount int32 `json:"success"`
FailedCount int32 `json:"faild"`
}

View File

@ -0,0 +1,19 @@
package btpanel
type apiResponse interface {
GetStatus() *bool
GetMessage() *string
}
type apiResponseBase struct {
Status *bool `json:"status,omitempty"`
Message *string `json:"msg,omitempty"`
}
func (r *apiResponseBase) GetStatus() *bool {
return r.Status
}
func (r *apiResponseBase) GetMessage() *string {
return r.Message
}

View File

@ -1,19 +0,0 @@
package btwaf
func (c *Client) GetSiteList(req *GetSiteListRequest) (*GetSiteListResponse, error) {
resp := &GetSiteListResponse{}
err := c.sendRequestWithResult("/wafmastersite/get_site_list", req, resp)
return resp, err
}
func (c *Client) ModifySite(req *ModifySiteRequest) (*ModifySiteResponse, error) {
resp := &ModifySiteResponse{}
err := c.sendRequestWithResult("/wafmastersite/modify_site", req, resp)
return resp, err
}
func (c *Client) ConfigSetSSL(req *ConfigSetSSLRequest) (*ConfigSetSSLResponse, error) {
resp := &ConfigSetSSLResponse{}
err := c.sendRequestWithResult("/config/set_cert", req, resp)
return resp, err
}

View File

@ -0,0 +1,36 @@
package btwaf
import (
"context"
"net/http"
)
type ConfigSetCertRequest struct {
CertContent *string `json:"certContent,omitempty"`
KeyContent *string `json:"keyContent,omitempty"`
}
type ConfigSetCertResponse struct {
apiResponseBase
}
func (c *Client) ConfigSetCert(req *ConfigSetCertRequest) (*ConfigSetCertResponse, error) {
return c.ConfigSetCertWithContext(context.Background(), req)
}
func (c *Client) ConfigSetCertWithContext(ctx context.Context, req *ConfigSetCertRequest) (*ConfigSetCertResponse, error) {
httpreq, err := c.newRequest(http.MethodPost, "/config/set_cert")
if err != nil {
return nil, err
} else {
httpreq.SetBody(req)
httpreq.SetContext(ctx)
}
result := &ConfigSetCertResponse{}
if _, err := c.doRequestWithResult(httpreq, result); err != nil {
return result, err
}
return result, nil
}

View File

@ -0,0 +1,42 @@
package btwaf
import (
"context"
"net/http"
)
type GetSiteListRequest struct {
Page *int32 `json:"p,omitempty"`
PageSize *int32 `json:"p_size,omitempty"`
SiteName *string `json:"site_name,omitempty"`
}
type GetSiteListResponse struct {
apiResponseBase
Result *struct {
List []*SiteRecord `json:"list"`
Total int32 `json:"total"`
} `json:"res,omitempty"`
}
func (c *Client) GetSiteList(req *GetSiteListRequest) (*GetSiteListResponse, error) {
return c.GetSiteListWithContext(context.Background(), req)
}
func (c *Client) GetSiteListWithContext(ctx context.Context, req *GetSiteListRequest) (*GetSiteListResponse, error) {
httpreq, err := c.newRequest(http.MethodPost, "/wafmastersite/get_site_list")
if err != nil {
return nil, err
} else {
httpreq.SetBody(req)
httpreq.SetContext(ctx)
}
result := &GetSiteListResponse{}
if _, err := c.doRequestWithResult(httpreq, result); err != nil {
return result, err
}
return result, nil
}

View File

@ -0,0 +1,37 @@
package btwaf
import (
"context"
"net/http"
)
type ModifySiteRequest struct {
SiteId *string `json:"site_id,omitempty"`
Type *string `json:"types,omitempty"`
Server *SiteServerInfo `json:"server,omitempty"`
}
type ModifySiteResponse struct {
apiResponseBase
}
func (c *Client) ModifySite(req *ModifySiteRequest) (*ModifySiteResponse, error) {
return c.ModifySiteWithContext(context.Background(), req)
}
func (c *Client) ModifySiteWithContext(ctx context.Context, req *ModifySiteRequest) (*ModifySiteResponse, error) {
httpreq, err := c.newRequest(http.MethodPost, "/wafmastersite/modify_site")
if err != nil {
return nil, err
} else {
httpreq.SetBody(req)
httpreq.SetContext(ctx)
}
result := &ModifySiteResponse{}
if _, err := c.doRequestWithResult(httpreq, result); err != nil {
return result, err
}
return result, nil
}

View File

@ -7,6 +7,7 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"net/http" "net/http"
"net/url"
"strings" "strings"
"time" "time"
@ -17,9 +18,20 @@ type Client struct {
client *resty.Client client *resty.Client
} }
func NewClient(serverUrl, apiKey string) *Client { func NewClient(serverUrl, apiKey string) (*Client, error) {
if serverUrl == "" {
return nil, fmt.Errorf("sdkerr: unset serverUrl")
}
if _, err := url.Parse(serverUrl); err != nil {
return nil, fmt.Errorf("sdkerr: invalid serverUrl: %w", err)
}
if apiKey == "" {
return nil, fmt.Errorf("sdkerr: unset apiKey")
}
client := resty.New(). client := resty.New().
SetBaseURL(strings.TrimRight(serverUrl, "/")+"/api"). SetBaseURL(strings.TrimRight(serverUrl, "/")+"/api").
SetHeader("Accept", "application/json").
SetHeader("Content-Type", "application/json"). SetHeader("Content-Type", "application/json").
SetHeader("User-Agent", "certimate"). SetHeader("User-Agent", "certimate").
SetPreRequestHook(func(c *resty.Client, req *http.Request) error { SetPreRequestHook(func(c *resty.Client, req *http.Request) error {
@ -34,44 +46,73 @@ func NewClient(serverUrl, apiKey string) *Client {
return nil return nil
}) })
return &Client{ return &Client{client}, nil
client: client,
}
} }
func (c *Client) WithTimeout(timeout time.Duration) *Client { func (c *Client) SetTimeout(timeout time.Duration) *Client {
c.client.SetTimeout(timeout) c.client.SetTimeout(timeout)
return c return c
} }
func (c *Client) WithTLSConfig(config *tls.Config) *Client { func (c *Client) SetTLSConfig(config *tls.Config) *Client {
c.client.SetTLSClientConfig(config) c.client.SetTLSClientConfig(config)
return c return c
} }
func (c *Client) sendRequest(path string, params interface{}) (*resty.Response, error) { func (c *Client) newRequest(method string, path string) (*resty.Request, error) {
req := c.client.R().SetBody(params) if method == "" {
resp, err := req.Post(path) return nil, fmt.Errorf("sdkerr: unset method")
}
if path == "" {
return nil, fmt.Errorf("sdkerr: unset path")
}
req := c.client.R()
req.Method = method
req.URL = path
return req, nil
}
func (c *Client) doRequest(req *resty.Request) (*resty.Response, error) {
if req == nil {
return nil, fmt.Errorf("sdkerr: nil request")
}
// WARN:
// PLEASE DO NOT USE `req.SetResult` or `req.SetError` HERE! USE `doRequestWithResult` INSTEAD.
resp, err := req.Send()
if err != nil { if err != nil {
return resp, fmt.Errorf("baota api error: failed to send request: %w", err) return resp, fmt.Errorf("sdkerr: failed to send request: %w", err)
} else if resp.IsError() { } else if resp.IsError() {
return resp, fmt.Errorf("baota api error: unexpected status code: %d, resp: %s", resp.StatusCode(), resp.String()) return resp, fmt.Errorf("sdkerr: unexpected status code: %d, resp: %s", resp.StatusCode(), resp.String())
} }
return resp, nil return resp, nil
} }
func (c *Client) sendRequestWithResult(path string, params interface{}, result BaseResponse) error { func (c *Client) doRequestWithResult(req *resty.Request, res apiResponse) (*resty.Response, error) {
resp, err := c.sendRequest(path, params) if req == nil {
return nil, fmt.Errorf("sdkerr: nil request")
}
resp, err := c.doRequest(req)
if err != nil { if err != nil {
return err if resp != nil {
json.Unmarshal(resp.Body(), &res)
}
return resp, err
} }
if err := json.Unmarshal(resp.Body(), &result); err != nil { if len(resp.Body()) != 0 {
return fmt.Errorf("baota api error: failed to unmarshal response: %w", err) if err := json.Unmarshal(resp.Body(), &res); err != nil {
} else if errcode := result.GetCode(); errcode != 0 { return resp, fmt.Errorf("sdkerr: failed to unmarshal response: %w", err)
return fmt.Errorf("baota api error: code='%d'", errcode) } else {
if code := res.GetCode(); code != 0 {
return resp, fmt.Errorf("sdkerr: api error: code='%d'", code)
}
}
} }
return nil return resp, nil
} }

View File

@ -1,67 +0,0 @@
package btwaf
type BaseResponse interface {
GetCode() int32
}
type baseResponse struct {
Code *int32 `json:"code,omitempty"`
}
func (r *baseResponse) GetCode() int32 {
if r.Code != nil {
return *r.Code
}
return 0
}
type GetSiteListRequest struct {
Page *int32 `json:"p,omitempty"`
PageSize *int32 `json:"p_size,omitempty"`
SiteName *string `json:"site_name,omitempty"`
}
type GetSiteListResponse struct {
baseResponse
Result *struct {
List []*struct {
SiteId string `json:"site_id"`
SiteName string `json:"site_name"`
Type string `json:"types"`
Status int32 `json:"status"`
CreateTime int64 `json:"create_time"`
UpdateTime int64 `json:"update_time"`
} `json:"list"`
Total int32 `json:"total"`
} `json:"res,omitempty"`
}
type SiteServerInfo struct {
ListenSSLPorts *[]int32 `json:"listen_ssl_port,omitempty"`
SSL *SiteServerSSLInfo `json:"ssl,omitempty"`
}
type SiteServerSSLInfo struct {
IsSSL *int32 `json:"is_ssl,omitempty"`
FullChain *string `json:"full_chain,omitempty"`
PrivateKey *string `json:"private_key,omitempty"`
}
type ModifySiteRequest struct {
SiteId string `json:"site_id"`
Type *string `json:"types,omitempty"`
Server *SiteServerInfo `json:"server,omitempty"`
}
type ModifySiteResponse struct {
baseResponse
}
type ConfigSetSSLRequest struct {
CertContent string `json:"certContent"`
KeyContent string `json:"keyContent"`
}
type ConfigSetSSLResponse struct {
baseResponse
}

View File

@ -0,0 +1,39 @@
package btwaf
type apiResponse interface {
GetCode() int32
}
type apiResponseBase struct {
Code *int32 `json:"code,omitempty"`
}
func (r *apiResponseBase) GetCode() int32 {
if r.Code == nil {
return 0
}
return *r.Code
}
var _ apiResponse = (*apiResponseBase)(nil)
type SiteRecord struct {
SiteId string `json:"site_id"`
SiteName string `json:"site_name"`
Type string `json:"types"`
Status int32 `json:"status"`
CreateTime int64 `json:"create_time"`
UpdateTime int64 `json:"update_time"`
}
type SiteServerInfo struct {
ListenSSLPorts *[]int32 `json:"listen_ssl_port,omitempty"`
SSL *SiteServerSSLInfo `json:"ssl,omitempty"`
}
type SiteServerSSLInfo struct {
IsSSL *int32 `json:"is_ssl,omitempty"`
FullChain *string `json:"full_chain,omitempty"`
PrivateKey *string `json:"private_key,omitempty"`
}

View File

@ -1,16 +0,0 @@
package bunny
import (
"fmt"
"net/http"
"net/url"
)
func (c *Client) AddCustomCertificate(req *AddCustomCertificateRequest) ([]byte, error) {
if req.PullZoneId == "" {
return nil, fmt.Errorf("bunny api error: invalid parameter: PullZoneId")
}
resp, err := c.sendRequest(http.MethodPost, fmt.Sprintf("/pullzone/%s/addCertificate", url.PathEscape(req.PullZoneId)), req)
return resp.Body(), err
}

View File

@ -0,0 +1,38 @@
package bunny
import (
"context"
"fmt"
"net/http"
"net/url"
)
type AddCustomCertificateRequest struct {
Hostname string `json:"Hostname"`
Certificate string `json:"Certificate"`
CertificateKey string `json:"CertificateKey"`
}
func (c *Client) AddCustomCertificate(pullZoneId string, req *AddCustomCertificateRequest) error {
return c.AddCustomCertificateWithContext(context.Background(), pullZoneId, req)
}
func (c *Client) AddCustomCertificateWithContext(ctx context.Context, pullZoneId string, req *AddCustomCertificateRequest) error {
if pullZoneId == "" {
return fmt.Errorf("sdkerr: unset pullZoneId")
}
httpreq, err := c.newRequest(http.MethodPost, fmt.Sprintf("/pullzone/%s/addCertificate", url.PathEscape(pullZoneId)))
if err != nil {
return err
} else {
httpreq.SetBody(req)
httpreq.SetContext(ctx)
}
if _, err := c.doRequest(httpreq); err != nil {
return err
}
return nil
}

View File

@ -1,10 +1,7 @@
package bunny package bunny
import ( import (
"encoding/json"
"fmt" "fmt"
"net/http"
"strings"
"time" "time"
"github.com/go-resty/resty/v2" "github.com/go-resty/resty/v2"
@ -14,47 +11,53 @@ type Client struct {
client *resty.Client client *resty.Client
} }
func NewClient(apiToken string) *Client { func NewClient(apiToken string) (*Client, error) {
if apiToken == "" {
return nil, fmt.Errorf("sdkerr: unset apiToken")
}
client := resty.New(). client := resty.New().
SetBaseURL("https://api.bunny.net"). SetBaseURL("https://api.bunny.net").
SetHeader("Accept", "application/json").
SetHeader("Content-Type", "application/json").
SetHeader("User-Agent", "certimate"). SetHeader("User-Agent", "certimate").
SetHeader("AccessKey", apiToken) SetHeader("AccessKey", apiToken)
return &Client{ return &Client{client}, nil
client: client,
}
} }
func (c *Client) WithTimeout(timeout time.Duration) *Client { func (c *Client) SetTimeout(timeout time.Duration) *Client {
c.client.SetTimeout(timeout) c.client.SetTimeout(timeout)
return c return c
} }
func (c *Client) sendRequest(method string, path string, params interface{}) (*resty.Response, error) { func (c *Client) newRequest(method string, path string) (*resty.Request, error) {
req := c.client.R() if method == "" {
if strings.EqualFold(method, http.MethodGet) { return nil, fmt.Errorf("sdkerr: unset method")
qs := make(map[string]string) }
if params != nil { if path == "" {
temp := make(map[string]any) return nil, fmt.Errorf("sdkerr: unset path")
jsonb, _ := json.Marshal(params)
json.Unmarshal(jsonb, &temp)
for k, v := range temp {
if v != nil {
qs[k] = fmt.Sprintf("%v", v)
}
}
}
req = req.SetQueryParams(qs)
} else {
req = req.SetHeader("Content-Type", "application/json").SetBody(params)
} }
resp, err := req.Execute(method, path) req := c.client.R()
req.Method = method
req.URL = path
return req, nil
}
func (c *Client) doRequest(req *resty.Request) (*resty.Response, error) {
if req == nil {
return nil, fmt.Errorf("sdkerr: nil request")
}
// WARN:
// PLEASE DO NOT USE `req.SetResult` or `req.SetError` HERE! USE `doRequestWithResult` INSTEAD.
resp, err := req.Send()
if err != nil { if err != nil {
return resp, fmt.Errorf("bunny api error: failed to send request: %w", err) return resp, fmt.Errorf("sdkerr: failed to send request: %w", err)
} else if resp.IsError() { } else if resp.IsError() {
return resp, fmt.Errorf("bunny api error: unexpected status code: %d, resp: %s", resp.StatusCode(), resp.String()) return resp, fmt.Errorf("sdkerr: unexpected status code: %d, resp: %s", resp.StatusCode(), resp.String())
} }
return resp, nil return resp, nil

View File

@ -1,8 +0,0 @@
package bunny
type AddCustomCertificateRequest struct {
Hostname string `json:"Hostname"`
PullZoneId string `json:"-"`
Certificate string `json:"Certificate"`
CertificateKey string `json:"CertificateKey"`
}

View File

@ -1,11 +0,0 @@
package cachefly
import (
"net/http"
)
func (c *Client) CreateCertificate(req *CreateCertificateRequest) (*CreateCertificateResponse, error) {
resp := &CreateCertificateResponse{}
err := c.sendRequestWithResult(http.MethodPost, "/certificates", req, resp)
return resp, err
}

Some files were not shown because too many files have changed in this diff Show More