Skip to content

Commit 113648a

Browse files
authored
gandiv5: add Personal Access Token support (#2007)
1 parent 766e581 commit 113648a

File tree

4 files changed

+39
-26
lines changed

4 files changed

+39
-26
lines changed

providers/dns/gandiv5/gandiv5.go

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"time"
1212

1313
"github.com/go-acme/lego/v4/challenge/dns01"
14+
"github.com/go-acme/lego/v4/log"
1415
"github.com/go-acme/lego/v4/platform/config/env"
1516
"github.com/go-acme/lego/v4/providers/dns/gandiv5/internal"
1617
)
@@ -23,7 +24,8 @@ const minTTL = 300
2324
const (
2425
envNamespace = "GANDIV5_"
2526

26-
EnvAPIKey = envNamespace + "API_KEY"
27+
EnvAPIKey = envNamespace + "API_KEY"
28+
EnvPersonalAccessToken = envNamespace + "PERSONAL_ACCESS_TOKEN"
2729

2830
EnvTTL = envNamespace + "TTL"
2931
EnvPropagationTimeout = envNamespace + "PROPAGATION_TIMEOUT"
@@ -39,12 +41,13 @@ type inProgressInfo struct {
3941

4042
// Config is used to configure the creation of the DNSProvider.
4143
type Config struct {
42-
BaseURL string
43-
APIKey string
44-
PropagationTimeout time.Duration
45-
PollingInterval time.Duration
46-
TTL int
47-
HTTPClient *http.Client
44+
BaseURL string
45+
APIKey string // Deprecated use PersonalAccessToken
46+
PersonalAccessToken string
47+
PropagationTimeout time.Duration
48+
PollingInterval time.Duration
49+
TTL int
50+
HTTPClient *http.Client
4851
}
4952

5053
// NewDefaultConfig returns a default configuration for the DNSProvider.
@@ -76,13 +79,10 @@ type DNSProvider struct {
7679
// NewDNSProvider returns a DNSProvider instance configured for Gandi.
7780
// Credentials must be passed in the environment variable: GANDIV5_API_KEY.
7881
func NewDNSProvider() (*DNSProvider, error) {
79-
values, err := env.Get(EnvAPIKey)
80-
if err != nil {
81-
return nil, fmt.Errorf("gandi: %w", err)
82-
}
83-
82+
// TODO(ldez): rewrite this when APIKey will be removed.
8483
config := NewDefaultConfig()
85-
config.APIKey = values[EnvAPIKey]
84+
config.APIKey = env.GetOrFile(EnvAPIKey)
85+
config.PersonalAccessToken = env.GetOrFile(EnvPersonalAccessToken)
8686

8787
return NewDNSProviderConfig(config)
8888
}
@@ -93,15 +93,19 @@ func NewDNSProviderConfig(config *Config) (*DNSProvider, error) {
9393
return nil, errors.New("gandiv5: the configuration of the DNS provider is nil")
9494
}
9595

96-
if config.APIKey == "" {
97-
return nil, errors.New("gandiv5: no API Key given")
96+
if config.APIKey != "" {
97+
log.Print("gandiv5: API Key is deprecated, use Personal Access Token instead")
98+
}
99+
100+
if config.APIKey == "" && config.PersonalAccessToken == "" {
101+
return nil, errors.New("gandiv5: credentials information are missing")
98102
}
99103

100104
if config.TTL < minTTL {
101105
return nil, fmt.Errorf("gandiv5: invalid TTL, TTL (%d) must be greater than %d", config.TTL, minTTL)
102106
}
103107

104-
client := internal.NewClient(config.APIKey)
108+
client := internal.NewClient(config.APIKey, config.PersonalAccessToken)
105109

106110
if config.BaseURL != "" {
107111
baseURL, err := url.Parse(config.BaseURL)

providers/dns/gandiv5/gandiv5.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,14 @@ Code = "gandiv5"
55
Since = "v0.5.0"
66

77
Example = '''
8-
GANDIV5_API_KEY=abcdefghijklmnopqrstuvwx \
8+
GANDIV5_PERSONAL_ACCESS_TOKEN=abcdefghijklmnopqrstuvwx \
99
lego --email [email protected] --dns gandiv5 --domains my.example.org run
1010
'''
1111

1212
[Configuration]
1313
[Configuration.Credentials]
14-
GANDIV5_API_KEY = "API key"
14+
GANDIV5_PERSONAL_ACCESS_TOKEN = "Personal Access Token"
15+
GANDIV5_API_KEY = "API key (Deprecated)"
1516
[Configuration.Additional]
1617
GANDIV5_POLLING_INTERVAL = "Time between DNS propagation check"
1718
GANDIV5_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation"

providers/dns/gandiv5/gandiv5_test.go

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,10 @@ import (
1010

1111
"github.com/go-acme/lego/v4/log"
1212
"github.com/go-acme/lego/v4/platform/tester"
13-
"github.com/go-acme/lego/v4/providers/dns/gandiv5/internal"
1413
"github.com/stretchr/testify/require"
1514
)
1615

17-
var envTest = tester.NewEnvTest(EnvAPIKey)
16+
var envTest = tester.NewEnvTest(EnvAPIKey, EnvPersonalAccessToken)
1817

1918
func TestNewDNSProvider(t *testing.T) {
2019
testCases := []struct {
@@ -33,7 +32,7 @@ func TestNewDNSProvider(t *testing.T) {
3332
envVars: map[string]string{
3433
EnvAPIKey: "",
3534
},
36-
expected: "gandi: some credentials information are missing: GANDIV5_API_KEY",
35+
expected: "gandiv5: credentials information are missing",
3736
},
3837
}
3938

@@ -70,7 +69,7 @@ func TestNewDNSProviderConfig(t *testing.T) {
7069
},
7170
{
7271
desc: "missing credentials",
73-
expected: "gandiv5: no API Key given",
72+
expected: "gandiv5: credentials information are missing",
7473
},
7574
}
7675

@@ -122,8 +121,8 @@ func TestDNSProvider(t *testing.T) {
122121
mux.HandleFunc("/domains/example.com/records/_acme-challenge.abc.def/TXT", func(rw http.ResponseWriter, req *http.Request) {
123122
log.Infof("request: %s %s", req.Method, req.URL)
124123

125-
if req.Header.Get(internal.APIKeyHeader) == "" {
126-
http.Error(rw, `{"message": "missing API key"}`, http.StatusUnauthorized)
124+
if req.Header.Get("Authorization") == "" {
125+
http.Error(rw, `{"message": "missing Authorization"}`, http.StatusUnauthorized)
127126
return
128127
}
129128

@@ -165,7 +164,7 @@ func TestDNSProvider(t *testing.T) {
165164
}
166165

167166
config := NewDefaultConfig()
168-
config.APIKey = "123412341234123412341234"
167+
config.PersonalAccessToken = "123412341234123412341234"
169168
config.BaseURL = server.URL
170169

171170
provider, err := NewDNSProviderConfig(config)

providers/dns/gandiv5/internal/client.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,20 +20,25 @@ const defaultBaseURL = "https://dns.api.gandi.net/api/v5"
2020
// APIKeyHeader API key header.
2121
const APIKeyHeader = "X-Api-Key"
2222

23+
// Related to Personal Access Token.
24+
const authorizationHeader = "Authorization"
25+
2326
// Client the Gandi API v5 client.
2427
type Client struct {
2528
apiKey string
29+
pat string
2630

2731
BaseURL *url.URL
2832
HTTPClient *http.Client
2933
}
3034

3135
// NewClient Creates a new Client.
32-
func NewClient(apiKey string) *Client {
36+
func NewClient(apiKey, pat string) *Client {
3337
baseURL, _ := url.Parse(defaultBaseURL)
3438

3539
return &Client{
3640
apiKey: apiKey,
41+
pat: pat,
3742
BaseURL: baseURL,
3843
HTTPClient: &http.Client{Timeout: 5 * time.Second},
3944
}
@@ -128,6 +133,10 @@ func (c *Client) do(req *http.Request, result any) error {
128133
req.Header.Set(APIKeyHeader, c.apiKey)
129134
}
130135

136+
if c.pat != "" {
137+
req.Header.Set(authorizationHeader, c.pat)
138+
}
139+
131140
resp, err := c.HTTPClient.Do(req)
132141
if err != nil {
133142
return errutils.NewHTTPDoError(req, err)

0 commit comments

Comments
 (0)