Kyverno: проверка и изменение ресурсов

Менеджер политик, отчёт по политикам, примеры политик.

Введение

В разделе Безопасность кластера доступны страницы по управлению политиками безопасности на базе Kyverno:

  • Менеджер политик безопасности — список политик, создание, просмотр, изменение и удаление.
  • Отчёт по политикам безопасности — результаты анализа в разрезе политик и неймспейсов, выгрузка в CSV/PDF.

Модуль анализа конфигураций приложений — shturval-policy-manager. Поддерживаются политики типов Generate (добавление данных в ресурс), Mutate (изменение ресурса), Validate (проверка и при необходимости блокировка). Подробнее о типах правил — в официальной документации Kyverno.

Сводный отчёт по политикам всех кластеров платформы и другие места отображения результатов анализа описаны на странице Какие отчёты есть в платформе и где они находятся.


Менеджер политик безопасности

Страница представляет собой таблицу со списком политик безопасности. Колонки:

  • Название — доступна фильтрация;
  • Дата создания — доступна сортировка.

На странице доступны создание, просмотр, изменение и удаление политик.

Скриншот: список политик безопасности

Список политик безопасности

Чтобы добавить политику, используйте импорт манифеста: нажмите + Добавить политику безопасности, вставьте YAML и выполните проверку. После успешного прохождения проверки нажмите Загрузить.

Скриншоты: импорт манифеста политики

Добавление политики безопасности

Импорт манифеста политики безопасности

На странице просмотра политики четыре вкладки: политика, лейблы и аннотации, события, манифест.

Скриншот: просмотр политики безопасности

Просмотр политики безопасности

Политику можно изменить через YAML на вкладке Манифест: внесите изменения, нажмите Проверить — в правой части экрана отобразится результат проверки. Раскройте блок результата проверки, чтобы увидеть полный манифест, затем сохраните изменения.

Скриншот: редактирование манифеста политики

Редактирование манифеста политики безопасности


Какие кастомные ресурсы создаёт Kyverno

При установке Kyverno в кластере появляются несколько типов кастомных ресурсов Kubernetes:

  • ClusterPolicy и Policy (группы kyverno.io) — собственно политики Kyverno:
    • ClusterPolicy — кластерные политики (действуют во всех неймспейсах);
    • Policy — неймспейсные политики (ограничены конкретным namespace).
  • ClusterPolicyReport и PolicyReport (группа wgpolicyk8s.io) — отчёты о срабатывании политик:
    • агрегируют результаты проверки ресурсов (успешные, с предупреждениями и ошибками);
    • используются модулем shturval-policy-manager для построения отчётов в GUI.
  • Дополнительные служебные ресурсы (могут отличаться по версии Kyverno):
    • UpdateRequest / GenerateRequest — внутренняя очередь для генерации/обновления ресурсов по правилам Generate;
    • отчёты фонового сканирования (background scan) в виде PolicyReport‑ов.

В интерфейсе платформы эти ресурсы отображаются:

  • в разделе Безопасность → Менеджер политик безопасности (ClusterPolicy/Policy);
  • в Отчёте по политикам безопасности (PolicyReport/ClusterPolicyReport);
  • в разделе Администрирование → Кастомные ресурсы (просмотр всех CR Kyverno при необходимости).

Отчёт по политикам безопасности

На странице Отчёт по политикам безопасности представлены результаты анализа объектов на соответствие политикам Kyverno. Доступен просмотр:

  • в разрезе политик;
  • в разрезе неймспейсов.
Скриншоты: отчёт по политикам и неймспейсам

Отчёт по политикам безопасности в разрезе политик

Отчёт по политикам безопасности в разрезе неймспейсов

Дополнительно доступна фильтрация по системным или пользовательским неймспейсам. По умолчанию отображается отчёт по всем неймспейсам. Чтобы отфильтровать неймспейсы, в правом верхнем углу из выпадающего списка выберите нужный фильтр.

