zibs
zibs

Reputation: 1

Terraform for loop to generate security groups with different ports and protocols

I hope can someone can help? I'm a beginner in my terraform journey and from what i have discovered I need to use combination of dynamic function with flatten in order to achieve my reqs. My requirements are:

Jus to give a background, I need to create AWS FSx service(with managed AD) that will allow following set up access to and from FSx service: https://docs.aws.amazon.com/fsx/latest/WindowsGuide/limit-access-security-groups.html Initially the security was done based on 1x security group for 4x different CIDRs with multiple rules but I ended up reaching AWS quota(60) for amount of rules per ingress/egress, so to not extend it best way recommendation from AWS support was to split each CIDR traffic as a separate security group.

So I tried to modify the code from link below but this does not seem to work: https://www.terraform.io/language/functions/flatten

variables.tfvars

security_config = {
      ports = [{
        tcp_port     = ["135", "389", "445", "636", "3268", "3269", "5985", "9389", "49152 - 65535"]
        tcp_udp_port = ["53", "88", "123", "389", "464"]
        udp_port     = ["123"]
        protocol     = ["tcp", "udp"]
        cidr_block   = ["10.1.0.0/28", "10.2.0.0/28", "10.3.0.0/28", "10.4.0.0/28"]
      }
      ]
    }

locals.tf

locals {
      security_rules = flatten([
        for port_key, port in var.ports : [
          for protocol_key, protocol in port.protocols : {
            from_port  = port_key
            to_port    = port_key
            protocol   = protocol_key
            cidr_block = security_rules.cidr_block
          }
        ]
      ])
    }
    

main.tf

resource "aws_security_group" "fsx_flatten" {
          for_each = {
            for port in local.security_rules : "${port.port_key}.${port.protocol_key}" => port
          }
        
          vpc_id      = each.value.vpc_id
          name        = each.value.name
          description = each.value.description
        }

I would like to have something similar output to:

security_config = {
          security_groups = [{
                name        = "sg_1"
                description = "security group 1 - primary site"
                ingress = {
                  from_port  = 53
                  to_port    = 53
                  protocol   = "tcp"
                  cidr_block = ["10.1.0.0/28"]
                }
                 ingress = {
                  from_port  = 53
                  to_port    = 53
                  protocol   = "udp"
                  cidr_block = ["10.1.0.0/28"]
                }
                ingress = {
                  from_port  = 88
                  to_port    = 88
                  protocol   = "tcp"
                  cidr_block = ["10.1.0.0/28"]
                }
                }
                ingress = {
                  from_port  = 88
                  to_port    = 88
                  protocol   = "udp"
                  cidr_block = ["10.1.0.0/28"]
                }
                 ingress = {
                  from_port  = 123
                  to_port    = 123
                  protocol   = "udp"
                  cidr_block = ["10.1.0.0/28"]
                }
                 ingress = {
                  from_port  = 135
                  to_port    = 135
                  protocol   = "tcp"
                  cidr_block = ["10.1.0.0/28"]
                }
                egress = {
                  from_port  = 53
                  to_port    = 53
                  protocol   = "tcp"
                  cidr_block = ["10.1.0.0/28"]
                }
                }
                egress = {
                  from_port  = 53
                  to_port    = 53
                  protocol   = "udp"
                  cidr_block = ["10.1.0.0/28"]
                }
                egress = {
                  from_port  = 88
                  to_port    = 88
                  protocol   = "tcp"
                  cidr_block = ["10.1.0.0/28"]
                }
                }
                egress = {
                  from_port  = 88
                  to_port    = 88
                  protocol   = "udp"
                  cidr_block = ["10.1.0.0/28"]
                }
                 egress = {
                  from_port  = 123
                  to_port    = 123
                  protocol   = "udp"
                  cidr_block = ["10.1.0.0/28"]
                }
                 egress = {
                  from_port  = 135
                  to_port    = 135
                  protocol   = "tcp"
                  cidr_block = ["10.1.0.0/28"]
                }
                },
                {
                  name        = "sg_2"
                  description = "security group 2 - secondary site"
                ingress = {
                  from_port  = 53
                  to_port    = 53
                  protocol   = "tcp"
                  cidr_block = ["10.2.0.0/28"]
                }
                 ingress = {
                  from_port  = 53
                  to_port    = 53
                  protocol   = "udp"
                  cidr_block = ["10.2.0.0/28"]
                }
                ingress = {
                  from_port  = 88
                  to_port    = 88
                  protocol   = "tcp"
                  cidr_block = ["10.2.0.0/28"]
                }
                }
                ingress = {
                  from_port  = 88
                  to_port    = 88
                  protocol   = "udp"
                  cidr_block = ["10.2.0.0/28"]
                }
                 ingress = {
                  from_port  = 123
                  to_port    = 123
                  protocol   = "udp"
                  cidr_block = ["10.2.0.0/28"]
                }
                 ingress = {
                  from_port  = 135
                  to_port    = 135
                  protocol   = "tcp"
                  cidr_block = ["10.2.0.0/28"]
                }
                egress = {
                  from_port  = 53
                  to_port    = 53
                  protocol   = "tcp"
                  cidr_block = ["10.2.0.0/28"]
                }
                }
                egress = {
                  from_port  = 53
                  to_port    = 53
                  protocol   = "udp"
                  cidr_block = ["10.2.0.0/28"]
                }
                egress = {
                  from_port  = 88
                  to_port    = 88
                  protocol   = "tcp"
                  cidr_block = ["10.2.0.0/28"]
                }
                }
                egress = {
                  from_port  = 88
                  to_port    = 88
                  protocol   = "udp"
                  cidr_block = ["10.2.0.0/28"]
                }
                 egress = {
                  from_port  = 123
                  to_port    = 123
                  protocol   = "udp"
                  cidr_block = ["10.2.0.0/28"]
                }
                 egress = {
                  from_port  = 135
                  to_port    = 135
                  protocol   = "tcp"
                  cidr_block = ["10.2.0.0/28"]
                }
              ]
            }

