Stand up a real vulnerable web application in AWS. Learn ECS, ALB, and security groups hands-on.
Tenzai's agent needs targets to attack. Understanding how to deploy and secure (or intentionally leave vulnerable) web applications is fundamental to our work.
Deploy OWASP Juice Shop to ECS Fargate with an ALB. Make it accessible via HTTPS. Then manually verify you can trigger some vulnerabilities.
tenzai-sandbox (credentials in 1Password)us-east-1 (unless you have a reason to change)Project = onboardingOwner = your-name
┌─────────────────────────────────────────────────────────────────┐
│ INTERNET │
└──────────────────────────────┬──────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ ALB (Application Load Balancer) │
│ - HTTPS listener (port 443) │
│ - ACM certificate (*.sandbox.tenzai.ai or self-signed) │
│ - Security Group: Allow 443 from anywhere │
└──────────────────────────────┬──────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ ECS Fargate Service │
│ - Task: bkimminich/juice-shop:latest │
│ - Port: 3000 │
│ - Security Group: Allow 3000 from ALB only │
│ - Fargate Spot (cost savings) │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ CloudWatch Logs │
│ - /ecs/juice-shop │
└─────────────────────────────────────────────────────────────────┘
Choose your path based on what you want to learn:
Use the AWS Console to create each resource manually. Good for understanding what each resource does.
Write Terraform to deploy everything. Good for learning IaC patterns.
Use your preferred IaC tool. Document your choices.
# For simplicity, use the default VPC
data "aws_vpc" "default" {
default = true
}
data "aws_subnets" "default" {
filter {
name = "vpc-id"
values = [data.aws_vpc.default.id]
}
}
resource "aws_security_group" "alb" {
name = "juice-shop-alb-sg"
description = "Allow HTTPS inbound"
vpc_id = data.aws_vpc.default.id
ingress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Project = "onboarding"
Owner = "your-name"
}
}
resource "aws_security_group" "ecs" {
name = "juice-shop-ecs-sg"
description = "Allow traffic from ALB"
vpc_id = data.aws_vpc.default.id
ingress {
from_port = 3000
to_port = 3000
protocol = "tcp"
security_groups = [aws_security_group.alb.id]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
resource "aws_ecs_cluster" "main" {
name = "juice-shop-cluster"
setting {
name = "containerInsights"
value = "enabled"
}
}
resource "aws_ecs_task_definition" "juice_shop" {
family = "juice-shop"
network_mode = "awsvpc"
requires_compatibilities = ["FARGATE"]
cpu = "256"
memory = "512"
execution_role_arn = aws_iam_role.ecs_execution.arn
container_definitions = jsonencode([
{
name = "juice-shop"
image = "bkimminich/juice-shop:latest"
portMappings = [
{
containerPort = 3000
hostPort = 3000
}
]
logConfiguration = {
logDriver = "awslogs"
options = {
"awslogs-group" = "/ecs/juice-shop"
"awslogs-region" = "us-east-1"
"awslogs-stream-prefix" = "ecs"
}
}
}
])
}
resource "aws_lb" "main" {
name = "juice-shop-alb"
internal = false
load_balancer_type = "application"
security_groups = [aws_security_group.alb.id]
subnets = data.aws_subnets.default.ids
}
resource "aws_lb_target_group" "main" {
name = "juice-shop-tg"
port = 3000
protocol = "HTTP"
vpc_id = data.aws_vpc.default.id
target_type = "ip"
health_check {
path = "/"
healthy_threshold = 2
unhealthy_threshold = 10
}
}
# If using Terraform
terraform destroy
# If using Console, delete in reverse order:
# 1. ECS Service
# 2. ALB Listener
# 3. ALB
# 4. Target Group
# 5. ECS Task Definition
# 6. ECS Cluster
# 7. Security Groups
# 8. CloudWatch Log Group