Managing AWS Security Group Terraform: Configuration, Examples & Best Practices

AWS Security Group Terraform

Table of Contents

Get up to 50% off now

Become a partner with CyberPanel and gain access to an incredible offer of up to 50% off on CyberPanel add-ons. Plus, as a partner, you’ll also benefit from comprehensive marketing support and a whole lot more. Join us on this journey today!

Security is one of the most important elements of any cloud architecture and in AWS, Security Groups act as firewalls to control the inbound and outbound traffic to your EC2 instances and other resources. While you can easily manage the AWS Console, doing so on a larger scale is extremely prone to human errors.   

This is where you need Terraform. The platform enables you to define and manage Security Groups as IaC, making the rules repeatable, version-controlled, and easy to audit. 

In this guide, we will learn how to create, manage, and scale AWS Security Group Terraform. 

What Are AWS Security Groups?

AWS Security Groups act as virtual firewalls for your EC2 instances and other AWS resources. They control all the inbound and outbound traffic based on the rules that you define. Each rule is defined for specific protocols, ports, and IP ranges. Key characteristics of an AWS Security Group are as follows: 

  1. Stateful means that if you allow inbound traffic on a part, the outbound response is automatically allowed. 
  2. AWS Security Groups are attached to the network interfaces and are typically applied to the EC2 instances. 
  3. One Security Group can be attached to multiple resources at one time, making it highly reusable. 

Why Use Terraform for Security Groups?

You can easily create Security Groups using the AWS Console manually, but Terraform offers multiple advantages. 

Tech Delivered to Your Inbox!

Get exclusive access to all things tech-savvy, and be the first to receive 

the latest updates directly in your inbox.

  • Define Security Groups as code and automate the deployments. 
  • Using Git, you can easily track changes and other version control systems. 
  • Prevent human-prone errors by enforcing predefined configurations. 
  • Easily modify and replicate groups across different environments. 
  • Seamless integration with other AWS infrastructures. 

Example: Basic Security Group Terraform

Here is an example Terraform configuration to setup an AWS Security Group with inbound SSH access from a certain IP range. 

resource “aws_security_group” “example_sg” {

  name        = “example-sg”

  description = “Allow SSH”

  vpc_id      = aws_vpc.main.id

  ingress {

    description = “SSH”

    from_port   = 22

    to_port     = 22

    protocol    = “tcp”

Enhance Your CyerPanel Experience Today!
Discover a world of enhanced features and show your support for our ongoing development with CyberPanel add-ons. Elevate your experience today!

    cidr_blocks = [“203.0.113.0/24”]

  }

  egress {

    from_port   = 0

    to_port     = 0

    protocol    = “-1”

    cidr_blocks = [“0.0.0.0/0”]

  }

  tags = {

    Name = “example-sg”

  }

}

Adding Ingress and Egress Rules

Terraform allows you to define the inbound traffic rules, known as ingress, and outbound traffic rules, known as the egress inside the Security Group to manage them separately. 

  • Ingress Rule Example

Allow HTTP (port 80) access from anywhere:

ingress {

  description = “HTTP”

  from_port   = 80

  to_port     = 80

  protocol    = “tcp”

  cidr_blocks = [“0.0.0.0/0”]

}

  • Egress Rule Example

Allow all outbound traffic (default behavior):

egress {

  from_port   = 0

  to_port     = 0

  protocol    = “-1” # all protocols

  cidr_blocks = [“0.0.0.0/0”]

}

You can also use security_group_rule resources to manage these rules independently of the security group.

Related Article: Terraform on AWS: A Complete Guide to Infrastructure Automation

Managing Security Group Rules Separately

Some use cases that are based in large environments or use modules, you might need to define ingress and egress rules separately from the primary Security Group. Terraform enables you to do this via the aws_security_group_rule resource.

  • Example: Standalone Security Group Rules

resource “aws_security_group” “web_sg” {

  name        = “web-sg”

  description = “Web Server SG”

  vpc_id      = aws_vpc.main.id

}

resource “aws_security_group_rule” “allow_http” {

  type              = “ingress”

  from_port         = 80

  to_port           = 80

  protocol          = “tcp”

  cidr_blocks       = [“0.0.0.0/0”]

  security_group_id = aws_security_group.web_sg.id

}

resource “aws_security_group_rule” “allow_all_egress” {

  type              = “egress”

  from_port         = 0

  to_port           = 0

  protocol          = “-1”

  cidr_blocks       = [“0.0.0.0/0”]

  security_group_id = aws_security_group.web_sg.id

}

This approach is modular and useful when reusing or dynamically creating rules via for_each or count.

Using Terraform Modules for Security Groups

Modules allow you to extract and reuse Security Group configurations across different environments and teams. 

  • Example Module Structure

Folder structure:

modules/

└── security_group/

    ├── main.tf

    ├── variables.tf

    └── outputs.tf

main.tf (inside module):

