parent
8f9e90b2a0
commit
c4bbb4b819
55 changed files with 671 additions and 560 deletions
27
platform/config/env/env.go
vendored
Normal file
27
platform/config/env/env.go
vendored
Normal 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
|
||||||
|
}
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"github.com/edeckers/auroradnsclient/records"
|
"github.com/edeckers/auroradnsclient/records"
|
||||||
"github.com/edeckers/auroradnsclient/zones"
|
"github.com/edeckers/auroradnsclient/zones"
|
||||||
"github.com/xenolf/lego/acme"
|
"github.com/xenolf/lego/acme"
|
||||||
|
"github.com/xenolf/lego/platform/config/env"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DNSProvider describes a provider for AuroraDNS
|
// DNSProvider describes a provider for AuroraDNS
|
||||||
|
@ -22,20 +23,23 @@ type DNSProvider struct {
|
||||||
// Credentials must be passed in the environment variables: AURORA_USER_ID
|
// Credentials must be passed in the environment variables: AURORA_USER_ID
|
||||||
// and AURORA_KEY.
|
// and AURORA_KEY.
|
||||||
func NewDNSProvider() (*DNSProvider, error) {
|
func NewDNSProvider() (*DNSProvider, error) {
|
||||||
userID := os.Getenv("AURORA_USER_ID")
|
values, err := env.Get("AURORA_USER_ID", "AURORA_KEY")
|
||||||
key := os.Getenv("AURORA_KEY")
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("AuroraDNS: %v", err)
|
||||||
endpoint := os.Getenv("AURORA_ENDPOINT")
|
|
||||||
if endpoint == "" {
|
|
||||||
endpoint = "https://api.auroradns.eu"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
// NewDNSProviderCredentials uses the supplied credentials to return a
|
||||||
// DNSProvider instance configured for AuroraDNS.
|
// DNSProvider instance configured for AuroraDNS.
|
||||||
func NewDNSProviderCredentials(baseURL string, userID string, key string) (*DNSProvider, error) {
|
func NewDNSProviderCredentials(baseURL string, userID string, key string) (*DNSProvider, error) {
|
||||||
|
if baseURL == "" {
|
||||||
|
baseURL = "https://api.auroradns.eu"
|
||||||
|
}
|
||||||
|
|
||||||
client, err := auroradnsclient.NewAuroraDNSClient(baseURL, userID, key)
|
client, err := auroradnsclient.NewAuroraDNSClient(baseURL, userID, key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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)
|
authZone, err := acme.FindZoneByFqdn(acme.ToFqdn(domain), acme.RecursiveNameservers)
|
||||||
if err != nil {
|
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,
|
// 1. Aurora will happily create the TXT record when it is provided a fqdn,
|
||||||
|
|
|
@ -6,6 +6,9 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
var fakeAuroraDNSUserID = "asdf1234"
|
var fakeAuroraDNSUserID = "asdf1234"
|
||||||
|
@ -26,28 +29,13 @@ func TestAuroraDNSPresent(t *testing.T) {
|
||||||
|
|
||||||
requestReceived = true
|
requestReceived = true
|
||||||
|
|
||||||
if got, want := r.Method, "POST"; got != want {
|
assert.Equal(t, http.MethodPost, r.Method, "method")
|
||||||
t.Errorf("Expected method to be '%s' but got '%s'", want, got)
|
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")
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
|
|
||||||
reqBody, err := ioutil.ReadAll(r.Body)
|
reqBody, err := ioutil.ReadAll(r.Body)
|
||||||
if err != nil {
|
require.NoError(t, err, "reading request body")
|
||||||
t.Fatalf("Error reading request body: %v", err)
|
assert.Equal(t, `{"type":"TXT","name":"_acme-challenge","content":"w6uP8Tcg6K2QR905Rms8iXTlksL6OD1KOWBxTK7wxPI","ttl":300}`, string(reqBody))
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
|
|
||||||
w.WriteHeader(http.StatusCreated)
|
w.WriteHeader(http.StatusCreated)
|
||||||
fmt.Fprintf(w, `{
|
fmt.Fprintf(w, `{
|
||||||
|
@ -61,22 +49,13 @@ func TestAuroraDNSPresent(t *testing.T) {
|
||||||
defer mock.Close()
|
defer mock.Close()
|
||||||
|
|
||||||
auroraProvider, err := NewDNSProviderCredentials(mock.URL, fakeAuroraDNSUserID, fakeAuroraDNSKey)
|
auroraProvider, err := NewDNSProviderCredentials(mock.URL, fakeAuroraDNSUserID, fakeAuroraDNSKey)
|
||||||
if auroraProvider == nil {
|
require.NoError(t, err)
|
||||||
t.Fatal("Expected non-nil AuroraDNS provider, but was nil")
|
require.NotNil(t, auroraProvider)
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Expected no error creating provider, but got: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = auroraProvider.Present("example.com", "", "foobar")
|
err = auroraProvider.Present("example.com", "", "foobar")
|
||||||
if err != nil {
|
require.NoError(t, err, "fail to create TXT record")
|
||||||
t.Fatalf("Expected no error creating TXT record, but got: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !requestReceived {
|
assert.True(t, requestReceived, "Expected request to be received by mock backend, but it wasn't")
|
||||||
t.Error("Expected request to be received by mock backend, but it wasn't")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAuroraDNSCleanUp(t *testing.T) {
|
func TestAuroraDNSCleanUp(t *testing.T) {
|
||||||
|
@ -105,18 +84,9 @@ func TestAuroraDNSCleanUp(t *testing.T) {
|
||||||
|
|
||||||
requestReceived = true
|
requestReceived = true
|
||||||
|
|
||||||
if got, want := r.Method, "DELETE"; got != want {
|
assert.Equal(t, http.MethodDelete, r.Method, "method")
|
||||||
t.Errorf("Expected method to be '%s' but got '%s'", want, got)
|
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")
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
|
|
||||||
w.WriteHeader(http.StatusCreated)
|
w.WriteHeader(http.StatusCreated)
|
||||||
fmt.Fprintf(w, `{}`)
|
fmt.Fprintf(w, `{}`)
|
||||||
|
@ -124,25 +94,14 @@ func TestAuroraDNSCleanUp(t *testing.T) {
|
||||||
defer mock.Close()
|
defer mock.Close()
|
||||||
|
|
||||||
auroraProvider, err := NewDNSProviderCredentials(mock.URL, fakeAuroraDNSUserID, fakeAuroraDNSKey)
|
auroraProvider, err := NewDNSProviderCredentials(mock.URL, fakeAuroraDNSUserID, fakeAuroraDNSKey)
|
||||||
if auroraProvider == nil {
|
require.NoError(t, err)
|
||||||
t.Fatal("Expected non-nil AuroraDNS provider, but was nil")
|
require.NotNil(t, auroraProvider)
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Expected no error creating provider, but got: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = auroraProvider.Present("example.com", "", "foobar")
|
err = auroraProvider.Present("example.com", "", "foobar")
|
||||||
if err != nil {
|
require.NoError(t, err, "fail to create TXT record")
|
||||||
t.Fatalf("Expected no error creating TXT record, but got: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = auroraProvider.CleanUp("example.com", "", "foobar")
|
err = auroraProvider.CleanUp("example.com", "", "foobar")
|
||||||
if err != nil {
|
require.NoError(t, err, "fail to remove TXT record")
|
||||||
t.Fatalf("Expected no error removing TXT record, but got: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !requestReceived {
|
assert.True(t, requestReceived, "Expected request to be received by mock backend, but it wasn't")
|
||||||
t.Error("Expected request to be received by mock backend, but it wasn't")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,8 +5,8 @@ package azure
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@ import (
|
||||||
"github.com/Azure/go-autorest/autorest/azure"
|
"github.com/Azure/go-autorest/autorest/azure"
|
||||||
"github.com/Azure/go-autorest/autorest/to"
|
"github.com/Azure/go-autorest/autorest/to"
|
||||||
"github.com/xenolf/lego/acme"
|
"github.com/xenolf/lego/acme"
|
||||||
|
"github.com/xenolf/lego/platform/config/env"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DNSProvider is an implementation of the acme.ChallengeProvider interface
|
// 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,
|
// Credentials must be passed in the environment variables: AZURE_CLIENT_ID,
|
||||||
// AZURE_CLIENT_SECRET, AZURE_SUBSCRIPTION_ID, AZURE_TENANT_ID, AZURE_RESOURCE_GROUP
|
// AZURE_CLIENT_SECRET, AZURE_SUBSCRIPTION_ID, AZURE_TENANT_ID, AZURE_RESOURCE_GROUP
|
||||||
func NewDNSProvider() (*DNSProvider, error) {
|
func NewDNSProvider() (*DNSProvider, error) {
|
||||||
clientID := os.Getenv("AZURE_CLIENT_ID")
|
values, err := env.Get("AZURE_CLIENT_ID", "AZURE_CLIENT_SECRET", "AZURE_SUBSCRIPTION_ID", "AZURE_TENANT_ID", "AZURE_RESOURCE_GROUP")
|
||||||
clientSecret := os.Getenv("AZURE_CLIENT_SECRET")
|
if err != nil {
|
||||||
subscriptionID := os.Getenv("AZURE_SUBSCRIPTION_ID")
|
return nil, fmt.Errorf("Azure: %v", err)
|
||||||
tenantID := os.Getenv("AZURE_TENANT_ID")
|
}
|
||||||
resourceGroup := os.Getenv("AZURE_RESOURCE_GROUP")
|
|
||||||
return NewDNSProviderCredentials(clientID, clientSecret, subscriptionID, tenantID, resourceGroup)
|
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
|
// NewDNSProviderCredentials uses the supplied credentials to return a
|
||||||
// DNSProvider instance configured for azure.
|
// DNSProvider instance configured for azure.
|
||||||
func NewDNSProviderCredentials(clientID, clientSecret, subscriptionID, tenantID, resourceGroup string) (*DNSProvider, error) {
|
func NewDNSProviderCredentials(clientID, clientSecret, subscriptionID, tenantID, resourceGroup string) (*DNSProvider, error) {
|
||||||
if clientID == "" || clientSecret == "" || subscriptionID == "" || tenantID == "" || resourceGroup == "" {
|
if clientID == "" || clientSecret == "" || subscriptionID == "" || tenantID == "" || resourceGroup == "" {
|
||||||
var missingEnvVars []string
|
return nil, errors.New("Azure: some credentials information are missing")
|
||||||
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 &DNSProvider{
|
return &DNSProvider{
|
||||||
|
|
|
@ -30,7 +30,7 @@ func init() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func restoreAzureEnv() {
|
func restoreEnv() {
|
||||||
os.Setenv("AZURE_CLIENT_ID", azureClientID)
|
os.Setenv("AZURE_CLIENT_ID", azureClientID)
|
||||||
os.Setenv("AZURE_SUBSCRIPTION_ID", azureSubscriptionID)
|
os.Setenv("AZURE_SUBSCRIPTION_ID", azureSubscriptionID)
|
||||||
}
|
}
|
||||||
|
@ -39,27 +39,32 @@ func TestNewDNSProviderValid(t *testing.T) {
|
||||||
if !azureLiveTest {
|
if !azureLiveTest {
|
||||||
t.Skip("skipping live test (requires credentials)")
|
t.Skip("skipping live test (requires credentials)")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
defer restoreEnv()
|
||||||
os.Setenv("AZURE_CLIENT_ID", "")
|
os.Setenv("AZURE_CLIENT_ID", "")
|
||||||
|
|
||||||
_, err := NewDNSProviderCredentials(azureClientID, azureClientSecret, azureSubscriptionID, azureTenantID, azureResourceGroup)
|
_, err := NewDNSProviderCredentials(azureClientID, azureClientSecret, azureSubscriptionID, azureTenantID, azureResourceGroup)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
restoreAzureEnv()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewDNSProviderValidEnv(t *testing.T) {
|
func TestNewDNSProviderValidEnv(t *testing.T) {
|
||||||
if !azureLiveTest {
|
if !azureLiveTest {
|
||||||
t.Skip("skipping live test (requires credentials)")
|
t.Skip("skipping live test (requires credentials)")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
defer restoreEnv()
|
||||||
os.Setenv("AZURE_CLIENT_ID", "other")
|
os.Setenv("AZURE_CLIENT_ID", "other")
|
||||||
|
|
||||||
_, err := NewDNSProvider()
|
_, err := NewDNSProvider()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
restoreAzureEnv()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewDNSProviderMissingCredErr(t *testing.T) {
|
func TestNewDNSProviderMissingCredErr(t *testing.T) {
|
||||||
|
defer restoreEnv()
|
||||||
os.Setenv("AZURE_SUBSCRIPTION_ID", "")
|
os.Setenv("AZURE_SUBSCRIPTION_ID", "")
|
||||||
|
|
||||||
_, err := NewDNSProvider()
|
_, err := NewDNSProvider()
|
||||||
assert.EqualError(t, err, "Azure configuration missing: AZURE_CLIENT_ID,AZURE_CLIENT_SECRET,AZURE_SUBSCRIPTION_ID,AZURE_TENANT_ID,AZURE_RESOURCE_GROUP")
|
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")
|
||||||
restoreAzureEnv()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLiveAzurePresent(t *testing.T) {
|
func TestLiveAzurePresent(t *testing.T) {
|
||||||
|
|
|
@ -6,16 +6,15 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"io/ioutil"
|
|
||||||
|
|
||||||
"github.com/xenolf/lego/acme"
|
"github.com/xenolf/lego/acme"
|
||||||
|
"github.com/xenolf/lego/platform/config/env"
|
||||||
)
|
)
|
||||||
|
|
||||||
const bluecatURLTemplate = "%s/Services/REST/v1"
|
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
|
// and external DNS View Name must be passed in BLUECAT_CONFIG_NAME and
|
||||||
// BLUECAT_DNS_VIEW
|
// BLUECAT_DNS_VIEW
|
||||||
func NewDNSProvider() (*DNSProvider, error) {
|
func NewDNSProvider() (*DNSProvider, error) {
|
||||||
server := os.Getenv("BLUECAT_SERVER_URL")
|
values, err := env.Get("BLUECAT_SERVER_URL", "BLUECAT_USER_NAME", "BLUECAT_CONFIG_NAME", "BLUECAT_CONFIG_NAME", "BLUECAT_DNS_VIEW")
|
||||||
userName := os.Getenv("BLUECAT_USER_NAME")
|
if err != nil {
|
||||||
password := os.Getenv("BLUECAT_PASSWORD")
|
return nil, fmt.Errorf("BlueCat: %v", err)
|
||||||
configName := os.Getenv("BLUECAT_CONFIG_NAME")
|
}
|
||||||
dnsView := os.Getenv("BLUECAT_DNS_VIEW")
|
|
||||||
httpClient := http.Client{Timeout: 30 * time.Second}
|
httpClient := &http.Client{Timeout: 30 * time.Second}
|
||||||
return NewDNSProviderCredentials(server, userName, password, configName, dnsView, httpClient)
|
|
||||||
|
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
|
// NewDNSProviderCredentials uses the supplied credentials to return a
|
||||||
// DNSProvider instance configured for Bluecat DNS.
|
// 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 == "" {
|
if server == "" || userName == "" || password == "" || configName == "" || dnsView == "" {
|
||||||
return nil, fmt.Errorf("Bluecat credentials missing")
|
return nil, fmt.Errorf("Bluecat credentials missing")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
client := http.DefaultClient
|
||||||
|
if httpClient != nil {
|
||||||
|
client = httpClient
|
||||||
|
}
|
||||||
|
|
||||||
return &DNSProvider{
|
return &DNSProvider{
|
||||||
baseURL: fmt.Sprintf(bluecatURLTemplate, server),
|
baseURL: fmt.Sprintf(bluecatURLTemplate, server),
|
||||||
userName: userName,
|
userName: userName,
|
||||||
password: password,
|
password: password,
|
||||||
configName: configName,
|
configName: configName,
|
||||||
dnsView: dnsView,
|
dnsView: dnsView,
|
||||||
httpClient: http.DefaultClient,
|
httpClient: client,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,15 +5,15 @@ package cloudflare
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/xenolf/lego/acme"
|
"github.com/xenolf/lego/acme"
|
||||||
|
"github.com/xenolf/lego/platform/config/env"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CloudFlareAPIURL represents the API endpoint to call.
|
// CloudFlareAPIURL represents the API endpoint to call.
|
||||||
|
@ -30,23 +30,19 @@ type DNSProvider struct {
|
||||||
// Credentials must be passed in the environment variables: CLOUDFLARE_EMAIL
|
// Credentials must be passed in the environment variables: CLOUDFLARE_EMAIL
|
||||||
// and CLOUDFLARE_API_KEY.
|
// and CLOUDFLARE_API_KEY.
|
||||||
func NewDNSProvider() (*DNSProvider, error) {
|
func NewDNSProvider() (*DNSProvider, error) {
|
||||||
email := os.Getenv("CLOUDFLARE_EMAIL")
|
values, err := env.Get("CLOUDFLARE_EMAIL", "CLOUDFLARE_API_KEY")
|
||||||
key := os.Getenv("CLOUDFLARE_API_KEY")
|
if err != nil {
|
||||||
return NewDNSProviderCredentials(email, key)
|
return nil, fmt.Errorf("CloudFlare: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return NewDNSProviderCredentials(values["CLOUDFLARE_EMAIL"], values["CLOUDFLARE_API_KEY"])
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDNSProviderCredentials uses the supplied credentials to return a
|
// NewDNSProviderCredentials uses the supplied credentials to return a
|
||||||
// DNSProvider instance configured for cloudflare.
|
// DNSProvider instance configured for cloudflare.
|
||||||
func NewDNSProviderCredentials(email, key string) (*DNSProvider, error) {
|
func NewDNSProviderCredentials(email, key string) (*DNSProvider, error) {
|
||||||
if email == "" || key == "" {
|
if email == "" || key == "" {
|
||||||
missingEnvVars := []string{}
|
return nil, errors.New("CloudFlare: some credentials information are missing")
|
||||||
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 &DNSProvider{
|
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
|
// Present creates a TXT record to fulfil the dns-01 challenge
|
||||||
func (c *DNSProvider) Present(domain, token, keyAuth string) error {
|
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)
|
zoneID, err := c.getHostedZoneID(fqdn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -73,7 +69,7 @@ func (c *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||||
Type: "TXT",
|
Type: "TXT",
|
||||||
Name: acme.UnFqdn(fqdn),
|
Name: acme.UnFqdn(fqdn),
|
||||||
Content: value,
|
Content: value,
|
||||||
TTL: 120,
|
TTL: ttl,
|
||||||
}
|
}
|
||||||
|
|
||||||
body, err := json.Marshal(rec)
|
body, err := json.Marshal(rec)
|
||||||
|
@ -122,7 +118,7 @@ func (c *DNSProvider) getHostedZoneID(fqdn string) (string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(hostedZone) != 1 {
|
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
|
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}
|
client := http.Client{Timeout: 30 * time.Second}
|
||||||
resp, err := client.Do(req)
|
resp, err := client.Do(req)
|
||||||
if err != nil {
|
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()
|
defer resp.Body.Close()
|
||||||
|
|
|
@ -24,7 +24,7 @@ func init() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func restoreCloudFlareEnv() {
|
func restoreEnv() {
|
||||||
os.Setenv("CLOUDFLARE_EMAIL", cflareEmail)
|
os.Setenv("CLOUDFLARE_EMAIL", cflareEmail)
|
||||||
os.Setenv("CLOUDFLARE_API_KEY", cflareAPIKey)
|
os.Setenv("CLOUDFLARE_API_KEY", cflareAPIKey)
|
||||||
}
|
}
|
||||||
|
@ -32,32 +32,37 @@ func restoreCloudFlareEnv() {
|
||||||
func TestNewDNSProviderValid(t *testing.T) {
|
func TestNewDNSProviderValid(t *testing.T) {
|
||||||
os.Setenv("CLOUDFLARE_EMAIL", "")
|
os.Setenv("CLOUDFLARE_EMAIL", "")
|
||||||
os.Setenv("CLOUDFLARE_API_KEY", "")
|
os.Setenv("CLOUDFLARE_API_KEY", "")
|
||||||
|
defer restoreEnv()
|
||||||
|
|
||||||
_, err := NewDNSProviderCredentials("123", "123")
|
_, err := NewDNSProviderCredentials("123", "123")
|
||||||
|
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
restoreCloudFlareEnv()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewDNSProviderValidEnv(t *testing.T) {
|
func TestNewDNSProviderValidEnv(t *testing.T) {
|
||||||
|
defer restoreEnv()
|
||||||
os.Setenv("CLOUDFLARE_EMAIL", "test@example.com")
|
os.Setenv("CLOUDFLARE_EMAIL", "test@example.com")
|
||||||
os.Setenv("CLOUDFLARE_API_KEY", "123")
|
os.Setenv("CLOUDFLARE_API_KEY", "123")
|
||||||
|
|
||||||
_, err := NewDNSProvider()
|
_, err := NewDNSProvider()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
restoreCloudFlareEnv()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewDNSProviderMissingCredErr(t *testing.T) {
|
func TestNewDNSProviderMissingCredErr(t *testing.T) {
|
||||||
|
defer restoreEnv()
|
||||||
os.Setenv("CLOUDFLARE_EMAIL", "")
|
os.Setenv("CLOUDFLARE_EMAIL", "")
|
||||||
os.Setenv("CLOUDFLARE_API_KEY", "")
|
os.Setenv("CLOUDFLARE_API_KEY", "")
|
||||||
|
|
||||||
_, err := NewDNSProvider()
|
_, err := NewDNSProvider()
|
||||||
assert.EqualError(t, err, "CloudFlare credentials missing: CLOUDFLARE_EMAIL,CLOUDFLARE_API_KEY")
|
assert.EqualError(t, err, "CloudFlare: some credentials information are missing: CLOUDFLARE_EMAIL,CLOUDFLARE_API_KEY")
|
||||||
restoreCloudFlareEnv()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewDNSProviderMissingCredErrSingle(t *testing.T){
|
func TestNewDNSProviderMissingCredErrSingle(t *testing.T) {
|
||||||
os.Setenv("CLOUDFLARE_EMAIL", "awesome@possum.com")
|
defer restoreEnv()
|
||||||
_, err:= NewDNSProvider()
|
os.Setenv("CLOUDFLARE_EMAIL", "awesome@possum.com")
|
||||||
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) {
|
func TestCloudFlarePresent(t *testing.T) {
|
||||||
|
|
|
@ -9,11 +9,11 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/xenolf/lego/acme"
|
"github.com/xenolf/lego/acme"
|
||||||
|
"github.com/xenolf/lego/platform/config/env"
|
||||||
)
|
)
|
||||||
|
|
||||||
const cloudXNSBaseURL = "https://www.cloudxns.net/api2/"
|
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
|
// Credentials must be passed in the environment variables: CLOUDXNS_API_KEY
|
||||||
// and CLOUDXNS_SECRET_KEY.
|
// and CLOUDXNS_SECRET_KEY.
|
||||||
func NewDNSProvider() (*DNSProvider, error) {
|
func NewDNSProvider() (*DNSProvider, error) {
|
||||||
apiKey := os.Getenv("CLOUDXNS_API_KEY")
|
values, err := env.Get("CLOUDXNS_API_KEY", "CLOUDXNS_SECRET_KEY")
|
||||||
secretKey := os.Getenv("CLOUDXNS_SECRET_KEY")
|
if err != nil {
|
||||||
return NewDNSProviderCredentials(apiKey, secretKey)
|
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
|
// NewDNSProviderCredentials uses the supplied credentials to return a
|
||||||
|
|
|
@ -24,33 +24,36 @@ func init() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func restoreCloudXNSEnv() {
|
func restoreEnv() {
|
||||||
os.Setenv("CLOUDXNS_API_KEY", cxAPIKey)
|
os.Setenv("CLOUDXNS_API_KEY", cxAPIKey)
|
||||||
os.Setenv("CLOUDXNS_SECRET_KEY", cxSecretKey)
|
os.Setenv("CLOUDXNS_SECRET_KEY", cxSecretKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewDNSProviderValid(t *testing.T) {
|
func TestNewDNSProviderValid(t *testing.T) {
|
||||||
|
defer restoreEnv()
|
||||||
os.Setenv("CLOUDXNS_API_KEY", "")
|
os.Setenv("CLOUDXNS_API_KEY", "")
|
||||||
os.Setenv("CLOUDXNS_SECRET_KEY", "")
|
os.Setenv("CLOUDXNS_SECRET_KEY", "")
|
||||||
|
|
||||||
_, err := NewDNSProviderCredentials("123", "123")
|
_, err := NewDNSProviderCredentials("123", "123")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
restoreCloudXNSEnv()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewDNSProviderValidEnv(t *testing.T) {
|
func TestNewDNSProviderValidEnv(t *testing.T) {
|
||||||
|
defer restoreEnv()
|
||||||
os.Setenv("CLOUDXNS_API_KEY", "123")
|
os.Setenv("CLOUDXNS_API_KEY", "123")
|
||||||
os.Setenv("CLOUDXNS_SECRET_KEY", "123")
|
os.Setenv("CLOUDXNS_SECRET_KEY", "123")
|
||||||
|
|
||||||
_, err := NewDNSProvider()
|
_, err := NewDNSProvider()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
restoreCloudXNSEnv()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewDNSProviderMissingCredErr(t *testing.T) {
|
func TestNewDNSProviderMissingCredErr(t *testing.T) {
|
||||||
|
defer restoreEnv()
|
||||||
os.Setenv("CLOUDXNS_API_KEY", "")
|
os.Setenv("CLOUDXNS_API_KEY", "")
|
||||||
os.Setenv("CLOUDXNS_SECRET_KEY", "")
|
os.Setenv("CLOUDXNS_SECRET_KEY", "")
|
||||||
|
|
||||||
_, err := NewDNSProvider()
|
_, err := NewDNSProvider()
|
||||||
assert.EqualError(t, err, "CloudXNS credentials missing")
|
assert.EqualError(t, err, "CloudXNS: some credentials information are missing: CLOUDXNS_API_KEY,CLOUDXNS_SECRET_KEY")
|
||||||
restoreCloudXNSEnv()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCloudXNSPresent(t *testing.T) {
|
func TestCloudXNSPresent(t *testing.T) {
|
||||||
|
|
|
@ -7,11 +7,11 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/xenolf/lego/acme"
|
"github.com/xenolf/lego/acme"
|
||||||
|
"github.com/xenolf/lego/platform/config/env"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DNSProvider is an implementation of the acme.ChallengeProvider interface
|
// 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:
|
// Ocean. Credentials must be passed in the environment variable:
|
||||||
// DO_AUTH_TOKEN.
|
// DO_AUTH_TOKEN.
|
||||||
func NewDNSProvider() (*DNSProvider, error) {
|
func NewDNSProvider() (*DNSProvider, error) {
|
||||||
apiAuthToken := os.Getenv("DO_AUTH_TOKEN")
|
values, err := env.Get("DO_AUTH_TOKEN")
|
||||||
return NewDNSProviderCredentials(apiAuthToken)
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("DigitalOcean: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return NewDNSProviderCredentials(values["DO_AUTH_TOKEN"])
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDNSProviderCredentials uses the supplied credentials to return a
|
// NewDNSProviderCredentials uses the supplied credentials to return a
|
||||||
|
|
|
@ -6,6 +6,9 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
var fakeDigitalOceanAuth = "asdf1234"
|
var fakeDigitalOceanAuth = "asdf1234"
|
||||||
|
@ -16,26 +19,14 @@ func TestDigitalOceanPresent(t *testing.T) {
|
||||||
mock := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
mock := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
requestReceived = true
|
requestReceived = true
|
||||||
|
|
||||||
if got, want := r.Method, "POST"; got != want {
|
assert.Equal(t, http.MethodPost, r.Method, "method")
|
||||||
t.Errorf("Expected method to be '%s' but got '%s'", want, got)
|
assert.Equal(t, "/v2/domains/example.com/records", r.URL.Path, "Path")
|
||||||
}
|
assert.Equal(t, "application/json", r.Header.Get("Content-Type"), "Content-Type")
|
||||||
if got, want := r.URL.Path, "/v2/domains/example.com/records"; got != want {
|
assert.Equal(t, "Bearer asdf1234", r.Header.Get("Authorization"), "Authorization")
|
||||||
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)
|
|
||||||
}
|
|
||||||
|
|
||||||
reqBody, err := ioutil.ReadAll(r.Body)
|
reqBody, err := ioutil.ReadAll(r.Body)
|
||||||
if err != nil {
|
require.NoError(t, err, "reading request body")
|
||||||
t.Fatalf("Error reading request body: %v", err)
|
assert.Equal(t, `{"type":"TXT","name":"_acme-challenge.example.com.","data":"w6uP8Tcg6K2QR905Rms8iXTlksL6OD1KOWBxTK7wxPI","ttl":30}`, string(reqBody))
|
||||||
}
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
|
|
||||||
w.WriteHeader(http.StatusCreated)
|
w.WriteHeader(http.StatusCreated)
|
||||||
fmt.Fprintf(w, `{
|
fmt.Fprintf(w, `{
|
||||||
|
@ -54,20 +45,13 @@ func TestDigitalOceanPresent(t *testing.T) {
|
||||||
digitalOceanBaseURL = mock.URL
|
digitalOceanBaseURL = mock.URL
|
||||||
|
|
||||||
doprov, err := NewDNSProviderCredentials(fakeDigitalOceanAuth)
|
doprov, err := NewDNSProviderCredentials(fakeDigitalOceanAuth)
|
||||||
if doprov == nil {
|
require.NoError(t, err)
|
||||||
t.Fatal("Expected non-nil DigitalOcean provider, but was nil")
|
require.NotNil(t, doprov)
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Expected no error creating provider, but got: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = doprov.Present("example.com", "", "foobar")
|
err = doprov.Present("example.com", "", "foobar")
|
||||||
if err != nil {
|
require.NoError(t, err, "fail to create TXT record")
|
||||||
t.Fatalf("Expected no error creating TXT record, but got: %v", err)
|
|
||||||
}
|
assert.True(t, requestReceived, "Expected request to be received by mock backend, but it wasn't")
|
||||||
if !requestReceived {
|
|
||||||
t.Error("Expected request to be received by mock backend, but it wasn't")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDigitalOceanCleanUp(t *testing.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) {
|
mock := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
requestReceived = true
|
requestReceived = true
|
||||||
|
|
||||||
if got, want := r.Method, "DELETE"; got != want {
|
assert.Equal(t, http.MethodDelete, r.Method, "method")
|
||||||
t.Errorf("Expected method to be '%s' but got '%s'", want, got)
|
assert.Equal(t, "/v2/domains/example.com/records/1234567", r.URL.Path, "Path")
|
||||||
}
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
// NOTE: Even though the body is empty, DigitalOcean API docs still show setting this Content-Type...
|
// 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 {
|
assert.Equal(t, "application/json", r.Header.Get("Content-Type"), "Content-Type")
|
||||||
t.Errorf("Expected Content-Type to be '%s' but got '%s'", want, got)
|
assert.Equal(t, "Bearer asdf1234", r.Header.Get("Authorization"), "Authorization")
|
||||||
}
|
|
||||||
if got, want := r.Header.Get("Authorization"), "Bearer asdf1234"; got != want {
|
|
||||||
t.Errorf("Expected Authorization to be '%s' but got '%s'", want, got)
|
|
||||||
}
|
|
||||||
|
|
||||||
w.WriteHeader(http.StatusNoContent)
|
w.WriteHeader(http.StatusNoContent)
|
||||||
}))
|
}))
|
||||||
|
@ -96,22 +72,15 @@ func TestDigitalOceanCleanUp(t *testing.T) {
|
||||||
digitalOceanBaseURL = mock.URL
|
digitalOceanBaseURL = mock.URL
|
||||||
|
|
||||||
doprov, err := NewDNSProviderCredentials(fakeDigitalOceanAuth)
|
doprov, err := NewDNSProviderCredentials(fakeDigitalOceanAuth)
|
||||||
if doprov == nil {
|
require.NoError(t, err)
|
||||||
t.Fatal("Expected non-nil DigitalOcean provider, but was nil")
|
require.NotNil(t, doprov)
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Expected no error creating provider, but got: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
doprov.recordIDsMu.Lock()
|
doprov.recordIDsMu.Lock()
|
||||||
doprov.recordIDs["_acme-challenge.example.com."] = 1234567
|
doprov.recordIDs["_acme-challenge.example.com."] = 1234567
|
||||||
doprov.recordIDsMu.Unlock()
|
doprov.recordIDsMu.Unlock()
|
||||||
|
|
||||||
err = doprov.CleanUp("example.com", "", "")
|
err = doprov.CleanUp("example.com", "", "")
|
||||||
if err != nil {
|
require.NoError(t, err, "fail to remove TXT record")
|
||||||
t.Fatalf("Expected no error removing TXT record, but got: %v", err)
|
|
||||||
}
|
assert.True(t, requestReceived, "Expected request to be received by mock backend, but it wasn't")
|
||||||
if !requestReceived {
|
|
||||||
t.Error("Expected request to be received by mock backend, but it wasn't")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,6 @@ package dns
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
"reflect"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
@ -25,23 +24,24 @@ func restoreExoscaleEnv() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestKnownDNSProviderSuccess(t *testing.T) {
|
func TestKnownDNSProviderSuccess(t *testing.T) {
|
||||||
|
defer restoreExoscaleEnv()
|
||||||
os.Setenv("EXOSCALE_API_KEY", "abc")
|
os.Setenv("EXOSCALE_API_KEY", "abc")
|
||||||
os.Setenv("EXOSCALE_API_SECRET", "123")
|
os.Setenv("EXOSCALE_API_SECRET", "123")
|
||||||
|
|
||||||
provider, err := NewDNSChallengeProviderByName("exoscale")
|
provider, err := NewDNSChallengeProviderByName("exoscale")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.NotNil(t, provider)
|
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))
|
assert.IsType(t, &exoscale.DNSProvider{}, provider, "Not loaded correct DNS provider")
|
||||||
}
|
|
||||||
restoreExoscaleEnv()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestKnownDNSProviderError(t *testing.T) {
|
func TestKnownDNSProviderError(t *testing.T) {
|
||||||
|
defer restoreExoscaleEnv()
|
||||||
os.Setenv("EXOSCALE_API_KEY", "")
|
os.Setenv("EXOSCALE_API_KEY", "")
|
||||||
os.Setenv("EXOSCALE_API_SECRET", "")
|
os.Setenv("EXOSCALE_API_SECRET", "")
|
||||||
|
|
||||||
_, err := NewDNSChallengeProviderByName("exoscale")
|
_, err := NewDNSChallengeProviderByName("exoscale")
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
restoreExoscaleEnv()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestUnknownDNSProvider(t *testing.T) {
|
func TestUnknownDNSProvider(t *testing.T) {
|
||||||
|
|
|
@ -31,7 +31,7 @@ func init() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func restoreDNSimpleEnv() {
|
func restoreEnv() {
|
||||||
os.Setenv("DNSIMPLE_OAUTH_TOKEN", dnsimpleOauthToken)
|
os.Setenv("DNSIMPLE_OAUTH_TOKEN", dnsimpleOauthToken)
|
||||||
os.Setenv("DNSIMPLE_BASE_URL", dnsimpleBaseURL)
|
os.Setenv("DNSIMPLE_BASE_URL", dnsimpleBaseURL)
|
||||||
}
|
}
|
||||||
|
@ -41,9 +41,9 @@ func restoreDNSimpleEnv() {
|
||||||
//
|
//
|
||||||
|
|
||||||
func TestNewDNSProviderValid(t *testing.T) {
|
func TestNewDNSProviderValid(t *testing.T) {
|
||||||
defer restoreDNSimpleEnv()
|
defer restoreEnv()
|
||||||
|
|
||||||
os.Setenv("DNSIMPLE_OAUTH_TOKEN", "123")
|
os.Setenv("DNSIMPLE_OAUTH_TOKEN", "123")
|
||||||
|
|
||||||
provider, err := NewDNSProvider()
|
provider, err := NewDNSProvider()
|
||||||
|
|
||||||
assert.NotNil(t, provider)
|
assert.NotNil(t, provider)
|
||||||
|
@ -52,10 +52,10 @@ func TestNewDNSProviderValid(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewDNSProviderValidWithBaseUrl(t *testing.T) {
|
func TestNewDNSProviderValidWithBaseUrl(t *testing.T) {
|
||||||
defer restoreDNSimpleEnv()
|
defer restoreEnv()
|
||||||
|
|
||||||
os.Setenv("DNSIMPLE_OAUTH_TOKEN", "123")
|
os.Setenv("DNSIMPLE_OAUTH_TOKEN", "123")
|
||||||
os.Setenv("DNSIMPLE_BASE_URL", "https://api.dnsimple.test")
|
os.Setenv("DNSIMPLE_BASE_URL", "https://api.dnsimple.test")
|
||||||
|
|
||||||
provider, err := NewDNSProvider()
|
provider, err := NewDNSProvider()
|
||||||
|
|
||||||
assert.NotNil(t, provider)
|
assert.NotNil(t, provider)
|
||||||
|
@ -65,11 +65,8 @@ func TestNewDNSProviderValidWithBaseUrl(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewDNSProviderInvalidWithMissingOauthToken(t *testing.T) {
|
func TestNewDNSProviderInvalidWithMissingOauthToken(t *testing.T) {
|
||||||
if dnsimpleLiveTest {
|
defer restoreEnv()
|
||||||
t.Skip("skipping test in live mode")
|
os.Setenv("DNSIMPLE_OAUTH_TOKEN", "")
|
||||||
}
|
|
||||||
|
|
||||||
defer restoreDNSimpleEnv()
|
|
||||||
|
|
||||||
provider, err := NewDNSProvider()
|
provider, err := NewDNSProvider()
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/xenolf/lego/acme"
|
"github.com/xenolf/lego/acme"
|
||||||
|
"github.com/xenolf/lego/platform/config/env"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DNSProvider is an implementation of the acme.ChallengeProvider interface that uses
|
// 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
|
// Credentials must be passed in the environment variables: DNSMADEEASY_API_KEY
|
||||||
// and DNSMADEEASY_API_SECRET.
|
// and DNSMADEEASY_API_SECRET.
|
||||||
func NewDNSProvider() (*DNSProvider, error) {
|
func NewDNSProvider() (*DNSProvider, error) {
|
||||||
dnsmadeeasyAPIKey := os.Getenv("DNSMADEEASY_API_KEY")
|
values, err := env.Get("DNSMADEEASY_API_KEY", "DNSMADEEASY_API_SECRET")
|
||||||
dnsmadeeasyAPISecret := os.Getenv("DNSMADEEASY_API_SECRET")
|
if err != nil {
|
||||||
dnsmadeeasySandbox := os.Getenv("DNSMADEEASY_SANDBOX")
|
return nil, fmt.Errorf("DNSMadeEasy: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
var baseURL string
|
var baseURL string
|
||||||
|
if sandbox, _ := strconv.ParseBool(os.Getenv("DNSMADEEASY_SANDBOX")); sandbox {
|
||||||
sandbox, _ := strconv.ParseBool(dnsmadeeasySandbox)
|
|
||||||
if sandbox {
|
|
||||||
baseURL = "https://api.sandbox.dnsmadeeasy.com/V2.0"
|
baseURL = "https://api.sandbox.dnsmadeeasy.com/V2.0"
|
||||||
} else {
|
} else {
|
||||||
baseURL = "https://api.dnsmadeeasy.com/V2.0"
|
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
|
// NewDNSProviderCredentials uses the supplied credentials to return a
|
||||||
|
|
|
@ -4,11 +4,11 @@ package dnspod
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/decker502/dnspod-go"
|
"github.com/decker502/dnspod-go"
|
||||||
"github.com/xenolf/lego/acme"
|
"github.com/xenolf/lego/acme"
|
||||||
|
"github.com/xenolf/lego/platform/config/env"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DNSProvider is an implementation of the acme.ChallengeProvider interface.
|
// DNSProvider is an implementation of the acme.ChallengeProvider interface.
|
||||||
|
@ -19,8 +19,12 @@ type DNSProvider struct {
|
||||||
// NewDNSProvider returns a DNSProvider instance configured for dnspod.
|
// NewDNSProvider returns a DNSProvider instance configured for dnspod.
|
||||||
// Credentials must be passed in the environment variables: DNSPOD_API_KEY.
|
// Credentials must be passed in the environment variables: DNSPOD_API_KEY.
|
||||||
func NewDNSProvider() (*DNSProvider, error) {
|
func NewDNSProvider() (*DNSProvider, error) {
|
||||||
key := os.Getenv("DNSPOD_API_KEY")
|
values, err := env.Get("DNSPOD_API_KEY")
|
||||||
return NewDNSProviderCredentials(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
|
// 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 {
|
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)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
package dnspod
|
package dnspod
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -21,28 +22,31 @@ func init() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func restorednspodEnv() {
|
func restoreEnv() {
|
||||||
os.Setenv("DNSPOD_API_KEY", dnspodAPIKey)
|
os.Setenv("DNSPOD_API_KEY", dnspodAPIKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewDNSProviderValid(t *testing.T) {
|
func TestNewDNSProviderValid(t *testing.T) {
|
||||||
|
defer restoreEnv()
|
||||||
os.Setenv("DNSPOD_API_KEY", "")
|
os.Setenv("DNSPOD_API_KEY", "")
|
||||||
|
|
||||||
_, err := NewDNSProviderCredentials("123")
|
_, err := NewDNSProviderCredentials("123")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
restorednspodEnv()
|
|
||||||
}
|
}
|
||||||
func TestNewDNSProviderValidEnv(t *testing.T) {
|
func TestNewDNSProviderValidEnv(t *testing.T) {
|
||||||
|
defer restoreEnv()
|
||||||
os.Setenv("DNSPOD_API_KEY", "123")
|
os.Setenv("DNSPOD_API_KEY", "123")
|
||||||
|
|
||||||
_, err := NewDNSProvider()
|
_, err := NewDNSProvider()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
restorednspodEnv()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewDNSProviderMissingCredErr(t *testing.T) {
|
func TestNewDNSProviderMissingCredErr(t *testing.T) {
|
||||||
|
defer restoreEnv()
|
||||||
os.Setenv("DNSPOD_API_KEY", "")
|
os.Setenv("DNSPOD_API_KEY", "")
|
||||||
|
|
||||||
_, err := NewDNSProvider()
|
_, err := NewDNSProvider()
|
||||||
assert.EqualError(t, err, "dnspod credentials missing")
|
assert.EqualError(t, err, "DNSPod: some credentials information are missing: DNSPOD_API_KEY")
|
||||||
restorednspodEnv()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLivednspodPresent(t *testing.T) {
|
func TestLivednspodPresent(t *testing.T) {
|
||||||
|
|
|
@ -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.
|
// See http://www.duckdns.org/spec.jsp for more info on updating TXT records.
|
||||||
package duckdns
|
package duckdns
|
||||||
|
|
||||||
|
@ -6,30 +6,33 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/xenolf/lego/acme"
|
"github.com/xenolf/lego/acme"
|
||||||
|
"github.com/xenolf/lego/platform/config/env"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DNSProvider adds and removes the record for the DNS challenge
|
// DNSProvider adds and removes the record for the DNS challenge
|
||||||
type DNSProvider struct {
|
type DNSProvider struct {
|
||||||
// The duckdns api token
|
// The api token
|
||||||
token string
|
token string
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDNSProvider returns a new DNS provider using
|
// NewDNSProvider returns a new DNS provider using
|
||||||
// environment variable DUCKDNS_TOKEN for adding and removing the DNS record.
|
// environment variable DUCKDNS_TOKEN for adding and removing the DNS record.
|
||||||
func NewDNSProvider() (*DNSProvider, error) {
|
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
|
// NewDNSProviderCredentials uses the supplied credentials to return a
|
||||||
// DNSProvider instance configured for http://duckdns.org .
|
// DNSProvider instance configured for http://duckdns.org .
|
||||||
func NewDNSProviderCredentials(duckdnsToken string) (*DNSProvider, error) {
|
func NewDNSProviderCredentials(duckdnsToken string) (*DNSProvider, error) {
|
||||||
if duckdnsToken == "" {
|
if duckdnsToken == "" {
|
||||||
return nil, errors.New("environment variable DUCKDNS_TOKEN not set")
|
return nil, errors.New("DuckDNS: credentials missing")
|
||||||
}
|
}
|
||||||
|
|
||||||
return &DNSProvider{token: duckdnsToken}, nil
|
return &DNSProvider{token: duckdnsToken}, nil
|
||||||
|
|
|
@ -22,22 +22,26 @@ func init() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func restoreDuckdnsEnv() {
|
func restoreEnv() {
|
||||||
os.Setenv("DUCKDNS_TOKEN", duckdnsToken)
|
os.Setenv("DUCKDNS_TOKEN", duckdnsToken)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewDNSProviderValidEnv(t *testing.T) {
|
func TestNewDNSProviderValidEnv(t *testing.T) {
|
||||||
|
defer restoreEnv()
|
||||||
os.Setenv("DUCKDNS_TOKEN", "123")
|
os.Setenv("DUCKDNS_TOKEN", "123")
|
||||||
|
|
||||||
_, err := NewDNSProvider()
|
_, err := NewDNSProvider()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
restoreDuckdnsEnv()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewDNSProviderMissingCredErr(t *testing.T) {
|
func TestNewDNSProviderMissingCredErr(t *testing.T) {
|
||||||
|
defer restoreEnv()
|
||||||
os.Setenv("DUCKDNS_TOKEN", "")
|
os.Setenv("DUCKDNS_TOKEN", "")
|
||||||
|
|
||||||
_, err := NewDNSProvider()
|
_, err := NewDNSProvider()
|
||||||
assert.EqualError(t, err, "environment variable DUCKDNS_TOKEN not set")
|
assert.EqualError(t, err, "DuckDNS: some credentials information are missing: DUCKDNS_TOKEN")
|
||||||
restoreDuckdnsEnv()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLiveDuckdnsPresent(t *testing.T) {
|
func TestLiveDuckdnsPresent(t *testing.T) {
|
||||||
if !duckdnsLiveTest {
|
if !duckdnsLiveTest {
|
||||||
t.Skip("skipping live test")
|
t.Skip("skipping live test")
|
||||||
|
|
|
@ -7,11 +7,11 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/xenolf/lego/acme"
|
"github.com/xenolf/lego/acme"
|
||||||
|
"github.com/xenolf/lego/platform/config/env"
|
||||||
)
|
)
|
||||||
|
|
||||||
var dynBaseURL = "https://api.dynect.net/REST"
|
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,
|
// Credentials must be passed in the environment variables: DYN_CUSTOMER_NAME,
|
||||||
// DYN_USER_NAME and DYN_PASSWORD.
|
// DYN_USER_NAME and DYN_PASSWORD.
|
||||||
func NewDNSProvider() (*DNSProvider, error) {
|
func NewDNSProvider() (*DNSProvider, error) {
|
||||||
customerName := os.Getenv("DYN_CUSTOMER_NAME")
|
values, err := env.Get("DYN_CUSTOMER_NAME", "DYN_USER_NAME", "DYN_PASSWORD")
|
||||||
userName := os.Getenv("DYN_USER_NAME")
|
if err != nil {
|
||||||
password := os.Getenv("DYN_PASSWORD")
|
return nil, fmt.Errorf("DynDNS: %v", err)
|
||||||
return NewDNSProviderCredentials(customerName, userName, password)
|
}
|
||||||
|
|
||||||
|
return NewDNSProviderCredentials(values["DYN_CUSTOMER_NAME"], values["DYN_USER_NAME"], values["DYN_PASSWORD"])
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDNSProviderCredentials uses the supplied credentials to return a
|
// NewDNSProviderCredentials uses the supplied credentials to return a
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
|
|
||||||
"github.com/exoscale/egoscale"
|
"github.com/exoscale/egoscale"
|
||||||
"github.com/xenolf/lego/acme"
|
"github.com/xenolf/lego/acme"
|
||||||
|
"github.com/xenolf/lego/platform/config/env"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DNSProvider is an implementation of the acme.ChallengeProvider interface.
|
// 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:
|
// NewDNSProvider Credentials must be passed in the environment variables:
|
||||||
// EXOSCALE_API_KEY, EXOSCALE_API_SECRET, EXOSCALE_ENDPOINT.
|
// EXOSCALE_API_KEY, EXOSCALE_API_SECRET, EXOSCALE_ENDPOINT.
|
||||||
func NewDNSProvider() (*DNSProvider, error) {
|
func NewDNSProvider() (*DNSProvider, error) {
|
||||||
key := os.Getenv("EXOSCALE_API_KEY")
|
values, err := env.Get("EXOSCALE_API_KEY", "EXOSCALE_API_SECRET")
|
||||||
secret := os.Getenv("EXOSCALE_API_SECRET")
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Exoscale: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
endpoint := os.Getenv("EXOSCALE_ENDPOINT")
|
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
|
// 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 == "" {
|
if key == "" || secret == "" {
|
||||||
return nil, fmt.Errorf("Exoscale credentials missing")
|
return nil, fmt.Errorf("Exoscale credentials missing")
|
||||||
}
|
}
|
||||||
|
|
||||||
if endpoint == "" {
|
if endpoint == "" {
|
||||||
endpoint = "https://api.exoscale.ch/dns"
|
endpoint = "https://api.exoscale.ch/dns"
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,32 +24,36 @@ func init() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func restoreExoscaleEnv() {
|
func restoreEnv() {
|
||||||
os.Setenv("EXOSCALE_API_KEY", exoscaleAPIKey)
|
os.Setenv("EXOSCALE_API_KEY", exoscaleAPIKey)
|
||||||
os.Setenv("EXOSCALE_API_SECRET", exoscaleAPISecret)
|
os.Setenv("EXOSCALE_API_SECRET", exoscaleAPISecret)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewDNSProviderValid(t *testing.T) {
|
func TestNewDNSProviderValid(t *testing.T) {
|
||||||
|
defer restoreEnv()
|
||||||
os.Setenv("EXOSCALE_API_KEY", "")
|
os.Setenv("EXOSCALE_API_KEY", "")
|
||||||
os.Setenv("EXOSCALE_API_SECRET", "")
|
os.Setenv("EXOSCALE_API_SECRET", "")
|
||||||
|
|
||||||
_, err := NewDNSProviderClient("example@example.com", "123", "")
|
_, err := NewDNSProviderClient("example@example.com", "123", "")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
restoreExoscaleEnv()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewDNSProviderValidEnv(t *testing.T) {
|
func TestNewDNSProviderValidEnv(t *testing.T) {
|
||||||
|
defer restoreEnv()
|
||||||
os.Setenv("EXOSCALE_API_KEY", "example@example.com")
|
os.Setenv("EXOSCALE_API_KEY", "example@example.com")
|
||||||
os.Setenv("EXOSCALE_API_SECRET", "123")
|
os.Setenv("EXOSCALE_API_SECRET", "123")
|
||||||
|
|
||||||
_, err := NewDNSProvider()
|
_, err := NewDNSProvider()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
restoreExoscaleEnv()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewDNSProviderMissingCredErr(t *testing.T) {
|
func TestNewDNSProviderMissingCredErr(t *testing.T) {
|
||||||
os.Setenv("EXOSCALE_API_KEY", "")
|
os.Setenv("EXOSCALE_API_KEY", "")
|
||||||
os.Setenv("EXOSCALE_API_SECRET", "")
|
os.Setenv("EXOSCALE_API_SECRET", "")
|
||||||
|
defer restoreEnv()
|
||||||
|
|
||||||
_, err := NewDNSProvider()
|
_, err := NewDNSProvider()
|
||||||
assert.EqualError(t, err, "Exoscale credentials missing")
|
assert.EqualError(t, err, "Exoscale: some credentials information are missing: EXOSCALE_API_KEY,EXOSCALE_API_SECRET")
|
||||||
restoreExoscaleEnv()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestExtractRootRecordName(t *testing.T) {
|
func TestExtractRootRecordName(t *testing.T) {
|
||||||
|
|
|
@ -2,12 +2,12 @@ package fastdns
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
|
|
||||||
configdns "github.com/akamai/AkamaiOPEN-edgegrid-golang/configdns-v1"
|
configdns "github.com/akamai/AkamaiOPEN-edgegrid-golang/configdns-v1"
|
||||||
"github.com/akamai/AkamaiOPEN-edgegrid-golang/edgegrid"
|
"github.com/akamai/AkamaiOPEN-edgegrid-golang/edgegrid"
|
||||||
"github.com/xenolf/lego/acme"
|
"github.com/xenolf/lego/acme"
|
||||||
|
"github.com/xenolf/lego/platform/config/env"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DNSProvider is an implementation of the acme.ChallengeProvider interface.
|
// 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:
|
// NewDNSProvider uses the supplied environment variables to return a DNSProvider instance:
|
||||||
// AKAMAI_HOST, AKAMAI_CLIENT_TOKEN, AKAMAI_CLIENT_SECRET, AKAMAI_ACCESS_TOKEN
|
// AKAMAI_HOST, AKAMAI_CLIENT_TOKEN, AKAMAI_CLIENT_SECRET, AKAMAI_ACCESS_TOKEN
|
||||||
func NewDNSProvider() (*DNSProvider, error) {
|
func NewDNSProvider() (*DNSProvider, error) {
|
||||||
host := os.Getenv("AKAMAI_HOST")
|
values, err := env.Get("AKAMAI_HOST", "AKAMAI_CLIENT_TOKEN", "AKAMAI_CLIENT_SECRET", "AKAMAI_ACCESS_TOKEN")
|
||||||
clientToken := os.Getenv("AKAMAI_CLIENT_TOKEN")
|
if err != nil {
|
||||||
clientSecret := os.Getenv("AKAMAI_CLIENT_SECRET")
|
return nil, fmt.Errorf("FastDNS: %v", err)
|
||||||
accessToken := os.Getenv("AKAMAI_ACCESS_TOKEN")
|
}
|
||||||
|
|
||||||
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
|
// NewDNSProviderClient uses the supplied parameters to return a DNSProvider instance
|
||||||
// configured for FastDNS.
|
// configured for FastDNS.
|
||||||
func NewDNSProviderClient(host, clientToken, clientSecret, accessToken string) (*DNSProvider, error) {
|
func NewDNSProviderClient(host, clientToken, clientSecret, accessToken string) (*DNSProvider, error) {
|
||||||
if clientToken == "" || clientSecret == "" || accessToken == "" || host == "" {
|
if clientToken == "" || clientSecret == "" || accessToken == "" || host == "" {
|
||||||
return nil, fmt.Errorf("Akamai FastDNS credentials missing")
|
return nil, fmt.Errorf("FastDNS credentials are missing")
|
||||||
}
|
}
|
||||||
config := edgegrid.Config{
|
config := edgegrid.Config{
|
||||||
Host: host,
|
Host: host,
|
||||||
|
|
|
@ -29,7 +29,7 @@ func init() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func restoreFastdnsEnv() {
|
func restoreEnv() {
|
||||||
os.Setenv("AKAMAI_HOST", host)
|
os.Setenv("AKAMAI_HOST", host)
|
||||||
os.Setenv("AKAMAI_CLIENT_TOKEN", clientToken)
|
os.Setenv("AKAMAI_CLIENT_TOKEN", clientToken)
|
||||||
os.Setenv("AKAMAI_CLIENT_SECRET", clientSecret)
|
os.Setenv("AKAMAI_CLIENT_SECRET", clientSecret)
|
||||||
|
@ -37,33 +37,36 @@ func restoreFastdnsEnv() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewDNSProviderValid(t *testing.T) {
|
func TestNewDNSProviderValid(t *testing.T) {
|
||||||
|
defer restoreEnv()
|
||||||
os.Setenv("AKAMAI_HOST", "")
|
os.Setenv("AKAMAI_HOST", "")
|
||||||
os.Setenv("AKAMAI_CLIENT_TOKEN", "")
|
os.Setenv("AKAMAI_CLIENT_TOKEN", "")
|
||||||
os.Setenv("AKAMAI_CLIENT_SECRET", "")
|
os.Setenv("AKAMAI_CLIENT_SECRET", "")
|
||||||
os.Setenv("AKAMAI_ACCESS_TOKEN", "")
|
os.Setenv("AKAMAI_ACCESS_TOKEN", "")
|
||||||
|
|
||||||
_, err := NewDNSProviderClient("somehost", "someclienttoken", "someclientsecret", "someaccesstoken")
|
_, err := NewDNSProviderClient("somehost", "someclienttoken", "someclientsecret", "someaccesstoken")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
restoreFastdnsEnv()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewDNSProviderValidEnv(t *testing.T) {
|
func TestNewDNSProviderValidEnv(t *testing.T) {
|
||||||
|
defer restoreEnv()
|
||||||
os.Setenv("AKAMAI_HOST", "somehost")
|
os.Setenv("AKAMAI_HOST", "somehost")
|
||||||
os.Setenv("AKAMAI_CLIENT_TOKEN", "someclienttoken")
|
os.Setenv("AKAMAI_CLIENT_TOKEN", "someclienttoken")
|
||||||
os.Setenv("AKAMAI_CLIENT_SECRET", "someclientsecret")
|
os.Setenv("AKAMAI_CLIENT_SECRET", "someclientsecret")
|
||||||
os.Setenv("AKAMAI_ACCESS_TOKEN", "someaccesstoken")
|
os.Setenv("AKAMAI_ACCESS_TOKEN", "someaccesstoken")
|
||||||
|
|
||||||
_, err := NewDNSProvider()
|
_, err := NewDNSProvider()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
restoreFastdnsEnv()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewDNSProviderMissingCredErr(t *testing.T) {
|
func TestNewDNSProviderMissingCredErr(t *testing.T) {
|
||||||
|
defer restoreEnv()
|
||||||
os.Setenv("AKAMAI_HOST", "")
|
os.Setenv("AKAMAI_HOST", "")
|
||||||
os.Setenv("AKAMAI_CLIENT_TOKEN", "")
|
os.Setenv("AKAMAI_CLIENT_TOKEN", "")
|
||||||
os.Setenv("AKAMAI_CLIENT_SECRET", "")
|
os.Setenv("AKAMAI_CLIENT_SECRET", "")
|
||||||
os.Setenv("AKAMAI_ACCESS_TOKEN", "")
|
os.Setenv("AKAMAI_ACCESS_TOKEN", "")
|
||||||
|
|
||||||
_, err := NewDNSProvider()
|
_, err := NewDNSProvider()
|
||||||
assert.EqualError(t, err, "Akamai FastDNS credentials missing")
|
assert.EqualError(t, err, "FastDNS: some credentials information are missing: AKAMAI_HOST,AKAMAI_CLIENT_TOKEN,AKAMAI_CLIENT_SECRET,AKAMAI_ACCESS_TOKEN")
|
||||||
restoreFastdnsEnv()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLiveFastdnsPresent(t *testing.T) {
|
func TestLiveFastdnsPresent(t *testing.T) {
|
||||||
|
|
|
@ -9,12 +9,12 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/xenolf/lego/acme"
|
"github.com/xenolf/lego/acme"
|
||||||
|
"github.com/xenolf/lego/platform/config/env"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Gandi API reference: http://doc.rpc.gandi.net/index.html
|
// 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.
|
// NewDNSProvider returns a DNSProvider instance configured for Gandi.
|
||||||
// Credentials must be passed in the environment variable: GANDI_API_KEY.
|
// Credentials must be passed in the environment variable: GANDI_API_KEY.
|
||||||
func NewDNSProvider() (*DNSProvider, error) {
|
func NewDNSProvider() (*DNSProvider, error) {
|
||||||
apiKey := os.Getenv("GANDI_API_KEY")
|
values, err := env.Get("GANDI_API_KEY")
|
||||||
return NewDNSProviderCredentials(apiKey)
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("GandiDNS: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return NewDNSProviderCredentials(values["GANDI_API_KEY"])
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDNSProviderCredentials uses the supplied credentials to return a
|
// NewDNSProviderCredentials uses the supplied credentials to return a
|
||||||
|
|
|
@ -8,6 +8,8 @@ import (
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TestDNSProvider runs Present and CleanUp against a fake Gandi RPC
|
// TestDNSProvider runs Present and CleanUp against a fake Gandi RPC
|
||||||
|
@ -15,55 +17,49 @@ import (
|
||||||
func TestDNSProvider(t *testing.T) {
|
func TestDNSProvider(t *testing.T) {
|
||||||
fakeAPIKey := "123412341234123412341234"
|
fakeAPIKey := "123412341234123412341234"
|
||||||
fakeKeyAuth := "XXXX"
|
fakeKeyAuth := "XXXX"
|
||||||
|
|
||||||
provider, err := NewDNSProviderCredentials(fakeAPIKey)
|
provider, err := NewDNSProviderCredentials(fakeAPIKey)
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
regexpDate, err := regexp.Compile(`\[ACME Challenge [^\]:]*:[^\]]*\]`)
|
regexpDate, err := regexp.Compile(`\[ACME Challenge [^\]:]*:[^\]]*\]`)
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
// start fake RPC server
|
// start fake RPC server
|
||||||
fakeServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
fakeServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
if r.Header.Get("Content-Type") != "text/xml" {
|
require.Equal(t, "text/xml", r.Header.Get("Content-Type"), "invalid content type")
|
||||||
t.Fatalf("Content-Type: text/xml header not found")
|
|
||||||
}
|
|
||||||
req, err := ioutil.ReadAll(r.Body)
|
req, err := ioutil.ReadAll(r.Body)
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
t.Fatal(err)
|
|
||||||
}
|
req = regexpDate.ReplaceAllLiteral(req, []byte(`[ACME Challenge 01 Jan 16 00:00 +0000]`))
|
||||||
req = regexpDate.ReplaceAllLiteral(
|
|
||||||
req, []byte(`[ACME Challenge 01 Jan 16 00:00 +0000]`))
|
|
||||||
resp, ok := serverResponses[string(req)]
|
resp, ok := serverResponses[string(req)]
|
||||||
if !ok {
|
require.True(t, ok, "Server response for request not found")
|
||||||
t.Fatalf("Server response for request not found")
|
|
||||||
}
|
|
||||||
_, err = io.Copy(w, strings.NewReader(resp))
|
_, err = io.Copy(w, strings.NewReader(resp))
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
}))
|
}))
|
||||||
defer fakeServer.Close()
|
defer fakeServer.Close()
|
||||||
|
|
||||||
// define function to override findZoneByFqdn with
|
// define function to override findZoneByFqdn with
|
||||||
fakeFindZoneByFqdn := func(fqdn string, nameserver []string) (string, error) {
|
fakeFindZoneByFqdn := func(fqdn string, nameserver []string) (string, error) {
|
||||||
return "example.com.", nil
|
return "example.com.", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// override gandi endpoint and findZoneByFqdn function
|
// override gandi endpoint and findZoneByFqdn function
|
||||||
savedEndpoint, savedFindZoneByFqdn := endpoint, findZoneByFqdn
|
savedEndpoint, savedFindZoneByFqdn := endpoint, findZoneByFqdn
|
||||||
defer func() {
|
defer func() {
|
||||||
endpoint, findZoneByFqdn = savedEndpoint, savedFindZoneByFqdn
|
endpoint, findZoneByFqdn = savedEndpoint, savedFindZoneByFqdn
|
||||||
}()
|
}()
|
||||||
|
|
||||||
endpoint, findZoneByFqdn = fakeServer.URL+"/", fakeFindZoneByFqdn
|
endpoint, findZoneByFqdn = fakeServer.URL+"/", fakeFindZoneByFqdn
|
||||||
|
|
||||||
// run Present
|
// run Present
|
||||||
err = provider.Present("abc.def.example.com", "", fakeKeyAuth)
|
err = provider.Present("abc.def.example.com", "", fakeKeyAuth)
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
// run CleanUp
|
// run CleanUp
|
||||||
err = provider.CleanUp("abc.def.example.com", "", fakeKeyAuth)
|
err = provider.CleanUp("abc.def.example.com", "", fakeKeyAuth)
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// serverResponses is the XML-RPC Request->Response map used by the
|
// serverResponses is the XML-RPC Request->Response map used by the
|
||||||
|
|
|
@ -7,12 +7,12 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/xenolf/lego/acme"
|
"github.com/xenolf/lego/acme"
|
||||||
|
"github.com/xenolf/lego/platform/config/env"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Gandi API reference: http://doc.livedns.gandi.net/
|
// Gandi API reference: http://doc.livedns.gandi.net/
|
||||||
|
@ -45,8 +45,12 @@ type DNSProvider struct {
|
||||||
// NewDNSProvider returns a DNSProvider instance configured for Gandi.
|
// NewDNSProvider returns a DNSProvider instance configured for Gandi.
|
||||||
// Credentials must be passed in the environment variable: GANDIV5_API_KEY.
|
// Credentials must be passed in the environment variable: GANDIV5_API_KEY.
|
||||||
func NewDNSProvider() (*DNSProvider, error) {
|
func NewDNSProvider() (*DNSProvider, error) {
|
||||||
apiKey := os.Getenv("GANDIV5_API_KEY")
|
values, err := env.Get("GANDIV5_API_KEY")
|
||||||
return NewDNSProviderCredentials(apiKey)
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("GandiDNS: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return NewDNSProviderCredentials(values["GANDIV5_API_KEY"])
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDNSProviderCredentials uses the supplied credentials to return a
|
// NewDNSProviderCredentials uses the supplied credentials to return a
|
||||||
|
|
|
@ -8,6 +8,8 @@ import (
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TestDNSProvider runs Present and CleanUp against a fake Gandi RPC
|
// TestDNSProvider runs Present and CleanUp against a fake Gandi RPC
|
||||||
|
@ -15,55 +17,50 @@ import (
|
||||||
func TestDNSProvider(t *testing.T) {
|
func TestDNSProvider(t *testing.T) {
|
||||||
fakeAPIKey := "123412341234123412341234"
|
fakeAPIKey := "123412341234123412341234"
|
||||||
fakeKeyAuth := "XXXX"
|
fakeKeyAuth := "XXXX"
|
||||||
|
|
||||||
provider, err := NewDNSProviderCredentials(fakeAPIKey)
|
provider, err := NewDNSProviderCredentials(fakeAPIKey)
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
regexpToken, err := regexp.Compile(`"rrset_values":\[".+"\]`)
|
regexpToken, err := regexp.Compile(`"rrset_values":\[".+"\]`)
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
// start fake RPC server
|
// start fake RPC server
|
||||||
fakeServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
fakeServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
if r.Header.Get("Content-Type") != "application/json" {
|
require.Equal(t, "application/json", r.Header.Get("Content-Type"), "invalid content type")
|
||||||
t.Fatalf("Content-Type: application/json header not found")
|
|
||||||
}
|
|
||||||
req, err := ioutil.ReadAll(r.Body)
|
req, err := ioutil.ReadAll(r.Body)
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
t.Fatal(err)
|
|
||||||
}
|
req = regexpToken.ReplaceAllLiteral(req, []byte(`"rrset_values":["TOKEN"]`))
|
||||||
req = regexpToken.ReplaceAllLiteral(
|
|
||||||
req, []byte(`"rrset_values":["TOKEN"]`))
|
|
||||||
resp, ok := serverResponses[string(req)]
|
resp, ok := serverResponses[string(req)]
|
||||||
if !ok {
|
require.True(t, ok, "Server response for request not found")
|
||||||
t.Fatalf("Server response for request not found")
|
|
||||||
}
|
|
||||||
_, err = io.Copy(w, strings.NewReader(resp))
|
_, err = io.Copy(w, strings.NewReader(resp))
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
}))
|
}))
|
||||||
defer fakeServer.Close()
|
defer fakeServer.Close()
|
||||||
|
|
||||||
// define function to override findZoneByFqdn with
|
// define function to override findZoneByFqdn with
|
||||||
fakeFindZoneByFqdn := func(fqdn string, nameserver []string) (string, error) {
|
fakeFindZoneByFqdn := func(fqdn string, nameserver []string) (string, error) {
|
||||||
return "example.com.", nil
|
return "example.com.", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// override gandi endpoint and findZoneByFqdn function
|
// override gandi endpoint and findZoneByFqdn function
|
||||||
savedEndpoint, savedFindZoneByFqdn := endpoint, findZoneByFqdn
|
savedEndpoint, savedFindZoneByFqdn := endpoint, findZoneByFqdn
|
||||||
defer func() {
|
defer func() {
|
||||||
endpoint, findZoneByFqdn = savedEndpoint, savedFindZoneByFqdn
|
endpoint, findZoneByFqdn = savedEndpoint, savedFindZoneByFqdn
|
||||||
}()
|
}()
|
||||||
|
|
||||||
endpoint, findZoneByFqdn = fakeServer.URL, fakeFindZoneByFqdn
|
endpoint, findZoneByFqdn = fakeServer.URL, fakeFindZoneByFqdn
|
||||||
|
|
||||||
// run Present
|
// run Present
|
||||||
err = provider.Present("abc.def.example.com", "", fakeKeyAuth)
|
err = provider.Present("abc.def.example.com", "", fakeKeyAuth)
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
// run CleanUp
|
// run CleanUp
|
||||||
err = provider.CleanUp("abc.def.example.com", "", fakeKeyAuth)
|
err = provider.CleanUp("abc.def.example.com", "", fakeKeyAuth)
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// serverResponses is the JSON Request->Response map used by the
|
// serverResponses is the JSON Request->Response map used by the
|
||||||
|
|
|
@ -31,6 +31,7 @@ func NewDNSProvider() (*DNSProvider, error) {
|
||||||
if saFile, ok := os.LookupEnv("GCE_SERVICE_ACCOUNT_FILE"); ok {
|
if saFile, ok := os.LookupEnv("GCE_SERVICE_ACCOUNT_FILE"); ok {
|
||||||
return NewDNSProviderServiceAccount(saFile)
|
return NewDNSProviderServiceAccount(saFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
project := os.Getenv("GCE_PROJECT")
|
project := os.Getenv("GCE_PROJECT")
|
||||||
return NewDNSProviderCredentials(project)
|
return NewDNSProviderCredentials(project)
|
||||||
}
|
}
|
||||||
|
@ -44,11 +45,11 @@ func NewDNSProviderCredentials(project string) (*DNSProvider, error) {
|
||||||
|
|
||||||
client, err := google.DefaultClient(context.Background(), dns.NdevClouddnsReadwriteScope)
|
client, err := google.DefaultClient(context.Background(), dns.NdevClouddnsReadwriteScope)
|
||||||
if err != nil {
|
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)
|
svc, err := dns.New(client)
|
||||||
if err != nil {
|
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{
|
return &DNSProvider{
|
||||||
project: project,
|
project: project,
|
||||||
|
@ -65,7 +66,7 @@ func NewDNSProviderServiceAccount(saFile string) (*DNSProvider, error) {
|
||||||
|
|
||||||
dat, err := ioutil.ReadFile(saFile)
|
dat, err := ioutil.ReadFile(saFile)
|
||||||
if err != nil {
|
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
|
// read project id from service account file
|
||||||
|
@ -74,19 +75,19 @@ func NewDNSProviderServiceAccount(saFile string) (*DNSProvider, error) {
|
||||||
}
|
}
|
||||||
err = json.Unmarshal(dat, &datJSON)
|
err = json.Unmarshal(dat, &datJSON)
|
||||||
if err != nil || datJSON.ProjectID == "" {
|
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
|
project := datJSON.ProjectID
|
||||||
|
|
||||||
conf, err := google.JWTConfigFromJSON(dat, dns.NdevClouddnsReadwriteScope)
|
conf, err := google.JWTConfigFromJSON(dat, dns.NdevClouddnsReadwriteScope)
|
||||||
if err != nil {
|
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())
|
client := conf.Client(context.Background())
|
||||||
|
|
||||||
svc, err := dns.New(client)
|
svc, err := dns.New(client)
|
||||||
if err != nil {
|
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{
|
return &DNSProvider{
|
||||||
project: project,
|
project: project,
|
||||||
|
@ -189,7 +190,7 @@ func (c *DNSProvider) getHostedZone(domain string) (string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(zones.ManagedZones) == 0 {
|
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
|
return zones.ManagedZones[0].Name, nil
|
||||||
|
@ -202,7 +203,7 @@ func (c *DNSProvider) findTxtRecords(zone, fqdn string) ([]*dns.ResourceRecordSe
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
found := []*dns.ResourceRecordSet{}
|
var found []*dns.ResourceRecordSet
|
||||||
for _, r := range recs.Rrsets {
|
for _, r := range recs.Rrsets {
|
||||||
if r.Type == "TXT" && r.Name == fqdn {
|
if r.Type == "TXT" && r.Name == fqdn {
|
||||||
found = append(found, r)
|
found = append(found, r)
|
||||||
|
|
|
@ -27,7 +27,7 @@ func init() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func restoreGCloudEnv() {
|
func restoreEnv() {
|
||||||
os.Setenv("GCE_PROJECT", gcloudProject)
|
os.Setenv("GCE_PROJECT", gcloudProject)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,27 +35,32 @@ func TestNewDNSProviderValid(t *testing.T) {
|
||||||
if !gcloudLiveTest {
|
if !gcloudLiveTest {
|
||||||
t.Skip("skipping live test (requires credentials)")
|
t.Skip("skipping live test (requires credentials)")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
defer restoreEnv()
|
||||||
os.Setenv("GCE_PROJECT", "")
|
os.Setenv("GCE_PROJECT", "")
|
||||||
|
|
||||||
_, err := NewDNSProviderCredentials("my-project")
|
_, err := NewDNSProviderCredentials("my-project")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
restoreGCloudEnv()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewDNSProviderValidEnv(t *testing.T) {
|
func TestNewDNSProviderValidEnv(t *testing.T) {
|
||||||
if !gcloudLiveTest {
|
if !gcloudLiveTest {
|
||||||
t.Skip("skipping live test (requires credentials)")
|
t.Skip("skipping live test (requires credentials)")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
defer restoreEnv()
|
||||||
os.Setenv("GCE_PROJECT", "my-project")
|
os.Setenv("GCE_PROJECT", "my-project")
|
||||||
|
|
||||||
_, err := NewDNSProvider()
|
_, err := NewDNSProvider()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
restoreGCloudEnv()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewDNSProviderMissingCredErr(t *testing.T) {
|
func TestNewDNSProviderMissingCredErr(t *testing.T) {
|
||||||
|
defer restoreEnv()
|
||||||
os.Setenv("GCE_PROJECT", "")
|
os.Setenv("GCE_PROJECT", "")
|
||||||
|
|
||||||
_, err := NewDNSProvider()
|
_, err := NewDNSProvider()
|
||||||
assert.EqualError(t, err, "Google Cloud project name missing")
|
assert.EqualError(t, err, "Google Cloud project name missing")
|
||||||
restoreGCloudEnv()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLiveGoogleCloudPresent(t *testing.T) {
|
func TestLiveGoogleCloudPresent(t *testing.T) {
|
||||||
|
|
|
@ -7,13 +7,13 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/xenolf/lego/acme"
|
"github.com/xenolf/lego/acme"
|
||||||
"github.com/xenolf/lego/log"
|
"github.com/xenolf/lego/log"
|
||||||
|
"github.com/xenolf/lego/platform/config/env"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GleSYS API reference: https://github.com/GleSYS/API/wiki/API-Documentation
|
// 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
|
// Credentials must be passed in the environment variables: GLESYS_API_USER
|
||||||
// and GLESYS_API_KEY.
|
// and GLESYS_API_KEY.
|
||||||
func NewDNSProvider() (*DNSProvider, error) {
|
func NewDNSProvider() (*DNSProvider, error) {
|
||||||
apiUser := os.Getenv("GLESYS_API_USER")
|
values, err := env.Get("GLESYS_API_USER", "GLESYS_API_KEY")
|
||||||
apiKey := os.Getenv("GLESYS_API_KEY")
|
if err != nil {
|
||||||
return NewDNSProviderCredentials(apiUser, apiKey)
|
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
|
// NewDNSProviderCredentials uses the supplied credentials to return a
|
||||||
|
|
|
@ -2,18 +2,17 @@
|
||||||
package godaddy
|
package godaddy
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"net/http"
|
|
||||||
"os"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/xenolf/lego/acme"
|
"github.com/xenolf/lego/acme"
|
||||||
|
"github.com/xenolf/lego/platform/config/env"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GoDaddyAPIURL represents the API endpoint to call.
|
// 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
|
// Credentials must be passed in the environment variables: GODADDY_API_KEY
|
||||||
// and GODADDY_API_SECRET.
|
// and GODADDY_API_SECRET.
|
||||||
func NewDNSProvider() (*DNSProvider, error) {
|
func NewDNSProvider() (*DNSProvider, error) {
|
||||||
apikey := os.Getenv("GODADDY_API_KEY")
|
values, err := env.Get("GODADDY_API_KEY", "GODADDY_API_SECRET")
|
||||||
secret := os.Getenv("GODADDY_API_SECRET")
|
if err != nil {
|
||||||
return NewDNSProviderCredentials(apikey, secret)
|
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
|
// NewDNSProviderCredentials uses the supplied credentials to return a
|
||||||
|
|
|
@ -8,40 +8,40 @@ import (
|
||||||
"github.com/aws/aws-sdk-go/aws"
|
"github.com/aws/aws-sdk-go/aws"
|
||||||
"github.com/aws/aws-sdk-go/aws/session"
|
"github.com/aws/aws-sdk-go/aws/session"
|
||||||
"github.com/aws/aws-sdk-go/service/lightsail"
|
"github.com/aws/aws-sdk-go/service/lightsail"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestLightsailTTL(t *testing.T) {
|
func TestLightsailTTL(t *testing.T) {
|
||||||
|
|
||||||
m, err := testGetAndPreCheck()
|
m, err := testGetAndPreCheck()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Skip(err.Error())
|
t.Skip(err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
provider, err := NewDNSProvider()
|
provider, err := NewDNSProvider()
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
t.Fatalf("Fatal: %s", err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
err = provider.Present(m["lightsailDomain"], "foo", "bar")
|
err = provider.Present(m["lightsailDomain"], "foo", "bar")
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
t.Fatalf("Fatal: %s", err.Error())
|
|
||||||
}
|
|
||||||
// we need a separate Lightshail client here as the one in the DNS provider is
|
// we need a separate Lightshail client here as the one in the DNS provider is
|
||||||
// unexported.
|
// unexported.
|
||||||
fqdn := "_acme-challenge." + m["lightsailDomain"]
|
fqdn := "_acme-challenge." + m["lightsailDomain"]
|
||||||
svc := lightsail.New(session.New())
|
svc := lightsail.New(session.New())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
provider.CleanUp(m["lightsailDomain"], "foo", "bar")
|
provider.CleanUp(m["lightsailDomain"], "foo", "bar")
|
||||||
t.Fatalf("Fatal: %s", err.Error())
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
params := &lightsail.GetDomainInput{
|
params := &lightsail.GetDomainInput{
|
||||||
DomainName: aws.String(m["lightsailDomain"]),
|
DomainName: aws.String(m["lightsailDomain"]),
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err := svc.GetDomain(params)
|
resp, err := svc.GetDomain(params)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
provider.CleanUp(m["lightsailDomain"], "foo", "bar")
|
provider.CleanUp(m["lightsailDomain"], "foo", "bar")
|
||||||
t.Fatalf("Fatal: %s", err.Error())
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
entries := resp.Domain.DomainEntries
|
entries := resp.Domain.DomainEntries
|
||||||
for _, entry := range entries {
|
for _, entry := range entries {
|
||||||
if *entry.Type == "TXT" && *entry.Name == fqdn {
|
if *entry.Type == "TXT" && *entry.Name == fqdn {
|
||||||
|
@ -49,6 +49,7 @@ func TestLightsailTTL(t *testing.T) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
provider.CleanUp(m["lightsailDomain"], "foo", "bar")
|
provider.CleanUp(m["lightsailDomain"], "foo", "bar")
|
||||||
t.Fatalf("Could not find a TXT record for _acme-challenge.%s", m["lightsailDomain"])
|
t.Fatalf("Could not find a TXT record for _acme-challenge.%s", m["lightsailDomain"])
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ func init() {
|
||||||
lightsailSecret = os.Getenv("AWS_SECRET_ACCESS_KEY")
|
lightsailSecret = os.Getenv("AWS_SECRET_ACCESS_KEY")
|
||||||
}
|
}
|
||||||
|
|
||||||
func restoreLightsailEnv() {
|
func restoreEnv() {
|
||||||
os.Setenv("AWS_ACCESS_KEY_ID", lightsailKey)
|
os.Setenv("AWS_ACCESS_KEY_ID", lightsailKey)
|
||||||
os.Setenv("AWS_SECRET_ACCESS_KEY", lightsailSecret)
|
os.Setenv("AWS_SECRET_ACCESS_KEY", lightsailSecret)
|
||||||
os.Setenv("AWS_REGION", "us-east-1")
|
os.Setenv("AWS_REGION", "us-east-1")
|
||||||
|
@ -43,6 +43,7 @@ func makeLightsailProvider(ts *httptest.Server) *DNSProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCredentialsFromEnv(t *testing.T) {
|
func TestCredentialsFromEnv(t *testing.T) {
|
||||||
|
defer restoreEnv()
|
||||||
os.Setenv("AWS_ACCESS_KEY_ID", "123")
|
os.Setenv("AWS_ACCESS_KEY_ID", "123")
|
||||||
os.Setenv("AWS_SECRET_ACCESS_KEY", "123")
|
os.Setenv("AWS_SECRET_ACCESS_KEY", "123")
|
||||||
os.Setenv("AWS_REGION", "us-east-1")
|
os.Setenv("AWS_REGION", "us-east-1")
|
||||||
|
@ -54,8 +55,6 @@ func TestCredentialsFromEnv(t *testing.T) {
|
||||||
sess := session.New(config)
|
sess := session.New(config)
|
||||||
_, err := sess.Config.Credentials.Get()
|
_, err := sess.Config.Credentials.Get()
|
||||||
assert.NoError(t, err, "Expected credentials to be set from environment")
|
assert.NoError(t, err, "Expected credentials to be set from environment")
|
||||||
|
|
||||||
restoreLightsailEnv()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLightsailPresent(t *testing.T) {
|
func TestLightsailPresent(t *testing.T) {
|
||||||
|
|
|
@ -4,12 +4,13 @@ package linode
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"os"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/timewasted/linode/dns"
|
"github.com/timewasted/linode/dns"
|
||||||
"github.com/xenolf/lego/acme"
|
"github.com/xenolf/lego/acme"
|
||||||
|
"github.com/xenolf/lego/platform/config/env"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -31,8 +32,12 @@ type DNSProvider struct {
|
||||||
// NewDNSProvider returns a DNSProvider instance configured for Linode.
|
// NewDNSProvider returns a DNSProvider instance configured for Linode.
|
||||||
// Credentials must be passed in the environment variable: LINODE_API_KEY.
|
// Credentials must be passed in the environment variable: LINODE_API_KEY.
|
||||||
func NewDNSProvider() (*DNSProvider, error) {
|
func NewDNSProvider() (*DNSProvider, error) {
|
||||||
apiKey := os.Getenv("LINODE_API_KEY")
|
values, err := env.Get("LINODE_API_KEY")
|
||||||
return NewDNSProviderCredentials(apiKey)
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Linode: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return NewDNSProviderCredentials(values["LINODE_API_KEY"])
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDNSProviderCredentials uses the supplied credentials to return a
|
// NewDNSProviderCredentials uses the supplied credentials to return a
|
||||||
|
|
|
@ -48,8 +48,7 @@ func newMockServer(t *testing.T, responses MockResponseMap) *httptest.Server {
|
||||||
action := r.URL.Query().Get("api_action")
|
action := r.URL.Query().Get("api_action")
|
||||||
resp, ok := responses[action]
|
resp, ok := responses[action]
|
||||||
if !ok {
|
if !ok {
|
||||||
msg := fmt.Sprintf("Unsupported mock action: %s", action)
|
require.FailNowf(t, "Unsupported mock action: %s", action)
|
||||||
require.FailNow(t, msg)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build the response that the server will return.
|
// 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) {
|
func TestNewDNSProviderWithEnv(t *testing.T) {
|
||||||
os.Setenv("LINODE_API_KEY", "testing")
|
|
||||||
defer restoreEnv()
|
defer restoreEnv()
|
||||||
|
os.Setenv("LINODE_API_KEY", "testing")
|
||||||
|
|
||||||
_, err := NewDNSProvider()
|
_, err := NewDNSProvider()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewDNSProviderWithoutEnv(t *testing.T) {
|
func TestNewDNSProviderWithoutEnv(t *testing.T) {
|
||||||
os.Setenv("LINODE_API_KEY", "")
|
|
||||||
defer restoreEnv()
|
defer restoreEnv()
|
||||||
|
os.Setenv("LINODE_API_KEY", "")
|
||||||
|
|
||||||
_, err := NewDNSProvider()
|
_, 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) {
|
func TestNewDNSProviderCredentialsWithKey(t *testing.T) {
|
||||||
|
@ -99,8 +100,9 @@ func TestNewDNSProviderCredentialsWithoutKey(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDNSProvider_Present(t *testing.T) {
|
func TestDNSProvider_Present(t *testing.T) {
|
||||||
os.Setenv("LINODE_API_KEY", "testing")
|
|
||||||
defer restoreEnv()
|
defer restoreEnv()
|
||||||
|
os.Setenv("LINODE_API_KEY", "testing")
|
||||||
|
|
||||||
p, err := NewDNSProvider()
|
p, err := NewDNSProvider()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
@ -109,7 +111,7 @@ func TestDNSProvider_Present(t *testing.T) {
|
||||||
mockResponses := MockResponseMap{
|
mockResponses := MockResponseMap{
|
||||||
"domain.list": MockResponse{
|
"domain.list": MockResponse{
|
||||||
Response: []dns.Domain{
|
Response: []dns.Domain{
|
||||||
dns.Domain{
|
{
|
||||||
Domain: domain,
|
Domain: domain,
|
||||||
DomainID: 1234,
|
DomainID: 1234,
|
||||||
},
|
},
|
||||||
|
@ -121,8 +123,10 @@ func TestDNSProvider_Present(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
mockSrv := newMockServer(t, mockResponses)
|
mockSrv := newMockServer(t, mockResponses)
|
||||||
defer mockSrv.Close()
|
defer mockSrv.Close()
|
||||||
|
|
||||||
p.linode.ToLinode().SetEndpoint(mockSrv.URL)
|
p.linode.ToLinode().SetEndpoint(mockSrv.URL)
|
||||||
|
|
||||||
err = p.Present(domain, "", keyAuth)
|
err = p.Present(domain, "", keyAuth)
|
||||||
|
@ -130,8 +134,9 @@ func TestDNSProvider_Present(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDNSProvider_PresentNoDomain(t *testing.T) {
|
func TestDNSProvider_PresentNoDomain(t *testing.T) {
|
||||||
os.Setenv("LINODE_API_KEY", "testing")
|
|
||||||
defer restoreEnv()
|
defer restoreEnv()
|
||||||
|
os.Setenv("LINODE_API_KEY", "testing")
|
||||||
|
|
||||||
p, err := NewDNSProvider()
|
p, err := NewDNSProvider()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
@ -140,15 +145,17 @@ func TestDNSProvider_PresentNoDomain(t *testing.T) {
|
||||||
mockResponses := MockResponseMap{
|
mockResponses := MockResponseMap{
|
||||||
"domain.list": MockResponse{
|
"domain.list": MockResponse{
|
||||||
Response: []dns.Domain{
|
Response: []dns.Domain{
|
||||||
dns.Domain{
|
{
|
||||||
Domain: "foobar.com",
|
Domain: "foobar.com",
|
||||||
DomainID: 1234,
|
DomainID: 1234,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
mockSrv := newMockServer(t, mockResponses)
|
mockSrv := newMockServer(t, mockResponses)
|
||||||
defer mockSrv.Close()
|
defer mockSrv.Close()
|
||||||
|
|
||||||
p.linode.ToLinode().SetEndpoint(mockSrv.URL)
|
p.linode.ToLinode().SetEndpoint(mockSrv.URL)
|
||||||
|
|
||||||
err = p.Present(domain, "", keyAuth)
|
err = p.Present(domain, "", keyAuth)
|
||||||
|
@ -156,8 +163,9 @@ func TestDNSProvider_PresentNoDomain(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDNSProvider_PresentCreateFailed(t *testing.T) {
|
func TestDNSProvider_PresentCreateFailed(t *testing.T) {
|
||||||
os.Setenv("LINODE_API_KEY", "testing")
|
|
||||||
defer restoreEnv()
|
defer restoreEnv()
|
||||||
|
os.Setenv("LINODE_API_KEY", "testing")
|
||||||
|
|
||||||
p, err := NewDNSProvider()
|
p, err := NewDNSProvider()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
@ -166,7 +174,7 @@ func TestDNSProvider_PresentCreateFailed(t *testing.T) {
|
||||||
mockResponses := MockResponseMap{
|
mockResponses := MockResponseMap{
|
||||||
"domain.list": MockResponse{
|
"domain.list": MockResponse{
|
||||||
Response: []dns.Domain{
|
Response: []dns.Domain{
|
||||||
dns.Domain{
|
{
|
||||||
Domain: domain,
|
Domain: domain,
|
||||||
DomainID: 1234,
|
DomainID: 1234,
|
||||||
},
|
},
|
||||||
|
@ -175,7 +183,7 @@ func TestDNSProvider_PresentCreateFailed(t *testing.T) {
|
||||||
"domain.resource.create": MockResponse{
|
"domain.resource.create": MockResponse{
|
||||||
Response: nil,
|
Response: nil,
|
||||||
Errors: []linode.ResponseError{
|
Errors: []linode.ResponseError{
|
||||||
linode.ResponseError{
|
{
|
||||||
Code: 1234,
|
Code: 1234,
|
||||||
Message: "Failed to create domain resource",
|
Message: "Failed to create domain resource",
|
||||||
},
|
},
|
||||||
|
@ -184,6 +192,7 @@ func TestDNSProvider_PresentCreateFailed(t *testing.T) {
|
||||||
}
|
}
|
||||||
mockSrv := newMockServer(t, mockResponses)
|
mockSrv := newMockServer(t, mockResponses)
|
||||||
defer mockSrv.Close()
|
defer mockSrv.Close()
|
||||||
|
|
||||||
p.linode.ToLinode().SetEndpoint(mockSrv.URL)
|
p.linode.ToLinode().SetEndpoint(mockSrv.URL)
|
||||||
|
|
||||||
err = p.Present(domain, "", keyAuth)
|
err = p.Present(domain, "", keyAuth)
|
||||||
|
@ -197,8 +206,9 @@ func TestDNSProvider_PresentLive(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDNSProvider_CleanUp(t *testing.T) {
|
func TestDNSProvider_CleanUp(t *testing.T) {
|
||||||
os.Setenv("LINODE_API_KEY", "testing")
|
|
||||||
defer restoreEnv()
|
defer restoreEnv()
|
||||||
|
os.Setenv("LINODE_API_KEY", "testing")
|
||||||
|
|
||||||
p, err := NewDNSProvider()
|
p, err := NewDNSProvider()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
@ -207,7 +217,7 @@ func TestDNSProvider_CleanUp(t *testing.T) {
|
||||||
mockResponses := MockResponseMap{
|
mockResponses := MockResponseMap{
|
||||||
"domain.list": MockResponse{
|
"domain.list": MockResponse{
|
||||||
Response: []dns.Domain{
|
Response: []dns.Domain{
|
||||||
dns.Domain{
|
{
|
||||||
Domain: domain,
|
Domain: domain,
|
||||||
DomainID: 1234,
|
DomainID: 1234,
|
||||||
},
|
},
|
||||||
|
@ -215,7 +225,7 @@ func TestDNSProvider_CleanUp(t *testing.T) {
|
||||||
},
|
},
|
||||||
"domain.resource.list": MockResponse{
|
"domain.resource.list": MockResponse{
|
||||||
Response: []dns.Resource{
|
Response: []dns.Resource{
|
||||||
dns.Resource{
|
{
|
||||||
DomainID: 1234,
|
DomainID: 1234,
|
||||||
Name: "_acme-challenge",
|
Name: "_acme-challenge",
|
||||||
ResourceID: 1234,
|
ResourceID: 1234,
|
||||||
|
@ -230,8 +240,10 @@ func TestDNSProvider_CleanUp(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
mockSrv := newMockServer(t, mockResponses)
|
mockSrv := newMockServer(t, mockResponses)
|
||||||
defer mockSrv.Close()
|
defer mockSrv.Close()
|
||||||
|
|
||||||
p.linode.ToLinode().SetEndpoint(mockSrv.URL)
|
p.linode.ToLinode().SetEndpoint(mockSrv.URL)
|
||||||
|
|
||||||
err = p.CleanUp(domain, "", keyAuth)
|
err = p.CleanUp(domain, "", keyAuth)
|
||||||
|
@ -239,8 +251,9 @@ func TestDNSProvider_CleanUp(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDNSProvider_CleanUpNoDomain(t *testing.T) {
|
func TestDNSProvider_CleanUpNoDomain(t *testing.T) {
|
||||||
os.Setenv("LINODE_API_KEY", "testing")
|
|
||||||
defer restoreEnv()
|
defer restoreEnv()
|
||||||
|
os.Setenv("LINODE_API_KEY", "testing")
|
||||||
|
|
||||||
p, err := NewDNSProvider()
|
p, err := NewDNSProvider()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
@ -249,15 +262,17 @@ func TestDNSProvider_CleanUpNoDomain(t *testing.T) {
|
||||||
mockResponses := MockResponseMap{
|
mockResponses := MockResponseMap{
|
||||||
"domain.list": MockResponse{
|
"domain.list": MockResponse{
|
||||||
Response: []dns.Domain{
|
Response: []dns.Domain{
|
||||||
dns.Domain{
|
{
|
||||||
Domain: "foobar.com",
|
Domain: "foobar.com",
|
||||||
DomainID: 1234,
|
DomainID: 1234,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
mockSrv := newMockServer(t, mockResponses)
|
mockSrv := newMockServer(t, mockResponses)
|
||||||
defer mockSrv.Close()
|
defer mockSrv.Close()
|
||||||
|
|
||||||
p.linode.ToLinode().SetEndpoint(mockSrv.URL)
|
p.linode.ToLinode().SetEndpoint(mockSrv.URL)
|
||||||
|
|
||||||
err = p.CleanUp(domain, "", keyAuth)
|
err = p.CleanUp(domain, "", keyAuth)
|
||||||
|
@ -265,8 +280,9 @@ func TestDNSProvider_CleanUpNoDomain(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDNSProvider_CleanUpDeleteFailed(t *testing.T) {
|
func TestDNSProvider_CleanUpDeleteFailed(t *testing.T) {
|
||||||
os.Setenv("LINODE_API_KEY", "testing")
|
|
||||||
defer restoreEnv()
|
defer restoreEnv()
|
||||||
|
os.Setenv("LINODE_API_KEY", "testing")
|
||||||
|
|
||||||
p, err := NewDNSProvider()
|
p, err := NewDNSProvider()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
@ -275,7 +291,7 @@ func TestDNSProvider_CleanUpDeleteFailed(t *testing.T) {
|
||||||
mockResponses := MockResponseMap{
|
mockResponses := MockResponseMap{
|
||||||
"domain.list": MockResponse{
|
"domain.list": MockResponse{
|
||||||
Response: []dns.Domain{
|
Response: []dns.Domain{
|
||||||
dns.Domain{
|
{
|
||||||
Domain: domain,
|
Domain: domain,
|
||||||
DomainID: 1234,
|
DomainID: 1234,
|
||||||
},
|
},
|
||||||
|
@ -283,7 +299,7 @@ func TestDNSProvider_CleanUpDeleteFailed(t *testing.T) {
|
||||||
},
|
},
|
||||||
"domain.resource.list": MockResponse{
|
"domain.resource.list": MockResponse{
|
||||||
Response: []dns.Resource{
|
Response: []dns.Resource{
|
||||||
dns.Resource{
|
{
|
||||||
DomainID: 1234,
|
DomainID: 1234,
|
||||||
Name: "_acme-challenge",
|
Name: "_acme-challenge",
|
||||||
ResourceID: 1234,
|
ResourceID: 1234,
|
||||||
|
@ -295,23 +311,19 @@ func TestDNSProvider_CleanUpDeleteFailed(t *testing.T) {
|
||||||
"domain.resource.delete": MockResponse{
|
"domain.resource.delete": MockResponse{
|
||||||
Response: nil,
|
Response: nil,
|
||||||
Errors: []linode.ResponseError{
|
Errors: []linode.ResponseError{
|
||||||
linode.ResponseError{
|
{
|
||||||
Code: 1234,
|
Code: 1234,
|
||||||
Message: "Failed to delete domain resource",
|
Message: "Failed to delete domain resource",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
mockSrv := newMockServer(t, mockResponses)
|
mockSrv := newMockServer(t, mockResponses)
|
||||||
defer mockSrv.Close()
|
defer mockSrv.Close()
|
||||||
|
|
||||||
p.linode.ToLinode().SetEndpoint(mockSrv.URL)
|
p.linode.ToLinode().SetEndpoint(mockSrv.URL)
|
||||||
|
|
||||||
err = p.CleanUp(domain, "", keyAuth)
|
err = p.CleanUp(domain, "", keyAuth)
|
||||||
assert.EqualError(t, err, "Failed to delete domain resource")
|
assert.EqualError(t, err, "Failed to delete domain resource")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDNSProvider_CleanUpLive(t *testing.T) {
|
|
||||||
if !isTestLive {
|
|
||||||
t.Skip("Skipping live test")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -8,11 +8,11 @@ import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/xenolf/lego/acme"
|
"github.com/xenolf/lego/acme"
|
||||||
|
"github.com/xenolf/lego/platform/config/env"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Notes about namecheap's tool API:
|
// Notes about namecheap's tool API:
|
||||||
|
@ -48,9 +48,12 @@ type DNSProvider struct {
|
||||||
// Credentials must be passed in the environment variables: NAMECHEAP_API_USER
|
// Credentials must be passed in the environment variables: NAMECHEAP_API_USER
|
||||||
// and NAMECHEAP_API_KEY.
|
// and NAMECHEAP_API_KEY.
|
||||||
func NewDNSProvider() (*DNSProvider, error) {
|
func NewDNSProvider() (*DNSProvider, error) {
|
||||||
apiUser := os.Getenv("NAMECHEAP_API_USER")
|
values, err := env.Get("NAMECHEAP_API_USER", "NAMECHEAP_API_KEY")
|
||||||
apiKey := os.Getenv("NAMECHEAP_API_KEY")
|
if err != nil {
|
||||||
return NewDNSProviderCredentials(apiUser, apiKey)
|
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
|
// NewDNSProviderCredentials uses the supplied credentials to return a
|
||||||
|
@ -117,7 +120,7 @@ func getClientIP() (addr string, err error) {
|
||||||
return string(clientIP), nil
|
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.
|
// to lets-encrypt.
|
||||||
type challenge struct {
|
type challenge struct {
|
||||||
domain string
|
domain string
|
||||||
|
|
|
@ -241,24 +241,27 @@ func TestNamecheapDomainSplit(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
valid := true
|
test := test
|
||||||
ch, err := newChallenge(test.domain, "", tlds)
|
t.Run(test.domain, func(t *testing.T) {
|
||||||
if err != nil {
|
valid := true
|
||||||
valid = false
|
ch, err := newChallenge(test.domain, "", tlds)
|
||||||
}
|
if err != nil {
|
||||||
|
valid = false
|
||||||
|
}
|
||||||
|
|
||||||
if test.valid && !valid {
|
if test.valid && !valid {
|
||||||
t.Errorf("Expected '%s' to split", test.domain)
|
t.Errorf("Expected '%s' to split", test.domain)
|
||||||
} else if !test.valid && valid {
|
} else if !test.valid && valid {
|
||||||
t.Errorf("Expected '%s' to produce error", test.domain)
|
t.Errorf("Expected '%s' to produce error", test.domain)
|
||||||
}
|
}
|
||||||
|
|
||||||
if test.valid && valid {
|
if test.valid && valid {
|
||||||
assertEq(t, "domain", ch.domain, test.domain)
|
assertEq(t, "domain", ch.domain, test.domain)
|
||||||
assertEq(t, "tld", ch.tld, test.tld)
|
assertEq(t, "tld", ch.tld, test.tld)
|
||||||
assertEq(t, "sld", ch.sld, test.sld)
|
assertEq(t, "sld", ch.sld, test.sld)
|
||||||
assertEq(t, "host", ch.host, test.host)
|
assertEq(t, "host", ch.host, test.host)
|
||||||
}
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
|
|
||||||
"github.com/namedotcom/go/namecom"
|
"github.com/namedotcom/go/namecom"
|
||||||
"github.com/xenolf/lego/acme"
|
"github.com/xenolf/lego/acme"
|
||||||
|
"github.com/xenolf/lego/platform/config/env"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DNSProvider is an implementation of the acme.ChallengeProvider interface.
|
// DNSProvider is an implementation of the acme.ChallengeProvider interface.
|
||||||
|
@ -19,11 +20,13 @@ type DNSProvider struct {
|
||||||
// NewDNSProvider returns a DNSProvider instance configured for namedotcom.
|
// NewDNSProvider returns a DNSProvider instance configured for namedotcom.
|
||||||
// Credentials must be passed in the environment variables: NAMECOM_USERNAME and NAMECOM_API_TOKEN
|
// Credentials must be passed in the environment variables: NAMECOM_USERNAME and NAMECOM_API_TOKEN
|
||||||
func NewDNSProvider() (*DNSProvider, error) {
|
func NewDNSProvider() (*DNSProvider, error) {
|
||||||
username := os.Getenv("NAMECOM_USERNAME")
|
values, err := env.Get("NAMECOM_USERNAME", "NAMECOM_API_TOKEN")
|
||||||
apiToken := os.Getenv("NAMECOM_API_TOKEN")
|
if err != nil {
|
||||||
server := os.Getenv("NAMECOM_SERVER")
|
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
|
// 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)
|
_, err := c.client.CreateRecord(request)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("namedotcom API call failed: %v", err)
|
return fmt.Errorf("Name.com API call failed: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -27,7 +27,7 @@ func init() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLivenamedotcomPresent(t *testing.T) {
|
func TestLiveNamedotcomPresent(t *testing.T) {
|
||||||
if !namedotcomLiveTest {
|
if !namedotcomLiveTest {
|
||||||
t.Skip("skipping live test")
|
t.Skip("skipping live test")
|
||||||
}
|
}
|
||||||
|
@ -43,7 +43,7 @@ func TestLivenamedotcomPresent(t *testing.T) {
|
||||||
// Cleanup
|
// Cleanup
|
||||||
//
|
//
|
||||||
|
|
||||||
func TestLivenamedotcomCleanUp(t *testing.T) {
|
func TestLiveNamedotcomCleanUp(t *testing.T) {
|
||||||
if !namedotcomLiveTest {
|
if !namedotcomLiveTest {
|
||||||
t.Skip("skipping live test")
|
t.Skip("skipping live test")
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,10 +5,10 @@ package ns1
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/xenolf/lego/acme"
|
"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"
|
||||||
"gopkg.in/ns1/ns1-go.v2/rest/model/dns"
|
"gopkg.in/ns1/ns1-go.v2/rest/model/dns"
|
||||||
)
|
)
|
||||||
|
@ -21,11 +21,12 @@ type DNSProvider struct {
|
||||||
// NewDNSProvider returns a DNSProvider instance configured for NS1.
|
// NewDNSProvider returns a DNSProvider instance configured for NS1.
|
||||||
// Credentials must be passed in the environment variables: NS1_API_KEY.
|
// Credentials must be passed in the environment variables: NS1_API_KEY.
|
||||||
func NewDNSProvider() (*DNSProvider, error) {
|
func NewDNSProvider() (*DNSProvider, error) {
|
||||||
key := os.Getenv("NS1_API_KEY")
|
values, err := env.Get("NS1_API_KEY")
|
||||||
if key == "" {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("NS1 credentials missing")
|
return nil, fmt.Errorf("NS1: %v", err)
|
||||||
}
|
}
|
||||||
return NewDNSProviderCredentials(key)
|
|
||||||
|
return NewDNSProviderCredentials(values["NS1_API_KEY"])
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDNSProviderCredentials uses the supplied credentials to return a
|
// NewDNSProviderCredentials uses the supplied credentials to return a
|
||||||
|
|
|
@ -22,22 +22,24 @@ func init() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func restoreNS1Env() {
|
func restoreEnv() {
|
||||||
os.Setenv("NS1_API_KEY", apiKey)
|
os.Setenv("NS1_API_KEY", apiKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewDNSProviderValid(t *testing.T) {
|
func TestNewDNSProviderValid(t *testing.T) {
|
||||||
|
defer restoreEnv()
|
||||||
os.Setenv("NS1_API_KEY", "")
|
os.Setenv("NS1_API_KEY", "")
|
||||||
|
|
||||||
_, err := NewDNSProviderCredentials("123")
|
_, err := NewDNSProviderCredentials("123")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
restoreNS1Env()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewDNSProviderMissingCredErr(t *testing.T) {
|
func TestNewDNSProviderMissingCredErr(t *testing.T) {
|
||||||
|
defer restoreEnv()
|
||||||
os.Setenv("NS1_API_KEY", "")
|
os.Setenv("NS1_API_KEY", "")
|
||||||
|
|
||||||
_, err := NewDNSProvider()
|
_, err := NewDNSProvider()
|
||||||
assert.EqualError(t, err, "NS1 credentials missing")
|
assert.EqualError(t, err, "NS1: some credentials information are missing: NS1_API_KEY")
|
||||||
restoreNS1Env()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLivePresent(t *testing.T) {
|
func TestLivePresent(t *testing.T) {
|
||||||
|
|
|
@ -13,6 +13,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/xenolf/lego/acme"
|
"github.com/xenolf/lego/acme"
|
||||||
|
"github.com/xenolf/lego/platform/config/env"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DNSProvider is an implementation of the acme.ChallengeProvider interface that uses
|
// 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,
|
// Credentials must be passed in the environment variables: OTC_USER_NAME,
|
||||||
// OTC_DOMAIN_NAME, OTC_PASSWORD OTC_PROJECT_NAME and OTC_IDENTITY_ENDPOINT.
|
// OTC_DOMAIN_NAME, OTC_PASSWORD OTC_PROJECT_NAME and OTC_IDENTITY_ENDPOINT.
|
||||||
func NewDNSProvider() (*DNSProvider, error) {
|
func NewDNSProvider() (*DNSProvider, error) {
|
||||||
domainName := os.Getenv("OTC_DOMAIN_NAME")
|
values, err := env.Get("OTC_DOMAIN_NAME", "OTC_USER_NAME", "OTC_PASSWORD", "OTC_PROJECT_NAME")
|
||||||
userName := os.Getenv("OTC_USER_NAME")
|
if err != nil {
|
||||||
password := os.Getenv("OTC_PASSWORD")
|
return nil, fmt.Errorf("OTC: %v", err)
|
||||||
projectName := os.Getenv("OTC_PROJECT_NAME")
|
}
|
||||||
identityEndpoint := os.Getenv("OTC_IDENTITY_ENDPOINT")
|
|
||||||
return NewDNSProviderCredentials(domainName, userName, password, projectName, identityEndpoint)
|
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
|
// NewDNSProviderCredentials uses the supplied credentials to return a
|
||||||
|
|
|
@ -2,10 +2,11 @@ package otc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
"github.com/stretchr/testify/suite"
|
|
||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/suite"
|
||||||
)
|
)
|
||||||
|
|
||||||
type OTCDNSTestSuite struct {
|
type OTCDNSTestSuite struct {
|
||||||
|
@ -34,6 +35,8 @@ func (s *OTCDNSTestSuite) createDNSProvider() (*DNSProvider, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *OTCDNSTestSuite) TestOTCDNSLoginEnv() {
|
func (s *OTCDNSTestSuite) TestOTCDNSLoginEnv() {
|
||||||
|
defer os.Clearenv()
|
||||||
|
|
||||||
os.Setenv("OTC_DOMAIN_NAME", "unittest1")
|
os.Setenv("OTC_DOMAIN_NAME", "unittest1")
|
||||||
os.Setenv("OTC_USER_NAME", "unittest2")
|
os.Setenv("OTC_USER_NAME", "unittest2")
|
||||||
os.Setenv("OTC_PASSWORD", "unittest3")
|
os.Setenv("OTC_PASSWORD", "unittest3")
|
||||||
|
@ -53,15 +56,13 @@ func (s *OTCDNSTestSuite) TestOTCDNSLoginEnv() {
|
||||||
provider, err = NewDNSProvider()
|
provider, err = NewDNSProvider()
|
||||||
assert.Nil(s.T(), err)
|
assert.Nil(s.T(), err)
|
||||||
assert.Equal(s.T(), provider.identityEndpoint, "https://iam.eu-de.otc.t-systems.com:443/v3/auth/tokens")
|
assert.Equal(s.T(), provider.identityEndpoint, "https://iam.eu-de.otc.t-systems.com:443/v3/auth/tokens")
|
||||||
|
|
||||||
os.Clearenv()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *OTCDNSTestSuite) TestOTCDNSLoginEnvEmpty() {
|
func (s *OTCDNSTestSuite) TestOTCDNSLoginEnvEmpty() {
|
||||||
_, err := NewDNSProvider()
|
defer os.Clearenv()
|
||||||
assert.Equal(s.T(), "OTC credentials missing", err.Error())
|
|
||||||
|
|
||||||
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() {
|
func (s *OTCDNSTestSuite) TestOTCDNSLogin() {
|
||||||
|
|
|
@ -4,12 +4,12 @@ package ovh
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/ovh/go-ovh/ovh"
|
"github.com/ovh/go-ovh/ovh"
|
||||||
"github.com/xenolf/lego/acme"
|
"github.com/xenolf/lego/acme"
|
||||||
|
"github.com/xenolf/lego/platform/config/env"
|
||||||
)
|
)
|
||||||
|
|
||||||
// OVH API reference: https://eu.api.ovh.com/
|
// OVH API reference: https://eu.api.ovh.com/
|
||||||
|
@ -30,11 +30,17 @@ type DNSProvider struct {
|
||||||
// OVH_APPLICATION_SECRET
|
// OVH_APPLICATION_SECRET
|
||||||
// OVH_CONSUMER_KEY
|
// OVH_CONSUMER_KEY
|
||||||
func NewDNSProvider() (*DNSProvider, error) {
|
func NewDNSProvider() (*DNSProvider, error) {
|
||||||
apiEndpoint := os.Getenv("OVH_ENDPOINT")
|
values, err := env.Get("OVH_ENDPOINT", "OVH_APPLICATION_KEY", "OVH_APPLICATION_SECRET", "OVH_CONSUMER_KEY")
|
||||||
applicationKey := os.Getenv("OVH_APPLICATION_KEY")
|
if err != nil {
|
||||||
applicationSecret := os.Getenv("OVH_APPLICATION_SECRET")
|
return nil, fmt.Errorf("OVH: %v", err)
|
||||||
consumerKey := os.Getenv("OVH_CONSUMER_KEY")
|
}
|
||||||
return NewDNSProviderCredentials(apiEndpoint, applicationKey, applicationSecret, consumerKey)
|
|
||||||
|
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
|
// NewDNSProviderCredentials uses the supplied credentials to return a
|
||||||
|
|
|
@ -33,47 +33,88 @@ func restoreEnv() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewDNSProviderValidEnv(t *testing.T) {
|
func TestNewDNSProviderValidEnv(t *testing.T) {
|
||||||
|
defer restoreEnv()
|
||||||
os.Setenv("OVH_ENDPOINT", "ovh-eu")
|
os.Setenv("OVH_ENDPOINT", "ovh-eu")
|
||||||
os.Setenv("OVH_APPLICATION_KEY", "1234")
|
os.Setenv("OVH_APPLICATION_KEY", "1234")
|
||||||
os.Setenv("OVH_APPLICATION_SECRET", "5678")
|
os.Setenv("OVH_APPLICATION_SECRET", "5678")
|
||||||
os.Setenv("OVH_CONSUMER_KEY", "abcde")
|
os.Setenv("OVH_CONSUMER_KEY", "abcde")
|
||||||
defer restoreEnv()
|
|
||||||
_, err := NewDNSProvider()
|
_, err := NewDNSProvider()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewDNSProviderMissingCredErr(t *testing.T) {
|
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()
|
defer restoreEnv()
|
||||||
_, err := NewDNSProvider()
|
|
||||||
assert.EqualError(t, err, "OVH credentials missing")
|
|
||||||
|
|
||||||
os.Setenv("OVH_ENDPOINT", "ovh-eu")
|
testCases := []struct {
|
||||||
os.Setenv("OVH_APPLICATION_KEY", "")
|
desc string
|
||||||
os.Setenv("OVH_APPLICATION_SECRET", "5678")
|
envVars map[string]string
|
||||||
os.Setenv("OVH_CONSUMER_KEY", "abcde")
|
expected string
|
||||||
defer restoreEnv()
|
}{
|
||||||
_, err = NewDNSProvider()
|
{
|
||||||
assert.EqualError(t, err, "OVH credentials missing")
|
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",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
os.Setenv("OVH_ENDPOINT", "ovh-eu")
|
for _, test := range testCases {
|
||||||
os.Setenv("OVH_APPLICATION_KEY", "1234")
|
test := test
|
||||||
os.Setenv("OVH_APPLICATION_SECRET", "")
|
t.Run(test.desc, func(t *testing.T) {
|
||||||
os.Setenv("OVH_CONSUMER_KEY", "abcde")
|
|
||||||
defer restoreEnv()
|
|
||||||
_, err = NewDNSProvider()
|
|
||||||
assert.EqualError(t, err, "OVH credentials missing")
|
|
||||||
|
|
||||||
os.Setenv("OVH_ENDPOINT", "ovh-eu")
|
for key, value := range test.envVars {
|
||||||
os.Setenv("OVH_APPLICATION_KEY", "1234")
|
os.Setenv(key, value)
|
||||||
os.Setenv("OVH_APPLICATION_SECRET", "5678")
|
}
|
||||||
os.Setenv("OVH_CONSUMER_KEY", "")
|
|
||||||
defer restoreEnv()
|
_, err := NewDNSProvider()
|
||||||
_, err = NewDNSProvider()
|
assert.EqualError(t, err, test.expected)
|
||||||
assert.EqualError(t, err, "OVH credentials missing")
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLivePresent(t *testing.T) {
|
func TestLivePresent(t *testing.T) {
|
||||||
|
|
|
@ -9,12 +9,12 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/xenolf/lego/acme"
|
"github.com/xenolf/lego/acme"
|
||||||
|
"github.com/xenolf/lego/platform/config/env"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DNSProvider is an implementation of the acme.ChallengeProvider interface
|
// DNSProvider is an implementation of the acme.ChallengeProvider interface
|
||||||
|
@ -28,13 +28,17 @@ type DNSProvider struct {
|
||||||
// Credentials must be passed in the environment variable:
|
// Credentials must be passed in the environment variable:
|
||||||
// PDNS_API_URL and PDNS_API_KEY.
|
// PDNS_API_URL and PDNS_API_KEY.
|
||||||
func NewDNSProvider() (*DNSProvider, error) {
|
func NewDNSProvider() (*DNSProvider, error) {
|
||||||
key := os.Getenv("PDNS_API_KEY")
|
values, err := env.Get("PDNS_API_KEY", "PDNS_API_URL")
|
||||||
hostURL, err := url.Parse(os.Getenv("PDNS_API_URL"))
|
|
||||||
if err != nil {
|
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
|
// NewDNSProviderCredentials uses the supplied credentials to return a
|
||||||
|
|
|
@ -26,42 +26,46 @@ func init() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func restorePdnsEnv() {
|
func restoreEnv() {
|
||||||
os.Setenv("PDNS_API_URL", pdnsURLStr)
|
os.Setenv("PDNS_API_URL", pdnsURLStr)
|
||||||
os.Setenv("PDNS_API_KEY", pdnsAPIKey)
|
os.Setenv("PDNS_API_KEY", pdnsAPIKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewDNSProviderValid(t *testing.T) {
|
func TestNewDNSProviderValid(t *testing.T) {
|
||||||
|
defer restoreEnv()
|
||||||
os.Setenv("PDNS_API_URL", "")
|
os.Setenv("PDNS_API_URL", "")
|
||||||
os.Setenv("PDNS_API_KEY", "")
|
os.Setenv("PDNS_API_KEY", "")
|
||||||
|
|
||||||
tmpURL, _ := url.Parse("http://localhost:8081")
|
tmpURL, _ := url.Parse("http://localhost:8081")
|
||||||
_, err := NewDNSProviderCredentials(tmpURL, "123")
|
_, err := NewDNSProviderCredentials(tmpURL, "123")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
restorePdnsEnv()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewDNSProviderValidEnv(t *testing.T) {
|
func TestNewDNSProviderValidEnv(t *testing.T) {
|
||||||
|
defer restoreEnv()
|
||||||
os.Setenv("PDNS_API_URL", "http://localhost:8081")
|
os.Setenv("PDNS_API_URL", "http://localhost:8081")
|
||||||
os.Setenv("PDNS_API_KEY", "123")
|
os.Setenv("PDNS_API_KEY", "123")
|
||||||
|
|
||||||
_, err := NewDNSProvider()
|
_, err := NewDNSProvider()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
restorePdnsEnv()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewDNSProviderMissingHostErr(t *testing.T) {
|
func TestNewDNSProviderMissingHostErr(t *testing.T) {
|
||||||
|
defer restoreEnv()
|
||||||
os.Setenv("PDNS_API_URL", "")
|
os.Setenv("PDNS_API_URL", "")
|
||||||
os.Setenv("PDNS_API_KEY", "123")
|
os.Setenv("PDNS_API_KEY", "123")
|
||||||
|
|
||||||
_, err := NewDNSProvider()
|
_, err := NewDNSProvider()
|
||||||
assert.EqualError(t, err, "PDNS API URL missing")
|
assert.EqualError(t, err, "PDNS: some credentials information are missing: PDNS_API_URL")
|
||||||
restorePdnsEnv()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewDNSProviderMissingKeyErr(t *testing.T) {
|
func TestNewDNSProviderMissingKeyErr(t *testing.T) {
|
||||||
|
defer restoreEnv()
|
||||||
os.Setenv("PDNS_API_URL", pdnsURLStr)
|
os.Setenv("PDNS_API_URL", pdnsURLStr)
|
||||||
os.Setenv("PDNS_API_KEY", "")
|
os.Setenv("PDNS_API_KEY", "")
|
||||||
|
|
||||||
_, err := NewDNSProvider()
|
_, err := NewDNSProvider()
|
||||||
assert.EqualError(t, err, "PDNS API key missing")
|
assert.EqualError(t, err, "PDNS: some credentials information are missing: PDNS_API_KEY,PDNS_API_URL")
|
||||||
restorePdnsEnv()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPdnsPresentAndCleanup(t *testing.T) {
|
func TestPdnsPresentAndCleanup(t *testing.T) {
|
||||||
|
|
|
@ -8,10 +8,10 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/xenolf/lego/acme"
|
"github.com/xenolf/lego/acme"
|
||||||
|
"github.com/xenolf/lego/platform/config/env"
|
||||||
)
|
)
|
||||||
|
|
||||||
// rackspaceAPIURL represents the Identity API endpoint to call
|
// 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
|
// Credentials must be passed in the environment variables: RACKSPACE_USER
|
||||||
// and RACKSPACE_API_KEY.
|
// and RACKSPACE_API_KEY.
|
||||||
func NewDNSProvider() (*DNSProvider, error) {
|
func NewDNSProvider() (*DNSProvider, error) {
|
||||||
user := os.Getenv("RACKSPACE_USER")
|
values, err := env.Get("RACKSPACE_USER", "RACKSPACE_API_KEY")
|
||||||
key := os.Getenv("RACKSPACE_API_KEY")
|
if err != nil {
|
||||||
return NewDNSProviderCredentials(user, key)
|
return nil, fmt.Errorf("Rackspace: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return NewDNSProviderCredentials(values["RACKSPACE_USER"], values["RACKSPACE_API_KEY"])
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDNSProviderCredentials uses the supplied credentials to return a
|
// NewDNSProviderCredentials uses the supplied credentials to return a
|
||||||
|
|
|
@ -38,6 +38,7 @@ func NewDNSProvider() (*DNSProvider, error) {
|
||||||
tsigKey := os.Getenv("RFC2136_TSIG_KEY")
|
tsigKey := os.Getenv("RFC2136_TSIG_KEY")
|
||||||
tsigSecret := os.Getenv("RFC2136_TSIG_SECRET")
|
tsigSecret := os.Getenv("RFC2136_TSIG_SECRET")
|
||||||
timeout := os.Getenv("RFC2136_TIMEOUT")
|
timeout := os.Getenv("RFC2136_TIMEOUT")
|
||||||
|
|
||||||
return NewDNSProviderCredentials(nameserver, tsigAlgorithm, tsigKey, tsigSecret, timeout)
|
return NewDNSProviderCredentials(nameserver, tsigAlgorithm, tsigKey, tsigSecret, timeout)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,13 +59,14 @@ func NewDNSProviderCredentials(nameserver, tsigAlgorithm, tsigKey, tsigSecret, t
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
d := &DNSProvider{
|
|
||||||
nameserver: nameserver,
|
d := &DNSProvider{nameserver: nameserver}
|
||||||
}
|
|
||||||
if tsigAlgorithm == "" {
|
if tsigAlgorithm == "" {
|
||||||
tsigAlgorithm = dns.HmacMD5
|
tsigAlgorithm = dns.HmacMD5
|
||||||
}
|
}
|
||||||
d.tsigAlgorithm = tsigAlgorithm
|
d.tsigAlgorithm = tsigAlgorithm
|
||||||
|
|
||||||
if len(tsigKey) > 0 && len(tsigSecret) > 0 {
|
if len(tsigKey) > 0 && len(tsigSecret) > 0 {
|
||||||
d.tsigKey = tsigKey
|
d.tsigKey = tsigKey
|
||||||
d.tsigSecret = tsigSecret
|
d.tsigSecret = tsigSecret
|
||||||
|
|
|
@ -10,6 +10,8 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/miekg/dns"
|
"github.com/miekg/dns"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
"github.com/xenolf/lego/acme"
|
"github.com/xenolf/lego/acme"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -32,22 +34,20 @@ func TestRFC2136CanaryLocalTestServer(t *testing.T) {
|
||||||
defer dns.HandleRemove("example.com.")
|
defer dns.HandleRemove("example.com.")
|
||||||
|
|
||||||
server, addrstr, err := runLocalDNSTestServer("127.0.0.1:0", false)
|
server, addrstr, err := runLocalDNSTestServer("127.0.0.1:0", false)
|
||||||
if err != nil {
|
require.NoError(t, err, "Failed to start test server")
|
||||||
t.Fatalf("Failed to start test server: %v", err)
|
|
||||||
}
|
|
||||||
defer server.Shutdown()
|
defer server.Shutdown()
|
||||||
|
|
||||||
c := new(dns.Client)
|
c := new(dns.Client)
|
||||||
m := new(dns.Msg)
|
m := new(dns.Msg)
|
||||||
|
|
||||||
m.SetQuestion("example.com.", dns.TypeTXT)
|
m.SetQuestion("example.com.", dns.TypeTXT)
|
||||||
|
|
||||||
r, _, err := c.Exchange(m, addrstr)
|
r, _, err := c.Exchange(m, addrstr)
|
||||||
if err != nil || len(r.Extra) == 0 {
|
require.NoError(t, err, "Failed to communicate with test server")
|
||||||
t.Fatalf("Failed to communicate with test server: %v", err)
|
assert.Len(t, r.Extra, 1, "Failed to communicate with test server")
|
||||||
}
|
|
||||||
txt := r.Extra[0].(*dns.TXT).Txt[0]
|
txt := r.Extra[0].(*dns.TXT).Txt[0]
|
||||||
if txt != "Hello world" {
|
assert.Equal(t, "Hello world", txt)
|
||||||
t.Error("Expected test server to return 'Hello world' but got: ", txt)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRFC2136ServerSuccess(t *testing.T) {
|
func TestRFC2136ServerSuccess(t *testing.T) {
|
||||||
|
@ -56,18 +56,14 @@ func TestRFC2136ServerSuccess(t *testing.T) {
|
||||||
defer dns.HandleRemove(rfc2136TestZone)
|
defer dns.HandleRemove(rfc2136TestZone)
|
||||||
|
|
||||||
server, addrstr, err := runLocalDNSTestServer("127.0.0.1:0", false)
|
server, addrstr, err := runLocalDNSTestServer("127.0.0.1:0", false)
|
||||||
if err != nil {
|
require.NoError(t, err, "Failed to start test server")
|
||||||
t.Fatalf("Failed to start test server: %v", err)
|
|
||||||
}
|
|
||||||
defer server.Shutdown()
|
defer server.Shutdown()
|
||||||
|
|
||||||
provider, err := NewDNSProviderCredentials(addrstr, "", "", "", "")
|
provider, err := NewDNSProviderCredentials(addrstr, "", "", "", "")
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
t.Fatalf("Expected NewDNSProviderCredentials() to return no error but the error was -> %v", err)
|
|
||||||
}
|
err = provider.Present(rfc2136TestDomain, "", rfc2136TestKeyAuth)
|
||||||
if err := provider.Present(rfc2136TestDomain, "", rfc2136TestKeyAuth); err != nil {
|
require.NoError(t, err)
|
||||||
t.Errorf("Expected Present() to return no error but the error was -> %v", err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRFC2136ServerError(t *testing.T) {
|
func TestRFC2136ServerError(t *testing.T) {
|
||||||
|
@ -76,19 +72,16 @@ func TestRFC2136ServerError(t *testing.T) {
|
||||||
defer dns.HandleRemove(rfc2136TestZone)
|
defer dns.HandleRemove(rfc2136TestZone)
|
||||||
|
|
||||||
server, addrstr, err := runLocalDNSTestServer("127.0.0.1:0", false)
|
server, addrstr, err := runLocalDNSTestServer("127.0.0.1:0", false)
|
||||||
if err != nil {
|
require.NoError(t, err, "Failed to start test server")
|
||||||
t.Fatalf("Failed to start test server: %v", err)
|
|
||||||
}
|
|
||||||
defer server.Shutdown()
|
defer server.Shutdown()
|
||||||
|
|
||||||
provider, err := NewDNSProviderCredentials(addrstr, "", "", "", "")
|
provider, err := NewDNSProviderCredentials(addrstr, "", "", "", "")
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
t.Fatalf("Expected NewDNSProviderCredentials() to return no error but the error was -> %v", err)
|
|
||||||
}
|
err = provider.Present(rfc2136TestDomain, "", rfc2136TestKeyAuth)
|
||||||
if err := provider.Present(rfc2136TestDomain, "", rfc2136TestKeyAuth); err == nil {
|
require.Error(t, err)
|
||||||
t.Errorf("Expected Present() to return an error but it did not.")
|
if !strings.Contains(err.Error(), "NOTZONE") {
|
||||||
} else 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)
|
||||||
t.Errorf("Expected Present() to return an error with the 'NOTZONE' rcode string but it did not.")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,18 +91,14 @@ func TestRFC2136TsigClient(t *testing.T) {
|
||||||
defer dns.HandleRemove(rfc2136TestZone)
|
defer dns.HandleRemove(rfc2136TestZone)
|
||||||
|
|
||||||
server, addrstr, err := runLocalDNSTestServer("127.0.0.1:0", true)
|
server, addrstr, err := runLocalDNSTestServer("127.0.0.1:0", true)
|
||||||
if err != nil {
|
require.NoError(t, err, "Failed to start test server")
|
||||||
t.Fatalf("Failed to start test server: %v", err)
|
|
||||||
}
|
|
||||||
defer server.Shutdown()
|
defer server.Shutdown()
|
||||||
|
|
||||||
provider, err := NewDNSProviderCredentials(addrstr, "", rfc2136TestTsigKey, rfc2136TestTsigSecret, "")
|
provider, err := NewDNSProviderCredentials(addrstr, "", rfc2136TestTsigKey, rfc2136TestTsigSecret, "")
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
t.Fatalf("Expected NewDNSProviderCredentials() to return no error but the error was -> %v", err)
|
|
||||||
}
|
err = provider.Present(rfc2136TestDomain, "", rfc2136TestKeyAuth)
|
||||||
if err := provider.Present(rfc2136TestDomain, "", rfc2136TestKeyAuth); err != nil {
|
require.NoError(t, err)
|
||||||
t.Errorf("Expected Present() to return no error but the error was -> %v", err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRFC2136ValidUpdatePacket(t *testing.T) {
|
func TestRFC2136ValidUpdatePacket(t *testing.T) {
|
||||||
|
@ -118,9 +107,7 @@ func TestRFC2136ValidUpdatePacket(t *testing.T) {
|
||||||
defer dns.HandleRemove(rfc2136TestZone)
|
defer dns.HandleRemove(rfc2136TestZone)
|
||||||
|
|
||||||
server, addrstr, err := runLocalDNSTestServer("127.0.0.1:0", false)
|
server, addrstr, err := runLocalDNSTestServer("127.0.0.1:0", false)
|
||||||
if err != nil {
|
require.NoError(t, err, "Failed to start test server")
|
||||||
t.Fatalf("Failed to start test server: %v", err)
|
|
||||||
}
|
|
||||||
defer server.Shutdown()
|
defer server.Shutdown()
|
||||||
|
|
||||||
txtRR, _ := dns.NewRR(fmt.Sprintf("%s %d IN TXT %s", rfc2136TestFqdn, rfc2136TestTTL, rfc2136TestValue))
|
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.RemoveRRset(rrs)
|
||||||
m.Insert(rrs)
|
m.Insert(rrs)
|
||||||
expectstr := m.String()
|
expectstr := m.String()
|
||||||
|
|
||||||
expect, err := m.Pack()
|
expect, err := m.Pack()
|
||||||
if err != nil {
|
require.NoError(t, err, "error packing")
|
||||||
t.Fatalf("Error packing expect msg: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
provider, err := NewDNSProviderCredentials(addrstr, "", "", "", "")
|
provider, err := NewDNSProviderCredentials(addrstr, "", "", "", "")
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
t.Fatalf("Expected NewDNSProviderCredentials() to return no error but the error was -> %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := provider.Present(rfc2136TestDomain, "", "1234d=="); err != nil {
|
err = provider.Present(rfc2136TestDomain, "", "1234d==")
|
||||||
t.Errorf("Expected Present() to return no error but the error was -> %v", err)
|
require.NoError(t, err)
|
||||||
}
|
|
||||||
|
|
||||||
rcvMsg := <-reqChan
|
rcvMsg := <-reqChan
|
||||||
rcvMsg.Id = m.Id
|
rcvMsg.Id = m.Id
|
||||||
|
|
||||||
actual, err := rcvMsg.Pack()
|
actual, err := rcvMsg.Pack()
|
||||||
if err != nil {
|
require.NoError(t, err, "error packing")
|
||||||
t.Fatalf("Error packing actual msg: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !bytes.Equal(actual, expect) {
|
if !bytes.Equal(actual, expect) {
|
||||||
tmp := new(dns.Msg)
|
tmp := new(dns.Msg)
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"github.com/aws/aws-sdk-go/aws"
|
"github.com/aws/aws-sdk-go/aws"
|
||||||
"github.com/aws/aws-sdk-go/aws/session"
|
"github.com/aws/aws-sdk-go/aws/session"
|
||||||
"github.com/aws/aws-sdk-go/service/route53"
|
"github.com/aws/aws-sdk-go/service/route53"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestRoute53TTL(t *testing.T) {
|
func TestRoute53TTL(t *testing.T) {
|
||||||
|
@ -17,14 +18,10 @@ func TestRoute53TTL(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
provider, err := NewDNSProvider()
|
provider, err := NewDNSProvider()
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = provider.Present(m["route53Domain"], "foo", "bar")
|
err = provider.Present(m["route53Domain"], "foo", "bar")
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// we need a separate R53 client here as the one in the DNS provider is
|
// we need a separate R53 client here as the one in the DNS provider is
|
||||||
// unexported.
|
// unexported.
|
||||||
|
|
|
@ -26,7 +26,7 @@ func init() {
|
||||||
route53Zone = os.Getenv("AWS_HOSTED_ZONE_ID")
|
route53Zone = os.Getenv("AWS_HOSTED_ZONE_ID")
|
||||||
}
|
}
|
||||||
|
|
||||||
func restoreRoute53Env() {
|
func restoreEnv() {
|
||||||
os.Setenv("AWS_ACCESS_KEY_ID", route53Key)
|
os.Setenv("AWS_ACCESS_KEY_ID", route53Key)
|
||||||
os.Setenv("AWS_SECRET_ACCESS_KEY", route53Secret)
|
os.Setenv("AWS_SECRET_ACCESS_KEY", route53Secret)
|
||||||
os.Setenv("AWS_REGION", route53Region)
|
os.Setenv("AWS_REGION", route53Region)
|
||||||
|
@ -46,6 +46,7 @@ func makeRoute53Provider(ts *httptest.Server) *DNSProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCredentialsFromEnv(t *testing.T) {
|
func TestCredentialsFromEnv(t *testing.T) {
|
||||||
|
defer restoreEnv()
|
||||||
os.Setenv("AWS_ACCESS_KEY_ID", "123")
|
os.Setenv("AWS_ACCESS_KEY_ID", "123")
|
||||||
os.Setenv("AWS_SECRET_ACCESS_KEY", "123")
|
os.Setenv("AWS_SECRET_ACCESS_KEY", "123")
|
||||||
os.Setenv("AWS_REGION", "us-east-1")
|
os.Setenv("AWS_REGION", "us-east-1")
|
||||||
|
@ -57,23 +58,20 @@ func TestCredentialsFromEnv(t *testing.T) {
|
||||||
sess := session.New(config)
|
sess := session.New(config)
|
||||||
_, err := sess.Config.Credentials.Get()
|
_, err := sess.Config.Credentials.Get()
|
||||||
assert.NoError(t, err, "Expected credentials to be set from environment")
|
assert.NoError(t, err, "Expected credentials to be set from environment")
|
||||||
|
|
||||||
restoreRoute53Env()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRegionFromEnv(t *testing.T) {
|
func TestRegionFromEnv(t *testing.T) {
|
||||||
|
defer restoreEnv()
|
||||||
os.Setenv("AWS_REGION", "us-east-1")
|
os.Setenv("AWS_REGION", "us-east-1")
|
||||||
|
|
||||||
sess := session.New(aws.NewConfig())
|
sess := session.New(aws.NewConfig())
|
||||||
assert.Equal(t, "us-east-1", aws.StringValue(sess.Config.Region), "Expected Region to be set from environment")
|
assert.Equal(t, "us-east-1", aws.StringValue(sess.Config.Region), "Expected Region to be set from environment")
|
||||||
|
|
||||||
restoreRoute53Env()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHostedZoneIDFromEnv(t *testing.T) {
|
func TestHostedZoneIDFromEnv(t *testing.T) {
|
||||||
const testZoneID = "testzoneid"
|
defer restoreEnv()
|
||||||
|
|
||||||
defer restoreRoute53Env()
|
const testZoneID = "testzoneid"
|
||||||
os.Setenv("AWS_HOSTED_ZONE_ID", testZoneID)
|
os.Setenv("AWS_HOSTED_ZONE_ID", testZoneID)
|
||||||
|
|
||||||
provider, err := NewDNSProvider()
|
provider, err := NewDNSProvider()
|
||||||
|
|
|
@ -5,11 +5,11 @@ package vultr
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
vultr "github.com/JamesClonk/vultr/lib"
|
vultr "github.com/JamesClonk/vultr/lib"
|
||||||
"github.com/xenolf/lego/acme"
|
"github.com/xenolf/lego/acme"
|
||||||
|
"github.com/xenolf/lego/platform/config/env"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DNSProvider is an implementation of the acme.ChallengeProvider interface.
|
// 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.
|
// NewDNSProvider returns a DNSProvider instance with a configured Vultr client.
|
||||||
// Authentication uses the VULTR_API_KEY environment variable.
|
// Authentication uses the VULTR_API_KEY environment variable.
|
||||||
func NewDNSProvider() (*DNSProvider, error) {
|
func NewDNSProvider() (*DNSProvider, error) {
|
||||||
apiKey := os.Getenv("VULTR_API_KEY")
|
values, err := env.Get("VULTR_API_KEY")
|
||||||
return NewDNSProviderCredentials(apiKey)
|
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
|
// NewDNSProviderCredentials uses the supplied credentials to return a DNSProvider
|
||||||
|
|
|
@ -25,17 +25,19 @@ func restoreEnv() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewDNSProviderValidEnv(t *testing.T) {
|
func TestNewDNSProviderValidEnv(t *testing.T) {
|
||||||
os.Setenv("VULTR_API_KEY", "123")
|
|
||||||
defer restoreEnv()
|
defer restoreEnv()
|
||||||
|
os.Setenv("VULTR_API_KEY", "123")
|
||||||
|
|
||||||
_, err := NewDNSProvider()
|
_, err := NewDNSProvider()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewDNSProviderMissingCredErr(t *testing.T) {
|
func TestNewDNSProviderMissingCredErr(t *testing.T) {
|
||||||
os.Setenv("VULTR_API_KEY", "")
|
|
||||||
defer restoreEnv()
|
defer restoreEnv()
|
||||||
|
os.Setenv("VULTR_API_KEY", "")
|
||||||
|
|
||||||
_, err := NewDNSProvider()
|
_, 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) {
|
func TestLivePresent(t *testing.T) {
|
||||||
|
|
Loading…
Reference in a new issue