12

I've been writing reusable modules for an AWS infrastructure. In creating a security group, my approach is to create a generic module for a security group and provide a list of ports in the control code. However, when using count it creates a security group each for every port. Is there a way around this to iterate a specific part like in this scenario?

SG Module

resource "aws_security_group" "this" {
  name        = var.sg_name
  description = var.description
  vpc_id      = var.vpc_id

  count = min(length(var.ingress_ports))
  ingress {
    from_port   = var.ingress_ports[count.index]
    to_port     = var.ingress_ports[count.index]
    protocol    = "tcp"
    cidr_blocks = ["10.0.0.0/8"]
  }

  egress {
    from_port       = 0
    to_port         = 0
    protocol        = "-1"
    cidr_blocks     = ["0.0.0.0/0"]
  }
}

Control Code

module "qliksense_sg" {
  source = "modules/aws-sg"

  sg_name = "My-SG"
  description = "A security group"
  vpc_id = module.vpc.vpc_id

  ingress_ports = ["80", "443"]
}
Udara Jayawardana
  • 1,073
  • 2
  • 14
  • 27

1 Answers1

20

To do this in Terraform 0.12 you can use dynamic blocks. In fact, the example given in that documentation link is for adding ingress rules over a list of ports:

resource "aws_security_group" "example" {
  name = "example" # can use expressions here

  dynamic "ingress" {
    for_each = var.service_ports
    content {
      from_port = ingress.value
      to_port   = ingress.value
      protocol  = "tcp"
    }
  }
}
ydaetskcoR
  • 53,225
  • 8
  • 158
  • 177
  • Thank you Tom! It works. For anyone looking, this example helps too. https://github.com/hashicorp/terraform-guides/tree/master/infrastructure-as-code/terraform-0.12-examples/dynamic-blocks-and-splat-expressions – Udara Jayawardana Dec 04 '19 at 04:59