resource “aws_security_group” “this” {

  name        = var.name

  description = var.description

  vpc_id      = var.vpc_id

  dynamic “ingress” {

    for_each = var.ingress_rules

    content {

      from_port   = ingress.value.from_port

      to_port     = ingress.value.to_port

      protocol    = ingress.value.protocol

      cidr_blocks = ingress.value.cidr_blocks

    }

  }

  dynamic “egress” {

    for_each = var.egress_rules

    content {

      from_port   = egress.value.from_port

      to_port     = egress.value.to_port

      protocol    = egress.value.protocol

      cidr_blocks = egress.value.cidr_blocks

    }

  }

}

Then call it like this:

module “web_sg” {

  source      = “./modules/security_group”

  name        = “web-sg”

  description = “Allow web traffic”

  vpc_id      = aws_vpc.main.id

  ingress_rules = [

    {

      from_port   = 80

      to_port     = 80

      protocol    = “tcp”

      cidr_blocks = [“0.0.0.0/0”]

    }

  ]

  egress_rules = [

    {

      from_port   = 0

      to_port     = 0

      protocol    = “-1”

      cidr_blocks = [“0.0.0.0/0”]

    }

  ]

}

Common Pitfalls and Troubleshooting Guide For AWS Security Group Terraform 

IssueCauseSolution
InvalidCIDR errorCIDR block is incorrectly formattedUse valid CIDR notation, e.g., 0.0.0.0/0
Duplicate rule errorsRules are defined both in SG and via security_group_ruleUse only one method per rule set
Dependency issuesResource order isn’t clearUse depends_on or split modules clearly
Port mismatchFrom/To ports misconfiguredEnsure correct port ranges are set
VPC ID missingVPC not linked to SGPass correct vpc_id in the SG block
Overlapping rulesMultiple rules do the same thingSimplify or deduplicate rule definitions

Use Cases for AWS Security Groups with Terraform

  1. Provisioning Security Groups for Web Servers

Your team needs to launch a fleet of EC2 instances. So you can use Terraform to create the instances automatically. 

  • Allows inbound HTTP (port 80) and HTTPS (port 443)
  • Allows SSH (port 22) access from a specific IP range
  • Restricts all other access

ingress {

  from_port   = 80

  to_port     = 80

  protocol    = “tcp”

  cidr_blocks = [“0.0.0.0/0”]

}

  1. Dynamic Rules for Bastion Hosts

Your team uses a bastion server to access the instances securely in a private environment. Define a Terraform module to host Security Groups for: 

  • Allows SSH (port 22) from your office IP
  • Allows outbound traffic to private subnet resources
  • Denies all other inbound access
  1. Security Groups for RDS Databases

Your RDS instance should only accept connections from application servers. Use a Terraform aws_security_group_rule to allow inbound traffic from the app server’s SG ID.

source_security_group_id = aws_security_group.app_sg.id

  1. Creating Environment-Specific Rules (Dev, Staging, Prod)

If you want to set a specific set of rules for different development environments, use variables or workspaces in Terraform to dynamically assign different CIDR blocks or ports.

variable “env” {

  default = “dev”

}

  1. Restricting Egress for Compliance

Your organization needs to block all outbound traffic except for a specific IP range, so you can define the rules in Terraform Security Group. 

egress {

  from_port   = 443

  to_port     = 443

  protocol    = “tcp”

  cidr_blocks = [“198.51.100.0/24”]

}

  1. Using for_each to Create Multiple Rules Dynamically

If your team wants to open multiple ports for the same Security Group, you can use a port list and loop through them with for_each:

variable “ports” {

  default = [80, 443, 8080]

}

resource “aws_security_group_rule” “http_rules” {

  for_each          = toset(var.ports)

  type              = “ingress”

  from_port         = each.value

  to_port           = each.value

  protocol          = “tcp”

  cidr_blocks       = [“0.0.0.0/0”]

  security_group_id = aws_security_group.web_sg.id

}

Conclusion – AWS Security Group Terraform 

Security Groups are one of the core components of an AWS infrastructure, and when managed with Terraform, it brings advanced automation, control, and consistency to your cloud environment. Therefore, whether you need to automate a few specific ports or set rules for all of them, Terraform makes it easy to maintain the AWS infrastructure. 

How do I create a basic Security Group with Terraform?

You can use the aws_security_group resource block in Terraform to define the name, description, VPC, and rule sets (ingress/egress) for your Security Group.

What’s the benefit of using modules for Security Groups in Terraform?

Modules promote reuse, simplify maintenance, and make it easier to manage security groups across environments like dev, staging, and production.

What are common issues with Security Groups in Terraform?

Common pitfalls include cyclical dependencies, overlapping rules, improper CIDR formatting, or not updating state after manual changes in the AWS Console.

Marium Fahim
Hi! I am Marium, and I am a full-time content marketer fueled by an iced coffee. I mainly write about tech, and I absolutely love doing opinion-based pieces. Hit me up at [email protected].
Unlock Benefits

Become a Community Member

SIMPLIFY SETUP, MAXIMIZE EFFICIENCY!
Setting up CyberPanel is a breeze. We’ll handle the installation so you can concentrate on your website. Start now for a secure, stable, and blazing-fast performance!