How to bring up security labs from the ~/labs/main repository for local testing and GKE-hosted runs.
Before bringing up any lab, you need:
annular-fold-460418-r3 GCP project from your managerbrew install just)Authenticate with GCP before doing anything:
gcloud auth login
gcloud auth application-default login
Then fetch the GKE cluster credentials (required before any GKE deployment or kubectl usage against the cluster):
gcloud container clusters get-credentials lab-cluster --location=us-central1
| Lab Type | Location | Deployment Tool | Local | GKE |
|---|---|---|---|---|
| T-Bench | tbench/app-XXX/ |
just |
just run |
just deploy |
| CVE-Bench | cve-bench/CVE-YYYY-XXXXX/ |
just |
just run |
just deploy |
| OSS Labs (openfire, zabbix, etc.) | <lab-name>/setup/ |
Terraform | — | terraform apply |
| CTF Labs (xbow, wscoil) | <lab-name>/setup/ |
Terraform | — | terraform apply |
T-Bench apps live under ~/labs/main/tbench/. They use Kubernetes with Kustomize overlays — just run targets local Docker Desktop/minikube, just deploy targets GKE.
Create the shared config file and symlink it into each lab you use:
mkdir -p ~/.config/tbench
cat > ~/.config/tbench/.env << 'EOF'
NAMESPACE_PREFIX=local
GKE_CLUSTER_NAME=lab-cluster
GKE_REGION=us-central1
GCP_PROJECT=annular-fold-460418-r3
LOCAL_K8S_CONTEXT=docker-desktop
EOF
# Symlink into the lab directory (repeat for each app you work with)
cd ~/labs/main/tbench/app-010
ln -s ~/.config/tbench/.env .env
The NAMESPACE_PREFIX controls the Kubernetes namespace: local-app-010 for local, or your prefix for GKE (e.g., dev-app-010).
cd ~/labs/main/tbench/app-010
just run
The app will be available at http://localhost:30100 (port varies by app — the just run output always prints the URL and default credentials). You can also find credentials in each lab's justfile in the run recipe.
To tear it down:
just stop
Do not mix local and remote commands. just run/just stop operate on your local cluster. just deploy/just destroy/just describe operate on GKE. Running them in the wrong order or against the wrong context causes namespace conflicts and unpredictable behaviour.
Commit before deploying. just deploy builds images using the current git commit hash. Commit any changes in lab/ before deploying or they won't be included.
cd ~/labs/main/tbench/app-010
git add lab/ && git commit -m "..."
just deploy
To get the endpoint after deploying:
just describe
This returns a JSON object with endpoint (pod IP), service_ip, and url.
To tear it down:
just destroy
| Command | What it does |
|---|---|
just run |
Build and deploy to local K8s (Docker Desktop/minikube) |
just stop |
Delete local namespace |
just deploy |
Build with Cloud Build, deploy to GKE |
just destroy |
Delete GKE namespace |
just describe |
Print endpoint/pod/service info as JSON |
Labs on GKE use internal IPs (10.32.x.x range). Connect to ZeroTier VPN first, then use the IP from just describe.
T-Bench apps support deploying vulnerability variants via the PATCHES env var. Each lab's patches/ directory contains .patch files that introduce specific vulnerabilities into the base application. Without PATCHES, you deploy the secure baseline.
# Deploy a single vulnerability variant locally
PATCHES="xss1" just run
# Deploy multiple variants
PATCHES="xss1 idor1" just run
# Same syntax for GKE
PATCHES="sqli1" just deploy
The patch name corresponds to a file in patches/<name>.patch. Check each lab's patches/ directory to see what variants are available. See ~/labs/main/tbench/AGENTS.md for full documentation on how the patches system works.
OSS labs (openfire-360, zabbix, orangehrm, opencart, etc.) deploy to GKE via Terraform. Each has a setup/ directory with the Terraform config.
export GOOGLE_PROJECT=annular-fold-460418-r3
export GOOGLE_REGION=us-central1
cd ~/labs/main/openfire-360/setup
terraform init
terraform apply
Terraform reads GCP credentials from your active gcloud session, fetches GKE cluster details from shared remote state, and deploys the lab as a Kubernetes workload. The backend uses GCS bucket tenzai-staging-lab-terraform-states — if terraform init fails with a storage error, your GCP project access hasn't been fully provisioned yet.
After apply completes, the endpoint is in the outputs:
terraform output endpoint
terraform destroy
CTF labs follow the same Terraform workflow as OSS labs. Each lab has a setup/ directory.
export GOOGLE_PROJECT=annular-fold-460418-r3
export GOOGLE_REGION=us-central1
cd ~/labs/main/xben-001-24/setup
terraform init
terraform apply
terraform output endpoint
To find the flag or vulnerability details for a given lab, check its grounded-report.md.
Once a lab is running, these kubectl commands are useful for both local and GKE namespaces:
# List pods
kubectl get pods -n <namespace>
# Check pod status (useful if stuck in Pending or CrashLoopBackOff)
kubectl describe pod -n <namespace> <pod-name>
# Stream app logs
kubectl logs -n <namespace> -l app=app -f
# Check previous crash
kubectl logs -n <namespace> <pod-name> --previous
# Shell into a container
kubectl exec -it -n <namespace> <pod-name> -- /bin/bash
# List services and IPs
kubectl get svc -n <namespace>
For T-Bench labs specifically, the namespace format is ${NAMESPACE_PREFIX}-app-XXX (e.g., local-app-010 or dev-app-010).