Решения
Безопасность 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‑ключи в журнале. Включайте редакцию/маскирование.