Результаты аудита безопасности Kubernetes нужно проверять по приоритету риска. Сначала анализируют доступ к Kubernetes API и RBAC, затем секреты и токены ServiceAccount, права подов и возможность выхода к узлу. Следующими зонами становятся NetworkPolicy, безопасность контейнерных образов и контроль действий в runtime.
Наивысший приоритет получают ClusterRoleBinding с cluster-admin или эквивалентными правами, wildcard-разрешения на ресурсы и verbs, чтение Secrets других namespace, открытый или анонимный Kubernetes API, privileged-контейнеры, hostPath с записью, hostNetwork, hostPID и доступ к сокету container runtime.
Контейнеры разделяют ядро хостовой ОС, поэтому слабая настройка одного workload способна затронуть соседние контейнеры и сам узел. AppArmor, SELinux, seccomp и другие механизмы MAC ограничивают последствия обхода верхних уровней защиты, но исходную опасную конфигурацию все равно нужно исправить. При оценке учитывайте эксплуатируемость, радиус воздействия, ценность данных, доступность точки атаки и компенсирующие меры.
Для быстрого старта используйте базовые проверки безопасности Kubernetes: они помогают собрать сведения о RBAC, ServiceAccount, namespace, NetworkPolicy, Secrets, etcd и control plane.
Краткий вывод: что проверять в первую очередь
Порядок первичной проверки результатов аудита
- Доступ к Kubernetes API и RBAC. Проверьте, кто может обращаться к API, создавать workloads, читать Secrets, выполнять команды через Pods/exec и изменять роли. Это предотвращает несанкционированное управление кластером.
- Секреты и сервисные токены. Найдите значения, попавшие в Git, CI/CD-логи, Helm values, переменные окружения, резервные копии etcd и отладочные интерфейсы. Это снижает риск использования украденных учетных данных для доступа к API и внешним системам.
- Права подов и граница между контейнером и узлом. Отдельно проверьте privileged, hostPath, hostNetwork, hostPID, hostIPC, SYS_ADMIN, allowPrivilegeEscalation, запуск от root и доступ к Docker или containerd socket. Эти параметры могут превратить компрометацию приложения в захват узла.
- Сетевое разделение. Проверьте NetworkPolicy для ingress и egress, поддержку политик используемым CNI и доступ между namespace. Сегментация затрудняет lateral movement, обращение к базам данных, control plane и внутренним административным сервисам.
- Образы и реестр. Оцените критичные CVE, происхождение базового образа, наличие встроенных секретов, запуск от root, использование latest, фиксацию по digest и проверку подписей. Это уменьшает риск запуска уязвимого или подмененного кода.
- Runtime-мониторинг и контроль изменений. Проверьте аудит API, события, логи CNI, блокировки AppArmor и SELinux, обнаружение новых привилегированных workloads и изменение RBAC. Такой контроль помогает увидеть эксплуатацию и повторное появление закрытых проблем.
Порядок можно менять только после оценки архитектуры. Например, публичный API с украденным токеном получает более высокий приоритет, чем устаревший пакет в изолированном внутреннем образе. Критичность определяет не число нарушений, а возможный сценарий компрометации.
Почему одна найденная настройка может затронуть весь кластер
В Kubernetes namespace разделяют объекты логически. Они не создают границу уровня виртуальной машины. Если ServiceAccount получает широкую ClusterRole, приложение в одном namespace может получить доступ к объектам соседних команд. Если workload запускается с hostPath на запись, последствия могут выйти за пределы его файловой системы.
Плотный кластер часто обслуживает сотни контейнеров и десятки команд. Одна ошибка в ClusterRoleBinding, общий токен или привилегированный DaemonSet расширяют радиус воздействия на узлы, секреты, внутренние сервисы и workloads других владельцев.
При анализе находки задайте четыре вопроса:
- Доступна ли точка атаки из интернета, корпоративной сети или только с узла?
- Какие права нужны атакующему: анонимный доступ, учетная запись приложения, доступ к pod или права администратора?
- Какие объекты затрагиваются: один pod, namespace, несколько команд, control plane или весь узел?
- Какие ограничения уже действуют: MFA, NetworkPolicy, Pod Security Admission, MAC-профили, sandbox-рантайм и аудит API?
Для учебного или staging-кластера удобно использовать облачную площадку с готовыми ресурсами Kubernetes, например Timeweb Cloud. Перед переносом рабочих нагрузок проверьте сетевой доступ к control plane, модель хранения секретов, журналирование и границы ответственности между платформой и командой.
Как расставить приоритеты по результатам аудита
Признаки критичного результата
Критичной считают находку, которая дает короткий путь к управлению кластером, чтению чувствительных данных или доступу к узлу. Быстрой реакции требуют следующие признаки:
- публичный Kubernetes API без надежной аутентификации, ограничения источников и сетевого контроля;
- анонимные запросы или учетные записи без дополнительной защиты;
- cluster-admin у пользователя, группы или ServiceAccount без подтвержденной необходимости;
- права на чтение Secrets во всех namespace;
- возможность создавать Pod, DaemonSet, RoleBinding или Admission-конфигурации;
- privileged-контейнер, hostPath с записью в системные каталоги или доступ к сокету runtime;
- путь от уязвимого приложения к токену ServiceAccount, Kubernetes API и секретам;
- образ из неподтвержденного публичного реестра без digest, подписи и контроля допуска;
- отсутствие сетевой изоляции в production namespace, где хранятся базы данных или административные сервисы;
- отключенные или permissive-профили AppArmor и SELinux на узлах с чувствительными workload.
Отсутствие NetworkPolicy в изолированном тестовом namespace может получить плановый приоритет, если там нет ценных данных и доступ ограничен. Возможность запуска privileged-пода в production требует немедленного ограничения, поскольку она создает путь к хостовой ОС и соседним контейнерам.
Для практической оценки используйте внутреннюю шкалу по пяти параметрам. Оцените каждый параметр баллами от 0 до 2, затем отдельно зафиксируйте компенсирующие меры:
| Параметр | Вопрос | Высокий риск |
|---|---|---|
| Доступность | Кто может добраться до точки атаки? | Интернет, общая сеть или любой pod |
| Требуемые права | Какие условия нужны для эксплуатации? | Анонимный запрос или права обычного приложения |
| Радиус воздействия | Сколько объектов можно затронуть? | Несколько namespace, узел или control plane |
| Ценность | Какие данные и сервисы находятся под угрозой? | Ключи доступа, персональные данные, production-базы |
| Ограничения | Что остановит развитие атаки? | Нет NetworkPolicy, MAC-профиля, аудита или admission-контроля |
Эта шкала помогает отделить критичную уязвимость от формального отклонения политики. Она не заменяет анализ CVSS или внутренние требования, но дает единый язык для команды эксплуатации и владельцев сервисов.
Какие данные фиксировать в отчете
Формулировка «конфигурация небезопасна» не помогает исправить проблему. Каждая запись должна позволять воспроизвести проверку и подтвердить закрытие риска.
| Поле | Что указать |
|---|---|
| Ресурс | Тип, имя, namespace, узел и ссылка на конфигурационный файл внутри системы учета |
| Субъект или workload | Пользователь, группа, ServiceAccount, Deployment, Job или DaemonSet |
| Фактическое разрешение | Ресурс, verb, namespace и способ проверки через kubectl auth can-i или анализ политики |
| Вектор атаки | Публичный API, уязвимое приложение, украденный токен, образ или соседний pod |
| Радиус воздействия | Конкретные Secrets, сервисы, namespace, узлы и внешние системы |
| Доказательство | Фрагмент манифеста, результат команды, событие, лог или снимок настройки |
| Риск для эксплуатации | Утечка данных, изменение workload, простой, потеря доверия к узлу или нарушение требований |
| Исправление | Что удалить, ограничить, заменить или добавить |
| Повторная проверка | Команда, ожидаемый результат и ответственный за контроль |
Для повторяемости храните отчет вместе с датой проверки, версией Kubernetes, версией CNI, используемым runtime и перечнем исключений. Без этих данных сравнение двух аудитов часто дает ложную картину улучшения или ухудшения.
Шаблон отчета и порядок проверки нескольких уровней инфраструктуры удобно дополнить материалом о комплексном аудите IT-инфраструктуры.
Доступы, RBAC и настройки Kubernetes API
Избыточные роли и опасные привязки
RBAC нужно проверять через фактические разрешения, а не по названию роли. Субъект с ролью developer может получить опасный доступ через несколько RoleBinding, а безопасное название ClusterRole может скрывать wildcard-разрешения.
В первую очередь найдите привязки cluster-admin, роли с ресурсами и verbs, доступ к Secrets, Pods/exec, созданию workload и изменению прав:
kubectl get clusterrolebindings -o custom-columns=NAME:.metadata.name,ROLE:.roleRef.name,SUBJECTS:.subjects[*].name
kubectl get rolebindings -A -o custom-columns=NAMESPACE:.metadata.namespace,NAME:.metadata.name,ROLE:.roleRef.name,SUBJECTS:.subjects[*].name
kubectl get clusterrole,role -A -o yaml | grep -E 'resources:|verbs:|secrets|pods/exec|rolebindings|daemonsets'
Последняя команда дает грубый поиск и не заменяет разбор YAML. Для каждого пользователя, группы и ServiceAccount проверьте реальное действие:
kubectl auth can-i --list --as=alice
kubectl auth can-i get secrets --all-namespaces --as=system:serviceaccount:prod:api
kubectl auth can-i create pods -n prod --as=system:serviceaccount:prod:api
kubectl auth can-i create rolebindings -n prod --as=alice
Проверку impersonation запускайте с разрешенной учетной записью аудитора. Если субъект может создавать Pod в namespace, этого иногда достаточно для чтения подключаемых секретов, использования доверенного ServiceAccount или запуска опасной конфигурации. Права на RoleBinding, DaemonSet и admission-объекты требуют отдельного внимания, поскольку они меняют границы доступа сразу для нескольких workload.
Сопоставьте каждое разрешение с рабочей операцией. Учетной записи, которая читает конфигурацию приложения, не нужен доступ к Secrets всех namespace. Контроллеру, который обновляет Deployment в одном namespace, не нужна ClusterRole с ресурсами из всей системы.
Сервисные аккаунты и токены
ServiceAccount часто становится промежуточным звеном между уязвимым приложением и Kubernetes API. После компрометации pod атакующий проверяет смонтированный токен, endpoint API и разрешения учетной записи.
Соберите список ServiceAccount и связанных привязок:
kubectl get serviceaccounts -A
kubectl get pods -A -o custom-columns=NAMESPACE:.metadata.namespace,POD:.metadata.name,SERVICEACCOUNT:.spec.serviceAccountName
kubectl get rolebindings,clusterrolebindings -A -o yaml | grep -E 'serviceAccount:|roleRef:|name:'
Для каждого workload ответьте на три вопроса:
- Нужен ли приложению доступ к Kubernetes API?
- Можно ли отключить automountServiceAccountToken на уровне ServiceAccount или Pod?
- Не использует ли несколько несвязанных приложений одну учетную запись?
Разделяйте ServiceAccount по workload и namespace. Удаляйте неиспользуемые привязки, сокращайте срок жизни внешних ключей и проверяйте старые Secret-объекты с токенами. Короткоживущий projected-токен уменьшает окно злоупотребления, но не компенсирует избыточный RBAC.
Экспозиция и защита Kubernetes API
Проверьте, кто может подключиться к API server, какие методы аутентификации включены и попадают ли запросы в аудит-логи. Внешняя доступность control plane усиливает последствия каждой ошибки RBAC и каждой утечки токена.
- Ограничьте сетевой доступ к API разрешенными адресами, приватной сетью или защищенным шлюзом.
- Отключите анонимные запросы, если они не нужны архитектуре, и проверьте результат отдельно для health endpoint.
- Проверьте TLS для API, корректность сертификатов и срок их действия.
- Сопоставьте группы внешнего провайдера идентификации с ClusterRoleBinding.
- Настройте аудит запросов к Secrets, Exec, изменению RBAC и созданию workload.
- Проверьте, кто имеет доступ к kubeconfig и как отзываются старые учетные данные.
kubectl cluster-info
kubectl get --raw='/readyz?verbose'
kubectl get endpoints kubernetes -n default -o wide
В управляемом Kubernetes часть параметров control plane скрыта от команды. В этом случае запросите у провайдера сведения о публичных endpoint, фильтрации источников, журналировании и процедуре отзыва доступа. Локальный результат kubectl не подтверждает, что внешний API закрыт на сетевом уровне.
Секреты: где аудит выявляет риск компрометации
Каналы утечки секретов
Объект Secret в Kubernetes не описывает весь жизненный цикл пароля или ключа. Значение может появиться в нескольких системах, а после ротации остаться в старой копии, логе или артефакте сборки.
- Git. Ищите пароли, токены, приватные ключи и строки подключения в истории, ветках, pull request и артефактах. Удаление строки из последнего коммита не очищает историю.
- CI/CD. Проверьте логи jobs, переменные окружения, кэш, артефакты и вывод команд с включенным debug-режимом.
- Манифесты и Helm values. Ищите секреты в открытом виде, шаблонах, values-файлах и локальных пакетах релиза.
- Логи приложения. Проверьте ошибки авторизации, debug-вывод, трассировку и сообщения с полными HTTP-заголовками.
- Переменные окружения и командная строка. Они могут попасть в дампы процессов, диагностические endpoints и журналы запуска.
- События и отладочные интерфейсы. Убедитесь, что приложения не печатают конфигурацию при старте и не публикуют административные данные без защиты.
- Резервные копии. Проверьте backup etcd, snapshots дисков, дампы namespace и хранилища CI/CD.
git grep -nEi 'password|passwd|secret|token|private_key|api_key' -- '*.yaml' '*.yml' '*.json' '*.env'
kubectl get events -A --sort-by=.lastTimestamp
kubectl get secrets -A -o custom-columns=NAMESPACE:.metadata.namespace,NAME:.metadata.name,TYPE:.type
Поиск строк не доказывает отсутствие утечки. Секреты в бинарных файлах, архивах и истории Git проверяйте отдельными средствами сканирования. При обнаружении реального ключа считайте его раскрытым, пока владелец системы не подтвердит отзыв.
Хранение и доступ к Secrets
Base64 кодирует значение и не защищает его от чтения. Пользователь или ServiceAccount с правом get secrets получает исходные данные независимо от того, как они представлены в YAML.
Проверьте четыре уровня:
- Хранение в etcd. Убедитесь, что Secrets шифруются при записи, ключи шифрования защищены, а конфигурация применяется ко всем control plane.
- Доступ через RBAC. Составьте список субъектов с правами get, list и watch на Secrets. Право list может раскрыть имена и структуру секретов, право get дает значения.
- Резервные копии. Защитите backup etcd и проверьте, кто может его скачать или восстановить в отдельном окружении.
- Использование workload. Сопоставьте каждый секрет с конкретным приложением. Уберите доступ, который появился временно и сохранился после изменения архитектуры.
Внешний менеджер секретов снижает количество чувствительных значений в манифестах и репозиториях. Он не отменяет проверку RBAC, журналов, прав на узлах и резервных копий. Утечка учетных данных внешнего менеджера может дать больший радиус воздействия, чем один Kubernetes Secret.
Ротация после аудита
Ротация нужна сразу после подтвержденной утечки. Изменение объекта Secret не отзывает ключ во внешней базе, облачном API или системе CI/CD.
- Составьте перечень раскрытых значений и систем, где они действуют.
- Отзовите старые ключи, токены, пароли и сертификаты у владельцев соответствующих систем.
- Выпустите новые значения с минимальным набором прав.
- Обновите Secret и перезапустите workload способом, который гарантирует загрузку новых данных.
- Проверьте Git-историю, логи, кэш, backup и дампы процессов.
- Добавьте проверку секретов в CI/CD и запрет публикации открытых значений.
- Зафиксируйте дату ротации и проведите повторную проверку старых учетных данных.
Права подов и изоляция контейнеров от узлов
Настройки, которые резко повышают радиус воздействия
Безопасность pod нужно оценивать по совокупности полей. Один параметр может быть допустим для системного агента, но опасен для веб-приложения, доступного из внешней сети.
| Настройка | Риск | Безопасная альтернатива |
|---|---|---|
| privileged: true | Контейнер получает расширенные права и приближается к возможностям узла | Обычный режим и точечные capabilities |
| hostPath с записью | Изменение файлов узла, конфигурации, журналов и сокетов | PersistentVolume с ограниченным путем и read-only доступом |
| hostNetwork: true | Обход обычной сетевой изоляции pod и доступ к сетевым службам узла | Сеть pod с явными NetworkPolicy |
| hostPID или hostIPC | Видимость процессов и IPC-объектов узла или соседних workload | Изолированные namespace процессов и IPC |
| SYS_ADMIN и другие опасные capabilities | Расширение операций ядра и файловой системы | Удаление capabilities и добавление только подтвержденных |
| Сокет Docker или containerd | Запуск контейнеров с правами, близкими к правам узла | Специализированный безопасный builder без доступа к runtime |
| allowPrivilegeEscalation: true | Процесс может получить больше прав через setuid или аналогичный механизм | allowPrivilegeEscalation: false |
| Запуск от root | Компрометация процесса получает расширенные права внутри контейнера | runAsNonRoot, фиксированный UID и readOnlyRootFilesystem |
Проверьте pod и шаблоны контроллеров, потому что исправление одного запущенного pod исчезнет после следующего rollout:
kubectl get pods -A -o yaml | grep -E 'privileged|hostPath|hostNetwork|hostPID|hostIPC|allowPrivilegeEscalation|runAsUser|runAsNonRoot|SYS_ADMIN|seccomp'
kubectl get daemonsets,deployments,statefulsets -A -o yaml | grep -E 'privileged|hostPath|hostNetwork|hostPID|hostIPC'
Проверяйте запись в hostPath отдельно. Read-only mount снижает риск изменения узла, но не превращает чувствительный путь в безопасный, если контейнер может читать ключи или конфигурацию.
AppArmor и SELinux как последняя линия защиты
AppArmor и SELinux ограничивают действия процесса на уровне Linux kernel. Эти MAC-механизмы могут запретить доступ к файлам, системным вызовам, устройствам и операциям, которые контейнеру не нужны по назначению.
В результатах аудита ищите следующие признаки:
- профиль AppArmor не назначен workload, переведен в complain-режим или не загружен на узле;
- SELinux отключен либо работает не в enforcing-режиме;
- профиль применяется к одному Deployment, но отсутствует у Job, CronJob или DaemonSet с похожими правами;
- блокировки MAC не попадают в централизованные логи;
- исключения выданы namespace целиком, хотя нужны одному системному компоненту.
aa-status
getenforce
ausearch -m avc -ts recent
dmesg | grep -Ei 'apparmor|selinux|denied'
Набор команд зависит от дистрибутива и доступа к узлам. В управляемом кластере запросите аналогичные сведения у провайдера или проверьте доступные события runtime.
MAC-профили снижают последствия обхода RBAC, NetworkPolicy или ошибки приложения. Они не исправляют privileged, hostPath или доступ к runtime socket. Если контейнеру выданы избыточные права, сначала уберите права, затем подтвердите, что AppArmor или SELinux блокируют неожиданные операции.
Pod Security Admission и политики запуска
Pod Security Admission позволяет отклонять опасные параметры на этапе создания pod. Для namespace задайте подходящий уровень: restricted для обычных приложений, baseline для workloads с ограниченными исключениями. Системные компоненты выносите в отдельные namespace и документируйте их исключения.
Проверьте labels namespace:
kubectl get namespace --show-labels
kubectl get namespace -L pod-security.kubernetes.io/enforce
kubectl get namespace -L pod-security.kubernetes.io/warn
kubectl get namespace -L pod-security.kubernetes.io/audit
Политика должна блокировать privileged, host namespaces, опасные capabilities, запуск от root, hostPath и отсутствие seccomp там, где это допускает workload. Для системных агентов задайте минимальное исключение с владельцем, причиной и сроком пересмотра.
Перед изменением режима enforce проверьте workload в warn или audit режиме. Иначе обновление политики может остановить легитимные Deployment и создать простой. Результат проверки фиксируйте по namespace, владельцу и конкретному запрещенному полю.
Сетевые политики и защита от перемещения внутри кластера
Default deny и минимально необходимые разрешения
Базовая модель для чувствительного namespace, запрет входящего и исходящего трафика с явными исключениями. Политика должна реально применяться CNI, иначе YAML-файл создает ложное чувство защиты.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny
namespace: prod
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
После default deny разрешите только нужные направления:
- DNS к системному сервису разрешения имен;
- трафик от ingress-контроллера к конкретным приложениям;
- соединения приложения с нужной базой данных или очередью;
- доступ к API только для контроллеров, которым он нужен;
- выход к заранее определенным внешним endpoint;
- служебный трафик мониторинга и резервного копирования.
Правила для ingress и egress проверяйте отдельно. Запрет входящих соединений не мешает pod отправлять данные наружу, а запрет исходящих соединений не ограничивает все способы входа.
Проверка межпространственного и внешнего доступа
Скомпрометированный pod часто используется как точка разведки. Проверьте соединения к соседним namespace, Kubernetes API, etcd, облачному metadata endpoint, внутренним базам, очередям и административным интерфейсам.
Соберите матрицу доступа:
| Источник | Назначение | Порт или протокол | Причина |
|---|---|---|---|
| ingress-контроллер | frontend в prod | TCP 8080 | Публикация приложения |
| frontend | backend в prod | TCP 8443 | Вызов API |
| backend | database в data | TCP 5432 | Работа приложения |
| все нужные pod | DNS | UDP и TCP 53 | Разрешение имен |
Сверьте матрицу с селекторами pod и namespace. Ошибка в matchLabels может применить правило к пустому набору или открыть доступ большему числу workload.
Как подтвердить результат на практике
Наличие NetworkPolicy в выводе kubectl не доказывает ее работу. Подтвердите поведение тестовыми запросами из разрешенного и запрещенного pod. Используйте диагностический образ, согласованный с политикой безопасности, и не устанавливайте инструменты в production-контейнер без разрешения владельца.
kubectl get networkpolicy -A
kubectl describe networkpolicy -n prod
kubectl get pods -A -o wide
kubectl get nodes -o wide
Для каждого направления зафиксируйте ожидаемый результат и фактический:
- разрешенный запрос к приложению должен проходить;
- запрос из постороннего namespace должен блокироваться;
- DNS должен работать только через разрешенный сервис;
- доступ к API и metadata endpoint должен соответствовать архитектуре;
- запрос к базе с неподходящего pod должен завершаться отказом.
Проверьте логи CNI и особенности hostNetwork. Часть сетевых путей, трафик узла и системные компоненты может обходить обычную модель NetworkPolicy. Это нужно отразить в отчете как ограничение контроля.
Контейнерные образы, реестр и цепочка поставки
Уязвимости и небезопасные настройки образа
Результат сканирования образа оценивайте вместе с контекстом запуска. Критичная CVE в библиотеке приложения, доступного из интернета, получает более высокий приоритет, чем такая же CVE в неиспользуемом бинарном файле закрытого batch-job.
Проверьте:
- критичные и высокие CVE в базовом образе и пакетах приложения;
- возраст базового образа и регулярность обновлений;
- запуск процесса от root и наличие фиксированного UID;
- встроенные пароли, токены, сертификаты и приватные ключи;
- лишние shell, отладочные утилиты, компиляторы и сетевые клиенты;
- устаревшие зависимости и пакеты, которые не нужны runtime;
- лишние Linux capabilities и запись в корневую файловую систему.
trivy image --severity CRITICAL,HIGH registry.example/app:release
kubectl get pods -A -o custom-columns=NAMESPACE:.metadata.namespace,POD:.metadata.name,IMAGE:.spec.containers[*].image
Статус fixed или unfixed фиксируйте отдельно. Для неисправимой CVE укажите компенсирующие меры: NetworkPolicy, отсутствие внешнего доступа, read-only filesystem, seccomp, MAC-профиль и минимальные права ServiceAccount.
Доверие к источнику и неизменяемость версии
Плавающий тег усложняет расследование. Сегодня workload может работать с одним содержимым, а после повторной загрузки получить другой образ с тем же тегом.
Для production закрепляйте образ по digest:
image: registry.example/team/app@sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
В аудите реестра проверьте:
- аутентификацию пользователей, роботов и CI/CD;
- разделение прав на push, pull, удаление и перезапись тегов;
- запрет публикации образов в production-репозитории без проверки;
- защиту тегов от перезаписи и срок хранения старых версий;
- подпись образов и наличие provenance для сборки;
- журналирование скачивания, публикации и удаления артефактов;
- ограничение списка разрешенных registry.
Образ из публичного registry не должен считаться доверенным по факту размещения. Источник, подпись, digest и результат проверки должны подтверждаться до запуска.
Сканирование и admission-контроль до запуска
Сканирование в CI/CD переносит обнаружение CVE ближе к сборке. Установите порог блокировки для критичных проблем, встроенных секретов, запрещенных пользователей и неподтвержденных источников.
Admission-контроллер может отклонять манифест, если:
- образ использует latest или другой плавающий тег;
- образ не закреплен по digest;
- подпись или provenance отсутствуют;
- registry не входит в разрешенный список;
- pod запускается privileged, с hostPath или опасными capabilities;
- ServiceAccount получает права, не соответствующие namespace;
- манифест содержит открытый секрет.
Практические команды для Trivy, Docker Bench, kube-bench и проверок NetworkPolicy собраны в руководстве по аудиту контейнеров и Kubernetes-кластера.
Сканирование не заменяет runtime-контроль. Образ без известных CVE может содержать уязвимость бизнес-логики, а безопасный образ может получить опасные права после развертывания.
Как найденные проблемы превращаются в сценарий атаки
Компрометация приложения и кража токена
Типовая цепочка начинается с уязвимости веб-приложения. Атакующий выполняет команды внутри контейнера, находит автоматически смонтированный токен ServiceAccount и обращается к Kubernetes API.
- Приложение получает удаленный запрос через ingress.
- Ошибка в приложении дает выполнение команд в pod.
- Процесс читает токен и переменные окружения.
- Атакующий проверяет права через API и находит доступ к Secrets или workload.
- Полученные данные позволяют обратиться к базе, внешнему API или другому namespace.
- Право создавать Pod или изменять RoleBinding расширяет контроль над кластером.
Цепочку сокращают отключение automountServiceAccountToken для приложений без API-доступа, минимальный RBAC, NetworkPolicy с ограничением egress и аудит запросов к Secrets. Отсутствие одного слоя не должно автоматически открывать весь кластер.
От привилегированного пода к узлу
Вторая цепочка начинается с вредоносного или уязвимого образа. Если pod получает privileged, hostPath, hostPID или доступ к runtime socket, процесс получает возможности, которых нет у обычного контейнера.
- В контейнер попадает вредоносный код или эксплуатируется уязвимость.
- Процесс использует расширенные capabilities или доступный hostPath.
- Атакующий читает ключи, конфигурацию и токены на узле.
- Через runtime socket запускается дополнительный контейнер с широкими правами.
- Компрометированный узел становится источником атаки на соседние workloads.
AppArmor, SELinux, seccomp и sandbox-рантаймы могут заблокировать отдельные операции. Они не делают привилегированный pod безопасным. Первое исправление, удаление избыточных прав и замена hostPath на ограниченное хранилище.
Операционные последствия для команды
Техническая находка получает высокий приоритет, если она может привести к конкретному ущербу:
- утечке паролей, API-ключей, сертификатов и данных клиентов;
- изменению или удалению Deployment, StatefulSet, Job и сетевых политик;
- простою production-сервисов после захвата узла или control plane;
- компрометации workloads соседней команды через общий namespace, сеть или роль;
- подмене контейнерного образа и скрытому добавлению вредоносного кода;
- потере доверия к резервным копиям и необходимости полной проверки узлов;
- нарушению требований аудита, сегментации и управления доступом.
После захвата узла нельзя ограничиваться удалением одного pod. Проверьте образы, Secrets, токены, kubeconfig, журналы, соседние workloads и сохранность control plane. Сценарий восстановления должен учитывать возможность закрепления злоумышленника.
Практический план исправления и повторной проверки
Что исправлять немедленно
- Ограничьте доступ к API. Закройте публичный и анонимный доступ, пересмотрите правила firewall и отзовите скомпрометированные kubeconfig.
- Уберите лишние права. Удалите неиспользуемые cluster-admin-привязки, wildcard-разрешения и доступ к Secrets без подтвержденной причины.
- Изолируйте подозрительные workloads. Ограничьте их сеть, остановите опасные Job и сохраните артефакты для расследования.
- Отзовите раскрытые секреты. Выпустите новые ключи, обновите workloads и проверьте старые копии.
- Запретите опасные pod-настройки. Уберите privileged, hostPath с записью, host namespaces, SYS_ADMIN и runtime socket.
- Заблокируйте неподтвержденные образы. Остановите deployment образов из неизвестных registry, latest и версий без digest.
- Усилите сетевые ограничения. Добавьте default deny там, где это безопасно для доступности, затем разрешите проверенные соединения.
- Сохраните доказательства. Зафиксируйте манифесты, события, API-аудит и логи до изменения конфигурации.
Сетевые политики и Pod Security Admission меняйте поэтапно. Перед каждым изменением проверьте зависимости приложения, чтобы закрытие риска не привело к незапланированному простою.
Что автоматизировать в CI/CD и кластере
- проверку Kubernetes-манифестов и Terraform или других IaC-файлов;
- поиск privileged, hostPath, hostNetwork, hostPID, root и опасных capabilities;
- сканирование образов на CVE и секреты;
- фиксацию образов по digest и проверку подписи;
- admission-политики для registry, тегов, RBAC и Pod Security;
- контроль ClusterRoleBinding и доступа ServiceAccount;
- проверку NetworkPolicy для ingress и egress;
- runtime-мониторинг процессов, файловых операций, сетевых соединений и обращений к сокетам;
- централизованный сбор аудита Kubernetes API, событий и блокировок AppArmor или SELinux;
- регулярный повторный аудит после обновления Kubernetes, CNI, runtime и базовых образов.
Пять последовательных этапов с командами для RBAC, pod, сетевых политик, секретов и kubelet описаны в практическом плане аудита Kubernetes.
Критерии успешной повторной проверки
Закрытая находка должна иметь проверяемое условие. Статус «исправлено» ставьте после повторного теста, а не после изменения YAML.
| Зона | Условие закрытия | Что проверить повторно |
|---|---|---|
| RBAC | Нет лишних ClusterRoleBinding и wildcard-прав | kubectl auth can-i для пользователей и ServiceAccount |
| Secrets | Доступ получают только нужные субъекты, раскрытые значения отозваны | RBAC, Git, логи, backup и действительность старых ключей |
| API | Нет анонимного или неограниченного публичного доступа | Сетевой путь, TLS, аутентификация и аудит запросов |
| Pod | Запрещены privileged, опасные host-настройки и лишние capabilities | Шаблоны Deployment, Job, CronJob и DaemonSet |
| MAC | Профили AppArmor или SELinux применяются в enforcing-режиме | Настройки узлов, события блокировок и журналы |
| Сеть | Разрешенные соединения совпадают с матрицей | Тесты ingress, egress, DNS, API и межnamespace-доступа |
| Образы | Разрешены проверенные registry, digest и подписи | Манифесты, CI/CD, admission и журнал реестра |
| Мониторинг | Опасные действия попадают в журналы и создают оповещение | Аудит API, runtime, CNI и изменения политик |
Финальный отчет должен показывать изменение риска: что было доступно, какое ограничение добавили, какой тест подтвердил результат и кто отвечает за регулярный контроль. Такой формат превращает аудит безопасности Kubernetes в рабочий процесс, а не в разовый список замечаний.