diff --git a/build/int.cloudbuild.yaml b/build/int.cloudbuild.yaml index 08f66775..aa513346 100644 --- a/build/int.cloudbuild.yaml +++ b/build/int.cloudbuild.yaml @@ -158,6 +158,27 @@ steps: - verify internal-lb-http gce-mig name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS' args: ['/bin/bash', '-c', 'cft test run TestInternalLbGCEMIG --stage teardown --verbose'] + # Backend Service with IAP Enabled +- id: init backend-with-iap + waitFor: + - teardown internal-lb-http gce-mig + name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS' + args: ['/bin/bash', '-c', 'cft test run TestLbBackendServiceIap --stage init --verbose'] +- id: apply backend-with-iap + waitFor: + - init backend-with-iap + name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS' + args: ['/bin/bash', '-c', 'cft test run TestLbBackendServiceIap --stage apply --verbose'] +- id: verify backend-with-iap + waitFor: + - apply backend-with-iap + name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS' + args: ['/bin/bash', '-c', 'cft test run TestLbBackendServiceIap --stage verify --verbose'] +- id: teardown backend-with-iap + waitFor: + - verify backend-with-iap + name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS' + args: ['/bin/bash', '-c', 'cft test run TestLbBackendServiceIap --stage teardown --verbose'] tags: - 'ci' - 'integration' diff --git a/examples/backend-with-iap/main.tf b/examples/backend-with-iap/main.tf new file mode 100644 index 00000000..ce556beb --- /dev/null +++ b/examples/backend-with-iap/main.tf @@ -0,0 +1,36 @@ +/** + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +module "lb-backend-iap" { + source = "terraform-google-modules/lb-http/google//modules/backend" + version = "~> 12.0" + + project_id = var.project_id + name = "backend-with-iap" + iap_config = { + enable = true + iap_members = ["user:test@test.test"] + } +} + +module "lb-frontend" { + source = "terraform-google-modules/lb-http/google//modules/frontend" + version = "~> 12.0" + + project_id = var.project_id + name = "global-lb-fe-bucket" + url_map_input = module.lb-backend-iap.backend_service_info +} diff --git a/examples/backend-with-iap/outputs.tf b/examples/backend-with-iap/outputs.tf new file mode 100644 index 00000000..ac843af5 --- /dev/null +++ b/examples/backend-with-iap/outputs.tf @@ -0,0 +1,26 @@ +/** + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +output "project_id" { + value = module.lb-backend-iap.project_id + description = "Project ID of the service" +} + +output "service_name" { + value = module.lb-backend-iap.service_name + description = "Name of the created service" +} diff --git a/examples/backend-with-iap/variables.tf b/examples/backend-with-iap/variables.tf new file mode 100644 index 00000000..419e3a19 --- /dev/null +++ b/examples/backend-with-iap/variables.tf @@ -0,0 +1,19 @@ +/** + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +variable "project_id" { + type = string +} diff --git a/examples/lb-http-separate-frontend-and-backend/main.tf b/examples/lb-http-separate-frontend-and-backend/main.tf index 8ba29ca4..3a25f810 100644 --- a/examples/lb-http-separate-frontend-and-backend/main.tf +++ b/examples/lb-http-separate-frontend-and-backend/main.tf @@ -68,8 +68,9 @@ module "cloud-nat-group2" { } module "lb-http-backend" { - source = "terraform-google-modules/lb-http/google//modules/backend" - version = "~> 12.0" + source = "terraform-google-modules/lb-http/google//modules/backend" + version = "~> 12.0" + project_id = var.project_id name = "backend-lb" target_tags = [ diff --git a/metadata.display.yaml b/metadata.display.yaml index acb5c79d..8ea229ef 100644 --- a/metadata.display.yaml +++ b/metadata.display.yaml @@ -1,4 +1,4 @@ -# Copyright 2024 Google LLC +# Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/metadata.yaml b/metadata.yaml index 04497664..18e95d68 100644 --- a/metadata.yaml +++ b/metadata.yaml @@ -40,6 +40,8 @@ spec: - name: serverless_negs location: modules/serverless_negs examples: + - name: backend-with-iap + location: examples/backend-with-iap - name: cdn-policy location: examples/cdn-policy - name: certificate-map @@ -336,13 +338,13 @@ spec: roles: - level: Project roles: - - roles/run.admin - roles/iam.serviceAccountUser - roles/certificatemanager.owner - roles/vpcaccess.admin - roles/iam.serviceAccountAdmin - roles/storage.admin - roles/compute.admin + - roles/run.admin services: - certificatemanager.googleapis.com - cloudresourcemanager.googleapis.com diff --git a/modules/backend/README.md b/modules/backend/README.md index 3ffde877..34369fcc 100644 --- a/modules/backend/README.md +++ b/modules/backend/README.md @@ -22,7 +22,7 @@ This module creates `google_compute_backend_service` resource and its dependenci | groups | The list of backend instance group which serves the traffic. |
list(object({
group = string
description = optional(string)

balancing_mode = optional(string)
capacity_scaler = optional(number)
max_connections = optional(number)
max_connections_per_instance = optional(number)
max_connections_per_endpoint = optional(number)
max_rate = optional(number)
max_rate_per_instance = optional(number)
max_rate_per_endpoint = optional(number)
max_utilization = optional(number)
}))
| `[]` | no | | health\_check | Input for creating HttpHealthCheck or HttpsHealthCheck resource for health checking this BackendService. A health check must be specified unless the backend service uses an internet or serverless NEG as a backend. |
object({
host = optional(string, null)
request_path = optional(string, null)
request = optional(string, null)
response = optional(string, null)
port = optional(number, null)
port_name = optional(string, null)
proxy_header = optional(string, null)
port_specification = optional(string, null)
protocol = optional(string, null)
check_interval_sec = optional(number, 5)
timeout_sec = optional(number, 5)
healthy_threshold = optional(number, 2)
unhealthy_threshold = optional(number, 2)
logging = optional(bool, false)
})
| `null` | no | | host\_path\_mappings | The list of host/path for which traffic could be sent to the backend service |
list(object({
host = string
path = string
}))
|
[
{
"host": "*",
"path": "/*"
}
]
| no | -| iap\_config | Settings for enabling Cloud Identity Aware Proxy Structure. |
object({
enable = bool
oauth2_client_id = optional(string)
oauth2_client_secret = optional(string)
})
|
{
"enable": false
}
| no | +| iap\_config | Settings for enabling Cloud Identity Aware Proxy and Users/SAs to be given IAP HttpResourceAccessor access to the service. |
object({
enable = bool
oauth2_client_id = optional(string)
oauth2_client_secret = optional(string)
iap_members = optional(list(string))
})
|
{
"enable": false
}
| no | | load\_balancing\_scheme | Load balancing scheme type (EXTERNAL for classic external load balancer, EXTERNAL\_MANAGED for Envoy-based load balancer, INTERNAL\_MANAGED for internal load balancer and INTERNAL\_SELF\_MANAGED for traffic director) | `string` | `"EXTERNAL_MANAGED"` | no | | locality\_lb\_policy | The load balancing algorithm used within the scope of the locality. | `string` | `null` | no | | log\_config | This field denotes the logging options for the load balancer traffic served by this backend service. If logging is enabled, logs will be exported to Stackdriver. |
object({
enable = bool
sample_rate = number
})
|
{
"enable": true,
"sample_rate": 1
}
| no | @@ -44,5 +44,7 @@ This module creates `google_compute_backend_service` resource and its dependenci |------|-------------| | apphub\_service\_uri | Service URI in CAIS style to be used by Apphub. | | backend\_service\_info | Host, path and backend service mapping | +| project\_id | Project ID of the service | +| service\_name | Name of the created service | diff --git a/modules/backend/main.tf b/modules/backend/main.tf index 927ca8c4..5487fdc3 100644 --- a/modules/backend/main.tf +++ b/modules/backend/main.tf @@ -17,6 +17,7 @@ locals { is_backend_bucket = var.backend_bucket_name != null && var.backend_bucket_name != "" serverless_neg_backends = local.is_backend_bucket ? [] : var.serverless_neg_backends + iap_access_members = var.iap_config.enable ? coalesce(var.iap_config.iap_members, []) : [] } resource "google_compute_backend_service" "default" { @@ -365,3 +366,12 @@ resource "google_compute_backend_bucket" "default" { } } } + +resource "google_iap_web_backend_service_iam_member" "member" { + for_each = toset(local.iap_access_members) + project = google_compute_backend_service.default[0].project + web_backend_service = google_compute_backend_service.default[0].name + role = "roles/iap.httpsResourceAccessor" + member = each.value +} + diff --git a/modules/backend/metadata.display.yaml b/modules/backend/metadata.display.yaml index ce481043..8ec61619 100644 --- a/modules/backend/metadata.display.yaml +++ b/modules/backend/metadata.display.yaml @@ -1,4 +1,4 @@ -# Copyright 2024 Google LLC +# Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -31,6 +31,9 @@ spec: affinity_cookie_ttl_sec: name: affinity_cookie_ttl_sec title: Affinity Cookie Ttl Sec + backend_bucket_name: + name: backend_bucket_name + title: Backend Bucket Name cdn_policy: name: cdn_policy title: Cdn Policy @@ -66,6 +69,9 @@ spec: firewall_projects: name: firewall_projects title: Firewall Projects + firewall_source_ranges: + name: firewall_source_ranges + title: Firewall Source Ranges groups: name: groups title: Groups @@ -79,6 +85,12 @@ spec: iap_config: name: iap_config title: Iap Config + properties: + iap_members: + name: iap_members + title: Iap Members + regexValidation: ^(?:allUsers|allAuthenticatedUsers)$|^((?:user|group|serviceAccount):(?:[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})|(?:domain:(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,})|(?:projectOwner|projectEditor|projectViewer):[a-z][a-z0-9-]{0,28}[a-z0-9])$ + validation: Must be allUsers, allAuthenticatedUsers, or a service account in the format serviceAccount:email@example.com. [More info](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/iap_web_backend_service_iam#google_iap_web_backend_service_iam_member). load_balancing_scheme: name: load_balancing_scheme title: Load Balancing Scheme @@ -125,3 +137,6 @@ spec: target_tags: name: target_tags title: Target Tags + timeout_sec: + name: timeout_sec + title: Timeout Sec diff --git a/modules/backend/metadata.yaml b/modules/backend/metadata.yaml index 7bb32df3..f0369f9f 100644 --- a/modules/backend/metadata.yaml +++ b/modules/backend/metadata.yaml @@ -32,6 +32,8 @@ spec: description: {} content: examples: + - name: backend-with-iap + location: examples/backend-with-iap - name: cdn-policy location: examples/cdn-policy - name: certificate-map @@ -189,12 +191,13 @@ spec: spec: outputExpr: name - name: iap_config - description: Settings for enabling Cloud Identity Aware Proxy Structure. + description: Settings for enabling Cloud Identity Aware Proxy and Users/SAs to be given IAP HttpResourceAccessor access to the service. varType: |- object({ enable = bool oauth2_client_id = optional(string) oauth2_client_secret = optional(string) + iap_members = optional(list(string)) }) defaultValue: enable: false @@ -327,20 +330,25 @@ spec: - backend_service: string host: string path: string + - name: project_id + description: Project ID of the service + - name: service_name + description: Name of the created service requirements: roles: - level: Project roles: - - roles/run.admin - - roles/compute.networkAdmin - - roles/iap.admin - roles/iam.serviceAccountUser - roles/iam.serviceAccountAdmin - roles/compute.admin - roles/storage.admin + - roles/run.admin + - roles/compute.networkAdmin + - roles/iap.admin services: - cloudresourcemanager.googleapis.com - compute.googleapis.com + - iap.googleapis.com - run.googleapis.com - storage-api.googleapis.com - vpcaccess.googleapis.com diff --git a/modules/backend/outputs.tf b/modules/backend/outputs.tf index a8dab938..d072070b 100644 --- a/modules/backend/outputs.tf +++ b/modules/backend/outputs.tf @@ -43,3 +43,13 @@ output "apphub_service_uri" { ) description = "Service URI in CAIS style to be used by Apphub." } + +output "project_id" { + value = var.project_id + description = "Project ID of the service" +} + +output "service_name" { + value = var.name + description = "Name of the created service" +} diff --git a/modules/backend/variables.tf b/modules/backend/variables.tf index 4203dd7d..f825bda1 100644 --- a/modules/backend/variables.tf +++ b/modules/backend/variables.tf @@ -154,11 +154,12 @@ variable "backend_bucket_name" { } variable "iap_config" { - description = "Settings for enabling Cloud Identity Aware Proxy Structure." + description = "Settings for enabling Cloud Identity Aware Proxy and Users/SAs to be given IAP HttpResourceAccessor access to the service." type = object({ enable = bool oauth2_client_id = optional(string) oauth2_client_secret = optional(string) + iap_members = optional(list(string)) }) default = { enable = false } } diff --git a/modules/dynamic_backends/metadata.display.yaml b/modules/dynamic_backends/metadata.display.yaml index 8f5ed328..7b533863 100644 --- a/modules/dynamic_backends/metadata.display.yaml +++ b/modules/dynamic_backends/metadata.display.yaml @@ -1,4 +1,4 @@ -# Copyright 2024 Google LLC +# Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/modules/dynamic_backends/metadata.yaml b/modules/dynamic_backends/metadata.yaml index 7c8c22b3..ba9a6da3 100644 --- a/modules/dynamic_backends/metadata.yaml +++ b/modules/dynamic_backends/metadata.yaml @@ -32,6 +32,8 @@ spec: description: {} content: examples: + - name: backend-with-iap + location: examples/backend-with-iap - name: cdn-policy location: examples/cdn-policy - name: certificate-map @@ -328,13 +330,13 @@ spec: roles: - level: Project roles: + - roles/vpcaccess.admin + - roles/iam.serviceAccountAdmin - roles/storage.admin - roles/compute.admin - roles/run.admin - roles/iam.serviceAccountUser - roles/certificatemanager.owner - - roles/vpcaccess.admin - - roles/iam.serviceAccountAdmin services: - certificatemanager.googleapis.com - cloudresourcemanager.googleapis.com diff --git a/modules/frontend/metadata.display.yaml b/modules/frontend/metadata.display.yaml index 20435325..cee668c1 100644 --- a/modules/frontend/metadata.display.yaml +++ b/modules/frontend/metadata.display.yaml @@ -1,4 +1,4 @@ -# Copyright 2024 Google LLC +# Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -67,6 +67,9 @@ spec: https_redirect: name: https_redirect title: Https Redirect + internal_forwarding_rules_config: + name: internal_forwarding_rules_config + title: Internal Forwarding Rules Config ipv6_address: name: ipv6_address title: Ipv6 Address diff --git a/modules/frontend/metadata.yaml b/modules/frontend/metadata.yaml index f80639ce..4ae47ec9 100644 --- a/modules/frontend/metadata.yaml +++ b/modules/frontend/metadata.yaml @@ -32,6 +32,8 @@ spec: description: {} content: examples: + - name: backend-with-iap + location: examples/backend-with-iap - name: cdn-policy location: examples/cdn-policy - name: certificate-map @@ -244,11 +246,11 @@ spec: roles: - level: Project roles: - - roles/compute.admin - roles/storage.admin - roles/iap.admin - roles/certificatemanager.owner - roles/iam.serviceAccountUser + - roles/compute.admin services: - certificatemanager.googleapis.com - compute.googleapis.com diff --git a/modules/serverless_negs/metadata.display.yaml b/modules/serverless_negs/metadata.display.yaml index 01ad3ef9..6a6b669b 100644 --- a/modules/serverless_negs/metadata.display.yaml +++ b/modules/serverless_negs/metadata.display.yaml @@ -1,4 +1,4 @@ -# Copyright 2024 Google LLC +# Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/modules/serverless_negs/metadata.yaml b/modules/serverless_negs/metadata.yaml index 6cffd289..fae7288a 100644 --- a/modules/serverless_negs/metadata.yaml +++ b/modules/serverless_negs/metadata.yaml @@ -32,6 +32,8 @@ spec: description: {} content: examples: + - name: backend-with-iap + location: examples/backend-with-iap - name: cdn-policy location: examples/cdn-policy - name: certificate-map @@ -292,13 +294,13 @@ spec: roles: - level: Project roles: + - roles/iam.serviceAccountUser + - roles/certificatemanager.owner - roles/vpcaccess.admin - roles/iam.serviceAccountAdmin - roles/storage.admin - roles/compute.admin - roles/run.admin - - roles/iam.serviceAccountUser - - roles/certificatemanager.owner services: - certificatemanager.googleapis.com - cloudresourcemanager.googleapis.com diff --git a/test/integration/backend-with-iap/backend_with_iap_test.go b/test/integration/backend-with-iap/backend_with_iap_test.go new file mode 100644 index 00000000..bc065609 --- /dev/null +++ b/test/integration/backend-with-iap/backend_with_iap_test.go @@ -0,0 +1,42 @@ +// Copyright 2025 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package backend_with_iap + +import ( + "fmt" + "testing" + + "github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test/pkg/tft" + "github.com/stretchr/testify/assert" + "github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test/pkg/gcloud" +) + +func TestLbBackendServiceIap(t *testing.T) { + backendServiceWithIAP := tft.NewTFBlueprintTest(t) + + backendServiceWithIAP.DefineVerify(func(assert *assert.Assertions) { + + projectID := backendServiceWithIAP.GetTFSetupStringOutput("project_id") + serviceName := backendServiceWithIAP.GetStringOutput("service_name") + + backendServiceDescribeCmd := gcloud.Run(t, "compute backend-services describe", gcloud.WithCommonArgs([]string{serviceName, "--project", projectID, "--global", "--format", "json"})) + + //verify IAP is enabled in backend-services + iapConfig := backendServiceDescribeCmd.Get("iap").Map() + assert.Equal("true", iapConfig["enabled"].String(), fmt.Sprintf("IAP should be enabled")) + }) + backendServiceWithIAP.Test() +} + diff --git a/test/setup/iam.tf b/test/setup/iam.tf index d65b85cb..7a379c5d 100644 --- a/test/setup/iam.tf +++ b/test/setup/iam.tf @@ -32,7 +32,8 @@ locals { "roles/compute.networkAdmin", "roles/iap.admin", "roles/iam.serviceAccountUser", - "roles/iam.serviceAccountAdmin" + "roles/iam.serviceAccountAdmin", + "roles/iap.admin" ] dynamic_backends = [ "roles/storage.admin", diff --git a/test/setup/main.tf b/test/setup/main.tf index 21e76c0e..efe704a1 100644 --- a/test/setup/main.tf +++ b/test/setup/main.tf @@ -32,6 +32,7 @@ locals { "storage-api.googleapis.com", "vpcaccess.googleapis.com", "cloudresourcemanager.googleapis.com", + "iap.googleapis.com", ] dynamic_backends = [ "cloudresourcemanager.googleapis.com",