Цель аудита безопасности Kubernetes-кластера отвечает на один вопрос: что должно измениться в состоянии кластера после проверки. Формулировка «проверить безопасность кластера» такого ответа не даёт, поэтому аудит заканчивается отчётом на двести строк, а не планом работ с приоритетами.
Цели строят от четырёх групп рисков: небезопасные манифесты, избыточные RBAC-права, открытый API-сервер и отсутствие сетевых политик. Под каждый риск пишут отдельную цель с метрикой, инструментом проверки, критерием приёмки и сроком. Порог задают числом: ноль подов с privileged: true, ноль успешных анонимных запросов в audit log, сто процентов продакшн-namespace с default-deny NetworkPolicy.
Типовая ситуация выглядит так: команда запускает сканер, получает больше двухсот находок, из которых большинство помечены низким приоритетом, и тратит неделю на спор о том, что закрывать первым. Заранее описанные цели снимают этот спор. Измеримая цель фиксирует, что именно проверяем, каким инструментом, какой порог считаем успехом и в каком временном окне.
Зачем формулировать цели аудита до начала проверки
Аудит «по чек-листу вообще» даёт инвентаризацию находок без приоритетов. Аудит под риски даёт последовательность действий: понятно, что чинить на этой неделе, а что переходит в квартальный план. Разница видна по результату: в первом случае появляется документ, во втором — изменение конфигураций кластера и набор метрик, по которым повторная проверка покажет динамику.
Цели аудита служат входом в план устранения, а не финальным документом. Их формулируют до того, как аудитор получил доступ к кластеру, иначе найденные проблемы начинают определять повестку, и самые громкие находки вытесняют самые опасные.
Чем цель аудита отличается от задачи и от проверки
Три уровня отличаются вопросом, на который отвечают. Цель отвечает, что должно измениться в состоянии кластера. Задача отвечает, какую конфигурацию для этого меняем. Проверка отвечает, чем подтверждаем результат.
- Цель: исключить запуск privileged-контейнеров в продакшн-namespace. Задача: перевести namespace на профиль restricted в Pod Security Admission или описать ограничения в политиках OPA Gatekeeper. Проверка: Trivy config scan манифестов и сверка с baseline.
- Цель: сократить поверхность атаки на API-сервер. Задача: отключить анонимную аутентификацию и включить режим авторизации Node,RBAC. Проверка: kube-bench по разделу, отвечающему за настройки apiserver.
- Цель: не допустить lateral movement между namespace. Задача: включить default-deny NetworkPolicy в продакшн-namespace и описать разрешённые потоки. Проверка: kubectl get networkpolicy -A вместе с анализом фактического трафика.
Формулировка «запустить kube-hunter» целью не является. Это проверка. Если в отчёте об аудите цели подменены списком запущенных команд, читатель не поймёт, какие риски закрыты, а какие остались.
Как связать цели аудита с бизнес-рисками
Обоснование аудита перед руководством строится на цепочке: риск — сценарий эксплуатации — влияние — цель аудита — метрика. Технический риск без влияния звучит как абстракция, поэтому цепочку доводят до последствий, которые понятны вне команды эксплуатации: недоступность сервиса, утечка данных клиентов, нарушение требований к защите персональных данных, репутационные потери.
Пример для RBAC. Риск: избыточные права service account в продакшене. Сценарий эксплуатации: злоумышленник компрометирует под, у которого есть права на чтение secrets в нескольких namespace, и перемещается по кластеру. Влияние: доступ к учётным данным баз данных и внешних сервисов. Цель аудита: свести к нулю количество ClusterRoleBinding с правами wildcard для сервисных аккаунтов приложений. Метрика: ноль таких привязок в продакшн-namespace, подтверждённое ручным разбором.
Такую же связку применяют к манифестам. Риск: контейнер с hostPath монтирует каталог ноды. Сценарий: компрометация приложения даёт запись в файловую систему ноды. Влияние: выход за границы кластера и потенциальная компрометация узла целиком. Цель: ноль подов с hostPath вне системных namespace.
Отдельно стоит посмотреть, как цели аудита формулируют для других инфраструктурных контуров: практический разбор постановки измеримых целей аудита для DevOps-инженеров и системных администраторов полезен, когда в компании уже есть методика для серверного парка и её нужно согласовать с подходом для Kubernetes.
Ключевые риски безопасности Kubernetes-кластера
Четыре группы рисков из темы покрывают основную часть реальных инцидентов в кластерах. Ниже — конкретные конфигурации и то, во что каждая превращается при эксплуатации.
Небезопасные манифесты: что именно искать
Проверяемые поля в securityContext и связанных секциях спецификации пода:
- securityContext.privileged: true — контейнер получает доступ к устройствам и возможностям ядра хоста.
- securityContext.runAsUser: 0 и отсутствие runAsNonRoot — процесс в контейнере работает от root.
- allowPrivilegeEscalation: true — процесс может получить больше прав, чем у родительского.
- hostPath, hostNetwork, hostPID, hostIPC — доступ к файловой системе ноды, её сети и пространству процессов.
- capabilities.add с SYS_ADMIN, NET_ADMIN или SYS_PTRACE.
- Отсутствие readOnlyRootFilesystem: true, отсутствие профилей seccomp и AppArmor.
- Образ с тегом latest и imagePullPolicy: Always — невоспроизводимая сборка и непредсказуемые обновления.
- Отсутствие requests и limits по CPU и памяти — риск отказа соседних подов на ноде.
apiVersion: v1
kind: Pod
metadata:
name: legacy-agent
spec:
hostNetwork: true
containers:
- name: agent
image: registry.example.com/agent:latest
securityContext:
privileged: true
volumeMounts:
- name: host-root
mountPath: /host
volumes:
- name: host-root
hostPath:
path: /
type: Directory
Такой под при компрометации приложения даёт атакующему запись в корень файловой системы ноды, доступ к сети хоста и возможность влиять на другие поды через пространство процессов. Цель аудита здесь формулируется как отсутствие подобных конфигураций в продакшене, а инструментом проверки выступает сканирование манифестов в режиме config scan.
Избыточные RBAC-права: типовые ошибки
Самая частая ошибка — ClusterRoleBinding на cluster-admin, выданный сервисному аккаунту CI/CD. Конвейеру сборки он нужен редко: в большинстве случаев достаточно прав на создание объектов в конкретных namespace. Вторая ошибка — роли с verbs: ["*"] и resources: ["*"] в продакшн-контуре, где приложению нужен доступ к двум-трём типам объектов.
Дальше идут менее заметные проблемы: права на secrets в чужих namespace, права на создание pod/create и pod/exec, которые превращают любой скомпрометированный под в точку входа в соседние сервисы, а также отсутствие ревизии неиспользуемых ролей. Роль, которой не пользовались полгода, но которая осталась привязанной, сохраняет риск в полном объёме.
kubectl auth can-i --list --as=system:serviceaccount:prod:deployer -n prod kubectl get clusterrolebinding -o wide | grep -i admin kubectl get rolebinding,clusterrolebinding -A -o json | grep -i system:serviceaccount
Команда kubectl auth can-i показывает фактические права сервисного аккаунта с учётом всех ролей и привязок, что быстрее ручного чтения манифестов. Инструмент kube-bench проверяет часть настроек, связанных с RBAC и сервисными аккаунтами, по CIS Kubernetes Benchmark, однако оценка избыточности в контексте конкретного кластера остаётся ручной работой: формально корректная роль может быть избыточной для этого приложения.
Открытый API-сервер: векторы атаки
Опасные настройки, которые встречаются в разборах инцидентов и в отчётах сканеров:
- --anonymous-auth=true на kube-apiserver — неаутентифицированные запросы проходят дальше по цепочке авторизации.
- --insecure-port — устаревший параметр, объявленный deprecated с версии 1.10 и удалённый в актуальных версиях Kubernetes, но сохранившийся в старых конфигурациях.
- Отсутствие --authorization-mode=Node,RBAC — без Node в списке режимов kubelet получает слишком широкие полномочия.
- Публичный LoadBalancer на порту 6443 без allowlist адресов.
- Отсутствие audit policy, из-за чего нельзя подтвердить, были ли анонимные запросы.
- Отключённый admission-контроллер NodeRestriction, который ограничивает права kubelet.
Внешний периметр проверяется сканером в активном режиме, который находит доступные endpoint, открытые панели и незащищённые хранилища ключей. Цель по этому риску удобно формулировать через журнал: ноль успешных анонимных запросов к API-серверу за период аудита. Метрика проверяема, а её изменение видно в динамике.
Отсутствие сетевых политик: плоская сеть
По умолчанию, если в namespace нет ни одной NetworkPolicy, весь входящий и исходящий трафик к подам и от подов в этом namespace разрешён. Пока в кластере нет ни одной NetworkPolicy, сеть остаётся плоской. Сценарий эксплуатации: приложение в dev-namespace скомпрометировано, и с него напрямую доступна база данных в prod-namespace.
Базовая практика — default-deny для входящего трафика в каждом продакшн-namespace с последующим перечислением разрешённых потоков. Проверка выполняется двумя способами: статический обзор политик через kubectl get networkpolicy -A и анализ фактических соединений (Cilium Hubble, журналы потоков Calico). Расхождение между описанными политиками и реальным трафиком — типовая находка: политика есть, но разрешённые правила шире, чем требуется приложению.
Цель звучит так: все продакшн-namespace имеют default-deny NetworkPolicy, а количество разрешённых межnamespace-потоков сокращено до задокументированного списка. Итоги подобной работы удобно сверять с приоритетными зонами проверки, разобранными в материале о результатах аудита безопасности Kubernetes и контейнерной инфраструктуры.
Как превратить риск в измеримую цель аудита
Перевод риска в цель идёт по шагам: выбрать риск, описать сценарий эксплуатации, определить целевое состояние кластера, назначить метрику (количество, доля, бинарный флаг), выбрать инструмент проверки, задать критерий приёмки и окно проверки. Шаг с метрикой пропускать нельзя: цель без метрики остаётся пожеланием.
Шаблон формулировки цели: что, чем, до какого порога
Формула: «[Что проверяем] в [границы аудита] с помощью [инструмент] соответствует [порог] к [срок]». Пример: количество подов с privileged: true в namespace prod-* по результатам сканирования манифестов равно нулю к концу периода аудита.
Метрика может быть строгой или относительной. Строгая версия: ноль подов с privileged: true. Относительная: сокращение числа таких подов на девяносто процентов за месяц с планом на остаток. Вторая формулировка уместна там, где полное устранение зависит от внешнего оператора, который требует привилегированный режим. В обоих случаях метрика, инструмент и срок остаются в тексте цели, а не в приложении к отчёту.
Приоритизация целей: что чинить первым
Критерии расстановки приоритетов: вероятность эксплуатации, влияние на продакшн, наличие публично описанных способов эксплуатации и регуляторные требования к защите данных. Быстрые победы закрывают за дни: отключение анонимной аутентификации, включение Node в режим авторизации, добавление securityContext в шаблон деплоймента. Долгие цели требуют пересборки модели доступа: разбор RBAC, введение default-deny в десятках namespace, перевод операторов на непривилегированные режимы.
Матрица «влияние на вероятность» помогает договориться с владельцами сервисов. Высокое влияние и высокая вероятность — первый приоритет. Низкое влияние и низкая вероятность — отложенные цели, которые фиксируются в реестре с датой пересмотра.
| Риск | Цель | Метрика | Инструмент | Критерий приёмки |
|---|---|---|---|---|
| Небезопасные манифесты | Убрать запуск привилегированных контейнеров в продакшене | Число подов с privileged: true | Сканирование манифестов | 0 находок уровня HIGH и CRITICAL |
| Избыточные RBAC-права | Забрать cluster-admin у сервисных аккаунтов приложений | Число ClusterRoleBinding с cluster-admin вне системных namespace | kubectl auth can-i и ручной разбор | 0 |
| Открытый API-сервер | Закрыть анонимный доступ | Число успешных анонимных запросов | Audit log и kube-bench | 0 за 7 дней периода аудита |
| Плоская сеть | Ограничить трафик между namespace | Доля продакшн-namespace с default-deny | kubectl get networkpolicy и журналы потоков | 100% |
Инструменты для аудита: что закрывает каждый
Три инструмента из темы закрывают разные задачи и не заменяют друг друга. Запускать всё подряд без привязки к целям бессмысленно: вывод каждого сканера должен маппиться на конкретную цель аудита.
kube-bench: проверка по CIS Benchmark
Инструмент сверяет настройки control plane и нод с CIS Kubernetes Benchmark: kube-apiserver, kube-controller-manager, kube-scheduler, etcd, kubelet, а также настройки политик и сервисных аккаунтов. Результат выдаётся секциями и пунктами со статусами PASS, FAIL и WARN, к каждому пункту прилагается рекомендация по исправлению. По умолчанию kube-bench сам определяет набор тестов по версии Kubernetes на машине, при этом однозначного соответствия между релизами Kubernetes и релизами CIS Benchmark нет.
kube-bench run --targets master,node kubectl apply -f job.yaml
Запускают двумя способами: как Job внутри кластера или как бинарник прямо на ноде. Второй вариант надёжнее для проверки файлов конфигурации kubelet. При запуске в поде инструменту нужен доступ к PID namespace хоста и к каталогам хоста с конфигурационными файлами, а результаты сохраняются в логах пода. Ограничение: kube-bench не проверяет манифесты приложений и не оценивает избыточность RBAC, поэтому цели по этим областям он не закрывает.
kube-hunter: сканирование периметра и внутренней сети
Сканер ищет уязвимости в самом кластере и в его доступности извне. Запускают его тремя способами: удалённо с любой машины по IP или домену кластера, на машине внутри кластера с проверкой всех локальных сетевых интерфейсов и в поде внутри кластера. По умолчанию активное сканирование не выполняется: режим включается флагом --active, может выполнять изменяющие состояние кластера операции и потому потенциально опасен. Картирование сети узлов делают через --cidr с флагом --mapping. Типичные находки: открытый API-сервер, доступный kubelet, dashboard без аутентификации, etcd без TLS.
kube-hunter --remote 203.0.113.10 --active kube-hunter --cidr 192.168.0.0/24 --mapping kube-hunter --pod
Внешний запуск проверяет периметр, запуск внутри пода показывает картину с точки зрения скомпрометированного контейнера. Активный режим в продакшене согласуют с владельцами кластера заранее: сканирование создаёт нагрузку и может быть воспринято системами мониторинга как инцидент.
Trivy: образы, манифесты, кластер
Инструмент закрывает три задачи, и путать их режимы не стоит. Сканирование образа ищет уязвимости в пакетах и библиотеках. Сканирование конфигураций проверяет манифесты, Helm-чарты и Terraform на небезопасные паттерны. Сканирование кластера командой trivy k8s собирает картину по развёрнутым объектам и их настройкам, различая инфраструктуру кластера (api-server, kubelet, addons), конфигурацию кластера (Roles, ClusterRoles) и рабочие нагрузки приложений.
trivy image registry.example.com/app:1.4.2 trivy config ./manifests trivy k8s --report summary cluster trivy k8s --include-namespaces kube-system --severity=CRITICAL --report=summary
По умолчанию trivy k8s выдаёт краткую сводку, полный отчёт формируется флагом --report=all, а фильтрация по severity и по сканерам (Vulnerabilities, Secrets, Misconfigurations) выполняется флагами --severity и --scanners. Режим config находит privileged: true, отсутствующий securityContext, тег latest, отсутствие limits. Встроенный в конвейер сборки, он не пропускает небезопасный манифест в кластер, и цель по манифестам закрывается на этапе ревью, а не после разбора инцидента. Как автоматика сочетается с ручным анализом и где сканеры принципиально не видят проблему, разобрано в материале про сочетание автоматизированного и ручного аудита безопасности.
Ни один из трёх инструментов не заменяет ручной анализ RBAC и сетевых потоков. Сканер покажет формальные нарушения политик, но не скажет, нужны ли приложению выданные права.
Чек-лист подготовки к аудиту
Ответы на вопросы ниже определяют, какие цели аудита достижимы в принципе. Часть проверок недоступна в managed-кластерах, и это лучше выяснить до старта, а не в середине работы.
Вопросы по границам и инвентаризации
- Сколько кластеров в продакшене и какие версии Kubernetes в них работают?
- Есть ли managed-кластеры (EKS, GKE, AKS) с ограниченным доступом к control plane?
- Какие namespace считаются продакшн, какие относятся к dev и staging?
- Есть ли отдельный кластер для CI/CD и что он видит в продакшене?
- Какой CNI используется и поддерживает ли он NetworkPolicy и журналы потоков?
- Какие admission-контроллеры и операторы установлены в кластере?
В managed-кластерах провайдер закрывает доступ к файлам конфигурации kube-apiserver и etcd, поэтому часть пунктов kube-bench недоступна. Цели по этим пунктам переносят в зону ответственности провайдера или фиксируют как принятые ограничения.
Вопросы по доступам и окну проведения
- Есть ли read-only доступ к API-серверу для аудитора и выдан ли отдельный сервисный аккаунт?
- Разрешено ли создавать объекты в кластере: Job для kube-bench, поды для активного сканирования?
- Согласован ли активный режим сканирования с владельцами кластера?
- Есть ли окно обслуживания и кто дежурит во время проверки?
- Каков план отката, если сканирование вызовет деградацию сервиса?
Активное сканирование создаёт нагрузку и может сработать как триггер алертов, поэтому окно и ответственный за реакцию на алерты согласуют заранее.
Вопросы по отчётности и владельцам
- В каком формате нужен отчёт и куда он попадает?
- Кто получатель: команда эксплуатации, служба безопасности, руководство?
- Какие сроки устранения назначаются находкам разного уровня критичности?
- Кто владелец каждого namespace и кто согласует изменения в RBAC и NetworkPolicy?
Без назначенных владельцев цели аудита остаются на бумаге. Способ упаковать результаты так, чтобы руководство согласовало ресурсы на устранение, описан в статье о том, как представить результаты аудита безопасности руководству и команде.
Примеры целей аудита для типового продакшн-кластера
Восемь формулировок ниже покрывают четыре группы рисков. Каждую адаптируют под свой кластер, меняя границы аудита, порог и срок.
- Цель: в namespace prod-* нет подов с privileged: true. Метрика: число находок. Инструмент: Trivy config scan. Критерий: ноль находок уровня HIGH и CRITICAL. Адаптация: если оператор требует привилегированного режима, исключение фиксируют отдельно с обоснованием.
- Цель: сто процентов подов имеют securityContext с runAsNonRoot: true и readOnlyRootFilesystem: true. Метрика: доля подов. Инструмент: Trivy config scan. Критерий: сто процентов. Адаптация: приложения, пишущие в свой корневой каталог, требуют временного emptyDir.
- Цель: ноль подов с hostPath вне системных namespace. Метрика: число подов. Инструмент: обзор манифестов и состояние кластера. Критерий: ноль. Адаптация: агентам мониторинга вместо hostPath подходит DaemonSet с projection конфигураций.
- Цель: ноль ClusterRoleBinding с cluster-admin для сервисных аккаунтов вне kube-system. Метрика: число привязок. Инструмент: kubectl get clusterrolebinding и kubectl auth can-i --list. Критерий: ноль. Адаптация: конвейеру сборки выдают Role в конкретном namespace.
- Цель: все сервисные аккаунты приложений имеют только namespace-скоуп. Метрика: число ClusterRoleBinding для приложений. Инструмент: ручной аудит RBAC. Критерий: ноль. Адаптация: проверяют также неиспользуемые роли и привязки за последние месяцы.
- Цель: анонимная аутентификация на API-сервере отключена. Метрика: статус пункта проверки. Инструмент: kube-bench. Критерий: PASS по пункту про anonymous-auth. Адаптация: в managed-кластерах настройку проверяют через прокси провайдера или фиксируют ограничение.
- Цель: ноль успешных анонимных запросов к API-серверу. Метрика: число записей в audit log. Инструмент: анализ audit log и kube-hunter. Критерий: ноль за период аудита. Адаптация: сначала включают audit policy, иначе метрику снять негде.
- Цель: все продакшн-namespace имеют default-deny NetworkPolicy, разрешённые межnamespace-потоки задокументированы и не превышают согласованный список. Метрика: доля namespace и число потоков. Инструмент: kubectl get networkpolicy -A и журналы потоков CNI. Критерий: сто процентов namespace, список потоков согласован. Адаптация: для кластеров с Cilium удобно опираться на журналы Hubble.
Что делать после аудита: от целей к плану устранения
После проверки находки группируют по целям, для каждой цели выставляют статус: достигнута, достигнута частично, не достигнута. Статус без метрики не выставляется, поэтому цель изначально формулируют так, чтобы её можно было измерить повторно.
Дальше формируют план устранения: действие, владелец, срок, критерий проверки. Повторная проверка использует те же инструменты и те же метрики, иначе сравнить результаты не получится. Практический пример: цель по привилегированным подам не достигнута, потому что один оператор требует privileged. Исключение фиксируют письменно с обоснованием, компенсирующими мерами и датой пересмотра, а не вычёркивают из отчёта.
Цели аудита обновляют при изменении кластера: смена версии Kubernetes, появление новых namespace, подключение операторов, смена CNI. Регламент повторяемой процедуры и типовые промахи при его составлении разобраны в статье про ошибки при составлении регламента аудита безопасности. Следующий шаг после чтения: выписать четыре риска, которые актуальны для вашего кластера, и для каждого зафиксировать цель с метрикой, инструментом, критерием приёмки и датой повторной проверки.