From bc927db71a5265757d7833f7d825e827db711484 Mon Sep 17 00:00:00 2001 From: Miriam Lauter Date: Thu, 16 May 2019 13:18:53 -0400 Subject: [PATCH] Add support for Shielded VMs to compute_instance and compute_instance_template (#3209) (#3531) --- google/compute_instance_helpers.go | 26 +++ google/data_source_google_compute_instance.go | 5 + google/resource_compute_instance.go | 49 ++++++ google/resource_compute_instance_template.go | 41 +++++ ...resource_compute_instance_template_test.go | 164 +++++++++++++++++- google/resource_compute_instance_test.go | 155 ++++++++++++++++- .../datasource_compute_instance.html.markdown | 10 ++ website/docs/r/compute_instance.html.markdown | 11 ++ .../r/compute_instance_template.html.markdown | 15 +- 9 files changed, 465 insertions(+), 11 deletions(-) diff --git a/google/compute_instance_helpers.go b/google/compute_instance_helpers.go index b42b0035cd3..41cc40a1b02 100644 --- a/google/compute_instance_helpers.go +++ b/google/compute_instance_helpers.go @@ -303,3 +303,29 @@ func resourceInstanceTags(d TerraformResourceData) *computeBeta.Tags { return tags } + +func expandShieldedVmConfigs(d *schema.ResourceData) *computeBeta.ShieldedVmConfig { + if _, ok := d.GetOk("shielded_instance_config"); !ok { + return nil + } + + prefix := "shielded_instance_config.0" + return &computeBeta.ShieldedVmConfig{ + EnableSecureBoot: d.Get(prefix + ".enable_secure_boot").(bool), + EnableVtpm: d.Get(prefix + ".enable_vtpm").(bool), + EnableIntegrityMonitoring: d.Get(prefix + ".enable_integrity_monitoring").(bool), + ForceSendFields: []string{"EnableSecureBoot", "EnableVtpm", "EnableIntegrityMonitoring"}, + } +} + +func flattenShieldedVmConfig(shieldedVmConfig *computeBeta.ShieldedVmConfig) []map[string]bool { + if shieldedVmConfig == nil { + return nil + } + + return []map[string]bool{{ + "enable_secure_boot": shieldedVmConfig.EnableSecureBoot, + "enable_vtpm": shieldedVmConfig.EnableVtpm, + "enable_integrity_monitoring": shieldedVmConfig.EnableIntegrityMonitoring, + }} +} diff --git a/google/data_source_google_compute_instance.go b/google/data_source_google_compute_instance.go index f2f72811575..0e418068fad 100644 --- a/google/data_source_google_compute_instance.go +++ b/google/data_source_google_compute_instance.go @@ -135,6 +135,11 @@ func dataSourceGoogleComputeInstanceRead(d *schema.ResourceData, meta interface{ return err } + err = d.Set("shielded_instance_config", flattenShieldedVmConfig(instance.ShieldedVmConfig)) + if err != nil { + return err + } + d.Set("attached_disk", ads) d.Set("cpu_platform", instance.CpuPlatform) d.Set("min_cpu_platform", instance.MinCpuPlatform) diff --git a/google/resource_compute_instance.go b/google/resource_compute_instance.go index ee909fae94b..9c5707b3685 100644 --- a/google/resource_compute_instance.go +++ b/google/resource_compute_instance.go @@ -510,6 +510,37 @@ func resourceComputeInstance() *schema.Resource { }, }, + "shielded_instance_config": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + // Since this block is used by the API based on which + // image being used, the field needs to be marked as Computed. + Computed: true, + DiffSuppressFunc: emptyOrDefaultStringSuppress(""), + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enable_secure_boot": { + Type: schema.TypeBool, + Optional: true, + Default: false, + }, + + "enable_vtpm": { + Type: schema.TypeBool, + Optional: true, + Default: true, + }, + + "enable_integrity_monitoring": { + Type: schema.TypeBool, + Optional: true, + Default: true, + }, + }, + }, + }, + "tags": { Type: schema.TypeSet, Optional: true, @@ -685,6 +716,7 @@ func expandComputeInstance(project string, zone *compute.Zone, d *schema.Resourc DeletionProtection: d.Get("deletion_protection").(bool), Hostname: d.Get("hostname").(string), ForceSendFields: []string{"CanIpForward", "DeletionProtection"}, + ShieldedVmConfig: expandShieldedVmConfigs(d), }, nil } @@ -904,6 +936,7 @@ func resourceComputeInstanceRead(d *schema.ResourceData, meta interface{}) error d.Set("scratch_disk", scratchDisks) d.Set("scheduling", flattenScheduling(instance.Scheduling)) d.Set("guest_accelerator", flattenGuestAccelerators(instance.GuestAccelerators)) + d.Set("shielded_instance_config", flattenShieldedVmConfig(instance.ShieldedVmConfig)) d.Set("cpu_platform", instance.CpuPlatform) d.Set("min_cpu_platform", instance.MinCpuPlatform) d.Set("deletion_protection", instance.DeletionProtection) @@ -1366,6 +1399,22 @@ func resourceComputeInstanceUpdate(d *schema.ResourceData, meta interface{}) err } } + if d.HasChange("shielded_instance_config") { + shieldedVmConfig := expandShieldedVmConfigs(d) + + op, err := config.clientComputeBeta.Instances.UpdateShieldedVmConfig(project, zone, d.Id(), shieldedVmConfig).Do() + if err != nil { + return fmt.Errorf("Error updating shielded vm config: %s", err) + } + + opErr := computeSharedOperationWaitTime(config.clientCompute, op, project, int(d.Timeout(schema.TimeoutUpdate).Minutes()), "shielded vm config update") + if opErr != nil { + return opErr + } + + d.SetPartial("shielded_instance_config") + } + // We made it, disable partial mode d.Partial(false) diff --git a/google/resource_compute_instance_template.go b/google/resource_compute_instance_template.go index 1bc81f0006e..873e15968b1 100644 --- a/google/resource_compute_instance_template.go +++ b/google/resource_compute_instance_template.go @@ -389,6 +389,41 @@ func resourceComputeInstanceTemplate() *schema.Resource { }, }, + "shielded_instance_config": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + ForceNew: true, + // Since this block is used by the API based on which + // image being used, the field needs to be marked as Computed. + Computed: true, + DiffSuppressFunc: emptyOrDefaultStringSuppress(""), + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enable_secure_boot": { + Type: schema.TypeBool, + Optional: true, + Default: false, + ForceNew: true, + }, + + "enable_vtpm": { + Type: schema.TypeBool, + Optional: true, + Default: true, + ForceNew: true, + }, + + "enable_integrity_monitoring": { + Type: schema.TypeBool, + Optional: true, + Default: true, + ForceNew: true, + }, + }, + }, + }, + "guest_accelerator": { Type: schema.TypeList, Optional: true, @@ -644,6 +679,7 @@ func resourceComputeInstanceTemplateCreate(d *schema.ResourceData, meta interfac Scheduling: scheduling, ServiceAccounts: expandServiceAccounts(d.Get("service_account").([]interface{})), Tags: resourceInstanceTags(d), + ShieldedVmConfig: expandShieldedVmConfigs(d), } if _, ok := d.GetOk("labels"); ok { @@ -841,6 +877,11 @@ func resourceComputeInstanceTemplateRead(d *schema.ResourceData, meta interface{ return fmt.Errorf("Error setting guest_accelerator: %s", err) } } + if instanceTemplate.Properties.ShieldedVmConfig != nil { + if err = d.Set("shielded_instance_config", flattenShieldedVmConfig(instanceTemplate.Properties.ShieldedVmConfig)); err != nil { + return fmt.Errorf("Error setting shielded_instance_config: %s", err) + } + } return nil } diff --git a/google/resource_compute_instance_template_test.go b/google/resource_compute_instance_template_test.go index bd43e757645..e2e519dbab8 100644 --- a/google/resource_compute_instance_template_test.go +++ b/google/resource_compute_instance_template_test.go @@ -9,6 +9,7 @@ import ( "github.com/hashicorp/terraform/helper/acctest" "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/terraform" + computeBeta "google.golang.org/api/compute/v0.beta" "google.golang.org/api/compute/v1" ) @@ -17,7 +18,7 @@ const DEFAULT_MIN_CPU_TEST_VALUE = "Intel Haswell" func TestAccComputeInstanceTemplate_basic(t *testing.T) { t.Parallel() - var instanceTemplate compute.InstanceTemplate + var instanceTemplate computeBeta.InstanceTemplate resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -32,6 +33,7 @@ func TestAccComputeInstanceTemplate_basic(t *testing.T) { testAccCheckComputeInstanceTemplateTag(&instanceTemplate, "foo"), testAccCheckComputeInstanceTemplateMetadata(&instanceTemplate, "foo", "bar"), testAccCheckComputeInstanceTemplateContainsLabel(&instanceTemplate, "my_label", "foobar"), + testAccCheckComputeInstanceTemplateLacksShieldedVmConfig(&instanceTemplate), ), }, { @@ -520,6 +522,58 @@ func TestAccComputeInstanceTemplate_soleTenantNodeAffinities(t *testing.T) { }) } +func TestAccComputeInstanceTemplate_shieldedVmConfig1(t *testing.T) { + t.Parallel() + + var instanceTemplate computeBeta.InstanceTemplate + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckComputeInstanceTemplateDestroy, + Steps: []resource.TestStep{ + { + Config: testAccComputeInstanceTemplate_shieldedVmConfig(true, true, true), + Check: resource.ComposeTestCheckFunc( + testAccCheckComputeInstanceTemplateExists("google_compute_instance_template.foobar", &instanceTemplate), + testAccCheckComputeInstanceTemplateHasShieldedVmConfig(&instanceTemplate, true, true, true), + ), + }, + { + ResourceName: "google_compute_instance_template.foobar", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccComputeInstanceTemplate_shieldedVmConfig2(t *testing.T) { + t.Parallel() + + var instanceTemplate computeBeta.InstanceTemplate + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckComputeInstanceTemplateDestroy, + Steps: []resource.TestStep{ + { + Config: testAccComputeInstanceTemplate_shieldedVmConfig(true, true, false), + Check: resource.ComposeTestCheckFunc( + testAccCheckComputeInstanceTemplateExists("google_compute_instance_template.foobar", &instanceTemplate), + testAccCheckComputeInstanceTemplateHasShieldedVmConfig(&instanceTemplate, true, true, false), + ), + }, + { + ResourceName: "google_compute_instance_template.foobar", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + func testAccCheckComputeInstanceTemplateDestroy(s *terraform.State) error { config := testAccProvider.Meta().(*Config) @@ -538,8 +592,19 @@ func testAccCheckComputeInstanceTemplateDestroy(s *terraform.State) error { return nil } -func testAccCheckComputeInstanceTemplateExists(n string, instanceTemplate *compute.InstanceTemplate) resource.TestCheckFunc { - return testAccCheckComputeInstanceTemplateExistsInProject(n, getTestProjectFromEnv(), instanceTemplate) +func testAccCheckComputeInstanceTemplateExists(n string, instanceTemplate interface{}) resource.TestCheckFunc { + if instanceTemplate == nil { + panic("Attempted to check existence of Instance template that was nil.") + } + + switch instanceTemplate.(type) { + case *compute.InstanceTemplate: + return testAccCheckComputeInstanceTemplateExistsInProject(n, getTestProjectFromEnv(), instanceTemplate.(*compute.InstanceTemplate)) + case *computeBeta.InstanceTemplate: + return testAccCheckComputeBetaInstanceTemplateExistsInProject(n, getTestProjectFromEnv(), instanceTemplate.(*computeBeta.InstanceTemplate)) + default: + panic("Attempted to check existence of an Instance template of unknown type.") + } } func testAccCheckComputeInstanceTemplateExistsInProject(n, p string, instanceTemplate *compute.InstanceTemplate) resource.TestCheckFunc { @@ -571,8 +636,37 @@ func testAccCheckComputeInstanceTemplateExistsInProject(n, p string, instanceTem } } +func testAccCheckComputeBetaInstanceTemplateExistsInProject(n, p string, instanceTemplate *computeBeta.InstanceTemplate) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s", n) + } + + if rs.Primary.ID == "" { + return fmt.Errorf("No ID is set") + } + + config := testAccProvider.Meta().(*Config) + + found, err := config.clientComputeBeta.InstanceTemplates.Get( + p, rs.Primary.ID).Do() + if err != nil { + return err + } + + if found.Name != rs.Primary.ID { + return fmt.Errorf("Instance template not found") + } + + *instanceTemplate = *found + + return nil + } +} + func testAccCheckComputeInstanceTemplateMetadata( - instanceTemplate *compute.InstanceTemplate, + instanceTemplate *computeBeta.InstanceTemplate, k string, v string) resource.TestCheckFunc { return func(s *terraform.State) error { if instanceTemplate.Properties.Metadata == nil { @@ -633,7 +727,7 @@ func testAccCheckComputeInstanceTemplateSubnetwork(instanceTemplate *compute.Ins } } -func testAccCheckComputeInstanceTemplateTag(instanceTemplate *compute.InstanceTemplate, n string) resource.TestCheckFunc { +func testAccCheckComputeInstanceTemplateTag(instanceTemplate *computeBeta.InstanceTemplate, n string) resource.TestCheckFunc { return func(s *terraform.State) error { if instanceTemplate.Properties.Tags == nil { return fmt.Errorf("no tags") @@ -718,7 +812,7 @@ func testAccCheckComputeInstanceTemplateNetworkIPAddress(n, ipAddress string, in } } -func testAccCheckComputeInstanceTemplateContainsLabel(instanceTemplate *compute.InstanceTemplate, key string, value string) resource.TestCheckFunc { +func testAccCheckComputeInstanceTemplateContainsLabel(instanceTemplate *computeBeta.InstanceTemplate, key string, value string) resource.TestCheckFunc { return func(s *terraform.State) error { v, ok := instanceTemplate.Properties.Labels[key] if !ok { @@ -783,6 +877,34 @@ func testAccCheckComputeInstanceTemplateHasMinCpuPlatform(instanceTemplate *comp } } +func testAccCheckComputeInstanceTemplateHasShieldedVmConfig(instanceTemplate *computeBeta.InstanceTemplate, enableSecureBoot bool, enableVtpm bool, enableIntegrityMonitoring bool) resource.TestCheckFunc { + + return func(s *terraform.State) error { + if instanceTemplate.Properties.ShieldedVmConfig.EnableSecureBoot != enableSecureBoot { + return fmt.Errorf("Wrong shieldedVmConfig enableSecureBoot: expected %t, got, %t", enableSecureBoot, instanceTemplate.Properties.ShieldedVmConfig.EnableSecureBoot) + } + + if instanceTemplate.Properties.ShieldedVmConfig.EnableVtpm != enableVtpm { + return fmt.Errorf("Wrong shieldedVmConfig enableVtpm: expected %t, got, %t", enableVtpm, instanceTemplate.Properties.ShieldedVmConfig.EnableVtpm) + } + + if instanceTemplate.Properties.ShieldedVmConfig.EnableIntegrityMonitoring != enableIntegrityMonitoring { + return fmt.Errorf("Wrong shieldedVmConfig enableIntegrityMonitoring: expected %t, got, %t", enableIntegrityMonitoring, instanceTemplate.Properties.ShieldedVmConfig.EnableIntegrityMonitoring) + } + return nil + } +} + +func testAccCheckComputeInstanceTemplateLacksShieldedVmConfig(instanceTemplate *computeBeta.InstanceTemplate) resource.TestCheckFunc { + return func(s *terraform.State) error { + if instanceTemplate.Properties.ShieldedVmConfig != nil { + return fmt.Errorf("Expected no shielded vm config") + } + + return nil + } +} + func testAccComputeInstanceTemplate_basic() string { return fmt.Sprintf(` data "google_compute_image" "my_image" { @@ -1508,3 +1630,33 @@ resource "google_compute_instance_template" "foobar" { } }`, acctest.RandString(10)) } + +func testAccComputeInstanceTemplate_shieldedVmConfig(enableSecureBoot bool, enableVtpm bool, enableIntegrityMonitoring bool) string { + return fmt.Sprintf(` +data "google_compute_image" "my_image" { + family = "centos-7" + project = "gce-uefi-images" +} + +resource "google_compute_instance_template" "foobar" { + name = "instancet-test-%s" + machine_type = "n1-standard-1" + can_ip_forward = false + + disk { + source_image = "${data.google_compute_image.my_image.self_link}" + auto_delete = true + boot = true + } + + network_interface { + network = "default" + } + + shielded_instance_config { + enable_secure_boot = %t + enable_vtpm = %t + enable_integrity_monitoring = %t + } +}`, acctest.RandString(10), enableSecureBoot, enableVtpm, enableIntegrityMonitoring) +} diff --git a/google/resource_compute_instance_test.go b/google/resource_compute_instance_test.go index 87bee26cf33..de7a27f9a4f 100644 --- a/google/resource_compute_instance_test.go +++ b/google/resource_compute_instance_test.go @@ -10,6 +10,7 @@ import ( "github.com/hashicorp/terraform/helper/acctest" "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/terraform" + computeBeta "google.golang.org/api/compute/v0.beta" "google.golang.org/api/compute/v1" ) @@ -1115,7 +1116,9 @@ func TestAccComputeInstance_secondaryAliasIpRange(t *testing.T) { func TestAccComputeInstance_hostname(t *testing.T) { t.Parallel() - var instanceName = fmt.Sprintf("instance-test-%s", acctest.RandString(10)) + var instance computeBeta.Instance + instanceName := fmt.Sprintf("instance-test-%s", acctest.RandString(10)) + resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, @@ -1125,6 +1128,53 @@ func TestAccComputeInstance_hostname(t *testing.T) { Config: testAccComputeInstance_hostname(instanceName), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttrSet("google_compute_instance.foobar", "hostname"), + testAccCheckComputeInstanceLacksShieldedVmConfig(&instance), + ), + }, + computeInstanceImportStep("us-central1-a", instanceName, []string{}), + }, + }) +} + +func TestAccComputeInstance_shieldedVmConfig1(t *testing.T) { + t.Parallel() + + var instance computeBeta.Instance + instanceName := fmt.Sprintf("terraform-test-%s", acctest.RandString(10)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckComputeInstanceDestroy, + Steps: []resource.TestStep{ + { + Config: testAccComputeInstance_shieldedVmConfig(instanceName, true, true, true), + Check: resource.ComposeTestCheckFunc( + testAccCheckComputeInstanceExists("google_compute_instance.foobar", &instance), + testAccCheckComputeInstanceHasShieldedVmConfig(&instance, true, true, true), + ), + }, + computeInstanceImportStep("us-central1-a", instanceName, []string{}), + }, + }) +} + +func TestAccComputeInstance_shieldedVmConfig2(t *testing.T) { + t.Parallel() + + var instance computeBeta.Instance + instanceName := fmt.Sprintf("terraform-test-%s", acctest.RandString(10)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckComputeInstanceDestroy, + Steps: []resource.TestStep{ + { + Config: testAccComputeInstance_shieldedVmConfig(instanceName, true, true, false), + Check: resource.ComposeTestCheckFunc( + testAccCheckComputeInstanceExists("google_compute_instance.foobar", &instance), + testAccCheckComputeInstanceHasShieldedVmConfig(&instance, true, true, false), ), }, computeInstanceImportStep("us-central1-a", instanceName, []string{}), @@ -1189,8 +1239,19 @@ func testAccCheckComputeInstanceDestroy(s *terraform.State) error { return nil } -func testAccCheckComputeInstanceExists(n string, instance *compute.Instance) resource.TestCheckFunc { - return testAccCheckComputeInstanceExistsInProject(n, getTestProjectFromEnv(), instance) +func testAccCheckComputeInstanceExists(n string, instance interface{}) resource.TestCheckFunc { + if instance == nil { + panic("Attempted to check existence of Instance that was nil.") + } + + switch instance.(type) { + case *compute.Instance: + return testAccCheckComputeInstanceExistsInProject(n, getTestProjectFromEnv(), instance.(*compute.Instance)) + case *computeBeta.Instance: + return testAccCheckComputeBetaInstanceExistsInProject(n, getTestProjectFromEnv(), instance.(*computeBeta.Instance)) + default: + panic("Attempted to check existence of an Instance of unknown type.") + } } func testAccCheckComputeInstanceExistsInProject(n, p string, instance *compute.Instance) resource.TestCheckFunc { @@ -1222,6 +1283,35 @@ func testAccCheckComputeInstanceExistsInProject(n, p string, instance *compute.I } } +func testAccCheckComputeBetaInstanceExistsInProject(n, p string, instance *computeBeta.Instance) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s", n) + } + + if rs.Primary.ID == "" { + return fmt.Errorf("No ID is set") + } + + config := testAccProvider.Meta().(*Config) + + found, err := config.clientComputeBeta.Instances.Get( + p, rs.Primary.Attributes["zone"], rs.Primary.ID).Do() + if err != nil { + return err + } + + if found.Name != rs.Primary.ID { + return fmt.Errorf("Instance not found") + } + + *instance = *found + + return nil + } +} + func testAccCheckComputeInstanceMetadata( instance *compute.Instance, k string, v string) resource.TestCheckFunc { @@ -1650,6 +1740,34 @@ func testAccCheckComputeInstanceHasConfiguredDeletionProtection(instance *comput } } +func testAccCheckComputeInstanceHasShieldedVmConfig(instance *computeBeta.Instance, enableSecureBoot bool, enableVtpm bool, enableIntegrityMonitoring bool) resource.TestCheckFunc { + + return func(s *terraform.State) error { + if instance.ShieldedVmConfig.EnableSecureBoot != enableSecureBoot { + return fmt.Errorf("Wrong shieldedVmConfig enableSecureBoot: expected %t, got, %t", enableSecureBoot, instance.ShieldedVmConfig.EnableSecureBoot) + } + + if instance.ShieldedVmConfig.EnableVtpm != enableVtpm { + return fmt.Errorf("Wrong shieldedVmConfig enableVtpm: expected %t, got, %t", enableVtpm, instance.ShieldedVmConfig.EnableVtpm) + } + + if instance.ShieldedVmConfig.EnableIntegrityMonitoring != enableIntegrityMonitoring { + return fmt.Errorf("Wrong shieldedVmConfig enableIntegrityMonitoring: expected %t, got, %t", enableIntegrityMonitoring, instance.ShieldedVmConfig.EnableIntegrityMonitoring) + } + return nil + } +} + +func testAccCheckComputeInstanceLacksShieldedVmConfig(instance *computeBeta.Instance) resource.TestCheckFunc { + return func(s *terraform.State) error { + if instance.ShieldedVmConfig != nil { + return fmt.Errorf("Expected no shielded vm config") + } + + return nil + } +} + func testAccComputeInstance_basic(instance string) string { return fmt.Sprintf(` data "google_compute_image" "my_image" { @@ -3435,3 +3553,34 @@ resource "google_compute_node_group" "nodes" { } `, instance, nodeTemplate, nodeGroup) } + +func testAccComputeInstance_shieldedVmConfig(instance string, enableSecureBoot bool, enableVtpm bool, enableIntegrityMonitoring bool) string { + return fmt.Sprintf(` +data "google_compute_image" "my_image" { + family = "centos-7" + project = "gce-uefi-images" +} + +resource "google_compute_instance" "foobar" { + name = "%s" + machine_type = "n1-standard-1" + zone = "us-central1-a" + + boot_disk { + initialize_params{ + image = "${data.google_compute_image.my_image.self_link}" + } + } + + network_interface { + network = "default" + } + + shielded_instance_config { + enable_secure_boot = %t + enable_vtpm = %t + enable_integrity_monitoring = %t + } +} +`, instance, enableSecureBoot, enableVtpm, enableIntegrityMonitoring) +} diff --git a/website/docs/d/datasource_compute_instance.html.markdown b/website/docs/d/datasource_compute_instance.html.markdown index 0292936b7c0..48385cfcd37 100644 --- a/website/docs/d/datasource_compute_instance.html.markdown +++ b/website/docs/d/datasource_compute_instance.html.markdown @@ -85,6 +85,8 @@ The following arguments are supported: * `cpu_platform` - The CPU platform used by this instance. +* `shielded_instance_config` - The shielded vm config being used by the instance. Structure is documented below. + * `network_interface.0.network_ip` - The internal ip address of the instance, either manually or dynamically assigned. * `network_interface.0.access_config.0.nat_ip` - If the instance has an access config, either the given external ip (in the `nat_ip` field) or the ephemeral (generated) ip (if you didn't provide one). @@ -192,3 +194,11 @@ The `guest_accelerator` block supports: * `count` - The number of the guest accelerator cards exposed to this instance. [network-tier]: https://cloud.google.com/network-tiers/docs/overview + +The `shielded_instance_config` block supports: + +* `enable_secure_boot` -- Whether secure boot is enabled for the instance. + +* `enable_vtpm` -- Whether the instance uses vTPM. + +* `enable_integrity_monitoring` -- Whether integrity monitoring is enabled for the instance. diff --git a/website/docs/r/compute_instance.html.markdown b/website/docs/r/compute_instance.html.markdown index d1f96e1c6e7..7b6453b05cc 100644 --- a/website/docs/r/compute_instance.html.markdown +++ b/website/docs/r/compute_instance.html.markdown @@ -134,6 +134,9 @@ The following arguments are supported: * `tags` - (Optional) A list of tags to attach to the instance. +* `shielded_instance_config` - (Optional) Enable [Shielded VM](https://cloud.google.com/security/shielded-cloud/shielded-vm) on this instance. Shielded VM provides verifiable integrity to prevent against malware and rootkits. Defaults to disabled. Structure is documented below. + **Note**: [`shielded_instance_config`](#shielded_instance_config) can only be used with boot images with shielded vm support. See the complete list [here](https://cloud.google.com/compute/docs/images#shielded-images). + --- The `boot_disk` block supports: @@ -304,6 +307,14 @@ The `node_affinities` block supports: * `value` (Required) - The values for the node affinity label. +The `shielded_instance_config` block supports: + +* `enable_secure_boot` (Optional) -- Verify the digital signature of all boot components, and halt the boot process if signature verification fails. Defaults to false. + +* `enable_vtpm` (Optional) -- Use a virtualized trusted platform module, which is a specialized computer chip you can use to encrypt objects like keys and certificates. Defaults to true. + +* `enable_integrity_monitoring` (Optional) -- Compare the most recent boot measurements to the integrity policy baseline and return a pair of pass/fail results depending on whether they match or not. Defaults to true. + ## Attributes Reference In addition to the arguments listed above, the following computed attributes are diff --git a/website/docs/r/compute_instance_template.html.markdown b/website/docs/r/compute_instance_template.html.markdown index 156cb90f8a2..a2ba1e81979 100644 --- a/website/docs/r/compute_instance_template.html.markdown +++ b/website/docs/r/compute_instance_template.html.markdown @@ -244,6 +244,9 @@ The following arguments are supported: * `min_cpu_platform` - (Optional) Specifies a minimum CPU platform. Applicable values are the friendly names of CPU platforms, such as `Intel Haswell` or `Intel Skylake`. See the complete list [here](https://cloud.google.com/compute/docs/instances/specify-min-cpu-platform). +* `shielded_instance_config` - (Optional) Enable [Shielded VM](https://cloud.google.com/security/shielded-cloud/shielded-vm) on this instance. Shielded VM provides verifiable integrity to prevent against malware and rootkits. Defaults to disabled. Structure is documented below. + **Note**: [`shielded_instance_config`](#shielded_instance_config) can only be used with boot images with shielded vm support. See the complete list [here](https://cloud.google.com/compute/docs/images#shielded-images). + The `disk` block supports: * `auto_delete` - (Optional) Whether or not the disk should be auto-deleted. @@ -273,7 +276,7 @@ The `disk` block supports: read-write mode. * `source` - (Required if source_image not set) The name (**not self_link**) - of the disk (such as those managed by `google_compute_disk`) to attach. + of the disk (such as those managed by `google_compute_disk`) to attach. * `disk_type` - (Optional) The GCE disk type. Can be either `"pd-ssd"`, `"local-ssd"`, or `"pd-standard"`. @@ -372,7 +375,7 @@ The `scheduling` block supports: * `preemptible` - (Optional) Allows instance to be preempted. This defaults to false. Read more on this [here](https://cloud.google.com/compute/docs/instances/preemptible). - + * `node_affinities` - (Optional) Specifies node affinities or anti-affinities to determine which sole-tenant nodes your instances and managed instance groups will use as host systems. Read more on sole-tenant node creation @@ -394,6 +397,14 @@ The `node_affinities` block supports: * `value` (Required) - The values for the node affinity label. +The `shielded_instance_config` block supports: + +* `enable_secure_boot` (Optional) -- Verify the digital signature of all boot components, and halt the boot process if signature verification fails. Defaults to false. + +* `enable_vtpm` (Optional) -- Use a virtualized trusted platform module, which is a specialized computer chip you can use to encrypt objects like keys and certificates. Defaults to true. + +* `enable_integrity_monitoring` (Optional) -- Compare the most recent boot measurements to the integrity policy baseline and return a pair of pass/fail results depending on whether they match or not. Defaults to true. + ## Attributes Reference In addition to the arguments listed above, the following computed attributes are