DDD безопасность — security-инженер участвует в 7 из 16 разделов DDD-спецификации. Его задача -- обеспечить защиту данных, предотвратить утечки, контролировать авторизацию и аудит на всех уровнях системы: от API до интеграций и событийной шины.

Полная структура артефакта описана в Шаблоне. Ниже собраны все блоки, адресованные Security-инженеру, с привязкой к разделам спецификации.

Все примеры используют единый домен -- "Интернет-магазин: оформление заказа".


DDD безопасность: 1. Авторизация и доступ (раздел 5 -- Роли и права доступа)

Роли -- фундамент модели авторизации. В системе три роли: Customer, Manager, Admin. Каждая имеет строго ограниченный набор команд и область видимости данных.

Принцип least privilege. Каждая роль получает только минимально необходимые права. Customer видит и управляет только своими заказами. Manager -- заказами своего региона. Admin имеет полный доступ, но не может удалять заказы (данные сохраняются для аудита).

IDOR (Insecure Direct Object Reference). Каждый эндпоинт, принимающий orderId, обязан проверять, что текущий пользователь имеет право доступа к этому заказу. UUID сам по себе не является защитой -- его можно подобрать или перехватить.

Privilege escalation. В системе не должно быть API-метода или последовательности вызовов, позволяющих повысить роль пользователя. Роль определяется из JWT claim и не может быть изменена через бизнес-операции.

Аудит действий. Все команды логируются: кто (userId, роль), когда, что сделал, результат. Логи -- immutable, доступ к ним ограничен Security-командой.

Session management. Таймаут сессии должен быть настроен. При смене роли пользователя -- инвалидация текущей сессии.


2. Безопасность команд (раздел 7 -- Commands)

Команды -- это точки входа для атак. Каждая команда принимает пользовательский ввод и изменяет состояние системы.

Input validation. Все параметры валидируются на сервере, независимо от клиентской валидации. quantity -- целое число от 1 до 99. productId -- формат без спецсимволов. deliveryAddress -- санитизация от XSS. reason в CancelOrder -- ограничение длины, запрет HTML/JS.

SQL injection. Все запросы к базе данных через prepared statements / parameterized queries. Никакой конкатенации пользовательского ввода в SQL.

Rate limiting. Ограничения на частоту вызовов команд:

  • CreateOrder -- не более 10 в минуту на пользователя
  • ConfirmOrder -- не более 5 в минуту на пользователя
  • Превышение лимита -- HTTP 429 и событие аудита безопасности

Idempotency key. Команда CreateOrder принимает idempotency key, привязанный к userId. Это предотвращает дублирование заказов при повторных отправках и защищает от replay-атак.

Mass assignment. DTO команд содержат только разрешенные поля. Покупатель не может передать status: PAID или role: ADMIN в теле запроса. Сервер игнорирует любые поля, не определенные в контракте.


3. Защита данных в событиях (раздел 8 -- Domain Events)

Доменные события -- потенциальный канал утечки персональных данных. События публикуются в Kafka и доступны всем подписчикам топика.

PII в payload. Событие OrderCreated содержит customerId, адрес доставки, телефон, ФИО получателя. Эти данные попадают в Kafka и оседают в логах подписчиков. Решения:

  • Минимизация: передавать только customerId, подписчик запрашивает ПД по ID при необходимости
  • Шифрование PII-полей в payload события
  • Отдельный топик с ограниченным доступом для событий, содержащих ПД

GDPR / 152-ФЗ. При запросе субъекта на удаление персональных данных -- применять crypto-shredding: удаление ключа шифрования делает зашифрованные ПД в событиях нечитаемыми без необходимости модификации самих событий.

Audit events. Помимо доменных событий, система формирует события аудита безопасности:

  • Неудачная авторизация
  • Попытка IDOR (доступ к чужому заказу)
  • Превышение rate limit
  • Формат: {eventType, action, userId, targetOrderId, ip, userAgent, timestamp}
  • Хранение: отдельный топик или БД, retention >= 1 год

Kafka ACL. Топик order-events доступен только авторизованным consumer groups. Список разрешенных групп фиксируется и ревьюится при добавлении нового подписчика.


4. Безопасность API (раздел 9.1 -- API-контракт)

API-контракт определяет поверхность атаки системы. Каждый эндпоинт -- потенциальная точка входа.

Утечка PII в ответах. Эндпоинт GetOrder возвращает адрес доставки с ФИО и телефоном получателя. Эти данные доступны только владельцу заказа и авторизованным ролям (Manager своего региона, Admin). Для остальных -- 404.

PII в query params. Запрещено передавать персональные данные в параметрах URL: GET /api/v1/orders?phone=... -- недопустимо. ПД передаются только в body (POST) или как идентификатор в path. Query params логируются веб-серверами и прокси.

Авторизация каждого эндпоинта. В OpenAPI spec для каждого эндпоинта указана security схема. Нет эндпоинтов без авторизации (кроме health check).

