mirror of
https://github.com/coredns/coredns.git
synced 2025-10-27 08:14:18 -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
|
The route53 plugin is useful for serving zones from resource record
|
||||||
sets in AWS route53. This plugin supports all Amazon Route 53 records
|
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)).
|
([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
|
## Syntax
|
||||||
|
|
||||||
@@ -31,9 +31,9 @@ route53 [ZONE:HOSTED_ZONE_ID...] {
|
|||||||
accessed.
|
accessed.
|
||||||
|
|
||||||
* **AWS\_ACCESS\_KEY\_ID** and **AWS\_SECRET\_ACCESS\_KEY** the AWS access key ID and secret access key
|
* **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
|
to be used when querying AWS (optional). If they are not provided, CoreDNS tries to access
|
||||||
AWS credentials the same way as AWS CLI, e.g., environmental variables, AWS credentials file,
|
AWS credentials the same way as AWS CLI - environment variables, shared credential file (and optionally
|
||||||
instance profile credentials, etc.
|
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,
|
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
|
user can use other methods to pass crentials, e.g., with environmental variable `AWS_ACCESS_KEY_ID` and
|
||||||
`AWS_SECRET_ACCESS_KEY`, respectively.
|
`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
|
* `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.
|
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 overriding the shared credentials **FILENAME** and the **PROFILE** name for a
|
||||||
zone. **PROFILE** is the AWS account profile name. Defaults to `default`. **FILENAME** is the
|
given zone. **PROFILE** is the AWS account profile name. Defaults to `default`. **FILENAME** is the
|
||||||
AWS credentials filename, defaults to `~/.aws/credentials`.
|
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.
|
* `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
|
If **ZONES** is omitted, then fallthrough happens for all zones for which the plugin is
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package route53
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@@ -26,8 +27,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, endpoint *string) route53iface.Route53API {
|
var f = func(opts session.Options) route53iface.Route53API {
|
||||||
return route53.New(session.Must(session.NewSession(&aws.Config{Credentials: credential, Endpoint: endpoint})))
|
return route53.New(session.Must(session.NewSessionWithOptions(opts)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func setup(c *caddy.Controller) error {
|
func setup(c *caddy.Controller) error {
|
||||||
@@ -35,16 +36,15 @@ func setup(c *caddy.Controller) error {
|
|||||||
keyPairs := map[string]struct{}{}
|
keyPairs := map[string]struct{}{}
|
||||||
keys := map[string][]string{}
|
keys := map[string][]string{}
|
||||||
|
|
||||||
// Route53 plugin attempts to find AWS credentials by using ChainCredentials.
|
// Route53 plugin attempts to load AWS credentials following default SDK chaining.
|
||||||
// And the order of that provider chain is as follows:
|
// The order configuration is loaded in is:
|
||||||
// Static AWS keys -> Environment Variables -> Credentials file -> IAM role
|
// * Static AWS keys set in Corefile (deprecated)
|
||||||
// With that said, even though a user doesn't define any credentials in
|
// * Environment Variables
|
||||||
// Corefile, we should still attempt to read the default credentials file,
|
// * Shared Credentials file
|
||||||
// ~/.aws/credentials with the default profile.
|
// * Shared Configuration file (if AWS_SDK_LOAD_CONFIG is set to truthy value)
|
||||||
sharedProvider := &credentials.SharedCredentialsProvider{}
|
// * EC2 Instance Metadata (credentials only)
|
||||||
var providers []credentials.Provider
|
opts := session.Options{}
|
||||||
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
|
||||||
|
|
||||||
@@ -74,16 +74,11 @@ func setup(c *caddy.Controller) error {
|
|||||||
if len(v) < 2 {
|
if len(v) < 2 {
|
||||||
return plugin.Error("route53", c.Errf("invalid access key: '%v'", v))
|
return plugin.Error("route53", c.Errf("invalid access key: '%v'", v))
|
||||||
}
|
}
|
||||||
providers = append(providers, &credentials.StaticProvider{
|
opts.Config.Credentials = credentials.NewStaticCredentials(v[0], v[1], "")
|
||||||
Value: credentials.Value{
|
|
||||||
AccessKeyID: v[0],
|
|
||||||
SecretAccessKey: v[1],
|
|
||||||
},
|
|
||||||
})
|
|
||||||
log.Warningf("Save aws_access_key in Corefile has been deprecated, please use other authentication methods instead")
|
log.Warningf("Save aws_access_key in Corefile has been deprecated, please use other authentication methods instead")
|
||||||
case "aws_endpoint":
|
case "aws_endpoint":
|
||||||
if c.NextArg() {
|
if c.NextArg() {
|
||||||
endpoint = c.Val()
|
opts.Config.Endpoint = aws.String(c.Val())
|
||||||
} else {
|
} else {
|
||||||
return plugin.Error("route53", c.ArgErr())
|
return plugin.Error("route53", c.ArgErr())
|
||||||
}
|
}
|
||||||
@@ -91,12 +86,17 @@ func setup(c *caddy.Controller) error {
|
|||||||
c.RemainingArgs() // eats args
|
c.RemainingArgs() // eats args
|
||||||
case "credentials":
|
case "credentials":
|
||||||
if c.NextArg() {
|
if c.NextArg() {
|
||||||
sharedProvider.Profile = c.Val()
|
opts.Profile = c.Val()
|
||||||
} else {
|
} else {
|
||||||
return c.ArgErr()
|
return c.ArgErr()
|
||||||
}
|
}
|
||||||
if c.NextArg() {
|
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":
|
case "fallthrough":
|
||||||
fall.SetZonesFromArgs(c.RemainingArgs())
|
fall.SetZonesFromArgs(c.RemainingArgs())
|
||||||
@@ -122,13 +122,7 @@ func setup(c *caddy.Controller) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
session, err := session.NewSession(&aws.Config{})
|
client := f(opts)
|
||||||
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)
|
|
||||||
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 {
|
||||||
|
|||||||
@@ -5,12 +5,12 @@ import (
|
|||||||
|
|
||||||
"github.com/coredns/caddy"
|
"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"
|
"github.com/aws/aws-sdk-go/service/route53/route53iface"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestSetupRoute53(t *testing.T) {
|
func TestSetupRoute53(t *testing.T) {
|
||||||
f = func(credential *credentials.Credentials, endpoint *string) route53iface.Route53API {
|
f = func(opts session.Options) route53iface.Route53API {
|
||||||
return fakeRoute53{}
|
return fakeRoute53{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user