Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for creating instances with CMEK #3481

Merged
merged 8 commits into from
May 13, 2019
Merged
Changes from 1 commit
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
Next Next commit
Add support for creating instances with CMEK
zachberger committed Apr 23, 2019
commit 3b53e237d77e599071a8d568ec20154713b8ac7f
1 change: 1 addition & 0 deletions google/data_source_google_compute_instance.go
Original file line number Diff line number Diff line change
@@ -101,6 +101,7 @@ func dataSourceGoogleComputeInstanceRead(d *schema.ResourceData, meta interface{
}
if key := disk.DiskEncryptionKey; key != nil {
di["disk_encryption_key_sha256"] = key.Sha256
di["kms_key_self_link"] = key.KmsKeyName
}
attachedDisks = append(attachedDisks, di)
}
31 changes: 31 additions & 0 deletions google/resource_compute_instance.go
Original file line number Diff line number Diff line change
@@ -75,6 +75,12 @@ func resourceComputeInstance() *schema.Resource {
Computed: true,
},

"kms_key_self_link": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
},

"initialize_params": {
Type: schema.TypeList,
Optional: true,
@@ -270,6 +276,11 @@ func resourceComputeInstance() *schema.Resource {
Sensitive: true,
},

"kms_key_self_link": {
Type: schema.TypeString,
Optional: true,
},

"disk_encryption_key_sha256": {
Type: schema.TypeString,
Computed: true,
@@ -355,6 +366,12 @@ func resourceComputeInstance() *schema.Resource {
Sensitive: true,
},

"kms_key_self_link": {
zachberger marked this conversation as resolved.
Show resolved Hide resolved
Type: schema.TypeString,
Optional: true,
ForceNew: true,
},

"disk_encryption_key_sha256": {
Type: schema.TypeString,
Computed: true,
@@ -860,6 +877,7 @@ func resourceComputeInstanceRead(d *schema.ResourceData, meta interface{}) error
if inConfig {
di["disk_encryption_key_raw"] = d.Get(fmt.Sprintf("attached_disk.%d.disk_encryption_key_raw", adIndex))
}
di["kms_key_self_link"] = key.KmsKeyName
di["disk_encryption_key_sha256"] = key.Sha256
}
// We want the disks to remain in the order we set in the config, so if a disk
@@ -1371,6 +1389,12 @@ func expandAttachedDisk(diskConfig map[string]interface{}, d *schema.ResourceDat
RawKey: v.(string),
}
}

if v, ok := diskConfig["kms_key_self_link"]; ok {
disk.DiskEncryptionKey = &computeBeta.CustomerEncryptionKey{
KmsKeyName: v.(string),
zachberger marked this conversation as resolved.
Show resolved Hide resolved
}
}
return disk, nil
}

@@ -1506,6 +1530,12 @@ func expandBootDisk(d *schema.ResourceData, config *Config, zone *compute.Zone,
}
}

if v, ok := d.GetOk("boot_disk.0.kms_key_self_link"); ok {
zachberger marked this conversation as resolved.
Show resolved Hide resolved
disk.DiskEncryptionKey = &computeBeta.CustomerEncryptionKey{
KmsKeyName: v.(string),
}
}

