For_each chaining across multiple resources?

I have a use case where I’m using the Keycloak Terraform provider.

I need to create a Keycloak user role which requires info from the keycloak_realm, keycloal_user, and keycloak_role resources.

However, I have multiple keycloak realms and keycloak users so all of those resources use a for_each statement and the keycloak_user resource uses for_each chaining to explicitly state a 1 to 1 relation between a realm and its user.

How can I do the same thing with a Keycloak user role if it requires an ID from both the realm and the user resources?

Normally I would just say e.g. “keycloak_realm.id” or in a loop I would say “each.id” but now I have to simultaneously loop over two different resource maps.

Is this even possible?

The main.tf for reference:

resource "keycloak_realm" "realm" {
  for_each = var.realms
  realm             = each.key
  enabled           = true
  display_name      = each.value.display_name
  display_name_html = "<b>${each.value.display_name}</b>"
}

data "keycloak_role" "realm_role" {
  for_each = keycloak_realm.realm
  realm_id = each.value.id
  name     = "${each.value.realm}-role"
}

resource "keycloak_user" "user" {
  for_each = keycloak_realm.realm
  realm_id = each.value.id
  username = "johndoe-services"
  enabled  = true

  email      = "johndoe@gmail.com"
  first_name = "John"
  last_name  = "Doe"

  initial_password {
    value     = "password"
    temporary = false
  }
}

# How do I make this part work across each of the keys in var.realms?
resource "keycloak_user_roles" "user_roles" {
  realm_id = keycloak_realm.realm.id
  user_id = keycloak_user.user.id

  role_ids = [
    data.keycloak_role.realm_role.id,
  ]
}

Hi @pritster5,

If I’m reading your configuration correctly, it seems that there’s a one-to-one relationship between “realms”, “roles”, and “users”, and because you’re chaining between them you can assume that they are all using the same instance keys.

Therefore I would expect the following to work:

resource "keycloak_user_roles" "user_roles" {
  for_each = keycloak_realm.realm

  realm_id = each.value.id
  user_id  = keycloak_user.user[each.key].id
  role_ids = [
    data.keycloak_role.realm_role[each.key].id,
  ]
}

This continues the idea of chaining from keycloak_realm.realm, but also uses each.key to find the corresponding instances of keycloak_user.user and data.keycloak_role.realm_role, by relying on the fact that those also have the same for_each and therefore the same instance keys.

1 Like

This worked beautifully, thanks!

However, I realized after asking this question that a module in this case is probably a better solution, because then I can just use for_each on the module itself, and then have the for_each iterate over a map in thetfvars file.

This topic was automatically closed 62 days after the last reply. New replies are no longer allowed.