diff --git a/builder/amazon/common/ami_config_test.go b/builder/amazon/common/ami_config_test.go index 0e420de5f..5cdff587c 100644 --- a/builder/amazon/common/ami_config_test.go +++ b/builder/amazon/common/ami_config_test.go @@ -67,6 +67,17 @@ func TestAMIConfigPrepare_regions(t *testing.T) { t.Fatal("shouldn't have error") } + c.SnapshotUsers = []string{"user-foo", "user-bar"} + c.AMIRegions = []string{"us-east-1", "us-east-2", "us-west-1"} + c.AMIRegionKmsKeyIds = map[string]string{ + "us-east-1": "123-456-7890", + "us-west-1": "789-012-3456", + "us-east-2": "", + } + if err := c.Prepare(nil); err == nil { + t.Fatal("should have an error b/c can't use default KMS key if sharing") + } + c.AMIRegions = []string{"us-east-1", "us-west-1"} c.AMIRegionKmsKeyIds = map[string]string{ "us-east-1": "123-456-7890", diff --git a/builder/amazon/common/step_ami_region_copy.go b/builder/amazon/common/step_ami_region_copy.go index 6020ae1de..dae550ee1 100644 --- a/builder/amazon/common/step_ami_region_copy.go +++ b/builder/amazon/common/step_ami_region_copy.go @@ -13,9 +13,11 @@ import ( ) type StepAMIRegionCopy struct { - AccessConfig *AccessConfig - Regions []string - Name string + AccessConfig *AccessConfig + Regions []string + RegionKeyIds map[string]string + EncryptBootVolume bool + Name string } func (s *StepAMIRegionCopy) Run(state multistep.StateBag) multistep.StepAction { @@ -33,6 +35,7 @@ func (s *StepAMIRegionCopy) Run(state multistep.StateBag) multistep.StepAction { var lock sync.Mutex var wg sync.WaitGroup + var reg_key_id string errs := new(packer.MultiError) for _, region := range s.Regions { if region == *ec2conn.Config.Region { @@ -44,10 +47,14 @@ func (s *StepAMIRegionCopy) Run(state multistep.StateBag) multistep.StepAction { wg.Add(1) ui.Message(fmt.Sprintf("Copying to: %s", region)) + reg_key_id = s.RegionKeyIds[region] + if !s.EncryptBootVolume { + reg_key_id = "" + } + go func(region string) { defer wg.Done() - id, snapshotIds, err := amiRegionCopy(state, s.AccessConfig, s.Name, ami, region, *ec2conn.Config.Region) - + id, snapshotIds, err := amiRegionCopy(state, s.AccessConfig, s.Name, ami, region, *ec2conn.Config.Region, reg_key_id) lock.Lock() defer lock.Unlock() amis[region] = id @@ -80,8 +87,9 @@ func (s *StepAMIRegionCopy) Cleanup(state multistep.StateBag) { // amiRegionCopy does a copy for the given AMI to the target region and // returns the resulting ID and snapshot IDs, or error. func amiRegionCopy(state multistep.StateBag, config *AccessConfig, name string, imageId string, - target string, source string) (string, []string, error) { + target string, source string, key_id string) (string, []string, error) { snapshotIds := []string{} + is_encrypted := false // Connect to the region where the AMI will be copied to awsConfig, err := config.Config() @@ -95,11 +103,16 @@ func amiRegionCopy(state multistep.StateBag, config *AccessConfig, name string, return "", snapshotIds, err } regionconn := ec2.New(session) - + // if we've provided a map of key ids to regions, use those keys. + if len(key_id) > 0 { + is_encrypted = true + } resp, err := regionconn.CopyImage(&ec2.CopyImageInput{ SourceRegion: &source, SourceImageId: &imageId, Name: &name, + Encrypted: aws.Bool(is_encrypted), + KmsKeyId: aws.String(key_id), }) if err != nil { diff --git a/builder/amazon/common/step_encrypted_ami.go b/builder/amazon/common/step_encrypted_ami.go index 5fb1797eb..18f227d2b 100644 --- a/builder/amazon/common/step_encrypted_ami.go +++ b/builder/amazon/common/step_encrypted_ami.go @@ -25,7 +25,7 @@ func (s *StepCreateEncryptedAMICopy) Run(state multistep.StateBag) multistep.Ste // Encrypt boot not set, so skip step if !s.EncryptBootVolume { if kmsKeyId != "" { - log.Printf("Ignoring KMS Key ID: %s, encrypted_boot=false", kmsKeyId) + log.Printf("Ignoring KMS Key ID: %s, encrypted=false", kmsKeyId) } return multistep.ActionContinue } @@ -36,14 +36,14 @@ func (s *StepCreateEncryptedAMICopy) Run(state multistep.StateBag) multistep.Ste var region, id string if amis != nil { for region, id = range amis { - break // Only get the first + break // There is only ever one region:ami pair in this map } } ui.Say(fmt.Sprintf("Copying AMI: %s(%s)", region, id)) if kmsKeyId != "" { - ui.Say(fmt.Sprintf("Encrypting with KMS Key ID: %s", kmsKeyId)) + ui.Say(fmt.Sprintf("Encypting with KMS Key ID: %s", kmsKeyId)) } copyOpts := &ec2.CopyImageInput{ diff --git a/builder/amazon/ebs/builder.go b/builder/amazon/ebs/builder.go index 0d0bc045a..fb30ff535 100644 --- a/builder/amazon/ebs/builder.go +++ b/builder/amazon/ebs/builder.go @@ -198,9 +198,11 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe Name: b.config.AMIName, }, &awscommon.StepAMIRegionCopy{ - AccessConfig: &b.config.AccessConfig, - Regions: b.config.AMIRegions, - Name: b.config.AMIName, + AccessConfig: &b.config.AccessConfig, + Regions: b.config.AMIRegions, + RegionKeyIds: b.config.AMIRegionKmsKeyIds, + EncryptBootVolume: b.config.AMIEncryptBootVolume, + Name: b.config.AMIName, }, &awscommon.StepModifyAMIAttributes{ Description: b.config.AMIDescription,