- I’ve created primary_sg, secondary_sg_tcpci, secondary_sg_tcpqa, secondary_sq_tcpprod security groups. primary_sg has three outbound rules to it and each one is associated with secondary_sg securitygroup as destination.
- For secondary, I created three security groups secondary_sg_tcpci, secondary_sg_tcpqa and secondary_sg_tcpprod. Each of these security group inbound rules are associated again with same primary_sg securitygroup as source in it and referring to some local variables.
main.tf
data "aws_vpc" "default" {
id = "vpc-1234"
}
data "aws_security_groups" "server_sg"{
tags = {
name = "server_sg"
}
}
locals {
vpc_id = data.aws_vpc.default.id
server_jumpbox_security_groups = data.aws_security_groups.server_sg.id
}
####### primary_sg###########
resource "aws_security_group" "primary_sg" {
name = "primary_security_group"
description = "Allows outbound rules"
vpc_id = local.vpc_id
}
resource "aws_security_group_rule" "rule_01" {
type = "egress"
from_port = 22
to_port = 22
protocol = "tcp"
source_security_group_id = aws_security_group.secondary_sg_tcpci.id ## Associating secondary_sg_tcpci as destination security group ####
description = "primary_sg rule01"
security_group_id = aws_security_group.primary_sg.id
}
resource "aws_security_group_rule" "rule_02" {
type = "egress"
from_port = 22
to_port = 22
protocol = "tcp"
source_security_group_id = aws_security_group.secondary_sg_tcpqa.id ## Associating secondary_sg_tcpqa as destination security group ####
description = "primary_sg rule02"
security_group_id = aws_security_group.primary_sg.id
}
resource "aws_security_group_rule" "rule_03" {
type = "egress"
from_port = 22
to_port = 22
protocol = "tcp"
source_security_group_id = aws_security_group.secondary_sg_tcpprod.id ## Associating secondary_sg_tcpprod as destination security group ####
description = "primary_sg rule02"
security_group_id = aws_security_group.primary_sg.id
}
########secondary_sg#########
resource "aws_security_group" "secondary_sg_tcpci" {
name = "secondary_sg_tcpci"
description = "RDS SG for TCPCI env"
vpc_id = data.aws_vpc.default.id
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
security_groups = [local.server_jumpbox_security_groups]
description = "Server SG"
}
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
security_groups = ["${aws_security_group.primary_sg.id}"]
description = "Secondary SG"
}
lifecycle {
create_before_destroy = true
}
}
resource "aws_security_group" "secondary_sg_tcpqa" {
name = "secondary_sg_tcpqa"
description = "RDS SG for TCPQA env"
vpc_id = data.aws_vpc.default.id
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
security_groups = [local.server_jumpbox_security_groups]
description = "Server SG"
}
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
security_groups = ["${aws_security_group.primary_sg.id}"]
description = "Secondary SG"
}
lifecycle {
create_before_destroy = true
}
}
resource "aws_security_group" "secondary_sg_tcpprod" {
name = "secondary_sg_tcpprod"
description = "RDS SG for TCPQA env"
vpc_id = data.aws_vpc.default.id
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
security_groups = [local.server_jumpbox_security_groups]
description = "Server SG"
}
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
security_groups = ["${aws_security_group.primary_sg.id}"]
description = "Secondary SG"
}
lifecycle {
create_before_destroy = true
}
}
I tried using for_each loop. main.tf
resource "aws_security_group" "secondary_sg_tcpci" {
for_each = var.config
name = "${each.key}-rds"
description = "RDS SG for TCPCI env"
vpc_id = data.aws_vpc.default.id
dynamic "ingress" {
for_each = var.ingress_rules
iterator = port
content {
from_port = ingress.value.port
to_port = ingress.value.port
protocol = ingress.value.protocol
security_groups = ["${aws_security_group.primary_sg.id}"]
}
}
}
resource "aws_security_group" "primary_sg" {
name = "primary_security_group"
description = "Allows outbound rules"
vpc_id = local.vpc_id
}
resource "aws_security_group_rule" "rule_01" {
type = "egress"
from_port = 22
to_port = 22
protocol = "tcp"
source_security_group_id = aws_security_group.secondary_sg_tcpci.id ## Associating secondary_sg_tcpci as destination security group ####
description = "primary_sg rule01"
security_group_id = aws_security_group.primary_sg.id
}
resource "aws_security_group_rule" "rule_02" {
type = "egress"
from_port = 22
to_port = 22
protocol = "tcp"
source_security_group_id = aws_security_group.secondary_sg_tcpqa.id ## Associating secondary_sg_tcpqa as destination security group ####
description = "primary_sg rule02"
security_group_id = aws_security_group.primary_sg.id
}
vars.tf
variable "config" {
description = "Security groups configuration"
type = map(object({
name = string
}))
default = {
"sg-1" = {
name = "sg-1"
}
"sg-2" = {
name = "sg-2"
}
}
}
variable "ingress_rules" {
type = map(object({
port = number
protocol = string
}))
default = {
"22" = {
cidr_block = ["0.0.0.0/0"]
port = 22
protocol = "tcp"
}
"22" = {
cidr_block = ["0.0.0.0/0"]
port = 22
protocol = "tcp"
}
}
}
CodePudding user response:
Since you are creating the SG with for_each
, you can only access the SG attributes but using proper keys. There is also a small error in other parts of code as in the dynamic
block you are setting the iterator
and then later on in the content you are not using it, so you can drop it (as it will default to the dynamic block name which is ingress
):
resource "aws_security_group" "secondary_sg_tcpci" {
for_each = var.config
name = "${each.key}-rds"
description = "RDS SG for TCPCI env"
vpc_id = data.aws_vpc.default.id
dynamic "ingress" {
for_each = var.ingress_rules
content {
from_port = ingress.value.port
to_port = ingress.value.port
protocol = ingress.value.protocol
security_groups = [aws_security_group.primary_sg.id]
}
}
}
resource "aws_security_group" "primary_sg" {
name = "primary_security_group"
description = "Allows outbound rules"
vpc_id = local.vpc_id
}
resource "aws_security_group_rule" "rule_01" {
for_each = aws_security_group.secondary_sg_tcpci
type = "egress"
from_port = 22
to_port = 22
protocol = "tcp"
source_security_group_id = each.value.id # <--- this is how you would reference the security IDs for all the SGs created with `for_each`
description = "primary_sg rule01"
security_group_id = aws_security_group.primary_sg.id
}
This is only for the one SG created with for_each
. This technique is called resource chaining with for_each
[1]. If you need to repeat the same for other SGs (tcpqa
, tcpprod
etc.) you would have to adjust the rest of the code.