Add IAM deny policies support (#3970)

* Added IAM denial policies

* Moved default to empty, removed trys, added condition vars to expression

* remove redundant null checks

* reduce line length

* boilerplate and principal context expansion

* update readmes

* add explicit validation against null values

* add context tests

* Add missing license headers to examples

---------

Co-authored-by: Julio Castillo <jccb@google.com>
This commit is contained in:
kovagoadam
2026-05-21 02:38:06 +00:00
committed by GitHub
parent 36ca3c33a5
commit 1907c38e22
41 changed files with 1829 additions and 10 deletions

View File

@@ -104,6 +104,7 @@ module "folder-1-iam" {
iam_by_principals = lookup(each.value, "iam_by_principals", {})
iam_by_principals_additive = lookup(each.value, "iam_by_principals_additive", {})
iam_by_principals_conditional = lookup(each.value, "iam_by_principals_conditional", {})
iam_deny_policies = lookup(each.value, "iam_deny_policies", {})
logging_data_access = lookup(each.value, "data_access_logs", {})
logging_sinks = try(each.value.logging.sinks, {})
tag_bindings = lookup(each.value, "tag_bindings", {})
@@ -181,6 +182,7 @@ module "folder-2-iam" {
iam_by_principals = lookup(each.value, "iam_by_principals", {})
iam_by_principals_additive = lookup(each.value, "iam_by_principals_additive", {})
iam_by_principals_conditional = lookup(each.value, "iam_by_principals_conditional", {})
iam_deny_policies = lookup(each.value, "iam_deny_policies", {})
logging_data_access = lookup(each.value, "data_access_logs", {})
logging_sinks = try(each.value.logging.sinks, {})
tag_bindings = lookup(each.value, "tag_bindings", {})
@@ -261,6 +263,7 @@ module "folder-3-iam" {
iam_by_principals = lookup(each.value, "iam_by_principals", {})
iam_by_principals_additive = lookup(each.value, "iam_by_principals_additive", {})
iam_by_principals_conditional = lookup(each.value, "iam_by_principals_conditional", {})
iam_deny_policies = lookup(each.value, "iam_deny_policies", {})
logging_data_access = lookup(each.value, "data_access_logs", {})
logging_sinks = try(each.value.logging.sinks, {})
tag_bindings = lookup(each.value, "tag_bindings", {})
@@ -344,6 +347,7 @@ module "folder-4-iam" {
logging_data_access = lookup(each.value, "data_access_logs", {})
logging_sinks = try(each.value.logging.sinks, {})
tag_bindings = lookup(each.value, "tag_bindings", {})
iam_deny_policies = lookup(each.value, "iam_deny_policies", {})
context = merge(local.ctx, {
folder_ids = merge(local.ctx.folder_ids, {
for k, v in module.folder-3 : k => v.id

View File

@@ -260,7 +260,8 @@ module "projects-iam" {
tags_config = {
force_context_ids = true
}
universe = each.value.universe
iam_deny_policies = lookup(each.value, "iam_deny_policies", {})
universe = each.value.universe
# we use explicit depends_on as this allows us passing name and prefix
depends_on = [
module.projects

View File

@@ -357,6 +357,85 @@
"iam_by_principals_conditional": {
"$ref": "#/$defs/iam_by_principals_conditional"
},
"iam_deny_policies": {
"type": "object",
"additionalProperties": false,
"patternProperties": {
"^[a-z0-9-]+$": {
"type": "object",
"additionalProperties": false,
"required": [
"rules"
],
"properties": {
"display_name": {
"type": "string"
},
"rules": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": false,
"required": [
"denied_permissions",
"denied_principals"
],
"properties": {
"description": {
"type": "string"
},
"denied_permissions": {
"type": "array",
"items": {
"type": "string"
}
},
"denied_principals": {
"type": "array",
"items": {
"type": "string"
}
},
"denial_condition": {
"type": "object",
"additionalProperties": false,
"required": [
"expression"
],
"properties": {
"expression": {
"type": "string"
},
"title": {
"type": "string"
},
"description": {
"type": "string"
},
"location": {
"type": "string"
}
}
},
"exception_permissions": {
"type": "array",
"items": {
"type": "string"
}
},
"exception_principals": {
"type": "array",
"items": {
"type": "string"
}
}
}
}
}
}
}
}
},
"name": {
"type": "string"
},

View File

@@ -112,6 +112,29 @@
- **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_deny_policies**: *object*
<br>*additional properties: false*
- **`^[a-z0-9-]+$`**: *object*
<br>*additional properties: false*
- **display_name**: *string*
- ⁺**rules**: *array*
- items: *object*
<br>*additional properties: false*
- **description**: *string*
- ⁺**denied_permissions**: *array*
- items: *string*
- ⁺**denied_principals**: *array*
- items: *string*
- **denial_condition**: *object*
<br>*additional properties: false*
- ⁺**expression**: *string*
- **title**: *string*
- **description**: *string*
- **location**: *string*
- **exception_permissions**: *array*
- items: *string*
- **exception_principals**: *array*
- items: *string*
- **name**: *string*
- **org_policies**: *object*
<br>*additional properties: false*

View File

@@ -344,6 +344,85 @@
"iam_by_principals_additive": {
"$ref": "#/$defs/iam_by_principals"
},
"iam_deny_policies": {
"type": "object",
"additionalProperties": false,
"patternProperties": {
"^[a-z0-9-]+$": {
"type": "object",
"additionalProperties": false,
"required": [
"rules"
],
"properties": {
"display_name": {
"type": "string"
},
"rules": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": false,
"required": [
"denied_permissions",
"denied_principals"
],
"properties": {
"description": {
"type": "string"
},
"denied_permissions": {
"type": "array",
"items": {
"type": "string"
}
},
"denied_principals": {
"type": "array",
"items": {
"type": "string"
}
},
"denial_condition": {
"type": "object",
"additionalProperties": false,
"required": [
"expression"
],
"properties": {
"expression": {
"type": "string"
},
"title": {
"type": "string"
},
"description": {
"type": "string"
},
"location": {
"type": "string"
}
}
},
"exception_permissions": {
"type": "array",
"items": {
"type": "string"
}
},
"exception_principals": {
"type": "array",
"items": {
"type": "string"
}
}
}
}
}
}
}
}
},
"kms": {
"type": "object",
"additionalProperties": false,

View File

@@ -110,6 +110,29 @@
- **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))*
- **iam_deny_policies**: *object*
<br>*additional properties: false*
- **`^[a-z0-9-]+$`**: *object*
<br>*additional properties: false*
- **display_name**: *string*
- ⁺**rules**: *array*
- items: *object*
<br>*additional properties: false*
- **description**: *string*
- ⁺**denied_permissions**: *array*
- items: *string*
- ⁺**denied_principals**: *array*
- items: *string*
- **denial_condition**: *object*
<br>*additional properties: false*
- ⁺**expression**: *string*
- **title**: *string*
- **description**: *string*
- **location**: *string*
- **exception_permissions**: *array*
- items: *string*
- **exception_principals**: *array*
- items: *string*
- **kms**: *object*
<br>*additional properties: false*
- **autokeys**: *object*