Skip to content

Commit 8e13e8d

Browse files
shielded instance config for Workbench instances (#9622) (#17306)
* shielded instance config for Workbench instances * Add test to double apply [upstream:25d06fee267f69dfaf8dc323a95997fbf869b1c1] Signed-off-by: Modular Magician <[email protected]>
1 parent dc38398 commit 8e13e8d

6 files changed

+383
-1
lines changed

.changelog/9622.txt

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
```release-note:enhancement
2+
workbench: added `shielded_instance_config` field to `google_workbench_instance` resource
3+
```

google/services/workbench/resource_workbench_instance.go

+125-1
Original file line numberDiff line numberDiff line change
@@ -465,6 +465,42 @@ service account. Set by the CLH to https://www.googleapis.com/auth/cloud-platfor
465465
},
466466
},
467467
},
468+
"shielded_instance_config": {
469+
Type: schema.TypeList,
470+
Computed: true,
471+
Optional: true,
472+
Description: `A set of Shielded Instance options. See [Images using supported Shielded
473+
VM features](https://cloud.google.com/compute/docs/instances/modifying-shielded-vm).
474+
Not all combinations are valid.`,
475+
MaxItems: 1,
476+
Elem: &schema.Resource{
477+
Schema: map[string]*schema.Schema{
478+
"enable_integrity_monitoring": {
479+
Type: schema.TypeBool,
480+
Optional: true,
481+
Description: `Optional. Defines whether the VM instance has integrity monitoring
482+
enabled. Enables monitoring and attestation of the boot integrity of the VM
483+
instance. The attestation is performed against the integrity policy baseline.
484+
This baseline is initially derived from the implicitly trusted boot image
485+
when the VM instance is created. Enabled by default.`,
486+
},
487+
"enable_secure_boot": {
488+
Type: schema.TypeBool,
489+
Optional: true,
490+
Description: `Optional. Defines whether the VM instance has Secure Boot enabled.
491+
Secure Boot helps ensure that the system only runs authentic software by verifying
492+
the digital signature of all boot components, and halting the boot process
493+
if signature verification fails. Disabled by default.`,
494+
},
495+
"enable_vtpm": {
496+
Type: schema.TypeBool,
497+
Optional: true,
498+
Description: `Optional. Defines whether the VM instance has the vTPM enabled.
499+
Enabled by default.`,
500+
},
501+
},
502+
},
503+
},
468504
"tags": {
469505
Type: schema.TypeList,
470506
Computed: true,
@@ -922,7 +958,7 @@ func resourceWorkbenchInstanceUpdate(d *schema.ResourceData, meta interface{}) e
922958
return err
923959
}
924960
name := d.Get("name").(string)
925-
if d.HasChange("gce_setup.0.machine_type") || d.HasChange("gce_setup.0.accelerator_configs") {
961+
if d.HasChange("gce_setup.0.machine_type") || d.HasChange("gce_setup.0.accelerator_configs") || d.HasChange("gce_setup.0.shielded_instance_config") {
926962
state := d.Get("state").(string)
927963

928964
if state != "STOPPED" {
@@ -951,6 +987,9 @@ func resourceWorkbenchInstanceUpdate(d *schema.ResourceData, meta interface{}) e
951987
if d.HasChange("gce_setup.0.accelerator_configs") {
952988
newUpdateMask = append(newUpdateMask, "gce_setup.accelerator_configs")
953989
}
990+
if d.HasChange("gce_setup.0.shielded_instance_config") {
991+
newUpdateMask = append(newUpdateMask, "gce_setup.shielded_instance_config")
992+
}
954993
if d.HasChange("gce_setup.0.metadata") {
955994
newUpdateMask = append(newUpdateMask, "gceSetup.metadata")
956995
}
@@ -1110,6 +1149,8 @@ func flattenWorkbenchInstanceGceSetup(v interface{}, d *schema.ResourceData, con
11101149
flattenWorkbenchInstanceGceSetupMachineType(original["machineType"], d, config)
11111150
transformed["accelerator_configs"] =
11121151
flattenWorkbenchInstanceGceSetupAcceleratorConfigs(original["acceleratorConfigs"], d, config)
1152+
transformed["shielded_instance_config"] =
1153+
flattenWorkbenchInstanceGceSetupShieldedInstanceConfig(original["shieldedInstanceConfig"], d, config)
11131154
transformed["service_accounts"] =
11141155
flattenWorkbenchInstanceGceSetupServiceAccounts(original["serviceAccounts"], d, config)
11151156
transformed["vm_image"] =
@@ -1164,6 +1205,32 @@ func flattenWorkbenchInstanceGceSetupAcceleratorConfigsCoreCount(v interface{},
11641205
return v
11651206
}
11661207

1208+
func flattenWorkbenchInstanceGceSetupShieldedInstanceConfig(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
1209+
if v == nil {
1210+
return nil
1211+
}
1212+
original := v.(map[string]interface{})
1213+
transformed := make(map[string]interface{})
1214+
transformed["enable_secure_boot"] =
1215+
flattenWorkbenchInstanceGceSetupShieldedInstanceConfigEnableSecureBoot(original["enableSecureBoot"], d, config)
1216+
transformed["enable_vtpm"] =
1217+
flattenWorkbenchInstanceGceSetupShieldedInstanceConfigEnableVtpm(original["enableVtpm"], d, config)
1218+
transformed["enable_integrity_monitoring"] =
1219+
flattenWorkbenchInstanceGceSetupShieldedInstanceConfigEnableIntegrityMonitoring(original["enableIntegrityMonitoring"], d, config)
1220+
return []interface{}{transformed}
1221+
}
1222+
func flattenWorkbenchInstanceGceSetupShieldedInstanceConfigEnableSecureBoot(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
1223+
return v
1224+
}
1225+
1226+
func flattenWorkbenchInstanceGceSetupShieldedInstanceConfigEnableVtpm(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
1227+
return v
1228+
}
1229+
1230+
func flattenWorkbenchInstanceGceSetupShieldedInstanceConfigEnableIntegrityMonitoring(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
1231+
return v
1232+
}
1233+
11671234
func flattenWorkbenchInstanceGceSetupServiceAccounts(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
11681235
if v == nil {
11691236
return v
@@ -1474,6 +1541,13 @@ func expandWorkbenchInstanceGceSetup(v interface{}, d tpgresource.TerraformResou
14741541
transformed["acceleratorConfigs"] = transformedAcceleratorConfigs
14751542
}
14761543

1544+
transformedShieldedInstanceConfig, err := expandWorkbenchInstanceGceSetupShieldedInstanceConfig(original["shielded_instance_config"], d, config)
1545+
if err != nil {
1546+
return nil, err
1547+
} else {
1548+
transformed["shieldedInstanceConfig"] = transformedShieldedInstanceConfig
1549+
}
1550+
14771551
transformedServiceAccounts, err := expandWorkbenchInstanceGceSetupServiceAccounts(original["service_accounts"], d, config)
14781552
if err != nil {
14791553
return nil, err
@@ -1581,6 +1655,56 @@ func expandWorkbenchInstanceGceSetupAcceleratorConfigsCoreCount(v interface{}, d
15811655
return v, nil
15821656
}
15831657

1658+
func expandWorkbenchInstanceGceSetupShieldedInstanceConfig(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
1659+
l := v.([]interface{})
1660+
if len(l) == 0 {
1661+
return nil, nil
1662+
}
1663+
1664+
if l[0] == nil {
1665+
transformed := make(map[string]interface{})
1666+
return transformed, nil
1667+
}
1668+
raw := l[0]
1669+
original := raw.(map[string]interface{})
1670+
transformed := make(map[string]interface{})
1671+
1672+
transformedEnableSecureBoot, err := expandWorkbenchInstanceGceSetupShieldedInstanceConfigEnableSecureBoot(original["enable_secure_boot"], d, config)
1673+
if err != nil {
1674+
return nil, err
1675+
} else if val := reflect.ValueOf(transformedEnableSecureBoot); val.IsValid() && !tpgresource.IsEmptyValue(val) {
1676+
transformed["enableSecureBoot"] = transformedEnableSecureBoot
1677+
}
1678+
1679+
transformedEnableVtpm, err := expandWorkbenchInstanceGceSetupShieldedInstanceConfigEnableVtpm(original["enable_vtpm"], d, config)
1680+
if err != nil {
1681+
return nil, err
1682+
} else if val := reflect.ValueOf(transformedEnableVtpm); val.IsValid() && !tpgresource.IsEmptyValue(val) {
1683+
transformed["enableVtpm"] = transformedEnableVtpm
1684+
}
1685+
1686+
transformedEnableIntegrityMonitoring, err := expandWorkbenchInstanceGceSetupShieldedInstanceConfigEnableIntegrityMonitoring(original["enable_integrity_monitoring"], d, config)
1687+
if err != nil {
1688+
return nil, err
1689+
} else if val := reflect.ValueOf(transformedEnableIntegrityMonitoring); val.IsValid() && !tpgresource.IsEmptyValue(val) {
1690+
transformed["enableIntegrityMonitoring"] = transformedEnableIntegrityMonitoring
1691+
}
1692+
1693+
return transformed, nil
1694+
}
1695+
1696+
func expandWorkbenchInstanceGceSetupShieldedInstanceConfigEnableSecureBoot(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
1697+
return v, nil
1698+
}
1699+
1700+
func expandWorkbenchInstanceGceSetupShieldedInstanceConfigEnableVtpm(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
1701+
return v, nil
1702+
}
1703+
1704+
func expandWorkbenchInstanceGceSetupShieldedInstanceConfigEnableIntegrityMonitoring(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
1705+
return v, nil
1706+
}
1707+
15841708
func expandWorkbenchInstanceGceSetupServiceAccounts(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
15851709
l := v.([]interface{})
15861710
req := make([]interface{}, 0, len(l))

google/services/workbench/resource_workbench_instance_generated_test.go

+12
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,12 @@ resource "google_workbench_instance" "instance" {
145145
gce_setup {
146146
machine_type = "e2-standard-4"
147147
148+
shielded_instance_config {
149+
enable_secure_boot = false
150+
enable_vtpm = false
151+
enable_integrity_monitoring = false
152+
}
153+
148154
service_accounts {
149155
email = "%{service_account}"
150156
}
@@ -219,6 +225,12 @@ resource "google_workbench_instance" "instance" {
219225
core_count = 1
220226
}
221227
228+
shielded_instance_config {
229+
enable_secure_boot = true
230+
enable_vtpm = true
231+
enable_integrity_monitoring = true
232+
}
233+
222234
disable_public_ip = false
223235
224236
service_accounts {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
package workbench_test
4+
5+
import (
6+
"testing"
7+
8+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
9+
10+
"github.com/hashicorp/terraform-provider-google/google/acctest"
11+
)
12+
13+
func TestAccWorkbenchInstance_shielded_config_update(t *testing.T) {
14+
t.Parallel()
15+
16+
context := map[string]interface{}{
17+
"random_suffix": acctest.RandString(t, 10),
18+
}
19+
20+
acctest.VcrTest(t, resource.TestCase{
21+
PreCheck: func() { acctest.AccTestPreCheck(t) },
22+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
23+
Steps: []resource.TestStep{
24+
{
25+
Config: testAccWorkbenchInstance_shielded_config_false(context),
26+
},
27+
{
28+
ResourceName: "google_workbench_instance.instance",
29+
ImportState: true,
30+
ImportStateVerify: true,
31+
ImportStateVerifyIgnore: []string{"name", "instance_owners", "location", "instance_id", "request_id", "labels", "terraform_labels"},
32+
},
33+
{
34+
Config: testAccWorkbenchInstance_shielded_config_true(context),
35+
},
36+
{
37+
ResourceName: "google_workbench_instance.instance",
38+
ImportState: true,
39+
ImportStateVerify: true,
40+
ImportStateVerifyIgnore: []string{"name", "instance_owners", "location", "instance_id", "request_id", "labels", "terraform_labels"},
41+
},
42+
},
43+
})
44+
}
45+
46+
func TestAccWorkbenchInstance_shielded_config_remove(t *testing.T) {
47+
t.Parallel()
48+
49+
context := map[string]interface{}{
50+
"random_suffix": acctest.RandString(t, 10),
51+
}
52+
53+
acctest.VcrTest(t, resource.TestCase{
54+
PreCheck: func() { acctest.AccTestPreCheck(t) },
55+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
56+
Steps: []resource.TestStep{
57+
{
58+
Config: testAccWorkbenchInstance_shielded_config_true(context),
59+
},
60+
{
61+
ResourceName: "google_workbench_instance.instance",
62+
ImportState: true,
63+
ImportStateVerify: true,
64+
ImportStateVerifyIgnore: []string{"name", "instance_owners", "location", "instance_id", "request_id", "labels", "terraform_labels"},
65+
},
66+
{
67+
Config: testAccWorkbenchInstance_shielded_config_none(context),
68+
},
69+
{
70+
ResourceName: "google_workbench_instance.instance",
71+
ImportState: true,
72+
ImportStateVerify: true,
73+
ImportStateVerifyIgnore: []string{"name", "instance_owners", "location", "instance_id", "request_id", "labels", "terraform_labels"},
74+
},
75+
},
76+
})
77+
}
78+
79+
func TestAccWorkbenchInstance_shielded_config_double_apply(t *testing.T) {
80+
t.Parallel()
81+
82+
context := map[string]interface{}{
83+
"random_suffix": acctest.RandString(t, 10),
84+
}
85+
86+
acctest.VcrTest(t, resource.TestCase{
87+
PreCheck: func() { acctest.AccTestPreCheck(t) },
88+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
89+
Steps: []resource.TestStep{
90+
{
91+
Config: testAccWorkbenchInstance_shielded_config_none(context),
92+
},
93+
{
94+
ResourceName: "google_workbench_instance.instance",
95+
ImportState: true,
96+
ImportStateVerify: true,
97+
ImportStateVerifyIgnore: []string{"name", "instance_owners", "location", "instance_id", "request_id", "labels", "terraform_labels"},
98+
},
99+
{
100+
Config: testAccWorkbenchInstance_shielded_config_none(context),
101+
},
102+
{
103+
ResourceName: "google_workbench_instance.instance",
104+
ImportState: true,
105+
ImportStateVerify: true,
106+
ImportStateVerifyIgnore: []string{"name", "instance_owners", "location", "instance_id", "request_id", "labels", "terraform_labels"},
107+
},
108+
{
109+
Config: testAccWorkbenchInstance_shielded_config_false(context),
110+
},
111+
{
112+
ResourceName: "google_workbench_instance.instance",
113+
ImportState: true,
114+
ImportStateVerify: true,
115+
ImportStateVerifyIgnore: []string{"name", "instance_owners", "location", "instance_id", "request_id", "labels", "terraform_labels"},
116+
},
117+
{
118+
Config: testAccWorkbenchInstance_shielded_config_false(context),
119+
},
120+
{
121+
ResourceName: "google_workbench_instance.instance",
122+
ImportState: true,
123+
ImportStateVerify: true,
124+
ImportStateVerifyIgnore: []string{"name", "instance_owners", "location", "instance_id", "request_id", "labels", "terraform_labels"},
125+
},
126+
{
127+
Config: testAccWorkbenchInstance_shielded_config_true(context),
128+
},
129+
{
130+
ResourceName: "google_workbench_instance.instance",
131+
ImportState: true,
132+
ImportStateVerify: true,
133+
ImportStateVerifyIgnore: []string{"name", "instance_owners", "location", "instance_id", "request_id", "labels", "terraform_labels"},
134+
},
135+
{
136+
Config: testAccWorkbenchInstance_shielded_config_true(context),
137+
},
138+
{
139+
ResourceName: "google_workbench_instance.instance",
140+
ImportState: true,
141+
ImportStateVerify: true,
142+
ImportStateVerifyIgnore: []string{"name", "instance_owners", "location", "instance_id", "request_id", "labels", "terraform_labels"},
143+
},
144+
},
145+
})
146+
}
147+
148+
func testAccWorkbenchInstance_shielded_config_true(context map[string]interface{}) string {
149+
return acctest.Nprintf(`
150+
resource "google_workbench_instance" "instance" {
151+
name = "tf-test-workbench-instance%{random_suffix}"
152+
location = "us-central1-a"
153+
154+
gce_setup {
155+
shielded_instance_config {
156+
enable_secure_boot = true
157+
enable_vtpm = true
158+
enable_integrity_monitoring = true
159+
}
160+
}
161+
}
162+
`, context)
163+
}
164+
165+
func testAccWorkbenchInstance_shielded_config_false(context map[string]interface{}) string {
166+
return acctest.Nprintf(`
167+
resource "google_workbench_instance" "instance" {
168+
name = "tf-test-workbench-instance%{random_suffix}"
169+
location = "us-central1-a"
170+
171+
gce_setup {
172+
shielded_instance_config {
173+
enable_secure_boot = false
174+
enable_vtpm = false
175+
enable_integrity_monitoring = false
176+
}
177+
}
178+
179+
}
180+
`, context)
181+
}
182+
183+
func testAccWorkbenchInstance_shielded_config_none(context map[string]interface{}) string {
184+
return acctest.Nprintf(`
185+
resource "google_workbench_instance" "instance" {
186+
name = "tf-test-workbench-instance%{random_suffix}"
187+
location = "us-central1-a"
188+
}
189+
`, context)
190+
}

0 commit comments

Comments
 (0)