4.18. 以非 root 用户身份使用 Buildah 构建容器镜像


作为 root 用户在容器上运行 Pipelines,可以将容器进程和主机公开给其他潜在的恶意资源。您可以作为容器中的特定非 root 用户运行工作负载来降低此类风险。要以非 root 用户身份使用 Buildah 运行容器镜像的构建,可以执行以下步骤:

  • 定义自定义服务帐户 (SA) 和安全性上下文约束 (SCC)。
  • 配置 Buildah,以使用 ID 为 1000build 用户。
  • 使用自定义配置映射启动任务运行,或将其与管道运行集成。

4.18.1. 配置自定义服务帐户和安全上下文约束

默认 pipeline SA 允许使用命名空间范围之外的用户 ID。要减少对默认 SA 的依赖性,您可以为 ID 为 1000build 用户定义具有必要的集群角色和角色绑定的自定义 SA 和 SCC。

重要

目前,Buildah 需要启用 allowPrivilegeEscalation 设置,才能在容器中运行。通过这个设置,Buildah 可以在以非 root 用户身份运行时利用 SETUIDSETGID 功能。

流程

  • 使用必要的集群角色和角色绑定创建自定义 SA 和 SCC。

    示例:用户 id 为 1000 的自定义 SA 和 SCC。

    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: pipelines-sa-userid-1000 1
    ---
    kind: SecurityContextConstraints
    metadata:
      annotations:
      name: pipelines-scc-userid-1000 2
    allowHostDirVolumePlugin: false
    allowHostIPC: false
    allowHostNetwork: false
    allowHostPID: false
    allowHostPorts: false
    allowPrivilegeEscalation: true 3
    allowPrivilegedContainer: false
    allowedCapabilities: null
    apiVersion: security.openshift.io/v1
    defaultAddCapabilities: null
    fsGroup:
      type: MustRunAs
    groups:
    - system:cluster-admins
    priority: 10
    readOnlyRootFilesystem: false
    requiredDropCapabilities:
    - MKNOD
    - KILL
    runAsUser: 4
      type: MustRunAs
      uid: 1000
    seLinuxContext:
      type: MustRunAs
    supplementalGroups:
      type: RunAsAny
    users: []
    volumes:
    - configMap
    - downwardAPI
    - emptyDir
    - persistentVolumeClaim
    - projected
    - secret
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRole
    metadata:
      name: pipelines-scc-userid-1000-clusterrole 5
    rules:
    - apiGroups:
      - security.openshift.io
      resourceNames:
      - pipelines-scc-userid-1000
      resources:
      - securitycontextconstraints
      verbs:
      - use
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: RoleBinding
    metadata:
      name: pipelines-scc-userid-1000-rolebinding 6
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: ClusterRole
      name: pipelines-scc-userid-1000-clusterrole
    subjects:
    - kind: ServiceAccount
      name: pipelines-sa-userid-1000

1
定义一个自定义 SA。
2
使用修改的 runAsUser 字段,定义基于受限特权创建的自定义 SCC。
3
目前,Buildah 需要启用 allowPrivilegeEscalation 设置,才能在容器中运行。通过这个设置,Buildah 可以在以非 root 用户身份运行时利用 SETUIDSETGID 功能。
4
限制通过自定义 SA 附加了自定义 SCC 的 Pod,使其以用户 ID 1000 身份运行。
5
定义使用自定义 SCC 的集群角色。
6
将使用自定义 SCC 的集群角色绑定到自定义 SA。

4.18.2. 配置 Buildah 以使用 build 用户

您可以定义一个 Buildah 任务,以使用带有用户 ID 1000build 用户。

