Стадия жизненного цикла модуля: General Availability
У модуля есть требования для установки
Модуль выполняет автоматические проверки безопасности кластера в соответствии со спецификацией CIS Kubernetes Benchmark.
Используемая версия
Модуль реализует проверки согласно спецификации CIS Kubernetes Benchmark v1.23.
Данная документация описывает внешний модуль operator-trivy, доступный начиная с DKP 1.75.
В DKP 1.74 и ранее использовался встроенный модуль с Trivy v0.55.2.
Версии используемых компонентов:
| Компонент | Версия |
|---|---|
| Trivy | v0.67.2 |
| Trivy Operator | v0.29.0 |
| k8s-node-collector | v0.3.1 |
Про актуальность версий. Таблица версий в этом документе относится к текущей версии модуля (обновляется вместе с модулем). Если вам нужен «источник истины» для конкретного кластера, проверьте фактически запущенные образы:
d8 k -n d8-operator-trivy get pods -o json | \
jq -r '.items[] | .metadata.name as $p | .spec.containers[] | "\($p)\t\(.name)\t\(.image)"'Категории проверок
Проверки CIS Kubernetes Benchmark сгруппированы по следующим категориям:
| Категория | Раздел CIS | Идентификатор | Описание |
|---|---|---|---|
| Control Plane | 1.x | AVD-KCV-* | Конфигурация API server, controller manager, scheduler |
| etcd | 2.x | AVD-KCV-* | Параметры безопасности etcd |
| Control Plane | 3.x | — | Аутентификация и логирование (ручные проверки) |
| Worker Nodes | 4.x | AVD-KCV-* | Конфигурация kubelet и права доступа к файлам |
| Политики | 5.x | AVD-KSV-* | RBAC, Pod Security Standards, сетевые политики |
Исключения
В Deckhouse Kubernetes Platform (DKP) часть проверок отключена или исключена из отчётов. Это обусловлено архитектурными особенностями платформы и требованиями к работе системных компонентов.
Примечание: документ описывает текущую реализацию проверок CIS в DKP и применяемые исключения. Результаты CIS зависят от конфигурации кластера и состава компонентов, поэтому 100% PASS по всем контролям не гарантируется.
Глобально отключённые проверки
Следующие проверки отключены для всех ресурсов кластера:
CIS 1.2.1 — Anonymous auth (AVD-KCV-0001)
Проверка: Ensure that the --anonymous-auth argument is set to false.
Статус: Полностью отключена.
Причина: Проверка Trivy/defsec для CIS 1.2.1 основана на анализе устаревшего флага --anonymous-auth. В современных версиях Kubernetes настройка анонимной аутентификации может задаваться иначе (например, через AuthenticationConfiguration), поэтому флаговая проверка может давать ложные FAIL/WARN (в том числе в kube-bench). Для аудита используйте фактическую конфигурацию kube-apiserver и ограничения доступа в вашей инфраструктуре.
CIS 1.2.13 — SecurityContextDeny (AVD-KCV-0013)
Проверка: Ensure that the admission control plugin SecurityContextDeny is set if PodSecurityPolicy is not used.
Статус: Полностью отключена.
Причина: Admission controller SecurityContextDeny был объявлен устаревшим и полностью удалён в Kubernetes v1.30. Этот контроллер блокировал поды с привилегированными настройками, но его подход был слишком грубым и не позволял гранулярно настраивать политики.
Альтернатива в DKP: Deckhouse использует Pod Security Standards, реализованные в модуле admission-policy-engine на базе OPA Gatekeeper. Это позволяет:
- Применять политики
Privileged,BaselineилиRestrictedна уровне неймспейса - Создавать исключения для конкретных workloads
- Гибко настраивать правила под требования организации
Проверки, отключённые для системных неймспейсов
Следующие проверки отключены для неймспейсов kube-system и d8-* (все неймспейсы Deckhouse начинаются с префикса d8-).
Для пользовательских неймспейсов эти проверки выполняются в полном объёме и помогают выявить небезопасные конфигурации.
Почему системным компонентам нужны привилегии?
Kubernetes-кластер требует компонентов, работающих на низком уровне: управление сетью, хранилищем, мониторинг ресурсов хоста. Эти компоненты по своей природе не могут работать в изолированном контейнере без привилегий.
| CIS ID | Check ID | Проверка | Примеры в DKP |
|---|---|---|---|
| 5.2.2 | AVD-KSV-0017 | Minimize the admission of privileged containers | DaemonSet/d8-cni-cilium/agent (privileged: true), DaemonSet/d8-cloud-instance-manager/fencing-agent-* (privileged: true) |
| 5.2.3 | AVD-KSV-0010 | Minimize the admission of containers wishing to share the host process ID namespace | DaemonSet/d8-monitoring/node-exporter (hostPID: true), DaemonSet/d8-monitoring/ebpf-exporter (hostPID: true) |
| 5.2.5 | AVD-KSV-0009 | Minimize the admission of containers wishing to share the host network namespace | DaemonSet/d8-monitoring/node-exporter (hostNetwork: true) |
| 5.2.6 | AVD-KSV-0001 | Minimize the admission of containers with allowPrivilegeEscalation | DaemonSet/d8-cni-cilium/agent (allowPrivilegeEscalation: true), DaemonSet/d8-istio/ztunnel (allowPrivilegeEscalation: true) |
| 5.2.7 | AVD-KSV-0012 | Minimize the admission of root containers | DaemonSet/d8-istio/ztunnel (runAsUser: 0) |
| 5.2.8 | AVD-KSV-0022 | Minimize the admission of containers with the NET_RAW capability | DaemonSet/d8-istio/ztunnel (capabilities: NET_RAW) |
| 5.2.12 | AVD-KSV-0023 | Minimize the admission of HostPath volumes | DaemonSet/d8-monitoring/node-exporter (hostPath: /, /etc/containerd, /var/run/node-exporter-textfile) |
| 5.2.13 | AVD-KSV-0024 | Minimize the admission of containers which use HostPorts | DaemonSet/d8-ingress-nginx/controller-* (hostPort: 80/443 в режимах HostPort/Failover) |
Частичные исключения
Для отдельных ресурсов действуют специфические исключения:
CIS 5.7.4 — Default namespace (AVD-KSV-0110)
Проверка: The default namespace should not be used.
Исключение: Ресурс default/service-kubernetes.
Причина: Сервис kubernetes в неймспейсе default — это встроенный сервис Kubernetes API Server. Он создаётся автоматически при инициализации кластера и не может быть перемещён в другой неймспейс. Это стандартное поведение Kubernetes, задокументированное в официальной документации.
CIS 5.7.3 — Security Context (AVD-KSV-0020, AVD-KSV-0021)
Проверка: Apply Security Context to Your Pods and Containers.
Исключение: ReplicaSets в неймспейсах d8-*.
Причина: Проверки требуют runAsUser > 10000 и runAsGroup > 10000 (использование непривилегированных UID/GID). В DKP существуют системные workloads, которые запускаются от root (runAsUser/runAsGroup = 0) или не задают runAsUser/runAsGroup явно — это может быть нужно для совместимости с доступом к файловой системе хоста и низкоуровневыми операциями.
- Совместимости с правами доступа на файлы хоста
- Корректной работы с volumes, где права уже настроены
- Соответствия стандартным практикам системных сервисов
Как проверить, какие объекты “ниже порога” 5.7.3 в вашем кластере (читаемый формат):
Краткая сводка (pod-level runAsUser/runAsGroup) для системных неймспейсов d8-*, kube-system, kube-public, kube-node-lease:
d8 k get deploy,rs,ds,sts -A -o json | jq -r '
.items[]
| select(.metadata.namespace | test("^(d8-)|^(kube-system|kube-public|kube-node-lease)$"))
| . as $o
| ($o.spec.template.spec.securityContext.runAsUser // null) as $u
| ($o.spec.template.spec.securityContext.runAsGroup // null) as $g
| select((($u|tonumber? // -1) <= 10000) or (($g|tonumber? // -1) <= 10000))
| [
$o.kind,
$o.metadata.namespace,
$o.metadata.name,
("runAsUser=" + (($u|tostring) // "null")),
("runAsGroup=" + (($g|tostring) // "null"))
] | @tsv'Детализация по контейнерам (container-level runAsUser/runAsGroup), чтобы увидеть, что задано на уровне pod и что — на уровне container:
d8 k get deploy,rs,ds,sts -A -o json | jq -r '
.items[]
| select(.metadata.namespace | test("^(d8-)|^(kube-system|kube-public|kube-node-lease)$"))
| . as $o
| ($o.spec.template.spec.securityContext.runAsUser // null) as $pu
| ($o.spec.template.spec.securityContext.runAsGroup // null) as $pg
| $o.spec.template.spec.containers[]?
| . as $c
| ($c.securityContext.runAsUser // null) as $cu
| ($c.securityContext.runAsGroup // null) as $cg
| select((($pu|tonumber? // 999999) <= 10000) or (($pg|tonumber? // 999999) <= 10000) or (($cu|tonumber? // 999999) <= 10000) or (($cg|tonumber? // 999999) <= 10000))
| [
$o.kind,
$o.metadata.namespace,
$o.metadata.name,
("pod.runAsUser=" + (($pu|tostring) // "null")),
("pod.runAsGroup=" + (($pg|tostring) // "null")),
("container=" + $c.name),
("container.runAsUser=" + (($cu|tostring) // "null")),
("container.runAsGroup=" + (($cg|tostring) // "null"))
] | @tsv'Проверки, исключённые из метрик
Следующие проверки выполняются, но их результаты не отображаются в Prometheus-метриках и на дашборде Grafana. Это сделано намеренно, чтобы дашборд отражал реальные проблемы безопасности, а не ложные срабатывания.
Важно: Результаты этих проверок по-прежнему сохраняются в ClusterComplianceReport и доступны для аудита.
CIS 5.1.2 — Access to secrets (AVD-KSV-0041)
Проверка: Minimize access to secrets.
Что проверяет: Находит все Roles/ClusterRoles с правами get, list или watch на ресурс secrets.
Почему исключена из метрик:
В оригинальном CIS Benchmark эта проверка помечена как type: manual и scored: false, потому что:
- Невозможно автоматически определить, легитимен ли доступ к secrets
- Любой контроллер, работающий с TLS или credentials, требует такого доступа
Примеры ролей с легитимным доступом к secrets в DKP:
d8:ingress-nginx:kruise-role— управление секретами для ingress-контроллеровd8:node-manager:machine-controller-manager— роль дляmachine-controller-manager(nsd8-cloud-instance-manager) читает secrets/configmapsd8:operator-prometheus— ClusterRole оператора Prometheus читает/создаёт secretsRole/d8-log-shipper/log-shipper— Role модуля log-shipper читает secrets вd8-log-shipper
Где посмотреть полный список ролей/кто имеет доступ к secrets:
# Все Roles/ClusterRoles, которые имеют доступ к secrets (get/list/watch)
d8 k get clusterroles,roles -A -o json | jq -r '
.items[]
| select(any(.rules[]?;
((.resources // []) | index("secrets")) != null
and (
((.verbs // []) | index("get")) != null
or ((.verbs // []) | index("list")) != null
or ((.verbs // []) | index("watch")) != null
)
))
| "\(.kind)\t\(.metadata.namespace // "-")\t\(.metadata.name)"'
# Быстрый поиск привязок по имени роли (пример)
role_name="d8:operator-prometheus"
d8 k get clusterrolebindings,rolebindings -A | grep -F "$role_name"Как анализировать результаты:
# Получить все роли с доступом к secrets
d8 k get clustercompliancereports.aquasecurity.github.io cis -ojson | \
jq '.status.detailReport.results | map(select(.id == "5.1.2")) | .[].checks'Проанализируйте список и убедитесь, что:
- Все роли принадлежат известным системным компонентам
- Нет пользовательских ролей с избыточным доступом
CIS 5.1.3 — Wildcard use in Roles (AVD-KSV-0044, AVD-KSV-0045, AVD-KSV-0046)
Проверка: Minimize wildcard use in Roles and ClusterRoles.
Что проверяет: Находит роли с wildcards (*) в полях resources, verbs или apiGroups.
Почему исключена из метрик:
В оригинальном CIS Benchmark эта проверка помечена как type: manual и scored: false, потому что:
cluster-admin— стандартная роль Kubernetes, содержит wildcards- Операторы часто требуют широкого доступа для управления разнообразными ресурсами
Примеры легитимного использования wildcards в DKP:
cluster-admin— полный доступ для администраторовdeckhouseClusterRole — управление всеми модулями Deckhouse- CRD-операторы — доступ ко всем ресурсам своего API group
Как анализировать результаты:
# Получить все роли с wildcards
d8 k get clustercompliancereports.aquasecurity.github.io cis -ojson | \
jq '.status.detailReport.results | map(select(.id == "5.1.3")) | .[].checks'Убедитесь, что wildcards используются только в:
- Системных ролях Kubernetes (
cluster-admin,admin,edit,view) - Ролях компонентов Deckhouse (
d8-*) - Ролях известных операторов
Известные особенности
Проверка TLS-сертификатов kubelet (CIS 4.2.10)
Проверки AVD-KCV-0088 и AVD-KCV-0089 могут показывать статус FAIL. Это ожидаемое поведение: Deckhouse использует механизм автоматической ротации сертификатов kubelet (RotateKubeletServerCertificate) вместо статических файлов --tls-cert-file и --tls-private-key-file.
Подробнее см. в FAQ модуля control-plane-manager.
Ручные проверки
Следующие проверки требуют ручной верификации и не автоматизированы. Это соответствует оригинальной спецификации CIS Benchmark, где они помечены как Manual.
| CIS ID | Проверка | Рекомендации |
|---|---|---|
| 3.1.1 | Client certificate authentication should not be used for users | Настройте аутентификацию через OIDC с помощью модуля user-authn. |
| 3.2.1 | Ensure that a minimal audit policy is created | Deckhouse автоматически настраивает базовые audit policy. См. документацию по аудиту. |
| 3.2.2 | Ensure that the audit policy covers key security concerns | Проведите ревью audit policy на соответствие требованиям безопасности вашей организации. |
| 5.3.1 | Ensure that the CNI in use supports Network Policies | Deckhouse использует CNI с поддержкой Network Policies (Cilium или Flannel с Calico). |
| 5.4.1 | Prefer using secrets as files over secrets as environment variables | Рекомендация по архитектуре приложений. Проведите аудит ваших workloads. |
| 5.4.2 | Consider external secret storage | Рекомендуемый вариант для DKP — использовать Stronghold (Vault‑совместимое хранилище секретов) и хранить секреты вне Kubernetes. См. документацию Stronghold. Для синхронизации секретов в Kubernetes можно использовать модуль secrets-store-integration. |
| 5.5.1 | Configure Image Provenance using ImagePolicyWebhook | Используйте модуль admission-policy-engine с политиками проверки подписей образов. |
| 5.7.1 | Create administrative boundaries between resources using namespaces | Проведите ревью структуры неймспейсов в соответствии с требованиями вашей организации. |
Сопоставление с kube-bench
DKP использует Trivy Operator для проверок CIS вместо утилиты kube-bench. Соответствие проверок:
| Тип проверки | Идентификатор | Механизм выполнения | Аналог в kube-bench |
|---|---|---|---|
| Control Plane, Worker Nodes | AVD-KCV-* | k8s-node-collector выполняет команды на нодах | Проверки master/node |
| Политики безопасности | AVD-KSV-* | Trivy анализирует объекты Kubernetes | Отсутствует |
Для сопоставления результатов используйте CIS Control ID (например, 1.2.1, 5.2.2).
Просмотр результатов
Grafana
Результаты проверок доступны на дашборде Security / CIS Kubernetes Benchmark.
Командная строка
Получить все результаты:
d8 k get clustercompliancereports.aquasecurity.github.io cis -ojson | \
jq '.status.detailReport.results'Получить только проваленные проверки:
d8 k get clustercompliancereports.aquasecurity.github.io cis -ojson | \
jq '.status.detailReport.results | map(select(.checks | map(.success) | all | not))'Получить результат конкретной проверки:
d8 k get clustercompliancereports.aquasecurity.github.io cis -ojson | \
jq '.status.detailReport.results | map(select(.id == "5.7.3"))'Расписание проверок
Проверки CIS Benchmark выполняются:
- каждые 6 часов (cron:
0 */6 * * *); - при запуске оператора.