gendesign/docs/runbooks/basic_auth_management.md
lekss361 0e294641a1
All checks were successful
Deploy / changes (push) Successful in 5s
Deploy / build-backend (push) Successful in 36s
Deploy / build-worker (push) Successful in 36s
Deploy / build-frontend (push) Successful in 42s
Deploy / deploy (push) Successful in 57s
fix(security): log_credentials + auth_audit.log → username из 401 (#436)
2026-05-23 09:59:50 +00:00

5.9 KiB
Raw Blame History

Basic Auth Management Runbook

Установлено: 2026-05-23 (PR #426, commit cc2d148) Realm: "GenDesign Pilot" URL: https://gendsgn.ru/

Добавить пользователя

./scripts/auth/add_user.sh <username>
# Вводи пароль интерактивно; скрипт добавляет в caddy/users.caddy.snippet

После: commit snippet → PR → merge → GHA deploy → Caddy reload (автоматически в deploy.yml).

Удалить пользователя

  1. ./scripts/auth/remove_user.sh <username> ASAP
  2. Commit + push + PR (merge приоритетным)
  3. docker compose exec caddy caddy reload после deploy
  4. Сгенерировать новый credential через add_user.sh
  5. Уведомить остальных стейкхолдеров о замене

Просмотр текущих пользователей

./scripts/auth/list_users.sh

Credencial rotation

При компрометации пароля: remove_user + add_user с новым паролем + PR-merge + разослать новый credential.

Аудит логи

  • Auth audit: /var/log/caddy/auth_audit.log — все события basic_auth (включая raw Authorization). Содержит plain credentials в Base64 — accessible только root на VPS. Используется forwarder'ом (см. ops/glitchtip-auth-forwarder/forwarder.py). Retention: 7 дней (roll_size 10MiB, keep 3, 168h).

  • Access log: /var/log/caddy/gendsgn.ru.log — все requests, format JSON. Тоже содержит raw Authorization из-за global log_credentials (Caddy 2.x — опция только global, нельзя per-block). Retention: 30 дней (roll_size 50MiB, keep 5, 720h).

Failed auth последние 100:

docker compose -f docker-compose.prod.yml exec caddy \
  grep -P '"status":401' /var/log/caddy/auth_audit.log | tail -100 | jq

Security note

log_credentials — опция под servers { } global block, нельзя per-virtual-host. Plain Base64 credentials попадают в оба log файла. Mitigation:

  • VPS root-only (только SSH key authorized owner)
  • Retention: gendsgn.ru.log = 30 дней, auth_audit.log = 7 дней
  • Не выгружать логи на внешние системы без redaction

Диагностика

# Посмотреть 401-ошибки в auth audit log
ssh gendesign 'docker compose -p gendesign exec caddy tail -f /var/log/caddy/auth_audit.log' | grep '"status":401'

# Reload конфига Caddy без перезапуска
ssh gendesign 'docker compose -p gendesign exec -T caddy caddy reload --config /etc/caddy/Caddyfile'

GlitchTip auth event forwarding

Sidecar gendesign-auth-forwarder шлёт 401 события в GlitchTip как Sentry warning events.

  • Состояние: docker compose -p gendesign ps | grep auth-forwarder
  • Logs: docker compose -p gendesign logs -f glitchtip-auth-forwarder
  • GlitchTip dashboard: https://errors.gendsgn.ru/ — фильтр event_type:basic_auth_failed
  • Storm digest: при >10 failed auth за 60s → отдельный event_type:basic_auth_storm event
  • Мониторы (GlitchTip uptime, SentryUptimeBot) — получают 401 стабильно из-за отсутствия credentials; они фильтруются как individual events, учитываются только в storm digest

Если sidecar упал — failed auth события не теряются (offset persistent в auth_forwarder_state volume), но в GlitchTip не доезжают пока container down.

Перезапуск forwarder

ssh gendesign 'docker compose -p gendesign restart glitchtip-auth-forwarder'

Переменные окружения forwarder

Задаются в /opt/gendesign/.env на VPS:

Переменная Описание Обязательна
GLITCHTIP_DSN Sentry DSN GlitchTip (project backend) Да

Deploy

Sidecar собирается локально на VPS на каждом запуске deploy.yml (после merge в main). Не требует pre-push image build, не использует GHCR.

Forwarder контейнер пересоздаётся --force-recreate чтобы подхватить новый image при изменении кода.

В случае sidecar не запустился:

ssh gendesign 'docker compose -p gendesign -f docker-compose.prod.yml logs --tail=100 glitchtip-auth-forwarder'

Если build fail на VPS — проверь ops/glitchtip-auth-forwarder/Dockerfile локально:

docker build ops/glitchtip-auth-forwarder/

Phase 2 — реализовано (PR #430)

GlitchTip forwarder sidecar добавлен в ops/glitchtip-auth-forwarder/. Архитектура: Python 3.12 slim, sentry-sdk 2.18, tail live Caddy log, offset в named volume. Deploy автоматизирован через deploy.yml — ручной SSH на VPS не нужен.

Phase 3 — реализовано (PR #436)

log_credentials + auth_audit.log → forwarder получает реальный username из 401.

  • Global log_credentials в Caddyfile — Caddy перестаёт редактировать Authorization header.
  • Отдельный auth_audit.log (retention 7d) — forwarder читает именно его.
  • _extract_attempted_username декодирует Basic auth → attempted_username tag в GlitchTip event.
  • Результат: GlitchTip event получает attempted_username:testbruteforce вместо (none).

Phase 4 (TODO)

  • При >30 users — миграция на OAuth/NextAuth
  • Разделение admin/user по доступу через Caddy path matcher или app-level RBAC