| name | network-security-groups |
| description | Configure network security groups and firewall rules to control inbound/outbound traffic and implement network segmentation. |
Network Security Groups
Overview
Implement network security groups and firewall rules to enforce least privilege access, segment networks, and protect infrastructure from unauthorized access.
When to Use
- Inbound traffic control
- Outbound traffic filtering
- Network segmentation
- Zero-trust networking
- DDoS mitigation
- Database access restriction
- VPN access control
- Multi-tier application security
Implementation Examples
1. AWS Security Groups
# aws-security-groups.yaml
Resources:
# VPC Security Group
VPCSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: VPC security group
VpcId: vpc-12345678
SecurityGroupIngress:
# Allow HTTP from anywhere
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0
Description: "HTTP from anywhere"
# Allow HTTPS from anywhere
- IpProtocol: tcp
FromPort: 443
ToPort: 443
CidrIp: 0.0.0.0/0
Description: "HTTPS from anywhere"
# Allow SSH from admin network only
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: 10.0.0.0/8
Description: "SSH from admin network"
SecurityGroupEgress:
# Allow all outbound
- IpProtocol: -1
CidrIp: 0.0.0.0/0
Description: "All outbound traffic"
Tags:
- Key: Name
Value: vpc-security-group
# Database Security Group
DatabaseSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Database security group
VpcId: vpc-12345678
SecurityGroupIngress:
# Allow PostgreSQL from app tier only
- IpProtocol: tcp
FromPort: 5432
ToPort: 5432
SourceSecurityGroupId: !Ref AppSecurityGroup
Description: "PostgreSQL from app tier"
SecurityGroupEgress:
- IpProtocol: -1
CidrIp: 0.0.0.0/0
Tags:
- Key: Name
Value: database-security-group
# Application Tier Security Group
AppSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Application tier security group
VpcId: vpc-12345678
SecurityGroupIngress:
# Allow traffic from load balancer
- IpProtocol: tcp
FromPort: 8080
ToPort: 8080
SourceSecurityGroupId: !Ref LBSecurityGroup
Description: "App traffic from LB"
SecurityGroupEgress:
# Allow to databases
- IpProtocol: tcp
FromPort: 5432
ToPort: 5432
DestinationSecurityGroupId: !Ref DatabaseSecurityGroup
Description: "Database access"
# Allow to external APIs
- IpProtocol: tcp
FromPort: 443
ToPort: 443
CidrIp: 0.0.0.0/0
Description: "HTTPS external APIs"
Tags:
- Key: Name
Value: app-security-group
# Load Balancer Security Group
LBSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Load balancer security group
VpcId: vpc-12345678
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0
- IpProtocol: tcp
FromPort: 443
ToPort: 443
CidrIp: 0.0.0.0/0
SecurityGroupEgress:
- IpProtocol: tcp
FromPort: 8080
ToPort: 8080
DestinationSecurityGroupId: !Ref AppSecurityGroup
Tags:
- Key: Name
Value: lb-security-group
2. Kubernetes Network Policies
# kubernetes-network-policies.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-all-ingress
namespace: production
spec:
podSelector: {}
policyTypes:
- Ingress
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend
namespace: production
spec:
podSelector:
matchLabels:
app: frontend
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
name: ingress-nginx
ports:
- protocol: TCP
port: 8080
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-backend-to-database
namespace: production
spec:
podSelector:
matchLabels:
tier: database
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
tier: backend
ports:
- protocol: TCP
port: 5432
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-backend-to-cache
namespace: production
spec:
podSelector:
matchLabels:
tier: cache
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
tier: backend
ports:
- protocol: TCP
port: 6379
---
# Egress policy
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: backend-egress
namespace: production
spec:
podSelector:
matchLabels:
tier: backend
policyTypes:
- Egress
egress:
# Allow to database
- to:
- podSelector:
matchLabels:
tier: database
ports:
- protocol: TCP
port: 5432
# Allow to cache
- to:
- podSelector:
matchLabels:
tier: cache
ports:
- protocol: TCP
port: 6379
# Allow DNS
- to:
- namespaceSelector: {}
podSelector:
matchLabels:
k8s-app: kube-dns
ports:
- protocol: UDP
port: 53
# Allow external APIs
- to:
- namespaceSelector: {}
ports:
- protocol: TCP
port: 443
3. GCP Firewall Rules
# gcp-firewall-rules.yaml
apiVersion: compute.cnrm.cloud.google.com/v1beta1
kind: ComputeFirewall
metadata:
name: allow-http-https
spec:
network:
name: default
direction: INGRESS
priority: 1000
sourceRanges:
- 0.0.0.0/0
allowed:
- IPProtocol: tcp
ports:
- "80"
- "443"
targetTags:
- http-server
- https-server
---
apiVersion: compute.cnrm.cloud.google.com/v1beta1
kind: ComputeFirewall
metadata:
name: allow-ssh-internal
spec:
network:
name: default
direction: INGRESS
priority: 1000
sourceRanges:
- 10.0.0.0/8
allowed:
- IPProtocol: tcp
ports:
- "22"
targetTags:
- allow-ssh
---
apiVersion: compute.cnrm.cloud.google.com/v1beta1
kind: ComputeFirewall
metadata:
name: deny-all-ingress
spec:
network:
name: default
direction: INGRESS
priority: 65534
denied:
- IPProtocol: all
4. Security Group Management Script
#!/bin/bash
# manage-security-groups.sh - Security group management utility
set -euo pipefail
ACTION="${1:-list}"
REGION="${2:-us-east-1}"
# List security groups
list_security_groups() {
echo "Security Groups in $REGION:"
aws ec2 describe-security-groups \
--region "$REGION" \
--query 'SecurityGroups[*].[GroupId,GroupName,VpcId]' \
--output table
}
# Show security group details
show_security_group() {
local sg_id="$1"
echo "Inbound Rules for $sg_id:"
aws ec2 describe-security-groups \
--group-ids "$sg_id" \
--region "$REGION" \
--query 'SecurityGroups[0].IpPermissions' \
--output table
echo -e "\nOutbound Rules for $sg_id:"
aws ec2 describe-security-groups \
--group-ids "$sg_id" \
--region "$REGION" \
--query 'SecurityGroups[0].IpPermissionsEgress' \
--output table
}
# Add inbound rule
add_inbound_rule() {
local sg_id="$1"
local protocol="$2"
local port="$3"
local cidr="$4"
local description="${5:-}"
aws ec2 authorize-security-group-ingress \
--group-id "$sg_id" \
--protocol "$protocol" \
--port "$port" \
--cidr "$cidr" \
--region "$REGION" \
${description:+--description "$description"}
echo "Rule added to $sg_id"
}
# Audit security groups for overly permissive rules
audit_security_groups() {
echo "Auditing security groups for overly permissive rules..."
aws ec2 describe-security-groups \
--region "$REGION" \
--query 'SecurityGroups[*].[GroupId,IpPermissions]' \
--output text | while read sg_id; do
# Check for 0.0.0.0/0 on sensitive ports
if aws ec2 describe-security-groups \
--group-ids "$sg_id" \
--region "$REGION" \
--query "SecurityGroups[0].IpPermissions[?FromPort==\`22\` || FromPort==\`3306\` || FromPort==\`5432\`]" \
--output json | grep -q "0.0.0.0/0"; then
echo "WARNING: $sg_id has sensitive ports open to 0.0.0.0/0"
fi
done
}
# Main
case "$ACTION" in
list)
list_security_groups
;;
show)
show_security_group "$3"
;;
add-rule)
add_inbound_rule "$3" "$4" "$5" "$6" "${7:-}"
;;
audit)
audit_security_groups
;;
*)
echo "Usage: $0 {list|show|add-rule|audit} [args]"
exit 1
;;
esac
Best Practices
✅ DO
- Implement least privilege access
- Use security groups for segmentation
- Document rule purposes
- Regularly audit rules
- Separate inbound and outbound rules
- Use security group references
- Monitor rule changes
- Test access before enabling
❌ DON'T
- Allow 0.0.0.0/0 for databases
- Open all ports unnecessarily
- Mix environments in single SG
- Ignore egress rules
- Allow all protocols
- Forget to document rules
- Use single catch-all rule
- Deploy without firewall
Common Rules
| Port |
Protocol |
Purpose |
| 22 |
TCP |
SSH (Admin only) |
| 80 |
TCP |
HTTP (Public) |
| 443 |
TCP |
HTTPS (Public) |
| 3306 |
TCP |
MySQL (App tier only) |
| 5432 |
TCP |
PostgreSQL (App tier only) |
| 6379 |
TCP |
Redis (App tier only) |
Resources