feat(auth): shared-secret auth web-app → ops-agent

- ops-agent/src/auth.ts: constant-time compare via timingSafeEqual to prevent timing attacks; store secret as Buffer
- ops-agent/src/index.ts + ops-agent.service: bind on 127.0.0.1:3099 (was 4242, per plan)
- app/api/agent/[...path]/route.ts: Next.js proxy route that verifies ops_session cookie then forwards requests to agent with Authorization: Bearer <secret>
- .env.example + deploy/ops-dashboard.env.example: add OPS_AGENT_SECRET and OPS_AGENT_URL
- README.md: rotation procedure for the shared secret

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Scrum4Me Agent 2026-05-13 17:22:37 +02:00
parent d605eb17a5
commit 92d450609c
7 changed files with 90 additions and 8 deletions

View file

@ -14,7 +14,7 @@ StandardOutput=journal
StandardError=journal
SyslogIdentifier=ops-agent
Environment=OPS_AGENT_PORT=4242
Environment=OPS_AGENT_PORT=3099
Environment=OPS_AGENT_HOST=127.0.0.1
Environment=OPS_AGENT_WHITELIST_PATH=/etc/ops-agent/commands.yml
Environment=OPS_AGENT_SECRET_PATH=/etc/ops-agent/secret

View file

@ -3,3 +3,6 @@ DATABASE_URL="postgresql://USER:PASSWORD@postgres:5432/ops_dashboard"
SEED_USER_EMAIL="admin@example.com"
SEED_USER_PASSWORD="changeme"
SESSION_SECRET="replace-with-a-long-random-string"
# Shared secret for ops-agent auth — must match /etc/ops-agent/secret on the host
OPS_AGENT_SECRET="replace-with-contents-of-/etc/ops-agent/secret"
OPS_AGENT_URL="http://127.0.0.1:3099"