Скриншот: фильтрация отчёта по неймспейсам

Фильтрация отчёта по политикам безопасности

Отчёт можно скачать в формате CSV или PDF. Если в отчёте нет данных, при скачивании в формате CSV формируется пустой файл. Имя скачиваемого CSV-файла: Report on violated policies.

Импорт CSV в Microsoft Excel

Excel 2019 и новее

  1. Создайте новый файл Excel и перейдите на вкладку Данные.
Скриншот: вкладка «Данные»

Вкладка «Данные» в Excel 2019 и новее

  1. В левой части панели выберите Из текста/CSV, укажите скачанный файл отчёта и нажмите Импорт.
Скриншот: импорт CSV-файла

Импорт CSV-файла в Excel 2019 и новее

  1. В появившемся окне выберите разделитель Запятая и нажмите Загрузить.
Скриншот: выбор разделителя

Выбор разделителя при импорте CSV в Excel 2019 и новее

Excel 2018 и ниже

  1. Создайте новый файл Excel и перейдите на вкладку Данные.
Скриншот: вкладка «Данные»

Вкладка «Данные» в Excel 2018 и ниже

  1. В левой части панели выберите Из текста, укажите скачанный файл отчёта и нажмите Импорт.
Скриншот: импорт текстового файла

Импорт текстового файла в Excel 2018 и ниже

  1. В мастере импорта выберите формат данных С разделителями и нажмите Далее.
Скриншот: формат данных

Выбор формата данных с разделителями

  1. Укажите разделитель Запятая и нажмите Далее.
Скриншот: выбор разделителя

Выбор запятой в качестве разделителя

  1. Выберите формат столбцов Общий и нажмите Готово.
Скриншот: формат столбцов

Выбор общего формата столбцов

  1. Укажите лист и начальную ячейку для импорта и нажмите ОК.
Скриншот: размещение импортированных данных

Выбор листа и начальной ячейки для импорта


Работа с Kyverno из консоли

В дополнение к графическому интерфейсу, с Kyverno можно работать привычным способом через kubectl.

Политики (ClusterPolicy/Policy)

Список кластерных политик:

kubectl get clusterpolicies.kyverno.io

Список неймспейсных политик в нужном неймспейсе:

kubectl get policies.kyverno.io -n <namespace>

Просмотр манифеста конкретной политики:

kubectl get clusterpolicy absence-of-cpu-requests -o yaml

Создание или обновление политики из файла:

kubectl apply -f ./policy.yaml

Удаление политики:

kubectl delete clusterpolicy absence-of-cpu-requests

Отчёты по политикам (PolicyReport / ClusterPolicyReport)

Список отчётов по политикам (кластерный уровень):

kubectl get clusterpolicyreports.wgpolicyk8s.io

Список отчётов в конкретном неймспейсе:

kubectl get policyreports.wgpolicyk8s.io -n <namespace>

Просмотр отчёта:

kubectl get policyreport <report-name> -n <namespace> -o yaml

В отчётах видны:

  • ресурсы, к которым применялась политика;
  • результаты (pass / fail / warn);
  • сообщение валидации и имя политики.

Служебные ресурсы Kyverno

При отладке срабатывания правил Generate или при разборе фоновых сканирований могут быть полезны служебные ресурсы:

kubectl get updaterequests.kyverno.io -A
kubectl get generaterequests.kyverno.io -A  # если CRD присутствует в используемой версии

Однако в большинстве случаев администратору достаточно:

  • управлять политиками через ClusterPolicy/Policy;
  • анализировать результаты через PolicyReport/ClusterPolicyReport (в GUI и/или через kubectl).

Рекомендуемые политики

Ниже — типичные политики для усиления безопасности кластера. Чтобы добавить политику, откройте импорт манифеста в менеджере политик, вставьте YAML (из примеров ниже или из внешнего набора), нажмите Проверить, затем Загрузить.

