Create AWS security group and rules dynamically

Hello experts!
I need to create 3 different application security groups and its appropriate rules. Each security group has different set of rules (ingress and egress with different ports and different cidr_blocks)

I was trying to achieve with the below code

# Application Security Group Rule creation
locals {
  rule_set1= {
    "app1"  = { port = ["8445", "22"], source_ip = ["192.168.0.1/32", "192.168.0.2/32"] },
    "app2"  = { port = ["8443"], source_ip = ["10.0.0.9/32"] },
    "app3" = { port = ["443"], source_ip = ["10.0.0.10/32"] }
  }

  rule_set2= {
    "app1"  = { port = ["1521", "443"], source_ip = ["192.168.0.5/32", "192.168.0.6/32"] },
    "app2"  = { port = ["8445"], source_ip = ["10.0.0.21/32"] },
    "app3" = { port = ["22"], source_ip = ["10.0.0.22/32"] }
  }
}

module "app_sg" {
 for_each = local.rule_set1
  source              = "../modules/sg"  # Change the path accordingly
  description         = "${each.key} Security Group"
  sg_name             = each.key
  from_port           = each.value.port
  to_port             = each.value.port
  src_ip              = each.value.source_ip
}

## Child module under (../module/sg)
resource "aws_security_group" "dev_test" {
  description = "SG for web server"

  ingress {
    from_port       = var.from_port
    protocol        = "tcp"
    to_port         = var.to_port
    cidr_blocks     = var.src_ip
    description     = "allow ingress port"
  }

  egress {
    from_port       = var.from_port
    protocol        = "tcp"
    to_port         = var.to_port
    cidr_blocks     = var.src_ip
    description     = "allow egress port"
  }
}
  
  
variable "sg_name" {
  default = ""
}

variable "description" {
  default = ""
}

variable "from_port" {
  default = ""
}

variable "to_port" {
  default = ""
}

variable "src_ip" {
  default = ""
}

There may be some erroneous from the above code blocks. Please suggest me the solution for this scenario. I need to this with minimal code and re-usable. Should be easy for me to manage (add/remove) the rules in the future as well.

resource “aws_security_group” “sec_rule1” {
vpc_id = aws_vpc.vpc000.id
name = “secgrp000”
dynamic “ingress” {
for_each = var.ports1
content {
from_port = ingress.value
to_port = ingress.value
protocol = “tcp”
cidr_blocks = [var.mynet[0],var.mynet[1] ]
}
}
dynamic “ingress” {
for_each = var.ports2
content {
from_port = ingress.value
to_port = ingress.value
protocol = “tcp”
cidr_blocks = [var.mynet[2]]
}
}
dynamic “ingress” {
for_each = var.ports3
content {
from_port = ingress.value
to_port = ingress.value
protocol = “tcp”
cidr_blocks = [var.mynet[3]]
}
}
dynamic “ingress” {
for_each = var.ports4
content {
from_port = ingress.value
to_port = ingress.value
protocol = “tcp”
cidr_blocks = [var.mynet[6] ,var.mynet[7]]
}
}
dynamic “ingress” {
for_each = var.ports5
content {
from_port = ingress.value
to_port = ingress.value
protocol = “tcp”
cidr_blocks = [var.mynet[4] ]
}
}
dynamic “ingress” {
for_each = var.ports6
content {
from_port = ingress.value
to_port = ingress.value
protocol = “tcp”
cidr_blocks = [var.mynet[5] ]
}
}
dynamic “ingress” {
for_each = var.ports6
content {
from_port = ingress.value
to_port = ingress.value
protocol = “tcp”
cidr_blocks = [var.mynet[3]]
}
}
egress {
cidr_blocks = [“0.0.0.0/0”]
from_port = 0
protocol = “-1”
to_port = 0
}

}

variable “ports1” {
type = list(number)
default = [ 22 , 8445]
}
variable “ports2” {
type = list(number)
default = [ 8443 ]
}
variable “ports3” {
type = list(number)
default = [ 443 ]
}
variable “ports4” {
type = list(number)
default = [ 1521 , 443 ]
}
variable “ports5” {
type = list(number)
default = [ 8445 ]
}
variable “ports6” {
type = list(number)
default = [ 22 ]
}
variable “mynet” {
type = list
default = [ “192.168.0.1/32” , “192.168.0.2/32” , “10.0.0.9/32”,“10.0.0.10/32”,“10.0.0.21/32”,“10.0.0.22/32”,“192.168.0.5/32”,“192.168.0.6/32”]
}

1 Like