404 вместо 403 для чужих заказов. При запросе чужого заказа система возвращает 404 (ORDER_NOT_FOUND), а не 403. Это не подтверждает существование ресурса и защищает от перебора идентификаторов.

Rate limiting headers. Все ответы API включают заголовки: X-RateLimit-Limit, X-RateLimit-Remaining, Retry-After. Это позволяет клиентам корректно обрабатывать ограничения и снижает нагрузку от повторных запросов.


5. Каталог ошибок (раздел 13)

Сообщения об ошибках -- потенциальный канал утечки информации о внутреннем устройстве системы.

Information leakage. В ответах клиенту запрещены: stack traces, SQL-запросы, внутренние пути файловой системы, версии ПО и библиотек, имена серверов и IP-адреса.

Enumeration protection. Для чужих заказов система возвращает ORDER_NOT_FOUND (HTTP 404), а не 403 Forbidden. Это не позволяет атакующему определить, существует ли заказ с данным ID.

5xx ошибки. При внутренних ошибках клиент получает generic-сообщение "Внутренняя ошибка сервера" с requestId для корреляции. Никаких технических деталей. requestId позволяет сопровождению найти полную информацию в логах.

Logging vs response. Полная техническая информация об ошибке (stack trace, параметры запроса, состояние системы) фиксируется в логах. Клиенту отдается только код ошибки и user-friendly сообщение. Два потока информации не должны пересекаться.


6. Безопасность интеграций (раздел 14 -- Context Mapping)

Интеграции с внешними системами расширяют поверхность атаки. Каждое внешнее соединение -- потенциальная точка компрометации.

TLS everywhere. Все соединения используют HTTPS/TLS 1.2+. Для внутренних сервисов -- mTLS (взаимная аутентификация по сертификатам).

Аутентификация между сервисами:

  • Каталог товаров -- API key или OAuth2 client credentials
  • Платежный шлюз -- mTLS + API key (требования PCI DSS)
  • Kafka -- SASL/SCRAM или mTLS

Секреты. API-ключи, пароли, сертификаты не хранятся в коде и не коммитятся в репозиторий. Используется Vault или Sealed Secrets с регулярной ротацией.

Input validation от внешних систем. ACL-адаптер валидирует все входящие данные от внешних систем. Внешняя система может быть скомпрометирована -- её ответы нельзя считать доверенными.

Webhook verification. Callback от платежного шлюза (событие OrderPaid) -- обязательная проверка HMAC-подписи. Без валидной подписи webhook отклоняется.

PII через интеграции. При передаче данных в контекст "Доставка" отправляется минимум: адрес и имя получателя. Не передаются: email, история заказов, платежные данные.

Network policies. В Kubernetes сетевой доступ ограничен: сервис заказов может обращаться только к Каталогу, Оплате, Складу и Доставке. Все остальные соединения запрещены на уровне NetworkPolicy.


7. Аутентификация и защита данных (раздел 16 -- НФТ)

Нефункциональные требования определяют базовый уровень безопасности системы.

Аутентификация. JWT с алгоритмом RS256 (асимметричная подпись, не HS256). Access token TTL <= 15 минут. Refresh token -- httpOnly secure cookie. CORS -- только домены фронтенда, запрещено *.

PCI DSS. Данные банковских карт не хранятся и не логируются в системе. Используется tokenization через платежный шлюз.

PII защита. ФИО, адрес, телефон -- маскирование в логах: +7 (999) ***-**-67. Шифрование PII at rest в базе данных. Право на удаление (GDPR / 152-ФЗ): реализован механизм анонимизации данных клиента по запросу.


8. Аудит (раздел 16 -- НФТ)

Аудит -- основа для расследования инцидентов и compliance.

Формат записи аудита:

{timestamp, userId, role, action, resourceType, resourceId, ip, userAgent, result}

Хранение. Отдельная БД, immutable (append-only). Retention >= 1 год. Данные аудита не удаляются и не модифицируются.

Доступ. Только Security-команда и compliance-отдел. Разработчики и сопровождение не имеют прямого доступа к аудит-логам.


9. OWASP Top 10 -- чеклист (раздел 16 -- НФТ)

УгрозаМера
Injection (SQL, NoSQL)Parameterized queries, input validation на всех входных точках
Broken AuthenticationJWT RS256, token rotation, rate limit на логин
Sensitive Data ExposureTLS для всех соединений, encryption at rest, PII masking в логах
Broken Access ControlRBAC + IDOR checks на каждом эндпоинте, server-side authorization
Security MisconfigurationНет default credentials, security headers (CSP, HSTS, X-Frame-Options), отключен debug в prod
SSRFWhitelist внешних URL в ACL-адаптерах, запрет произвольных HTTP-запросов
Vulnerable ComponentsРегулярное обновление зависимостей, Dependabot/Snyk, мониторинг CVE
Insufficient LoggingStructured audit log, алерты на подозрительную активность (брутфорс, IDOR, rate limit)