Skip to content

Commit

Permalink
Add support for Shielded VMs to compute_instance and compute_instance…
Browse files Browse the repository at this point in the history
…_template (#3209)
  • Loading branch information
mlauter committed May 1, 2019
1 parent 5ea4adf commit 42b662e
Show file tree
Hide file tree
Showing 9 changed files with 444 additions and 4 deletions.
25 changes: 25 additions & 0 deletions google/compute_instance_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -204,3 +204,28 @@ func resourceInstanceTags(d TerraformResourceData) *computeBeta.Tags {

return tags
}

func expandShieldedVmConfigs(d *schema.ResourceData) *computeBeta.ShieldedVmConfig {
if _, ok := d.GetOk("shielded_vm_config"); !ok {
return nil
}

prefix := "shielded_vm_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),
}
}

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,
}}
}
5 changes: 5 additions & 0 deletions google/data_source_google_compute_instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,11 @@ func dataSourceGoogleComputeInstanceRead(d *schema.ResourceData, meta interface{
return err
}

err = d.Set("shielded_vm_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)
Expand Down
49 changes: 49 additions & 0 deletions google/resource_compute_instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -488,6 +488,33 @@ func resourceComputeInstance() *schema.Resource {
},
},

"shielded_vm_config": {
Type: schema.TypeList,
MaxItems: 1,
Optional: true,
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: false,
},

"enable_integrity_monitoring": {
Type: schema.TypeBool,
Optional: true,
Default: false,
},
},
},
},

"tags": {
Type: schema.TypeSet,
Optional: true,
Expand Down Expand Up @@ -676,6 +703,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
}

Expand Down Expand Up @@ -880,6 +908,11 @@ func resourceComputeInstanceRead(d *schema.ResourceData, meta interface{}) error
}
}

err = d.Set("shielded_vm_config", flattenShieldedVmConfig(instance.ShieldedVmConfig))
if err != nil {
return err
}

d.Set("service_account", flattenServiceAccounts(instance.ServiceAccounts))
d.Set("attached_disk", ads)
d.Set("scratch_disk", scratchDisks)
Expand Down Expand Up @@ -1349,6 +1382,22 @@ func resourceComputeInstanceUpdate(d *schema.ResourceData, meta interface{}) err
}
}

if d.HasChange("shielded_vm_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_vm_config")
}

// We made it, disable partial mode
d.Partial(false)

Expand Down
38 changes: 38 additions & 0 deletions google/resource_compute_instance_template.go
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,37 @@ func resourceComputeInstanceTemplate() *schema.Resource {
},
},

"shielded_vm_config": {
Type: schema.TypeList,
MaxItems: 1,
Optional: true,
ForceNew: true,
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: false,
ForceNew: true,
},

"enable_integrity_monitoring": {
Type: schema.TypeBool,
Optional: true,
Default: false,
ForceNew: true,
},
},
},
},

"guest_accelerator": {
Type: schema.TypeList,
Optional: true,
Expand Down Expand Up @@ -667,6 +698,8 @@ func resourceComputeInstanceTemplateCreate(d *schema.ResourceData, meta interfac

instanceProperties.GuestAccelerators = expandInstanceTemplateGuestAccelerators(d, config)

instanceProperties.ShieldedVmConfig = expandShieldedVmConfigs(d)

instanceProperties.Tags = resourceInstanceTags(d)
if _, ok := d.GetOk("labels"); ok {
instanceProperties.Labels = expandLabels(d)
Expand Down Expand Up @@ -863,6 +896,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_vm_config", flattenShieldedVmConfig(instanceTemplate.Properties.ShieldedVmConfig)); err != nil {
return fmt.Errorf("Error setting shielded_vm_config: %s", err)
}
}
return nil
}

Expand Down
150 changes: 148 additions & 2 deletions google/resource_compute_instance_template_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)

Expand Down Expand Up @@ -498,6 +499,53 @@ func TestAccComputeInstanceTemplate_EncryptKMS(t *testing.T) {
})
}

func TestAccComputeInstanceTemplate_shieldedVmConfig(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(),
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_shieldedVmConfigSkip(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_basic(),
Check: resource.ComposeTestCheckFunc(
testAccCheckComputeInstanceTemplateExists("google_compute_instance_template.foobar", &instanceTemplate),
testAccCheckComputeInstanceTemplateLacksShieldedVmConfig(&instanceTemplate),
),
},
},
})
}

func testAccCheckComputeInstanceTemplateDestroy(s *terraform.State) error {
config := testAccProvider.Meta().(*Config)

Expand All @@ -516,8 +564,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 {
Expand Down Expand Up @@ -549,6 +608,35 @@ 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,
k string, v string) resource.TestCheckFunc {
Expand Down Expand Up @@ -761,6 +849,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" {
Expand Down Expand Up @@ -1449,3 +1565,33 @@ resource "google_compute_instance_template" "foobar" {
}
}`, acctest.RandString(10), kmsLink)
}

func testAccComputeInstanceTemplate_shieldedVmConfig() 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_vm_config {
enable_secure_boot = true
enable_vtpm = true
enable_integrity_monitoring = true
}
}`, acctest.RandString(10))
}
Loading

0 comments on commit 42b662e

Please sign in to comment.