- panel/teams.py: create/start/stop teams with isolated ports+creds, per-team receivers with CHALLENGE_PORT/CONTAINER env, flag randomization, submit validation + leaderboard
- panel/main.py: /api/teams, /api/teams/{idx}/randomize, /api/flag/submit, /api/leaderboard, /api/public/teams, /submit page
- panel/static/submit.html: public flag submission UI for teams
- receiver: _ch_port/_ch_container read .env per team, container name overrides
- .gitignore: exclude teams/, .venv, __pycache__
59 lines
2.0 KiB
Python
59 lines
2.0 KiB
Python
1|from fastapi import Depends, FastAPI, HTTPException
|
|
2|from pydantic import BaseModel
|
|
3|from fastapi.security import HTTPBasic, HTTPBasicCredentials
|
|
4|from config import get_settings
|
|
5|
|
|
6|from challenges.Blogpost import Blogpost
|
|
7|from challenges.Carbeat import Carbeat
|
|
8|from challenges.CDN import CDN
|
|
9|from challenges.Phew import Phew
|
|
10|from challenges.Sheesh import Sheesh
|
|
11|from challenges.Warmup import Warmup
|
|
12|
|
|
13|import os
|
|
14|import asyncio
|
|
15|import logging
|
|
16|
|
|
17|# Setup logging
|
|
18|logging.basicConfig(level=logging.INFO)
|
|
19|logger = logging.getLogger(__name__)
|
|
20|
|
|
21|app = FastAPI()
|
|
22|security = HTTPBasic()
|
|
23|settings = get_settings()
|
|
24|
|
|
25|def _ch_port(name: str, default: int) -> int:
|
|
# read from .env manually (pydantic settings has fixed fields)
|
|
val = os.environ.get(f"CHALLENGE_PORT_{name.upper()}")
|
|
if not val:
|
|
try:
|
|
with open(os.path.join(os.path.dirname(__file__), ".env")) as f:
|
|
for line in f:
|
|
if line.startswith(f"CHALLENGE_PORT_{name.upper()}="):
|
|
val = line.strip().split("=", 1)[1]
|
|
except Exception:
|
|
pass
|
|
return int(val) if val else default
|
|
|
|
def _ch_container(name: str, default: str) -> str:
|
|
val = os.environ.get(f"CHALLENGE_CONTAINER_{name.upper()}")
|
|
if not val:
|
|
try:
|
|
with open(os.path.join(os.path.dirname(__file__), ".env")) as f:
|
|
for line in f:
|
|
if line.startswith(f"CHALLENGE_CONTAINER_{name.upper()}="):
|
|
val = line.strip().split("=", 1)[1]
|
|
except Exception:
|
|
pass
|
|
return val or default
|
|
challenges = {
|
|
32| "blogpost": Blogpost(_ch_port("blogpost", 10000)),
|
|
33| "carbeat": Carbeat(_ch_port("carbeat", 11000)),
|
|
34| "cdn": CDN(_ch_port("cdn", 12000)),
|
|
35| "phew": Phew(_ch_port("phew", 13000)),
|
|
36| "sheesh": Sheesh(_ch_port("sheesh", 14000)),
|
|
37| "warmup": Warmup(_ch_port("warmup", 15000)),
|
|
38|}
|
|
39|
|
|
40|async def run_challenge_checks():
|
|
41| |