Merge pull request #610 from imlonghao/feat/bunny

feat: support bunny as dns and cdn provider
This commit is contained in:
Yoan.liu
2025-04-19 10:45:51 +08:00
committed by GitHub
26 changed files with 690 additions and 0 deletions

View File

@@ -0,0 +1,36 @@
package bunny
import (
"time"
"github.com/go-acme/lego/v4/challenge"
"github.com/go-acme/lego/v4/providers/dns/bunny"
)
type ChallengeProviderConfig struct {
ApiKey string `json:"apiKey"`
DnsPropagationTimeout int32 `json:"dnsPropagationTimeout,omitempty"`
DnsTTL int32 `json:"dnsTTL,omitempty"`
}
func NewChallengeProvider(config *ChallengeProviderConfig) (challenge.Provider, error) {
if config == nil {
panic("config is nil")
}
providerConfig := bunny.NewDefaultConfig()
providerConfig.APIKey = config.ApiKey
if config.DnsPropagationTimeout != 0 {
providerConfig.PropagationTimeout = time.Duration(config.DnsPropagationTimeout) * time.Second
}
if config.DnsTTL != 0 {
providerConfig.TTL = int(config.DnsTTL)
}
provider, err := bunny.NewDNSProviderConfig(providerConfig)
if err != nil {
return nil, err
}
return provider, nil
}

View File

@@ -0,0 +1,70 @@
package bunnycdn
import (
"context"
"encoding/base64"
"log/slog"
xerrors "github.com/pkg/errors"
"github.com/usual2970/certimate/internal/pkg/core/deployer"
bunnysdk "github.com/usual2970/certimate/internal/pkg/vendors/bunny-sdk"
)
type DeployerConfig struct {
// Bunny API Key
ApiKey string `json:"apiKey"`
// Bunny Pull Zone ID
PullZoneId string `json:"pullZoneId"`
// Bunny CDN Hostname支持泛域名
HostName string `json:"hostName"`
}
type DeployerProvider struct {
config *DeployerConfig
logger *slog.Logger
sdkClient *bunnysdk.Client
}
var _ deployer.Deployer = (*DeployerProvider)(nil)
func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
if config == nil {
panic("config is nil")
}
return &DeployerProvider{
config: config,
logger: slog.Default(),
sdkClient: bunnysdk.NewClient(config.ApiKey),
}, nil
}
func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer {
if logger == nil {
d.logger = slog.Default()
} else {
d.logger = logger
}
return d
}
func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
// Prepare
certPemBase64 := base64.StdEncoding.EncodeToString([]byte(certPem))
privkeyPemBase64 := base64.StdEncoding.EncodeToString([]byte(privkeyPem))
// 上传证书
createCertificateReq := &bunnysdk.AddCustomCertificateRequest{
Hostname: d.config.HostName,
PullZoneId: d.config.PullZoneId,
Certificate: certPemBase64,
CertificateKey: privkeyPemBase64,
}
createCertificateResp, err := d.sdkClient.AddCustomCertificate(createCertificateReq)
d.logger.Debug("sdk request 'bunny-cdn.AddCustomCertificate'", slog.Any("request", createCertificateReq), slog.Any("response", createCertificateResp))
if err != nil {
return nil, xerrors.Wrap(err, "failed to execute sdk request 'bunny-cdn.AddCustomCertificate'")
}
return &deployer.DeployResult{}, nil
}

View File

@@ -0,0 +1,75 @@
package bunnycdn_test
import (
"context"
"flag"
"fmt"
"os"
"strings"
"testing"
provider "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/bunny-cdn"
)
var (
fInputCertPath string
fInputKeyPath string
fApiKey string
fPullZoneId string
fHostName string
)
func init() {
argsPrefix := "CERTIMATE_DEPLOYER_BUNNYCDN_"
flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "")
flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "")
flag.StringVar(&fApiKey, argsPrefix+"APIKEY", "", "")
flag.StringVar(&fPullZoneId, argsPrefix+"PULLZONEID", "", "")
flag.StringVar(&fHostName, argsPrefix+"HOSTNAME", "", "")
}
/*
Shell command to run this test:
go test -v ./bunny_cdn_test.go -args \
--CERTIMATE_DEPLOYER_BUNNYCDN_INPUTCERTPATH="/path/to/your-input-cert.pem" \
--CERTIMATE_DEPLOYER_BUNNYCDN_INPUTKEYPATH="/path/to/your-input-key.pem" \
--CERTIMATE_DEPLOYER_BUNNYCDN_APITOKEN="your-api-token" \
--CERTIMATE_DEPLOYER_BUNNYCDN_PULLZONEID="your-pull-zone-id" \
--CERTIMATE_DEPLOYER_BUNNYCDN_HOSTNAME="example.com"
*/
func TestDeploy(t *testing.T) {
flag.Parse()
t.Run("Deploy", func(t *testing.T) {
t.Log(strings.Join([]string{
"args:",
fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath),
fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath),
fmt.Sprintf("APIKEY: %v", fApiKey),
fmt.Sprintf("PULLZONEID: %v", fPullZoneId),
fmt.Sprintf("HOSTNAME: %v", fHostName),
}, "\n"))
deployer, err := provider.NewDeployer(&provider.DeployerConfig{
ApiKey: fApiKey,
PullZoneId: fPullZoneId,
HostName: fHostName,
})
if err != nil {
t.Errorf("err: %+v", err)
return
}
fInputCertData, _ := os.ReadFile(fInputCertPath)
fInputKeyData, _ := os.ReadFile(fInputKeyPath)
res, err := deployer.Deploy(context.Background(), string(fInputCertData), string(fInputKeyData))
if err != nil {
t.Errorf("err: %+v", err)
return
}
t.Logf("ok: %v", res)
})
}