Abhishek Kumar
Abhishek Kumar

Reputation: 452

Terraform: Inappropriate value for attribute "ingress" while creating SG

I'm creating a Security group using terraform, and when I'm running terraform plan. It is giving me an error like some fields are required, and all those fields are optional.

Terraform Version: v1.0.5

AWS Provider version: v3.57.0

main.tf

resource "aws_security_group" "sg_oregon" {
  name        = "tf-sg"
  description = "Allow web traffics"
  vpc_id      = aws_vpc.vpc_terraform.id

  ingress = [
    {
      description      = "HTTP"
      from_port        = 80
      to_port          = 80
      protocol         = "tcp"
      cidr_blocks      = ["0.0.0.0/0"]  
    },
  {
      description      = "HTTPS"
      from_port        = 443
      to_port          = 443
      protocol         = "tcp"
      cidr_blocks      = ["0.0.0.0/0"]  
  },

    {
      description      = "SSH"
      from_port        = 22
      to_port          = 22
      protocol         = "tcp"
      cidr_blocks      = ["0.0.0.0/0"]  
    }
  ]


  egress = [
    {
      description      = "for all outgoing traffics"
      from_port        = 0
      to_port          = 0
      protocol         = "-1"
      cidr_blocks      = ["0.0.0.0/0"]
      ipv6_cidr_blocks = ["::/0"]
      
    }
  ]

  tags = {
    Name = "sg-for-subnet"
  }
}

error in console

│ Inappropriate value for attribute "ingress": element 0: attributes "ipv6_cidr_blocks", "prefix_list_ids", "security_groups", and "self" are required.

│ Inappropriate value for attribute "egress": element 0: attributes "prefix_list_ids", "security_groups", and "self" are required.

I'm following this doc: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group

Any help would be appreciated.

Upvotes: 15

Views: 9761

Answers (3)

Robin Bowes
Robin Bowes

Reputation: 115

Another useful approach is to put the rules in a variable, and use a loop in the resource, something like this:

locals {
  ingress_rules = [
    {
      description      = "HTTP"
      from_port        = 80
      to_port          = 80
      protocol         = "tcp"
      cidr_blocks      = ["0.0.0.0/0"]  
    },
    {
      description      = "HTTPS"
      from_port        = 443
      to_port          = 443
      protocol         = "tcp"
      cidr_blocks      = ["0.0.0.0/0"]  
    },
    {
      description      = "SSH"
      from_port        = 22
      to_port          = 22
      protocol         = "tcp"
      cidr_blocks      = ["0.0.0.0/0"]  
    }
  ]
}

resource "aws_security_group" "sg_oregon" {
  name        = "tf-sg"
  description = "Allow web traffics"
  vpc_id      = aws_vpc.vpc_terraform.id

  ingress = [
    for rule in local.ingress_rules : {
      cidr_blocks              = lookup(rule, "cidr_blocks", null)
      description              = lookup(rule, "description", null)
      from_port                = lookup(rule, "from_port", null)
      ipv6_cidr_blocks         = lookup(rule, "ipv6_cidr_blocks", null)
      prefix_list_ids          = lookup(rule, "prefix_list_ids", null)
      protocol                 = lookup(rule, "protocol", null)
      security_groups          = lookup(rule, "security_groups", null)
      self                     = lookup(rule, "self", null)
      source_security_group_id = lookup(rule, "source_security_group_id", null)
      to_port                  = lookup(rule, "to_port", null)
    }
  ]
}

You could even make a simple module that you use something like:

module "sg_oregon" {
  source = ... # wherever
  name = "tf-sg"
  description = "Allow web traffics"
  vpc_id      = aws_vpc.vpc_terraform.id
  ingress_rules = local.ingress_rules
  egress_rules = local.egress_rules
  tags = local.tags
}

Upvotes: 1

Jon Burgess
Jon Burgess

Reputation: 2115

You can avoid having to specify the so called optional parameters by declaring the rules in an alternative format:

resource "aws_security_group" "sg_oregon" {
  name        = "tf-sg"
  description = "Allow web traffics"
  vpc_id      = aws_vpc.vpc_terraform.id

  ingress {
    description = "HTTP"
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  ingress {
    description = "HTTPS"
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  ingress {
    description = "SSH"
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  egress {
    description      = "for all outgoing traffics"
    from_port        = 0
    to_port          = 0
    protocol         = "-1"
    cidr_blocks      = ["0.0.0.0/0"]
    ipv6_cidr_blocks = ["::/0"]

  }

  tags = {
    Name = "sg-for-subnet"
  }
}

Upvotes: 8

Marcin
Marcin

Reputation: 238299

Since you are using Attributes as Blocks you have to provide values for all options:

resource "aws_security_group" "sg_oregon" {
  name        = "tf-sg"
  description = "Allow web traffics"
  vpc_id      = aws_vpc.vpc_terraform.id

  ingress = [
    {
      description      = "HTTP"
      from_port        = 80
      to_port          = 80
      protocol         = "tcp"
      cidr_blocks      = ["0.0.0.0/0"]  
      ipv6_cidr_blocks = []
      prefix_list_ids = []
      security_groups = []
      self = false
    },
  {
      description      = "HTTPS"
      from_port        = 443
      to_port          = 443
      protocol         = "tcp"
      cidr_blocks      = ["0.0.0.0/0"]  
      ipv6_cidr_blocks = []
      prefix_list_ids = []
      security_groups = []
      self = false      
  },

    {
      description      = "SSH"
      from_port        = 22
      to_port          = 22
      protocol         = "tcp"
      cidr_blocks      = ["0.0.0.0/0"]  
      ipv6_cidr_blocks = []
      prefix_list_ids = []
      security_groups = []
      self = false      
    }
  ]


  egress = [
    {
      description      = "for all outgoing traffics"
      from_port        = 0
      to_port          = 0
      protocol         = "-1"
      cidr_blocks      = ["0.0.0.0/0"]
      ipv6_cidr_blocks = ["::/0"]
      prefix_list_ids = []
      security_groups = []
      self = false
    }
  ]

  tags = {
    Name = "sg-for-subnet"
  }
}

Upvotes: 32

Related Questions