Add iam_by_principals_additive to project, organization and folder modules (#2814)
* First attempt at iam_by_principals_additive * Remove validation * Update IAM ADR * Apply to organization and project modules * Update READMEs * Add tests * Remove "cycle errors"
This commit is contained in:
@@ -1,13 +1,14 @@
|
||||
# Refactor IAM interface
|
||||
|
||||
**authors:** [Ludo](https://github.com/ludoo), [Julio](https://github.com/juliocc)
|
||||
**last modified:** February 12, 2024
|
||||
**last modified:** January 14, 2025
|
||||
|
||||
## Status
|
||||
|
||||
- Implemented in [#1595](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1595).
|
||||
- Authoritative bindings type changed as per [#1622](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/issues/1622).
|
||||
- Extended by [#2064](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/issues/2064).
|
||||
- Extended by #2805 and #2814 to include `iam_by_principals_additive`
|
||||
|
||||
## Context
|
||||
|
||||
@@ -20,6 +21,7 @@ We currently support, with uneven coverage across modules:
|
||||
- legacy additive `iam_additive` in `ROLE => [PRINCIPALS]` format which breaks for dynamic values
|
||||
- legacy additive `iam_additive_members` in `PRINCIPAL => [ROLES]` format which breaks for dynamic values
|
||||
- new additive `iam_members` in `KEY => {role: ROLE, member: MEMBER, condition: CONDITION}` format which works with dynamic values and supports conditions
|
||||
- new additive `iam_by_principals_additive` in `PRINCIPAL => [ROLES]` format
|
||||
- policy authoritative `iam_policy`
|
||||
- specific support for third party resource bindings in the service account module
|
||||
|
||||
@@ -122,7 +124,7 @@ The **proposal** is to remove the IAM policy variable and resources, as its cove
|
||||
|
||||
```hcl
|
||||
variable "iam_by_principals" {
|
||||
description = "Authoritative IAM binding in {PRINCIPAL => [ROLES]} format. Principals need to be statically defined to avoid cycle errors. Merged internally with the `iam` variable."
|
||||
description = "Authoritative IAM binding in {PRINCIPAL => [ROLES]} format. Principals need to be statically defined to avoid errors. Merged internally with the `iam` variable."
|
||||
type = map(list(string))
|
||||
default = {}
|
||||
nullable = false
|
||||
@@ -132,6 +134,20 @@ variable "iam_by_principals" {
|
||||
|
||||
See #2064 and [this ADR](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/blob/ludo/iam-changes/fast/docs/0-domainless-iam.md) for more details.
|
||||
|
||||
### IAM by Principals Additive
|
||||
> [!NOTE]
|
||||
> This section was added on 2025-01-14
|
||||
|
||||
#2805 and #2814 introduced an additive version of `iam_by_principals`. The new variable format is shown below
|
||||
|
||||
```hcl
|
||||
variable "iam_by_principals_additive" {
|
||||
description = "Additive IAM binding in {PRINCIPAL => [ROLES]} format. Principals need to be statically defined to avoid errors. Merged internally with the `iam_bindings_additive` variable."
|
||||
type = map(list(string))
|
||||
default = {}
|
||||
nullable = false
|
||||
}
|
||||
```
|
||||
|
||||
## Decision
|
||||
|
||||
@@ -202,8 +218,15 @@ variable "iam_bindings_additive" {
|
||||
nullable = false
|
||||
}
|
||||
|
||||
variable "iam_by_principals_additive" {
|
||||
description = "Additive IAM binding in {PRINCIPAL => [ROLES]} format. Principals need to be statically defined to avoid errors. Merged internally with the `iam_bindings_additive` variable."
|
||||
type = map(list(string))
|
||||
default = {}
|
||||
nullable = false
|
||||
}
|
||||
|
||||
variable "iam_by_principals" {
|
||||
description = "Authoritative IAM binding in {PRINCIPAL => [ROLES]} format. Principals need to be statically defined to avoid cycle errors. Merged internally with the `iam` variable."
|
||||
description = "Authoritative IAM binding in {PRINCIPAL => [ROLES]} format. Principals need to be statically defined to avoid errors. Merged internally with the `iam` variable."
|
||||
type = map(list(string))
|
||||
default = {}
|
||||
nullable = false
|
||||
@@ -228,6 +251,19 @@ locals {
|
||||
try(local._iam_principals[role], [])
|
||||
)
|
||||
}
|
||||
iam_bindings_additive = merge(
|
||||
var.iam_bindings_additive,
|
||||
[
|
||||
for principal, roles in var.iam_by_principals_additive : {
|
||||
for role in roles :
|
||||
"iam-bpa:${principal}-${role}" => {
|
||||
member = principal
|
||||
role = role
|
||||
condition = null
|
||||
}
|
||||
}
|
||||
]...
|
||||
)
|
||||
}
|
||||
resource "google_RESOURCE_TYPE_iam_binding" "authoritative" {
|
||||
for_each = local.iam
|
||||
@@ -253,7 +289,7 @@ resource "google_RESOURCE_TYPE_iam_binding" "bindings" {
|
||||
}
|
||||
|
||||
resource "google_RESOURCE_TYPE_iam_member" "bindings" {
|
||||
for_each = var.iam_bindings_additive
|
||||
for_each = local.iam_bindings_additive
|
||||
role = each.value.role
|
||||
member = each.value.member
|
||||
// add extra attributes (e.g. resource id)
|
||||
|
||||
@@ -403,7 +403,8 @@ module "folder" {
|
||||
| [iam](variables-iam.tf#L17) | IAM bindings in {ROLE => [MEMBERS]} format. | <code>map(list(string))</code> | | <code>{}</code> |
|
||||
| [iam_bindings](variables-iam.tf#L24) | Authoritative IAM bindings in {KEY => {role = ROLE, members = [], condition = {}}}. Keys are arbitrary. | <code title="map(object({ members = list(string) role = string condition = optional(object({ expression = string title = string description = optional(string) })) }))">map(object({…}))</code> | | <code>{}</code> |
|
||||
| [iam_bindings_additive](variables-iam.tf#L39) | Individual additive IAM bindings. Keys are arbitrary. | <code title="map(object({ member = string role = string condition = optional(object({ expression = string title = string description = optional(string) })) }))">map(object({…}))</code> | | <code>{}</code> |
|
||||
| [iam_by_principals](variables-iam.tf#L54) | Authoritative IAM binding in {PRINCIPAL => [ROLES]} format. Principals need to be statically defined to avoid cycle errors. Merged internally with the `iam` variable. | <code>map(list(string))</code> | | <code>{}</code> |
|
||||
| [iam_by_principals](variables-iam.tf#L61) | Authoritative IAM binding in {PRINCIPAL => [ROLES]} format. Principals need to be statically defined to avoid errors. Merged internally with the `iam` variable. | <code>map(list(string))</code> | | <code>{}</code> |
|
||||
| [iam_by_principals_additive](variables-iam.tf#L54) | Additive IAM binding in {PRINCIPAL => [ROLES]} format. Principals need to be statically defined to avoid errors. Merged internally with the `iam_bindings_additive` variable. | <code>map(list(string))</code> | | <code>{}</code> |
|
||||
| [id](variables.tf#L107) | Folder ID in case you use folder_create=false. | <code>string</code> | | <code>null</code> |
|
||||
| [logging_data_access](variables-logging.tf#L17) | Control activation of data access logs. Format is service => { log type => [exempted members]}. The special 'allServices' key denotes configuration for all services. | <code>map(map(list(string)))</code> | | <code>{}</code> |
|
||||
| [logging_exclusions](variables-logging.tf#L32) | Logging exclusions for this folder in the form {NAME -> FILTER}. | <code>map(string)</code> | | <code>{}</code> |
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright 2024 Google LLC
|
||||
* Copyright 2025 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -31,6 +31,19 @@ locals {
|
||||
try(local._iam_principals[role], [])
|
||||
)
|
||||
}
|
||||
iam_bindings_additive = merge(
|
||||
var.iam_bindings_additive,
|
||||
[
|
||||
for principal, roles in var.iam_by_principals_additive : {
|
||||
for role in roles :
|
||||
"iam-bpa:${principal}-${role}" => {
|
||||
member = principal
|
||||
role = role
|
||||
condition = null
|
||||
}
|
||||
}
|
||||
]...
|
||||
)
|
||||
}
|
||||
|
||||
resource "google_folder_iam_binding" "authoritative" {
|
||||
@@ -56,7 +69,7 @@ resource "google_folder_iam_binding" "bindings" {
|
||||
}
|
||||
|
||||
resource "google_folder_iam_member" "bindings" {
|
||||
for_each = var.iam_bindings_additive
|
||||
for_each = local.iam_bindings_additive
|
||||
folder = local.folder_id
|
||||
role = each.value.role
|
||||
member = each.value.member
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright 2024 Google LLC
|
||||
* Copyright 2025 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -51,8 +51,15 @@ variable "iam_bindings_additive" {
|
||||
default = {}
|
||||
}
|
||||
|
||||
variable "iam_by_principals" {
|
||||
description = "Authoritative IAM binding in {PRINCIPAL => [ROLES]} format. Principals need to be statically defined to avoid cycle errors. Merged internally with the `iam` variable."
|
||||
variable "iam_by_principals_additive" {
|
||||
description = "Additive IAM binding in {PRINCIPAL => [ROLES]} format. Principals need to be statically defined to avoid errors. Merged internally with the `iam_bindings_additive` variable."
|
||||
type = map(list(string))
|
||||
default = {}
|
||||
nullable = false
|
||||
}
|
||||
|
||||
variable "iam_by_principals" {
|
||||
description = "Authoritative IAM binding in {PRINCIPAL => [ROLES]} format. Principals need to be statically defined to avoid errors. Merged internally with the `iam` variable."
|
||||
type = map(list(string))
|
||||
default = {}
|
||||
nullable = false
|
||||
|
||||
@@ -542,7 +542,8 @@ module "org" {
|
||||
| [iam](variables-iam.tf#L17) | IAM bindings, in {ROLE => [MEMBERS]} format. | <code>map(list(string))</code> | | <code>{}</code> |
|
||||
| [iam_bindings](variables-iam.tf#L24) | Authoritative IAM bindings in {KEY => {role = ROLE, members = [], condition = {}}}. Keys are arbitrary. | <code title="map(object({ members = list(string) role = string condition = optional(object({ expression = string title = string description = optional(string) })) }))">map(object({…}))</code> | | <code>{}</code> |
|
||||
| [iam_bindings_additive](variables-iam.tf#L39) | Individual additive IAM bindings. Keys are arbitrary. | <code title="map(object({ member = string role = string condition = optional(object({ expression = string title = string description = optional(string) })) }))">map(object({…}))</code> | | <code>{}</code> |
|
||||
| [iam_by_principals](variables-iam.tf#L54) | Authoritative IAM binding in {PRINCIPAL => [ROLES]} format. Principals need to be statically defined to avoid cycle errors. Merged internally with the `iam` variable. | <code>map(list(string))</code> | | <code>{}</code> |
|
||||
| [iam_by_principals](variables-iam.tf#L61) | Authoritative IAM binding in {PRINCIPAL => [ROLES]} format. Principals need to be statically defined to avoid errors. Merged internally with the `iam` variable. | <code>map(list(string))</code> | | <code>{}</code> |
|
||||
| [iam_by_principals_additive](variables-iam.tf#L54) | Additive IAM binding in {PRINCIPAL => [ROLES]} format. Principals need to be statically defined to avoid errors. Merged internally with the `iam_bindings_additive` variable. | <code>map(list(string))</code> | | <code>{}</code> |
|
||||
| [logging_data_access](variables-logging.tf#L17) | Control activation of data access logs. Format is service => { log type => [exempted members]}. The special 'allServices' key denotes configuration for all services. | <code>map(map(list(string)))</code> | | <code>{}</code> |
|
||||
| [logging_exclusions](variables-logging.tf#L32) | Logging exclusions for this organization in the form {NAME -> FILTER}. | <code>map(string)</code> | | <code>{}</code> |
|
||||
| [logging_settings](variables-logging.tf#L39) | Default settings for logging resources. | <code title="object({ disable_default_sink = optional(bool) storage_location = optional(string) })">object({…})</code> | | <code>null</code> |
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright 2024 Google LLC
|
||||
* Copyright 2025 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -51,6 +51,19 @@ locals {
|
||||
try(local._iam_principals[role], [])
|
||||
)
|
||||
}
|
||||
iam_bindings_additive = merge(
|
||||
var.iam_bindings_additive,
|
||||
[
|
||||
for principal, roles in var.iam_by_principals_additive : {
|
||||
for role in roles :
|
||||
"iam-bpa:${principal}-${role}" => {
|
||||
member = principal
|
||||
role = role
|
||||
condition = null
|
||||
}
|
||||
}
|
||||
]...
|
||||
)
|
||||
}
|
||||
|
||||
# we use a different key for custom roles to allow referring to the role alias
|
||||
@@ -101,7 +114,7 @@ resource "google_organization_iam_binding" "bindings" {
|
||||
}
|
||||
|
||||
resource "google_organization_iam_member" "bindings" {
|
||||
for_each = var.iam_bindings_additive
|
||||
for_each = local.iam_bindings_additive
|
||||
org_id = local.organization_id_numeric
|
||||
role = each.value.role
|
||||
member = each.value.member
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright 2024 Google LLC
|
||||
* Copyright 2025 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -51,8 +51,15 @@ variable "iam_bindings_additive" {
|
||||
default = {}
|
||||
}
|
||||
|
||||
variable "iam_by_principals" {
|
||||
description = "Authoritative IAM binding in {PRINCIPAL => [ROLES]} format. Principals need to be statically defined to avoid cycle errors. Merged internally with the `iam` variable."
|
||||
variable "iam_by_principals_additive" {
|
||||
description = "Additive IAM binding in {PRINCIPAL => [ROLES]} format. Principals need to be statically defined to avoid errors. Merged internally with the `iam_bindings_additive` variable."
|
||||
type = map(list(string))
|
||||
default = {}
|
||||
nullable = false
|
||||
}
|
||||
|
||||
variable "iam_by_principals" {
|
||||
description = "Authoritative IAM binding in {PRINCIPAL => [ROLES]} format. Principals need to be statically defined to avoid errors. Merged internally with the `iam` variable."
|
||||
type = map(list(string))
|
||||
default = {}
|
||||
nullable = false
|
||||
|
||||
@@ -1593,7 +1593,8 @@ alerts:
|
||||
| [iam](variables-iam.tf#L17) | Authoritative IAM bindings in {ROLE => [MEMBERS]} format. | <code>map(list(string))</code> | | <code>{}</code> |
|
||||
| [iam_bindings](variables-iam.tf#L24) | Authoritative IAM bindings in {KEY => {role = ROLE, members = [], condition = {}}}. Keys are arbitrary. | <code title="map(object({ members = list(string) role = string condition = optional(object({ expression = string title = string description = optional(string) })) }))">map(object({…}))</code> | | <code>{}</code> |
|
||||
| [iam_bindings_additive](variables-iam.tf#L39) | Individual additive IAM bindings. Keys are arbitrary. | <code title="map(object({ member = string role = string condition = optional(object({ expression = string title = string description = optional(string) })) }))">map(object({…}))</code> | | <code>{}</code> |
|
||||
| [iam_by_principals](variables-iam.tf#L54) | Authoritative IAM binding in {PRINCIPAL => [ROLES]} format. Principals need to be statically defined to avoid cycle errors. Merged internally with the `iam` variable. | <code>map(list(string))</code> | | <code>{}</code> |
|
||||
| [iam_by_principals](variables-iam.tf#L61) | Authoritative IAM binding in {PRINCIPAL => [ROLES]} format. Principals need to be statically defined to avoid errors. Merged internally with the `iam` variable. | <code>map(list(string))</code> | | <code>{}</code> |
|
||||
| [iam_by_principals_additive](variables-iam.tf#L54) | Additive IAM binding in {PRINCIPAL => [ROLES]} format. Principals need to be statically defined to avoid errors. Merged internally with the `iam_bindings_additive` variable. | <code>map(list(string))</code> | | <code>{}</code> |
|
||||
| [labels](variables.tf#L96) | Resource labels. | <code>map(string)</code> | | <code>{}</code> |
|
||||
| [lien_reason](variables.tf#L103) | If non-empty, creates a project lien with this description. | <code>string</code> | | <code>null</code> |
|
||||
| [log_scopes](variables-observability.tf#L117) | Log scopes under this project. | <code title="map(object({ description = optional(string) resource_names = list(string) }))">map(object({…}))</code> | | <code>{}</code> |
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright 2024 Google LLC
|
||||
* Copyright 2025 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -54,6 +54,19 @@ locals {
|
||||
try(local._iam_principals[role], [])
|
||||
)
|
||||
}
|
||||
iam_bindings_additive = merge(
|
||||
var.iam_bindings_additive,
|
||||
[
|
||||
for principal, roles in var.iam_by_principals_additive : {
|
||||
for role in roles :
|
||||
"iam-bpa:${principal}-${role}" => {
|
||||
member = principal
|
||||
role = role
|
||||
condition = null
|
||||
}
|
||||
}
|
||||
]...
|
||||
)
|
||||
}
|
||||
|
||||
# we use a different key for custom roles to allow referring to the role alias
|
||||
@@ -110,7 +123,7 @@ resource "google_project_iam_binding" "bindings" {
|
||||
}
|
||||
|
||||
resource "google_project_iam_member" "bindings" {
|
||||
for_each = var.iam_bindings_additive
|
||||
for_each = local.iam_bindings_additive
|
||||
project = local.project.project_id
|
||||
role = each.value.role
|
||||
member = each.value.member
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright 2024 Google LLC
|
||||
* Copyright 2025 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -51,8 +51,15 @@ variable "iam_bindings_additive" {
|
||||
default = {}
|
||||
}
|
||||
|
||||
variable "iam_by_principals" {
|
||||
description = "Authoritative IAM binding in {PRINCIPAL => [ROLES]} format. Principals need to be statically defined to avoid cycle errors. Merged internally with the `iam` variable."
|
||||
variable "iam_by_principals_additive" {
|
||||
description = "Additive IAM binding in {PRINCIPAL => [ROLES]} format. Principals need to be statically defined to avoid errors. Merged internally with the `iam_bindings_additive` variable."
|
||||
type = map(list(string))
|
||||
default = {}
|
||||
nullable = false
|
||||
}
|
||||
|
||||
variable "iam_by_principals" {
|
||||
description = "Authoritative IAM binding in {PRINCIPAL => [ROLES]} format. Principals need to be statically defined to avoid errors. Merged internally with the `iam` variable."
|
||||
type = map(list(string))
|
||||
default = {}
|
||||
nullable = false
|
||||
|
||||
4
tests/modules/folder/iam_by_principals_additive.tfvars
Normal file
4
tests/modules/folder/iam_by_principals_additive.tfvars
Normal file
@@ -0,0 +1,4 @@
|
||||
iam_by_principals_additive = {
|
||||
"user:user1@example.com" = ["role1", "role2"]
|
||||
"user:user2@example.com" = ["role2", "role3"]
|
||||
}
|
||||
35
tests/modules/folder/iam_by_principals_additive.yaml
Normal file
35
tests/modules/folder/iam_by_principals_additive.yaml
Normal file
@@ -0,0 +1,35 @@
|
||||
# Copyright 2025 Google LLC
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
values:
|
||||
google_folder_iam_member.bindings["iam-bpa:user:user1@example.com-role1"]:
|
||||
condition: []
|
||||
member: user:user1@example.com
|
||||
role: role1
|
||||
google_folder_iam_member.bindings["iam-bpa:user:user1@example.com-role2"]:
|
||||
condition: []
|
||||
member: user:user1@example.com
|
||||
role: role2
|
||||
google_folder_iam_member.bindings["iam-bpa:user:user2@example.com-role2"]:
|
||||
condition: []
|
||||
member: user:user2@example.com
|
||||
role: role2
|
||||
google_folder_iam_member.bindings["iam-bpa:user:user2@example.com-role3"]:
|
||||
condition: []
|
||||
member: user:user2@example.com
|
||||
role: role3
|
||||
|
||||
counts:
|
||||
google_folder: 1
|
||||
google_folder_iam_member: 4
|
||||
21
tests/modules/folder/tftest.yaml
Normal file
21
tests/modules/folder/tftest.yaml
Normal file
@@ -0,0 +1,21 @@
|
||||
# Copyright 2025 Google LLC
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
module: modules/folder
|
||||
|
||||
common_tfvars:
|
||||
- common.tfvars
|
||||
|
||||
tests:
|
||||
iam_by_principals_additive:
|
||||
@@ -0,0 +1,4 @@
|
||||
iam_by_principals_additive = {
|
||||
"user:user1@example.com" = ["role1", "role2"]
|
||||
"user:user2@example.com" = ["role2", "role3"]
|
||||
}
|
||||
39
tests/modules/organization/iam_by_principals_additive.yaml
Normal file
39
tests/modules/organization/iam_by_principals_additive.yaml
Normal file
@@ -0,0 +1,39 @@
|
||||
# Copyright 2025 Google LLC
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
values:
|
||||
google_organization_iam_member.bindings["iam-bpa:user:user1@example.com-role1"]:
|
||||
condition: []
|
||||
member: user:user1@example.com
|
||||
org_id: '1234567890'
|
||||
role: role1
|
||||
google_organization_iam_member.bindings["iam-bpa:user:user1@example.com-role2"]:
|
||||
condition: []
|
||||
member: user:user1@example.com
|
||||
org_id: '1234567890'
|
||||
role: role2
|
||||
google_organization_iam_member.bindings["iam-bpa:user:user2@example.com-role2"]:
|
||||
condition: []
|
||||
member: user:user2@example.com
|
||||
org_id: '1234567890'
|
||||
role: role2
|
||||
google_organization_iam_member.bindings["iam-bpa:user:user2@example.com-role3"]:
|
||||
condition: []
|
||||
member: user:user2@example.com
|
||||
org_id: '1234567890'
|
||||
role: role3
|
||||
|
||||
counts:
|
||||
google_organization_iam_member: 4
|
||||
resources: 4
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright 2023 Google LLC
|
||||
# Copyright 2025 Google LLC
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
@@ -22,3 +22,4 @@ tests:
|
||||
org_policies_boolean:
|
||||
org_policies_custom_constraints:
|
||||
tags:
|
||||
iam_by_principals_additive:
|
||||
|
||||
4
tests/modules/project/iam_by_principals_additive.tfvars
Normal file
4
tests/modules/project/iam_by_principals_additive.tfvars
Normal file
@@ -0,0 +1,4 @@
|
||||
iam_by_principals_additive = {
|
||||
"user:user1@example.com" = ["role1", "role2"]
|
||||
"user:user2@example.com" = ["role2", "role3"]
|
||||
}
|
||||
41
tests/modules/project/iam_by_principals_additive.yaml
Normal file
41
tests/modules/project/iam_by_principals_additive.yaml
Normal file
@@ -0,0 +1,41 @@
|
||||
# Copyright 2025 Google LLC
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
values:
|
||||
google_project.project[0]:
|
||||
name: my-project
|
||||
google_project_iam_member.bindings["iam-bpa:user:user1@example.com-role1"]:
|
||||
condition: []
|
||||
member: user:user1@example.com
|
||||
project: my-project
|
||||
role: role1
|
||||
google_project_iam_member.bindings["iam-bpa:user:user1@example.com-role2"]:
|
||||
condition: []
|
||||
member: user:user1@example.com
|
||||
project: my-project
|
||||
role: role2
|
||||
google_project_iam_member.bindings["iam-bpa:user:user2@example.com-role2"]:
|
||||
condition: []
|
||||
member: user:user2@example.com
|
||||
project: my-project
|
||||
role: role2
|
||||
google_project_iam_member.bindings["iam-bpa:user:user2@example.com-role3"]:
|
||||
condition: []
|
||||
member: user:user2@example.com
|
||||
project: my-project
|
||||
role: role3
|
||||
|
||||
counts:
|
||||
google_project: 1
|
||||
google_project_iam_member: 4
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright 2023 Google LLC
|
||||
# Copyright 2025 Google LLC
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
@@ -26,3 +26,4 @@ tests:
|
||||
service_encryption_keys:
|
||||
org_policies_list:
|
||||
org_policies_boolean:
|
||||
iam_by_principals_additive:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Copyright 2023 Google LLC
|
||||
# Copyright 2025 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,4 +40,4 @@ echo -- Blueprint metadata --
|
||||
python3 tools/validate_metadata.py -v blueprints --verbose --failed-only
|
||||
|
||||
echo -- Version checks --
|
||||
find . -type f -name 'versions.tf' -exec diff -ub default-versions.tf {} \;
|
||||
find . -type f -name 'versions.tf' -exec diff -I '[[:space:]]*module_name' -ub default-versions.tf {} \;
|
||||
|
||||
Reference in New Issue
Block a user