It's possible to create a string using a map?

Hello guys hope you are all well, has the title says i want to know if it’s possible to convert a map to a string but only for a specific resource this is my code:

main.tf

module "groups" {
  source = "../../Groups/module/module"

  groups = {
    security_tooling_prod = {
      group = "some group"
      users = ["user1", "user2"]
    }
  }
}

variables.tf inside module

variable "groups" {
  type = map(any)
}

module.tf

data "aws_ssoadmin_instances" "this" {}

data "aws_identitystore_user" "this" {
  for_each          = local.users
  identity_store_id = local.ssoadmin_instance_id

  alternate_identifier {
    unique_attribute {
      attribute_path  = "UserName"
      attribute_value = each.value
    }
  }
}

resource "aws_identitystore_group" "this" {
  for_each          = var.groups
  display_name      = "aws-outcloud-${replace(lower(each.value.group), "/\\s+/", "-")}"
  identity_store_id = local.ssoadmin_instance_id
}

resource "aws_identitystore_group_membership" "this" {
  for_each          = var.groups
  identity_store_id = local.ssoadmin_instance_id
  group_id          = aws_identitystore_group.this[each.key].group_id
  member_id         = data.aws_identitystore_user.this[each.key].user_id
}

local.tf

locals {
  ssoadmin_instance_id = tolist(data.aws_ssoadmin_instances.this.identity_store_ids)[0]
  users = toset([for k , v in var.groups : v.users]...)
}

In data.aws_identitystore_user.this I need to change my list of users to a string for each value in the list, i think i managed to do that using the locals but it creates a new error:

│ Error: Invalid index
│ 
│   on ../../Groups/module/module/main.tf line 26, in resource "aws_identitystore_group_membership" "this":
│   26:   member_id         = data.aws_identitystore_user.this[each.key].user_id
│     ├────────────────
│     │ data.aws_identitystore_user.this is object with 2 attributes
│     │ each.key is "security_tooling_prod"
│
│ The given key does not identify an element in this collection value.

Can someone please explain to me what am i doing wrong?

Thank you in advance!

Hi @joao.gomes,

I think the first problem here is that your resource "aws_identitystore_group_membership" "this" block has for_each = var.groups, so each.key in there are the group keys, but you are trying to use each.key to look up an instance of data "aws_identitystore_user" "this" whose for_each is var.users, and so the instance keys there are the user keys (“user1” and “user2”) and therefore don’t match.

Based on the name I assume the requirement here is to have one instance for every pair of group and user implied by the input variable, and so you will need to derive a new data structure that has one element per pair, perhaps by using a technique like what’s shown in Flattening nested structures for for_each.


Also, tangentially, I notice that your input variable declaration is incorrect. You’ve declared that your module can accept a map of any element type, but in the rest of the module source code we can clearly see that it won’t work if given anything other than an object type with “group” and “users” attributes, so here is the correct declaration:

variable "groups" {
  type = map(object({
    group = string
    users = set(string)
  }))
}

Using a correct declaration of what your module requires will avoid strange problems later as your requirements grow and it becomes more ambiguous exactly what type you meant by “any” and Terraform may start guessing incorrectly.