builder/amazon: Cleaned up credential handeling

This properly handles:
- Preference between types of credential
- Assume role via ECS Task Role
This commit is contained in:
Rickard von Essen 2017-02-25 20:08:53 +01:00 committed by Matthew Hooker
parent 7360ba4fd7
commit 3833d34829
No known key found for this signature in database
GPG Key ID: 7B5F933D9CE8C6A1
2 changed files with 28 additions and 60 deletions

View File

@ -4,11 +4,12 @@ import (
"fmt"
"log"
"github.com/aws/aws-sdk-go/aws/ec2metadata"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/hashicorp/packer/builder/amazon/common"
"github.com/hashicorp/packer/packer"
"github.com/mitchellh/multistep"
)
// StepInstanceInfo verifies that this builder is running on an EC2 instance.
type StepInstanceInfo struct{}
@ -19,9 +20,11 @@ func (s *StepInstanceInfo) Run(state multistep.StateBag) multistep.StepAction {
// Get our own instance ID
ui.Say("Gathering information about this EC2 instance...")
instanceIdBytes, err := common.GetInstanceMetaData("instance-id")
sess := session.New()
ec2meta := ec2metadata.New(sess)
identity, err := ec2meta.GetInstanceIdentityDocument()
if err != nil {
log.Printf("Error: %s", err)
err := fmt.Errorf(
"Error retrieving the ID of the instance Packer is running on.\n" +
"Please verify Packer is running on a proper AWS EC2 instance.")
@ -29,12 +32,10 @@ func (s *StepInstanceInfo) Run(state multistep.StateBag) multistep.StepAction {
ui.Error(err.Error())
return multistep.ActionHalt
}
instanceId := string(instanceIdBytes)
log.Printf("Instance ID: %s", instanceId)
log.Printf("Instance ID: %s", identity.InstanceID)
// Query the entire instance metadata
instancesResp, err := ec2conn.DescribeInstances(&ec2.DescribeInstancesInput{InstanceIds: []*string{&instanceId}})
instancesResp, err := ec2conn.DescribeInstances(&ec2.DescribeInstancesInput{InstanceIds: []*string{&identity.InstanceID}})
if err != nil {
err := fmt.Errorf("Error getting instance data: %s", err)
state.Put("error", err)

View File

@ -2,14 +2,10 @@ package common
import (
"fmt"
"io/ioutil"
"net/http"
"strings"
"unicode"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds"
"github.com/aws/aws-sdk-go/aws/defaults"
"github.com/aws/aws-sdk-go/aws/ec2metadata"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/hashicorp/packer/template/interpolate"
@ -35,35 +31,27 @@ func (c *AccessConfig) Config() (*aws.Config, error) {
if err != nil {
return nil, err
}
config := aws.NewConfig().WithRegion(region).WithMaxRetries(11)
config := aws.NewConfig().WithRegion(region).WithMaxRetries(11)
if c.CustomEndpointEc2 != "" {
config.Endpoint = &c.CustomEndpointEc2
}
if c.ProfileName != "" {
profile, err := NewFromProfile(c.ProfileName)
if err != nil {
return nil, err
}
creds, err = profile.CredentialsFromProfile(config)
if err != nil {
return nil, err
}
} else {
creds = credentials.NewChainCredentials([]credentials.Provider{
&credentials.StaticProvider{Value: credentials.Value{
AccessKeyID: c.AccessKey,
SecretAccessKey: c.SecretKey,
SessionToken: c.Token,
}},
&credentials.EnvProvider{},
&credentials.SharedCredentialsProvider{Filename: "", Profile: ""},
&ec2rolecreds.EC2RoleProvider{
Client: ec2metadata.New(session.New(config)),
creds = credentials.NewChainCredentials(
[]credentials.Provider{
&credentials.StaticProvider{
Value: credentials.Value{
AccessKeyID: c.AccessKey,
SecretAccessKey: c.SecretKey,
SessionToken: c.Token,
},
},
&credentials.EnvProvider{},
&credentials.SharedCredentialsProvider{
Profile: c.ProfileName,
},
defaults.RemoteCredProvider(*(defaults.Config()), defaults.Handlers()),
})
}
return config.WithCredentials(creds), nil
}
@ -79,13 +67,13 @@ func (c *AccessConfig) Region() (string, error) {
return c.RawRegion, nil
}
md, err := GetInstanceMetaData("placement/availability-zone")
sess := session.New()
ec2meta := ec2metadata.New(sess)
identity, err := ec2meta.GetInstanceIdentityDocument()
if err != nil {
return "", err
}
region := strings.TrimRightFunc(string(md), unicode.IsLetter)
return region, nil
return identity.Region, nil
}
func (c *AccessConfig) Prepare(ctx *interpolate.Context) []error {
@ -102,24 +90,3 @@ func (c *AccessConfig) Prepare(ctx *interpolate.Context) []error {
return nil
}
func GetInstanceMetaData(path string) (contents []byte, err error) {
url := "http://169.254.169.254/latest/meta-data/" + path
resp, err := http.Get(url)
if err != nil {
return
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
err = fmt.Errorf("Code %d returned for url %s", resp.StatusCode, url)
return
}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return
}
return body, err
}