Files
attack-defense-platform/panel/prune_disabled.sh
T
Cyrene ae50acfe40 fix(ssh): per-challenge SSH login + phew buffering/leak/timeout
Passwords failed on 10/16 challenges while state.json looked correct:
- only the 6 native GEMASTIK XVIII images provision 'ctfuser'; every imported
  XVI/XVII image does 'echo root:${PASSWORD} | chpasswd' and logs in as root.
  set_ssh_passwords() hardcoded ctfuser, so chpasswd set a password on an
  account nobody uses -> 'Permission denied' everywhere.
  Registry gains a per-challenge 'ssh_user'; chpasswd now targets the real
  login (and ctfuser/ctf when present) and reports failures loudly.
- phew checker: chall.py block-buffers stdout through the docker exec pipe
  (PYTHONUNBUFFERED now set) and leaks chall.py inside the container on
  timeout (26 orphans, container saturated) -> reaps the whole exec process
  group. Startup does a fresh Pailier keygen (~12 s) so crypto reads need
  _CRYPTO_TIMEOUT, not the 5 s prompt default.

Adds panel/verify_ssh_creds.py (proves the state->container binding from
inside via a real login), audit_ssh_users.sh, reset_runtime.sh.
2026-09-26 14:40:10 +08:00

49 lines
1.8 KiB
Bash

#!/usr/bin/env bash
# Remove containers + images for challenges that are no longer enabled.
#
# Why: the platform can host 28 challenges but the images are large (1.2 GB for
# pasta alone) and the host disk is 79 GB. Keeping every image resident filled
# it to 98% and started failing builds. Disabled challenges keep their source in
# services/ and can be re-enabled at any time — only the runtime artifacts go.
set -uo pipefail
cd /opt/gemastik18-final/panel
ENABLED=$(python3 - <<'PY'
import sys
sys.path.insert(0, '.')
import teams
print(" ".join(c["name"] for c in teams.enabled_challenges()))
PY
)
echo "enabled: $ENABLED"
echo "--- stopping containers of disabled challenges ---"
for name in $(docker ps -a --format '{{.Names}}' | grep '_container_team' || true); do
base=${name%%_container_team*}
keep=0
for e in $ENABLED; do
[ "$base" = "$e" ] && keep=1
done
[ "$keep" = "0" ] && docker rm -f "$name" >/dev/null 2>&1 && echo "removed container $name"
done
echo "--- removing images of disabled challenges ---"
for img in $(docker images --format '{{.Repository}}' | grep -E '^(services-|team[0-9]+-)' || true); do
base=${img#services-}
base=${base#team[0-9]-}
# only challenge-shaped names (services-blogpost, team2-art, ...)
case "$base" in
blogpost|carbeat|cdn|phew|sheesh|warmup|art|xl|pasta|gemas-fetcher|s3|crawlback|back-to-basic|anti-alchemy|asmr|bit-canvas|fjb|gift-card|gift-voucher|gleam-drive|go-green|kode-viewer|more-less|ticketer|hirnfick|burvesigner|back-to-basic|gemas-notes|tempest-poc) ;;
*) continue ;;
esac
keep=0
for e in $ENABLED; do
[ "$base" = "$e" ] && keep=1
done
[ "$keep" = "0" ] && docker rmi "$img" >/dev/null 2>&1 && echo "removed image $img"
done
echo "--- done ---"
docker images --format '{{.Repository}}' | grep -c '^services-' || true
df -h / | tail -1