Политики можно включать в режиме Audit (только отчёт) или Enforce (блокировка создания и обновления при несоответствии). Для постепенного внедрения сначала используйте Audit и проверьте политику в тестовом окружении, затем при необходимости переведите её в Enforce. В примерах ниже по умолчанию указан режим Audit; при необходимости измените validationFailureAction в манифесте.

При проектировании политик также учитывайте failurePolicy: значение Ignore не блокирует запрос, если проверка не выполнена из-за ошибки, например при недоступности webhook.

Дополнительные примеры — в репозитории Kyverno policies — best-practices.

absence-of-cpu-requests

Политика проверяет, что у всех контейнеров (включая init-контейнеры) задан resources.requests.cpu. Отсутствие запросов может привести к исчерпанию ресурсов узла (DoS) и нарушить работу HPA.

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  annotations:
    meta.helm.sh/release-name: shturval-policies
    meta.helm.sh/release-namespace: kyverno
    policies.kyverno.io/category: infosec
    policies.kyverno.io/description: Kubernetes обладает возможностью установки и ограничений
      на потребление ресурсов CPU запускаемыми контейнерами. В случае, если ограничения
      отсутствуют, может произойти Denial of Service (DoS), обусловленный тем, что
      pod (контейнер) будет использовать все ресурсы узла, которые ему доступны. Поэтому
      хорошей практикой считается установка параметров Request (запрос на ресурс)
      на CPU.
    policies.kyverno.io/severity: High
    policies.kyverno.io/title: CPU Requests checker
  labels:
    app.kubernetes.io/managed-by: Helm
  name: absence-of-cpu-requests
spec:
  admission: true
  background: true
  failurePolicy: Ignore
  rules:
  - match:
      any:
      - resources:
          kinds:
          - Pod
    name: check-for-cpu-requests
    skipBackgroundRequests: true
    validate:
      foreach:
      - list: request.object.spec.[initContainers, containers][]
        pattern:
          resources:
            requests:
              cpu: ?*
      message: Параметр Requests для CPU не установлен у Container/InitContainer
  schemaValidation: true
  validationFailureAction: Audit
  webhookTimeoutSeconds: 10
absence-of-ram-requests-limits

Политика проверяет наличие resources.requests.memory и resources.limits.memory у контейнеров (включая init-контейнеры). Отсутствие лимитов и запросов повышает риск DoS на узле.

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  annotations:
    meta.helm.sh/release-name: shturval-policies
    meta.helm.sh/release-namespace: kyverno
    policies.kyverno.io/category: infosec
    policies.kyverno.io/description: Kubernetes обладает возможностью ограничения
      на потребление ресурсов RAM запускаемыми контейнерами. В случае, если такие
      параметры не установлены, возможна вероятность Denial of Service (DoS), обусловленной
      тем, что pod (контейнер) будет использовать все ресурсы узла, которые ему доступны.
      По этому хорошей практикой считается установка параметров Request (запрос на
      ресурс) и Limits (максимально допустимое количество ресурсов) на RAM.
    policies.kyverno.io/severity: High
    policies.kyverno.io/title: RAM Requests and Limits checker
  generation: 1
  labels:
    app.kubernetes.io/managed-by: Helm
  name: absence-of-ram-requests-limits
spec:
  admission: true
  background: true
  failurePolicy: Ignore
  rules:
  - match:
      any:
      - resources:
          kinds:
          - Pod
    name: check-for-ram-requests
    skipBackgroundRequests: true
    validate:
      foreach:
      - list: request.object.spec.[initContainers, containers][]
        pattern:
          resources:
            requests:
              memory: ?*
      message: Параметр Requests для RAM не установлен у Container/InitContainer
  - match:
      any:
      - resources:
          kinds:
          - Pod
    name: check-for-ram-limits
    skipBackgroundRequests: true
    validate:
      foreach:
      - list: request.object.spec.[initContainers, containers][]
        pattern:
          resources:
            limits:
              memory: ?*
      message: Параметр Limits для RAM не установлен у Container/InitContainer
  schemaValidation: true
  validationFailureAction: Audit
  webhookTimeoutSeconds: 10
