gandiv5: add Personal Access Token support (#2007)
This commit is contained in:
parent
766e581f8d
commit
113648a368
4 changed files with 39 additions and 26 deletions
|
@ -11,6 +11,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/go-acme/lego/v4/challenge/dns01"
|
||||
"github.com/go-acme/lego/v4/log"
|
||||
"github.com/go-acme/lego/v4/platform/config/env"
|
||||
"github.com/go-acme/lego/v4/providers/dns/gandiv5/internal"
|
||||
)
|
||||
|
@ -24,6 +25,7 @@ const (
|
|||
envNamespace = "GANDIV5_"
|
||||
|
||||
EnvAPIKey = envNamespace + "API_KEY"
|
||||
EnvPersonalAccessToken = envNamespace + "PERSONAL_ACCESS_TOKEN"
|
||||
|
||||
EnvTTL = envNamespace + "TTL"
|
||||
EnvPropagationTimeout = envNamespace + "PROPAGATION_TIMEOUT"
|
||||
|
@ -40,7 +42,8 @@ type inProgressInfo struct {
|
|||
// Config is used to configure the creation of the DNSProvider.
|
||||
type Config struct {
|
||||
BaseURL string
|
||||
APIKey string
|
||||
APIKey string // Deprecated use PersonalAccessToken
|
||||
PersonalAccessToken string
|
||||
PropagationTimeout time.Duration
|
||||
PollingInterval time.Duration
|
||||
TTL int
|
||||
|
@ -76,13 +79,10 @@ type DNSProvider struct {
|
|||
// NewDNSProvider returns a DNSProvider instance configured for Gandi.
|
||||
// Credentials must be passed in the environment variable: GANDIV5_API_KEY.
|
||||
func NewDNSProvider() (*DNSProvider, error) {
|
||||
values, err := env.Get(EnvAPIKey)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("gandi: %w", err)
|
||||
}
|
||||
|
||||
// TODO(ldez): rewrite this when APIKey will be removed.
|
||||
config := NewDefaultConfig()
|
||||
config.APIKey = values[EnvAPIKey]
|
||||
config.APIKey = env.GetOrFile(EnvAPIKey)
|
||||
config.PersonalAccessToken = env.GetOrFile(EnvPersonalAccessToken)
|
||||
|
||||
return NewDNSProviderConfig(config)
|
||||
}
|
||||
|
@ -93,15 +93,19 @@ func NewDNSProviderConfig(config *Config) (*DNSProvider, error) {
|
|||
return nil, errors.New("gandiv5: the configuration of the DNS provider is nil")
|
||||
}
|
||||
|
||||
if config.APIKey == "" {
|
||||
return nil, errors.New("gandiv5: no API Key given")
|
||||
if config.APIKey != "" {
|
||||
log.Print("gandiv5: API Key is deprecated, use Personal Access Token instead")
|
||||
}
|
||||
|
||||
if config.APIKey == "" && config.PersonalAccessToken == "" {
|
||||
return nil, errors.New("gandiv5: credentials information are missing")
|
||||
}
|
||||
|
||||
if config.TTL < minTTL {
|
||||
return nil, fmt.Errorf("gandiv5: invalid TTL, TTL (%d) must be greater than %d", config.TTL, minTTL)
|
||||
}
|
||||
|
||||
client := internal.NewClient(config.APIKey)
|
||||
client := internal.NewClient(config.APIKey, config.PersonalAccessToken)
|
||||
|
||||
if config.BaseURL != "" {
|
||||
baseURL, err := url.Parse(config.BaseURL)
|
||||
|
|
|
@ -5,13 +5,14 @@ Code = "gandiv5"
|
|||
Since = "v0.5.0"
|
||||
|
||||
Example = '''
|
||||
GANDIV5_API_KEY=abcdefghijklmnopqrstuvwx \
|
||||
GANDIV5_PERSONAL_ACCESS_TOKEN=abcdefghijklmnopqrstuvwx \
|
||||
lego --email you@example.com --dns gandiv5 --domains my.example.org run
|
||||
'''
|
||||
|
||||
[Configuration]
|
||||
[Configuration.Credentials]
|
||||
GANDIV5_API_KEY = "API key"
|
||||
GANDIV5_PERSONAL_ACCESS_TOKEN = "Personal Access Token"
|
||||
GANDIV5_API_KEY = "API key (Deprecated)"
|
||||
[Configuration.Additional]
|
||||
GANDIV5_POLLING_INTERVAL = "Time between DNS propagation check"
|
||||
GANDIV5_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation"
|
||||
|
|
|
@ -10,11 +10,10 @@ import (
|
|||
|
||||
"github.com/go-acme/lego/v4/log"
|
||||
"github.com/go-acme/lego/v4/platform/tester"
|
||||
"github.com/go-acme/lego/v4/providers/dns/gandiv5/internal"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
var envTest = tester.NewEnvTest(EnvAPIKey)
|
||||
var envTest = tester.NewEnvTest(EnvAPIKey, EnvPersonalAccessToken)
|
||||
|
||||
func TestNewDNSProvider(t *testing.T) {
|
||||
testCases := []struct {
|
||||
|
@ -33,7 +32,7 @@ func TestNewDNSProvider(t *testing.T) {
|
|||
envVars: map[string]string{
|
||||
EnvAPIKey: "",
|
||||
},
|
||||
expected: "gandi: some credentials information are missing: GANDIV5_API_KEY",
|
||||
expected: "gandiv5: credentials information are missing",
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -70,7 +69,7 @@ func TestNewDNSProviderConfig(t *testing.T) {
|
|||
},
|
||||
{
|
||||
desc: "missing credentials",
|
||||
expected: "gandiv5: no API Key given",
|
||||
expected: "gandiv5: credentials information are missing",
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -122,8 +121,8 @@ func TestDNSProvider(t *testing.T) {
|
|||
mux.HandleFunc("/domains/example.com/records/_acme-challenge.abc.def/TXT", func(rw http.ResponseWriter, req *http.Request) {
|
||||
log.Infof("request: %s %s", req.Method, req.URL)
|
||||
|
||||
if req.Header.Get(internal.APIKeyHeader) == "" {
|
||||
http.Error(rw, `{"message": "missing API key"}`, http.StatusUnauthorized)
|
||||
if req.Header.Get("Authorization") == "" {
|
||||
http.Error(rw, `{"message": "missing Authorization"}`, http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -165,7 +164,7 @@ func TestDNSProvider(t *testing.T) {
|
|||
}
|
||||
|
||||
config := NewDefaultConfig()
|
||||
config.APIKey = "123412341234123412341234"
|
||||
config.PersonalAccessToken = "123412341234123412341234"
|
||||
config.BaseURL = server.URL
|
||||
|
||||
provider, err := NewDNSProviderConfig(config)
|
||||
|
|
|
@ -20,20 +20,25 @@ const defaultBaseURL = "https://dns.api.gandi.net/api/v5"
|
|||
// APIKeyHeader API key header.
|
||||
const APIKeyHeader = "X-Api-Key"
|
||||
|
||||
// Related to Personal Access Token.
|
||||
const authorizationHeader = "Authorization"
|
||||
|
||||
// Client the Gandi API v5 client.
|
||||
type Client struct {
|
||||
apiKey string
|
||||
pat string
|
||||
|
||||
BaseURL *url.URL
|
||||
HTTPClient *http.Client
|
||||
}
|
||||
|
||||
// NewClient Creates a new Client.
|
||||
func NewClient(apiKey string) *Client {
|
||||
func NewClient(apiKey, pat string) *Client {
|
||||
baseURL, _ := url.Parse(defaultBaseURL)
|
||||
|
||||
return &Client{
|
||||
apiKey: apiKey,
|
||||
pat: pat,
|
||||
BaseURL: baseURL,
|
||||
HTTPClient: &http.Client{Timeout: 5 * time.Second},
|
||||
}
|
||||
|
@ -128,6 +133,10 @@ func (c *Client) do(req *http.Request, result any) error {
|
|||
req.Header.Set(APIKeyHeader, c.apiKey)
|
||||
}
|
||||
|
||||
if c.pat != "" {
|
||||
req.Header.Set(authorizationHeader, c.pat)
|
||||
}
|
||||
|
||||
resp, err := c.HTTPClient.Do(req)
|
||||
if err != nil {
|
||||
return errutils.NewHTTPDoError(req, err)
|
||||
|
|
Loading…
Reference in a new issue