Skip to content

Commit 071fb95

Browse files
Add tlsSettings field to the compute.BackendService resource (#13439) (#9654)
[upstream:114a03a6a8d329f5182ae6e481c42690aac9bbcf] Signed-off-by: Modular Magician <[email protected]>
1 parent 81dd802 commit 071fb95

5 files changed

+344
-0
lines changed

.changelog/13439.txt

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
```release-note:enhancement
2+
compute: added `tls_settings` field to `google_compute_backend_service` resource (beta)
3+
```

google-beta/services/compute/resource_compute_backend_service.go

+195
Original file line numberDiff line numberDiff line change
@@ -1229,6 +1229,56 @@ For more information see, [Backend service settings](https://cloud.google.com/co
12291229
The default is 30 seconds.
12301230
The full range of timeout values allowed goes from 1 through 2,147,483,647 seconds.`,
12311231
},
1232+
"tls_settings": {
1233+
Type: schema.TypeList,
1234+
Optional: true,
1235+
Description: `Configuration for Backend Authenticated TLS and mTLS. May only be specified when the backend protocol is SSL, HTTPS or HTTP2.`,
1236+
MaxItems: 1,
1237+
Elem: &schema.Resource{
1238+
Schema: map[string]*schema.Schema{
1239+
"authentication_config": {
1240+
Type: schema.TypeString,
1241+
Optional: true,
1242+
Description: `Reference to the BackendAuthenticationConfig resource from the networksecurity.googleapis.com namespace.
1243+
Can be used in authenticating TLS connections to the backend, as specified by the authenticationMode field.
1244+
Can only be specified if authenticationMode is not NONE.`,
1245+
},
1246+
"sni": {
1247+
Type: schema.TypeString,
1248+
Optional: true,
1249+
Description: `Server Name Indication - see RFC3546 section 3.1. If set, the load balancer sends this string as the SNI hostname in the
1250+
TLS connection to the backend, and requires that this string match a Subject Alternative Name (SAN) in the backend's
1251+
server certificate. With a Regional Internet NEG backend, if the SNI is specified here, the load balancer uses it
1252+
regardless of whether the Regional Internet NEG is specified with FQDN or IP address and port.`,
1253+
},
1254+
"subject_alt_names": {
1255+
Type: schema.TypeList,
1256+
Optional: true,
1257+
Description: `A list of Subject Alternative Names (SANs) that the Load Balancer verifies during a TLS handshake with the backend.
1258+
When the server presents its X.509 certificate to the Load Balancer, the Load Balancer inspects the certificate's SAN field,
1259+
and requires that at least one SAN match one of the subjectAltNames in the list. This field is limited to 5 entries.
1260+
When both sni and subjectAltNames are specified, the load balancer matches the backend certificate's SAN only to
1261+
subjectAltNames.`,
1262+
Elem: &schema.Resource{
1263+
Schema: map[string]*schema.Schema{
1264+
"dns_name": {
1265+
Type: schema.TypeString,
1266+
Optional: true,
1267+
Description: `The SAN specified as a DNS Name.`,
1268+
ExactlyOneOf: []string{},
1269+
},
1270+
"uniform_resource_identifier": {
1271+
Type: schema.TypeString,
1272+
Optional: true,
1273+
Description: `The SAN specified as a URI.`,
1274+
ExactlyOneOf: []string{},
1275+
},
1276+
},
1277+
},
1278+
},
1279+
},
1280+
},
1281+
},
12321282
"creation_timestamp": {
12331283
Type: schema.TypeString,
12341284
Computed: true,
@@ -1621,6 +1671,12 @@ func resourceComputeBackendServiceCreate(d *schema.ResourceData, meta interface{
16211671
} else if v, ok := d.GetOkExists("service_lb_policy"); !tpgresource.IsEmptyValue(reflect.ValueOf(serviceLbPolicyProp)) && (ok || !reflect.DeepEqual(v, serviceLbPolicyProp)) {
16221672
obj["serviceLbPolicy"] = serviceLbPolicyProp
16231673
}
1674+
tlsSettingsProp, err := expandComputeBackendServiceTlsSettings(d.Get("tls_settings"), d, config)
1675+
if err != nil {
1676+
return err
1677+
} else if v, ok := d.GetOkExists("tls_settings"); !tpgresource.IsEmptyValue(reflect.ValueOf(tlsSettingsProp)) && (ok || !reflect.DeepEqual(v, tlsSettingsProp)) {
1678+
obj["tlsSettings"] = tlsSettingsProp
1679+
}
16241680

16251681
obj, err = resourceComputeBackendServiceEncoder(d, meta, obj)
16261682
if err != nil {
@@ -1887,6 +1943,9 @@ func resourceComputeBackendServiceRead(d *schema.ResourceData, meta interface{})
18871943
if err := d.Set("service_lb_policy", flattenComputeBackendServiceServiceLbPolicy(res["serviceLbPolicy"], d, config)); err != nil {
18881944
return fmt.Errorf("Error reading BackendService: %s", err)
18891945
}
1946+
if err := d.Set("tls_settings", flattenComputeBackendServiceTlsSettings(res["tlsSettings"], d, config)); err != nil {
1947+
return fmt.Errorf("Error reading BackendService: %s", err)
1948+
}
18901949
if err := d.Set("self_link", tpgresource.ConvertSelfLinkToV1(res["selfLink"].(string))); err != nil {
18911950
return fmt.Errorf("Error reading BackendService: %s", err)
18921951
}
@@ -2096,6 +2155,12 @@ func resourceComputeBackendServiceUpdate(d *schema.ResourceData, meta interface{
20962155
} else if v, ok := d.GetOkExists("service_lb_policy"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, serviceLbPolicyProp)) {
20972156
obj["serviceLbPolicy"] = serviceLbPolicyProp
20982157
}
2158+
tlsSettingsProp, err := expandComputeBackendServiceTlsSettings(d.Get("tls_settings"), d, config)
2159+
if err != nil {
2160+
return err
2161+
} else if v, ok := d.GetOkExists("tls_settings"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, tlsSettingsProp)) {
2162+
obj["tlsSettings"] = tlsSettingsProp
2163+
}
20992164

21002165
obj, err = resourceComputeBackendServiceEncoder(d, meta, obj)
21012166
if err != nil {
@@ -3671,6 +3736,58 @@ func flattenComputeBackendServiceServiceLbPolicy(v interface{}, d *schema.Resour
36713736
return v
36723737
}
36733738

3739+
func flattenComputeBackendServiceTlsSettings(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
3740+
if v == nil {
3741+
return nil
3742+
}
3743+
original := v.(map[string]interface{})
3744+
if len(original) == 0 {
3745+
return nil
3746+
}
3747+
transformed := make(map[string]interface{})
3748+
transformed["sni"] =
3749+
flattenComputeBackendServiceTlsSettingsSni(original["sni"], d, config)
3750+
transformed["subject_alt_names"] =
3751+
flattenComputeBackendServiceTlsSettingsSubjectAltNames(original["subjectAltNames"], d, config)
3752+
transformed["authentication_config"] =
3753+
flattenComputeBackendServiceTlsSettingsAuthenticationConfig(original["authenticationConfig"], d, config)
3754+
return []interface{}{transformed}
3755+
}
3756+
func flattenComputeBackendServiceTlsSettingsSni(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
3757+
return v
3758+
}
3759+
3760+
func flattenComputeBackendServiceTlsSettingsSubjectAltNames(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
3761+
if v == nil {
3762+
return v
3763+
}
3764+
l := v.([]interface{})
3765+
transformed := make([]interface{}, 0, len(l))
3766+
for _, raw := range l {
3767+
original := raw.(map[string]interface{})
3768+
if len(original) < 1 {
3769+
// Do not include empty json objects coming back from the api
3770+
continue
3771+
}
3772+
transformed = append(transformed, map[string]interface{}{
3773+
"dns_name": flattenComputeBackendServiceTlsSettingsSubjectAltNamesDnsName(original["dnsName"], d, config),
3774+
"uniform_resource_identifier": flattenComputeBackendServiceTlsSettingsSubjectAltNamesUniformResourceIdentifier(original["uniformResourceIdentifier"], d, config),
3775+
})
3776+
}
3777+
return transformed
3778+
}
3779+
func flattenComputeBackendServiceTlsSettingsSubjectAltNamesDnsName(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
3780+
return v
3781+
}
3782+
3783+
func flattenComputeBackendServiceTlsSettingsSubjectAltNamesUniformResourceIdentifier(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
3784+
return v
3785+
}
3786+
3787+
func flattenComputeBackendServiceTlsSettingsAuthenticationConfig(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
3788+
return v
3789+
}
3790+
36743791
func expandComputeBackendServiceAffinityCookieTtlSec(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
36753792
return v, nil
36763793
}
@@ -5024,6 +5141,84 @@ func expandComputeBackendServiceServiceLbPolicy(v interface{}, d tpgresource.Ter
50245141
return v, nil
50255142
}
50265143

5144+
func expandComputeBackendServiceTlsSettings(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
5145+
l := v.([]interface{})
5146+
if len(l) == 0 || l[0] == nil {
5147+
return nil, nil
5148+
}
5149+
raw := l[0]
5150+
original := raw.(map[string]interface{})
5151+
transformed := make(map[string]interface{})
5152+
5153+
transformedSni, err := expandComputeBackendServiceTlsSettingsSni(original["sni"], d, config)
5154+
if err != nil {
5155+
return nil, err
5156+
} else if val := reflect.ValueOf(transformedSni); val.IsValid() && !tpgresource.IsEmptyValue(val) {
5157+
transformed["sni"] = transformedSni
5158+
}
5159+
5160+
transformedSubjectAltNames, err := expandComputeBackendServiceTlsSettingsSubjectAltNames(original["subject_alt_names"], d, config)
5161+
if err != nil {
5162+
return nil, err
5163+
} else if val := reflect.ValueOf(transformedSubjectAltNames); val.IsValid() && !tpgresource.IsEmptyValue(val) {
5164+
transformed["subjectAltNames"] = transformedSubjectAltNames
5165+
}
5166+
5167+
transformedAuthenticationConfig, err := expandComputeBackendServiceTlsSettingsAuthenticationConfig(original["authentication_config"], d, config)
5168+
if err != nil {
5169+
return nil, err
5170+
} else if val := reflect.ValueOf(transformedAuthenticationConfig); val.IsValid() && !tpgresource.IsEmptyValue(val) {
5171+
transformed["authenticationConfig"] = transformedAuthenticationConfig
5172+
}
5173+
5174+
return transformed, nil
5175+
}
5176+
5177+
func expandComputeBackendServiceTlsSettingsSni(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
5178+
return v, nil
5179+
}
5180+
5181+
func expandComputeBackendServiceTlsSettingsSubjectAltNames(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
5182+
l := v.([]interface{})
5183+
req := make([]interface{}, 0, len(l))
5184+
for _, raw := range l {
5185+
if raw == nil {
5186+
continue
5187+
}
5188+
original := raw.(map[string]interface{})
5189+
transformed := make(map[string]interface{})
5190+
5191+
transformedDnsName, err := expandComputeBackendServiceTlsSettingsSubjectAltNamesDnsName(original["dns_name"], d, config)
5192+
if err != nil {
5193+
return nil, err
5194+
} else if val := reflect.ValueOf(transformedDnsName); val.IsValid() && !tpgresource.IsEmptyValue(val) {
5195+
transformed["dnsName"] = transformedDnsName
5196+
}
5197+
5198+
transformedUniformResourceIdentifier, err := expandComputeBackendServiceTlsSettingsSubjectAltNamesUniformResourceIdentifier(original["uniform_resource_identifier"], d, config)
5199+
if err != nil {
5200+
return nil, err
5201+
} else if val := reflect.ValueOf(transformedUniformResourceIdentifier); val.IsValid() && !tpgresource.IsEmptyValue(val) {
5202+
transformed["uniformResourceIdentifier"] = transformedUniformResourceIdentifier
5203+
}
5204+
5205+
req = append(req, transformed)
5206+
}
5207+
return req, nil
5208+
}
5209+
5210+
func expandComputeBackendServiceTlsSettingsSubjectAltNamesDnsName(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
5211+
return v, nil
5212+
}
5213+
5214+
func expandComputeBackendServiceTlsSettingsSubjectAltNamesUniformResourceIdentifier(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
5215+
return v, nil
5216+
}
5217+
5218+
func expandComputeBackendServiceTlsSettingsAuthenticationConfig(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
5219+
return v, nil
5220+
}
5221+
50275222
func resourceComputeBackendServiceEncoder(d *schema.ResourceData, meta interface{}, obj map[string]interface{}) (map[string]interface{}, error) {
50285223
backendsRaw, ok := obj["backends"]
50295224
if !ok {

google-beta/services/compute/resource_compute_backend_service_generated_meta.yaml

+4
Original file line numberDiff line numberDiff line change
@@ -121,3 +121,7 @@ fields:
121121
- field: 'strong_session_affinity_cookie.ttl.nanos'
122122
- field: 'strong_session_affinity_cookie.ttl.seconds'
123123
- field: 'timeout_sec'
124+
- field: 'tls_settings.authentication_config'
125+
- field: 'tls_settings.sni'
126+
- field: 'tls_settings.subject_alt_names.dns_name'
127+
- field: 'tls_settings.subject_alt_names.uniform_resource_identifier'

google-beta/services/compute/resource_compute_backend_service_generated_test.go

+61
Original file line numberDiff line numberDiff line change
@@ -742,6 +742,67 @@ resource "google_compute_health_check" "default" {
742742
`, context)
743743
}
744744

