Skip to content

Security: sssaturX/farm

Security

docs/SECURITY.md

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

Документ описывает меры безопасности, реализованные в проекте: защита API, хранение ключей бирж и общая архитектура безопасности.


1. Аутентификация и авторизация API

1.1 JWT-токены

  • Access Token: срок жизни 15 минут, алгоритм HS256
  • Refresh Token: срок жизни 7 дней, хранится в PostgreSQL как bcrypt-хеш
  • Все маршруты /api/* защищены middleware, кроме /api/auth/* и /api/health

1.2 Проверка токена

  • Требуется заголовок Authorization: Bearer <token>
  • При истечении access token клиент использует refresh token для получения новой пары
  • Refresh-токены хранятся только в виде хеша (bcrypt), нельзя восстановить исходный токен из БД

1.3 Пароли пользователей

  • Хеширование: bcrypt с 12 раундами
  • Пароль не хранится в открытом виде, в БД — только password_hash
  • Валидация при регистрации: минимум 8 символов, максимум 128

1.4 Изоляция по пользователям

  • Каждый запрос привязан к userId из JWT
  • Доступ к аккаунтам бирж, позициям и ордерам ограничен данными текущего пользователя
  • exchange_accounts, manual_positions, trade_tasks фильтруются по user_id

2. Защита ключей бирж (KMS)

2.1 Key Management Service (key-service)

Выделенный микросервис — единственное место в системе, где хранится и используется мастер-ключ шифрования.

  • Алгоритм: AES-256-GCM (аутентифицированное шифрование)
  • IV: 12 случайных байт на каждое шифрование
  • MASTER_ENCRYPTION_KEY: 64 hex-символа (32 байта), передаётся только в key-service через MASTER_ENCRYPTION_KEY

2.2 Хранение ключей в БД

В PostgreSQL в таблице exchange_accounts хранятся:

  • encrypted_credentials — зашифрованный JSON с apiKey, apiSecret, authToken и т.п.
  • encryption_iv — инициализационный вектор
  • encryption_tag — тег аутентификации GCM

Ключи в открытом виде в БД не хранятся.

2.3 Дешифрование

  • node-service не имеет прямого доступа к мастер-ключу
  • Для дешифрования credentials используется HTTP-клиент (kms-client.ts), который вызывает key-service
  • trading-worker при исполнении ордеров запрашивает расшифровку у key-service по accountId
  • Credentials передаются по внутренней сети и не сохраняются в логах

2.4 Изоляция key-service

  • Порт key-service не пробрасывается на хост — доступ только из Docker-сети
  • Доступ к эндпоинтам key-service защищён внутренним токеном KMS_INTERNAL_TOKEN
  • Заголовок x-internal-token обязателен при вызове /encrypt, /decrypt, /decrypt-raw (если токен задан)
  • В dev-режиме, если KMS_INTERNAL_TOKEN не задан, доступ разрешён для упрощения разработки

3. Rate limiting

3.1 Ограничения на запросы

Маршрут Лимит Ключ
Общие API-запросы 100/мин userId
Торговые операции (/api/orders) 10/мин userId
Аутентификация (/api/auth/*) 20/мин IP

3.2 Хранение счётчиков

  • Redis (prefixes: rl:general, rl:trading, rl:auth)
  • Окно: 60 секунд
  • При недоступности Redis лимиты не применяются (graceful degradation)

4. Аудит и логирование

4.1 Audit logs

События записываются в таблицу audit_logs:

  • Регистрация (register)
  • Вход (login)
  • Добавление аккаунта биржи (add_account)
  • Удаление аккаунта (delete_account)

Содержимое: user_id, action, details (JSON), ip_address, created_at.

4.2 Что не логируется

  • Пароли и токены не логируются
  • Расшифрованные credentials не пишутся в логи
  • В логах trading-worker — только taskId, exchange, symbol, без передаваемых объёмов и цен в явном виде

5. Микросервисная архитектура

5.1 Разделение ответственности

  • API (node-service) — аутентификация, валидация, маршрутизация; не выполняет ордера напрямую
  • trading-worker — единственный компонент, выполняющий ордера на биржах; получает credentials только через key-service
  • key-service — только шифрование и дешифрование; не участвует в логике торговли
  • ws-service — стриминг цен и позиций; не имеет доступа к ключам

5.2 Внутренняя коммуникация

  • NATS JetStream для очереди ордеров — сообщения содержат accountId (UUID), а не сами ключи
  • Внутренние HTTP-вызовы (node-service → key-service, trading-worker → key-service) — только внутри Docker-сети

6. Рекомендации для production

  1. JWT_SECRET — надёжный случайный секрет длиной не менее 32 байт
  2. MASTER_ENCRYPTION_KEY — 64 hex-символа, хранить в secrets manager, не в репозитории
  3. KMS_INTERNAL_TOKEN — задать для production; без него key-service доступен любому сервису в сети
  4. POSTGRES_PASSWORD — сильный пароль
  5. HTTPS — использовать Nginx с SSL/TLS; для production — валидный сертификат
  6. Firewall — не открывать порты key-service, postgres, redis, nats наружу, если это не требуется

7. Схема доступа к ключам

┌─────────────┐     JWT      ┌─────────────┐    accountId    ┌──────────────┐
│  Dashboard  │ ───────────► │ node-service│ ──────────────► │ NATS         │
└─────────────┘              └─────────────┘                 └──────┬───────┘
                        │                                          │
                        │ kmsEncrypt (при добавлении аккаунта)      │ trades.open/close
                        ▼                                          ▼
                 ┌─────────────┐                            ┌──────────────┐
                 │ key-service │ ◄── decrypt (accountId) ─── │trading-worker│
                 │ MASTER_KEY  │                            └──────────────┘
                 └──────┬──────┘
                        │
                        │ читает encrypted_credentials из PostgreSQL
                        ▼
                 ┌─────────────┐
                 │ PostgreSQL  │  (encrypted_credentials, iv, tag)
                 └─────────────┘

Документ актуален на дату последнего обновления.

There aren't any published security advisories