mirror of
https://github.com/letic/terraform-provider-google.git
synced 2024-07-03 08:42:39 +00:00
Add IAP support for backend services (#471)
* initial work on adding IAP support for backend services * readback of IAP * flatten IAP + static set id * expandIap function * removed enabled flag/state rework Removed the enabled flag for IAP IAP is now enabled when the client id and secret are set IAP now correctly disables when IAP stanza is removed Client secret is now correctly hashed against the secret hash stored on the server * Tests for IAP * added comments, fixed tabs. * testing for IAP disabled
This commit is contained in:
parent
c882a77db6
commit
d37f352f41
|
@ -2,6 +2,7 @@ package google
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/sha256"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
|
@ -39,8 +40,35 @@ func resourceComputeBackendService() *schema.Resource {
|
|||
MaxItems: 1,
|
||||
},
|
||||
|
||||
"iap": &schema.Schema{
|
||||
Type: schema.TypeList,
|
||||
Optional: true,
|
||||
MaxItems: 1,
|
||||
Elem: &schema.Resource{
|
||||
Schema: map[string]*schema.Schema{
|
||||
"oauth2_client_id": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
},
|
||||
"oauth2_client_secret": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
Sensitive: true,
|
||||
DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool {
|
||||
if old == fmt.Sprintf("%x", sha256.Sum256([]byte(new))) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
"backend": &schema.Schema{
|
||||
Type: schema.TypeSet,
|
||||
Type: schema.TypeSet,
|
||||
Optional: true,
|
||||
Set: resourceGoogleComputeBackendServiceBackendHash,
|
||||
Elem: &schema.Resource{
|
||||
Schema: map[string]*schema.Schema{
|
||||
"group": &schema.Schema{
|
||||
|
@ -77,8 +105,6 @@ func resourceComputeBackendService() *schema.Resource {
|
|||
},
|
||||
},
|
||||
},
|
||||
Optional: true,
|
||||
Set: resourceGoogleComputeBackendServiceBackendHash,
|
||||
},
|
||||
|
||||
"description": &schema.Schema{
|
||||
|
@ -209,6 +235,7 @@ func resourceComputeBackendServiceRead(d *schema.ResourceData, meta interface{})
|
|||
d.Set("self_link", service.SelfLink)
|
||||
d.Set("backend", flattenBackends(service.Backends))
|
||||
d.Set("connection_draining_timeout_sec", service.ConnectionDraining.DrainingTimeoutSec)
|
||||
d.Set("iap", flattenIap(service.Iap))
|
||||
|
||||
d.Set("health_checks", service.HealthChecks)
|
||||
|
||||
|
@ -270,6 +297,31 @@ func resourceComputeBackendServiceDelete(d *schema.ResourceData, meta interface{
|
|||
return nil
|
||||
}
|
||||
|
||||
func expandIap(configured []interface{}) *compute.BackendServiceIAP {
|
||||
data := configured[0].(map[string]interface{})
|
||||
iap := &compute.BackendServiceIAP{
|
||||
Enabled: true,
|
||||
Oauth2ClientId: data["oauth2_client_id"].(string),
|
||||
Oauth2ClientSecret: data["oauth2_client_secret"].(string),
|
||||
ForceSendFields: []string{"Enabled", "Oauth2ClientId", "Oauth2ClientSecret"},
|
||||
}
|
||||
|
||||
return iap
|
||||
}
|
||||
|
||||
func flattenIap(iap *compute.BackendServiceIAP) []map[string]interface{} {
|
||||
if iap == nil {
|
||||
return make([]map[string]interface{}, 1, 1)
|
||||
}
|
||||
|
||||
iapMap := map[string]interface{}{
|
||||
"enabled": iap.Enabled,
|
||||
"oauth2_client_id": iap.Oauth2ClientId,
|
||||
"oauth2_client_secret": iap.Oauth2ClientSecretSha256,
|
||||
}
|
||||
return []map[string]interface{}{iapMap}
|
||||
}
|
||||
|
||||
func expandBackends(configured []interface{}) ([]*compute.Backend, error) {
|
||||
backends := make([]*compute.Backend, 0, len(configured))
|
||||
|
||||
|
@ -323,7 +375,6 @@ func flattenBackends(backends []*compute.Backend) []map[string]interface{} {
|
|||
data["max_rate"] = b.MaxRate
|
||||
data["max_rate_per_instance"] = b.MaxRatePerInstance
|
||||
data["max_utilization"] = b.MaxUtilization
|
||||
|
||||
result = append(result, data)
|
||||
}
|
||||
|
||||
|
@ -337,9 +388,23 @@ func expandBackendService(d *schema.ResourceData) (*compute.BackendService, erro
|
|||
healthChecks = append(healthChecks, v.(string))
|
||||
}
|
||||
|
||||
// The IAP service is enabled and disabled by adding or removing
|
||||
// the IAP configuration block (and providing the client id
|
||||
// and secret). We are force sending the three required API fields
|
||||
// to enable/disable IAP at all times here, and relying on Golang's
|
||||
// type defaults to enable or disable IAP in the existance or absense
|
||||
// of the block, instead of checking if the block exists, zeroing out
|
||||
// fields, etc.
|
||||
service := &compute.BackendService{
|
||||
Name: d.Get("name").(string),
|
||||
HealthChecks: healthChecks,
|
||||
Iap: &compute.BackendServiceIAP{
|
||||
ForceSendFields: []string{"Enabled", "Oauth2ClientId", "Oauth2ClientSecret"},
|
||||
},
|
||||
}
|
||||
|
||||
if v, ok := d.GetOk("iap"); ok {
|
||||
service.Iap = expandIap(v.([]interface{}))
|
||||
}
|
||||
|
||||
var err error
|
||||
|
|
|
@ -120,6 +120,48 @@ func TestAccComputeBackendService_withBackendAndUpdate(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestAccComputeBackendService_withBackendAndIAP(t *testing.T) {
|
||||
serviceName := fmt.Sprintf("tf-test-%s", acctest.RandString(10))
|
||||
igName := fmt.Sprintf("tf-test-%s", acctest.RandString(10))
|
||||
itName := fmt.Sprintf("tf-test-%s", acctest.RandString(10))
|
||||
checkName := fmt.Sprintf("tf-test-%s", acctest.RandString(10))
|
||||
var svc compute.BackendService
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
Providers: testAccProviders,
|
||||
CheckDestroy: testAccCheckComputeBackendServiceDestroy,
|
||||
Steps: []resource.TestStep{
|
||||
resource.TestStep{
|
||||
Config: testAccComputeBackendService_withBackendAndIAP(
|
||||
serviceName, igName, itName, checkName, 10),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckComputeBackendServiceExistsWithIAP(
|
||||
"google_compute_backend_service.lipsum", &svc),
|
||||
),
|
||||
},
|
||||
resource.TestStep{
|
||||
Config: testAccComputeBackendService_withBackend(
|
||||
serviceName, igName, itName, checkName, 10),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckComputeBackendServiceExistsWithoutIAP(
|
||||
"google_compute_backend_service.lipsum", &svc),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
if svc.TimeoutSec != 10 {
|
||||
t.Errorf("Expected TimeoutSec == 10, got %d", svc.TimeoutSec)
|
||||
}
|
||||
if svc.Protocol != "HTTP" {
|
||||
t.Errorf("Expected Protocol to be HTTP, got %q", svc.Protocol)
|
||||
}
|
||||
if len(svc.Backends) != 1 {
|
||||
t.Errorf("Expected 1 backend, got %d", len(svc.Backends))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestAccComputeBackendService_updatePreservesOptionalParameters(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
@ -287,6 +329,71 @@ func testAccCheckComputeBackendServiceExists(n string, svc *compute.BackendServi
|
|||
}
|
||||
}
|
||||
|
||||
func testAccCheckComputeBackendServiceExistsWithIAP(n string, svc *compute.BackendService) 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.clientCompute.BackendServices.Get(
|
||||
config.Project, rs.Primary.ID).Do()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if found.Name != rs.Primary.ID {
|
||||
return fmt.Errorf("Backend service %s not found", rs.Primary.ID)
|
||||
}
|
||||
|
||||
if found.Iap == nil || found.Iap.Enabled == false {
|
||||
return fmt.Errorf("IAP not found or not enabled.")
|
||||
}
|
||||
|
||||
*svc = *found
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func testAccCheckComputeBackendServiceExistsWithoutIAP(n string, svc *compute.BackendService) 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.clientCompute.BackendServices.Get(
|
||||
config.Project, rs.Primary.ID).Do()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if found.Name != rs.Primary.ID {
|
||||
return fmt.Errorf("Backend service %s not found", rs.Primary.ID)
|
||||
}
|
||||
|
||||
if found.Iap != nil && found.Iap.Enabled == true {
|
||||
return fmt.Errorf("IAP enabled when it should be disabled")
|
||||
}
|
||||
|
||||
*svc = *found
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
func TestAccComputeBackendService_withCDNEnabled(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
@ -460,6 +567,60 @@ resource "google_compute_http_health_check" "default" {
|
|||
`, serviceName, timeout, igName, itName, checkName)
|
||||
}
|
||||
|
||||
func testAccComputeBackendService_withBackendAndIAP(
|
||||
serviceName, igName, itName, checkName string, timeout int64) string {
|
||||
return fmt.Sprintf(`
|
||||
resource "google_compute_backend_service" "lipsum" {
|
||||
name = "%s"
|
||||
description = "Hello World 1234"
|
||||
port_name = "http"
|
||||
protocol = "HTTP"
|
||||
timeout_sec = %v
|
||||
|
||||
backend {
|
||||
group = "${google_compute_instance_group_manager.foobar.instance_group}"
|
||||
}
|
||||
|
||||
iap {
|
||||
oauth2_client_id = "test"
|
||||
oauth2_client_secret = "test"
|
||||
}
|
||||
|
||||
health_checks = ["${google_compute_http_health_check.default.self_link}"]
|
||||
}
|
||||
|
||||
resource "google_compute_instance_group_manager" "foobar" {
|
||||
name = "%s"
|
||||
instance_template = "${google_compute_instance_template.foobar.self_link}"
|
||||
base_instance_name = "foobar"
|
||||
zone = "us-central1-f"
|
||||
target_size = 1
|
||||
}
|
||||
|
||||
resource "google_compute_instance_template" "foobar" {
|
||||
name = "%s"
|
||||
machine_type = "n1-standard-1"
|
||||
|
||||
network_interface {
|
||||
network = "default"
|
||||
}
|
||||
|
||||
disk {
|
||||
source_image = "debian-8-jessie-v20160803"
|
||||
auto_delete = true
|
||||
boot = true
|
||||
}
|
||||
}
|
||||
|
||||
resource "google_compute_http_health_check" "default" {
|
||||
name = "%s"
|
||||
request_path = "/"
|
||||
check_interval_sec = 1
|
||||
timeout_sec = 1
|
||||
}
|
||||
`, serviceName, timeout, igName, itName, checkName)
|
||||
}
|
||||
|
||||
func testAccComputeBackendService_withSessionAffinity(serviceName, checkName, description, affinityName string) string {
|
||||
return fmt.Sprintf(`
|
||||
resource "google_compute_backend_service" "foobar" {
|
||||
|
|
Loading…
Reference in New Issue
Block a user