automated-satoken-mount-used

Не использовать автоматическую подстановку Service Account Token в под (automountServiceAccountToken), если это не требуется: токен даёт доступ к API-серверу, который большинству подов не нужен.

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  annotations:
    meta.helm.sh/release-name: shturval-policies
    meta.helm.sh/release-namespace: kyverno
    policies.kyverno.io/category: infosec
    policies.kyverno.io/description: 'По умолчанию Kubernetes реализует подстановку
      ServiceAccount Token в pod. При помощи этого Token можно взаимодействовать с
      API-сервером, что НЕ требуется большинству pods. Рекомендуется отключать эту
      возможность и реализовывать ее только там, где это по-настоящему требуется.   '
    policies.kyverno.io/severity: High
    policies.kyverno.io/title: automountServiceAccountToken is set to true
  generation: 1
  labels:
    app.kubernetes.io/managed-by: Helm
  name: automated-satoken-mount-used
spec:
  admission: true
  background: true
  failurePolicy: Ignore
  rules:
  - match:
      any:
      - resources:
          kinds:
          - Pod
    name: check-for-automount-serviceaccount-token
    skipBackgroundRequests: true
    validate:
      message: Добавлена автоматическая подстановка ServiceAccount Token в Pod
      pattern:
        spec:
          automountServiceAccountToken: "false"
  schemaValidation: true
  validationFailureAction: Audit
  webhookTimeoutSeconds: 10
container-is-privileged

Запрет привилегированных контейнеров (privileged: true): привилегированный режим может использоваться для повышения привилегий и развития атаки на кластер.

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  annotations:
    meta.helm.sh/release-name: shturval-policies
    meta.helm.sh/release-namespace: kyverno
    policies.kyverno.io/category: infosec
    policies.kyverno.io/description: 'Указанный флаг запускает контейнер в привилегированном
      режиме, что может быть использовано злоумышленником. Например, для повышения
      привилегий и развития атаки на кластер. Большинство контейнеров не требует использование
      указанного флага, поэтому рекомендуется НЕ использовать его.   '
    policies.kyverno.io/severity: High
    policies.kyverno.io/title: privileged flag in spec.containers is set to true
  generation: 1
  labels:
    app.kubernetes.io/managed-by: Helm
  name: container-is-privileged
spec:
  admission: true
  background: true
  failurePolicy: Ignore
  rules:
  - match:
      any:
      - resources:
          kinds:
          - Pod
    name: check-for-privileged
    skipBackgroundRequests: true
    validate:
      message: Обнаружен контейнер с флагом privileged
      pattern:
        spec:
          containers:
          - =(securityContext):
              =(privileged): "false"
  schemaValidation: true
  validationFailureAction: Audit
  webhookTimeoutSeconds: 10
default-ns-is-used

Запрет размещения ресурсов в неймспейсе default: рекомендуется использовать отдельные неймспейсы под приложения и команды.

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  annotations:
    meta.helm.sh/release-name: shturval-policies
    meta.helm.sh/release-namespace: kyverno
    pod-policies.kyverno.io/autogen-controllers: none
    policies.kyverno.io/category: infosec
    policies.kyverno.io/description: 'Использование namespace с именем "default" не
      рекомендуется. Хорошей практикой считается использование специально-созданных
      namespace под нужды специалистов и/или приложений.   '
    policies.kyverno.io/severity: High
    policies.kyverno.io/title: deployment to default namespace
  generation: 1
  labels:
    app.kubernetes.io/managed-by: Helm
  name: default-ns-is-used
