These step-by-step demonstrations walk you through complete workflows using the security-group module. Each demonstration includes prerequisites, detailed instructions, and verification steps.

Getting Started

To follow any demonstration, ensure you have:

  1. Prerequisites met: Terraform >= 1.0, AWS CLI configured
  2. Authenticate with the registry: terraform login registry.patterneddesigns.ca
  3. Clone the demonstration repository: git clone <demo-repo-url>
  4. Follow the step-by-step instructions below

Step-by-Step Guides

Three-Tier Architecture Security

Configure security groups for a three-tier web application

Step 1: Create Web Tier Security Group

module "web_sg" {
  source  = "registry.patterneddesigns.ca/patterneddesigns/security-group/aws"
  version = "1.2.0"

  name   = "web-tier"
  vpc_id = module.vpc.vpc_id

  ingress_rules = [
    {
      from_port   = 443
      to_port     = 443
      protocol    = "tcp"
      cidr_blocks = ["0.0.0.0/0"]
    }
  ]
}

Step 2: Create Application Tier

Allow traffic only from the web tier.

Step 3: Create Database Tier

Allow traffic only from the application tier.

Complete VPC Security Setup

End-to-end VPC security configuration with multiple security groups

This demonstration walks through setting up a complete VPC security architecture with multiple security groups for a production-ready environment.

Step 1: Create the VPC

First, set up the VPC infrastructure that will host the security groups.

module "vpc" {
  source  = "registry.patterneddesigns.ca/patterneddesigns/vpc/aws"
  version = "2.0.0"

  name       = "production"
  cidr_block = "10.0.0.0/16"

  availability_zones = ["us-east-1a", "us-east-1b", "us-east-1c"]

  public_subnets  = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"]
  private_subnets = ["10.0.11.0/24", "10.0.12.0/24", "10.0.13.0/24"]
  data_subnets    = ["10.0.21.0/24", "10.0.22.0/24", "10.0.23.0/24"]
}

Step 2: Create Load Balancer Security Group

Allow public HTTPS traffic to the application load balancer.

module "alb_sg" {
  source  = "registry.patterneddesigns.ca/patterneddesigns/security-group/aws"
  version = "1.2.0"

  name   = "production-alb"
  vpc_id = module.vpc.vpc_id

  ingress_rules = [
    {
      from_port   = 443
      to_port     = 443
      protocol    = "tcp"
      cidr_blocks = ["0.0.0.0/0"]
      description = "HTTPS from internet"
    },
    {
      from_port   = 80
      to_port     = 80
      protocol    = "tcp"
      cidr_blocks = ["0.0.0.0/0"]
      description = "HTTP for redirect"
    }
  ]

  egress_rules = [
    {
      from_port       = 8080
      to_port         = 8080
      protocol        = "tcp"
      security_groups = [module.app_sg.security_group_id]
      description     = "Forward to application servers"
    }
  ]
}

Step 3: Create Application Security Group

Allow traffic only from the load balancer.

module "app_sg" {
  source  = "registry.patterneddesigns.ca/patterneddesigns/security-group/aws"
  version = "1.2.0"

  name   = "production-app"
  vpc_id = module.vpc.vpc_id

  ingress_rules = [
    {
      from_port       = 8080
      to_port         = 8080
      protocol        = "tcp"
      security_groups = [module.alb_sg.security_group_id]
      description     = "Application traffic from ALB"
    }
  ]

  egress_rules = [
    {
      from_port       = 5432
      to_port         = 5432
      protocol        = "tcp"
      security_groups = [module.db_sg.security_group_id]
      description     = "PostgreSQL database"
    },
    {
      from_port       = 6379
      to_port         = 6379
      protocol        = "tcp"
      security_groups = [module.cache_sg.security_group_id]
      description     = "Redis cache"
    },
    {
      from_port   = 443
      to_port     = 443
      protocol    = "tcp"
      cidr_blocks = ["0.0.0.0/0"]
      description = "HTTPS to external services"
    }
  ]
}

Step 4: Create Database Security Group

Allow access only from application servers.

module "db_sg" {
  source  = "registry.patterneddesigns.ca/patterneddesigns/security-group/aws"
  version = "1.2.0"

  name   = "production-database"
  vpc_id = module.vpc.vpc_id

  ingress_rules = [
    {
      from_port       = 5432
      to_port         = 5432
      protocol        = "tcp"
      security_groups = [module.app_sg.security_group_id]
      description     = "PostgreSQL from application tier"
    }
  ]

  # No egress rules - database does not initiate connections
  egress_rules = []
}

Step 5: Create Cache Security Group

Allow access from application servers only.

module "cache_sg" {
  source  = "registry.patterneddesigns.ca/patterneddesigns/security-group/aws"
  version = "1.2.0"

  name   = "production-cache"
  vpc_id = module.vpc.vpc_id

  ingress_rules = [
    {
      from_port       = 6379
      to_port         = 6379
      protocol        = "tcp"
      security_groups = [module.app_sg.security_group_id]
      description     = "Redis from application tier"
    }
  ]

  egress_rules = []
}

Step 6: Create Bastion Security Group

Allow SSH access from corporate network for administration.

data "aws_ec2_managed_prefix_list" "corporate" {
  name = "corporate-network"
}

module "bastion_sg" {
  source  = "registry.patterneddesigns.ca/patterneddesigns/security-group/aws"
  version = "1.2.0"

  name   = "production-bastion"
  vpc_id = module.vpc.vpc_id

  ingress_rules = [
    {
      from_port       = 22
      to_port         = 22
      protocol        = "tcp"
      prefix_list_ids = [data.aws_ec2_managed_prefix_list.corporate.id]
      description     = "SSH from corporate network"
    }
  ]

  egress_rules = [
    {
      from_port       = 22
      to_port         = 22
      protocol        = "tcp"
      security_groups = [
        module.app_sg.security_group_id,
        module.db_sg.security_group_id
      ]
      description = "SSH to internal instances"
    }
  ]
}

Step 7: Output Security Group IDs

Export the security group IDs for use by other resources.

output "security_groups" {
  value = {
    alb     = module.alb_sg.security_group_id
    app     = module.app_sg.security_group_id
    db      = module.db_sg.security_group_id
    cache   = module.cache_sg.security_group_id
    bastion = module.bastion_sg.security_group_id
  }
  description = "Security group IDs for all tiers"
}

Architecture Diagram

Internet
┌─────────────┐
│  ALB (443)  │ ──────► alb_sg
└─────────────┘
    ▼ (8080)
┌─────────────┐
│ App Servers │ ──────► app_sg
└─────────────┘
    ├──────────────────┐
    ▼ (5432)           ▼ (6379)
┌─────────────┐   ┌─────────────┐
│  Database   │   │    Cache    │
│   (RDS)     │   │ (ElastiCache│
└─────────────┘   └─────────────┘
      │                 │
      ▼                 ▼
   db_sg            cache_sg

Corporate Network (SSH)
┌─────────────┐
│   Bastion   │ ──────► bastion_sg
└─────────────┘

Security Considerations

  • All security groups use security group references instead of CIDR blocks where possible
  • Database and cache have no egress rules (deny all outbound)
  • SSH access is restricted to the corporate network via prefix list
  • Each tier can only communicate with its immediate neighbors