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