Upvotes: 0

Views: 2287

Answers (1)

Oki Marzuqi
Oki Marzuqi

Reputation: 11

hope this helps to solve your problem

main.tf

resource "aws_security_group" "main" {
...
  dynamic "ingress" {
    for_each = var.ingress_roles
    content {
      description      = ingress.value["description"]
      from_port        = ingress.value["from_port"]
      to_port          = ingress.value["to_port"]
      protocol         = ingress.value["protocol"]
      cidr_blocks      = tolist(ingress.value["cidr_blocks"])
      ipv6_cidr_blocks = tolist(ingress.value["ipv6_cidr_blocks"])
    }
  }

  dynamic "egress" {
    for_each = var.egress_roles
    content {
      from_port        = egress.value["from_port"]
      to_port          = egress.value["to_port"]
      protocol         = egress.value["protocol"]
      cidr_blocks      = tolist(egress.value["cidr_blocks"])
      ipv6_cidr_blocks = tolist(egress.value["ipv6_cidr_blocks"])
    }
  }
...
}

variables.tf

...
    ingress_security_group=[{
            description      = "http from VPC"
            from_port        = 80
            to_port          = 80
            protocol         = "tcp"
            cidr_blocks      = ["0.0.0.0/0"]
            ipv6_cidr_blocks = ["::/0"]
        },
        {
            description      = "TLS from VPC"
            from_port        = 443
            to_port          = 443
            protocol         = "tcp"
            cidr_blocks      = ["0.0.0.0/0"]
            ipv6_cidr_blocks = ["::/0"]
        }
    ]
    egress_security_group=[{
            from_port        = 0
            to_port          = 0
            protocol         = "all"
            cidr_blocks      = ["0.0.0.0/0"]
            ipv6_cidr_blocks = ["::/0"]
        }
    ]
...

My purpose is to use dynamic blocks expression to iterate over ingress and egress objects whenever I add a rule

Terraform plan

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # module.ec2.aws_security_group.main will be created
  + resource "aws_security_group" "main" {
      ...
      + ingress                = [
          + {
              + cidr_blocks      = [
                  + "0.0.0.0/0",
                ]
              + description      = "TLS from VPC"
              + from_port        = 443
              + ipv6_cidr_blocks = [
                  + "::/0",
                ]
              + prefix_list_ids  = []
              + protocol         = "tcp"
              + security_groups  = []
              + self             = false
              + to_port          = 443
            },
          + {
              + cidr_blocks      = [
                  + "0.0.0.0/0",
                ]
              + description      = "http from VPC"
              + from_port        = 80
              + ipv6_cidr_blocks = [
                  + "::/0",
                ]
              + prefix_list_ids  = []
              + protocol         = "tcp"
              + security_groups  = []
              + self             = false
              + to_port          = 80
            },
        ]
    ...
    }

Plan: 1 to add, 0 to change, 0 to destroy.

Reference:

Upvotes: 1

Related Questions