From bbec0d887451f0ed6709040d94e168ef06425657 Mon Sep 17 00:00:00 2001 From: stack72 Date: Mon, 24 Jun 2019 20:10:24 +0300 Subject: [PATCH] resource/aws_instance: Adding support for Root Device Encryption MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As released https://aws.amazon.com/about-aws/whats-new/2019/05/launch-encrypted-ebs-backed-ec2-instances-from-unencrypted-amis-in-a-single-step/ ``` ▶ acctests aws TestAccAWSInstance_encryptedRootDevice === RUN TestAccAWSInstance_encryptedRootDevice === PAUSE TestAccAWSInstance_encryptedRootDevice === CONT TestAccAWSInstance_encryptedRootDevice --- PASS: TestAccAWSInstance_encryptedRootDevice (161.17s) PASS ok github.com/terraform-providers/terraform-provider-aws/aws 161.229s ``` --- aws/data_source_aws_instance.go | 10 ++++ aws/resource_aws_instance.go | 32 ++++++++++- aws/resource_aws_instance_test.go | 82 +++++++++++++++++++++++++++ website/docs/d/instance.html.markdown | 2 + website/docs/r/instance.html.markdown | 5 ++ 5 files changed, 128 insertions(+), 3 deletions(-) diff --git a/aws/data_source_aws_instance.go b/aws/data_source_aws_instance.go index 9b28684431fa..de664d02a70a 100644 --- a/aws/data_source_aws_instance.go +++ b/aws/data_source_aws_instance.go @@ -238,6 +238,16 @@ func dataSourceAwsInstance() *schema.Resource { Type: schema.TypeString, Computed: true, }, + + "encrypted": { + Type: schema.TypeBool, + Computed: true, + }, + + "kms_key_id": { + Type: schema.TypeString, + Computed: true, + }, }, }, }, diff --git a/aws/resource_aws_instance.go b/aws/resource_aws_instance.go index b18587864ffe..418b68defc11 100644 --- a/aws/resource_aws_instance.go +++ b/aws/resource_aws_instance.go @@ -458,6 +458,19 @@ func resourceAwsInstance() *schema.Resource { Type: schema.TypeString, Computed: true, }, + + "encrypted": { + Type: schema.TypeBool, + Optional: true, + Default: false, + ForceNew: true, + }, + + "kms_key_id": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + }, }, }, }, @@ -1329,15 +1342,20 @@ func readBlockDevicesFromInstance(instance *ec2.Instance, conn *ec2.EC2) (map[st bd["iops"] = *vol.Iops } + if vol.Encrypted != nil { + bd["encrypted"] = *vol.Encrypted + } + if blockDeviceIsRoot(instanceBd, instance) { blockDevices["root"] = bd + + if vol.KmsKeyId != nil { + bd["kms_key_id"] = *vol.KmsKeyId + } } else { if instanceBd.DeviceName != nil { bd["device_name"] = *instanceBd.DeviceName } - if vol.Encrypted != nil { - bd["encrypted"] = *vol.Encrypted - } if vol.SnapshotId != nil { bd["snapshot_id"] = *vol.SnapshotId } @@ -1563,6 +1581,14 @@ func readBlockDeviceMappingsFromConfig( ebs.VolumeType = aws.String(v) } + if v, ok := bd["encrypted"].(bool); ok { + ebs.Encrypted = aws.Bool(v) + } + + if v, ok := bd["kms_key_id"].(string); ok && v != "" { + ebs.KmsKeyId = aws.String(v) + } + if v, ok := bd["iops"].(int); ok && v > 0 && *ebs.VolumeType == "io1" { // Only set the iops attribute if the volume type is io1. Setting otherwise // can trigger a refresh/plan loop based on the computed value that is given diff --git a/aws/resource_aws_instance_test.go b/aws/resource_aws_instance_test.go index 9b282141984c..89e5d5cb8401 100644 --- a/aws/resource_aws_instance_test.go +++ b/aws/resource_aws_instance_test.go @@ -417,6 +417,38 @@ func TestAccAWSInstance_GP2WithIopsValue(t *testing.T) { }) } +func TestAccAWSInstance_encryptedRootDevice(t *testing.T) { + rName := acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum) + + var v ec2.Instance + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + IDRefreshName: "aws_instance.foo", + IDRefreshIgnore: []string{"ephemeral_block_device", "user_data"}, + Providers: testAccProviders, + CheckDestroy: testAccCheckInstanceDestroy, + Steps: []resource.TestStep{ + { + Config: testAccInstanceEncryptedRootDevice(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckInstanceExists( + "aws_instance.foo", &v), + resource.TestCheckResourceAttr( + "aws_instance.foo", "root_block_device.#", "1"), + resource.TestMatchResourceAttr( + "aws_instance.foo", "root_block_device.0.volume_id", regexp.MustCompile("vol-[a-z0-9]+")), + resource.TestCheckResourceAttr( + "aws_instance.foo", "root_block_device.0.volume_size", "11"), + resource.TestCheckResourceAttr( + "aws_instance.foo", "root_block_device.0.volume_type", "gp2"), + resource.TestCheckResourceAttr( + "aws_instance.foo", "root_block_device.0.encrypted", "true"), + ), + }, + }, + }) +} + func TestAccAWSInstance_blockDevices(t *testing.T) { var v ec2.Instance @@ -2466,6 +2498,56 @@ resource "aws_instance" "foo" { } ` +func testAccInstanceEncryptedRootDevice(rName string) string { + return fmt.Sprintf(` +resource "aws_kms_key" "foo" { + description = "Terraform acc test %s" + deletion_window_in_days = 7 + + policy = <