diff options
author | 2022-05-09 10:35:42 -0700 | |
---|---|---|
committer | 2022-05-09 13:35:42 -0400 | |
commit | 2895b067324f8d9add221f24020b5b4e4fc237bc (patch) | |
tree | 6d539b89ccba0b421ea282bc1f735fa51d4b4a4c | |
parent | be009ed6729b1710d149be33236b6d8032010981 (diff) | |
download | coredns-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.md | 17 | ||||
-rw-r--r-- | plugin/route53/setup.go | 48 | ||||
-rw-r--r-- | plugin/route53/setup_test.go | 4 |
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{} } |