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 = <