Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

297
Views
Variable values in Terraform for aws security groups

I am new to terraform and trying to create an AWS security group with ingress and egress rules. Rather than hardcoding the values and creating multiple ingress and egress blocks, I am trying to make use of terraform lookup function.

main.tf file looks like this:

provider "aws" {
  version                 = "~> 2.0"
  region                  = var.region
  profile                 = var.profile
}

resource "aws_security_group" "this" {
  name = "test-sg"
  description = "test security group"

  dynamic "ingress" {
    for_each = var.ingress_rules
    content {
      description      = lookup(ingress.value, "description", null)
      from_port        = lookup(ingress.value, "from_port", null)
      to_port          = lookup(ingress.value, "to_port", null)
      protocol         = lookup(ingress.value, "protocol", null)
      cidr_blocks      = lookup(ingress.value, "cidr_blocks", null)
    }
  }

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

  tags = {
    Name = "test-sg"
  }
}

variables.tf file looks like this

variable "ingress_rules" {
  default     = {
    "description" = ["For HTTP", "For SSH"]
    "from_port"   = ["80", "22"]
    "to_port"     = ["80", "22"]
    "protocol"    = ["tcp", "tcp"]
    "cidr_blocks" = ["0.0.0.0/0", "0.0.0.0/0"]
  }
  type        = map(list(string))
  description = "Security group rules"
}

When I run terraform validate it shows configuration is valid, but when I run terraform plan, it shows the following error:

 ingress.value is list of string with 2 elements
 
 Invalid value for "inputMap" parameter: lookup() requires a map as the first
 argument.

After spending a long time still, I am not able to figure out how to solve this error. What is the correct way to pass lookup values to variables.tf file.

over 4 years ago · Santiago Trujillo
2 answers
Answer question

0

You have constructed your variable's default value as five maps with a string key and list of strings value. You probably wanted a single map with a series of keys and values associated with the various attributes of your ingress rule. You can update the variable value accordingly like:

variable "ingress_rules" {
  default     = {
    "my ingress rule" = {
      "description" = "For HTTP"
      "from_port"   = "80"
      "to_port"     = "80"
      "protocol"    = "tcp"
      "cidr_blocks" = ["0.0.0.0/0"]
    },
    "my other ingress rule" = {
      "description" = "For SSH"
      "from_port"   = "22"
      "to_port"     = "22"
      "protocol"    = "tcp"
      "cidr_blocks" = ["0.0.0.0/0"]
    }
  }
  type        = map(any)
  description = "Security group rules"
}

Now, in your for_each iterator, the value of the first ingress.key will be my ingress rule, and the value of the first ingress.value will be your entire map of keys and strings. Before, the first ingress.key would have been description, and the first value would have been ["For HTTP", "For SSH"]. That is why you were getting that error: you cannot lookup a value with key description from a list of ["For HTTP", "For SSH"]. After making this variable value update, you should have your expected behavior.

Note that you can refine your type further with an object:

default = {
  "my ingress rule" = {
    description = "For HTTP"
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  },
  "my other ingress rule" = {
    description = "For SSH"
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
}
type = map(object({
  description = string
  from_port   = number
  to_port     = number
  protocol    = string
  cidr_blocks = list(string)
}))
over 4 years ago · Santiago Trujillo Report

0

I would implement it as follows:

resource "aws_security_group" "test_security_group" {
  name = "test-sg"
  description = "test security group"

  dynamic "ingress" {
    for_each = var.sg_ingress_rules
    content {
      from_port   = ingress.value.from_port
      to_port     = ingress.value.to_port
      protocol    = ingress.value.protocol
      cidr_blocks = ingress.value.cidr_blocks
      description = ingress.value.description
    }
  }

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

  tags = {
    Name = "test security group"
  }
}

variables.tf

variable "sg_ingress_rules" {
  description = "Ingress security group rules"
  type        = map
}

my_vars.tfvars

sg_ingress_rules = {
  "1" = {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
    description = "HTTP"
  },
  "2" = {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["<my_private_ip>/32"]
    description = "SSH"
  }
}

Hope it helps to understand further!

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!