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

    Обзор возможности

    Стандарт 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
    • Запуск workload в средах с высокими требованиями к регулированию

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

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

    Понимание ограниченного стандарта

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

    • Обычные контейнеры (containers)
    • Init-контейнеры (initContainers)
    • Эфемерные контейнеры (ephemeralContainers)

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

    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-профиль контейнерного runtimeОграничивает системные вызовы, доступные контейнеру, уменьшая площадь атаки ядра

    Шаги

    1. Настройте Tekton для добавления securityContext в init-контейнеры

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

    Вариант 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, созданные после этого изменения, автоматически получат необходимый securityContext, примененный к init-контейнерам.

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

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

    Пример Task с securityContext:

    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-контейнеры, создаваемые Tekton, будут автоматически соответствовать стандарту restricted
    2. Пользовательские Tasks: шаги ваших пользовательских Task будут иметь требуемый securityContext
    3. Container Images: образы будут запускаться от имени пользователей без 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, чтобы автоматически внедрять необходимый securityContext во все контейнеры. Создав Kyverno Policy (с использованием apiVersion: kyverno.io/v1 и kind: Policy), можно автоматически изменять Pod, добавляя необходимые конфигурации securityContext.

    Для получения дополнительной информации см. Сценарий 4: Принудительное применение `SecurityContext` в указанном namespace.

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

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

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

    Встроенные Tasks и ограниченный стандарт

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

    buildah Task требует следующего securityContext:

    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. Используйте buildah Task в отдельном namespace с режимом baseline вместо режима restricted (например, pod-security.kubernetes.io/enforce=baseline)
    2. Рассмотрите альтернативные способы сборки контейнерных образов, которые могут иметь другие требования к безопасности

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

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

    • "container has runAsNonRoot and image will run as root" — в образе контейнера в Containerfile отсутствует директива USER (по умолчанию используется 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 задает securityContext на уровне Pod, который наследуется всеми контейнерами, если не переопределен на уровне контейнера.

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

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

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

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

    Init-контейнеры завершаются ошибками доступа

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

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

    Подробнее