Решения

Безопасность ML на GPU: ключи, токены и приватные данные

Цель. Дать минимальный, но достаточный набор практик для безопасной работы с облачными GPU: хранение секретов, доступы (SSH/Jupyter/HTTP‑порты), защита данных и чекпоинтов, хардненинг контейнеров, логирование без утечек, PII/guardrails для LLM.

Ключевые принципы: наименьшие привилегии, «нулевое доверие» (Zero Trust), явная сегрегация секретов и данных, быстрый аудит и ротация.

Модель угроз и базовый периметр

  • Кто и к чему может достучаться? Чётко разделите роли: разработчик, оператор, сервисный аккаунт. Давайте минимум прав и на минимальный срок (principle of least privilege).
  • Поверхности атаки: открытые порты (Jupyter/UI/API), SSH, уязвимые образы/зависимости, логи с токенами, object storage с данными.
  • Быстрый приоритет: (1) секреты, (2) сетевые правила, (3) контейнеры/образы, (4) логи и аудит.

Секреты: токены/ключи вне кода и образов

  • Не хранить секреты в git/образах — используйте секрет‑менеджер или, как минимум, монтируйте секреты как файлы (/run/secrets/…) и передавайте их в контейнер через -v /run/secrets/…:ro или переменные окружения, поставляемые внешне (а не через ENV в Dockerfile).
  • Ротация по расписанию и отзыв при утечке. Включите оповещения о неподтверждённых изменениях конфигурации.
  • Шифрование в покое/передаче и строгая изоляция от логов.
  • Практики суммированы в OWASP Secrets Management Cheat Sheet.

Доступ к окружению: Jupyter/SSH/порты

Jupyter

  • Запускайте с токеном по умолчанию или c паролем, но не одновременно; доступ ограничивайте (не выставляйте на «весь интернет»), предпочтительно — через SSH‑туннель.
  • Пример запуска: jupyter lab —ServerApp.ip=127.0.0.1 —ServerApp.port=8888 и локальный туннель ssh -L 8888:127.0.0.1:8888 user@host.

SSH

  • Ключи вместо паролей, отключить PasswordAuthentication, запретить root‑логин, ограничить разрешённые пользователи, включить fail2ban.
  • Для админ‑операций используйте sudo с записью в аудит‑журнал.

HTTP/API‑порты

  • Экспонируйте только нужные порты; закрывайте панельки админки и системные UI наружу.
  • Для публичных API — мидлвари авторизации и rate‑limit, ориентируясь на OWASP API Security Top‑10.

Данные: классификация, шифрование, чекпоинты

  • Классифицируйте: публичные / внутренние / ограниченные (PII/коммерческая тайна/лицензии).
  • Хранение: «горячие» данные и модели — на локальном NVMe; архивы/резерв — в объектном хранилище.
  • Шифрование: включите шифрование «в покое» в хранилище; для особо чувствительного — клиентское шифрование перед выгрузкой.
  • Чекпоинты: атомарная запись (*.tmp → *.pt) и мгновенная копия в долговременное хранилище, чтобы переживать прерывания. См. подробности: /solutions/storage-data/.

Контейнеры и цепочка поставок (supply chain)

  • Запуск не от root, по возможности read‑only FS + отдельные tmpfs. Снимайте лишние capabilities (—cap-drop=ALL), монтируйте тома как :ro, что можно — в noexec. Рекомендации OWASP по Docker‑безопасности: read‑only, tmpfs для /tmp и минимум привилегий.
  • Доверять демону Docker только доверенным пользователям — иначе контейнер может изменять host‑FS без ограничений.
  • Сканируйте образы и зависимые слои на CVE/секреты/мисконфиги:
    trivy image —scanners vuln,secret,misconfig your/image:tag
    Trivy умеет находить секреты и уязвимости и по файлам, и по конфигу образа. 
  • Для Kubernetes ориентируйтесь на CIS Benchmarks (Docker/K8s) как на базовую «шпаргалку» хардненинга. 

Логи, мониторинг, аудит

Обучение:

  • Не журналируйте секреты и PII — включите редакцию/маскирование, храните логи как чувствительные данные, разграничьте доступ. Рекомендации — OWASP Logging Cheat Sheet.
  • Аудит действий: входы (SSH/Jupyter), sudo, изменения конфигов, деплой образов.
  • Наблюдаемость: соберите метрики и алерты по GPU/VRAM/диску/ошибкам. См. /solutions/monitoring-logging/.

PII и guardrails для LLM/генераторов

  • Для текстов и логов используйте PII‑детекторы/анонимайзеры (например, Microsoft Presidio) до сохранения/выгрузки артефактов.
  • Для чатов/LLM‑API добавляйте guardrails (политики, фильтры, контроль тематики/инструментов), например NVIDIA NeMo Guardrails.
  • В прод‑сценариях: вынесите PII‑санитайзер в отдельный шаг пайплайна и логируйте только результат после маскирования. См. также: /solutions/llm-inference/guardrails/.

Быстрые рецепты (копируйте в чек‑листы)

Dockerfile (не root + минимум слоёв):

				
					FROM nvidia/cuda:12.3.1-runtime-ubuntu22.04
RUN useradd -m -u 1000 app && mkdir -p /app && chown -R app:app /app
USER app
WORKDIR /app
# Секреты не кладём в образ; зависимости — pin по версиям

				
			

Запуск контейнера в «жёстком» режиме:

				
					docker run --gpus all --read-only --cap-drop=ALL \
  --tmpfs /tmp --tmpfs /run \
  -v /data:/data:ro -v /run/secrets:/run/secrets:ro \
  -e HF_HOME=/data/.cache/hf -p 127.0.0.1:8000:8000 your/image:tag

				
			

Jupyter только через localhost + токен:

				
					jupyter lab --ServerApp.ip=127.0.0.1 --ServerApp.port=8888
# локально: ssh -L 8888:127.0.0.1:8888 user@host

				
			

(Токен‑аутентификация включена по умолчанию в Jupyter Server.)

Сканирование образа перед релизом:

				
					trivy image --scanners vuln,secret,misconfig --exit-code 1 your/image:tag

				
			

(Trivy находит CVE и секреты в файлах и конфиге образа.)

Мини‑чек‑лист перед запуском

  • Секреты не в git/образе; ротация настроена.
  • Jupyter не торчит наружу; доступ по токену/паролю, предпочтительно через SSH‑туннель.
  • Контейнеры не от root; —read-only, —cap-drop=ALL, только нужные порты.
  • Образ просканирован (CVE/секреты/мисконфиги).
  • Логи без токенов/PII; доступ к логам ограничен.
  • Для LLM включены PII‑фильтры/guardrails.

Частые ошибки

  • Секреты в .env внутри образа → при утечке образа компрометация токенов. Держите .env снаружи, в .dockerignore.
  • Jupyter на 0.0.0.0:8888 без прокси → анонимный доступ при угадывании URL. Используйте токен/пароль и туннель.
  • Слишком широкие порты → ненужные UI доступны наружу; ограничивайте -p 127.0.0.1:… и настройте ACL.
  • Логи «как есть» → токены/API‑ключи в журнале. Включайте редакцию/маскирование.