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

    Обзор функции

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

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

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

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

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

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

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

    Стандарт 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-бинарники или возможности файлов
    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 (не встроенных в платформу) необходимо явно добавить 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:

    # Добавить не-root пользователя с UID 65532 (синтаксис Alpine)
    RUN adduser -u 65532 -h /home/nonroot -D nonroot
    
    # Установить соответствующие права для рабочих директорий
    RUN chown -R 65532:65532 /app
    
    # Переключиться на не-root пользователя (использовать числовой UID)
    USER 65532

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

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

    # Проверить, что образ запускается не от root
    $ podman run -it --rm ${registry} id
    
    uid=65532(nonroot) gid=65532(nonroot) groups=65532(nonroot)

    Подробные рекомендации по настройке Containerfiles смотрите в Adjust Containerfile for Building Task-Compatible Custom Images.

    Результаты работы

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

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

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

    # Пометить пространство имён стандартом restricted
    $ kubectl label namespace test-ns pod-security.kubernetes.io/enforce=restricted
    
    namespace/test-ns labeled
    
    # Создать TaskRun в пространстве имён с ограничениями
    $ kubectl -n test-ns create -f taskrun.yaml
    
    taskrun.tekton.dev/example-taskrun created
    
    # Проверить успешность TaskRun
    $ 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 PolicyapiVersion: kyverno.io/v1 и kind: Policy), вы можете автоматически мутировать Pods, добавляя необходимые конфигурации securityContext.

    Для дополнительной информации смотрите Scenario 4: Specified Namespace Security Context Enforcement.

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

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

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

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

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

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

    securityContext:
      # allowPrivilegeEscalation: false  # Нельзя установить в false — buildah должен повышать привилегии для использования возможности SETFCAP при установке возможностей файлов во время сборки образов; принудительное false также блокирует newuidmap/newgidmap, из-за чего rootless переходит к однопользовательскому отображению UID/GID с предупреждениями и возможными ошибками владения файлами
      runAsNonRoot: true
      capabilities:
        # drop: ["ALL"]  # Нельзя сбрасывать все capabilities — buildah требует SETFCAP для установки возможностей (например, cap_net_bind_service) на файлы в образах во время сборки
        add: ["SETFCAP"]
      # seccompProfile:
      #   type: RuntimeDefault  # Нельзя использовать RuntimeDefault — профиль seccomp по умолчанию блокирует вызовы unshare/clone(CLONE_NEWUSER)/setns, необходимые buildah, что приводит к сбою сборки; используйте Unconfined или кастомный профиль, разрешающий эти вызовы

    Решения:

    1. Используйте buildah Task в отдельном пространстве имён с режимом baseline вместо restricted (например, pod-security.kubernetes.io/enforce=baseline)
    2. Рассмотрите альтернативные методы сборки образов контейнеров с другими требованиями безопасности

    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. Пересоберите образ с числовым UID не-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. Наличие соответствующих политик безопасности в пространстве имён
    2. Настройку образов контейнеров, используемых Tekton, на запуск от не-root пользователя
    3. Актуальность установки Tekton

    Дополнительная информация