How to attach 1st SG to 1st instance and 2nd SG to 2nd Instance

Hi Experts,

I’m new to Terraform. In my code I just try to create vpc, one public subnet, one private subnet, two security groups and two EC2 Instances.
How to attach a 1st Security group to 1st EC2 Instance and 2nd Security group to 2nd EC2 Instance. Based on my code both security groups is attaching to both Instances.

#Create VPC 
resource "aws_vpc" "test1" {
  cidr_block = var.VPCCIDR
  tags = {
    Name = var.VPCtag_name
  }
}

#Create Public Subnet
resource "aws_subnet" "Man-test1" {
  vpc_id                  = aws_vpc.test1.id
  cidr_block              = var.Subnetpublic
  map_public_ip_on_launch = "true"
  tags = {
    Name = var.Publicsubnet_name
  }
}

#Create Private Subnet
resource "aws_subnet" "Man-test2" {
  vpc_id     = aws_vpc.test1.id
  cidr_block = var.Subnetprivate
  tags = {
    Name = var.Privatesubnet_name
  }
}

#Create Securitygroup for 1st Instance
resource "aws_security_group" "testsg" {
  name   = var.sg_name
  vpc_id = aws_vpc.test1.id
  ingress {
    from_port   = var.ssh
    to_port     = var.ssh
    protocol    = "tcp"
    cidr_blocks = ["10.0.2.24/32"]
  }
  ingress {
    from_port   = var.http
    to_port     = var.http
    protocol    = "tcp"
    cidr_blocks = ["10.0.2.24/32"]
  }
  ingress {
    from_port   = -1
    to_port     = -1
    protocol    = "icmp"
    cidr_blocks = ["10.0.2.24/32"]
  }
  egress {
    from_port        = 0
    to_port          = 0
    protocol         = "-1"
    cidr_blocks      = ["0.0.0.0/0"]
    ipv6_cidr_blocks = ["::/0"]
  }
  tags = {
    Name = var.sgtag_name
  }
}

#Create Securitygroup for 2nd Instance
resource "aws_security_group" "privatesg" {
  name   = var.privsg_name
  vpc_id = aws_vpc.test1.id
  ingress {
    from_port   = -1
    to_port     = -1
    protocol    = "icmp"
    cidr_blocks = ["10.0.1.0/24"]
  }
  egress {
    from_port        = 0
    to_port          = 0
    protocol         = "-1"
    cidr_blocks      = ["0.0.0.0/0"]
    ipv6_cidr_blocks = ["::/0"]
  }
  tags = {
    Name = var.sgtag_name
  }
}

#Create two ec2 resource
resource "aws_instance" "Ec2" {
  count                  = length(var.EC2tag)
  ami                    = var.AMI
  instance_type          = var.Instancetype
  subnet_id              = element([aws_subnet.Man-test1.id, aws_subnet.Man-test2.id], count.index)
  vpc_security_group_ids = ["${aws_security_group.testsg.id}","${aws_security_group.privatesg.id}"]
  tags = {
    Name = element(var.EC2tag, count.index)
  }
}

Actually I’d recommend using for_each instead of count for creating multiple resources (even for the SG and the ec2 instance).

Apart from that you could use a locals block to generate a list of the SG.

locals {
  all_sgs = ["${aws_security_group.testsg.id}","${aws_security_group.privatesg.id}"]
}



#Create two ec2 resource
resource "aws_instance" "Ec2" {
  count                  = length(var.EC2tag)
  ami                    = var.AMI
  instance_type          = var.Instancetype
  subnet_id              = element([aws_subnet.Man-test1.id, aws_subnet.Man-test2.id], count.index)
  vpc_security_group_ids = tolist(element(local.all_sgs,count.index))
  tags = {
    Name = element(var.EC2tag, count.index)
  }
}
....



Hi @tbugfinder, Thanks for the information, But it not worked getting Error Invalid function argument.

 Error: Invalid function argument
│
│   on main.tf line 60, in resource "aws_instance" "Ec2":
│   60:   vpc_security_group_ids = tolist(element(local.all_sgs, count.index))
│     ├────────────────
│     │ count.index is 1
│     │ local.all_sgs is tuple with 2 elements
│
│ Invalid value for "v" parameter: cannot convert string to list of any single type.

It was rather meant as dummy code than ready to execute.

vpc_security_group_ids = [element(local.all_sgs, count.index)]

Hi @tbugfinder Thanks for your reply, It was worked with out using locals functions.

vpc_security_group_ids = [element([aws_security_group.testsg.id, aws_security_group.privatesg.id], count.index)]