Skip to content

Commit 3b53e23

Browse files
committed
Add support for creating instances with CMEK
1 parent 86caed3 commit 3b53e23

3 files changed

+110
-0
lines changed

google/data_source_google_compute_instance.go

+1
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ func dataSourceGoogleComputeInstanceRead(d *schema.ResourceData, meta interface{
101101
}
102102
if key := disk.DiskEncryptionKey; key != nil {
103103
di["disk_encryption_key_sha256"] = key.Sha256
104+
di["kms_key_self_link"] = key.KmsKeyName
104105
}
105106
attachedDisks = append(attachedDisks, di)
106107
}

google/resource_compute_instance.go

+31
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,12 @@ func resourceComputeInstance() *schema.Resource {
7575
Computed: true,
7676
},
7777

78+
"kms_key_self_link": {
79+
Type: schema.TypeString,
80+
Optional: true,
81+
ForceNew: true,
82+
},
83+
7884
"initialize_params": {
7985
Type: schema.TypeList,
8086
Optional: true,
@@ -270,6 +276,11 @@ func resourceComputeInstance() *schema.Resource {
270276
Sensitive: true,
271277
},
272278

279+
"kms_key_self_link": {
280+
Type: schema.TypeString,
281+
Optional: true,
282+
},
283+
273284
"disk_encryption_key_sha256": {
274285
Type: schema.TypeString,
275286
Computed: true,
@@ -355,6 +366,12 @@ func resourceComputeInstance() *schema.Resource {
355366
Sensitive: true,
356367
},
357368

369+
"kms_key_self_link": {
370+
Type: schema.TypeString,
371+
Optional: true,
372+
ForceNew: true,
373+
},
374+
358375
"disk_encryption_key_sha256": {
359376
Type: schema.TypeString,
360377
Computed: true,
@@ -860,6 +877,7 @@ func resourceComputeInstanceRead(d *schema.ResourceData, meta interface{}) error
860877
if inConfig {
861878
di["disk_encryption_key_raw"] = d.Get(fmt.Sprintf("attached_disk.%d.disk_encryption_key_raw", adIndex))
862879
}
880+
di["kms_key_self_link"] = key.KmsKeyName
863881
di["disk_encryption_key_sha256"] = key.Sha256
864882
}
865883
// 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
13711389
RawKey: v.(string),
13721390
}
13731391
}
1392+
1393+
if v, ok := diskConfig["kms_key_self_link"]; ok {
1394+
disk.DiskEncryptionKey = &computeBeta.CustomerEncryptionKey{
1395+
KmsKeyName: v.(string),
1396+
}
1397+
}
13741398
return disk, nil
13751399
}
13761400

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

