1

I use the aws provider. For each security group I specify same rule for ssh. How to extract it to a variable and assign to aws_security_group.ingress list?

What do I expect:

variable "ssh_ingress" {
  default = {
    from_port = 22
    protocol = "tcp"
    to_port = 22
    description = "SSH for administration."
  }
}
resource "aws_security_group" "main" {
  ingress += var.ssh_ingress // That not work.

  ingress {
    from_port = 0
    protocol = "-1"
    to_port = 0
    self = true
  }

}
Marcin
  • 215,873
  • 14
  • 235
  • 294
Belenot
  • 248
  • 1
  • 3
  • 10

2 Answers2

1

You could use aws_security_group_rule add rules to existing security group.

For example:

variable "ssh_ingress" {
  default = {
    from_port = 22
    protocol = "tcp"
    to_port = 22
    description = "SSH for administration."
  }
}

resource "aws_security_group" "main" {
  name        = "allow_tls"
  description = "Allow TLS inbound traffic"
  vpc_id      = data.aws_vpc.main.id
}

resource "aws_security_group_rule" "default" {
  type              = "ingress"
  from_port         = 0
  to_port           = 0
  protocol          = -1
  self              = true
  security_group_id = aws_security_group.main.id
}

resource "aws_security_group_rule" "example" {
  type              = "ingress"
  from_port         = var.ssh_ingress.from_port
  to_port           = var.ssh_ingress.to_port
  protocol          = var.ssh_ingress.protocol
  cidr_blocks       = ["10.0.0.0/11"]
  security_group_id = aws_security_group.main.id
}

Alternative wiht multiple inline ingress rules

resource "aws_security_group" "main" {
  name        = "allow_tls"
  description = "Allow TLS inbound traffic"
  vpc_id      = data.aws_vpc.main.id
  
  ingress {
    from_port = 0
    protocol = "-1"
    to_port = 0
    self = true
  }
  
 ingress {
   from_port         = var.ssh_ingress.from_port
   to_port           = var.ssh_ingress.to_port
   protocol          = var.ssh_ingress.protocol
   cidr_blocks       = ["10.0.0.0/11"]
  }
  
}
Marcin
  • 215,873
  • 14
  • 235
  • 294
  • Thanks, but What about this Note on aws_security_group doc page. Won't inline ingress rule be overriden? ```Terraform currently provides both a standalone Security Group Rule resource (a single ingress or egress rule), and a Security Group resource with ingress and egress rules defined in-line. At this time you cannot use a Security Group with in-line rules in conjunction with any Security Group Rule resources. Doing so will cause a conflict of rule settings and will overwrite rules.``` https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group#cidr_blocks – Belenot Jan 07 '21 at 07:35
  • @Belenot You are right. It will deploy, but better not to take a risk. Then you can have all the rules separate or use multiple inline rules. I will updated the answer. – Marcin Jan 07 '21 at 07:40
0

You can write out an ingress block with references to the attributes of your variable:

variable "ssh_ingress" {
  type = object({
    from_port   = number
    to_port     = number
    protocol    = string
    description = string
  })

  default = {
    from_port = 22
    protocol = "tcp"
    to_port = 22
    description = "SSH for administration."
  }
}

resource "aws_security_group" "main" {
  ingress {
    from_port   = var.ssh_ingress.from_port
    protocol    = var.ssh_ingress.protocol
    to_port     = var.ssh_ingress.to_port
    description = var.ssh_ingress.description
  }
}

The ingress block itself is a static structure rather than a value. You can populate its arguments with dynamic values, but you can't generate the arguments themselves dynamically. Terraform verifies that all of the expected arguments are present before considering the configuration to be valid.

However, Terraform considers the value null in a block like this to be equivalent to omitting the argument, so if the caller of your module were to set description = null, for example, then the AWS provider will see that in exactly the same way as having omitted the description argument altogether.

Martin Atkins
  • 62,420
  • 8
  • 120
  • 138