security: enforce real plugin secret, fix proxy auth bypass, loopback DB ports, nightly backups
- SHARED_SECRET now read from env and fail-closed: unset/placeholder refuses ALL plugin connections (constant-time compare). The old hardcoded 'your_shared_secret' in this public repo was no auth at all. Dockerfile default removed; generate_data.py reads the env var. - SECRET_KEY fails closed at startup (main.py and agent/auth.py) instead of falling back to a publicly-known signing key; agent systemd unit now requires /etc/overlord/agent.env (no '-' prefix). - AuthMiddleware + /ws/live: replace the 172.x source-IP trust (which every nginx-proxied internet request satisfied via docker-proxy — full session bypass and unauthenticated in-game command injection) with private-source AND no X-Forwarded-For, i.e. only genuinely internal callers (overlord-agent on the host, compose-network services). Invariant documented in nginx/overlord.conf: every tracker-bound location must set X-Forwarded-For. - /character-stats/test endpoints gated behind admin (they upsert real rows). - docker-compose: bind 5432/5433 to 127.0.0.1 (both DBs were internet- reachable; active brute-force observed in dereth-db logs). - discord-rare-monitor: drop dead SHARED_SECRET constant. - scripts/backup-databases.sh + docs/backups.md: nightly pg_dump of both DBs (telemetry/spawn hypertable data excluded), 10MB canary, umask 077, TimescaleDB restore procedure. - Remove stray mangled-path css file from repo root. Adversarially reviewed pre-deploy (3-lens workflow): ship verdict; deploy- sequencing blockers addressed (secret staged before enforcement, exec bit set, cron uses bash). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
c6a1af0c39
commit
a28b61511c
12 changed files with 261 additions and 2579 deletions
|
|
@ -12,8 +12,15 @@ import os
|
|||
from fastapi import HTTPException, Request, status
|
||||
from itsdangerous import BadSignature, SignatureExpired, URLSafeTimedSerializer
|
||||
|
||||
# Mirror main.py:996-998
|
||||
SECRET_KEY = os.getenv("SECRET_KEY", "change-me-in-production-please")
|
||||
# Mirror main.py — and fail closed like it does: starting with a known
|
||||
# default key would let anyone forge a valid session cookie.
|
||||
SECRET_KEY = os.getenv("SECRET_KEY", "")
|
||||
if not SECRET_KEY or SECRET_KEY == "change-me-in-production-please":
|
||||
raise RuntimeError(
|
||||
"SECRET_KEY env var must be set (shared with dereth-tracker; see "
|
||||
"/etc/overlord/agent.env) — refusing to start with a forgeable "
|
||||
"session-signing key"
|
||||
)
|
||||
SESSION_MAX_AGE = 30 * 24 * 3600 # 30 days
|
||||
_serializer = URLSafeTimedSerializer(SECRET_KEY)
|
||||
|
||||
|
|
|
|||
|
|
@ -20,8 +20,10 @@ WorkingDirectory=/home/erik/MosswartOverlord
|
|||
# HOME explicitly set so claude reads /var/lib/overlord-agent/.claude/*
|
||||
# instead of trying /home/erik/.claude/* (which is now 0700, locked out).
|
||||
Environment="HOME=/var/lib/overlord-agent"
|
||||
# Secrets file (root:overlord-agent 0640).
|
||||
EnvironmentFile=-/etc/overlord/agent.env
|
||||
# Secrets file (root:overlord-agent 0640). REQUIRED (no leading '-'):
|
||||
# a missing secrets file must abort startup, not fail open — auth.py also
|
||||
# refuses to start without SECRET_KEY.
|
||||
EnvironmentFile=/etc/overlord/agent.env
|
||||
# Run inside the venv populated by install.sh.
|
||||
ExecStart=/home/erik/MosswartOverlord/agent/.venv/bin/python -m agent.service
|
||||
Restart=on-failure
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue