feat: adds support for direct cloud run iap

This commit is contained in:
Maciej Sikora
2025-06-16 10:42:21 +02:00
committed by Wiktor Niesiobędzki
parent 3ba695b0ed
commit c0bac5acc0
3 changed files with 96 additions and 14 deletions

View File

@@ -813,9 +813,9 @@ module "cloud_run" {
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
| [name](variables.tf#L181) | Name used for Cloud Run service. | <code>string</code> | ✓ | |
| [project_id](variables.tf#L196) | Project id used for all resources. | <code>string</code> | ✓ | |
| [region](variables.tf#L201) | Region used for all resources. | <code>string</code> | ✓ | |
| [name](variables.tf#L223) | Name used for Cloud Run service. | <code>string</code> | ✓ | |
| [project_id](variables.tf#L238) | Project id used for all resources. | <code>string</code> | ✓ | |
| [region](variables.tf#L243) | Region used for all resources. | <code>string</code> | ✓ | |
| [containers](variables.tf#L17) | Containers in name => attributes format. | <code title="map&#40;object&#40;&#123;&#10; image &#61; string&#10; depends_on &#61; optional&#40;list&#40;string&#41;&#41;&#10; command &#61; optional&#40;list&#40;string&#41;&#41;&#10; args &#61; optional&#40;list&#40;string&#41;&#41;&#10; env &#61; optional&#40;map&#40;string&#41;&#41;&#10; env_from_key &#61; optional&#40;map&#40;object&#40;&#123;&#10; secret &#61; string&#10; version &#61; string&#10; &#125;&#41;&#41;&#41;&#10; liveness_probe &#61; optional&#40;object&#40;&#123;&#10; grpc &#61; optional&#40;object&#40;&#123;&#10; port &#61; optional&#40;number&#41;&#10; service &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10; http_get &#61; optional&#40;object&#40;&#123;&#10; http_headers &#61; optional&#40;map&#40;string&#41;&#41;&#10; path &#61; optional&#40;string&#41;&#10; port &#61; optional&#40;number&#41;&#10; &#125;&#41;&#41;&#10; failure_threshold &#61; optional&#40;number&#41;&#10; initial_delay_seconds &#61; optional&#40;number&#41;&#10; period_seconds &#61; optional&#40;number&#41;&#10; timeout_seconds &#61; optional&#40;number&#41;&#10; &#125;&#41;&#41;&#10; ports &#61; optional&#40;map&#40;object&#40;&#123;&#10; container_port &#61; optional&#40;number&#41;&#10; name &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#41;&#10; resources &#61; optional&#40;object&#40;&#123;&#10; limits &#61; optional&#40;object&#40;&#123;&#10; cpu &#61; string&#10; memory &#61; string&#10; &#125;&#41;&#41;&#10; cpu_idle &#61; optional&#40;bool&#41;&#10; startup_cpu_boost &#61; optional&#40;bool&#41;&#10; &#125;&#41;&#41;&#10; startup_probe &#61; optional&#40;object&#40;&#123;&#10; grpc &#61; optional&#40;object&#40;&#123;&#10; port &#61; optional&#40;number&#41;&#10; service &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10; http_get &#61; optional&#40;object&#40;&#123;&#10; http_headers &#61; optional&#40;map&#40;string&#41;&#41;&#10; path &#61; optional&#40;string&#41;&#10; port &#61; optional&#40;number&#41;&#10; &#125;&#41;&#41;&#10; tcp_socket &#61; optional&#40;object&#40;&#123;&#10; port &#61; optional&#40;number&#41;&#10; &#125;&#41;&#41;&#10; failure_threshold &#61; optional&#40;number&#41;&#10; initial_delay_seconds &#61; optional&#40;number&#41;&#10; period_seconds &#61; optional&#40;number&#41;&#10; timeout_seconds &#61; optional&#40;number&#41;&#10; &#125;&#41;&#41;&#10; volume_mounts &#61; optional&#40;map&#40;string&#41;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [create_job](variables.tf#L80) | Create Cloud Run Job instead of Service. | <code>bool</code> | | <code>false</code> |
| [custom_audiences](variables.tf#L86) | Custom audiences for service. | <code>list&#40;string&#41;</code> | | <code>null</code> |
@@ -823,17 +823,19 @@ module "cloud_run" {
| [encryption_key](variables.tf#L98) | The full resource name of the Cloud KMS CryptoKey. | <code>string</code> | | <code>null</code> |
| [eventarc_triggers](variables.tf#L104) | Event arc triggers for different sources. | <code title="object&#40;&#123;&#10; audit_log &#61; optional&#40;map&#40;object&#40;&#123;&#10; method &#61; string&#10; service &#61; string&#10; &#125;&#41;&#41;&#41;&#10; pubsub &#61; optional&#40;map&#40;string&#41;&#41;&#10; service_account_email &#61; optional&#40;string&#41;&#10; service_account_create &#61; optional&#40;bool, false&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>&#123;&#125;</code> |
| [iam](variables.tf#L122) | IAM bindings for Cloud Run service in {ROLE => [MEMBERS]} format. | <code>map&#40;list&#40;string&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [ingress](variables.tf#L128) | Ingress settings. | <code>string</code> | | <code>null</code> |
| [invoker_iam_disabled](variables.tf#L145) | Disables IAM permission check for run.routes.invoke for callers of this service. | <code>bool</code> | | <code>false</code> |
| [labels](variables.tf#L151) | Resource labels. | <code>map&#40;string&#41;</code> | | <code>&#123;&#125;</code> |
| [launch_stage](variables.tf#L157) | The launch stage as defined by Google Cloud Platform Launch Stages. | <code>string</code> | | <code>null</code> |
| [managed_revision](variables.tf#L174) | Whether the Terraform module should control the deployment of revisions. | <code>bool</code> | | <code>true</code> |
| [prefix](variables.tf#L186) | Optional prefix used for resource names. | <code>string</code> | | <code>null</code> |
| [revision](variables.tf#L206) | Revision template configurations. | <code title="object&#40;&#123;&#10; labels &#61; optional&#40;map&#40;string&#41;&#41;&#10; name &#61; optional&#40;string&#41;&#10; gen2_execution_environment &#61; optional&#40;bool&#41;&#10; max_concurrency &#61; optional&#40;number&#41;&#10; max_instance_count &#61; optional&#40;number&#41;&#10; min_instance_count &#61; optional&#40;number&#41;&#10; job &#61; optional&#40;object&#40;&#123;&#10; max_retries &#61; optional&#40;number&#41;&#10; task_count &#61; optional&#40;number&#41;&#10; &#125;&#41;, &#123;&#125;&#41;&#10; vpc_access &#61; optional&#40;object&#40;&#123;&#10; connector &#61; optional&#40;string&#41;&#10; egress &#61; optional&#40;string&#41;&#10; network &#61; optional&#40;string&#41;&#10; subnet &#61; optional&#40;string&#41;&#10; tags &#61; optional&#40;list&#40;string&#41;&#41;&#10; &#125;&#41;, &#123;&#125;&#41;&#10; timeout &#61; optional&#40;string&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>&#123;&#125;</code> |
| [service_account](variables.tf#L245) | Service account email. Unused if service account is auto-created. | <code>string</code> | | <code>null</code> |
| [service_account_create](variables.tf#L251) | Auto-create service account. | <code>bool</code> | | <code>false</code> |
| [tag_bindings](variables.tf#L257) | Tag bindings for this service, in key => tag value id format. | <code>map&#40;string&#41;</code> | | <code>&#123;&#125;</code> |
| [volumes](variables.tf#L264) | Named volumes in containers in name => attributes format. | <code title="map&#40;object&#40;&#123;&#10; secret &#61; optional&#40;object&#40;&#123;&#10; name &#61; string&#10; default_mode &#61; optional&#40;string&#41;&#10; path &#61; optional&#40;string&#41;&#10; version &#61; optional&#40;string&#41;&#10; mode &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10; cloud_sql_instances &#61; optional&#40;list&#40;string&#41;&#41;&#10; empty_dir_size &#61; optional&#40;string&#41;&#10; gcs &#61; optional&#40;object&#40;&#123;&#10; bucket &#61; string&#10; is_read_only &#61; optional&#40;bool&#41;&#10; &#125;&#41;&#41;&#10; nfs &#61; optional&#40;object&#40;&#123;&#10; server &#61; string&#10; path &#61; optional&#40;string&#41;&#10; is_read_only &#61; optional&#40;bool&#41;&#10; &#125;&#41;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [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 | <code>bool</code> | | <code>false</code> |
| [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 | <code title="object&#40;&#123;&#10; iam_emails &#61; list&#40;string&#41;&#10; authoritative_mode &#61; optional&#40;bool, false&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [ingress](variables.tf#L166) | Ingress settings. | <code>string</code> | | <code>null</code> |
| [invoker_iam_disabled](variables.tf#L183) | Disables IAM permission check for run.routes.invoke for callers of this service. | <code>bool</code> | | <code>false</code> |
| [labels](variables.tf#L189) | Resource labels. | <code>map&#40;string&#41;</code> | | <code>&#123;&#125;</code> |
| [launch_stage](variables.tf#L195) | The launch stage as defined by Google Cloud Platform Launch Stages. | <code>string</code> | | <code>null</code> |
| [managed_revision](variables.tf#L216) | Whether the Terraform module should control the deployment of revisions. | <code>bool</code> | | <code>true</code> |
| [prefix](variables.tf#L228) | Optional prefix used for resource names. | <code>string</code> | | <code>null</code> |
| [revision](variables.tf#L248) | Revision template configurations. | <code title="object&#40;&#123;&#10; labels &#61; optional&#40;map&#40;string&#41;&#41;&#10; name &#61; optional&#40;string&#41;&#10; gen2_execution_environment &#61; optional&#40;bool&#41;&#10; max_concurrency &#61; optional&#40;number&#41;&#10; max_instance_count &#61; optional&#40;number&#41;&#10; min_instance_count &#61; optional&#40;number&#41;&#10; job &#61; optional&#40;object&#40;&#123;&#10; max_retries &#61; optional&#40;number&#41;&#10; task_count &#61; optional&#40;number&#41;&#10; &#125;&#41;, &#123;&#125;&#41;&#10; vpc_access &#61; optional&#40;object&#40;&#123;&#10; connector &#61; optional&#40;string&#41;&#10; egress &#61; optional&#40;string&#41;&#10; network &#61; optional&#40;string&#41;&#10; subnet &#61; optional&#40;string&#41;&#10; tags &#61; optional&#40;list&#40;string&#41;&#41;&#10; &#125;&#41;, &#123;&#125;&#41;&#10; timeout &#61; optional&#40;string&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>&#123;&#125;</code> |
| [service_account](variables.tf#L287) | Service account email. Unused if service account is auto-created. | <code>string</code> | | <code>null</code> |
| [service_account_create](variables.tf#L293) | Auto-create service account. | <code>bool</code> | | <code>false</code> |
| [tag_bindings](variables.tf#L299) | Tag bindings for this service, in key => tag value id format. | <code>map&#40;string&#41;</code> | | <code>&#123;&#125;</code> |
| [volumes](variables.tf#L306) | Named volumes in containers in name => attributes format. | <code title="map&#40;object&#40;&#123;&#10; secret &#61; optional&#40;object&#40;&#123;&#10; name &#61; string&#10; default_mode &#61; optional&#40;string&#41;&#10; path &#61; optional&#40;string&#41;&#10; version &#61; optional&#40;string&#41;&#10; mode &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10; cloud_sql_instances &#61; optional&#40;list&#40;string&#41;&#41;&#10; empty_dir_size &#61; optional&#40;string&#41;&#10; gcs &#61; optional&#40;object&#40;&#123;&#10; bucket &#61; string&#10; is_read_only &#61; optional&#40;bool&#41;&#10; &#125;&#41;&#41;&#10; nfs &#61; optional&#40;object&#40;&#123;&#10; server &#61; string&#10; path &#61; optional&#40;string&#41;&#10; is_read_only &#61; optional&#40;bool&#41;&#10; &#125;&#41;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [vpc_connector_create](variables-vpcconnector.tf#L17) | Populate this to create a Serverless VPC Access connector. | <code title="object&#40;&#123;&#10; ip_cidr_range &#61; optional&#40;string&#41;&#10; machine_type &#61; optional&#40;string&#41;&#10; name &#61; optional&#40;string&#41;&#10; network &#61; optional&#40;string&#41;&#10; instances &#61; optional&#40;object&#40;&#123;&#10; max &#61; optional&#40;number&#41;&#10; min &#61; optional&#40;number&#41;&#10; &#125;&#41;, &#123;&#125;&#10; &#41;&#10; throughput &#61; optional&#40;object&#40;&#123;&#10; max &#61; optional&#40;number&#41;&#10; min &#61; optional&#40;number&#41;&#10; &#125;&#41;, &#123;&#125;&#10; &#41;&#10; subnet &#61; optional&#40;object&#40;&#123;&#10; name &#61; optional&#40;string&#41;&#10; project_id &#61; optional&#40;string&#41;&#10; &#125;&#41;, &#123;&#125;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
## Outputs

View File

@@ -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
}

View File

@@ -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" {