Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions aws/data_source_aws_instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
},
},
},
},
Expand Down
32 changes: 29 additions & 3 deletions aws/resource_aws_instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
},
},
},
},
Expand Down Expand Up @@ -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
}
Expand Down Expand Up @@ -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
Expand Down
82 changes: 82 additions & 0 deletions aws/resource_aws_instance_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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 = <<POLICY
{
"Version": "2012-10-17",
"Id": "kms-tf-1",
"Statement": [
{
"Sid": "Enable IAM User Permissions",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "kms:*",
"Resource": "*"
}
]
}
POLICY

tags = {
Name = "tf-acc-test-kms-key-%s"
}
}

resource "aws_instance" "foo" {
# us-west-2
ami = "ami-55a7ea65"

# In order to attach an encrypted volume to an instance you need to have an
# m3.medium or larger. See "Supported Instance Types" in:
# http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/EBSEncryption.html
instance_type = "m3.medium"

root_block_device {
volume_type = "gp2"
volume_size = 11
# configured explicitly
iops = 10
encrypted = true
kms_key_id = "${aws_kms_key.foo.arn}"
}
}
`, rName, rName)
}

const testAccInstanceConfigBlockDevices = `
resource "aws_instance" "foo" {
# us-west-2
Expand Down
2 changes: 2 additions & 0 deletions website/docs/d/instance.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ interpolation.
* `iops` - `0` If the volume is not a provisioned IOPS image, otherwise the supported IOPS count.
* `volume_size` - The size of the volume, in GiB.
* `volume_type` - The type of the volume.
* `encrypted` - If the volume is encrypted.
* `kms_key_id` - The ID of the KMS Key that was used to encrypt the volume.
* `security_groups` - The associated security groups.
* `source_dest_check` - Whether the network interface performs source/destination checking (Boolean).
* `subnet_id` - The VPC subnet ID.
Expand Down
5 changes: 5 additions & 0 deletions website/docs/r/instance.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,11 @@ The `root_block_device` mapping supports the following:
using that type
* `delete_on_termination` - (Optional) Whether the volume should be destroyed
on instance termination (Default: `true`).
* `encrypted` - (Optional) Enables [EBS
encryption](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/EBSEncryption.html)
on the volume (Default: `false`).
* `kms_key_id` - (Optional) Identifier (key ID, key alias, ID ARN, or alias ARN) for a user-managed CMK
under which the EBS volume is encrypted.

Modifying any of the `root_block_device` settings requires resource
replacement.
Expand Down