1533+
if v, ok := d.GetOk("boot_disk.0.kms_key_self_link"); ok {
1534+
disk.DiskEncryptionKey = &computeBeta.CustomerEncryptionKey{
1535+
KmsKeyName: v.(string),
1536+
}
1537+
}
1538+
15091539
if v, ok := d.GetOk("boot_disk.0.source"); ok {
15101540
source, err := ParseDiskFieldValue(v.(string), d, config)
15111541
if err != nil {
@@ -1576,6 +1606,7 @@ func flattenBootDisk(d *schema.ResourceData, disk *computeBeta.AttachedDisk, con
15761606

15771607
if disk.DiskEncryptionKey != nil {
15781608
result["disk_encryption_key_sha256"] = disk.DiskEncryptionKey.Sha256
1609+
result["kms_key_self_link"] = disk.DiskEncryptionKey.KmsKeyName
15791610
}
15801611

15811612
return []map[string]interface{}{result}

google/resource_compute_instance_test.go

+78
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,40 @@ func TestAccComputeInstance_diskEncryption(t *testing.T) {
282282
})
283283
}
284284

285+
func TestAccComputeInstance_kmsDiskEncryption(t *testing.T) {
286+
t.Parallel()
287+
288+
var instance compute.Instance
289+
var instanceName = fmt.Sprintf("instance-test-%s", acctest.RandString(10))
290+
bootKmsKeyName := "projects/project/locations/us-central1/keyRings/testing-cloud-kms/cryptoKeys/key-0/cryptoKeyVersions/1"
291+
diskNameToEncryptionKey := map[string]*compute.CustomerEncryptionKey{
292+
fmt.Sprintf("instance-testd-%s", acctest.RandString(10)): {
293+
KmsKeyName: "projects/project/locations/us-central1/keyRings/testing-cloud-kms/cryptoKeys/key-1/cryptoKeyVersions/1",
294+
},
295+
fmt.Sprintf("instance-testd-%s", acctest.RandString(10)): {
296+
KmsKeyName: "projects/project/locations/us-central1/keyRings/testing-cloud-kms/cryptoKeys/key-2/cryptoKeyVersions/1",
297+
},
298+
fmt.Sprintf("instance-testd-%s", acctest.RandString(10)): {
299+
KmsKeyName: "projects/project/locations/us-central1/keyRings/testing-cloud-kms/cryptoKeys/key-3/cryptoKeyVersions/1",
300+
},
301+
}
302+
303+
resource.Test(t, resource.TestCase{
304+
PreCheck: func() { testAccPreCheck(t) },
305+
Providers: testAccProviders,
306+
CheckDestroy: testAccCheckComputeInstanceDestroy,
307+
Steps: []resource.TestStep{
308+
{
309+
Config: testAccComputeInstance_disks_encryption(bootKmsKeyName, diskNameToEncryptionKey, instanceName),
310+
Check: resource.ComposeTestCheckFunc(
311+
testAccCheckComputeInstanceExists("google_compute_instance.foobar", &instance),
312+
testAccCheckComputeInstanceDiskKmsEncryptionKey("google_compute_instance.foobar", &instance, bootKmsKeyName, diskNameToEncryptionKey),
313+
),
314+
},
315+
},
316+
})
317+
}
318+
285319
func TestAccComputeInstance_attachedDisk(t *testing.T) {
286320
t.Parallel()
287321

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

1400+
func testAccCheckComputeInstanceDiskKmsEncryptionKey(n string, instance *compute.Instance, bootDiskEncryptionKey string, diskNameToEncryptionKey map[string]*compute.CustomerEncryptionKey) resource.TestCheckFunc {
1401+
return func(s *terraform.State) error {
1402+
rs, ok := s.RootModule().Resources[n]
1403+
if !ok {
1404+
return fmt.Errorf("Not found: %s", n)
1405+
}
1406+
1407+
for i, disk := range instance.Disks {
1408+
if disk.Boot {
1409+
attr := rs.Primary.Attributes["boot_disk.0.kms_key_self_link"]
1410+
if attr != bootDiskEncryptionKey {
1411+
return fmt.Errorf("Boot disk has wrong encryption key in state.\nExpected: %s\nActual: %s", bootDiskEncryptionKey, attr)
1412+
}
1413+
if disk.DiskEncryptionKey == nil && attr != "" {
1414+
return fmt.Errorf("Disk %d has mismatched encryption key.\nTF State: %+v\nGCP State: <empty>", i, attr)
1415+
}
1416+
} else {
1417+
if disk.DiskEncryptionKey != nil {
1418+
expectedKey := diskNameToEncryptionKey[GetResourceNameFromSelfLink(disk.Source)].KmsKeyName
1419+
if disk.DiskEncryptionKey.KmsKeyName != expectedKey {
1420+
return fmt.Errorf("Disk %d has unexpected encryption key in GCP.\nExpected: %s\nActual: %s", i, expectedKey, disk.DiskEncryptionKey.Sha256)
1421+
}
1422+
}
1423+
}
1424+
}
1425+
1426+
numAttachedDisks, err := strconv.Atoi(rs.Primary.Attributes["attached_disk.#"])
1427+
if err != nil {
1428+
return fmt.Errorf("Error converting value of attached_disk.#")
1429+
}
1430+
for i := 0; i < numAttachedDisks; i++ {
1431+
diskName := GetResourceNameFromSelfLink(rs.Primary.Attributes[fmt.Sprintf("attached_disk.%d.source", i)])
1432+
kmsKeyName := rs.Primary.Attributes[fmt.Sprintf("attached_disk.%d.kms_key_self_link", i)]
1433+
if key, ok := diskNameToEncryptionKey[diskName]; ok {
1434+
expectedEncryptionKey := key.KmsKeyName
1435+
if kmsKeyName != expectedEncryptionKey {
1436+
return fmt.Errorf("Attached disk %d has unexpected encryption key in state.\nExpected: %s\nActual: %s", i, expectedEncryptionKey, kmsKeyName)
1437+
}
1438+
}
1439+
}
1440+
return nil
1441+
}
1442+
}
1443+
13661444
func testAccCheckComputeInstanceTag(instance *compute.Instance, n string) resource.TestCheckFunc {
13671445
return func(s *terraform.State) error {
13681446
if instance.Tags == nil {

0 commit comments

Comments
 (0)