Skip to content

Commit

Permalink
Add certificate_map to compute_target_ssl_proxy (#6443) (#4654)
Browse files Browse the repository at this point in the history
Co-authored-by: Pawel Krawczyk <pawkra@google.com>
Signed-off-by: Modular Magician <magic-modules@google.com>

Signed-off-by: Modular Magician <magic-modules@google.com>
Co-authored-by: Pawel Krawczyk <pawkra@google.com>
  • Loading branch information
modular-magician and Pawel Krawczyk authored Sep 2, 2022
1 parent 724c9f3 commit 2c08dd3
Show file tree
Hide file tree
Showing 4 changed files with 262 additions and 26 deletions.
3 changes: 3 additions & 0 deletions .changelog/6443.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:enhancement
compute: added `certificate_map` to `compute_target_ssl_proxy` resource
```
80 changes: 70 additions & 10 deletions google-beta/resource_compute_target_ssl_proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,16 +59,13 @@ first character must be a lowercase letter, and all following
characters must be a dash, lowercase letter, or digit, except the last
character, which cannot be a dash.`,
},
"ssl_certificates": {
Type: schema.TypeList,
Required: true,
Description: `A list of SslCertificate resources that are used to authenticate
connections between users and the load balancer. At least one
SSL certificate must be specified.`,
Elem: &schema.Schema{
Type: schema.TypeString,
DiffSuppressFunc: compareSelfLinkOrResourceName,
},
"certificate_map": {
Type: schema.TypeString,
Optional: true,
Description: `A reference to the CertificateMap resource uri that identifies a certificate map
associated with the given target proxy. This field can only be set for global target proxies.
Accepted format is '//certificatemanager.googleapis.com/projects/{project}/locations/{location}/certificateMaps/{resourceName}'.`,
ExactlyOneOf: []string{"ssl_certificates", "certificate_map"},
},
"description": {
Type: schema.TypeString,
Expand All @@ -84,6 +81,18 @@ SSL certificate must be specified.`,
the backend. Default value: "NONE" Possible values: ["NONE", "PROXY_V1"]`,
Default: "NONE",
},
"ssl_certificates": {
Type: schema.TypeList,
Optional: true,
Description: `A list of SslCertificate resources that are used to authenticate
connections between users and the load balancer. At least one
SSL certificate must be specified.`,
Elem: &schema.Schema{
Type: schema.TypeString,
DiffSuppressFunc: compareSelfLinkOrResourceName,
},
ExactlyOneOf: []string{"ssl_certificates", "certificate_map"},
},
"ssl_policy": {
Type: schema.TypeString,
Optional: true,
Expand Down Expand Up @@ -155,6 +164,12 @@ func resourceComputeTargetSslProxyCreate(d *schema.ResourceData, meta interface{
} else if v, ok := d.GetOkExists("ssl_certificates"); !isEmptyValue(reflect.ValueOf(sslCertificatesProp)) && (ok || !reflect.DeepEqual(v, sslCertificatesProp)) {
obj["sslCertificates"] = sslCertificatesProp
}
certificateMapProp, err := expandComputeTargetSslProxyCertificateMap(d.Get("certificate_map"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("certificate_map"); !isEmptyValue(reflect.ValueOf(certificateMapProp)) && (ok || !reflect.DeepEqual(v, certificateMapProp)) {
obj["certificateMap"] = certificateMapProp
}
sslPolicyProp, err := expandComputeTargetSslProxySslPolicy(d.Get("ssl_policy"), d, config)
if err != nil {
return err
Expand Down Expand Up @@ -263,6 +278,9 @@ func resourceComputeTargetSslProxyRead(d *schema.ResourceData, meta interface{})
if err := d.Set("ssl_certificates", flattenComputeTargetSslProxySslCertificates(res["sslCertificates"], d, config)); err != nil {
return fmt.Errorf("Error reading TargetSslProxy: %s", err)
}
if err := d.Set("certificate_map", flattenComputeTargetSslProxyCertificateMap(res["certificateMap"], d, config)); err != nil {
return fmt.Errorf("Error reading TargetSslProxy: %s", err)
}
if err := d.Set("ssl_policy", flattenComputeTargetSslProxySslPolicy(res["sslPolicy"], d, config)); err != nil {
return fmt.Errorf("Error reading TargetSslProxy: %s", err)
}
Expand Down Expand Up @@ -392,6 +410,40 @@ func resourceComputeTargetSslProxyUpdate(d *schema.ResourceData, meta interface{
return err
}
}
if d.HasChange("certificate_map") {
obj := make(map[string]interface{})

certificateMapProp, err := expandComputeTargetSslProxyCertificateMap(d.Get("certificate_map"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("certificate_map"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, certificateMapProp)) {
obj["certificateMap"] = certificateMapProp
}

url, err := replaceVars(d, config, "{{ComputeBasePath}}projects/{{project}}/global/targetSslProxies/{{name}}/setCertificateMap")
if err != nil {
return err
}

// err == nil indicates that the billing_project value was found
if bp, err := getBillingProject(d, config); err == nil {
billingProject = bp
}

res, err := sendRequestWithTimeout(config, "POST", billingProject, url, userAgent, obj, d.Timeout(schema.TimeoutUpdate))
if err != nil {
return fmt.Errorf("Error updating TargetSslProxy %q: %s", d.Id(), err)
} else {
log.Printf("[DEBUG] Finished updating TargetSslProxy %q: %#v", d.Id(), res)
}

err = computeOperationWaitTime(
config, res, project, "Updating TargetSslProxy", userAgent,
d.Timeout(schema.TimeoutUpdate))
if err != nil {
return err
}
}
if d.HasChange("ssl_policy") {
obj := make(map[string]interface{})

Expand Down Expand Up @@ -544,6 +596,10 @@ func flattenComputeTargetSslProxySslCertificates(v interface{}, d *schema.Resour
return convertAndMapStringArr(v.([]interface{}), ConvertSelfLinkToV1)
}

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

func flattenComputeTargetSslProxySslPolicy(v interface{}, d *schema.ResourceData, config *Config) interface{} {
if v == nil {
return v
Expand Down Expand Up @@ -587,6 +643,10 @@ func expandComputeTargetSslProxySslCertificates(v interface{}, d TerraformResour
return req, nil
}

func expandComputeTargetSslProxyCertificateMap(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
return v, nil
}

func expandComputeTargetSslProxySslPolicy(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
f, err := parseGlobalFieldValue("sslPolicies", v.(string), "project", d, config, true)
if err != nil {
Expand Down
187 changes: 177 additions & 10 deletions google-beta/resource_compute_target_ssl_proxy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import (

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

compute "google.golang.org/api/compute/v0.beta"
)

func TestAccComputeTargetSslProxy_update(t *testing.T) {
Expand All @@ -17,6 +19,9 @@ func TestAccComputeTargetSslProxy_update(t *testing.T) {
backend2 := fmt.Sprintf("tssl-test-%s", randString(t, 10))
hc := fmt.Sprintf("tssl-test-%s", randString(t, 10))

resourceSuffix := randString(t, 10)
var proxy compute.TargetSslProxy

vcrTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Expand All @@ -25,22 +30,42 @@ func TestAccComputeTargetSslProxy_update(t *testing.T) {
{
Config: testAccComputeTargetSslProxy_basic1(target, sslPolicy, cert1, backend1, hc),
Check: resource.ComposeTestCheckFunc(
testAccCheckComputeTargetSslProxy(
t, "google_compute_target_ssl_proxy.foobar", "NONE", cert1),
testAccCheckComputeTargetSslProxyExists(
t, "google_compute_target_ssl_proxy.foobar", &proxy),
testAccCheckComputeTargetSslProxyHeader(t, "NONE", &proxy),
testAccCheckComputeTargetSslProxyHasSslCertificate(t, cert1, &proxy),
),
},
{
Config: testAccComputeTargetSslProxy_basic2(target, sslPolicy, cert1, cert2, backend1, backend2, hc),
Check: resource.ComposeTestCheckFunc(
testAccCheckComputeTargetSslProxy(
t, "google_compute_target_ssl_proxy.foobar", "PROXY_V1", cert2),
testAccCheckComputeTargetSslProxyExists(
t, "google_compute_target_ssl_proxy.foobar", &proxy),
testAccCheckComputeTargetSslProxyHeader(t, "PROXY_V1", &proxy),
testAccCheckComputeTargetSslProxyHasSslCertificate(t, cert2, &proxy),
),
},
{
Config: testAccComputeTargetSslProxy_certificateMap1(resourceSuffix),
Check: resource.ComposeTestCheckFunc(
testAccCheckComputeTargetSslProxyExists(
t, "google_compute_target_ssl_proxy.with_certificate_map", &proxy),
testAccCheckComputeTargetSslProxyHasCertificateMap(t, "certificatemap-test-1-"+resourceSuffix, &proxy),
),
},
{
Config: testAccComputeTargetSslProxy_certificateMap2(resourceSuffix),
Check: resource.ComposeTestCheckFunc(
testAccCheckComputeTargetSslProxyExists(
t, "google_compute_target_ssl_proxy.with_certificate_map", &proxy),
testAccCheckComputeTargetSslProxyHasCertificateMap(t, "certificatemap-test-2-"+resourceSuffix, &proxy),
),
},
},
})
}

func testAccCheckComputeTargetSslProxy(t *testing.T, n, proxyHeader, sslCert string) resource.TestCheckFunc {
func testAccCheckComputeTargetSslProxyExists(t *testing.T, n string, proxy *compute.TargetSslProxy) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[n]
if !ok {
Expand All @@ -64,15 +89,44 @@ func testAccCheckComputeTargetSslProxy(t *testing.T, n, proxyHeader, sslCert str
return fmt.Errorf("TargetSslProxy not found")
}

if found.ProxyHeader != proxyHeader {
return fmt.Errorf("Wrong proxy header. Expected '%s', got '%s'", proxyHeader, found.ProxyHeader)
*proxy = *found

return nil
}
}

func testAccCheckComputeTargetSslProxyHeader(t *testing.T, proxyHeader string, proxy *compute.TargetSslProxy) resource.TestCheckFunc {
return func(s *terraform.State) error {
if proxy.ProxyHeader != proxyHeader {
return fmt.Errorf("Wrong proxy header. Expected '%s', got '%s'", proxyHeader, proxy.ProxyHeader)
}
return nil
}
}

func testAccCheckComputeTargetSslProxyHasSslCertificate(t *testing.T, cert string, proxy *compute.TargetSslProxy) resource.TestCheckFunc {
return func(s *terraform.State) error {
config := googleProviderConfig(t)
certURL := fmt.Sprintf(canonicalSslCertificateTemplate, config.Project, cert)

foundCertName := GetResourceNameFromSelfLink(found.SslCertificates[0])
if foundCertName != sslCert {
return fmt.Errorf("Wrong ssl certificates. Expected '%s', got '%s'", sslCert, foundCertName)
for _, sslCertificate := range proxy.SslCertificates {
if ConvertSelfLinkToV1(sslCertificate) == certURL {
return nil
}
}

return fmt.Errorf("Ssl certificate not found: expected'%s'", certURL)
}
}

func testAccCheckComputeTargetSslProxyHasCertificateMap(t *testing.T, certificateMap string, proxy *compute.TargetSslProxy) resource.TestCheckFunc {
return func(s *terraform.State) error {
config := googleProviderConfig(t)
wantCertMapURL := fmt.Sprintf(canonicalCertificateMapTemplate, config.Project, certificateMap)
gotCertMapURL := ConvertSelfLinkToV1(proxy.CertificateMap)
if wantCertMapURL != gotCertMapURL {
return fmt.Errorf("certificate map not found: got %q, want %q", gotCertMapURL, wantCertMapURL)
}
return nil
}
}
Expand Down Expand Up @@ -169,3 +223,116 @@ resource "google_compute_health_check" "zero" {
}
`, target, sslPolicy, sslCert1, sslCert2, backend1, backend2, hc)
}

func testAccComputeTargetSslProxy_certificateMap1(id string) string {
return fmt.Sprintf(`
resource "google_compute_target_ssl_proxy" "with_certificate_map" {
description = "Resource created for Terraform acceptance testing"
name = "ssl-proxy-%s"
backend_service = google_compute_backend_service.foo.self_link
certificate_map = "//certificatemanager.googleapis.com/${google_certificate_manager_certificate_map.map1.id}"
}
resource "google_compute_backend_service" "foo" {
name = "backend-service-%s"
protocol = "SSL"
health_checks = [google_compute_health_check.zero.self_link]
}
resource "google_compute_health_check" "zero" {
name = "health-check-%s"
check_interval_sec = 1
timeout_sec = 1
tcp_health_check {
port = "443"
}
}
resource "google_certificate_manager_certificate_map" "map1" {
name = "certificatemap-test-1-%s"
}
resource "google_certificate_manager_certificate_map_entry" "map_entry" {
name = "certificatemapentry-test-%s"
map = google_certificate_manager_certificate_map.map1.name
certificates = [google_certificate_manager_certificate.certificate.id]
matcher = "PRIMARY"
}
resource "google_certificate_manager_certificate" "certificate" {
name = "certificate-test-%s"
scope = "DEFAULT"
managed {
domains = [
google_certificate_manager_dns_authorization.instance.domain,
]
dns_authorizations = [
google_certificate_manager_dns_authorization.instance.id,
]
}
}
resource "google_certificate_manager_dns_authorization" "instance" {
name = "dnsauthorization-test-%s"
domain = "mysite.com"
}
`, id, id, id, id, id, id, id)
}

func testAccComputeTargetSslProxy_certificateMap2(id string) string {
return fmt.Sprintf(`
resource "google_compute_target_ssl_proxy" "with_certificate_map" {
description = "Resource created for Terraform acceptance testing"
name = "ssl-proxy-%s"
backend_service = google_compute_backend_service.foo.self_link
certificate_map = "//certificatemanager.googleapis.com/${google_certificate_manager_certificate_map.map2.id}"
}
resource "google_compute_backend_service" "foo" {
name = "backend-service-%s"
protocol = "SSL"
health_checks = [google_compute_health_check.zero.self_link]
}
resource "google_compute_health_check" "zero" {
name = "health-check-%s"
check_interval_sec = 1
timeout_sec = 1
tcp_health_check {
port = "443"
}
}
resource "google_certificate_manager_certificate_map" "map1" {
name = "certificatemap-test-1-%s"
}
resource "google_certificate_manager_certificate_map" "map2" {
name = "certificatemap-test-2-%s"
}
resource "google_certificate_manager_certificate_map_entry" "map_entry" {
name = "certificatemapentry-test-%s"
map = google_certificate_manager_certificate_map.map1.name
certificates = [google_certificate_manager_certificate.certificate.id]
matcher = "PRIMARY"
}
resource "google_certificate_manager_certificate" "certificate" {
name = "certificate-test-%s"
scope = "DEFAULT"
managed {
domains = [
google_certificate_manager_dns_authorization.instance.domain,
]
dns_authorizations = [
google_certificate_manager_dns_authorization.instance.id,
]
}
}
resource "google_certificate_manager_dns_authorization" "instance" {
name = "dnsauthorization-test-%s"
domain = "mysite.com"
}
`, id, id, id, id, id, id, id, id)
}
18 changes: 12 additions & 6 deletions website/docs/r/compute_target_ssl_proxy.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -89,12 +89,6 @@ The following arguments are supported:
(Required)
A reference to the BackendService resource.

* `ssl_certificates` -
(Required)
A list of SslCertificate resources that are used to authenticate
connections between users and the load balancer. At least one
SSL certificate must be specified.


- - -

Expand All @@ -110,6 +104,18 @@ The following arguments are supported:
Default value is `NONE`.
Possible values are `NONE` and `PROXY_V1`.

* `ssl_certificates` -
(Optional)
A list of SslCertificate resources that are used to authenticate
connections between users and the load balancer. At least one
SSL certificate must be specified.

* `certificate_map` -
(Optional)
A reference to the CertificateMap resource uri that identifies a certificate map
associated with the given target proxy. This field can only be set for global target proxies.
Accepted format is `//certificatemanager.googleapis.com/projects/{project}/locations/{location}/certificateMaps/{resourceName}`.

* `ssl_policy` -
(Optional)
A reference to the SslPolicy resource that will be associated with
Expand Down

0 comments on commit 2c08dd3

Please sign in to comment.