builder/amazon: Use sdk default cred providers
I think we were overcomplicating things. The SDK provides the correct credential chain by default, so let's use that. This patch does a quick check for static credentials and uses those if found, then defaults to the default credential provider chain. This patch also removes the metadata timeout argument. Current versions of the SDK have short timeouts by default, so I don't believe this is needed.
This commit is contained in:
parent
e483087574
commit
b16f2ec64b
|
@ -3,14 +3,12 @@ package common
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/aws/aws-sdk-go/aws"
|
"github.com/aws/aws-sdk-go/aws"
|
||||||
"github.com/aws/aws-sdk-go/aws/awserr"
|
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||||
"github.com/aws/aws-sdk-go/aws/credentials"
|
"github.com/aws/aws-sdk-go/aws/credentials"
|
||||||
"github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds"
|
|
||||||
"github.com/aws/aws-sdk-go/aws/ec2metadata"
|
"github.com/aws/aws-sdk-go/aws/ec2metadata"
|
||||||
"github.com/aws/aws-sdk-go/aws/session"
|
"github.com/aws/aws-sdk-go/aws/session"
|
||||||
"github.com/hashicorp/go-cleanhttp"
|
"github.com/hashicorp/go-cleanhttp"
|
||||||
|
@ -38,66 +36,13 @@ func (c *AccessConfig) Session() (*session.Session, error) {
|
||||||
return c.session, nil
|
return c.session, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// build a chain provider, lazy-evaluated by aws-sdk
|
|
||||||
providers := []credentials.Provider{
|
|
||||||
&credentials.StaticProvider{Value: credentials.Value{
|
|
||||||
AccessKeyID: c.AccessKey,
|
|
||||||
SecretAccessKey: c.SecretKey,
|
|
||||||
SessionToken: c.Token,
|
|
||||||
}},
|
|
||||||
&credentials.EnvProvider{},
|
|
||||||
&credentials.SharedCredentialsProvider{
|
|
||||||
Filename: "",
|
|
||||||
Profile: c.ProfileName,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build isolated HTTP client to avoid issues with globally-shared settings
|
|
||||||
client := cleanhttp.DefaultClient()
|
|
||||||
|
|
||||||
// Keep the default timeout (100ms) low as we don't want to wait in non-EC2 environments
|
|
||||||
client.Timeout = 100 * time.Millisecond
|
|
||||||
|
|
||||||
const userTimeoutEnvVar = "AWS_METADATA_TIMEOUT"
|
|
||||||
userTimeout := os.Getenv(userTimeoutEnvVar)
|
|
||||||
if userTimeout != "" {
|
|
||||||
newTimeout, err := time.ParseDuration(userTimeout)
|
|
||||||
if err == nil {
|
|
||||||
if newTimeout.Nanoseconds() > 0 {
|
|
||||||
client.Timeout = newTimeout
|
|
||||||
} else {
|
|
||||||
log.Printf("[WARN] Non-positive value of %s (%s) is meaningless, ignoring", userTimeoutEnvVar, newTimeout.String())
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
log.Printf("[WARN] Error converting %s to time.Duration: %s", userTimeoutEnvVar, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Printf("[INFO] Setting AWS metadata API timeout to %s", client.Timeout.String())
|
|
||||||
cfg := &aws.Config{
|
|
||||||
HTTPClient: client,
|
|
||||||
}
|
|
||||||
if !c.SkipMetadataApiCheck {
|
|
||||||
// Real AWS should reply to a simple metadata request.
|
|
||||||
// We check it actually does to ensure something else didn't just
|
|
||||||
// happen to be listening on the same IP:Port
|
|
||||||
metadataClient := ec2metadata.New(session.New(cfg))
|
|
||||||
if metadataClient.Available() {
|
|
||||||
providers = append(providers, &ec2rolecreds.EC2RoleProvider{
|
|
||||||
Client: metadataClient,
|
|
||||||
})
|
|
||||||
log.Print("[INFO] AWS EC2 instance detected via default metadata" +
|
|
||||||
" API endpoint, EC2RoleProvider added to the auth chain")
|
|
||||||
} else {
|
|
||||||
log.Printf("[INFO] Ignoring AWS metadata API endpoint " +
|
|
||||||
"as it doesn't return any instance-id")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
creds := credentials.NewChainCredentials(providers)
|
|
||||||
|
|
||||||
config := aws.NewConfig().WithCredentialsChainVerboseErrors(true)
|
config := aws.NewConfig().WithCredentialsChainVerboseErrors(true)
|
||||||
|
|
||||||
|
staticCreds := credentials.NewStaticCredentials(c.AccessKey, c.SecretKey, c.Token)
|
||||||
|
if _, err := staticCreds.Get(); err != credentials.ErrStaticCredentialsEmpty {
|
||||||
|
config.WithCredentials(staticCreds)
|
||||||
|
}
|
||||||
|
|
||||||
if c.RawRegion != "" {
|
if c.RawRegion != "" {
|
||||||
config = config.WithRegion(c.RawRegion)
|
config = config.WithRegion(c.RawRegion)
|
||||||
} else if region := c.metadataRegion(); region != "" {
|
} else if region := c.metadataRegion(); region != "" {
|
||||||
|
@ -123,8 +68,6 @@ func (c *AccessConfig) Session() (*session.Session, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
config = config.WithCredentials(creds)
|
|
||||||
|
|
||||||
if sess, err := session.NewSessionWithOptions(opts); err != nil {
|
if sess, err := session.NewSessionWithOptions(opts); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
} else if *sess.Config.Region == "" {
|
} else if *sess.Config.Region == "" {
|
||||||
|
@ -185,6 +128,9 @@ func (c *AccessConfig) metadataRegion() string {
|
||||||
func (c *AccessConfig) Prepare(ctx *interpolate.Context) []error {
|
func (c *AccessConfig) Prepare(ctx *interpolate.Context) []error {
|
||||||
var errs []error
|
var errs []error
|
||||||
|
|
||||||
|
if c.SkipMetadataApiCheck {
|
||||||
|
log.Println("(WARN) skip_metadata_api_check ignored.")
|
||||||
|
}
|
||||||
// Either both access and secret key must be set or neither of them should
|
// Either both access and secret key must be set or neither of them should
|
||||||
// be.
|
// be.
|
||||||
if (len(c.AccessKey) > 0) != (len(c.SecretKey) > 0) {
|
if (len(c.AccessKey) > 0) != (len(c.SecretKey) > 0) {
|
||||||
|
|
|
@ -123,14 +123,6 @@ This is a preferred approach over any other when running in EC2 as you can
|
||||||
avoid hard coding credentials. Instead these are leased on-the-fly by Packer,
|
avoid hard coding credentials. Instead these are leased on-the-fly by Packer,
|
||||||
which reduces the chance of leakage.
|
which reduces the chance of leakage.
|
||||||
|
|
||||||
The default deadline for the EC2 metadata API endpoint is 100 milliseconds,
|
|
||||||
which can be overidden by setting the `AWS_METADATA_TIMEOUT` environment
|
|
||||||
variable. The variable expects a positive golang Time.Duration string, which is
|
|
||||||
a sequence of decimal numbers and a unit suffix; valid suffixes are `ns`
|
|
||||||
(nanoseconds), `us` (microseconds), `ms` (milliseconds), `s` (seconds), `m`
|
|
||||||
(minutes), and `h` (hours). Examples of valid inputs: `100ms`, `250ms`, `1s`,
|
|
||||||
`2.5s`, `2.5m`, `1m30s`.
|
|
||||||
|
|
||||||
The following policy document provides the minimal set permissions necessary
|
The following policy document provides the minimal set permissions necessary
|
||||||
for Packer to work:
|
for Packer to work:
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue