22package hetzner
33
44import (
5- "context"
65 "errors"
7- "fmt"
86 "net/http"
7+ "os"
98 "time"
109
1110 "github.com/go-acme/lego/v4/challenge"
1211 "github.com/go-acme/lego/v4/challenge/dns01"
1312 "github.com/go-acme/lego/v4/platform/config/env"
14- "github.com/go-acme/lego/v4/providers/dns/hetzner/internal"
13+ "github.com/go-acme/lego/v4/providers/dns/hetzner/internal/hetznerv1"
14+ "github.com/go-acme/lego/v4/providers/dns/hetzner/internal/legacy"
1515)
1616
1717// Environment variables names.
1818const (
19- envNamespace = "HETZNER_"
20-
21- EnvAPIKey = envNamespace + "API_KEY"
22-
23- EnvTTL = envNamespace + "TTL"
24- EnvPropagationTimeout = envNamespace + "PROPAGATION_TIMEOUT"
25- EnvPollingInterval = envNamespace + "POLLING_INTERVAL"
26- EnvHTTPTimeout = envNamespace + "HTTP_TIMEOUT"
19+ // Deprecated: use EnvAPIToken instead.
20+ EnvAPIKey = legacy . EnvAPIKey
21+ EnvAPIToken = hetznerv1 . EnvAPIToken
22+
23+ EnvTTL = hetznerv1 . EnvTTL
24+ EnvPropagationTimeout = hetznerv1 . EnvPropagationTimeout
25+ EnvPollingInterval = hetznerv1 . EnvPollingInterval
26+ EnvHTTPTimeout = hetznerv1 . EnvHTTPTimeout
2727)
2828
2929const minTTL = 60
@@ -32,7 +32,11 @@ var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
3232
3333// Config is used to configure the creation of the DNSProvider.
3434type Config struct {
35- APIKey string
35+ // Deprecated: use APIToken instead
36+ APIKey string
37+
38+ APIToken string
39+
3640 PropagationTimeout time.Duration
3741 PollingInterval time.Duration
3842 TTL int
@@ -53,22 +57,40 @@ func NewDefaultConfig() *Config {
5357
5458// DNSProvider implements the challenge.Provider interface.
5559type DNSProvider struct {
56- config * Config
57- client * internal.Client
60+ provider challenge.ProviderTimeout
5861}
5962
6063// NewDNSProvider returns a DNSProvider instance configured for hetzner.
6164// Credentials must be passed in the environment variable: HETZNER_API_KEY.
6265func NewDNSProvider () (* DNSProvider , error ) {
63- values , err := env .Get (EnvAPIKey )
64- if err != nil {
65- return nil , fmt .Errorf ("hetzner: %w" , err )
66- }
66+ _ , foundAPIToken := os .LookupEnv (EnvAPIToken )
67+ _ , foundAPIKey := os .LookupEnv (EnvAPIKey )
6768
68- config := NewDefaultConfig ()
69- config .APIKey = values [EnvAPIKey ]
69+ switch {
70+ case foundAPIToken :
71+ provider , err := hetznerv1 .NewDNSProvider ()
72+ if err != nil {
73+ return nil , err
74+ }
7075
71- return NewDNSProviderConfig (config )
76+ return & DNSProvider {provider : provider }, nil
77+
78+ case foundAPIKey :
79+ provider , err := legacy .NewDNSProvider ()
80+ if err != nil {
81+ return nil , err
82+ }
83+
84+ return & DNSProvider {provider : provider }, nil
85+
86+ default :
87+ provider , err := hetznerv1 .NewDNSProvider ()
88+ if err != nil {
89+ return nil , err
90+ }
91+
92+ return & DNSProvider {provider : provider }, nil
93+ }
7294}
7395
7496// NewDNSProviderConfig return a DNSProvider instance configured for hetzner.
@@ -77,98 +99,55 @@ func NewDNSProviderConfig(config *Config) (*DNSProvider, error) {
7799 return nil , errors .New ("hetzner: the configuration of the DNS provider is nil" )
78100 }
79101
80- if config .APIKey == "" {
81- return nil , errors .New ("hetzner: credentials missing" )
82- }
102+ switch {
103+ case config .APIToken != "" :
104+ cfg := & hetznerv1.Config {
105+ APIToken : config .APIToken ,
106+ PropagationTimeout : config .PropagationTimeout ,
107+ PollingInterval : config .PollingInterval ,
108+ TTL : config .TTL ,
109+ HTTPClient : config .HTTPClient ,
110+ }
83111
84- if config .TTL < minTTL {
85- return nil , fmt .Errorf ("hetzner: invalid TTL, TTL (%d) must be greater than %d" , config .TTL , minTTL )
86- }
112+ provider , err := hetznerv1 .NewDNSProviderConfig (cfg )
113+ if err != nil {
114+ return nil , err
115+ }
116+
117+ return & DNSProvider {provider : provider }, nil
87118
88- client := internal .NewClient (config .APIKey )
119+ case config .APIKey != "" :
120+ cfg := & legacy.Config {
121+ APIKey : config .APIKey ,
122+ PropagationTimeout : config .PropagationTimeout ,
123+ PollingInterval : config .PollingInterval ,
124+ TTL : config .TTL ,
125+ HTTPClient : config .HTTPClient ,
126+ }
89127
90- if config .HTTPClient != nil {
91- client .HTTPClient = config .HTTPClient
128+ provider , err := legacy .NewDNSProviderConfig (cfg )
129+ if err != nil {
130+ return nil , err
131+ }
132+
133+ return & DNSProvider {provider : provider }, nil
92134 }
93135
94- return & DNSProvider { config : config , client : client }, nil
136+ return nil , errors . New ( "hetzner: credentials missing" )
95137}
96138
97139// Timeout returns the timeout and interval to use when checking for DNS propagation.
98140// Adjusting here to cope with spikes in propagation times.
99141func (d * DNSProvider ) Timeout () (timeout , interval time.Duration ) {
100- return d .config . PropagationTimeout , d . config . PollingInterval
142+ return d .provider . Timeout ()
101143}
102144
103145// Present creates a TXT record to fulfill the dns-01 challenge.
104146func (d * DNSProvider ) Present (domain , token , keyAuth string ) error {
105- info := dns01 .GetChallengeInfo (domain , keyAuth )
106-
107- authZone , err := dns01 .FindZoneByFqdn (info .EffectiveFQDN )
108- if err != nil {
109- return fmt .Errorf ("hetzner: could not find zone for domain %q: %w" , domain , err )
110- }
111-
112- zone := dns01 .UnFqdn (authZone )
113-
114- ctx := context .Background ()
115-
116- zoneID , err := d .client .GetZoneID (ctx , zone )
117- if err != nil {
118- return fmt .Errorf ("hetzner: %w" , err )
119- }
120-
121- subDomain , err := dns01 .ExtractSubDomain (info .EffectiveFQDN , zone )
122- if err != nil {
123- return fmt .Errorf ("hetzner: %w" , err )
124- }
125-
126- record := internal.DNSRecord {
127- Type : "TXT" ,
128- Name : subDomain ,
129- Value : info .Value ,
130- TTL : d .config .TTL ,
131- ZoneID : zoneID ,
132- }
133-
134- if err := d .client .CreateRecord (ctx , record ); err != nil {
135- return fmt .Errorf ("hetzner: failed to add TXT record: fqdn=%s, zoneID=%s: %w" , info .EffectiveFQDN , zoneID , err )
136- }
137-
138- return nil
147+ return d .provider .Present (domain , token , keyAuth )
139148}
140149
141150// CleanUp removes the TXT record matching the specified parameters.
142151func (d * DNSProvider ) CleanUp (domain , token , keyAuth string ) error {
143- info := dns01 .GetChallengeInfo (domain , keyAuth )
144-
145- authZone , err := dns01 .FindZoneByFqdn (info .EffectiveFQDN )
146- if err != nil {
147- return fmt .Errorf ("hetzner: could not find zone for domain %q: %w" , domain , err )
148- }
149-
150- zone := dns01 .UnFqdn (authZone )
151-
152- ctx := context .Background ()
153-
154- zoneID , err := d .client .GetZoneID (ctx , zone )
155- if err != nil {
156- return fmt .Errorf ("hetzner: %w" , err )
157- }
158-
159- subDomain , err := dns01 .ExtractSubDomain (info .EffectiveFQDN , zone )
160- if err != nil {
161- return fmt .Errorf ("hetzner: %w" , err )
162- }
163-
164- record , err := d .client .GetTxtRecord (ctx , subDomain , info .Value , zoneID )
165- if err != nil {
166- return fmt .Errorf ("hetzner: %w" , err )
167- }
168-
169- if err := d .client .DeleteRecord (ctx , record .ID ); err != nil {
170- return fmt .Errorf ("hetzner: failed to delete TXT record: id=%s, name=%s: %w" , record .ID , record .Name , err )
171- }
172-
173- return nil
152+ return d .provider .CleanUp (domain , token , keyAuth )
174153}
0 commit comments