Большинство современных приложений живут в контейнерах и облаке. Там свои классы ошибок: слишком широкие права, публичные хранилища, контейнеры от root, открытые панели управления. Хорошая новость: почти всё это конфигурация, и её можно проверять автоматически.
Модель общей ответственности
Облачный провайдер отвечает за безопасность облака (железо, гипервизор, физические ЦОД), клиент за безопасность в облаке: настройки IAM, сети, хранилищ, ОС виртуальных машин, данные и код. Большинство облачных утечек это ошибки клиента: открытый бакет, ключ с правами администратора в репозитории.
IAM
- Минимальные привилегии: роль сервиса может только то, что ему нужно (
s3:GetObjectна один бакет, а неs3:*на всё). - Роли и временные учётные данные вместо долгоживущих ключей пользователей. Сервисы получают роль через метаданные машины, сервисный аккаунт Kubernetes или OIDC-федерацию.
- MFA для людей, отдельные аккаунты или проекты для прода и разработки.
- Регулярный аудит неиспользуемых прав и ключей.
- Главные учётные записи (root аккаунта) без ключей и под замком.
Хранилища и сеть
- Бакеты закрыты по умолчанию, публичный доступ запрещён политикой на уровне аккаунта. Файлы пользователям отдаются короткими подписанными ссылками.
- Шифрование на диске и при передаче (обычно включено по умолчанию, но проверьте ключи и доступ к KMS).
- Базы, Redis, Elasticsearch, панели управления не торчат в интернет. Группы безопасности открывают только нужные порты нужным источникам.
- Журналы действий в облаке (аудит API-вызовов) включены и хранятся отдельно.
Безопасность образов
- Минимальный базовый образ: distroless, alpine, slim. Меньше пакетов, меньше уязвимостей и инструментов для атакующего.
- Закреплять версию базового образа (тег, лучше digest), не
latest. - Не root:
USER 10001в Dockerfile. Процесс от root в контейнере при уязвимости ядра или неправильной настройке ближе к root на хосте. - Многоэтапная сборка: компиляторы и исходники остаются в builder-этапе.
- Секреты не в образе: ни в
ENV, ни в скопированных файлах, ни в слоях. Для сборкиRUN --mount=type=secret. - Сканирование образов (Trivy, Grype) в CI и в реестре, подпись (cosign) и проверка подписи при деплое.
Безопасность запуска контейнера
- Не
--privileged, не монтировать/var/run/docker.sock(это root на хосте). - Корневая файловая система только для чтения,
no-new-privileges, сброс лишних capabilities (--cap-drop ALL). - Ограничения ресурсов: память, CPU, число процессов.
- Не использовать сеть и PID-пространство хоста без необходимости.
Kubernetes
- RBAC: сервисные аккаунты с минимальными правами, не выдавать
cluster-admin, отключать автомонтирование токена сервисного аккаунта, если поду он не нужен. - Pod Security Standards (уровни privileged, baseline, restricted) через встроенный Pod Security Admission: запрещают привилегированные поды, hostPath, запуск от root.
- NetworkPolicy: по умолчанию поды видят друг друга. Политика «запретить всё» и явные разрешения ограничивают боковое перемещение.
- Secrets: шифрование etcd, ограничение доступа, внешнее хранилище.
- API-сервер и kubelet не открыты в интернет, аудит-лог включён.
- Политики допуска (Kyverno, OPA Gatekeeper): только подписанные образы из своего реестра, обязательные securityContext и лимиты.
IaC
Инфраструктура как код (Terraform, Helm, манифесты) проверяется так же, как код приложения: сканеры Checkov, tfsec или Trivy в CI находят публичные бакеты, открытые группы безопасности, отключённое шифрование до того, как они появятся в облаке.
Частые ошибки
s3:*и*:*«чтобы заработало».- Публичный бакет для «временного» обмена файлами.
- Контейнер от root с docker.sock.
- Kubernetes без NetworkPolicy и с токеном сервисного аккаунта в каждом поде.
- Долгоживущие ключи облака в CI.
Что спросят на собесе
- Модель общей ответственности: что на вас, что на провайдере.
- Как вы проверите и усилите Dockerfile.
- Какие настройки пода в Kubernetes вы считаете обязательными.
- Чем опасен смонтированный docker.sock.
- Как ограничить права сервиса в облаке.
- Что может сделать атакующий после компрометации одного пода и как этому помешать.