Skip to content

Commit f0c314c

Browse files
authored
hetzner: update to new API (#2663)
1 parent 213d7b8 commit f0c314c

35 files changed

+1583
-165
lines changed

cmd/zz_gen_cmd_dnshelp.go

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/content/dns/zz_gen_hetzner.md

Lines changed: 5 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/content/dns/zz_gen_hetznerv1.md

Lines changed: 67 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

providers/dns/hetzner/hetzner.go

Lines changed: 76 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -2,28 +2,28 @@
22
package hetzner
33

44
import (
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.
1818
const (
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

2929
const minTTL = 60
@@ -32,7 +32,11 @@ var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
3232

3333
// Config is used to configure the creation of the DNSProvider.
3434
type 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.
5559
type 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.
6265
func 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.
99141
func (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.
104146
func (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.
142151
func (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
}

providers/dns/hetzner/hetzner.toml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,18 @@ Code = "hetzner"
55
Since = "v3.7.0"
66

77
Example = '''
8-
HETZNER_API_KEY=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx \
8+
HETZNER_API_TOKEN="xxxxxxxxxxxxxxxxxxxxx" \
99
lego --email [email protected] --dns hetzner -d '*.example.com' -d example.com run
1010
'''
1111

1212
[Configuration]
1313
[Configuration.Credentials]
14-
HETZNER_API_KEY = "API key"
14+
HETZNER_API_TOKEN = "API token"
1515
[Configuration.Additional]
1616
HETZNER_POLLING_INTERVAL = "Time between DNS propagation check in seconds (Default: 2)"
17-
HETZNER_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation in seconds (Default: 120)"
18-
HETZNER_TTL = "The TTL of the TXT record used for the DNS challenge in seconds (Default: 60)"
17+
HETZNER_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation in seconds (Default: 60)"
18+
HETZNER_TTL = "The TTL of the TXT record used for the DNS challenge in seconds (Default: 120)"
1919
HETZNER_HTTP_TIMEOUT = "API request timeout in seconds (Default: 30)"
2020

2121
[Links]
22-
API = "https://dns.hetzner.com/api-docs"
22+
API = "https://docs.hetzner.cloud/reference/cloud#dns"

0 commit comments

Comments
 (0)