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

132 lines
5.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Basic Auth Management Runbook
**Установлено**: 2026-05-23 (PR #426, commit `cc2d148`)
**Realm**: `"GenDesign Pilot"`
**URL**: <https://gendsgn.ru/>
## Добавить пользователя
```bash
./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. Уведомить остальных стейкхолдеров о замене
## Просмотр текущих пользователей
```bash
./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:
```bash
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
## Диагностика
```bash
# Посмотреть 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
```bash
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 не запустился:
```bash
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` локально:
```bash
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