forked from TrueCloudLab/lego
Make DNS provider credential-handling more consistent.
Different DNS providers were handling credentials in different ways. Some were reading credential environment variables in cli_handlers.go and then passing them into the NewDNSProvider function, while others were reading the environment variables within their NewDNSProvider functions. This change replaces each DNS challenge's NewDNSProvider function with two new functions: (1) a NewDNSProvider function that takes no parameters and uses the environment to read credentials, and (2) a NewDNSProviderCredentials that takes credentials as parameters.
This commit is contained in:
parent
43c55a690f
commit
47219adc00
18 changed files with 214 additions and 160 deletions
|
@ -14,12 +14,12 @@ import (
|
|||
"github.com/xenolf/lego/providers/dns/cloudflare"
|
||||
"github.com/xenolf/lego/providers/dns/digitalocean"
|
||||
"github.com/xenolf/lego/providers/dns/dnsimple"
|
||||
"github.com/xenolf/lego/providers/dns/dyn"
|
||||
"github.com/xenolf/lego/providers/dns/gandi"
|
||||
"github.com/xenolf/lego/providers/dns/googlecloud"
|
||||
"github.com/xenolf/lego/providers/dns/namecheap"
|
||||
"github.com/xenolf/lego/providers/dns/rfc2136"
|
||||
"github.com/xenolf/lego/providers/dns/route53"
|
||||
"github.com/xenolf/lego/providers/dns/dyn"
|
||||
"github.com/xenolf/lego/providers/http/webroot"
|
||||
)
|
||||
|
||||
|
@ -89,38 +89,25 @@ func setup(c *cli.Context) (*Configuration, *Account, *acme.Client) {
|
|||
var provider acme.ChallengeProvider
|
||||
switch c.GlobalString("dns") {
|
||||
case "cloudflare":
|
||||
provider, err = cloudflare.NewDNSProvider("", "")
|
||||
provider, err = cloudflare.NewDNSProvider()
|
||||
case "digitalocean":
|
||||
authToken := os.Getenv("DO_AUTH_TOKEN")
|
||||
|
||||
provider, err = digitalocean.NewDNSProvider(authToken)
|
||||
provider, err = digitalocean.NewDNSProvider()
|
||||
case "dnsimple":
|
||||
provider, err = dnsimple.NewDNSProvider("", "")
|
||||
case "gandi":
|
||||
apiKey := os.Getenv("GANDI_API_KEY")
|
||||
provider, err = gandi.NewDNSProvider(apiKey)
|
||||
case "gcloud":
|
||||
provider, err = googlecloud.NewDNSProvider("")
|
||||
case "namecheap":
|
||||
provider, err = namecheap.NewDNSProvider("", "")
|
||||
case "route53":
|
||||
awsRegion := os.Getenv("AWS_REGION")
|
||||
provider, err = route53.NewDNSProvider("", "", awsRegion)
|
||||
case "rfc2136":
|
||||
nameserver := os.Getenv("RFC2136_NAMESERVER")
|
||||
tsigAlgorithm := os.Getenv("RFC2136_TSIG_ALGORITHM")
|
||||
tsigKey := os.Getenv("RFC2136_TSIG_KEY")
|
||||
tsigSecret := os.Getenv("RFC2136_TSIG_SECRET")
|
||||
|
||||
provider, err = rfc2136.NewDNSProvider(nameserver, tsigAlgorithm, tsigKey, tsigSecret)
|
||||
provider, err = dnsimple.NewDNSProvider()
|
||||
case "dyn":
|
||||
dynCustomerName := os.Getenv("DYN_CUSTOMER_NAME")
|
||||
dynUserName := os.Getenv("DYN_USER_NAME")
|
||||
dynPassword := os.Getenv("DYN_PASSWORD")
|
||||
|
||||
provider, err = dyn.NewDNSProvider(dynCustomerName, dynUserName, dynPassword)
|
||||
provider, err = dyn.NewDNSProvider()
|
||||
case "gandi":
|
||||
provider, err = gandi.NewDNSProvider()
|
||||
case "gcloud":
|
||||
provider, err = googlecloud.NewDNSProvider()
|
||||
case "manual":
|
||||
provider, err = acme.NewDNSProviderManual()
|
||||
case "namecheap":
|
||||
provider, err = namecheap.NewDNSProvider()
|
||||
case "route53":
|
||||
provider, err = route53.NewDNSProvider()
|
||||
case "rfc2136":
|
||||
provider, err = rfc2136.NewDNSProvider()
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
// Package cloudflare implements a DNS provider for solving the DNS-01 challenge using cloudflare DNS.
|
||||
// Package cloudflare implements a DNS provider for solving the DNS-01
|
||||
// challenge using cloudflare DNS.
|
||||
package cloudflare
|
||||
|
||||
import (
|
||||
|
@ -24,19 +25,25 @@ type DNSProvider struct {
|
|||
authKey string
|
||||
}
|
||||
|
||||
// NewDNSProvider returns a DNSProvider instance with a configured cloudflare client.
|
||||
// Credentials can either be passed as arguments or through CLOUDFLARE_EMAIL and CLOUDFLARE_API_KEY env vars.
|
||||
func NewDNSProvider(cloudflareEmail, cloudflareKey string) (*DNSProvider, error) {
|
||||
if cloudflareEmail == "" || cloudflareKey == "" {
|
||||
cloudflareEmail, cloudflareKey = cloudflareEnvAuth()
|
||||
if cloudflareEmail == "" || cloudflareKey == "" {
|
||||
// NewDNSProvider returns a DNSProvider instance configured for cloudflare.
|
||||
// Credentials must be passed in the environment variables: CLOUDFLARE_EMAIL
|
||||
// and CLOUDFLARE_API_KEY.
|
||||
func NewDNSProvider() (*DNSProvider, error) {
|
||||
email := os.Getenv("CLOUDFLARE_EMAIL")
|
||||
key := os.Getenv("CLOUDFLARE_API_KEY")
|
||||
return NewDNSProviderCredentials(email, key)
|
||||
}
|
||||
|
||||
// NewDNSProviderCredentials uses the supplied credentials to return a
|
||||
// DNSProvider instance configured for cloudflare.
|
||||
func NewDNSProviderCredentials(email, key string) (*DNSProvider, error) {
|
||||
if email == "" || key == "" {
|
||||
return nil, fmt.Errorf("CloudFlare credentials missing")
|
||||
}
|
||||
}
|
||||
|
||||
return &DNSProvider{
|
||||
authEmail: cloudflareEmail,
|
||||
authKey: cloudflareKey,
|
||||
authEmail: email,
|
||||
authKey: key,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -192,15 +199,6 @@ func (c *DNSProvider) makeRequest(method, uri string, body io.Reader) (json.RawM
|
|||
return r.Result, nil
|
||||
}
|
||||
|
||||
func cloudflareEnvAuth() (email, apiKey string) {
|
||||
email = os.Getenv("CLOUDFLARE_EMAIL")
|
||||
apiKey = os.Getenv("CLOUDFLARE_API_KEY")
|
||||
if len(email) == 0 || len(apiKey) == 0 {
|
||||
return "", ""
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// cloudFlareRecord represents a CloudFlare DNS record
|
||||
type cloudFlareRecord struct {
|
||||
Name string `json:"name"`
|
||||
|
|
|
@ -32,7 +32,7 @@ func restoreCloudFlareEnv() {
|
|||
func TestNewDNSProviderValid(t *testing.T) {
|
||||
os.Setenv("CLOUDFLARE_EMAIL", "")
|
||||
os.Setenv("CLOUDFLARE_API_KEY", "")
|
||||
_, err := NewDNSProvider("123", "123")
|
||||
_, err := NewDNSProviderCredentials("123", "123")
|
||||
assert.NoError(t, err)
|
||||
restoreCloudFlareEnv()
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ func TestNewDNSProviderValid(t *testing.T) {
|
|||
func TestNewDNSProviderValidEnv(t *testing.T) {
|
||||
os.Setenv("CLOUDFLARE_EMAIL", "test@example.com")
|
||||
os.Setenv("CLOUDFLARE_API_KEY", "123")
|
||||
_, err := NewDNSProvider("", "")
|
||||
_, err := NewDNSProvider()
|
||||
assert.NoError(t, err)
|
||||
restoreCloudFlareEnv()
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ func TestNewDNSProviderValidEnv(t *testing.T) {
|
|||
func TestNewDNSProviderMissingCredErr(t *testing.T) {
|
||||
os.Setenv("CLOUDFLARE_EMAIL", "")
|
||||
os.Setenv("CLOUDFLARE_API_KEY", "")
|
||||
_, err := NewDNSProvider("", "")
|
||||
_, err := NewDNSProvider()
|
||||
assert.EqualError(t, err, "CloudFlare credentials missing")
|
||||
restoreCloudFlareEnv()
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ func TestCloudFlarePresent(t *testing.T) {
|
|||
t.Skip("skipping live test")
|
||||
}
|
||||
|
||||
provider, err := NewDNSProvider(cflareEmail, cflareAPIKey)
|
||||
provider, err := NewDNSProviderCredentials(cflareEmail, cflareAPIKey)
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = provider.Present(cflareDomain, "", "123d==")
|
||||
|
@ -72,7 +72,7 @@ func TestCloudFlareCleanUp(t *testing.T) {
|
|||
|
||||
time.Sleep(time.Second * 2)
|
||||
|
||||
provider, err := NewDNSProvider(cflareEmail, cflareAPIKey)
|
||||
provider, err := NewDNSProviderCredentials(cflareEmail, cflareAPIKey)
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = provider.CleanUp(cflareDomain, "", "123d==")
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
// Package digitalocean implements a DNS provider for solving the DNS-01 challenge using digitalocean DNS.
|
||||
// Package digitalocean implements a DNS provider for solving the DNS-01
|
||||
// challenge using digitalocean DNS.
|
||||
package digitalocean
|
||||
|
||||
import (
|
||||
|
@ -6,6 +7,7 @@ import (
|
|||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
|
@ -20,10 +22,20 @@ type DNSProvider struct {
|
|||
recordIDsMu sync.Mutex
|
||||
}
|
||||
|
||||
// NewDNSProvider returns a new DNSProvider instance.
|
||||
// apiAuthToken is the personal access token created in the DigitalOcean account
|
||||
// control panel, and it will be sent in bearer authorization headers.
|
||||
func NewDNSProvider(apiAuthToken string) (*DNSProvider, error) {
|
||||
// NewDNSProvider returns a DNSProvider instance configured for Digital
|
||||
// Ocean. Credentials must be passed in the environment variable:
|
||||
// DO_AUTH_TOKEN.
|
||||
func NewDNSProvider() (*DNSProvider, error) {
|
||||
apiAuthToken := os.Getenv("DO_AUTH_TOKEN")
|
||||
return NewDNSProviderCredentials(apiAuthToken)
|
||||
}
|
||||
|
||||
// NewDNSProviderCredentials uses the supplied credentials to return a
|
||||
// DNSProvider instance configured for Digital Ocean.
|
||||
func NewDNSProviderCredentials(apiAuthToken string) (*DNSProvider, error) {
|
||||
if apiAuthToken == "" {
|
||||
return nil, fmt.Errorf("DigitalOcean credentials missing")
|
||||
}
|
||||
return &DNSProvider{
|
||||
apiAuthToken: apiAuthToken,
|
||||
recordIDs: make(map[string]int),
|
||||
|
|
|
@ -53,7 +53,7 @@ func TestDigitalOceanPresent(t *testing.T) {
|
|||
defer mock.Close()
|
||||
digitalOceanBaseURL = mock.URL
|
||||
|
||||
doprov, err := NewDNSProvider(fakeDigitalOceanAuth)
|
||||
doprov, err := NewDNSProviderCredentials(fakeDigitalOceanAuth)
|
||||
if doprov == nil {
|
||||
t.Fatal("Expected non-nil DigitalOcean provider, but was nil")
|
||||
}
|
||||
|
@ -95,7 +95,7 @@ func TestDigitalOceanCleanUp(t *testing.T) {
|
|||
defer mock.Close()
|
||||
digitalOceanBaseURL = mock.URL
|
||||
|
||||
doprov, err := NewDNSProvider(fakeDigitalOceanAuth)
|
||||
doprov, err := NewDNSProviderCredentials(fakeDigitalOceanAuth)
|
||||
if doprov == nil {
|
||||
t.Fatal("Expected non-nil DigitalOcean provider, but was nil")
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
// Package dnsimple implements a DNS provider for solving the DNS-01 challenge using dnsimple DNS.
|
||||
// Package dnsimple implements a DNS provider for solving the DNS-01 challenge
|
||||
// using dnsimple DNS.
|
||||
package dnsimple
|
||||
|
||||
import (
|
||||
|
@ -15,22 +16,25 @@ type DNSProvider struct {
|
|||
client *dnsimple.Client
|
||||
}
|
||||
|
||||
// NewDNSProvider returns a DNSProvider instance with a configured dnsimple client.
|
||||
// Authentication is either done using the passed credentials or - when empty - using the environment
|
||||
// variables DNSIMPLE_EMAIL and DNSIMPLE_API_KEY.
|
||||
func NewDNSProvider(dnsimpleEmail, dnsimpleAPIKey string) (*DNSProvider, error) {
|
||||
if dnsimpleEmail == "" || dnsimpleAPIKey == "" {
|
||||
dnsimpleEmail, dnsimpleAPIKey = dnsimpleEnvAuth()
|
||||
if dnsimpleEmail == "" || dnsimpleAPIKey == "" {
|
||||
// NewDNSProvider returns a DNSProvider instance configured for dnsimple.
|
||||
// Credentials must be passed in the environment variables: DNSIMPLE_EMAIL
|
||||
// and DNSIMPLE_API_KEY.
|
||||
func NewDNSProvider() (*DNSProvider, error) {
|
||||
email := os.Getenv("DNSIMPLE_EMAIL")
|
||||
key := os.Getenv("DNSIMPLE_API_KEY")
|
||||
return NewDNSProviderCredentials(email, key)
|
||||
}
|
||||
|
||||
// NewDNSProviderCredentials uses the supplied credentials to return a
|
||||
// DNSProvider instance configured for dnsimple.
|
||||
func NewDNSProviderCredentials(email, key string) (*DNSProvider, error) {
|
||||
if email == "" || key == "" {
|
||||
return nil, fmt.Errorf("DNSimple credentials missing")
|
||||
}
|
||||
}
|
||||
|
||||
c := &DNSProvider{
|
||||
client: dnsimple.NewClient(dnsimpleAPIKey, dnsimpleEmail),
|
||||
}
|
||||
|
||||
return c, nil
|
||||
return &DNSProvider{
|
||||
client: dnsimple.NewClient(key, email),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Present creates a TXT record to fulfil the dns-01 challenge.
|
||||
|
@ -130,12 +134,3 @@ func (c *DNSProvider) extractRecordName(fqdn, domain string) string {
|
|||
}
|
||||
return name
|
||||
}
|
||||
|
||||
func dnsimpleEnvAuth() (email, apiKey string) {
|
||||
email = os.Getenv("DNSIMPLE_EMAIL")
|
||||
apiKey = os.Getenv("DNSIMPLE_API_KEY")
|
||||
if len(email) == 0 || len(apiKey) == 0 {
|
||||
return "", ""
|
||||
}
|
||||
return
|
||||
}
|
||||
|
|
|
@ -32,14 +32,14 @@ func restoreDNSimpleEnv() {
|
|||
func TestNewDNSProviderValid(t *testing.T) {
|
||||
os.Setenv("DNSIMPLE_EMAIL", "")
|
||||
os.Setenv("DNSIMPLE_API_KEY", "")
|
||||
_, err := NewDNSProvider("example@example.com", "123")
|
||||
_, err := NewDNSProviderCredentials("example@example.com", "123")
|
||||
assert.NoError(t, err)
|
||||
restoreDNSimpleEnv()
|
||||
}
|
||||
func TestNewDNSProviderValidEnv(t *testing.T) {
|
||||
os.Setenv("DNSIMPLE_EMAIL", "example@example.com")
|
||||
os.Setenv("DNSIMPLE_API_KEY", "123")
|
||||
_, err := NewDNSProvider("", "")
|
||||
_, err := NewDNSProvider()
|
||||
assert.NoError(t, err)
|
||||
restoreDNSimpleEnv()
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ func TestNewDNSProviderValidEnv(t *testing.T) {
|
|||
func TestNewDNSProviderMissingCredErr(t *testing.T) {
|
||||
os.Setenv("DNSIMPLE_EMAIL", "")
|
||||
os.Setenv("DNSIMPLE_API_KEY", "")
|
||||
_, err := NewDNSProvider("", "")
|
||||
_, err := NewDNSProvider()
|
||||
assert.EqualError(t, err, "DNSimple credentials missing")
|
||||
restoreDNSimpleEnv()
|
||||
}
|
||||
|
@ -57,7 +57,7 @@ func TestLiveDNSimplePresent(t *testing.T) {
|
|||
t.Skip("skipping live test")
|
||||
}
|
||||
|
||||
provider, err := NewDNSProvider(dnsimpleEmail, dnsimpleAPIKey)
|
||||
provider, err := NewDNSProviderCredentials(dnsimpleEmail, dnsimpleAPIKey)
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = provider.Present(dnsimpleDomain, "", "123d==")
|
||||
|
@ -71,7 +71,7 @@ func TestLiveDNSimpleCleanUp(t *testing.T) {
|
|||
|
||||
time.Sleep(time.Second * 1)
|
||||
|
||||
provider, err := NewDNSProvider(dnsimpleEmail, dnsimpleAPIKey)
|
||||
provider, err := NewDNSProviderCredentials(dnsimpleEmail, dnsimpleAPIKey)
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = provider.CleanUp(dnsimpleDomain, "", "123d==")
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
// Package dyn implements a DNS provider for solving the DNS-01 challenge using Dyn Managed DNS.
|
||||
// Package dyn implements a DNS provider for solving the DNS-01 challenge
|
||||
// using Dyn Managed DNS.
|
||||
package dyn
|
||||
|
||||
import (
|
||||
|
@ -6,6 +7,7 @@ import (
|
|||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
|
@ -37,10 +39,23 @@ type DNSProvider struct {
|
|||
token string
|
||||
}
|
||||
|
||||
// NewDNSProvider returns a new DNSProvider instance. customerName is
|
||||
// the customer name of the Dyn account. userName is the user name. password is
|
||||
// the password.
|
||||
func NewDNSProvider(customerName, userName, password string) (*DNSProvider, error) {
|
||||
// NewDNSProvider returns a DNSProvider instance configured for Dyn DNS.
|
||||
// Credentials must be passed in the environment variables: DYN_CUSTOMER_NAME,
|
||||
// DYN_USER_NAME and DYN_PASSWORD.
|
||||
func NewDNSProvider() (*DNSProvider, error) {
|
||||
customerName := os.Getenv("DYN_CUSTOMER_NAME")
|
||||
userName := os.Getenv("DYN_USER_NAME")
|
||||
password := os.Getenv("DYN_PASSWORD")
|
||||
return NewDNSProviderCredentials(customerName, userName, password)
|
||||
}
|
||||
|
||||
// NewDNSProviderCredentials uses the supplied credentials to return a
|
||||
// DNSProvider instance configured for Dyn DNS.
|
||||
func NewDNSProviderCredentials(customerName, userName, password string) (*DNSProvider, error) {
|
||||
if customerName == "" || userName == "" || password == "" {
|
||||
return nil, fmt.Errorf("DynDNS credentials missing")
|
||||
}
|
||||
|
||||
return &DNSProvider{
|
||||
customerName: customerName,
|
||||
userName: userName,
|
||||
|
|
|
@ -31,7 +31,7 @@ func TestLiveDynPresent(t *testing.T) {
|
|||
t.Skip("skipping live test")
|
||||
}
|
||||
|
||||
provider, err := NewDNSProvider(dynCustomerName, dynUserName, dynPassword)
|
||||
provider, err := NewDNSProvider()
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = provider.Present(dynDomain, "", "123d==")
|
||||
|
@ -45,7 +45,7 @@ func TestLiveDynCleanUp(t *testing.T) {
|
|||
|
||||
time.Sleep(time.Second * 1)
|
||||
|
||||
provider, err := NewDNSProvider(dynCustomerName, dynUserName, dynPassword)
|
||||
provider, err := NewDNSProvider()
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = provider.CleanUp(dynDomain, "", "123d==")
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
@ -35,9 +36,16 @@ type DNSProvider struct {
|
|||
inProgressMu sync.Mutex
|
||||
}
|
||||
|
||||
// NewDNSProvider returns a new DNSProvider instance. apiKey is the
|
||||
// API access key obtained from the Gandi account control panel.
|
||||
func NewDNSProvider(apiKey string) (*DNSProvider, error) {
|
||||
// NewDNSProvider returns a DNSProvider instance configured for Gandi.
|
||||
// Credentials must be passed in the environment variable: GANDI_API_KEY.
|
||||
func NewDNSProvider() (*DNSProvider, error) {
|
||||
apiKey := os.Getenv("GANDI_API_KEY")
|
||||
return NewDNSProviderCredentials(apiKey)
|
||||
}
|
||||
|
||||
// NewDNSProviderCredentials uses the supplied credentials to return a
|
||||
// DNSProvider instance configured for Gandi.
|
||||
func NewDNSProviderCredentials(apiKey string) (*DNSProvider, error) {
|
||||
if apiKey == "" {
|
||||
return nil, fmt.Errorf("No Gandi API Key given")
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package gandi_test
|
||||
package gandi
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
@ -8,8 +8,6 @@ import (
|
|||
"regexp"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/xenolf/lego/providers/dns/gandi"
|
||||
)
|
||||
|
||||
// TestDNSProvider runs Present and CleanUp against a fake Gandi RPC
|
||||
|
@ -17,7 +15,7 @@ import (
|
|||
func TestDNSProvider(t *testing.T) {
|
||||
fakeAPIKey := "123412341234123412341234"
|
||||
fakeKeyAuth := "XXXX"
|
||||
provider, err := gandi.NewDNSProvider(fakeAPIKey)
|
||||
provider, err := NewDNSProviderCredentials(fakeAPIKey)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -47,11 +45,11 @@ func TestDNSProvider(t *testing.T) {
|
|||
}))
|
||||
defer fakeServer.Close()
|
||||
// override gandi endpoint to point to fake server
|
||||
savedEndpoint := gandi.Endpoint
|
||||
savedEndpoint := Endpoint
|
||||
defer func() {
|
||||
gandi.Endpoint = savedEndpoint
|
||||
Endpoint = savedEndpoint
|
||||
}()
|
||||
gandi.Endpoint = fakeServer.URL + "/"
|
||||
Endpoint = fakeServer.URL + "/"
|
||||
// run Present
|
||||
err = provider.Present("abc.def.example.com", "", fakeKeyAuth)
|
||||
if err != nil {
|
||||
|
|
|
@ -22,12 +22,16 @@ type DNSProvider struct {
|
|||
client *dns.Service
|
||||
}
|
||||
|
||||
// NewDNSProvider returns a DNSProvider instance with a configured gcloud client.
|
||||
// Authentication is done using the local account credentials managed by the gcloud utility.
|
||||
func NewDNSProvider(project string) (*DNSProvider, error) {
|
||||
if project == "" {
|
||||
project = gcloudEnvAuth()
|
||||
}
|
||||
// NewDNSProvider returns a DNSProvider instance configured for Google Cloud
|
||||
// DNS. Credentials must be passed in the environment variable: GCE_PROJECT.
|
||||
func NewDNSProvider() (*DNSProvider, error) {
|
||||
project := os.Getenv("GCE_PROJECT")
|
||||
return NewDNSProviderCredentials(project)
|
||||
}
|
||||
|
||||
// NewDNSProviderCredentials uses the supplied credentials to return a
|
||||
// DNSProvider instance configured for Google Cloud DNS.
|
||||
func NewDNSProviderCredentials(project string) (*DNSProvider, error) {
|
||||
if project == "" {
|
||||
return nil, fmt.Errorf("Google Cloud project name missing")
|
||||
}
|
||||
|
@ -149,7 +153,3 @@ func (c *DNSProvider) findTxtRecords(zone, fqdn string) ([]*dns.ResourceRecordSe
|
|||
|
||||
return found, nil
|
||||
}
|
||||
|
||||
func gcloudEnvAuth() (gcloud string) {
|
||||
return os.Getenv("GCE_PROJECT")
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ func TestNewDNSProviderValid(t *testing.T) {
|
|||
t.Skip("skipping live test (requires credentials)")
|
||||
}
|
||||
os.Setenv("GCE_PROJECT", "")
|
||||
_, err := NewDNSProvider("my-project")
|
||||
_, err := NewDNSProviderCredentials("my-project")
|
||||
assert.NoError(t, err)
|
||||
restoreGCloudEnv()
|
||||
}
|
||||
|
@ -46,14 +46,14 @@ func TestNewDNSProviderValidEnv(t *testing.T) {
|
|||
t.Skip("skipping live test (requires credentials)")
|
||||
}
|
||||
os.Setenv("GCE_PROJECT", "my-project")
|
||||
_, err := NewDNSProvider("")
|
||||
_, err := NewDNSProvider()
|
||||
assert.NoError(t, err)
|
||||
restoreGCloudEnv()
|
||||
}
|
||||
|
||||
func TestNewDNSProviderMissingCredErr(t *testing.T) {
|
||||
os.Setenv("GCE_PROJECT", "")
|
||||
_, err := NewDNSProvider("")
|
||||
_, err := NewDNSProvider()
|
||||
assert.EqualError(t, err, "Google Cloud project name missing")
|
||||
restoreGCloudEnv()
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ func TestLiveGoogleCloudPresent(t *testing.T) {
|
|||
t.Skip("skipping live test")
|
||||
}
|
||||
|
||||
provider, err := NewDNSProvider(gcloudProject)
|
||||
provider, err := NewDNSProviderCredentials(gcloudProject)
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = provider.Present(gcloudDomain, "", "123d==")
|
||||
|
@ -77,7 +77,7 @@ func TestLiveGoogleCloudCleanUp(t *testing.T) {
|
|||
|
||||
time.Sleep(time.Second * 1)
|
||||
|
||||
provider, err := NewDNSProvider(gcloudProject)
|
||||
provider, err := NewDNSProviderCredentials(gcloudProject)
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = provider.CleanUp(gcloudDomain, "", "123d==")
|
||||
|
|
|
@ -44,16 +44,21 @@ type DNSProvider struct {
|
|||
clientIP string
|
||||
}
|
||||
|
||||
// NewDNSProvider returns a new DNSProvider instance. apiUser is the namecheap
|
||||
// API user's account name, and apiKey is the account's API access key.
|
||||
func NewDNSProvider(apiUser, apiKey string) (*DNSProvider, error) {
|
||||
if apiUser == "" || apiKey == "" {
|
||||
apiUser = os.Getenv("NAMECHEAP_API_USER")
|
||||
apiKey = os.Getenv("NAMECHEAP_API_KEY")
|
||||
// NewDNSProvider returns a DNSProvider instance configured for namecheap.
|
||||
// Credentials must be passed in the environment variables: NAMECHEAP_API_USER
|
||||
// and NAMECHEAP_API_KEY.
|
||||
func NewDNSProvider() (*DNSProvider, error) {
|
||||
apiUser := os.Getenv("NAMECHEAP_API_USER")
|
||||
apiKey := os.Getenv("NAMECHEAP_API_KEY")
|
||||
return NewDNSProviderCredentials(apiUser, apiKey)
|
||||
}
|
||||
|
||||
// NewDNSProviderCredentials uses the supplied credentials to return a
|
||||
// DNSProvider instance configured for namecheap.
|
||||
func NewDNSProviderCredentials(apiUser, apiKey string) (*DNSProvider, error) {
|
||||
if apiUser == "" || apiKey == "" {
|
||||
return nil, fmt.Errorf("Namecheap credentials missing")
|
||||
}
|
||||
}
|
||||
|
||||
clientIP, err := getClientIP()
|
||||
if err != nil {
|
||||
|
@ -68,8 +73,9 @@ func NewDNSProvider(apiUser, apiKey string) (*DNSProvider, error) {
|
|||
}, nil
|
||||
}
|
||||
|
||||
// Timeout : Namecheap can sometimes take a long time to complete an update, so wait
|
||||
// up to 60 minutes for the update to propagate.
|
||||
// Timeout returns the timeout and interval to use when checking for DNS
|
||||
// propagation. Namecheap can sometimes take a long time to complete an
|
||||
// update, so wait up to 60 minutes for the update to propagate.
|
||||
func (d *DNSProvider) Timeout() (timeout, interval time.Duration) {
|
||||
return 60 * time.Minute, 15 * time.Second
|
||||
}
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
// Package rfc2136 implements a DNS provider for solving the DNS-01 challenge using the rfc2136 dynamic update.
|
||||
// Package rfc2136 implements a DNS provider for solving the DNS-01 challenge
|
||||
// using the rfc2136 dynamic update.
|
||||
package rfc2136
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
|
@ -20,10 +22,29 @@ type DNSProvider struct {
|
|||
tsigSecret string
|
||||
}
|
||||
|
||||
// NewDNSProvider returns a new DNSProvider instance.
|
||||
// To disable TSIG authentication 'tsigAlgorithm, 'tsigKey' and 'tsigSecret' must be set to the empty string.
|
||||
// 'nameserver' must be a network address in the the form "host" or "host:port".
|
||||
func NewDNSProvider(nameserver, tsigAlgorithm, tsigKey, tsigSecret string) (*DNSProvider, error) {
|
||||
// NewDNSProvider returns a DNSProvider instance configured for rfc2136
|
||||
// dynamic update. Credentials must be passed in the environment variables:
|
||||
// RFC2136_NAMESERVER, RFC2136_TSIG_ALGORITHM, RFC2136_TSIG_KEY and
|
||||
// RFC2136_TSIG_SECRET. To disable TSIG authentication, leave the TSIG
|
||||
// variables unset. RFC2136_NAMESERVER must be a network address in the form
|
||||
// "host" or "host:port".
|
||||
func NewDNSProvider() (*DNSProvider, error) {
|
||||
nameserver := os.Getenv("RFC2136_NAMESERVER")
|
||||
tsigAlgorithm := os.Getenv("RFC2136_TSIG_ALGORITHM")
|
||||
tsigKey := os.Getenv("RFC2136_TSIG_KEY")
|
||||
tsigSecret := os.Getenv("RFC2136_TSIG_SECRET")
|
||||
return NewDNSProviderCredentials(nameserver, tsigAlgorithm, tsigKey, tsigSecret)
|
||||
}
|
||||
|
||||
// NewDNSProviderCredentials uses the supplied credentials to return a
|
||||
// DNSProvider instance configured for rfc2136 dynamic update. To disable TSIG
|
||||
// authentication, leave the TSIG parameters as empty strings.
|
||||
// nameserver must be a network address in the form "host" or "host:port".
|
||||
func NewDNSProviderCredentials(nameserver, tsigAlgorithm, tsigKey, tsigSecret string) (*DNSProvider, error) {
|
||||
if nameserver == "" {
|
||||
return nil, fmt.Errorf("RFC2136 nameserver missing")
|
||||
}
|
||||
|
||||
// Append the default DNS port if none is specified.
|
||||
if _, _, err := net.SplitHostPort(nameserver); err != nil {
|
||||
if strings.Contains(err.Error(), "missing port") {
|
||||
|
|
|
@ -61,9 +61,9 @@ func TestRFC2136ServerSuccess(t *testing.T) {
|
|||
}
|
||||
defer server.Shutdown()
|
||||
|
||||
provider, err := NewDNSProvider(addrstr, "", "", "")
|
||||
provider, err := NewDNSProviderCredentials(addrstr, "", "", "")
|
||||
if err != nil {
|
||||
t.Fatalf("Expected NewDNSProvider() to return no error but the error was -> %v", err)
|
||||
t.Fatalf("Expected NewDNSProviderCredentials() to return no error but the error was -> %v", err)
|
||||
}
|
||||
if err := provider.Present(rfc2136TestDomain, "", rfc2136TestKeyAuth); err != nil {
|
||||
t.Errorf("Expected Present() to return no error but the error was -> %v", err)
|
||||
|
@ -81,9 +81,9 @@ func TestRFC2136ServerError(t *testing.T) {
|
|||
}
|
||||
defer server.Shutdown()
|
||||
|
||||
provider, err := NewDNSProvider(addrstr, "", "", "")
|
||||
provider, err := NewDNSProviderCredentials(addrstr, "", "", "")
|
||||
if err != nil {
|
||||
t.Fatalf("Expected NewDNSProvider() to return no error but the error was -> %v", err)
|
||||
t.Fatalf("Expected NewDNSProviderCredentials() to return no error but the error was -> %v", err)
|
||||
}
|
||||
if err := provider.Present(rfc2136TestDomain, "", rfc2136TestKeyAuth); err == nil {
|
||||
t.Errorf("Expected Present() to return an error but it did not.")
|
||||
|
@ -103,9 +103,9 @@ func TestRFC2136TsigClient(t *testing.T) {
|
|||
}
|
||||
defer server.Shutdown()
|
||||
|
||||
provider, err := NewDNSProvider(addrstr, "", rfc2136TestTsigKey, rfc2136TestTsigSecret)
|
||||
provider, err := NewDNSProviderCredentials(addrstr, "", rfc2136TestTsigKey, rfc2136TestTsigSecret)
|
||||
if err != nil {
|
||||
t.Fatalf("Expected NewDNSProvider() to return no error but the error was -> %v", err)
|
||||
t.Fatalf("Expected NewDNSProviderCredentials() to return no error but the error was -> %v", err)
|
||||
}
|
||||
if err := provider.Present(rfc2136TestDomain, "", rfc2136TestKeyAuth); err != nil {
|
||||
t.Errorf("Expected Present() to return no error but the error was -> %v", err)
|
||||
|
@ -135,9 +135,9 @@ func TestRFC2136ValidUpdatePacket(t *testing.T) {
|
|||
t.Fatalf("Error packing expect msg: %v", err)
|
||||
}
|
||||
|
||||
provider, err := NewDNSProvider(addrstr, "", "", "")
|
||||
provider, err := NewDNSProviderCredentials(addrstr, "", "", "")
|
||||
if err != nil {
|
||||
t.Fatalf("Expected NewDNSProvider() to return no error but the error was -> %v", err)
|
||||
t.Fatalf("Expected NewDNSProviderCredentials() to return no error but the error was -> %v", err)
|
||||
}
|
||||
|
||||
if err := provider.Present(rfc2136TestDomain, "", "1234d=="); err != nil {
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
// Package route53 implements a DNS provider for solving the DNS-01 challenge using route53 DNS.
|
||||
// Package route53 implements a DNS provider for solving the DNS-01 challenge
|
||||
// using route53 DNS.
|
||||
package route53
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
|
@ -16,25 +18,35 @@ type DNSProvider struct {
|
|||
client *route53.Route53
|
||||
}
|
||||
|
||||
// NewDNSProvider returns a DNSProvider instance with a configured route53 client.
|
||||
// Authentication is either done using the passed credentials or - when empty - falling back to
|
||||
// the customary AWS credential mechanisms, including the file referenced by $AWS_CREDENTIAL_FILE
|
||||
// (defaulting to $HOME/.aws/credentials) optionally scoped to $AWS_PROFILE, credentials
|
||||
// supplied by the environment variables AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY [ + AWS_SECURITY_TOKEN ],
|
||||
// and finally credentials available via the EC2 instance metadata service.
|
||||
func NewDNSProvider(awsAccessKey, awsSecretKey, awsRegionName string) (*DNSProvider, error) {
|
||||
region, ok := aws.Regions[awsRegionName]
|
||||
// NewDNSProvider returns a DNSProvider instance configured for the AWS
|
||||
// route53 service. The AWS region name must be passed in the environment
|
||||
// variable AWS_REGION.
|
||||
func NewDNSProvider() (*DNSProvider, error) {
|
||||
regionName := os.Getenv("AWS_REGION")
|
||||
return NewDNSProviderCredentials("", "", regionName)
|
||||
}
|
||||
|
||||
// NewDNSProviderCredentials uses the supplied credentials to return a
|
||||
// DNSProvider instance configured for the AWS route53 service. Authentication
|
||||
// is done using the passed credentials or, if empty, falling back to the
|
||||
// custonmary AWS credential mechanisms, including the file referenced by
|
||||
// $AWS_CREDENTIAL_FILE (defaulting to $HOME/.aws/credentials) optionally
|
||||
// scoped to $AWS_PROFILE, credentials supplied by the environment variables
|
||||
// AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY [ + AWS_SECURITY_TOKEN ], and
|
||||
// finally credentials available via the EC2 instance metadata service.
|
||||
func NewDNSProviderCredentials(accessKey, secretKey, regionName string) (*DNSProvider, error) {
|
||||
region, ok := aws.Regions[regionName]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Invalid AWS region name %s", awsRegionName)
|
||||
return nil, fmt.Errorf("Invalid AWS region name %s", regionName)
|
||||
}
|
||||
|
||||
// use aws.GetAuth, which tries really hard to find credentails:
|
||||
// - uses awsAccessKey and awsSecretKey, if provided
|
||||
// - uses accessKey and secretKey, if provided
|
||||
// - uses AWS_PROFILE / AWS_CREDENTIAL_FILE, if provided
|
||||
// - uses AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY and optionally AWS_SECURITY_TOKEN, if provided
|
||||
// - uses EC2 instance metadata credentials (http://169.254.169.254/latest/meta-data/…), if available
|
||||
// ...and otherwise returns an error
|
||||
auth, err := aws.GetAuth(awsAccessKey, awsSecretKey)
|
||||
auth, err := aws.GetAuth(accessKey, secretKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -100,7 +100,8 @@ func makeRoute53Provider(server *testutil.HTTPServer) *DNSProvider {
|
|||
func TestNewDNSProviderValid(t *testing.T) {
|
||||
os.Setenv("AWS_ACCESS_KEY_ID", "")
|
||||
os.Setenv("AWS_SECRET_ACCESS_KEY", "")
|
||||
_, err := NewDNSProvider("123", "123", "us-east-1")
|
||||
os.Setenv("AWS_REGION", "")
|
||||
_, err := NewDNSProviderCredentials("123", "123", "us-east-1")
|
||||
assert.NoError(t, err)
|
||||
restoreRoute53Env()
|
||||
}
|
||||
|
@ -108,7 +109,8 @@ func TestNewDNSProviderValid(t *testing.T) {
|
|||
func TestNewDNSProviderValidEnv(t *testing.T) {
|
||||
os.Setenv("AWS_ACCESS_KEY_ID", "123")
|
||||
os.Setenv("AWS_SECRET_ACCESS_KEY", "123")
|
||||
_, err := NewDNSProvider("", "", "us-east-1")
|
||||
os.Setenv("AWS_REGION", "us-east-1")
|
||||
_, err := NewDNSProvider()
|
||||
assert.NoError(t, err)
|
||||
restoreRoute53Env()
|
||||
}
|
||||
|
@ -124,7 +126,7 @@ func TestNewDNSProviderMissingAuthErr(t *testing.T) {
|
|||
awsClient := aws.RetryingClient
|
||||
aws.RetryingClient = &http.Client{Timeout: time.Millisecond}
|
||||
|
||||
_, err := NewDNSProvider("", "", "us-east-1")
|
||||
_, err := NewDNSProviderCredentials("", "", "us-east-1")
|
||||
assert.EqualError(t, err, "No valid AWS authentication found")
|
||||
restoreRoute53Env()
|
||||
|
||||
|
@ -133,7 +135,7 @@ func TestNewDNSProviderMissingAuthErr(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestNewDNSProviderInvalidRegionErr(t *testing.T) {
|
||||
_, err := NewDNSProvider("123", "123", "us-east-3")
|
||||
_, err := NewDNSProviderCredentials("123", "123", "us-east-3")
|
||||
assert.EqualError(t, err, "Invalid AWS region name us-east-3")
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue