diff --git a/builder/amazon/common/ami_config.go b/builder/amazon/common/ami_config.go index c59653863..fa442cb5c 100644 --- a/builder/amazon/common/ami_config.go +++ b/builder/amazon/common/ami_config.go @@ -21,6 +21,7 @@ type AMIConfig struct { AMIForceDeregister bool `mapstructure:"force_deregister"` AMIForceDeleteSnapshot bool `mapstructure:"force_delete_snapshot"` AMIEncryptBootVolume bool `mapstructure:"encrypt_boot"` + AMIKmsKeyId string `mapstructure:"kms_key_id"` SnapshotTags map[string]string `mapstructure:"snapshot_tags"` } diff --git a/builder/amazon/common/ami_config_test.go b/builder/amazon/common/ami_config_test.go index 9d52cfc3b..ecb88bcb4 100644 --- a/builder/amazon/common/ami_config_test.go +++ b/builder/amazon/common/ami_config_test.go @@ -59,11 +59,18 @@ func TestAMIConfigPrepare_regions(t *testing.T) { } -func TestAMIConfigPrepare_EncryptBoot(t *testing.T) { +func TestAMIConfigPrepare_Share_EncryptedBoot(t *testing.T) { c := testAMIConfig() c.AMIUsers = []string{"testAccountID"} c.AMIEncryptBootVolume = true + + c.AMIKmsKeyId = "" if err := c.Prepare(nil); err == nil { - t.Fatal("should have error") + t.Fatal("shouldn't be able to share ami with encrypted boot volume") + } + + c.AMIKmsKeyId = "89c3fb9a-de87-4f2a-aedc-fddc5138193c" + if err := c.Prepare(nil); err == nil { + t.Fatal("shouldn't be able to share ami with encrypted boot volume") } } diff --git a/builder/amazon/ebs/step_encrypted_ami.go b/builder/amazon/ebs/step_encrypted_ami.go index f51b944bc..5721def98 100644 --- a/builder/amazon/ebs/step_encrypted_ami.go +++ b/builder/amazon/ebs/step_encrypted_ami.go @@ -2,6 +2,7 @@ package ebs import ( "fmt" + "log" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/ec2" @@ -18,9 +19,13 @@ func (s *stepCreateEncryptedAMICopy) Run(state multistep.StateBag) multistep.Ste config := state.Get("config").(Config) ec2conn := state.Get("ec2").(*ec2.EC2) ui := state.Get("ui").(packer.Ui) + kmsKeyId := config.AMIConfig.AMIKmsKeyId // Encrypt boot not set, so skip step if !config.AMIConfig.AMIEncryptBootVolume { + if kmsKeyId != "" { + log.Printf(fmt.Sprintf("Ignoring KMS Key ID: %s, encrypted=false", kmsKeyId)) + } return multistep.ActionContinue } @@ -36,11 +41,16 @@ func (s *stepCreateEncryptedAMICopy) Run(state multistep.StateBag) multistep.Ste ui.Say(fmt.Sprintf("Copying AMI: %s(%s)", region, id)) + if kmsKeyId != "" { + ui.Say(fmt.Sprintf("Encypting with KMS Key ID: %s", kmsKeyId)) + } + copyOpts := &ec2.CopyImageInput{ Name: &config.AMIName, // Try to overwrite existing AMI SourceImageId: aws.String(id), SourceRegion: aws.String(region), Encrypted: aws.Bool(true), + KmsKeyId: aws.String(kmsKeyId), } copyResp, err := ec2conn.CopyImage(copyOpts) diff --git a/website/source/docs/builders/amazon-ebs.html.md b/website/source/docs/builders/amazon-ebs.html.md index 92e366e0e..00615e2eb 100644 --- a/website/source/docs/builders/amazon-ebs.html.md +++ b/website/source/docs/builders/amazon-ebs.html.md @@ -162,6 +162,8 @@ builder. AMI with an encrypted boot volume (discarding the initial unencrypted AMI in the process). Default `false`. +- `kms_key_id` (string) - The ID of the KMS key to use for boot volume encryption. + - `iam_instance_profile` (string) - The name of an [IAM instance profile](https://docs.aws.amazon.com/IAM/latest/UserGuide/instance-profiles.html) to launch the EC2 instance with.