Files

5.1 KiB
Raw Permalink Blame History

Безопасность

Compton MVP — не банк, но и не «admin/admin в prod». Ниже — как устроена защита и что проверить перед выкладкой.

Auth: схема

sequenceDiagram
  participant B as Браузер
  participant API as FastAPI
  participant RD as Redis
  participant PG as PostgreSQL

  B->>API: POST /auth/login
  API->>PG: bcrypt verify
  API->>RD: read auth_epoch
  API-->>B: access JWT (memory) + refresh cookie

  B->>API: GET /users/me + Bearer
  API->>RD: jti denied? epoch ok?
  alt revoked
    API-->>B: 401 TOKEN_REVOKED
  else ok
    API-->>B: 200
  end

  B->>API: POST /auth/logout
  API->>RD: deny_jti + revoke refresh
  API-->>B: cookie cleared

Токены

Токен Где живёт Отзыв
Access JWT память frontend jti denylist + auth_epoch (Redis)
Refresh HttpOnly cookie rotation + family reuse detection
Email/reset opaque → hash в БД one-time, TTL 1ч

JWT claims: sub, role, jti, auth_epoch, exp.

Мгновенный revoke

apps/api/app/core/jwt_denylist.py:

Redis key Смысл
jwt:deny:{jti} конкретный access-токен
auth:epoch:{user_id} версия сессий пользователя
Событие Действие
Logout deny jti + revoke refresh
Block INCR epoch + revoke refresh
Смена/reset пароля INCR epoch + revoke refresh

Production: без Redis API не стартует. Redis упал — fail-closed (401, не «ну ладно»).

Dev: in-memory fallback (не путать с prod).

Криптография

Всё через apps/api/app/core/crypto.py:

Данные Метод
Пароли bcrypt cost 12
Access JWT HS256
Refresh/email tokens SHA-256 + pepper
Media URLs HMAC-SHA256 + TTL
Install secrets secrets.token_*, generate-once + lock

Install secrets

python apps/api/scripts/bootstrap_install.py   # до первого docker compose up
Файл Содержимое
data/secrets/install.env PG, JWT, S3, MinIO
install.meta.json install ID, lock time

Не ротировать POSTGRES_PASSWORD / JWT после bootstrap без плана — иначе Postgres скажет фразу, которую вы уже видели, и будет прав.

Reveal: Admin → Security → Install Secrets (superuser, аудит в admin-audit.jsonl).

Восстановление: deploy.md § восстановление.

RBAC

Правило Enforcement
/admin → role=admin Guard + API
Security/Diagnostics/secrets → superuser API + UI tabs
Нельзя block/demote себя admin service
Last admin protected admin service
blocked/pending → 403 refresh auth service
forgot_password skip для blocked auth service
IDOR на профиль users router

HTTP / инфра

Nginx headers

Header Значение
X-Frame-Options DENY
X-Content-Type-Options nosniff
Referrer-Policy strict-origin-when-cross-origin
HSTS default.tls.conf (staging/prod)

Прочее

  • Origin/Referer на cookie-auth endpoints
  • Rate limit (prod: обязателен)
  • CMS: bleach, протоколы http/https/mailto
  • Avatar: jpeg/png/webp, re-encode, SVG — нет
  • CI: Bandit, pip-audit, gitleaks, npm audit
  • Postgres/Redis/MinIO — internal network
  • Firewall VPS: 22, 80, 443

Production guards

APP_ENV=production → API не стартует, если:

Проблема Env
Test routes ENABLE_TEST_ROUTES=true
OpenAPI ENABLE_DOCS=true
Rate limit off ENABLE_RATE_LIMIT=false
Cookie без Secure COOKIE_SECURE=false
Placeholder JWT change-me-*
Дефолтная БД user:pass
Без SSL mode нет sslmode=require
Без Redis JWT revocation

Prod env (минимум)

Переменная Значение
APP_ENV production
ENABLE_DOCS false
ENABLE_TEST_ROUTES false
COOKIE_SECURE true
ENABLE_RATE_LIMIT true
EMAIL_DELIVERY_MODE smtp
SEED_DEMO_USERS false
DATABASE_URL …?sslmode=require

Чеклист

Сделано в коде

  • JWT в memory, refresh HttpOnly
  • Anti-enumeration auth
  • Origin/Referer validation
  • RBAC + superuser
  • CMS sanitization
  • Nginx security headers
  • CI security scans
  • Install secrets bootstrap + lock
  • JWT jti denylist + auth_epoch
  • Admin audit log

Проверить на staging

  • /api/v1/docs → 404
  • HSTS за TLS
  • Dry-run recovery секретов
  • ZAP: 0 High/Critical → release.md
  • k6 pass → release.md
  • Lighthouse ≥ 85 на /