Add support for creating multiple workforce identity pools (#3846)

* Added support for multiple workforce identity pools

* Fixed organization module workforce identity federation outputs

* tfdoc

---------

Co-authored-by: Ludovico Magnocavallo <ludomagno@google.com>
Co-authored-by: Julio Castillo <jccb@google.com>
This commit is contained in:
kovagoadam
2026-04-14 08:55:18 +02:00
committed by GitHub
parent f7d74a6b1f
commit 1050daff71
8 changed files with 278 additions and 250 deletions

View File

@@ -911,60 +911,60 @@ Auto-population of provider attributes is supported via the `attribute_mapping_t
module "org" {
source = "./fabric/modules/organization"
organization_id = var.organization_id
workforce_identity_config = {
# optional, defaults to 'default'
pool_name = "test-pool"
display_name = "Test Pool"
description = "Workforce pool for testing."
providers = {
saml-basic = {
attribute_mapping_template = "azuread"
identity_provider = {
saml = {
idp_metadata_xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?>..."
}
}
}
saml-full = {
attribute_mapping = {
"google.subject" = "assertion.sub"
}
identity_provider = {
saml = {
idp_metadata_xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?>..."
}
}
oauth2_client_config = {
extra_attributes = {
issuer_uri = "https://login.microsoftonline.com/abcdef/v2.0"
client_id = "client-id"
client_secret = "client-secret"
attributes_type = "AZURE_AD_GROUPS_ID"
query_filter = "mail:gcp"
}
}
}
oidc-full = {
attribute_mapping = {
"google.subject" = "assertion.sub"
}
identity_provider = {
oidc = {
issuer_uri = "https://sts.windows.net/abcd01234/"
client_id = "https://analysis.windows.net/powerbi/connector/GoogleBigQuery"
client_secret = "client-secret"
web_sso_config = {
response_type = "CODE"
assertion_claims_behavior = "MERGE_USER_INFO_OVER_ID_TOKEN_CLAIMS"
workforce_identity_pools = {
"test-pool" = {
display_name = "Test Pool"
description = "Workforce pool for testing."
providers = {
saml-basic = {
attribute_mapping_template = "azuread"
identity_provider = {
saml = {
idp_metadata_xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?>..."
}
}
}
oauth2_client_config = {
extra_attributes = {
issuer_uri = "https://login.microsoftonline.com/abcd01234/v2.0"
client_id = "client-id"
client_secret = "client-secret"
attributes_type = "AZURE_AD_GROUPS_MAIL"
saml-full = {
attribute_mapping = {
"google.subject" = "assertion.sub"
}
identity_provider = {
saml = {
idp_metadata_xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?>..."
}
}
oauth2_client_config = {
extra_attributes = {
issuer_uri = "https://login.microsoftonline.com/abcdef/v2.0"
client_id = "client-id"
client_secret = "client-secret"
attributes_type = "AZURE_AD_GROUPS_ID"
query_filter = "mail:gcp"
}
}
}
oidc-full = {
attribute_mapping = {
"google.subject" = "assertion.sub"
}
identity_provider = {
oidc = {
issuer_uri = "https://sts.windows.net/abcd01234/"
client_id = "https://analysis.windows.net/powerbi/connector/GoogleBigQuery"
client_secret = "client-secret"
web_sso_config = {
response_type = "CODE"
assertion_claims_behavior = "MERGE_USER_INFO_OVER_ID_TOKEN_CLAIMS"
}
}
}
oauth2_client_config = {
extra_attributes = {
issuer_uri = "https://login.microsoftonline.com/abcd01234/v2.0"
client_id = "client-id"
client_secret = "client-secret"
attributes_type = "AZURE_AD_GROUPS_MAIL"
}
}
}
}
@@ -1033,7 +1033,7 @@ module "org" {
| [tag_bindings](variables-tags.tf#L89) | Tag bindings for this organization, in key => tag value id format. | <code>map&#40;string&#41;</code> | | <code>&#123;&#125;</code> |
| [tags](variables-tags.tf#L96) | Tags by key name. If `id` is provided, key or value creation is skipped. The `iam` attribute behaves like the similarly named one at module level. | <code>map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [tags_config](variables-tags.tf#L161) | Fine-grained control on tag resource and IAM creation. | <code>object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>&#123;&#125;</code> |
| [workforce_identity_config](variables-identity-providers.tf#L17) | Workforce Identity Federation pool and providers. | <code>object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [workforce_identity_pools](variables-identity-providers.tf#L17) | Workforce Identity Federation pools and providers. | <code>map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
## Outputs
@@ -1055,6 +1055,7 @@ module "org" {
| [sink_writer_identities](outputs.tf#L125) | Writer identities created for each sink. | |
| [tag_keys](outputs.tf#L133) | Tag key resources. | |
| [tag_values](outputs.tf#L142) | Tag value resources. | |
| [workforce_identity_provider_names](outputs.tf#L150) | Workforce Identity provider names. | |
| [workforce_identity_providers](outputs.tf#L157) | Workforce Identity provider attributes. | |
| [workforce_identity_pool_ids](outputs.tf#L150) | Workforce identity pool ids. | |
| [workforce_identity_provider_names](outputs.tf#L157) | Workforce Identity provider names. | |
| [workforce_identity_providers](outputs.tf#L164) | Workforce Identity provider attributes. | |
<!-- END TFDOC -->

View File

@@ -35,23 +35,32 @@ locals {
"attribute.user_email" = "assertion.attributes.email[0]"
}
}
wfif_providers = merge([
for k, v in var.workforce_identity_pools : {
for pk, pv in v.providers : "${k}/${pk}" => merge(pv, {
provider_id = pk
pool = k
})
}
]...)
}
resource "google_iam_workforce_pool" "default" {
count = var.workforce_identity_config == null ? 0 : 1
for_each = var.workforce_identity_pools
parent = var.organization_id
location = "global"
workforce_pool_id = var.workforce_identity_config.pool_name
description = var.workforce_identity_config.description
disabled = var.workforce_identity_config.disabled
display_name = var.workforce_identity_config.display_name
session_duration = var.workforce_identity_config.session_duration
workforce_pool_id = each.key
description = each.value.description
disabled = each.value.disabled
display_name = each.value.display_name
session_duration = each.value.session_duration
dynamic "access_restrictions" {
for_each = var.workforce_identity_config.access_restrictions != null ? [""] : []
for_each = each.value.access_restrictions != null ? [""] : []
content {
disable_programmatic_signin = var.workforce_identity_config.access_restrictions.disable_programmatic_signin
disable_programmatic_signin = each.value.access_restrictions.disable_programmatic_signin
dynamic "allowed_services" {
for_each = coalesce(var.workforce_identity_config.access_restrictions.allowed_services, [])
for_each = coalesce(each.value.access_restrictions.allowed_services, [])
content {
domain = allowed_services.value.domain
}
@@ -61,8 +70,8 @@ resource "google_iam_workforce_pool" "default" {
}
resource "google_iam_workforce_pool_provider" "default" {
for_each = try(var.workforce_identity_config.providers, {})
provider_id = each.key
for_each = local.wfif_providers
provider_id = each.value.provider_id
attribute_condition = each.value.attribute_condition
description = each.value.description
disabled = each.value.disabled
@@ -71,8 +80,10 @@ resource "google_iam_workforce_pool_provider" "default" {
try(local.wfif_attribute_mappings[each.value.attribute_mapping_template], {}),
each.value.attribute_mapping
)
location = google_iam_workforce_pool.default[0].location
workforce_pool_id = google_iam_workforce_pool.default[0].workforce_pool_id
location = "global"
workforce_pool_id = (
google_iam_workforce_pool.default[each.value.pool].workforce_pool_id
)
dynamic "saml" {
for_each = each.value.identity_provider.saml == null ? [] : [""]
content {

View File

@@ -147,6 +147,13 @@ output "tag_values" {
}
}
output "workforce_identity_pool_ids" {
description = "Workforce identity pool ids."
value = {
for k, v in google_iam_workforce_pool.default : k => v.name
}
}
output "workforce_identity_provider_names" {
description = "Workforce Identity provider names."
value = {
@@ -157,9 +164,9 @@ output "workforce_identity_provider_names" {
output "workforce_identity_providers" {
description = "Workforce Identity provider attributes."
value = {
for k, v in google_iam_workforce_pool_provider.default : k => {
name = v.name
pool = try(google_iam_workforce_pool.default[0].name, null)
for k, v in local.wfif_providers : k => {
name = google_iam_workforce_pool_provider.default[k].name
pool = google_iam_workforce_pool.default[v.pool].name
}
}
}

View File

@@ -14,10 +14,9 @@
* limitations under the License.
*/
variable "workforce_identity_config" {
description = "Workforce Identity Federation pool and providers."
type = object({
pool_name = optional(string, "default")
variable "workforce_identity_pools" {
description = "Workforce Identity Federation pools and providers."
type = map(object({
description = optional(string)
disabled = optional(bool)
display_name = optional(string)
@@ -69,12 +68,12 @@ variable "workforce_identity_config" {
}))
}), {})
})), {})
})
nullable = true
default = null
}))
nullable = false
default = {}
validation {
condition = alltrue([
for v in try(var.workforce_identity_config.providers, {}) : contains(
for v in try(var.workforce_identity_pools.providers, {}) : contains(
["azuread", "okta"],
coalesce(v.attribute_mapping_template, "azuread")
)
@@ -83,7 +82,7 @@ variable "workforce_identity_config" {
}
validation {
condition = alltrue([
for v in try(var.workforce_identity_config.providers, {}) : (
for v in try(var.workforce_identity_pools.providers, {}) : (
(try(v.identity_provider.oidc, null) == null ? 0 : 1) +
(try(v.identity_provider.saml, null) == null ? 0 : 1)
) == 1
@@ -92,7 +91,7 @@ variable "workforce_identity_config" {
}
validation {
condition = alltrue([
for v in try(var.workforce_identity_config.providers, {}) : contains(
for v in try(var.workforce_identity_pools.providers, {}) : contains(
["CODE", "ID_TOKEN"],
coalesce(try(
v.identity_provider.oidc.web_sso_config.response_type, null
@@ -103,7 +102,7 @@ variable "workforce_identity_config" {
}
validation {
condition = alltrue([
for v in try(var.workforce_identity_config.providers, {}) : contains(
for v in try(var.workforce_identity_pools.providers, {}) : contains(
["MERGE_USER_INFO_OVER_ID_TOKEN_CLAIMS", "ONLY_ID_TOKEN_CLAIMS"],
coalesce(try(
v.identity_provider.oidc.web_sso_config.assertion_claims_behavior, null
@@ -114,7 +113,7 @@ variable "workforce_identity_config" {
}
validation {
condition = alltrue([
for v in try(var.workforce_identity_config.providers, {}) : contains(
for v in try(var.workforce_identity_pools.providers, {}) : contains(
["AZURE_AD_GROUPS_MAIL", "AZURE_AD_GROUPS_ID"],
coalesce(try(
v.oauth2_client_config.extended_attributes.attributes_type, null
@@ -125,7 +124,7 @@ variable "workforce_identity_config" {
}
validation {
condition = alltrue([
for v in try(var.workforce_identity_config.providers, {}) : contains(
for v in try(var.workforce_identity_pools.providers, {}) : contains(
["AZURE_AD_GROUPS_MAIL", "AZURE_AD_GROUPS_ID"],
coalesce(try(
v.oauth2_client_config.extra_attributes.attributes_type, null