spec:
  admission: true
  background: true
  failurePolicy: Ignore
  rules:
  - match:
      resources:
        kinds:
        - Pod
    name: check-for-default-ns
    skipBackgroundRequests: true
    validate:
      message: Обнаружен ресурс в неймспейсе default
      pattern:
        metadata:
          namespace: '!default'
  - match:
      resources:
        kinds:
        - DaemonSet
        - Deployment
        - Job
        - CronJob
        - StatefulSet
    name: check-for-default-ns-pod-controller
    skipBackgroundRequests: true
    validate:
      message: Обнаружен ресурс в неймспейсе default
      pattern:
        metadata:
          namespace: '!default'
  schemaValidation: true
  validationFailureAction: Audit
  webhookTimeoutSeconds: 10
hostnetwork-is-used

Не использовать сеть узла (hostNetwork) без необходимости: с точки зрения сетевого плагина под оказывается в сети узла, что обходит сетевые политики.

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  annotations:
    meta.helm.sh/release-name: shturval-policies
    meta.helm.sh/release-namespace: kyverno
    policies.kyverno.io/category: infosec
    policies.kyverno.io/description: 'Использование параметра hostNetwork позволяет
      обойти требования сетевых политик, т.к. с точки зрения сетевого плагина рассматриваемый
      pod находится в другой сети (сеть узла).      '
    policies.kyverno.io/severity: medium
    policies.kyverno.io/title: hostNetwork is set to `true`
  generation: 1
  labels:
    app.kubernetes.io/managed-by: Helm
  managedFields:
  - apiVersion: kyverno.io/v1
  name: hostnetwork-is-used
spec:
  admission: true
  background: true
  failurePolicy: Ignore
  rules:
  - match:
      any:
      - resources:
          kinds:
          - Pod
    name: check-for-hostnetwork
    skipBackgroundRequests: true
    validate:
      message: 'Использована сеть узлов для Pod. Рекомендуется удалить или отключить
        параметр hostNetwork          '
      pattern:
        spec:
          =(hostNetwork): "false"
  schemaValidation: true
  validationFailureAction: Audit
  webhookTimeoutSeconds: 10
master-tolerations-are-set

Не планировать пользовательские поды на узлах control plane: tolerations, снимающие taint node-role.kubernetes.io/control-plane:NoSchedule, допускают запуск на control-plane.

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  annotations:
    meta.helm.sh/release-name: shturval-policies
    meta.helm.sh/release-namespace: kyverno
    policies.kyverno.io/category: infosec
    policies.kyverno.io/description: 'Использование tolerations позволяет запускать
      Pods на узлах, которые обладают соответствующими taints. Хорошей практикой считается
      НЕ запускать Pods на ControlPlane узлах, которые по умолчанию обладают taints:
      node-role.kubernetes.io/master:NoSchedule  '
    policies.kyverno.io/severity: Medium
    policies.kyverno.io/title: Tolerations for scheduling on ControlPlane Nodes
  generation: 1
  labels:
    app.kubernetes.io/managed-by: Helm
  name: master-tolerations-are-set
spec:
  admission: true
  background: true
  failurePolicy: Ignore
  rules:
  - match:
      resources:
        kinds:
        - Pod
    name: check-for-tolerations
    skipBackgroundRequests: true
    validate:
      message: Обнаружены tolerations, запустившие Pod на ControlPlane-узле с taints
        `node-role.kubernetes.io/control-plane:NoSchedule`
      pattern:
        spec:
          =(tolerations):
          - key: '!node-role.kubernetes.io/control-plane'
  schemaValidation: true
  validationFailureAction: Audit
  webhookTimeoutSeconds: 10
secrets-in-env-var

Предупреждение или запрет хранения секретов в переменных окружения: такие значения проще скомпрометировать; рекомендуется внешнее управление секретами.

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  annotations:
    meta.helm.sh/release-name: shturval-policies
    meta.helm.sh/release-namespace: kyverno
    policies.kyverno.io/category: infosec
    policies.kyverno.io/description: 'Секреты, указываемые в качестве переменных окружения
      могут быть скомпрометированы. Рекомендуется использование сторонних систем (Secret
      Management) для управления секретами.   '
    policies.kyverno.io/severity: High
    policies.kyverno.io/title: secrets are stored in env vars
  generation: 1
  name: secrets-in-env-var
