Search code examples
amazon-web-servicesterraform-provider-aws

Security groups should be able to communicate to other security groups


My company requires that I we expressly specify all allowed ports and protocols in security group ingress rules. I would like to have a long list of ports protocols and security groups to allow ingress/egress for

from_port, to_port, protocol, security_group_that_port_protocol_restriction_applies_to  

The below example has the problem that the "master-sg-ingress-security-groups" variable needs to have the security groups to be defined.

resource "aws_security_group" "master_lb_sg" {
....
}


resource "aws_security_group" "worker_sg" {
  ......
}


########
####### list of port protocols and security groups to create ingress blocks for.   Problem is that security groups to not exist at variable creation time.
########

variable "master-sg-ingress-security-groups" {
  depends_on  = [aws_security_group.master_lb_sg, aws_security_group.worker_sg]

  description = "List of port numbers for specific security group.  company bans allowing all ports and protocols.  "

  type        = map(any)
  default = {
    "ingress1" = [80, 80, "TCP", aws_security_group.master_lb_sg],
    "ingress2" = [443, 443, "TCP", aws_security_group.master_lb_sg],
    "ingress3" = [3398,3398, "RDP", aws_security_group.bastion_host_sg],
    
     ....
   
     "ingress4" = [1024, 1024, "UDP", aws_security_group.worker_sg]
  }
}

#####
####  I want to iterate over the above list of security groups and create dynamic ingress rules but other security groups do not exist
####

resource "aws_security_group" "test" {
  depends_on  = [aws_security_group.master_lb_sg, aws_security_group.worker_sg]
  provider    = aws.region_master
  name        = "master-sg"
  description = "security group for Jenkins master"
  vpc_id      = aws_vpc.vpc_master.id

  dynamic "ingress" {
    # this for_each is not identical to for_each in line 21
    for_each = var.master-sg-ingress-security-groups
    content {
      from_port   = ingress.value[0]
      to_port     = ingress.value[1]
      protocol    = ingress.value[2]
      security_group = ingress[3]
    }
  }
}

I am think ing I have to just copy paste blocks of text for each ingress


Solution

  • Is there a way to get around the problem of aws_security_group.worker_sg in a variable

    Sadly not from TF itself. Variables must be fully defined when you run your script. But you could maybe modify master-sg-ingress-security-groups into a local variable. This way you could construct your map which includes other variables.

    So depending exactly on your use-case, you could maybe have a base variable called base-master-sg-ingress-security-groups, and then in locals construct a final map which would containe references to other existing SGs.

    Alternatively, you could split your TF script into two parts. The first one would deploy core SGs and output their IDs. Then these IDs would be used as input variables for the second part which would deploy SGs that reference the core ones.