diff --git a/modules/cloud-run-v2/README.md b/modules/cloud-run-v2/README.md
index b237175b3..91ef4887e 100644
--- a/modules/cloud-run-v2/README.md
+++ b/modules/cloud-run-v2/README.md
@@ -813,9 +813,9 @@ module "cloud_run" {
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
-| [name](variables.tf#L181) | Name used for Cloud Run service. | string | ✓ | |
-| [project_id](variables.tf#L196) | Project id used for all resources. | string | ✓ | |
-| [region](variables.tf#L201) | Region used for all resources. | string | ✓ | |
+| [name](variables.tf#L223) | Name used for Cloud Run service. | string | ✓ | |
+| [project_id](variables.tf#L238) | Project id used for all resources. | string | ✓ | |
+| [region](variables.tf#L243) | Region used for all resources. | string | ✓ | |
| [containers](variables.tf#L17) | Containers in name => attributes format. | map(object({…})) | | {} |
| [create_job](variables.tf#L80) | Create Cloud Run Job instead of Service. | bool | | false |
| [custom_audiences](variables.tf#L86) | Custom audiences for service. | list(string) | | null |
@@ -823,17 +823,19 @@ module "cloud_run" {
| [encryption_key](variables.tf#L98) | The full resource name of the Cloud KMS CryptoKey. | string | | null |
| [eventarc_triggers](variables.tf#L104) | Event arc triggers for different sources. | object({…}) | | {} |
| [iam](variables.tf#L122) | IAM bindings for Cloud Run service in {ROLE => [MEMBERS]} format. | map(list(string)) | | {} |
-| [ingress](variables.tf#L128) | Ingress settings. | string | | null |
-| [invoker_iam_disabled](variables.tf#L145) | Disables IAM permission check for run.routes.invoke for callers of this service. | bool | | false |
-| [labels](variables.tf#L151) | Resource labels. | map(string) | | {} |
-| [launch_stage](variables.tf#L157) | The launch stage as defined by Google Cloud Platform Launch Stages. | string | | null |
-| [managed_revision](variables.tf#L174) | Whether the Terraform module should control the deployment of revisions. | bool | | true |
-| [prefix](variables.tf#L186) | Optional prefix used for resource names. | string | | null |
-| [revision](variables.tf#L206) | Revision template configurations. | object({…}) | | {} |
-| [service_account](variables.tf#L245) | Service account email. Unused if service account is auto-created. | string | | null |
-| [service_account_create](variables.tf#L251) | Auto-create service account. | bool | | false |
-| [tag_bindings](variables.tf#L257) | Tag bindings for this service, in key => tag value id format. | map(string) | | {} |
-| [volumes](variables.tf#L264) | Named volumes in containers in name => attributes format. | map(object({…})) | | {} |
+| [iap_enabled](variables.tf#L128) | <<-EOT Enables Identity-Aware Proxy (IAP) for this service. IAP can only be enabled for Cloud Run services (create_job = false). EOT | bool | | false |
+| [iap_http_resource_accessors_config](variables.tf#L142) | <<-EOT IAP HTTP resource accessors configuration. When authoritative_mode is true, the google_iap_web_cloud_run_service_iam_binding resource is used which replaces any existing IAM policy attached to the IAP web service. When authoritative_mode is false (default), the google_iap_web_cloud_run_service_iam_member resource is used which adds the IAM policies to the service. EOT | object({…}) | | null |
+| [ingress](variables.tf#L166) | Ingress settings. | string | | null |
+| [invoker_iam_disabled](variables.tf#L183) | Disables IAM permission check for run.routes.invoke for callers of this service. | bool | | false |
+| [labels](variables.tf#L189) | Resource labels. | map(string) | | {} |
+| [launch_stage](variables.tf#L195) | The launch stage as defined by Google Cloud Platform Launch Stages. | string | | null |
+| [managed_revision](variables.tf#L216) | Whether the Terraform module should control the deployment of revisions. | bool | | true |
+| [prefix](variables.tf#L228) | Optional prefix used for resource names. | string | | null |
+| [revision](variables.tf#L248) | Revision template configurations. | object({…}) | | {} |
+| [service_account](variables.tf#L287) | Service account email. Unused if service account is auto-created. | string | | null |
+| [service_account_create](variables.tf#L293) | Auto-create service account. | bool | | false |
+| [tag_bindings](variables.tf#L299) | Tag bindings for this service, in key => tag value id format. | map(string) | | {} |
+| [volumes](variables.tf#L306) | Named volumes in containers in name => attributes format. | map(object({…})) | | {} |
| [vpc_connector_create](variables-vpcconnector.tf#L17) | Populate this to create a Serverless VPC Access connector. | object({…}) | | null |
## Outputs
diff --git a/modules/cloud-run-v2/service.tf b/modules/cloud-run-v2/service.tf
index a9b1e0fea..808b9ecd2 100644
--- a/modules/cloud-run-v2/service.tf
+++ b/modules/cloud-run-v2/service.tf
@@ -30,6 +30,7 @@ resource "google_cloud_run_v2_service" "service" {
launch_stage = var.launch_stage
custom_audiences = var.custom_audiences
deletion_protection = var.deletion_protection
+ iap_enabled = var.iap_enabled
template {
labels = var.revision.labels
@@ -274,6 +275,7 @@ resource "google_cloud_run_v2_service" "service_unmanaged" {
launch_stage = var.launch_stage
custom_audiences = var.custom_audiences
deletion_protection = var.deletion_protection
+ iap_enabled = var.iap_enabled
template {
labels = var.revision.labels
@@ -522,3 +524,39 @@ resource "google_cloud_run_v2_service_iam_binding" "binding" {
)
)
}
+
+locals {
+ use_iap_member = (
+ !var.create_job &&
+ var.iap_http_resource_accessors_config != null &&
+ !var.iap_http_resource_accessors_config.authoritative_mode
+ )
+
+ iap_member_list = local.use_iap_member ? toset(var.iap_http_resource_accessors_config.iam_emails) : []
+
+ use_iap_iam_binding = (
+ !var.create_job &&
+ var.iap_http_resource_accessors_config != null &&
+ var.iap_http_resource_accessors_config.authoritative_mode
+ )
+ iap_binding_dict = local.use_iap_iam_binding ? { "iap" = var.iap_http_resource_accessors_config.iam_emails } : {}
+
+}
+
+resource "google_iap_web_cloud_run_service_iam_member" "member" {
+ for_each = local.iap_member_list
+ project = local.service.project
+ location = local.service.location
+ cloud_run_service_name = local.service.name
+ role = "roles/iap.httpsResourceAccessor"
+ member = each.key
+}
+
+resource "google_iap_web_cloud_run_service_iam_binding" "binding" {
+ for_each = local.iap_binding_dict
+ project = local.service.project
+ location = local.service.location
+ cloud_run_service_name = local.service.name
+ role = "roles/iap.httpsResourceAccessor"
+ members = each.value
+}
\ No newline at end of file
diff --git a/modules/cloud-run-v2/variables.tf b/modules/cloud-run-v2/variables.tf
index 61a9ab95c..15649e55f 100644
--- a/modules/cloud-run-v2/variables.tf
+++ b/modules/cloud-run-v2/variables.tf
@@ -125,6 +125,44 @@ variable "iam" {
default = {}
}
+variable "iap_enabled" {
+ description = <<-EOT
+ Enables Identity-Aware Proxy (IAP) for this service.
+ IAP can only be enabled for Cloud Run services (create_job = false).
+ EOT
+ type = bool
+ default = false
+
+ validation {
+ condition = !var.iap_enabled || (var.iap_enabled && !var.create_job)
+ error_message = "IAP can only be enabled for Cloud Run services (create_job = false), not for jobs."
+ }
+}
+
+variable "iap_http_resource_accessors_config" {
+ description = <<-EOT
+ IAP HTTP resource accessors configuration.
+ When authoritative_mode is true, the google_iap_web_cloud_run_service_iam_binding resource is used
+ which replaces any existing IAM policy attached to the IAP web service.
+ When authoritative_mode is false (default), the google_iap_web_cloud_run_service_iam_member resource is used
+ which adds the IAM policies to the service.
+ EOT
+ type = object({
+ iam_emails = list(string)
+ authoritative_mode = optional(bool, false)
+ })
+ default = null
+
+ validation {
+ condition = var.iap_http_resource_accessors_config == null || var.iap_enabled
+ error_message = "iap_http_resource_accessors_config can only be set when iap_enabled = true."
+ }
+ validation {
+ condition = var.iap_http_resource_accessors_config == null || (var.iap_http_resource_accessors_config != null && length(var.iap_http_resource_accessors_config.iam_emails) > 0)
+ error_message = "When iap_http_resource_accessors_config is set, iam_emails must not be empty."
+ }
+}
+
variable "ingress" {
description = "Ingress settings."
type = string
@@ -169,6 +207,10 @@ variable "launch_stage" {
BETA, GA, DEPRECATED.
EOF
}
+ validation {
+ condition = !var.iap_enabled || (var.iap_enabled && var.launch_stage == "BETA")
+ error_message = "When IAP is enabled (iap_enabled = true), launch_stage must be set to 'BETA'."
+ }
}
variable "managed_revision" {