For_each loop on multiple levels map

Hi all,

Hope you’re doing well these days. I’m really sorry to bother but I’m completely stuck, any help would be really appreciated.

My problem is that I would like to create aws_security_group & aws_security_group_rule with this kind of for_each loop in a module :

variable "security_group" {
  description = "A mapping of security groups with their attributes."
  type        = any
  default     = {}
}

variable "tags" {
  description = "A mapping of tags to assign to the resource."
  type        = map(string)
  default     = {}
}



resource "aws_security_group" "this" {
  for_each = var.security_group

  name                   = each.key
  description            = lookup(each.value, "description", null)
  revoke_rules_on_delete = lookup(each.value, "revoke_rules_on_delete", null)
  vpc_id                 = lookup(each.value, "vpc_id", null)
  tags = merge(
    {
      "Name" = each.key
    },
    var.tags
  )
}

resource "aws_security_group_rule" "ingress" {
  for_each = var.security_group

  description              = lookup(each.value.ingress_rule, "description", null)
  protocol                 = lookup(each.value.ingress_rule, "protocol", "all")
  security_group_id        = ?
  cidr_blocks              = lookup(each.value.ingress_rule, "cidr_blocks", null)
  from_port                = lookup(each.value.ingress_rule, "from_port", 0)
  to_port                  = lookup(each.value.ingress_rule, "to_port", 65535)
  type                     = "ingress"
}

And then call the module :

module "sg" {
  source = "./modules/sg"

  security_group = {
    ec2-runner-sg = {
      vpc_id = data.aws_vpc.main.id
      ingress_rule = [
        {
          rule-1 = {
            protocol    = "tcp"
            cidr_blocks = ["0.0.0.0/0"]
            from_port   = 22
            to_port     = 22
          }
          rule-2 = {
            protocol    = "tcp"
            cidr_blocks = ["0.0.0.0/0"]
            from_port   = 5432
            to_port     = 5432
          }
        }
      ]
    }
  }

  tags = {}
}

Of course this code does not work.

It’s OK for the aws_security_group resource but not for the rules. I don’t know how I could lookup on each rule-1 rule-2, and also how to get the security_group_id for these rules.

Do you know how I could achieve this ? Is it even possible ? Thanks a lot for your help.

aws_security_group can set the ingress & egress rules directly. You don’t need a separate aws_security_group_rule resource.

You can then use dynamic blocks to loop over your rules fairly simply.

Oh my god… I didn’t notice that the aws_security_group resource accepts multiple ingress and egress blocks… I thought that only one of each could be specified. Thanks a lot I’ll try this out !