Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions iac/provider-gcp/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,11 @@ module "cluster" {
# ClickHouse stateful data disk
clickhouse_stateful_disk_type = var.clickhouse_stateful_disk_type
clickhouse_stateful_disk_size_gb = var.clickhouse_stateful_disk_size_gb

# Nomad IAP
nomad_iap_oauth2_client_id = var.nomad_iap_oauth2_client_id
nomad_iap_oauth2_client_secret = var.nomad_iap_oauth2_client_secret
nomad_iap_members = var.nomad_iap_members
}

module "nomad" {
Expand Down
4 changes: 4 additions & 0 deletions iac/provider-gcp/nomad-cluster/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,10 @@ module "network" {

cluster_tag_name = var.cluster_tag_name

nomad_iap_oauth2_client_id = var.nomad_iap_oauth2_client_id
nomad_iap_oauth2_client_secret = var.nomad_iap_oauth2_client_secret
nomad_iap_members = var.nomad_iap_members

labels = var.labels
prefix = var.prefix
}
Expand Down
23 changes: 23 additions & 0 deletions iac/provider-gcp/nomad-cluster/network/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,10 @@ locals {
port = var.nomad_port
}
groups = [{ group = var.server_instance_group }]
iap = var.nomad_iap_oauth2_client_id != null ? {
oauth2_client_id = var.nomad_iap_oauth2_client_id
oauth2_client_secret = var.nomad_iap_oauth2_client_secret
} : null
Comment on lines +94 to +97

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The IAP configuration for the Nomad backend only checks for the presence of the OAuth2 client ID. If a client ID is provided but the client secret is missing, the backend service resource will attempt to enable IAP with a null secret, which will cause a failure during the Terraform apply phase. The condition should ensure both the client ID and secret are present before enabling the IAP block.

      iap = (var.nomad_iap_oauth2_client_id != null && var.nomad_iap_oauth2_client_secret != null) ? {
        oauth2_client_id     = var.nomad_iap_oauth2_client_id
        oauth2_client_secret = var.nomad_iap_oauth2_client_secret
      } : null

Comment thread
cursor[bot] marked this conversation as resolved.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sensitive backend map breaks plans

High Severity

Including nomad_iap_oauth2_client_secret in the iap block within local.backends makes the collection sensitive. Terraform's for_each cannot process sensitive values when creating google_compute_backend_service resources, causing plan failures when Nomad IAP is enabled.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 6c4296f. Configure here.

}
}
health_checked_backends = { for backend_index, backend_value in local.backends : backend_index => backend_value }
Expand Down Expand Up @@ -369,11 +373,30 @@ resource "google_compute_backend_service" "default" {
}
}

dynamic "iap" {
for_each = lookup(each.value, "iap", null) != null ? [each.value.iap] : []
content {
enabled = true
oauth2_client_id = iap.value["oauth2_client_id"]
oauth2_client_secret = iap.value["oauth2_client_secret"]
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IAP blocks Nomad API clients

High Severity

IAP is enabled on the same nomad.${domain} endpoint used by the Terraform nomad provider, but that provider is only configured with the Nomad ACL token. Once active, Terraform Nomad job management hits the IAP login barrier and fails.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 1db68f2. Configure here.

}

depends_on = [
google_compute_health_check.default
]
}

# IAP IAM binding for Nomad backend
resource "google_iap_web_backend_service_iam_binding" "nomad_iap" {
count = var.nomad_iap_oauth2_client_id != null && length(var.nomad_iap_members) > 0 ? 1 : 0

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The IAM binding for IAP is created based on the presence of the client ID and a non-empty members list. However, if the client ID is provided but the client secret is missing, the backend service will fail to enable IAP (or fail to apply), leading to an inconsistent state where an IAM binding exists for a feature that is not correctly configured on the target resource. This condition should be updated to match the logic used for enabling IAP on the backend service.

  count = var.nomad_iap_oauth2_client_id != null && var.nomad_iap_oauth2_client_secret != null && length(var.nomad_iap_members) > 0 ? 1 : 0


project = var.gcp_project_id
web_backend_service = google_compute_backend_service.default["nomad"].name
role = "roles/iap.httpsResourceAccessor"
members = var.nomad_iap_members

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IAP can enable without access

Medium Severity

IAP turns on when nomad_iap_oauth2_client_id is set, but the access binding is skipped when nomad_iap_members is empty. That can apply successfully while leaving the Nomad UI with no Terraform-managed IAP users.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 1db68f2. Configure here.

}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IAP API is never enabled

Medium Severity

google_iap_web_backend_service_iam_binding uses the IAP API, but the GCP init module never enables iap.googleapis.com. Enabling Nomad IAP can fail at apply time in fresh projects.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 1db68f2. Configure here.


resource "google_compute_health_check" "default" {
for_each = local.health_checked_backends
name = "${var.prefix}hc-${each.key}"
Expand Down
19 changes: 19 additions & 0 deletions iac/provider-gcp/nomad-cluster/network/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -113,3 +113,22 @@ variable "additional_api_paths_handled_by_ingress" {
variable "ingress_timeout_seconds" {
type = number
}

variable "nomad_iap_oauth2_client_id" {
description = "OAuth2 client ID for IAP on Nomad backend. If set, IAP will be enabled."
type = string
default = null
}

variable "nomad_iap_oauth2_client_secret" {
description = "OAuth2 client secret for IAP on Nomad backend."
type = string
default = null
sensitive = true
}

variable "nomad_iap_members" {
description = "List of members who can access the Nomad UI through IAP (e.g., ['user:admin@example.com', 'group:devs@example.com'])"
type = list(string)
default = []
}
19 changes: 19 additions & 0 deletions iac/provider-gcp/nomad-cluster/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -392,3 +392,22 @@ variable "additional_api_paths_handled_by_ingress" {
variable "ingress_timeout_seconds" {
type = number
}

variable "nomad_iap_oauth2_client_id" {
description = "OAuth2 client ID for IAP on Nomad backend. If set, IAP will be enabled."
type = string
default = null
}

variable "nomad_iap_oauth2_client_secret" {
description = "OAuth2 client secret for IAP on Nomad backend."
type = string
default = null
sensitive = true
}

variable "nomad_iap_members" {
description = "List of members who can access the Nomad UI through IAP (e.g., ['user:admin@example.com', 'group:devs@example.com'])"
type = list(string)
default = []
}
19 changes: 19 additions & 0 deletions iac/provider-gcp/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -783,3 +783,22 @@ variable "ingress_timeout_seconds" {
type = number
default = 80
}

variable "nomad_iap_oauth2_client_id" {
description = "OAuth2 client ID for IAP on Nomad backend. If set, IAP will be enabled."
type = string
default = null
}

variable "nomad_iap_oauth2_client_secret" {
description = "OAuth2 client secret for IAP on Nomad backend."
type = string
default = null
sensitive = true
}

variable "nomad_iap_members" {
description = "List of members who can access the Nomad UI through IAP (e.g., ['user:admin@example.com', 'group:devs@example.com'])"
type = list(string)
default = []
}
Loading