A turnkey AWS-hosted learning lab and a 2-day on-site hackathon kit. One repo. One linear path.
START-HERE.md — picks the right path for you (admin / facilitator / participant / sponsor) and gives you the linear reading order.
If you don't know whether you're an admin or a facilitator: read START-HERE.md. It will tell you.
Two products in one repo. You can run #1 without #2. You cannot run #2 without #1.
A single EC2 box in your dev VPC running:
- Juice Shop, DVWA, bWAPP — three deliberately broken web apps for the OWASP Top 10
- DonkeyDocker ×40 — one CTF container per participant (web shell → SSH → priv-esc → Docker breakout)
- PentAGI on AWS Bedrock — an AI pentest agent participants can drive
- Langfuse — traces every AI call so you can see how it reasoned
- Dashboard on port 9000 — health, teams, OWASP heatmap, leaderboard, cost
Reached via SSM port-forwarding: no public IPs, no SSH keys, no VPN.
Built with one terraform apply. Torn down with one terraform destroy.
- Day 1: foundations, OWASP Top 10 intro, paper attack-tree exercise, hands-on warm-ups
- Day 2: team CTF (3 rounds), AI co-pilot challenge, insights canvases, lightning talks, awards
- Outputs: a concrete DevSecOps backlog signed by each team — secure-coding rules, CI/CD gates, cloud baselines, all with owners and dates
START-HERE.md
│
▼
docs/GLOSSARY.md ← decode every acronym (10 min)
│
▼
docs/LEARN-FIRST.md ← facilitator warm-up (2–4 hrs, week before)
│
▼
docs/SETUP.md ← admin stands up the lab (90 min, one time)
│
▼
docs/FACILITATOR-GUIDE.md ← runbook for the 2 days
│
▼
hackathon/BLUEPRINT.md ← the design doc
│
▼
hackathon/day1/ → hackathon/day2/ → hackathon/templates/
Everything else in the repo (terraform/, dashboard/, cli/, prompts/, scripts/) is the runtime — code you operate, not documents you read end-to-end.
| You are a… | Read |
|---|---|
| First-time visitor | START-HERE.md |
| Admin standing up the lab | docs/SETUP.md |
| Facilitator running the event | docs/FACILITATOR-GUIDE.md |
| Participant on Day 1 morning | docs/DEV-ONBOARDING.md |
| Sponsor approving the spend | hackathon/BLUEPRINT.md + cost section in SETUP.md |
| Confused by an acronym | docs/GLOSSARY.md |
| Service | Purpose | Per dev or shared? | Local URL (after dev-connect.sh) |
|---|---|---|---|
| DonkeyDocker | CTF: web shell → SSH → Docker priv-esc to host | one per dev | http://localhost:8001 + ssh smith@localhost -p 22001 |
| OWASP Juice Shop | Modern broken web shop, ~100 graded challenges | shared | http://localhost:3000 |
| DVWA | Classic PHP/MySQL app with side-by-side fixes | shared | http://localhost:4280 |
| bWAPP | 100+ bugs mapped to OWASP Top 10 | shared | http://localhost:4281 |
| PentAGI | AI pentest agent using AWS Bedrock (github) | shared, multi-user | https://localhost:8443 |
| Langfuse | LLM call traces — see what the AI did | shared | http://localhost:4000 |
| Dashboard | Health, teams, OWASP heatmap, cost | shared, admins only | http://localhost:9000 |
All reached via SSM port-forwarding — no public IPs, no SSH keys, no VPN.
Deploy (TL;DR — the full version is in SETUP.md)
# 1. Prereqs (see SETUP.md §0): VPC IDs ready, Bedrock model access enabled, SSM plugin installed
git clone https://github.com/DevOpsMadDog/pentest-lab.git
cd pentest-lab/terraform
# 2. Configure
cp variables.example.tfvars terraform.tfvars
$EDITOR terraform.tfvars # fill in vpc_id, subnet IDs, dev_count
# 3. Apply
terraform init
terraform apply
# 4. Wait ~15 min for user-data, then port-forward the dashboard
INSTANCE_ID=$(terraform output -raw instance_id)
aws ssm start-session --target $INSTANCE_ID \
--document-name AWS-StartPortForwardingSession \
--parameters 'portNumber=["9000"],localPortNumber=["9000"]'
open http://localhost:9000pentest-lab/
├── START-HERE.md ⭐ read first
├── README.md ← you are here
│
├── docs/ ← all explanatory writing, read in this order:
│ ├── GLOSSARY.md ← 1. decode acronyms
│ ├── LEARN-FIRST.md ← 2. facilitator warm-up
│ ├── SETUP.md ← 3. admin: stand up the lab
│ ├── FACILITATOR-GUIDE.md ← 4. how to run the 2 days
│ ├── DEV-ONBOARDING.md ← participant connect guide
│ ├── COURSE.md ← optional pre-reading
│ └── INSTRUCTOR-RUNSHEET.md ← legacy (superseded by FACILITATOR-GUIDE)
│
├── hackathon/ ← the 2-day event content
│ ├── BLUEPRINT.md ← design rationale
│ ├── day1/ ← morning intro + paper exercise
│ ├── day2/ ← CTF rules + awards script
│ ├── judging/ ← scoring rubric
│ └── templates/ ← insights canvas + lightning talk
│
├── terraform/ ← AWS infrastructure (one-time apply)
├── scripts/ ← dev-connect.sh + admin cheatsheet
├── cli/lab ← `lab up | adddev | grade | cost | …`
├── dashboard/ ← FastAPI + browser SPA (port 9000)
├── prompts/ ← 13 pre-baked PentAGI tasks
└── .github/workflows/ ← CI: tflint, tfsec, checkov, gitleaks, semgrep, …
| Mode | Cost |
|---|---|
| Lab running 24/7 | ~AUD 600/mo |
| Lab with auto-stop on weeknights/weekends | ~AUD 340–490/mo |
| Lab destroyed between events | ~AUD 0 (re-apply takes 15 min) |
| Per training day | ~AUD 60–110 |
| Bedrock token spend | ~AUD 5–20 per session |
See SETUP.md cost section for the breakdown.
- No public-internet exposure. Everything is dev-VPC-internal. No
0.0.0.0/0security group rules. If you want a public CTF, this is the wrong repo. - No production data. Every target is deliberately broken software. Don't point it at anything real.
- No supplied AI keys. Bedrock is via instance role. If you want OpenAI/Anthropic direct, see PentAGI's docs and set up your own key store.
- No CI of the targets themselves. The deliberately-vulnerable apps fail every security scanner in existence. The CI in this repo scans our code (Terraform, dashboard, scripts).
Apache 2.0 — see LICENSE.
The vulnerable apps (Juice Shop, DVWA, bWAPP, DonkeyDocker) retain their original licenses. Use at your own risk in a contained dev VPC only.
Start with START-HERE.md.