mirror of
https://github.com/certimate-go/certimate.git
synced 2026-09-24 23:10:13 +08:00
feat(provider): new acme dns-01 provider: dnsexit
This commit is contained in:
@@ -42,8 +42,8 @@ type Config struct {
|
||||
}
|
||||
|
||||
type DNSProvider struct {
|
||||
client *ecloudsdkclouddns.Client
|
||||
config *Config
|
||||
client *ecloudsdkclouddns.Client
|
||||
|
||||
recordIDs map[string]string
|
||||
recordIDsMu sync.Mutex
|
||||
@@ -88,8 +88,8 @@ func NewDNSProviderConfig(cfg *Config) (*DNSProvider, error) {
|
||||
})
|
||||
|
||||
return &DNSProvider{
|
||||
client: client,
|
||||
config: cfg,
|
||||
client: client,
|
||||
recordIDs: make(map[string]string),
|
||||
recordIDsMu: sync.Mutex{},
|
||||
}, nil
|
||||
|
||||
@@ -74,7 +74,7 @@ func NewDNSProviderConfig(config *Config) (*DNSProvider, error) {
|
||||
|
||||
client, err := ctyundns.NewClient(config.AccessKeyId, config.SecretAccessKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("ctyun: %w", err)
|
||||
} else {
|
||||
client.SetTimeout(config.HTTPTimeout)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
package dnsexit
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/certimate-go/certimate/pkg/core/certifier"
|
||||
"github.com/certimate-go/certimate/pkg/core/certifier/challengers/dns01/dnsexit/internal"
|
||||
)
|
||||
|
||||
type ChallengerConfig struct {
|
||||
ApiKey string `json:"apiKey"`
|
||||
DnsPropagationTimeout int `json:"dnsPropagationTimeout,omitempty"`
|
||||
DnsTTL int `json:"dnsTTL,omitempty"`
|
||||
}
|
||||
|
||||
func NewChallenger(config *ChallengerConfig) (certifier.ACMEChallenger, error) {
|
||||
if config == nil {
|
||||
return nil, errors.New("the configuration of the acme challenge provider is nil")
|
||||
}
|
||||
|
||||
providerConfig := internal.NewDefaultConfig()
|
||||
providerConfig.APIKey = config.ApiKey
|
||||
if config.DnsPropagationTimeout != 0 {
|
||||
providerConfig.PropagationTimeout = time.Duration(config.DnsPropagationTimeout) * time.Second
|
||||
}
|
||||
if config.DnsTTL != 0 {
|
||||
providerConfig.TTL = config.DnsTTL
|
||||
}
|
||||
|
||||
provider, err := internal.NewDNSProviderConfig(providerConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return provider, nil
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
package internal
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/go-acme/lego/v4/challenge"
|
||||
"github.com/go-acme/lego/v4/challenge/dns01"
|
||||
"github.com/go-acme/lego/v4/platform/config/env"
|
||||
"github.com/samber/lo"
|
||||
|
||||
dnsexitsdk "github.com/certimate-go/certimate/pkg/sdk3rd/dnsexit"
|
||||
)
|
||||
|
||||
const (
|
||||
envNamespace = "DNSEXIT_"
|
||||
|
||||
EnvAPIKey = envNamespace + "APIKEY"
|
||||
|
||||
EnvTTL = envNamespace + "TTL"
|
||||
EnvPropagationTimeout = envNamespace + "PROPAGATION_TIMEOUT"
|
||||
EnvPollingInterval = envNamespace + "POLLING_INTERVAL"
|
||||
EnvHTTPTimeout = envNamespace + "HTTP_TIMEOUT"
|
||||
)
|
||||
|
||||
var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
|
||||
|
||||
type Config struct {
|
||||
APIKey string
|
||||
|
||||
PropagationTimeout time.Duration
|
||||
PollingInterval time.Duration
|
||||
TTL int
|
||||
HTTPTimeout time.Duration
|
||||
}
|
||||
|
||||
func NewDefaultConfig() *Config {
|
||||
return &Config{
|
||||
TTL: env.GetOrDefaultInt(EnvTTL, 0),
|
||||
PropagationTimeout: env.GetOrDefaultSecond(EnvPropagationTimeout, dns01.DefaultPropagationTimeout),
|
||||
PollingInterval: env.GetOrDefaultSecond(EnvPollingInterval, dns01.DefaultPollingInterval),
|
||||
HTTPTimeout: env.GetOrDefaultSecond(EnvHTTPTimeout, 30*time.Second),
|
||||
}
|
||||
}
|
||||
|
||||
type DNSProvider struct {
|
||||
config *Config
|
||||
client *dnsexitsdk.Client
|
||||
}
|
||||
|
||||
func NewDNSProvider() (*DNSProvider, error) {
|
||||
values, err := env.Get(EnvAPIKey)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("dnsexit: %w", err)
|
||||
}
|
||||
|
||||
config := NewDefaultConfig()
|
||||
config.APIKey = values[EnvAPIKey]
|
||||
|
||||
return NewDNSProviderConfig(config)
|
||||
}
|
||||
|
||||
func NewDNSProviderConfig(config *Config) (*DNSProvider, error) {
|
||||
if config == nil {
|
||||
return nil, errors.New("dnsexit: the configuration of the DNS provider is nil")
|
||||
}
|
||||
|
||||
client, err := dnsexitsdk.NewClient(config.APIKey)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("dnsexit: %w", err)
|
||||
} else {
|
||||
client.SetTimeout(config.HTTPTimeout)
|
||||
}
|
||||
|
||||
return &DNSProvider{
|
||||
config: config,
|
||||
client: client,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||
info := dns01.GetChallengeInfo(domain, keyAuth)
|
||||
|
||||
authZone, err := dns01.FindZoneByFqdn(info.EffectiveFQDN)
|
||||
if err != nil {
|
||||
return fmt.Errorf("dnsexit: could not find zone for domain %q: %w", domain, err)
|
||||
}
|
||||
|
||||
subDomain, err := dns01.ExtractSubDomain(info.EffectiveFQDN, authZone)
|
||||
if err != nil {
|
||||
return fmt.Errorf("dnsexit: %w", err)
|
||||
}
|
||||
|
||||
// REF: https://dnsexit.com/dns/dns-api/#example-add-new
|
||||
request := &dnsexitsdk.DnsRecordRequest{
|
||||
Domain: lo.ToPtr(dns01.UnFqdn(authZone)),
|
||||
Add: &dnsexitsdk.DnsRecord{
|
||||
Type: lo.ToPtr("TXT"),
|
||||
Name: lo.ToPtr(subDomain),
|
||||
Content: lo.ToPtr(info.Value),
|
||||
TTL: lo.ToPtr(d.config.TTL),
|
||||
Overwrite: lo.ToPtr(true),
|
||||
},
|
||||
}
|
||||
if _, err := d.client.DnsRecord(request); err != nil {
|
||||
return fmt.Errorf("dnsexit: error when create record: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
||||
info := dns01.GetChallengeInfo(domain, keyAuth)
|
||||
|
||||
authZone, err := dns01.FindZoneByFqdn(info.EffectiveFQDN)
|
||||
if err != nil {
|
||||
return fmt.Errorf("dnsexit: could not find zone for domain %q: %w", domain, err)
|
||||
}
|
||||
|
||||
subDomain, err := dns01.ExtractSubDomain(info.EffectiveFQDN, authZone)
|
||||
if err != nil {
|
||||
return fmt.Errorf("dnsexit: %w", err)
|
||||
}
|
||||
|
||||
// REF: https://dnsexit.com/dns/dns-api/#delete-a-record
|
||||
request := &dnsexitsdk.DnsRecordRequest{
|
||||
Domain: lo.ToPtr(dns01.UnFqdn(authZone)),
|
||||
Delete: &dnsexitsdk.DnsRecord{
|
||||
Type: lo.ToPtr("TXT"),
|
||||
Name: lo.ToPtr(subDomain),
|
||||
},
|
||||
}
|
||||
if _, err := d.client.DnsRecord(request); err != nil {
|
||||
return fmt.Errorf("dnsexit: error when delete record: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *DNSProvider) Timeout() (timeout, interval time.Duration) {
|
||||
return d.config.PropagationTimeout, d.config.PollingInterval
|
||||
}
|
||||
@@ -40,8 +40,8 @@ type Config struct {
|
||||
}
|
||||
|
||||
type DNSProvider struct {
|
||||
client *dnslasdk.Client
|
||||
config *Config
|
||||
client *dnslasdk.Client
|
||||
|
||||
recordIDs map[string]string
|
||||
recordIDsMu sync.Mutex
|
||||
@@ -76,14 +76,14 @@ func NewDNSProviderConfig(config *Config) (*DNSProvider, error) {
|
||||
|
||||
client, err := dnslasdk.NewClient(config.APIId, config.APISecret)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("dnsla: %w", err)
|
||||
} else {
|
||||
client.SetTimeout(config.HTTPTimeout)
|
||||
}
|
||||
|
||||
return &DNSProvider{
|
||||
client: client,
|
||||
config: config,
|
||||
client: client,
|
||||
recordIDs: make(map[string]string),
|
||||
recordIDsMu: sync.Mutex{},
|
||||
}, nil
|
||||
|
||||
@@ -34,8 +34,8 @@ type Config struct {
|
||||
}
|
||||
|
||||
type DNSProvider struct {
|
||||
client *dynv6.Provider
|
||||
config *Config
|
||||
client *dynv6.Provider
|
||||
}
|
||||
|
||||
func NewDefaultConfig() *Config {
|
||||
@@ -66,8 +66,8 @@ func NewDNSProviderConfig(config *Config) (*DNSProvider, error) {
|
||||
client := &dynv6.Provider{Token: config.HTTPToken}
|
||||
|
||||
return &DNSProvider{
|
||||
client: client,
|
||||
config: config,
|
||||
client: client,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -39,8 +39,8 @@ type Config struct {
|
||||
}
|
||||
|
||||
type DNSProvider struct {
|
||||
client *gnamesdk.Client
|
||||
config *Config
|
||||
client *gnamesdk.Client
|
||||
|
||||
recordIDs map[string]int64
|
||||
recordIDsMu sync.Mutex
|
||||
@@ -75,14 +75,14 @@ func NewDNSProviderConfig(config *Config) (*DNSProvider, error) {
|
||||
|
||||
client, err := gnamesdk.NewClient(config.AppID, config.AppKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("gname: %w", err)
|
||||
} else {
|
||||
client.SetTimeout(config.HTTPTimeout)
|
||||
}
|
||||
|
||||
return &DNSProvider{
|
||||
client: client,
|
||||
config: config,
|
||||
client: client,
|
||||
recordIDs: make(map[string]int64),
|
||||
recordIDsMu: sync.Mutex{},
|
||||
}, nil
|
||||
|
||||
@@ -41,8 +41,8 @@ type Config struct {
|
||||
}
|
||||
|
||||
type DNSProvider struct {
|
||||
client *DomainserviceClient
|
||||
config *Config
|
||||
client *DomainserviceClient
|
||||
|
||||
recordIDs map[string]int
|
||||
recordIDsMu sync.Mutex
|
||||
@@ -81,8 +81,8 @@ func NewDNSProviderConfig(config *Config) (*DNSProvider, error) {
|
||||
client.Config.SetTimeout(config.HTTPTimeout)
|
||||
|
||||
return &DNSProvider{
|
||||
client: client,
|
||||
config: config,
|
||||
client: client,
|
||||
recordIDs: make(map[string]int),
|
||||
recordIDsMu: sync.Mutex{},
|
||||
}, nil
|
||||
|
||||
@@ -39,8 +39,8 @@ type Config struct {
|
||||
}
|
||||
|
||||
type DNSProvider struct {
|
||||
client *qingcloudsdk.Client
|
||||
config *Config
|
||||
client *qingcloudsdk.Client
|
||||
|
||||
recordIDs map[string]*int64
|
||||
recordIDsMu sync.Mutex
|
||||
@@ -75,14 +75,14 @@ func NewDNSProviderConfig(config *Config) (*DNSProvider, error) {
|
||||
|
||||
client, err := qingcloudsdk.NewClient(config.AccessKey, config.AccessSecret)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("qingcloud: %w", err)
|
||||
} else {
|
||||
client.SetTimeout(config.HTTPTimeout)
|
||||
}
|
||||
|
||||
return &DNSProvider{
|
||||
client: client,
|
||||
config: config,
|
||||
client: client,
|
||||
recordIDs: make(map[string]*int64),
|
||||
recordIDsMu: sync.Mutex{},
|
||||
}, nil
|
||||
|
||||
@@ -41,8 +41,8 @@ type Config struct {
|
||||
}
|
||||
|
||||
type DNSProvider struct {
|
||||
client *udnr.UDNRClient
|
||||
config *Config
|
||||
client *udnr.UDNRClient
|
||||
}
|
||||
|
||||
func NewDefaultConfig() *Config {
|
||||
@@ -81,8 +81,8 @@ func NewDNSProviderConfig(config *Config) (*DNSProvider, error) {
|
||||
client := udnr.NewClient(&cfg, &credential)
|
||||
|
||||
return &DNSProvider{
|
||||
client: client,
|
||||
config: config,
|
||||
client: client,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -39,8 +39,8 @@ type Config struct {
|
||||
}
|
||||
|
||||
type DNSProvider struct {
|
||||
client *xinnetsdk.Client
|
||||
config *Config
|
||||
client *xinnetsdk.Client
|
||||
|
||||
recordIDs map[string]*int64
|
||||
recordIDsMu sync.Mutex
|
||||
@@ -75,14 +75,14 @@ func NewDNSProviderConfig(config *Config) (*DNSProvider, error) {
|
||||
|
||||
client, err := xinnetsdk.NewClient(config.AgentID, config.AppSecret)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("xinnet: %w", err)
|
||||
} else {
|
||||
client.SetTimeout(config.HTTPTimeout)
|
||||
}
|
||||
|
||||
return &DNSProvider{
|
||||
client: client,
|
||||
config: config,
|
||||
client: client,
|
||||
recordIDs: make(map[string]*int64),
|
||||
recordIDsMu: sync.Mutex{},
|
||||
}, nil
|
||||
|
||||
@@ -196,8 +196,9 @@ func (d *Deployer) Deploy(ctx context.Context, certPEM, privkeyPEM string) (*dep
|
||||
|
||||
privkey, err := xcert.ParsePrivateKeyFromPEM(privkeyPEM)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not parse private key: %w", err)
|
||||
return nil, fmt.Errorf("failed to parse private key: %w", err)
|
||||
}
|
||||
|
||||
privkeyAlg, _, _ := xcryptokey.GetPrivateKeyAlgorithm(privkey)
|
||||
privkeyAlgStr := ""
|
||||
switch privkeyAlg {
|
||||
|
||||
Reference in New Issue
Block a user