Стадия жизненного цикла модуля: 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 (ns d8-cloud-instance-manager) читает secrets/configmaps
  • d8:operator-prometheus — ClusterRole оператора Prometheus читает/создаёт secrets
  • Role/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 — полный доступ для администраторов
  • deckhouse ClusterRole — управление всеми модулями 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 * * *);
  • при запуске оператора.