Review DNS providers. (#565)

* refactor: review DNS providers.
This commit is contained in:
Ludovic Fernandez 2018-06-11 17:32:50 +02:00 committed by GitHub
parent 8f9e90b2a0
commit c4bbb4b819
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
55 changed files with 671 additions and 560 deletions

27
platform/config/env/env.go vendored Normal file
View file

@ -0,0 +1,27 @@
package env
import (
"fmt"
"os"
"strings"
)
// Get environment variables
func Get(names ...string) (map[string]string, error) {
values := map[string]string{}
var missingEnvVars []string
for _, envVar := range names {
value := os.Getenv(envVar)
if value == "" {
missingEnvVars = append(missingEnvVars, envVar)
}
values[envVar] = value
}
if len(missingEnvVars) > 0 {
return nil, fmt.Errorf("some credentials information are missing: %s", strings.Join(missingEnvVars, ","))
}
return values, nil
}

View file

@ -9,6 +9,7 @@ import (
"github.com/edeckers/auroradnsclient/records"
"github.com/edeckers/auroradnsclient/zones"
"github.com/xenolf/lego/acme"
"github.com/xenolf/lego/platform/config/env"
)
// DNSProvider describes a provider for AuroraDNS
@ -22,20 +23,23 @@ type DNSProvider struct {
// Credentials must be passed in the environment variables: AURORA_USER_ID
// and AURORA_KEY.
func NewDNSProvider() (*DNSProvider, error) {
userID := os.Getenv("AURORA_USER_ID")
key := os.Getenv("AURORA_KEY")
endpoint := os.Getenv("AURORA_ENDPOINT")
if endpoint == "" {
endpoint = "https://api.auroradns.eu"
values, err := env.Get("AURORA_USER_ID", "AURORA_KEY")
if err != nil {
return nil, fmt.Errorf("AuroraDNS: %v", err)
}
return NewDNSProviderCredentials(endpoint, userID, key)
endpoint := os.Getenv("AURORA_ENDPOINT")
return NewDNSProviderCredentials(endpoint, values["AURORA_USER_ID"], values["AURORA_KEY"])
}
// NewDNSProviderCredentials uses the supplied credentials to return a
// DNSProvider instance configured for AuroraDNS.
func NewDNSProviderCredentials(baseURL string, userID string, key string) (*DNSProvider, error) {
if baseURL == "" {
baseURL = "https://api.auroradns.eu"
}
client, err := auroradnsclient.NewAuroraDNSClient(baseURL, userID, key)
if err != nil {
return nil, err
@ -69,7 +73,7 @@ func (provider *DNSProvider) Present(domain, token, keyAuth string) error {
authZone, err := acme.FindZoneByFqdn(acme.ToFqdn(domain), acme.RecursiveNameservers)
if err != nil {
return fmt.Errorf("Could not determine zone for domain: '%s'. %s", domain, err)
return fmt.Errorf("could not determine zone for domain: '%s'. %s", domain, err)
}
// 1. Aurora will happily create the TXT record when it is provided a fqdn,

View file

@ -6,6 +6,9 @@ import (
"net/http"
"net/http/httptest"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
var fakeAuroraDNSUserID = "asdf1234"
@ -26,28 +29,13 @@ func TestAuroraDNSPresent(t *testing.T) {
requestReceived = true
if got, want := r.Method, "POST"; got != want {
t.Errorf("Expected method to be '%s' but got '%s'", want, got)
}
if got, want := r.URL.Path, "/zones/c56a4180-65aa-42ec-a945-5fd21dec0538/records"; got != want {
t.Errorf("Expected path to be '%s' but got '%s'", want, got)
}
if got, want := r.Header.Get("Content-Type"), "application/json"; got != want {
t.Errorf("Expected Content-Type to be '%s' but got '%s'", want, got)
}
assert.Equal(t, http.MethodPost, r.Method, "method")
assert.Equal(t, "/zones/c56a4180-65aa-42ec-a945-5fd21dec0538/records", r.URL.Path, "Path")
assert.Equal(t, "application/json", r.Header.Get("Content-Type"), "Content-Type")
reqBody, err := ioutil.ReadAll(r.Body)
if err != nil {
t.Fatalf("Error reading request body: %v", err)
}
if got, want := string(reqBody),
`{"type":"TXT","name":"_acme-challenge","content":"w6uP8Tcg6K2QR905Rms8iXTlksL6OD1KOWBxTK7wxPI","ttl":300}`; got != want {
t.Errorf("Expected body data to be: `%s` but got `%s`", want, got)
}
require.NoError(t, err, "reading request body")
assert.Equal(t, `{"type":"TXT","name":"_acme-challenge","content":"w6uP8Tcg6K2QR905Rms8iXTlksL6OD1KOWBxTK7wxPI","ttl":300}`, string(reqBody))
w.WriteHeader(http.StatusCreated)
fmt.Fprintf(w, `{
@ -61,22 +49,13 @@ func TestAuroraDNSPresent(t *testing.T) {
defer mock.Close()
auroraProvider, err := NewDNSProviderCredentials(mock.URL, fakeAuroraDNSUserID, fakeAuroraDNSKey)
if auroraProvider == nil {
t.Fatal("Expected non-nil AuroraDNS provider, but was nil")
}
if err != nil {
t.Fatalf("Expected no error creating provider, but got: %v", err)
}
require.NoError(t, err)
require.NotNil(t, auroraProvider)
err = auroraProvider.Present("example.com", "", "foobar")
if err != nil {
t.Fatalf("Expected no error creating TXT record, but got: %v", err)
}
require.NoError(t, err, "fail to create TXT record")
if !requestReceived {
t.Error("Expected request to be received by mock backend, but it wasn't")
}
assert.True(t, requestReceived, "Expected request to be received by mock backend, but it wasn't")
}
func TestAuroraDNSCleanUp(t *testing.T) {
@ -105,18 +84,9 @@ func TestAuroraDNSCleanUp(t *testing.T) {
requestReceived = true
if got, want := r.Method, "DELETE"; got != want {
t.Errorf("Expected method to be '%s' but got '%s'", want, got)
}
if got, want := r.URL.Path,
"/zones/c56a4180-65aa-42ec-a945-5fd21dec0538/records/ec56a4180-65aa-42ec-a945-5fd21dec0538"; got != want {
t.Errorf("Expected path to be '%s' but got '%s'", want, got)
}
if got, want := r.Header.Get("Content-Type"), "application/json"; got != want {
t.Errorf("Expected Content-Type to be '%s' but got '%s'", want, got)
}
assert.Equal(t, http.MethodDelete, r.Method, "method")
assert.Equal(t, "/zones/c56a4180-65aa-42ec-a945-5fd21dec0538/records/ec56a4180-65aa-42ec-a945-5fd21dec0538", r.URL.Path, "Path")
assert.Equal(t, "application/json", r.Header.Get("Content-Type"), "Content-Type")
w.WriteHeader(http.StatusCreated)
fmt.Fprintf(w, `{}`)
@ -124,25 +94,14 @@ func TestAuroraDNSCleanUp(t *testing.T) {
defer mock.Close()
auroraProvider, err := NewDNSProviderCredentials(mock.URL, fakeAuroraDNSUserID, fakeAuroraDNSKey)
if auroraProvider == nil {
t.Fatal("Expected non-nil AuroraDNS provider, but was nil")
}
if err != nil {
t.Fatalf("Expected no error creating provider, but got: %v", err)
}
require.NoError(t, err)
require.NotNil(t, auroraProvider)
err = auroraProvider.Present("example.com", "", "foobar")
if err != nil {
t.Fatalf("Expected no error creating TXT record, but got: %v", err)
}
require.NoError(t, err, "fail to create TXT record")
err = auroraProvider.CleanUp("example.com", "", "foobar")
if err != nil {
t.Fatalf("Expected no error removing TXT record, but got: %v", err)
}
require.NoError(t, err, "fail to remove TXT record")
if !requestReceived {
t.Error("Expected request to be received by mock backend, but it wasn't")
}
assert.True(t, requestReceived, "Expected request to be received by mock backend, but it wasn't")
}

View file

@ -5,8 +5,8 @@ package azure
import (
"context"
"errors"
"fmt"
"os"
"strings"
"time"
@ -16,6 +16,7 @@ import (
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/to"
"github.com/xenolf/lego/acme"
"github.com/xenolf/lego/platform/config/env"
)
// DNSProvider is an implementation of the acme.ChallengeProvider interface
@ -32,25 +33,25 @@ type DNSProvider struct {
// Credentials must be passed in the environment variables: AZURE_CLIENT_ID,
// AZURE_CLIENT_SECRET, AZURE_SUBSCRIPTION_ID, AZURE_TENANT_ID, AZURE_RESOURCE_GROUP
func NewDNSProvider() (*DNSProvider, error) {
clientID := os.Getenv("AZURE_CLIENT_ID")
clientSecret := os.Getenv("AZURE_CLIENT_SECRET")
subscriptionID := os.Getenv("AZURE_SUBSCRIPTION_ID")
tenantID := os.Getenv("AZURE_TENANT_ID")
resourceGroup := os.Getenv("AZURE_RESOURCE_GROUP")
return NewDNSProviderCredentials(clientID, clientSecret, subscriptionID, tenantID, resourceGroup)
values, err := env.Get("AZURE_CLIENT_ID", "AZURE_CLIENT_SECRET", "AZURE_SUBSCRIPTION_ID", "AZURE_TENANT_ID", "AZURE_RESOURCE_GROUP")
if err != nil {
return nil, fmt.Errorf("Azure: %v", err)
}
return NewDNSProviderCredentials(
values["AZURE_CLIENT_ID"],
values["AZURE_CLIENT_SECRET"],
values["AZURE_SUBSCRIPTION_ID"],
values["AZURE_TENANT_ID"],
values["AZURE_RESOURCE_GROUP"],
)
}
// NewDNSProviderCredentials uses the supplied credentials to return a
// DNSProvider instance configured for azure.
func NewDNSProviderCredentials(clientID, clientSecret, subscriptionID, tenantID, resourceGroup string) (*DNSProvider, error) {
if clientID == "" || clientSecret == "" || subscriptionID == "" || tenantID == "" || resourceGroup == "" {
var missingEnvVars []string
for _, envVar := range []string{"AZURE_CLIENT_ID", "AZURE_CLIENT_SECRET", "AZURE_SUBSCRIPTION_ID", "AZURE_TENANT_ID", "AZURE_RESOURCE_GROUP"} {
if os.Getenv(envVar) == "" {
missingEnvVars = append(missingEnvVars, envVar)
}
}
return nil, fmt.Errorf("Azure configuration missing: %s", strings.Join(missingEnvVars, ","))
return nil, errors.New("Azure: some credentials information are missing")
}
return &DNSProvider{

View file

@ -30,7 +30,7 @@ func init() {
}
}
func restoreAzureEnv() {
func restoreEnv() {
os.Setenv("AZURE_CLIENT_ID", azureClientID)
os.Setenv("AZURE_SUBSCRIPTION_ID", azureSubscriptionID)
}
@ -39,27 +39,32 @@ func TestNewDNSProviderValid(t *testing.T) {
if !azureLiveTest {
t.Skip("skipping live test (requires credentials)")
}
defer restoreEnv()
os.Setenv("AZURE_CLIENT_ID", "")
_, err := NewDNSProviderCredentials(azureClientID, azureClientSecret, azureSubscriptionID, azureTenantID, azureResourceGroup)
assert.NoError(t, err)
restoreAzureEnv()
}
func TestNewDNSProviderValidEnv(t *testing.T) {
if !azureLiveTest {
t.Skip("skipping live test (requires credentials)")
}
defer restoreEnv()
os.Setenv("AZURE_CLIENT_ID", "other")
_, err := NewDNSProvider()
assert.NoError(t, err)
restoreAzureEnv()
}
func TestNewDNSProviderMissingCredErr(t *testing.T) {
defer restoreEnv()
os.Setenv("AZURE_SUBSCRIPTION_ID", "")
_, err := NewDNSProvider()
assert.EqualError(t, err, "Azure configuration missing: AZURE_CLIENT_ID,AZURE_CLIENT_SECRET,AZURE_SUBSCRIPTION_ID,AZURE_TENANT_ID,AZURE_RESOURCE_GROUP")
restoreAzureEnv()
assert.EqualError(t, err, "Azure: some credentials information are missing: AZURE_CLIENT_ID,AZURE_CLIENT_SECRET,AZURE_SUBSCRIPTION_ID,AZURE_TENANT_ID,AZURE_RESOURCE_GROUP")
}
func TestLiveAzurePresent(t *testing.T) {

View file

@ -6,16 +6,15 @@ import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"os"
"regexp"
"strconv"
"strings"
"time"
"io/ioutil"
"github.com/xenolf/lego/acme"
"github.com/xenolf/lego/platform/config/env"
)
const bluecatURLTemplate = "%s/Services/REST/v1"
@ -51,29 +50,42 @@ type DNSProvider struct {
// and external DNS View Name must be passed in BLUECAT_CONFIG_NAME and
// BLUECAT_DNS_VIEW
func NewDNSProvider() (*DNSProvider, error) {
server := os.Getenv("BLUECAT_SERVER_URL")
userName := os.Getenv("BLUECAT_USER_NAME")
password := os.Getenv("BLUECAT_PASSWORD")
configName := os.Getenv("BLUECAT_CONFIG_NAME")
dnsView := os.Getenv("BLUECAT_DNS_VIEW")
httpClient := http.Client{Timeout: 30 * time.Second}
return NewDNSProviderCredentials(server, userName, password, configName, dnsView, httpClient)
values, err := env.Get("BLUECAT_SERVER_URL", "BLUECAT_USER_NAME", "BLUECAT_CONFIG_NAME", "BLUECAT_CONFIG_NAME", "BLUECAT_DNS_VIEW")
if err != nil {
return nil, fmt.Errorf("BlueCat: %v", err)
}
httpClient := &http.Client{Timeout: 30 * time.Second}
return NewDNSProviderCredentials(
values["BLUECAT_SERVER_URL"],
values["BLUECAT_USER_NAME"],
values["BLUECAT_PASSWORD"],
values["BLUECAT_CONFIG_NAME"],
values["BLUECAT_DNS_VIEW"],
httpClient,
)
}
// NewDNSProviderCredentials uses the supplied credentials to return a
// DNSProvider instance configured for Bluecat DNS.
func NewDNSProviderCredentials(server, userName, password, configName, dnsView string, httpClient http.Client) (*DNSProvider, error) {
func NewDNSProviderCredentials(server, userName, password, configName, dnsView string, httpClient *http.Client) (*DNSProvider, error) {
if server == "" || userName == "" || password == "" || configName == "" || dnsView == "" {
return nil, fmt.Errorf("Bluecat credentials missing")
}
client := http.DefaultClient
if httpClient != nil {
client = httpClient
}
return &DNSProvider{
baseURL: fmt.Sprintf(bluecatURLTemplate, server),
userName: userName,
password: password,
configName: configName,
dnsView: dnsView,
httpClient: http.DefaultClient,
httpClient: client,
}, nil
}

View file

@ -5,15 +5,15 @@ package cloudflare
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"io"
"io/ioutil"
"net/http"
"os"
"strings"
"time"
"github.com/xenolf/lego/acme"
"github.com/xenolf/lego/platform/config/env"
)
// CloudFlareAPIURL represents the API endpoint to call.
@ -30,23 +30,19 @@ type DNSProvider struct {
// 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)
values, err := env.Get("CLOUDFLARE_EMAIL", "CLOUDFLARE_API_KEY")
if err != nil {
return nil, fmt.Errorf("CloudFlare: %v", err)
}
return NewDNSProviderCredentials(values["CLOUDFLARE_EMAIL"], values["CLOUDFLARE_API_KEY"])
}
// NewDNSProviderCredentials uses the supplied credentials to return a
// DNSProvider instance configured for cloudflare.
func NewDNSProviderCredentials(email, key string) (*DNSProvider, error) {
if email == "" || key == "" {
missingEnvVars := []string{}
if email == "" {
missingEnvVars = append(missingEnvVars, "CLOUDFLARE_EMAIL")
}
if key == "" {
missingEnvVars = append(missingEnvVars, "CLOUDFLARE_API_KEY")
}
return nil, fmt.Errorf("CloudFlare credentials missing: %s", strings.Join(missingEnvVars, ","))
return nil, errors.New("CloudFlare: some credentials information are missing")
}
return &DNSProvider{
@ -63,7 +59,7 @@ func (c *DNSProvider) Timeout() (timeout, interval time.Duration) {
// Present creates a TXT record to fulfil the dns-01 challenge
func (c *DNSProvider) Present(domain, token, keyAuth string) error {
fqdn, value, _ := acme.DNS01Record(domain, keyAuth)
fqdn, value, ttl := acme.DNS01Record(domain, keyAuth)
zoneID, err := c.getHostedZoneID(fqdn)
if err != nil {
return err
@ -73,7 +69,7 @@ func (c *DNSProvider) Present(domain, token, keyAuth string) error {
Type: "TXT",
Name: acme.UnFqdn(fqdn),
Content: value,
TTL: 120,
TTL: ttl,
}
body, err := json.Marshal(rec)
@ -122,7 +118,7 @@ func (c *DNSProvider) getHostedZoneID(fqdn string) (string, error) {
}
if len(hostedZone) != 1 {
return "", fmt.Errorf("Zone %s not found in CloudFlare for domain %s", authZone, fqdn)
return "", fmt.Errorf("zone %s not found in CloudFlare for domain %s", authZone, fqdn)
}
return hostedZone[0].ID, nil
@ -184,7 +180,7 @@ func (c *DNSProvider) makeRequest(method, uri string, body io.Reader) (json.RawM
client := http.Client{Timeout: 30 * time.Second}
resp, err := client.Do(req)
if err != nil {
return nil, fmt.Errorf("Error querying Cloudflare API -> %v", err)
return nil, fmt.Errorf("error querying Cloudflare API -> %v", err)
}
defer resp.Body.Close()

View file

@ -24,7 +24,7 @@ func init() {
}
}
func restoreCloudFlareEnv() {
func restoreEnv() {
os.Setenv("CLOUDFLARE_EMAIL", cflareEmail)
os.Setenv("CLOUDFLARE_API_KEY", cflareAPIKey)
}
@ -32,32 +32,37 @@ func restoreCloudFlareEnv() {
func TestNewDNSProviderValid(t *testing.T) {
os.Setenv("CLOUDFLARE_EMAIL", "")
os.Setenv("CLOUDFLARE_API_KEY", "")
defer restoreEnv()
_, err := NewDNSProviderCredentials("123", "123")
assert.NoError(t, err)
restoreCloudFlareEnv()
}
func TestNewDNSProviderValidEnv(t *testing.T) {
defer restoreEnv()
os.Setenv("CLOUDFLARE_EMAIL", "test@example.com")
os.Setenv("CLOUDFLARE_API_KEY", "123")
_, err := NewDNSProvider()
assert.NoError(t, err)
restoreCloudFlareEnv()
}
func TestNewDNSProviderMissingCredErr(t *testing.T) {
defer restoreEnv()
os.Setenv("CLOUDFLARE_EMAIL", "")
os.Setenv("CLOUDFLARE_API_KEY", "")
_, err := NewDNSProvider()
assert.EqualError(t, err, "CloudFlare credentials missing: CLOUDFLARE_EMAIL,CLOUDFLARE_API_KEY")
restoreCloudFlareEnv()
assert.EqualError(t, err, "CloudFlare: some credentials information are missing: CLOUDFLARE_EMAIL,CLOUDFLARE_API_KEY")
}
func TestNewDNSProviderMissingCredErrSingle(t *testing.T){
func TestNewDNSProviderMissingCredErrSingle(t *testing.T) {
defer restoreEnv()
os.Setenv("CLOUDFLARE_EMAIL", "awesome@possum.com")
_, err:= NewDNSProvider()
assert.EqualError(t, err, "CloudFlare credentials missing: CLOUDFLARE_API_KEY")
restoreCloudFlareEnv()
_, err := NewDNSProvider()
assert.EqualError(t, err, "CloudFlare: some credentials information are missing: CLOUDFLARE_API_KEY")
}
func TestCloudFlarePresent(t *testing.T) {

View file

@ -9,11 +9,11 @@ import (
"encoding/json"
"fmt"
"net/http"
"os"
"strconv"
"time"
"github.com/xenolf/lego/acme"
"github.com/xenolf/lego/platform/config/env"
)
const cloudXNSBaseURL = "https://www.cloudxns.net/api2/"
@ -28,9 +28,12 @@ type DNSProvider struct {
// Credentials must be passed in the environment variables: CLOUDXNS_API_KEY
// and CLOUDXNS_SECRET_KEY.
func NewDNSProvider() (*DNSProvider, error) {
apiKey := os.Getenv("CLOUDXNS_API_KEY")
secretKey := os.Getenv("CLOUDXNS_SECRET_KEY")
return NewDNSProviderCredentials(apiKey, secretKey)
values, err := env.Get("CLOUDXNS_API_KEY", "CLOUDXNS_SECRET_KEY")
if err != nil {
return nil, fmt.Errorf("CloudXNS: %v", err)
}
return NewDNSProviderCredentials(values["CLOUDXNS_API_KEY"], values["CLOUDXNS_SECRET_KEY"])
}
// NewDNSProviderCredentials uses the supplied credentials to return a

View file

@ -24,33 +24,36 @@ func init() {
}
}
func restoreCloudXNSEnv() {
func restoreEnv() {
os.Setenv("CLOUDXNS_API_KEY", cxAPIKey)
os.Setenv("CLOUDXNS_SECRET_KEY", cxSecretKey)
}
func TestNewDNSProviderValid(t *testing.T) {
defer restoreEnv()
os.Setenv("CLOUDXNS_API_KEY", "")
os.Setenv("CLOUDXNS_SECRET_KEY", "")
_, err := NewDNSProviderCredentials("123", "123")
assert.NoError(t, err)
restoreCloudXNSEnv()
}
func TestNewDNSProviderValidEnv(t *testing.T) {
defer restoreEnv()
os.Setenv("CLOUDXNS_API_KEY", "123")
os.Setenv("CLOUDXNS_SECRET_KEY", "123")
_, err := NewDNSProvider()
assert.NoError(t, err)
restoreCloudXNSEnv()
}
func TestNewDNSProviderMissingCredErr(t *testing.T) {
defer restoreEnv()
os.Setenv("CLOUDXNS_API_KEY", "")
os.Setenv("CLOUDXNS_SECRET_KEY", "")
_, err := NewDNSProvider()
assert.EqualError(t, err, "CloudXNS credentials missing")
restoreCloudXNSEnv()
assert.EqualError(t, err, "CloudXNS: some credentials information are missing: CLOUDXNS_API_KEY,CLOUDXNS_SECRET_KEY")
}
func TestCloudXNSPresent(t *testing.T) {

View file

@ -7,11 +7,11 @@ import (
"encoding/json"
"fmt"
"net/http"
"os"
"sync"
"time"
"github.com/xenolf/lego/acme"
"github.com/xenolf/lego/platform/config/env"
)
// DNSProvider is an implementation of the acme.ChallengeProvider interface
@ -32,8 +32,12 @@ func (d *DNSProvider) Timeout() (timeout, interval time.Duration) {
// 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)
values, err := env.Get("DO_AUTH_TOKEN")
if err != nil {
return nil, fmt.Errorf("DigitalOcean: %v", err)
}
return NewDNSProviderCredentials(values["DO_AUTH_TOKEN"])
}
// NewDNSProviderCredentials uses the supplied credentials to return a

View file

@ -6,6 +6,9 @@ import (
"net/http"
"net/http/httptest"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
var fakeDigitalOceanAuth = "asdf1234"
@ -16,26 +19,14 @@ func TestDigitalOceanPresent(t *testing.T) {
mock := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
requestReceived = true
if got, want := r.Method, "POST"; got != want {
t.Errorf("Expected method to be '%s' but got '%s'", want, got)
}
if got, want := r.URL.Path, "/v2/domains/example.com/records"; got != want {
t.Errorf("Expected path to be '%s' but got '%s'", want, got)
}
if got, want := r.Header.Get("Content-Type"), "application/json"; got != want {
t.Errorf("Expected Content-Type to be '%s' but got '%s'", want, got)
}
if got, want := r.Header.Get("Authorization"), "Bearer asdf1234"; got != want {
t.Errorf("Expected Authorization to be '%s' but got '%s'", want, got)
}
assert.Equal(t, http.MethodPost, r.Method, "method")
assert.Equal(t, "/v2/domains/example.com/records", r.URL.Path, "Path")
assert.Equal(t, "application/json", r.Header.Get("Content-Type"), "Content-Type")
assert.Equal(t, "Bearer asdf1234", r.Header.Get("Authorization"), "Authorization")
reqBody, err := ioutil.ReadAll(r.Body)
if err != nil {
t.Fatalf("Error reading request body: %v", err)
}
if got, want := string(reqBody), `{"type":"TXT","name":"_acme-challenge.example.com.","data":"w6uP8Tcg6K2QR905Rms8iXTlksL6OD1KOWBxTK7wxPI","ttl":30}`; got != want {
t.Errorf("Expected body data to be: `%s` but got `%s`", want, got)
}
require.NoError(t, err, "reading request body")
assert.Equal(t, `{"type":"TXT","name":"_acme-challenge.example.com.","data":"w6uP8Tcg6K2QR905Rms8iXTlksL6OD1KOWBxTK7wxPI","ttl":30}`, string(reqBody))
w.WriteHeader(http.StatusCreated)
fmt.Fprintf(w, `{
@ -54,20 +45,13 @@ func TestDigitalOceanPresent(t *testing.T) {
digitalOceanBaseURL = mock.URL
doprov, err := NewDNSProviderCredentials(fakeDigitalOceanAuth)
if doprov == nil {
t.Fatal("Expected non-nil DigitalOcean provider, but was nil")
}
if err != nil {
t.Fatalf("Expected no error creating provider, but got: %v", err)
}
require.NoError(t, err)
require.NotNil(t, doprov)
err = doprov.Present("example.com", "", "foobar")
if err != nil {
t.Fatalf("Expected no error creating TXT record, but got: %v", err)
}
if !requestReceived {
t.Error("Expected request to be received by mock backend, but it wasn't")
}
require.NoError(t, err, "fail to create TXT record")
assert.True(t, requestReceived, "Expected request to be received by mock backend, but it wasn't")
}
func TestDigitalOceanCleanUp(t *testing.T) {
@ -76,19 +60,11 @@ func TestDigitalOceanCleanUp(t *testing.T) {
mock := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
requestReceived = true
if got, want := r.Method, "DELETE"; got != want {
t.Errorf("Expected method to be '%s' but got '%s'", want, got)
}
if got, want := r.URL.Path, "/v2/domains/example.com/records/1234567"; got != want {
t.Errorf("Expected path to be '%s' but got '%s'", want, got)
}
assert.Equal(t, http.MethodDelete, r.Method, "method")
assert.Equal(t, "/v2/domains/example.com/records/1234567", r.URL.Path, "Path")
// NOTE: Even though the body is empty, DigitalOcean API docs still show setting this Content-Type...
if got, want := r.Header.Get("Content-Type"), "application/json"; got != want {
t.Errorf("Expected Content-Type to be '%s' but got '%s'", want, got)
}
if got, want := r.Header.Get("Authorization"), "Bearer asdf1234"; got != want {
t.Errorf("Expected Authorization to be '%s' but got '%s'", want, got)
}
assert.Equal(t, "application/json", r.Header.Get("Content-Type"), "Content-Type")
assert.Equal(t, "Bearer asdf1234", r.Header.Get("Authorization"), "Authorization")
w.WriteHeader(http.StatusNoContent)
}))
@ -96,22 +72,15 @@ func TestDigitalOceanCleanUp(t *testing.T) {
digitalOceanBaseURL = mock.URL
doprov, err := NewDNSProviderCredentials(fakeDigitalOceanAuth)
if doprov == nil {
t.Fatal("Expected non-nil DigitalOcean provider, but was nil")
}
if err != nil {
t.Fatalf("Expected no error creating provider, but got: %v", err)
}
require.NoError(t, err)
require.NotNil(t, doprov)
doprov.recordIDsMu.Lock()
doprov.recordIDs["_acme-challenge.example.com."] = 1234567
doprov.recordIDsMu.Unlock()
err = doprov.CleanUp("example.com", "", "")
if err != nil {
t.Fatalf("Expected no error removing TXT record, but got: %v", err)
}
if !requestReceived {
t.Error("Expected request to be received by mock backend, but it wasn't")
}
require.NoError(t, err, "fail to remove TXT record")
assert.True(t, requestReceived, "Expected request to be received by mock backend, but it wasn't")
}

View file

@ -2,7 +2,6 @@ package dns
import (
"os"
"reflect"
"testing"
"github.com/stretchr/testify/assert"
@ -25,23 +24,24 @@ func restoreExoscaleEnv() {
}
func TestKnownDNSProviderSuccess(t *testing.T) {
defer restoreExoscaleEnv()
os.Setenv("EXOSCALE_API_KEY", "abc")
os.Setenv("EXOSCALE_API_SECRET", "123")
provider, err := NewDNSChallengeProviderByName("exoscale")
assert.NoError(t, err)
assert.NotNil(t, provider)
if reflect.TypeOf(provider) != reflect.TypeOf(&exoscale.DNSProvider{}) {
t.Errorf("Not loaded correct DNS proviver: %v is not *exoscale.DNSProvider", reflect.TypeOf(provider))
}
restoreExoscaleEnv()
assert.IsType(t, &exoscale.DNSProvider{}, provider, "Not loaded correct DNS provider")
}
func TestKnownDNSProviderError(t *testing.T) {
defer restoreExoscaleEnv()
os.Setenv("EXOSCALE_API_KEY", "")
os.Setenv("EXOSCALE_API_SECRET", "")
_, err := NewDNSChallengeProviderByName("exoscale")
assert.Error(t, err)
restoreExoscaleEnv()
}
func TestUnknownDNSProvider(t *testing.T) {

View file

@ -31,7 +31,7 @@ func init() {
}
}
func restoreDNSimpleEnv() {
func restoreEnv() {
os.Setenv("DNSIMPLE_OAUTH_TOKEN", dnsimpleOauthToken)
os.Setenv("DNSIMPLE_BASE_URL", dnsimpleBaseURL)
}
@ -41,9 +41,9 @@ func restoreDNSimpleEnv() {
//
func TestNewDNSProviderValid(t *testing.T) {
defer restoreDNSimpleEnv()
defer restoreEnv()
os.Setenv("DNSIMPLE_OAUTH_TOKEN", "123")
provider, err := NewDNSProvider()
assert.NotNil(t, provider)
@ -52,10 +52,10 @@ func TestNewDNSProviderValid(t *testing.T) {
}
func TestNewDNSProviderValidWithBaseUrl(t *testing.T) {
defer restoreDNSimpleEnv()
defer restoreEnv()
os.Setenv("DNSIMPLE_OAUTH_TOKEN", "123")
os.Setenv("DNSIMPLE_BASE_URL", "https://api.dnsimple.test")
provider, err := NewDNSProvider()
assert.NotNil(t, provider)
@ -65,11 +65,8 @@ func TestNewDNSProviderValidWithBaseUrl(t *testing.T) {
}
func TestNewDNSProviderInvalidWithMissingOauthToken(t *testing.T) {
if dnsimpleLiveTest {
t.Skip("skipping test in live mode")
}
defer restoreDNSimpleEnv()
defer restoreEnv()
os.Setenv("DNSIMPLE_OAUTH_TOKEN", "")
provider, err := NewDNSProvider()

View file

@ -15,6 +15,7 @@ import (
"time"
"github.com/xenolf/lego/acme"
"github.com/xenolf/lego/platform/config/env"
)
// DNSProvider is an implementation of the acme.ChallengeProvider interface that uses
@ -45,20 +46,19 @@ type Record struct {
// Credentials must be passed in the environment variables: DNSMADEEASY_API_KEY
// and DNSMADEEASY_API_SECRET.
func NewDNSProvider() (*DNSProvider, error) {
dnsmadeeasyAPIKey := os.Getenv("DNSMADEEASY_API_KEY")
dnsmadeeasyAPISecret := os.Getenv("DNSMADEEASY_API_SECRET")
dnsmadeeasySandbox := os.Getenv("DNSMADEEASY_SANDBOX")
values, err := env.Get("DNSMADEEASY_API_KEY", "DNSMADEEASY_API_SECRET")
if err != nil {
return nil, fmt.Errorf("DNSMadeEasy: %v", err)
}
var baseURL string
sandbox, _ := strconv.ParseBool(dnsmadeeasySandbox)
if sandbox {
if sandbox, _ := strconv.ParseBool(os.Getenv("DNSMADEEASY_SANDBOX")); sandbox {
baseURL = "https://api.sandbox.dnsmadeeasy.com/V2.0"
} else {
baseURL = "https://api.dnsmadeeasy.com/V2.0"
}
return NewDNSProviderCredentials(baseURL, dnsmadeeasyAPIKey, dnsmadeeasyAPISecret)
return NewDNSProviderCredentials(baseURL, values["DNSMADEEASY_API_KEY"], values["DNSMADEEASY_API_SECRET"])
}
// NewDNSProviderCredentials uses the supplied credentials to return a

View file

@ -4,11 +4,11 @@ package dnspod
import (
"fmt"
"os"
"strings"
"github.com/decker502/dnspod-go"
"github.com/xenolf/lego/acme"
"github.com/xenolf/lego/platform/config/env"
)
// DNSProvider is an implementation of the acme.ChallengeProvider interface.
@ -19,8 +19,12 @@ type DNSProvider struct {
// NewDNSProvider returns a DNSProvider instance configured for dnspod.
// Credentials must be passed in the environment variables: DNSPOD_API_KEY.
func NewDNSProvider() (*DNSProvider, error) {
key := os.Getenv("DNSPOD_API_KEY")
return NewDNSProviderCredentials(key)
values, err := env.Get("DNSPOD_API_KEY")
if err != nil {
return nil, fmt.Errorf("DNSPod: %v", err)
}
return NewDNSProviderCredentials(values["DNSPOD_API_KEY"])
}
// NewDNSProviderCredentials uses the supplied credentials to return a
@ -95,7 +99,7 @@ func (c *DNSProvider) getHostedZone(domain string) (string, string, error) {
}
if hostedZone.ID == 0 {
return "", "", fmt.Errorf("Zone %s not found in dnspod for domain %s", authZone, domain)
return "", "", fmt.Errorf("zone %s not found in dnspod for domain %s", authZone, domain)
}

View file

@ -1,10 +1,11 @@
package dnspod
import (
"github.com/stretchr/testify/assert"
"os"
"testing"
"time"
"github.com/stretchr/testify/assert"
)
var (
@ -21,28 +22,31 @@ func init() {
}
}
func restorednspodEnv() {
func restoreEnv() {
os.Setenv("DNSPOD_API_KEY", dnspodAPIKey)
}
func TestNewDNSProviderValid(t *testing.T) {
defer restoreEnv()
os.Setenv("DNSPOD_API_KEY", "")
_, err := NewDNSProviderCredentials("123")
assert.NoError(t, err)
restorednspodEnv()
}
func TestNewDNSProviderValidEnv(t *testing.T) {
defer restoreEnv()
os.Setenv("DNSPOD_API_KEY", "123")
_, err := NewDNSProvider()
assert.NoError(t, err)
restorednspodEnv()
}
func TestNewDNSProviderMissingCredErr(t *testing.T) {
defer restoreEnv()
os.Setenv("DNSPOD_API_KEY", "")
_, err := NewDNSProvider()
assert.EqualError(t, err, "dnspod credentials missing")
restorednspodEnv()
assert.EqualError(t, err, "DNSPod: some credentials information are missing: DNSPOD_API_KEY")
}
func TestLivednspodPresent(t *testing.T) {

View file

@ -1,4 +1,4 @@
// Package duckdns Adds lego support for http://duckdns.org .
// Package duckdns Adds lego support for http://duckdns.org.
// See http://www.duckdns.org/spec.jsp for more info on updating TXT records.
package duckdns
@ -6,30 +6,33 @@ import (
"errors"
"fmt"
"io/ioutil"
"os"
"github.com/xenolf/lego/acme"
"github.com/xenolf/lego/platform/config/env"
)
// DNSProvider adds and removes the record for the DNS challenge
type DNSProvider struct {
// The duckdns api token
// The api token
token string
}
// NewDNSProvider returns a new DNS provider using
// environment variable DUCKDNS_TOKEN for adding and removing the DNS record.
func NewDNSProvider() (*DNSProvider, error) {
duckdnsToken := os.Getenv("DUCKDNS_TOKEN")
values, err := env.Get("DUCKDNS_TOKEN")
if err != nil {
return nil, fmt.Errorf("DuckDNS: %v", err)
}
return NewDNSProviderCredentials(duckdnsToken)
return NewDNSProviderCredentials(values["DUCKDNS_TOKEN"])
}
// NewDNSProviderCredentials uses the supplied credentials to return a
// DNSProvider instance configured for http://duckdns.org .
func NewDNSProviderCredentials(duckdnsToken string) (*DNSProvider, error) {
if duckdnsToken == "" {
return nil, errors.New("environment variable DUCKDNS_TOKEN not set")
return nil, errors.New("DuckDNS: credentials missing")
}
return &DNSProvider{token: duckdnsToken}, nil

View file

@ -22,22 +22,26 @@ func init() {
}
}
func restoreDuckdnsEnv() {
func restoreEnv() {
os.Setenv("DUCKDNS_TOKEN", duckdnsToken)
}
func TestNewDNSProviderValidEnv(t *testing.T) {
defer restoreEnv()
os.Setenv("DUCKDNS_TOKEN", "123")
_, err := NewDNSProvider()
assert.NoError(t, err)
restoreDuckdnsEnv()
}
func TestNewDNSProviderMissingCredErr(t *testing.T) {
defer restoreEnv()
os.Setenv("DUCKDNS_TOKEN", "")
_, err := NewDNSProvider()
assert.EqualError(t, err, "environment variable DUCKDNS_TOKEN not set")
restoreDuckdnsEnv()
assert.EqualError(t, err, "DuckDNS: some credentials information are missing: DUCKDNS_TOKEN")
}
func TestLiveDuckdnsPresent(t *testing.T) {
if !duckdnsLiveTest {
t.Skip("skipping live test")

View file

@ -7,11 +7,11 @@ import (
"encoding/json"
"fmt"
"net/http"
"os"
"strconv"
"time"
"github.com/xenolf/lego/acme"
"github.com/xenolf/lego/platform/config/env"
)
var dynBaseURL = "https://api.dynect.net/REST"
@ -43,10 +43,12 @@ type DNSProvider struct {
// 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)
values, err := env.Get("DYN_CUSTOMER_NAME", "DYN_USER_NAME", "DYN_PASSWORD")
if err != nil {
return nil, fmt.Errorf("DynDNS: %v", err)
}
return NewDNSProviderCredentials(values["DYN_CUSTOMER_NAME"], values["DYN_USER_NAME"], values["DYN_PASSWORD"])
}
// NewDNSProviderCredentials uses the supplied credentials to return a

View file

@ -9,6 +9,7 @@ import (
"github.com/exoscale/egoscale"
"github.com/xenolf/lego/acme"
"github.com/xenolf/lego/platform/config/env"
)
// DNSProvider is an implementation of the acme.ChallengeProvider interface.
@ -19,10 +20,13 @@ type DNSProvider struct {
// NewDNSProvider Credentials must be passed in the environment variables:
// EXOSCALE_API_KEY, EXOSCALE_API_SECRET, EXOSCALE_ENDPOINT.
func NewDNSProvider() (*DNSProvider, error) {
key := os.Getenv("EXOSCALE_API_KEY")
secret := os.Getenv("EXOSCALE_API_SECRET")
values, err := env.Get("EXOSCALE_API_KEY", "EXOSCALE_API_SECRET")
if err != nil {
return nil, fmt.Errorf("Exoscale: %v", err)
}
endpoint := os.Getenv("EXOSCALE_ENDPOINT")
return NewDNSProviderClient(key, secret, endpoint)
return NewDNSProviderClient(values["EXOSCALE_API_KEY"], values["EXOSCALE_API_SECRET"], endpoint)
}
// NewDNSProviderClient Uses the supplied parameters to return a DNSProvider instance
@ -31,6 +35,7 @@ func NewDNSProviderClient(key, secret, endpoint string) (*DNSProvider, error) {
if key == "" || secret == "" {
return nil, fmt.Errorf("Exoscale credentials missing")
}
if endpoint == "" {
endpoint = "https://api.exoscale.ch/dns"
}

View file

@ -24,32 +24,36 @@ func init() {
}
}
func restoreExoscaleEnv() {
func restoreEnv() {
os.Setenv("EXOSCALE_API_KEY", exoscaleAPIKey)
os.Setenv("EXOSCALE_API_SECRET", exoscaleAPISecret)
}
func TestNewDNSProviderValid(t *testing.T) {
defer restoreEnv()
os.Setenv("EXOSCALE_API_KEY", "")
os.Setenv("EXOSCALE_API_SECRET", "")
_, err := NewDNSProviderClient("example@example.com", "123", "")
assert.NoError(t, err)
restoreExoscaleEnv()
}
func TestNewDNSProviderValidEnv(t *testing.T) {
defer restoreEnv()
os.Setenv("EXOSCALE_API_KEY", "example@example.com")
os.Setenv("EXOSCALE_API_SECRET", "123")
_, err := NewDNSProvider()
assert.NoError(t, err)
restoreExoscaleEnv()
}
func TestNewDNSProviderMissingCredErr(t *testing.T) {
os.Setenv("EXOSCALE_API_KEY", "")
os.Setenv("EXOSCALE_API_SECRET", "")
defer restoreEnv()
_, err := NewDNSProvider()
assert.EqualError(t, err, "Exoscale credentials missing")
restoreExoscaleEnv()
assert.EqualError(t, err, "Exoscale: some credentials information are missing: EXOSCALE_API_KEY,EXOSCALE_API_SECRET")
}
func TestExtractRootRecordName(t *testing.T) {

View file

@ -2,12 +2,12 @@ package fastdns
import (
"fmt"
"os"
"reflect"
configdns "github.com/akamai/AkamaiOPEN-edgegrid-golang/configdns-v1"
"github.com/akamai/AkamaiOPEN-edgegrid-golang/edgegrid"
"github.com/xenolf/lego/acme"
"github.com/xenolf/lego/platform/config/env"
)
// DNSProvider is an implementation of the acme.ChallengeProvider interface.
@ -18,19 +18,24 @@ type DNSProvider struct {
// NewDNSProvider uses the supplied environment variables to return a DNSProvider instance:
// AKAMAI_HOST, AKAMAI_CLIENT_TOKEN, AKAMAI_CLIENT_SECRET, AKAMAI_ACCESS_TOKEN
func NewDNSProvider() (*DNSProvider, error) {
host := os.Getenv("AKAMAI_HOST")
clientToken := os.Getenv("AKAMAI_CLIENT_TOKEN")
clientSecret := os.Getenv("AKAMAI_CLIENT_SECRET")
accessToken := os.Getenv("AKAMAI_ACCESS_TOKEN")
values, err := env.Get("AKAMAI_HOST", "AKAMAI_CLIENT_TOKEN", "AKAMAI_CLIENT_SECRET", "AKAMAI_ACCESS_TOKEN")
if err != nil {
return nil, fmt.Errorf("FastDNS: %v", err)
}
return NewDNSProviderClient(host, clientToken, clientSecret, accessToken)
return NewDNSProviderClient(
values["AKAMAI_HOST"],
values["AKAMAI_CLIENT_TOKEN"],
values["AKAMAI_CLIENT_SECRET"],
values["AKAMAI_ACCESS_TOKEN"],
)
}
// NewDNSProviderClient uses the supplied parameters to return a DNSProvider instance
// configured for FastDNS.
func NewDNSProviderClient(host, clientToken, clientSecret, accessToken string) (*DNSProvider, error) {
if clientToken == "" || clientSecret == "" || accessToken == "" || host == "" {
return nil, fmt.Errorf("Akamai FastDNS credentials missing")
return nil, fmt.Errorf("FastDNS credentials are missing")
}
config := edgegrid.Config{
Host: host,

View file

@ -29,7 +29,7 @@ func init() {
}
}
func restoreFastdnsEnv() {
func restoreEnv() {
os.Setenv("AKAMAI_HOST", host)
os.Setenv("AKAMAI_CLIENT_TOKEN", clientToken)
os.Setenv("AKAMAI_CLIENT_SECRET", clientSecret)
@ -37,33 +37,36 @@ func restoreFastdnsEnv() {
}
func TestNewDNSProviderValid(t *testing.T) {
defer restoreEnv()
os.Setenv("AKAMAI_HOST", "")
os.Setenv("AKAMAI_CLIENT_TOKEN", "")
os.Setenv("AKAMAI_CLIENT_SECRET", "")
os.Setenv("AKAMAI_ACCESS_TOKEN", "")
_, err := NewDNSProviderClient("somehost", "someclienttoken", "someclientsecret", "someaccesstoken")
assert.NoError(t, err)
restoreFastdnsEnv()
}
func TestNewDNSProviderValidEnv(t *testing.T) {
defer restoreEnv()
os.Setenv("AKAMAI_HOST", "somehost")
os.Setenv("AKAMAI_CLIENT_TOKEN", "someclienttoken")
os.Setenv("AKAMAI_CLIENT_SECRET", "someclientsecret")
os.Setenv("AKAMAI_ACCESS_TOKEN", "someaccesstoken")
_, err := NewDNSProvider()
assert.NoError(t, err)
restoreFastdnsEnv()
}
func TestNewDNSProviderMissingCredErr(t *testing.T) {
defer restoreEnv()
os.Setenv("AKAMAI_HOST", "")
os.Setenv("AKAMAI_CLIENT_TOKEN", "")
os.Setenv("AKAMAI_CLIENT_SECRET", "")
os.Setenv("AKAMAI_ACCESS_TOKEN", "")
_, err := NewDNSProvider()
assert.EqualError(t, err, "Akamai FastDNS credentials missing")
restoreFastdnsEnv()
assert.EqualError(t, err, "FastDNS: some credentials information are missing: AKAMAI_HOST,AKAMAI_CLIENT_TOKEN,AKAMAI_CLIENT_SECRET,AKAMAI_ACCESS_TOKEN")
}
func TestLiveFastdnsPresent(t *testing.T) {

View file

@ -9,12 +9,12 @@ import (
"io"
"io/ioutil"
"net/http"
"os"
"strings"
"sync"
"time"
"github.com/xenolf/lego/acme"
"github.com/xenolf/lego/platform/config/env"
)
// Gandi API reference: http://doc.rpc.gandi.net/index.html
@ -49,8 +49,12 @@ type DNSProvider struct {
// 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)
values, err := env.Get("GANDI_API_KEY")
if err != nil {
return nil, fmt.Errorf("GandiDNS: %v", err)
}
return NewDNSProviderCredentials(values["GANDI_API_KEY"])
}
// NewDNSProviderCredentials uses the supplied credentials to return a

View file

@ -8,6 +8,8 @@ import (
"regexp"
"strings"
"testing"
"github.com/stretchr/testify/require"
)
// TestDNSProvider runs Present and CleanUp against a fake Gandi RPC
@ -15,55 +17,49 @@ import (
func TestDNSProvider(t *testing.T) {
fakeAPIKey := "123412341234123412341234"
fakeKeyAuth := "XXXX"
provider, err := NewDNSProviderCredentials(fakeAPIKey)
if err != nil {
t.Fatal(err)
}
require.NoError(t, err)
regexpDate, err := regexp.Compile(`\[ACME Challenge [^\]:]*:[^\]]*\]`)
if err != nil {
t.Fatal(err)
}
require.NoError(t, err)
// start fake RPC server
fakeServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Header.Get("Content-Type") != "text/xml" {
t.Fatalf("Content-Type: text/xml header not found")
}
require.Equal(t, "text/xml", r.Header.Get("Content-Type"), "invalid content type")
req, err := ioutil.ReadAll(r.Body)
if err != nil {
t.Fatal(err)
}
req = regexpDate.ReplaceAllLiteral(
req, []byte(`[ACME Challenge 01 Jan 16 00:00 +0000]`))
require.NoError(t, err)
req = regexpDate.ReplaceAllLiteral(req, []byte(`[ACME Challenge 01 Jan 16 00:00 +0000]`))
resp, ok := serverResponses[string(req)]
if !ok {
t.Fatalf("Server response for request not found")
}
require.True(t, ok, "Server response for request not found")
_, err = io.Copy(w, strings.NewReader(resp))
if err != nil {
t.Fatal(err)
}
require.NoError(t, err)
}))
defer fakeServer.Close()
// define function to override findZoneByFqdn with
fakeFindZoneByFqdn := func(fqdn string, nameserver []string) (string, error) {
return "example.com.", nil
}
// override gandi endpoint and findZoneByFqdn function
savedEndpoint, savedFindZoneByFqdn := endpoint, findZoneByFqdn
defer func() {
endpoint, findZoneByFqdn = savedEndpoint, savedFindZoneByFqdn
}()
endpoint, findZoneByFqdn = fakeServer.URL+"/", fakeFindZoneByFqdn
// run Present
err = provider.Present("abc.def.example.com", "", fakeKeyAuth)
if err != nil {
t.Fatal(err)
}
require.NoError(t, err)
// run CleanUp
err = provider.CleanUp("abc.def.example.com", "", fakeKeyAuth)
if err != nil {
t.Fatal(err)
}
require.NoError(t, err)
}
// serverResponses is the XML-RPC Request->Response map used by the

View file

@ -7,12 +7,12 @@ import (
"encoding/json"
"fmt"
"net/http"
"os"
"strings"
"sync"
"time"
"github.com/xenolf/lego/acme"
"github.com/xenolf/lego/platform/config/env"
)
// Gandi API reference: http://doc.livedns.gandi.net/
@ -45,8 +45,12 @@ 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) {
apiKey := os.Getenv("GANDIV5_API_KEY")
return NewDNSProviderCredentials(apiKey)
values, err := env.Get("GANDIV5_API_KEY")
if err != nil {
return nil, fmt.Errorf("GandiDNS: %v", err)
}
return NewDNSProviderCredentials(values["GANDIV5_API_KEY"])
}
// NewDNSProviderCredentials uses the supplied credentials to return a

View file

@ -8,6 +8,8 @@ import (
"regexp"
"strings"
"testing"
"github.com/stretchr/testify/require"
)
// TestDNSProvider runs Present and CleanUp against a fake Gandi RPC
@ -15,55 +17,50 @@ import (
func TestDNSProvider(t *testing.T) {
fakeAPIKey := "123412341234123412341234"
fakeKeyAuth := "XXXX"
provider, err := NewDNSProviderCredentials(fakeAPIKey)
if err != nil {
t.Fatal(err)
}
require.NoError(t, err)
regexpToken, err := regexp.Compile(`"rrset_values":\[".+"\]`)
if err != nil {
t.Fatal(err)
}
require.NoError(t, err)
// start fake RPC server
fakeServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Header.Get("Content-Type") != "application/json" {
t.Fatalf("Content-Type: application/json header not found")
}
require.Equal(t, "application/json", r.Header.Get("Content-Type"), "invalid content type")
req, err := ioutil.ReadAll(r.Body)
if err != nil {
t.Fatal(err)
}
req = regexpToken.ReplaceAllLiteral(
req, []byte(`"rrset_values":["TOKEN"]`))
require.NoError(t, err)
req = regexpToken.ReplaceAllLiteral(req, []byte(`"rrset_values":["TOKEN"]`))
resp, ok := serverResponses[string(req)]
if !ok {
t.Fatalf("Server response for request not found")
}
require.True(t, ok, "Server response for request not found")
_, err = io.Copy(w, strings.NewReader(resp))
if err != nil {
t.Fatal(err)
}
require.NoError(t, err)
}))
defer fakeServer.Close()
// define function to override findZoneByFqdn with
fakeFindZoneByFqdn := func(fqdn string, nameserver []string) (string, error) {
return "example.com.", nil
}
// override gandi endpoint and findZoneByFqdn function
savedEndpoint, savedFindZoneByFqdn := endpoint, findZoneByFqdn
defer func() {
endpoint, findZoneByFqdn = savedEndpoint, savedFindZoneByFqdn
}()
endpoint, findZoneByFqdn = fakeServer.URL, fakeFindZoneByFqdn
// run Present
err = provider.Present("abc.def.example.com", "", fakeKeyAuth)
if err != nil {
t.Fatal(err)
}
require.NoError(t, err)
// run CleanUp
err = provider.CleanUp("abc.def.example.com", "", fakeKeyAuth)
if err != nil {
t.Fatal(err)
}
require.NoError(t, err)
}
// serverResponses is the JSON Request->Response map used by the

View file

@ -31,6 +31,7 @@ func NewDNSProvider() (*DNSProvider, error) {
if saFile, ok := os.LookupEnv("GCE_SERVICE_ACCOUNT_FILE"); ok {
return NewDNSProviderServiceAccount(saFile)
}
project := os.Getenv("GCE_PROJECT")
return NewDNSProviderCredentials(project)
}
@ -44,11 +45,11 @@ func NewDNSProviderCredentials(project string) (*DNSProvider, error) {
client, err := google.DefaultClient(context.Background(), dns.NdevClouddnsReadwriteScope)
if err != nil {
return nil, fmt.Errorf("Unable to get Google Cloud client: %v", err)
return nil, fmt.Errorf("unable to get Google Cloud client: %v", err)
}
svc, err := dns.New(client)
if err != nil {
return nil, fmt.Errorf("Unable to create Google Cloud DNS service: %v", err)
return nil, fmt.Errorf("unable to create Google Cloud DNS service: %v", err)
}
return &DNSProvider{
project: project,
@ -65,7 +66,7 @@ func NewDNSProviderServiceAccount(saFile string) (*DNSProvider, error) {
dat, err := ioutil.ReadFile(saFile)
if err != nil {
return nil, fmt.Errorf("Unable to read Service Account file: %v", err)
return nil, fmt.Errorf("unable to read Service Account file: %v", err)
}
// read project id from service account file
@ -74,19 +75,19 @@ func NewDNSProviderServiceAccount(saFile string) (*DNSProvider, error) {
}
err = json.Unmarshal(dat, &datJSON)
if err != nil || datJSON.ProjectID == "" {
return nil, fmt.Errorf("Project ID not found in Google Cloud Service Account file")
return nil, fmt.Errorf("project ID not found in Google Cloud Service Account file")
}
project := datJSON.ProjectID
conf, err := google.JWTConfigFromJSON(dat, dns.NdevClouddnsReadwriteScope)
if err != nil {
return nil, fmt.Errorf("Unable to acquire config: %v", err)
return nil, fmt.Errorf("unable to acquire config: %v", err)
}
client := conf.Client(context.Background())
svc, err := dns.New(client)
if err != nil {
return nil, fmt.Errorf("Unable to create Google Cloud DNS service: %v", err)
return nil, fmt.Errorf("unable to create Google Cloud DNS service: %v", err)
}
return &DNSProvider{
project: project,
@ -189,7 +190,7 @@ func (c *DNSProvider) getHostedZone(domain string) (string, error) {
}
if len(zones.ManagedZones) == 0 {
return "", fmt.Errorf("No matching GoogleCloud domain found for domain %s", authZone)
return "", fmt.Errorf("no matching GoogleCloud domain found for domain %s", authZone)
}
return zones.ManagedZones[0].Name, nil
@ -202,7 +203,7 @@ func (c *DNSProvider) findTxtRecords(zone, fqdn string) ([]*dns.ResourceRecordSe
return nil, err
}
found := []*dns.ResourceRecordSet{}
var found []*dns.ResourceRecordSet
for _, r := range recs.Rrsets {
if r.Type == "TXT" && r.Name == fqdn {
found = append(found, r)

View file

@ -27,7 +27,7 @@ func init() {
}
}
func restoreGCloudEnv() {
func restoreEnv() {
os.Setenv("GCE_PROJECT", gcloudProject)
}
@ -35,27 +35,32 @@ func TestNewDNSProviderValid(t *testing.T) {
if !gcloudLiveTest {
t.Skip("skipping live test (requires credentials)")
}
defer restoreEnv()
os.Setenv("GCE_PROJECT", "")
_, err := NewDNSProviderCredentials("my-project")
assert.NoError(t, err)
restoreGCloudEnv()
}
func TestNewDNSProviderValidEnv(t *testing.T) {
if !gcloudLiveTest {
t.Skip("skipping live test (requires credentials)")
}
defer restoreEnv()
os.Setenv("GCE_PROJECT", "my-project")
_, err := NewDNSProvider()
assert.NoError(t, err)
restoreGCloudEnv()
}
func TestNewDNSProviderMissingCredErr(t *testing.T) {
defer restoreEnv()
os.Setenv("GCE_PROJECT", "")
_, err := NewDNSProvider()
assert.EqualError(t, err, "Google Cloud project name missing")
restoreGCloudEnv()
}
func TestLiveGoogleCloudPresent(t *testing.T) {

View file

@ -7,13 +7,13 @@ import (
"encoding/json"
"fmt"
"net/http"
"os"
"strings"
"sync"
"time"
"github.com/xenolf/lego/acme"
"github.com/xenolf/lego/log"
"github.com/xenolf/lego/platform/config/env"
)
// GleSYS API reference: https://github.com/GleSYS/API/wiki/API-Documentation
@ -35,9 +35,12 @@ type DNSProvider struct {
// Credentials must be passed in the environment variables: GLESYS_API_USER
// and GLESYS_API_KEY.
func NewDNSProvider() (*DNSProvider, error) {
apiUser := os.Getenv("GLESYS_API_USER")
apiKey := os.Getenv("GLESYS_API_KEY")
return NewDNSProviderCredentials(apiUser, apiKey)
values, err := env.Get("GLESYS_API_USER", "GLESYS_API_KEY")
if err != nil {
return nil, fmt.Errorf("GleSYS DNS: %v", err)
}
return NewDNSProviderCredentials(values["GLESYS_API_USER"], values["GLESYS_API_KEY"])
}
// NewDNSProviderCredentials uses the supplied credentials to return a

View file

@ -2,18 +2,17 @@
package godaddy
import (
"fmt"
"io"
"net/http"
"os"
"time"
"bytes"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"net/http"
"strings"
"time"
"github.com/xenolf/lego/acme"
"github.com/xenolf/lego/platform/config/env"
)
// GoDaddyAPIURL represents the API endpoint to call.
@ -29,9 +28,12 @@ type DNSProvider struct {
// Credentials must be passed in the environment variables: GODADDY_API_KEY
// and GODADDY_API_SECRET.
func NewDNSProvider() (*DNSProvider, error) {
apikey := os.Getenv("GODADDY_API_KEY")
secret := os.Getenv("GODADDY_API_SECRET")
return NewDNSProviderCredentials(apikey, secret)
values, err := env.Get("GODADDY_API_KEY", "GODADDY_API_SECRET")
if err != nil {
return nil, fmt.Errorf("GoDaddy: %v", err)
}
return NewDNSProviderCredentials(values["GODADDY_API_KEY"], values["GODADDY_API_SECRET"])
}
// NewDNSProviderCredentials uses the supplied credentials to return a

View file

@ -8,40 +8,40 @@ import (
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/lightsail"
"github.com/stretchr/testify/require"
)
func TestLightsailTTL(t *testing.T) {
m, err := testGetAndPreCheck()
if err != nil {
t.Skip(err.Error())
}
provider, err := NewDNSProvider()
if err != nil {
t.Fatalf("Fatal: %s", err.Error())
}
require.NoError(t, err)
err = provider.Present(m["lightsailDomain"], "foo", "bar")
if err != nil {
t.Fatalf("Fatal: %s", err.Error())
}
require.NoError(t, err)
// we need a separate Lightshail client here as the one in the DNS provider is
// unexported.
fqdn := "_acme-challenge." + m["lightsailDomain"]
svc := lightsail.New(session.New())
if err != nil {
provider.CleanUp(m["lightsailDomain"], "foo", "bar")
t.Fatalf("Fatal: %s", err.Error())
t.Fatal(err)
}
params := &lightsail.GetDomainInput{
DomainName: aws.String(m["lightsailDomain"]),
}
resp, err := svc.GetDomain(params)
if err != nil {
provider.CleanUp(m["lightsailDomain"], "foo", "bar")
t.Fatalf("Fatal: %s", err.Error())
t.Fatal(err)
}
entries := resp.Domain.DomainEntries
for _, entry := range entries {
if *entry.Type == "TXT" && *entry.Name == fqdn {
@ -49,6 +49,7 @@ func TestLightsailTTL(t *testing.T) {
return
}
}
provider.CleanUp(m["lightsailDomain"], "foo", "bar")
t.Fatalf("Could not find a TXT record for _acme-challenge.%s", m["lightsailDomain"])
}

View file

@ -23,7 +23,7 @@ func init() {
lightsailSecret = os.Getenv("AWS_SECRET_ACCESS_KEY")
}
func restoreLightsailEnv() {
func restoreEnv() {
os.Setenv("AWS_ACCESS_KEY_ID", lightsailKey)
os.Setenv("AWS_SECRET_ACCESS_KEY", lightsailSecret)
os.Setenv("AWS_REGION", "us-east-1")
@ -43,6 +43,7 @@ func makeLightsailProvider(ts *httptest.Server) *DNSProvider {
}
func TestCredentialsFromEnv(t *testing.T) {
defer restoreEnv()
os.Setenv("AWS_ACCESS_KEY_ID", "123")
os.Setenv("AWS_SECRET_ACCESS_KEY", "123")
os.Setenv("AWS_REGION", "us-east-1")
@ -54,8 +55,6 @@ func TestCredentialsFromEnv(t *testing.T) {
sess := session.New(config)
_, err := sess.Config.Credentials.Get()
assert.NoError(t, err, "Expected credentials to be set from environment")
restoreLightsailEnv()
}
func TestLightsailPresent(t *testing.T) {

View file

@ -4,12 +4,13 @@ package linode
import (
"errors"
"os"
"fmt"
"strings"
"time"
"github.com/timewasted/linode/dns"
"github.com/xenolf/lego/acme"
"github.com/xenolf/lego/platform/config/env"
)
const (
@ -31,8 +32,12 @@ type DNSProvider struct {
// NewDNSProvider returns a DNSProvider instance configured for Linode.
// Credentials must be passed in the environment variable: LINODE_API_KEY.
func NewDNSProvider() (*DNSProvider, error) {
apiKey := os.Getenv("LINODE_API_KEY")
return NewDNSProviderCredentials(apiKey)
values, err := env.Get("LINODE_API_KEY")
if err != nil {
return nil, fmt.Errorf("Linode: %v", err)
}
return NewDNSProviderCredentials(values["LINODE_API_KEY"])
}
// NewDNSProviderCredentials uses the supplied credentials to return a

View file

@ -48,8 +48,7 @@ func newMockServer(t *testing.T, responses MockResponseMap) *httptest.Server {
action := r.URL.Query().Get("api_action")
resp, ok := responses[action]
if !ok {
msg := fmt.Sprintf("Unsupported mock action: %s", action)
require.FailNow(t, msg)
require.FailNowf(t, "Unsupported mock action: %s", action)
}
// Build the response that the server will return.
@ -75,17 +74,19 @@ func newMockServer(t *testing.T, responses MockResponseMap) *httptest.Server {
}
func TestNewDNSProviderWithEnv(t *testing.T) {
os.Setenv("LINODE_API_KEY", "testing")
defer restoreEnv()
os.Setenv("LINODE_API_KEY", "testing")
_, err := NewDNSProvider()
assert.NoError(t, err)
}
func TestNewDNSProviderWithoutEnv(t *testing.T) {
os.Setenv("LINODE_API_KEY", "")
defer restoreEnv()
os.Setenv("LINODE_API_KEY", "")
_, err := NewDNSProvider()
assert.EqualError(t, err, "Linode credentials missing")
assert.EqualError(t, err, "Linode: some credentials information are missing: LINODE_API_KEY")
}
func TestNewDNSProviderCredentialsWithKey(t *testing.T) {
@ -99,8 +100,9 @@ func TestNewDNSProviderCredentialsWithoutKey(t *testing.T) {
}
func TestDNSProvider_Present(t *testing.T) {
os.Setenv("LINODE_API_KEY", "testing")
defer restoreEnv()
os.Setenv("LINODE_API_KEY", "testing")
p, err := NewDNSProvider()
assert.NoError(t, err)
@ -109,7 +111,7 @@ func TestDNSProvider_Present(t *testing.T) {
mockResponses := MockResponseMap{
"domain.list": MockResponse{
Response: []dns.Domain{
dns.Domain{
{
Domain: domain,
DomainID: 1234,
},
@ -121,8 +123,10 @@ func TestDNSProvider_Present(t *testing.T) {
},
},
}
mockSrv := newMockServer(t, mockResponses)
defer mockSrv.Close()
p.linode.ToLinode().SetEndpoint(mockSrv.URL)
err = p.Present(domain, "", keyAuth)
@ -130,8 +134,9 @@ func TestDNSProvider_Present(t *testing.T) {
}
func TestDNSProvider_PresentNoDomain(t *testing.T) {
os.Setenv("LINODE_API_KEY", "testing")
defer restoreEnv()
os.Setenv("LINODE_API_KEY", "testing")
p, err := NewDNSProvider()
assert.NoError(t, err)
@ -140,15 +145,17 @@ func TestDNSProvider_PresentNoDomain(t *testing.T) {
mockResponses := MockResponseMap{
"domain.list": MockResponse{
Response: []dns.Domain{
dns.Domain{
{
Domain: "foobar.com",
DomainID: 1234,
},
},
},
}
mockSrv := newMockServer(t, mockResponses)
defer mockSrv.Close()
p.linode.ToLinode().SetEndpoint(mockSrv.URL)
err = p.Present(domain, "", keyAuth)
@ -156,8 +163,9 @@ func TestDNSProvider_PresentNoDomain(t *testing.T) {
}
func TestDNSProvider_PresentCreateFailed(t *testing.T) {
os.Setenv("LINODE_API_KEY", "testing")
defer restoreEnv()
os.Setenv("LINODE_API_KEY", "testing")
p, err := NewDNSProvider()
assert.NoError(t, err)
@ -166,7 +174,7 @@ func TestDNSProvider_PresentCreateFailed(t *testing.T) {
mockResponses := MockResponseMap{
"domain.list": MockResponse{
Response: []dns.Domain{
dns.Domain{
{
Domain: domain,
DomainID: 1234,
},
@ -175,7 +183,7 @@ func TestDNSProvider_PresentCreateFailed(t *testing.T) {
"domain.resource.create": MockResponse{
Response: nil,
Errors: []linode.ResponseError{
linode.ResponseError{
{
Code: 1234,
Message: "Failed to create domain resource",
},
@ -184,6 +192,7 @@ func TestDNSProvider_PresentCreateFailed(t *testing.T) {
}
mockSrv := newMockServer(t, mockResponses)
defer mockSrv.Close()
p.linode.ToLinode().SetEndpoint(mockSrv.URL)
err = p.Present(domain, "", keyAuth)
@ -197,8 +206,9 @@ func TestDNSProvider_PresentLive(t *testing.T) {
}
func TestDNSProvider_CleanUp(t *testing.T) {
os.Setenv("LINODE_API_KEY", "testing")
defer restoreEnv()
os.Setenv("LINODE_API_KEY", "testing")
p, err := NewDNSProvider()
assert.NoError(t, err)
@ -207,7 +217,7 @@ func TestDNSProvider_CleanUp(t *testing.T) {
mockResponses := MockResponseMap{
"domain.list": MockResponse{
Response: []dns.Domain{
dns.Domain{
{
Domain: domain,
DomainID: 1234,
},
@ -215,7 +225,7 @@ func TestDNSProvider_CleanUp(t *testing.T) {
},
"domain.resource.list": MockResponse{
Response: []dns.Resource{
dns.Resource{
{
DomainID: 1234,
Name: "_acme-challenge",
ResourceID: 1234,
@ -230,8 +240,10 @@ func TestDNSProvider_CleanUp(t *testing.T) {
},
},
}
mockSrv := newMockServer(t, mockResponses)
defer mockSrv.Close()
p.linode.ToLinode().SetEndpoint(mockSrv.URL)
err = p.CleanUp(domain, "", keyAuth)
@ -239,8 +251,9 @@ func TestDNSProvider_CleanUp(t *testing.T) {
}
func TestDNSProvider_CleanUpNoDomain(t *testing.T) {
os.Setenv("LINODE_API_KEY", "testing")
defer restoreEnv()
os.Setenv("LINODE_API_KEY", "testing")
p, err := NewDNSProvider()
assert.NoError(t, err)
@ -249,15 +262,17 @@ func TestDNSProvider_CleanUpNoDomain(t *testing.T) {
mockResponses := MockResponseMap{
"domain.list": MockResponse{
Response: []dns.Domain{
dns.Domain{
{
Domain: "foobar.com",
DomainID: 1234,
},
},
},
}
mockSrv := newMockServer(t, mockResponses)
defer mockSrv.Close()
p.linode.ToLinode().SetEndpoint(mockSrv.URL)
err = p.CleanUp(domain, "", keyAuth)
@ -265,8 +280,9 @@ func TestDNSProvider_CleanUpNoDomain(t *testing.T) {
}
func TestDNSProvider_CleanUpDeleteFailed(t *testing.T) {
os.Setenv("LINODE_API_KEY", "testing")
defer restoreEnv()
os.Setenv("LINODE_API_KEY", "testing")
p, err := NewDNSProvider()
assert.NoError(t, err)
@ -275,7 +291,7 @@ func TestDNSProvider_CleanUpDeleteFailed(t *testing.T) {
mockResponses := MockResponseMap{
"domain.list": MockResponse{
Response: []dns.Domain{
dns.Domain{
{
Domain: domain,
DomainID: 1234,
},
@ -283,7 +299,7 @@ func TestDNSProvider_CleanUpDeleteFailed(t *testing.T) {
},
"domain.resource.list": MockResponse{
Response: []dns.Resource{
dns.Resource{
{
DomainID: 1234,
Name: "_acme-challenge",
ResourceID: 1234,
@ -295,23 +311,19 @@ func TestDNSProvider_CleanUpDeleteFailed(t *testing.T) {
"domain.resource.delete": MockResponse{
Response: nil,
Errors: []linode.ResponseError{
linode.ResponseError{
{
Code: 1234,
Message: "Failed to delete domain resource",
},
},
},
}
mockSrv := newMockServer(t, mockResponses)
defer mockSrv.Close()
p.linode.ToLinode().SetEndpoint(mockSrv.URL)
err = p.CleanUp(domain, "", keyAuth)
assert.EqualError(t, err, "Failed to delete domain resource")
}
func TestDNSProvider_CleanUpLive(t *testing.T) {
if !isTestLive {
t.Skip("Skipping live test")
}
}

View file

@ -8,11 +8,11 @@ import (
"io/ioutil"
"net/http"
"net/url"
"os"
"strings"
"time"
"github.com/xenolf/lego/acme"
"github.com/xenolf/lego/platform/config/env"
)
// Notes about namecheap's tool API:
@ -48,9 +48,12 @@ type DNSProvider struct {
// 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)
values, err := env.Get("NAMECHEAP_API_USER", "NAMECHEAP_API_KEY")
if err != nil {
return nil, fmt.Errorf("NameCheap: %v", err)
}
return NewDNSProviderCredentials(values["NAMECHEAP_API_USER"], values["NAMECHEAP_API_KEY"])
}
// NewDNSProviderCredentials uses the supplied credentials to return a
@ -117,7 +120,7 @@ func getClientIP() (addr string, err error) {
return string(clientIP), nil
}
// A challenge repesents all the data needed to specify a dns-01 challenge
// A challenge represents all the data needed to specify a dns-01 challenge
// to lets-encrypt.
type challenge struct {
domain string

View file

@ -241,6 +241,8 @@ func TestNamecheapDomainSplit(t *testing.T) {
}
for _, test := range tests {
test := test
t.Run(test.domain, func(t *testing.T) {
valid := true
ch, err := newChallenge(test.domain, "", tlds)
if err != nil {
@ -259,6 +261,7 @@ func TestNamecheapDomainSplit(t *testing.T) {
assertEq(t, "sld", ch.sld, test.sld)
assertEq(t, "host", ch.host, test.host)
}
})
}
}

View file

@ -9,6 +9,7 @@ import (
"github.com/namedotcom/go/namecom"
"github.com/xenolf/lego/acme"
"github.com/xenolf/lego/platform/config/env"
)
// DNSProvider is an implementation of the acme.ChallengeProvider interface.
@ -19,11 +20,13 @@ type DNSProvider struct {
// NewDNSProvider returns a DNSProvider instance configured for namedotcom.
// Credentials must be passed in the environment variables: NAMECOM_USERNAME and NAMECOM_API_TOKEN
func NewDNSProvider() (*DNSProvider, error) {
username := os.Getenv("NAMECOM_USERNAME")
apiToken := os.Getenv("NAMECOM_API_TOKEN")
server := os.Getenv("NAMECOM_SERVER")
values, err := env.Get("NAMECOM_USERNAME", "NAMECOM_API_TOKEN")
if err != nil {
return nil, fmt.Errorf("Name.com: %v", err)
}
return NewDNSProviderCredentials(username, apiToken, server)
server := os.Getenv("NAMECOM_SERVER")
return NewDNSProviderCredentials(values["NAMECOM_USERNAME"], values["NAMECOM_API_TOKEN"], server)
}
// NewDNSProviderCredentials uses the supplied credentials to return a
@ -59,7 +62,7 @@ func (c *DNSProvider) Present(domain, token, keyAuth string) error {
_, err := c.client.CreateRecord(request)
if err != nil {
return fmt.Errorf("namedotcom API call failed: %v", err)
return fmt.Errorf("Name.com API call failed: %v", err)
}
return nil

View file

@ -27,7 +27,7 @@ func init() {
}
}
func TestLivenamedotcomPresent(t *testing.T) {
func TestLiveNamedotcomPresent(t *testing.T) {
if !namedotcomLiveTest {
t.Skip("skipping live test")
}
@ -43,7 +43,7 @@ func TestLivenamedotcomPresent(t *testing.T) {
// Cleanup
//
func TestLivenamedotcomCleanUp(t *testing.T) {
func TestLiveNamedotcomCleanUp(t *testing.T) {
if !namedotcomLiveTest {
t.Skip("skipping live test")
}

View file

@ -5,10 +5,10 @@ package ns1
import (
"fmt"
"net/http"
"os"
"time"
"github.com/xenolf/lego/acme"
"github.com/xenolf/lego/platform/config/env"
"gopkg.in/ns1/ns1-go.v2/rest"
"gopkg.in/ns1/ns1-go.v2/rest/model/dns"
)
@ -21,11 +21,12 @@ type DNSProvider struct {
// NewDNSProvider returns a DNSProvider instance configured for NS1.
// Credentials must be passed in the environment variables: NS1_API_KEY.
func NewDNSProvider() (*DNSProvider, error) {
key := os.Getenv("NS1_API_KEY")
if key == "" {
return nil, fmt.Errorf("NS1 credentials missing")
values, err := env.Get("NS1_API_KEY")
if err != nil {
return nil, fmt.Errorf("NS1: %v", err)
}
return NewDNSProviderCredentials(key)
return NewDNSProviderCredentials(values["NS1_API_KEY"])
}
// NewDNSProviderCredentials uses the supplied credentials to return a

View file

@ -22,22 +22,24 @@ func init() {
}
}
func restoreNS1Env() {
func restoreEnv() {
os.Setenv("NS1_API_KEY", apiKey)
}
func TestNewDNSProviderValid(t *testing.T) {
defer restoreEnv()
os.Setenv("NS1_API_KEY", "")
_, err := NewDNSProviderCredentials("123")
assert.NoError(t, err)
restoreNS1Env()
}
func TestNewDNSProviderMissingCredErr(t *testing.T) {
defer restoreEnv()
os.Setenv("NS1_API_KEY", "")
_, err := NewDNSProvider()
assert.EqualError(t, err, "NS1 credentials missing")
restoreNS1Env()
assert.EqualError(t, err, "NS1: some credentials information are missing: NS1_API_KEY")
}
func TestLivePresent(t *testing.T) {

View file

@ -13,6 +13,7 @@ import (
"time"
"github.com/xenolf/lego/acme"
"github.com/xenolf/lego/platform/config/env"
)
// DNSProvider is an implementation of the acme.ChallengeProvider interface that uses
@ -31,12 +32,18 @@ type DNSProvider struct {
// Credentials must be passed in the environment variables: OTC_USER_NAME,
// OTC_DOMAIN_NAME, OTC_PASSWORD OTC_PROJECT_NAME and OTC_IDENTITY_ENDPOINT.
func NewDNSProvider() (*DNSProvider, error) {
domainName := os.Getenv("OTC_DOMAIN_NAME")
userName := os.Getenv("OTC_USER_NAME")
password := os.Getenv("OTC_PASSWORD")
projectName := os.Getenv("OTC_PROJECT_NAME")
identityEndpoint := os.Getenv("OTC_IDENTITY_ENDPOINT")
return NewDNSProviderCredentials(domainName, userName, password, projectName, identityEndpoint)
values, err := env.Get("OTC_DOMAIN_NAME", "OTC_USER_NAME", "OTC_PASSWORD", "OTC_PROJECT_NAME")
if err != nil {
return nil, fmt.Errorf("OTC: %v", err)
}
return NewDNSProviderCredentials(
values["OTC_DOMAIN_NAME"],
values["OTC_USER_NAME"],
values["OTC_PASSWORD"],
values["OTC_PROJECT_NAME"],
os.Getenv("OTC_IDENTITY_ENDPOINT"),
)
}
// NewDNSProviderCredentials uses the supplied credentials to return a

View file

@ -2,10 +2,11 @@ package otc
import (
"fmt"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/suite"
"os"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/suite"
)
type OTCDNSTestSuite struct {
@ -34,6 +35,8 @@ func (s *OTCDNSTestSuite) createDNSProvider() (*DNSProvider, error) {
}
func (s *OTCDNSTestSuite) TestOTCDNSLoginEnv() {
defer os.Clearenv()
os.Setenv("OTC_DOMAIN_NAME", "unittest1")
os.Setenv("OTC_USER_NAME", "unittest2")
os.Setenv("OTC_PASSWORD", "unittest3")
@ -53,15 +56,13 @@ func (s *OTCDNSTestSuite) TestOTCDNSLoginEnv() {
provider, err = NewDNSProvider()
assert.Nil(s.T(), err)
assert.Equal(s.T(), provider.identityEndpoint, "https://iam.eu-de.otc.t-systems.com:443/v3/auth/tokens")
os.Clearenv()
}
func (s *OTCDNSTestSuite) TestOTCDNSLoginEnvEmpty() {
_, err := NewDNSProvider()
assert.Equal(s.T(), "OTC credentials missing", err.Error())
defer os.Clearenv()
os.Clearenv()
_, err := NewDNSProvider()
assert.EqualError(s.T(), err, "OTC: some credentials information are missing: OTC_DOMAIN_NAME,OTC_USER_NAME,OTC_PASSWORD,OTC_PROJECT_NAME")
}
func (s *OTCDNSTestSuite) TestOTCDNSLogin() {

View file

@ -4,12 +4,12 @@ package ovh
import (
"fmt"
"os"
"strings"
"sync"
"github.com/ovh/go-ovh/ovh"
"github.com/xenolf/lego/acme"
"github.com/xenolf/lego/platform/config/env"
)
// OVH API reference: https://eu.api.ovh.com/
@ -30,11 +30,17 @@ type DNSProvider struct {
// OVH_APPLICATION_SECRET
// OVH_CONSUMER_KEY
func NewDNSProvider() (*DNSProvider, error) {
apiEndpoint := os.Getenv("OVH_ENDPOINT")
applicationKey := os.Getenv("OVH_APPLICATION_KEY")
applicationSecret := os.Getenv("OVH_APPLICATION_SECRET")
consumerKey := os.Getenv("OVH_CONSUMER_KEY")
return NewDNSProviderCredentials(apiEndpoint, applicationKey, applicationSecret, consumerKey)
values, err := env.Get("OVH_ENDPOINT", "OVH_APPLICATION_KEY", "OVH_APPLICATION_SECRET", "OVH_CONSUMER_KEY")
if err != nil {
return nil, fmt.Errorf("OVH: %v", err)
}
return NewDNSProviderCredentials(
values["OVH_ENDPOINT"],
values["OVH_APPLICATION_KEY"],
values["OVH_APPLICATION_SECRET"],
values["OVH_CONSUMER_KEY"],
)
}
// NewDNSProviderCredentials uses the supplied credentials to return a

View file

@ -33,47 +33,88 @@ func restoreEnv() {
}
func TestNewDNSProviderValidEnv(t *testing.T) {
defer restoreEnv()
os.Setenv("OVH_ENDPOINT", "ovh-eu")
os.Setenv("OVH_APPLICATION_KEY", "1234")
os.Setenv("OVH_APPLICATION_SECRET", "5678")
os.Setenv("OVH_CONSUMER_KEY", "abcde")
defer restoreEnv()
_, err := NewDNSProvider()
assert.NoError(t, err)
}
func TestNewDNSProviderMissingCredErr(t *testing.T) {
os.Setenv("OVH_ENDPOINT", "")
os.Setenv("OVH_APPLICATION_KEY", "1234")
os.Setenv("OVH_APPLICATION_SECRET", "5678")
os.Setenv("OVH_CONSUMER_KEY", "abcde")
defer restoreEnv()
testCases := []struct {
desc string
envVars map[string]string
expected string
}{
{
desc: "missing OVH_ENDPOINT",
envVars: map[string]string{
"OVH_ENDPOINT": "",
"OVH_APPLICATION_KEY": "1234",
"OVH_APPLICATION_SECRET": "5678",
"OVH_CONSUMER_KEY": "abcde",
},
expected: "OVH: some credentials information are missing: OVH_ENDPOINT",
},
{
desc: "missing OVH_APPLICATION_KEY",
envVars: map[string]string{
"OVH_ENDPOINT": "ovh-eu",
"OVH_APPLICATION_KEY": "",
"OVH_APPLICATION_SECRET": "5678",
"OVH_CONSUMER_KEY": "abcde",
},
expected: "OVH: some credentials information are missing: OVH_APPLICATION_KEY",
},
{
desc: "missing OVH_APPLICATION_SECRET",
envVars: map[string]string{
"OVH_ENDPOINT": "ovh-eu",
"OVH_APPLICATION_KEY": "1234",
"OVH_APPLICATION_SECRET": "",
"OVH_CONSUMER_KEY": "abcde",
},
expected: "OVH: some credentials information are missing: OVH_APPLICATION_SECRET",
},
{
desc: "missing OVH_CONSUMER_KEY",
envVars: map[string]string{
"OVH_ENDPOINT": "ovh-eu",
"OVH_APPLICATION_KEY": "1234",
"OVH_APPLICATION_SECRET": "5678",
"OVH_CONSUMER_KEY": "",
},
expected: "OVH: some credentials information are missing: OVH_CONSUMER_KEY",
},
{
desc: "all missing",
envVars: map[string]string{
"OVH_ENDPOINT": "",
"OVH_APPLICATION_KEY": "",
"OVH_APPLICATION_SECRET": "",
"OVH_CONSUMER_KEY": "",
},
expected: "OVH: some credentials information are missing: OVH_ENDPOINT,OVH_APPLICATION_KEY,OVH_APPLICATION_SECRET,OVH_CONSUMER_KEY",
},
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
for key, value := range test.envVars {
os.Setenv(key, value)
}
_, err := NewDNSProvider()
assert.EqualError(t, err, "OVH credentials missing")
os.Setenv("OVH_ENDPOINT", "ovh-eu")
os.Setenv("OVH_APPLICATION_KEY", "")
os.Setenv("OVH_APPLICATION_SECRET", "5678")
os.Setenv("OVH_CONSUMER_KEY", "abcde")
defer restoreEnv()
_, err = NewDNSProvider()
assert.EqualError(t, err, "OVH credentials missing")
os.Setenv("OVH_ENDPOINT", "ovh-eu")
os.Setenv("OVH_APPLICATION_KEY", "1234")
os.Setenv("OVH_APPLICATION_SECRET", "")
os.Setenv("OVH_CONSUMER_KEY", "abcde")
defer restoreEnv()
_, err = NewDNSProvider()
assert.EqualError(t, err, "OVH credentials missing")
os.Setenv("OVH_ENDPOINT", "ovh-eu")
os.Setenv("OVH_APPLICATION_KEY", "1234")
os.Setenv("OVH_APPLICATION_SECRET", "5678")
os.Setenv("OVH_CONSUMER_KEY", "")
defer restoreEnv()
_, err = NewDNSProvider()
assert.EqualError(t, err, "OVH credentials missing")
assert.EqualError(t, err, test.expected)
})
}
}
func TestLivePresent(t *testing.T) {

View file

@ -9,12 +9,12 @@ import (
"io"
"net/http"
"net/url"
"os"
"strconv"
"strings"
"time"
"github.com/xenolf/lego/acme"
"github.com/xenolf/lego/platform/config/env"
)
// DNSProvider is an implementation of the acme.ChallengeProvider interface
@ -28,13 +28,17 @@ type DNSProvider struct {
// Credentials must be passed in the environment variable:
// PDNS_API_URL and PDNS_API_KEY.
func NewDNSProvider() (*DNSProvider, error) {
key := os.Getenv("PDNS_API_KEY")
hostURL, err := url.Parse(os.Getenv("PDNS_API_URL"))
values, err := env.Get("PDNS_API_KEY", "PDNS_API_URL")
if err != nil {
return nil, err
return nil, fmt.Errorf("PDNS: %v", err)
}
return NewDNSProviderCredentials(hostURL, key)
hostURL, err := url.Parse(values["PDNS_API_URL"])
if err != nil {
return nil, fmt.Errorf("PDNS: %v", err)
}
return NewDNSProviderCredentials(hostURL, values["PDNS_API_KEY"])
}
// NewDNSProviderCredentials uses the supplied credentials to return a

View file

@ -26,42 +26,46 @@ func init() {
}
}
func restorePdnsEnv() {
func restoreEnv() {
os.Setenv("PDNS_API_URL", pdnsURLStr)
os.Setenv("PDNS_API_KEY", pdnsAPIKey)
}
func TestNewDNSProviderValid(t *testing.T) {
defer restoreEnv()
os.Setenv("PDNS_API_URL", "")
os.Setenv("PDNS_API_KEY", "")
tmpURL, _ := url.Parse("http://localhost:8081")
_, err := NewDNSProviderCredentials(tmpURL, "123")
assert.NoError(t, err)
restorePdnsEnv()
}
func TestNewDNSProviderValidEnv(t *testing.T) {
defer restoreEnv()
os.Setenv("PDNS_API_URL", "http://localhost:8081")
os.Setenv("PDNS_API_KEY", "123")
_, err := NewDNSProvider()
assert.NoError(t, err)
restorePdnsEnv()
}
func TestNewDNSProviderMissingHostErr(t *testing.T) {
defer restoreEnv()
os.Setenv("PDNS_API_URL", "")
os.Setenv("PDNS_API_KEY", "123")
_, err := NewDNSProvider()
assert.EqualError(t, err, "PDNS API URL missing")
restorePdnsEnv()
assert.EqualError(t, err, "PDNS: some credentials information are missing: PDNS_API_URL")
}
func TestNewDNSProviderMissingKeyErr(t *testing.T) {
defer restoreEnv()
os.Setenv("PDNS_API_URL", pdnsURLStr)
os.Setenv("PDNS_API_KEY", "")
_, err := NewDNSProvider()
assert.EqualError(t, err, "PDNS API key missing")
restorePdnsEnv()
assert.EqualError(t, err, "PDNS: some credentials information are missing: PDNS_API_KEY,PDNS_API_URL")
}
func TestPdnsPresentAndCleanup(t *testing.T) {

View file

@ -8,10 +8,10 @@ import (
"fmt"
"io"
"net/http"
"os"
"time"
"github.com/xenolf/lego/acme"
"github.com/xenolf/lego/platform/config/env"
)
// rackspaceAPIURL represents the Identity API endpoint to call
@ -28,9 +28,12 @@ type DNSProvider struct {
// Credentials must be passed in the environment variables: RACKSPACE_USER
// and RACKSPACE_API_KEY.
func NewDNSProvider() (*DNSProvider, error) {
user := os.Getenv("RACKSPACE_USER")
key := os.Getenv("RACKSPACE_API_KEY")
return NewDNSProviderCredentials(user, key)
values, err := env.Get("RACKSPACE_USER", "RACKSPACE_API_KEY")
if err != nil {
return nil, fmt.Errorf("Rackspace: %v", err)
}
return NewDNSProviderCredentials(values["RACKSPACE_USER"], values["RACKSPACE_API_KEY"])
}
// NewDNSProviderCredentials uses the supplied credentials to return a

View file

@ -38,6 +38,7 @@ func NewDNSProvider() (*DNSProvider, error) {
tsigKey := os.Getenv("RFC2136_TSIG_KEY")
tsigSecret := os.Getenv("RFC2136_TSIG_SECRET")
timeout := os.Getenv("RFC2136_TIMEOUT")
return NewDNSProviderCredentials(nameserver, tsigAlgorithm, tsigKey, tsigSecret, timeout)
}
@ -58,13 +59,14 @@ func NewDNSProviderCredentials(nameserver, tsigAlgorithm, tsigKey, tsigSecret, t
return nil, err
}
}
d := &DNSProvider{
nameserver: nameserver,
}
d := &DNSProvider{nameserver: nameserver}
if tsigAlgorithm == "" {
tsigAlgorithm = dns.HmacMD5
}
d.tsigAlgorithm = tsigAlgorithm
if len(tsigKey) > 0 && len(tsigSecret) > 0 {
d.tsigKey = tsigKey
d.tsigSecret = tsigSecret

View file

@ -10,6 +10,8 @@ import (
"time"
"github.com/miekg/dns"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/xenolf/lego/acme"
)
@ -32,22 +34,20 @@ func TestRFC2136CanaryLocalTestServer(t *testing.T) {
defer dns.HandleRemove("example.com.")
server, addrstr, err := runLocalDNSTestServer("127.0.0.1:0", false)
if err != nil {
t.Fatalf("Failed to start test server: %v", err)
}
require.NoError(t, err, "Failed to start test server")
defer server.Shutdown()
c := new(dns.Client)
m := new(dns.Msg)
m.SetQuestion("example.com.", dns.TypeTXT)
r, _, err := c.Exchange(m, addrstr)
if err != nil || len(r.Extra) == 0 {
t.Fatalf("Failed to communicate with test server: %v", err)
}
require.NoError(t, err, "Failed to communicate with test server")
assert.Len(t, r.Extra, 1, "Failed to communicate with test server")
txt := r.Extra[0].(*dns.TXT).Txt[0]
if txt != "Hello world" {
t.Error("Expected test server to return 'Hello world' but got: ", txt)
}
assert.Equal(t, "Hello world", txt)
}
func TestRFC2136ServerSuccess(t *testing.T) {
@ -56,18 +56,14 @@ func TestRFC2136ServerSuccess(t *testing.T) {
defer dns.HandleRemove(rfc2136TestZone)
server, addrstr, err := runLocalDNSTestServer("127.0.0.1:0", false)
if err != nil {
t.Fatalf("Failed to start test server: %v", err)
}
require.NoError(t, err, "Failed to start test server")
defer server.Shutdown()
provider, err := NewDNSProviderCredentials(addrstr, "", "", "", "")
if err != nil {
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)
}
require.NoError(t, err)
err = provider.Present(rfc2136TestDomain, "", rfc2136TestKeyAuth)
require.NoError(t, err)
}
func TestRFC2136ServerError(t *testing.T) {
@ -76,19 +72,16 @@ func TestRFC2136ServerError(t *testing.T) {
defer dns.HandleRemove(rfc2136TestZone)
server, addrstr, err := runLocalDNSTestServer("127.0.0.1:0", false)
if err != nil {
t.Fatalf("Failed to start test server: %v", err)
}
require.NoError(t, err, "Failed to start test server")
defer server.Shutdown()
provider, err := NewDNSProviderCredentials(addrstr, "", "", "", "")
if err != nil {
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.")
} else if !strings.Contains(err.Error(), "NOTZONE") {
t.Errorf("Expected Present() to return an error with the 'NOTZONE' rcode string but it did not.")
require.NoError(t, err)
err = provider.Present(rfc2136TestDomain, "", rfc2136TestKeyAuth)
require.Error(t, err)
if !strings.Contains(err.Error(), "NOTZONE") {
t.Errorf("Expected Present() to return an error with the 'NOTZONE' rcode string but it did not: %v", err)
}
}
@ -98,18 +91,14 @@ func TestRFC2136TsigClient(t *testing.T) {
defer dns.HandleRemove(rfc2136TestZone)
server, addrstr, err := runLocalDNSTestServer("127.0.0.1:0", true)
if err != nil {
t.Fatalf("Failed to start test server: %v", err)
}
require.NoError(t, err, "Failed to start test server")
defer server.Shutdown()
provider, err := NewDNSProviderCredentials(addrstr, "", rfc2136TestTsigKey, rfc2136TestTsigSecret, "")
if err != nil {
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)
}
require.NoError(t, err)
err = provider.Present(rfc2136TestDomain, "", rfc2136TestKeyAuth)
require.NoError(t, err)
}
func TestRFC2136ValidUpdatePacket(t *testing.T) {
@ -118,9 +107,7 @@ func TestRFC2136ValidUpdatePacket(t *testing.T) {
defer dns.HandleRemove(rfc2136TestZone)
server, addrstr, err := runLocalDNSTestServer("127.0.0.1:0", false)
if err != nil {
t.Fatalf("Failed to start test server: %v", err)
}
require.NoError(t, err, "Failed to start test server")
defer server.Shutdown()
txtRR, _ := dns.NewRR(fmt.Sprintf("%s %d IN TXT %s", rfc2136TestFqdn, rfc2136TestTTL, rfc2136TestValue))
@ -130,26 +117,21 @@ func TestRFC2136ValidUpdatePacket(t *testing.T) {
m.RemoveRRset(rrs)
m.Insert(rrs)
expectstr := m.String()
expect, err := m.Pack()
if err != nil {
t.Fatalf("Error packing expect msg: %v", err)
}
require.NoError(t, err, "error packing")
provider, err := NewDNSProviderCredentials(addrstr, "", "", "", "")
if err != nil {
t.Fatalf("Expected NewDNSProviderCredentials() to return no error but the error was -> %v", err)
}
require.NoError(t, err)
if err := provider.Present(rfc2136TestDomain, "", "1234d=="); err != nil {
t.Errorf("Expected Present() to return no error but the error was -> %v", err)
}
err = provider.Present(rfc2136TestDomain, "", "1234d==")
require.NoError(t, err)
rcvMsg := <-reqChan
rcvMsg.Id = m.Id
actual, err := rcvMsg.Pack()
if err != nil {
t.Fatalf("Error packing actual msg: %v", err)
}
require.NoError(t, err, "error packing")
if !bytes.Equal(actual, expect) {
tmp := new(dns.Msg)

View file

@ -8,6 +8,7 @@ import (
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/route53"
"github.com/stretchr/testify/require"
)
func TestRoute53TTL(t *testing.T) {
@ -17,14 +18,10 @@ func TestRoute53TTL(t *testing.T) {
}
provider, err := NewDNSProvider()
if err != nil {
t.Fatal(err)
}
require.NoError(t, err)
err = provider.Present(m["route53Domain"], "foo", "bar")
if err != nil {
t.Fatal(err)
}
require.NoError(t, err)
// we need a separate R53 client here as the one in the DNS provider is
// unexported.

View file

@ -26,7 +26,7 @@ func init() {
route53Zone = os.Getenv("AWS_HOSTED_ZONE_ID")
}
func restoreRoute53Env() {
func restoreEnv() {
os.Setenv("AWS_ACCESS_KEY_ID", route53Key)
os.Setenv("AWS_SECRET_ACCESS_KEY", route53Secret)
os.Setenv("AWS_REGION", route53Region)
@ -46,6 +46,7 @@ func makeRoute53Provider(ts *httptest.Server) *DNSProvider {
}
func TestCredentialsFromEnv(t *testing.T) {
defer restoreEnv()
os.Setenv("AWS_ACCESS_KEY_ID", "123")
os.Setenv("AWS_SECRET_ACCESS_KEY", "123")
os.Setenv("AWS_REGION", "us-east-1")
@ -57,23 +58,20 @@ func TestCredentialsFromEnv(t *testing.T) {
sess := session.New(config)
_, err := sess.Config.Credentials.Get()
assert.NoError(t, err, "Expected credentials to be set from environment")
restoreRoute53Env()
}
func TestRegionFromEnv(t *testing.T) {
defer restoreEnv()
os.Setenv("AWS_REGION", "us-east-1")
sess := session.New(aws.NewConfig())
assert.Equal(t, "us-east-1", aws.StringValue(sess.Config.Region), "Expected Region to be set from environment")
restoreRoute53Env()
}
func TestHostedZoneIDFromEnv(t *testing.T) {
const testZoneID = "testzoneid"
defer restoreEnv()
defer restoreRoute53Env()
const testZoneID = "testzoneid"
os.Setenv("AWS_HOSTED_ZONE_ID", testZoneID)
provider, err := NewDNSProvider()

View file

@ -5,11 +5,11 @@ package vultr
import (
"fmt"
"os"
"strings"
vultr "github.com/JamesClonk/vultr/lib"
"github.com/xenolf/lego/acme"
"github.com/xenolf/lego/platform/config/env"
)
// DNSProvider is an implementation of the acme.ChallengeProvider interface.
@ -20,8 +20,12 @@ type DNSProvider struct {
// NewDNSProvider returns a DNSProvider instance with a configured Vultr client.
// Authentication uses the VULTR_API_KEY environment variable.
func NewDNSProvider() (*DNSProvider, error) {
apiKey := os.Getenv("VULTR_API_KEY")
return NewDNSProviderCredentials(apiKey)
values, err := env.Get("VULTR_API_KEY")
if err != nil {
return nil, fmt.Errorf("Vultr: %v", err)
}
return NewDNSProviderCredentials(values["VULTR_API_KEY"])
}
// NewDNSProviderCredentials uses the supplied credentials to return a DNSProvider

View file

@ -25,17 +25,19 @@ func restoreEnv() {
}
func TestNewDNSProviderValidEnv(t *testing.T) {
os.Setenv("VULTR_API_KEY", "123")
defer restoreEnv()
os.Setenv("VULTR_API_KEY", "123")
_, err := NewDNSProvider()
assert.NoError(t, err)
}
func TestNewDNSProviderMissingCredErr(t *testing.T) {
os.Setenv("VULTR_API_KEY", "")
defer restoreEnv()
os.Setenv("VULTR_API_KEY", "")
_, err := NewDNSProvider()
assert.EqualError(t, err, "Vultr credentials missing")
assert.EqualError(t, err, "Vultr: some credentials information are missing: VULTR_API_KEY")
}
func TestLivePresent(t *testing.T) {