aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar dilyevsky <ilyevsky@gmail.com> 2022-05-09 10:35:42 -0700
committerGravatar GitHub <noreply@github.com> 2022-05-09 13:35:42 -0400
commit2895b067324f8d9add221f24020b5b4e4fc237bc (patch)
tree6d539b89ccba0b421ea282bc1f735fa51d4b4a4c
parentbe009ed6729b1710d149be33236b6d8032010981 (diff)
downloadcoredns-2895b067324f8d9add221f24020b5b4e4fc237bc.tar.gz
coredns-2895b067324f8d9add221f24020b5b4e4fc237bc.tar.zst
coredns-2895b067324f8d9add221f24020b5b4e4fc237bc.zip
[plugin/route53] Cleanup AWS config/credentials setup. (#5370)
Signed-off-by: Dmitry Ilyevsky <ilyevsky@gmail.com>
-rw-r--r--plugin/route53/README.md17
-rw-r--r--plugin/route53/setup.go48
-rw-r--r--plugin/route53/setup_test.go4
3 files changed, 33 insertions, 36 deletions
diff --git a/plugin/route53/README.md b/plugin/route53/README.md
index d9efa8cc2..d3f982d17 100644
--- a/plugin/route53/README.md
+++ b/plugin/route53/README.md
@@ -9,7 +9,7 @@
The route53 plugin is useful for serving zones from resource record
sets in AWS route53. This plugin supports all Amazon Route 53 records
([https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/ResourceRecordTypes.html](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/ResourceRecordTypes.html)).
-The route53 plugin can be used when coredns is deployed on AWS or elsewhere.
+The route53 plugin can be used when CoreDNS is deployed on AWS or elsewhere.
## Syntax
@@ -31,9 +31,9 @@ route53 [ZONE:HOSTED_ZONE_ID...] {
accessed.
* **AWS\_ACCESS\_KEY\_ID** and **AWS\_SECRET\_ACCESS\_KEY** the AWS access key ID and secret access key
- to be used when query AWS (optional). If they are not provided, then coredns tries to access
- AWS credentials the same way as AWS CLI, e.g., environmental variables, AWS credentials file,
- instance profile credentials, etc.
+ to be used when querying AWS (optional). If they are not provided, CoreDNS tries to access
+ AWS credentials the same way as AWS CLI - environment variables, shared credential file (and optionally
+ shared config file if `AWS_SDK_LOAD_CONFIG` env is set), and lastly EC2 Instance Roles.
Note the usage of `aws_access_key` has been deprecated and may be removed in future versions. Instead,
user can use other methods to pass crentials, e.g., with environmental variable `AWS_ACCESS_KEY_ID` and
`AWS_SECRET_ACCESS_KEY`, respectively.
@@ -41,9 +41,12 @@ route53 [ZONE:HOSTED_ZONE_ID...] {
* `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
- zone. **PROFILE** is the AWS account profile name. Defaults to `default`. **FILENAME** is the
- AWS credentials filename, defaults to `~/.aws/credentials`.
+* `credentials` is used for overriding the shared credentials **FILENAME** and the **PROFILE** name for a
+ given zone. **PROFILE** is the AWS account profile name. Defaults to `default`. **FILENAME** is the
+ AWS shared credentials filename, defaults to `~/.aws/credentials`. CoreDNS will only load shared credentials
+ file and not shared config file (`~/.aws/config`) by default. Set `AWS_SDK_LOAD_CONFIG` env variable to
+ a truthy value to enable also loading of `~/.aws/config` (e.g. if you want to provide assumed IAM role
+ configuration). Will be ignored if static keys are set via `aws_access_key`.
* `fallthrough` If zone matches and no record can be generated, pass request to the next plugin.
If **ZONES** is omitted, then fallthrough happens for all zones for which the plugin is
diff --git a/plugin/route53/setup.go b/plugin/route53/setup.go
index 31176039a..e3117e706 100644
--- a/plugin/route53/setup.go
+++ b/plugin/route53/setup.go
@@ -3,6 +3,7 @@ package route53
import (
"context"
"fmt"
+ "os"
"strconv"
"strings"
"time"
@@ -26,8 +27,8 @@ var log = clog.NewWithPlugin("route53")
func init() { plugin.Register("route53", setup) }
// exposed for testing
-var f = func(credential *credentials.Credentials, endpoint *string) route53iface.Route53API {
- return route53.New(session.Must(session.NewSession(&aws.Config{Credentials: credential, Endpoint: endpoint})))
+var f = func(opts session.Options) route53iface.Route53API {
+ return route53.New(session.Must(session.NewSessionWithOptions(opts)))
}
func setup(c *caddy.Controller) error {
@@ -35,16 +36,15 @@ func setup(c *caddy.Controller) error {
keyPairs := map[string]struct{}{}
keys := map[string][]string{}
- // Route53 plugin attempts to find AWS credentials by using ChainCredentials.
- // And the order of that provider chain is as follows:
- // Static AWS keys -> Environment Variables -> Credentials file -> IAM role
- // With that said, even though a user doesn't define any credentials in
- // Corefile, we should still attempt to read the default credentials file,
- // ~/.aws/credentials with the default profile.
- sharedProvider := &credentials.SharedCredentialsProvider{}
- var providers []credentials.Provider
+ // Route53 plugin attempts to load AWS credentials following default SDK chaining.
+ // The order configuration is loaded in is:
+ // * Static AWS keys set in Corefile (deprecated)
+ // * Environment Variables
+ // * Shared Credentials file
+ // * Shared Configuration file (if AWS_SDK_LOAD_CONFIG is set to truthy value)
+ // * EC2 Instance Metadata (credentials only)
+ opts := session.Options{}
var fall fall.F
- var endpoint string
refresh := time.Duration(1) * time.Minute // default update frequency to 1 minute
@@ -74,16 +74,11 @@ func setup(c *caddy.Controller) error {
if len(v) < 2 {
return plugin.Error("route53", c.Errf("invalid access key: '%v'", v))
}
- providers = append(providers, &credentials.StaticProvider{
- Value: credentials.Value{
- AccessKeyID: v[0],
- SecretAccessKey: v[1],
- },
- })
+ opts.Config.Credentials = credentials.NewStaticCredentials(v[0], v[1], "")
log.Warningf("Save aws_access_key in Corefile has been deprecated, please use other authentication methods instead")
case "aws_endpoint":
if c.NextArg() {
- endpoint = c.Val()
+ opts.Config.Endpoint = aws.String(c.Val())
} else {
return plugin.Error("route53", c.ArgErr())
}
@@ -91,12 +86,17 @@ func setup(c *caddy.Controller) error {
c.RemainingArgs() // eats args
case "credentials":
if c.NextArg() {
- sharedProvider.Profile = c.Val()
+ opts.Profile = c.Val()
} else {
return c.ArgErr()
}
if c.NextArg() {
- sharedProvider.Filename = c.Val()
+ opts.SharedConfigFiles = []string{c.Val()}
+ // If AWS_SDK_LOAD_CONFIG is set also load ~/.aws/config to stay consistent
+ // with default SDK behavior.
+ if ok, _ := strconv.ParseBool(os.Getenv("AWS_SDK_LOAD_CONFIG")); ok {
+ opts.SharedConfigFiles = append(opts.SharedConfigFiles, defaults.SharedConfigFilename())
+ }
}
case "fallthrough":
fall.SetZonesFromArgs(c.RemainingArgs())
@@ -122,13 +122,7 @@ func setup(c *caddy.Controller) error {
}
}
- session, err := session.NewSession(&aws.Config{})
- if err != nil {
- return plugin.Error("route53", err)
- }
-
- providers = append(providers, &credentials.EnvProvider{}, sharedProvider, defaults.RemoteCredProvider(*session.Config, session.Handlers))
- client := f(credentials.NewChainCredentials(providers), &endpoint)
+ client := f(opts)
ctx, cancel := context.WithCancel(context.Background())
h, err := New(ctx, client, keys, refresh)
if err != nil {
diff --git a/plugin/route53/setup_test.go b/plugin/route53/setup_test.go
index 98e7caa8d..5d2792f5f 100644
--- a/plugin/route53/setup_test.go
+++ b/plugin/route53/setup_test.go
@@ -5,12 +5,12 @@ import (
"github.com/coredns/caddy"
- "github.com/aws/aws-sdk-go/aws/credentials"
+ "github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/route53/route53iface"
)
func TestSetupRoute53(t *testing.T) {
- f = func(credential *credentials.Credentials, endpoint *string) route53iface.Route53API {
+ f = func(opts session.Options) route53iface.Route53API {
return fakeRoute53{}
}