745+
func TestAccComputeBackendService_backendServiceTlsSettingsExample(t *testing.T) {
746+
t.Parallel()
747+
748+
context := map[string]interface{}{
749+
"random_suffix": acctest.RandString(t, 10),
750+
}
751+
752+
acctest.VcrTest(t, resource.TestCase{
753+
PreCheck: func() { acctest.AccTestPreCheck(t) },
754+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t),
755+
CheckDestroy: testAccCheckComputeBackendServiceDestroyProducer(t),
756+
Steps: []resource.TestStep{
757+
{
758+
Config: testAccComputeBackendService_backendServiceTlsSettingsExample(context),
759+
},
760+
{
761+
ResourceName: "google_compute_backend_service.default",
762+
ImportState: true,
763+
ImportStateVerify: true,
764+
ImportStateVerifyIgnore: []string{"iap.0.oauth2_client_secret", "security_settings.0.aws_v4_authentication.0.access_key"},
765+
},
766+
},
767+
})
768+
}
769+
770+
func testAccComputeBackendService_backendServiceTlsSettingsExample(context map[string]interface{}) string {
771+
return acctest.Nprintf(`
772+
resource "google_compute_backend_service" "default" {
773+
provider = google-beta
774+
name = "tf-test-backend-service%{random_suffix}"
775+
health_checks = [google_compute_health_check.default.id]
776+
load_balancing_scheme = "EXTERNAL_MANAGED"
777+
protocol = "HTTPS"
778+
tls_settings {
779+
sni = "example.com"
780+
subject_alt_names {
781+
dns_name = "example.com"
782+
}
783+
subject_alt_names {
784+
uniform_resource_identifier = "https://example.com"
785+
}
786+
authentication_config = "//networksecurity.googleapis.com/${google_network_security_backend_authentication_config.default.id}"
787+
}
788+
}
789+
790+
resource "google_compute_health_check" "default" {
791+
provider = google-beta
792+
name = "tf-test-health-check%{random_suffix}"
793+
http_health_check {
794+
port = 80
795+
}
796+
}
797+
798+
resource "google_network_security_backend_authentication_config" "default" {
799+
provider = google-beta
800+
name = "authentication%{random_suffix}"
801+
well_known_roots = "PUBLIC_ROOTS"
802+
}
803+
`, context)
804+
}
805+
745806
func testAccCheckComputeBackendServiceDestroyProducer(t *testing.T) func(s *terraform.State) error {
746807
return func(s *terraform.State) error {
747808
for name, rs := range s.RootModule().Resources {

0 commit comments

Comments
 (0)