chore: migrate to aws-sdk-go-v2 (lightsail, route53) (#1973)
This commit is contained in:
parent
ed14dda361
commit
fc47c35e89
14 changed files with 317 additions and 213 deletions
|
@ -95,7 +95,7 @@ Alternatively, you can also set the `Resource` to `*` (wildcard), which allow to
|
||||||
## More information
|
## More information
|
||||||
|
|
||||||
|
|
||||||
- [Go client](https://github.com/aws/aws-sdk-go/)
|
- [Go client](https://github.com/aws/aws-sdk-go-v2)
|
||||||
|
|
||||||
<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->
|
<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->
|
||||||
<!-- providers/dns/lightsail/lightsail.toml -->
|
<!-- providers/dns/lightsail/lightsail.toml -->
|
||||||
|
|
|
@ -178,7 +178,7 @@ Replace `Z11111112222222333333` with your hosted zone ID and `example.com` with
|
||||||
## More information
|
## More information
|
||||||
|
|
||||||
- [API documentation](https://docs.aws.amazon.com/Route53/latest/APIReference/API_Operations_Amazon_Route_53.html)
|
- [API documentation](https://docs.aws.amazon.com/Route53/latest/APIReference/API_Operations_Amazon_Route_53.html)
|
||||||
- [Go client](https://github.com/aws/aws-sdk-go/aws)
|
- [Go client](https://github.com/aws/aws-sdk-go-v2)
|
||||||
|
|
||||||
<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->
|
<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->
|
||||||
<!-- providers/dns/route53/route53.toml -->
|
<!-- providers/dns/route53/route53.toml -->
|
||||||
|
|
16
go.mod
16
go.mod
|
@ -3,6 +3,7 @@ module github.com/go-acme/lego/v4
|
||||||
go 1.19
|
go 1.19
|
||||||
|
|
||||||
// github.com/exoscale/egoscale v1.19.0 => It is an error, please don't use it.
|
// github.com/exoscale/egoscale v1.19.0 => It is an error, please don't use it.
|
||||||
|
|
||||||
require (
|
require (
|
||||||
cloud.google.com/go/compute/metadata v0.2.3
|
cloud.google.com/go/compute/metadata v0.2.3
|
||||||
github.com/Azure/azure-sdk-for-go v68.0.0+incompatible
|
github.com/Azure/azure-sdk-for-go v68.0.0+incompatible
|
||||||
|
@ -17,7 +18,12 @@ require (
|
||||||
github.com/OpenDNS/vegadns2client v0.0.0-20180418235048-a3fa4a771d87
|
github.com/OpenDNS/vegadns2client v0.0.0-20180418235048-a3fa4a771d87
|
||||||
github.com/akamai/AkamaiOPEN-edgegrid-golang v1.2.2
|
github.com/akamai/AkamaiOPEN-edgegrid-golang v1.2.2
|
||||||
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1755
|
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1755
|
||||||
github.com/aws/aws-sdk-go v1.39.0
|
github.com/aws/aws-sdk-go-v2 v1.19.0
|
||||||
|
github.com/aws/aws-sdk-go-v2/config v1.18.28
|
||||||
|
github.com/aws/aws-sdk-go-v2/credentials v1.13.27
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/lightsail v1.27.2
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/route53 v1.28.4
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/sts v1.19.3
|
||||||
github.com/cenkalti/backoff/v4 v4.2.1
|
github.com/cenkalti/backoff/v4 v4.2.1
|
||||||
github.com/civo/civogo v0.3.11
|
github.com/civo/civogo v0.3.11
|
||||||
github.com/cloudflare/cloudflare-go v0.70.0
|
github.com/cloudflare/cloudflare-go v0.70.0
|
||||||
|
@ -89,6 +95,14 @@ require (
|
||||||
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
|
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
|
||||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0 // indirect
|
github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0 // indirect
|
||||||
github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129 // indirect
|
github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129 // indirect
|
||||||
|
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.5 // indirect
|
||||||
|
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.35 // indirect
|
||||||
|
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.29 // indirect
|
||||||
|
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.36 // indirect
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.29 // indirect
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/sso v1.12.13 // indirect
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.13 // indirect
|
||||||
|
github.com/aws/smithy-go v1.13.5 // indirect
|
||||||
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc // indirect
|
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc // indirect
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
|
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
|
|
31
go.sum
31
go.sum
|
@ -74,8 +74,34 @@ github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kd
|
||||||
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
||||||
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
|
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
|
||||||
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||||
github.com/aws/aws-sdk-go v1.39.0 h1:74BBwkEmiqBbi2CGflEh34l0YNtIibTjZsibGarkNjo=
|
github.com/aws/aws-sdk-go-v2 v1.19.0 h1:klAT+y3pGFBU/qVf1uzwttpBbiuozJYWzNLHioyDJ+k=
|
||||||
github.com/aws/aws-sdk-go v1.39.0/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
|
github.com/aws/aws-sdk-go-v2 v1.19.0/go.mod h1:uzbQtefpm44goOPmdKyAlXSNcwlRgF3ePWVW6EtJvvw=
|
||||||
|
github.com/aws/aws-sdk-go-v2/config v1.18.28 h1:TINEaKyh1Td64tqFvn09iYpKiWjmHYrG1fa91q2gnqw=
|
||||||
|
github.com/aws/aws-sdk-go-v2/config v1.18.28/go.mod h1:nIL+4/8JdAuNHEjn/gPEXqtnS02Q3NXB/9Z7o5xE4+A=
|
||||||
|
github.com/aws/aws-sdk-go-v2/credentials v1.13.27 h1:dz0yr/yR1jweAnsCx+BmjerUILVPQ6FS5AwF/OyG1kA=
|
||||||
|
github.com/aws/aws-sdk-go-v2/credentials v1.13.27/go.mod h1:syOqAek45ZXZp29HlnRS/BNgMIW6uiRmeuQsz4Qh2UE=
|
||||||
|
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.5 h1:kP3Me6Fy3vdi+9uHd7YLr6ewPxRL+PU6y15urfTaamU=
|
||||||
|
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.5/go.mod h1:Gj7tm95r+QsDoN2Fhuz/3npQvcZbkEf5mL70n3Xfluc=
|
||||||
|
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.35 h1:hMUCiE3Zi5AHrRNGf5j985u0WyqI6r2NULhUfo0N/No=
|
||||||
|
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.35/go.mod h1:ipR5PvpSPqIqL5Mi82BxLnfMkHVbmco8kUwO2xrCi0M=
|
||||||
|
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.29 h1:yOpYx+FTBdpk/g+sBU6Cb1H0U/TLEcYYp66mYqsPpcc=
|
||||||
|
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.29/go.mod h1:M/eUABlDbw2uVrdAn+UsI6M727qp2fxkp8K0ejcBDUY=
|
||||||
|
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.36 h1:8r5m1BoAWkn0TDC34lUculryf7nUF25EgIMdjvGCkgo=
|
||||||
|
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.36/go.mod h1:Rmw2M1hMVTwiUhjwMoIBFWFJMhvJbct06sSidxInkhY=
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.29 h1:IiDolu/eLmuB18DRZibj77n1hHQT7z12jnGO7Ze3pLc=
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.29/go.mod h1:fDbkK4o7fpPXWn8YAPmTieAMuB9mk/VgvW64uaUqxd4=
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/lightsail v1.27.2 h1:PwNeYoonBzmTdCztKiiutws3U24KrnDBuabzRfIlZY4=
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/lightsail v1.27.2/go.mod h1:gQhLZrTEath4zik5ixIe6axvgY5jJrgSBDJ360Fxnco=
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/route53 v1.28.4 h1:p4mTxJfCAyiTT4Wp6p/mOPa6j5MqCSRGot8qZwFs+Z0=
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/route53 v1.28.4/go.mod h1:VBLWpaHvhQNeu7N9rMEf00SWeOONb/HvaDUxe/7b44k=
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/sso v1.12.13 h1:sWDv7cMITPcZ21QdreULwxOOAmE05JjEsT6fCDtDA9k=
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/sso v1.12.13/go.mod h1:DfX0sWuT46KpcqbMhJ9QWtxAIP1VozkDWf8VAkByjYY=
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.13 h1:BFubHS/xN5bjl818QaroN6mQdjneYQ+AOx44KNXlyH4=
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.13/go.mod h1:BzqsVVFduubEmzrVtUFQQIQdFqvUItF8XUq2EnS8Wog=
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/sts v1.19.3 h1:e5mnydVdCVWxP+5rPAGi2PYxC7u2OZgH1ypC114H04U=
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/sts v1.19.3/go.mod h1:yVGZA1CPkmUhBdA039jXNJJG7/6t+G+EBWmFq23xqnY=
|
||||||
|
github.com/aws/smithy-go v1.13.5 h1:hgz0X/DX0dGqTYpGALqXJoRKRj5oQ7150i5FdTePzO8=
|
||||||
|
github.com/aws/smithy-go v1.13.5/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA=
|
||||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||||
|
@ -220,6 +246,7 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
||||||
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
|
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
|
||||||
|
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||||
github.com/google/go-github/v32 v32.1.0/go.mod h1:rIEpZD9CTDQwDK9GDrtMTycQNA4JU3qBsCizh3q2WCI=
|
github.com/google/go-github/v32 v32.1.0/go.mod h1:rIEpZD9CTDQwDK9GDrtMTycQNA4JU3qBsCizh3q2WCI=
|
||||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||||
|
|
|
@ -51,6 +51,11 @@ func (e *EnvTest) WithLiveTestRequirements(keys ...string) *EnvTest {
|
||||||
panic(fmt.Sprintf("Unauthorized action, the env var %s is not managed or it's not the key of the domain.", key))
|
panic(fmt.Sprintf("Unauthorized action, the env var %s is not managed or it's not the key of the domain.", key))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if e.domainKey == key {
|
||||||
|
countValuedVars++
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
if _, ok := e.values[key]; ok {
|
if _, ok := e.values[key]; ok {
|
||||||
countValuedVars++
|
countValuedVars++
|
||||||
}
|
}
|
||||||
|
|
|
@ -148,6 +148,22 @@ func TestEnvTest(t *testing.T) {
|
||||||
assert.Equal(t, "", envTest.GetDomain())
|
assert.Equal(t, "", envTest.GetDomain())
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
desc: "WithLiveTestRequirements with domain as requirement",
|
||||||
|
envVars: map[string]string{
|
||||||
|
envVar01: "A",
|
||||||
|
envVar02: "B",
|
||||||
|
},
|
||||||
|
envTestSetup: func() *tester.EnvTest {
|
||||||
|
return tester.NewEnvTest(envVar01, envVar02).WithDomain(envVarDomain).WithLiveTestRequirements(envVar02, envVarDomain)
|
||||||
|
},
|
||||||
|
expected: func(t *testing.T, envTest *tester.EnvTest) {
|
||||||
|
assert.True(t, envTest.IsLiveTest())
|
||||||
|
assert.Equal(t, "A", envTest.GetValue(envVar01))
|
||||||
|
assert.Equal(t, "B", envTest.GetValue(envVar02))
|
||||||
|
assert.Equal(t, "", envTest.GetDomain())
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
desc: "WithLiveTestRequirements non required var missing",
|
desc: "WithLiveTestRequirements non required var missing",
|
||||||
envVars: map[string]string{
|
envVars: map[string]string{
|
||||||
|
|
|
@ -2,17 +2,18 @@
|
||||||
package lightsail
|
package lightsail
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/aws/aws-sdk-go/aws"
|
"github.com/aws/aws-sdk-go-v2/aws"
|
||||||
"github.com/aws/aws-sdk-go/aws/client"
|
"github.com/aws/aws-sdk-go-v2/aws/retry"
|
||||||
"github.com/aws/aws-sdk-go/aws/request"
|
awsconfig "github.com/aws/aws-sdk-go-v2/config"
|
||||||
"github.com/aws/aws-sdk-go/aws/session"
|
"github.com/aws/aws-sdk-go-v2/service/lightsail"
|
||||||
"github.com/aws/aws-sdk-go/service/lightsail"
|
awstypes "github.com/aws/aws-sdk-go-v2/service/lightsail/types"
|
||||||
"github.com/go-acme/lego/v4/challenge/dns01"
|
"github.com/go-acme/lego/v4/challenge/dns01"
|
||||||
"github.com/go-acme/lego/v4/platform/config/env"
|
"github.com/go-acme/lego/v4/platform/config/env"
|
||||||
)
|
)
|
||||||
|
@ -32,27 +33,6 @@ const (
|
||||||
EnvPollingInterval = envNamespace + "POLLING_INTERVAL"
|
EnvPollingInterval = envNamespace + "POLLING_INTERVAL"
|
||||||
)
|
)
|
||||||
|
|
||||||
// customRetryer implements the client.Retryer interface by composing the DefaultRetryer.
|
|
||||||
// It controls the logic for retrying recoverable request errors (e.g. when rate limits are exceeded).
|
|
||||||
type customRetryer struct {
|
|
||||||
client.DefaultRetryer
|
|
||||||
}
|
|
||||||
|
|
||||||
// RetryRules overwrites the DefaultRetryer's method.
|
|
||||||
// It uses a basic exponential backoff algorithm that returns an initial
|
|
||||||
// delay of ~400ms with an upper limit of ~30 seconds which should prevent
|
|
||||||
// causing a high number of consecutive throttling errors.
|
|
||||||
// For reference: Route 53 enforces an account-wide(!) 5req/s query limit.
|
|
||||||
func (c customRetryer) RetryRules(r *request.Request) time.Duration {
|
|
||||||
retryCount := r.RetryCount
|
|
||||||
if retryCount > 7 {
|
|
||||||
retryCount = 7
|
|
||||||
}
|
|
||||||
|
|
||||||
delay := (1 << uint(retryCount)) * (rand.Intn(50) + 200)
|
|
||||||
return time.Duration(delay) * time.Millisecond
|
|
||||||
}
|
|
||||||
|
|
||||||
// Config is used to configure the creation of the DNSProvider.
|
// Config is used to configure the creation of the DNSProvider.
|
||||||
type Config struct {
|
type Config struct {
|
||||||
DNSZone string
|
DNSZone string
|
||||||
|
@ -71,7 +51,7 @@ func NewDefaultConfig() *Config {
|
||||||
|
|
||||||
// DNSProvider implements the challenge.Provider interface.
|
// DNSProvider implements the challenge.Provider interface.
|
||||||
type DNSProvider struct {
|
type DNSProvider struct {
|
||||||
client *lightsail.Lightsail
|
client *lightsail.Client
|
||||||
config *Config
|
config *Config
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,35 +82,55 @@ func NewDNSProviderConfig(config *Config) (*DNSProvider, error) {
|
||||||
return nil, errors.New("lightsail: the configuration of the DNS provider is nil")
|
return nil, errors.New("lightsail: the configuration of the DNS provider is nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
retryer := customRetryer{}
|
ctx := context.Background()
|
||||||
retryer.NumMaxRetries = maxRetries
|
|
||||||
|
|
||||||
conf := aws.NewConfig().WithRegion(config.Region)
|
cfg, err := awsconfig.LoadDefaultConfig(ctx,
|
||||||
sess, err := session.NewSession(request.WithRetryer(conf, retryer))
|
awsconfig.WithRegion(config.Region),
|
||||||
|
awsconfig.WithRetryer(func() aws.Retryer {
|
||||||
|
return retry.NewStandard(func(options *retry.StandardOptions) {
|
||||||
|
options.MaxAttempts = maxRetries
|
||||||
|
|
||||||
|
// It uses a basic exponential backoff algorithm that returns an initial
|
||||||
|
// delay of ~400ms with an upper limit of ~30 seconds which should prevent
|
||||||
|
// causing a high number of consecutive throttling errors.
|
||||||
|
// For reference: Route 53 enforces an account-wide(!) 5req/s query limit.
|
||||||
|
options.Backoff = retry.BackoffDelayerFunc(func(attempt int, err error) (time.Duration, error) {
|
||||||
|
retryCount := attempt
|
||||||
|
if retryCount > 7 {
|
||||||
|
retryCount = 7
|
||||||
|
}
|
||||||
|
|
||||||
|
delay := (1 << uint(retryCount)) * (rand.Intn(50) + 200)
|
||||||
|
return time.Duration(delay) * time.Millisecond, nil
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &DNSProvider{
|
return &DNSProvider{
|
||||||
config: config,
|
config: config,
|
||||||
client: lightsail.New(sess),
|
client: lightsail.NewFromConfig(cfg),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Present creates a TXT record using the specified parameters.
|
// Present creates a TXT record using the specified parameters.
|
||||||
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
func (d *DNSProvider) Present(domain, _, keyAuth string) error {
|
||||||
|
ctx := context.Background()
|
||||||
info := dns01.GetChallengeInfo(domain, keyAuth)
|
info := dns01.GetChallengeInfo(domain, keyAuth)
|
||||||
|
|
||||||
params := &lightsail.CreateDomainEntryInput{
|
params := &lightsail.CreateDomainEntryInput{
|
||||||
DomainName: aws.String(d.config.DNSZone),
|
DomainName: aws.String(d.config.DNSZone),
|
||||||
DomainEntry: &lightsail.DomainEntry{
|
DomainEntry: &awstypes.DomainEntry{
|
||||||
Name: aws.String(info.EffectiveFQDN),
|
Name: aws.String(info.EffectiveFQDN),
|
||||||
Target: aws.String(strconv.Quote(info.Value)),
|
Target: aws.String(strconv.Quote(info.Value)),
|
||||||
Type: aws.String("TXT"),
|
Type: aws.String("TXT"),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := d.client.CreateDomainEntry(params)
|
_, err := d.client.CreateDomainEntry(ctx, params)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("lightsail: %w", err)
|
return fmt.Errorf("lightsail: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -139,19 +139,20 @@ func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// CleanUp removes the TXT record matching the specified parameters.
|
// CleanUp removes the TXT record matching the specified parameters.
|
||||||
func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
func (d *DNSProvider) CleanUp(domain, _, keyAuth string) error {
|
||||||
|
ctx := context.Background()
|
||||||
info := dns01.GetChallengeInfo(domain, keyAuth)
|
info := dns01.GetChallengeInfo(domain, keyAuth)
|
||||||
|
|
||||||
params := &lightsail.DeleteDomainEntryInput{
|
params := &lightsail.DeleteDomainEntryInput{
|
||||||
DomainName: aws.String(d.config.DNSZone),
|
DomainName: aws.String(d.config.DNSZone),
|
||||||
DomainEntry: &lightsail.DomainEntry{
|
DomainEntry: &awstypes.DomainEntry{
|
||||||
Name: aws.String(info.EffectiveFQDN),
|
Name: aws.String(info.EffectiveFQDN),
|
||||||
Type: aws.String("TXT"),
|
Type: aws.String("TXT"),
|
||||||
Target: aws.String(strconv.Quote(info.Value)),
|
Target: aws.String(strconv.Quote(info.Value)),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := d.client.DeleteDomainEntry(params)
|
_, err := d.client.DeleteDomainEntry(ctx, params)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("lightsail: %w", err)
|
return fmt.Errorf("lightsail: %w", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,4 +56,4 @@ Alternatively, you can also set the `Resource` to `*` (wildcard), which allow to
|
||||||
LIGHTSAIL_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation"
|
LIGHTSAIL_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation"
|
||||||
|
|
||||||
[Links]
|
[Links]
|
||||||
GoClient = "https://github.com/aws/aws-sdk-go/"
|
GoClient = "https://github.com/aws/aws-sdk-go-v2"
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
package lightsail
|
package lightsail
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/aws/aws-sdk-go/aws"
|
"github.com/aws/aws-sdk-go-v2/aws"
|
||||||
"github.com/aws/aws-sdk-go/aws/session"
|
awsconfig "github.com/aws/aws-sdk-go-v2/config"
|
||||||
"github.com/aws/aws-sdk-go/service/lightsail"
|
"github.com/aws/aws-sdk-go-v2/service/lightsail"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -24,13 +25,15 @@ func TestLiveTTL(t *testing.T) {
|
||||||
err = provider.Present(domain, "foo", "bar")
|
err = provider.Present(domain, "foo", "bar")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// we need a separate Lightsail client here as the one in the DNS provider is
|
// we need a separate Lightsail client here as the one in the DNS provider is unexported.
|
||||||
// unexported.
|
|
||||||
fqdn := "_acme-challenge." + domain
|
fqdn := "_acme-challenge." + domain
|
||||||
sess, err := session.NewSession()
|
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
cfg, err := awsconfig.LoadDefaultConfig(ctx)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
svc := lightsail.New(sess)
|
svc := lightsail.NewFromConfig(cfg)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
|
@ -44,15 +47,24 @@ func TestLiveTTL(t *testing.T) {
|
||||||
DomainName: aws.String(domain),
|
DomainName: aws.String(domain),
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err := svc.GetDomain(params)
|
resp, err := svc.GetDomain(ctx, params)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
entries := resp.Domain.DomainEntries
|
entries := resp.Domain.DomainEntries
|
||||||
for _, entry := range entries {
|
for _, entry := range entries {
|
||||||
if aws.StringValue(entry.Type) == "TXT" && aws.StringValue(entry.Name) == fqdn {
|
if deref(entry.Type) == "TXT" && deref(entry.Name) == fqdn {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Fatalf("Could not find a TXT record for _acme-challenge.%s", domain)
|
t.Fatalf("Could not find a TXT record for _acme-challenge.%s", domain)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func deref[T string | int | int32 | int64 | bool](v *T) T {
|
||||||
|
if v == nil {
|
||||||
|
var zero T
|
||||||
|
return zero
|
||||||
|
}
|
||||||
|
|
||||||
|
return *v
|
||||||
|
}
|
||||||
|
|
|
@ -1,14 +1,16 @@
|
||||||
package lightsail
|
package lightsail
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/aws/aws-sdk-go/aws"
|
"github.com/aws/aws-sdk-go-v2/aws"
|
||||||
"github.com/aws/aws-sdk-go/aws/credentials"
|
awsconfig "github.com/aws/aws-sdk-go-v2/config"
|
||||||
"github.com/aws/aws-sdk-go/aws/session"
|
"github.com/aws/aws-sdk-go-v2/credentials"
|
||||||
"github.com/aws/aws-sdk-go/service/lightsail"
|
"github.com/aws/aws-sdk-go-v2/service/lightsail"
|
||||||
"github.com/go-acme/lego/v4/platform/tester"
|
"github.com/go-acme/lego/v4/platform/tester"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -29,23 +31,26 @@ var envTest = tester.NewEnvTest(
|
||||||
WithDomain(EnvDNSZone).
|
WithDomain(EnvDNSZone).
|
||||||
WithLiveTestRequirements(envAwsAccessKeyID, envAwsSecretAccessKey, EnvDNSZone)
|
WithLiveTestRequirements(envAwsAccessKeyID, envAwsSecretAccessKey, EnvDNSZone)
|
||||||
|
|
||||||
func makeProvider(serverURL string) (*DNSProvider, error) {
|
type endpointResolverMock struct {
|
||||||
config := &aws.Config{
|
endpoint string
|
||||||
Credentials: credentials.NewStaticCredentials("abc", "123", " "),
|
|
||||||
Endpoint: aws.String(serverURL),
|
|
||||||
Region: aws.String("mock-region"),
|
|
||||||
MaxRetries: aws.Int(1),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sess, err := session.NewSession(config)
|
func (e endpointResolverMock) ResolveEndpoint(_, _ string, _ ...interface{}) (aws.Endpoint, error) {
|
||||||
if err != nil {
|
return aws.Endpoint{URL: e.endpoint}, nil
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
conf := NewDefaultConfig()
|
func makeProvider(serverURL string) *DNSProvider {
|
||||||
|
config := aws.Config{
|
||||||
|
Credentials: credentials.NewStaticCredentialsProvider("abc", "123", " "),
|
||||||
|
Region: "mock-region",
|
||||||
|
EndpointResolverWithOptions: endpointResolverMock{endpoint: serverURL},
|
||||||
|
RetryMaxAttempts: 1,
|
||||||
|
}
|
||||||
|
|
||||||
client := lightsail.New(sess)
|
return &DNSProvider{
|
||||||
return &DNSProvider{client: client, config: conf}, nil
|
client: lightsail.NewFromConfig(config),
|
||||||
|
config: NewDefaultConfig(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCredentialsFromEnv(t *testing.T) {
|
func TestCredentialsFromEnv(t *testing.T) {
|
||||||
|
@ -56,15 +61,19 @@ func TestCredentialsFromEnv(t *testing.T) {
|
||||||
_ = os.Setenv(envAwsSecretAccessKey, "123")
|
_ = os.Setenv(envAwsSecretAccessKey, "123")
|
||||||
_ = os.Setenv(envAwsRegion, "us-east-1")
|
_ = os.Setenv(envAwsRegion, "us-east-1")
|
||||||
|
|
||||||
config := &aws.Config{
|
ctx := context.Background()
|
||||||
CredentialsChainVerboseErrors: aws.Bool(true),
|
cfg, err := awsconfig.LoadDefaultConfig(ctx)
|
||||||
}
|
|
||||||
|
|
||||||
sess, err := session.NewSession(config)
|
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
_, err = sess.Config.Credentials.Get()
|
cs, err := cfg.Credentials.Retrieve(ctx)
|
||||||
require.NoError(t, err, "Expected credentials to be set from environment")
|
require.NoError(t, err, "Expected credentials to be set from environment")
|
||||||
|
|
||||||
|
expected := aws.Credentials{
|
||||||
|
AccessKeyID: "123",
|
||||||
|
SecretAccessKey: "123",
|
||||||
|
Source: "EnvConfigCredentials",
|
||||||
|
}
|
||||||
|
assert.Equal(t, expected, cs)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDNSProvider_Present(t *testing.T) {
|
func TestDNSProvider_Present(t *testing.T) {
|
||||||
|
@ -74,12 +83,11 @@ func TestDNSProvider_Present(t *testing.T) {
|
||||||
|
|
||||||
serverURL := newMockServer(t, mockResponses)
|
serverURL := newMockServer(t, mockResponses)
|
||||||
|
|
||||||
provider, err := makeProvider(serverURL)
|
provider := makeProvider(serverURL)
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
domain := "example.com"
|
domain := "example.com"
|
||||||
keyAuth := "123456d=="
|
keyAuth := "123456d=="
|
||||||
|
|
||||||
err = provider.Present(domain, "", keyAuth)
|
err := provider.Present(domain, "", keyAuth)
|
||||||
require.NoError(t, err, "Expected Present to return no error")
|
require.NoError(t, err, "Expected Present to return no error")
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,19 +2,21 @@
|
||||||
package route53
|
package route53
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/aws/aws-sdk-go/aws"
|
"github.com/aws/aws-sdk-go-v2/aws"
|
||||||
"github.com/aws/aws-sdk-go/aws/client"
|
"github.com/aws/aws-sdk-go-v2/aws/retry"
|
||||||
"github.com/aws/aws-sdk-go/aws/credentials"
|
awsconfig "github.com/aws/aws-sdk-go-v2/config"
|
||||||
"github.com/aws/aws-sdk-go/aws/credentials/stscreds"
|
"github.com/aws/aws-sdk-go-v2/credentials"
|
||||||
"github.com/aws/aws-sdk-go/aws/request"
|
"github.com/aws/aws-sdk-go-v2/credentials/stscreds"
|
||||||
"github.com/aws/aws-sdk-go/aws/session"
|
"github.com/aws/aws-sdk-go-v2/service/route53"
|
||||||
"github.com/aws/aws-sdk-go/service/route53"
|
awstypes "github.com/aws/aws-sdk-go-v2/service/route53/types"
|
||||||
|
"github.com/aws/aws-sdk-go-v2/service/sts"
|
||||||
"github.com/go-acme/lego/v4/challenge/dns01"
|
"github.com/go-acme/lego/v4/challenge/dns01"
|
||||||
"github.com/go-acme/lego/v4/platform/config/env"
|
"github.com/go-acme/lego/v4/platform/config/env"
|
||||||
"github.com/go-acme/lego/v4/platform/wait"
|
"github.com/go-acme/lego/v4/platform/wait"
|
||||||
|
@ -55,7 +57,7 @@ type Config struct {
|
||||||
PropagationTimeout time.Duration
|
PropagationTimeout time.Duration
|
||||||
PollingInterval time.Duration
|
PollingInterval time.Duration
|
||||||
|
|
||||||
Client *route53.Route53
|
Client *route53.Client
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDefaultConfig returns a default configuration for the DNSProvider.
|
// NewDefaultConfig returns a default configuration for the DNSProvider.
|
||||||
|
@ -74,31 +76,10 @@ func NewDefaultConfig() *Config {
|
||||||
|
|
||||||
// DNSProvider implements the challenge.Provider interface.
|
// DNSProvider implements the challenge.Provider interface.
|
||||||
type DNSProvider struct {
|
type DNSProvider struct {
|
||||||
client *route53.Route53
|
client *route53.Client
|
||||||
config *Config
|
config *Config
|
||||||
}
|
}
|
||||||
|
|
||||||
// customRetryer implements the client.Retryer interface by composing the DefaultRetryer.
|
|
||||||
// It controls the logic for retrying recoverable request errors (e.g. when rate limits are exceeded).
|
|
||||||
type customRetryer struct {
|
|
||||||
client.DefaultRetryer
|
|
||||||
}
|
|
||||||
|
|
||||||
// RetryRules overwrites the DefaultRetryer's method.
|
|
||||||
// It uses a basic exponential backoff algorithm:
|
|
||||||
// that returns an initial delay of ~400ms with an upper limit of ~30 seconds,
|
|
||||||
// which should prevent causing a high number of consecutive throttling errors.
|
|
||||||
// For reference: Route 53 enforces an account-wide(!) 5req/s query limit.
|
|
||||||
func (d customRetryer) RetryRules(r *request.Request) time.Duration {
|
|
||||||
retryCount := r.RetryCount
|
|
||||||
if retryCount > 7 {
|
|
||||||
retryCount = 7
|
|
||||||
}
|
|
||||||
|
|
||||||
delay := (1 << uint(retryCount)) * (rand.Intn(50) + 200)
|
|
||||||
return time.Duration(delay) * time.Millisecond
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewDNSProvider returns a DNSProvider instance configured for the AWS Route 53 service.
|
// NewDNSProvider returns a DNSProvider instance configured for the AWS Route 53 service.
|
||||||
//
|
//
|
||||||
// AWS Credentials are automatically detected in the following locations and prioritized in the following order:
|
// AWS Credentials are automatically detected in the following locations and prioritized in the following order:
|
||||||
|
@ -124,13 +105,15 @@ func NewDNSProviderConfig(config *Config) (*DNSProvider, error) {
|
||||||
return &DNSProvider{client: config.Client, config: config}, nil
|
return &DNSProvider{client: config.Client, config: config}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
sess, err := createSession(config)
|
ctx := context.Background()
|
||||||
|
|
||||||
|
cfg, err := createAWSConfig(ctx, config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &DNSProvider{
|
return &DNSProvider{
|
||||||
client: route53.New(sess),
|
client: route53.NewFromConfig(cfg),
|
||||||
config: config,
|
config: config,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
@ -142,14 +125,15 @@ func (d *DNSProvider) Timeout() (timeout, interval time.Duration) {
|
||||||
|
|
||||||
// Present creates a TXT record using the specified parameters.
|
// Present creates a TXT record using the specified parameters.
|
||||||
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||||
|
ctx := context.Background()
|
||||||
info := dns01.GetChallengeInfo(domain, keyAuth)
|
info := dns01.GetChallengeInfo(domain, keyAuth)
|
||||||
|
|
||||||
hostedZoneID, err := d.getHostedZoneID(info.EffectiveFQDN)
|
hostedZoneID, err := d.getHostedZoneID(ctx, info.EffectiveFQDN)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("route53: failed to determine hosted zone ID: %w", err)
|
return fmt.Errorf("route53: failed to determine hosted zone ID: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
records, err := d.getExistingRecordSets(hostedZoneID, info.EffectiveFQDN)
|
records, err := d.getExistingRecordSets(ctx, hostedZoneID, info.EffectiveFQDN)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("route53: %w", err)
|
return fmt.Errorf("route53: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -158,39 +142,41 @@ func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||||
|
|
||||||
var found bool
|
var found bool
|
||||||
for _, record := range records {
|
for _, record := range records {
|
||||||
if aws.StringValue(record.Value) == realValue {
|
if deref(record.Value) == realValue {
|
||||||
found = true
|
found = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !found {
|
if !found {
|
||||||
records = append(records, &route53.ResourceRecord{Value: aws.String(realValue)})
|
records = append(records, awstypes.ResourceRecord{Value: aws.String(realValue)})
|
||||||
}
|
}
|
||||||
|
|
||||||
recordSet := &route53.ResourceRecordSet{
|
recordSet := &awstypes.ResourceRecordSet{
|
||||||
Name: aws.String(info.EffectiveFQDN),
|
Name: aws.String(info.EffectiveFQDN),
|
||||||
Type: aws.String("TXT"),
|
Type: "TXT",
|
||||||
TTL: aws.Int64(int64(d.config.TTL)),
|
TTL: aws.Int64(int64(d.config.TTL)),
|
||||||
ResourceRecords: records,
|
ResourceRecords: records,
|
||||||
}
|
}
|
||||||
|
|
||||||
err = d.changeRecord(route53.ChangeActionUpsert, hostedZoneID, recordSet)
|
err = d.changeRecord(ctx, awstypes.ChangeActionUpsert, hostedZoneID, recordSet)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("route53: %w", err)
|
return fmt.Errorf("route53: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CleanUp removes the TXT record matching the specified parameters.
|
// CleanUp removes the TXT record matching the specified parameters.
|
||||||
func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
||||||
|
ctx := context.Background()
|
||||||
info := dns01.GetChallengeInfo(domain, keyAuth)
|
info := dns01.GetChallengeInfo(domain, keyAuth)
|
||||||
|
|
||||||
hostedZoneID, err := d.getHostedZoneID(info.EffectiveFQDN)
|
hostedZoneID, err := d.getHostedZoneID(ctx, info.EffectiveFQDN)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to determine Route 53 hosted zone ID: %w", err)
|
return fmt.Errorf("failed to determine Route 53 hosted zone ID: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
records, err := d.getExistingRecordSets(hostedZoneID, info.EffectiveFQDN)
|
records, err := d.getExistingRecordSets(ctx, hostedZoneID, info.EffectiveFQDN)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("route53: %w", err)
|
return fmt.Errorf("route53: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -199,33 +185,33 @@ func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
recordSet := &route53.ResourceRecordSet{
|
recordSet := &awstypes.ResourceRecordSet{
|
||||||
Name: aws.String(info.EffectiveFQDN),
|
Name: aws.String(info.EffectiveFQDN),
|
||||||
Type: aws.String("TXT"),
|
Type: "TXT",
|
||||||
TTL: aws.Int64(int64(d.config.TTL)),
|
TTL: aws.Int64(int64(d.config.TTL)),
|
||||||
ResourceRecords: records,
|
ResourceRecords: records,
|
||||||
}
|
}
|
||||||
|
|
||||||
err = d.changeRecord(route53.ChangeActionDelete, hostedZoneID, recordSet)
|
err = d.changeRecord(ctx, awstypes.ChangeActionDelete, hostedZoneID, recordSet)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("route53: %w", err)
|
return fmt.Errorf("route53: %w", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *DNSProvider) changeRecord(action, hostedZoneID string, recordSet *route53.ResourceRecordSet) error {
|
func (d *DNSProvider) changeRecord(ctx context.Context, action awstypes.ChangeAction, hostedZoneID string, recordSet *awstypes.ResourceRecordSet) error {
|
||||||
recordSetInput := &route53.ChangeResourceRecordSetsInput{
|
recordSetInput := &route53.ChangeResourceRecordSetsInput{
|
||||||
HostedZoneId: aws.String(hostedZoneID),
|
HostedZoneId: aws.String(hostedZoneID),
|
||||||
ChangeBatch: &route53.ChangeBatch{
|
ChangeBatch: &awstypes.ChangeBatch{
|
||||||
Comment: aws.String("Managed by Lego"),
|
Comment: aws.String("Managed by Lego"),
|
||||||
Changes: []*route53.Change{{
|
Changes: []awstypes.Change{{
|
||||||
Action: aws.String(action),
|
Action: action,
|
||||||
ResourceRecordSet: recordSet,
|
ResourceRecordSet: recordSet,
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err := d.client.ChangeResourceRecordSets(recordSetInput)
|
resp, err := d.client.ChangeResourceRecordSets(ctx, recordSetInput)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to change record set: %w", err)
|
return fmt.Errorf("failed to change record set: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -235,26 +221,26 @@ func (d *DNSProvider) changeRecord(action, hostedZoneID string, recordSet *route
|
||||||
return wait.For("route53", d.config.PropagationTimeout, d.config.PollingInterval, func() (bool, error) {
|
return wait.For("route53", d.config.PropagationTimeout, d.config.PollingInterval, func() (bool, error) {
|
||||||
reqParams := &route53.GetChangeInput{Id: changeID}
|
reqParams := &route53.GetChangeInput{Id: changeID}
|
||||||
|
|
||||||
resp, err := d.client.GetChange(reqParams)
|
resp, err := d.client.GetChange(ctx, reqParams)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, fmt.Errorf("failed to query change status: %w", err)
|
return false, fmt.Errorf("failed to query change status: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if aws.StringValue(resp.ChangeInfo.Status) == route53.ChangeStatusInsync {
|
if resp.ChangeInfo.Status == awstypes.ChangeStatusInsync {
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
return false, fmt.Errorf("unable to retrieve change: ID=%s", aws.StringValue(changeID))
|
return false, fmt.Errorf("unable to retrieve change: ID=%s", deref(changeID))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *DNSProvider) getExistingRecordSets(hostedZoneID, fqdn string) ([]*route53.ResourceRecord, error) {
|
func (d *DNSProvider) getExistingRecordSets(ctx context.Context, hostedZoneID, fqdn string) ([]awstypes.ResourceRecord, error) {
|
||||||
listInput := &route53.ListResourceRecordSetsInput{
|
listInput := &route53.ListResourceRecordSetsInput{
|
||||||
HostedZoneId: aws.String(hostedZoneID),
|
HostedZoneId: aws.String(hostedZoneID),
|
||||||
StartRecordName: aws.String(fqdn),
|
StartRecordName: aws.String(fqdn),
|
||||||
StartRecordType: aws.String("TXT"),
|
StartRecordType: "TXT",
|
||||||
}
|
}
|
||||||
|
|
||||||
recordSetsOutput, err := d.client.ListResourceRecordSets(listInput)
|
recordSetsOutput, err := d.client.ListResourceRecordSets(ctx, listInput)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -263,10 +249,10 @@ func (d *DNSProvider) getExistingRecordSets(hostedZoneID, fqdn string) ([]*route
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var records []*route53.ResourceRecord
|
var records []awstypes.ResourceRecord
|
||||||
|
|
||||||
for _, recordSet := range recordSetsOutput.ResourceRecordSets {
|
for _, recordSet := range recordSetsOutput.ResourceRecordSets {
|
||||||
if aws.StringValue(recordSet.Name) == fqdn {
|
if deref(recordSet.Name) == fqdn {
|
||||||
records = append(records, recordSet.ResourceRecords...)
|
records = append(records, recordSet.ResourceRecords...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -274,7 +260,7 @@ func (d *DNSProvider) getExistingRecordSets(hostedZoneID, fqdn string) ([]*route
|
||||||
return records, nil
|
return records, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *DNSProvider) getHostedZoneID(fqdn string) (string, error) {
|
func (d *DNSProvider) getHostedZoneID(ctx context.Context, fqdn string) (string, error) {
|
||||||
if d.config.HostedZoneID != "" {
|
if d.config.HostedZoneID != "" {
|
||||||
return d.config.HostedZoneID, nil
|
return d.config.HostedZoneID, nil
|
||||||
}
|
}
|
||||||
|
@ -288,7 +274,7 @@ func (d *DNSProvider) getHostedZoneID(fqdn string) (string, error) {
|
||||||
reqParams := &route53.ListHostedZonesByNameInput{
|
reqParams := &route53.ListHostedZonesByNameInput{
|
||||||
DNSName: aws.String(dns01.UnFqdn(authZone)),
|
DNSName: aws.String(dns01.UnFqdn(authZone)),
|
||||||
}
|
}
|
||||||
resp, err := d.client.ListHostedZonesByName(reqParams)
|
resp, err := d.client.ListHostedZonesByName(ctx, reqParams)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
@ -296,8 +282,8 @@ func (d *DNSProvider) getHostedZoneID(fqdn string) (string, error) {
|
||||||
var hostedZoneID string
|
var hostedZoneID string
|
||||||
for _, hostedZone := range resp.HostedZones {
|
for _, hostedZone := range resp.HostedZones {
|
||||||
// .Name has a trailing dot
|
// .Name has a trailing dot
|
||||||
if !aws.BoolValue(hostedZone.Config.PrivateZone) && aws.StringValue(hostedZone.Name) == authZone {
|
if !hostedZone.Config.PrivateZone && deref(hostedZone.Name) == authZone {
|
||||||
hostedZoneID = aws.StringValue(hostedZone.Id)
|
hostedZoneID = deref(hostedZone.Id)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -311,45 +297,60 @@ func (d *DNSProvider) getHostedZoneID(fqdn string) (string, error) {
|
||||||
return hostedZoneID, nil
|
return hostedZoneID, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func createSession(config *Config) (*session.Session, error) {
|
func createAWSConfig(ctx context.Context, config *Config) (aws.Config, error) {
|
||||||
if err := createSessionCheckParams(config); err != nil {
|
if err := createAWSConfigCheckParams(config); err != nil {
|
||||||
return nil, err
|
return aws.Config{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
retry := customRetryer{}
|
optFns := []func(options *awsconfig.LoadOptions) error{
|
||||||
retry.NumMaxRetries = config.MaxRetries
|
awsconfig.WithRetryer(func() aws.Retryer {
|
||||||
|
return retry.NewStandard(func(options *retry.StandardOptions) {
|
||||||
|
options.MaxAttempts = config.MaxRetries
|
||||||
|
|
||||||
|
// It uses a basic exponential backoff algorithm that returns an initial
|
||||||
|
// delay of ~400ms with an upper limit of ~30 seconds which should prevent
|
||||||
|
// causing a high number of consecutive throttling errors.
|
||||||
|
// For reference: Route 53 enforces an account-wide(!) 5req/s query limit.
|
||||||
|
options.Backoff = retry.BackoffDelayerFunc(func(attempt int, err error) (time.Duration, error) {
|
||||||
|
retryCount := attempt
|
||||||
|
if retryCount > 7 {
|
||||||
|
retryCount = 7
|
||||||
|
}
|
||||||
|
|
||||||
|
delay := (1 << uint(retryCount)) * (rand.Intn(50) + 200)
|
||||||
|
return time.Duration(delay) * time.Millisecond, nil
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
|
||||||
awsConfig := aws.NewConfig()
|
|
||||||
if config.AccessKeyID != "" && config.SecretAccessKey != "" {
|
if config.AccessKeyID != "" && config.SecretAccessKey != "" {
|
||||||
awsConfig = awsConfig.WithCredentials(credentials.NewStaticCredentials(config.AccessKeyID, config.SecretAccessKey, config.SessionToken))
|
optFns = append(optFns,
|
||||||
|
awsconfig.WithCredentialsProvider(credentials.NewStaticCredentialsProvider(config.AccessKeyID, config.SecretAccessKey, config.SessionToken)),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.Region != "" {
|
if config.Region != "" {
|
||||||
awsConfig = awsConfig.WithRegion(config.Region)
|
optFns = append(optFns, awsconfig.WithRegion(config.Region))
|
||||||
}
|
}
|
||||||
|
|
||||||
sessionCfg := request.WithRetryer(awsConfig, retry)
|
cfg, err := awsconfig.LoadDefaultConfig(ctx, optFns...)
|
||||||
|
|
||||||
sess, err := session.NewSessionWithOptions(session.Options{Config: *sessionCfg})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return aws.Config{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.AssumeRoleArn == "" {
|
if config.AssumeRoleArn != "" {
|
||||||
return sess, nil
|
cfg.Credentials = stscreds.NewAssumeRoleProvider(sts.NewFromConfig(cfg), config.AssumeRoleArn, func(options *stscreds.AssumeRoleOptions) {
|
||||||
}
|
|
||||||
|
|
||||||
return session.NewSession(&aws.Config{
|
|
||||||
Region: sess.Config.Region,
|
|
||||||
Credentials: stscreds.NewCredentials(sess, config.AssumeRoleArn, func(arp *stscreds.AssumeRoleProvider) {
|
|
||||||
if config.ExternalID != "" {
|
if config.ExternalID != "" {
|
||||||
arp.ExternalID = &config.ExternalID
|
options.ExternalID = &config.ExternalID
|
||||||
}
|
}
|
||||||
}),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func createSessionCheckParams(config *Config) error {
|
return cfg, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func createAWSConfigCheckParams(config *Config) error {
|
||||||
if config == nil {
|
if config == nil {
|
||||||
return errors.New("config is nil")
|
return errors.New("config is nil")
|
||||||
}
|
}
|
||||||
|
@ -364,3 +365,12 @@ func createSessionCheckParams(config *Config) error {
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func deref[T string | int | int32 | int64 | bool](v *T) T {
|
||||||
|
if v == nil {
|
||||||
|
var zero T
|
||||||
|
return zero
|
||||||
|
}
|
||||||
|
|
||||||
|
return *v
|
||||||
|
}
|
||||||
|
|
|
@ -140,4 +140,4 @@ Replace `Z11111112222222333333` with your hosted zone ID and `example.com` with
|
||||||
|
|
||||||
[Links]
|
[Links]
|
||||||
API = "https://docs.aws.amazon.com/Route53/latest/APIReference/API_Operations_Amazon_Route_53.html"
|
API = "https://docs.aws.amazon.com/Route53/latest/APIReference/API_Operations_Amazon_Route_53.html"
|
||||||
GoClient = "https://github.com/aws/aws-sdk-go/aws"
|
GoClient = "https://github.com/aws/aws-sdk-go-v2"
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
package route53
|
package route53
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/aws/aws-sdk-go/aws"
|
"github.com/aws/aws-sdk-go-v2/aws"
|
||||||
"github.com/aws/aws-sdk-go/aws/session"
|
awsconfig "github.com/aws/aws-sdk-go-v2/config"
|
||||||
"github.com/aws/aws-sdk-go/service/route53"
|
"github.com/aws/aws-sdk-go-v2/service/route53"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -26,9 +27,13 @@ func TestLiveTTL(t *testing.T) {
|
||||||
|
|
||||||
// we need a separate R53 client here as the one in the DNS provider is unexported.
|
// we need a separate R53 client here as the one in the DNS provider is unexported.
|
||||||
fqdn := "_acme-challenge." + domain + "."
|
fqdn := "_acme-challenge." + domain + "."
|
||||||
sess, err := session.NewSession()
|
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
cfg, err := awsconfig.LoadDefaultConfig(ctx)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
svc := route53.New(sess)
|
|
||||||
|
svc := route53.NewFromConfig(cfg)
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
errC := provider.CleanUp(domain, "foo", "bar")
|
errC := provider.CleanUp(domain, "foo", "bar")
|
||||||
|
@ -37,17 +42,17 @@ func TestLiveTTL(t *testing.T) {
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
zoneID, err := provider.getHostedZoneID(fqdn)
|
zoneID, err := provider.getHostedZoneID(context.Background(), fqdn)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
params := &route53.ListResourceRecordSetsInput{
|
params := &route53.ListResourceRecordSetsInput{
|
||||||
HostedZoneId: aws.String(zoneID),
|
HostedZoneId: aws.String(zoneID),
|
||||||
}
|
}
|
||||||
resp, err := svc.ListResourceRecordSets(params)
|
resp, err := svc.ListResourceRecordSets(ctx, params)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
for _, v := range resp.ResourceRecordSets {
|
for _, v := range resp.ResourceRecordSets {
|
||||||
if aws.StringValue(v.Name) == fqdn && aws.StringValue(v.Type) == "TXT" && aws.Int64Value(v.TTL) == 10 {
|
if deref(v.Name) == fqdn && v.Type == "TXT" && deref(v.TTL) == 10 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,15 @@
|
||||||
package route53
|
package route53
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/aws/aws-sdk-go/aws"
|
"github.com/aws/aws-sdk-go-v2/aws"
|
||||||
"github.com/aws/aws-sdk-go/aws/credentials"
|
awsconfig "github.com/aws/aws-sdk-go-v2/config"
|
||||||
"github.com/aws/aws-sdk-go/aws/session"
|
"github.com/aws/aws-sdk-go-v2/credentials"
|
||||||
"github.com/aws/aws-sdk-go/service/route53"
|
"github.com/aws/aws-sdk-go-v2/service/route53"
|
||||||
"github.com/go-acme/lego/v4/platform/tester"
|
"github.com/go-acme/lego/v4/platform/tester"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
@ -28,21 +29,26 @@ var envTest = tester.NewEnvTest(
|
||||||
WithDomain(envDomain).
|
WithDomain(envDomain).
|
||||||
WithLiveTestRequirements(EnvAccessKeyID, EnvSecretAccessKey, EnvRegion, envDomain)
|
WithLiveTestRequirements(EnvAccessKeyID, EnvSecretAccessKey, EnvRegion, envDomain)
|
||||||
|
|
||||||
|
type endpointResolverMock struct {
|
||||||
|
endpoint string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e endpointResolverMock) ResolveEndpoint(_, _ string, _ ...interface{}) (aws.Endpoint, error) {
|
||||||
|
return aws.Endpoint{URL: e.endpoint}, nil
|
||||||
|
}
|
||||||
|
|
||||||
func makeTestProvider(t *testing.T, serverURL string) *DNSProvider {
|
func makeTestProvider(t *testing.T, serverURL string) *DNSProvider {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
config := &aws.Config{
|
cfg := aws.Config{
|
||||||
Credentials: credentials.NewStaticCredentials("abc", "123", " "),
|
Credentials: credentials.NewStaticCredentialsProvider("abc", "123", " "),
|
||||||
Endpoint: aws.String(serverURL),
|
Region: "mock-region",
|
||||||
Region: aws.String("mock-region"),
|
EndpointResolverWithOptions: endpointResolverMock{endpoint: serverURL},
|
||||||
MaxRetries: aws.Int(1),
|
RetryMaxAttempts: 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
sess, err := session.NewSession(config)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
return &DNSProvider{
|
return &DNSProvider{
|
||||||
client: route53.New(sess),
|
client: route53.NewFromConfig(cfg),
|
||||||
config: NewDefaultConfig(),
|
config: NewDefaultConfig(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -55,22 +61,21 @@ func Test_loadCredentials_FromEnv(t *testing.T) {
|
||||||
_ = os.Setenv(EnvSecretAccessKey, "456")
|
_ = os.Setenv(EnvSecretAccessKey, "456")
|
||||||
_ = os.Setenv(EnvRegion, "us-east-1")
|
_ = os.Setenv(EnvRegion, "us-east-1")
|
||||||
|
|
||||||
config := &aws.Config{
|
ctx := context.Background()
|
||||||
CredentialsChainVerboseErrors: aws.Bool(true),
|
|
||||||
}
|
|
||||||
|
|
||||||
sess, err := session.NewSession(config)
|
cfg, err := awsconfig.LoadDefaultConfig(ctx)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
value, err := sess.Config.Credentials.Get()
|
value, err := cfg.Credentials.Retrieve(ctx)
|
||||||
require.NoError(t, err, "Expected credentials to be set from environment")
|
require.NoError(t, err, "Expected credentials to be set from environment")
|
||||||
|
|
||||||
expected := credentials.Value{
|
expected := aws.Credentials{
|
||||||
AccessKeyID: "123",
|
AccessKeyID: "123",
|
||||||
SecretAccessKey: "456",
|
SecretAccessKey: "456",
|
||||||
SessionToken: "",
|
SessionToken: "",
|
||||||
ProviderName: "EnvConfigCredentials",
|
Source: "EnvConfigCredentials",
|
||||||
}
|
}
|
||||||
|
|
||||||
assert.Equal(t, expected, value)
|
assert.Equal(t, expected, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,13 +83,12 @@ func Test_loadRegion_FromEnv(t *testing.T) {
|
||||||
defer envTest.RestoreEnv()
|
defer envTest.RestoreEnv()
|
||||||
envTest.ClearEnv()
|
envTest.ClearEnv()
|
||||||
|
|
||||||
os.Setenv(EnvRegion, route53.CloudWatchRegionUsEast1)
|
_ = os.Setenv(EnvRegion, "foo")
|
||||||
|
|
||||||
sess, err := session.NewSession(aws.NewConfig())
|
cfg, err := awsconfig.LoadDefaultConfig(context.Background())
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
region := aws.StringValue(sess.Config.Region)
|
assert.Equal(t, "foo", cfg.Region, "Region")
|
||||||
assert.Equal(t, route53.CloudWatchRegionUsEast1, region, "Region")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_getHostedZoneID_FromEnv(t *testing.T) {
|
func Test_getHostedZoneID_FromEnv(t *testing.T) {
|
||||||
|
@ -93,12 +97,12 @@ func Test_getHostedZoneID_FromEnv(t *testing.T) {
|
||||||
|
|
||||||
expectedZoneID := "zoneID"
|
expectedZoneID := "zoneID"
|
||||||
|
|
||||||
os.Setenv(EnvHostedZoneID, expectedZoneID)
|
_ = os.Setenv(EnvHostedZoneID, expectedZoneID)
|
||||||
|
|
||||||
provider, err := NewDNSProvider()
|
provider, err := NewDNSProvider()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
hostedZoneID, err := provider.getHostedZoneID("whatever")
|
hostedZoneID, err := provider.getHostedZoneID(context.Background(), "whatever")
|
||||||
require.NoError(t, err, "HostedZoneID")
|
require.NoError(t, err, "HostedZoneID")
|
||||||
|
|
||||||
assert.Equal(t, expectedZoneID, hostedZoneID)
|
assert.Equal(t, expectedZoneID, hostedZoneID)
|
||||||
|
@ -144,7 +148,7 @@ func TestNewDefaultConfig(t *testing.T) {
|
||||||
t.Run(test.desc, func(t *testing.T) {
|
t.Run(test.desc, func(t *testing.T) {
|
||||||
envTest.ClearEnv()
|
envTest.ClearEnv()
|
||||||
for key, value := range test.envVars {
|
for key, value := range test.envVars {
|
||||||
os.Setenv(key, value)
|
_ = os.Setenv(key, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
config := NewDefaultConfig()
|
config := NewDefaultConfig()
|
||||||
|
@ -157,7 +161,7 @@ func TestNewDefaultConfig(t *testing.T) {
|
||||||
func TestDNSProvider_Present(t *testing.T) {
|
func TestDNSProvider_Present(t *testing.T) {
|
||||||
mockResponses := MockResponseMap{
|
mockResponses := MockResponseMap{
|
||||||
"/2013-04-01/hostedzonesbyname": {StatusCode: 200, Body: ListHostedZonesByNameResponse},
|
"/2013-04-01/hostedzonesbyname": {StatusCode: 200, Body: ListHostedZonesByNameResponse},
|
||||||
"/2013-04-01/hostedzone/ABCDEFG/rrset/": {StatusCode: 200, Body: ChangeResourceRecordSetsResponse},
|
"/2013-04-01/hostedzone/ABCDEFG/rrset": {StatusCode: 200, Body: ChangeResourceRecordSetsResponse},
|
||||||
"/2013-04-01/change/123456": {StatusCode: 200, Body: GetChangeResponse},
|
"/2013-04-01/change/123456": {StatusCode: 200, Body: GetChangeResponse},
|
||||||
"/2013-04-01/hostedzone/ABCDEFG/rrset?name=_acme-challenge.example.com.&type=TXT": {
|
"/2013-04-01/hostedzone/ABCDEFG/rrset?name=_acme-challenge.example.com.&type=TXT": {
|
||||||
StatusCode: 200,
|
StatusCode: 200,
|
||||||
|
@ -178,12 +182,12 @@ func TestDNSProvider_Present(t *testing.T) {
|
||||||
require.NoError(t, err, "Expected Present to return no error")
|
require.NoError(t, err, "Expected Present to return no error")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCreateSession(t *testing.T) {
|
func Test_createAWSConfig(t *testing.T) {
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
desc string
|
desc string
|
||||||
env map[string]string
|
env map[string]string
|
||||||
config *Config
|
config *Config
|
||||||
wantCreds credentials.Value
|
wantCreds aws.Credentials
|
||||||
wantDefaultChain bool
|
wantDefaultChain bool
|
||||||
wantRegion string
|
wantRegion string
|
||||||
wantErr string
|
wantErr string
|
||||||
|
@ -218,11 +222,11 @@ func TestCreateSession(t *testing.T) {
|
||||||
AccessKeyID: "one",
|
AccessKeyID: "one",
|
||||||
SecretAccessKey: "two",
|
SecretAccessKey: "two",
|
||||||
},
|
},
|
||||||
wantCreds: credentials.Value{
|
wantCreds: aws.Credentials{
|
||||||
AccessKeyID: "one",
|
AccessKeyID: "one",
|
||||||
SecretAccessKey: "two",
|
SecretAccessKey: "two",
|
||||||
SessionToken: "",
|
SessionToken: "",
|
||||||
ProviderName: credentials.StaticProviderName,
|
Source: credentials.StaticCredentialsName,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -232,11 +236,11 @@ func TestCreateSession(t *testing.T) {
|
||||||
SecretAccessKey: "two",
|
SecretAccessKey: "two",
|
||||||
SessionToken: "three",
|
SessionToken: "three",
|
||||||
},
|
},
|
||||||
wantCreds: credentials.Value{
|
wantCreds: aws.Credentials{
|
||||||
AccessKeyID: "one",
|
AccessKeyID: "one",
|
||||||
SecretAccessKey: "two",
|
SecretAccessKey: "two",
|
||||||
SessionToken: "three",
|
SessionToken: "three",
|
||||||
ProviderName: credentials.StaticProviderName,
|
Source: credentials.StaticCredentialsName,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -268,24 +272,26 @@ func TestCreateSession(t *testing.T) {
|
||||||
|
|
||||||
envTest.Apply(test.env)
|
envTest.Apply(test.env)
|
||||||
|
|
||||||
sess, err := createSession(test.config)
|
ctx := context.Background()
|
||||||
|
|
||||||
|
cfg, err := createAWSConfig(ctx, test.config)
|
||||||
requireErr(t, err, test.wantErr)
|
requireErr(t, err, test.wantErr)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
gotCreds, err := sess.Config.Credentials.Get()
|
gotCreds, err := cfg.Credentials.Retrieve(ctx)
|
||||||
|
|
||||||
if test.wantDefaultChain {
|
if test.wantDefaultChain {
|
||||||
assert.NotEqual(t, credentials.StaticProviderName, gotCreds.ProviderName)
|
assert.NotEqual(t, credentials.StaticCredentialsName, gotCreds.Source)
|
||||||
} else {
|
} else {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, test.wantCreds, gotCreds)
|
assert.Equal(t, test.wantCreds, gotCreds)
|
||||||
}
|
}
|
||||||
|
|
||||||
if test.wantRegion != "" {
|
if test.wantRegion != "" {
|
||||||
assert.Equal(t, test.wantRegion, aws.StringValue(sess.Config.Region))
|
assert.Equal(t, test.wantRegion, cfg.Region)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue