• Русский
  • Политика безопасности томов

    В этом руководстве показано, как настроить Kyverno для применения политик безопасности томов, которые ограничивают использование опасных типов томов и конфигураций, способных скомпрометировать безопасность контейнеров.

    Что такое безопасность томов?

    Безопасность томов включает контроль над тем, какие типы томов могут монтировать контейнеры и каким образом они могут к ним обращаться. Правильная безопасность томов предотвращает:

    • Доступ к файловой системе хоста: Несанкционированный доступ к директориям хоста
    • Повышение привилегий: Использование томов для получения повышенных прав
    • Экфильтрация данных: Доступ к конфиденциальным данным хоста через монтирование томов
    • Выход из контейнера: Нарушение изоляции контейнера через доступ к томам
    • Небезопасные типы томов: Использование типов томов, обходящих механизмы безопасности

    Быстрый старт

    1. Ограничение типов томов

    apiVersion: kyverno.io/v1
    kind: ClusterPolicy
    metadata:
      name: restrict-volume-types
      annotations:
        policies.kyverno.io/title: Restrict Volume Types
        policies.kyverno.io/category: Pod Security Standards (Restricted)
        policies.kyverno.io/severity: medium
        policies.kyverno.io/subject: Pod,Volume
        policies.kyverno.io/description: >-
          Only allow safe volume types. This policy restricts volumes to configMap, csi, 
          downwardAPI, emptyDir, ephemeral, persistentVolumeClaim, projected, and secret.
    spec:
      validationFailureAction: Enforce
      background: true
      rules:
        - name: restrict-volume-types
          match:
            any:
            - resources:
                kinds:
                - Pod
          validate:
            message: >-
              Only the following types of volumes may be used: configMap, csi, downwardAPI, 
              emptyDir, ephemeral, persistentVolumeClaim, projected, and secret.
            foreach:
            - list: "request.object.spec.volumes || []"
              deny:
                conditions:
                  all:
                  - key: "{{ element.keys(@) }}"
                    operator: AnyNotIn
                    value:
                    - name
                    - configMap
                    - csi
                    - downwardAPI
                    - emptyDir
                    - ephemeral
                    - persistentVolumeClaim
                    - projected
                    - secret

    2. Тестирование политики

    # Применить политику
    kubectl apply -f restrict-volume-types.yaml
    
    # Попытка создать pod с томом hostPath (должно завершиться ошибкой)
    cat <<EOF | kubectl apply -f -
    apiVersion: v1
    kind: Pod
    metadata:
      name: test-hostpath
    spec:
      containers:
      - name: nginx
        image: nginx
        volumeMounts:
        - name: host-vol
          mountPath: /host
      volumes:
      - name: host-vol
        hostPath:
          path: /
    EOF
    
    # Сначала создать тестовый ConfigMap
    kubectl create configmap test-config --from-literal=key=value
    
    # Попытка создать pod с разрешённым томом (должно сработать)
    cat <<EOF | kubectl apply -f -
    apiVersion: v1
    kind: Pod
    metadata:
      name: test-configmap
    spec:
      containers:
      - name: nginx
        image: nginx
        volumeMounts:
        - name: config-vol
          mountPath: /config
      volumes:
      - name: config-vol
        configMap:
          name: test-config
    EOF
    
    # Очистка
    kubectl delete pod test-hostpath test-configmap --ignore-not-found
    kubectl delete configmap test-config --ignore-not-found

    Основные политики безопасности томов

    Политика 1: Запрет томов HostPath

    Запретить контейнерам монтировать пути файловой системы хоста:

    apiVersion: kyverno.io/v1
    kind: ClusterPolicy
    metadata:
      name: disallow-host-path
      annotations:
        policies.kyverno.io/title: Disallow Host Path
        policies.kyverno.io/category: Pod Security Standards (Baseline)
        policies.kyverno.io/severity: medium
        policies.kyverno.io/subject: Pod,Volume
        policies.kyverno.io/description: >-
          HostPath volumes let Pods use host directories and volumes in containers.
          Using host resources can be used to access shared data or escalate privileges
          and should not be allowed.
    spec:
      validationFailureAction: Enforce
      background: true
      rules:
        - name: host-path
          match:
            any:
            - resources:
                kinds:
                - Pod
          validate:
            message: >-
              HostPath volumes are forbidden. The field spec.volumes[*].hostPath must be unset.
            pattern:
              spec:
                =(volumes):
                  - X(hostPath): "null"

    Политика 2: Ограничение томов HostPath (только для чтения)

    Разрешить определённые тома hostPath с доступом только для чтения:

    apiVersion: kyverno.io/v1
    kind: ClusterPolicy
    metadata:
      name: restrict-host-path-readonly
      annotations:
        policies.kyverno.io/title: Restrict Host Path (Read-Only)
        policies.kyverno.io/category: Pod Security Standards (Baseline)
        policies.kyverno.io/severity: medium
        policies.kyverno.io/subject: Pod,Volume
        policies.kyverno.io/description: >-
          HostPath volumes which are allowed must be read-only and restricted to specific paths.
    spec:
      validationFailureAction: Enforce
      background: true
      rules:
        - name: host-path-readonly
          match:
            any:
            - resources:
                kinds:
                - Pod
          preconditions:
            all:
            - key: "{{ request.object.spec.volumes[?hostPath] | length(@) }}"
              operator: GreaterThan
              value: 0
          validate:
            message: >-
              HostPath volumes must be read-only and limited to allowed paths.
            foreach:
            - list: "request.object.spec.volumes[?hostPath]"
              deny:
                conditions:
                  any:
                  # Запрет, если путь не входит в разрешённый список
                  - key: "{{ element.hostPath.path }}"
                    operator: AnyNotIn
                    value:
                    - "/var/log"
                    - "/var/lib/docker/containers"
                    - "/proc"
                    - "/sys"
            foreach:
            - list: "request.object.spec.containers[].volumeMounts[?name]"
              deny:
                conditions:
                  any:
                  # Запрет, если монтирование тома не является только для чтения
                  - key: "{{ element.readOnly || false }}"
                    operator: Equals
                    value: false

    Политика 3: Запрет привилегированных типов томов

    Блокировать типы томов, которые могут обходить механизмы безопасности:

    apiVersion: kyverno.io/v1
    kind: ClusterPolicy
    metadata:
      name: disallow-privileged-volumes
      annotations:
        policies.kyverno.io/title: Disallow Privileged Volume Types
        policies.kyverno.io/category: Pod Security Standards (Baseline)
        policies.kyverno.io/severity: high
        policies.kyverno.io/subject: Pod,Volume
        policies.kyverno.io/description: >-
          Certain volume types are considered privileged and should not be allowed.
    spec:
      validationFailureAction: Enforce
      background: true
      rules:
        - name: disallow-privileged-volumes
          match:
            any:
            - resources:
                kinds:
                - Pod
          validate:
            message: >-
              Privileged volume types are not allowed: hostPath, gcePersistentDisk, 
              awsElasticBlockStore, gitRepo, nfs, iscsi, glusterfs, rbd, flexVolume, 
              cinder, cephFS, flocker, fc, azureFile, azureDisk, vsphereVolume, quobyte, 
              portworxVolume, scaleIO, storageos.
            foreach:
            - list: "request.object.spec.volumes || []"
              deny:
                conditions:
                  any:
                  - key: "{{ element.keys(@) }}"
                    operator: AnyIn
                    value:
                    - hostPath
                    - gcePersistentDisk
                    - awsElasticBlockStore
                    - gitRepo
                    - nfs
                    - iscsi
                    - glusterfs
                    - rbd
                    - flexVolume
                    - cinder
                    - cephFS
                    - flocker
                    - fc
                    - azureFile
                    - azureDisk
                    - vsphereVolume
                    - quobyte
                    - portworxVolume
                    - scaleIO
                    - storageos

    Политика 4: Требовать корневую файловую систему только для чтения

    Обеспечить использование контейнерами корневой файловой системы только для чтения:

    apiVersion: kyverno.io/v1
    kind: ClusterPolicy
    metadata:
      name: require-readonly-rootfs
      annotations:
        policies.kyverno.io/title: Require Read-Only Root Filesystem
        policies.kyverno.io/category: Pod Security Standards (Restricted)
        policies.kyverno.io/severity: medium
        policies.kyverno.io/subject: Pod
        policies.kyverno.io/description: >-
          A read-only root file system helps to enforce an immutable infrastructure strategy; 
          the container only needs to write on the mounted volume that persists the state.
    spec:
      validationFailureAction: Enforce
      background: true
      rules:
        - name: readonly-rootfs
          match:
            any:
            - resources:
                kinds:
                - Pod
          validate:
            message: >-
              Root filesystem must be read-only. Set readOnlyRootFilesystem to true.
            foreach:
            - list: request.object.spec.[ephemeralContainers, initContainers, containers][]
              deny:
                conditions:
                  any:
                  - key: "{{ element.securityContext.readOnlyRootFilesystem || false }}"
                    operator: Equals
                    value: false

    Политика 5: Контроль разрешений монтирования томов

    Ограничить разрешения и пути монтирования томов:

    apiVersion: kyverno.io/v1
    kind: ClusterPolicy
    metadata:
      name: control-volume-mounts
      annotations:
        policies.kyverno.io/title: Control Volume Mount Permissions
        policies.kyverno.io/category: Pod Security Standards (Restricted)
        policies.kyverno.io/severity: medium
        policies.kyverno.io/subject: Pod,Volume
        policies.kyverno.io/description: >-
          Control where volumes can be mounted and with what permissions.
    spec:
      validationFailureAction: Enforce
      background: true
      rules:
        - name: restrict-mount-paths
          match:
            any:
            - resources:
                kinds:
                - Pod
          validate:
            message: >-
              Volume mounts to sensitive paths are not allowed.
            foreach:
            - list: request.object.spec.[ephemeralContainers, initContainers, containers][].volumeMounts[]
              deny:
                conditions:
                  any:
                  # Блокировать монтирование в чувствительные системные пути
                  - key: "{{ element.mountPath }}"
                    operator: AnyIn
                    value:
                    - "/etc"
                    - "/root"
                    - "/var/run/docker.sock"
                    - "/var/lib/kubelet"
                    - "/var/lib/docker"
                    - "/usr/bin"
                    - "/usr/sbin"
                    - "/sbin"
                    - "/bin"
        - name: require-readonly-sensitive-mounts
          match:
            any:
            - resources:
                kinds:
                - Pod
          validate:
            message: >-
              Mounts to /proc and /sys must be read-only.
            foreach:
            - list: request.object.spec.[ephemeralContainers, initContainers, containers][].volumeMounts[]
              preconditions:
                any:
                - key: "{{ element.mountPath }}"
                  operator: AnyIn
                  value:
                  - "/proc"
                  - "/sys"
              deny:
                conditions:
                  any:
                  - key: "{{ element.readOnly || false }}"
                    operator: Equals
                    value: false

    Расширенные сценарии

    Сценарий 1: Политики томов для разных сред

    Различные ограничения томов для разных сред:

    apiVersion: kyverno.io/v1
    kind: ClusterPolicy
    metadata:
      name: environment-volume-security
    spec:
      validationFailureAction: Enforce
      background: true
      rules:
        # Production: Строгий контроль томов
        - name: production-volume-restrictions
          match:
            any:
            - resources:
                kinds:
                - Pod
                namespaces:
                - production
                - prod-*
          validate:
            message: "Production environments allow only secure volume types"
            foreach:
            - list: "request.object.spec.volumes || []"
              deny:
                conditions:
                  all:
                  - key: "{{ element.keys(@) }}"
                    operator: AnyNotIn
                    value:
                    - name
                    - configMap
                    - secret
                    - persistentVolumeClaim
                    - emptyDir
        
        # Development: Более либеральные, но безопасные
        - name: development-volume-restrictions
          match:
            any:
            - resources:
                kinds:
                - Pod
                namespaces:
                - development
                - dev-*
                - staging
          validate:
            message: "Development environments allow additional volume types"
            foreach:
            - list: "request.object.spec.volumes || []"
              deny:
                conditions:
                  any:
                  - key: "{{ element.keys(@) }}"
                    operator: AnyIn
                    value:
                    - hostPath  # Всё ещё блокировать hostPath в dev
                    - nfs       # Блокировать сетевые файловые системы

    Сценарий 2: Политики томов для разных типов приложений

    Различные политики томов для разных типов приложений:

    apiVersion: kyverno.io/v1
    kind: ClusterPolicy
    metadata:
      name: application-volume-policies
    spec:
      validationFailureAction: Enforce
      background: true
      rules:
        # Приложения баз данных: Разрешить постоянное хранилище
        - name: database-volume-policy
          match:
            any:
            - resources:
                kinds:
                - Pod
                selector:
                  matchLabels:
                    app.type: database
          validate:
            message: "Database applications must use persistent volumes"
            pattern:
              spec:
                volumes:
                - persistentVolumeClaim: {}
        
        # Веб-приложения: Ограничить безопасными томами
        - name: web-app-volume-policy
          match:
            any:
            - resources:
                kinds:
                - Pod
                selector:
                  matchLabels:
                    app.type: web
          validate:
            message: "Web applications can only use safe volume types"
            foreach:
            - list: "request.object.spec.volumes || []"
              deny:
                conditions:
                  all:
                  - key: "{{ element.keys(@) }}"
                    operator: AnyNotIn
                    value:
                    - name
                    - configMap
                    - secret
                    - emptyDir
                    - projected

    Сценарий 3: Ограничения по размеру томов и ресурсам

    Контроль размеров томов и использования ресурсов:

    apiVersion: kyverno.io/v1
    kind: ClusterPolicy
    metadata:
      name: volume-resource-limits
    spec:
      validationFailureAction: Enforce
      background: true
      rules:
        - name: limit-emptydir-size
          match:
            any:
            - resources:
                kinds:
                - Pod
          validate:
            message: "EmptyDir volumes must have size limits"
            foreach:
            - list: "request.object.spec.volumes[?emptyDir]"
              deny:
                conditions:
                  any:
                  - key: "{{ element.emptyDir.sizeLimit || '' }}"
                    operator: Equals
                    value: ""
        - name: limit-emptydir-memory
          match:
            any:
            - resources:
                kinds:
                - Pod
          validate:
            message: "EmptyDir memory volumes are not allowed"
            foreach:
            - list: "request.object.spec.volumes[?emptyDir]"
              deny:
                conditions:
                  any:
                  - key: "{{ element.emptyDir.medium || '' }}"
                    operator: Equals
                    value: "Memory"

    Тестирование и проверка

    Тест тома HostPath (должен завершиться ошибкой)

    cat <<EOF | kubectl apply -f -
    apiVersion: v1
    kind: Pod
    metadata:
      name: test-hostpath
    spec:
      containers:
      - name: nginx
        image: nginx
        volumeMounts:
        - name: host-vol
          mountPath: /host
      volumes:
      - name: host-vol
        hostPath:
          path: /
    EOF