From 5fdb212a23f039a7c43d1e9134d1d343c736a46e Mon Sep 17 00:00:00 2001 From: sprokopienko Date: Wed, 7 Oct 2026 10:05:03 -0400 Subject: [PATCH 01/10] chore(jit): Changing how tenant default-entitlement is managed --- google_permissions/pam_entitlement.tf | 4 ++-- google_permissions/variables.tf | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/google_permissions/pam_entitlement.tf b/google_permissions/pam_entitlement.tf index c9076211..791c58e5 100644 --- a/google_permissions/pam_entitlement.tf +++ b/google_permissions/pam_entitlement.tf @@ -87,7 +87,7 @@ locals { # now we handle the additional entitlements - these need to be created for BOTH environments resource "google_privileged_access_manager_entitlement" "default_prod_entitlement" { - count = var.entitlement_enabled && (var.google_prod_project_id != "") ? 1 : 0 + count = var.entitlement_enabled && var.default_entitlement_enabled && (var.google_prod_project_id != "") ? 1 : 0 entitlement_id = local.default_admin_entitlement_name location = "global" max_request_duration = "${local.max_allowed_request_duration}s" @@ -139,7 +139,7 @@ resource "google_privileged_access_manager_entitlement" "default_prod_entitlemen # now we handle the additional entitlements - these need to be created for BOTH environments resource "google_privileged_access_manager_entitlement" "default_nonprod_entitlement" { - count = var.entitlement_enabled && (var.google_nonprod_project_id != "") ? 1 : 0 + count = var.entitlement_enabled && var.default_entitlement_enabled && (var.google_nonprod_project_id != "") ? 1 : 0 entitlement_id = local.default_admin_entitlement_name location = "global" max_request_duration = "${local.max_allowed_request_duration}s" diff --git a/google_permissions/variables.tf b/google_permissions/variables.tf index 27cb0c54..9aef8afd 100644 --- a/google_permissions/variables.tf +++ b/google_permissions/variables.tf @@ -10,6 +10,25 @@ variable "entitlement_enabled" { default = false } +variable "default_entitlement_enabled" { + description = <<-EOT + Whether this module creates the tenant's default admin entitlement + (admin-entitlement-01). + + Set to false once the tenant's default entitlement is created centrally in + global-platform-admin (projects/tf//pam_global.tf). Leaving it true in + both places collides: entitlement IDs are unique per parent and both are + parented at the same project. + + This gate is deliberately separate from entitlement_enabled, which also controls + additional_entitlements, the Cloud Asset feed used for Slack notifications, and + the JITAccessUser bindings. Turning entitlement_enabled off to retire the default + would take all of those with it. See MZCLD-4250. + EOT + type = bool + default = true +} + variable "entitlement_data" { description = "The entitlement data for the project." type = object({ From 99ff4341f9cbefdf568714850df8e9ebc2c2d168 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 30 Oct 2026 02:02:02 +0000 Subject: [PATCH 02/10] chore(docs): google_permissions/README.md --- google_permissions/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/google_permissions/README.md b/google_permissions/README.md index bc6745c2..77801118 100644 --- a/google_permissions/README.md +++ b/google_permissions/README.md @@ -64,6 +64,7 @@ module "permissions" { | [admin\_ids](#input\_admin\_ids) | List of admin IDs to add to the project. | `list(string)` | `[]` | no | | [admin\_only](#input\_admin\_only) | Whether or not to create a project with admin-only role. | `bool` | `false` | no | | [app\_code](#input\_app\_code) | The application code for the permissions. See https://github.com/mozilla-services/inventory/blob/master/application_component_registry.csv. | `string` | `""` | no | +| [default\_entitlement\_enabled](#input\_default\_entitlement\_enabled) | Whether this module creates the tenant's default admin entitlement
(admin-entitlement-01).

Set to false once the tenant's default entitlement is created centrally in
global-platform-admin (projects/tf//pam\_global.tf). Leaving it true in
both places collides: entitlement IDs are unique per parent and both are
parented at the same project.

This gate is deliberately separate from entitlement\_enabled, which also controls
additional\_entitlements, the Cloud Asset feed used for Slack notifications, and
the JITAccessUser bindings. Turning entitlement\_enabled off to retire the default
would take all of those with it. See MZCLD-4250. | `bool` | `true` | no | | [developer\_ids](#input\_developer\_ids) | List of developer IDs to add to the project. | `list(string)` | `[]` | no | | [entitlement\_data](#input\_entitlement\_data) | The entitlement data for the project. |
object({
enabled = bool
additional_roles = list(string)
additional_entitlements = list(object({
name = string
roles = list(string)
principals = list(string)
approval_workflow = optional(object({
principals = list(string)
}))
}))
})
|
{
"additional_entitlements": [],
"additional_roles": [],
"enabled": false
}
| no | | [entitlement\_enabled](#input\_entitlement\_enabled) | Whether or not to enable entitlements. | `bool` | `false` | no | From de34236cacb29fb0ec890f8187666ea9b0a79baf Mon Sep 17 00:00:00 2001 From: sprokopienko Date: Thu, 29 Oct 2026 22:02:59 -0400 Subject: [PATCH 03/10] chore(jit): Changing how tenant default-entitlement is managed --- google_permissions/pam_entitlement.tf | 2 ++ google_permissions/variables.tf | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/google_permissions/pam_entitlement.tf b/google_permissions/pam_entitlement.tf index 791c58e5..3b67be2a 100644 --- a/google_permissions/pam_entitlement.tf +++ b/google_permissions/pam_entitlement.tf @@ -188,6 +188,8 @@ resource "google_privileged_access_manager_entitlement" "default_nonprod_entitle # } } +# Not gated on entitlement_enabled, so tenants can add these without the legacy default +# entitlement. resource "google_privileged_access_manager_entitlement" "additional_entitlements" { for_each = var.entitlement_enabled ? { for entitlement in local.additional_entitlements : entitlement.key => entitlement diff --git a/google_permissions/variables.tf b/google_permissions/variables.tf index 9aef8afd..aa4c122e 100644 --- a/google_permissions/variables.tf +++ b/google_permissions/variables.tf @@ -26,7 +26,7 @@ variable "default_entitlement_enabled" { would take all of those with it. See MZCLD-4250. EOT type = bool - default = true + default = false } variable "entitlement_data" { From 78a8ba2fbc4484b7de9b0c30c33df438ba9ef19e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 30 Oct 2026 02:03:36 +0000 Subject: [PATCH 04/10] chore(docs): google_permissions/README.md --- google_permissions/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/google_permissions/README.md b/google_permissions/README.md index 77801118..34ba4fda 100644 --- a/google_permissions/README.md +++ b/google_permissions/README.md @@ -64,7 +64,7 @@ module "permissions" { | [admin\_ids](#input\_admin\_ids) | List of admin IDs to add to the project. | `list(string)` | `[]` | no | | [admin\_only](#input\_admin\_only) | Whether or not to create a project with admin-only role. | `bool` | `false` | no | | [app\_code](#input\_app\_code) | The application code for the permissions. See https://github.com/mozilla-services/inventory/blob/master/application_component_registry.csv. | `string` | `""` | no | -| [default\_entitlement\_enabled](#input\_default\_entitlement\_enabled) | Whether this module creates the tenant's default admin entitlement
(admin-entitlement-01).

Set to false once the tenant's default entitlement is created centrally in
global-platform-admin (projects/tf//pam\_global.tf). Leaving it true in
both places collides: entitlement IDs are unique per parent and both are
parented at the same project.

This gate is deliberately separate from entitlement\_enabled, which also controls
additional\_entitlements, the Cloud Asset feed used for Slack notifications, and
the JITAccessUser bindings. Turning entitlement\_enabled off to retire the default
would take all of those with it. See MZCLD-4250. | `bool` | `true` | no | +| [default\_entitlement\_enabled](#input\_default\_entitlement\_enabled) | Whether this module creates the tenant's default admin entitlement
(admin-entitlement-01).

Set to false once the tenant's default entitlement is created centrally in
global-platform-admin (projects/tf//pam\_global.tf). Leaving it true in
both places collides: entitlement IDs are unique per parent and both are
parented at the same project.

This gate is deliberately separate from entitlement\_enabled, which also controls
additional\_entitlements, the Cloud Asset feed used for Slack notifications, and
the JITAccessUser bindings. Turning entitlement\_enabled off to retire the default
would take all of those with it. See MZCLD-4250. | `bool` | `false` | no | | [developer\_ids](#input\_developer\_ids) | List of developer IDs to add to the project. | `list(string)` | `[]` | no | | [entitlement\_data](#input\_entitlement\_data) | The entitlement data for the project. |
object({
enabled = bool
additional_roles = list(string)
additional_entitlements = list(object({
name = string
roles = list(string)
principals = list(string)
approval_workflow = optional(object({
principals = list(string)
}))
}))
})
|
{
"additional_entitlements": [],
"additional_roles": [],
"enabled": false
}
| no | | [entitlement\_enabled](#input\_entitlement\_enabled) | Whether or not to enable entitlements. | `bool` | `false` | no | From 7d6897b83b3782956c45a26fa405bade05a61ff2 Mon Sep 17 00:00:00 2001 From: sprokopienko Date: Fri, 30 Oct 2026 12:02:02 -0400 Subject: [PATCH 05/10] chore(jit): Changing how tenant default-entitlement is managed; changing variable name --- google_permissions/pam_entitlement.tf | 4 ++-- google_permissions/variables.tf | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/google_permissions/pam_entitlement.tf b/google_permissions/pam_entitlement.tf index 3b67be2a..fdc02fc0 100644 --- a/google_permissions/pam_entitlement.tf +++ b/google_permissions/pam_entitlement.tf @@ -87,7 +87,7 @@ locals { # now we handle the additional entitlements - these need to be created for BOTH environments resource "google_privileged_access_manager_entitlement" "default_prod_entitlement" { - count = var.entitlement_enabled && var.default_entitlement_enabled && (var.google_prod_project_id != "") ? 1 : 0 + count = var.entitlement_enabled && var.legacy_admin_entitlement_01 && (var.google_prod_project_id != "") ? 1 : 0 entitlement_id = local.default_admin_entitlement_name location = "global" max_request_duration = "${local.max_allowed_request_duration}s" @@ -139,7 +139,7 @@ resource "google_privileged_access_manager_entitlement" "default_prod_entitlemen # now we handle the additional entitlements - these need to be created for BOTH environments resource "google_privileged_access_manager_entitlement" "default_nonprod_entitlement" { - count = var.entitlement_enabled && var.default_entitlement_enabled && (var.google_nonprod_project_id != "") ? 1 : 0 + count = var.entitlement_enabled && var.legacy_admin_entitlement_01 && (var.google_nonprod_project_id != "") ? 1 : 0 entitlement_id = local.default_admin_entitlement_name location = "global" max_request_duration = "${local.max_allowed_request_duration}s" diff --git a/google_permissions/variables.tf b/google_permissions/variables.tf index aa4c122e..830cb9e8 100644 --- a/google_permissions/variables.tf +++ b/google_permissions/variables.tf @@ -10,7 +10,7 @@ variable "entitlement_enabled" { default = false } -variable "default_entitlement_enabled" { +variable "legacy_admin_entitlement_01" { description = <<-EOT Whether this module creates the tenant's default admin entitlement (admin-entitlement-01). From ebb546263363a5e88cdc4979a039c897bc81de61 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 30 Oct 2026 16:02:42 +0000 Subject: [PATCH 06/10] chore(docs): google_permissions/README.md --- google_permissions/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/google_permissions/README.md b/google_permissions/README.md index 34ba4fda..6bf0326e 100644 --- a/google_permissions/README.md +++ b/google_permissions/README.md @@ -64,7 +64,6 @@ module "permissions" { | [admin\_ids](#input\_admin\_ids) | List of admin IDs to add to the project. | `list(string)` | `[]` | no | | [admin\_only](#input\_admin\_only) | Whether or not to create a project with admin-only role. | `bool` | `false` | no | | [app\_code](#input\_app\_code) | The application code for the permissions. See https://github.com/mozilla-services/inventory/blob/master/application_component_registry.csv. | `string` | `""` | no | -| [default\_entitlement\_enabled](#input\_default\_entitlement\_enabled) | Whether this module creates the tenant's default admin entitlement
(admin-entitlement-01).

Set to false once the tenant's default entitlement is created centrally in
global-platform-admin (projects/tf//pam\_global.tf). Leaving it true in
both places collides: entitlement IDs are unique per parent and both are
parented at the same project.

This gate is deliberately separate from entitlement\_enabled, which also controls
additional\_entitlements, the Cloud Asset feed used for Slack notifications, and
the JITAccessUser bindings. Turning entitlement\_enabled off to retire the default
would take all of those with it. See MZCLD-4250. | `bool` | `false` | no | | [developer\_ids](#input\_developer\_ids) | List of developer IDs to add to the project. | `list(string)` | `[]` | no | | [entitlement\_data](#input\_entitlement\_data) | The entitlement data for the project. |
object({
enabled = bool
additional_roles = list(string)
additional_entitlements = list(object({
name = string
roles = list(string)
principals = list(string)
approval_workflow = optional(object({
principals = list(string)
}))
}))
})
|
{
"additional_entitlements": [],
"additional_roles": [],
"enabled": false
}
| no | | [entitlement\_enabled](#input\_entitlement\_enabled) | Whether or not to enable entitlements. | `bool` | `false` | no | @@ -74,6 +73,7 @@ module "permissions" { | [google\_folder\_id](#input\_google\_folder\_id) | The ID of the folder to create the project in. | `string` | n/a | yes | | [google\_nonprod\_project\_id](#input\_google\_nonprod\_project\_id) | The ID of the nonprod project. | `string` | `""` | no | | [google\_prod\_project\_id](#input\_google\_prod\_project\_id) | The ID of the prod project. | `string` | `""` | no | +| [legacy\_admin\_entitlement\_01](#input\_legacy\_admin\_entitlement\_01) | Whether this module creates the tenant's default admin entitlement
(admin-entitlement-01).

Set to false once the tenant's default entitlement is created centrally in
global-platform-admin (projects/tf//pam\_global.tf). Leaving it true in
both places collides: entitlement IDs are unique per parent and both are
parented at the same project.

This gate is deliberately separate from entitlement\_enabled, which also controls
additional\_entitlements, the Cloud Asset feed used for Slack notifications, and
the JITAccessUser bindings. Turning entitlement\_enabled off to retire the default
would take all of those with it. See MZCLD-4250. | `bool` | `false` | no | | [nonprod\_roles](#input\_nonprod\_roles) | List of roles to apply to the nonprod project. | `list(string)` | `[]` | no | | [prod\_roles](#input\_prod\_roles) | List of roles to apply to the prod project. | `list(string)` | `[]` | no | | [viewer\_ids](#input\_viewer\_ids) | List of viewer IDs to add to the project. | `list(string)` | `[]` | no | From c2d43d91d68d29a21c4b9b5374bc23e216c34b34 Mon Sep 17 00:00:00 2001 From: sprokopienko Date: Fri, 30 Oct 2026 12:38:11 -0400 Subject: [PATCH 07/10] chore(jit): Changing how tenant default-entitlement is managed; clarifying inline comment, adding gaurd to prevent legacy entitlement creation --- google_permissions/pam_entitlement.tf | 9 ++++++++- google_permissions/variables.tf | 15 +++++---------- google_permissions/versions.tf | 2 +- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/google_permissions/pam_entitlement.tf b/google_permissions/pam_entitlement.tf index fdc02fc0..00ebdff3 100644 --- a/google_permissions/pam_entitlement.tf +++ b/google_permissions/pam_entitlement.tf @@ -83,7 +83,14 @@ locals { } } - +# legacy_admin_entitlement_01 only keeps an existing admin-entitlement-01; it must never create one. +# This read fails the plan with "... not found" for a tenant that doesn't already have it. +data "google_privileged_access_manager_entitlement" "legacy_admin_entitlement_01_must_exist" { + for_each = var.entitlement_enabled && var.legacy_admin_entitlement_01 ? toset(local.environments) : toset([]) + parent = "projects/${each.value == "prod" ? var.google_prod_project_id : var.google_nonprod_project_id}" + location = "global" + entitlement_id = local.default_admin_entitlement_name +} # now we handle the additional entitlements - these need to be created for BOTH environments resource "google_privileged_access_manager_entitlement" "default_prod_entitlement" { diff --git a/google_permissions/variables.tf b/google_permissions/variables.tf index 830cb9e8..52b2e58f 100644 --- a/google_permissions/variables.tf +++ b/google_permissions/variables.tf @@ -12,18 +12,13 @@ variable "entitlement_enabled" { variable "legacy_admin_entitlement_01" { description = <<-EOT - Whether this module creates the tenant's default admin entitlement + Whether this module keeps the tenant's legacy default admin entitlement (admin-entitlement-01). + Set to true only in stacks that already have the legacy admin-entitlement-01, to keep it. + New tenants should leave it false. - Set to false once the tenant's default entitlement is created centrally in - global-platform-admin (projects/tf//pam_global.tf). Leaving it true in - both places collides: entitlement IDs are unique per parent and both are - parented at the same project. - - This gate is deliberately separate from entitlement_enabled, which also controls - additional_entitlements, the Cloud Asset feed used for Slack notifications, and - the JITAccessUser bindings. Turning entitlement_enabled off to retire the default - would take all of those with it. See MZCLD-4250. + Separate from entitlement_enabled, which also controls additional_entitlements + and the JITAccessUser bindings. EOT type = bool default = false diff --git a/google_permissions/versions.tf b/google_permissions/versions.tf index 37ea1d76..42c60def 100644 --- a/google_permissions/versions.tf +++ b/google_permissions/versions.tf @@ -2,7 +2,7 @@ terraform { required_providers { google = { source = "hashicorp/google" - version = ">= 6.0, < 8.0" + version = ">= 6.5, < 8.0" } google-beta = { source = "hashicorp/google-beta" From eef49024ff3354a848783046920aefbc6790f727 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 30 Oct 2026 16:43:12 +0000 Subject: [PATCH 08/10] chore(docs): google_permissions/README.md --- google_permissions/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/google_permissions/README.md b/google_permissions/README.md index 6bf0326e..458cbc26 100644 --- a/google_permissions/README.md +++ b/google_permissions/README.md @@ -73,7 +73,7 @@ module "permissions" { | [google\_folder\_id](#input\_google\_folder\_id) | The ID of the folder to create the project in. | `string` | n/a | yes | | [google\_nonprod\_project\_id](#input\_google\_nonprod\_project\_id) | The ID of the nonprod project. | `string` | `""` | no | | [google\_prod\_project\_id](#input\_google\_prod\_project\_id) | The ID of the prod project. | `string` | `""` | no | -| [legacy\_admin\_entitlement\_01](#input\_legacy\_admin\_entitlement\_01) | Whether this module creates the tenant's default admin entitlement
(admin-entitlement-01).

Set to false once the tenant's default entitlement is created centrally in
global-platform-admin (projects/tf//pam\_global.tf). Leaving it true in
both places collides: entitlement IDs are unique per parent and both are
parented at the same project.

This gate is deliberately separate from entitlement\_enabled, which also controls
additional\_entitlements, the Cloud Asset feed used for Slack notifications, and
the JITAccessUser bindings. Turning entitlement\_enabled off to retire the default
would take all of those with it. See MZCLD-4250. | `bool` | `false` | no | +| [legacy\_admin\_entitlement\_01](#input\_legacy\_admin\_entitlement\_01) | Whether this module keeps the tenant's legacy default admin entitlement
(admin-entitlement-01).
Set to true only in stacks that already have the legacy admin-entitlement-01, to keep it.
New tenants should leave it false.

Separate from entitlement\_enabled, which also controls additional\_entitlements
and the JITAccessUser bindings. | `bool` | `false` | no | | [nonprod\_roles](#input\_nonprod\_roles) | List of roles to apply to the nonprod project. | `list(string)` | `[]` | no | | [prod\_roles](#input\_prod\_roles) | List of roles to apply to the prod project. | `list(string)` | `[]` | no | | [viewer\_ids](#input\_viewer\_ids) | List of viewer IDs to add to the project. | `list(string)` | `[]` | no | From c89d20d6a9e63a2deb1a70e263643c4b60ac170b Mon Sep 17 00:00:00 2001 From: sprokopienko Date: Fri, 30 Oct 2026 13:23:07 -0400 Subject: [PATCH 09/10] chore(jit): Changing how tenant default-entitlement is managed; clarifying inline comment, adding guard to prevent legacy entitlement creation --- .../examples/entitlement_basic/locals.tf | 1 - .../examples/entitlement_basic/permissions.tf | 3 +-- google_permissions/main.tf | 1 - google_permissions/pam_entitlement.tf | 18 +++++++++--------- google_permissions/variables.tf | 9 --------- 5 files changed, 10 insertions(+), 22 deletions(-) diff --git a/google_permissions/examples/entitlement_basic/locals.tf b/google_permissions/examples/entitlement_basic/locals.tf index ce7592b6..fa952240 100644 --- a/google_permissions/examples/entitlement_basic/locals.tf +++ b/google_permissions/examples/entitlement_basic/locals.tf @@ -6,6 +6,5 @@ locals { tenant_entitlements = data.terraform_remote_state.platform_shared.outputs.tenant_entitlements[local.application] google_prod_project_id = local.tenant_entitlements.prod google_nonprod_project_id = local.tenant_entitlements.nonprod - entitlement_enabled = local.tenant_entitlements.entitlements.enabled entitlement_data = local.tenant_entitlements.entitlements } diff --git a/google_permissions/examples/entitlement_basic/permissions.tf b/google_permissions/examples/entitlement_basic/permissions.tf index e1b4ecef..ff989faf 100644 --- a/google_permissions/examples/entitlement_basic/permissions.tf +++ b/google_permissions/examples/entitlement_basic/permissions.tf @@ -5,8 +5,7 @@ module "permissions" { // the appcode (aka application or tenant name) is used to create the workgroups and entitlements if used app_code = local.application - entitlement_enabled = local.entitlement_enabled - entitlement_data = local.entitlement_data + entitlement_data = local.entitlement_data google_folder_id = local.project.folder.id diff --git a/google_permissions/main.tf b/google_permissions/main.tf index 1b78bc8e..32fa723f 100644 --- a/google_permissions/main.tf +++ b/google_permissions/main.tf @@ -67,7 +67,6 @@ resource "google_project_iam_member" "developers_secretmanager_secretVersionAdde // if admin_only is true OR var.use_entitlements is true, we don't create these permissions at all resource "google_folder_iam_binding" "owner" { - #count = var.admin_only || var.entitlement_enabled == true ? 0 : 1 folder = var.google_folder_id role = "roles/owner" members = module.admins_workgroup.members diff --git a/google_permissions/pam_entitlement.tf b/google_permissions/pam_entitlement.tf index 00ebdff3..0ed09580 100644 --- a/google_permissions/pam_entitlement.tf +++ b/google_permissions/pam_entitlement.tf @@ -86,7 +86,7 @@ locals { # legacy_admin_entitlement_01 only keeps an existing admin-entitlement-01; it must never create one. # This read fails the plan with "... not found" for a tenant that doesn't already have it. data "google_privileged_access_manager_entitlement" "legacy_admin_entitlement_01_must_exist" { - for_each = var.entitlement_enabled && var.legacy_admin_entitlement_01 ? toset(local.environments) : toset([]) + for_each = var.legacy_admin_entitlement_01 ? toset(local.environments) : toset([]) parent = "projects/${each.value == "prod" ? var.google_prod_project_id : var.google_nonprod_project_id}" location = "global" entitlement_id = local.default_admin_entitlement_name @@ -94,7 +94,7 @@ data "google_privileged_access_manager_entitlement" "legacy_admin_entitlement_01 # now we handle the additional entitlements - these need to be created for BOTH environments resource "google_privileged_access_manager_entitlement" "default_prod_entitlement" { - count = var.entitlement_enabled && var.legacy_admin_entitlement_01 && (var.google_prod_project_id != "") ? 1 : 0 + count = var.legacy_admin_entitlement_01 && (var.google_prod_project_id != "") ? 1 : 0 entitlement_id = local.default_admin_entitlement_name location = "global" max_request_duration = "${local.max_allowed_request_duration}s" @@ -146,7 +146,7 @@ resource "google_privileged_access_manager_entitlement" "default_prod_entitlemen # now we handle the additional entitlements - these need to be created for BOTH environments resource "google_privileged_access_manager_entitlement" "default_nonprod_entitlement" { - count = var.entitlement_enabled && var.legacy_admin_entitlement_01 && (var.google_nonprod_project_id != "") ? 1 : 0 + count = var.legacy_admin_entitlement_01 && (var.google_nonprod_project_id != "") ? 1 : 0 entitlement_id = local.default_admin_entitlement_name location = "global" max_request_duration = "${local.max_allowed_request_duration}s" @@ -198,9 +198,9 @@ resource "google_privileged_access_manager_entitlement" "default_nonprod_entitle # Not gated on entitlement_enabled, so tenants can add these without the legacy default # entitlement. resource "google_privileged_access_manager_entitlement" "additional_entitlements" { - for_each = var.entitlement_enabled ? { + for_each = { for entitlement in local.additional_entitlements : entitlement.key => entitlement - } : {} + } entitlement_id = each.value.entitlement.name location = "global" max_request_duration = "${local.max_allowed_request_duration}s" @@ -250,7 +250,7 @@ resource "google_privileged_access_manager_entitlement" "additional_entitlements // ref: https://stackoverflow.com/questions/63785247/gcp-managed-service-account-is-not-created-for-cloud-asset-api // resource "google_project_service_identity" "cloud_asset_sa" { - for_each = var.entitlement_enabled && var.entitlement_slack_topic != "" ? toset(local.environments) : [] + for_each = var.entitlement_slack_topic != "" ? toset(local.environments) : [] provider = google-beta project = each.value == "nonprod" ? var.google_nonprod_project_id : var.google_prod_project_id service = "cloudasset.googleapis.com" @@ -258,7 +258,7 @@ resource "google_project_service_identity" "cloud_asset_sa" { // Create a feed that sends notifications about network resource updates. resource "google_cloud_asset_project_feed" "project_feed" { - for_each = var.entitlement_enabled && var.entitlement_slack_topic != "" ? toset(local.environments) : [] + for_each = var.entitlement_slack_topic != "" ? toset(local.environments) : [] project = each.value == "nonprod" ? var.google_nonprod_project_id : var.google_prod_project_id feed_id = var.feed_id content_type = "RESOURCE" @@ -276,14 +276,14 @@ resource "google_cloud_asset_project_feed" "project_feed" { # custom role for JIT access - created at the org level resource "google_project_iam_member" "developers_jitaccess_nonprod" { - for_each = var.entitlement_enabled && var.google_nonprod_project_id != "" ? toset(module.developers_workgroup.members) : toset([]) + for_each = var.legacy_admin_entitlement_01 && var.google_nonprod_project_id != "" ? toset(module.developers_workgroup.members) : toset([]) project = var.google_nonprod_project_id role = local.jit_access_user_role member = each.value } resource "google_project_iam_member" "developers_jitaccess_prod" { - for_each = var.entitlement_enabled && var.google_prod_project_id != "" ? toset(module.developers_workgroup.members) : toset([]) + for_each = var.legacy_admin_entitlement_01 && var.google_prod_project_id != "" ? toset(module.developers_workgroup.members) : toset([]) project = var.google_prod_project_id role = local.jit_access_user_role member = each.value diff --git a/google_permissions/variables.tf b/google_permissions/variables.tf index 52b2e58f..41ba5da3 100644 --- a/google_permissions/variables.tf +++ b/google_permissions/variables.tf @@ -4,21 +4,12 @@ variable "app_code" { default = "" } -variable "entitlement_enabled" { - description = "Whether or not to enable entitlements." - type = bool - default = false -} - variable "legacy_admin_entitlement_01" { description = <<-EOT Whether this module keeps the tenant's legacy default admin entitlement (admin-entitlement-01). Set to true only in stacks that already have the legacy admin-entitlement-01, to keep it. New tenants should leave it false. - - Separate from entitlement_enabled, which also controls additional_entitlements - and the JITAccessUser bindings. EOT type = bool default = false From 391bf9213e095a2c64a7639059162e46921d731b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 30 Oct 2026 17:23:46 +0000 Subject: [PATCH 10/10] chore(docs): google_permissions/README.md --- google_permissions/README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/google_permissions/README.md b/google_permissions/README.md index 458cbc26..4dbf0a14 100644 --- a/google_permissions/README.md +++ b/google_permissions/README.md @@ -66,14 +66,13 @@ module "permissions" { | [app\_code](#input\_app\_code) | The application code for the permissions. See https://github.com/mozilla-services/inventory/blob/master/application_component_registry.csv. | `string` | `""` | no | | [developer\_ids](#input\_developer\_ids) | List of developer IDs to add to the project. | `list(string)` | `[]` | no | | [entitlement\_data](#input\_entitlement\_data) | The entitlement data for the project. |
object({
enabled = bool
additional_roles = list(string)
additional_entitlements = list(object({
name = string
roles = list(string)
principals = list(string)
approval_workflow = optional(object({
principals = list(string)
}))
}))
})
|
{
"additional_entitlements": [],
"additional_roles": [],
"enabled": false
}
| no | -| [entitlement\_enabled](#input\_entitlement\_enabled) | Whether or not to enable entitlements. | `bool` | `false` | no | | [entitlement\_slack\_topic](#input\_entitlement\_slack\_topic) | The name of the pubsub topic to use for slack notifications. | `string` | `""` | no | | [feed\_id](#input\_feed\_id) | The ID of the feed to be created | `string` | `"grant_feed"` | no | | [folder\_roles](#input\_folder\_roles) | List of roles to apply at the folder level. Also used as the roles in the entitlement. | `list(string)` | `[]` | no | | [google\_folder\_id](#input\_google\_folder\_id) | The ID of the folder to create the project in. | `string` | n/a | yes | | [google\_nonprod\_project\_id](#input\_google\_nonprod\_project\_id) | The ID of the nonprod project. | `string` | `""` | no | | [google\_prod\_project\_id](#input\_google\_prod\_project\_id) | The ID of the prod project. | `string` | `""` | no | -| [legacy\_admin\_entitlement\_01](#input\_legacy\_admin\_entitlement\_01) | Whether this module keeps the tenant's legacy default admin entitlement
(admin-entitlement-01).
Set to true only in stacks that already have the legacy admin-entitlement-01, to keep it.
New tenants should leave it false.

Separate from entitlement\_enabled, which also controls additional\_entitlements
and the JITAccessUser bindings. | `bool` | `false` | no | +| [legacy\_admin\_entitlement\_01](#input\_legacy\_admin\_entitlement\_01) | Whether this module keeps the tenant's legacy default admin entitlement
(admin-entitlement-01).
Set to true only in stacks that already have the legacy admin-entitlement-01, to keep it.
New tenants should leave it false. | `bool` | `false` | no | | [nonprod\_roles](#input\_nonprod\_roles) | List of roles to apply to the nonprod project. | `list(string)` | `[]` | no | | [prod\_roles](#input\_prod\_roles) | List of roles to apply to the prod project. | `list(string)` | `[]` | no | | [viewer\_ids](#input\_viewer\_ids) | List of viewer IDs to add to the project. | `list(string)` | `[]` | no |