Skip to content

Commit

Permalink
shielded instance config for Workbench instances (#9622) (#17306)
Browse files Browse the repository at this point in the history
* shielded instance config for Workbench instances

* Add test to double apply

[upstream:25d06fee267f69dfaf8dc323a95997fbf869b1c1]

Signed-off-by: Modular Magician <magic-modules@google.com>
  • Loading branch information
modular-magician authored Feb 16, 2024
1 parent dc38398 commit 8e13e8d
Show file tree
Hide file tree
Showing 6 changed files with 383 additions and 1 deletion.
3 changes: 3 additions & 0 deletions .changelog/9622.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:enhancement
workbench: added `shielded_instance_config` field to `google_workbench_instance` resource
```
126 changes: 125 additions & 1 deletion google/services/workbench/resource_workbench_instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,42 @@ service account. Set by the CLH to https://www.googleapis.com/auth/cloud-platfor
},
},
},
"shielded_instance_config": {
Type: schema.TypeList,
Computed: true,
Optional: true,
Description: `A set of Shielded Instance options. See [Images using supported Shielded
VM features](https://cloud.google.com/compute/docs/instances/modifying-shielded-vm).
Not all combinations are valid.`,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"enable_integrity_monitoring": {
Type: schema.TypeBool,
Optional: true,
Description: `Optional. Defines whether the VM instance has integrity monitoring
enabled. Enables monitoring and attestation of the boot integrity of the VM
instance. The attestation is performed against the integrity policy baseline.
This baseline is initially derived from the implicitly trusted boot image
when the VM instance is created. Enabled by default.`,
},
"enable_secure_boot": {
Type: schema.TypeBool,
Optional: true,
Description: `Optional. Defines whether the VM instance has Secure Boot enabled.
Secure Boot helps ensure that the system only runs authentic software by verifying
the digital signature of all boot components, and halting the boot process
if signature verification fails. Disabled by default.`,
},
"enable_vtpm": {
Type: schema.TypeBool,
Optional: true,
Description: `Optional. Defines whether the VM instance has the vTPM enabled.
Enabled by default.`,
},
},
},
},
"tags": {
Type: schema.TypeList,
Computed: true,
Expand Down Expand Up @@ -922,7 +958,7 @@ func resourceWorkbenchInstanceUpdate(d *schema.ResourceData, meta interface{}) e
return err
}
name := d.Get("name").(string)
if d.HasChange("gce_setup.0.machine_type") || d.HasChange("gce_setup.0.accelerator_configs") {
if d.HasChange("gce_setup.0.machine_type") || d.HasChange("gce_setup.0.accelerator_configs") || d.HasChange("gce_setup.0.shielded_instance_config") {
state := d.Get("state").(string)

if state != "STOPPED" {
Expand Down Expand Up @@ -951,6 +987,9 @@ func resourceWorkbenchInstanceUpdate(d *schema.ResourceData, meta interface{}) e
if d.HasChange("gce_setup.0.accelerator_configs") {
newUpdateMask = append(newUpdateMask, "gce_setup.accelerator_configs")
}
if d.HasChange("gce_setup.0.shielded_instance_config") {
newUpdateMask = append(newUpdateMask, "gce_setup.shielded_instance_config")
}
if d.HasChange("gce_setup.0.metadata") {
newUpdateMask = append(newUpdateMask, "gceSetup.metadata")
}
Expand Down Expand Up @@ -1110,6 +1149,8 @@ func flattenWorkbenchInstanceGceSetup(v interface{}, d *schema.ResourceData, con
flattenWorkbenchInstanceGceSetupMachineType(original["machineType"], d, config)
transformed["accelerator_configs"] =
flattenWorkbenchInstanceGceSetupAcceleratorConfigs(original["acceleratorConfigs"], d, config)
transformed["shielded_instance_config"] =
flattenWorkbenchInstanceGceSetupShieldedInstanceConfig(original["shieldedInstanceConfig"], d, config)
transformed["service_accounts"] =
flattenWorkbenchInstanceGceSetupServiceAccounts(original["serviceAccounts"], d, config)
transformed["vm_image"] =
Expand Down Expand Up @@ -1164,6 +1205,32 @@ func flattenWorkbenchInstanceGceSetupAcceleratorConfigsCoreCount(v interface{},
return v
}

func flattenWorkbenchInstanceGceSetupShieldedInstanceConfig(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
if v == nil {
return nil
}
original := v.(map[string]interface{})
transformed := make(map[string]interface{})
transformed["enable_secure_boot"] =
flattenWorkbenchInstanceGceSetupShieldedInstanceConfigEnableSecureBoot(original["enableSecureBoot"], d, config)
transformed["enable_vtpm"] =
flattenWorkbenchInstanceGceSetupShieldedInstanceConfigEnableVtpm(original["enableVtpm"], d, config)
transformed["enable_integrity_monitoring"] =
flattenWorkbenchInstanceGceSetupShieldedInstanceConfigEnableIntegrityMonitoring(original["enableIntegrityMonitoring"], d, config)
return []interface{}{transformed}
}
func flattenWorkbenchInstanceGceSetupShieldedInstanceConfigEnableSecureBoot(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}

func flattenWorkbenchInstanceGceSetupShieldedInstanceConfigEnableVtpm(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}

func flattenWorkbenchInstanceGceSetupShieldedInstanceConfigEnableIntegrityMonitoring(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}

func flattenWorkbenchInstanceGceSetupServiceAccounts(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
if v == nil {
return v
Expand Down Expand Up @@ -1474,6 +1541,13 @@ func expandWorkbenchInstanceGceSetup(v interface{}, d tpgresource.TerraformResou
transformed["acceleratorConfigs"] = transformedAcceleratorConfigs
}

transformedShieldedInstanceConfig, err := expandWorkbenchInstanceGceSetupShieldedInstanceConfig(original["shielded_instance_config"], d, config)
if err != nil {
return nil, err
} else {
transformed["shieldedInstanceConfig"] = transformedShieldedInstanceConfig
}

transformedServiceAccounts, err := expandWorkbenchInstanceGceSetupServiceAccounts(original["service_accounts"], d, config)
if err != nil {
return nil, err
Expand Down Expand Up @@ -1581,6 +1655,56 @@ func expandWorkbenchInstanceGceSetupAcceleratorConfigsCoreCount(v interface{}, d
return v, nil
}

func expandWorkbenchInstanceGceSetupShieldedInstanceConfig(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
l := v.([]interface{})
if len(l) == 0 {
return nil, nil
}

if l[0] == nil {
transformed := make(map[string]interface{})
return transformed, nil
}
raw := l[0]
original := raw.(map[string]interface{})
transformed := make(map[string]interface{})

transformedEnableSecureBoot, err := expandWorkbenchInstanceGceSetupShieldedInstanceConfigEnableSecureBoot(original["enable_secure_boot"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedEnableSecureBoot); val.IsValid() && !tpgresource.IsEmptyValue(val) {
transformed["enableSecureBoot"] = transformedEnableSecureBoot
}

transformedEnableVtpm, err := expandWorkbenchInstanceGceSetupShieldedInstanceConfigEnableVtpm(original["enable_vtpm"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedEnableVtpm); val.IsValid() && !tpgresource.IsEmptyValue(val) {
transformed["enableVtpm"] = transformedEnableVtpm
}

transformedEnableIntegrityMonitoring, err := expandWorkbenchInstanceGceSetupShieldedInstanceConfigEnableIntegrityMonitoring(original["enable_integrity_monitoring"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedEnableIntegrityMonitoring); val.IsValid() && !tpgresource.IsEmptyValue(val) {
transformed["enableIntegrityMonitoring"] = transformedEnableIntegrityMonitoring
}

return transformed, nil
}

func expandWorkbenchInstanceGceSetupShieldedInstanceConfigEnableSecureBoot(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
return v, nil
}

func expandWorkbenchInstanceGceSetupShieldedInstanceConfigEnableVtpm(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
return v, nil
}

func expandWorkbenchInstanceGceSetupShieldedInstanceConfigEnableIntegrityMonitoring(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
return v, nil
}

func expandWorkbenchInstanceGceSetupServiceAccounts(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
l := v.([]interface{})
req := make([]interface{}, 0, len(l))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,12 @@ resource "google_workbench_instance" "instance" {
gce_setup {
machine_type = "e2-standard-4"
shielded_instance_config {
enable_secure_boot = false
enable_vtpm = false
enable_integrity_monitoring = false
}
service_accounts {
email = "%{service_account}"
}
Expand Down Expand Up @@ -219,6 +225,12 @@ resource "google_workbench_instance" "instance" {
core_count = 1
}
shielded_instance_config {
enable_secure_boot = true
enable_vtpm = true
enable_integrity_monitoring = true
}
disable_public_ip = false
service_accounts {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
package workbench_test

import (
"testing"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"

"github.com/hashicorp/terraform-provider-google/google/acctest"
)

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

context := map[string]interface{}{
"random_suffix": acctest.RandString(t, 10),
}

acctest.VcrTest(t, resource.TestCase{
PreCheck: func() { acctest.AccTestPreCheck(t) },
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
Steps: []resource.TestStep{
{
Config: testAccWorkbenchInstance_shielded_config_false(context),
},
{
ResourceName: "google_workbench_instance.instance",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"name", "instance_owners", "location", "instance_id", "request_id", "labels", "terraform_labels"},
},
{
Config: testAccWorkbenchInstance_shielded_config_true(context),
},
{
ResourceName: "google_workbench_instance.instance",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"name", "instance_owners", "location", "instance_id", "request_id", "labels", "terraform_labels"},
},
},
})
}

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

context := map[string]interface{}{
"random_suffix": acctest.RandString(t, 10),
}

acctest.VcrTest(t, resource.TestCase{
PreCheck: func() { acctest.AccTestPreCheck(t) },
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
Steps: []resource.TestStep{
{
Config: testAccWorkbenchInstance_shielded_config_true(context),
},
{
ResourceName: "google_workbench_instance.instance",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"name", "instance_owners", "location", "instance_id", "request_id", "labels", "terraform_labels"},
},
{
Config: testAccWorkbenchInstance_shielded_config_none(context),
},
{
ResourceName: "google_workbench_instance.instance",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"name", "instance_owners", "location", "instance_id", "request_id", "labels", "terraform_labels"},
},
},
})
}

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

context := map[string]interface{}{
"random_suffix": acctest.RandString(t, 10),
}

acctest.VcrTest(t, resource.TestCase{
PreCheck: func() { acctest.AccTestPreCheck(t) },
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
Steps: []resource.TestStep{
{
Config: testAccWorkbenchInstance_shielded_config_none(context),
},
{
ResourceName: "google_workbench_instance.instance",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"name", "instance_owners", "location", "instance_id", "request_id", "labels", "terraform_labels"},
},
{
Config: testAccWorkbenchInstance_shielded_config_none(context),
},
{
ResourceName: "google_workbench_instance.instance",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"name", "instance_owners", "location", "instance_id", "request_id", "labels", "terraform_labels"},
},
{
Config: testAccWorkbenchInstance_shielded_config_false(context),
},
{
ResourceName: "google_workbench_instance.instance",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"name", "instance_owners", "location", "instance_id", "request_id", "labels", "terraform_labels"},
},
{
Config: testAccWorkbenchInstance_shielded_config_false(context),
},
{
ResourceName: "google_workbench_instance.instance",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"name", "instance_owners", "location", "instance_id", "request_id", "labels", "terraform_labels"},
},
{
Config: testAccWorkbenchInstance_shielded_config_true(context),
},
{
ResourceName: "google_workbench_instance.instance",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"name", "instance_owners", "location", "instance_id", "request_id", "labels", "terraform_labels"},
},
{
Config: testAccWorkbenchInstance_shielded_config_true(context),
},
{
ResourceName: "google_workbench_instance.instance",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"name", "instance_owners", "location", "instance_id", "request_id", "labels", "terraform_labels"},
},
},
})
}

func testAccWorkbenchInstance_shielded_config_true(context map[string]interface{}) string {
return acctest.Nprintf(`
resource "google_workbench_instance" "instance" {
name = "tf-test-workbench-instance%{random_suffix}"
location = "us-central1-a"
gce_setup {
shielded_instance_config {
enable_secure_boot = true
enable_vtpm = true
enable_integrity_monitoring = true
}
}
}
`, context)
}

func testAccWorkbenchInstance_shielded_config_false(context map[string]interface{}) string {
return acctest.Nprintf(`
resource "google_workbench_instance" "instance" {
name = "tf-test-workbench-instance%{random_suffix}"
location = "us-central1-a"
gce_setup {
shielded_instance_config {
enable_secure_boot = false
enable_vtpm = false
enable_integrity_monitoring = false
}
}
}
`, context)
}

func testAccWorkbenchInstance_shielded_config_none(context map[string]interface{}) string {
return acctest.Nprintf(`
resource "google_workbench_instance" "instance" {
name = "tf-test-workbench-instance%{random_suffix}"
location = "us-central1-a"
}
`, context)
}
Loading

0 comments on commit 8e13e8d

Please sign in to comment.