From 56c513088b97e10b9753e1c2ae00f6b129dce952 Mon Sep 17 00:00:00 2001 From: Matthew Hooker Date: Wed, 1 Mar 2017 16:43:09 -0800 Subject: [PATCH] I think this was the intention --- builder/amazon/chroot/builder.go | 8 +- builder/amazon/common/access_config.go | 76 ++++++++++++++----- builder/amazon/common/step_ami_region_copy.go | 14 ++-- builder/amazon/ebs/builder.go | 7 +- builder/amazon/ebs/builder_acc_test.go | 7 +- builder/amazon/ebssurrogate/builder.go | 12 +-- builder/amazon/ebsvolume/builder.go | 10 +-- builder/amazon/instance/builder.go | 8 +- builder/amazon/instance/step_upload_bundle.go | 3 +- .../amazon-import/post-processor.go | 11 +-- 10 files changed, 75 insertions(+), 81 deletions(-) diff --git a/builder/amazon/chroot/builder.go b/builder/amazon/chroot/builder.go index da82e496b..65660cf4f 100644 --- a/builder/amazon/chroot/builder.go +++ b/builder/amazon/chroot/builder.go @@ -9,7 +9,6 @@ import ( "log" "runtime" - "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/ec2" awscommon "github.com/hashicorp/packer/builder/amazon/common" "github.com/hashicorp/packer/common" @@ -182,12 +181,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe return nil, errors.New("The amazon-chroot builder only works on Linux environments.") } - config, err := b.config.Config() - if err != nil { - return nil, err - } - - session, err := session.NewSession(config) + session, err := b.config.Session() if err != nil { return nil, err } diff --git a/builder/amazon/common/access_config.go b/builder/amazon/common/access_config.go index 856cd7fa7..e041df0b6 100644 --- a/builder/amazon/common/access_config.go +++ b/builder/amazon/common/access_config.go @@ -2,7 +2,8 @@ package common import ( "fmt" - "time" + "log" + "os" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/credentials" @@ -19,19 +20,30 @@ type AccessConfig struct { AssumeRoleArn string `mapstructure:"assume_role_arn"` CustomEndpointEc2 string `mapstructure:"custom_endpoint_ec2"` ExternalID string `mapstructure:"external_id"` + ExternalID string `mapstructure:"external_id"` + MFACode string `mapstructure:"mfa_code"` MFACode string `mapstructure:"mfa_code"` MFASerial string `mapstructure:"mfa_serial"` + MFASerial string `mapstructure:"mfa_serial"` + ProfileName string `mapstructure:"profile"` ProfileName string `mapstructure:"profile"` RawRegion string `mapstructure:"region"` + RawRegion string `mapstructure:"region"` + SecretKey string `mapstructure:"secret_key"` SecretKey string `mapstructure:"secret_key"` SkipValidation bool `mapstructure:"skip_region_validation"` + SkipValidation bool `mapstructure:"skip_region_validation"` Token string `mapstructure:"token"` + Token string `mapstructure:"token"` + session *session.Session } // Config returns a valid aws.Config object for access to AWS services, or // an error if the authentication and region couldn't be resolved -func (c *AccessConfig) Config() (*aws.Config, error) { - var creds *credentials.Credentials +func (c *AccessConfig) Session() (*session.Session, error) { + if c.session != nil { + return c.session, nil + } region, err := c.Region() if err != nil { @@ -59,26 +71,55 @@ func (c *AccessConfig) Config() (*aws.Config, error) { }) if c.AssumeRoleArn != "" { - var mfa func(*stscreds.AssumeRoleProvider) + var options []func(*stscreds.AssumeRoleProvider) if c.MFACode != "" { - mfa = func(p *stscreds.AssumeRoleProvider) { + options = append(options, func(p *stscreds.AssumeRoleProvider) { p.SerialNumber = aws.String(c.MFASerial) p.TokenProvider = func() (string, error) { return c.MFACode, nil } - } + }) } - - sess := session.Must(session.NewSession(config.WithCredentials(creds))) - creds = stscreds.NewCredentials(sess, c.AssumeRoleArn, mfa, func(p *stscreds.AssumeRoleProvider) { - p.Duration = time.Duration(60) * time.Minute - if len(c.ExternalID) > 0 { - p.ExternalID = aws.String(c.ExternalID) - } - }) - } - return config.WithCredentials(creds), nil + + if c.ProfileName != "" { + err := os.Setenv("AWS_PROFILE", c.ProfileName) + if err != nil { + log.Printf("Set env error: %s", err) + } + } + + config := aws.NewConfig().WithRegion(region).WithMaxRetries(11).WithCredentialsChainVerboseErrors(true) + + if c.AccessKey != "" { + creds := credentials.NewChainCredentials( + []credentials.Provider{ + &credentials.StaticProvider{ + Value: credentials.Value{ + AccessKeyID: c.AccessKey, + SecretAccessKey: c.SecretKey, + SessionToken: c.Token, + }, + }, + }) + config = config.WithCredentials(creds) + } + + opts := session.Options{ + SharedConfigState: session.SharedConfigEnable, + Config: *config, + } + if c.MFACode != "" { + opts.AssumeRoleTokenProvider = func() (string, error) { + return c.MFACode, nil + } + } + c.session, err = session.NewSessionWithOptions(opts) + if err != nil { + return nil, err + } + + return c.session, nil } // Region returns the aws.Region object for access to AWS services, requesting @@ -113,7 +154,8 @@ func (c *AccessConfig) Prepare(ctx *interpolate.Context) []error { hasAssumeRoleArn := len(c.AssumeRoleArn) > 0 hasMFASerial := len(c.MFASerial) > 0 hasMFACode := len(c.MFACode) > 0 - if hasAssumeRoleArn && (!hasMFACode || !hasMFASerial) { + if hasAssumeRoleArn && (hasMFACode != hasMFASerial) { + // either both mfa code and serial must be set, or neither. errs = append(errs, fmt.Errorf("Both mfa_serial and mfa_code must be specified.")) } diff --git a/builder/amazon/common/step_ami_region_copy.go b/builder/amazon/common/step_ami_region_copy.go index 1eb82653a..f98dcbb92 100644 --- a/builder/amazon/common/step_ami_region_copy.go +++ b/builder/amazon/common/step_ami_region_copy.go @@ -5,7 +5,6 @@ import ( "sync" "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/ec2" "github.com/hashicorp/packer/packer" @@ -91,21 +90,18 @@ func amiRegionCopy(state multistep.StateBag, config *AccessConfig, name string, isEncrypted := false // Connect to the region where the AMI will be copied to - awsConfig, err := config.Config() + session, err := config.Session() if err != nil { return "", snapshotIds, err } - awsConfig.Region = aws.String(target) - - session, err := session.NewSession(awsConfig) - if err != nil { - return "", snapshotIds, err - } - regionconn := ec2.New(session) // if we've provided a map of key ids to regions, use those keys. if len(keyID) > 0 { isEncrypted = true } + regionconn := ec2.New(session.Copy(&aws.Config{ + Region: aws.String(target)}, + )) + resp, err := regionconn.CopyImage(&ec2.CopyImageInput{ SourceRegion: &source, SourceImageId: &imageId, diff --git a/builder/amazon/ebs/builder.go b/builder/amazon/ebs/builder.go index 9b3b00897..79ef6e687 100644 --- a/builder/amazon/ebs/builder.go +++ b/builder/amazon/ebs/builder.go @@ -9,7 +9,6 @@ import ( "fmt" "log" - "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/ec2" awscommon "github.com/hashicorp/packer/builder/amazon/common" "github.com/hashicorp/packer/common" @@ -78,12 +77,8 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { } func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packer.Artifact, error) { - config, err := b.config.Config() - if err != nil { - return nil, err - } - session, err := session.NewSession(config) + session, err := b.config.Session() if err != nil { return nil, err } diff --git a/builder/amazon/ebs/builder_acc_test.go b/builder/amazon/ebs/builder_acc_test.go index c59712390..9ea9c87f9 100644 --- a/builder/amazon/ebs/builder_acc_test.go +++ b/builder/amazon/ebs/builder_acc_test.go @@ -6,7 +6,6 @@ import ( "testing" "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/ec2" "github.com/hashicorp/packer/builder/amazon/common" builderT "github.com/hashicorp/packer/helper/builder/testing" @@ -255,15 +254,11 @@ func testAccPreCheck(t *testing.T) { func testEC2Conn() (*ec2.EC2, error) { access := &common.AccessConfig{RawRegion: "us-east-1"} - config, err := access.Config() + session, err := access.Session() if err != nil { return nil, err } - session, err := session.NewSession(config) - if err != nil { - return nil, err - } return ec2.New(session), nil } diff --git a/builder/amazon/ebssurrogate/builder.go b/builder/amazon/ebssurrogate/builder.go index c0d680071..5508abde3 100644 --- a/builder/amazon/ebssurrogate/builder.go +++ b/builder/amazon/ebssurrogate/builder.go @@ -7,9 +7,7 @@ import ( "fmt" "log" - "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/ec2" - "github.com/hashicorp/errwrap" awscommon "github.com/hashicorp/packer/builder/amazon/common" "github.com/hashicorp/packer/common" "github.com/hashicorp/packer/helper/communicator" @@ -94,17 +92,11 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { } func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packer.Artifact, error) { - awsConfig, err := b.config.Config() + session, err := b.config.Session() if err != nil { return nil, err } - - awsSession, err := session.NewSession(awsConfig) - if err != nil { - return nil, errwrap.Wrapf("Error creating AWS Session: {{err}}", err) - } - - ec2conn := ec2.New(awsSession) + ec2conn := ec2.New(session) // If the subnet is specified but not the VpcId or AZ, try to determine them automatically if b.config.SubnetId != "" && (b.config.AvailabilityZone == "" || b.config.VpcId == "") { diff --git a/builder/amazon/ebsvolume/builder.go b/builder/amazon/ebsvolume/builder.go index dbdc46d09..098cb4c9e 100644 --- a/builder/amazon/ebsvolume/builder.go +++ b/builder/amazon/ebsvolume/builder.go @@ -6,9 +6,7 @@ import ( "fmt" "log" - "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/ec2" - "github.com/hashicorp/errwrap" awscommon "github.com/hashicorp/packer/builder/amazon/common" "github.com/hashicorp/packer/common" "github.com/hashicorp/packer/helper/communicator" @@ -72,16 +70,10 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { } func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packer.Artifact, error) { - config, err := b.config.Config() + session, err := b.config.Session() if err != nil { return nil, err } - - session, err := session.NewSession(config) - if err != nil { - return nil, errwrap.Wrapf("Error creating AWS Session: {{err}}", err) - } - ec2conn := ec2.New(session) // If the subnet is specified but not the VpcId or AZ, try to determine them automatically diff --git a/builder/amazon/instance/builder.go b/builder/amazon/instance/builder.go index 151205ddc..d45dc64d8 100644 --- a/builder/amazon/instance/builder.go +++ b/builder/amazon/instance/builder.go @@ -9,7 +9,6 @@ import ( "os" "strings" - "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/ec2" awscommon "github.com/hashicorp/packer/builder/amazon/common" "github.com/hashicorp/packer/common" @@ -164,12 +163,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { } func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packer.Artifact, error) { - config, err := b.config.Config() - if err != nil { - return nil, err - } - - session, err := session.NewSession(config) + session, err := b.config.Session() if err != nil { return nil, err } diff --git a/builder/amazon/instance/step_upload_bundle.go b/builder/amazon/instance/step_upload_bundle.go index 91a64918e..ef4aed5e0 100644 --- a/builder/amazon/instance/step_upload_bundle.go +++ b/builder/amazon/instance/step_upload_bundle.go @@ -38,7 +38,8 @@ func (s *StepUploadBundle) Run(state multistep.StateBag) multistep.StepAction { accessKey := config.AccessKey secretKey := config.SecretKey - accessConfig, err := config.AccessConfig.Config() + session, err := config.AccessConfig.Session() + accessConfig := session.Config if err == nil && accessKey == "" && secretKey == "" { credentials, err := accessConfig.Credentials.Get() if err == nil { diff --git a/post-processor/amazon-import/post-processor.go b/post-processor/amazon-import/post-processor.go index 2a6f9552c..f66c2435e 100644 --- a/post-processor/amazon-import/post-processor.go +++ b/post-processor/amazon-import/post-processor.go @@ -7,7 +7,6 @@ import ( "strings" "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/ec2" "github.com/aws/aws-sdk-go/service/s3" "github.com/aws/aws-sdk-go/service/s3/s3manager" @@ -99,10 +98,11 @@ func (p *PostProcessor) Configure(raws ...interface{}) error { func (p *PostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (packer.Artifact, bool, error) { var err error - config, err := p.config.Config() + session, err := p.config.Session() if err != nil { return nil, false, err } + config := session.Config // Render this key since we didn't in the configure phase p.config.S3Key, err = interpolate.Render(p.config.S3Key, &p.config.ctx) @@ -126,13 +126,6 @@ func (p *PostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (pac return nil, false, fmt.Errorf("No OVA file found in artifact from builder") } - // Set up the AWS session - log.Println("Creating AWS session") - session, err := session.NewSession(config) - if err != nil { - return nil, false, err - } - // open the source file log.Printf("Opening file %s to upload", source) file, err := os.Open(source)