Skip to content

Game Day Console

Three-tier AWS stack in Terraform · six broken-infrastructure challenges

Terraform ≥ 1.9 AWS provider ~> 5.x IMDSv2 required Flow logs + ALB logs MIT
GitHub
–
Challenges
–
Planted defects
–
Terraform modules
–
Security controls
–
Minutes of content

01Architecture

The internet reaches exactly one thing: an Application Load Balancer sitting in public subnets. Everything that runs application code lives in private subnets with no public IP and no inbound path except the load balancer's security group. Logs and state sit in a third boundary that neither of the other two can read from.

Three-tier AWS topology with four trust boundaries Public internet clients reach an Application Load Balancer in public subnets over TCP 443 or 80. The load balancer forwards to an Auto Scaling group of nginx instances in private subnets over TCP 80, permitted only by security group reference. Instances reach the internet outbound through a NAT gateway. The load balancer writes access logs to S3, the VPC writes flow logs to CloudWatch, and Terraform state is held in S3 with DynamoDB locking. Trust Boundary Public Internet Clients browser / curl Trust Boundary Public Subnets (ALB) Application LB 3 AZs · sg-alb drop_invalid_header_fields NAT Gateway egress only Trust Boundary Private Subnets (ASG) Auto Scaling Group nginx on Ubuntu 22.04 no public IP · sg-app IMDSv2 required, hop limit 1 encrypted gp3 root volume SSM Session Manager, no :22 Trust Boundary Data / Ops (logs, state) S3 access logs SSE-S3, versioned public access blocked TLS-only policy 90-day expiry CloudWatch VPC flow logs (ALL) ALB 5xx alarm unhealthy host alarm → SNS (KMS) Terraform state S3, encrypted DynamoDB lock CI assumes role via GitHub OIDC TCP 443 · TLS 1.2+ 80 → 301 redirect TCP 80 · sg-ref only egress 80/443 → NAT ALB access logs (bucket policy + TLS-only) flow logs · metrics
Four trust boundaries. The only unauthenticated edge is the load balancer listener; every other hop is permitted by security group reference, an IAM role, or a bucket policy.

02Challenges

Each challenge is a Terraform file with deliberate defects and a symptom instead of an error message. Reveal the hint only when a team is genuinely stuck; the solution file explains the root cause and the lesson. Scoring is in the facilitator guide.

    03What the refactor changed

    The original configuration deployed instances into public subnets behind a security group open to the world on ports 22 and 80, with no encryption, no logging and no state locking. These are the controls that replaced it.

    Security controls introduced by the refactor
    ControlWhereWhy it matters

    04Review it without an AWS account

    Nothing on this page needs credentials, and neither does reviewing the code. The test suite runs against mocked providers, so the whole security posture is checkable offline and for free.

    git clone https://github.com/Freddricklogan/aws-terraform-gameday
    cd aws-terraform-gameday
    
    make init      # terraform init -backend=false
    make lint      # fmt -check, validate, tflint
    make test      # terraform test -- mocked providers, no AWS calls, no cost
    make scan      # checkov + trivy config