providers/aws: detect credentials more robustly

aws hides its credentials in many places:
multiple env vars, config files,
ec2 metadata.

Terraform currently recognizes only the env vars;
to use the other options, you had to put in a
dummy empty value for access_key and secret_key.

Rather than duplicate all aws checks, ask the
aws sdk to fetch credentials earlier.
This commit is contained in:
Josh Bleecher Snyder 2015-05-06 20:02:09 -07:00
parent febf27a48e
commit ed67f8f588
2 changed files with 33 additions and 22 deletions

View File

@ -62,16 +62,9 @@ func (c *Config) Client() (interface{}, error) {
client.region = c.Region client.region = c.Region
log.Println("[INFO] Building AWS auth structure") log.Println("[INFO] Building AWS auth structure")
creds := credentials.NewChainCredentials([]credentials.Provider{ // We fetched all credential sources in Provider.
&credentials.StaticProvider{Value: credentials.Value{ // If it is available, it is stored in c.
AccessKeyID: c.AccessKey, creds := credentials.NewStaticCredentials(c.AccessKey, c.SecretKey, c.Token)
SecretAccessKey: c.SecretKey,
SessionToken: c.Token,
}},
&credentials.EnvProvider{},
&credentials.SharedCredentialsProvider{Filename: "", Profile: ""},
&credentials.EC2RoleProvider{},
})
awsConfig := &aws.Config{ awsConfig := &aws.Config{
Credentials: creds, Credentials: creds,
Region: c.Region, Region: c.Region,

View File

@ -1,6 +1,9 @@
package aws package aws
import ( import (
"sync"
"github.com/awslabs/aws-sdk-go/aws/credentials"
"github.com/hashicorp/terraform/helper/hashcode" "github.com/hashicorp/terraform/helper/hashcode"
"github.com/hashicorp/terraform/helper/schema" "github.com/hashicorp/terraform/helper/schema"
"github.com/hashicorp/terraform/terraform" "github.com/hashicorp/terraform/terraform"
@ -11,35 +14,50 @@ func Provider() terraform.ResourceProvider {
// TODO: Move the validation to this, requires conditional schemas // TODO: Move the validation to this, requires conditional schemas
// TODO: Move the configuration to this, requires validation // TODO: Move the configuration to this, requires validation
// Prepare to handle external sources of credentials.
// Static credentials are intentionally omitted;
// this is used when no static credentials are provided.
creds := credentials.NewChainCredentials([]credentials.Provider{
&credentials.EnvProvider{},
&credentials.SharedCredentialsProvider{},
&credentials.EC2RoleProvider{},
})
var credVal credentials.Value
var credErr error
var once sync.Once
getCreds := func() {
credVal, credErr = creds.Get()
}
return &schema.Provider{ return &schema.Provider{
Schema: map[string]*schema.Schema{ Schema: map[string]*schema.Schema{
"access_key": &schema.Schema{ "access_key": &schema.Schema{
Type: schema.TypeString, Type: schema.TypeString,
Required: true, Required: true,
DefaultFunc: schema.MultiEnvDefaultFunc([]string{ DefaultFunc: func() (interface{}, error) {
"AWS_ACCESS_KEY", once.Do(getCreds)
"AWS_ACCESS_KEY_ID", return credVal.AccessKeyID, credErr
}, nil), },
Description: descriptions["access_key"], Description: descriptions["access_key"],
}, },
"secret_key": &schema.Schema{ "secret_key": &schema.Schema{
Type: schema.TypeString, Type: schema.TypeString,
Required: true, Required: true,
DefaultFunc: schema.MultiEnvDefaultFunc([]string{ DefaultFunc: func() (interface{}, error) {
"AWS_SECRET_KEY", once.Do(getCreds)
"AWS_SECRET_ACCESS_KEY", return credVal.SecretAccessKey, credErr
}, nil), },
Description: descriptions["secret_key"], Description: descriptions["secret_key"],
}, },
"token": &schema.Schema{ "token": &schema.Schema{
Type: schema.TypeString, Type: schema.TypeString,
Optional: true, Optional: true,
DefaultFunc: schema.MultiEnvDefaultFunc([]string{ DefaultFunc: func() (interface{}, error) {
"AWS_SESSION_TOKEN", once.Do(getCreds)
"AWS_SECURITY_TOKEN", return credVal.SessionToken, credErr
}, ""), },
Description: descriptions["token"], Description: descriptions["token"],
}, },