mirror of
https://github.com/coredns/coredns.git
synced 2025-10-27 16:24:19 -04:00
[plugin/route53] Cleanup AWS config/credentials setup. (#5370)
Signed-off-by: Dmitry Ilyevsky <ilyevsky@gmail.com>
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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{}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user