Skip to content

Commit 42a1068

Browse files
Add Confidential VM support to instances and instance templates (#3824) (#2369)
* added compute confidential vm support * fix typo * add tests for compute instance * added additional tests * add beta version gate to tests * added tests for instance template * updated testing and add beta provider to tests * remove import tests Signed-off-by: Modular Magician <[email protected]>
1 parent d110e65 commit 42a1068

File tree

6 files changed

+239
-35
lines changed

6 files changed

+239
-35
lines changed

.changelog/3824.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
```release-note:enhancement
2+
compute: added confidential_instance_config block to google_compute_instance
3+
```
4+
```release-note:enhancement
5+
compute: added confidential_instance_config block to google_compute_instance_template
6+
```

google-beta/compute_instance_helpers.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,28 @@ func expandShieldedVmConfigs(d TerraformResourceData) *computeBeta.ShieldedInsta
324324
}
325325
}
326326

327+
func expandConfidentialInstanceConfig(d TerraformResourceData) *computeBeta.ConfidentialInstanceConfig {
328+
if _, ok := d.GetOk("confidential_instance_config"); !ok {
329+
return nil
330+
}
331+
332+
prefix := "confidential_instance_config.0"
333+
return &computeBeta.ConfidentialInstanceConfig{
334+
EnableConfidentialCompute: d.Get(prefix + ".enable_confidential_compute").(bool),
335+
ForceSendFields: []string{"EnableSecureBoot"},
336+
}
337+
}
338+
339+
func flattenConfidentialInstanceConfig(ConfidentialInstanceConfig *computeBeta.ConfidentialInstanceConfig) []map[string]bool {
340+
if ConfidentialInstanceConfig == nil {
341+
return nil
342+
}
343+
344+
return []map[string]bool{{
345+
"enable_confidential_compute": ConfidentialInstanceConfig.EnableConfidentialCompute,
346+
}}
347+
}
348+
327349
func flattenShieldedVmConfig(shieldedVmConfig *computeBeta.ShieldedInstanceConfig) []map[string]bool {
328350
if shieldedVmConfig == nil {
329351
return nil

google-beta/resource_compute_instance.go

Lines changed: 38 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -606,7 +606,23 @@ func resourceComputeInstance() *schema.Resource {
606606
},
607607
},
608608
},
609-
609+
"confidential_instance_config": {
610+
Type: schema.TypeList,
611+
MaxItems: 1,
612+
Optional: true,
613+
ForceNew: true,
614+
Computed: true,
615+
Description: `The Confidential VM config being used by the instance. on_host_maintenance has to be set to TERMINATE or this will fail to create.`,
616+
Elem: &schema.Resource{
617+
Schema: map[string]*schema.Schema{
618+
"enable_confidential_compute": {
619+
Type: schema.TypeBool,
620+
Required: true,
621+
Description: `Defines whether the instance should have confidential compute enabled.`,
622+
},
623+
},
624+
},
625+
},
610626
"desired_status": {
611627
Type: schema.TypeString,
612628
Optional: true,
@@ -795,25 +811,26 @@ func expandComputeInstance(project string, d *schema.ResourceData, config *Confi
795811

796812
// Create the instance information
797813
return &computeBeta.Instance{
798-
CanIpForward: d.Get("can_ip_forward").(bool),
799-
Description: d.Get("description").(string),
800-
Disks: disks,
801-
MachineType: machineTypeUrl,
802-
Metadata: metadata,
803-
Name: d.Get("name").(string),
804-
NetworkInterfaces: networkInterfaces,
805-
Tags: resourceInstanceTags(d),
806-
Labels: expandLabels(d),
807-
ServiceAccounts: expandServiceAccounts(d.Get("service_account").([]interface{})),
808-
GuestAccelerators: accels,
809-
MinCpuPlatform: d.Get("min_cpu_platform").(string),
810-
Scheduling: scheduling,
811-
DeletionProtection: d.Get("deletion_protection").(bool),
812-
Hostname: d.Get("hostname").(string),
813-
ForceSendFields: []string{"CanIpForward", "DeletionProtection"},
814-
ShieldedInstanceConfig: expandShieldedVmConfigs(d),
815-
DisplayDevice: expandDisplayDevice(d),
816-
ResourcePolicies: convertStringArr(d.Get("resource_policies").([]interface{})),
814+
CanIpForward: d.Get("can_ip_forward").(bool),
815+
Description: d.Get("description").(string),
816+
Disks: disks,
817+
MachineType: machineTypeUrl,
818+
Metadata: metadata,
819+
Name: d.Get("name").(string),
820+
NetworkInterfaces: networkInterfaces,
821+
Tags: resourceInstanceTags(d),
822+
Labels: expandLabels(d),
823+
ServiceAccounts: expandServiceAccounts(d.Get("service_account").([]interface{})),
824+
GuestAccelerators: accels,
825+
MinCpuPlatform: d.Get("min_cpu_platform").(string),
826+
Scheduling: scheduling,
827+
DeletionProtection: d.Get("deletion_protection").(bool),
828+
Hostname: d.Get("hostname").(string),
829+
ForceSendFields: []string{"CanIpForward", "DeletionProtection"},
830+
ConfidentialInstanceConfig: expandConfidentialInstanceConfig(d),
831+
ShieldedInstanceConfig: expandShieldedVmConfigs(d),
832+
DisplayDevice: expandDisplayDevice(d),
833+
ResourcePolicies: convertStringArr(d.Get("resource_policies").([]interface{})),
817834
}, nil
818835
}
819836

@@ -1106,7 +1123,7 @@ func resourceComputeInstanceRead(d *schema.ResourceData, meta interface{}) error
11061123
d.Set("description", instance.Description)
11071124
d.Set("hostname", instance.Hostname)
11081125
d.Set("current_status", instance.Status)
1109-
1126+
d.Set("confidential_instance_config", flattenConfidentialInstanceConfig(instance.ConfidentialInstanceConfig))
11101127
if d.Get("desired_status") != "" {
11111128
d.Set("desired_status", instance.Status)
11121129
}

google-beta/resource_compute_instance_template.go

Lines changed: 37 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -521,7 +521,23 @@ func resourceComputeInstanceTemplate() *schema.Resource {
521521
},
522522
},
523523
},
524-
524+
"confidential_instance_config": {
525+
Type: schema.TypeList,
526+
MaxItems: 1,
527+
Optional: true,
528+
ForceNew: true,
529+
Computed: true,
530+
Description: `The Confidential VM config being used by the instance. on_host_maintenance has to be set to TERMINATE or this will fail to create.`,
531+
Elem: &schema.Resource{
532+
Schema: map[string]*schema.Schema{
533+
"enable_confidential_compute": {
534+
Type: schema.TypeBool,
535+
Required: true,
536+
Description: `Defines whether the instance should have confidential compute enabled.`,
537+
},
538+
},
539+
},
540+
},
525541
"guest_accelerator": {
526542
Type: schema.TypeList,
527543
Optional: true,
@@ -819,19 +835,20 @@ func resourceComputeInstanceTemplateCreate(d *schema.ResourceData, meta interfac
819835
}
820836

821837
instanceProperties := &computeBeta.InstanceProperties{
822-
CanIpForward: d.Get("can_ip_forward").(bool),
823-
Description: d.Get("instance_description").(string),
824-
GuestAccelerators: expandInstanceTemplateGuestAccelerators(d, config),
825-
MachineType: d.Get("machine_type").(string),
826-
MinCpuPlatform: d.Get("min_cpu_platform").(string),
827-
Disks: disks,
828-
Metadata: metadata,
829-
NetworkInterfaces: networks,
830-
Scheduling: scheduling,
831-
ServiceAccounts: expandServiceAccounts(d.Get("service_account").([]interface{})),
832-
Tags: resourceInstanceTags(d),
833-
ShieldedInstanceConfig: expandShieldedVmConfigs(d),
834-
DisplayDevice: expandDisplayDevice(d),
838+
CanIpForward: d.Get("can_ip_forward").(bool),
839+
Description: d.Get("instance_description").(string),
840+
GuestAccelerators: expandInstanceTemplateGuestAccelerators(d, config),
841+
MachineType: d.Get("machine_type").(string),
842+
MinCpuPlatform: d.Get("min_cpu_platform").(string),
843+
Disks: disks,
844+
Metadata: metadata,
845+
NetworkInterfaces: networks,
846+
Scheduling: scheduling,
847+
ServiceAccounts: expandServiceAccounts(d.Get("service_account").([]interface{})),
848+
Tags: resourceInstanceTags(d),
849+
ConfidentialInstanceConfig: expandConfidentialInstanceConfig(d),
850+
ShieldedInstanceConfig: expandShieldedVmConfigs(d),
851+
DisplayDevice: expandDisplayDevice(d),
835852
}
836853

837854
if _, ok := d.GetOk("labels"); ok {
@@ -1198,6 +1215,12 @@ func resourceComputeInstanceTemplateRead(d *schema.ResourceData, meta interface{
11981215
return fmt.Errorf("Error setting shielded_instance_config: %s", err)
11991216
}
12001217
}
1218+
1219+
if instanceTemplate.Properties.ConfidentialInstanceConfig != nil {
1220+
if err = d.Set("confidential_instance_config", flattenConfidentialInstanceConfig(instanceTemplate.Properties.ConfidentialInstanceConfig)); err != nil {
1221+
return fmt.Errorf("Error setting confidential_instance_config: %s", err)
1222+
}
1223+
}
12011224
if instanceTemplate.Properties.DisplayDevice != nil {
12021225
if err = d.Set("enable_display", flattenEnableDisplay(instanceTemplate.Properties.DisplayDevice)); err != nil {
12031226
return fmt.Errorf("Error setting enable_display: %s", err)

google-beta/resource_compute_instance_template_test.go

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -786,6 +786,27 @@ func TestAccComputeInstanceTemplate_shieldedVmConfig2(t *testing.T) {
786786
})
787787
}
788788

789+
func TestAccComputeInstanceTemplate_ConfidentialInstanceConfigMain(t *testing.T) {
790+
t.Parallel()
791+
792+
var instanceTemplate computeBeta.InstanceTemplate
793+
794+
vcrTest(t, resource.TestCase{
795+
PreCheck: func() { testAccPreCheck(t) },
796+
Providers: testAccProvidersOiCS,
797+
CheckDestroy: testAccCheckComputeInstanceTemplateDestroyProducer(t),
798+
Steps: []resource.TestStep{
799+
{
800+
Config: testAccComputeInstanceTemplateConfidentialInstanceConfig(randString(t, 10), true),
801+
Check: resource.ComposeTestCheckFunc(
802+
testAccCheckComputeInstanceTemplateExists(t, "google_compute_instance_template.foobar", &instanceTemplate),
803+
testAccCheckComputeInstanceTemplateHasConfidentialInstanceConfig(&instanceTemplate, true),
804+
),
805+
},
806+
},
807+
})
808+
}
809+
789810
func TestAccComputeInstanceTemplate_enableDisplay(t *testing.T) {
790811
t.Parallel()
791812

@@ -1185,6 +1206,17 @@ func testAccCheckComputeInstanceTemplateHasShieldedVmConfig(instanceTemplate *co
11851206
}
11861207
}
11871208

1209+
func testAccCheckComputeInstanceTemplateHasConfidentialInstanceConfig(instanceTemplate *computeBeta.InstanceTemplate, EnableConfidentialCompute bool) resource.TestCheckFunc {
1210+
1211+
return func(s *terraform.State) error {
1212+
if instanceTemplate.Properties.ConfidentialInstanceConfig.EnableConfidentialCompute != EnableConfidentialCompute {
1213+
return fmt.Errorf("Wrong ConfidentialInstanceConfig EnableConfidentialCompute: expected %t, got, %t", EnableConfidentialCompute, instanceTemplate.Properties.ConfidentialInstanceConfig.EnableConfidentialCompute)
1214+
}
1215+
1216+
return nil
1217+
}
1218+
}
1219+
11881220
func testAccCheckComputeInstanceTemplateLacksShieldedVmConfig(instanceTemplate *computeBeta.InstanceTemplate) resource.TestCheckFunc {
11891221
return func(s *terraform.State) error {
11901222
if instanceTemplate.Properties.ShieldedVmConfig != nil {
@@ -2023,6 +2055,41 @@ resource "google_compute_instance_template" "foobar" {
20232055
`, suffix, enableSecureBoot, enableVtpm, enableIntegrityMonitoring)
20242056
}
20252057

2058+
func testAccComputeInstanceTemplateConfidentialInstanceConfig(suffix string, enableConfidentialCompute bool) string {
2059+
return fmt.Sprintf(`
2060+
data "google_compute_image" "my_image" {
2061+
provider = google-beta
2062+
family = "ubuntu-2004-lts"
2063+
project = "ubuntu-os-cloud"
2064+
}
2065+
2066+
resource "google_compute_instance_template" "foobar" {
2067+
provider = google-beta
2068+
name = "cvm-%s"
2069+
machine_type = "n2d-standard-2"
2070+
2071+
disk {
2072+
source_image = data.google_compute_image.my_image.self_link
2073+
auto_delete = true
2074+
boot = true
2075+
}
2076+
2077+
network_interface {
2078+
network = "default"
2079+
}
2080+
2081+
confidential_instance_config {
2082+
enable_confidential_compute = %t
2083+
}
2084+
2085+
scheduling {
2086+
on_host_maintenance = "TERMINATE"
2087+
}
2088+
2089+
}
2090+
`, suffix, enableConfidentialCompute)
2091+
}
2092+
20262093
func testAccComputeInstanceTemplate_enableDisplay(suffix string) string {
20272094
return fmt.Sprintf(`
20282095
data "google_compute_image" "my_image" {

google-beta/resource_compute_instance_test.go

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1303,6 +1303,28 @@ func TestAccComputeInstance_shieldedVmConfig2(t *testing.T) {
13031303
})
13041304
}
13051305

1306+
func TestAccComputeInstanceConfidentialInstanceConfigMain(t *testing.T) {
1307+
t.Parallel()
1308+
1309+
var instance computeBeta.Instance
1310+
instanceName := fmt.Sprintf("tf-test-%s", randString(t, 10))
1311+
1312+
vcrTest(t, resource.TestCase{
1313+
PreCheck: func() { testAccPreCheck(t) },
1314+
Providers: testAccProvidersOiCS,
1315+
CheckDestroy: testAccCheckComputeInstanceDestroyProducer(t),
1316+
Steps: []resource.TestStep{
1317+
{
1318+
Config: testAccComputeInstanceConfidentialInstanceConfig(instanceName, true),
1319+
Check: resource.ComposeTestCheckFunc(
1320+
testAccCheckComputeInstanceExists(t, "google_compute_instance.foobar", &instance),
1321+
testAccCheckComputeInstanceHasConfidentialInstanceConfig(&instance, true),
1322+
),
1323+
},
1324+
},
1325+
})
1326+
}
1327+
13061328
func TestAccComputeInstance_enableDisplay(t *testing.T) {
13071329
t.Parallel()
13081330

@@ -2453,6 +2475,17 @@ func testAccCheckComputeInstanceHasShieldedVmConfig(instance *computeBeta.Instan
24532475
}
24542476
}
24552477

2478+
func testAccCheckComputeInstanceHasConfidentialInstanceConfig(instance *computeBeta.Instance, EnableConfidentialCompute bool) resource.TestCheckFunc {
2479+
2480+
return func(s *terraform.State) error {
2481+
if instance.ConfidentialInstanceConfig.EnableConfidentialCompute != EnableConfidentialCompute {
2482+
return fmt.Errorf("Wrong ConfidentialInstanceConfig EnableConfidentialCompute: expected %t, got, %t", EnableConfidentialCompute, instance.ConfidentialInstanceConfig.EnableConfidentialCompute)
2483+
}
2484+
2485+
return nil
2486+
}
2487+
}
2488+
24562489
func testAccCheckComputeInstanceLacksShieldedVmConfig(instance *computeBeta.Instance) resource.TestCheckFunc {
24572490
return func(s *terraform.State) error {
24582491
if instance.ShieldedVmConfig != nil {
@@ -4462,6 +4495,42 @@ resource "google_compute_instance" "foobar" {
44624495
`, instance, enableSecureBoot, enableVtpm, enableIntegrityMonitoring)
44634496
}
44644497

4498+
func testAccComputeInstanceConfidentialInstanceConfig(instance string, enableConfidentialCompute bool) string {
4499+
return fmt.Sprintf(`
4500+
data "google_compute_image" "my_image" {
4501+
provider = google-beta
4502+
family = "ubuntu-2004-lts"
4503+
project = "ubuntu-os-cloud"
4504+
}
4505+
4506+
resource "google_compute_instance" "foobar" {
4507+
provider = google-beta
4508+
name = "%s"
4509+
machine_type = "n2d-standard-2"
4510+
zone = "us-central1-a"
4511+
4512+
boot_disk {
4513+
initialize_params {
4514+
image = data.google_compute_image.my_image.self_link
4515+
}
4516+
}
4517+
4518+
network_interface {
4519+
network = "default"
4520+
}
4521+
4522+
confidential_instance_config {
4523+
enable_confidential_compute = %t
4524+
}
4525+
4526+
scheduling {
4527+
on_host_maintenance = "TERMINATE"
4528+
}
4529+
4530+
}
4531+
`, instance, enableConfidentialCompute)
4532+
}
4533+
44654534
func testAccComputeInstance_enableDisplay(instance string) string {
44664535
return fmt.Sprintf(`
44674536
data "google_compute_image" "my_image" {

0 commit comments

Comments
 (0)