流程

  1. 作为普通任务,创建 buildah 集群任务的副本。

    $ oc get clustertask buildah -o yaml | yq '. |= (del .metadata |= with_entries(select(.key == "name" )))' | yq '.kind="Task"' | yq '.metadata.name="buildah-as-user"' | oc create -f -
  2. 编辑复制的 buildah 任务。

    $ oc edit task buildah-as-user

    示例:使用 build 用户修改 Buildah 任务

    apiVersion: tekton.dev/v1beta1
    kind: Task
    metadata:
      name: buildah-as-user
    spec:
      description: >-
        Buildah task builds source into a container image and
        then pushes it to a container registry.
        Buildah Task builds source into a container image using Project Atomic's
        Buildah build tool.It uses Buildah's support for building from Dockerfiles,
        using its buildah bud command.This command executes the directives in the
        Dockerfile to assemble a container image, then pushes that image to a
        container registry.
      params:
      - name: IMAGE
        description: Reference of the image buildah will produce.
      - name: BUILDER_IMAGE
        description: The location of the buildah builder image.
        default: registry.redhat.io/rhel8/buildah@sha256:99cae35f40c7ec050fed3765b2b27e0b8bbea2aa2da7c16408e2ca13c60ff8ee
      - name: STORAGE_DRIVER
        description: Set buildah storage driver
        default: vfs
      - name: DOCKERFILE
        description: Path to the Dockerfile to build.
        default: ./Dockerfile
      - name: CONTEXT
        description: Path to the directory to use as context.
        default: .
      - name: TLSVERIFY
        description: Verify the TLS on the registry endpoint (for push/pull to a non-TLS registry)
        default: "true"
      - name: FORMAT
        description: The format of the built container, oci or docker
        default: "oci"
      - name: BUILD_EXTRA_ARGS
        description: Extra parameters passed for the build command when building images.
        default: ""
      - description: Extra parameters passed for the push command when pushing images.
        name: PUSH_EXTRA_ARGS
        type: string
        default: ""
      - description: Skip pushing the built image
        name: SKIP_PUSH
        type: string
        default: "false"
      results:
      - description: Digest of the image just built.
        name: IMAGE_DIGEST
        type: string
      workspaces:
      - name: source
      steps:
      - name: build
        securityContext:
          runAsUser: 1000 1
        image: $(params.BUILDER_IMAGE)
        workingDir: $(workspaces.source.path)
        script: |
          echo "Running as USER ID `id`" 2
          buildah --storage-driver=$(params.STORAGE_DRIVER) bud \
            $(params.BUILD_EXTRA_ARGS) --format=$(params.FORMAT) \
            --tls-verify=$(params.TLSVERIFY) --no-cache \
            -f $(params.DOCKERFILE) -t $(params.IMAGE) $(params.CONTEXT)
          [[ "$(params.SKIP_PUSH)" == "true" ]] && echo "Push skipped" && exit 0
          buildah --storage-driver=$(params.STORAGE_DRIVER) push \
            $(params.PUSH_EXTRA_ARGS) --tls-verify=$(params.TLSVERIFY) \
            --digestfile $(workspaces.source.path)/image-digest $(params.IMAGE) \
            docker://$(params.IMAGE)
          cat $(workspaces.source.path)/image-digest | tee /tekton/results/IMAGE_DIGEST
        volumeMounts:
        - name: varlibcontainers
          mountPath: /home/build/.local/share/containers 3
      volumes:
      - name: varlibcontainers
        emptyDir: {}

    1
    以用户 id 1000 明确运行容器,它与 Buildah 镜像中的 build 用户对应。
    2
    显示用户 id,以确认进程以用户 ID 1000 身份运行。
    3
    您可以根据需要更改卷挂载的路径。

4.18.3. 使用自定义配置映射或管道运行启动任务运行

定义自定义 Buildah 集群任务后,您可以创建一个 TaskRun 对象,该对象以 build 用户,使用用户 id 1000 来构建镜像。另外,您还可以将 TaskRun 对象集成为 PipelineRun 对象的一部分。

