Архитектура безопасности
Общая схема
Client → Nginx/Ingress (TLS) → CORS middleware → Rate limiter
→ Security headers → Auth middleware → RBAC middleware → HandlerКаждый запрос проходит несколько уровней проверки.
JWT аутентификация
SLOzy использует JWT (HS256) для аутентификации API-запросов.
- Access token: живёт 8 часов, передаётся в заголовке
Authorization: Bearer <token> - Refresh token: живёт 30 дней, используется для обновления access token
- Claims: user_id, organization_id, email, name
json
{
"user_id": 42,
"organization_id": 1,
"email": "user@example.com",
"exp": 1750000000,
"iss": "slozy"
}RBAC (Role-Based Access Control)
Четыре предопределённых роли:
| Роль | Описание | Права |
|---|---|---|
| Admin | Полный доступ | Все permissions |
| Manager | Управление SLO и командами | read, write, manage_teams, view_analytics |
| Developer | Работа с SLO и метриками | read, write, view_analytics |
| Viewer | Только чтение | read, view_analytics |
Rate limiting
Реализован token bucket алгоритм:
- Глобальный лимит: 1000 запросов/минуту
- На IP: 100 запросов/минуту
- Burst: 50 (глобальный), 10 (на IP)
- Чистка: неактивные посетители удаляются через 5 минут
Security headers
Каждый ответ содержит защитные заголовки:
http
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Referrer-Policy: strict-origin-when-cross-origin
Strict-Transport-Security: max-age=31536000; includeSubDomains
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'
Permissions-Policy: default-src 'self'
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corpCORS
CORS middleware проверяет Origin запроса против белого списка:
go
allowedOrigins := []string{
"http://localhost:3000",
"http://localhost:8080",
"https://slozy.example.com",
}Настройка через переменную окружения CORS_ORIGINS.
Prometheus TLS
Для защиты /metrics эндпоинта Prometheus настроен с TLS:
yaml
- job_name: 'kubernetes-pods'
scheme: https
tls_config:
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crtВ production рекомендуется закрыть метрики за basic auth или использовать отдельный service mesh.