From 4ce3b8712af965a4d373c9143c114a8cb8de8d94 Mon Sep 17 00:00:00 2001 From: Rickard von Essen Date: Sun, 4 Dec 2016 20:18:27 +0100 Subject: [PATCH] Replace unencrypted EBS snapshots with encrypted To ensure that groups and users attributes are added to the encrypted snapshots. --- builder/amazon/common/ami_config.go | 4 +++ builder/amazon/ebs/step_encrypted_ami.go | 37 +++++++++++++++------ website/source/docs/builders/amazon.html.md | 2 +- 3 files changed, 32 insertions(+), 11 deletions(-) diff --git a/builder/amazon/common/ami_config.go b/builder/amazon/common/ami_config.go index e8ab11303..c7674dbbe 100644 --- a/builder/amazon/common/ami_config.go +++ b/builder/amazon/common/ami_config.go @@ -64,6 +64,10 @@ func (c *AMIConfig) Prepare(ctx *interpolate.Context) []error { errs = append(errs, fmt.Errorf("Cannot share AMI with encrypted boot volume")) } + if len(c.SnapshotUsers) > 0 && len(c.AMIKmsKeyId) == 0 && c.AMIEncryptBootVolume { + errs = append(errs, fmt.Errorf("Cannot share snapshot encrypted with default KMS key")) + } + if len(errs) > 0 { return errs } diff --git a/builder/amazon/ebs/step_encrypted_ami.go b/builder/amazon/ebs/step_encrypted_ami.go index 5721def98..59f3298bd 100644 --- a/builder/amazon/ebs/step_encrypted_ami.go +++ b/builder/amazon/ebs/step_encrypted_ami.go @@ -77,6 +77,22 @@ func (s *stepCreateEncryptedAMICopy) Run(state multistep.StateBag) multistep.Ste return multistep.ActionHalt } + // Get the encrypted AMI image, we need the new snapshot id's + encImagesResp, err := ec2conn.DescribeImages(&ec2.DescribeImagesInput{ImageIds: []*string{aws.String(*copyResp.ImageId)}}) + if err != nil { + err := fmt.Errorf("Error searching for AMI: %s", err) + state.Put("error", err) + ui.Error(err.Error()) + return multistep.ActionHalt + } + encImage := encImagesResp.Images[0] + var encSnapshots []string + for _, blockDevice := range encImage.BlockDeviceMappings { + if blockDevice.Ebs != nil && blockDevice.Ebs.SnapshotId != nil { + encSnapshots = append(encSnapshots, *blockDevice.Ebs.SnapshotId) + } + } + // Get the unencrypted AMI image unencImagesResp, err := ec2conn.DescribeImages(&ec2.DescribeImagesInput{ImageIds: []*string{aws.String(id)}}) if err != nil { @@ -97,25 +113,26 @@ func (s *stepCreateEncryptedAMICopy) Run(state multistep.StateBag) multistep.Ste // Remove associated unencrypted snapshot(s) ui.Say("Deleting unencrypted snapshots") + snapshots := state.Get("snapshots").(map[string][]string) for _, blockDevice := range unencImage.BlockDeviceMappings { - if blockDevice.Ebs != nil { - if blockDevice.Ebs.SnapshotId != nil { - ui.Message(fmt.Sprintf("Snapshot ID: %s", *blockDevice.Ebs.SnapshotId)) - deleteSnapOpts := &ec2.DeleteSnapshotInput{ - SnapshotId: aws.String(*blockDevice.Ebs.SnapshotId), - } - if _, err := ec2conn.DeleteSnapshot(deleteSnapOpts); err != nil { - ui.Error(fmt.Sprintf("Error deleting snapshot, may still be around: %s", err)) - return multistep.ActionHalt - } + if blockDevice.Ebs != nil && blockDevice.Ebs.SnapshotId != nil { + ui.Message(fmt.Sprintf("Snapshot ID: %s", *blockDevice.Ebs.SnapshotId)) + deleteSnapOpts := &ec2.DeleteSnapshotInput{ + SnapshotId: aws.String(*blockDevice.Ebs.SnapshotId), + } + if _, err := ec2conn.DeleteSnapshot(deleteSnapOpts); err != nil { + ui.Error(fmt.Sprintf("Error deleting snapshot, may still be around: %s", err)) + return multistep.ActionHalt } } } // Replace original AMI ID with Encrypted ID in state amis[region] = *copyResp.ImageId + snapshots[region] = encSnapshots state.Put("amis", amis) + state.Put("snapshots", snapshots) imagesResp, err := ec2conn.DescribeImages(&ec2.DescribeImagesInput{ImageIds: []*string{copyResp.ImageId}}) if err != nil { diff --git a/website/source/docs/builders/amazon.html.md b/website/source/docs/builders/amazon.html.md index 4b31e1012..7cd40f8b6 100644 --- a/website/source/docs/builders/amazon.html.md +++ b/website/source/docs/builders/amazon.html.md @@ -129,7 +129,7 @@ Packer to work: "ec2:GetPasswordData", "ec2:ModifyImageAttribute", "ec2:ModifyInstanceAttribute", - "ec2:ModifySnapshotAttribute" + "ec2:ModifySnapshotAttribute", "ec2:RegisterImage", "ec2:RunInstances", "ec2:StopInstances",