Search code examples
amazon-web-servicesterraformterraform-provider-awsaws-security-group

How to create module for security group in terraform


I have this resource to make security groups and have several entry rules.

These files are inside the "security-group" folder because I have to create a module for it.

Main.tf

resource "aws_security_group" "main" {
   name   = var.sg_name

   dynamic "ingress" {
       for_each = local.ingress_rules

       content {
           description = ingress.value.description
           from_port   = ingress.value.port
           to_port     = ingress.value.port
           protocol    = "tcp"
           cidr_blocks = ["0.0.0.0/0"]
       }
   }
}

variable.tf

locals {
   ingress_rules = [{
       port        = 443
       description = "Port 443"
   },
   {
       port        = 80
       description = "Port 80"
   }]
}

Now outside of the modules/security-group/ folder I have the main .tf file where I want to call that module to create security groups.

module "security_group" {
 source = "./modules/security-group"

   dynamic "ingress" {
       for_each = local.ingress_rules

       content {
           description = ingress.value.description
           from_port   = ingress.value.port
           to_port     = ingress.value.port
           protocol    = "tcp"
           cidr_blocks = ["0.0.0.0/0"]
       }
   }
}

│ Error: Unsupported block type
│
│   on main.tf line 29, in module "security_group":
│   29:         dynamic "ingress" {
│
│ Blocks of type "dynamic" are not expected here.
╵

How else can I call this module to create the rules and other necessary things? Many thanks in advance


Solution

  • There are no dynamic blocks for modules. You have to pass your rules as regular variables to the module, not local values:

    variable "ingress_rules" {
      default = [{
           from_port   = 443
           to_port     = 443
           description = "Port 443"
       },
       {
           from_port   = 80
           to_port     = 80
           description = "Port 80"
       }]
    }
    
    resource "aws_security_group" "main" {
       name   = var.sg_name
    
       dynamic "ingress" {
           for_each = var.ingress_rules
    
           content {
               description = ingress.value.description
               from_port   = ingress.value.from_port   
               to_port     = ingress.value.to_port     
               protocol    = "tcp"
               cidr_blocks = ["0.0.0.0/0"]
           }
       }
    }
    

    then in parent folder:

    module "security_group" {
     source = "./modules/security-group"
    
     ingress_rules =    [
           {
               description =  "description"
               from_port   = 20
               to_port     = 20
               protocol    = "tcp"
               cidr_blocks = ["0.0.0.0/0"]
         }
       ] 
    }
    

    You have to fix all those names of your attributes. You can't just mix port and to_port.