spec:
  admission: true
  background: true
  failurePolicy: Ignore
  rules:
  - match:
      any:
      - resources:
          kinds:
          - Pod
    name: check-for-secrets-in-env
    skipBackgroundRequests: true
    validate:
      foreach:
      - list: request.object.spec.[initContainers, containers][]
        pattern:
          =(env):
          - =(valueFrom):
              X(secretKeyRef): "null"
      message: Обнаружены секреты в переменных окружения
  schemaValidation: true
  validationFailureAction: Audit
  webhookTimeoutSeconds: 10
service-nodeport-used

Рекомендация не использовать Service типа NodePort: внешний доступ лучше организовать через Ingress; NodePort сложнее контролировать сетевыми политиками.

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  annotations:
    meta.helm.sh/release-name: shturval-policies
    meta.helm.sh/release-namespace: kyverno
    policies.kyverno.io/category: infosec
    policies.kyverno.io/description: 'NodePort может быть использован для предоставления
      доступа извне кластера к приложениям. Однако, такой подход не является примером
      хороших практик и не может контролироваться при помощи NetworkPolicy. Рекомендуется
      использование альтернатив - например, Ingress, для предоставления внешнего доступа
      к приложениям кластера.   '
    policies.kyverno.io/severity: High
    policies.kyverno.io/title: service type is set to NodePort
  generation: 1
  labels:
    app.kubernetes.io/managed-by: Helm
  name: service-nodeport-used
spec:
  admission: true
  background: true
  failurePolicy: Ignore
  rules:
  - match:
      any:
      - resources:
          kinds:
          - Service
    name: check-for-nodeport
    skipBackgroundRequests: true
    validate:
      message: Обнаружен Service Type NodePort. Рекомендуется использовать Ingress
      pattern:
        spec:
          type: '!NodePort'
  schemaValidation: true
  validationFailureAction: Audit
  webhookTimeoutSeconds: 10
sysadmin-capabilities-used

Запрет или аудит добавления capability SYS_ADMIN: она даёт широкие полномочия и может способствовать побегу из контейнера.

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  annotations:
    meta.helm.sh/release-name: shturval-policies
    meta.helm.sh/release-namespace: kyverno
    policies.kyverno.io/category: infosec
    policies.kyverno.io/description: 'Указанная Linux Capability обладает крайне большими
      полномочиями (согласно документации на Linux Capabilities: CAP_SYS_ADMIN - this
      capability is overloaded, Don''t choose CAP_SYS_ADMIN if you can possibly avoid
      it!). Большинство приложений не требуют наличия этой возможности. Поэтому надо
      следить за тем, чтобы указанная capability появлялась как можно реже. Использование
      ее возможностей может привести к ИБ-проблемам, в том числе "побегу" (escape)
      из pod (container).     '
    policies.kyverno.io/severity: High
    policies.kyverno.io/title: SYS_ADMIN capability added to container
  generation: 1
  labels:
    app.kubernetes.io/managed-by: Helm
  name: sysadmin-capabilities-used
spec:
  admission: true
  background: true
  failurePolicy: Ignore
  rules:
  - match:
      any:
      - resources:
          kinds:
          - Pod
    name: check-for-sysadmin-capabilities-enabled
    skipBackgroundRequests: true
    validate:
      foreach:
      - deny:
          conditions:
            any:
            - key: SYS_ADMIN
              operator: AnyIn
              value: '{{ element.securityContext.capabilities.add || '''' }}'
        list: request.object.spec.[initContainers, containers][]
      message: Установлен параметр SYS_ADMIN в описании Capabilities у Container/InitContainer
  schemaValidation: true
  validationFailureAction: Audit
  webhookTimeoutSeconds: 10

Дополнительные материалы