Skip to content

Commit d8f7388

Browse files
authored
Merge pull request #1 from thedevopstooling/post/ec2-security-groups
post aws ec2 security groups
2 parents 21317a1 + 1dbebc2 commit d8f7388

8 files changed

Lines changed: 296 additions & 0 deletions

aws-ec2-security-groups/README.md

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
# AWS EC2 Security Groups Explained 🔐
2+
3+
**Understand how AWS controls inbound and outbound traffic to your EC2 instances.**
4+
Visual, practical, and DevOps-ready.
5+
6+
---
7+
8+
## 🧠 Key Concepts
9+
10+
- Security Groups act as **instance-level firewalls**
11+
- Network ACLs act at the **subnet level**
12+
- SGs are **stateful**, NACLs are **stateless**
13+
- Traffic rules control **inbound** (incoming) and **outbound** (outgoing) flows
14+
15+
---
16+
17+
## 📊 Inbound vs Outbound Rules
18+
19+
| Direction | Example | Purpose |
20+
|------------|----------|----------|
21+
| **Inbound** | Allow SSH (port 22) from your IP | Admin access |
22+
| **Outbound** | Allow all | Internet updates |
23+
24+
---
25+
26+
## ⚙️ Best Practices
27+
28+
✅ Use least-privilege rules
29+
✅ Avoid `0.0.0.0/0` where not required
30+
✅ Group SGs by role (web, db, bastion)
31+
✅ Review regularly
32+
33+
---
34+
35+
## 📈 Diagram
36+
37+
## 📊 1. Inbound & Outbound Traffic Flow
38+
![Inbound & Outbound Traffic Flow](./images/AWS%20EC2%20Security%20Groups%20-%20AWS%20EC2%20Security%20Group%20Inbound%20%26%20Outbound%20Traffic%20Flow%20-%20the%20devops%20tooling.png)
39+
> **Diagram 1:** Visualizing how inbound and outbound rules are applied in AWS Security Groups.
40+
> Source: [TheDevOpsTooling.com](https://thedevopstooling.com/aws-ec2-security-groups-explained/)
41+
42+
---
43+
44+
## 🧱 2. Security Groups vs Network ACLs
45+
![Security Groups vs NACLs](./images/AWS%20EC2%20Security%20Groups%20-%20AWS%20Security%20Groups%20vs%20NACLs%20Instance%20vs%20Subnet%20Level%20-%20the%20devops%20tooling.png)
46+
> **Diagram 2:** Instance-level (SG) vs Subnet-level (NACL) filtering.
47+
48+
---
49+
50+
## 🧩 3. Security Group Traffic Evaluation
51+
![Traffic Evaluation](./images/AWS%20EC2%20Security%20Groups%20-%20Security%20Group%20Traffic%20Evaluation%20-%20the%20devops%20tooling.png)
52+
> **Diagram 3:** Rule evaluation flow for AWS Security Groups.
53+
54+
---
55+
56+
## 🏗️ 4. Three-Tier Architecture Example
57+
![Layered Security Architecture](./images/AWS%20EC2%20Security%20Groups%20-%20Three-Tier%20AWS%20Architecture%20Security%20Groups%20as%20Layered%20Shields%20-%20the%20devops%20tooling.png)
58+
> **Diagram 4:** Web, App, and DB layer Security Groups in a three-tier AWS design.
59+
60+
---
61+
62+
## 🔗 Reference
63+
64+
Full post: [AWS EC2 Security Groups Explained](https://thedevopstooling.com/aws-ec2-security-groups-explained/)
65+
More guides at [TheDevOpsTooling.com](https://thedevopstooling.com)
66+
67+
---
68+
69+
### ✍️ Author
70+
**Srikanth Chowdari** — Senior DevOps Engineer
71+
Follow for more AWS & DevOps tutorials: [@thedevopstooling](https://github.com/thedevopstooling)
Loading
Loading
747 KB
Loading
Loading
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Terraform: AWS EC2 Security Groups (three-tier example)
2+
3+
This folder contains Terraform code to create security groups for a three-tier architecture:
4+
- web-tier (public HTTP/HTTPS + SSH from bastion)
5+
- app-tier (app port only from web-tier + SSH from bastion)
6+
- database-tier (PostgreSQL only from app-tier; limited egress to S3 prefix list)
7+
- bastion (SSH access from office CIDR)
8+
9+
## Usage
10+
11+
1. Create a `terraform.tfvars` with values for required variables:
12+
```hcl
13+
vpc_id = "vpc-0123456789abcdef"
14+
office_cidr = "203.0.113.0/24"
15+
private_subnet_cidr = "10.0.1.0/24"
16+
s3_prefix_list_id = "pl-0abcd1234"
17+
environment = "prod"
18+
region = "us-east-1"
19+
20+
## Initialize & apply:
21+
22+
cd aws-ec2-security-groups/terraform
23+
terraform init
24+
terraform plan -out=tfplan
25+
terraform apply tfplan
26+
27+
# Destroy (when needed):
28+
29+
terraform destroy
30+
31+
32+
See theDevOpsTooling article: https://thedevopstooling.com/aws-ec2-security-groups-explained/
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
terraform {
2+
required_providers {
3+
aws = {
4+
source = "hashicorp/aws"
5+
version = "~> 5.0"
6+
}
7+
}
8+
required_version = ">= 1.4.0"
9+
}
10+
11+
provider "aws" {
12+
region = var.region
13+
}
14+
15+
#
16+
# Web Tier Security Group
17+
#
18+
resource "aws_security_group" "web_tier" {
19+
name = "web-tier-sg"
20+
description = "Security group for web tier - allows public HTTP/HTTPS"
21+
vpc_id = var.vpc_id
22+
23+
ingress {
24+
description = "HTTP from public internet"
25+
from_port = 80
26+
to_port = 80
27+
protocol = "tcp"
28+
cidr_blocks = ["0.0.0.0/0"]
29+
}
30+
31+
ingress {
32+
description = "HTTPS from public internet"
33+
from_port = 443
34+
to_port = 443
35+
protocol = "tcp"
36+
cidr_blocks = ["0.0.0.0/0"]
37+
}
38+
39+
ingress {
40+
description = "SSH from bastion host"
41+
from_port = 22
42+
to_port = 22
43+
protocol = "tcp"
44+
security_groups = [aws_security_group.bastion.id]
45+
}
46+
47+
egress {
48+
description = "Allow all outbound"
49+
from_port = 0
50+
to_port = 0
51+
protocol = "-1"
52+
cidr_blocks = ["0.0.0.0/0"]
53+
}
54+
55+
tags = {
56+
Name = "web-tier-sg"
57+
Environment = var.environment
58+
ManagedBy = "Terraform"
59+
}
60+
}
61+
62+
#
63+
# Application Tier Security Group
64+
#
65+
resource "aws_security_group" "app_tier" {
66+
name = "app-tier-sg"
67+
description = "Security group for application tier - only accessible from web tier"
68+
vpc_id = var.vpc_id
69+
70+
ingress {
71+
description = "Application port from web tier"
72+
from_port = 8080
73+
to_port = 8080
74+
protocol = "tcp"
75+
security_groups = [aws_security_group.web_tier.id]
76+
}
77+
78+
ingress {
79+
description = "SSH from bastion host"
80+
from_port = 22
81+
to_port = 22
82+
protocol = "tcp"
83+
security_groups = [aws_security_group.bastion.id]
84+
}
85+
86+
egress {
87+
description = "Allow all outbound"
88+
from_port = 0
89+
to_port = 0
90+
protocol = "-1"
91+
cidr_blocks = ["0.0.0.0/0"]
92+
}
93+
94+
tags = {
95+
Name = "app-tier-sg"
96+
Environment = var.environment
97+
ManagedBy = "Terraform"
98+
}
99+
}
100+
101+
#
102+
# Database Tier Security Group
103+
#
104+
resource "aws_security_group" "database" {
105+
name = "database-sg"
106+
description = "Security group for database tier - only accessible from app tier"
107+
vpc_id = var.vpc_id
108+
109+
ingress {
110+
description = "PostgreSQL from application tier"
111+
from_port = 5432
112+
to_port = 5432
113+
protocol = "tcp"
114+
security_groups = [aws_security_group.app_tier.id]
115+
}
116+
117+
egress {
118+
description = "Allow HTTPS to S3 VPC endpoint for backups"
119+
from_port = 443
120+
to_port = 443
121+
protocol = "tcp"
122+
prefix_list_ids = [var.s3_prefix_list_id]
123+
}
124+
125+
tags = {
126+
Name = "database-sg"
127+
Environment = var.environment
128+
ManagedBy = "Terraform"
129+
}
130+
}
131+
132+
#
133+
# Bastion Host Security Group
134+
#
135+
resource "aws_security_group" "bastion" {
136+
name = "bastion-sg"
137+
description = "Security group for bastion host - restricted SSH access"
138+
vpc_id = var.vpc_id
139+
140+
ingress {
141+
description = "SSH from office network"
142+
from_port = 22
143+
to_port = 22
144+
protocol = "tcp"
145+
cidr_blocks = [var.office_cidr]
146+
}
147+
148+
egress {
149+
description = "SSH to private subnets"
150+
from_port = 22
151+
to_port = 22
152+
protocol = "tcp"
153+
cidr_blocks = [var.private_subnet_cidr]
154+
}
155+
156+
tags = {
157+
Name = "bastion-sg"
158+
Environment = var.environment
159+
ManagedBy = "Terraform"
160+
}
161+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
variable "region" {
2+
description = "AWS region"
3+
type = string
4+
default = "us-east-1"
5+
}
6+
7+
variable "vpc_id" {
8+
description = "VPC ID where Security Groups will be created"
9+
type = string
10+
}
11+
12+
variable "environment" {
13+
description = "Environment name (dev, staging, prod)"
14+
type = string
15+
default = "dev"
16+
}
17+
18+
variable "office_cidr" {
19+
description = "CIDR block for office network"
20+
type = string
21+
}
22+
23+
variable "private_subnet_cidr" {
24+
description = "CIDR block for private subnets"
25+
type = string
26+
}
27+
28+
variable "s3_prefix_list_id" {
29+
description = "Prefix list ID for S3 VPC endpoint (for egress)"
30+
type = string
31+
default = null
32+
}

0 commit comments

Comments
 (0)