• Русский
  • Соответствие стандарту Pod Security Restricted

    Обзор функциональности

    Стандарт pod-security.kubernetes.io/enforce=restricted является самым строгим Pod Security Standard и обеспечивает соблюдение актуальных рекомендаций по hardening pod. Когда для namespace задана метка с этим стандартом, все pod, создаваемые в этом namespace, должны соответствовать строгим требованиям безопасности.

    В этом руководстве объясняется, как настроить Tekton Pipelines для соответствия стандарту безопасности restricted, чтобы все контейнеры в ваших Tasks могли успешно запускаться в namespace с ограничениями.

    Сценарии использования

    • Запуск Tekton Pipelines в namespace с меткой pod-security.kubernetes.io/enforce=restricted
    • Выполнение требований организации по соответствию требованиям безопасности
    • Повышение уровня безопасности ваших CI/CD pipeline
    • Запуск workloads в средах с высокими требованиями к регулированию

    Предварительные требования

    • Tekton Pipelines установлен через CR TektonPipeline или TektonConfig
    • У вас есть разрешение на изменение ресурсов TektonPipeline или TektonConfig
    • Вы можете создавать или редактировать определения Task
    • Для пользовательских образов у вас есть доступ к изменению Containerfile и пересборке образов

    Понимание стандарта Restricted

    Стандарт pod-security.kubernetes.io/enforce=restricted требует, чтобы все три типа контейнеров в Pod соответствовали следующим требованиям к security context:

    • Обычные контейнеры (containers)
    • Init containers (initContainers)
    • Ephemeral containers (ephemeralContainers)

    Каждый контейнер должен иметь следующую конфигурацию security context:

    securityContext:
      allowPrivilegeEscalation: false
      runAsNonRoot: true
      capabilities:
        drop:
          - "ALL"
      seccompProfile:
        type: RuntimeDefault

    Разбор конфигурации:

    ПолеЗначениеНазначениеВлияние
    allowPrivilegeEscalationfalseПредотвращает получение процессами привилегий, превышающих привилегии родительского процессаБлокирует попытки вредоносного кода повышать привилегии через двоичные файлы с setuid или file capabilities
    runAsNonRoottrueТребует, чтобы контейнеры запускались от имени пользователя, не являющегося root (UID ≠ 0)Не позволяет контейнерам запускаться от имени root, снижая влияние уязвимостей, связанных с выходом из контейнера
    capabilities.drop["ALL"]Удаляет все Linux capabilities из контейнераОграничивает возможность контейнера выполнять привилегированные операции (например, настройку сети, загрузку модулей ядра)
    seccompProfile.typeRuntimeDefaultПрименяет профиль seccomp по умолчанию среды выполнения контейнеровОграничивает набор системных вызовов, доступных контейнеру, снижая площадь атаки на kernel

    Шаги

    1. Настройте Tekton для добавления security context в init containers

    Tekton создает init containers для каждого управляемого им Pod. Чтобы соответствовать стандарту restricted, необходимо включить автоматическое добавление требуемого security context к этим init containers.

    Вариант A: Настройка через TektonPipeline

    Если вы управляете Tekton напрямую через CR TektonPipeline:

    apiVersion: operator.tekton.dev/v1alpha1
    kind: TektonPipeline
    spec:
      set-security-context: true

    Примените конфигурацию:

    $ kubectl patch tektonpipeline tektonpipeline \
      --type merge \
      -p '{"spec":{"set-security-context":true}}'
    
    tektonpipeline.operator.tekton.dev/tektonpipeline patched

    Вариант B: Настройка через TektonConfig

    Если вы управляете Tekton через CR TektonConfig:

    apiVersion: operator.tekton.dev/v1alpha1
    kind: TektonConfig
    spec:
      pipeline:
        set-security-context: true

    Примените конфигурацию:

    $ kubectl patch tektonconfig config \
      --type merge \
      -p '{"spec":{"pipeline":{"set-security-context":true}}}'
    
    tektonconfig.operator.tekton.dev/config patched

    Примечание: Это изменение конфигурации вступает в силу немедленно и не требует перезапуска контроллера Tekton. Новые TaskRuns и PipelineRuns, созданные после этого изменения, автоматически получат требуемый security context для init containers.

    2. Добавьте security context в определения пользовательских Task

    Для пользовательских Tasks (не встроенных Tasks, предоставляемых платформой) необходимо явно добавить security context для каждого шага.

    Пример Task с security context:

    apiVersion: tekton.dev/v1
    kind: Task
    metadata:
      name: custom-build-task
    spec:
      steps:
        - name: build
          image: registry.example.com/builder:latest
          securityContext:
            allowPrivilegeEscalation: false
            runAsNonRoot: true
            capabilities:
              drop:
                - "ALL"
            seccompProfile:
              type: RuntimeDefault
          script: |
            #!/bin/sh
            echo "Building application..."

    Важно: Этот шаг относится к пользовательским Tasks. Встроенные Tasks, предоставляемые платформой (за исключением buildah, см. раздел «Устранение неполадок»), совместимы с этими ограничениями безопасности, но их определения Task не содержат явных настроек securityContext, поскольку они рассчитаны на работу в различных контекстах безопасности, а не только в режиме restricted.

    3. Настройте контейнерные образы для использования пользователей без root-прав

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

    В вашем Containerfile добавьте пользователя без root-прав и установите его в качестве пользователя по умолчанию. Ниже приведен пример для образов на основе Alpine:

    # Add a non-root user with UID 65532 (Alpine syntax)
    RUN adduser -u 65532 -h /home/nonroot -D nonroot
    
    # Set appropriate permissions for working directories
    RUN chown -R 65532:65532 /app
    
    # Switch to the non-root user (use numeric UID)
    USER 65532

    Примечание: Синтаксис команды adduser зависит от базового образа. См. приведенную ниже документацию с примерами для других базовых образов.

    Проверьте конфигурацию образа:

    # Check that the image runs as non-root
    $ podman run -it --rm ${registry} id
    
    uid=65532(nonroot) gid=65532(nonroot) groups=65532(nonroot)

    Для подробных рекомендаций по настройке Containerfile см. Настроить Containerfile для сборки пользовательских образов, совместимых с Task.

    Результаты выполнения

    После выполнения указанных выше шагов:

    1. Init Containers: init containers, создаваемые Tekton, будут автоматически соответствовать стандарту restricted
    2. Пользовательские Tasks: ваши пользовательские шаги Task будут иметь требуемый security context
    3. Контейнерные образы: образы будут запускаться от имени пользователей без root-прав с минимальными привилегиями

    Вы можете проверить соответствие, создав TaskRun в namespace с ограничениями:

    # Label a namespace with the restricted standard
    $ kubectl label namespace test-ns pod-security.kubernetes.io/enforce=restricted
    
    namespace/test-ns labeled
    
    # Create a TaskRun in the restricted namespace
    $ kubectl -n test-ns create -f taskrun.yaml
    
    taskrun.tekton.dev/example-taskrun created
    
    # Verify the TaskRun succeeds
    $ kubectl -n test-ns get taskrun
    
    NAME               SUCCEEDED   REASON      STARTTIME   COMPLETIONTIME
    example-taskrun    True        Succeeded   2m ago      1m ago

    Успешный TaskRun отображает SUCCEEDED со значением True и REASON со значением Succeeded, что указывает на то, что все контейнеры были успешно запущены с требуемыми ограничениями безопасности.

    Использование инструментов принудительного применения политик

    Для более автоматизированного подхода можно использовать инструменты принудительного применения политик, такие как Kyverno, чтобы автоматически внедрять требуемый security context во все контейнеры. Создав Policy Kyverno (с использованием apiVersion: kyverno.io/v1 и kind: Policy), вы можете автоматически изменять Pods, добавляя необходимые настройки security context.

    Подробнее см. Сценарий 4: Принудительное применение security context для указанного namespace.

    Ограничение Buildah

    Этот подход на основе Kyverno не делает встроенный Task buildah совместимым со стандартом restricted. Описание ограничения buildah см. в разделе Встроенные Tasks и стандарт Restricted ниже.

    Этот подход устраняет необходимость вручную настраивать security context для каждого Task, упрощая управление соответствием требованиям.

    Подробные рекомендации по настройке политик Kyverno для этой цели см. здесь:

    Устранение неполадок

    Встроенные Tasks и стандарт Restricted

    Среди встроенных Tasks, предоставляемых платформой, только Task buildah не может работать в рамках стандарта restricted. Это связано с тем, что для сборки контейнерных образов buildah требуются повышенные привилегии.

    Это ограничение сохраняется даже при использовании Kyverno для автоматического внедрения требуемого security context restricted в Pods. Kyverno может добавить поля, требуемые стандартом restricted, но не может сделать встроенный Task buildah совместимым с restricted, поскольку buildah требует привилегий, запрещенных этим стандартом.

    Task buildah требует следующую конфигурацию security context:

    securityContext:
      # allowPrivilegeEscalation: false  # Cannot be set to false - buildah needs to escalate privileges to use the SETFCAP capability for setting file capabilities during container image builds; forcing false also blocks newuidmap/newgidmap, causing rootless to fall back to single UID/GID mapping with warnings and potentially incorrect file ownership
      runAsNonRoot: true
      capabilities:
        # drop: ["ALL"]  # Cannot drop ALL capabilities - buildah requires SETFCAP capability to set file capabilities (e.g., cap_net_bind_service) on files within container images during the build process
        add: ["SETFCAP"]
      # seccompProfile:
      #   type: RuntimeDefault  # Cannot use RuntimeDefault - default seccomp blocks unshare/clone(CLONE_NEWUSER)/setns needed by buildah, leading to build failure; use Unconfined or a custom profile that allows these syscalls instead

    Решения:

    1. Используйте Task buildah в отдельном namespace с режимом baseline вместо режима restricted.

      Чтобы workloads buildah могли выполняться, необходимо изменить pod-security.kubernetes.io/enforce на baseline. Метки warn и audit не блокируют допуск.

      # Required: change enforce to baseline for buildah workloads
      $ kubectl label namespace build-ns \
        pod-security.kubernetes.io/enforce=baseline \
        --overwrite
      
      namespace/build-ns labeled

      После изменения метки namespace создайте новый TaskRun или PipelineRun, использующий Task buildah в этом namespace. Если правильно настроены учетные данные реестра, Containerfile и workspace, Task buildah может нормально выполняться в рамках стандарта baseline.

    2. Рассмотрите альтернативные способы сборки container image, которые могут иметь другие требования к безопасности.

    TaskRun завершается ошибкой из-за пользователя контейнера

    Вы можете столкнуться с одной из следующих ошибок:

    • "container has runAsNonRoot and image will run as root" — в контейнерном образе отсутствует директива USER в Containerfile (по умолчанию используется root) либо явно задано USER 0 или USER root
    • "container has runAsNonRoot and image has non-numeric user" — контейнерный образ использует символьное имя пользователя (например, USER appuser) вместо числового UID

    Решения:

    1. Пересоберите образ с использованием числового идентификатора пользователя без root-прав, как описано в шаге 3. Например, используйте USER 65532 вместо USER appuser или USER root.

    2. Укажите пользователя в securityContext Task:

      apiVersion: tekton.dev/v1
      kind: Task
      metadata:
        name: example-task
      spec:
        steps:
          - name: step1
            image: registry.example.com/myimage:latest
            securityContext:
              runAsUser: 65532
              runAsNonRoot: true
              allowPrivilegeEscalation: false
              capabilities:
                drop:
                  - "ALL"
              seccompProfile:
                type: RuntimeDefault
            script: |
              #!/bin/sh
              echo "Running as user $(id -u)"
    3. Укажите пользователя в podTemplate TaskRun:

      apiVersion: tekton.dev/v1
      kind: TaskRun
      metadata:
        name: example-taskrun
      spec:
        taskRef:
          name: example-task
        podTemplate:
          securityContext:
            runAsUser: 65532
            runAsNonRoot: true
            fsGroup: 65532

    Примечание: podTemplate.securityContext задает security context на уровне Pod, который наследуется всеми контейнерами, если не переопределен на уровне контейнера.

    Варианты 2 и 3 полезны, когда вы не можете изменить контейнерный образ.

    TaskRun завершается ошибкой "Forbidden: cannot set securityContext.capabilities"

    Эта ошибка возникает, когда в security context пытаются добавить capabilities при одновременном удалении всех capabilities.

    Решение: Убедитесь, что ваш Task не добавляет никаких capabilities. Оставляйте только удаление capabilities, как показано в примерах.

    Init containers завершаются ошибками доступа

    Если после установки set-security-context: true init containers завершаются ошибками доступа, проверьте, что:

    1. В namespace заданы соответствующие политики безопасности
    2. Контейнерные образы, используемые Tekton, настроены на запуск от имени пользователя без root-прав
    3. Установка Tekton обновлена до актуальной версии

    Подробнее