Introduce iam_by_principals_conditional (#3649)

* Introduce iam_by_principals_conditional

* Add iam_by_principals_conditional to project factory

* Update IAM ADR

* Update project factory readme

* Sync FAST schemas

* Update organization schema

* Add resman tests for iam_by_principals_conditional

* Update PF project-defaults.tf

* Update copyright
This commit is contained in:
Julio Castillo
2026-01-14 12:16:07 +01:00
committed by GitHub
parent 649cab0020
commit cff8a25c59
48 changed files with 1358 additions and 75 deletions

File diff suppressed because one or more lines are too long

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2025 Google LLC
* Copyright 2026 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -80,13 +80,14 @@ module "folder-1-iam" {
# we do anything that can refer to IAM and custom roles in this call
pam_entitlements = try(each.value.factories_config.pam_entitlements, null)
}
folder_create = false
autokey_config = lookup(each.value, "autokey_config", null)
iam = lookup(each.value, "iam", {})
iam_bindings = lookup(each.value, "iam_bindings", {})
iam_bindings_additive = lookup(each.value, "iam_bindings_additive", {})
iam_by_principals = lookup(each.value, "iam_by_principals", {})
logging_data_access = lookup(each.value, "data_access_logs", {})
folder_create = false
autokey_config = lookup(each.value, "autokey_config", null)
iam = lookup(each.value, "iam", {})
iam_bindings = lookup(each.value, "iam_bindings", {})
iam_bindings_additive = lookup(each.value, "iam_bindings_additive", {})
iam_by_principals = lookup(each.value, "iam_by_principals", {})
iam_by_principals_conditional = lookup(each.value, "iam_by_principals_conditional", {})
logging_data_access = lookup(each.value, "data_access_logs", {})
context = merge(local.ctx, {
iam_principals = local.ctx_iam_principals
project_ids = local.ctx_project_ids
@@ -129,13 +130,14 @@ module "folder-2-iam" {
# we do anything that can refer to IAM and custom roles in this call
pam_entitlements = try(each.value.factories_config.pam_entitlements, null)
}
folder_create = false
autokey_config = lookup(each.value, "autokey_config", null)
iam = lookup(each.value, "iam", {})
iam_bindings = lookup(each.value, "iam_bindings", {})
iam_bindings_additive = lookup(each.value, "iam_bindings_additive", {})
iam_by_principals = lookup(each.value, "iam_by_principals", {})
logging_data_access = lookup(each.value, "data_access_logs", {})
folder_create = false
autokey_config = lookup(each.value, "autokey_config", null)
iam = lookup(each.value, "iam", {})
iam_bindings = lookup(each.value, "iam_bindings", {})
iam_bindings_additive = lookup(each.value, "iam_bindings_additive", {})
iam_by_principals = lookup(each.value, "iam_by_principals", {})
iam_by_principals_conditional = lookup(each.value, "iam_by_principals_conditional", {})
logging_data_access = lookup(each.value, "data_access_logs", {})
context = merge(local.ctx, {
folder_ids = merge(local.ctx.folder_ids, {
for k, v in module.folder-1 : k => v.id
@@ -181,13 +183,14 @@ module "folder-3-iam" {
# we do anything that can refer to IAM and custom roles in this call
pam_entitlements = try(each.value.factories_config.pam_entitlements, null)
}
folder_create = false
autokey_config = lookup(each.value, "autokey_config", null)
iam = lookup(each.value, "iam", {})
iam_bindings = lookup(each.value, "iam_bindings", {})
iam_bindings_additive = lookup(each.value, "iam_bindings_additive", {})
iam_by_principals = lookup(each.value, "iam_by_principals", {})
logging_data_access = lookup(each.value, "data_access_logs", {})
folder_create = false
autokey_config = lookup(each.value, "autokey_config", null)
iam = lookup(each.value, "iam", {})
iam_bindings = lookup(each.value, "iam_bindings", {})
iam_bindings_additive = lookup(each.value, "iam_bindings_additive", {})
iam_by_principals = lookup(each.value, "iam_by_principals", {})
iam_by_principals_conditional = lookup(each.value, "iam_by_principals_conditional", {})
logging_data_access = lookup(each.value, "data_access_logs", {})
context = merge(local.ctx, {
folder_ids = merge(local.ctx.folder_ids, {
for k, v in module.folder-2 : k => v.id
@@ -233,13 +236,14 @@ module "folder-4-iam" {
# we do anything that can refer to IAM and custom roles in this call
pam_entitlements = try(each.value.factories_config.pam_entitlements, null)
}
folder_create = false
autokey_config = lookup(each.value, "autokey_config", null)
iam = lookup(each.value, "iam", {})
iam_bindings = lookup(each.value, "iam_bindings", {})
iam_bindings_additive = lookup(each.value, "iam_bindings_additive", {})
iam_by_principals = lookup(each.value, "iam_by_principals", {})
logging_data_access = lookup(each.value, "data_access_logs", {})
folder_create = false
autokey_config = lookup(each.value, "autokey_config", null)
iam = lookup(each.value, "iam", {})
iam_bindings = lookup(each.value, "iam_bindings", {})
iam_bindings_additive = lookup(each.value, "iam_bindings_additive", {})
iam_by_principals = lookup(each.value, "iam_by_principals", {})
iam_by_principals_conditional = lookup(each.value, "iam_by_principals_conditional", {})
logging_data_access = lookup(each.value, "data_access_logs", {})
context = merge(local.ctx, {
folder_ids = merge(local.ctx.folder_ids, {
for k, v in module.folder-3 : k => v.id

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2025 Google LLC
* Copyright 2026 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -49,12 +49,13 @@ locals {
try(v.contacts, null),
local.data_defaults.defaults.contacts
)
factories_config = try(v.factories_config, {})
iam = try(v.iam, {}) # type: map(list(string))
iam_bindings = try(v.iam_bindings, {}) # type: map(object({...}))
iam_bindings_additive = try(v.iam_bindings_additive, {}) # type: map(object({...}))
iam_by_principals_additive = try(v.iam_by_principals_additive, {}) # type: map(list(string))
iam_by_principals = try(v.iam_by_principals, {}) # map(list(string))
factories_config = try(v.factories_config, {})
iam = try(v.iam, {}) # type: map(list(string))
iam_bindings = try(v.iam_bindings, {}) # type: map(object({...}))
iam_bindings_additive = try(v.iam_bindings_additive, {}) # type: map(object({...}))
iam_by_principals_additive = try(v.iam_by_principals_additive, {}) # type: map(list(string))
iam_by_principals = try(v.iam_by_principals, {}) # map(list(string))
iam_by_principals_conditional = try(v.iam_by_principals_conditional, {}) # map(object({...}))
kms = {
autokeys = try(v.kms.autokeys, {})
keyrings = try(v.kms.keyrings, {})

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2025 Google LLC
* Copyright 2026 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -166,13 +166,14 @@ module "projects-iam" {
# we do anything that can refer to IAM and custom roles in this call
pam_entitlements = try(each.value.factories_config.pam_entitlements, null)
}
iam = lookup(each.value, "iam", {})
iam_bindings = lookup(each.value, "iam_bindings", {})
iam_bindings_additive = lookup(each.value, "iam_bindings_additive", {})
iam_by_principals = lookup(each.value, "iam_by_principals", {})
iam_by_principals_additive = lookup(each.value, "iam_by_principals_additive", {})
logging_data_access = lookup(each.value, "logging_data_access", {})
pam_entitlements = try(each.value.pam_entitlements, {})
iam = lookup(each.value, "iam", {})
iam_bindings = lookup(each.value, "iam_bindings", {})
iam_bindings_additive = lookup(each.value, "iam_bindings_additive", {})
iam_by_principals = lookup(each.value, "iam_by_principals", {})
iam_by_principals_conditional = lookup(each.value, "iam_by_principals_conditional", {})
iam_by_principals_additive = lookup(each.value, "iam_by_principals_additive", {})
logging_data_access = lookup(each.value, "logging_data_access", {})
pam_entitlements = try(each.value.pam_entitlements, {})
service_agents_config = {
create_primary_agents = false
grant_default_roles = false

View File

@@ -179,6 +179,9 @@
"iam_by_principals": {
"$ref": "#/$defs/iam_by_principals"
},
"iam_by_principals_conditional": {
"$ref": "#/$defs/iam_by_principals_conditional"
},
"name": {
"type": "string"
},
@@ -453,6 +456,48 @@
}
}
},
"iam_by_principals_conditional": {
"type": "object",
"additionalProperties": false,
"patternProperties": {
"^(?:domain:|group:|serviceAccount:|user:|principal:|principalSet:|\\$iam_principals:)": {
"type": "object",
"additionalProperties": false,
"required": [
"condition",
"roles"
],
"properties": {
"condition": {
"type": "object",
"additionalProperties": false,
"required": [
"expression",
"title"
],
"properties": {
"expression": {
"type": "string"
},
"title": {
"type": "string"
},
"description": {
"type": "string"
}
}
},
"roles": {
"type": "array",
"items": {
"type": "string",
"pattern": "^(?:roles/|\\$custom_roles:)"
}
}
}
}
}
},
"iam_billing_roles": {
"type": "object",
"additionalProperties": false,

View File

@@ -62,6 +62,7 @@
- **iam_bindings**: *reference([iam_bindings](#refs-iam_bindings))*
- **iam_bindings_additive**: *reference([iam_bindings_additive](#refs-iam_bindings_additive))*
- **iam_by_principals**: *reference([iam_by_principals](#refs-iam_by_principals))*
- **iam_by_principals_conditional**: *reference([iam_by_principals_conditional](#refs-iam_by_principals_conditional))*
- **name**: *string*
- **org_policies**: *object*
<br>*additional properties: false*
@@ -157,6 +158,18 @@
- **`^(?:domain:|group:|serviceAccount:|user:|principal:|principalSet:|\$iam_principals:)`**: *array*
- items: *string*
<br>*pattern: ^(?:roles/|\$custom_roles:)*
- **iam_by_principals_conditional**<a name="refs-iam_by_principals_conditional"></a>: *object*
<br>*additional properties: false*
- **`^(?:domain:|group:|serviceAccount:|user:|principal:|principalSet:|\$iam_principals:)`**: *object*
<br>*additional properties: false*
- ⁺**condition**: *object*
<br>*additional properties: false*
- ⁺**expression**: *string*
- ⁺**title**: *string*
- **description**: *string*
- ⁺**roles**: *array*
- items: *string*
<br>*pattern: ^(?:roles/|\$custom_roles:)*
- **iam_billing_roles**<a name="refs-iam_billing_roles"></a>: *object*
<br>*additional properties: false*
- **`^[a-z0-9-]+$`**: *array*

View File

@@ -210,6 +210,9 @@
"iam_by_principals": {
"$ref": "#/$defs/iam_by_principals"
},
"iam_by_principals_conditional": {
"$ref": "#/$defs/iam_by_principals_conditional"
},
"iam_by_principals_additive": {
"$ref": "#/$defs/iam_by_principals"
},
@@ -1204,6 +1207,48 @@
}
}
},
"iam_by_principals_conditional": {
"type": "object",
"additionalProperties": false,
"patternProperties": {
"^(?:domain:|group:|serviceAccount:|user:|principal:|principalSet:|\\$iam_principals:[a-z0-9_-]+)": {
"type": "object",
"additionalProperties": false,
"required": [
"condition",
"roles"
],
"properties": {
"condition": {
"type": "object",
"additionalProperties": false,
"required": [
"expression",
"title"
],
"properties": {
"expression": {
"type": "string"
},
"title": {
"type": "string"
},
"description": {
"type": "string"
}
}
},
"roles": {
"type": "array",
"items": {
"type": "string",
"pattern": "^(?:roles/|\\$custom_roles:)"
}
}
}
}
}
},
"iam_billing_roles": {
"type": "object",
"additionalProperties": false,

View File

@@ -71,6 +71,7 @@
- **iam_bindings**: *reference([iam_bindings](#refs-iam_bindings))*
- **iam_bindings_additive**: *reference([iam_bindings_additive](#refs-iam_bindings_additive))*
- **iam_by_principals**: *reference([iam_by_principals](#refs-iam_by_principals))*
- **iam_by_principals_conditional**: *reference([iam_by_principals_conditional](#refs-iam_by_principals_conditional))*
- **iam_by_principals_additive**: *reference([iam_by_principals](#refs-iam_by_principals))*
- **kms**: *object*
<br>*additional properties: false*
@@ -342,6 +343,18 @@
- **`^(?:domain:|group:|serviceAccount:|user:|principal:|principalSet:|\$iam_principals:[a-z0-9_-]+)`**: *array*
- items: *string*
<br>*pattern: ^(?:roles/|\$custom_roles:)*
- **iam_by_principals_conditional**<a name="refs-iam_by_principals_conditional"></a>: *object*
<br>*additional properties: false*
- **`^(?:domain:|group:|serviceAccount:|user:|principal:|principalSet:|\$iam_principals:[a-z0-9_-]+)`**: *object*
<br>*additional properties: false*
- ⁺**condition**: *object*
<br>*additional properties: false*
- ⁺**expression**: *string*
- ⁺**title**: *string*
- **description**: *string*
- ⁺**roles**: *array*
- items: *string*
<br>*pattern: ^(?:roles/|\$custom_roles:)*
- **iam_billing_roles**<a name="refs-iam_billing_roles"></a>: *object*
<br>*additional properties: false*
- **`^[a-z0-9-]+$`**: *array*

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2025 Google LLC
* Copyright 2026 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -40,6 +40,14 @@ variable "folders" {
}))
})), {})
iam_by_principals = optional(map(list(string)), {})
iam_by_principals_conditional = optional(map(object({
roles = list(string)
condition = object({
expression = string
title = string
description = optional(string)
})
})), {})
pam_entitlements = optional(map(object({
max_request_duration = string
eligible_users = list(string)

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2025 Google LLC
* Copyright 2026 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -226,6 +226,14 @@ variable "projects" {
}))
})), {})
iam_by_principals = optional(map(list(string)), {})
iam_by_principals_conditional = optional(map(object({
roles = list(string)
condition = object({
expression = string
title = string
description = optional(string)
})
})), {})
kms = optional(object({
autokeys = optional(map(object({
location = string