Архитектура безопасности¶
1. Обзор архитектуры¶
Saga реализует многоуровневую архитектуру безопасности (defense-in-depth) с несколькими независимыми уровнями защиты.
flowchart TB
subgraph Internet["🌐 Интернет"]
User["👤 Пользователь"]
end
subgraph Layer1["Уровень 1: TLS терминация"]
NGINX["🔒 NGINX<br/>TLS 1.3 / HSTS<br/>Let's Encrypt"]
end
subgraph Layer2["Уровень 2: Middleware"]
CORS["CORS"]
Headers["Security<br/>Headers"]
RateLimit["Rate<br/>Limiting"]
Auth["JWT<br/>Auth"]
end
subgraph Layer3["Уровень 3: Бизнес-логика"]
AuthService["Auth<br/>Service"]
InvestService["Investment<br/>Service"]
WithdrawService["Withdrawal<br/>Service"]
end
subgraph Layer4["Уровень 4: Данные"]
DB[("PostgreSQL<br/>Parameterized queries")]
end
subgraph External["Внешние сервисы (SOC 2)"]
Supabase["Supabase Auth"]
Fordefi["Fordefi Custody"]
Crypto2B["Crypto2B"]
end
User --> NGINX
NGINX --> CORS --> Headers --> RateLimit --> Auth
Auth --> AuthService
Auth --> InvestService
Auth --> WithdrawService
AuthService --> DB
InvestService --> DB
WithdrawService --> DB
AuthService --> Supabase
WithdrawService --> Fordefi
AuthService --> Crypto2B
2. Границы доверия¶
Граница 1: Интернет → Приложение¶
Контроли:
- TLS 1.3 терминация на NGINX
- HSTS enforcement (production)
- Rate limiting на входе
Граница 2: Frontend → Backend API¶
Контроли:
- JWT аутентификация обязательна
- CORS валидация origin
- Content Security Policy
- Ограничение размера запросов
Граница 3: Backend → База данных¶
Контроли:
- Параметризованные запросы (без SQL injection)
- Connection pooling с лимитами
- TCP соединение (127.0.0.1, не socket)
Граница 4: Backend → Внешние сервисы¶
Контроли:
- API key аутентификация
- Верификация подписи webhook'ов
- Только HTTPS коммуникация
- Логирование запросов/ответов
3. Архитектура аутентификации¶
3.1 Двухтокенная система¶
sequenceDiagram
participant U as Пользователь
participant F as Frontend
participant S as Supabase Auth
participant B as Backend
participant DB as PostgreSQL
U->>F: Вход через Google/Email
F->>S: OAuth / Email Auth
S-->>F: Supabase JWT
F->>B: POST /api/auth/supabase/login
B->>S: Верификация JWKS
S-->>B: Token валиден
B->>DB: Upsert пользователя
B-->>F: Backend JWT (HS256)
F->>F: Сохранение в localStorage
3.2 Типы токенов¶
| Тип токена | Аудитория | Время жизни | Claims |
|---|---|---|---|
| JWTClaims (User) | /api/user/* |
24ч | user_id, email |
| AdminClaims | /api/admin/* |
24ч | email, permissions, roles |
3.3 Безопасность JWT¶
| Свойство | Значение |
|---|---|
| Алгоритм | HS256 (HMAC-SHA256) |
| Длина секрета | 32+ байт (из env) |
| Issuer | saga-defi-platform |
| Expiration | 24 часа |
| Refresh | Не реализован (требуется повторная авторизация) |
Файлы реализации:
backend/auth/service/jwt_mvp.gobackend/shared/http/jwt_validator.gobackend/shared/middleware/auth_middleware.gobackend/shared/middleware/admin_auth_middleware.go
4. Модель авторизации¶
4.1 Ролевой доступ (RBAC)¶
flowchart LR
subgraph Public["🔓 Публичные (без auth)"]
H["/health"]
AH["/api/health"]
AA["/api/auth/*"]
end
subgraph User["👤 Пользовательские (JWTClaims)"]
UB["/api/user/balance"]
UI["/api/user/investments"]
UW["/api/user/withdrawals"]
end
subgraph Admin["👑 Админские (AdminClaims)"]
AU["/api/admin/users"]
AW["/api/admin/withdrawals/*/approve"]
AI["/api/admin/investments"]
end
4.2 Проверка администратора¶
Администраторы определяются в конфигурации, НЕ в базе данных:
# config/auth.yaml
admins:
- email: "admin@saga.fund"
permissions:
- "approve_withdrawals"
- "view_all_users"
Проверка в middleware:
if !cfg.IsAdmin(adminEmail) {
http_helpers.SendError(w, http.StatusForbidden, "Not an admin")
return
}
5. Стек Security Middleware¶
5.1 Порядок выполнения¶
flowchart LR
R["Request"] --> C["CORS"]
C --> S["Security Headers"]
S --> RL["Rate Limit"]
RL --> A["Auth"]
A --> H["Handler"]
5.2 Security Headers¶
| Заголовок | Значение | Защита от |
|---|---|---|
| Content-Security-Policy | См. секцию CSP | XSS |
| X-Frame-Options | DENY | Clickjacking |
| X-Content-Type-Options | nosniff | MIME sniffing |
| Referrer-Policy | strict-origin-when-cross-origin | Утечка информации |
| Permissions-Policy | camera=(), microphone=(), geolocation=() | Злоупотребление API |
| Cross-Origin-Opener-Policy | same-origin-allow-popups | Cross-origin атаки |
| Strict-Transport-Security | max-age=31536000; includeSubDomains | Downgrade атаки |
Реализация: backend/shared/middleware/security_headers_middleware.go
5.3 Content Security Policy¶
default-src 'self';
script-src 'self' 'unsafe-inline' 'unsafe-eval' https://accounts.google.com;
style-src 'self' 'unsafe-inline';
img-src 'self' data: https:;
connect-src 'self' https://*.supabase.co wss://*.supabase.co;
frame-src 'self' https://accounts.google.com;
Реализация: backend/shared/middleware/csp.go
5.4 Rate Limiting¶
| Тип endpoint | Лимит | Окно | Алгоритм |
|---|---|---|---|
Финансовые (/api/user/investments, /api/user/withdrawals) |
5 req | 60с | Token Bucket |
Аутентификация (/api/auth/*) |
20 req | 60с | Token Bucket |
| Общие | 100 req | 60с | Token Bucket |
Идентификация клиента: По IP (X-Forwarded-For или RemoteAddr)
Реализация: backend/shared/middleware/rate_limiting_middleware.go
6. Защита данных¶
6.1 Классификация данных¶
| Категория | Примеры | Защита |
|---|---|---|
| Критичные | JWT секреты, API ключи | Env переменные, никогда не логируются |
| Чувствительные | Email пользователей, балансы | Шифрование в транзите, контроль доступа |
| Внутренние | ID транзакций, timestamps | Стандартный контроль доступа |
| Публичные | Инвестиционные стратегии, ставки | Без специальной защиты |
6.2 Шифрование¶
| Уровень | Метод |
|---|---|
| В транзите | TLS 1.3 (NGINX) |
| В покое | PostgreSQL (OS-level encryption) |
| JWT | HMAC-SHA256 подпись |
6.3 Управление секретами¶
| Секрет | Хранение | Ротация |
|---|---|---|
| JWT_SECRET | .env файл | Ручная (рекомендуется: ежеквартально) |
| Учётные данные БД | .env файл | При компрометации |
| Fordefi API key | .env файл | По политике Fordefi |
| Crypto2B API key | .env файл | По политике Crypto2B |
| Supabase keys | .env файл | По политике Supabase |
ВАЖНО: Никакие секреты не коммитятся в git. Все через env переменные.
7. Валидация входных данных¶
7.1 Backend валидация¶
Библиотека: go-playground/validator/v10
type CreateWithdrawalRequest struct {
Amount decimal.Decimal `json:"amount" validate:"required,gt=0"`
ToAddress string `json:"to_address" validate:"required,eth_addr"`
Currency string `json:"currency" validate:"required,oneof=USDC USDT"`
}
7.2 Валидация адресов¶
Ethereum адреса валидируются с помощью библиотеки go-ethereum:
7.3 Финансовые вычисления¶
Тип: SafeDecimal (обёртка над shopspring/decimal)
- Без арифметики с плавающей точкой
- Защита от overflow/underflow
- Точность: 18 десятичных знаков
8. Логирование и мониторинг¶
8.1 Security логирование¶
Что логируется:
- Попытки аутентификации (успех/неудача)
- Отказы в авторизации
- Срабатывания rate limit
- Ошибки API
- Неудачные валидации токенов (только префикс)
Что НЕ логируется:
- Полные JWT токены
- Пароли
- API ключи
- Приватные ключи (на платформе отсутствуют)
8.2 Структурированное логирование¶
logger.WarnStructured("JWT validation failed",
"component", "auth_middleware",
"token_prefix", token[:20], // Только первые 20 символов
"error", err.Error())
9. Безопасность инфраструктуры¶
9.1 Безопасность контейнера¶
- Единый контейнер с минимальными зависимостями
- Выполнение от non-root пользователя
- Read-only файловая система где возможно
- Нет SSH доступа внутри контейнера
9.2 Сетевая архитектура¶
flowchart LR
Internet["🌐 Интернет"] --> NGINX["NGINX :443"]
NGINX --> App["App Container :8080"]
App --> DB["PostgreSQL :5432<br/>(только localhost)"]
9.3 Blue-Green Deployment¶
- Zero-downtime deployments
- Автоматический rollback при провале health check
- Immutable deployments (без обновлений на месте)
10. Аспекты реагирования на инциденты¶
10.1 События безопасности¶
| Событие | Обнаружение | Реакция |
|---|---|---|
| Brute force auth | Логи rate limit | Авто-блокировка IP |
| Компрометация JWT | Ручной отчёт | Ротация JWT_SECRET |
| Компрометация admin аккаунта | Обнаружение аномалий | Отзыв доступа, аудит логов |
| Утечка данных | Внешний отчёт | План реагирования на инциденты |
10.2 Audit Trail¶
Все финансовые операции записываются в таблицу transactions:
- Immutable (append-only)
- С timestamps
- С атрибуцией пользователя
- С отслеживанием статуса