plugin/route53: Configurable AWS Endpoint (#4963)

Provide the ability to configure the AWS endpoint

Signed-off-by: Matthew Palmer <matthew.palmer@helpsystems.com>
This commit is contained in:
Matt Palmer 2021-11-08 14:45:45 +00:00 committed by GitHub
parent 3f031b6b65
commit e53bff9043
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 31 additions and 4 deletions

View file

@ -16,6 +16,7 @@ The route53 plugin can be used when coredns is deployed on AWS or elsewhere.
~~~ txt ~~~ txt
route53 [ZONE:HOSTED_ZONE_ID...] { route53 [ZONE:HOSTED_ZONE_ID...] {
aws_access_key [AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY] aws_access_key [AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY]
aws_endpoint ENDPOINT
credentials PROFILE [FILENAME] credentials PROFILE [FILENAME]
fallthrough [ZONES...] fallthrough [ZONES...]
refresh DURATION refresh DURATION
@ -34,6 +35,9 @@ route53 [ZONE:HOSTED_ZONE_ID...] {
AWS credentials the same way as AWS CLI, e.g., environmental variables, AWS credentials file, AWS credentials the same way as AWS CLI, e.g., environmental variables, AWS credentials file,
instance profile credentials, etc. instance profile credentials, etc.
* `aws_endpoint` can be used to control the endpoint to use when querying AWS (optional). **ENDPOINT** is the
URL of the endpoint to use. If this is not provided the default AWS endpoint resolution will occur.
* `credentials` is used for reading the credential **FILENAME** and setting the **PROFILE** name for a given * `credentials` is used for reading the credential **FILENAME** and setting the **PROFILE** name for a given
zone. **PROFILE** is the AWS account profile name. Defaults to `default`. **FILENAME** is the zone. **PROFILE** is the AWS account profile name. Defaults to `default`. **FILENAME** is the
AWS credentials filename, defaults to `~/.aws/credentials`. AWS credentials filename, defaults to `~/.aws/credentials`.
@ -75,6 +79,16 @@ example.org {
} }
~~~ ~~~
Enable route53 with an explicit AWS endpoint:
~~~ txt
example.org {
route53 example.org.:Z1Z2Z3Z4DZ5Z6Z7 {
aws_endpoint https://test.us-west-2.amazonaws.com
}
}
~~~
Enable route53 with fallthrough: Enable route53 with fallthrough:
~~~ txt ~~~ txt

View file

@ -26,8 +26,8 @@ var log = clog.NewWithPlugin("route53")
func init() { plugin.Register("route53", setup) } func init() { plugin.Register("route53", setup) }
// exposed for testing // exposed for testing
var f = func(credential *credentials.Credentials) route53iface.Route53API { var f = func(credential *credentials.Credentials, endpoint *string) route53iface.Route53API {
return route53.New(session.Must(session.NewSession(&aws.Config{Credentials: credential}))) return route53.New(session.Must(session.NewSession(&aws.Config{Credentials: credential, Endpoint: endpoint})))
} }
func setup(c *caddy.Controller) error { func setup(c *caddy.Controller) error {
@ -44,6 +44,7 @@ func setup(c *caddy.Controller) error {
sharedProvider := &credentials.SharedCredentialsProvider{} sharedProvider := &credentials.SharedCredentialsProvider{}
var providers []credentials.Provider var providers []credentials.Provider
var fall fall.F var fall fall.F
var endpoint string
refresh := time.Duration(1) * time.Minute // default update frequency to 1 minute refresh := time.Duration(1) * time.Minute // default update frequency to 1 minute
@ -79,6 +80,12 @@ func setup(c *caddy.Controller) error {
SecretAccessKey: v[1], SecretAccessKey: v[1],
}, },
}) })
case "aws_endpoint":
if c.NextArg() {
endpoint = c.Val()
} else {
return plugin.Error("route53", c.ArgErr())
}
case "upstream": case "upstream":
c.RemainingArgs() // eats args c.RemainingArgs() // eats args
case "credentials": case "credentials":
@ -120,7 +127,7 @@ func setup(c *caddy.Controller) error {
} }
providers = append(providers, &credentials.EnvProvider{}, sharedProvider, defaults.RemoteCredProvider(*session.Config, session.Handlers)) providers = append(providers, &credentials.EnvProvider{}, sharedProvider, defaults.RemoteCredProvider(*session.Config, session.Handlers))
client := f(credentials.NewChainCredentials(providers)) client := f(credentials.NewChainCredentials(providers), &endpoint)
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
h, err := New(ctx, client, keys, refresh) h, err := New(ctx, client, keys, refresh)
if err != nil { if err != nil {

View file

@ -10,7 +10,7 @@ import (
) )
func TestSetupRoute53(t *testing.T) { func TestSetupRoute53(t *testing.T) {
f = func(credential *credentials.Credentials) route53iface.Route53API { f = func(credential *credentials.Credentials, endpoint *string) route53iface.Route53API {
return fakeRoute53{} return fakeRoute53{}
} }
@ -70,6 +70,12 @@ func TestSetupRoute53(t *testing.T) {
{`route53 example.org { {`route53 example.org {
}`, true}, }`, true},
{`route53 example.org:12345678 {
aws_endpoint
}`, true},
{`route53 example.org:12345678 {
aws_endpoint https://localhost
}`, false},
} }
for _, test := range tests { for _, test := range tests {