流程

  1. 使用自定义 ConfigMapDockerfile 对象创建一个 TaskRun 对象。

    示例:以用户 ID 1000 身份运行 Buildah 的任务运行

    apiVersion: v1
    data:
      Dockerfile: |
        ARG BASE_IMG=registry.access.redhat.com/ubi8/ubi
        FROM $BASE_IMG AS buildah-runner
        RUN dnf -y update && \
            dnf -y install git && \
            dnf clean all
        CMD git
    kind: ConfigMap
    metadata:
      name: dockerfile 1
    ---
    apiVersion: tekton.dev/v1beta1
    kind: TaskRun
    metadata:
      name: buildah-as-user-1000
    spec:
      serviceAccountName: pipelines-sa-userid-1000 2
      params:
      - name: IMAGE
        value: image-registry.openshift-image-registry.svc:5000/test/buildahuser
      taskRef:
        kind: Task
        name: buildah-as-user
      workspaces:
      - configMap:
          name: dockerfile 3
        name: source

    1
    使用配置映射,因为重点是在任务运行中,而无需使用 Dockerfile 获取某些源的以前的任务。
    2
    您创建的服务帐户的名称。
    3
    将配置映射挂载为 buildah-as-user 任务的源工作区。
  2. (可选)创建管道和对应的管道运行。

    示例:管道和对应的管道运行

    apiVersion: tekton.dev/v1beta1
    kind: Pipeline
    metadata:
      name: pipeline-buildah-as-user-1000
    spec:
      params:
      - name: IMAGE
      - name: URL
      workspaces:
      - name: shared-workspace
      - name: sslcertdir
        optional: true
      tasks:
      - name: fetch-repository 1
        taskRef:
          name: git-clone
          kind: ClusterTask
        workspaces:
        - name: output
          workspace: shared-workspace
        params:
        - name: url
          value: $(params.URL)
        - name: subdirectory
          value: ""
        - name: deleteExisting
          value: "true"
      - name: buildah
        taskRef:
          name: buildah-as-user 2
        runAfter:
        - fetch-repository
        workspaces:
        - name: source
          workspace: shared-workspace
        - name: sslcertdir
          workspace: sslcertdir
        params:
        - name: IMAGE
          value: $(params.IMAGE)
    ---
    apiVersion: tekton.dev/v1beta1
    kind: PipelineRun
    metadata:
      name: pipelinerun-buildah-as-user-1000
    spec:
      taskRunSpecs:
        - pipelineTaskName: buildah
          taskServiceAccountName: pipelines-sa-userid-1000 3
      params:
      - name: URL
        value: https://github.com/openshift/pipelines-vote-api
      - name: IMAGE
        value: image-registry.openshift-image-registry.svc:5000/test/buildahuser
      pipelineRef:
        name: pipeline-buildah-as-user-1000
      workspaces:
      - name: shared-workspace 4
        volumeClaimTemplate:
          spec:
            accessModes:
              - ReadWriteOnce
            resources:
              requests:
                storage: 100Mi

    1
    使用 git-clone 集群任务获取包含 Dockerfile 的源,并使用修改后的 Buildah 任务构建它。
    2
    请参阅修改后的 Buildah 任务。
    3
    使用您为 Buildah 任务创建的服务帐户。
    4
    使用控制器自动创建的持久性卷声明 (PVC) 在 git-clone 任务和修改后的 Buildah 任务间共享数据。
  3. 启动任务运行或管道运行。

4.18.4. 无特权构建的限制

无特权构建的进程可用于大多数 Dockerfile 对象。但是,一些已知的限制可能会导致构建失败:

  • 由于缺少必要权限问题,使用 --mount=type=cache 选项可能会失败。如需更多信息,请参阅本文档
  • 使用 --mount=type=secret 选项会失败,因为挂载资源需要未由自定义 SCC 提供的额外功能。
Red Hat logoGithubRedditYoutubeTwitter

学习

尝试、购买和销售

社区

关于红帽文档

通过我们的产品和服务,以及可以信赖的内容,帮助红帽用户创新并实现他们的目标。

让开源更具包容性

红帽致力于替换我们的代码、文档和 Web 属性中存在问题的语言。欲了解更多详情,请参阅红帽博客.

關於紅帽

我们提供强化的解决方案,使企业能够更轻松地跨平台和环境(从核心数据中心到网络边缘)工作。

© 2024 Red Hat, Inc.