forked from TrueCloudLab/lego
Route53: Make it possible to configure from the env (#603)
This commit is contained in:
parent
725b6b816a
commit
ef7cd04002
5 changed files with 134 additions and 41 deletions
12
platform/config/env/env.go
vendored
12
platform/config/env/env.go
vendored
|
@ -3,6 +3,7 @@ package env
|
|||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
|
@ -25,3 +26,14 @@ func Get(names ...string) (map[string]string, error) {
|
|||
|
||||
return values, nil
|
||||
}
|
||||
|
||||
// GetOrDefaultInt returns the given environment variable value as an integer.
|
||||
// Returns the default if the envvar cannot be coopered to an int, or is not found.
|
||||
func GetOrDefaultInt(envVar string, defaultValue int) int {
|
||||
v, err := strconv.Atoi(os.Getenv(envVar))
|
||||
if err != nil {
|
||||
return defaultValue
|
||||
}
|
||||
|
||||
return v
|
||||
}
|
||||
|
|
56
platform/config/env/env_test.go
vendored
Normal file
56
platform/config/env/env_test.go
vendored
Normal file
|
@ -0,0 +1,56 @@
|
|||
package env
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func Test_GetOrDefaultInt(t *testing.T) {
|
||||
testCases := []struct {
|
||||
desc string
|
||||
envValue string
|
||||
defaultValue int
|
||||
expected int
|
||||
}{
|
||||
{
|
||||
desc: "valid value",
|
||||
envValue: "100",
|
||||
defaultValue: 2,
|
||||
expected: 100,
|
||||
},
|
||||
{
|
||||
desc: "invalid content, use default value",
|
||||
envValue: "abc123",
|
||||
defaultValue: 2,
|
||||
expected: 2,
|
||||
},
|
||||
{
|
||||
desc: "valid negative value",
|
||||
envValue: "-111",
|
||||
defaultValue: 2,
|
||||
expected: -111,
|
||||
},
|
||||
{
|
||||
desc: "float: invalid type, use default value",
|
||||
envValue: "1.11",
|
||||
defaultValue: 2,
|
||||
expected: 2,
|
||||
},
|
||||
}
|
||||
|
||||
const key = "LEGO_ENV_TC"
|
||||
|
||||
for _, test := range testCases {
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
defer os.Unsetenv(key)
|
||||
err := os.Setenv(key, test.envValue)
|
||||
require.NoError(t, err)
|
||||
|
||||
result := GetOrDefaultInt(key, test.defaultValue)
|
||||
assert.Equal(t, test.expected, result)
|
||||
})
|
||||
}
|
||||
}
|
|
@ -16,6 +16,7 @@ import (
|
|||
"github.com/aws/aws-sdk-go/aws/session"
|
||||
"github.com/aws/aws-sdk-go/service/route53"
|
||||
"github.com/xenolf/lego/acme"
|
||||
"github.com/xenolf/lego/platform/config/env"
|
||||
)
|
||||
|
||||
// Config is used to configure the creation of the DNSProvider
|
||||
|
@ -29,11 +30,13 @@ type Config struct {
|
|||
|
||||
// NewDefaultConfig returns a default configuration for the DNSProvider
|
||||
func NewDefaultConfig() *Config {
|
||||
propagationMins := env.GetOrDefaultInt("AWS_PROPAGATION_TIMEOUT", 2)
|
||||
intervalSecs := env.GetOrDefaultInt("AWS_POLLING_INTERVAL", 4)
|
||||
return &Config{
|
||||
MaxRetries: 5,
|
||||
TTL: 10,
|
||||
PropagationTimeout: time.Minute * 2,
|
||||
PollingInterval: time.Second * 4,
|
||||
MaxRetries: env.GetOrDefaultInt("AWS_MAX_RETRIES", 5),
|
||||
TTL: env.GetOrDefaultInt("AWS_TTL", 10),
|
||||
PropagationTimeout: time.Minute * time.Duration(propagationMins),
|
||||
PollingInterval: time.Second * time.Duration(intervalSecs),
|
||||
HostedZoneID: os.Getenv("AWS_HOSTED_ZONE_ID"),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,18 +1,17 @@
|
|||
package route53
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/session"
|
||||
"github.com/aws/aws-sdk-go/service/route53"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/xenolf/lego/platform/config/env"
|
||||
)
|
||||
|
||||
func TestRoute53TTL(t *testing.T) {
|
||||
m, err := testGetAndPreCheck()
|
||||
config, err := env.Get("AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY", "AWS_REGION", "R53_DOMAIN")
|
||||
if err != nil {
|
||||
t.Skip(err.Error())
|
||||
}
|
||||
|
@ -20,16 +19,16 @@ func TestRoute53TTL(t *testing.T) {
|
|||
provider, err := NewDNSProvider()
|
||||
require.NoError(t, err)
|
||||
|
||||
err = provider.Present(m["route53Domain"], "foo", "bar")
|
||||
err = provider.Present(config["R53_DOMAIN"], "foo", "bar")
|
||||
require.NoError(t, err)
|
||||
|
||||
// we need a separate R53 client here as the one in the DNS provider is
|
||||
// unexported.
|
||||
fqdn := "_acme-challenge." + m["route53Domain"] + "."
|
||||
fqdn := "_acme-challenge." + config["R53_DOMAIN"] + "."
|
||||
svc := route53.New(session.New())
|
||||
zoneID, err := provider.getHostedZoneID(fqdn)
|
||||
if err != nil {
|
||||
provider.CleanUp(m["route53Domain"], "foo", "bar")
|
||||
provider.CleanUp(config["R53_DOMAIN"], "foo", "bar")
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
|
@ -38,32 +37,17 @@ func TestRoute53TTL(t *testing.T) {
|
|||
}
|
||||
resp, err := svc.ListResourceRecordSets(params)
|
||||
if err != nil {
|
||||
provider.CleanUp(m["route53Domain"], "foo", "bar")
|
||||
provider.CleanUp(config["R53_DOMAIN"], "foo", "bar")
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
for _, v := range resp.ResourceRecordSets {
|
||||
if aws.StringValue(v.Name) == fqdn && aws.StringValue(v.Type) == "TXT" && aws.Int64Value(v.TTL) == 10 {
|
||||
provider.CleanUp(m["route53Domain"], "foo", "bar")
|
||||
provider.CleanUp(config["R53_DOMAIN"], "foo", "bar")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
provider.CleanUp(m["route53Domain"], "foo", "bar")
|
||||
t.Fatalf("Could not find a TXT record for _acme-challenge.%s with a TTL of 10", m["route53Domain"])
|
||||
}
|
||||
|
||||
func testGetAndPreCheck() (map[string]string, error) {
|
||||
m := map[string]string{
|
||||
"route53Key": os.Getenv("AWS_ACCESS_KEY_ID"),
|
||||
"route53Secret": os.Getenv("AWS_SECRET_ACCESS_KEY"),
|
||||
"route53Region": os.Getenv("AWS_REGION"),
|
||||
"route53Domain": os.Getenv("R53_DOMAIN"),
|
||||
}
|
||||
for _, v := range m {
|
||||
if v == "" {
|
||||
return nil, fmt.Errorf("AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_REGION, and R53_DOMAIN are needed to run this test")
|
||||
}
|
||||
}
|
||||
return m, nil
|
||||
provider.CleanUp(config["R53_DOMAIN"], "foo", "bar")
|
||||
t.Fatalf("Could not find a TXT record for _acme-challenge.%s with a TTL of 10", config["R53_DOMAIN"])
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"net/http/httptest"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/credentials"
|
||||
|
@ -13,24 +14,40 @@ import (
|
|||
)
|
||||
|
||||
var (
|
||||
route53Secret string
|
||||
route53Key string
|
||||
route53Region string
|
||||
route53Zone string
|
||||
r53AwsSecretAccessKey string
|
||||
r53AwsAccessKeyID string
|
||||
r53AwsRegion string
|
||||
r53AwsHostedZoneID string
|
||||
|
||||
r53AwsMaxRetries string
|
||||
r53AwsTTL string
|
||||
r53AwsPropagationTimeout string
|
||||
r53AwsPollingInterval string
|
||||
)
|
||||
|
||||
func init() {
|
||||
route53Key = os.Getenv("AWS_ACCESS_KEY_ID")
|
||||
route53Secret = os.Getenv("AWS_SECRET_ACCESS_KEY")
|
||||
route53Region = os.Getenv("AWS_REGION")
|
||||
route53Zone = os.Getenv("AWS_HOSTED_ZONE_ID")
|
||||
r53AwsAccessKeyID = os.Getenv("AWS_ACCESS_KEY_ID")
|
||||
r53AwsSecretAccessKey = os.Getenv("AWS_SECRET_ACCESS_KEY")
|
||||
r53AwsRegion = os.Getenv("AWS_REGION")
|
||||
r53AwsHostedZoneID = os.Getenv("AWS_HOSTED_ZONE_ID")
|
||||
|
||||
r53AwsMaxRetries = os.Getenv("AWS_MAX_RETRIES")
|
||||
r53AwsTTL = os.Getenv("AWS_TTL")
|
||||
r53AwsPropagationTimeout = os.Getenv("AWS_PROPAGATION_TIMEOUT")
|
||||
r53AwsPollingInterval = os.Getenv("AWS_POLLING_INTERVAL")
|
||||
}
|
||||
|
||||
func restoreEnv() {
|
||||
os.Setenv("AWS_ACCESS_KEY_ID", route53Key)
|
||||
os.Setenv("AWS_SECRET_ACCESS_KEY", route53Secret)
|
||||
os.Setenv("AWS_REGION", route53Region)
|
||||
os.Setenv("AWS_HOSTED_ZONE_ID", route53Zone)
|
||||
os.Setenv("AWS_ACCESS_KEY_ID", r53AwsAccessKeyID)
|
||||
os.Setenv("AWS_SECRET_ACCESS_KEY", r53AwsSecretAccessKey)
|
||||
os.Setenv("AWS_REGION", r53AwsRegion)
|
||||
os.Setenv("AWS_HOSTED_ZONE_ID", r53AwsHostedZoneID)
|
||||
|
||||
os.Setenv("AWS_MAX_RETRIES", r53AwsMaxRetries)
|
||||
os.Setenv("AWS_TTL", r53AwsTTL)
|
||||
os.Setenv("AWS_PROPAGATION_TIMEOUT", r53AwsPropagationTimeout)
|
||||
os.Setenv("AWS_POLLING_INTERVAL", r53AwsPollingInterval)
|
||||
|
||||
}
|
||||
|
||||
func makeRoute53Provider(ts *httptest.Server) *DNSProvider {
|
||||
|
@ -84,6 +101,27 @@ func TestHostedZoneIDFromEnv(t *testing.T) {
|
|||
assert.Equal(t, testZoneID, fqdn)
|
||||
}
|
||||
|
||||
func TestConfigFromEnv(t *testing.T) {
|
||||
defer restoreEnv()
|
||||
|
||||
config := NewDefaultConfig()
|
||||
assert.Equal(t, config.TTL, 10, "Expected TTL to be use the default")
|
||||
|
||||
os.Setenv("AWS_MAX_RETRIES", "10")
|
||||
os.Setenv("AWS_TTL", "99")
|
||||
os.Setenv("AWS_PROPAGATION_TIMEOUT", "60")
|
||||
os.Setenv("AWS_POLLING_INTERVAL", "60")
|
||||
const zoneID = "abc123"
|
||||
os.Setenv("AWS_HOSTED_ZONE_ID", zoneID)
|
||||
|
||||
config = NewDefaultConfig()
|
||||
assert.Equal(t, config.MaxRetries, 10, "Expected PropagationTimeout to be configured from the environment")
|
||||
assert.Equal(t, config.TTL, 99, "Expected TTL to be configured from the environment")
|
||||
assert.Equal(t, config.PropagationTimeout, time.Minute*60, "Expected PropagationTimeout to be configured from the environment")
|
||||
assert.Equal(t, config.PollingInterval, time.Second*60, "Expected PollingInterval to be configured from the environment")
|
||||
assert.Equal(t, config.HostedZoneID, zoneID, "Expected HostedZoneID to be configured from the environment")
|
||||
}
|
||||
|
||||
func TestRoute53Present(t *testing.T) {
|
||||
mockResponses := MockResponseMap{
|
||||
"/2013-04-01/hostedzonesbyname": MockResponse{StatusCode: 200, Body: ListHostedZonesByNameResponse},
|
||||
|
|
Loading…
Reference in a new issue