if v, ok := d.GetOk("boot_disk.0.source"); ok {
source, err := ParseDiskFieldValue(v.(string), d, config)
if err != nil {
@@ -1576,6 +1606,7 @@ func flattenBootDisk(d *schema.ResourceData, disk *computeBeta.AttachedDisk, con

if disk.DiskEncryptionKey != nil {
result["disk_encryption_key_sha256"] = disk.DiskEncryptionKey.Sha256
result["kms_key_self_link"] = disk.DiskEncryptionKey.KmsKeyName
}

return []map[string]interface{}{result}
78 changes: 78 additions & 0 deletions google/resource_compute_instance_test.go
Original file line number Diff line number Diff line change
@@ -282,6 +282,40 @@ func TestAccComputeInstance_diskEncryption(t *testing.T) {
})
}

func TestAccComputeInstance_kmsDiskEncryption(t *testing.T) {
t.Parallel()

var instance compute.Instance
var instanceName = fmt.Sprintf("instance-test-%s", acctest.RandString(10))
bootKmsKeyName := "projects/project/locations/us-central1/keyRings/testing-cloud-kms/cryptoKeys/key-0/cryptoKeyVersions/1"
diskNameToEncryptionKey := map[string]*compute.CustomerEncryptionKey{
zachberger marked this conversation as resolved.
Show resolved Hide resolved
fmt.Sprintf("instance-testd-%s", acctest.RandString(10)): {
KmsKeyName: "projects/project/locations/us-central1/keyRings/testing-cloud-kms/cryptoKeys/key-1/cryptoKeyVersions/1",
zachberger marked this conversation as resolved.
Show resolved Hide resolved
},
fmt.Sprintf("instance-testd-%s", acctest.RandString(10)): {
KmsKeyName: "projects/project/locations/us-central1/keyRings/testing-cloud-kms/cryptoKeys/key-2/cryptoKeyVersions/1",
},
fmt.Sprintf("instance-testd-%s", acctest.RandString(10)): {
KmsKeyName: "projects/project/locations/us-central1/keyRings/testing-cloud-kms/cryptoKeys/key-3/cryptoKeyVersions/1",
},
}

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckComputeInstanceDestroy,
Steps: []resource.TestStep{
{
Config: testAccComputeInstance_disks_encryption(bootKmsKeyName, diskNameToEncryptionKey, instanceName),
Check: resource.ComposeTestCheckFunc(
testAccCheckComputeInstanceExists("google_compute_instance.foobar", &instance),
testAccCheckComputeInstanceDiskKmsEncryptionKey("google_compute_instance.foobar", &instance, bootKmsKeyName, diskNameToEncryptionKey),
),
},
},
zachberger marked this conversation as resolved.
Show resolved Hide resolved
})
}

func TestAccComputeInstance_attachedDisk(t *testing.T) {
t.Parallel()

@@ -1363,6 +1397,50 @@ func testAccCheckComputeInstanceDiskEncryptionKey(n string, instance *compute.In
}
}

func testAccCheckComputeInstanceDiskKmsEncryptionKey(n string, instance *compute.Instance, bootDiskEncryptionKey string, diskNameToEncryptionKey map[string]*compute.CustomerEncryptionKey) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[n]
if !ok {
return fmt.Errorf("Not found: %s", n)
}

for i, disk := range instance.Disks {
if disk.Boot {
attr := rs.Primary.Attributes["boot_disk.0.kms_key_self_link"]
if attr != bootDiskEncryptionKey {
return fmt.Errorf("Boot disk has wrong encryption key in state.\nExpected: %s\nActual: %s", bootDiskEncryptionKey, attr)
}
if disk.DiskEncryptionKey == nil && attr != "" {
return fmt.Errorf("Disk %d has mismatched encryption key.\nTF State: %+v\nGCP State: <empty>", i, attr)
}
} else {
if disk.DiskEncryptionKey != nil {
expectedKey := diskNameToEncryptionKey[GetResourceNameFromSelfLink(disk.Source)].KmsKeyName
if disk.DiskEncryptionKey.KmsKeyName != expectedKey {
return fmt.Errorf("Disk %d has unexpected encryption key in GCP.\nExpected: %s\nActual: %s", i, expectedKey, disk.DiskEncryptionKey.Sha256)
}
}
}
}

numAttachedDisks, err := strconv.Atoi(rs.Primary.Attributes["attached_disk.#"])
if err != nil {
return fmt.Errorf("Error converting value of attached_disk.#")
}
for i := 0; i < numAttachedDisks; i++ {
diskName := GetResourceNameFromSelfLink(rs.Primary.Attributes[fmt.Sprintf("attached_disk.%d.source", i)])
kmsKeyName := rs.Primary.Attributes[fmt.Sprintf("attached_disk.%d.kms_key_self_link", i)]
if key, ok := diskNameToEncryptionKey[diskName]; ok {
expectedEncryptionKey := key.KmsKeyName
if kmsKeyName != expectedEncryptionKey {
return fmt.Errorf("Attached disk %d has unexpected encryption key in state.\nExpected: %s\nActual: %s", i, expectedEncryptionKey, kmsKeyName)
}
}
}
return nil
}
}

func testAccCheckComputeInstanceTag(instance *compute.Instance, n string) resource.TestCheckFunc {
return func(s *terraform.State) error {
if instance.Tags == nil {